如何在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片段中查看完整的代码,以及更多示例。