The Power of Closures – Part 1
Here is an example of how functions are (usually) created in JavaScript.
function square(x) {
return x*x;
}
After the interpreter processes this code, a square object will exist in the global scope that contains our defined function. This function is invoked by putting a (param-list)after it.
square(1); // 1
square(2); // 4
square(3); // 9
function (x) {
return x*x;
};
Since there is no name associated with it, there is no way to call this function. But since all functions are simply objects, we could store our anonymous function in a regular variable called square:
var square = function (x) {
return x *x;
};
As it turns out, this is identical to the original function we created. And, in fact, the first form is actually just syntactic sugar on this form. Similar to our original function, we can invoke it by putting (param-list)after it. So we can write:
square(1); // 1
square(2); // 4
square(3); // 9
If we can invoke any function by putting (param-list)after it, then we should be able to invoke our anonymous function directly.
var foo = function (x) {
return x*x;
}(10);
When this has finished executing, foo will be set to that value 100. Why? Because after the anonymous function was created, it was immediately invoked with a parameter (10). The anonymous function was evaluated, and it returned a value of 100. This return value is what was assigned to foo. This type of construct is called a self-invoking function.
Consider this case:
var foo = function () {
return fuction (y) {
return y*y*y;
}
}();
foo(3); // What does this evaluate to?
What is the value of foo(3)?. The outer anonymous function was self-invoked, returning another anonymous ‘cubing’ function. This ‘cubing’ function was invoked with parameter (3), and the result is 27.
So the real question is why would you ever want to use such an ugly construct? I will answer that question with another question:
var foo = function () {
var counter = 0; return function () {
counter = counter + 1;
return counter;
}
}();
What happens when we call foo()?: