Backbone Collection not unique?

2020-02-15 13:01发布

问题:

I've got a simple setup going for the beginnings of an app in Backbone.js
The code is in this gist.
It is pretty straightforward. A Coin model and collection, a Player model and collection. Each Player has a collection of Coins. I manually add the type of Coins a player should be getting.

At the end of initialize, each of the Players Coins collection has 32 items in it and Coins.player_id is set to 4 in all 4 Players.

What am I missing?

回答1:

I'd guess that your problem is your defaults in Player:

var Player = Backbone.Model.extend({
    defaults: {
        id: 0,
        name: '',
        coins: new Coins()
    },
    //...
});

That defaults will be shallow-copied to new Players so they'll all end up sharing exactly the same coins: new Coins(). Similar things happen whenever defaults contains any mutable data (i.e. arrays, object literals, ...). So all of these:

this.Taylor.get("coins")
this.Sugar.get("coins")
this.Darlene.get("coins")
this.Cody.get("coins")

will end up as the exact same object. The fine manual has this to say:

defaults model.defaults or model.defaults()

The defaults hash (or function) can be used to specify the default attributes for your model. When creating an instance of the model, any unspecified attributes will be set to their default value.
[...]
Remember that in JavaScript, objects are passed by reference, so if you include an object as a default value, it will be shared among all instances.

Note that little caveat at the end. If you use a function for defaults:

var Player = Backbone.Model.extend({
    defaults: function() {
        return {
            id: 0,
            name: '',
            coins: new Coins()
        };
    },
    //...
});

then you should get distinct 'coins' for each Player. Alternatively, you could manually set 'coins' in your initialize:

var Player = Backbone.Model.extend({
    //...
    initialize: function() {
        this.set('coins', new Coins);
        // Or only set it if it isn't there if that makes sense...
    },
    //...
});