对象内部的XMLHttpRequest:如何保持对“this”的引用

时间:2010-05-11 05:41:50

标签: javascript ajax

我在javascript对象中进行了一些Ajax调用。:

myObject.prototye = {
  ajax: function() {
    this.foo = 1;

    var req = new XMLHttpRequest();
    req.open('GET', url, true);
    req.onreadystatechange = function (aEvt) {  
      if (req.readyState == 4) {  
        if(req.status == 200)  {
          alert(this.foo); // reference to this is lost
        }
      }
  }
};

在onreadystatechange函数中,这不再引用主对象,所以我无法访问this.foo。我可以在XMLHttpRequest事件中保留对主对象的引用吗?

2 个答案:

答案 0 :(得分:7)

最简单的方法通常是将this的值存储在局部变量上:

myObject.prototype = {
  ajax: function (url) { // (url argument missing ?)
    var instance = this; // <-- store reference to the `this` value
    this.foo = 1;

    var req = new XMLHttpRequest();
    req.open('GET', url, true);
    req.onreadystatechange = function (aEvt) {  
      if (req.readyState == 4) {  
        if (req.status == 200)  {
          alert(instance.foo); // <-- use the reference
        }
      }
    };
  }
};

我还怀疑您的myObject标识符确实是constructor function(您正在分配prototype属性)。

如果是这种情况,请不要忘记包含正确的constructor属性(因为您要替换整个prototype),这只是对构造函数的引用。

可能偏离此问题,但建议阅读:

答案 1 :(得分:5)

另一个简单的解决方案是将onreadystatechange函数绑定到此。 bind - 该函数与CMS的答案基本相同(即将值添加到闭包中),但bind以透明方式执行:您继续使用{{1}而不是设置this变量。

如果您的代码库不包含一个instance,那么这是一个Function#bind实现:

Function.prototype.bind = function(obj) {
    var __method = this;
    var args = []; for(var i=1; i<arguments.length; i++) args.push(arguments[i]);
    return function() {
        var args2 = []; for(var i=0; i<arguments.length; i++) args2.push(arguments[i]);
        return __method.apply(obj, args.concat(args2));
    };
}

以下是您在代码中使用它的方法:

myObject.prototype = {
  ajax: function() {
    this.foo = 1;

    var req = new XMLHttpRequest();
    req.open('GET', url, true);
    req.onreadystatechange = function (aEvt) {  
      if (req.readyState == 4) {  
        if(req.status == 200)  {
          alert(this.foo); // reference to this is *kept*
        }
      }
    }.bind(this) // <- only change
  }
};