A Simple Explanation of JavaScript "Closures"
Tags: javascript, closures, lexicalenvironment, scope
Published: 2021-09-08 12:57:15

The first thing that we need to know about closures is that a closure is not a feature that we explicitly use. So we don't create closures manually, like we create a new array or a new function. So a closure simply happens automatically in certain situations, we just need to recognize those situations.

Most of the times when we run code in other languages we can not access variables outside of a function inside of that function, that is just not always possible in other languages but it is possible in javaScript and it is what we call a **closure**.
Let's Start with this simple code: 

```
let a = 1;

function print() {
  console.log(a);
}

print();
```

**It printed number 1. This is actually a closure.**

We have an inner scope of the function:
 ```
function print() {
  console.log(a);
}

``` 

And this inner scope is accessible in variable `a` which is inside the outer scope.
Now, if we take `a` and reassign it to `2` before we call `print()` function, now it prints out number `2`.

``` 
let a = 1

function print() {
  console.log(a);
}

a = 2
print();
``` 

This is because this `print()` takes whatever the most recent value of `a` is, whenever we call `print()`.

But usually closures are defined as functions inside of other functions;
``` 
function print(variable) {

  return function func(variable2) {
    console.log(variable);
    console.log(variabl2);
  }
}
``` 

we are calling function `print` which takes a variable and is returing a brand new function which is going to log out a variable from `print` as well as a variable2 from `func` function.
Now:
```
function print(variable) {

  return function func(variable2) {
    console.log(variable);
    console.log(variable2);
  }
}

let a = print(1);
```
This is doing as calling  `function print()`, so `a` is a new function. Now we call `a()` and we pass to it `2`

```
function print(variable) {

  return function func(variable2) {
    console.log(variable);
    console.log(variable2);
  }
}

let a = print(1);
a(2);
```


`a(2)` will call function `print(variable)` which is going to log out `variable` which is `1` and then is going to log out `variable2` which we  passed into `function func(variable2)` which is `a(2)` . Result is :

**1**
**2**
We have an inner scope that has access to `variable2` and also has access to `variable` from the outer scope of the `print(variable)`. Now we add `C` variable:

```
function print(variable) {
  let c= 3;
  return function func(variable2) {
    console.log(variable);
    console.log(variable2);
    console.log(c);
  }
}

let a = print(1);
a(2);
```

Result:

**1**
**2**
**3**

Even if the `c` is defined out of the function `func`, since JavaScript is able to read outside of  inner scope, we have inner scope: 
```
  return function func(variable2) {
    console.log(variable);
    console.log(variable2);
    console.log(c);
  }
}

```

that is in outer scope: 
```
function print(variable) {
  let c= 3;
  return function func(variable2) {
    console.log(variable);
    console.log(variable2);
    console.log(c);
  }
}

let a = print(1);
a(2);
```

it is able to access variable `c` as well as `variable` in print(variable) and `variabl2` which is inside the current scope.

**Another Example:**
```
let myName = "Pinkey";

function printName() {

  console.log(myName);
}

printName();
```

So this variable( myName) that is external to `printName()`, is actually available internally inside `printName()`, myName is a global variable essentially and it is available inside `printName()`.
We have the entire javaScript file that is one scope and then our function is another scope, so every scope has access to everything outside of it's scope.

Now we change the name; 

```
let myName = "Pinkey";

function printName() {

  console.log(myName);
}

let myName="pegah"
printName();
```

What is happening? it is taking the current live value of that name 

```
let myName = "Pinkey";

function printName() {

  console.log(myName);
}

let myName="pegah";
printName();

myName= "Parwane";
printName();
```



**It constantly going with whatever the most recent of that value is.**

Most people think of closures as functions inside of other functions:
```
function outerFunction(outerVariable) {

  return function innerFunction(innerVariable) {
    console.log("Outer Variable:" + outerVariable);
    console.log("Inner Variable:" + innerVariable);

  }
}

let newFunction = outerFunction("outside");
newFunction("inside");
```

Here we have a function called `outerFunction` and that function is returning another function inside of it called inner function and then we are calling down here outer function with variable outside .
Now we are getting a new function and then lastly we are calling that new function with the variable inside.

When we fist call `outerFunction` we have this `outervariable` which we set to outside and then we have `innerFunction` that gets returned and the reason we are able to access this `outervariable` inside of **innerFunction` is closures.

 `outerfunction` runs and `outervariable` is only available inside of `innerfunction`, now we remove this code:

```
newFunction("inside")
```

and nothing prints out and that's because we call 

`outerfunction` here in 

```
let newFunction=outerFunction("outside");
```

And it executes all of the code and then it's done executing
and  `outervariable` is no longer accessible for example we can not log out the `outervariable` 
 ```
 console.log(outervariable);
```

So how the `innerfunction` is able to access `outervariable` even after it is done being executed, `outervariable` has gone out of scope and that is where closures come.

`Innerfunction` is essentially saying: I am inside  `outerfunction`, it has `outervariable` so i am going to save  `outervariable` and even the function that defined this variable is no longer available, i am still going to keep track of the `outervariable`.

```
function outerFunction(outerVariable) {
  let outer2 = "hi";
  return function innerFunction(innerVariable) {
    console.log("Outer Variable:" + outerVariable);
    console.log("Inner Variable:" + innerVariable);
    console.log(outer2);

  }
}

let newFunction = outerFunction("outside");
newFunction("inside");
```


`outer2` is inside of scope but out of `innerfunction`, `outerfunction`is contained inside `innerfunction` so everything in the outer function is available inside the `innerfunction` since in javaScript anything on the inside has access to the things on the outside of it's scope essentially it has access to it's parent scope and it's parent parent scope and so on.

All we need to know about closures is that when we have a function defined inside of another function that `innerfunction` has access to the variables and the scope of the outer function even if the outer function finishes executing  and those variables are 
no longer accessible outside that function.

**Let's jump to another example:**

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f0e9ydnx51x7320eppvq.PNG)

`securebooking()` will return a new function. And what we do in this function is to update the `passengerCount` variable.And then let's just log the new `passengerCount` to the console.And now let's call the secure booking function and then store the result in a variable called `Booker`.

**So let's analyze in detail** :

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ze73l4p7vm4fotiksgyj.PNG)

Now, before we start running the secure booking function, our code is running in the global execution context. And in there, we currently only have this secure booking function. And so we can also say that the global scope now contains secure booking.Then when secure booking is actually executed, a new execution context is put on top of the execution stack. Each execution context has a variable environment, which contains all its local variables. In this case, it only contains the `passengerCount` set to zero.


![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cj1l2dn1g0ink244sxsi.PNG)

In the next line of the secure booking function, a new function is returned and it will be stored in the Booker variable. So the global context now also contains the Booker variable. And now what else happens when the secure booking function returns? It's execution context pops off the stack and disappears. So the secure booking function has done it's job and has now finished execution.


![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ly5tvp6ic1d8kbxt5bri.PNG)

**Now let's see closure in action:**


![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g41q3edd8rdqw0dy3jlr.PNG
)

let's call `booker()`  three times

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ibczejbsfqrwygahwl3h.PNG)

How can the Booker function update this `passengerCount` variable that's defined in a secure booking function that actually has already finished executing?! 

**a closure**

Now let's run the `booker()`

`Booker()` is located in the global scope. The first thing 
that's gonna happen is that a new execution context is created and put on top of the call stack and the variable environment of this context is emptied simply because there are no variables declared in this function.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q6ajjupzbwbcsaghuxya.PNG)

So how will the Booker function access the `passengerCount` variable? `The secret of the closure`

Any function always has access to the variable environment of the execution context in which the function was created. Now, in the case of `Booker`, this function was created. It was born in the execution context of secure booking, which was popped off the stack previously, So, therefore the Booker function will get access to this variable environment, which contains the `passengerCount` variable. And this is how the function will be able to read and manipulate the`passengerCount` variable. And so it's this connection that we call **closure**.