JavaScript 中let、var和const的主要区别总结:
| 特性 | var | let | const |
|---|---|---|---|
| 作用域 | 函数作用域(function-scoped) | 块级作用域(block-scoped) | 块级作用域(block-scoped) |
| 变量提升(Hoisting) | 是(提升至函数顶部,初始值为undefined) | 是(提升但不初始化,处于“暂时性死区”) | 是(提升但不初始化,处于“暂时性死区”) |
| 可重复声明 | 允许在同一作用域内重复声明 | 不允许在同一块作用域内重复声明 | 不允许在同一块作用域内重复声明 |
| 可重新赋值 | ✅ 可以重新赋值 | ✅ 可以重新赋值 | ❌ 不能重新赋值(但对象/数组内容可修改) |
| 初始化要求 | 可不初始化(默认undefined) | 可不初始化 | 必须在声明时初始化 |
| 全局对象属性 | 在全局作用域中声明会挂载到window(浏览器)或global(Node.js) | 不会挂载到全局对象 | 不会挂载到全局对象 |
| 适用场景 | 旧代码兼容(不推荐新项目使用) | 需要重新赋值的变量 | 声明后值不变的常量(如配置、API 地址等) |
补充说明:
- “暂时性死区”(Temporal Dead Zone, TDZ):在块级作用域内,
let和const声明的变量在声明前不可访问,否则会抛出ReferenceError。 const的“不可变”是引用不可变:对于对象或数组,虽然不能重新赋值,但可以修改其内部属性或元素。
Js
const obj = { a: 1 }; obj.a = 2; // ✅ 合法 obj = {}; // ❌ 报错:Assignment to constant variable.✅最佳实践:优先使用
const,需要重新赋值时用let,避免使用var。
const不能重新赋值(但对象/数组内容可修改)
在 JavaScript 中,const声明的变量不能重新赋值,但对象或数组的内容可以被修改。这看似矛盾,其实源于 JavaScript 中值类型(primitive)和引用类型(reference)的区别。
一、核心原理:const保证的是“绑定不变”,不是“值不变”
const的含义是:变量标识符与内存地址的绑定是常量。- 对于基本类型(如 number、string、boolean 等),值直接存储在变量中,因此值不可变。
- 对于引用类型(如 object、array、function),变量存储的是指向堆内存中对象的引用(地址),
const只保证这个引用地址不变,但不阻止你修改该地址所指向的对象内容。
二、示例对比
✅ 基本类型(不可变)
const x = 10; x = 20; // ❌ TypeError: Assignment to constant variable.因为
x直接保存值10,重新赋值会改变绑定,违反const规则。
✅ 引用类型(引用不可变,内容可变)
const user = { name: "Alice" }; user.name = "Bob"; // ✅ 合法:修改对象属性 user.age = 30; // ✅ 合法:添加新属性 // user 仍然指向同一个对象,只是对象内部变了 user = { name: "Charlie" }; // ❌ TypeError: Assignment to constant variable.这里
user变量保存的是对象的引用地址。只要不把user指向另一个新对象(即不改变引用),就符合const的规则。
数组同理:
Js
const colors = ["red", "green"]; colors.push("blue"); // ✅ 合法:修改数组内容 colors[0] = "yellow"; // ✅ 合法 colors = ["black"]; // ❌ 报错:试图重新赋值整个变量三、如何让对象真正“不可变”?
如果希望对象内容也不能被修改,可以使用Object.freeze():
const user = Object.freeze({ name: "Alice" }); user.name = "Bob"; // 在严格模式下会报错;非严格模式下静默失败(无效果)注意:
Object.freeze()是浅冻结,嵌套对象仍可能被修改。如需深度冻结,需递归实现。
四、总结
| 类型 | const行为 |
|---|---|
| 基本类型 | 值完全不可变 |
| 引用类型 | 引用地址不可变,但对象/数组内部可变 |
💡记住:
const≠ “不可变数据”,而是“不可重新赋值的变量”。
若需要真正的不可变性,应结合Object.freeze()或使用不可变数据库(如 Immutable.js)。