You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

函数声明的变量提升机制是怎样的?块级作用域内外为何表现不同?

理解块级函数声明的提升行为

首先咱们先把你的代码完整贴出来,方便一步步分析:

console.log("1:"+foo); 
{ 
  console.log("2:"+foo); 
  function foo(){ console.log("checked"); } 
  console.log("3:"+foo); 
} 
console.log("4:"+foo);

这个现象的核心是ES6标准对块级函数声明的提升规则做了明确调整,和传统全局/函数作用域里的函数提升逻辑有差异,咱们分阶段拆解:

1. 全局作用域的预编译阶段

在代码正式执行前,JavaScript引擎会先扫描全局作用域:

  • 发现块级作用域内有function foo()声明,会在全局作用域提前创建一个名为foo的变量(这是ES6非严格模式下的规则:块级函数会提升到外层作用域),但只做声明,不会赋值,所以此时全局的foo是undefined。
  • 这就是第一个console.log("1:"+foo)输出1:undefined的原因。

2. 进入块级作用域后的预编译

当代码执行到{}这个块级作用域时,引擎会单独扫描这个块的内容:

  • 块内的function foo()会被完全提升到块的顶部(声明+赋值,和函数作用域里的普通函数提升逻辑一致),所以在块内的第一个console.log("2:"+foo)就能直接拿到foo函数本身,输出2:function foo(){ console.log("checked"); }。
  • 当执行到function foo(){...}这行代码时,本质是再次给块内的foo赋值(和预编译时的赋值是同一个函数,所以没有变化),所以第三个console.log("3:"+foo)依然输出函数本身。

3. 块级作用域执行完毕后

当块内代码执行完成,非严格模式下,块级函数会被赋值给外层作用域(这里是全局)的同名变量,所以此时全局的foo从undefined变成了foo函数本身,最后一个console.log("4:"+foo)就输出函数内容了。

补充个小细节:如果是在严格模式下,块级函数只会被提升到块内的顶部,外层作用域不会提前创建foo变量,此时第一个console.log会直接抛出ReferenceError,这是严格模式和非严格模式的关键区别。

内容的提问来源于stack exchange,提问作者MaximPro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 03:32:14