深入理解 let、var 和 const

JavaScript 中的变量声明有三种主要方式:varlet 和 const。理解它们之间的差异对于编写清晰、有效的代码至关重要。本文将深入探讨这三种声明方式的区别、使用场景以及潜在的陷阱。

一、var 关键字

1.1 特点

  1. 函数作用域var 声明的变量在函数内是局部变量,在函数外是全局变量。
  2. 变量提升var 声明的变量会被提升到其作用域的顶部,但不会初始化。

1.2 示例

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

function testVar() {
    var b = 20;
    if (true) {
        var b = 30; // 同一作用域内变量重定义
        console.log(b); // 30
    }
    console.log(b); // 30
}

testVar();
​
 
 

在上述示例中,a 的声明被提升到了脚本的顶部,但其初始化仍在原来的位置。b 在函数 testVar 内被重新声明并赋值,两个 b 变量实际指向同一个变量。

二、let 关键字

2.1 特点

  1. 块作用域let 声明的变量在其所在的块级作用域内有效。
  2. 无变量提升let 声明的变量不会被提升,必须在声明后才能使用。
  3. 暂时性死区:在块级作用域内,let 声明的变量在声明之前不可用。

2.2 示例

if (true) {
    console.log(c); // ReferenceError: c is not defined
    let c = 10;
    console.log(c); // 10
}

function testLet() {
    let d = 20;
    if (true) {
        let d = 30; // 块级作用域内变量重定义
        console.log(d); // 30
    }
    console.log(d); // 20
}

testLet();
​
 
 

在这个示例中,c 在声明之前不可用,导致了引用错误。d 在 if 块内和块外是两个不同的变量。

三、const 关键字

3.1 特点

  1. 块作用域const 声明的变量在其所在的块级作用域内有效。
  2. 不可重新赋值const 声明的变量一旦赋值后不能再更改。
  3. 无变量提升:与 let 类似,const 声明的变量不会被提升。
  4. 暂时性死区const 声明的变量在声明之前不可用。

3.2 示例

if (true) {
    const e = 10;
    console.log(e); // 10
    // e = 20; // TypeError: Assignment to constant variable.
}

const f = { value: 30 };
f.value = 40; // 允许修改对象属性
console.log(f.value); // 40

// f = { value: 50 }; // TypeError: Assignment to constant variable.
​
 
 

在这个示例中,e 的值不能被重新赋值。f 是一个对象,尽管对象的属性可以被修改,但 f 不能被重新赋值为另一个对象。

四、对比与选择

4.1 作用域

  • var:函数作用域或全局作用域。
  • let 和 const:块级作用域。

4.2 变量提升

  • var:声明提升,但不会初始化。
  • let 和 const:没有变量提升,存在暂时性死区。

4.3 重新赋值

  • var 和 let:可以重新赋值。
  • const:不可重新赋值,但对象的属性可变。

4.4 使用建议

  • 优先使用 const 声明变量,确保变量不会被意外重新赋值。
  • 需要重新赋值的变量使用 let
  • 避免使用 var,除非有特殊需求,因其作用域和提升行为可能导致难以调试的问题。

五、实际应用场景

5.1 使用 let 和 const 替代 var

在现代JavaScript代码中,let 和 const 的使用逐渐取代了 var。以下是一个重构示例:

// 旧代码使用 var
function exampleVar() {
    var name = 'Alice';
    var age = 25;
    console.log(name, age);
}

// 新代码使用 let 和 const
function exampleLetConst() {
    const name = 'Alice';
    let age = 25;
    console.log(name, age);
}
​
 
 

5.2 块级作用域中的使用

在循环中使用 let 避免全局变量污染:

for (let i = 0; i < 5; i++) {
    setTimeout(() => console.log(i), 1000);
}
​
 
 

在这个示例中,let 保证了每次循环的 i 都是独立的,而不是共享一个全局变量。

posted @ 2025-06-19 15:28  kang_ms  阅读(50)  评论(0)    收藏  举报