← All concepts
Behind the Scenes

Hoisting

JavaScript sets up all your declarations before it runs a single line of your code.

Loading visual…

Definition

Before executing a scope, the JavaScript engine scans it and registers every `var` and `function` declaration in advance. Function declarations are hoisted whole, so they can be called before the line where they appear in the source. `var` declarations are hoisted too, but only the declaration, not the assignment, so the variable exists from the top of the scope and reads as `undefined` until its assignment line actually runs. `let` and `const` are also registered ahead of time, but they are not usable until their declaration line executes. The span between the start of the scope and that line is called the temporal dead zone, and touching the variable there throws a `ReferenceError` instead of returning `undefined`. This is why `let`/`const` are described as block-scoped and stricter about ordering, while `var` and function declarations feel like they float upward.

Examples

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

greet(); // works
function greet() { console.log("hi"); }

console.log(b); // ReferenceError
let b = 2;

var is hoisted and initialized to undefined, function declarations are hoisted whole, but let stays in the temporal dead zone until its line runs.

function useHoisted(n) {
  return sq(n);
  function sq(x) { return x * x; }
}
useHoisted(4); // 16

The call to sq happens before its definition in the source, but the hoisted function declaration is already in place when useHoisted starts running.

Where you see this

Practice this

Further reading