Closures - JavaScript Concepts
Tags: beginners, javascript
Published: 2019-12-08 19:32:52

This is part of a series where I try to explain through each of [33 JS Concepts](https://github.com/leonardomso/33-js-concepts).

> Originally written on [my blog](https://blog.agney.dev/scopes-and-closures/) with interactive examples

This part corresponds to the Closures.

## Closures

JavaScript is a language that treats functions as [first class citizens](https://developer.mozilla.org/en-US/docs/Glossary/First-class_Function). This is a part and parcel of the functional languages. Functions are just objects in JavaScript and they can be assigned to variables, pass them to functions or return them from functions itself.

Let's look at these conditions one by one:

### 1. Assigned to variables

```javascript
const foo = function(a) {
  return a++;
};
```

Here function is assigned to variable `foo`, to invoke this function we have call `foo()`. `foo` here is a reference to the function and can be reassigned or assigned to some other variable.

### 2. Pass them to functions

We just saw that functions can be assigned to variables. This is essentially an easy by product of the same. You can pass these references around as you would do with any other object.

```javascript
function inc(num) {
  return num+1;
}
function counter(num, incFun) {
  return incFun(num);
}
let number = 1;
number = counter(number, inc);
console.log(number);
// What happens on decrement action?
```

Here, you can see that `inc` is being passed into the `counter` function which in turn is invoking it. You might wonder why we have to take this approach instead of just calling `inc` directly from `counter`. The difference is that now we can control the factor of how much the `counter` is going to increment by from the outside. That is, we can pass another function that increments by 2 and Boom! we have a counter that adds by a factor of 2 instead of 1. We can do this without changing the function at all.

> We are not invoking it when write `inc`, the incrementing is only when the brackets are attached to it.

### 3. Return functions

This is going to be longer than the other ones, but bear with me here.

With the last example, we discussed how we can change the `counter` function by passing in different functions. Let us look at how we might achieve that result:

```javascript
function inc(num) {
  return num+1;
}
function incBy2(num) {
  return num+2;
}
function counter(num, incFun) {
  return incFun(num);
}
let number = 1;
number = counter(number, inc);
console.log(number);
number = counter(number, incBy2);
console.log(number);
```

We just created two functions: `inc` and `incBy2`. The first function increments by 1 and second increments by 2. But I guess we can agree that this is not the most elegant approach. If we had to create a function that adds by 3, then we would require a third function. How can we create a single function for this purpose?

Let us look at the simplest approach first:

```javascript
function inc(num, factor) {
  return num+factor;
}
function counter(num, factor, incFun) {
  return incFun(num, factor);
}
let number = 1;
number = counter(number, 1, inc);
console.log(number);
number = counter(number, 2, inc);
console.log(number);
```

Well, this does the work. But this is breaking the expectation we had set for ourselves. The whole objective of passing a funtion to `counter` was the fact that `counter` did not need to know the factor which was being increment or any operation being performed. By passing `factor` into `counter`, we have broken that encapsulation. We need better ways to create dynamic functions that we can pass into `counter`.

```javascript
function createInc(factor) {
  return function(num) {
    return num + factor;
  }
}
function counter(num, incFun) {
  return incFun(num);
}
let number = 1;
number = counter(number, createInc(1));
console.log(number);
number = counter(number, createInc(2));
console.log(number);
```

If this seems natural for you, then Congrats! 🎉🍾 You have successfully understood closures. If it doesn't read on:

`createInc` is a function that returns a function, let that sync in; A function that returns a function.

What we have to be concerned here is the variable `factor` that is passed in. If you look of the [call stack](http://localhost:8000/call-stack/) of this program, you can see that `createInc` is added to the stack and is popped as soon as the function inside it is returned. But the returned function is still using `factor` in runtime. How is that retained?

When a function is created, the function stores both it's local function and the context the function was created in. This context is known as the closure environment. A function when it is created, it stores the local variables and the closure scope it was created in. This closure scope is garbage collected only when the function itself is collected. This is part execution context of the function.

## Does this change the way I write code?

Well, it should. Scopes and Closures are some of the most integral cornerstones of the language. It can and should influence the way you think about the language and declarations.

Is there something I missed? Something wrong? Something good? Ping me on [Twitter](https://twitter.com/agneymenon)