JavaScript Closures
Tags: javascript, closure
Published: 2021-01-08 15:49:04

In today's blog post, I am going to attempt to explain a concept I have grown to love and appreciate, one that is also commonly misunderstood and somewhat complex: JavaScript Closures. 

Before we go any further, there is a term that I am going to use excessively throughout this article which is very important to understand. That term is **execution context**. 

> We can think of **execution context** as the environment the current code is being evaluated in. 

So for example **global execution context** would refer to the global environment – the default environment where your code first runs whenever you execute a program. **Local execution context** would refer to the local context of a function. Variables declared in the global execution context are referred to as **global variables** and variables declared within the local execution context of a given function are referred to as **local variables** as in their are local to the context and scope of that particular function. 

The one last term I would like to explain before we jump into things is the **Call Stack**. This is basically a mechanism JavaScript uses to keep track of where it is in the order of execution within a program. 

### What happens when we invoke a function?
It is very important to understand what is going on under the hood every time we run a function. Let's briefly go over this: 
1. A brand new execution context is created – a local execution context and inside of this context all local variables of that function will be stored. 
2. The local execution context of the function is added at the very top of the call stack.

### What happens when the function terminates?
A function is terminated when it encounters either a `return` statement or a closing bracket `}`. So what happens under the hood when a function encounters either one of these?
1. The local execution context of the function is removed from the call stack. 
2. If the function has any return values, it will return them out into the context within which it was called. If the function was called in the global context, the value will be returned out to the global context. If the function was called within the local context of another function, the value will be returned out to the local context of the function within which the function returning out the value was called. If the function does not have any return values, it returns out `undefined`
3. Lastly, the local execution context of that function is destroyed. This means that it no longer exists in memory and all the variables that were declared within that local execution context are destroyed and removed from memory as well. They are no longer available. 

### What does this look like in practice?
Let's take a look at the function below.
```
let x = 5
function squared(a) {
  let squaredValue = a * a
  return squaredValue
}
let y = squared(x)
console.log(y)
```
So this looks pretty simple, but there is quite a lot going on here. Let's go through this line by line. 

1. Line 1 – First we declare a variable `x` in the global execution context and assign it the value 5. This variable is stored in global memory. 
2. Still in the global execution context, we then declare the variable `squared` and assign to it a function definition. So what has happened here is that the code inside the function block is stored in memory inside the variable `squared`. At this point in time, the function is not invoked and the code inside the function block does not run – it is only stored in global memory. 
3. Line 7 – We then jump down to right after the function declaration and declare the variable `y` and assign to it the result of the invocation of the function `squared` with the argument `x` passed into it. Before `squared` is invoked, the variable `x` is uninitialised. 
4. The function `squared` is invoked. 
5. A brand new local execution context is created – we shall call this "squared execution context". 
6. We head back up to the function declaration and into the function block. 
**NOTE:** Javascript does not go back up to the code. The thread of execution is top down, it never goes up and in this case does not jump from line 6 back up to line 2 – it does not have to because when it saved `squared` in the beginning of the code, it saved all of the code in memory which is where it grabs the code from to start executing it.
7. We head into the function block in lines 2 and 3 – now you might be tempted to say that the first thing that happens is that we declare the variable `squaredValue` and assign to it the result of the expression `a * a` but there is a step before that. Before this, JavaScript looks for any arguments passed in. Because this function accepts arguments, and has the parameter `a`, a new variable `a` is declared in the local execution context and assigned to it is the argument that was passed in when the function was invoked which is `x`. JavaScript will look in global memory for `x` and find that the value is assigned to it is 5 and then assign the value 5 to `a`. Note that `a` is stored in the memory of the "squared execution context". 
8. The value is returned out to global context and is stored in variable `y`. 
9. The "squared execution context" is removed from the call stack and all the variables that were defined in the "squared execution context" are erased as well. 
10. Line 7 – We then log the value of `y` out onto the console. 

### JavaScript: A lexically scoped language
We're getting there. I know this might seem like a lot but all of this is crucial to understanding closures. The next concept I want to touch on is **Lexical Scope**. Well firstly, what is scope 🤔? 
> **Scope** is essentially a set of rules that define what data is available to you at any given line in the running of your code. 
JavaScript uses lexical (static) scoping. Let's take a function for example; wherever that function is saved determines what data the function will have access to whenever it runs. Let's take a quick detour and look at this quick example. 

```
let num = 3
function foo(x) {
  return x + num
}
```
Where is `foo` declared? In global context and as such has access to all the variables in the global context.

```
function foo(){
  let num2 = 10
  return num2 * num2
}

function doSomething(){
  return num2 + 10
}

console.log(foo())
console.log(doSomething())
```
What do you think will happen when we try run the last line of this code? We will get a reference error of "`num2` is not defined". We get this error because `num2` is out of scope and not within the scope of `doSomething`. JavaScript first looks in the function's local context for a variable and if it's not there, looks further up in its calling context and it if the variable is not found there still will continue further up until it reaches the global execution context. If the variable is not found in the global execution context, JavaScript will assign the value `undefined` to the variable. 

In our example above, JavaScript looks inside of the local execution context of `doSomething` for the variable `num2` which it does not find and so it jumps up to the global context and still does not find the variable there and so it assigns the value `undefined` to it. 

So **lexical scope** just means that a function has access to variables that are defined in its calling context. Where the function is defined determines what variables it has access to.

Now there are quite a number of caveats when it comes to scope which are beyond the scope of this article (do you get it? 😉😂). Maybe in future, I will post another article that deals specifically with scope in JavaScript. 

### A function returning another function? 💭 
We are almost there! This is the final piece of the puzzle before we get to the beauty that are closures. 

So, in JavaScript, it is very possible for us to return functions from other functions. Let's take a look at an example. 

```
function firstFunction(){
  function secondFunction(x) {
    return x * x
  }
  return secondFunction
}
const createdFunction = firstFunction()
const finalResult = createdFunction(10)
console.log(finalResult)
```
Let's dive deeper into what exactly is going on in the above code. 

1. In line 1 we have our first function declaration. We declare the variable `firstFunction` and we assign a function definition to it which is essentially the body of the function.
2. We head down to line 7 where we declare the variable `createdFunction` and assign to it the result of the invocation of `firstFunction`. Until `firstFunction` is invoked, `createdFunction` is uninitialised. 
3. We invoke `firstFunction` and create a brand new local execution context which we will refer to as *first local execution context*. When this invocation takes place, *first local execution context* is added to the top of the call stack.
4. We are now back at line 2, inside the *first local execution context* where we declare the variable `secondFunction` and assign to it a function definition. This variable is stored inside the memory of *first local execution context*. 
5. In line 5, we return out the value of `secondFunction` to the global execution context where it is stored inside the variable `createdFunction`.
6. The *first local execution context* is removed from the call stack and it is destroyed and so are all of the variables that were defined in and stored in the memory of the *first local execution context*. 
7. In the final line, line 8, we declare the variable `finalResult` in the global execution context and assign to it the result of the invocation of `createdFunction(10)`. 
8. We invoke `createdFunction` with the value 10 passed in as an argument. 
9. Upon invocation, a brand new local execution context is created, we will call this *second local execution context*. 
10. *Second local execution context* is added onto the top of the call stack.
11. The first thing JavaScript will do once the function is invoked, before even heading to the function body is check whether the function has parameters and whether arguments were passed in so the values of the respective arguments can be assigned to the parameters. With our example, there is a parameter: `x`. JavaScript will declare a variable `x` in the *second local execution context* and assign to it the value that was passed in as an argument which in this case is 10. So right now, in the memory of *second local execution context* is variable `x` with the value 10.
12. In line 3 of the code the result of the expression `x * x` is returned out. Where is this value returned out to? You might think that it is returned out to *first local execution context*. It might look like that because the `secondFunction` is nested inside of `firstFunction` but that is not actually the case. Remember that at this point *first local execution context* does not exist and `createdFunction` is not being called inside of `firstFunction`. **This would be a good time to remind you that a function will return a value out into its calling context**. `createdFunction` was called in global context and as such the result of the earlier expression (`x * x`) will be returned out into the global execution context and stored in the variable `finalResult`.
13. Once the value is returned out, *second local execution context* is popped off the call stack and is erased along with all of the variables that were defined inside of it. 
14. We then finally log to the console the value of `finalResult` is 100.

Now you might be wondering why I went through all of these steps in so much detail. The primary reason is to place emphasis on understanding what is going on in each line of code. The second reason is so that you have it engrained in your understanding that a **brand new** execution context is created every single time a function runs and that the newly created execution context is destroyed and erased when the function terminates along with all of the variables that were defined within that context. Lastly, I wanted to show you that functions can return functions – this is the fundamental pillar of the concept of closures.

### JavaScript Closures
You made it! You're finally here. Now that we have laid down a solid foundation we can dig into what closures are and why they are such a wonderful feature in JavaScript. 

Before we look at an example I want to quickly provide a brief explanation of what a closure is. You can almost think of it as a function's own little piece of memory. Closures are essentially a function's way of keeping memory of all the data that was inside the surrounding context within which the function was initially defined. For those looking for a technical definition: 
> A **closure** is a collection of all the variables that were in scope at the time of the function's creation. 
The closure contains all of the variables that are in scope at the time the function is created. **Think of closure as a backpack that the function carries with it wherever it goes**.

This might not make sense now so let's take a look at an example. 

```
function doSomething(){
  let num = 1
  function doubleNum(){
    num++
    console.log(num)
  }
  return doubleNum
}
const doSomethingElse = doSomething()
doSomethingElse()
doSomethingElse()
const doSomethingBetter = doSomething()
doSomethingBetter()
doSomethingBetter()
```
Let's dive into this function line by line. 

1. In line 1 we declare the variable `doSomething` and assign to it a function definition inside of the global execution context.
2. We jump down to line 9 and declare the variable `doSomethingElse` and assign to it the result of the invocation of `doSomething`. Until `doSomething` is invoked, `doSomethingElse` is uninitialised. 
3. `doSomething` is invoked and we create a brand new local execution context which we will refer to as *doSomething execution context*. 
4. *doSomething execution context* is added to the top of the call stack. 
5. We jump to line 2 inside the body of `doSomething`. 
6. We declare the variable `num` and assign to it the value 1. This variable is stored inside the memory of *doSomething execution context*. 
7. In line 3, still inside *doSomething execution context* we declare the variable `doubleNum` and assign to it a function definition. This is where it gets exciting!! This is where we see the beauty of closures. When `doubleNum` is defined, what also happens is that JavaScript creates a bind to the local variable environment through a hidden scope property on the function `doubleNum`. This means that when we return out `doubleNum`, attached to it is all of the local data. All the variables in scope at the time `doubleNum` is defined are attached to `doubleNum`. `doubleNum` has **closure** which contains inside of it all the variables that are in the context of which it is defined. So in the case of the above code, inside the closure of `doubleNum` are all of the variables inside of *doSomething execution context* which is basically just `num`. 
8. In line 7, we return out `doubleNum`. Not only do we return out the function definition, we also return out the closure – all of the variables in *doSomething execution context*. So the function definition assigned to `doubleNum` and its closure is returned out to the global context and stored in the variable `doSomethingElse`. 
9. After we return out `doubleNum`, the *doSomething execution context* is removed from the call stack and destroyed along with *all* of the variables that were defined inside of *doSomething execution context*. To further emphasise, at this point, `doubleNum` and `num` are erased as the *doSomething execution context* no longer exists. 
10. We are now at line 10 and we invoke `doSomethingElse`. 
11. A brand new execution context is created which we will call the *doSomethingElse execution context*. 
12. *doSomethingElse execution context* is added onto the call stack. 
13. We are now at line 4 inside the function body of `doubleNum`. *Remember, we are only jumping back up there so we can see what code is being executed when `doSomethingElse` is invoked. JavaScript has the function definition stored in memory and does not need to go back up in the execution thread*. In line 4, we increment `num` by 1. Before JavaScript performs the increment operation, it needs to get a value for `num`. So where will it look first? You guessed it – in the closure. Stored in the closure attached to the function definition that was assigned to `doSomethingElse`, is the variable `num` which has a value of 1. JavaScript then increments `num` by 1. This value is updated within the closure of `doSomethingElse`. This means that now `num` is 2. 
14. We then console log out the value which is 2. 
15. Back at line 11, we invoke `doSomethingElse` again and repeat steps `11` - `14`. The are two differences this time however. The first difference is that we are no longer dealing with *doSomethingElse execution context*, we are dealing with an entirely **brand new** execution context which we can refer to as *doSomethingElse2 execution context*. The second difference is that in step 13 when JavaScript looks to increment `num`, it looks inside the closure and finds that the value is 2 (as a result of the first invocation of `doSomethingElse`) and the result of the operation will be 3. 
16. With *doSomethingElse2 execution context* removed from the call stack, we are now at line 12 where we declare the variable `doSomethingBetter` and assign to it the result of the invocation of `doSomething`. 
17. We then repeat steps `3`-`9` with two key differences. The first being that again, a **brand new** execution context is created and we can call this *doSomething2 execution context*. *doSomething execution context* no longer exists. The second key difference to note is that a **brand new** closure is created and returned out to the variable `doSomethingBetter` along with the function definition. **Remember this as it will prove important in the next couple of steps – `doSomethingElse` and `doSomethingBetter` have different closures**. 
18. Now at line 13, we invoke the function `doSomethingBetter`. We repeat steps `11` - `14` with two important differences to remember. The first being that a **brand new** execution context is created which we will call *doSomethingBetter execution context*. The second important thing to remember is the value of `num`. You might be tempted to say that when JavaScript looks inside the closure for the value of `num` it will be 3 because of the previous invocations of `doSomethingElse`. This is not the case. Because `doSomethingElse` and `doSomethingBetter` have different closures, the value of `num` initially in the closure of `doSomethingBetter` is 1 as this was the value of `num` when the function definition was returned out to `doSomethingBetter`. Having said that, the value of `num` inside the closure of `doSomethingBetter` will be incremented by 1 resulting in 3. 
19. Once the operation has taken place and *doSomethingBetter execution context* is removed from the call stack and destroyed, we go to the final line, line 14 where we invoke `doSomethingBetter` a second time. 
20. A brand new execution context is created we run through steps `11` - `14` again taking into account the fact that the value of `num` inside the closure of `doSomethingBetter` is now 2 and that we are dealing with a brand new execution context and that *doSomethingBetter execution context* does not exist at this stage. 

Now this might seem like a mouthful and quite a lot to digest but there are a few things I wanted to highlight in this illustration. The first is that every time a function is returned out and stored in a variable, the function definition of that function has attached to it its own unique closure. We see this with `doSomethingElse` and `doSomethingBetter` – the variable `num` in the closures of these functions are not the same. **_Each individual function gets its own private closure with data inside from the running of the function `doSomething`, each has their own compartmentalised pocket of data_**.  The second point I wanted to drive home is that a new execution context is created **every single** time a function is invoked and that execution context is **destroyed** when the function is terminated. 

### What's the point?
At this stage you might still be wondering why and how this could be remotely useful? Well the beauty with closures is that they give our functions persistent memories and an entirely new toolkit for writing professional code. They give us the toolset to create helper functions like `once` and `memoize`. Iterators and generators use lexical scoping and closure to achieve patterns for handling data in JS. Closures help us in Asynchronous JavaScript – callbacks and promises rely on closure to persist state in an asynchronous environment. 

### Conclusion
If this all gets to complex for you, think of closure as a backpack that a given function carries around with it everywhere it goes. When it gets returned out of another function it gets returned out carrying its backpack which has inside of it all of the variables that were in the local environment where the function would have been defined. 

I would like to give credit and a shoutout to [Will Sentance](http://willsentance.com/) for explaining this concept so wonderfully in the JS Hard Parts Series. 

If you enjoyed reading this and you found it useful, please do not forget to share! 🚀 💥