P K
P K

Reputation: 10210

passing this.method in setTimeout doesn't work?

I am seeing problem with passing object method as argument to setTimeout. I know inside nested function, scope of this need to be set manually but what if i directly pass function object, in my case this.counting. What is the need of declaring anonymous function as first argument, this.counting is already a function.

Mozilla also uses function(msg) {self.remind(msg);} instead of this.remind inside setTimeout first argument.

function Timer(count,start){
    this.count = count;
    this.start = start;

}

//below code works
Timer.prototype.counting = function(){
    var self = this;
    setTimeout(function(){self.counting();},this.start);
    console.log(this.count);
    this.count++;
};

//below code doesn't work
/*
Timer.prototype.counting = function(){
    setTimeout(this.counting,this.start);
    console.log(this.count);
    this.count++;
};
*/
var t1 = new Timer(0,1000);
t1.counting();
var t2 = new Timer(100,1000);
t2.counting();

Upvotes: 2

Views: 280

Answers (1)

Felix Kling
Felix Kling

Reputation: 816364

The MDN documentation of setTimeout has a whole section about it, I recommend to read it.


Inside the callback you pass to setTimeout, this will refer to window, not to the instance of your class.

If the function is called, this.count (which refers to window.count) would be undefined, since there is no global count variable. Later it would become NaN (undefined++ is NaN). The count property of your object would not change at all.

By calling the function explicitly as a method of the object (self.counting()), you ensure that this correctly refers to the instance of your class.

You could achieve the same by using .bind [MDN], instead of using another function:

setTimeout(this.counting.bind(this), this.start);

Read this MDN article to learn more about this.

Upvotes: 4

Related Questions