having fun with code

Setting up timers and intervals inside JS objects

It may seem trivial but it has its tricky point. Usually, in procedural Javascript (this is, non object oriented programming), timers are set up passing the callback function on a string:

  1. function hello() {
  2.   alert("hello");
  3. }
  4. // Will execute hello() after 10 seconds
  5. setTimeout('hello()', 10000);

For this code to work, hello() has to be a global function (actually a function of the window object). Otherwise, when the timer times out, it won’t find it.

When writing object oriented code, one would like to call a function inside the object itself, not a global function. We can achieve this passing an anonymous function to the setTimeout function that calls our function:

  1. var MyClass = new Class({
  2.   initialize: function() {
  3.     setTimeout(function() { this.hello(); }, 10000); // This wont work
  4.   },
  5.   hello: function() {
  6.     alert("hello");
  7.   }
  8. });

The previous code wont work, since this inside the anonymous function points to the window object and not to our instance of MyClass. We solve this using the bind function provided by Mootools:

  1. var MyClass = new Class({
  2.   initialize: function() {
  3.     setTimeout(function() { this.hello(); }.bind(this), 10000);
  4.   },
  5.   hello: function() {
  6.     alert("hello");
  7.   }
  8. });

This code will work fine, but it still has a big problem. If we wanted to access any member or function of our instance inside the hello() function, it wouldn’t work. This is because when the timer times out, the context of our instance is lost. Inside the hello() function, this will point to the window object.

  1. var MyClass = new Class({
  2.   initialize: function() {
  3.     this.text = 'hello';
  4.     setTimeout(function() { this.hello(); }.bind(this), 10000);
  5.   },
  6.   hello: function() {
  7.     alert(this.text); // This wont work
  8.   }
  9. });

There are multiple ways to solve this issue but my favorite is to use the function call() of the function object. This function let’s you pass an object while calling your function that will become this inside it.

  1. var MyClass = new Class({
  2.   initialize: function() {
  3.     this.text = 'hello';
  4.     setTimeout(function() { this.hello.call(this); }.bind(this), 10000);
  5.   },
  6.   hello: function() {
  7.     alert(this.text);
  8.   }
  9. });

Now we can use this inside the hello() function and everything will work fine, no matter how many instances of MyClass we create.

  1. var MyClass = new Class({
  2.   initialize: function(text) {
  3.     this.text = text;
  4.     setTimeout(function() { this.hello.call(this); }.bind(this), 10000);
  5.   },
  6.   hello: function() {
  7.     alert(this.text);
  8.   }
  9. });
  10. new MyClass('hello');
  11. new MyClass('hi there!');
  12. new MyClass('wassup?');

Enjoy :)

Related Posts:

2 Comments to Setting up timers and intervals inside JS objects

  1. 3n's Gravatar 3n
    April 9, 2009 at 13:55 | Permalink

    Why not just use: “setTimeout(this.hello.bind(this), 1000);” (Mootools)

Leave a Reply

You can use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Additional comments powered by BackType

About the blog

This is a blog about development, focused mainly on Javascript but also other languages like python, shell scripts and more.

About the author

Eneko Alonso is a software engineer and UI developer with more than eight years of experience in software and web development. He lives in San Luis Obispo, California and works at LEVEL Studios.

Contact Info

Contact Info

PromoteJS

JavaScript JS Documentation