Closures in JavaScript

A function along with its lexical environment is called closure.

function x() {

var a = 10;

function y() {

console.log(a);

}

y();

}

x();

Output

10

The above code is an example of a closure. The function y doesn't have the variable a in its local memory. But it can access variable a as it is present in its lexical environment.

Lexical environment is the local memory plus the lexical environment of the parent.

Local memory is the memory allocated to the variables and functions during the memory allocation phase of the execution context.

Let's look at another example.

function x() {

var a = 10;

function y() {

console.log(a);

}

return y;

}

var z = x();

z();

Output

10

JavaScript creates a new execution context whenever a function is invoked. But it also destroys the execution context after the function is executed.

In the above code, we're returning the function y to the variable z.

The variable z is not inside the function x. But the variable a is declared inside the function x.

Looking at the output, we can say that the variable z was somehow able to point to the variable a and print its value.

This is because whenever a function is returned, they retain their lexical environment. This is why we are able to access the variable a even after its execution context has been destroyed.

This is the underlying concept of closures.

Repeating once more:

Whenever a function is returned, it maintains its lexical environment. That is why we are able to access the variables declared in its lexical environment even after the execution context of the function returned has been destroyed.

So we can say that whenever a function is returned, the function plus its lexical environment is returned. Now check the first line of this article!

Thus we can safely say that whenever a function is returned and assigned to another variable, the variable stores a closure.

Let's look at another example.

function x() {

var a = 10;

function y() {

console.log(a);

}

a = 20;

return y;

}

var z = x();

z();

Output

20

In this example, we're changing the value of a before returning the function y. But as mentioned above, a function retains its lexical environment when returned and the value does change in the lexical environment in this case.

Another way of putting it would be that variable a's reference is retained and not the value that a has (just like a pointer in C/C++).

Let's dive deeper with another example.

function x() {

var a = 10;

return function y() {

var b = 20;

return function z() {

console.log(a, b);

}

}

}

const p = x()();

p();

Output

10 20

In the above example, variable p receives the function z. Hence when we call p i.e., z we see that both the variables a and b were accessible to the returned colsure.