Tuesday, April 19, 2005

JavaScript: setInterval() problem

Have you been trying to write some class like this:
function y() {
this.x = 0;
this.start = function () {
this.interval = setInterval(this.run, 1000);
};

this.run = function () {
this.x++;
debug(this.x); // or some other things you want to do
};

this.stop = function () {
clearInterval(this.interval);
};
}
You may attempt to refer the x in the run() function. However, in JavaScript, the scope of the function becomes the window after running setInterval() (or setTimeout()).

To solve the problem, the code be written like this:
function y() {
this.x = 0;
var self;

this.start = function () {
self = this;
this.interval = setInterval(run, 1000);
};

function run() {
self.x++;
debug(self.x);
}

this.stop = function () {
clearInterval(this.interval);
self = undefined;
};
}
Since using the self variable will create a cyclic reference, it should be cleaned up properly. Otherwise, the garbage collector of the script interpreter(s) which use(s) reference count will not be able to collect the instance.

Update (2009-03-29)
Thanks to the comment by dedogs, we could actually write the code like this without the cyclic reference:
function y() {
this.x = 0;
this.start = function () {
var self = this;
this.interval = setInterval(function(){ self.run(); }, 1000);
};

this.run = function () {
this.x++;
debug(this.x); // or some other things you want to do
};

this.stop = function () {
clearInterval(this.interval);
};
}

5 comments:

Anonymous said...

THANK YOU!!
umm...could u suggest more about referrence and gabarge collector
THANK YOU!! again :)

culturekiosque said...

I'll second the "THANK YOU!!! THANK YOU!!!" This code fragment clarified a lot for me too. Now, off to do some cool JQuery tricks...

dedogs said...

Try this:

function myObject()
{
this._speed = 4000;
this._intID = 0;
}

myObject.prototype.myMethod = function() {
var instant = this;
this._intID = setInterval(function() { instant.aotherMethod(); }, this._speed);
}

myObject.prototype.aotherMethod= function() {
alert("It works");
}

kary said...

thanx a ton dude ...was stuck here ..now everythings clear.....

Christoph said...

THX a lot!