3

In Documentaion said that let and const are hoisted.

Variables declared with let and const are also hoisted but, unlike var, are not initialized with a default value. An exception will be thrown if a variable declared with let or const is read before it is initialized.

Also there are a pretty clear sample there:

 console.log(num); // Throws ReferenceError exception as the variable value is uninitialized
 let num = 6; // Initialization

But I don't understand why this rise the ReferenceError also:

x = 9

console.log(x) // Why: "Throws ReferenceError exception as the variable value is uninitialized" here ?

let x;

Specs says 'let' supports hoising. Initialization is going before using this variable. What's wrong? If the reason of the ReferenceError is TDZ then why in specs says that 'let' supports hoising, becouse of TDZ and hoising are mutually exclusive things... And what could be an example of hoising for 'let' if I can't use this varibable before declaration...

Barmar
  • 741,623
  • 53
  • 500
  • 612
nzim
  • 105
  • 2
  • 9
  • *"becouse of TDZ and hoising are mutually exclusive things"* No. TDZ only works *because of* hoisting. If the variable wasn't hoisted then the engine couldn't mark it as "uninitialized". Also it's not the `console.log(x)` call that causes the error but the assignment `x = 9`. – Felix Kling Jul 10 '22 at 21:04
  • 2
    Hoisting basically means that the variable is "visible" from the beginning of the scope and not from the point where it was declared. If hoisting didn't exist then we could do this: `let x = 42; { /*new scope*/ console.log(x); /*42*/ x = 21; let x = 1234; console.log(x)/*1234*/} console.log(x); /*21*/`. But hoisting does exist and so `console.log(x); x =21;` throws an error because `x` refers to the uninitialized variable `x`, which is declared/initialized afterwards. – Felix Kling Jul 10 '22 at 21:10

1 Answers1

4

Why throws ReferenceError exception as the variable value is uninitialized here, in the console.log line?

It doesn't. It throws it on access of the variable, which includes assignment:

x = 9; // exception happens here already!
let x;

You cannot use an uninitialised variable at all. It only gets initialised when the let/const statement itself is evaluated.

What could be an example of hoisting for 'let' if I can't use this variable before declaration?

You cannot use it, but you can refer to it, e.g. by creating a closure over it:

function log() {
    console.log(x);
}
// log(); - would fail here
let x = 9;
log();

Also it means that referring to x will actually refer to that uninitialised variable, not some other x from an outer scope. See Are variables declared with let or const hoisted? for more.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • `x = 9; console.log(x);` works, which looks like using an uninitialized variable. Probably x = 9 initializes it. So the answer is really, that javascript is crazy. In any real (edit: scratch out real, insert other) language none of this would work :) – topsail Jul 10 '22 at 21:10
  • 2
    @topsail: In non-strict mode assigning to an undeclared variable will create a global variable (more precisely: a property on the global object) – Felix Kling Jul 10 '22 at 21:12
  • @topsail `x = 9` without a declaration fails with an exception in [strict mode](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode). – Bergi Jul 10 '22 at 21:12
  • who said anything about strict mode? – topsail Jul 10 '22 at 21:14
  • 1
    @topsail You said "real language" :-P JavaScript isn't crazy, it's just backwards-compatible. Strict mode is the new default. – Bergi Jul 10 '22 at 21:14