Anirban Acharya Anirban Acharya - 2 months ago 6
Node.js Question

What is exactly happening when I am using setTimeout within another function and trying to print the value of the argument passed?

I was going through learnyounode when I had to complete the juggling async challenge, and that is where I came across a similar simpler problem as below:



// try print numbers 0 - 9
for (var i = 0; i < 10; i++) {
setTimeout(function() {
console.log(i)
})
}





the above snippet gives the output as:

10
10
10
10
10
10
10
10
10
10


which is not the intended result, however when I write it in the following way:



// try print numbers 0 - 9
var f = function(i) {
setTimeout(function() {
console.log(i)
})
}
for (var i = 0; i < 10; i++)f(i);





I get the desired output. So what is exactly happening when I am writing the setTimeout() portion inside that function?

Answer

In the first snipped, i variable is defined outside the function. You can access it just simply because it is on its (higher level) scope and there isn't another i variable defined in the function own (or any intermediate if it had been exist).

The for loop sets ten timeouts (enqueued to the event loop). But they will be executed only when the for loop had finished, so i value is 10 (the last of the iteration).

In the second example, you are surrounding the setTimeout() inside a closure (function) which is execued immediately each loop iteration.

In those iterations, when the function is called, the current value of i is passed as parameter (also named i, which is defined in the local function's scope and, because it has the same name, hides the fact you aren't calling the same variable).

See below slight modification of your second example:

// try print numbers 0 - 9
var f = function(j) {
  setTimeout(function() {
    console.log(i, j)
  })
}
for (var i = 0; i < 10; i++)f(i);

// Output:
// -------
// 10 0
// 10 1
// 10 2
// 10 3
// 10 4
// 10 5
// 10 6
// 10 7
// 10 8
// 10 9
Comments