如何在JavaScript中深度冻结对象?
在JavaScript中,对象是可变的,无论你是否将它们定义为const
变量。实际上,在定义对象时使用const
只是防止变量被重新赋值。然而,你可以重新赋值const
对象或数组的属性,如下所示:
const myObj = { a: 10, b: 20, c: 30 };
myObj.a = 12; // { a: 12, b: 20, c: 30 };
const myArr = [15, 25, 35];
myArr[1] = 28; // [15, 28, 35];
为了使对象不可变,我们可以使用Object.freeze()
,它将阻止添加新属性,并在一定程度上阻止删除和更改现有属性。然而,虽然Object.freeze()
提供了一种解决方案,但它只在下一层嵌套级别上减轻了问题,因为实际上它执行的是浅冻结。这意味着对象或数组的属性仍然可以被修改:
const myObj = {
a: 1,
b: 'hello',
c: [0, 1, 2],
d: { e: 1, f: 2 }
};
Object.freeze(myObj);
myObj.a = 10;
myObj.b = 'hi';
myObj.c[1] = 4;
myObj.d.e = 0;
/*
myObj = {
a: 1,
b: 'hello',
c: [0, 4, 2],
d: { e: 0, f: 2 }
}
*/
如你所见,Object.freeze()
是朝着正确的方向迈出的一步,但它只能对对象进行浅冻结。为了解决这个问题,我们可以使用递归,检查每个属性是否是对象,并且如果Object.isFrozen()
为false
,则对其应用Object.freeze()
:
```js const myObj = { a: 1, b: 'hello', c: [0, 1, 2], d: { e: 1, f: 2 } };
const deepFreeze = obj => { Object.keys(obj).forEach(prop => { if (typeof obj[prop] === 'object' && !Object.isFrozen(obj[prop])) deepFreeze(obj[prop]); }); return Object.freeze(obj); }; deepFreeze(myObj);
在上面的示例中,我们应用了之前描述的技术,以确保给定的对象被深度冻结。您可以在deepFreeze片段中查看完整的代码,以及更多示例。