A closure is the combination of a function and the lexical environment within which that function was declared.
Consider the following example:
function makeFunc() {
var name = 'Mozilla';
function displayName() {
alert(name);
}
return displayName;
}
var myFunc = makeFunc();
myFunc();
Running this code has exactly the same effect as the previous example of the init()
function above; what's different — and interesting — is that the displayName()
inner function is returned from the outer function before being executed.
At first glance, it may seem unintuitive that this code still works. In some programming languages, the local variables within a function exist only for the duration of that function's execution. Once makeFunc()
has finished executing, you might expect that the name variable would no longer be accessible. However, because the code still works as expected, this is obviously not the case in JavaScript.
The reason is that functions in JavaScript form closures. A closure is the combination of a function and the lexical environment within which that function was declared. This environment consists of any local variables that were in-scope at the time the closure was created. In this case, myFunc
is a reference to the instance of the function displayName
created when makeFunc
is run. The instance of displayName
maintains a reference to its lexical environment, within which the variable name
exists. For this reason, when myFunc
is invoked, the variable name
remains available for use and "Mozilla" is passed to alert
.
Here's a slightly more interesting example — a makeAdder
function:
function makeAdder(x) {
return function(y) {
return x + y;
};
}
var add5 = makeAdder(5);
var add10 = makeAdder(10);
console.log(add5(2)); // 7
console.log(add10(2)); // 12
In this example, we have defined a function makeAdder(x)
, which takes a single argument, x
, and returns a new function. The function it returns takes a single argument, y
, and returns the sum of x
and y
.
In essence, makeAdder
is a function factory — it creates functions which can add a specific value to their argument. In the above example we use our function factory to create two new functions — one that adds 5 to its argument, and one that adds 10.
add5
and add10
are both closures. They share the same function body definition, but store different lexical environments. In add5
's lexical environment, x
is 5, while in the lexical environment for add10
, x
is 10.