JavaScript 中的提升
发布: (2026年2月10日 GMT+8 23:30)
4 分钟阅读
原文: Dev.to
Source: Dev.to
理解执行上下文
JavaScript 并 不是 按严格的自上而下顺序执行代码。
在任何代码运行之前,引擎会创建一个 执行上下文,在其中它会:
- 为变量和函数分配内存。
- 将函数声明存入内存。
- 将
var声明的变量的初始值设为undefined。
这个 创建阶段 正是 提升(hoisting) 发生的地方——声明会被移动到其作用域的顶部,但实际代码 不会 被移动。
变量提升(var)
// Example
console.log(x); // → undefined, not a ReferenceError
var x = 10;
- 在创建阶段,JavaScript 为
x分配内存并将其初始化为undefined。 - 该变量的作用域是 函数级,而不是块级。
重要
这不是错误,因为x已经在创建阶段被创建;它只是在赋值语句执行之前保持undefined。
函数提升
// Function declaration
printMessage(); // Works because the function is hoisted
function printMessage() {
console.log('Hello, world!');
}
- 整个函数定义会在创建阶段存入内存。
- 因此,引擎在执行到调用之前就已经知道
printMessage是什么。
当执行开始时:
- 第 1 行 – 调用
printMessage()(函数已经被认识)。 - 第 2 行 –
console.log(x);输出undefined。 - 第 3 行 –
x = 10;为变量赋值。
最终输出
undefined
Hello, world!
函数表达式和箭头函数
// Function expression
const greet = function() {
console.log('Hi');
};
greet(); // Works after the assignment
// Arrow function (behaves like a function expression)
const add = (a, b) => a + b;
- 函数 表达式(包括箭头函数)并不会像声明那样被提升。
- 变量名(
greet、add)会被提升(var为undefined,let/const则进入暂时性死区),但实际的函数值只有在代码执行到表达式时才会赋值。
因此,在定义之前调用函数表达式会导致:
- 对
let/const声明的变量抛出ReferenceError。 - 对
var声明且仍为undefined的变量抛出TypeError。
关键要点
- 提升 发生在执行上下文的 创建阶段,而不是在代码执行期间。
var声明会被提升,并且初始值为undefined。- 函数 声明 会被完整提升,使其能够在源代码中出现之前被调用。
- 函数 表达式 和 箭头函数 被视为普通变量赋值;只有变量名被提升,函数值不会被提升。
- 理解这些规则可以让 JavaScript 的执行模型更可预测,也更易于推理。