Skip to content Skip to sidebar Skip to footer

Scope When Doing OO Javascript Callbacks

Folks - I'm trying to learn how to write OO Javascript, I come from as3 OO background... issue I'm having is with passing a class' method as a callback to another class... in the e

Solution 1:

Modify init to bind the callback to the original context:

this.init = function() {
    this.connection.detectInitialConnection(
        this.initialConnectionDetected.bind(this));
}

Unfortunately, bind is not supported in all browsers, but you can capture the current value of this in a closure to achieve a similar effect:

this.init = function() {
    var that = this;
    this.connection.detectInitialConnection(function(detected) {
        that.initialConnectionDetected(detected);
    });
}

Yet another approach is to make detectInitialConnection capable of handling an optional context parameter:

this.detectInitialConnection = function(callbackFunction, _this){
    setTimeout(function() {
        callbackFunction.apply(_this || this, arguments);
    }, 1000, [true]);
}

You'd then call it like this:

this.init = function() {
    this.connection.detectInitialConnection(
        this.initialConnectionDetected, this);
}

The point in each of these examples is to retain a reference to the value of this from the context in which detectInitialConnection was called.


Solution 2:

setTimeout will run the passed function bound to window. You can override this with ES5's bind:

this.connection.detectInitialConnection( this.initialConnectionDetected.bind(this) );

This doesn't work in older browsers, but the provided MDN link has a workaround.


Solution 3:

this is tricky in javascript especially as it relates to constructors and passing functions around. If you do this it will work:

//AppController Class
var AppContoller = function(){
this.body = $("body");
var self = this;
this.init = function(){
    this.connection = new ConnectionMonitor();
    this.connection.detectInitialConnection( this.initialConnectionDetected );
}

//callback function I pass
this.initialConnectionDetected = function(bool){
    if(bool){
        trace("app connected? "+bool); // logs - "app connected? true"
        self.showOnlineSwf();
    }
    else{

    }
}

this.showOnlineSwf = function(){
    trace("i'm online");

}

}

Solution 4:

The other answers are correct, but nobody seems to mention that Function.prototype.bind is not supported in all browsers. To make it work, you'll want to include Kris Kowal's es5-shim library.


Solution 5:

this.initialConnectionDetected will pass the function, but without the information that it should be executed on the instance.

Calling this.foo() will pass this information, but only when called directly, not when passed around and called later (which is what you're doing).

You have to bind this information (i.e. the this value, which is the instance) using e.g. .bind:

this.connection.detectInitialConnection(this.initialConnectionDetected.bind(this));

Note that .bind is not available in older browsers, but there are shims available which mimic the behaviour of it.


Post a Comment for "Scope When Doing OO Javascript Callbacks"