Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
764 views
in Technique[技术] by (71.8m points)

oop - Javascript Object.freeze() does not prevent changes to object

I am trying to understand the Object.freeze method of ECMAscript.

My understanding was that it essentially stops changes to all the properties of an object. MDN documentation says:

Prevents new properties from being added to it; prevents existing properties from being removed; and prevents existing properties, or their enumerability, configurability, or writability, from being changed.

This does not seem to be the case, but perhaps I have misinterpreted the docs.

Here is my object, with its enumerable property exampleArray

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

var obj = new myObject();
obj.exampleArray[0] = "foo";

Now if I freeze the object, I would expect the exampleArray property to be frozen too, as in it can no longer be changed in any way.

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

"bar" has been added to the array, thus the frozen object has been changed. My immediate solution is to just freeze the desired property:

Object.freeze(obj.exampleArray);
obj.exampleArray[2] = "boo";

Now changing the array throws an error, as desired.

However, I am developing my application and I don't yet know what will be assigned to my object. My use case is that I have some game objects which are initialized (from an XML file) when the game starts. After this, I do not want to be able to change any of their properties accidentally.

Perhaps I am misusing the freeze method? I would like to be able to freeze the whole object, a sort of recursive freeze. The best solution I can think of here is to loop through the properties and freeze each one.

I've already searched for this question and the only answer says it's an implementation bug. I am using the newest version of Chrome. Any help is appreciated.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Object.freeze is a shallow freeze.

If you look at the description in the docs, it says:

Values cannot be changed for data properties. Accessor properties (getters and setters) work the same (and still give the illusion that you are changing the value). Note that values that are objects can still be modified, unless they are also frozen.

If you want to deep-freeze an object, here's 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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...