【问题标题】:Google Closure: Passing 'this' into window.setInterval谷歌关闭:将“this”传递给window.setInterval
【发布时间】:2015-06-29 22:29:25
【问题描述】:

我有一个模型 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' 以获得正确的值,而不是获取窗口的 this。 我尝试将 this 的值存储在引用中,但这也不起作用。例如

var that = this;
window.setInterval(that.sendReport, that.ws_ErrLgr_config);

【问题讨论】:

    标签: javascript closures google-closure-compiler google-closure google-closure-library


    【解决方案1】:

    在 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


    PS:您代码中的另一个问题是它使用this.ws_ErrLgr_config 作为间隔,在原型中设置为true。这是不正确的,您应该选择一个数字来表示您的区间。

    【讨论】:

    • goog.bind 只是 Function.prototype.bind 的一个 pollyfill。如果浏览器支持原生函数绑定,goog.bind 会使用它。
    • 这真的很棒。非常感谢。
    【解决方案2】:

    或者这个:

    window.setInterval((function() {
        this.sendReport();
    }).bind(this), this.ws_ErrLgr_config.ReportInterval);
    

    【讨论】:

    • 是的,这也有效。更短的是:this.sendReport.bind(this)。但现在你忘记了间隔。 this.ws_ErrLgr_config.ReportInterval
    • 你是对的,我的错。更短的版本更好。我应该更改帖子吗?
    • 没关系,越多越好。看到解决问题的不同方法总是很有趣。
    【解决方案3】:

    你可以这样做:

    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(that.sendReport, ...) 指向全局范围内的 sendReport 函数,因为 javascript 是传值的。因此,将其包装在另一个函数中,然后调用 that.sendReport(); 将在正确的上下文中调用它。
    猜你喜欢
    • 2020-10-10
    • 2012-09-06
    • 2016-10-11
    • 1970-01-01
    • 1970-01-01
    • 2017-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多