Object.freeze不会主动报错,仅在严格模式下尝试修改时抛TypeError;应于对象构造完毕后立即冻结,嵌套结构需deepFreeze,配合严格模式、ESLint和测试校验,并避免原型链及特殊类型干扰。

Object.freeze 本身不会引发报错,报错只会在你尝试修改被冻结对象时发生——尤其在严格模式下。避免报错的关键不是“不让它报”,而是“不触发修改行为”+“提前预防误操作”。
明确冻结时机与范围
冻结必须在对象完全构造完毕后立即执行,且不能在模块导出后、被其他模块引用后再冻结。
- 错误做法:先
export default config,再在别处调用Object.freeze(config)—— 此时其他模块已拿到未冻结的引用,冻结无效 - 正确做法:在配置对象定义后、任何
import或使用前就冻结,例如:const config = { api: { url: '...' } }; Object.freeze(config); export default config; - 若含嵌套结构,必须用
deepFreeze递归冻结,否则config.api.url = 'new'不会报错但会静默失败或意外生效
启用严格模式并统一开发环境
非严格模式下修改冻结对象仅静默失败,问题难以发现;严格模式则直接抛 TypeError,便于定位。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 在脚本顶部加
"use strict";,或确保整个项目运行在严格模式(ES 模块默认严格) - 配合 ESLint 规则如
no-param-reassign、no-const-assign,在编码阶段拦截潜在修改 - 测试中可主动检查:
if (!Object.isFrozen(config)) throw new Error('配置未冻结')
规避原型链与特殊类型干扰
冻结只作用于对象自身属性,不影响原型链或内置对象实例,这些地方容易成为漏洞。
立即学习“Java免费学习笔记(深入)”;
- 不要把
Date、RegExp、Map等放入配置对象——它们无法被Object.freeze安全处理,且typeof返回'object'可能导致deepFreeze出错 - 若需彻底防污染,可在应用启动最早期冻结原生原型:
Object.freeze(Object.prototype)(注意:需放在所有第三方脚本之前) - 避免通过
obj.__proto__.x = 1或Reflect.set(obj, 'x', 1, obj.__proto__)绕过冻结——冻结后这类操作不影响对象自身,但会污染原型,应提前切断继承:Object.setPrototypeOf(config, null)
用只读语义替代运行时冻结
对纯配置场景,冻结是防御手段;但更优解是让修改在语法或设计层面就不成立。
- 用
const声明 + 冻结双保险:const CONFIG = Object.freeze({...}),既锁变量绑定,又锁内容 - 配置尽量扁平化,避免深度嵌套;必须嵌套时,用
Object.freeze封装每一层子对象,而非依赖单次调用 - 在构建时生成不可变配置(如通过 Webpack DefinePlugin 注入常量),从源头移除运行时修改可能性

















