Anirban
Anirban

Reputation: 197

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?

Upvotes: 0

Views: 27

Answers (2)

Jerry Chen
Jerry Chen

Reputation: 715

This is because variable declared with var is function-level, not block-level.

The first snippt is same code below ```

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

all 'i's point to same address in memory which eventually equal 10.

When it comes to second snippt,because you pass i as an parameter into a function, the real value of i will copy to new memory address in stack for the function. Each i in the function point to the new memory address with diffent value.

Upvotes: 1

bitifet
bitifet

Reputation: 3679

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

Upvotes: 2

Related Questions