From the words of Kyle Simpson,
Here’s a somewhat academic definition that will help you understand and spot a closure when you see one : closure is when a function is able to remember and access the variables of the outer (enclosing) function even when that function is executing outside its scope.
Closure is when a function is able to remember and access the variables of the outer (enclosing) function even when that function is executing outside its scope.
We will go back to the scope concept a little later. Just know for the moment that, depending on the position of a variable in the code, some functions will have access to it and some will not.
Now about the variables; as you already may know, a variable has two components : a name and a value. The name “variable” makes it very clear : its value can vary from one moment to the next. But sometimes, we need to keep the value as it was at a certain point in time to use it later.
setInterval() for example.
for loop example
Let’s take the example of a
for loop used to display a counter, and a
setTimout() function used to delay the execution of a function.
Looking at this code snippet, you would normally assume that it would print the numbers 0 to 9, one per second. In fact if you run this code, you get 10 printed out ten times, at a one-second interval :
Why is that happening ?
When the for loop runs and
setTimeout() gets called sometime in the future (in that case, one second later in the future), the value of the variable
i has already been incremented to the end of its range by the for loop.
This is a case where we need to store and access the value of a variable at a given time, before it is modified again. At each iteration loop, we need to “capture” the corresponding copy of
i and store it for later use. The good news is that closures are going to help us do just this : create a new closured scope at each iteration of the loop.
We will get back to this example and see how to add a closure to our loop. But before diving deeper inside the workings of closures, let’s take a brief detour and review some important concepts we need to understand well to get a full grasp of closures.
A function is also a variable
A function is a special variable : you can reassign a value to it and pass it to another function as parameters (this is useful in writing asynchronous functions which are passed as callbacks arguments).
The scope of a variable
Variables that are defined outside of a function can be accessed by that function. They can be modified outside of that function as well as by the function itself.
Variables that are defined inside of a function, as well as the arguments passed to a function, are only accessible inside the function.
(To learn more about the scope, please refer to this article)
Passing a variable to a function
When a variable is passed as an argument to a function, the value of the variable is copied inside the argument.
Taking closures by storm
Now that we finished our detour and got back, we are ready to tackle closures.
Let’s consider the following code :
Let’s dive a little deeper into this function : what’s going on here ?
We define an argument
number1 that will take the value of the variable passed to the function.
We define a function inside the function
myFunction. In this nested function, the variable
number1 is accessible because it has been defined outside of the
add function, in its parent function
We return the
add function, but we are not calling it. What does this mean ?
myFunction function returns a function : the
add function. When I print
myFunction to the console, it will display the return result of the function, which is another function (the
add function) :
Why is this important ? Because it means that I can assign a value to
number1, pass it to
myFunction, and this new value of
number1 will be stored for later use, when I will be ready to finish the job and call the add function.
And here is the awesome thing about closures : you can write functions with an intermediate state that can capture data from your application, at a very specific moment in time, and you can then use this data at another, later moment in time. Using closures is like adding a “pause” button inside your function. You can go back to it later, when there has been a change in your app (a click event from the user for example), and still be able to retrieve the value of your data before this change in the application happened.
That’s what happened in our first
for loop example : the
setTimeout function kind of arrived late for the war. The battles of the
for loop had already been fought and when the
setTimeout cavalry arrived, the
i variable had long been assigned 10, the latest value in the loop, and stayed that way until
Still not convinced or not sure when to use a closure ? Let’s take an example and explain how closures work by baking a cake.
Bake a cake with a closure
We are going to use this code that uses a function to bake cakes that have different ingredients and cooking temperatures :
ovenTemperature() function is a closure, a function inside a function, that can be called at any point in time after the
bakeCake() function has been called.
Notice how we have to take two steps to get the whole log in the console ? If your run this code and never call
carrotCake(), the console will only print :
"chocolate cake : add chocolate to the batter" "carrot cake : add carrot to the batter"
You wouldn’t get any error, but the function inside the function, the closure, would not run and the completion of baking the cake would not happen.
Notice also that I can use my
bakeCake() function to bake two very different cakes, each one being a separate instance of
bakeCake() that will remember its own
ingredient argument for later use.
Like in a real recipe, it is not enough to just add the
ingredient to the batter, you also have to set the right
temperature and baking
time to have a perfect cake. And for that, you have to call another function inside the function. As we saw in the earlier example with the
add() function, if this inner function isn’t called, the return of the outer function is simply another function, waiting for its time to be called, not a result value (yet).
bakeCake() function will not return the “ready to bake” line until you also call the
ovenTemperature() function with the two arguments : it is on hold until called properly.
You can put the chocolate in the batter, let the batter rest, and take all the time you need to check your recipe book for the right temperature and baking time. It can be an hour later, you may have to call your mother to get advice on it, and the batter with chocolate will still be here, waiting for you to give the final instructions. In other words, anytime you will call
ingredient argument, chocolate, will still be incorporated.
So how do I call this inner function when I am ready ? I’ve called my mother, checked every recipe on the internet, now let’s finish off these cakes, once and for all.
I have created two instances of the
bakeCake() function and assigned them to two different variables :
Let’s concentrate on the chocolate cake.
chocolateCake is a function, and an instance of
bakeCake, with a
chocolate argument. For
chocolateCake to return the “ready to bake” sentence, I just have to call it and pass the arguments needed by the
This means that
chocolateCake will not be fulfilled until we pass a second set of arguments for the closure to be triggered.
Here for simplicity of comprehension we first assigned
bakeCake("chocolate") to a variable (
chocolateCake), and then passed the second arguments to this variable, which is also a function. But if we already knew all the requirements of the recipe, we could have gone directly :
The ultimate take on this experiment, in the words of Douglas Crockford, is that:
“An inner function always has access to the vars and parameters of its outer function, even after the outer function has returned.”
Back to the
setTimeout() inside a
for loop example
Now with all we know from the
bakeCake() example, how can we modify the code from our first example to add a closure and make the function print the numbers from 0 to 9 instead of printing the number 10 ten times? ( remember 10 is the last known value of
i : on the last iteration of the loop, the function logged 9 in the console, then incremented this number by 1.
Let’s have a look at this function in real time :
Here is the code of our function :
For comparison purposes, we added a simple
console.log() for the
i counter at each iteration of the loop, and a
setTimeout() function that is supposed to do the same, this time at 1 second intervals.
From the image above we can easily see that that the
setTimeout() function does indeed print a result at one second intervals, but the increment of
i has already taken place and when
setTimeout() begins to run,
i has an unchanged value of 10 at each delayed iteration of the loop.
How are we getting out of this ?
Let’s apply what we have learned from using closures so far, and write a
timer()function that will act as the outer function for
setTimeout(), from which
setTimeout() will be able to access the value of
And… it works !
Here we declared a
timer() function and wrapped the
setTimeout() function inside of it. We then pass it the exact value of the counter at each iteration of the loop, hereby “closing” the value of
i inside the function at each iteration.
We could also have written :
where we declare an anonymous self-invoking function and pass it the argument
i at each iteration of the loop.
This will print the number 0 to 9 at one second intervals, thanks to the closure we created : we captured the value of
i at a given iteration of the loop, we closed it inside a function, passed the value to
setTimeout() and then called the function.
A closing word