Closures in Javascript

Closures in Javascript are very powerful, and without them, you wouldn’t really be able to do very much in Javascript. They can be defined as in Wikipedias post about closures:

In some languages, a closure may occur when a function is defined within another function, and the inner function refers to local variables of the outer function. At runtime, when the outer function executes, a closure is formed, consisting of the inner function’s code and references to any variables of the outer function required by the closure; such variables are called the upvalues of the closure.

That can be a bit of a dry explaination, so here’s an example.

function testClosure() {
  var foo = 'bar';
  return function() {
    alert(foo);
  }
}
var callback = testClosure();
callback();

This code will alert “bar”, even though there’s no “foo” variable in the anonymous function that testClosure returns. This is because the anonymous function we have created has access to its parent scope (that is, a closure has been created when the testClosure function executes). So when we alert the foo variable, Javascript will check for a variable called foo in the current function scope, and it won’t find it. Then it goes up to the parent scope, the scope of testClosure. It finds a variable called foo there, so that’s the variable that will be used. And you’ve probably seen this, perhaps without realizing that it’s a closure. Here’s some more explainatory code:

function testClosure() {
  var foo = 'bar';
  var fn = function() {
    var foo = 'baz';
    alert(foo);
  };
  alert(foo);
  return fn;
}
var callback = testClosure();
callback();

Instead of just alerting “bar”, this will alert “baz” as well as “bar”, since there’s a variable “foo” in the inner function, and the testClosure also alerts the foo variable. So here’s a gotcha for you:

function initEvents() {
  for(var i = 1; i <= 5; i++) {
    var element = document.getElementById('element'+ i);
    element.onclick = function() {
      alert(i);
    }
  }
}

One might hope that this code will result in alerting “3″ when you click on the element with the id “element3″, but it doesn’t. It alerts “6″ for all elements. And that’s because the value i is set to 6 in the last cycle of the loop. So by the time the element is clicked, the variable i will have the value of 6. The further prove the point, look at this code.

function initEvents() {
  for(var i = 1; i <= 5; i++) {
    var element = document.getElementById('element'+ i);
    element.onclick = function() {
      alert(i);
    }
  }
  i = 'foo';
}

Now all element clicks will alert “foo”. So how would we solve this, because we need the current value of i in the click event. There are of course more than one way to solve this, but in the context of closures, this is how we can solve it.

function initEvents() {
  for(var i = 1; i <= 5; i++) {
    bindEvent(i);
  }
}
function bindEvent(i) {
  var element = document.getElementById('element'+ i);
  element.onclick = function() {
    alert(i);
  }
}

Now that we’ve moved the event binding code to another function, we’re no longer bound by the latest value of i in initEvents. The value of i is passed to the bindEvent function. We’re still creating closures though. Everytime bindEvent is called, a closure is created between bindEvent and the onclick handler function. But since bindEvent is called five times, five closures are created, and every closure has a different value for i. This was not the case in the first example, because there was only one function call, thus only one closure was created, and there was only one value for i.

Now, closures aren’t just between a function and it’s direct parent scope only. The closure recurses up the tree, like in this code.

function topLevel() {
  var root = 'root';
  function level1() {
    function level2() {
      function level3() {
        alert(root);
      }
      level3();
    }
    level2();
  }
  level1();
}
topLevel();

When the level3 function tries to access the foo variable, Javascript looks for it in level2′s scope, then in level1, and then it finally finds it in topLevel.

A word of caution though. Since closures lets different functions share variables, you can accidentally override a variable in a function, and that will affect other functions that also has a reference to that variable. Something like:

window.onload = function() {
  var foo = 'bar';
  for(var i = 1; i <= 5; i++) {
    var element = document.getElementById('element'+ i);
    element.onclick = function() {
      foo += ' clicked! ';
      alert(foo);
    }
  }
}

For everytime you click one of those elements, the foo variable is changed, even if you click on different elements.

Using closures in OO Javascript

When you’re writing OO in Javascript, you really, really need closures. For these examples, I’m using John Resigs
Simple Javascript Inheritance.

So you have a User class, perhaps, like this.

var User = Class.extend({
  name: 'Andy',
  init: function() {
    var context = this;
    document.getElementById('show_name').onclick = function() {
      alert(context.getName());
    }
  },
  getName: function() {
    return this.name;
  }
});

Since “this” will have special meaning inside the onclick handler function, we define a “context” variable that holds the reference to the User object, and that will be available in the onclick handler thanks to the closure that is created. Some prefer to name that variable “self”, but I prefer “context”, since that’s really what it is, the handlers context.

So this enables you to access the User object inside the handler function without having to set the User object as a property on the DOM element, like this.

var User = Class.extend({
  name: 'Andy',
  init: function() {
    var element = document.getElementById('show_name');
    element.User = this;
    element.onclick = function() {
      alert(this.User.getName());
    }
  },
  getName: function() {
    return this.name;
  }
});

About this entry