题目:
var a = 10;
(function () {
console.log(a);
a = 5;
console.log(window.a);
var 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,找不到,沿着作用域链找,在全局作用域中找到变量a,返回123。 a = 456;// 修改全局变量 a的值为456 }()) console.log(a);// 返回456
-
全局作用域中无法访问局部作用域的变量
(function(){ var a = 456; }()); console.log(a) // Error: a is not defined
-
当局部作用域中进行隐式声明时,默认会在全局作用域中声明该变量
(function(){ a = 456 }()); console.log(a) // 456
回到本题
- 在立即执行函数中,第一行打印a, 在函数执行上下文中,因为var a = 20;var显示声明了变量a,变量提升到函数顶部,但没有赋值,所以第一次打印a为undefined。
- 由于变量声明提升,a = 5; 这条语句执行时,局部的变量a已经声明, 因此它产生的效果是对局部的变量a赋值,此时window.a 依旧是最开始赋值的10。
- 最后打印a,局部变量赋值为20,所以打印为20。
可以这样理解:
var a; // undefined
a = 10;
(function () {
var a; // undefined
console.log(a) // 此处因为是var是显式声明所以在函数作用域中访问到的,一定是他内部声明变量a
a = 5 // 显式声明的变量a 赋值为 5
console.log(window.a) // 直接找的是window的a,则不在函数作用域中寻找 有趣的是,function中不通过call或apply修改this指针,此处输出 `this.a` 的效果是一致的
a = 20;// 显式声明的变量a 由 5 变成 20
console.log(a)
})()