JavaScript possesses many advanced features that can often make us feel confused and bewildered. Let’s demystify two of them.

Closures

We encounter closures several times while coding in JavaScript. So it’s quite necessary to understand what they actually signify. Let’s first zip through some formal definitions.

What is a closure?

A closure is a function that has access to the parent scope, even after the scope has closed.

or we can also define it as:

A closure is the combination of a function and the lexical environment within which that function was declared.

Scope

The Scope is essentially the lifespan of a variable in JavaScript. Where a variable is defined plays a large role in how long that variable is around, and which functions in your program have access to it.

So it would be safe to say that any function can be considered a closure because a function can refer to or have access to:

Any variable or parameter in its own function scope.

Any variable or parameters of its outer (parent) functions.

Any variable from the global scope.

Let’s split the definition of Closure into three points:

We can refer to variables defined outside of the current function.

Here, the printData() function refers to the type variable and the model parameter of the enclosing function setData() . So when setData() is called, printData() uses the variables and parameters of the former to print the output “Audi is a Car”.

2. Inner functions can refer to variables defined in outer functions even after the latter have returned.

The above code may seem similar to the one in the first point. But here printData() is returned inside the outer setData() function, instead of being immediately called. So, the value of currentData is the inner printData() function.

3. Inner functions store their outer function’s variables by reference, not by value.

Here, carData() returns an object containing two closures, get() and set() , and they both refer to the outer variable Car . While get() obtains the current value of Car , set() updates it. When myCar.get() is called for the second time, it prints the updated value of Car – “Mercedes” – rather than the previous value “Audi”.

Closures have another very interesting feature which is that the variables in a closure are automatically hidden. Closures store data in their enclosed variables without providing direct access to them. The only way to alter those variables is by providing access to them indirectly. For example, in the last code snippet, we saw that we can modify the variable Car only obliquely by using the get() and set() closures.

Loops!

Looping is something that tends to take a toll on everyone. When loops are not written correctly, we are left with weird outputs. Let’s look at one such example where a loop produces a confusing result.

Running the above code snippet should give us the output as:

0 1 2

But instead our output will be:

3 3 3

JavaScript is single-threaded so it keeps an event queue where it queues up things to do. The closure created in each loop iteration is queued to run as soon as the rest of the current execution context finishes and CPU time is returned to the event loop. setTimeout here serves to simply defer the execution of each closure until after the loop finishes running. By that point, the final value of i is ‘3’.

We can use closures to overcome this problem. In the following code snippet, we make use of a closure by defining nested functions.

The above code prints the desired output, which is:

0 1 2

If you already have a loop that you don’t want to convert to use an iterator function, all you have to do is wrap your closure inside another closure in which you define new variables which capture the current value of the variables that change on each iteration.

The trick to capturing the variables is to make sure your outer closure executes immediately during the current iteration of the loop. Now the above code snippet will produce the desired result!