Contents

Frontend Development › JavaScript & TypeScript

Hoisting

Declarations behaving as if moved to the top of their scope.

Also known as: variable hoisting, function hoisting, temporal dead zone

Hoisting is JavaScript’s behavior of processing declarations before running the code, as if they were moved to the top of their scope. What’s hoisted depends on how you declare it.

console.log(a);     // undefined, not an error
var a = 5;

greet();            // "hi": works before its definition
function greet() { console.log("hi"); }

What happens for each kind

DeclarationBefore its line runs
varexists, with value undefined
function declarationfully usable (name and body)
let, constexists, but can’t be accessed: a ReferenceError. This period is the temporal dead zone
classsame as let: can’t be used before the declaration
function expression (const f = () => {})follows the variable’s rules
console.log(b);     // ReferenceError: Cannot access 'b' before initialization
let b = 5;

hello();            // TypeError: hello is not a function (var is undefined at that point)
var hello = function () {};

Only the declaration is hoisted, not the assignment. That’s why var a is undefined, not 5.

Classic mistakes

for (var i = 0; i < 3; i++) setTimeout(() => console.log(i));   // 3 3 3: var is function-scoped, one shared i
for (let i = 0; i < 3; i++) setTimeout(() => console.log(i));   // 0 1 2

Practical advice

  • Use const and let, not var. The dead zone turns use-before-declaration into a loud error instead of a silent undefined.
  • Declare variables at the top of the scope where you use them.
  • Function declarations may be called before they appear, which some people use to put main code first. Use it knowingly.
  • Hoisting is per scope. let and const are block-scoped, var is function-scoped (scope).
  • Linters flag most hoisting surprises. See also var, let and const.