2014-01-08 35 views
0

合適的對象我有目標對象獲取回調

function Foo() { 
    this.someVar = 'some var'; 
}; 

Foo.prototype.callback() { 
    console.log(this); 
}; 

和對象,將調用這個回調

function Bar(callback) { 
    this.callback = callback; 
}; 

Bar.prototype.onSomeAction = function() { 
    this.callback(); 
}; 

和初始代碼

foo = new Foo(); 
bar = new Bar(); 

bar.callback = foo.callback; 
bar.onSomeAction(); 

結果:我已經記錄到控制檯Bar()的上下文而不是Foo()。 如何獲得Foo()回調中的Foo()的上下文?

PS:我試圖關閉

Foo.prototype.callback() { 

    var foo = this; 
    return function(foo) { 
     console.log(foo); 
    }; 
}; 

但不起任何作用。我還沒有完全理解:(封的

回答

0

嘗試使用這些變化:

  1. 使用call設置背景:

    bar.onSomeAction.call(foo); 
    
  2. 而且我覺得你的callback功能需要改變,以:

    Foo.prototype.callback=function() {  
        console.log(this);  
    }; 
    
2

的原因,您原來的代碼不工作是,this方法調用內部的價值是它被稱爲對對象的值。這意味着,當你說:

bar.callback = foo.callback; 

然後調用:

bar.callback(); 

這裏定義的代碼:

Foo.prototype.callback = function() { 
    console.log(this); 
}; 

被稱爲與this其事bar一個參考,因爲bar是方法調用的.的左側。所以,無論何時將一個函數指定爲對象屬性,在該對象上調用該函數都會將其作爲對象調用this

你還可以這樣寫:

function callback() { 
    console.log(this); 
} 
bar.callback = callback; 
bar.callback(); 

而且你會發現,this仍然引用bar。實際上,如果您調用上面定義的普通函數callback();,則會發現this是對全局對象的引用,通常是網頁瀏覽器中的window。這是因爲所有的全局變量和函數的window性質,所以callback();是隱含window.callback();

說的this的價值取決於什麼對象調用函數繞過回調時可能會出現問題的事實,因爲有時你想this來引用該函數是一個屬性的原始對象。綁定方法是設計來解決這個問題,和Yuri Sulyma給出了正確的答案:

bar.callback = foo.callback.bind(foo); 

但是,你會做到這一點使用閉包的方式是調用正確的匿名函數中捕獲的Foo實例方法正確的對象:

foo = new Foo(); 
bar = new Bar(); 

bar.callback = function() { 
    foo.callback(); 
}; 
bar.onSomeAction(); 

這基本上是什麼綁定。事實上,我們所說的用一個封閉寫我們自己綁定的幼稚版本:

Function.prototype.bind = function (obj) { 
    var fn = this; 
    return function() { 
    fn.call(obj); 
    }; 
}; 

call讓我們調用一個函數明確定義的this值。這允許您在「設置上下文」中調用該功能,以便當您致電bar.callback()時調用obj.fn()。因爲當我們呼叫foo.callback.bind(foo);時,objfoofnfoo.callback,結果是呼叫bar.callback()變得與呼叫foo.callback()相同。

這就是Dalorzo的答案來自何處。他使用call來顯式設置上下文。

還有另一個函數用於設置名爲apply的上下文,該函數還將表示函數參數的數組作爲第二個參數。這使我們能夠利用特殊的arguments變量編寫更完整版本的綁定:

Function.prototype.bind = function (obj) { 
    var fn = this; 
    return function() { 
    fn.apply(obj, arguments); 
    }; 
}; 
+0

個人而言,我避免在回調函數中使用'this',而是堅持使用閉包。這樣,回調在被調用時的行爲方式與它的屬性無關。 –

+0

感謝您的詳細解答!但我對閉包不太熟悉,這是我第一個複雜的基於JS的應用程序。 – Neka

+0

閉包只是讓你說「運行這段代碼就好像它正在被寫入的地方,而不是它被調用的地方」的一種奇特的方式。這對於基於事件的API中的回調來說非常完美,因爲大多數情況下,回調中接下來要做的事情與剛做的事情處於相同的上下文環境中,所以您希望訪問所有相同的變量和所有內容。你所要做的就是將一些代碼包裝在一個函數中,並作爲回調傳遞給它。有時候瀏覽一些NodeJS代碼(有很多很好的例子),你會發現很多匿名函數作爲其他函數的參數。 –