我正在尝试理解ECMAscript的Object.freeze方法。
我的理解是它基本上停止了对象的所有属性的更改。 MDN文档说:
防止添加新属性;防止删除现有属性;并防止现有属性或其可枚举性,可配置性或可写性被更改。
似乎并非如此,但也许我误解了文档。
这是我的对象,具有可枚举的属性exampleArray
function myObject()
{
this.exampleArray = [];
}
var obj = new myObject();
obj.exampleArray[0] = "foo";
现在如果我冻结对象,我希望exampleArray属性也被冻结,因为它不能再以任何方式改变。
Object.freeze(obj);
obj.exampleArray[1] = "bar";
console.log(obj.exampleArray.length); // logs 2
“bar”已添加到数组中,因此冻结的对象已更改。我的直接解决方案是冻结所需的属性:
Object.freeze(obj.exampleArray);
obj.exampleArray[2] = "boo";
现在更改数组会根据需要抛出错误。
但是,我正在开发我的应用程序,我还不知道将为我的对象分配什么。我的用例是我有一些游戏对象在游戏开始时被初始化(来自XML文件)。在此之后,我不希望能够意外更改任何属性。
也许我在滥用冻结方法?我希望能够冻结整个对象,一种递归冻结。我能想到的最好的解决方案是遍历属性并冻结每个属性。
我已经搜索过这个问题了,唯一的答案是它是一个实现错误。我使用的是最新版本的Chrome。任何帮助表示赞赏。
答案 0 :(得分:5)
Object.freeze是一个浅层冻结。
如果您查看docs中的说明,则会说:
无法更改数据属性的值。访问器属性(getter和setter)的工作方式相同(并且仍然给出了您正在更改值的错觉)。 请注意,仍然可以修改作为对象的值,除非它们也被冻结。
如果你想深度冻结一个对象,这里是a good recursive example
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
答案 1 :(得分:0)
这很奇怪,但是冻结会阻止变异元素,向数组添加元素不会发生变异(奇怪的是)......
例如在ES6中,当您定义一个不会发生变化的变量时,您使用" const"来声明它。而不是"让"。如果你说:
const foo = 'foo'; const foo = 'bar;
它会抛出一个错误,因为你使用了const。当你说
const foo = ['foo']; foo.append('bar');
它不会抛出错误。
答案 2 :(得分:0)
使用writable:false
将对象的属性描述符设置为configurable:false
,Object.defineProprties
;然后在对象上调用Object.preventExtensions
。请参阅How to create static array in javascript。