Michael Martin-Smucker
Michael Martin-Smucker

Reputation: 12705

Why won't this Javascript method keep calling itself?

I have a JavaScript object with a privileged method. When this method has completed, I would like it to call itself (after a small timeout) and continue running indefinitely. Unfortunately, the method only runs twice, then it stops without any error (tested in Chrome and IE with the same results).

The code is as follows:

function Test() {
    // ... private variables that testMethod needs to access ...
    this.testMethod = function() {
        alert("Hello, from the method.");
        setTimeout(this.testMethod, 2000);
    };
}

var myTest = new Test();
myTest.testMethod();

I would expect to get the alert every two seconds, but instead it only shows the alert twice, then stops. You can see a live example here. Any idea why this would be happening?

Upvotes: 5

Views: 282

Answers (4)

benzado
benzado

Reputation: 84328

Because this outside the function is not the same as this inside the function. Try instead:

function Test() {
    // ... private variables that testMethod needs to access ...
    var me = this;
    this.testMethod = function() {
        alert("Hello, from the method.");
        setTimeout(me.testMethod, 2000);
    };
}

Upvotes: 10

Prusse
Prusse

Reputation: 4315

When you first call it with "myTest.testMethod();" the "this" keyword is bond to your "myTest" object, when the timeout fires the "window" object is bond to "this" keyword and "this.testMethod" is equivalent to "window.testMethod". Try:

function Test() {
    // ... private variables that testMethod needs to access ...
    this.testMethod = function() {
        alert("Hello, from the method.");
        setTimeout((function(self){
            return function(){self.testMethod();};
        })(this), 2000);
    };
}

var myTest = new Test();
myTest.testMethod();

Or:

function Test() {
    // ... private variables that testMethod needs to access ...
    this.testMethod = function() {
        alert("Hello, from the method.");
        var self = this;
        setTimeout(function(){self.testMethod();}, 2000);
    };
}

var myTest = new Test();
myTest.testMethod();

Upvotes: 6

Jakub Konecki
Jakub Konecki

Reputation: 46008

Try

function Test() {
    // ... private variables that testMethod needs to access ...
    this.testMethod = function() {
        alert("Hello, from the method.");
        var self = this;
        setTimeout(function() { self.testMethod(); }, 2000);
    };
}

or use setInterval.

Upvotes: 4

KOGI
KOGI

Reputation: 3989

because the this in your setTimeout is referring to the local function testMethod not Test -- essentially, you are saying setTimeout( testMethod.testMethod, 2000 )

function Test() {
    // ... private variables that testMethod needs to access ...
    var self = this;
    self.testMethod = function() {
        alert("Hello, from the method.");
        setTimeout(self.testMethod, 2000);
    };
}

var myTest = new Test();
myTest.testMethod();

Upvotes: 3

Related Questions