Backbone View inheritance - call parent leads to recursion

Erik picture Erik · Apr 13, 2013 · Viewed 9.3k times · Source

I have a three Backbone View class inheritance:

var preventRecursion = 0;

var parentView = Backbone.View.extend({

  initialize: function(){
    console.log('parentView');
  }
});

var nestedChildView = parentView.extend({

  initialize: function(){

    if (++preventRecursion == 5) {throw "Recursion"};

    console.log('nestedChildView');
    this.constructor.__super__.initialize.apply(this);          
  }
});

var nestedNestedChildView = nestedChildView.extend({

  initialize: function(){
    console.log('nestedNestedChildView');
    this.constructor.__super__.initialize.apply(this);          
  }
});

When I try to create nestedNestedChildView:

var t = new nestedNestedChildView();

I get infinite recursion: Here is jsfiddle

Answer

nikoshr picture nikoshr · Apr 13, 2013

As stated in the doc on Model.extend,

Brief aside on super: JavaScript does not provide a simple way to call super — the function of the same name defined higher on the prototype chain. If you override a core function like set, or save, and you want to invoke the parent object's implementation, you'll have to explicitly call it, along these lines:

In your class hierarchy, this.constructor always equals to the constructor of nestedNestedChildView, which means this.constructor.__super__.initialize will be nestedChildView.initialize and thus a loop. See http://jsfiddle.net/X5yBb/ for a test.

You could explicitly call the class __super__ (http://jsfiddle.net/X5yBb/1/)

var nestedChildView = parentView.extend({
  initialize: function(){
    console.log('nestedChildView');
    nestedChildView.__super__.initialize.apply(this);          
  }
});

var nestedNestedChildView = nestedChildView.extend({
  initialize: function(){
    console.log('nestedNestedChildView');
    nestedNestedChildView.__super__.initialize.apply(this);          
  }
});

or call the methods on the prototype chain if you prefer (http://jsfiddle.net/X5yBb/2/):

var nestedChildView = parentView.extend({
  initialize: function(){
    console.log('nestedChildView');
    parentView.prototype.initialize.apply(this);          
  }
});

var nestedNestedChildView = nestedChildView.extend({
  initialize: function(){
    console.log('nestedNestedChildView');
    nestedChildView.prototype.initialize.apply(this);          
  }
});

See Accessing parent class in Backbone and Super in Backbone for further info on the subject.