Closures and their importance in Javascript

Closures and their importance in Javascript

11 October 2021

What are Closures?

Functions along with a reference to its lexical environment bundled together are known as closures.
Each and every function in javascript has access to its outer lexical environment, which means it has access to the variables and functions which are present in its parent or parent’s parent. Even when this function is executed in some other scope, not in the scope where it is physically present, it still remembers the reference of its lexical scope.

Let’s have a look at a basic example of closures.

Closures_and_their_importance_in_Javascript_01

Explanation:

  • We have a simple function as outerFunc() and inside outerFunc() we have initialized a variable and also declared another function as innerFunc() and logged the value of the variable which was initialized inside outerFunc() and we invoked both the function.
  • On executing the above code, it will first search for count inside the innerFunc() and since it won’t find a value it will then move to its parent scope, and then it will log the value of count i.e. 2.
    Closures_and_their_importance_in_Javascript_02
  • If we look at source code in the browser and on putting a debugger on the line where we are logging the value of count, We can see Closure inside the scope and it holding the value of the count and pointing to outerFunc. 
  • Since we have stopped our program inside innerFunc() which apparently holds a value of outerFunc(), JS forms a closure of the outerFunc() and keeps the values that have dependencies later i.e. count in our case.

This was a simple explanation about closures now let’s deep dive into closures.

Closures_and_their_importance_in_Javascript_03

In the above example, when outerFunc() is assigned to invokeOuter variable, It will return the innerFunc function and the execution context of the outerFunc() will be removed from the call stack. Now after a couple of lines of different code, when we invoke invokeOuter() which contains the innerFunc function, It will still be able to get the value of the count that was present on outerFunc() execution context and that execution context is not present anymore. Here closures are coming into the picture.

Explanation:

  • After returning innerFunc() the outerFunc() execution context will pop out from the call stack.
  • Whenever a function is returned it always remembers its lexical scope no matter on which execution context is running, in our case when innerFunc() was returned it remembers its lexical scope from where it came.
  • In simple words when a function is returned it not only returns those lines of code of that function but it also creates a closure with its lexical environment and returns that also.
  • Due to this, when we try to access count inside innerFunc(), it still remembers that count was assigned with a value in its parent scope and that value will be stored as closure.

As we saw through the above examples, closure is a beautiful concept of javascript. It allows us to access variables and functions later whenever we need even if that function’s execution context is not there anymore. Closures also provide data encapsulation. Closures allow callbacks, event handlers capture variables. Every Javascript developer should be well introduced with closures while functional programming.

Request a quote