变量作用域
作用域是指对某一变量和方法具有访问权限的代码空间, 在JS中, 作用域是在函数中维护的.表示变量或函数起作用的区域,指代了它们在什么样的上下文中执行,亦即上下文执行环境。
js中有两种作用域: 全局作用域和函数作用域
全局作用域
- 直接编写在JS的script标签中的
- 全局作用域在页面打开时创建,在页面关闭时销毁
- 有一个全局对象window,代表一个浏览器窗口,由浏览器创建,我们可以直接使用
- 全局作用域中 创建的变量都作为window对象的属性保存
- 全局作用域中 创建的函数都作为window对象的方法保存
- 全局作用域中的变量是全局变量,页面任意部分都可以调用
//变量都作为window对象的属性
//函数都作为window对象的方法
<script>
var a = 2;
function test(){
var b = 3;
console.log(window.a);
}
window.test() // 2
</script>
可以看到在函数中可以访问到定义的变量a
函数作用域
- 调用函数时创建函数作用域,函数执行完毕后被销毁
- 每调用一次函数就会创建一个新的函数作用域,他们之间相互独立
- 函数作用域可以访问全局作用域中变量 ,全局无法访问函数作用域中变量
- 在函数作用域中操作变量时,先在自身作用域中寻找,如果没有,则向上一级作用域中寻找,直到全局作用域,全局作用域中也没有,报错。
- 在函数中想要访问全局作用域中的变量(自身也有同名变量),可以使用window,变量名调用
<script>
var a = 2;
function test(){
var b = 3;
console.log(window.a);
}
window.test()
console.log(b); // b is not defined
</script>
在正常条件下,函数外部无法访问函数内部的变量
块级作用域
在ES6中新增加了一个块级作用域,它可以解决js作用域的一些弊端
内部变量覆盖外层变量
<script>
var a = 121321
function test(){
console.log(a);
if(1){
var a = 'adasdad'
}
}
test() //undefined
</script>
在函数中log(a)会输出undefined,而不是我们以为的121321,这是因为var声明的变量存在变量提升,因此内部变量覆盖了外层变量
循环变量泄露为全局变量
var i = 0;
for(var i = 0;i<6;i++){
}
console.log(i); // 5
我们只想让循环变量在for循环里边起效,但它泄露成了全局变量
let,const
let,const是es6中添加的声明方式,它相比与var,没有变量提升但是多了块级作用域,块级作用域可以解决上述两个问题
var a = 121321
function test(){
console.log(a);
if(1){
let a = 'adasdad'
}
}
test() // 121321
var i = 0;
for(let i = 0;i<6;i++){
}
console.log(i); // 0