Reputation: 1852
I am extending Backbone views like:
var baseView = Backbone.View.extend({
fruits : [],
listFruits : function() {
console.log(this.fruits);
}
});
var firstView = baseView.extend({
initialize : function() {
this.fruits.push("apple");
}
});
var secondView = baseView.extend({
initialize : function() {
this.fruits.push("pear");
}
});
var firstViewInstance = new firstView(); // ["apple", "pear"]
var secondViewInstance = new secondView(); // ["apple", "pear"]
firstViewInstance.listFruits();
secondViewInstance.listFruits();
To my mind, firstViewInstance
and secondViewInstance
should be entirely separate, but they are clearly related. How can I achieve two separate view objects, both inheriting from a common base, but not sharing data?
EDIT:
Based on answers below I have an updated fiddle at http://jsfiddle.net/qZ7SU/ which seems to solve this problem. I'm still not entirely clear what is going on, but I think explicitly attaching fruits[]
to this
, creates it as an instance variable, rather than attaching it to the prototype.
Upvotes: 2
Views: 1115
Reputation: 4463
I wrote a more detailed blog post about this but the easiest way is to provide a custom constructor that ensures fruits
is created on the prototype of each subviews, and not on the baseView.prototype
which all subviews inherit.
var baseView = Backbone.View.extend({
constructor: function() {
this.fruits = [];
Backbone.View.apply(this, arguments);
},
listFruits : function() {
console.log(this.fruits);
}
});
var firstView = baseView.extend({
initialize : function() {
this.fruits.push("apple");
}
});
var secondView = baseView.extend({
initialize : function() {
this.fruits.push("pear");
}
});
var firstViewInstance = new firstView(); // ["apple"]
var secondViewInstance = new secondView(); // ["pear"]
Upvotes: 2
Reputation: 18556
This is because the reference to the original fruits
-property is the one being copied to the children view. See underscore.js extend
_.extend = function(obj) {
each(slice.call(arguments, 1), function(source) {
if (source) {
for (var prop in source) {
obj[prop] = source[prop];
}
}
});
return obj;
};
To inherit from the common base, but not share data, you need to initialize the not-shared properties in the initialize-function.
var baseView = Backbone.View.extend({
initialize: function() {
this._initializeBase();
},
_initializeBase: function() {
this.fruits = [];
},
listFruits : function() {
console.log(this.fruits);
}
});
var firstView = baseView.extend({
initialize : function() {
this._initializeBase();
this.fruits.push("apple");
}
});
This way the property will be added to the object when it is initialized and the data will not be shared.
Hope this helps!
Upvotes: 4