1

I'm just trying to understand closures in Javascript. I came across below three examples.
Expample 1:

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

And the output is as expected as it prints "i : 11" to the console 11 times because only one scope is created for entire loop that is global scope.To have different scope in each iteration I used IIFE(Immediately invoked function expression) please see the below code snippet.
example: 2

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

It prints from "i:0" to "i:10" as expected because different scope is created for each iteration.
I'm not able to understand what exactly is happening in the below code snippet.
example :3

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

It prints from "i:0" to "i:10".
1 .I'm not able to understand why the output is not as same as first example i.e print "1:11" 11 times?
2 . Is different scope is being created for each iteration if I use block scope?
3 . If different scope is being created, then how is it different from example-1?

dodov
  • 5,206
  • 3
  • 34
  • 65
prabhudas
  • 88
  • 10

2 Answers2

1

That is because let operates with block scope (var does not). This means that it is like declaring a local variable within the block of your code making up the for statement.

For example you can do this:

if (blockCount === 3) {
  let x = 1;
  // do something with x
} else {
  let x = 2:
  // do something with x
}

console.log(x);  // undefined since no longer in scope

This will work as written. If you try to access x outside the if statement it would be undefined.

See this link for more info.

rasmeister
  • 1,986
  • 1
  • 13
  • 19
0

In the first example, you call a setTimeout() that prints the variable i after a certain time. By the time the setTimeout() callbacks fire, the loop has finished and i possesses the last iteration value (11). All the callbacks print that variable.

In the second example, you use an immediately invoked function expression (IIFE). This is a function that is defined and called immediately, with the argument i passed to it. When you pass an argument to a function, it is like a new local variable was declared. For example:

var foo = 5;

function myLog(foo) {
  console.log(foo);
}

myLog("not 5"); // logs "not 5" instead of 5

This means that the argument i of the immediately invoked function is different from the i used in the loop, but has the same value, because you pass it at the current iteration of the loop.
With this approach, you create 12 different i variables. One for the loop, and 11 others for the IIFEs, which the setTimeout() callbacks inside of use.

In the third example, a similar thing happens. let declares a block scope local variable. When the loop runs, it's like 11 different variables were created and each setTimeout() callback references the variable created in its own local scope. This is more thoroughly explained here.

Community
  • 1
  • 1
dodov
  • 5,206
  • 3
  • 34
  • 65