Why is i = 2 let

Tell us what’s happening:
I understand the basics of the example but im having trouble understanding the reasoning behind getting i = 2 when we use “let”
instead of “var”.
in the first example,
We have a variable named printNumTwo and a for loop . this loop starts with a var i = 0 it will run as long as i is smaller than 3, i < 3 and will increment by 1 at every iteration of the loop i++ . this loop does not really do anything until **i == 2** at which point printNumTwo will be assigned as a function that can be executed , when this function is executed it will return the variable i . since all we are doing when i == 2 is creating a function, and not actually returning anything, the loop continuous with i++ making i = 3 , since i < 3 is false the loop ends.

Lastly we console.log(printNumTwo(()); a function that was created when our loop first ran, and all this function does is return i i = 3 because that’s when the loop ended.

So, when we use let, we will get a return of i = 2. i understand that let is not declaring i as a global statement, but since we declared i inside the loop using let, wouldn’t we get the same result of i = 3? i was incremented to 3 within the loop at which point the loop was falsely and stopped.

Your code so far

var printNumTwo;
for (var i = 0; i < 3; i++) {
  if (i === 2) {
    printNumTwo = function() {
      return i;
    };
  }
}
console.log(printNumTwo());
// returns 3
'use strict';
let printNumTwo;
for (let i = 0; i < 3; i++) {
  if (i === 2) {
    printNumTwo = function() {
      return i;
    };
  }
}
console.log(printNumTwo());
// returns 2
console.log(i);
// returns "i is not defined"

var printNumTwo;
for (var i = 0; i < 3; i++) {
if (i === 1) {
  printNumTwo = function() {
    return i;
  };
}
}
console.log(printNumTwo());
// returns 3

Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:81.0) Gecko/20100101 Firefox/81.0.

Challenge: Compare Scopes of the var and let Keywords

Link to the challenge:

Have read the docs? I think you’ve successfully discovered some subtle differences between the two types of variables.

https://stackoverflow.com/questions/762011/whats-the-difference-between-using-let-and-var#:~:text=The%20main%20difference%20is%20the,outside%20the%20loop%20for%20example.&text=let%20allows%20you%20to%20declare,on%20which%20it%20is%20used.

yes, i have read it. and think that i understand the basics of how let is a variable that only exists within its own block, yet, from a logical point of view i cant figure out the proccess behind the following js returning 2.

use strict';
let printNumTwo;
for (let i = 0; i < 3; i++) {
  if (i === 2) {
    printNumTwo = function() {
      return i;
    };
  }
}
console.log(printNumTwo());
// returns 2
console.log(i);
// returns "i is not defined"

Would it be possible to walk this function step by step as i was able to do with the function using var instead of let?

What might help explain this is to unroll the loop:

let printNumTwo;
{
  let i = 0;
  if (i === 2) {
    printNumTwo = function() {
      return i;
    };
  }
}
{
  let i = 1;
  if (i === 2) {
    printNumTwo = function() {
      return i;
    };
  }
}
{
  let i = 2;
  if (i === 2) {
    printNumTwo = function() {
      return i;
    };
  }
}
{
  let i = 3;
  if (i === 2) {
    printNumTwo = function() {
      return i;
    };
  }
}
console.log(printNumTwo());
// returns 2
console.log(i);
// returns "i is not defined"

What happens with var? Something like this:

et printNumTwo;
var i = 0;
{
  if (i === 2) {
    printNumTwo = function() {
      return i;
    };
  }
}
{
  i = 1;
  if (i === 2) {
    printNumTwo = function() {
      return i;
    };
  }
}
{
  i = 2;
  if (i === 2) {
    printNumTwo = function() {
      return i;
    };
  }
}
{
  i = 3;
  if (i === 2) {
    printNumTwo = function() {
      return i;
    };
  }
}
console.log(printNumTwo());
// returns 3
console.log(i);
// returns 3

In the let example the declared i’s are invisible outside of their scope. Therefore the function refers to the i in it’s scope and nothing else. Nothing outside can change it.

In the var example there is only one i and it’s shared amongst the scopes. The next iteration of the loop will change it, because it is referencing exactly the same variable.

With let there are 4 i variables, and 4 scopes. With var there is 1 i variable. There are still 4 scopes, and when they refer to i it’s the one i variable that is visible from all 4 scopes.

1 Like

That… makes sense now. I feel silly. Thabks to both of you for your help!

1 Like

No need to feel silly - this is one of the harder parts of JS to understand.