Google 闭包:将 'this' 传递给 window.setInterval
Google Closure: Passing 'this' into 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
}
}
在构造函数中,我调用了设置 window.setInterval 的 doInitialSend 函数。现在在 sendReport 函数中 'this' 的值不正确。如何正确传递 'this' 以获取正确的值而不是获取 window 的 this。
我尝试将 this 的值存储在引用中,但这也不起作用。例如
var that = this;
window.setInterval(that.sendReport, that.ws_ErrLgr_config);
你可以这样做:
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
,您可以在所需范围内调用该函数。
或者这样:
window.setInterval((function() {
this.sendReport();
}).bind(this), this.ws_ErrLgr_config.ReportInterval);
在 Google 闭包中执行此操作的惯用方法是使用 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
。这是不正确的,您应该选择一个数字来代表您的间隔。
我有一个模型 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
}
}
在构造函数中,我调用了设置 window.setInterval 的 doInitialSend 函数。现在在 sendReport 函数中 'this' 的值不正确。如何正确传递 'this' 以获取正确的值而不是获取 window 的 this。 我尝试将 this 的值存储在引用中,但这也不起作用。例如
var that = this;
window.setInterval(that.sendReport, that.ws_ErrLgr_config);
你可以这样做:
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
,您可以在所需范围内调用该函数。
或者这样:
window.setInterval((function() {
this.sendReport();
}).bind(this), this.ws_ErrLgr_config.ReportInterval);
在 Google 闭包中执行此操作的惯用方法是使用 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
。这是不正确的,您应该选择一个数字来代表您的间隔。