Javascript setTimeout function with 'this'

Javascript setTimeout function with 'this'

本文关键字:this with setTimeout function Javascript      更新时间:2023-09-26

可能重复:
setTimeout和“这";在JavaScript 中

我正试图在对象上设置超时。通过一些测试代码(见下文),我想减少timerPos,直到它达到0。当我使用startTimer()第一次调用timerIn()时下面的代码时,它将达到3(正如预期的那样)。当超时调用TimerIn()时,我将收到timerPos变量的"undefined"。我做错了什么?

function start(){
var alert = new Alert(3);
alert.startTimer();
}
function Alert(timer) {
    this.timerMinutes = timer;
    this.timerPos = 0;
    this.startTimer = function() {
        this.timerPos = this.timerMinutes+1;
        this.timerInc();
    };

    this.timerInc = function() { 
        if (this.timerPos > 0){     
            this.timerPos--;   
                    // first time this function gets called timerPos is 3
                    // the second time when its called by the timeout it
                    // will be 'undefined'
            setTimeout(this.timerInc,1000);
        }   
    };
}

(在超时时使用this.timerIn()而不是this.timer对我不起作用,使用引号也不起作用)

您需要将"this"变量绑定到另一个显式使用的变量,因为"this"的值会根据调用函数的人而更改!

function Alert(timer) {
  var that = this; // Store this Alert instance as "that".
  this.timerMinutes = timer;
  this.timerPos = 0;
  // ...
  this.timerInc = function() { 
    // Use the Alert instance "that", not whatever is bound to "this" at runtime.
    if (that.timerPos > 0){     
      that.timerPos--;
      setTimeout(that.timerInc, 1000);
    }
  };
}

问题是setTimeout()函数将从全局范围调用其函数参数,而不是在注册时从封闭对象的范围调用。因此,在全局范围内,"this"变量绑定到"全局"对象(可能是浏览器窗口)。

你可以这样验证:

setTimeout(function(){alert(this);}, 500); // => alerts "[object DOMWindow]"

首先,您应该使用prototype来声明类Alert的方法。改变你调用的函数的范围就可以了:

function start(){
var alert = new Alert(3);
alert.startTimer();
}
function Alert(timer) {
    this.timerMinutes = timer;
    this.timerPos = 0;
}
Alert.prototype.startTimer = function() {
        this.timerPos = this.timerMinutes+1;
        this.timerInc();
    };

Alert.prototype.timerInc = function() { 
    if (this.timerPos > 0){     
        this.timerPos--;
        console.log(this.timerPos);
        setTimeout(function(_this){_this.timerInc()},1000,this);
    }   
};

演示:http://jsfiddle.net/kmendes/HNYKa/1/