Now I Can See

The previous code snippets are somewhat academic and artificially constructed to illustrate using closure. But I promised you something more than just a cool new toy. I promised that closure was something all around you in your existing code. Let us now see that truth.

  1. function wait(message) {
  2. setTimeout( function timer(){
  3. console.log( message );
  4. }, 1000 );
  5. }
  6. wait( "Hello, closure!" );

We take an inner function (named timer) and pass it to setTimeout(..). But timer has a scope closure over the scope of wait(..), indeed keeping and using a reference to the variable message.

A thousand milliseconds after we have executed wait(..), and its inner scope should otherwise be long gone, that inner function timer still has closure over that scope.

Deep down in the guts of the Engine, the built-in utility setTimeout(..) has reference to some parameter, probably called fn or func or something like that. Engine goes to invoke that function, which is invoking our inner timer function, and the lexical scope reference is still intact.

Closure.

Or, if you’re of the jQuery persuasion (or any JS framework, for that matter):

  1. function setupBot(name,selector) {
  2. $( selector ).click( function activator(){
  3. console.log( "Activating: " + name );
  4. } );
  5. }
  6. setupBot( "Closure Bot 1", "#bot_1" );
  7. setupBot( "Closure Bot 2", "#bot_2" );

I am not sure what kind of code you write, but I regularly write code which is responsible for controlling an entire global drone army of closure bots, so this is totally realistic!

(Some) joking aside, essentially whenever and wherever you treat functions (which access their own respective lexical scopes) as first-class values and pass them around, you are likely to see those functions exercising closure. Be that timers, event handlers, Ajax requests, cross-window messaging, web workers, or any of the other asynchronous (or synchronous!) tasks, when you pass in a callback function, get ready to sling some closure around!

Note: Chapter 3 introduced the IIFE pattern. While it is often said that IIFE (alone) is an example of observed closure, I would somewhat disagree, by our definition above.

  1. var a = 2;
  2. (function IIFE(){
  3. console.log( a );
  4. })();

This code “works”, but it’s not strictly an observation of closure. Why? Because the function (which we named “IIFE” here) is not executed outside its lexical scope. It’s still invoked right there in the same scope as it was declared (the enclosing/global scope that also holds a). a is found via normal lexical scope look-up, not really via closure.

While closure might technically be happening at declaration time, it is not strictly observable, and so, as they say, it’s a tree falling in the forest with no one around to hear it.

Though an IIFE is not itself an example of closure, it absolutely creates scope, and it’s one of the most common tools we use to create scope which can be closed over. So IIFEs are indeed heavily related to closure, even if not exercising closure themselves.

Put this book down right now, dear reader. I have a task for you. Go open up some of your recent JavaScript code. Look for your functions-as-values and identify where you are already using closure and maybe didn’t even know it before.

I’ll wait.

Now… you see!