Object.create
дает новый объект с объектом, который вы передаете ему, установлен как прототип нового объекта. Если объект не имеет своего собственного свойства, установленного со значением, он использует значение из своего прототипа. Это именно то, что здесь происходит.
Кроме того, программа установки альбомов устанавливает значение непосредственно на musicCollection
(прототип), но вы, вероятно, хотели установить значение на this
(текущий объект).
Но поскольку вы изменяете существующий объект (альбомы) и поскольку каждый объект коллекции использует объект Albums
прототипа вместо своего собственного, эти изменения будут изменены во всех объектах коллекции, созданных с помощью createMusicCollection
.
Чтобы обойти это, вам нужно создать новый объект Albums
для каждого объекта коллекции. Вот где конструкторы пригодятся. Обычно вы используете синтаксис class
и определяете метод constructor
, чтобы сделать это при создании объекта с new
. Но так как вы используете фабричные методы, мы можем сделать это там. Вот как я бы порекомендовал изменить ваш код, если вы хотите продолжать использовать Object.create
:
let singerAlbum = {
Name: undefined,
get name() {
return this.Name;
},
set name(value) {
this.Name = value;
}
};
let musicCollection = {
Name: undefined,
// since we need to make a new album object each instance, don't make it here
Albums: undefined,
get name() {
return this.Name;
},
get albums() {
// we could check to see if `this.Albums` is defined before returning it,
// but let's create it in the "constructor" method instead
return this.Albums;
},
set name(value) {
this.Name = value;
},
set albums(value) {
let album = createSingerAlbum();
album.name = value;
this.Albums.add(album);
},
};
function createSingerAlbum() {
return Object.create(singerAlbum);
}
function createMusicCollection() {
let collection = Object.create(musicCollection);
collection.Albums = new Set();
return collection;
}
let collection1 = createMusicCollection();
let collection2 = createMusicCollection();
collection1.albums = "Abbey Road";
//modified to print a bit nicer in the snippet viewer
console.log("collection1:", ...collection1.albums);
console.log("collection2:", ...collection2.albums);
Как правило, единственными вещами, которые вы хотите определить в своем прототипе, являются неизменяемые объекты, такие как функции и строки, числа и т. Д. Массивы, объекты, наборы, карты и т. Д. Являются изменяемыми, и если вы планируете мутируя их, вы, вероятно, захотите разные копии для каждого экземпляра объекта.
Смотри также: