3

我有一个案例,我有一个对象“foo”,它需要在另一个对象“bar”上调用回调,并且我需要回调中的上下文是“bar”的上下文。然而,更重要的是,除了从“bar”获得回调之外,“foo”不应该对此一无所知。

例子:

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

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

};

foo.doStuff = bar.callback;

foo.doStuff();

我意识到通常你会使用“调用”或“应用”将上下文切换到 bar,但在我的特殊情况下,在调用时foo.doStuff()我不再有关于回调来自何处的信息。那么是否有另一种计算上下文的方法(比如从回调函数本身)?

4

3 回答 3

1

那么是否有另一种计算上下文的方法(比如从回调函数本身)?

没有。在您传递回调之前,并非没有一些额外的细节。如果您只有一个函数引用,那么您通常没有上下文。但是有了一些准备,就有了一些解决方案。

你可以包装回调。调用 this 时,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(); };
于 2012-11-21T19:16:53.943 回答
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

于 2012-11-21T19:47:53.907 回答
0

我会用闭包来做。

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

如果您担心 bar 的值在您创建回调的那一刻和它执行的那一刻之间发生了变化,您可以“锁定” bar 的值,但这可能是矫枉过正

foo.doStuff = (function(bar){
  return function(){
    bar.callback();
  }
})(bar);
于 2012-11-21T19:24:35.637 回答