deepFreeze 的核心目标是递归冻结嵌套对象所有层级,使其属性不可修改、添加、删除或重配置;它跳过原始值和 null,支持数组与循环引用(借助 WeakMap 避免重复冻结),但不处理 Symbol、Date、RegExp 等内置对象内部状态及函数闭包变量。

深度冻结函数 deepFreeze 的核心目标是:让嵌套对象及其所有层级的属性都变为不可修改、不可添加、不可删除、不可重配置——即真正意义上的“只读常量结构”。它不是简单调用 Object.freeze() 一层,而是递归地冻结每个对象属性(包括数组、普通对象,跳过原始值和 null)。
理解 deepFreeze 的作用边界
deepFreeze 不改变对象引用关系,也不处理 Symbol 属性(除非显式遍历)、不冻结 Date/RegExp/Map/Set 等内置类实例(它们本身不可扩展但内部状态仍可变),更不处理函数——函数对象虽被冻结,其闭包内变量仍可变。它只保证对象自身的属性描述符被锁定,且对每个子对象重复该操作。
基础实现:递归冻结 + 类型判断
关键逻辑:先冻结当前对象,再遍历其自有可枚举属性,对每个 对象类型(非 null,且 typeof === 'object') 递归调用 deepFreeze。注意避开原始值、null、数组(数组也是 object,需单独处理或统一处理)。
- 用
Object.isFrozen(obj)提前返回,避免重复冻结 - 用
Object.getOwnPropertyNames(obj)获取所有自有属性(含不可枚举) - 对每个属性值,若为对象且未冻结,则递归冻结
- 最后调用
Object.freeze(obj)锁定当前层
支持数组与循环引用的健壮版本
真实场景中,对象可能含数组或存在循环引用(如 a.b = a)。此时需引入 WeakMap 缓存已冻结对象,防止无限递归;同时把数组视为普通对象处理(Array.isArray(val) 判断后同样递归冻结其元素)。
- 初始化一个
WeakMap记录obj → frozenObj映射 - 每次进入函数,先查缓存,命中则直接返回缓存值
- 冻结前先设缓存占位(避免递归时重复进入),再执行冻结逻辑
- 数组元素若为对象,同样递归冻结;原始值无需处理
使用示例与验证技巧
冻结后可用 Object.isFrozen() 检查顶层,但要确认嵌套层是否生效,需手动尝试修改深层属性:
const obj = { a: { b: [1, 2] } }; deepFreeze(obj);-
obj.a.b.push(3)→ 报错(数组被冻结) -
obj.a.c = 4→ 静默失败(严格模式下报错) -
Object.defineProperty(obj.a, 'b', { value: [] })→ 报错(不可重配置)
注意:冻结后仍可读取、遍历、JSON.stringify,但任何写操作都会失效(非严格模式下静默,严格模式抛 TypeError)。


















