Saturday, December 19, 2009

Lexical Scoping in JavaScript

Take a look at the below code:

var f = function () {
    var n = 42;
    return function () {
        return n;
    };
}();

var result = f();
alert(result);

The function f is a self-invoking function that returns a function, that returns the variable n declared in the outer function.

The alert of the above code is, as you'd expect, 42

Now let's try rewriting the above code so that instead of returning a function that is declared internally, it now returns a function that was defined outside (but that does the same thing):

var f2 = function () {
    return n;
};

var f = function () {
    var n = 42;
    return f2;
}(); 

var result = f();
alert(result);

This should return the same result, no?

Actually, we are greeted with the following error:


n is not defined


This is because of JavaScript's static scoping, also known as lexical scoping, because matching a variable to its binding only requires analysis of the program text.

This means that the scope of the variable is determined at compile-time, and from the second code snippet we can see that during compile time variable n of function f2 has window (window.n) as it's scope; and since n doesn't exist in the global scope, it is undefined.