一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

如何用 const 锁定变量引用以降低程序中的意外状态修改

时间:2026-06-28 09:57:56 编辑:袖梨 来源:一聚教程网

const 只锁定引用而非值,故对象/数组内容仍可修改;需配合 Object.freeze()(浅冻结)或 structuredClone()+freeze(深冻结)等手段实现真正不可变。

const 不能锁定值,只能锁定引用;想防意外修改,得配合不可变数据结构或深度冻结。

为什么 const 声明的对象/数组仍可被修改

const 只保证变量绑定的内存地址不变,不阻止对引用目标内容的更改。比如:

const user = { name: 'Alice' };user.name = 'Bob'; // ✅ 合法 —— 引用没变,只是对象内部变了user = {}; // ❌ 报错 —— 尝试重新赋值引用

常见错误现象:函数接收 const 参数后仍意外改了传入对象,导致上游状态混乱。

  • 适用场景:声明配置对象、模块常量、DOM 元素引用等“不换人但可能动东西”的情况
  • 性能影响:零开销,纯语法约束,运行时不介入
  • 容易踩的坑:误以为 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)
  • 复杂嵌套:引入 immerproduce 或手写递归冻结(慎用,有性能代价)
  • 构建时防护:TypeScript 的 readonly 修饰符仅限编译期检查,不防运行时

数组和函数也得按需处理

数组用 const 声明后,pushsplice 等方法照常生效:

const list = [1, 2];list.push(3); // ✅ 合法list = [4, 5]; // ❌ 报错

若需真正只读数组,可:

  • Object.freeze(list) 冻结数组本身(但元素如果是对象,其属性仍可变)
  • Array.from(list) 或展开语法创建新数组再冻结,避免意外共享引用
  • 函数本身是引用类型,const fn = () => {} 不影响其内部逻辑,也不阻止重绑定 fn.prototype

真正难防的是跨作用域的引用共享,比如一个 const 对象被多个函数闭包持有,其中任一函数修改它,所有地方都感知得到——这时候光靠 const 没用,得从数据流设计上切断可变链。

热门栏目