Closures in Javascript

What's the deal with Scope, Lexical Environment, and Closures.

Closures in Javascript

Hey Folks, today in this article we are going to see what closures are. For us to understand the closures better, we will first clear some concepts on which the concept of closure builds. So in this article, we are going to discuss mainly three things

1-Scope

2-Lexical Environment

3-Closures

Alright, let's start with the learning

1-Scope

There are two perspectives through which we can understand what scope is

  • I: Consider the following piece of code
function x(){
y();
function y(){
var a= 10;
console.log(a)
}
console.log(a)
}
x();

when this code is executed, the inner function's console statement will work without any issue, but the console statement in the outer function will throw an error a is not defined

The reason for this behavior is that the variable a is defined in function y and cannot be accessed in function x, so the scope of variable a is limited to function y in our example

  • II: consider the below example
    function x(){
    var a = 10;
    }
    
    scope with respect to the above example can be defined as is variable a inside the scope of the function x?

I am sure that you have understood what scope means, so let's look at what Lexical environment is all about

2-Lexical environment

The lexical environment is nothing but a reference to local memory and lexical environment of the parent. Let's see what that means

We know that when a javascript program is executed a global execution context is created and pushed to the call stack, and while the execution is happening, if a function is encountered a new execution context is created and pushed to the call stack. Now my point to discuss this is that whenever an execution context is created, a lexical environment is created with it, which means a reference to the local memory of that execution context and lexical environment of the execution context of the parent of the current function

function x(){
var a = 10;
var b = 20;
console.log(a, b); //10 20
y();
function y(){
var c = 30;
var d = 40;
console.log(a,b,c,d); //10, 20, 30, 40
}
}
x();

in the above example, you must be thinking about how is console statement of inner function y getting access to variables in function x, well that's the beauty of the lexical environment, let me explain

when the program will be executed a global execution context will be created and pushed to the call stack. At this point, a lexical environment will also be created which will be of function x and will refer to the local memory of function x and parent lexical environment(nothing in this case as function x is itself present in the global execution state). Now inside function x, there is function y, whose execution will trigger the creation of another execution context and by default, a lexical environment will be created for function y. Now here comes the catch, the lexical environment of function y will refer to the local memory of function y and the parent lexical environment which is of function x (which holds the reference to c and d variables which are being used in function y), so this the reason function y is able to access the variables c and d which are actually not in its local memory because they are in the function's lexical environment

3- Closures

The closure is nothing but a function bundled together with its lexical environment

function x(){
 var a = 10;
 y();
 function y(){
 console.log(10)
 }
}
x();

In the above example, closure can be defined as function y bundled together with its lexical environment which will give it access to its local memory and parent lexical environment.

Now consider the following example

function x(){
var a = 10;
function y(){
console.log(a)
}
return y;
}
const f = x();
f();

Here function x is returning the function y which is being stored in f, then the f function is executed, the point of discussion here is that what will the execution of f() yield?

In normal behavior function, function y will be printing 10 upon being called, but when y is returned from x, after that x won't be in an execution context and will be released from the memory, so the variable a will no longer be in the memory, so what will the execution of function f result in?

It will print 10, confused? It's the beauty of closures, let me explain. When a function is returned from anywhere in a program, not only function but the closure of the function and its lexical scope is returned. So in our case when function y is returned a closure of function y and its lexical environment is returned, which in our case will be having the value of variable a, that's why even after execution of function x is done function f still has access to variable a and prints it's value

That's it from today's article. If you are reading this I hope that you found it worth your time and understood what closures are. Any questions, feel free to comment down below, I will surely get back to you.

Until next time, Adios