JavaScript closures

Explanation of closures via lexical scope

Understanding closures is fundamental to effective JavaScript programming. Here is my take on them.

Let us start with lexical scope first. In the following source fragment which variables can be printed using the console.log statement?

1
2
3
4
5
6
window.foo = 'foo';
var bar = 'bar';
function a() {
var one = 1;
}
console.log(...);

Answer: we can print variables window.foo and bar but cannot print variable one. Variable one is declared inside the function a and the console.log from the outer scope of the function cannot access it.

1
2
3
4
console.log(foo, bar);
// foo bar
console.log(one);
// ReferenceError: one is undefined

Call console.log cannot access variables inside a function, unless the function surrounds console.log itself. Even multiple levels of nesting are allowed

1
2
3
4
5
6
7
8
9
10
function a() {
var foo = 'foo';
function b() {
var bar = 'bar';
console.log(foo, bar);
}
b(); // 2
}
a(); // 1
// prints 'foo bar'

Notice two levels of nestings: variable bar can be reached by console.log because it belongs to the function b that surrounds the console.log statement. Variable foo can be reached by the console.log because it belongs to function a that also surrounds the console.log statement. Because this rule only looks at the way the source code is written, it is called lexical scoping. Another word for surrounds is closes, and thus the name for functions with variables reachable from inside: closures.

This principle becomes really useful when combined with another JavaScript language feature: functions can be passed as arguments to or returned from other functions. Whenever we pass a function around it can still access all variables outer to its lexical scope.

Let us take the previous example and instead of calling the inner function, return it.

1
2
3
4
5
6
7
8
9
10
11
12
function a() {
var foo = 'foo';
function b() {
var bar = 'bar';
console.log(foo, bar);
}
return b;
}
var f = a();
// pass f around, and some time later call
f();
// prints 'foo bar'

We have completely decoupled functions a and b, but they still follow lexical scope. Thus whenever we execute f(), we are really executing b(). console.log thus can access variable bar and foo. Even if no one else has a reference to the outer function a, and it is meant to be garbage collected - the collector knows that there is an inner function with access to foo and thus will not destroy it.

My favorite use of closures is to create private variables. For example, here is how we could implement a private increment-only counter.

1
2
3
4
5
6
7
8
9
var counter = (function closure() {
var n = 0;
return function inner() {
return n += 1;
};
}());
counter(); // 1
counter(); // 2
n = 0; // ReferenceError: n is undefined

We are hiding actual value n inside a closure function, and return function inner. The returned function has access to variable n due to lexical scope rule, but anyone else trying to access n will cause a ReferenceError.