JavaScript 中 let/const/var 的区别
变量声明方式比较
特性 | var | let | const |
---|---|---|---|
作用域 | 函数作用域 | 块级作用域 | 块级作用域 |
变量提升 | 是 | 否(暂时性死区) | 否(暂时性死区) |
重复声明 | 允许 | 不允许 | 不允许 |
初始化要求 | 不需要 | 不需要 | 必须初始化 |
全局声明时 | 成为全局对象属性 | 不成为全局对象属性 | 不成为全局对象属性 |
变量修改 | 可以 | 可以 | 不可以(对象内部属性可修改) |
详细解析
1. 作用域
var: 函数作用域 (Function Scope)
function varTest() {
var x = 1;
if (true) {
var x = 2; // 同一个变量
console.log(x); // 2
}
console.log(x); // 2
}
let/const: 块级作用域 (Block Scope)
function letTest() {
let x = 1;
if (true) {
let x = 2; // 不同的变量
console.log(x); // 2
}
console.log(x); // 1
}
2. 变量提升
var: 存在变量提升
console.log(a); // undefined (不会报错)
var a = 1;
// 等同于:
var a;
console.log(a); // undefined
a = 1;
let/const: 不存在变量提升,有"暂时性死区"
console.log(b); // ReferenceError: Cannot access 'b' before initialization
let b = 2;
// const 表现相同
console.log(c); // ReferenceError: Cannot access 'c' before initialization
const c = 3;
3. 重复声明
var: 允许重复声明
var a = 1;
var a = 2; // 合法,a = 2
let/const: 不允许在同一作用域重复声明
let b = 1;
let b = 2; // SyntaxError: Identifier 'b' has already been declared
const c = 1;
const c = 2; // SyntaxError: Identifier 'c' has already been declared
4. 初始化要求
var/let: 可以先声明后赋值
var a;
a = 1;
let b;
b = 2;
const: 声明时必须初始化
const c; // SyntaxError: Missing initializer in const declaration
const c = 3; // 正确
5. 全局声明
var: 在全局作用域中声明的变量会成为全局对象(window/global)的属性
var globalVar = "global";
console.log(window.globalVar); // 'global'
let/const: 不会成为全局对象的属性
let globalLet = "not global";
const globalConst = "not global";
console.log(window.globalLet); // undefined
console.log(window.globalConst); // undefined
6. 可修改性
var/let: 声明的变量可以重新赋值
var a = 1;
a = 2; // 合法
let b = 1;
b = 2; // 合法
const: 声明的变量不可重新赋值,但如果值是对象,其属性可以修改
const c = 1;
c = 2; // TypeError: Assignment to constant variable
const obj = { prop: 1 };
obj.prop = 2; // 合法 - 对象属性可以修改
obj = {}; // TypeError: Assignment to constant variable
最佳实践
- 默认使用 const:如果一个变量不需要重新赋值,始终使用 const 声明
- 需要重新赋值时使用 let:只在确实需要重新赋值的变量上使用 let
- 避免使用 var:在现代 JavaScript 中,几乎没有必要使用 var
- 在循环中使用 let:特别是在 for 循环中,let 能创建每次迭代的独立变量
延伸问题
- let/const/var 三者间的主要区别是什么?
- 什么是暂时性死区(Temporal Dead Zone)?
- const 声明的对象,为什么其属性可以被修改?
- 在什么情况下应该使用 var?
- let 和 const 如何影响闭包和循环?