2012-01-13 117 views
2

伙计们 - 我想学习如何编写OO Javascript,我来自as3 OO背景... 问题我有一个类的方法作为回调传递给另一个类...范围做OO javascript回调

在下面的例子中

,我创建的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()); 
} 

回答

2

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

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

这不起作用在旧的浏览器,但所提供的MDN链接有一种变通方法。

+0

谢谢,在铬中工作,但不是在FF 3.6? FF说:“his.initialConnectionDetected.bind不是一个函数 [Break On This Error] this.connection.detectInitialConnect ... tialConnectionDetected.bind(this));” – nuway 2012-01-13 20:57:17

+0

它在FF4中可用,有一个兼容性表文章。您可以包含MDN提供的代码片段或谷歌的“ES5垫片”。 – Dennis 2012-01-13 22:15:09

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

this.initialConnectionDetected将传递功能,但是不应该在实例执行的信息。

调用this.foo()将通过这些信息,但只有当周围过去了,后来被称为(这是你在做什么)时直接调用,没有。

则必须将此信息绑定(即,this值,这是实例)使用例如.bind

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

注意.bind是不是在旧的浏览器可用,但也有模仿它的行为垫片。

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

} 

}