为什么要使用 const?使用 const 有什么好处和坏处?
核心答案
const 是 ES6 引入的声明常量的关键字,用于声明不可重新赋值的变量。使用 const 的核心价值在于:
- 语义化表达意图:明确告诉其他开发者这个变量不会被重新赋值
- 防止意外修改:在编译/运行时捕获意外的重新赋值错误
- 代码可预测性:减少变量状态追踪的心智负担
深入解析
原理层面
1. const 的本质:绑定不可变,而非值不可变
const obj = { name: 'Alice' };
obj.name = 'Bob'; // ✅ 允许:修改对象属性
obj = { name: 'Bob' }; // ❌ TypeError:不允许重新赋值
const 保证的是变量与内存地址之间的绑定关系不变,而不是内存中的值不变。
2. 块级作用域
与 let 一样,const 具有块级作用域,解决了 var 的变量提升和函数作用域问题:
if (true) {
const x = 10;
}
console.log(x); // ReferenceError: x is not defined
3. 暂时性死区(TDZ)
console.log(a); // ReferenceError
const a = 1; // 在声明前访问会报错
好处
| 优点 | 说明 |
|---|---|
| 意图清晰 | 一眼就知道这个变量不会被重新赋值 |
| 防止 bug | 避免意外覆盖重要变量 |
| 便于优化 | 引擎可以做更好的优化(理论上) |
| 函数式友好 | 符合不可变数据的编程范式 |
| 团队协作 | 代码更易读、更可维护 |
坏处/局限
| 缺点 | 说明 |
|---|---|
| 引用类型可变 | 对象、数组的内容仍可被修改,容易误解 |
| 必须初始化 | 声明时必须赋值,不能先声明后赋值 |
| 循环中受限 | 不能用于需要递增的传统 for 循环计数器 |
常见误区
误区一:const 声明的对象完全不可变
错误!只是引用不可变,需要 Object.freeze() 实现浅层冻结:
const obj = Object.freeze({ a: 1 });
obj.a = 2; // 静默失败(严格模式报错)
误区二:const 比 let 性能更好
现代 JavaScript 引擎对 const 和 let 的性能优化几乎相同,选择应基于语义而非性能。
代码示例
// ✅ 推荐:不会重新赋值的变量用 const
const API_URL = 'https://api.example.com';
const user = { name: 'Alice', age: 25 };
const numbers = [1, 2, 3];
// 对象和数组的内容可以修改
user.age = 26; // ✅
numbers.push(4); // ✅
// ❌ 不能重新赋值
// API_URL = 'xxx'; // TypeError
// user = {}; // TypeError
// ✅ 循环中使用 const(for...of / for...in)
for (const item of numbers) {
console.log(item); // 每次迭代创建新的绑定
}
// ❌ 传统 for 循环计数器不能用 const
// for (const i = 0; i < 10; i++) {} // TypeError
// ✅ 用 let 处理需要重新赋值的场景
let count = 0;
count++;
实现真正的不可变
// 浅冻结
const frozen = Object.freeze({ a: 1, b: { c: 2 } });
frozen.a = 100; // 无效
frozen.b.c = 100; // 有效!嵌套对象未冻结
// 深冻结需要递归处理或使用 Immutable.js / Immer 等库
面试技巧
可能的追问
-
const、let、var 的区别?
- 作用域、变量提升、TDZ、重复声明、全局对象属性
-
const 声明的对象如何实现完全不可变?
Object.freeze()(浅)、递归冻结、Immutable.js、Immer
-
什么时候用 let,什么时候用 const?
- 默认用
const,只有需要重新赋值时才用let
- 默认用
-
const 在循环中的表现?
for...of/for...in可用(每次迭代新绑定)- 传统
for循环计数器不可用
展示深度的回答技巧
- 提到 TDZ(暂时性死区) 展示对执行机制的理解
- 区分 绑定不可变 vs 值不可变 展示对底层原理的掌握
- 结合 函数式编程 和 不可变数据 展示编程范式视野
一句话总结
const 保证的是"变量绑定不可变"而非"值不可变",默认优先使用 const,只有需要重新赋值时才用 let,永远不用 var。