1

My first question was about different consequences of using var and let keywords in initialization expression of for loop header which is a common question on stackoverflow. I read some other similar questions and now I know what is the difference but what I'm trying to understand is why this happens? I need to know what happens under the hood when we use let rather than var in for loop. So I thought up an explanation and want to know if It's correct and if not, what's the correct explanation?

1- The following code uses var for i:

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

My explanation: when i's value is 2 the if block executes and inside loop's body, we create a function and save it’s reference into printNumTwo variable. The function says return i. Here because i has been declared using var keyword and is global so we have access to i's value everywhere so the function's actual instruction is "return what is stored in i" whenever printNumTwo is called. So after calling printNumTwo() what is currently in i variable is printed to console which is the number after last update: 3.

2- The following code uses let for i:

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

My explanation: when i's value is 2 the if block executes and inside loop's body, we create a function and save it’s reference into printNumTwo variable. The function says return i. Here because i has been declared using let keyword and we don’t have access to it after for statement scope finishes, so the current value of i matters so the function's actual instruction is "returns the number 2" whenever it’s called. So after calling printNumTwo() number 2 is printed to console.

Vahid Pouyafar
  • 71
  • 1
  • 10
  • 1
    *"the function's actual instruction is "returns the number 2" whenever it’s called."* No, that's not right. The function still performs "return what is stored in `i`". The difference is that the function is not created in global scope but in a scope unique to that specific iteration. And in that scope `i` has the value `2`. – Felix Kling May 05 '21 at 13:43
  • 1
    I added a better duplicate target. – Felix Kling May 05 '21 at 13:45
  • @FelixKling Thank you. So because the loop is iterated 3 times, we have 3 different independent scopes and each scope has it's own `i` variable. But something I still don't understand: I suppose after the loop iteration is finished the loop scope is finished too so the corresponding `i` variable is lost. So when `printNumTwo()` is called how is it possible to return what is stored in the 'i` variable which doesn't exist now. I think there's something serious about scopes and storage that I'm not aware of! – Vahid Pouyafar May 05 '21 at 13:56
  • 1
    That's where "closures" come into play. Every function in JS is essentially a closure: It has a reference to scope/environment it was created in, and if it needs to resolve a variable that is not defined inside of it, it will look it up in that scope. You are right, those scopes are not "active" anymore but they still exist in memory somewhere. It's been a while but I create a post with lots of boxes and arrows, maybe it helps: https://stackoverflow.com/a/37493113/218196 – Felix Kling May 05 '21 at 14:06

0 Answers0