2

I am trying out the code snippets below -

1)

console.log(a);
let a = 5;

I get - Uncaught ReferenceError: a is not defined at :1:13

2)

a = 10;
let a = 5;

I get - Uncaught ReferenceError: Cannot access 'a' before initialization at :1:3

If I try out the same snippets inside a function -

3)

function someName() {
    console.log(a);
    let a = 5;    
}
someName()

I get - Uncaught ReferenceError: Cannot access 'a' before initialization at someName (:2:17) at :1:1

4)

function someName() {
        a = 10;
        let a = 5;    
}
someName()

I get - Uncaught ReferenceError: Cannot access 'a' before initialization at someName (:2:11) at :5:5

Why is there a difference in the error messages for 1) and 2) but not 3) and 4). Is 'let' hoisting different for global and local scopes?

Aditi Garg
  • 320
  • 2
  • 9
  • 2
    Are you trying this in the console? Because only then does the behaviour make sense. In the console, the code would be executed line by line, so it's trying to do `console.log(a)` and it's undefined. It hasn't processed `let a` yet. In a function, the statements would already be parsed before executing it. If you try it in a proper JS file, it should be equivalent, as the script is parsed and declarations hoisted before the execution starts. – VLAZ Mar 17 '21 at 12:03
  • 2
    Yes, but if that is the case, shouldn't - console.log(a); var a = 5; throw the same error? – Aditi Garg Mar 17 '21 at 12:05
  • @VLAZ - Also, shouldn't - a = 10; let a = 5; VM9983:1 Uncaught ReferenceError: Cannot access 'a' before initialization at :1:3 Not throw an error, and just initialize a as a global variable? Seems like there is some compilation of the entire code, before a line-by-line execution. – Aditi Garg Mar 17 '21 at 12:10
  • @AditiGarg where are you executing this? I tried code 1) in FF and Chrome and both give me (essentially) the same error "ReferenceError: can't access lexical declaration 'a' before initialization" (FF) and "ReferenceError: Cannot access 'a' before initialization" (Chrome). – VLAZ Mar 17 '21 at 12:15
  • @VLAZ - Executing it in chrome Version 80.0.3987.132 for MacOS. – Aditi Garg Mar 17 '21 at 12:17
  • `a = 10; let a = 5;` - why do you think that this should not throw an error and initialize `a` as a global variable? Because of Temporal Dead Zone, you _cannot_ access an identifier declared with either `let` or `const` _until_ its declaration has executed during step-by-step execution of the code. – Yousaf Mar 17 '21 at 12:19
  • @Yousaf - As per VLAZ's first comment - In the console, the code would be executed line by line, so it's trying to do console.log(a) and it's undefined. Similarly, when a = 10; is executed, the console is unaware of the next line. So 'a' should just be initialized as a global variable and assigned the value 10. – Aditi Garg Mar 17 '21 at 12:23
  • 1
    As I said, I tested 1) and it gives the correct error in both FF and Chrome. Seems like the console execution has been improved since the last time I looked into it. So, I'm not really sure why you're getting that. My version of Chrome was actually older (v75), I'm updating to see how it works with a more recent one. But the only explanation for the first result is that it's executed line by line *and* you have strict mode on. I cannot find an environment that does that, though. – VLAZ Mar 17 '21 at 12:30
  • @VLAZ - true. Looks like it's a console peculiarity. I tried the same code in a js file, and got the expected result. Thank you. – Aditi Garg Mar 17 '21 at 12:32
  • I just tested `console.log(a); var a = 5;` and `a = 10; let a = 5;` in the chrome (Version 89.0.4389.90) console and results can only be explained if there's some compilation/parsing step involved, – Yousaf Mar 17 '21 at 12:33
  • `console.log(a); let a = 5;` does actually throw "*ReferenceError: a is not defined*" in Chrome v89. So, at least as far back as v75 it worked "correctly". However, I wouldn't really trust the console to show "correct" behaviours. There are all sorts of tricky things that can happen. The Chrome console in particular "cheats" by modifying how the code gets executed *in some circumstances* (e.g., try `{a: 1}` vs `{a: 1};`). FF is a bit better as it doesn't inject magic but I'd still not draw any hard conclusions from code executed there. – VLAZ Mar 17 '21 at 12:36
  • See [Why is {} + {} no longer NaN in Chrome console?](https://stackoverflow.com/q/36438034) for an example of "magic" that the Chrome console does. – VLAZ Mar 17 '21 at 12:38

0 Answers0