JavaScript Closures for Everyone

© 2008, Martin Rinehart


(Note: I use the popular name JavaScript to refer to the subset of ECMAScript that Crockford defines in his book, JavaScript: The Good Parts.)

Introduction

It took me a week to tease out the secrets of closures in JavaScript. I had the best books (Flanagan, Resig, Crockford) and my really smart friend Mr. Google with his dozens of helpful suggestions. Resig says, "This particular topic can be very powerful and very complex." Powerful? Yes. Complex? By the end of this short article you'll know what I learned in a week. You judge.

Inner Functions

In JavaScript you can write functions within functions (nesting to any level). Example:

    function outer() {
        // vars here
        // code here
        function inner() {
            // more vars and code
        }
    } // end of outer()
You can also achieve a nearly identical result this way:

    function outer() {
        // vars here
        // code here
        var inner = function() {
            // more vars and code
        }
    } // end of outer()
I first saw that and said, "Well, looks simple enough, but what does it do that's useful?" Closures are one answer.

What Is a Closure?

A closure is a function with associated data. Unlike a normal function which allocates its internal data when it is called and frees the data when it returns, a closure's data is allocated when it is created and is not freed until the closure is freed. Unlike most JavaScript attributes (remember: all JavaScript variables are attributes), a closure's data is available to itself and nothing else. Succinctly, a closure is a function with persistent, private local variables.

Why Do You Want Closures?

In Java you can declare data "private" and it will be private—code outside the unit in which it is declared can't read it, write it, or even find out that it's there. JavaScript has no "private" or equivalent keyword. But it has closures and the data inside the closure is invisible except to the singe public function of the closure.

How Do You Create a Closure?

Declare an outer function, including any necessary parameters and data. Declare an inner function. Have the outer function return the inner function.

    function outer([params]) {
        // vars declared here
        var closure = function([params]) { /* code here */ }

        return closure;
    }
Someplace else:

    var myClosure = outer([args]); // closure returned by outer()
You now have a closure. Your returned inner function can access any vars, parameters and other inner functions (to any depth) declared in the outer function. Sort of.

How Does It Work?

JavaScript's elegant functional programming (more Pythonic than Python's functional programming!) disguises a lot of complications, which is a Good Thing. In addition to explicitly declared parameters and variables, there are other things. You can access some of them directly, such as this and arguments. Other parts, such as the activation object and the execution context are also present, but you cannot access them directly. The important one for us is the execution context.

The execution context contains names and values of, among others, variables, parameters and inner functions. When outer() returns a function it also returns its execution context at the time of the return.

Critical Point! outer() is gone.

When outer() returns the closure, outer() is done, as is every function which returns. It dies. It has no more execution context. The closure becomes the owner of outer()'s former execution context.

Some authors said (and this was where I got confused) that the closure has access to the variables of the outer function. This is sort of true. Really it has access to the variable's names and values at the moment the closure is created.

Example

Here is a simple closure that uses its copy of the makeCompounder() method's execution context to show compound growth.

        function closureSample() {
            var makeCompounder = function( b, m ) {
                var base = b;
                var multiplier = m;

                var compoundingClosure = function() {
                    base *= 1 + multiplier;
                    return base;
                }
                return compoundingClosure;

            } // end of makeCompounder()

            var growthFunc = makeCompounder( 100, 0.13 ); // grow 100 at 13%

            for ( var i = 0; i < 8; i++ ) {
                var val = growthFunc();
                var str = ' ' + Math.round( val );
                document.write( i + ':' + str + '<br>' );
            }

        } // end of closureSample()
It's output:

0: 113
1: 128
2: 144
3: 163
4: 184
5: 208
6: 235
7: 266
Note that closureSample() has returned and its execution context is gone (except that it lives on in the closure it returned). It is not executing. (Of course, you could call it again to get another closure with base and multiplier meeting your other needs.)

Summary

Your growthFunc() will continue growing each time you call it, though you have no other access to its variables. Ask for growthFunc.base and you get undefined. You have true private variables owned by a function that is both accessor and mutator.

Java's caretakers have decided to add closures for the 2009 version. Could JavaScript have a more obvious closure syntax, perhaps using a word like "private"?