我需要从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
}
}
如何在ajax.onload
中访问this.prefs?
答案 0 :(得分:84)
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);
}
答案 1 :(得分:75)
this.intervalID = setInterval(this.retrieve_rate.bind(this), this.INTERVAL);
答案 2 :(得分:18)
setInterval
的默认行为是绑定到全局上下文。您可以通过保存当前上下文的副本来调用成员函数。在retrieve_rate内部,this
变量将正确绑定到原始上下文。以下是您的代码的样子:
var self = this;
this.intervalID = setInterval(
function() { self.retrieve_rate(); },
this.INTERVAL);
额外提示:对于普通函数引用(与具有成员函数的对象引用相对),您可以使用JavaScript的call
或apply
方法更改上下文。
答案 3 :(得分:11)
通过改进浏览器支持,现在可以使用EcmaScript 6 enhancement, the arrow =>
method,以便正确保留this
。
startup : function()
{
// init prefs
...
this.retrieve_rate();
this.intervalID = setInterval( () => this.retrieve_rate(), this.INTERVAL);
},
使用=>当间隔调用this
时,方法会保留retrieve_rate()
。不需要时髦的自我或在参数中传递this
答案 4 :(得分:7)
window.setInterval(function(){console.log(this)}.bind(this), 100)
这在javascript中是合法的并且节省了大量代码:)
答案 5 :(得分:2)
这将是最干净的解决方案,因为大多数时候您实际上想要为连续的方法调用切换此上下文:
此外,它更容易理解。
// 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);
答案 6 :(得分: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
}
}
答案 7 :(得分:0)
在现代浏览器中,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>
答案 8 :(得分:-1)
这不是美容解决方案,但它是常用的:
var self = this;
var ajax = null;
//...
ajax.onload = function() {
self.prefs....;
}