Closures in JavaScript

I'm pleased to report that my decision to begin the Nashville Software School's fourth cohort has been a wise one. I'm currently four weeks in to the first half of the program, and although intense, I'm loving each and every moment. We're snowed in today, so I'm going to write a brief post in place of my usual commute time.

Up until this week, I'd understood closures only at face value... I could explain what they were, but hadn't reached the point of knowing how to really utilize them in my code. So, I want to record some notes explaining how they work, and an instance for using them effectively.

Every function, comes with an associated environment. JavaScript Allonge states this wonderfully; "Every time a function is invoked, a new environment is created. The "x" in a expression that we call a “variable” is itself an expression that is evaluated by looking up the value in the environment." When you define a function, within another function, the inner function's environment, also includes the outer function's environment.

Closures in JavaScript also mean that a functions variable values are set when the function is called... not when it's defined. With loops, this can get tricky! I've added some additional comments to the snippet below from Mark Story's blog explaining how this works. Essentially, we first define a function "clicker". Then, we call clicker within our loop to create a closure which captures each number, and ensures our event listener is set according to i's current iteration value.

var numbers = [1, 2, 3, 4, 5];
for (var i in numbers) {
  var num = numbers[i];
  var anchor = document.createElement('A');
  anchor.setAttribute('href', '#');
  anchor.appendChild(document.createTextNode(num));
  document.body.appendChild(anchor);

// attach event handler via an outer function that when called below 
// returns the inner function to be attached
// with number set to the current environment value for i

  var clicker = function(number) {
    return function (event) {
      event.preventDefault();
      console.log('My number is ' + number);
    };
  };

// functions variable values are set when the function is called, so...
// call clicker before existing the loop to pass in the current value of i

anchor.addEventListener('click', clicker(num), false);
}

Of course, there are a lot more examples of use cases for closures. In class, we've been using closures to create private properties for our classes.

Well, I've got a lot of code to write, and a lot of great material to read. I hope to post at least once monthly in order to highlight topics we're covering at NSS. Take care.

Written on February 3, 2014