Understanding Closures with Anonymous Functions

Closure is a pattern used in Javascript over and over again, so it's an important topic to understand thoroughly. Using anonymous functions as callbacks in higher-order functions is a breeze and is extremely useful, however if you don't know what a Javascript interpreter is doing under the hood an anonymous function accessing a closure variable can seem like black magic! Today I want to demystify the process and hopefully leave you with a solid understanding of making a closure with an anonymous function. First, a little context is necessary.

A closure is when a function is declared within another function, and the inner function has access to the variables of the outer function, even when the outer function has already returned! Check out this article for a more in-depth description. As an example, consider a scenario where we want to delay an action using setTimout. This timing function is provided by default in Javascript, and is stored in the global scope. With it we can pass a function to be invoked at a later time, and a time in milliseconds for the delay.

Below is a simple race car object, which has properties that describe its motion. The code will be in some arbitrary scope which is not the global scope. We have a goFast function that increments the acceleration up, simulating the race car driver putting the pedal to the metal. We are going to use setTimeout to simulate the delay in real life from when you press a car's gas pedal down to when the car actually starts accelerating.

var raceCar = {  
    acceleration: 0,
    velocity: 10,
    position: 4
};

var goFast = function(car) {  
    car.acceleration += 10;
};

//Will be invoked before being passed to setTimeout
setTimeout(goFast(raceCar), 500 );

//Will not have any args when invoked in setTimeout
setTimeout(goFast, 500 );

//Closure allows proper lookup of the arg we want to pass to goFast
setTimeout(function() { goFast(raceCar); }, 500 );  

Like described in the comments above each call to setTimeout is different, and the closure pattern in the last call is a good way to achieve the desired effect, which was to call the acceleration function with the race car object provided to it. In this case, the anonymous function is the closure function and goFast and raceCar are the variables being closed over. setTimeout will invoke the function in the global scope, which does not have access to the scope we are looking at currently. How does the callback invoked in the global scope still have access to the closure variables?

As a non-trivial example, here's a snippet of code I wrote recently that employs anonymous functions and closures to toggle a state on the event of a DOM element being clicked. The closure pattern lets the click listener attached to a "Canadian Dancer" instance access the clicks variable to know whether it needs to add or remove the dragging behavior.

Canadian.prototype.mouseListener = function() {

  var clicks = true;

  $('body').on('click', '.dancer.canadian', function(event) {
    if (clicks) {
      $('body').on('mousemove', function(event) {
        this.setPosition(event.pageY, event.pageX);
      }.bind(this));
      clicks = false;
    } else {
      $('body').off('mousemove');
      clicks = true;
    }

  }.bind(this));
};

We were making an interactive dance floor with several classes, and wanted our Canadian Dancers (think Terrence and Phillip) to have the ability to be clicked then dragged anywhere on the dance floor. Using this pattern, each instance of a Canadian has its own private clicks variable so each can behave independently. That's really useful!

You might have noticed that we used jQuery to select DOM elements and add event listeners to them. When the event is triggered, jQuery will know to invoke all the callbacks associated with the event, and then invoke them. However, this all happens in the jQuery runtime environment! The pattern is the same as the setTimeout example, and the question again is how does this totally separate scope know about the private clicks variable for each Canadian?

The answer lies in how the interpreter deals with anonymous functions and how execution contexts are built up in runtime.

Firstly, an execution context is a separate but related thing from scope. Any given scope in your Javascript code can have several different execution contexts. Specifically, it has one for each time the function enclosing the scope was invoked. When Javascript code is run in real time, these execution contexts are built up and exist during the entire runtime of the code. When variable lookup happens in runtime, it begins in the current context and falls through down it's containing contexts all the way down to the global scope. These are the same rules as scope, but now lookup is confined to that specific function invocation. Here is some more information on execution contexts.

Back to our race car example. We're imagining that the code is contained within some scope that's not the global scope. Now in runtime, the Javascript interpreter has built up an execution context specific to the function invocation it is currently in. When raceCar and goFast are initialized they are stored in memory inside the execution context. Let's say to make our code clearer we decided to declare our callback that we are passing to setTimeout before calling setTimeout, and we slapped a name tag on it.

var raceCar = {  
    acceleration: 0,
    velocity: 10,
    position: 4
};

var goFast = function(car) {  
    car.acceleration += 10;
};

//This new function instance is created in the current execution context
var accelerateRacecar = function() { goFast(raceCar); };

setTimeout(accelerateRacecar, 500);  

The new function, accelerateRacecar is stored within our current working execution context, and is given a name tag pointing towards its location in memory. Recall that functions are just objects with the special property of being invokable, and all objects in Javascript are pass-by-reference. This means that when setTimeout invokes the callback in the global scope, the name tag accelerateRacecar points the interpreter to its location in memory, then invokes the function. The function invocation will occur in the execution context it was initially stored in. Now when the variables inside the accelerateRacecar function are evaluated, lookup falls down one level to the correct execution context where they are defined! This is how a closure works.

The final step of mental gymnastics we must now perform is understanding that when the Javascript finds an anonymous function expression, it still retains a unique label pointing towards its location in runtime memory. Even though we didn't give it a name, the interpreter must still be able to find it when it gets invoked! You can imagine that might look something like this:

(anonymous function) = function() { goFast(raceCar); };

setTimeout((anonymous function), 500 );  

This notation is similar to what is seen in a debugger call stack trace for an anonymous function. When the interpreter visits the anonymous function expression, it must instantiate a new function object, and store it in the current execution context. Then it passes along a reference of the anonymous function to setTimeout. Even though we have no way to access this function because we didn't give it a name tag, the interpreter still passes the reference along. And that's it! The anonymous function reference works the exact same way as if there was a name tag attached to it. I hope I've now demystified the mechanics of using an anonymous function as a closure. Below is a list of relevant resources, and please feel free to give me feedback!

Understand JavaScript Closures With Ease

What is the Execution Context & Stack in JavaScript?

Javascript anonymous functions