Understanding closures in JavaScript
Tags: javascript, codenewbie, webdev
Published: 2020-11-13 06:07:18

### Introduction

In this article, we will learn about closures in JavaScript.

Every JavaScript developer should be aware of closures as it's the most frequently asked interview question as well as understanding it clearly will help you to avoid creating bugs in your code.

So let's get started.

## What is closure?

Before diving into closures, we first need to understand how scope works in JavaScript.

Take a look at the below code:

```js
function display() {
 var i = 10;
 console.log(i); // 10
}

display();
console.log(i); // Uncaught ReferenceError: i is not defined
```

When we declare a variable with `var/let/const` keyword inside a function, it's only available inside that function which means it's scoped to that function only because it becomes a private variable.

If you execute the above code, you will see that inside the function, `console.log` will print the value 10 as the variable `i` is available inside the function scope.

But outside the function the variable will not exist so when we try to print it, `Uncaught ReferenceError` is displayed.

Now, take a look at the below code:

```js
function add(x) {
 var sum = 5;

 function result(y) {
  sum = sum + (x * y);
  return sum;
 }
 
 return result;
}

var output = add(4); // output will contain the result function
console.log(output(5)); // 25
console.log(output(10)); // 65
```

In the above code, we have defined `result` function inside the `add` function and from the `add` function we're returning the `result` function.

So in the first `console.log` we get `25` as the output because `sum` is initialized to 5 inside the function so 5 + (4 * 5) = 25.

When we again call the function stored in the `output` variable by passing 10, even though the `sum` function has finished executing, it will still retain the value of `sum` variable calculated last time which was 25 so the output will be 65 because 25 + (4 * 10) = 65.

So here comes the definition of a closure.

> A function when defined inside another function and is returned from the outer function, will retain access to all the variables that were in the scope when the inner function was defined even after the outer function is terminated.

So in short in the above code, when we defined the `result` function, it has access to the `sum` variable and we're returning the `result` function from the `add` function so the `result` function will retain access to the `sum` variable even after the `add` function has finished executing.

This is known as closure.

> Closures are very useful as it provides a way to create private variables which are only accessible from inside the function and will retain its value across the function calls.

So we cannot access the `sum` variable directly and it's only accessible through the call to the `result` function avoiding the misuse of the `sum` variable.

Take a look at the below code: 

```js
function getCharacter(name) { 
 let i = 0;
 return function next() {
  const value = name[i++];
  return value;
 }
}

const next = getCharacter('hello');

console.log(next()); // h
console.log(next()); // e
console.log(next()); // l
console.log(next()); // l
console.log(next()); // o
```
 
In the above code, variable `i` will retain its value across the multiple function calls so we're able to get each character in every function call using closures.

We can re-write the above code as below:

 ```js
function getCharacter(name) { 
 let i = 0;
 
 return {
  next: function() {
   const value = name[i++];
   return value;
  }
 };
}

const obj = getCharacter('hello');

console.log(obj.next()); // h
console.log(obj.next()); // e
console.log(obj.next()); // l
console.log(obj.next()); // l
console.log(obj.next()); // o
```

In the above code, we're returning an object from the function and the object has function as a property so it will also be a closure.

Now, take a look at the below code:

```js
for(var i = 0; i < 5; i++) {
 setTimeout(function() {
  console.log(i);
 }, 1000);
}
```

This is a very famous interview question. 

You might think that the above code will print numbers from 0 to 4 but it actually prints the number 5 five times.

This is because we have used `setTimeout` function inside the for loop so by the time, the `setTimeout` executes(which is after 1 seconds), the for loop is already finished executing.

So the value of `i` is 5 when the for loop is finished so the `setTimeout` function will print the value 5 five times.

There are two ways we can fix this issue.

* using closures:

```js
for(var i = 0; i < 5; i++) {
 (function(i) { 
   setTimeout(function() {
    console.log(i);
   }, 1000) 
  })(i);
}
```

The above code will correctly print the values from 0 to 4.

This is because by wrapping the `setTimeout` call in a function, we're creating a unique scope for each interaction. 

So the value we're passing to the inner function at `(i)` will be passed to the function as a parameter `function(i)`.

* using let:

ES6 has added a `let` keyword which creates a new scope for each iteration when used inside a loop so we can just use the `let` keyword instead of `var` which will correctly print the value from 0 to 4.

```js
for(let i = 0; i < 5; i++) {
 setTimeout(function() {
  console.log(i);
 }, 1000);
}
```  

Now, take a look at the below code:

```js
var numbers = {};
for(var i = 0; i < 10; i++){
 numbers[i] = function() { 
   console.log(i);
 }
}

console.log(numbers[0]()); // 10
console.log(numbers[1]()); // 10
console.log(numbers[2]()); // 10
```

Here, also we get the value `10` printed every time instead of the actual value of the variable `i`.

We can fix this in 2 ways.

* using `let` instead of `var`
* defining the function outside the loop like this:

```js
var numbers = {};

function log(value) {
 return function getValue() {
  return value;
 }
}

for(var i = 0; i < 10; i++){
 numbers[i] = log(i);
}

console.log(numbers[0]()); // 0
console.log(numbers[1]()); // 1
console.log(numbers[2]()); // 2
```

In the above code, we have defined the `getValue` function inside the `log` function so we created a closure that will retain the value of `i` which was passed to it.

So we get the correct expected output.

## Conclusion

That's it about this article. 

I hope you're now clear with using closures in JavaScript.

**Don't forget to subscribe to get my weekly newsletter with amazing tips, tricks, and articles directly in your inbox [here](https://yogeshchavan.dev).**

[<img src="https://cdn.buymeacoffee.com/buttons/default-yellow.png" >](https://www.buymeacoffee.com/myogeshchavan97)