Quiz

What are the potential issues caused by hoisting?

Topics
JavaScript

TL;DR

JavaScript creates bindings before executing a scope's statements, but initializes different declaration forms differently. An early read of var produces undefined; an early read of let, const, or class throws because the binding is in the temporal dead zone; and function declarations are already callable. These differences—not literal source-code movement—can produce confusing bugs.

console.log(a); // undefined
var a = 5;
console.log(b); // ReferenceError: Cannot access 'b' before initialization
let b = 10;

Potential issues caused by hoisting

Variables being undefined

When using var, the binding is created and initialized to undefined during scope setup. It retains that value until the assignment executes.

console.log(a); // undefined
var a = 5;

Temporal dead zone with let and const

Variables declared with let and const are also hoisted, but they are not initialized. Accessing them before their declaration results in a ReferenceError due to the temporal dead zone.

console.log(b); // ReferenceError: Cannot access 'b' before initialization
let b = 10;

Function declarations vs. function expressions

Function declarations are initialized with their function during scope setup. A function expression is created only when its expression runs, so a var that will later receive a function still contains undefined beforehand and calling it throws TypeError.

foo(); // Works fine
function foo() {
console.log('Hello');
}
bar(); // TypeError: bar is not a function
var bar = function () {
console.log('Hello');
};

Redeclaration issues with var

Using var can lead to unintentional redeclarations, which can cause bugs that are hard to track down.

var x = 1;
if (true) {
var x = 2; // Same variable as above
}
console.log(x); // 2

Further reading

Exercises

Check your understanding
Beta
Check your understanding Exercise
Check your understanding Exercise

What happens when this script runs?

console.log(total);
console.log(status);
var total = 4;
let status = 'ready';