在回调中获取正确的对象

时间:2014-01-08 01:51:00

标签: javascript

我有目标对象

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

但它什么也没做。我还没有完全理解闭包:(

3 个答案:

答案 0 :(得分: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是对全局对象的引用,通常是Web浏览器中的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();

这本质上是绑定的作用。实际上,我们使用闭包来调用我们自己的naive版本的bind:

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

call让你调用一个明确定义this值的函数。这允许您“设置上下文”调用函数,以便与调用obj.fn()时调用bar.callback()相同。由于我们致电foo.callback.bind(foo);时,objfoofnfoo.callback,因此调用bar.callback()与调用{{}}相同{1}}。

Dalorzo的回答来自于此。他使用foo.callback()显式设置上下文。

还有另一个函数用于设置名为call的上下文,该函数还将表示函数参数的数组作为其第二个参数。这允许我们通过利用特殊的apply变量来编写更完整的bind版本:

arguments

答案 1 :(得分:0)

尝试使用这些更改:

  1. 使用call设置上下文:

    bar.onSomeAction.call(foo);
    
  2. 我认为您的callback功能需要更改为:

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

答案 2 :(得分:0)

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

如有必要,您可以填充Function.prototype.bind()https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind#Compatibility