javascript:使工厂项目在包含音乐专辑集的字段上显示适当的值



"singerAlbum"one_answers"musicCollection"是对象。musicCollection中的setter专辑用于创建新的歌手专辑。问题是:当创建两个不同的musicCollection,并在其中一个musicCollections中创建一个singerAlbum时,它也会出现在第二个musicCollection中,尽管它还没有添加到那里。代码(javascript):

let singerAlbum = {
Name: undefined,
get name() {
return this.Name;
},
set name(value) {
this.Name = value;
}
};
let musicCollection = {
Name: undefined,
Albums: new Set(),
get name() {
return this.Name;
},
get albums() {
return this.Albums;
},
set name(value) {
this.Name = value;
},
set albums(value) {
let album = createSingerAlbum();
album.name = value;
musicCollection.Albums.add(album);
},
};
function createSingerAlbum() {
return Object.create(singerAlbum);
}
function createMusicCollection() {
return Object.create(musicCollection);
}
let collection1 = createMusicCollection();
let collection2 = createMusicCollection();
collection1.albums = "Abbey Road";
console.log(collection1.albums);
console.log(collection2.albums);

结果是:

Set {Object {Name: "Abbey Road"}}
Set {Object {Name: "Abbey Road"}}

我想要达到的结果是:

Set {Object {Name: "Abbey Road"}}
Set {}

这就是我处理它的方法。

class Album {
constructor(name, artist) {
this.name = name
this.artist = artist
}
}
class Collection {
constructor(name) {
this.name = name;
this.albums = new Set()
}
addAlbum(name, artist) {
this.albums.add(new Album(name, artist))
}
}
const bettlesCollection = new Collection('Bettles Collection')
bettlesCollection.addAlbum('Abbey Road', 'The Beetles')
bettlesCollection.addAlbum('Sgt. Pepper...', 'The Beetles')
console.log(bettlesCollection)

Object.create给出一个新对象,传递给它的对象被设置为新对象的原型。如果一个对象没有自己的带有值的属性集,它将使用其原型中的值。这正是这里正在发生的事情。

此外,相册设置器直接在musicCollection(原型)上设置值,但您可能希望在this(当前对象)上设置一个值。

但是,由于您正在更改现有对象(相册),并且每个集合对象都使用原型的Albums对象而不是自己的对象,因此这些更改将在使用createMusicCollection创建的所有集合对象中更改。

为了解决这个问题,您需要为每个集合对象创建一个新的Albums对象。这就是构造函数派上用场的地方。通常,在使用new创建对象时,您会使用class语法并定义constructor方法来执行此操作。但既然你使用的是工厂的方法,我们可以在那里做。如果你想继续使用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);

通常,您只想在原型上定义不可变的对象,如函数、字符串、数字等。数组、对象、集合、映射等都是可变的,如果您计划对它们进行更改,则可能需要为对象的每个实例提供不同的副本。

另请参阅:

  • 继承与原型链
  • JavaScript中的继承

最新更新