Hoisting in JavaScript with let and const

let & const declarations are hoisted. But they're hoisted differently when compared to var declaration.

console.log(a);

var a = 10;

Output

undefined

console.log(a);

let a = 10;

Output

Uncaught ReferenceError: Cannot access 'a' before initialization

Looking at the above example, one could say let & const are not hoisted. But that's not true.

Whenever a JS program is run a global execution context is created. Along with the GEC, a global object (window in case of browser) and a variable this is also created. Further, a lexical environment is also created.

Let and const are also allocated memory during the memory creation phase of the execution context. They're allocated the same placeholder undefined. But they're in a temporal dead zone i.e., JavaScript recognizes that they've been declared but it won't let you use them until they're declared. Hence the error in the above example.

Temporal dead zone: It is the time between when the let & const variables are assigned undefined during the memory creation phase of the execution context and when they're initialized in the code during the code execution phase of the execution context.

So if a let variable is not initialized during the entire code, it'll remain in the temporal dead zone throughout the code execution.

Variables of var type get attached to the global object when declared in the global space.

But let & const are not attached to the global object. They're stored in a separate space.

#var

var a = 10;

console.log(a);

console.log(this.a);

console.log(window.a);

Output

10

10

10

[In the global space this points to window]

#let or const

let a = 10;

console.log(a);

console.log(this.a);

console.log(window.a);

console.log(window.xyz);

Output

10

undefined

undefined

undefined

Another point of difference between var and let is that we cannot re-declare a let variable with the same name in the same scope.

#var

var a = 10;

var a = 20;

console.log(a);

Output

20

#let

let a = 10;

let a = 20;

console.log(a);

Output

Uncaught SyntaxError: Identifier 'a' has already been declared

const behaves exactly the same way as let in hoisitng. But it's stricter than let in the sense that you'll have to initilize a const variable in the same line where it is declared.

#let

let a;

a = 10;

console.(a);

Output

10

#const

const a;

a = 10;

console.(a);

Output

Uncaught SyntaxError: Missing initializer in const declaration

The right way:

const a = 10;

console.log(a);

Output

10

Another difference between let & const would be that let can be re-initialized while const cannot be re-initialized. I'm sure you knew this before!

Minimizing the temporal dead zone

The best way to minimize the temporal dead zone would be to declare and initilize all the variables to be used in the code to the top of the program. This would shrink the tdz to pretty much non-existence.