带有“this”的 JavaScript setTimeout 函数

发布于 2024-12-27 19:20:34 字数 1063 浏览 0 评论 0原文

可能的重复:
JavaScript 中的 setTimeout 和“this”

我正在尝试对对象设置超时。通过一些测试代码(见下文),我想减少timerPos直到它达到0。当我使用startTimer()第一次调用timerInc()下面的代码时,它将达到3(如预期)。当 TimerInc() 被超时调用时,我将收到 timerPos 变量的“未定义”。我做错了什么?

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.timerInc() 而不是 this.timerInc 对我不起作用,使用引号也不起作用)

Possible Duplicate:
setTimeout and “this” in JavaScript

I am trying to put a timeout on an Object. With some test code (see below) I want to decrease the timerPos until it reaches 0. When I use the code below the first time timerInc() is called by startTimer(), it will reach 3 (as expected). When TimerInc() is called by the timeout i will receive 'undefined' for the timerPos variable. What am I doing wrong?

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);
        }   
    };
}

(using this.timerInc() in the timeout instead of this.timerInc does not work for me, neither does using quotes)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

耶耶耶 2025-01-03 19:20:34

您需要将“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]"

You need to bind the "this" variable to another one that you use explicitly since the value of "this" changes based on who is calling the function!

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);
    }
  };
}

The issue is that the setTimeout() function will call its function argument from global scope, not the scope of the enclosing object at the time it is registered. So in global scope the "this" variable is bound to the "global" object (likely the browser window).

You can verify like so:

setTimeout(function(){alert(this);}, 500); // => alerts "[object DOMWindow]"
吲‖鸣 2025-01-03 19:20:34

首先,您应该使用原型来声明类 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);
    }   
};

DEMO: http://jsfiddle .net/kmendes/HNYKa/1/

First of all you should use prototype to declare the methods of your class Alert. And changing the scope of the function you're calling is gonna do the job:

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);
    }   
};

DEMO: http://jsfiddle.net/kmendes/HNYKa/1/

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文