1

Say I have the following code:

[ { x: 1 }, { x: 2 }, { x: 3 } ]
> for (let { x } of a) console.log(x)
1
2
3

which makes sense. But what if I did:

> a = (x) => [{"x": x + 1}, {"x": x + 2}, {"x": x + 3}]
> x = 0
0
> for (let { x } of a(x)) console.log(x)
ReferenceError: x is not defined
> x
0

Why I got a ReferenceError? a(x) shouldn't be in the let's scope so x should be propagating upwards.


I know that the problem is coming from let, not for...of.

> x = 1
1
> f = x => x + 1;
[Function: f]
> let x = f(x)
ReferenceError: x is not defined

If the scope of let in the example above is global, then I shouldn't be getting a ReferenceError!

Atonal
  • 520
  • 4
  • 14
  • 2
    `let` is block scoped, so the `x` in `a(x)` is (I think) in the [temporal dead zone](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let#Temporal_dead_zone) - the `let x` "masks" the `x` from the outer scope, and then `x` is not initialised before use at `a(x)` – Jaromanda X Apr 02 '19 at 21:21
  • 2
    Do you understand why it throws in your second snippet, and are asking specifically about the [`let` in a `for … of` loop](https://stackoverflow.com/a/30900289/1048572)? Or are you confused about [`let` scope in general](https://stackoverflow.com/q/31219420/1048572)? – Bergi Apr 02 '19 at 21:26
  • 1
    @FelixKling Why `a(x)` is evaluated within the same scope as `let`? If you have an assignment, wouldn't the thing to which you'll be assigning needs to be evaluated first?! --- In Lisp for example `(define x 2)` and then `(let ([x x]) (+ x 1))` would make `x` to be `3` within the `let` block. I'm expecting this behavior. – Atonal Apr 02 '19 at 21:28
  • @Bergi I'm confused about let scope in general. I'll read the links nevertheless the question in my above comment still remains. – Atonal Apr 02 '19 at 21:29
  • 1
    @Atonal You'll want to check the second link again then, also [this question about the TDZ](https://stackoverflow.com/questions/33198849/what-is-the-temporal-dead-zone). `let` doesn't introduce the variable only when it is evaluated. It's not working like in Ocaml or Lisp. – Bergi Apr 02 '19 at 21:33
  • 1
    @Bergi I get what you're saying and according the semantics of `let` in these links, I understand my mistake. Nevertheless I'm asking why the semantics of `let` is this way in the first place, and why wouldn't you want to make it look like a lisp `let`? – Atonal Apr 02 '19 at 21:36
  • 1
    @Atonal [Hoisting allows mutually dependent declarations](https://stackoverflow.com/a/52880419/1048572). It's more like Haskell, but without the lazy evaluation :-) – Bergi Apr 02 '19 at 21:37
  • 1
    @Bergi Yes! Thanks! If you want to add a new answer, I'll accept it. Otherwise I'll just accept the duplicate flag. – Atonal Apr 02 '19 at 21:38
  • The short answer is: the designers of JavaScript had very different design goals in mind when creating the language than the the designers of Lisp. – p.s.w.g Apr 02 '19 at 21:39

0 Answers0