The
first part of this article series ended with the question, “What happens when we call
foo()
,” in this code sample?
var foo = function () { // start of outer function
var counter = 0; return function () { // start of inner function
counter = counter + 1;
return counter; // end of inner function
}
}(); // end of outer function
The outer function is self-invoked immediately after creation (by the ()
on the last line). After invocation, the outer function returns the inner anonymous function. However, the inner function references a variable, counter
, that was defined in the outer function. What happens when the inner function is invoked?
If you were to think of this as C++ or Java code there would be a problem. In C++ or Java,
counter
would be a local variable to the outer function block. Once the outer function finished executing,
counter
would be removed from the stack (C/C++), or garbage collected (Java).
As it turns out though, in JavaScript this just works. Repeated invocations to
foo()
yield:
foo(); // returns: 1
foo(); // returns: 2
foo(); // returns: 3
This works because when an anonymous function is created, it carries the state and scope in which it was created. This is called a closure because the anonymous function “closes around” the variables it uses, holding references to them, and preventing them from being garbage collected. It does not hold copies of the values of the variables, but rather references to the actual variables that were in its scope when it was created.
Big deal, right? Well as it turns out, it is.
One criticism of JavaScript is that it doesn’t support data hiding (like private members in Java or C++). Closures can be used to implement data hiding. Consider this extended counter example:
// Our counter “class”
var counter = function () {
// create a blank object we will bestow with public methods
// this is sort of like our class “instance”
var that = {}; // our hidden private member
var private_counter_value = 0; // method to increment counter
var incr = function () {
private_counter_value++;
} // method that returns the current counter value
var getCount = function () {
return private_counter_value;
}
// bestow that with public methods
that.incr = incr;
that.getCount = getCount; // return our class “instance”
return that;
}();
The code creates a “classical” looking counter, with two public methods:
incr
, and
getCount
. Since both of these methods contain a reference to
private_counter_value
, they both create a closure around it.
private_counter_value
has been successfully hidden since the only way it can be accessed is though the "public" methods that contain references to it. No external code can modify (or even see)
private_counter_value
directly.
counter.inc()
counter.inc()
alert(counter.getCount()); // displays “2”
It may seem that this counter implementation is more verbose and confusing than the corresponding Java or C++ code. After all, both of those languages have the
private
,
protected
, and
public
keywords that do this automatically. That’s true, but only because we tried to make our
counter
look and operate like a Java or C++ class. JavaScript’s closures, prototype system (don’t confuse this with the
popular JavaScript library of the same name, they are totally different), and
duck typing enable you to create all kinds of “classes” that look and behave nothing like Java or C++ classes. JavaScript approach to classes is more general, making it more powerful for some applications.
In the final part of this series, we will look at how closures make asynchronous programming simpler. This is very useful for applications using Ajax, or
gears workers.
Aside: Closures are not unique to JavaScript. Functional languages like Lisp have supported them for decades. Most modern dynamic programming languages (Python, Ruby, Perl, etc) support closures.