Search code examples
inheritancebackbone.jsbackbone-views

Backbone View inheritance - call parent leads to recursion


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


Solution

  • 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.