Javascript setInterval 和 `this` 解决方案

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2749244/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 01:44:43  来源:igfitidea点击:

Javascript setInterval and `this` solution

javascriptthissetinterval

提问by Pablo

I need to access thisfrom my setIntervalhandler

我需要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
        }
    }

How can I access this.prefs in ajax.onload?

如何访问 this.prefs ajax.onload

回答by AnthonyWJones

The setInterval line should look like this:-

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.
 ); 

Edit: The same principle applies to the " onload". In this case its common for the "outer" code to do little, it just sets up the request an then sends it. In this case the extra overhead an additinal function as in the above code is unnecessary. Your retrieve_rate should look more like this:-

编辑:同样的原则适用于“ 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);
}

回答by Nechehin

this.intervalID = setInterval(this.retrieve_rate.bind(this), this.INTERVAL);

回答by Joel Fillmore

The default behavior of setIntervalis to bind to the global context. You can call a member function by saving a copy of the current context. Inside retrieve_rate the thisvariable will be correctly bound to the original context. Here is what your code would look like:

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

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

Bonus tip: For a plain function reference (as opposed to an object reference which has a member function) you can change the context by using JavaScript's callor applymethods.

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

回答by Martlark

With improving browser support the time is now good to use the EcmaScript 6 enhancement, the arrow =>method, to preserve thisproperly.

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

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

Using => method preserves the thiswhen retrieve_rate()is called by the interval. No need for funky self or passing thisin parameters

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

回答by Daniel Apostolov

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

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

this is legal in javascript and saves lots of code :)

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

回答by Dbl

This would be the cleanest solution, since most of the time you actually want to switch the this context for your consecutive method calls:

这将是最干净的解决方案,因为大多数时候您实际上希望为连续的方法调用切换 this 上下文:

Also it's easier to grasp the concept of.

也更容易掌握概念。

    // 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);

回答by gaetanoM

With modern browsers the setInterval method allows additional parameters which are passed through to the function specified by func once the timer expires.

在现代浏览器中, setInterval 方法允许附加参数,一旦计时器到期,这些参数就会传递给 func 指定的函数。

var intervalID = scope.setInterval(func, delay[, param1, param2, ...]);

var intervalID = scope.setInterval(func, delay[, param1, param2, ...]);

Hence, a possible solution can be:

因此,一个可能的解决方案可以是:

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

A demo:

一个演示:

var timerId;
document.querySelector('#clickMe').addEventListener('click', function(e) {
    timerId = setInterval(function (self) {
        self.textContent = self.textContent.slice(0, -1);
        if (self.textContent.length == 0) {
            clearInterval(timerId);
            self.textContent = 'end..';
        }
    }, 250, this);
})
<button id="clickMe">ClickMe</button>

回答by Matthew Flaschen

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.
            // e.g. context.prefs
        }
    }

回答by Crozin

That's not a beauty solution but it's in common usage:

这不是美容解决方案,但它很常见:

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