2.3 变量提升(Hoisting)的机制

2.3 变量提升(Hoisting)的机制

变量提升(Hoisting)是 JavaScript 中一个重要的概念,它描述了变量和函数声明在代码执行前的行为。本节将详细讲解变量提升的机制,以及它对代码执行的影响。


2.3.1 什么是变量提升?

变量提升是指 JavaScript 引擎在执行代码之前,会将变量和函数的声明提升到其所在作用域的顶部。需要注意的是:

  • 声明会被提升,但赋值不会
  • 变量提升只适用于 var 声明的变量和函数声明,不适用于 letconst

2.3.2 var 的变量提升

1. 变量声明提升
使用 var 声明的变量会被提升到作用域的顶部,但赋值操作不会被提升:

console.log(x); // 输出 undefined
var x = 10;

等价于:

var x; // 声明被提升
console.log(x); // 输出 undefined
x = 10; // 赋值未被提升

2. 重复声明
var 允许重复声明同一个变量,后面的声明会覆盖前面的:

var x = 10;
var x = 20;
console.log(x); // 输出 20

2.3.3 函数声明提升

函数声明也会被提升,且整个函数体都会被提升:

foo(); // 输出 "Hello"
function foo() {
  console.log("Hello");
}

等价于:

function foo() {
  console.log("Hello");
}
foo(); // 输出 "Hello"

注意:函数表达式不会被提升:

bar(); // 报错:TypeError
var bar = function () {
  console.log("World");
};

等价于:

var bar; // 声明被提升
bar(); // 报错:TypeError
bar = function () {
  console.log("World");
};

2.3.4 letconst 的暂时性死区(TDZ)

letconst 声明的变量不会被提升,且在声明之前访问会触发暂时性死区(TDZ):

console.log(x); // 报错:ReferenceError
let x = 10;

2.3.5 变量提升的优先级

在同一个作用域中,函数声明优先于变量声明:

console.log(foo); // 输出函数 foo
var foo = 10;
function foo() {
  console.log("Hello");
}

等价于:

function foo() {
  console.log("Hello");
}
var foo; // 重复声明,被忽略
console.log(foo); // 输出函数 foo
foo = 10;

2.3.6 变量提升的示例

示例 1:var 的变量提升

console.log(a); // 输出 undefined
var a = 10;
console.log(a); // 输出 10

示例 2:函数声明提升

foo(); // 输出 "Hello"
function foo() {
  console.log("Hello");
}

示例 3:函数表达式不会提升

bar(); // 报错:TypeError
var bar = function () {
  console.log("World");
};

示例 4:letconst 的 TDZ

console.log(x); // 报错:ReferenceError
let x = 10;

2.3.7 总结

  • var 的变量提升:声明被提升到作用域顶部,但赋值不会被提升。
  • 函数声明提升:整个函数体被提升,可以在声明前调用。
  • letconst 的 TDZ:声明不会被提升,且在声明前访问会报错。
  • 优先级:函数声明优先于变量声明。

理解变量提升的机制有助于避免代码中的潜在问题,尤其是在使用 var 和函数声明时。现代开发中,建议优先使用 letconst,以减少变量提升带来的困扰。


思考题

  1. 为什么 var 的变量提升会导致代码难以维护?
  2. 函数声明和函数表达式的提升行为有什么区别?
  3. 如何避免暂时性死区(TDZ)导致的错误?
#前端开发 分享于 2025-03-12

【 内容由 AI 共享,不代表本站观点,请谨慎参考 】