将方法作为回调传递

3

我正在尝试将一个方法作为回调引用传递给另一个类的方法:

function A() {
    this.callback = function(){return 0;};
}

A.prototype.set = function(cb) {
    this.callback = cb;
};

A.prototype.test = function(){
    console.log("test " + this.callback());
};

function B(o) {
    this.prop = "blah B";
    o.set(this.blah);
}

B.prototype.blah = function() {
    console.log(this);
    return this.prop;
};

我对执行的期望

a = new A();
b = new B(a);
a.test();

是结果

>B { prop="blah B", blah=function()}
>test blah B

但是控制台显示的是:
>A { cb=function(), set=function(), test=function()}
>test undefined

似乎将方法blah分配给执行的A..

为什么我得到这个结果?
我该如何获得我预期的结果?

4个回答

3
"就好像方法blah已经被分配给执行对象a一样",你差不多理解了,只需在句子中将"A"替换为"a"。实际上,默认情况下,this指的是拥有该方法的实例
恰好,o.set(this.blah)可以翻译成a.callback = b.blah,这意味着a.callbackb.blah现在引用同一个函数。换句话说,同一个函数现在由实例ab所拥有:
a.callback() // "return (this -> a).prop" -> undefined
b.blah()     // "return (this -> b).prop" -> "blah B"

粗略地说,您需要一种方法在回调函数中将this重定向到b。您可以使用闭包中的任何一个:
var me = this;
o.set(function () {
    // this -> a
    // me   -> b
    return me.blah();
});

或者 绑定 (不支持IE8及以下版本) :

o.set(this.blah.bind(this));

闭包方法不起作用,需要是function(){return me.blah();}(因为blah返回一个值)。我不知道bind,它很有趣...而且对于IE兼容性来说并不重要,我的代码其余部分也不兼容<IE8... - Thierry J.
@ThierryJ。感谢您的回复,我已经相应地修正了答案。 - user1636522

2
是的,这就是 JavaScript 的 this 关键字的工作方式 - 它指的是当前执行上下文,在这种情况下它被调用的对象。你正在像调用A的方法一样调用它。你需要将它作为B实例的方法来调用。如果你不需要支持IE8或更低版本,你可以使用Function.prototype.bind this 绑定到函数中,以便它始终指向B实例。否则,A实例需要一个引用来调用该方法的B实例。
您可以使用 var self = this; hack 手动绑定该方法。您也可以在B构造函数中这样做:
function B(o) {
    var self = this;
    this.prop = "blah B";
    o.set(function() { self.blah(); });
}

但是,如果您能更详细地解释一下您想要做什么,可能会有更优雅的解决方案。

2
问题出在执行上下文——JavaScript中函数的this是如何绑定的。当调用最终行的a.test()时,callback会在对象a的上下文中查找名为prop的属性。在您的情况下,对象a没有prop属性,因此结果是undefined。当您向a提供一个prop属性时,它就可以正常工作了。带有console.log的最终代码在这里。在这里,回调被调用两次,一次没有分配prop,第二次分配了相同的prop
function B(o) {
    this.prop = "blah B";
    o.set(this.blah);
    o.prop = this.prop;
}

1
当在 test 方法内部调用 blah 方法时,this 指向一个 A 实例。由于 A 没有 prop 属性,因此返回 undefined。
你需要将 o.set(this.blah); 这行代码改为 o.set(this.blah.bind(this)); 现在,blah 总是绑定到一个 B 实例,并且当调用 test 时,this.prop 将返回预期的值 "blah B"。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接