JavaScript中不使用Object.freeze()可以实现对象冻结吗?
不使用Object.freeze()冻结对象的实现方案
首先明确:该需求可以实现,常用的原生实现方案有2种,无需额外依赖:
方案1:修改属性描述符+禁止对象扩展
该方案效果和原生Object.freeze()完全一致,直接修改原对象的属性配置:
const obj = { a:'test', b:'Something' } // 遍历所有自有属性,设置为不可修改、不可重新配置 Object.keys(obj).forEach(key => { Object.defineProperty(obj, key, { writable: false, // 禁止修改属性值 configurable: false // 禁止删除属性、修改属性描述符 }) }) // 禁止对象新增属性、修改原型 Object.preventExtensions(obj)
修改后对obj的赋值、删除属性、新增属性操作都会静默失败(严格模式下会抛出错误),和原生冻结效果完全相同。
方案2:使用Proxy代理拦截修改操作
该方案不会修改原对象,仅通过代理实例限制操作,适合需要保留原对象可修改能力的场景:
const obj = { a:'test', b:'Something' } const frozenObj = new Proxy(obj, { // 拦截属性赋值 set: () => { throw new Error('无法修改冻结对象的属性') }, // 拦截属性删除 deleteProperty: () => { throw new Error('无法删除冻结对象的属性') }, // 拦截新增/重定义属性 defineProperty: () => { throw new Error('无法为冻结对象新增/重定义属性') }, // 拦截原型修改 setPrototypeOf: () => { throw new Error('无法修改冻结对象的原型') } })
所有修改操作都需要通过frozenObj触发才会被拦截,直接操作原obj不受影响。
注意事项
如果需要实现深冻结效果,两种方案都需要递归处理所有嵌套的子对象,否则深层属性依然可以被修改。
内容的提问来源于stack exchange,提问作者Aniket
相关产品推荐
相关产品推荐

