Javascript — setTimeout and Loops- the most common interview question

Eishta Mittal
4 min readOct 30, 2022

What will be the output of the given code?

This is one of the most common questions asked in Javascript interviews. Why ?

This question and the logic behind solving it shows how well you understand scopes and closures in JS.

The output of the given code is definitely not

0 1 2

It is

3 3 3

But why 3 times 3 ? Whereas the below code gives the desired output.

It is because, the code here is executed synchronously. The execution of code happens like this:-

console.log(0); i = 0
console.log(1); i = 1
console.log(2); i = 2

Whereas , with setTimeout, we have wrapped the console.log in a callback. A callback is just some code we want to run after another function runs. This callback runs after the synchronous code has completed executing as the setTimeout callback is sent to a web API.

The callback we provide in setTimeout gets put into the event queue and is picked for execution after the callstack has implemented the synchoronous code.

So certainly, the callback has to keep a copy of i in order to use it, right?

The variable declared with var i creates a variable in global environment which is getting updated with each iteration.

The callback that we pass to the setTimeout creates a closure over its outer environment(variable i). So the callback is referencing the global variable i .

Variable declared with var inside loop creates a global variable

At the time when loop ends , that is , the callstack is empty and now its the time for eventloop to pick the code from the event queue, the value of i in the global environment is 3 (the value at which loop exits).

So the closure(callback in the setTimeout ) refers to this global environment variable i and hence prints 3 three times.

How can we resolve it ?

Its clear from the above discussion, that the solution lies in creating a different scope for i to exist in each time we call setTimeout, so that each callback in the event queue maintains a reference to a completely different variable, and we really have 3 different variables all named i, in different scopes.

1. Using let

Using let to declare the variable i creates a different scope for i in each iteration. As let has a block scope, it does not create a global variable for i and creates a different scope for each value of i in the loop.

We can also create a variable inside the loop. This will also give the same output:-

Here, i still remains a global variable but the variable j is limited to the block scope of the loop. So for each iteration, a different scope is created for j .

2. Using function

Each function creates a unique scope. Because of this, variables with the same name can exist in separate functions and not interfere with each other.

When the for loop is done, these three unique values of k are still in memory and are accessed appropriately by our console.log(k) statements. That is closure.

3. Using IIFE

Here, IIFE creates a new scope for each setTimeout callback without disturbing the global scope or parent scope.

4. Using Bind

The Function#bind function creates a new function that, when called, will call the original function using the first argument as this for the call and passing along any further arguments. So console.log.bind(null, i) creates (but doesn't call) a function that, when it is called, will call console.log with this set to null and passing along i as the first argument.

Source

https://dev.to/levimeahan/closures-scope-and-the-settimeout-for-loop-question-5bl6

https://www.freecodecamp.org/news/thrown-for-a-loop-understanding-for-loops-and-timeouts-in-javascript-558d8255d8a4

--

--