In ES6, do for loops with a let/const initializer create a separate scope?

Allen Wirfs-Brock allen at
Fri Jun 13 09:23:21 PDT 2014

On Jun 12, 2014, at 12:50 PM, Michael Zhou wrote:

> In other words, is
> for (let i = 0; i < 10; i++) {
>  let i;
> }
> legal? I feel it is, but I'm not sure if the specs has made that clear. Thanks!

The above is legal according to the current ES6 spec. draft.  The let in the loop  body block shadows the per iteration binding of i.

You can think of the body of a 'let i' for loops as desugaring into something like:

let $$lastIteration_i = <initialization expression for i>;
   let i = $$lastIteration_i;   //create and initialize per iteration i
   <test expression>;
   <loop body statement>
   <increment expression>;
   $$lastIteration_i = i;

For you sample, this expands to:

let $$lastIteration_i = 0;
   let i = $$lastIteration_i;   //create and initialize per iteration i
   if (!(i<10)) break;
      let i;
   $$lastIteration_i = i;

So you can see that the let i in the block simply shadows the per iteration i.

The spec. doesn't say anything explicit about this case. It just falls out of the specified evaluation semantics of for loops.

We could consider special cases loop bodies that are BlockStatements and statically reject those that contain declaration that shadow the loop declarations.  However, I think it is probably best to leave that sort of check for linters to perform. 


More information about the es-discuss mailing list