Skip to content Skip to sidebar Skip to footer

Javascript: Understanding Let Scope Inside For Loop

Please consider snippet below- for(let i = 1; i <= 5; i++) { setTimeout(function(){ console.log(i); },100); } In this case, logs inside setTimeout will contain val

Solution 1:

General Explanation

When you use let in the for loop construct like you show, there is a new variable i created for each invocation of the loop that is scoped just to the block of the loop (not accessible outside the loop).

The first iteration of the loop gets its value from the for loop initializer (i = 1 in your example). The other new i variables that are created each loop iteration get their value from the i for the previous invocation of the loop, not from the i = 1 which is why they aren't all initialized to 1.

So, each time through the loop there is a new variable i that is separate from all the other ones and each new one is initialized with the value of the previous one and then processed by the i++ in the for loop declaration.

For your ES6 code of this:

for(let i = 1; i <= 5; i++) {
   setTimeout(function(){
       console.log(i);
   },100);
} 

In ES5, this would be an essentially equivalent structure. If you really study this, it can be very informative for what's actually happening in your above ES6 code:

(function() {
    for (var i = 1; i <= 5; i++) {
        i = (function(j) {
            setTimeout(function(){
                console.log(j);
            },100);
            return j;
        })(i);
    }
})();

It takes two IIFE (immediately invoked function expressions) to simulate this. The outer one isolates the var i so that it doesn't leak out of the for loop and the inner one provides a separate scope and separate variable for each invocation of the for loop. The return j and the i = (function(j) {...})(i) is to show how the next iteration of the loop is affected by a modification to the loop variable.

Hopefully, this illustrates how incredibly useful let is for for loop in ES6 and how much other code it replaces when you need/want this functionality.

Now for Your Specific Questions

For this, I have read explanations over the Internet like - let creates a variable declaration for each loop which is block level declaration. So basically it creates a scope within { }

let defines variables that have block scope (not function scope like var). And, the { and } that delineate the for loop do indeed define a scope.

Also, variable i is declared, initialized and incremented outside the loop block i.e. curly braces in the for loop statement.

Well, not quite. The for loop is an instruction for how to initialize the first i created for the first invocation of the loop. The fact that the let i = 1 appears outside the loop does look a bit confusing, but it's really just an instruction for what to when it creates the first i variable for the first invocation of the loop. That first i variable doesn't actually exist outside the loop scope.

So, in each iteration isn’t the same variable i is incremented and utilized?

No. When ES6 encounters a for loop with a let definition, it creates a new variable for each iteration of the loop.

How exactly does let creates a variable declaration for each loop and has value of previous iteration?

It isn't let doing this. It's the for loop logic in the ES6+ JS interpreter. This is a special behavior for a for loop that has an index initializer declared with let. So, it's a combination behavior of let and for, but the real logic is in the way the for loop is executed by the interpreter.

Special Case When Modifying the Loop Variable

There is also a special case for let in for loops. If you assign to the value of i in the loop, it will change that particular value of i and it will also affect the next iteration's value of i. This is a bit of a special case, but it allows you to still manipulate the value of i in the loop.

for(let i = 1; i <= 5; i++) {
   let j = i;
   setTimeout(function(){
       console.log(j);
   },100);
   if (i === 2) {
      i++;         // bump the loop increment to skip the 3 value
   }
}

This creates the output:

1
2
4
5

So, this skips the 3 iteration of the loop because when i === 2, we increment it to 3, then the for loop does its i++ iteration and bumps it up to 4, effectively skipping the 3 iteration.

Solution 2:

A for loop like this:

for (let i = 1; i <= 5; i++) {
  setTimeout(function() {
    console.log(i);
  }, 100);
}

Is the same as doing this:

{
  let i = 1;
  setTimeout(function() {
    console.log(i);
  }, 100);
} 

{
  let i = 2;
  setTimeout(function() {
    console.log(i);
  }, 100);
} 

{
  let i = 3;
  setTimeout(function() {
    console.log(i);
  }, 100);
} 

{
  let i = 4;
  setTimeout(function() {
    console.log(i);
  }, 100);
} 

{
  let i = 5;
  setTimeout(function() {
    console.log(i);
  }, 100);
}

The variable is declared and assigned inside the scope of the for loop five separate times, and each instance is completely separate from the others.

Solution 3:

In javascript you can define a variable through either var or let. The variables which are defined as let does not refined.Lets consider an example code snippet

<!DOCTYPE html><html><body><h2>JavaScript let</h2><pid="demo"></p><script>var i = 3;
for (var i = 0; i < 10; i++) {
  // some statementsdocument.getElementById("demo").innerHTML += i;
}
document.getElementById("demo").innerHTML += i;
</script></body></html>

In this code the output will be --> 012345678910 In contrast, the variable with let in the loop does not redeclare the variable outside the loop.

<!DOCTYPE html><html><body><h2>JavaScript let</h2><pid="demo"></p><script>let i = 5;
for (let i = 0; i < 10; i++) {
  // some statementsdocument.getElementById("demo").innerHTML += i;
}
document.getElementById("demo").innerHTML += i;
</script></body></html>

Output of above code will be --> 01234567895 Here the variable outside the loop remains unchanged and the inner loop executed and after the loop finished, global variable remains with the same value 5. It basically separates the variable according to their scope.

Post a Comment for "Javascript: Understanding Let Scope Inside For Loop"