javascript : 使工厂项目在包含音乐专辑集的字段上显示正确的值
javascript : making a factory item display proper value on the field containing music albums set
"singerAlbum" 和 "musicCollection" 是对象。 musicCollection 中的 setter 专辑用于创建新歌手专辑。问题是:当创建两个不同的 musicCollection 并在其中一个 musicCollection 中创建一个 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
给出了一个新对象,你传递给它的对象被设置为新对象的原型。如果一个对象没有自己的 属性 设置值,它会使用其原型中的值。这正是这里发生的事情。
此外,您的相册 setter 直接在 musicCollection
(原型)上设置值,但您可能想在 this
(当前对象)上设置值.
但是由于您正在改变现有对象(Albums),并且因为每个集合对象使用原型的 Albums
对象而不是它自己的对象,所以这些更改将在使用 [=15 创建的所有集合对象中更改=].
为了解决这个问题,您需要为每个集合对象创建一个新的 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);
一般来说,你想在你的原型上定义的唯一东西是不可变的对象,比如函数和字符串、数字等。数组、对象、集合、映射等是可变的,如果你是计划改变它们,您可能需要为对象的每个实例创建不同的副本。
另请参阅:
"singerAlbum" 和 "musicCollection" 是对象。 musicCollection 中的 setter 专辑用于创建新歌手专辑。问题是:当创建两个不同的 musicCollection 并在其中一个 musicCollection 中创建一个 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
给出了一个新对象,你传递给它的对象被设置为新对象的原型。如果一个对象没有自己的 属性 设置值,它会使用其原型中的值。这正是这里发生的事情。
此外,您的相册 setter 直接在 musicCollection
(原型)上设置值,但您可能想在 this
(当前对象)上设置值.
但是由于您正在改变现有对象(Albums),并且因为每个集合对象使用原型的 Albums
对象而不是它自己的对象,所以这些更改将在使用 [=15 创建的所有集合对象中更改=].
为了解决这个问题,您需要为每个集合对象创建一个新的 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);
一般来说,你想在你的原型上定义的唯一东西是不可变的对象,比如函数和字符串、数字等。数组、对象、集合、映射等是可变的,如果你是计划改变它们,您可能需要为对象的每个实例创建不同的副本。
另请参阅: