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にアクセスするにはどうすればよいですか?
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);
}
this.intervalID = setInterval(this.retrieve_rate.bind(this), this.INTERVAL);
setInterval
のデフォルトの動作は、グローバルコンテキストにバインドすることです。現在のコンテキストのコピーを保存して、メンバー関数を呼び出すことができます。 retrieve_rate内では、this
変数は元のコンテキストに正しくバインドされます。コードは次のようになります。
var self = this;
this.intervalID = setInterval(
function() { self.retrieve_rate(); },
this.INTERVAL);
おまけのヒント:(メンバー関数を持つオブジェクト参照ではなく)単純な関数参照の場合、JavaScriptのcall
またはapply
メソッドを使用してコンテキストを変更できます。
ブラウザーのサポートが改善されたことで、 EcmaScript 6の機能強化、矢印_=>
_メソッド を使用してthis
を適切に保持できるようになりました。
_startup : function()
{
// init prefs
...
this.retrieve_rate();
this.intervalID = setInterval( () => this.retrieve_rate(), this.INTERVAL);
},
_
=>メソッドを使用すると、retrieve_rate()
が間隔によって呼び出されたときにthis
が保持されます。ファンキーな自己やパラメーターでthis
を渡す必要はありません
window.setInterval(function(){console.log(this)}.bind(this), 100)
これはjavascriptで合法であり、多くのコードを保存します:)
ほとんどの場合、実際の連続したメソッド呼び出しで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);
最新のブラウザでは、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>
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
}
}