Part I : Understanding Closures in JS

This is the Part I of the blog series in which I will explain Closures in Javascript using examples.

Let us say that we want a function called addByX which takes an argument and increment its value by x. So, if we have addByTwo(n), it will return n+2; Any such function can be easily defined as:

function addByTwo(n) {
   return n+2;
}

Now, what if we want another function called addByThree(n), which will return n+3 and so on. We certainly won't be writing another function like this, right?

💡 We can write a function addByX and pass two params, the first one being x and the other one being n. But that makes us pass the same first argument everytime unnecessarily

Let us take the help of closure here.

function addByX(x) {
   return function addFunc(n) {
      return n+x;
  }
}

const addByTwo = addByX(2);
console.log(addByTwo(3)); // 5
console.log(addByTwo(7)); // 9

const addByThree = addByX(3);
console.log(addByThree(3)); // 6
console.log(addByThree(7)); // 10

Done beautifully, isn't it? 💖

Now, let us understand, what is happening behind the scene:

  • A function named addByX is declared and stored in the global memory.
  • Then a constant named addByTwo is declared and at this time, the value it holds is undefined. A call to addByX is made with argument = 2 and the returned value will be stored in addByTwo.
  • A new execution context starts, as control goes inside the function addByX.
  • In the local memory, a variable x is declared and assigned the value 2.
  • The function returns another function called addFunc which will take argument when called and return something.

To give a better understanding of what exactly happened, after the execution is finished, addByTwo is something like this

addByTwo = function(n) {
   return n+x;
}

Ummm... 🤔 🧐 But, how exactly will addByTwo defined in global memory get access to x?

x was something internal to the function addByX.

Too many thoughts, assumptions, overthinking.

Well, the answer lies in a very interesting and often off-putting and misunderstood concept of Javascript - CLOSURES.

Demystifying:

  • When the function addByX is returning another function, which by the way, will need the value of x from its outer scope , it, quite brilliantly, returns the value of x with the function addFunc.
  • The value of x is stored in an object named [[Scopes]] (inside which there is Closure) and is not accessible by the function returned. This means that you cannot do something like addByTwo.[[Scopes]] . But, when needed, the function can just use it and it will get the value from the closure.

image.png

  • So, when addByTwo is called with n = 3, the function return n+x. Now it starts looking up for variables. It gets the value of n in its local memory, but for x, it finds nothing in local memory and then looks up in the backpack (Closure), finds it there and returns 3 + 2 = 5. (See the above image)

💡 You can also change the value of x and it will get changed inside the closure object.

Don't you think, that Closure kind of acts as a persistent memory for the function.

💡 Content idea for the next part of this blog series 😀

As a matter of fact, Closure is more specifically called

  • Persistent Lexical Scope Reference
  • Closed Over Variable Environment

Hope this helped consolidate your understanding of Closure.

If you really liked the blog, do give your feedback in the comments section and share it for better reach 😌

More parts to come ğŸŽŠğŸ¥³

.

.

.

Stay tuned ğŸ˜Ž

Bipin singh's photo

Great article

Vinit Raut's photo

Great article, explained closures beautifully!