Object.freeze()可将对象自身属性设为只读,但不递归冻结嵌套对象;深层冻结需手动递归实现;替代方案可用Object.defineProperty批量设置属性描述符;存在无法冻结Proxy、Map等内置类型及不可枚举symbol属性等限制。
可以通过 Object.freeze() 快速将对象所有自有属性设为只读(不可修改、不可添加、不可删除),但需注意它只作用于对象**自身属性**,不递归冻结嵌套对象。
Object.freeze() 是最直接的方式,适用于简单扁平对象:
writable、configurable、enumerable 描述符均被锁定示例:
const obj = { a: 1, b: 2 };Object.freeze(obj);obj.a = 99; // 无效(静默)obj.c = 3; // 无效(静默)delete obj.b; // 无效(静默)console.log(obj); // { a: 1, b: 2 }
若对象含嵌套对象(如数组、子对象),需手动递归处理:
立即学习“Java免费学习笔记(深入)”;
简易实现:
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]); } }); Object.freeze(obj); } return obj;}
使用:deepFreeze({ a: 1, nested: { x: 2 } }) → nested.x 也无法修改。
若需更精细控制(例如只设 writable: false,但保留 configurable: true),可用 Object.defineProperty 配合 Object.keys():
{ writable: false, configurable: false }(等效于 freeze 的效果)Object.getOwnPropertyNames() 覆盖示例:
function makeAllReadOnly(obj) { Object.getOwnPropertyNames(obj).forEach(key => { Object.defineProperty(obj, key, { writable: false, configurable: false, enumerable: true // 保持原有枚举性 }); }); return obj;}
Object.freeze() 和类似操作有明确边界:
getOwnPropertyNames 可覆盖)freeze 使用,确保 API 稳定不复杂但容易忽略。