对象冻结是使javaScript对象不可修改的最严格防篡改方式,通过Object.freeze()实现浅冻结,需递归处理嵌套对象;另有seal、preventExtensions等防护等级较低的替代方案。

对象冻结是指让一个 javascript 对象变为不可修改的状态:不能添加、删除或更改其属性,也不能修改属性的描述符(如 writable、configurable、enumerable)。这是最严格的防篡改方式之一,常用于确保关键配置、常量或共享数据不被意外改动。
使用 Object.freeze() 冻结对象
Object.freeze() 是最常用的方法,它会直接冻结传入的对象,并返回该对象(原地修改,不创建新对象)。
- 冻结后,尝试修改已有属性值(如
obj.name = "new")在严格模式下会报错,在非严格模式下静默失败 - 无法添加新属性、删除已有属性、重定义属性描述符
- 注意:它只做浅冻结 —— 如果属性值是对象,那个嵌套对象本身不会被冻结
示例:
const config = { api: “https://api.example.com”, timeout: 5000 };
Object.freeze(config);
config.timeout = 10000; // 无效(非严格模式)或报错(严格模式)
config.version = “1.0”; // 添加失败
冻结嵌套对象需递归处理
因为 Object.freeze() 不处理深层对象,若要完全冻结整个结构(比如配置对象里有子对象),需要手动递归调用:
立即学习“Java免费学习笔记(深入)”;
- 先检查属性是否为纯对象且未冻结,再对其调用
Object.freeze() - 跳过
NULL、原始类型(String/number/Boolean)、函数、date、regexp 等非普通对象 - 避免循环引用导致死循环(实际项目中建议加缓存判断)
简易递归冻结函数示例:
function deepFreeze(obj) {
if (obj && typeof obj === “object” && !Object.isFrozen(obj)) {
Object.getOwnPropertyNames(obj).forEach(prop => {
if (obj[prop] !== null && typeof obj[prop] === “object”) {
deepFreeze(obj[prop]);
}
});
return Object.freeze(obj);
}
return obj;
}
其他防修改方法对比
根据需求强度不同,还有几个相关 API 可选:
- Object.seal():禁止添加/删除属性,但允许修改已有属性值(
writable: true的属性仍可改) - Object.preventExtensions():只禁止添加新属性,其余都允许
- Object.defineProperty():可单独设置某个属性为只读(
writable: false)或不可配置(configurable: false)
三者防护等级:freeze > seal > preventExtensions。一般优先用 freeze,除非你明确需要保留某些修改能力。
冻结后如何检测?
可以用 Object.isFrozen(obj) 判断对象是否已被冻结。注意它只检查对象自身,不检查嵌套对象 —— 所以对深冻结对象,这个方法返回 false,除非你已递归冻结所有层级。
基本上就这些。冻结不是万能的(比如不能阻止原型链污染或 symbol 属性误操作),但在大多数业务场景下,Object.freeze() 加上必要递归,已经足够可靠。