const仅冻结变量绑定,不阻止对象/数组内部修改;需用Object.freeze()做浅层防护,深度嵌套需递归冻结,并配合命名规范与代码审查。

JS 中用 const 声明常量,本身已阻止“重新赋值”,但不能完全防止内容被修改——尤其是对象和数组。真正防意外修改,需要分层处理。
理解 const 的真实限制
const 锁定的是变量名与内存地址的绑定关系,不是值本身:
- 基础类型(string/number/boolean):赋值后确实不可改,如
const PI = 3.14,再写PI = 3.1415直接报错 - 引用类型(object/array):可修改内部属性或元素,如
const user = {name: 'Alice'},后续user.name = 'Bob'合法 - 不能在声明前访问(暂时性死区),也不能重复声明同一变量名
对对象/数组做浅层防护:Object.freeze()
冻结后,对象顶层属性不可增、删、改,配置特性也被锁定:
const config = Object.freeze({apiUrl: '/v1', timeout: 5000})- 尝试
config.apiUrl = '/v2'或config.newKey = 1都无效(非严格模式静默失败,严格模式报错) - 注意:
Object.freeze()只作用于当前层级,嵌套对象仍可变,例如config.nested.objProp = 'hacked'仍可能成功
需要深度防护时手动递归冻结
若配置含多层嵌套结构,需自己实现深冻结逻辑:
- 遍历对象所有属性,对每个子对象也调用
Object.freeze() - 跳过 null、原始值、函数、Symbol 键等非对象类型
- 用 WeakMap 记录已处理对象,避免循环引用导致栈溢出
- 实际项目中建议只对明确的静态配置对象使用,避免滥用影响性能
开发习惯与团队约束
技术手段之外,规范更能减少误操作:
- 命名约定:常量全大写加下划线,如
const MAX_RETRY_COUNT = 3,一眼识别不可变意图 - 默认先用 const,只有确认需重赋值时才换 let;var 已基本淘汰
- 模块顶层优先用 const 导出配置、工具函数等,配合 export 提升可维护性
- 代码审查时关注 const 变量是否被意外修改内部状态,必要时补
Object.freeze()


















