setTimeout + Closures Interview Question ๐Ÿ”ฅ

setTimeout + Closures Interview Question ๐Ÿ”ฅ

ยท

5 min read

In this blog, we are going to learn about a few interesting questions related to set timeout and closure. So let's start directly with an example.

function x(){
  var i = 1;
  setTimeout(function(){
   console.log(i);
   },1000)
}
x();

From the above example, we are just to learn what setTimout does and what exactly the above function will output. So basically setTimeout function takes two arguments first one function and the second one is a timer. Mainly we use it when we wanted to execute after a certain time.

In the above example, we have setTimeout in our function and we are passing one function inside it where we are just printing the value of variable i after 1000 ms.
So the output will be simply 1. So maybe not much to learn from example one it just gave us an idea about what is setTimeout but let's move to a little more interesting example.

function x(){
  var i = 1;
  setTimeout(function(){  // Line 1
   console.log(i);
   },1000)
   console.log('ALL IS WELL');  
   console.log('LINE 2'); 
}
x();

WHAT DO YOU THINK WILL BE THE OUTPUT NOW

So here most of the time we guess that the first setTimeout will wait for 1000 ms and it will print the value of i and then will print ALL IS WELL and at last it will print
LINE 2 but we are wrong here the actual output will be as below.

ALL IS WELL
LINE 2
1 // YES THIS WILL BE PRINTTED LAST

Now the question comes to mind why do we have output 1 at last and single line
the answer is javascript waits for none. We know javascript is the synchronized language it executes one line of code at a time from top to bottom now. When the program comes to line number 1 javascript sees the setTimout function with a timer of
1000 ms so rather than waiting for this function to get execute javascript take this function and put it somewhere else and move to the next line to execute the code. And this way it prints ALL IS WELL first then LINE 2 now javascript has nothing more to execute so it will see if setTimeout timer is completed if yes then let's execute the
function of setTimeout and print the value of the variable i which is 1. This example was a little bit more interesting than the previous one now let's take one more interesting example and this one is more like an interview question.

Que : Print value from 1 to 5 where 1 should be printed after 1 second 2 should be printed after 2 seconds and the same 5 should be printed after 5 seconds.

In most of our minds if we don't have clear idea of the scope then the most first idea that comes to mind is just to put setTimeout in for loop as below.

function funWithLoop(){
  for(var i = 1 ; i <= 5 ; ++){
    setTimeout(function () {
      console.log(i)
    },i * 1000); // for i= 1 1000 ms for i = 2 2000ms and so on
  }
}
funWithLoop();

Great working example but not really because this will print output as below.

 6 // after 1 sec
 6 // after 2 sec
 6 // after 3 sec
 6 // after 4 sec
 6 // after 5 sec

Why do we have an output like this let's understand so you see we are using var and we know that var function scope and here we are declaring a variable i for block scope and that's why the single variable value of i is keeps getting updated and until
loops end value of i became 6 now we also learned that javascript waits for none so as soon as 1000 ms get completed then javascript calls a function inside setTimeout and print the value of i which is 6. Understand one point here that we learned in closure also the function in its lexical environment holds the reference of the variable not the value and that's why all the five-time functions inside setTimout will have the same value 6 because they all hold the same variable i.

The simplest solution for the above problem is using let in for loop rather than var.
Because let is blocked scope and that's why for all five iterations new variable
will be created in block memory and will be used inside setTimeout functions.

function funWithLoop(){
  // ONLY CHANGED VAR TO LET AND EVERYTHING WORKED MAGIC HAPPENS
  for(let i = 1 ; i <= 5 ; ++){
    setTimeout(function () {
      console.log(i)
    },i * 1000); // for i= 1 1000 ms for i = 2 2000ms and so on
  }
}
funWithLoop();

One last point to learn here that how can we solve problems without using let and here the knowledge of closure will come into the picture. See what problem we had
when we were using var is single variable was getting created in memory because var is a function scoped and we have everything inside for loop block. So we can do one thing put for loop code into a different function and pass the value of i into that function this way we are passing parameter in the function and when the execution context for this function will be created then new memory will be assigned to this variable and this way for all different memory space will be created.

function funWithLoop(){
  // ONLY CHANGED VAR TO LET AND EVERYTHING WORKED MAGIC HAPPENS
  for(let i = 1 ; i <= 5 ; ++){
      understandMe(i) // see i am getting passed as argument 
  }
}
//Everytime i will get callled i will create for memory for i because
// its my parameter );
function understandMe(i){
 setTimeout(function () {
      console.log(i)
    },i * 1000); // for i= 1 1000 ms for i = 2 2000ms and so on
}
funWithLoop();

That's all about setTimeout + Closures in JS. And thanks to Akshay Saini for creating an incredible Namaste Javascript playlist this blog is just whatever learning I had from there.

ย