const 只锁定引用而非值,故对象/数组内容仍可修改;需配合 Object.freeze()(浅冻结)或 structuredClone()+freeze(深冻结)等手段实现真正不可变。
const 不能锁定值,只能锁定引用;想防意外修改,得配合不可变数据结构或深度冻结。
const 声明的对象/数组仍可被修改const 只保证变量绑定的内存地址不变,不阻止对引用目标内容的更改。比如:
const user = { name: 'Alice' };user.name = 'Bob'; // ✅ 合法 —— 引用没变,只是对象内部变了user = {}; // ❌ 报错 —— 尝试重新赋值引用
常见错误现象:函数接收 const 参数后仍意外改了传入对象,导致上游状态混乱。
const 能防止深层修改,尤其在多人协作或封装函数时漏掉防御性拷贝Object.freeze() 或 structuredClone()
Object.freeze() 是最轻量的运行时防护,但它只做浅冻结——嵌套对象仍可变:
const config = Object.freeze({ api: { url: '/v1' } });config.api.url = '/v2'; // ✅ 依然能改!
若需深冻结,目前没有标准 API,推荐方案:
structuredClone() + 再次 Object.freeze()(注意兼容性,Node.js ≥17.4 / Chrome ≥98)immer 的 produce 或手写递归冻结(慎用,有性能代价)readonly 修饰符仅限编译期检查,不防运行时数组用 const 声明后,push、splice 等方法照常生效:
const list = [1, 2];list.push(3); // ✅ 合法list = [4, 5]; // ❌ 报错
若需真正只读数组,可:
Object.freeze(list) 冻结数组本身(但元素如果是对象,其属性仍可变)Array.from(list) 或展开语法创建新数组再冻结,避免意外共享引用const fn = () => {} 不影响其内部逻辑,也不阻止重绑定 fn.prototype
真正难防的是跨作用域的引用共享,比如一个 const 对象被多个函数闭包持有,其中任一函数修改它,所有地方都感知得到——这时候光靠 const 没用,得从数据流设计上切断可变链。