JS setTimeout variable passing, accessing this and scope

I’m really not a JS ninja, but as the defacto language of the Web, it’s rather a unique day if i don’t read or write some javascript code and this a pattern that is well worth to know.

First example, a simple var:

function myFunction() {
    var myVar = 'test';
    setTimeout('alert(myVar)', 1000);
};

myFunction();

fails with myVar is not defined error, because setTimout works on the window object (the top level object for browsers), and there is no myVar registered as a global var (window.myVar is undefined).

You can easily work this out with a closure:

function myFunction() {
    var myVar = 'test';
    setTimeout(function() { alert(myVar) }, 1000);
};

myFunction();

simply a closure is a function declared inside other function. We have an anonymous function as the first argument of setTimeout inside myFunction, so it’s a closure. The magic of closures is that they keep state (the local variables remain accessible) after the container function has exited.

The curious case of this keyword… take the code:

function myClass () {
    this.myVar = 'test';

    this.myFunction = function() {
        setTimeout(function() {alert(this.myVar)}, 1000);
    }
}

myobj = new myClass();
myobj.myFunction();

and boum! undefined pops-up, WTF? after messing around with call, apply and even with i could only make it work assigning this to a local variable:

function myClass () {
    var self   = this;
    this.myVar = 'test';

    this.myFunction = function() {
        setTimeout(function() {alert(self.myVar)}, 1000);
    }
}

myobj = new myClass();
myobj.myFunction();

this of course is a non elegant solution, so please be my guest of posting a better solution to this issue.

Leave a Reply