Javascript - Variable hoisting var vs let

Introduction

Consider the following example to understand how hoisting affects the variables declared using the keyword var:

console.log(nbr);  // undefined 
var nbr = 42; 

The above example prints undefined because of hoisting.

When we declare the variable nbr using var, due to hoisting it becomes equivalent to declaring the variable at the start of the scope with its value set to undefined.

If you moved the console.log statement after the declaration, it would print the number 42, due to the fact that entering the scope of the variable declared using var.

When the execution reaches the declaration, this variable is then set to the specified value in the assignment statement.

Let's take a look at a similar example using let:

console.log(nbr); // Reference Error: nbr is not defined 
let nbr = 42; 

This would give you a Reference Error: nbr is not defined since no hoisting takes place here.

This Reference Error is technically called a Temporal Dead Zone (TDZ) error because you are accessing a variable that's been declared but not yet initialized.

let and const declare variables with a temporal dead zone (TDZ), in contrast to the hoisting that happens when you use var.

The variable in the Temporal Dead Zone is not yet initialized with any value.

let data = true; 

if (true) { // enter new scope, TDZ starts 
    // Uninitialized binding for "data" is created 
    console.log(data); // ReferenceError 
    let data; // TDZ ends, "data" is initialized with "undefined" 
} 
console.log(data); // true 

TDZs helps us ensure that a variable in runtime always has the correct value.

if (true) { 
    console.log(typeof anUndeclaredVariable); // 'undefined' 
    console.log(typeof random); // ReferenceError (TDZ) 

    let random; 
} 

Here, even if you try to access a variable in the temporal dead zone using typeof, you will get an exception.