Olivier
Olivier

Reputation: 3471

Backbone inheritance pattern with sibings instance of class inheriting of the same parent

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

Answers (2)

tkone
tkone

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

Derick Bailey
Derick Bailey

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

Related Questions