Need some clarification on var v let

I just wanted to get some clarification of the example discussed in the lesson ES6: Compare Scopes of the var and let Keywords.

In the below code, is the reason the result is 3 because it loops through 0, 1, 2, and then finally 3, and then just ignores the if statement?

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

Many thanks.

The if isn’t ignored. It’s a matter of the order in which things happen and the scope of i.

  1. printNumTwo is declared, but not initialized.
  2. i is declared and initialized to 0.
  3. i is checked and found to be less than 3, so the loop body executes.
  4. i is checked for equality to 2. The if body is not executed.
  5. i is set to 1.
  6. i is checked and found to be less than 3, so the loop body executes.
  7. i is checked for equality to 2. The if body is not executed.
  8. i is set to 2.
  9. i is checked and found to be less than 3, so the loop body executes.
  10. i is checked and found to be equal to 2, so the if body executes.
  11. printNumTwo is set to a function that returns the value of i.
  12. i is set to 3.
  13. i is checked and found not to be less than 3. The loop body does not execute.
  14. printNumTwo() is called. It returns the value of i, which is 3.
2 Likes

I see thanks!
So in step 11, is the value of i within the function 2?

Also it’s really confusing that i is 3 in the end, even when it explicitly says i must be smaller than 3… maybe this is just something I need to accept and remember that that’s just the way it is

The unexpected result comes from the fact that printNumTwo() is a function that returns the value of the variable i. It will return the value of whatever is in i at the time the function is called. It doesn’t matter what the value of i was when the function was created. At the time that printNumTwo() is called, the value of i has been changed to 3, so that is returned.

This happens because of the scope of var. If we use let instead we get the result you would have expected:

Sorry, this has actually confused me more…!

Isn’t the value of i at the time the function is called, 2? ie. step 10 in your first answer:

  1. i is checked and found to be equal to 2 , so the if body executes.

So doesn’t this mean that at the time that printNumTwo() is called, i is 2, since printNumTwo() comes directly after the if body? Why would 3 already come into play at this point?

I thought that 3 doesn’t even get past the for loop since it is not smaller than 3, so how would it even get to point of being at the if body?

Sorry if I am not getting it…

That’s not when the function is called. That’s when the function is created. The function is called when you do console.log(printNumTwo()). At that point the loop has already executed and i is 3.

The last argument of the for loop i++ happens at the end of each loop iteration. On the last execution of the loop body, i is equal to 2, then the if is evaluated, then i is set to3. After this i < 3 is false so the loop does not iterate again.

1 Like

Oh I see, I didn’t understand the difference between creating a function and calling a function, now I get it - thank you so much! :slight_smile:

I’m glad I could help. Happy coding!

1 Like