2012-01-13 115 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"); 

} 

}