Reputation: 1933
When using extend with collections and models are attributes that are not backbone methods set as the prototypal value of the defined "class"? Meaning that if those attributes are modified in one instance of the class they are changed for all instances of the class?
I'm running into a problem similar to that of the following.
For example :
var MyCollection = Backbone.Collection.extend({
options:
{
someAttribute: null,
anotherAttribute : null
},
url : function()
{
return this.options.someAttribute + "/" + this.options.anotherAttribute
});
var myCollectionInstance1 = new MyCollection();
_.extend(myCollectionInstance1.options,{
someAttribute: "page1",
anotherAttribute : "location1"});
var myCollectionInstance2 = new MyCollection();
_.extend(myCollectionInstance2.options,{
someAttribute: "page1",
anotherAttribute : "location2"});
// I call fetch here which will eventually run into my redefined url
// and now my url for this function is going to be
// "page1/location2" instead of what I expect "page1/location1"
// I assume this is because the protoype is being changed in the above
// of myCollectionInstance2.options
myCollectionInstance1.fetch();
If this is the case then what is the best way to attach instance variables to collections?
Upvotes: 1
Views: 40
Reputation: 434785
Yes, everything in the first argument to extend
ends up in the prototype and is thus shared by the instances. A common solution for mutable properties (such as objects and arrays) is to assign them inside initialize
:
var MyCollection = Backbone.Collection.extend({
initialize: function(options) {
this.options = {
someAttribute: null,
anotherAttribute: null
};
// The rest of the initialization goes here...
}
});
If you want to keep them where they are for documentation purposes, then you can _.clone
in initialize
:
var MyCollection = Backbone.Collection.extend({
default_options: {
someAttribute: null,
anotherAttribute: null
},
initialize: function(options) {
this.options = _(this.default_options).clone();
// The rest of the initialization goes here...
}
});
Note that _.clone
only does a shallow copy so you can still end up with accidental sharing if this.options
contains embedded arrays or objects.
Upvotes: 4
Reputation: 4129
Your problem is when you do this:
var MyCollection = Backbone.Collection.extend({
options:
{
someAttribute: null,
anotherAttribute : null
}
you are creating an object { someAttribute: null, anotherAttribute : null }
that's shared with all the instances, and when you do this:
_.extend(myCollectionInstance1.options,{ ...
you are updating this shared object.
The solution to your problem is when you want to set the collection.options
create new objects:
myCollectionInstance1.options = {
someAttribute: "page1",
anotherAttribute : "location1"
};
...
myCollectionInstance2.options = {
someAttribute: "page1",
anotherAttribute : "location2"
};
this way each collection will hold its own object.
Upvotes: 1