Closures

Mon Mar 29 2021

#javascript

Closure - in JavaScript programming you hear this term a lot. It took me a while to get my head wrapped around it, this is me trying to explain it.

We will use the following code for the explanation

1function red() { 2 let index = 0; 3 4 function green() { 5 6 const greenVariable = "Only green can see me"; // only defined for explanation 7 8 console.log(index++); 9 } 10 11 return green; 12} 13 14const yellow = red(); 15 16yellow(); 17yellow();

In perfect example we would call these functions makeFunction(), incrementCounter(), myFunction() but red(), green() and yellow() make it easier.

What is Closure ?

In simple words - when a function, on execution returns another function - we have created a closure of sorts (there is more to it)

Scopes

In order to understand Closure we need to understand scopes in JavaScript.

Scope in JavaScript lets us know if we are able to access a variable/function at that particular point in our code.

The accessibility is determined purely on the basis of where the variable/function was defined. - this is the key line.

Global Scope

By default, this is the scope we are in. Any variable/function that you define in JavaScript file that is not inside another function gets defined in Global Scope.

Who can access it?

Anyone can access these variables/functions from anywhere.

Function / Local Scope

If you define a variable/function inside another function, we are in a local scope and these variables/functions are accessible only within the execution cycle of that function.

Every function on its execution creates its own scope which is destroyed once the function has finished execution thereby making the variable/function inaccessible outside the function where they are defiend

The left part of the image below somewhat illustrates the local scope of all the functions in our code.

Who can access it?

These variables and functions are accessible only when the function where they are defined gets executed. Moroever any variable defined inside a function is accessible to all the other functions defined within it. (Not taking into account block scope etc.)

In our case, the function red defines variable index and a function green. From our above statement we understand green can access index which is defined outside its scope.

Accessibility flow

Accessibility normally flows from outer most scope to inner most scope i.e. green can access the variables defined within red but red cannot access the variable greenVariable which is defined inside of green.

And likewise we cannot access index outside of reds execution.

So what is in the scope when executing a returned function?

Closure image In our case, we return the function green and store it in yellow. Normally everytime we execute yellow we should have access only to variables/functions defined in green local scope.

Normally yes, but as green is a returned function which was defined inside red, when leaving the scope of red (at the end of execution cycle of red), green brings with it its own scope and the scope of red (where it was defined) enclosed with it. Both these scopes are now available within yellow.

Which makes it possible for yellow to access variable defined inside red even though green ( which was defined inside red ) is now being executed outside of red.

This way in which green in its execution cycle (at present which is outside of red execution cycle) is able to access red scoped variables/functions outside of red is due to what we call as Lexical Scoping in JavaScript.

Lexical Scoping can be defined as inner functions contain the scope of its parent function where it was defined even after parent function has finished its execution cycle.

The right side of the image illustrates the scope of yellow which has access to green scope and red scope enclosed in it.

Chrome Dev Tools

Running the script on Chrome with the devtools open you can see this in action. Just add a debugger statement or a break point anywhere within the green function.

Image from Chrome devtools

Flow while executing the line yellow()

JavaScript will start execution normal as any when the line yellow() is executed

  1. It will check if the variable yellow exists and it will find that variable resolves to the function green
  2. Seeing the () it will execute the function and the flow will jump into the function green
  3. After the const greenVariable declaration
  4. Try Local Scope: It moves to console.log(index++) line, it will try to find the variable index in the local scope of green. (From the chrome dev tools image you see the variable index is not present in the local scope). Failing to do so.
  5. Try Closure Scope: JavaScript will then try to find the variable in the enclosed closure scope and voila it finds the variable index there. After which it will perform the increment operation, log it out and exit the function.

In case it does not find it in the closure scope, it will move to the global scope to find the variable - if it does not even find it on the global scope, JavaScript will throw an error.

In conclusion

To sum it up and to put it metaphorically, cut me some slack for the next lines. Imagine a child is born in a parent's house, the child is raised with skills to perform specialised tasks and the parent always provides the child with the things it needs to perform these tasks when in parent's house. Now the child has to leave the parent's house and live a life of its own peforming these tasks outside the parent's house. In order to do so, while leaving the parent's house the child along with its own skills, takes with it all the necessary things the parent had initially provided it for performing the tasks - this child's name is green

And that is Closures in JavaScript. Thank you for reading.