Why does something sometimes work "before" you declare it?
Maybe it's happened to you: you call a function on line 2 even though you wrote it on line 20... and it works. It's not magic, it's hoisting.
Hoisting is the behavior by which JavaScript reads your code and, before running it, "moves up" the declarations to the top of their scope. Like tidying the kitchen before you start cooking.
Declared functions: hoisted completely
That's why you can call a function before writing it, with nothing breaking:
greet(); // ✅ works
function greet() {
console.log("Hello!");
}
Variables with let and const: the "temporal dead zone"
Variables aren't so friendly. let and const are hoisted too, but JavaScript
leaves them "reserved but locked": you can't use them before the line where
you declare them. If you try, you get an error:
// console.log(x); // ❌ ReferenceError
let x = 5;
That "forbidden" stretch (from the top of the scope down to its declaration) is called the Temporal Dead Zone. Deep down it's a good thing: it warns you about a mistake instead of carrying on with a weird value.
⚠️ Classic trap: var lies to you with an undefined
With var things go sideways. Using the variable before assigning it does not
throw: it returns undefined. And a silent undefined is exactly the kind of bug
that takes you an hour to track down. That's another reason to stick with let
and const: you'd rather have a clear error than a sneaky undefined.
Examples
We call add before defining it and still get 5: hoisting in action
console.log(add(2, 3)); // 5, even though the definition is below
function add(a, b) {
return a + b;
}