Understanding closures
Tags: javascript, webdev
Published: 2020-01-21 23:56:17

Quickly definition to who come from google searching "What is closure"

> A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). In other words, a closure gives you access to an outer function’s scope from an inner function. In JavaScript, closures are created every time a function is created, at function creation time.

In other words, it's a function that is able to remember the environment that was created.

Also known as ***"Closed over Variable Ambiente"*** (***C.O.V.E***) and ***"Persistent Lexical Scope Referenced Data"*** (***P.L.S.R.D***).

Ok, but what that means?

When we execute a function in Javascript, that function creates a brand new one execution context to it, with a local memory, variable ambiente and a state.

What happens is that when the function execution it's concluded, all of this context is excluded, including your local memory (which owns all of arguments that we passed for this function). Except the value that it returns.

But what if we could create "functions with memories". Functions that able persist data, like if could we store a state for it. This is the one of the most powerful concepts in Javascript, closures.


### Functions with memories 🧠
This can be a little abstract in this point (how the closures can be so powerful), but keep in your mind in this point that so much concepts using closures under the hood, like memoization functions, module pattern, iterator, currying and much more.


### Applying closures concept 🔥
Pay attention in the codes below, what we'll do it's called function decorator, which make us able to "edit" our functions (this is not the moment topic, soon i'll make one article series about functional programming).

```
const multiplyBy2 = (number) => number * 2;
```

Ok, nothing new until now.
Suppose we need to make with that our multiplication function, in a certain context, can be used only one time.

Can we create a ***counter*** inside of function for in the case when ***counter > 0*** it doesn't execute? This is not possible, because every time that function ends its execution its local memory is destroyed.

So, lets create a new function.

```
const oncefy = (fn) => {
  const counter = 0;
  const myFunction = () => {
   if (counter === 0) {
     fn();
     return;
   }
   console.log("Only one time");
  }
}
```

Our function ***oncefy*** receives one function like parameter, define a counter and verify if counter is equal 0, if is equal 0 execute our argument, else our function prints in the console.

Let's apply the closure concept in our function ***multiplyBy2***, passing it like argument for our function ***oncefy***, wich is responsable to memorizer our ***counter***.

```
const multiplyBy2 = (number) => {
  console.log(number * 2);
}
const oncefy = (fn) => {
  let counter = 0;
  const myFunction = (number) => {
    if (counter === 0) {
      fn(number); 
      counter++; 
      return;
    } 
    console.log("🍃");
  }
  return myFunction;
}
const multiplyBy2Once = oncefy(multiplyBy2);
multiplyBy2Once(3);
multiplyBy2Once(3);
```

Now, the function ***multiplyBy2Once*** will be executed only one time and nevermore. We "edit" our function ***multiplyBy2***, giving to it a new behavior. 
However, we don't need to change its original code, maintaining our function reusable.


### How it works ⚙️
Let's understand step by step in the code above how closures work.

1. We stored one *const* called ***multiplyBy2*** in the global memory, and its value its one function that receives one parameter called *number* and returns *number * 2*.

2. We stored one *const* called ***oncefy*** in the global memory, and its value its one function that receives one parameter called *fn* and returns one *const* called ***myFunction***.

3. We declared one *const* called ***multiplyBy2Once***, and its value we don't know yet because now we need execute the function oncefy first to know what it returns and atribute the return as the value.

4. In the moment that ***oncefy*** its executed, the interpreter creates a new execution context for this function. 
The first thing is take all function parameters (in this case ***multiplyBy2***) and stores in the local memory of this context.
Now the local memory have one *const* called ***fn*** that have ***multiplyBy2*** function as value.
Next step it's take all declarations inside the function and stores in the local memory (in this case, one *let* ***counter*** with value 0 and one *const* ***myFunction*** with value as one function that receives one parameter called ***number***).
After all declarations, it finally returns the *const* ***myFunction***.

5. When return our value ***myFunction***, all the execution context (including the local memory) are removed, except the returned value, that now it's the value of the *const* ***multiplyBy2Once***.

6. On the next line of our code we execute the function ***multiplyBy2Once*** which, in the realite it's the function ***myFunction*** returned by ***oncefy***

7. A new execution context is created for our function and again the first thing is take all function parameters of this function and stores in the local memory.

8. Now our local memory have one label called ***number*** and have the value the *argument* 0

It's in this moment that things become interesting.
In the next line of the execution, we have the condicional ***if (counter === 0)***
So the interpreter goes to the function's local memory searching for the counter variable, but this variable doesn't exist in this execution context.

It's now that closures make the magic.
When a function is defined, it gets a bond to the surrounding local memory
(“variable environment”) in which it has been defined.
So, because the function ***myFunction*** was defined inside of function ***oncefy***, the function ***myFunction*** "stores" all local memory of the context where that it's defined, including the *const* ***counter***.

When the interpreter doesn't find ***counter*** in the actual execution context scope, it goes up to the "backpack" that ***myFunction*** carries with itself (***aka closure***).

By keeping that memory, this context don't be erased, always remembering its last execution

### Conclusion 💡
Closure it's a very important concept in programming and can be used for much things.

Understand how it works may not be one easy task (and hard to explain too).

However, it's important understand closures to understand more complex concepts and develop powerful solutions.

See you soon!👋

If you lost:
[Understanding classes and prototypes](https://vequiato.dev/blog/understanding-classes-and-prototypes-5hhf/245484)
[Understanding Higher Order Function](https://vequiato.dev/blog/understanding-higher-order-function-1dlg/250804)