从回调中调用javascript对象方法

时间:2011-08-08 16:29:48

标签: javascript callback javascript-objects

我在用户脚本中定义了以下MyClass及其方法:

function MyClass() {
    this.myCallback = function() {
        alert("MyClass.myCallback()");
    };

    this.startRequest = function() {
        GM_xmlhttpRequest({
            'method': 'GET',
            'url': "http://www.google.com/",
            'onload': function (xhr) {
                myClassInstance.myCallback();
            }
        });
    };
}

var myClassInstance = new MyClass();
myClassInstance.startRequest();

此脚本有效, GM_xmlhttpRequest 完成后会调用myCallback()方法。

但是,它只能起作用,因为onload回调指的是全局变量myClassInstance。如果我将onload回调更新为:

'onload': function (xhr) {
    this.myCallback();
}

然后我收到了(Chrome)错误:

  

未捕获TypeError:对象[object DOMWindow]没有方法'myCallback'。

似乎在错误的背景下评估this

有没有办法调用myCallback() myClassInstance方法而不必使用全局变量?

3 个答案:

答案 0 :(得分:31)

将正确的this保存在变量中。然后你可以在以后引用它:

 this.startRequest = function() {
     var myself = this;
     GM_xmlhttpRequest({
         'method': 'GET',
         'url': "http://www.google.com/",
         'onload': function (xhr) {
             myself.myCallback();
         }
     });
 };

答案 1 :(得分:6)

正如已经指出的那样,最简单的解决方案是为保留在范围内的this创建别名。别名最受欢迎的变量名称是selfthat之类的东西,但实际上它们都有效。

另一种替代方案(可能会或可能不会更好,取决于用例)将方法绑定到“普通”函数并使用它来代替:

var f = this.callback.bind(this);

...
'onload': function(){
    f();
}
旧浏览器不支持

bind,但您可以在许多JS框架中找到替代方法。我给出的示例看起来不太好,但是当你想直接将你的方法作为回调函数传递时,它会非常方便(你也可能得到部分函数应用程序,而且非常整洁)

答案 2 :(得分:3)

存储对实例的引用并使用它:

function MyClass() {
    this.myCallback = function() {
        alert("MyClass.myCallback()");
    };

    var instance = this;

    instance.startRequest = function() {
        GM_xmlhttpRequest({
            'method': 'GET',
            'url': "http://www.google.com/",
            'onload': function (xhr) {
                instance.myCallback();
            }
        });
    };
}