1

I've done some research online, half of the articles suggest let/const/class are NOT hoisted, while the other half claim they are hoisted but are not initialized and ReferenceError is thrown when we try to access them before initialization.

So here is my question. Is 'let' hoisted or not?

a. If yes, then explain this:

x = 1;
let x;
console.log(x);

Output: ReferenceError: x is not defined.

Argument: If 'let' is hoisted then shouldn't let x; move to the top and hence when initialization takes place it should get the value 1 and hence 1 should get printed? But nope, its error.

b. If not then explain this:

var x = 1;
function print() {
    console.log(x);
    let x = 2
    console.log(x);
}
print();

Output: ReferenceError: x is not defined.

Argument: If 'let' is not hoisted then output should've been

1
2

Please help!

Howard
  • 109
  • 1
  • 6
  • 1
    Yes, it's hoisted. – VLAZ Jul 03 '19 at 10:26
  • @VLAZ Could you please elaborate your statement? Explaining the two code snippets attached. – Howard Jul 03 '19 at 10:28
  • 2
    It's half-way between being hoisted and not hoisted. The existence of the variable in the scope is recognised throughout the entire scope, but you can't use it before the `let` statement. – Quentin Jul 03 '19 at 10:28
  • Probably a duplicate of [*What is the temporal dead zone?*](https://stackoverflow.com/questions/33198849/what-is-the-temporal-dead-zone) – RobG Jul 03 '19 at 10:28
  • 1
    OK, you seem to be confused on what hoisting does. It doesn't magically change the order of the code but changes the *steps* taken when creating variables. There are three steps - *declare* the binding, so it's addressable, e.g., using `foo` will now resolve that binding. *initialisation* is making the binding usable. If a binding is declared but not initialised, it's unusable - that leads to the temporal dead zone. Final step is *assignment* - giving the binding a value. Hoisting for `let` will only move the declaration, not the initialisation. – VLAZ Jul 03 '19 at 10:29
  • Also your output are not correct. Real error: #1 - Uncaught ReferenceError: Cannot access 'x' before initialization #2 - Uncaught SyntaxError: Identifier 'x' has already been declared – Mosè Raguzzini Jul 03 '19 at 10:30
  • 1
    [Are variables declared with let or const not hoisted in ES6?](https://stackoverflow.com/questions/31219420) – adiga Jul 03 '19 at 10:32
  • I thought because of hoisting the declaration moves to the top and hence imagined the code snippet #1 would turn into this: `let x; x = 1; console.log(x)` And hence I thought it should've worked. But I realize it now, that it doesn't move it to the top. Its just a conceptual definition. In fact, declarations are put in memory first. That solves it, I guess. Thanks all! – Howard Jul 03 '19 at 10:57
  • @Howard yeah, that explanation used to work with `var`, since both the declaration and initialisation were hoisted in that case. But that is not the case with `let`/`const`. Actually, it was still inconsistent before, since `function` declarations would have the entire thing hoisted to top. A `var foo = 1` would just resolve to `undefined` if accessed before that line, while `function bar() {}` doesn't and resolves as the actual function. – VLAZ Jul 03 '19 at 12:31

0 Answers0