JS 中 var、let、const 的区别联系
在 JavaScript 里,let
和 const
都是 ES6(ES2015)新增的声明变量的方式,它们在很多方面和传统的 var
有所不同。下面将深入剖析它们的区别、联系以及使用方法,并结合具体案例进行说明。
1. 块级作用域(Block Scope)
let
和 const
都具备块级作用域,也就是说,变量的作用范围被限制在当前的代码块(由 {}
包裹)内。与之不同的是,var
的作用域是函数级的。
案例:
function testScope() {if (true) {var x = 10; // 函数级作用域let y = 20; // 块级作用域const z = 30; // 块级作用域}console.log(x); // 输出: 10console.log(y); // 报错: ReferenceErrorconsole.log(z); // 报错: ReferenceError
}
testScope();
2. 变量提升(Hoisting)
尽管 let
和 const
存在变量提升的情况,但在声明语句执行之前,它们处于 “暂时性死区”(Temporal Dead Zone, TDZ),无法被访问。而 var
会被提升到函数或全局作用域的顶部,并且可以在声明前使用(值为 undefined
)。
案例:
console.log(a); // 输出: undefined
console.log(b); // 报错: ReferenceError
var a = 1;
let b = 2;
3. 不可重复声明
在同一作用域内,let
和 const
不允许重复声明已有的变量,而 var
则可以。
案例:
let x = 10;
// let x = 20; // 报错: SyntaxErrorconst y = 100;
// const y = 200; // 报错: SyntaxErrorvar z = 5;
var z = 15; // 不会报错,后声明的会覆盖前面的
4. 必须初始化
使用 const
声明常量时,必须同时进行初始化赋值,后续也不能再重新赋值。而 let
声明的变量则可以先声明,之后再赋值。
案例:
// const PI; // 报错: SyntaxError
const PI = 3.14;
// PI = 3.14159; // 报错: TypeErrorlet count;
count = 1; // 合法
5. 常量引用与值的不可变性
const
保证的是变量引用的不可变性,而非值的不可变性。对于引用类型(如对象、数组),可以修改其内部属性。
案例:
const person = { name: 'Alice' };
person.name = 'Bob'; // 合法,修改对象属性
// person = { name: 'Charlie' }; // 报错: TypeErrorconst numbers = [1, 2, 3];
numbers.push(4); // 合法,修改数组内容
// numbers = [5, 6, 7]; // 报错: TypeError
6. 循环中的行为差异
在循环中,let
和 const
的表现与 var
有很大不同。let
和 const
会为每次迭代创建独立的变量副本。
案例:
// 使用 var 的情况
for (var i = 0; i < 3; i++) {setTimeout(() => console.log(i), 100); // 输出: 3, 3, 3
}// 使用 let 的情况
for (let j = 0; j < 3; j++) {setTimeout(() => console.log(j), 100); // 输出: 0, 1, 2
}// 使用 const 的情况(在 for 循环中需要特别注意)
for (const k = 0; k < 3; k++) { // 报错: TypeError(k 是常量,无法更新)setTimeout(() => console.log(k), 100);
}// 正确使用 const 的场景(for...of 循环)
const arr = [10, 20, 30];
for (const num of arr) {setTimeout(() => console.log(num), 100); // 输出: 10, 20, 30
}
最佳实践建议
- 优先使用
const
:除非确定变量需要被重新赋值,否则应优先使用const
。这样可以提高代码的安全性和可维护性。 - 使用
let
替代var
:由于let
具有块级作用域,能有效避免变量提升带来的问题,因此应尽量用let
替代var
。 - 避免重复声明:在同一作用域内,不要重复声明同一个变量。
- 常量命名规范:对于真正的常量(如配置项、数学常数),建议使用全大写字母加下划线的命名方式,例如
MAX_SIZE
。
总结
特性 | let | const | var |
---|---|---|---|
作用域 | 块级 | 块级 | 函数级 |
变量提升 | 存在(TDZ) | 存在(TDZ) | 存在 |
可重新赋值 | 是 | 否 | 是 |
可重复声明 | 否 | 否 | 是 |
必须初始化 | 否 | 是 | 否 |
理解 let
和 const
的区别,有助于编写更安全、更清晰的 JavaScript 代码,减少潜在的错误。在实际开发中,应根据变量是否需要重新赋值来选择合适的声明方式。