先看两种情况的代码以及输出结果。
第一种
PS:更新一下函数提升的结果
var a = 1;
{
console.log(a, window.a); // func, 1
a = 2;
console.log(a, window.a); // 2, 1
function a(){}
console.log(a, window.a); // 2, 2
a = 3;
console.log(a, window.a); // 3, 2
}
console.log(a) // 2
第二种
两种情况的区别在于函数声明和赋值语句的先后。这段代码还需要区分严格还是非严格模式,不然结果也不一样。
先说非严格模式,也就是上面两种情况。我直接摘取重要的地方写。
// 1
a = 2
function a() {
} // [flag]
// 1
function a() {
} // [flag]
a = 2
上面这两个执行到 // 1
的时候,都有一个函数提升,知道这块概念的都能明白。区别在于两个 flag
的位置。
先看 MDN 的说明。所以非严格模式下,块作用域里的函数声明,依旧赋值给 window
。
把 flag
处理解为完成函数声明。
所以在第一个的 flag
处,因为 a = 2
将作用域里的 a
变成了 2
,这个时候去完成声明,window.a
就是 2
了。而第二个依旧是函数,所以 window.a
是 func
。
至于为什么 a = 3
只在块内部,可以理解为是因为块内部因为声明函数,存在了一个变量 a
,这个赋值改的是块内部的变量 a
。
再来看看严格模式下的结果。
第一种
第二种
严格模式下,函数的声明只在块作用域中。
补充一下分析过程吧。当时是在 var a = 1
后面加了 debugger
然后一步一步看变化的,前面都还好,但是一到 flag
处,全局的 a
就变了,就很懵逼。怀疑来怀疑去,只可能是内部在这里做了赋值,然后去搜了一下。结果就是看到上面说的,非严格模式函数声明没有块级作用域。
自己尝试,然后注意图中的两个变量吧。
就酱紫,see you next time.