Object.freeze()完全冻结对象,禁止增删属性、修改属性描述符及数据属性值;Object.seal()仅密封结构,禁止增删属性但允许修改已有可写属性值;二者均为浅操作,不递归处理嵌套对象。

在 JavaScript 中,Object.freeze() 和 Object.seal() 是两个用于限制对象修改的内置方法,它们都属于“不可扩展性控制”范畴,但作用强度不同:前者更严格(完全冻结),后者稍宽松(仅禁止增删属性,允许修改已有属性值)。
Object.freeze():彻底冻结对象
调用 Object.freeze(obj) 后,对象将:
- 禁止添加新属性
- 禁止删除已有属性
- 禁止修改属性的可配置性(configurable)、可枚举性(enumerable)、可写性(writable)
- 对数据属性,其值无法被更改(即
writable: false) - 对访问器属性(getter/setter),setter 不再生效(但 getter 仍可调用)
注意:freeze 是浅冻结。如果对象某个属性本身是引用类型(如嵌套对象、数组),该嵌套对象本身不会被冻结,仍可被修改。
示例:
立即学习“Java免费学习笔记(深入)”;
const obj = { a: 1, b: { c: 2 } };
Object.freeze(obj);
obj.a = 99; // ❌ 无效(非严格模式静默失败;严格模式报 TypeError)
obj.d = 3; // ❌ 无效
delete obj.b; // ❌ 无效
obj.b.c = 999; // ✅ 成功!因为 obj.b 未被冻结
Object.seal():密封对象(禁止结构变更)
调用 Object.seal(obj) 后,对象将:
- 禁止添加新属性
- 禁止删除已有属性
- 所有现有属性的
configurable被设为false(即不能再 defineProperty 修改描述符) - 但允许修改已有数据属性的值(只要它是
writable: true)
换句话说,seal 只锁住“对象结构”,不锁“属性值”。
示例:
立即学习“Java免费学习笔记(深入)”;
const obj = { a: 1, b: 2 };
Object.seal(obj);
obj.a = 100; // ✅ 允许(a 仍是 writable)
obj.c = 3; // ❌ 无效(不能新增)
delete obj.b; // ❌ 无效(不能删除)
Object.defineProperty(obj, 'a', { writable: false }); // ❌ 报错:configurable 为 false
如何检测对象是否被冻结或密封?
JavaScript 提供了配套的判断方法:
-
Object.isFrozen(obj):返回true当且仅当对象是 frozen(包括所有属性不可配置、不可写,且对象不可扩展) -
Object.isSealed(obj):返回true当且仅当对象不可扩展且所有属性configurable: false
注意:两者都只检查当前对象自身,不递归检查嵌套对象。另外,空对象或不可扩展对象不一定 sealed 或 frozen —— 必须显式调用 seal/freeze 才会触发完整状态变更。
实际使用建议与注意事项
- 冻结/密封应在对象初始化完成后尽早执行,避免中间状态被意外修改
- 若需深度冻结(包括所有嵌套对象),需手动递归调用
Object.freeze,或借助工具函数(但注意循环引用问题) - 在开发环境可配合
"use strict",让非法操作直接抛错,便于调试 - 这些方法返回原对象(非副本),所以可链式调用,例如:
Object.freeze(Object.seal(obj))(等价于直接 freeze) - 它们对原始值(如字符串、数字)无影响,只对对象有效


















