JavaScript变量声明提升

92 阅读3分钟

JavaScript变量声明提升

JavaScript 中的 变量声明提升(Hoisting) 是 JavaScript 引擎在代码执行前将变量和函数声明提升到作用域顶部的行为。理解变量声明提升有助于避免代码中的潜在错误。

1. 变量声明提升的原理

  • 提升(Hoisting):JavaScript 引擎在代码执行前会扫描整个作用域,将变量和函数声明提升到作用域的顶部。
  • 仅提升声明:变量的赋值操作不会被提升,只有声明部分会被提升。

2. 变量声明提升的行为

(1) var 声明的变量

  • 提升:声明会被提升到作用域顶部,但赋值不会。
  • 初始值:提升后的变量值为 undefined

示例

console.log(a); // 输出:undefined(声明提升,但未赋值)
var a = 10;
console.log(a); // 输出:10

实际执行顺序

var a; // 声明提升
console.log(a); // 输出:undefined
a = 10; // 赋值
console.log(a); // 输出:10

(2) letconst 声明的变量

  • 提升:声明会被提升,但不会初始化(进入“暂时性死区”)。
  • 初始值:在声明前访问会抛出 ReferenceError

示例

console.log(b); // 报错:ReferenceError: Cannot access 'b' before initialization
let b = 20;
console.log(b); // 输出:20

实际执行顺序

let b; // 声明提升,但未初始化
console.log(b); // 报错:暂时性死区
b = 20; // 赋值
console.log(b); // 输出:20

3. 函数声明提升

(1) 函数声明

  • 提升:整个函数声明(包括函数体)会被提升到作用域顶部。
  • 行为:可以在声明前调用。

示例

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

实际执行顺序

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

(2) 函数表达式

  • 提升:只有变量声明会被提升,函数赋值不会被提升。
  • 行为:在赋值前调用会报错。

示例

bar(); // 报错:TypeError: bar is not a function
var bar = function() {
  console.log('World');
};

实际执行顺序

var bar; // 声明提升
bar(); // 报错:bar 是 undefined
bar = function() {
  console.log('World');
};

4. 变量声明提升的作用域

  • 函数作用域var 声明的变量会提升到函数作用域顶部。
  • 块级作用域letconst 声明的变量会提升到块级作用域顶部,但在声明前不可访问。

示例

function test() {
  console.log(x); // 输出:undefined
  if (true) {
    var x = 10;
    let y = 20;
  }
  console.log(x); // 输出:10
  console.log(y); // 报错:ReferenceError: y is not defined
}
test();

5. 变量声明提升的注意事项

  1. 避免使用未声明的变量:未声明的变量不会提升,直接使用会报错。

    console.log(z); // 报错:ReferenceError: z is not defined
    
  2. 避免重复声明

    • var 允许重复声明,后声明的变量会覆盖前者。
    • letconst 不允许重复声明,会报错。

    示例

    var a = 1;
    var a = 2; // 允许
    console.log(a); // 输出:2
    
    let b = 1;
    let b = 2; // 报错:SyntaxError: Identifier 'b' has already been declared
    
  3. 优先使用 letconst

    • letconst 提供了块级作用域,避免了 var 的变量提升问题。

总结

声明方式提升行为初始值作用域
var声明提升,赋值不提升undefined函数作用域
let声明提升,但进入暂时性死区不可访问块级作用域
const声明提升,但进入暂时性死区不可访问块级作用域
函数声明整个函数(包括函数体)提升函数体函数作用域
函数表达式仅变量声明提升,函数体不提升undefined函数作用域

理解变量声明提升有助于编写更健壮的 JavaScript 代码,避免因变量作用域和声明顺序导致的错误。

更多vue相关插件及后台管理模板可访问vue admin reference,代码详情请访问github