Подтвердить что ты не робот

Создание новых объектов из замороженных родительских объектов

В этом примере создается объект, зависает, а затем создается новый объект из замороженного объекта. Если второй объект пытается изменить свойство теста, он не может. Он остается замороженным с помощью первое значение объекта 10.

//Create an object and freeze it

var first = {
    test: 10
};
Object.freeze(first);

//Create a second object from the first one and
//try and change the new test property (you can't)

var second = Object.create(first);
second.test = 20;
console.log(second.test); //10

Вот мои вопросы:

Является ли second.test новым свойством для нового объекта, или это просто ссылка на свойство в замороженном первом объекте?
Можно ли использовать замороженный first.test как значение по умолчанию, но пусть second.test перезаписать его, если ему нужно?

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

Спасибо!

4b9b3361

Ответ 1

second - фактически новый объект, причем first является прототипом second. Причина, по которой

second.test = 20;

не работает, потому что при назначении он будет искать настройки в прототипе (т.е. configurable, enumerable, writable, [[Extensible]]) и не назначать экземпляру, если какой-либо из них является ложным 1. Чтобы назначить непосредственно экземпляру, вам нужно будет использовать Object.defineProperty в second:

var first = {
    test: 10
};
Object.freeze(first);

var second = Object.create(first);
Object.defineProperty(second, 'test', { value: 20, enumerable: true, configurable: true, writable: true });
console.log(second.test); // 20

1:[[Put]]: спецификация ECMAScript, §8.12.5

Ответ 2

Используйте Object.assign

         var first = {
            test: 10
        };
        Object.freeze(first);

        //Create a second object from the first one and
        //try and change the new test property (you can't)

        var second = Object.assign({}, first, {
            test: 20
        });
        console.log(second.test); //20

Ответ 3

В вашем случае second является ссылкой на first (как вы предполагали). Решение было бы клонировать ваш объект. Существует не построить способ клонировать объекты - вы должны сделать это сами, вот как (источник):

function clone(obj){
   if(obj == null || typeof(obj) != 'object')
      return obj;

   var temp = obj.constructor();

   for(var key in obj)
       temp[key] = clone(obj[key]);
   return temp;
}

Затем вы используете его следующим образом:

var first = {
    test: 10
};
Object.freeze(first);

// clone it into a new one
var second = clone(first);
second.test = 20;
console.log(second.test); // 20 where the first is locked