【问题标题】:"this" within setTimeout self executing function is undefinedsetTimeout 自执行函数中的“this”未定义
【发布时间】:2016-02-08 15:54:38
【问题描述】:

我知道 setTimeout 中的 this 默认对应窗口,所以我一直在使用 bind 并将其传递给自执行函数,但是当 setTimeout 最终运行时(第一次运行很好,由 TeaBot._manageTeaRound 调用(),但在自我执行时并不好)这是未定义的。这是我的代码,我哪里出错了? (我删除了一些可能不相关的代码行)。谢谢你的帮助:)

TeaBot.prototype._manageTeaRound = function(originalMessage, channel){
    var self = this;
    self.teaMaker = this._getUserById(originalMessage.user);

    //now wait 3 minutes for people to send their order
    self._runTimer(self,channel);
}
TeaBot.prototype._runTimer =function(self, channel) {
    // do stuff
    console.log(self.teaMaker.name); //undefined

    var interval = self.interval,
        teaMaker = self.teaMaker;

    console.log("self.interval is " + self.interval);

    if(interval === 0){

        interval++;
        self.interval = interval;

        setTimeout(self._runTimer.bind(self, channel), 180000);

    }else{
        self.interval = 0;
    }
}

【问题讨论】:

  • 签出: setInterval / clearInterval 。也许它对你有用..

标签: javascript settimeout


【解决方案1】:

这行有问题:

setTimeout(self._runTimer.bind(self, channel), 180000);

函数TeaBot.prototype._runTimer 期望self 是第一个参数-Function.prototype.bind() 第一个参数是context(函数的this)。尝试像这样使用它:

setTimeout(self._runTimer.bind(self, self, channel), 180000);

或者将context留空,因为你根本没有使用this

setTimeout(self._runTimer.bind(undefined, self, channel), 180000);

【讨论】:

  • 非常感谢,我完全误解了第一个参数怎么是上下文,不管我需要传递给函数的参数!谢谢你,现在一切都修好了:)
【解决方案2】:

这是因为您没有_runTimer 中使用this 的值。您正在绑定一个值 this,但 _runTimer 不在乎。

_runTimer 关心它的两个参数。第一个是上下文 (self)。您的代码的结构方式,没有理由在这里使用.bind

setTimeout(function(){
    self._runTimer(self, channel);
}, 180000);

(由于您将上下文 (self) 传递给函数,因此将 _runTimer 包含在 TeaBot.prototype 中是没有意义的,因为它需要传递给它的上下文。)


作为替代方案,您可以删除self 参数,并让_runTimer 引用this。那是你需要使用.bind()的时候。

TeaBot.prototype._manageTeaRound = function(originalMessage, channel){
    this.teaMaker = this._getUserById(originalMessage.user);

    //now wait 3 minutes for people to send their order
    this._runTimer(channel);
};
TeaBot.prototype._runTimer = function(channel) {
    // do stuff
    console.log(this.teaMaker.name);

    var interval = this.interval,
        teaMaker = this.teaMaker;

    console.log("this.interval is " + this.interval);

    if(interval === 0){

        interval++;
        this.interval = interval;

        setTimeout(this._runTimer.bind(this, channel), 180000);

    } else{
        this.interval = 0;
    }
};

【讨论】:

  • 非常感谢您的帮助,我误解了 setTimeout 的第一个参数是上下文!我将它设置为未定义,现在一切正常:)
  • @mfujica:setTimeout 的第一个参数是要运行的函数。 bind 的第一个参数是上下文。 :-)
猜你喜欢
  • 1970-01-01
  • 2016-11-09
  • 1970-01-01
  • 2019-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多