Tricky setTimeout() interview questions explained

Tricky setTimeout() interview questions explained

Introduction

setTimeout() questions are very common in JS interviews. Depending on how you answer them, your level of expertise is determined. In this blog, I will explain a few interview questions which have been asked repeatedly in JS interviews. Let's get started!

For each of the questions, the following are common:

  • The 'for' loop will run 'x' times (here, it is 5 times).
  • When the 'for' loop ends and the call stack is empty, the setTimeout() web API will be moved from the callback queue to the call stack.
  • Whenever the cb function of setTimeout() web API is invoked, a new local execution context is created.

Question 1

What will be the output of this code?

for (let i = 0; i < 5; i++) {
    setTimeout(() => console.log(i), 0);
}

// OUTPUT = 0 1 2 3 4

Explanation

  • We know that 'let' variable creates a block scope.
  • Hence, for each iteration in the 'for' loop, a new block scope is created due to the presence of 'let' and the value of 'i' is unique for each iteration.
  • Now, when the cb function of setTimeout() web API is invoked, the JS engine looks for the value of 'i' in its execution context. Since the value of 'i' is not there, the JS engine will look for the value of 'i' in its lexical scope chain.
  • The immediate lexical scope of the cb is the block scope created by the 'let' variable in that particular iteration, and the JS engine finds the value of 'i' and hence logs the value of 'i' on the console.
  • Similarly, the other cb functions of setTimeout() web API get executed in this fashion.

Animation.gif

Question 2

What will be the output of this code?

let j = 0;
for (j = 0; j < 5; j++) {
    setTimeout(() => console.log(j), 0);
}

// OUTPUT = 5 5 5 5 5

Explanation

  • We know that 'let' variable creates a block scope.
  • If you look at the code, the 'let' variable is created before the 'for' loop. This means that there is no new block scope created for every iteration. But this block scope is common for the entire 'for' loop.
  • Now, when the cb function of setTimeout() web API is invoked, the JS engine looks for the value of 'i' in its execution context. Since the value of 'i' is not there, the JS engine will look for the value of 'i' in its lexical scope chain.
  • The immediate lexical scope of the cb is the block scope created by the 'let' variable outside the 'for' loop, and the JS engine finds the value of 'i' (which is 5 because the 'for' loop has ended) and hence logs the value of 'i' on the console.
  • Similarly, the other cb functions of setTimeout() web API get executed in this fashion.

Animation.gif

Question 3

What will be the output of this code?

for (var k = 0; k < 5; k++) {
    setTimeout(() => console.log(k), 0);
}

// OUTPUT = 5 5 5 5 5

Explanation

  • We know that 'var' variable is function or globally scoped. In this case, since we haven't used a function, it is globally scoped.
  • Because of the 'var' variable, there is no new scope created in each iteration.
  • Now, when the cb function of setTimeout() web API is invoked, the JS engine looks for the value of 'i' in its execution context. Since the value of 'i' is not there, the JS engine will look for the value of 'i' in its lexical scope chain.
  • The immediate lexical scope of the cb is the global scope created by the 'var' variable, and the JS engine finds the value of 'i' (which is 5 because the 'for' loop has ended) and hence logs the value of 'i' on the console.
  • Similarly, the other cb functions of setTimeout() web API get executed in this fashion.

Animation.gif

Question 4

What will be the output of this code?

var k;
for (k = 0; k < 5; k++) {
    setTimeout(() => console.log(k), 0);
}

// OUTPUT = 5 5 5 5 5

Explanation

Explanation similar to Question 3.