0

Can the user observe the hoisting of identifiers declared with let (or const)?

I ask because referring to the identifier before the lexical declaration will always result in a ReferenceError as though it had not been hoisted.

Assume strict mode:

{ a; console.log(a); let a; } // ReferenceError: Cannot access 'a' before initialization
{ a; console.log(a); let b; } // ReferenceError: a is not defined

Is the different textual error description the only meaningful way to observe the hoisting in userland?

Ben Aston
  • 53,718
  • 65
  • 205
  • 331
  • 3
    Some good background in this article. `let` and `const` are hoisted, meaning the context is aware of them, but they aren't initialized until their lexical binding: https://blog.bitsrc.io/hoisting-in-modern-javascript-let-const-and-var-b290405adfda The writer of this article refers to it as the "Temporal Dead Zone" (I think I may have heard that phrase in Star Trek a few times lol). – jwatts1980 Jan 20 '20 at 00:11
  • 1
    Btw, I'd rather have seen [your answer on that "hoisting" question](https://stackoverflow.com/a/59815248/1048572) to be edited than to be deleted, as for other than the small inaccuracy I commented on it was quite good. – Bergi Jan 20 '20 at 00:21
  • 1
    Does this answer your question? [Are variables declared with let or const not hoisted in ES6?](https://stackoverflow.com/questions/31219420/are-variables-declared-with-let-or-const-not-hoisted-in-es6) – vgru Jan 20 '20 at 00:32

3 Answers3

2

The main use case of the hoisting is for function declarations referring to the variable above its declaration - and have the identifier still always refer to the same local variable. (Of course, the temporal dead zone is still in place, so you can't call the function until after the variable has been initialised):

function log() {
  console.log(x);
}
try { log(); } catch(e) {} // not a global variable reference
let x = "example";
log();
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • So `let` and `const` are hoisted to ensure identifier resolution is simplified? Without being hoisted you could have much more subtle code that could lend itself to errors. – Ben Aston Jan 20 '20 at 00:38
  • 2
    Not quite sure I follow your answer this time. Are you saying that `log` can access `x` because its hoisted? Because that's not actually the case. It can access it because it's defined in the same scope. It doesn't matter whether it's hoisted or not as long as it exists at the moment of the function call. If you replace `let x = "example";` with `eval('var x = "example";`)` it works as well. – Felix Kling Jan 20 '20 at 01:15
  • 1
    @Ben Yes, having identifiers always resolved the same in the same scope was the original intention behind introducing the scoping behaviour that came to be known as "hoisting". – Bergi Jan 20 '20 at 01:19
  • @FelixKling Thanks, you make an excellent point! However, I think the intention behind hoisting of `let` was that the `x` inside `log` resolves to the local variable right from the beginning, not changing the resolution of variables when the declaration is evaluated. (The example Ben cited in his answer demonstrates that better admittedly). And then, yeah, there's `eval` which does weird things to scopes - in sloppy mode only though… – Bergi Jan 20 '20 at 01:23
  • @Bergi: Ah, yes, I get that point. Trying to `eval` `let` doesn't actually work anyway. – Felix Kling Jan 20 '20 at 01:26
1

No, let and const does hoist like var. The only difference is let and const initialized with no value and you cannot use any variable which is not initialized yet (That's why you are getting this error "Cannot access 'a' before initialization") ; When you declare using var it gets initialized with undefined;

0

Yes.

x = "global";
// function scope:
(function() {
    x; // not "global"

    let x;
}());
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
Ben Aston
  • 53,718
  • 65
  • 205
  • 331
  • This seems to be a dupe of the [thread you linked to](https://stackoverflow.com/a/31222689/38522), and you answered it yourself by placing a link to an existing answer (answered by @Bergi who also answered this question a bit earlier). Wouldn't it make more sense to close it as a dupe then? – vgru Jan 20 '20 at 00:30
  • Not a dupe. A different question that can leverage part of the linked-to answer. – Ben Aston Jan 20 '20 at 00:36