为什么块级函数重声明会影响全局变量?
非严格模式下块级函数重声明的行为解析
先看你给出的代码片段:
console.log(a); //undefined { function a() {} console.log("Global", window.a, "Block", a); //Global ƒ a() {} Block ƒ a() {} a = 1; console.log("Global", window.a, "Block", a); //Global ƒ a() {} Block 1 a = 3; console.log("Global", window.a, "Block", a); //Global ƒ a() {} Block 3 function a() {} console.log("Global", window.a, "Block", a); //Global 3 Block 3 a = 2; console.log("Global", window.a, "Block", a); //Global 3 Block 2 } console.log(a); //3
核心逻辑拆解
非严格模式下,JavaScript引擎对块内函数声明的处理是混合了变量提升和作用域绑定的特殊兼容规则,对应你的困惑点逐一拆解:
- 第一行输出
undefined:引擎会在全局作用域提前声明变量a,但不会提前赋值,所以此时全局a是undefined。 - 进入块后第一个
function a(){}:这一步同时完成两个操作:- 把全局的
a赋值为这个函数; - 在块作用域内创建同名局部变量
a,同样指向该函数。因此此时全局和块内的a指向同一个函数引用。
- 把全局的
- 赋值
a=1和a=3:块内的局部a已经覆盖了全局绑定,此时操作的是块内局部变量,全局a不受影响,仍保持原来的函数引用。 - 重声明
function a(){}:这是关键——非严格模式下,块内重复函数声明的逻辑是:读取当前块内局部a的当前值,将其同步赋值给全局a,但不会修改块内的局部a。所以全局a被更新为局部a的当前值3,而局部a因为已经存在绑定,不会被新的函数覆盖。 - 后续赋值
a=2:依然操作块内局部a,全局a保持之前同步的3,所以块外最终输出3。
简单来说,非严格模式下块内的重复函数声明,本质是一次「局部变量值同步到全局」的操作,而非重新定义函数。
内容的提问来源于stack exchange,提问作者Jay Mehta
相关产品推荐
相关产品推荐

