1

我有以下 Javascript 代码,我正在尝试让回调工作,如下所示。我想看到一个带有“123”的警报。

var A = function(arg){
    this.storedArg = arg;
    this.callback = function(){ alert(this.storedArg); }
}

var B = function() {
    this.doCallback = function(callback){ callback(); }
}       

var pubCallback = function(){ alert('Public callback') };

var a = new A(123);
var b = new B();

b.doCallback(pubCallback); // works as expected
b.doCallback(a.callback);  // want 123, get undefined

我明白发生了什么,但我不知道如何解决它。如何获得引用我的对象的回调函数?就我而言,我可以更改 A 但不能更改 B。

4

6 回答 6

2

所以你想要的是将上下文传递给doCallBack.

例如

doCallBack = function (callback, callee) { 
    callback.apply(callee);
}

那么你会这样做:

b.doCallBack(a.callback, a);

如果你不能修改 B,那么你可以在 A 中使用闭包:

var A = function (arg) {
    var self = this;
    this.storedArg = arg;
    this.callback = function () { alert(self.storedArg); }
}
于 2012-10-15T14:51:22.387 回答
2

this您可以通过将其放入变量中来创建一个包含所需范围的变量that

var A = function(arg){
    this.storedArg = arg;
    var that = this; // Add this!
    this.callback = function(){ alert(that.storedArg); }
}

在这里工作演示:http: //jsfiddle.net/vdM5t/

于 2012-10-15T14:52:32.637 回答
1

我了解发生了什么(在第二次回调期间,“this”是 b 而不是 a)

不,JS 不是可能发生某些事情的基于类的语言。如果function(){ alert(this.storedArg);只是被称为callback();(如 in b.doCallback),则this关键字指向全局对象(window)。

要解决这个问题,您必须更改A

var A = function(arg){
    var that = this; // store reference to the current A object
    this.storedArg = arg;
    this.callback = function(){
        alert(that.storedArg); // and use that reference now instead of "this"
    };
}

如果您不希望storedArg属性发生变化,您甚至可以使其更简单:

var A = function(arg){
    this.storedArg = arg;
    this.callback = function(){
        alert(arg); // just use the argument of the A function,
                    // which is still in the variable scope
    };
}
于 2012-10-15T14:53:08.250 回答
1

您需要传递您希望回调执行的上下文:

var B = function() {
    this.doCallback = function(callback, context) {
        callback.apply(context); 
    };
};

b.doCallback(a.callback, a); // 123

http://jsfiddle.net/a9N66/

于 2012-10-15T14:55:07.313 回答
1

因为在A.callback函数内部,this不是指对象A而是window对象。

var A = function(arg){
    this.storedArg = arg;
    this.callback = function(){ alert(this.storedArg); }
    -----------------------------------^-----------------
}

你可以试试这个

var A = function(arg){
    this.storedArg = arg;
    var that = this;
    this.callback = function(){ alert(that.storedArg); }
}

var B = function() {
    this.doCallback = function(callback){ callback(); }
}       

var pubCallback = function(){ alert('Public callback') };

var a = new A(123);
var b = new B();

b.doCallback(pubCallback); // works as expected
b.doCallback(a.callback);  // alerts 123
于 2012-10-15T14:55:49.703 回答
0

当你这样做时:

b.doCallback(a.callback);

只是调用 a 的callback函数而不告诉它使用afor this;所以全局对象用于this.

一种解决方案是将回调包装起来:

b.doCallback(function() { a.callback(); });

其他解决方案包括将回调绑定a,使用jQuery.proxy()(这只是我第一个解决方案的一种奇特方式),或者使用apply传入adoCallback调用callbacka

于 2012-10-15T14:53:26.273 回答