3

Why const is not defined in global scope but defined in local? screenshoot from devTools

{
    console.log(b);
    const b = 2;
}
VM366:2 Uncaught ReferenceError: Cannot access 'b' before initialization
    at <anonymous>:2:17

console.log(a);
const a = 1;
VM382:1 Uncaught ReferenceError: a is not defined
    at <anonymous>:1:13

  • Your const is scoped to the block it's in `{ // this is inside a block}` Check https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const – James Jul 05 '22 at 17:48
  • 1
    That's not what this is about. The question is why is the error "is not defined" in the second case and not the first - in the first case, the error indicates that `b` is already "known" at this point but can't yet be accessed due to temporal dead zone, while the in the second case the error looks as if `a` was unheard of at that point. – CherryDT Jul 05 '22 at 17:50
  • By the way, `a = 0; const a = 1` does create an error "Assignment to constant variable."! – CherryDT Jul 05 '22 at 17:52
  • Try to understand the differences between const, var and let. if you understand function scope and block scope you will also be able to understand why you are getting this error. https://www.freecodecamp.org/news/var-let-and-const-whats-the-difference/ – Nexo Jul 05 '22 at 17:53
  • @Nikkkshit This is not what this is about. Function/block scope doesn't explain why in DevTools (only there by the way - try node.js REPL, a node.js file, `(0, eval)(...)` etc., and it doesn't happen) you get `is not defined` instead of `cannot access before initialization` in this case. – CherryDT Jul 05 '22 at 17:56
  • 1
    I think it is something weird DevTools is doing in particular, to be honest. – CherryDT Jul 05 '22 at 18:06

2 Answers2

1

This seems to be related to some "magic" in how REPL input is handled. It's not really a property of how JavaScript normally works.

If you try this in a node.js file, in a <script>, or even in an (0, eval)('...'), you'll get "Cannot access 'a' before initialization" as expected. Note that even in the DevTools console this won't happen if you are in a paused debugger state.

In a non-paused state (only there), the DevTools allow you to declare variables as if you were continuously writing a script, and the declarations will persist across commands. There is clearly "magic" outside of regular JavaScript involved, because even eval would create another temporary scope. That "magic" is handled by V8 itself. It is therefore pretty likely that whatever trickery is used here has the side effect of this slightly unexpected error. (I initially thought the side effect is that the variable declaration isn't hoisted, but if you do a = 0; const a = 1 then you get "Assignment to constant variable", so that doesn't seem to be the case.)

I tried to trace this to the source, but I got lost in the depths of V8. Nonetheless, I discovered (by opening another DevTools to debug the DevTools themselves!) that this only happens if the replMode argument (that gets passed to the V8 backend's evaluate method) is true. This can be verified by setting a breakpoint here and changing the value of options.replMode.

replMode is documented as follows:

Setting this flag to true enables let re-declaration and top-level await. Note that let variables can only be re-declared if they originate from replMode themselves.

CherryDT
  • 25,571
  • 5
  • 49
  • 74
0
  • Hoisting workd differently for const and let than var.
  • SO for const and let, which are block scoped gives ReferenceError error as they do not initialize value as undefined. -Whereas, for var it will initialize value as undefinded if you do not assign any v alue and var is function scoped. -You can see console from devToolis giving different error, whereasconsolefromstackoverflow``` giving error as our expectation that

"Uncaught ReferenceError: Cannot access 'a' before initialization. So I believe it's how devtool console treating the error for block-scope and global-scope. -Check it on ```morzila-devtool`.

{
  console.log("before initialization:" + b);
  var b = 2;
  console.log("after initialization:" + b);
}
console.log("before initialization:" + a);
const a = 1;
  • This is from Firefox browser Firefox browser console

  • This is from Microsoft Edge from edge from edge

  • I came to know from this post that, Chrome and IE both have a global event object. So when we are trying to access it first hoisting won't work for const and let. so it's says that we cannot access but window object has access to those variables, So I assume it's throwing error for a is not defined for window object, which is global object.

  • window object sets automatically to undefind. const window.variable = undefined (when not defined); Try to run this code:

{console.log(b); var b=1; console.log(window.c); const c=1;}
OUTPUT:
1 debugger eval code:1:9
undefined // window.c = undefined

And as window object has access to global scope it gives error for a or b or variable is not defined when we access it in global scope before initialisation using let or const.

Nexo
  • 2,125
  • 2
  • 10
  • 20