An Easy Explanation of JavaScript Closure

An Easy Explanation of JavaScript Closure

One of the most compulsive and fascinating topics in javaScript is Closure. It is also one of the most confused and struggled principles in JavaScript. It is a very frequently asked topic in interviews because in order to understand javascript closure, one should have good knowledge about hoisting, scope, and lexical scoping.

So lets us first understand about hoisting and scope, how does closure works and why does it matter ? !!

What is Scope?

Scope in layman’s terms is said to be a space where you can access your variable. There are two types of scope:-

  • Global Scope
  • Local Scope

Global Scope

If a variable initialized outside the function or curly brackets can be accessed at any part of code is said to have a global scope. Global scope variables can be accessed anywhere inside the function or curly brackets too.

javaScript scope

So the output would be,

Inside the curly bracket Devcript
In global scope Devcript
Inside the function Devcript

Local Scope

A variable declared inside the function or inside the curly bracket is said to have Local scope and it can only be accessed inside that particular space where it was initialized but with a small difference due to var variable.

Function Scope

Variable declared inside the function is said to have function scope, In this scope exception posed by var variable doesn’t reflect and variable declared inside the function scope can only be strictly accessed inside the function.

function scope

The output would be,

Welcome Aaquib Ahmed to Devcript
Uncaught ReferenceError: firstName is not defined
Uncaught ReferenceError: lastName is not defined

As you can see, we won’t able to access the ‘firstName’ and ‘lastName’ outside the function scope.

Block Scope

On the other hand, block scope ‘{}’ is not as strict as function scope, any variable declared using the var keyword, can be accessed outside the block scope also.

block scope

So the output would be,

Welcome Aaquib Ahmed to Devcript
Aaquib
Uncaught ReferenceError: lastName is not defined

This arises a huge problem if the programmer is not careful with the names and thus, it causes issues during execution. That’s why Javascript introduced let and const keywords to assign variables with ES2016 update. I have written a detailed blog on the difference between these var vs let vs const. For a simple overview, you can check the figure below,

var vs let vs const

What is Lexical Scoping?

A lexical scope in JavaScript is a phenomenon in which the child function inside the parent function can access the variable declared in the parent function inside its scope. In simpler words, if I declare a function and a variable inside it, and inside the very same function, I define a new function then I could easily able to access the variable from the outer function inside the inner function, due to lexical scoping. Lets us understand it with an example,

Lexical Scoping

now guess the output,

5
Uncaught ReferenceError: y is not defined"

We got this error due to the fact is y is not defined and accessed in the outerfunction scope, due to the function scope of innerFunction. It is important to note that inner functions can easily access the global variables and the variables of its outer function but it’s not vice versa, outer function cant access the variable of its child function because all the variables declared inside the inner or child function have function scope.

Also read, Do Children Really Need to Learn to Code?

What is Hoisting?

Hoisting in JavaScript is the process of moving all the declared functions and variables to the top of their scope before code execution. It basically means during code parsing, Javascript adds all the functions and variables to its own memory.

Let us understand it with an example,

javascript code

What do you think the output would be? the answer is

Devcript
10

Easy right !!, but now let’s flip the console and check again,

JavaScript snippet

but, what will the output be?

Devcript
undefined

So now you might be wondering, how we were able to invoke the function even before initialization and how we got undefined for var variable? It’s all because of Hoisting.

Always remember, as you understand the working of JavaScript, if not then I will highly recommend you to check my article on working of JavaScript, that even before code execution start, memory is allocated for all variables and functions.

In order to understand it in a detailed manner lets us jump into the debugger to know what is cooking behind the scene, go to ‘inspect element’, then sources and add breakpoints to the first line and start the debugger,

Javascript debugger

As you can see, even before code executing start JavaScript has already assigned the memory for variable a with value ‘undefined and whereas in the function ‘status’, we don’t get undefined but a copy of the function.

Javascript debugger

And when we run this program we get ‘Devcript and 10 in the console. Now let us check with the second example,

JavaScript snippet

Again, if you check your debugger, even before the execution of code has been started, memory has been allocated to the function and the variable. and now you understand how we are getting undefined for variable a or function status, even before initialization, the actual answer lies in the global execution process.

It is also crucial to understand the difference between ‘undefined‘ and ‘not defined’, undefined means variable’s memory has been allocated but the value has not been assigned, on the other hand, not defined means, variable’s memory has not been assigned and you are trying to access it.

Also read, How Does React Js works | Detail Explanation on Virtual DOM

What is Closure?

A closure is a combination of functions, packed together sharing the same, lexical environment. In the other words, It is a feature where an inner function has access to outer function variables. So, the closure has three main scope chains,

  • It has its own scope – variables defined inside it,
  • It has outer function scope – variables defined in the outer functions,
  • It has global scope – variables defined in the global scope

Let us understand it more with a JavaScript closure example,

javascript closure example

As you have read and understood about the lexical scope, You can easily understand that when we run code, in function b, it tries to find the value of x in its own scope and if it does not find it then moves to lexical parent, which is function a, and logs the value of x.

Value of X is: 10

And to your surprise, this what Closure is ? !!

Ok let’s now jump into the debugger and check what’s happening behind the scene, so inspect element your code, add breakpoints and run through it with each line,

closure

As you can see in the debugger, it’s stating a closure function, but what does it mean?  It states the function b forms the closure with variable x of function a.

Now let’s move to some other javascript closure example,

javascript closure example

So now guess the output of the following code,

function b(){
    console.log('Value of X is: ',x);
}
Value of X is: 10

You will be getting ‘function ‘b in return, as after calling the ‘function a’ to variable c, ‘a function’ will be removed from the stack. But if the ‘a function’ was removed from the call stack but how can we able to access the variable x? Though ‘function a’ was removed but ‘function b’ still remembered its lexical scope. So when the ‘function b’ was returned, the closure was also returned with it and it was put inside the ‘variable c’.

Let us understand it more with some corner cases,

JavaScript closure example

Now again guess the output, will it be 10 or 100,

Value of X is: 100

We will get a value of 100, understand that x in function b, does not refer to the value button the reference, ‘function b’ is not returned only but the reference of variable x is also returned. So when you run the code, it will look for the reference, the value 100 is still present in the memory due to the closure.

Hopefully, you might have understood the working of closure till here, now lets jump into one more important example,

JavaScript closure example

So now, if we have three functions, do you still think we would have closure? what will be the output?

Value of X and Y is: 10 20

Yes, it would still have closure, function b will form closure with the scope of function a and scope of function d. let us see it inside the debugger,

JavaScript closure debugger

Even if the ‘function b’ was returned to outside somewhere, but it would have retained the memory location of variable x and y due to closure.

Advantages of Closure

  • Currying
  • Functions like once, a function that can run only once during code execution
  • SetTimeouts
  • maintaining state in the async world
  • memoize
  • Iterators and many more…

Also read, JavaScript Functions | How does Function work in Js {Detail Explanation}

Final Words 

A few months back, when was interviewing for a Front-end role, the interviewer asked me about the working of closure with one tricky problem, I got completely blank at that point but somehow I was able to answer the question, which then I realized how important closure is, and it is not only important in JavaScript but any languages which heavily rely on closures (like C#, python).

I hope I was able to breakdown it in a much simpler way, please comment or hit me up on my mail or Twitter to let me know how you found this article if you like my article please share it with your friends and co-workers, and bookmark this page to get an awesome article like these, I am trying to make a blog playlist for JavaScript, so keep tune in and also you can check my previous articles on JavaScript and React too ?.


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *