This post was originally written in January 2019
Why closures? A couple of personal notes:
In the previous 2 years, I was very busy, I have had literally 0 (zero) free time, even on weekends. Busyness is definitely a widespread disease with constant stress and long working hours. I have less and less time for myself and for my personal interests. However, in all the rush, I constantly and always have had that empty feeling, the feeling of missing the JavaScript roots, missing some crucial educational points that I always ignored or had no time for, and therefore, I did not put too much effort nor attention to learn them deeply.
I am still busy with the same tempo, but this time I decided to change my morning schedule and routine. It’s the start of the 2019 year, I decided to wake up at 5 am, yes that’s right, one hour earlier than usual, I am using that extra hour to devote one hour per day to focus on learning the roots and filling the holes. To mention that a positive side is that I do work remotely, which is why I can always focus deeply on the work I do, remote working is another subject I want to write about in the future time.
In short, I really need to find a life-work balance ¯\_(ツ)_/¯
Why is important?
A lot happened on the JavaScript scene! I think that it is very hard to become a strong developer without a core knowledge of the language.
These days, trying and working with all of the useful and modern JavaScript frameworks such as React and lately Vue, you must be interested to understand how the language works under the hood. Because if you can’t trust the code that you are writing then you do not understand it.
Please note that this is not a tutorial, it is only a confirmation of the knowledge that I gained while learning about closures, I wanted to write publicly so feel free to follow.
An important prerequisite is to be already familiar with the scope or the scope chain in JavaScript.
What is a closure?
There are a couple of explanatory definitions:
- “Returning” a function from a function, complete with variables from an external scope, is called a closure.
- Being able to reference a specific instance of local variables in an enclosing function is called a closure.
- A function that “closes over” some local variables is called a closure.
- A closure is characteristic of a function in a lexically scoped environment, which gives power to that function to continue to access variables outside of itself, or to “remembers” its scope even when that function is passed to a different location and executed (this is my favorite).
In my words, I simplify it like this, when we return a function from a function, and we retain and use the variables (and their values) that exist or showed up in the outer function, then we have a closure.
The inner function always has open access to the outer function variables because they feel “global” to her, what it does is that first always looks and searches inside its own local scope, and if it does not find any variable (of course if there are none specified) then looks one level up and if the variable is there then assigns that variable. It kind of captures both function and its variables.
Before getting to know closures, you definitely must first understand clearly what lexical scope is, it has access on 3 levels:
- Access variables inside its scope.
- Access variables to the outer function.
- Access global variables.
The inner function still has access to the variables in the outer function scope, even after the outer function has returned. So when the outer function ends and has been returned, the inner function continues to have access to the inner function variables.
In short, the inner function survives the outer function.
This behavior frees us from having to worry about the lifetime of the variables because the closure wraps up an entire environment, it binds all variables from other scopes. Variables that are bound are also said to be closed over. Probably this is where the name closure comes from (my guess).
And is important to remember that closure is not a function, but a characteristic of a function in a lexically scoped environment, which gives power to that function to continue to access variables outside of itself, even when that function is passed to a different location and executed.
Kyle Simpson says that the scope and closure system is probably the most important concept ever invented in all of computing science, presenting the closure as a foundational concept of JavaScript.
How does the closure work and usage?
From my perspective to use a closure, define a function inside another function and expose it.
for (let i = 0; i<=3; i++) {
setTimeout(function(){
console.log("I have: " + i + "apples");
}, i*2000);
}
// > I have: 1 apples
// > I have: 2 apples
// > I have: 3 apples
To expose a function, you need to return it or pass it to another function. Here is an example below that I made while learning:
If you have been writing JavaScript code for some time, you have certainly used closure many times already without even knowing.
Closure binding and simple practical example:
Closures can even modify bound variables in the background, which means even if our local scope function has completed and disappeared it will still retain the value every single time.
Let’s make an interactive example, a practical example, let’s use the above snippet and extend, let’s build a small “app” and bind some variables with closure, and let’s have some fun with apples (I love apples):
Check and play with the Codepen here: https://codepen.io/ifkas/pen/MrvGMB
Let’s quickly examine the HTML code from the app above, as you notice is a form that has an input for the type of apple, where you write your type of apple and a select where you select a pre-defined color, basically, these two values are the ones that we will bind via closure.
Now, let’s quickly do the same with the JavaScript code, so what we have here is a simple binding of a variable, first, you create the function named appleColor which returns an anonymous function, the count variable, and as well the anonymous function value is stored, and the other separate executeClosure function is where the magic happens, different location and freely exposes the value.
Closure can exist in a shared and nested scope, in a shared scope when usually two different functions are closing over the same variable and therefore they share the same variable when one of the updates the latter function follows and updates the same exact thing, example with the setTimeout callback function:
In a nested scope, you can go deep into many scopes as long as there is a need to, variables are closed over in different scopes, and the closure will preserve access to those variables as long as those functions exist. Please note that without a solid knowledge of scope and hoisting is hard to understand how closure works.
Troubleshooting when using the for loop in closures:
Please take a look at the snippet below, in the first example the problem is that the variable “i”, within the function is bound to the same variable outside the function.
One of the ways to solve this is by using IIFE (Immediately Invoked Function Expression), you immediately call the function, and you can pass the parameter in the following snippet you close over the “i” variable that is on line 4 with the parameter of the anonymous function on line 2, this way you create new “i” for every each new iteration, please take a look at the snippet below:
Otherwise, if we do not add the anonymous function and close over the variable “i”, then the console will print “I have: 4 apples” each and every time, that is why you need to pass the “i” variable to the IIFE, which creates own copy and stores it as value, basically, with the IIFE you create a new scope for the variable “i”.
ES6
If you use ES6, which you should already use and put into practice as much as possible, then we can really simplify this by removing the IIFE and replacing the var with let and that’s it, magic happens, it will automatically create a new “i” for each iteration:
Interesting fact: Let’s give honor to JavaScript because believe it or not, I found out that JavaScript is the first language that introduced closures, afterwards Python, Ruby, C#, and other languages followed and adopted the closure example.
Personal fact: Learning JavaScript in-depth and in detail is a marathon that I must run on a daily basis, it is definitely not a sprint for me, and I enjoy every step of the track, the benefits, and the real thing begins when you start implementing the knowledge in practice.
P.S. — This post was originally written in January 2019.
Happy coding!
Hey 👋, if you’re enjoying these tips, I recently launched my blog where I share even more front-end tips and tricks!
Check it out here: https://front-end.tips
Also, let’s connect via X: https://x.com/ifkas