2012-11-21 27 views
3

我有一個情況,我有一個對象,「富」,需要調用另一個對象的回調,「酒吧」,我需要在回調內的上下文是「酒吧」的。不過,踢球者除了從「酒吧」得到回撥之外,「富」不應該知道這件事。從Javascript中的回調中的對象獲取上下文

例子:

var foo = 
{ 
    message: "Hello foo", 
    doStuff: undefined 
}; 

var bar = 
{ 
    message: "Hello bar", 
    callback = function() 
    { 
     alert(this.message); 
    } 

}; 

foo.doStuff = bar.callback; 

foo.doStuff(); 

我認識到,通常你會使用「呼叫」或「應用」來切換背景吧,但在我的特殊情況下,在調用foo.doStuff()我不再有信息的時間關於回調來自何處。那麼有沒有另外一種方法來確定上下文(比如從回調函數本身來說)?

+4

'foo.doStuff = bar.callback.bind(巴);'。或'foo.doStuff = function(){bar.callback.call(bar)};'這基本上是'bind'在幕後做的事情。 – banzomaikaka

+0

'bar.callback.call(bar)'在功能上與'bar.callback()'相同。 –

回答

1

那麼還有另一種方法來確定上下文(比如從回調函數本身來說)?

沒有。在通過回調之前不需要一些額外的具體內容。如果你只有一個函數引用,你通常沒有上下文。但有一些準備,有一些解決方案。

你可以包裝回調。當這個被調用時,bar.callback()將以完整形式被調用,保留bar的上下文。

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

或者在現代JS引擎中,您可以將回調綁定到特定的上下文。

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

或者使用underscore.js做,在所有的JS引擎。

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

或者如果您想要與舊引擎兼容並且不想爲整個庫使用它,請自行創建綁定函數。

var bind = function(fn, context) { 
    return function() { 
    fn.call(context); 
    }; 
}; 
foo.doStuff = bind(bar.callback, bar); 

所有這一切說,一個簡單的包裝,通常是最簡單也是最常見的。它沒有什麼缺點,它很快,很容易理解,並且可以很好地控制用什麼參數調用的東西。在這種情況下,這種形式使我覺得最有意義。

foo.doStuff = function() { bar.callback(); }; 
+0

謝謝,綁定正是我一直在尋找的。包裝在一個函數中可能會工作,但由於我動態地檢索回調函數,我不知道需要傳遞哪些參數(直到調用該函數爲止),所以我無法在將回調函數分配給另一個對象。 唯一可怕的部分是MDN說Safari瀏覽器手機不支持綁定(儘管一些使用jsfiddle的快速測試似乎證明不然)。儘管如此,儘管如此,我仍然需要添加一個polyfill才能使其工作。 – user1601333

0

我會做一個關閉。

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

如果您擔心條的值是您創建的回調執行它的那一刻剎那之間改變,你可以「鎖定」欄中的值,但可能是矯枉過正

foo.doStuff = (function(bar){ 
    return function(){ 
    bar.callback(); 
    } 
})(bar); 
1

使用關閉欄。

var foo = { 
    message: "Hello foo", 
    doStuff: undefined 
}; 

var bar = (function() { 
    var message = "Hello bar"; 
    return { 
     callback: function() {     
      alert(message); 
     } 
    }; 
})(); 


foo.doStuff = bar.callback; 
foo.doStuff(); 
​ 

jsfiddle