75

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

4

9 回答 9

104
this.intervalID = setInterval(this.retrieve_rate.bind(this), this.INTERVAL);
于 2014-02-11T20:24:17.180 回答
94

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);
}
于 2010-05-01T08:12:51.877 回答
19

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

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

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

于 2011-10-22T21:09:56.993 回答
14

随着浏览器支持的提高,现在可以使用EcmaScript 6 增强的箭头=>方法this正确保存。

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

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

于 2016-07-16T06:11:44.940 回答
10

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

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

于 2016-10-15T09:06:19.147 回答
3

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

也更容易掌握的概念。

    // 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);
于 2014-11-05T14:48:32.277 回答
2

在现代浏览器中,setInterval 方法允许在计时器到期后将附加参数传递给 func 指定的函数。

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

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

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

一个演示:

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>

于 2018-09-17T21:18:05.603 回答
0
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
        }
    }
于 2010-05-01T08:04:19.583 回答
-1

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

var self = this;
var ajax = null;
//...
ajax.onload = function() {
    self.prefs....;
}
于 2010-05-01T08:04:12.047 回答