Reputation: 3471
I encountered something strange in Backbone :
All children class of a common parent class seems to get "referenced" properties with their siblings... !!
Check this simple test case :
var MyParentClass = Backbone.View.extend({
items:['foo'],
initialize: function() {
}
});
var MyFirstChildrenClass = MyParentClass.extend({
initialize: function() {
MyFirstChildrenClass.__super__.initialize.apply(this, arguments);
console.warn('MyFirstChildrenClass::initalize()');
this.items.push('bar');
}
});
var MySecondChildrenClass = MyParentClass.extend({
initialize: function() {
MySecondChildrenClass.__super__.initialize.apply(this, arguments);
console.warn('MySecondChildrenClass::initalize()');
console.warn(this.items); // expecting [foo] & getting [foo,bar] !
}
});
var firstInstance = new MyFirstChildrenClass();
var secondInstance = new MySecondChildrenClass();
Upvotes: 2
Views: 749
Reputation: 22728
items
when you add it to the extend
call when making a new backbone "class" becomes part of the class prototype.
Since JavaScript uses Prototypal inheritance, this means it's available and shared by all instances of that class.
Upvotes: 0
Reputation: 72858
This is caused by the evaluation of object literals in JavaScript. This line:
items:['foo'],
evaluates the array immediately, and the parent type / sub-types all hold a reference to the same object.
All Backbone objects are extended with an object literal, to create the new type. Object literals are key:value pairs where the key is always the literal key, and the value is evaluated as soon as the JavaScript parser hits that line. Because of this, you are getting a single reference to the array ['foo']
in your parent class. Objects are by reference in JavaScript, and each of your sub-classes will contain a reference to the same array.
The easiest way to fix this is either assign items
to a function that returns the array (which doesn't seem like a good option in your case) or assign the array in the constructor of the parent class (or the initialize method, if you want):
Backbone.View.extend({
constructor: function(){
Backbone.View.prototype.constructor.apply(this, arguments);
this.items = ['foo'];
}
});
For a lengthy discussion on object literals and values (in the context of jQuery, but the same principles apply here), see my blog post here: http://lostechies.com/derickbailey/2011/11/09/backbone-js-object-literals-views-events-jquery-and-el/
Upvotes: 8