执行OOJavaScript回调时的作用域

执行OOJavaScript回调时的作用域,javascript,jquery,oop,callback,Javascript,Jquery,Oop,Callback,各位-我正在努力学习如何编写OO Javascript,我来自as3 OO背景。。。 我遇到的问题是将一个类的方法作为回调传递给另一个类 在下面的示例中,我创建了AppController类的一个实例,并在其中创建了ConnectionMonitor类的一个实例。我将AppController的一个方法传递给ConnectionMonitor调用。回调可以正常工作,但回调函数中的内容似乎会使其(AppController)中的类的作用域松动 有什么想法吗 //in the HTML <sc

各位-我正在努力学习如何编写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());
}
//在HTML中
$(文档).ready(函数(){
新的AppContoller().init();
});
//在js文件中
//AppController类
var AppContoller=函数(){
this.body=$(“body”);
this.init=函数(){
this.connection=新的ConnectionMonitor();
this.connection.detectinialconnection(this.initialConnectionDetected);
}
//我传递的回调函数
this.initialConnectionDetected=函数(bool){
如果(bool){
跟踪(“应用程序已连接?”+bool);//日志-“应用程序已连接?真”
this.showOnlineSwf();//thows错误-“对象[Object DOMWindow]没有方法“showOnline”
}
否则{
}
}
this.showOnlineSwf=函数(){
trace(“我在线”);
}
}
//连接监视器类
var ConnectionMonitor=函数()
{   
this.detectInitialConnection=函数(callbackFunction){
setTimeout(callbackFunction,1000,[true]);
}
}
函数跟踪(arg){
log(arg.toString());
}

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

this.init = function() {
    this.connection.detectInitialConnection(
        this.initialConnectionDetected.bind(this));
}
不幸的是,您可以在闭包中捕获
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);
}

这些示例中的每一点都是从调用
DetectinialConnection
的上下文中保留对
this
值的引用。

this.initialConnectionDetected
将传递函数,但不包含应在实例上执行的信息

调用
this.foo()
将传递此信息,但仅在直接调用时传递,而不是在传递和稍后调用时传递(这就是您正在做的)

必须使用例如
绑定此信息(即
值,即实例)。绑定

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

请注意,
.bind
在较旧的浏览器中不可用,但有模拟其行为的垫片可用。

setTimeout将运行绑定到
窗口的传递函数。您可以使用ES5覆盖此选项:


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

其他答案是正确的,但似乎没有人提到
Function.prototype.bind
是正确的。要使其正常工作,您需要包括。

这在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");

}

}

谢谢,这在chrome中有效,但在FF 3.6中无效??FF说“his.initialConnectionDetected.bind不是函数[Break On This Error]This.connection.detectInitialConnect…tialConnectionDetected.bind(This));”它从FF4开始可用,文章中有一个兼容表。您可以包括MDN提供的代码片段或google提供的“ES5垫片”。
//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");

}

}