Wednesday, 16 May 2018

setTimeout with Loop in JavaScript




I have a very trivial question. For a simple loop with setTimeout, like this:



for (var count = 0; count < 3; count++) {
setTimeout(function() {
alert("Count = " + count);
}, 1000 * count);
}


console gives an output like this:




Count = 3
Count = 3
Count = 3


Not sure why the output like this. Anyone could explain, please?


Answer



This has to do with how scoping and hoisting is being treated in JavaScript.




What happens in your code is that the JS engine modifies your code to this:



var count;

for (count = 0; count < 3; count++) {
setTimeout(function() {
alert("Count = " + count);
}, 1000 * count);
}



And when setTimeout() is being run it will first look in it's own scope after count but it won't find it so then it'll start looking in the functions that closes (this is called closures) over the setTimeout function until it finds the var count statement, which will have the value 3 since loop will have finished before the first timeout function has been executed.



More code-ily explained your code actually looks like this:



//first iteration
var count = 0; //this is 1 because of count++ in your for loop.

for (count = 0; count < 3; count++) {
setTimeout(function() {

alert("Count = " + 1);
}, 1000 * 1);
}
count = count + 1; //count = 1

//second iteration
var count = 1;

for (count = 0; count < 3; count++) {
setTimeout(function() {

alert("Count = " + 2);
}, 1000 * 2);
}
count = count + 1; //count = 2

//third iteration
var count = 2;

for (count = 0; count < 3; count++) {
setTimeout(function() {

alert("Count = " + 3);
}, 1000 * 3);
}
count = count + 1; //count = 3

//after 1000 ms
window.setTimeout(alert(count));
//after 2000 ms
window.setTimeout(alert(count));
//after 3000 ms

window.setTimeout(alert(count));

No comments:

Post a Comment

casting - Why wasn&#39;t Tobey Maguire in The Amazing Spider-Man? - Movies &amp; TV

In the Spider-Man franchise, Tobey Maguire is an outstanding performer as a Spider-Man and also reprised his role in the sequels Spider-Man...