Skip to content

Przemysław Konieczniak - Dev Notes

Closures

JavaScript, Functional Programming

Closure is a mechanism that allows an inner function to gain access to the variables from the outer/parent function scope, regardless of the context that the function was invoked.

The closure is created with every function creation. To create a closure you have to define a function or an object that contains functions as properties inside another function and return it. If the returning function in its definitions refers to any values from the parent scope, it will have access to these variables during the runtime.

The main reason to use closures is the fact that they allow us to encapsulate the state and keep it private and control them through public interfaces.

Closures are often used in a technique called Partial Application, but at this moment let's focus just on closures.

closure-timer
1function createCounter () {
2 let value = 0
3 return {
4 increment: () => { value += 1 },
5 decrement: () => { value -= 1 },
6 getValue: () => value
7 }
8}
9
10const counter = createCounter()
11counter.increment()
12counter.getValue() // 1

If you are preparing for the job interview it is a high probability that you will be asked about the closures. The typical question looks like: What will be the result of the below code snippet?

closure-interview-snippet
1let i;
2for (i = 0; i < 3; i++) {
3 const log = () => {
4 console.log(i);
5 }
6 setTimeout(log, 100);
7}

In the above example, the i variable is defined in the global scope. Each time the new log function is created, it's also created a new closure with the global i variable. Because the execution of each new log function is delayed of 100ms, any log function will be fired at least after the loop execution. It means that the value of i variable at the end equals 3. As a result, 3 will be printed three times.

1// 3
2// 3
3// 3

To fix this behavior and receive digits 0, 1, 2, we have to declare the i variable as a counter, instead of declaring this variable in the global scope. Now when the closure is created it refers to the current value of the loop counter instead of the global variable.

1for (let i = 0; i < 3; i++) {
2 const log = () => {
3 console.log(i);
4 }
5 setTimeout(log, 100);
6}
7// 1
8// 2
9// 3

Resources

© 2020 by Przemysław Konieczniak - Dev Notes. All rights reserved.