Closure and Scope
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.