5 tricky JavaScript Closure questions
We’ll cover some of the trickest and possibly the most commonly asked questions on closures.
Let’s begin with the basics.
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.
— MDN Web Docs
Simply put Closure is just a function nested inside a function that has the access to its parent function’s state.
function myFunc() {
var data = 'MyFunc' // Local varialbe of myFunc
function displayData { // Well this function is a closure
alert(data); // Access variable declared in parent
}
return displayData;
}
var func = myFunc();
func();
Well, now that we have that out of our way let's dive into the possible questions that you might be asked in an interview.
1. Write a function that will increment the number by 1 (or any other number).
Let's think about it. We want a function which when given a number will increment it by a predefined base. The solution requires us to create a closure that remembers the base value from its parent function and returns the result by adding the current and base values.
function myFunc(base) {
return function(num){
console.log(num + base)
}
}
var fun=myFunc(1)
fun(10)// logs 11
fun(20)// logs 21
var fun=myFunc(2)
fun(10)// logs 12
fun(20)// logs 22
2. What is the output of the given code?
var num = 10;
(()=>{
console.log(num);
var num = 20;
console.log(num);
})();
And the options are:
- 10 20
- undefined undefined
- 20 20
- undefined 20
The right answer here is undefined 20. This is because of the scope of the closure itself and a little feature of Javascript called hoisting. When the above code is interpreted, it is converted to this
var num = 10;
(()=>{
var num;
console.log(num); // undefined
num = 20;
console.log(num); // 20
})();
Javascript takes the deceleration of the variable num and moves it to the top of the closure(but not to the global level). While leaving the assignment where it was. So as such the first console.log prints undefined and the second prints the value 20.
3. Create a private counter.
After understanding the above 2 questions, this should be a piece of cake. Check out the code below:
function myCounter() {
let counter = 0
const myFunction = function() {
counter = counter + 1
return counter
}
return myFunction
}
var increment = myCounter()
increment() // returns 1
increment() // returns 2
increment() // returns 3
We create a function myCounter which has one private variable counter. This function myCounter along with its inner function forms a closure, which encapsulates the data and its logic. Hence when we declare a new variable increment and assign it with the function definition of the returned function, calling increment will run the inner function and add 1 to the counter variable and return it.
4. Multiply 3 numbers like mul(2)(3)(4).
Well, someone new to JS might think what is (2)(3)(4)? 😕 But it's a simple example of Currying.
Let's first break down the problem. We require a function such that it takes a number and returns us another function, which in turn will also return us a function which multiplies the inputs. Confused yet?
Well, don’t be just have a look below.
function mul(a) {
return function(b) { // closure
return function(c) { // closure
return a * b * c;
};
};
}
mul(2)(3)(4)
The function mul() takes in a as the first argument and returns us a function that is a closure. This second function takes in argument b and returns us the third function which is also a closure. And at last, the third function takes in the argument c and multiplies all the arguments, and returns us the results.
5. What is the output of the given code?
Saved the best for the last. (Probably the most commonly asked)
var i;
for (i = 0; i < 3; i++) {
setTimeout(() => {
console.log(i);
}, 100);
}
If you have just started preparing for JS interviews, then probably your answer might be 0,1,2. But no, that's incorrect (FYI — I also didn’t get it right the first time😅).
The correct answer is 3 being printed 3 times. Ok, let's go step by step. Firstly the for loop runs 3 times and for each iteration, a new anonymous function is created and attached to the set timeout. All the 3 iterations happen super fast before 100ms can pass and even the first set timeout function can execute.
All the closures get the reference of i. And once 100 ms has passed and it's time to run the inner functions, the value of i has become 3. Hence the output is 3 being printed 3 times.
If you enjoyed reading this, don’t forget the applause. 👏
Thank you.