Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

calling this._super() from inside setTimeout()

We use John Resig´s inherit.js. And that gives us access to the convenient _super() function to call the parent´s function. That´s awesome, but today I was stumped by a problem, I couldn´t call this._super() from inside a setTimeout, even if I bound this:

Code example

var Person = Class.extend({
  init: function(isDancing){
  this.dancing = isDancing;
},
    dance: function(){
        return this.dancing;
    }
});

var Ninja = Person.extend({
    init: function(){
        this._super( false );
},
dance: function(){
    window.setTimeout(function(){
        // Call the inherited version of dance()
        return this._super();
    }.bind(this),50);
});

this._super() is undefined! What is going on?

like image 362
jrewing Avatar asked Mar 23 '23 06:03

jrewing


1 Answers

To make this work you need to capture the _super method while in the subclassed method, like this:

dance: function(){
    // capture the super method for later usage
    var superMethod = this._super;
    window.setTimeout(function(){
        return superMethod();
    },50);
};

The reason this works, and your code does not, is that the extend() method in inherit.js captures the superclass' method as this._super right before your overridden method is run. It then runs your code, and after your code has run it restores _super to whatever it was set to before it ran. The action takes place in the following bit of code from inherit.js

      var tmp = this._super;

      // Add a new ._super() method that is the same method
      // but on the super-class
      this._super = _super[name];

      // The method only need to be bound temporarily, so we
      // remove it when we're done executing
      var ret = fn.apply(this, arguments);        
      this._super = tmp;

      return ret;

So to be more specific; when the original code was run, the function that was used as a parameter to setTimeout was bound to the original object. The reason it did not work was that, even though this referenced the right object, this._super referenced something else, since this._super was reset to point to whatever it pointed to before the method was run. Probably it was not set, so the value of this._super was most likely just undefined.

like image 124
oligofren Avatar answered Apr 01 '23 04:04

oligofren