变量提升的底层原理是什么?带你从ECMAScript规范理解hoisting
🧑🏫 作者:全栈老李
📅 更新时间:2025 年 5 月
🧑💻 适合人群:前端初学者、进阶开发者
🚀 版权:本文由全栈老李原创,转载请注明出处。
今天咱们来聊聊前端面试必考题——变量提升(hoisting)。很多同学都知道"变量会提升",但能说清楚底层原理的却不多。作为"全栈老李"的忠实读者,咱们可不能只停留在表面理解,得深入ECMAScript规范看看这玩意儿到底是怎么运作的。
你以为的变量提升可能都是错的
先来看个经典例子:
console.log(a); // 输出什么?
var a = 10;
大多数人都知道这里会输出undefined
,而不是报错。这就是变量提升的效果——声明被"提升"到了作用域顶部。但真相真的这么简单吗?
实际上,JavaScript引擎根本不会移动你的代码!所谓的"提升"只是ECMAScript规范中执行上下文创建阶段的一个副作用。下面咱们就拆开这个黑盒子看看。
执行上下文与变量环境
当JS引擎执行代码时,会创建执行上下文(Execution Context)。这就像拍电影时的场景布置——在真正"开拍"(代码执行)前,得先把场景(变量、函数等)准备好。
执行上下文的创建分为两个阶段:
- 创建阶段
- 执行阶段
关键来了:变量提升就发生在创建阶段!此时引擎会:
- 创建变量环境(Variable Environment)
- 扫描代码找出所有声明
- 在变量环境中注册这些声明
用伪代码表示这个过程:
// 创建阶段
ExecutionContext = {
VariableEnvironment: {
a: undefined // 先注册变量,初始值为undefined
}
}
// 执行阶段
console.log(a); // 查找VariableEnvironment中的a
a = 10