再来一题:关于变量提升和作用域的
var a = 10;
(function () {
console.log(a) // 输出:undefined
a = 5
console.log(window.a) // 输出:10
var a = 20;
console.log(a); // 输出:20
})()
// 前提是在浏览器中执行,node中 window.a会报错 window is not defined
复制代码
简单点的分析
-
在立即执行函数中,
var a = 20;
语句定义了一个局部变量a
,由于js的变量声明提升机制,局部变量a
的声明会被提升至立即执行函数的函数体最上方,且由于这样的提升并不包括赋值,因此第一条打印语句会打印undefined
,最后一条语句会打印20
。 -
由于变量声明提升,
a = 5;
这条语句执行时,局部的变量a已经声明,因此它产生的效果是对局部的变量a
赋值,此时window.a
依旧是最开始赋值的10
。
相当于:
var a = 10;
(function () {
var a; // 在函数作用域中,变量提升至此
console.log(a)
a = 5
console.log(window.a) //这里的window.a 在全局作用域中
a = 20;
console.log(a);
})()
复制代码
进阶分析
- 函数作用域可以访问全局作用域
var a = 123;
(function(){
console.log(a) // 123
a = 456
}());
console.log(a) // 456
复制代码
步骤解析:
var a = undefined;
a = 123;
(function(){
console.log(a) // 函数作用域寻找变量a
console.log(window.a) // 结果没找到,那么他会向上寻找,直到找到该变量,若最后没有找到,那么就会报该变量未定义
window.a = 456 // 因为找到的是window的变量`a`所以此处会修改window的变量`a`
}());
console.log(a) // 456
复制代码
在这里实际还涉及到隐式声明,所以我在下面会说明
- 全局作用域中无法访问局部作用域的变量
(function(){
var a = 456
}());
console.log(a) // Error: a is not defined
复制代码
步骤解析: window
已经是全局作用域了,在这里并没有发现变量a
所以不会继续向上寻找,直接输出 a is not defined
- 当局部作用域中进行隐式声明时,默认会在全局作用域中声明该变量
(function(){
a = 456
}());
console.log(a) // 456
复制代码
参见及感谢
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END