Создание новых объектов из замороженных родительских объектов
В этом примере создается объект, зависает, а затем создается новый объект из замороженного объекта.
Если второй объект пытается изменить свойство теста, он не может. Он остается замороженным с помощью
первое значение объекта 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
перезаписать его, если ему нужно?
Моя причина для запроса заключается в том, что я хочу создать неизменяемый базовый объект в качестве шаблона со значениями по умолчанию, а затем использовать его для создания новых объектов, которые я могу настроить. Какой лучший подход для этого?
Спасибо!
Ответы
Ответ 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