1

When let is used in the initialiser expression of a traditional for loop, it is scoped to the block of the for loop.

The spec says:

let and const declarations define variables that are scoped to the running execution context's LexicalEnvironment.

Does that mean that the point of declaration of i is (and even in ES5 was(?)) lexically (semantically I know using var it would be hoisted) inside the block comprising the body of the for loop (because naively it looks like it is outside it).

Or does it mean that this is a new feature of let and/or the for loop to give it the semantics of being lexically inside the loop body?

To be clear: I know that the visibility semantics are new (i.e. block scoping for let vs function scooping for var). I am interested in whether the lexical position of definition has always been taken to be inside the body of the loop.

for(let i = 0; i < 10; i++) {
  // the body of the loop....
}
Ben Aston
  • 49,455
  • 61
  • 188
  • 322
  • "*Does that mean that the point of declaration of `i` is lexically inside the block comprising the body of the for loop?*" - No, what makes you think that? – Bergi Jun 20 '17 at 16:14
  • 1
    Related: [The semantics of `let` and block scoping with for loops](https://stackoverflow.com/q/30899612/1048572) – Bergi Jun 20 '17 at 16:16
  • Shouldn't this post be tagged with [tag:language-lawyer]? – Dragomok Jun 20 '17 at 16:17
  • @Bergi I know this is basic stuff, but I just assumed I understood how it worked. Then I thought about it... Computers are hard – Ben Aston Jun 20 '17 at 16:20
  • @Bergi - intuitively it seemed that the semantic difference for `let` and `var` in a for loop was *more* than just the hoisting aspect. I was grasping at what that additional difference was. I think your linked answer tells me... – Ben Aston Jun 20 '17 at 16:28
  • @Ben I think the designers had the elimination of the [closures-within-for-loop problem](https://stackoverflow.com/q/750486/6445533) in mind, amongst other things. –  Jun 20 '17 at 16:37
  • That prompted the question! – Ben Aston Jun 20 '17 at 16:49

1 Answers1

2

Actually, think of it like an imaginary wrapper block with all the for-declared variables aliased within it. Kind of like this:

// Original
for (let i = 0; i < 10; i++) { ... }

// Equivalent
{
    let _i;
    for (_i = 0; _i < 10; _i++) {
        let i = _i;
        ...
        _i = i;
    }
}

It works by creating a new scope within the for to alias the variables, and then effectively updating the aliases at the end of each block.

(Of course, engines implement it differently than this, but that's when you get into compiler theory and the difference between observable semantics and actual implementation.)

Isiah Meadows
  • 1,353
  • 14
  • 27