May 2011 - Posts

The term closure refers to a function which references variables outside of its scope; the function is “closed over” those variables.

I’ll give an example of misusing closure in JavaScript and C#, then compare the solutions.  This example is going to attempt the trivial task of outputting the digits 0 through 9.

JavaScript
for (x = 0; x < 10; x++) {
    setTimeout(function () {
       console.log(x);
    }, 1);
}
C#
for (int x = 0; x < 10; x++) {
    setTimeout(() => 
		Console.WriteLine(x)
	, 1);
}

This assumes that a setTimeout method has been created for C#, just for the purposes of demonstrating this.  In reality, you’ll run into this when you’re wiring up events with lambdas, iterating over LINQ queries, or using methods like List<T>’s ForEach.

The problem in these two examples is that the function passed to setTimeout is closed over the variable x; that is, we’re not referencing the value of x in the function, but the variable itself (similarly to a ref parameter in a C# method).  By the time the function runs, x is 10, so the output to the console is actually 10 being output 10 times (see for yourself).

To fix this problem, we need to pass a new variable which always hold the correct value to each function.  In C# this is pretty easy, because the for block provides scope.

for (int x = 0; x < 10; x++) {
   var closedX = x;
   setTimeout(() =>
        Console.WriteLine(closedX)
    , 1);
}

However, in JavaScript, only functions provide scope.  If we tried this same technique in JavaScript, closedX would be the same variable in each run of the for loop (even though we’re using var to “declare” it).  We need a new function to provide the scope to create separate variables for each run.

for (x = 0; x < 10; x++) {
    setTimeout((function (closedX) {
       return function () {
           console.log(closedX);
        }
   }(x)), 1);
}

Here, we create a function which has one parameter, closedX, then immediately call it, passing in x.  The parameter is a new variable for each run of the for loop because the function give it a scope, so it gives us the desired outcome.

Feel free to leave any questions in the comments, play with the example above on jsFiddle, and enjoy JavaScript to its fullest.

I gave my JavaScript language talk at the St. Louis .NET/DotNetNuke User Group last night.  I’ve posted the presentation (with some updated, clarified example code) up on slideshare.

JavaScript: The Language presentation on SlideShareJavaScript: The Language

I woke up this morning thinking through all of the things that I could have explained better and how to more succinctly get the important points across.  So, I’m now declaring (so that you, my loyal readership, can hold me to it) that I’m going to do a series on this blog focusing on illuminating common difficulties and misconceptions in JavaScript.  Look forward to a discussion of closure sometime this week.

More Posts