Javascript setInterval 和 `this` 解决方案

IT技术 javascript this setinterval
2021-01-14 05:40:59

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

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
        }
    }

如何访问 this.prefs ajax.onload

6个回答
this.intervalID = setInterval(this.retrieve_rate.bind(this), this.INTERVAL);
从 IE9 开始就支持它,所以对我来说是一个干净的解决方案。
2021-03-17 05:40:59
但是这种方法有一个缺点。很可能,它不适用于旧版本的 IE
2021-03-18 05:40:59
@Nechehin 值得注意。但它仍然是一个更清洁的解决方案。
2021-04-04 05:40:59
这是正确的解决方案。公认的解决方案似乎需要不必要的更多代码。
2021-04-08 05:40:59
如果您需要支持 IE8并且您正在使用Underscore.js,您可以使用_.bindthis.intervalID = setInterval(_.bind(this.retrieve_rate, this), this.INTERVAL);
2021-04-08 05:40:59

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”。在这种情况下,“外部”代码通常做的很少,它只是设置请求然后发送它。在这种情况下,不需要额外的开销,如上述代码中的附加功能。您的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);
}
@Matthew Flaschen:它对这个场景和 for 循环一样有用。
2021-03-12 05:40:59
@Anthony:所以这里的技巧self是唯一的选择?你能确认马修的解决方案不起作用吗?
2021-03-28 05:40:59
@Michael:首先,它不是“技巧”,而是 Javascript 中的工作方式。在撰写此评论时,马修的回答目前无效。它的早期版本可能有效,但它涉及this作为参数传递,这是不必要的和尴尬的(任何调用者retrieve_rate都会知道这个不必要的特殊要求)。
2021-03-31 05:40:59
我最初打算这样做,但后来我想起了这种模式对于循环来说真的最有用。
2021-04-06 05:40:59
this作为参数传递(function(self){...})(this)in setInterval 对我不起作用,因为该函数是立即执行而不是被延迟。@Joel Fillmore 的解决方案对我有用
2021-04-09 05:40:59

的默认行为setInterval是绑定到全局上下文。您可以通过保存当前上下文的副本来调用成员函数。在retrieve_rate 中,this变量将正确绑定到原始上下文。您的代码如下所示:

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

额外提示:对于普通函数引用(与具有成员函数的对象引用相对),您可以使用 JavaScriptcallapply方法更改上下文

这对我有用,但似乎不需要调用“调用”。缺省情况下,retrieve_rate 的上下文应设置为 self,因为它是作为成员函数调用的。
2021-03-11 05:40:59
@Dreendle - 你是对的,我记得在需要的地方解决了这个回调函数引用。我已经修复了答案,谢谢!
2021-03-18 05:40:59

随着浏览器支持的改进,=>现在是时候使用EcmaScript 6 增强,即箭头方法this正确保存了

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

使用=>方法保留thisretrieve_rate()由间隔调用。不需要时髦的自我或传入this参数

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

这在 javascript 中是合法的,并且可以节省大量代码 :)