Закрытие Google: передача "this" в window.setInterval
У меня есть файл модели JS, который выглядит как
goog.provide('model.ErrorLogger');
/**
* @constructor
*/
model.ErrorLogger = function() {
window.onerror = goog.bind(this.errorHandler, this);
this.doInitialSend();
};
goog.addSingletonGetter(model.ErrorLogger);
model.ErrorLogger.prototype.ws_ErrLgr_config = true;
model.ErrorLogger.prototype.doInitialSend = function(){
if (this.ws_ErrLgr_config){
window.setInterval(this.sendReport, this.ws_ErrLgr_config);
}
};
model.ErrorLogger.prototype.sendReport = function(){
// the value of 'this' needs to be of the ErrorLogger model and not windows
if (!this.ws_ErrLgr_config || this.stopped) {
//some more code here
}
}
В конструкторе я вызываю функцию doInitialSend, которая устанавливает window.setInterval. Теперь в функции sendReport значение this не является правильным. Как правильно передать "this", чтобы получить правильное значение вместо окна "this". Я попытался сохранить значение этого в ссылке, но это тоже не сработало. Например
var that = this;
window.setInterval(that.sendReport, that.ws_ErrLgr_config);
3 ответа
Идиоматический способ сделать это в Google Closure использует goog.bind
с тем преимуществом, что гарантировано, что он всегда будет работать. Плюс это будет использовать Function.prototype.bind()
под капотом, когда это доступно.
В этом случае решение будет:
myIntervalInMilliseconds = 1000; // One second.
window.setInterval(goog.bind(this.sendReport, this), myIntervalInMilliseconds);
С помощью that = this
работает, но требует, чтобы вы явно обернули свою функцию в другую, чтобы захватить that
как this
в желаемой функции.
Это намного лучше, используя Function.prototype.bind()
для этого, как указано в других ответах. Однако это не сработает, если вы хотите поддерживать старые браузеры (IE <9).
PS: Еще одна проблема в вашем коде в том, что он использует this.ws_ErrLgr_config
в качестве интервала, который установлен в true
в прототипе. Это неверно, вы должны выбрать число для представления вашего интервала.
Или это:
window.setInterval((function() {
this.sendReport();
}).bind(this), this.ws_ErrLgr_config.ReportInterval);
Вы можете сделать это:
var that = this;
window.setInterval(function() {
that.sendReport()
}, this.ws_ErrLgr_config.ReportInterval);
Таким образом, вы можете вызвать sendReport в правильном контексте, также это работает:
window.setInterval(this.sendReport.bind(this), this.ws_ErrLgr_config.ReportInterval);
Причина по которой window.setInterval(that.sendReport, this.ws_ErrLgr_config.ReportInterval)
не работает, потому что Javascript передается по значению. Вышеупомянутое утверждение эквивалентно:
window.setInterval(function(){
// the value of 'this' needs to be of the ErrorLogger model and not windows
if (!this.ws_ErrLgr_config || this.stopped) {
//some more code here
}
}, this.ws_ErrLgr_config.ReportInterval);
Используя ключевое слово.bind() или поместив его в другую функцию, а затем ссылаясь на that
из внешнего прицела вы можете вызвать функцию в нужной вам области.