Javascript Object.freeze()不会阻止对对象的更改

Mus*_*man 4 javascript oop

我正在尝试了解ECMAscript的Object.freeze方法。

我的理解是,它实质上停止了对对象所有属性的更改。MDN文档说:

防止向其添加新属性;防止现有属性被删除;并防止更改现有属性或其可枚举性,可配置性或可写性。

似乎并非如此,但也许我误解了文档。

这是我的对象,它具有可枚举的属性exampleArray

function myObject()
{
    this.exampleArray = [];
}

var obj = new myObject();
obj.exampleArray[0] = "foo";
Run Code Online (Sandbox Code Playgroud)

现在,如果我冻结对象,我希望exampleArray属性也将被冻结,因为无法再以任何方式对其进行更改。

Object.freeze(obj);
obj.exampleArray[1] = "bar";
console.log(obj.exampleArray.length); // logs 2
Run Code Online (Sandbox Code Playgroud)

“ bar”已添加到数组,因此冻结的对象已更改。我的直接解决方案是冻结所需的属性:

Object.freeze(obj.exampleArray);
obj.exampleArray[2] = "boo";
Run Code Online (Sandbox Code Playgroud)

现在,根据需要更改数组会引发错误。

但是,我正在开发我的应用程序,但我还不知道将为对象分配什么。我的用例是,我有一些游戏对象在游戏开始时被初始化(来自XML文件)。此后,我不希望能够意外更改其任何属性。

也许我滥用冻结方法?我希望能够冻结整个对象,这是一种递归冻结。我能想到的最好的解决方案是遍历属性并冻结每个属性。

我已经搜索了这个问题,唯一的回答是这是一个实现错误。我正在使用最新版本的Chrome。任何帮助表示赞赏。

nem*_*035 6

Object.freeze是一个浅冻结。

如果您查看文档中的描述,它会说:

不能更改数据属性的值。访问器属性(获取器和设置器)的工作原理相同(并且仍然给人一种幻想,即您正在更改值)。请注意,除非将对象值冻结,否则仍可以对其进行修改。

如果要深度冻结对象,这是一个很好的递归示例

function deepFreeze(o) {
  Object.freeze(o);

  Object.getOwnPropertyNames(o).forEach(function(prop) {
    if (o.hasOwnProperty(prop)
    && o[prop] !== null
    && (typeof o[prop] === "object" || typeof o[prop] === "function")
    && !Object.isFrozen(o[prop])) {
        deepFreeze(o[prop]);
      }
  });

  return o;
}

function myObject() {
  this.exampleArray = [];
}

var obj = deepFreeze(new myObject());
obj.exampleArray[0] = "foo";
console.log(obj); // exampleArray is unchanged
Run Code Online (Sandbox Code Playgroud)