Introduction
In this new post I’m going to talk about “closures”. Just like [hoisting]({{ site.url }}/javascript-hoisting/), closures are a key concept to JavaScript, since they allow to create functions that bind the variables within a scope. Closures are usually used to build callback functions.
A good definition is available on the Mozilla Developers Network website, on which this post is entirely based.
Closures are functions that refer to independent (free) variables. In other words, the function defined in the closure ‘remembers’ the environment in which it was created.
Let’s start with a first example, to better understand what we are talking about:
function init() {
var name = "Foo";
function nowDisplay() {
alert(name);
}
nowDisplay();
}
init();
The init()
function creates a new local variable called name
and defines an internal function called nowDisplay
. This function has visibility on the variable declared and initialized in the outside function. The code is really intuitive and it is an easy example of functional scoping, in which nested functions can access to external variables.
Now we can edit the previous example in the following way:
function makeDisplay() {
var name = "Foo";
function nowDisplay() {
alert(name);
}
return nowDisplay;
}
var display = makeDisplay();
display();
This code behaves exactly like the previous one (you can try it on jsFiddle). The only difference is that the internal function is returned by the outer function, before its exectution. Intuitively one may expect that, after the execution of makeDisplay
, the inner variable name
would be erased from the stack (like C-languages) and it couldn’t be referenced by display
anymore. However running the code shows that the variable can still be used.
This feature is what really characterize closures. The display
variable holds the makeDisplay
function and every other variable visible to the function during the closure’s creation. Here’s another example:
function increment(base) {
this.base = base;
return function(value) {
return base + value;
}
}
var addTo5 = increment(5);
var addTo14 = increment(14);
alert(addTo5(5)); // output: 10
alert(addTo14(3)); // output: 17
The increment
function in this case is an example of function factory, a functions that adds a specific value to the passed argument. This particular function is used to build two new functions (addTo5
and addTo14
) that sets, in their respective environment, the values 5 and 14 as base (first operand of the addition). addTo5
and addTo14
in this case are closures.
It’s important to remember that internal variables are passed by reference and not by copy:
function say33() {
var num = 32;
var showAlert = function() {
alert(num);
}
num++;
return showAlert();
}
var show33 = say33;
show33();