Javascript的setInterval和`这个`解决scheme

我需要从我的setInterval处理程序访问this

 prefs: null, startup : function() { // init prefs ... this.retrieve_rate(); this.intervalID = setInterval(this.retrieve_rate, this.INTERVAL); }, retrieve_rate : function() { var ajax = null; ajax = new XMLHttpRequest(); ajax.open('GET', 'http://xyz.com', true); ajax.onload = function() { // access prefs here } } 

如何在ajax.onload访问this.prefs?

setInterval行应该像这样:

  this.intervalID = setInterval( (function(self) { //Self-executing func which takes 'this' as self return function() { //Return a function in the context of 'self' self.retrieve_rate(); //Thing you wanted to run as non-window 'this' } })(this), this.INTERVAL //normal interval, 'this' scope not impacted here. ); 

编辑 :同样的原则适用于“ onload ”。 在这种情况下,对于“外部”代码通常做的事情很less,它只是设置请求,然后发送它。 在这种情况下,额外的开销就像上面代码中的附加函数是不必要的。 您的retrieve_rate应该看起来更像这样:

 retrieve_rate : function() { var self = this; var ajax = new XMLHttpRequest(); ajax.open('GET', 'http://xyz.com', true); ajax.onreadystatechanged= function() { if (ajax.readyState == 4 && ajax.status == 200) { // prefs available as self.prefs } } ajax.send(null); } 
 this.intervalID = setInterval(this.retrieve_rate.bind(this), this.INTERVAL); 

setInterval的默认行为是绑定到全局上下文。 您可以通过保存当前上下文的副本来调用成员函数。 在retrieve_rate里面, thisvariables将被正确地绑定到原始上下文。 以下是你的代码的样子:

 var self = this; this.intervalID = setInterval( function() { self.retrieve_rate(); }, this.INTERVAL); 

奖金提示:对于普通函数引用(与具有成员函数的对象引用相对),可以使用JavaScript的callapply方法更改上下文。

通过改进浏览器支持,现在可以使用EcmaScript 6增强function(箭头=>方法)来正确保护this

 startup : function() { // init prefs ... this.retrieve_rate(); this.intervalID = setInterval( () => this.retrieve_rate(), this.INTERVAL); }, 

当间隔调用retrieve_rate()时,使用=>方法保留this 。 不需要时髦的自我或parameter passing

window.setInterval(function(){console.log(this)}.bind(this), 100)

这是合法的JavaScript和节省大量的代码:)

 prefs: null, startup : function() { // init prefs ... this.retrieve_rate(); var context = this; this.intervalID = setInterval(function() { context.retrieve_rate(); }, this.INTERVAL); }, retrieve_rate : function() { var ajax = null; ajax = new XMLHttpRequest(); ajax.open('GET', 'http://xyz.com', true); var context = this; ajax.onload = function() { // access prefs using context. // eg context.prefs } } 

这将是最干净的解决scheme,因为大多数情况下,您实际上想要为连续的方法调用切换此上下文:

也更容易把握这个概念。

  // store scope reference for our delegating method var that = this; setInterval(function() { // this would be changed here because of method scope, // but we still have a reference to that OURMETHODNAME.call(that); }, 200); 

这不是一个美容解决scheme,但它是常用的:

 var self = this; var ajax = null; //... ajax.onload = function() { self.prefs....; }