JavaScript 中的变量提升是什么?

变量提升指的是在 JavaScript 中,在编译阶段将变量和函数声明提前到其作用域顶部的行为,需注意赋值和访问顺序的问题。了解提升机制有助于避免一些常见的错误和提高代码的可维护性。

JavaScript 中等 JS基础 变量提升 作用域

提升(Hoisting)是 JavaScript 中的一种机制,指在执行代码之前,JavaScript 引擎会在编译阶段将变量声明和函数声明提升到它们所在作用域的顶部。这意味着声明的访问可以在定义位置之前进行,但赋值行为不会被提升。提升的行为因不同的声明类型(如 varletconst 和函数声明)而异。以下是详细解释:

1. 变量提升

  • var 声明:使用 var 声明的变量会被提升到作用域(函数或全局)的顶部,但只提升声明部分。如果声明前访问,值默认为 undefined
    • 示例代码:
      console.log(num); // 输出: undefined(声明提升但未赋值)
      var num = 10;    // 赋值在此处发生
      console.log(num); // 输出: 10
      

      等效执行过程:

      var num;          // 声明提升至顶部
      console.log(num); // undefined
      num = 10;         // 赋值保留在原位
      console.log(num); // 10
      
  • letconst 声明letconst 会提升声明,但不会初始化赋值,导致临时死区(Temporal Dead Zone, TDZ)。若在声明前访问,会抛出 ReferenceError
    • 示例代码:
      console.log(person); // TypeError: Cannot access 'person' before initialization
      let person = 'Alice';
      

      临时死区避免意外值赋值。

2. 函数提升

  • 函数声明:完整的函数声明(使用 function 关键字)被提升至作用域顶部,支持在声明前调用它。
    • 示例代码:
      greet(); // 输出: 'Hello!'
      function greet() {
        console.log('Hello!');
      }
      
  • 函数表达式:类似于变量提升,函数表达式只提升声明(未赋值),在赋值前访问会抛出错误。
    • 示例代码:
      sayHi(); // TypeError: sayHi is not a function
      var sayHi = function() {
        console.log('Hi!');
      };
      

      3. 其他规则

  • 优先级:函数声明提升优先级高于变量提升。同一作用域中的同名函数声明不会被同名变量覆盖,但在赋值后变量会覆盖函数。
    • 例如:
      function demo() {}
      var demo = 'value';
      console.log(typeof demo); // string (变量覆盖函数)
      
  • 提升作用范围:提升只发生在当前作用域内(如函数作用域)。块级作用域({})中的 var 声明也会提升到最近函数或全局作用域的顶部。

4. 作用机制分析

在编译阶段,引擎分配内存用于声明,并将声明移至作用域顶部。而在执行阶段才处理赋值和逻辑代码。优化了性能且避免了重复声明,但需注意 var 的陷阱(如默认值为 undefined)与 TDZ 的安全性需求。