从回调中调用 javascript 对象方法

问题描述 投票:0回答:4

我在用户脚本中定义了以下

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)错误:

未捕获类型错误:对象 [object DOMWindow] 没有方法“myCallback”。

似乎

this
正在错误的环境中进行评估。

有没有一种方法可以调用

myCallback()
myClassInstance
方法而无需使用全局变量?

javascript callback javascript-objects
4个回答
40
投票

将正确的

this
(当其在范围内时)保存到变量中。以后可以参考:

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

8
投票

正如已经指出的,最简单的解决方案是为保留在范围内的

this
创建一个别名。最流行的别名变量名称是
self
that
,但任何东西都可以,真的。

另一种选择(可能会更好,也可能不会更好,具体取决于用例)是将方法绑定到“普通”函数中并使用它:

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

...
'onload': function(){
    f();
}

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


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

0
投票

使用现代 JavaScript,可以通过箭头函数更优雅地解决这个问题,从而保留

this

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

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

var myClassInstance = new MyClass();
myClassInstance.startRequest();
© www.soinside.com 2019 - 2024. All rights reserved.