setTimeout() inside JavaScript Class using “this”

2020-01-24 20:59发布

I am trying to use setTimeout() inside a class function in JavaScript. The setTimeout() is supposed to trigger another method in the same Class, so the function I am passing it is written as window.setTimeout("this.anotherMethod", 4000). That bring the problem: this references the calling Object, in the case of setTimeout() it is window. How can I use enclosures to return a reference to the Class Object itself?

myObject = function(){

this.move = function(){
    alert(this + " is running");
}
this.turn = function(){
    alert(this + " is turning");
}
this.wait = function(){
    window.setTimeout("this.run" ,(1000 * randomNumber(1,5)));
}

this.run = function(){
    switch(randomNumber(0,2)){
        case 0:
            this.move();
        break;
        case 1:
            this.turn();
        break;
        case 2:
            this.wait();
    }
}

}

13条回答
我只想做你的唯一
2楼-- · 2020-01-24 21:38

At the top of your main myObject make a new reference to the current value of this:

var self = this;

and then create a closure for your timer callback that uses that new reference instead of the global object that setTimeout will use as the default context in callbacks:

setTimeout(function() {
    self.run();
}, 4000);
查看更多
叛逆
3楼-- · 2020-01-24 21:38

You can use this code instead, which works in all modern browsers -

setTimeout(function(thisObj) {thisObj.run();},1000,this);

Ref: http://klevo.sk/javascript/javascripts-settimeout-and-how-to-use-it-with-your-methods/

查看更多
虎瘦雄心在
4楼-- · 2020-01-24 21:43

It is not recommended to use setTimeout or setInterval using strings

setTimeout("myFunction()", 5000);

//this is the same as 

setTimeout(function(){ eval("myFunction()"); }, 5000)); //<-- eval == BAD
查看更多
爷、活的狠高调
5楼-- · 2020-01-24 21:45

this is sensitive to the context in which it is called. When you pass a string to setTimeout then that is evaled in a completely different context.

You need to preserve the current value of this (by copying it to a different variable) and maintain the scope (by not using (implied) eval).

this.wait = function(){
    var self = this;
    setTimeout(function () { self.run() },
              (1000 * randomNumber(1,5))
              );
}
查看更多
淡お忘
6楼-- · 2020-01-24 21:47

You can do this:

 var that = this;
 setTimeout(function () {
     that.doStuff();
 }, 4000);

You can also bind for more succinct code (as originally pointed out by @Raynos):

setTimeout(this.doStuff.bind(this), 4000);

bind is a standard library function for exactly this coding pattern (ie capturing this lexically).

查看更多
够拽才男人
7楼-- · 2020-01-24 21:47
this.wait = function(){
    var self = this;
    window.setTimeout(function() { self.run() } ,(1000 * randomNumber(1,5)));
}

So you store the reference to the object you're calling .run on in a local variable ('self').

查看更多
登录 后发表回答