Object.freeze仅浅冻结对象自身:禁止增删改自有属性、修改描述符及原型,但不冻结原型链和嵌套对象;需递归实现深冻结,且无法解冻。

Object.freeze 只冻结对象自身的可枚举属性,不冻结原型链,也不递归冻结嵌套对象。
它能做什么(有限但明确)
调用 Object.freeze(obj) 后:
- 不能添加、删除或重新配置对象自身的属性(
configurable: false) - 不能修改自身属性的值(所有自有数据属性变为
writable: false) - 不能改变对象的原型(
__proto__或[[Prototype]]被锁定) - 返回原对象(不创建新对象),且严格模式下对违规操作抛出
TypeError
它不能做什么(常见误解)
以下情况 不受保护:
-
原型上的属性和方法仍可被修改:冻结只作用于对象自身,不影响
obj.__proto__或其原型链上任何对象 - 嵌套对象/数组未被深度冻结:若属性值是另一个对象,该子对象本身仍可修改
- Symbol 属性同样被冻结(这点常被忽略,但其实是受保护的)
如何真正“彻底冻结”(含原型与嵌套)
没有内置 API 一键冻结原型和所有嵌套,但可组合实现:
- 先冻结目标对象:
Object.freeze(obj) - 手动冻结原型(如果需要):
Object.freeze(Object.getPrototypeOf(obj))(注意:这会影响所有继承自该原型的实例) - 对嵌套对象递归冻结(浅 freeze 不够时):
function deepFreeze(obj) {
if (obj !== null && typeof obj === 'object') {
Object.getOwnPropertyNames(obj).forEach(prop => {
if (obj[prop] !== null && typeof obj[prop] === 'object') {
deepFreeze(obj[prop]);
}
});
}
return Object.freeze(obj);
}
⚠️ 注意:此函数不处理循环引用,生产环境需额外判断。
验证是否真的冻结了
可用以下方式检查关键行为:
-
Object.isFrozen(obj)→ 返回布尔值(仅检测自身,不查原型) -
Object.getOwnPropertyDescriptor(obj, 'prop')→ 查看writable和configurable是否为false -
Object.getPrototypeOf(obj) === originalProto→ 确认原型未被替换 - 尝试
obj.newProp = 1或obj.existing = 'new'→ 严格模式下应报错


















