object.freeze()仅浅冻结对象自身属性,不递归冻结嵌套对象;不可逆、不影响原型链,且无内置深冻结能力,需手动递归实现并防循环引用。

Object.freeze() 的能力。真正用于冻结对象的是 Object.freeze(),而 Reflect 只是提供了一套更统一、更函数式风格的操作接口,比如 Reflect.set()、Reflect.deleteProperty() 等,但它不包含“冻结”语义。
冻结对象的正确方式是用 Object.freeze(),它会将对象变为不可扩展、所有自有属性设为不可配置且不可写(对数据属性),从而阻止添加、删除、修改属性值或重定义属性描述符。
如何真正冻结一个对象
调用 Object.freeze(target) 并传入目标对象即可:
- 返回原对象(不是副本),即冻结操作是就地修改
- 仅冻结对象自身的属性,**不会递归冻结嵌套对象**
- 冻结后尝试修改属性(如
obj.x = 1)在严格模式下会抛出TypeError,非严格模式下静默失败
为什么 Reflect.freeze 不存在
Reflect 的设计目标是为每个内部方法(如 [[Set]]、[[Get]]、[[DefineOwnProperty]])提供对应的方法,便于元编程和 Proxy 拦截。但“冻结”属于对象状态变更(改变 [[Extensible]] 和属性特性),并非单个内部操作,而是多个底层行为的组合,因此不属于 Reflect 的职责范围。
想用 Reflect 配合冻结?可以这样用
虽然 Reflect 不冻结,但你可以在冻结后,用 Reflect 方法安全地尝试读写(它们会尊重冻结状态):
-
Reflect.set(obj, 'x', 1)→ 返回false(因属性不可写) -
Reflect.defineProperty(obj, 'x', {...})→ 返回false(因属性不可配置) -
Reflect.deleteProperty(obj, 'x')→ 返回false(因属性不可配置)
这些返回值比直接赋值更易检测是否成功,适合配合冻结后的防御性编程。
需要深度冻结怎么办
Object.freeze() 是浅冻结。若需冻结嵌套对象,需手动递归处理:
function deepFreeze(obj) {
if (obj && typeof obj === 'object') {
Object.getOwnPropertyNames(obj).forEach(prop => {
if (obj[prop] && typeof obj[prop] === 'object') {
deepFreeze(obj[prop]);
}
});
}
return Object.freeze(obj);
}
注意:循环引用需额外处理,否则会栈溢出。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











