Redefining a let variable inside a for loop scope doesn't work?

Logan Smyth loganfsmyth at gmail.com
Fri Jul 15 02:14:53 UTC 2016


I think you may be misunderstanding that error. `for (let n of foo){ }`
does create an `n` value inside the loop. The issue isn't that `n` doesn't
exist inside the loop, it's that `n` has already been shadowed by the time
`n.a` is evaluated, meaning you're accessing `.a` of an uninitialized
binding.

In a little bit of a handwavy example, you could think of

```
let n = {a:[1,2,3]}
for (let n of n.a) {
  console.log(n);
}
```
expanding out kind of like this:

```
let n = {a:[1,2,3]};

let _iterable;
{
  _iterable = n.a;

  // Shadow 'n' so the line above here will always error out because 'n' is
uninitialized.
  let n;
}
for (var _value of _iterable) {
  let n = _value;

  console.log(n);
}
```

So the `let n;` shadows the outer `let n = {a: [1,2,3]};` when evaluating
`n.a`, resulting in a TDZ error.

You can see this behavior of the `for` head defined in
http://www.ecma-international.org/ecma-262/7.0/#sec-runtime-semantics-forin-div-ofheadevaluation-tdznames-expr-iterationkind,
where the usage of `let` in the head causes step 2 of loop head evaluation
to create a special new environment that specifically exists during the
execution of the `n.a` expression.


On Thu, Jul 14, 2016 at 1:36 PM, Blake Regalia <blake.regalia at gmail.com>
wrote:

> `let n of n.a` is inside the `function` scope, not the `for` scope (look
> at the brackets). This is invalid/terrible-practice because `n` is already
> defined, and you are trying to use `let` to declare a new variable even
> though it already exists in the same scope.
>
>
>  - Blake
>
> On Thu, Jul 14, 2016 at 1:26 PM, /#!/JoePea <joe at trusktr.io> wrote:
>
>> The following examples are very confusing, and throw an error that `n` is
>> undefined:
>>
>> ```js
>> function go(n){
>>   for (let n of n.a) {
>>     console.log(n);
>>   }
>> }
>>
>> go({a:[1,2,3]});
>> ```
>>
>> ```js
>> let n = {a:[1,2,3]}
>> for (let n of n.a) {
>>   console.log(n);
>> }
>> ```
>>
>> Why does the `let n` in the for loop not create a new variable inside the
>> for loop scope? This seems to go against the intuitive expectation of using
>> `let`, which is to make variable scoping more clear and less error-prone,
>> so it seems that one would expect the above examples to create a new
>> variable `n` inside the scope.
>>
>> Why is this not the case? Is it by design, and if so why?
>>
>>
>> */#!/*JoePea
>>
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>>
>
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20160714/acb80044/attachment-0001.html>


More information about the es-discuss mailing list