进行OO javascript回调时的范围

时间:2012-01-13 20:42:28

标签: javascript jquery oop callback

伙计 - 我试图学习如何编写OO Javascript,我来自as3 OO背景...... 我正在通过一个课程'方法作为对另一个类的回调......

在下面的示例中,我创建了一个AppController类的实例,在其中,我创建了一个ConnectionMonitor类的实例。我传递一个AppController方法,由ConnectionMonitor调用。回调工作正常,但似乎回调函数中的内容失去了它的范围(AppController)...

有什么想法吗?

//in the HTML
<script>
    $(document).ready( function(){
        new AppContoller().init();
    });
</script>


//in the js file

//AppController Class
var AppContoller = function(){
    this.body = $("body");

    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"
            this.showOnlineSwf();  //thows error - "Object [object DOMWindow] has no method 'showOnline' "
        }
        else{

        }
    }

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

    }

}

//ConnectionMonitor Class
var ConnectionMonitor = function()
{   
    this.detectInitialConnection = function(callbackFunction){
        setTimeout(callbackFunction, 1000, [true]);
    }
}




function trace(arg){
    console.log(arg.toString());
}

5 个答案:

答案 0 :(得分:4)

修改init以将回调绑定到原始上下文:

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

不幸的是,bind is not supported in all browsers,但您可以在闭包中捕获this的当前值以实现类似的效果:

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

另一种方法是使detectInitialConnection能够处理可选的上下文参数:

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

然后你会这样称呼它:

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

每个示例中的要点是保留对this被调用的上下文中detectInitialConnection的值的引用。

答案 1 :(得分:2)

setTimeout将运行绑定到window的传递函数。您可以使用ES5 bind

覆盖此内容
this.connection.detectInitialConnection( this.initialConnectionDetected.bind(this) );

这在旧版浏览器中不起作用,但提供的MDN链接有解决方法。

答案 2 :(得分:2)

这在javascript中很棘手,特别是因为它与构造函数和传递函数有关。如果你这样做,它将起作用:

//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");

}

}

答案 3 :(得分:1)

this.initialConnectionDetected将传递该函数,但没有它应该在实例上执行的信息。

调用this.foo()将传递此信息,但仅在直接调用时,而不是在传递并稍后调用时(这就是您正在执行的操作)。

您必须使用以下方法绑定此信息(即this值,即实例)。 .bind

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

请注意,.bind在旧版浏览器中不可用,但有可用的填充程序可以模仿它的行为。

答案 4 :(得分:1)

其他答案都是正确的,但似乎没有人提到Function.prototype.bindnot supported in all browsers。要使其有效,您需要添加Kris Kowal's es5-shim library