Closures and Namespaces

This reading is supplemental to Chapter 8 (through page 173), which uses Immediately Invoked Function Expressions (IIFEs) to establish namespaces. This reading also discusses closures, which are briefly described on page 133.

A closure is a special kind of function, and a namespace is a way that a programming language can support separation of code. Consequently, you'll learn more about these concepts in CS 251 (Programming Languages), but they are important, practical concepts that arise naturally in JavaScript code, so we'll learn about them now.

But, before we get to closures, let's review some ideas that you probably remember from prior CS classes, but I want to bring to the top of your mind.

Scope

In JavaScript, variables can be local or global. A global variable can be seen by any code anywhere; local variables can only be seen from a small part of the code. For example, consider the following code:

var glob = 13;

function fred(x) {
    return x+glob;
}

function george(x) {
    x = Math.random();
    glob = Math.random();
    return x+glob;
}

The global variable glob is visible to both functions. (The function names fred and george also go into the global namespace and so are visible to each other. For example, they could invoke each other.)

The local variable x is local to each function. I could simultaneously invoke fred and george with different values for x and nothing would go wrong, because they are different names and therefore different storage locations. Imagine each function is a family, and both families have a child named x (short for Xenophon and Xerxes). Different kids, different storage locations, but the identical names cause no confusion. For the functions, the x variable exists only during the function call and disappears when the function completes.

Other Scopes

There are other scopes in addition to local and global. We actually used these in the Plotting assignment without realizing it. Here's an example; see if you can figure out what it does:

function curve13(max, incr) {
    var xvals = range(max);
    var f = function (x) { return x+incr };
    var yvals = xvals.map(f);
    newPlot(xvals, yvals)
}

Focus on the f function. What is the scope of x? It's local to f, of course. What is the scope of incr? The incr variable is local to curve13 but it is non-local to f. The incr variable refers to the environment that curve13 created.

A variable that is non-local like incr means that f is a closure. We say that f is a "closure over incr".

If a closure is returned from a function, it can continue to refer to its original environment. We did this in the Plotting assignment as well: the functions returned from quadratic and cubic continued to refer to their original environments, which is how they continued to know their coefficient and roots.

What is a Closure?

Formally, a closure is a function plus an environment (you can read more about them in the Wikipedia article on Closures), so to begin getting a handle on them, we start with some more observations about functions.

Functional Programming

The following functions f1 and f2 depend only on their inputs (rather than on some global state information), which makes them easier to understand than the function g1 which depends on some global variable glob. (For example, suppose glob is a string: then the value of g1 is a string, too.)

var f1 = function (x y) { return x + y; };
var f2 = function (x) { return x + 4; };
var g1 = function (x) { return x + glob; };

When we talk about ''functional programming'' in Computer Science, we are thinking about functions like f1 and f2, where calling the functions with the same inputs always yields the same output. The same can't be said of g1. In general, when we say some code is functional, we mean that it depends only on its arguments, not on external state (like glob) or even internal state (its prior history of executions). We'll return to this later.

Function f1 is just the add function; we might call f2 the add4 function. Since functions are first-class objects in JavaScript, we can dynamically create them and return them from functions. So, the following function can create functions like add4:

var makeAdder = function (delta) {
    return function (x) { return x+delta; }
    };
var add4 = makeAdder(4);
alert(add4(3));

Now, what kind of function is add4? It's functional, in the sense that its value only depends on its arguments, not on any global state (certainly none that can change). Yet the code looks nearly the same as g1. What's the difference? The difference is that the glob that g1 refers to is global and can change dynamically, while delta is a lexical variable in the environment of the anonymous function returned by makeAdder. That function includes both the function plus that bit of environment, so it is a closure.

If you think about our earlier discussion of scopes and environments, the environment of the anonymous function returned by makeAdder includes the parameter delta and the delta continues to exist even though makeAdder has returned. It continues to exist because the anonymous function needs it. We say that the anonymous function has closed over the name delta.

An Example: A Shopping Example

Let's see closures in action in a web page. Suppose we have a page that has an item for sale, say apples, and it has an associated button that increments a counter, updates a database, updates the web page and maybe other things. So, you write some code like this:

function updateAppleDatabase(n) {
    console.log("Apple Database updated with "+n);
}

0 Apples

Here's the HTML code:


And here's the JavaScript code:


The event handler function we've written is not functional (it depends on the global variable appleClicks). Nevertheless, the code works fine.

Next, we decide to add additional buttons for bananas, coconuts, dates, eggplants, figs and the rest of the alphabet. Of course, we could copy/paste the code above for each of our grocery items, but copy/paste usually a bad idea. Duplicate code means that if we change our implementation, we have to update all the copies of the original implementation.

Event Handler Maker

But how do we write a generic event handler? We could write a function to make one. While we're at it, we'll make the updateAppleDatabase function more generic.

function groceryClickHandlerMaker(item,outputId) {
    var counter = 0;
    return function () {
         counter++;
         updateDatabase(item,counter);
         $(outputId).html(counter);
         };
}

How do we use the groceryClickHandlerMaker? Here are two examples, where we invoke the groceryClickHandlerMaker function to return a closure that we then attach as the click handler.

0 Bananas

0 Coconuts

Here's the JavaScript code:


Closure Variables

Let's look again at the groceryClickHandlerMaker:

function groceryClickHandlerMaker(item,outputId) {
    var counter = 0;
    return function () {
         counter++;
         updateDatabase(item,counter);
         $(outputId).html(counter);
         };
}

What variables does it close over? It closes over every variable that is not defined within the function. Here there are three:

  1. item
  2. outputId
  3. counter

The first two closure variables won't change ever, so the JavaScript engine can really just substitute the values as static constants. The counter, however, is interesting, because it's updated by the closure invocation, which means that the closure isn't functional in the technical sense of its behavior only depending on its arguments. Its behavior depends on how many times its been executed before.

Namespaces

Some very cool properties of the counter variable used by the click handlers above are that

  1. there are several of these variables, one for each handler
  2. they all have the same name, but
  3. they are all completely unrelated, and
  4. they are all completely private

Think about that last property for a moment: each click handler has its own private state variable. (This should remind you of instance variables in object-oriented programming.) Indeed, each closure has its own private namespace.

What's a namespace? In general, a namespace is a mapping from names (symbols) to values. You can think of the names as variables, as we will here, since in JavaScript we can assign a function to a variable. Namespaces are important in programming because they help us avoid name collisions. For example, many years ago, I was doing some graphics programming and I has some variables that stored the hex codes for various colors:

var red = 0xff0000;
var white = 0xffffff;
var tan = 0xd2b48c;
var teal = 0x00ffff;
...

I also needed to compute the tangent of an angle:

var tan_theta = tan(theta);

I'm embarrassed to admit that it took me hours to understand why the tangent function wasn't working. The problem was a name collision: I had only one namespace, so tan could only have one value.

In JavaScript, the tan function is safely in the Math object and so we say Math.tan to use it. The Math object gives us a kind of namespace. We could create one for Colors very easily in JavaScript using objects:

var Colors = {};
Colors.red = 0xff0000;
Colors.white = 0xffffff;
Colors.tan = 0xd2b48c;
Colors.teal = 0x00ffff;

We can put functions in the object as well, like the tan function is in Math. Suppose we had a function lighten and we didn't want to clutter up the global namespace with it. We could put it in Colors:

Colors.lighten = function (color) { ... };

This technique is very common in JavaScript programming. Another, even more common, is to use functions.

Functions as Namespaces

Let's take a very abstract example so that the details of the code don't confuse the issue. Suppose we want to have a bunch of global variables and functions with short, succinct names for brevity. The functions might be mutually recursive, might refer to the globals, and so forth. After all those definitions, the thing we actually want to do is compute f(1) and insert the result into page . Our code might look like this:


var a = 123;

var b = 456;

var f = function (n) { ... g(a*n); ... };

var g = function (x,y) { ... f(b*x)+f(b*y)...; }

$("#ans").html(f(1));

This code would work, but it would not be good software engineering, because of the potential for namespace conflicts. So, we can just make all these variables be local variables of a new, anonymous function that we will immediately execute.

(function () {

     // code from above

})();

Notice that the function expression is wrapped in parentheses: that's necessary so that it won't be treated as just a top-level function definition. The parenthesized function expression is then followed by a pair of empty parentheses which causes the function to be invoked. This is called an Immediately Invoked Function Expression or IIFE. Wikipedia has more about Immediately Invoked Function Expressions.

Using an IIFE means that no names are added to the global namespace, so the code has no footprint at all. (The footprint of code is the set of names that are added to the global JavaScript namespace.)