set_Timeout() Problem
What will the following program output?
To know the reason behind this behaviour, you need to have a little knowledge about the JavaScript Execution Model (Event Loop).
Code
function guessOutput() {
// declaration using `var`
for (var i = 0; i < 10; i++) {
// Web API
setTimeout(() => {
console.log(i);
});
}
}
guessOutput();
Output
10
10
10
10
10
10
10
10
10
10
By asking this question, the interviewer basically wants to check your knowledge about variable declarations, scoping and intervals/timers in JavaScript.
You might have thought the result would be 0,1,2,...,9
, but the actual output was much different. Why is this?
Upon examining the code snippet, we can make the following observations:
- Variable
i
is declared usingvar
(which has a function scope, rather than a block scope). setTimeout()
function is a part of Web APIs provided by web browsers (browser’s JS engine will take care of scheduling the execution of the specified callback function).- The
delay parameter
is not specified in thesetTimeout()
function (default argument is0
).
Because var
has function scope, all the callbacks created by setTimeout()
function will share the same variable i
, which is incremented in the loop. When setTimeout()
is called, the browser starts a timer and schedules the execution of the callback function after the specified delay (0
in this case). Once the delay has passed, and call stack is empty, the callback is placed in the callback queue. The event loop continuously checks the callback queue and moves the callback from the queue to the call stack for execution.
By the time the callback functions are executed, the loop would have been completed and the value of i
would be 10
. And since all the callbacks refer to the same i
(with value 10
), we get the output as mentioned above.
What if we want output as 0,1,2,...,9
?
To achieve the above output, we can replace var
with let
. Using let
will result in creation of block scope for each callback (with each iteration), and since each callback refers to its own private (and separate) variable i
, the required output will be achieved.
What if we use const
?
Using const
will result in a TypeError
. This is because const
variables are read-only and cannot be incremented or modified after assignment.
The call stack will get empty when the function
guessOutput()
gets destroyed (completely finished executing). But if the function itself got destroyed, how will thesetTimeout()
function access the variablei
?
Learn about closures here.