在 JavaScript 中,Object.preventExtensions、Object.seal 和 Object.freeze 是三个用于控制对象可变性的方法。它们都可以限制对象的行为,但限制的程度不同。
✅ 一句话区分(先给结论)
| 方法 | 能否添加属性 | 能否删除属性 | 能否修改属性值 | 能否修改属性描述符 |
|---|---|---|---|---|
preventExtensions | ❌ | ✅ | ✅ | ✅ |
seal | ❌ | ❌ | ✅ | ❌ |
freeze | ❌ | ❌ | ❌ | ❌ |
1. Object.preventExtensions(obj)
✅ 作用:
禁止添加新属性,但可以删除、修改已有属性。
🔍 示例:
const obj = { a: 1 };
Object.preventExtensions(obj);
obj.b = 2; // 静默失败(非严格模式)
console.log(obj.b); // undefined
delete obj.a; // ✅ 可以删除
obj.a = 10; // ✅ 可以修改
🧪 检测:
Object.isExtensible(obj); // false
2. Object.seal(obj)
✅ 作用:
- 禁止添加新属性
- 禁止删除已有属性
- 但可以修改属性值
相当于
preventExtensions+ 把所有属性设为configurable: false
🔍 示例:
const obj = { a: 1, b: 2 };
Object.seal(obj);
obj.a = 10; // ✅ 可以改值
delete obj.a; // ❌ 删除失败
obj.c = 3; // ❌ 添加失败
🧪 检测:
Object.isSealed(obj); // true
3. Object.freeze(obj)
✅ 作用:
- 禁止添加、删除、修改属性值
- 禁止修改属性描述符(如
writable、enumerable、configurable)
相当于
seal+ 把所有属性设为writable: false
🔍 示例:
const obj = { a: 1, b: { x: 10 } };
Object.freeze(obj);
obj.a = 100; // ❌ 修改失败
obj.c = 3; // ❌ 添加失败
delete obj.a; // ❌ 删除失败
⚠️ 注意:
freeze 是浅冻结,嵌套对象仍然可变:
obj.b.x = 999; // ✅ 可以改
🧪 检测:
Object.isFrozen(obj); // true
✅ 总结图(记忆版)
| 方法 | 添加 | 删除 | 修改值 | 修改描述符 |
|---|---|---|---|---|
preventExtensions | ❌ | ✅ | ✅ | ✅ |
seal | ❌ | ❌ | ✅ | ❌ |
freeze | ❌ | ❌ | ❌ | ❌ |
✅ 实际应用建议
| 场景 | 推荐方法 |
|---|---|
| 防止扩展结构 | preventExtensions |
| 保护配置对象(如全局配置) | seal |
| 实现不可变对象(如 Redux state) | freeze |
如需深冻结(递归冻结嵌套对象),可手动实现:
function deepFreeze(obj) {
Object.freeze(obj);
for (const key in obj) {
if (typeof obj[key] === 'object' && obj[key] !== null) {
deepFreeze(obj[key]);
}
}
return obj;
}