Closures in JS and Why It Matters
Tags: javascript, tutorial
Published: 2020-02-06 17:00:40

One of the main features when a developer writes JavaScript code is maybe the one most unknown by them. Maybe this happens just because no one writes code thinking directly or even knowing that the reason their code doesn't break is related to this feature.

_But what is that feature?_

Well... it is not a feature actually. It is a side-effect of how JavaScript is built and how it 'compile', run and executes. Let's dig in with an example.

Running the following in the browser dev tools will result in

```js
var age = 14;

function getOlder() {
  var age = 14;
  age++;
};

getOlder();

console.log(`I am ${age} years old.`); // <-- ???
```

1. It breaks (🤷)
2. Print `I am 14 years old.`
3. Print `I am 15 years old.`

The correct answer is `2`: `I am 14 years old.`! But why?

## Explaining the Execution

There is a lot of important information about AST (Abstract Syntax Tree) and how JS was conceived that will not be the case of study here but for the reader (check the References!), think like this:

When the Virtual Machine that runs inside your Browser (V8 in Chrome for example) executes the code it makes the naming resolution of each variable. This process of resolving the variables is required so while using a variable that is declared and defined it doesn't break your code. If the code tries to access some function or variable that is not properly defined yet it will output the famous:

`Uncaught ReferenceError: yourVariable is not defined`.


![Photo by Mark de Rooij on Unsplash](https://dev-to-uploads.s3.amazonaws.com/i/oqzy1lwadofqm6l85m9w.jpeg)
<figcaption>Photo by Mark de Rooij on Unsplash</figcaption>

## Resolving Variables by Hand

If the result after naming resolution is accessible, the original code will be converted to something roughly similar to:

```js
var global__age = 14;

function global__getOlder() {
  var getOlder__age = 14;
  getOlder__age++;
};

global__getOlder();

console.log(`I am ${global_age} years old.`); // --> 'I am 14 years old.'
```

Now it makes sense that the output is `I am 14 years old.`, right? This prefix added is related to the **Closure** of each variable and method when the naming resolution happens. As can be observed, there are 2 **Closures** in this code:

- `global`
- `getOlder`

It can be noticed that the `getOlder` Closure is inside the `global` Closure but the variables inside the `getOlder()` original function are only accessible inside those brackets.

So, it makes much more sense saying that the `getOlder__age` variable **only exists** inside the `global__getOlder()` function. A good example to validate is trying to log the variable from inside the function, outside of it:

```js
var global__age = 14;

function global__getOlder() {
  var getOlder__age = 14;
  getOlder__age++;
};

global__getOlder();

console.log(`I am ${getOlder__age} years old.`); // --> Error!
```

The resulted output is `Uncaught ReferenceError: getOlder__age is not defined` and the reason is that there is no variable with the naming resolved to `global` Closure valid for `getOlder__age`.

## But what about the Scopes?

In the creation of a function, a Closure is created the same way as a Scope. All variables and functions inside that both are accessible to all child functions and not outside of it (except if they are exposed like it'll be discussed ahead).

**Scope** and **Closure** are almost equal but the second one has some 'super-powers': Variables and functions created inside the **Closure** and exposed will still work outside of it, even without the existence of **Scope**. This is a very tight line between those two concepts.

This is true even if those exposed items depends on other variables/functions inside the **Closure** but are not exposed.

## Closures vs. Scopes

Using almost the same example as above with little changes in order to explain differences between these two concepts, the following code is a starting point

```js
function main() {
  var age = 14;

  function getOlder() {
    age++;

    console.log(`I am ${age} years old now.`); // --> 'I am 15 years old.'
  };

  getOlder();
};

main();
```

With this example, the function `getOlder()` will be called inside the `main()` function and it'll print `I am 15 years old now.`, correct? The variable `age` is inside the `main` scope and can be accessed by `getOlder()` function.

Returning the `getOlder()` function to the outside 'world' and executing it 3 times as the following example, what will be the result?

```js
function main() {
  var age = 14;

  function getOlder() {
    age++;

    console.log(`I am ${age} years old now.`); // <-- ???
  };

  return getOlder;
};

var getOlder = main();

getOlder(); // <-- ???
getOlder(); // <-- ???
getOlder(); // <-- ???
```

1. Nothing. The code will break.
2. 3 times `I am 15 years old now.`
3. The value of the `age` variable will still increase from `15`, to `16`, and then to `17`.

The correct answer is **answer 3**.

_But why this happens?_

Every time a **Closure** is created, all the variables and functions are stored inside its _state_. Even after the end of execution of the `main()` function, the respective **Closure** _state_ is still alive storing variables and functions!

Maybe the most awesome part of it is: the `age` variable is lost inside that `main()` **Closure** and is not accessible outside of it! If the next part of the code tries accessing that `age` variable, it'll result in the already discussed `Uncaught ReferenceError: age is not defined` error, as this variable doesn't exist outside the `main()` function!

![Photo by Maria Teneva on Unsplash](https://dev-to-uploads.s3.amazonaws.com/i/wanmznk1hjsdsr6pckj0.jpeg)
<figcaption>Photo by Maria Teneva on Unsplash</figcaption>


## Wrap up

Some awesome differences between **Closure** and **Scope** concepts were discussed:

- Closures always store _state_ about its variables and functions
- It is possible to expose some, all or none of those variables/functions by returning them at the end of the function that creates the Closure
- It is possible to even redefine some outside variables/functions inside the Closure with the same name and the Virtual Machine compiler will take care of it, avoiding errors in runtime and name collisions



Is this article useful for you? Did I miss something while explaining? Please, let me know in the comment section or send me a message!

## References

- [Article about AST and how JS works from Lachezar Nickolov
](https://blog.sessionstack.com/how-javascript-works-parsing-abstract-syntax-trees-asts-5-tips-on-how-to-minimize-parse-time-abfcf7e8a0c8)
- [MDN Article about Closures](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures)
- [GitHub Mirror repo of V8](https://github.com/v8/v8)