DEV Community

Yamin
Yamin

Posted on

Understanding Javascript Closures

alt text

It was really a hard concept to understand and it took me a while to comprehend what closures are. So here is my understanding of what it is with diagrams and code snippets for better visualisation

To warm up my brain, I will start with an example that doesn't involve closures and slowly change my example to involve closures at the end

function add1(){
  var x = 1;
  var f = function(y){
    return x + y;
  }
  return f(3);
}

console.log(add1());
Enter fullscreen mode Exit fullscreen mode

Here we have a simple function called add1.

  • It has a local variable x which has a value of 1
  • Another variable f which is assigned a function
  • This add1 function returns the function f

So if we run this code with it will return 4 with x = 1 and y = 3

Since we have a function declaration and that function is called in the console.log. The execution context will be as follows:

alt text

So first of all, we will have the global execution context being created. We will have the creation and execution phase. In the creation phase, we will hoist the add1 function to the top of the scope and in the execution phase we will execute the add1 function

Calling the add1 function will create add1 execution context and it will be as follows:
alt text

In this execution context, we will hoist the variables x and f in the creation phase and both are undefined in the creation phase. In the execution phase, x is assigned the value of 1 and f is assigned to the function that accepts a argument y. After assignment, it is then returning function call f(3);

alt text

This creates another execution context which is called f. In f execution context, we are not hoisting anything in the creation phase as there are no variables or function declared. In the execution phase, it is returning x+y where the value of x is retrieved from climbing the scope chain in the add1 execution context and the value of y is passed in by f(3)

So in overall x is 1 and y is 3. Returning 4. After each EC is executed, it is then popped off the stack one by one.

Let's take a look the scope chain
alt text

In the f execution context, it is returning x+y. The value of y is readily available in this context being the value of 3 but the value of x is not. So it reference the outer execution context and retrieve the value of x which is 1.


Phew.. That was alot. Hopefully you are able to grasp the execution context and scoping. So now we are ready to move on to something a bit more complicated that is related to closures. Here is the code snippet

var add = function() {
  var x = 1;
  var f = function(y) {
    return x + y;
  };
  return f;
};

var g = add();
console.log(g(3));
Enter fullscreen mode Exit fullscreen mode

This example is different from the first one where we are now returning a reference to the function and not the value. Then we are calling the function outside the scope of the function add when g(3) is called. Probably this part might be hard to grasp.

So let's go through the execution context once more and see how this adds up. First the global execution context

alt text

Followed by the add execution context

alt text

Now comes the interesting part. Once the add execution context finish executing, it will be popped off the stack

alt text

Next will be the g(3) execution context. Remember that the variable g contains the function f since that is the function that was returned in add function.

alt text

So g will return x + y.We are running g(3) so value of y will be 3.
What about the value of x?

Well if we look around, we won't be able to find x. But we remember that x was set to 1 in another execution context that was created, executed and popped off.

So in Javascript, if a function is created inside another function like g. So g will keep a reference to variables that were in the scope of the enclosing function in our case add. So meaning g still has got access to the memory of execution context of add and that includes the variable x.

alt text

Basically, the add execution context has ended, but g is still allowed to access the variables of the execution context which are still in the memory of the execution context of add.

Our function g can still climb up the scope chain and find x although it's not in the execution stack anymore.

g's execution context has closed in x which is an outer variable even if the x's execution context is gone. So our function g is a closure.

Closures like the g function internally store references to outer variables.

Let's take a look at the scope chain for this
alt text

We have the global execution context scope. We will have the add and g variable and their execution context.

After line var g = add(); finishes, the add execution context gets popped off the stack.(It's shaded for this reason)

We then create and execute the g execution context. Where it will still be able to reference the x outer variable even after the x's execution context is not on the stack anymore


Hopefully you were able to get some idea on what a closure is from this article. If you're still confused, please do read the following reference.

Here is the main reference that I used to further my understanding on this topic
Ultimate guide to execution context

Top comments (3)

Collapse
 
casperns profile image
Zelimir Stefanovic

Nice post and how I look at Closures:

When the main function is executed and some variables are assigned a return function,
even later by calling the returned function, we can access the variables that was in the call when the return function returned.

After the execution of the main function, the Scope chain is kept and referred to and is considered to be the parent of the function that is returned and which will be later called.

Collapse
 
abraham profile image
Abraham Williams

Small sidenote, if you label code snippets, they will look 🔥.

Collapse
 
yaminmhd profile image
Yamin

Oh wow! Cool! Thanks for the advise 🚀