Tuesday, April 19, 2005

JavaScript: setInterval() problem

Have you been trying to write some class like this:
  1. function y() {  
  2.   this.x = 0;  
  3.   this.start = function () {  
  4.       this.interval = setInterval(this.run, 1000);  
  5.   };  
  6.   
  7.   this.run = function () {  
  8.       this.x++;  
  9.       debug(this.x); // or some other things you want to do  
  10.   };  
  11.   
  12.   this.stop = function () {  
  13.       clearInterval(this.interval);  
  14.   };  
  15. }  
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:
  1. function y() {  
  2.    this.x = 0;  
  3.    var self;  
  4.   
  5.    this.start = function () {  
  6.        self = this;  
  7.        this.interval = setInterval(run, 1000);  
  8.    };  
  9.   
  10.    function run() {  
  11.        self.x++;  
  12.        debug(self.x);  
  13.    }  
  14.   
  15.    this.stop = function () {  
  16.        clearInterval(this.interval);  
  17.        self = undefined;  
  18.    };  
  19. }  
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:
  1. function y() {  
  2.   this.x = 0;  
  3.   this.start = function () {  
  4.       var self = this;  
  5.       this.interval = setInterval(function(){ self.run(); }, 1000);  
  6.   };  
  7.   
  8.   this.run = function () {  
  9.       this.x++;  
  10.       debug(this.x); // or some other things you want to do  
  11.   };  
  12.   
  13.   this.stop = function () {  
  14.       clearInterval(this.interval);  
  15.   };  
  16. }  

5 comments:

Anonymous said...

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

Anonymous 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...

nomadicdog 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!