【问题标题】:Invoke a javascript object method from within a callback从回调中调用 javascript 对象方法
【发布时间】:2011-10-22 13:16:17
【问题描述】:

我在用户脚本中定义了以下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 在错误的上下文中被评估。

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

【问题讨论】:

    标签: javascript callback javascript-objects


    【解决方案1】:

    正如已经指出的那样,最简单的解决方案是为保持在范围内的this 创建一个别名。别名中最流行的变量名称是 self 或 that,但任何东西都可以,真的。

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

    var f = this.callback.bind(this);
    
    ...
    'onload': function(){
        f();
    }
    

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

    【讨论】:

    • 小心self,因为window.self。
    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

      将正确的this(当它在范围内)保存到变量中。以后可以参考:

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

      【讨论】:

      • +1 你刚刚结束了我长达一小时的头撞会议。谢谢你。 :)
      猜你喜欢
      • 2014-11-13
      • 1970-01-01
      • 1970-01-01
      • 2016-02-11
      • 2015-02-12
      • 1970-01-01
      • 2021-08-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多