2010-05-11 19 views
8

我做一些Ajax从JavaScript对象:的XMLHttpRequest对象内:如何保持提及“本”

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事件中的主要对象的引用吗?

回答

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),这只是对构造函数的引用。

也许题外话到这个问题,但推荐阅读:

4

的其他简单的解决方案是将您的onreadystatechange函数绑定到这一点。 bind -ing该函数与CMS的答案基本相同(即将值添加到闭包中),但bind以透明的方式进行:您继续使用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 
    } 
}; 
+0

我会强烈建议检查如果在创建它之前存在'Function.prototype.bind'方法,因为它是ECMAScript第5版标准的一部分,并且它正在被所有主要浏览器供应商实现,不久本地实现将可用,并且您不希望用你自己的代码覆盖它:[WebKit](https:// bugs.webkit.org/show_bug.cgi?id=26382),[Mozilla](https://bugzilla.mozilla.org/show_bug.cgi?id=429507),[Google V8](http://code.google .COM/p/V8 /问题/细节?ID = 384)。 – CMS 2010-05-11 20:34:10

相关问题