Alberto Favaro
Alberto Favaro

Reputation: 1842

Invoke setTimeout() in IIFE against standard in a loop

What is the logic behind the IIFE function and the logic behind setTimeout() in a loop. There are two for:

for (var i = 0; i < 10; i++) {
  // Standard
  setTimeout(function() {
    console.log("Standard" + i);
  }, 1000 * i);
}

for (var j = 0; j < 10; j++) {
  // IIFE
  (function(j) {
    setTimeout(function() {
      console.log("IIFE " + j);
    }, 1000 * j);
  })(j);
}

Now when I run with node.js, I have this result after 10 seconds (each console.log() is executed every second):

PowerShell

Can someone explain to me the runtime logical difference between the invocation of the first function and the second ?

Especially if you can answer these questions:

Thank you in advance.

[Edit] I don't understand why in both for the console.log() is fired every second but the timeout seconds 1000 * i|j may be a visible timeout.

Upvotes: 1

Views: 476

Answers (2)

Anurag Lal
Anurag Lal

Reputation: 103

Why the log is executed each second in both for? (1000 * i|j is ignored)

This is because setTimeout() is an asynchronous function. So the execution does not get blocked at this step, rather a clock is started with the given time duration parameter and the execution moves on. Once the duration is passed, events are fired and the callback is added to the event loop queue for being executed one by one.

Why the value of i always 10?

This is because of the concept of closure. When the first "Standard" timeouts, the value of i by that time is already 10 (All setTimeouts are registered by then). While in the case of IIFE, j is a formal parameter in the function that receives the loop counter variable value after each iteration. And the setTimeouts contained in this function uses this j.

Upvotes: 1

Emil S. J&#248;rgensen
Emil S. J&#248;rgensen

Reputation: 6366

In the first version setTimeout is referencing the variable i from the parent scope when it fires, but by then it has already changed.

In the second you create a bunch new scope with a j parameter that is not a reference to the parent scopes j variable. Therefore it is unchanged when the setTimeout fires.

Upvotes: 0

Related Questions