后台js集合的集合问题



当我尝试使用主干js创建集合集合时,遇到了issue。这是代码:

型号和系列:

var Track = Backbone.Model.extend({
defaults : {
title : ""
}
})
var TrackCollection = Backbone.Collection.extend({
model : Track,
})
var Playlist = Backbone.Model.extend({
defaults : {
name : "",
tracks : new TrackCollection,
}
})
var PlaylistCollection = Backbone.Collection.extend({
model : Playlist,
})

创建播放列表集合:

var playlists = new PlaylistCollection;
// create and push the first playlist
playlists.push({ name : "classic" });
// create and push a track in the playlist just created
playlists.last().get("tracks").push({ title : "fur elise" });
// create and push the second playlist
playlists.push({ name : "c2c" });
// create and push a track in the playlist just created
playlists.last().get("tracks").push({ title : "fuya" });
// display first playlist
console.log(JSON.stringify(playlists.at(0).toJSON()))
// display second playlist
console.log(JSON.stringify(playlists.at(1).toJSON()))

这是输出:

{"name":"classic","tracks":[{"title":"fur elise"},{"title":"fuya"}]}
{"name":"c2c","tracks":[{"title":"fur elise"},{"title":"fuya"}]}

问题是,正如我们在输出中看到的那样,这两个播放列表有两首曲目"fur elise"one_answers"fuya"。

所以我的问题是为什么?我该怎么做才能让"fur elise"只出现在名为"classic"的第一个播放列表中,而"fuya"只出现"c2c"的第二个播放列表?

谢谢。

我认为您的问题是PlayList:中默认的tracks属性

var Playlist = Backbone.Model.extend({
defaults : {
name : "",
tracks : new TrackCollection,
}
});

Backbone在创建新实例时会浅层复制defaults

默认model.defaults or model.defaults()
[…]
请记住,在JavaScript中,对象是通过引用传递的,因此,如果包含一个对象作为默认值,它将在所有实例之间共享

结果是,使用默认tracks的每个PlayList实例将使用与其tracks属性完全相同的TrackCollection,并且TrackCollection将是defaults中引用的实例。

最简单的解决方案是使用defaults:的函数

var Playlist = Backbone.Model.extend({
defaults : function() {
return {
name : "",
tracks : new TrackCollection,
};
}
});

这样,defaults函数将在需要默认值时被调用,每次调用defaults时,您将在默认的tracks属性中获得一个全新的TrackCollection

这里有一个快速的经验法则:

如果要在defaults中放入除字符串、数字或布尔值之外的任何内容,请使用defaults函数而不是defaults对象。

最新更新