2016-11-03 2 views
2

Я пытаюсь понять метод Object.freeze для ECMAscript.Javascript 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 

«массив» был добавлен в массив, таким образом замороженный объект был изменен. Мое немедленное решение - просто заморозить требуемое свойство:

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

Теперь изменение массива вызывает ошибку, если требуется.

Однако я разрабатываю приложение и еще не знаю, что будет назначено моему объекту. Моим вариантом использования является то, что у меня есть некоторые игровые объекты, которые инициализируются (из файла XML), когда игра начинается. После этого я не хочу иметь возможность случайно изменить какие-либо их свойства.

Возможно, я злоупотребляю методом замораживания? Я хотел бы иметь возможность заморозить весь объект, своего рода рекурсивное замораживание. Лучшее решение, о котором я могу думать здесь, - это перебрать свойства и заморозить каждый из них.

Я уже искал этот вопрос, и единственный ответ говорит, что это ошибка реализации. Я использую новейшую версию Chrome. Любая помощь приветствуется.

+0

Половина этой страницы: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze это говорит: ** Следующий пример показывает, что значения объекта в замороженном объект может быть мутирован (замораживание неглубоко). ** Таким образом, он работает как разработанный. –

ответ

4

Object.freeze - это мелкая заморозка.

Если вы посмотрите на описании в docs, он говорит:

Значение не может быть изменен для свойств данных. Свойства аксессора (геттеры и сеттеры) работают одинаково (и все же дают иллюзию, что вы меняете значение). Обратите внимание, что значения, которые являются объектами, все еще могут быть изменены, если они также не заморожены.

Если вы хотите глубоко заморозить объект, вот 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

0

Это довольно странно, но замораживание предотвращает элемент мутирует, добавление элементов в массив является не мутируя (довольно странно) ...

Например, в ES6, когда вы определяете переменную, которая не изменится, вы объявляете ее «const», а не «let». Если вы говорите:

const foo = 'foo'; const foo = 'bar;

он выдаст ошибку, потому что вы использовали Уст. Когда вы говорите

const foo = ['foo']; foo.append('bar');

он не выдаст ошибку.

0

Установить дескрипторы свойств объекта на writable:false, configurable:false с использованием Object.defineProprties; затем вызовите Object.preventExtensions на объект. См. How to create static array in javascript.

Смежные вопросы