从回调中调用javascript对象方法

Jas*_*son 19 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();
Run Code Online (Sandbox Code Playgroud)

此脚本有效,GM_xmlhttpRequest完成后将myCallback()调用该方法.

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

'onload': function (xhr) {
    this.myCallback();
}
Run Code Online (Sandbox Code Playgroud)

然后我得到(Chrome)错误:

未捕获的TypeError:Object [object DOMWindow]没有方法'myCallback'.

似乎this正在错误的背景下进行评估.

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

Jer*_*emy 32

this其在范围内时保存到变量中.然后你可以在以后引用它:

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

  • +1你刚刚结束我的小时长头猛击会议.谢谢.:) (5认同)

hug*_*omg 6

正如已经指出的那样,最简单的解决方案是为this范围内的别名创建别名.别名最流行的变量名称是self或者类似的东西that,但是真的有效.

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

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

...
'onload': function(){
    f();
}
Run Code Online (Sandbox Code Playgroud)

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

  • 因为"window.self"而要小心`self`. (3认同)