Compile Ready
Module 4 · Execution Context & Hoisting

Hoisting

Intermediate12m read12m practice24m total
HoistingvarFunction DeclarationsOutput Prediction

Introduction

Hoisting is the name for JavaScript's behavior of processing declarations before executing code. It makes some names available before their source line appears — but different declaration kinds behave very differently.

The most important correction: hoisting does not mean JavaScript physically moves your code. It means bindings are created during the memory phase.

Why This Matters

Hoisting is one of the highest-frequency JavaScript interview topics because it combines execution contexts, declaration types, TDZ, and function calls. A strong answer is precise: var is hoisted to undefined, function declarations are hoisted as callable functions, and let/const/class are hoisted but blocked by TDZ.

Theory

Hoisting by declaration kind

Source formWhat is hoisted?Early read/call result
var xBinding initialized to undefinedundefined.
function f() {}Binding initialized to function objectCallable.
let xBinding created but uninitializedReferenceError in TDZ.
const xBinding created but uninitializedReferenceError in TDZ.
class C {}Binding created but uninitializedReferenceError in TDZ.
var f = function () {}Only f binding initialized to undefinedCalling gives TypeError.
const f = () => {}f binding in TDZReading/calling gives ReferenceError.

Assignments do not hoist

console.log(x); var x = 5; does not become var x = 5; console.log(x);. The actual mental rewrite is closer to var x; console.log(x); x = 5;.

Function declarations vs expressions

A function declaration is callable before it appears because the memory phase creates the function object. A function expression is just a value produced during execution. The variable may be hoisted, but the value is not assigned until the execution phase reaches the assignment.

let and const are not unhoisted

If let were truly not hoisted, an inner let would not affect code before its declaration. But it does: it shadows the outer name from the beginning of the block and throws in the TDZ. That proves the binding exists early.

Practical advice

Do not rely on hoisting for readability. Put declarations near the top of the scope, prefer const, use function declarations intentionally, and avoid mixing var with modern lexical declarations.

Visual Diagrams

Hoisting is binding creation, not code movement
Original source
  console.log(x)
  var x = 5

Mental model
  Creation: x -> undefined
  Execution: console.log(x) -> undefined
             x = 5

Not true
  var x = 5 moved above console.log

Only the declaration binding is prepared early; the assignment stays in place.

Declaration behavior ladder
Most available before line

function declaration -> callable
var declaration      -> readable as undefined
let / const / class  -> binding exists but TDZ throws

Least available before line

Hoisting is not one behavior; it depends on the declaration kind.

Code Examples

Function declaration vs function expression

The declaration is callable early. The expression assigned to var is not.

Loading…

Hoisting does not hoist the assignment

The first read sees the creation-phase value, not the later assigned value.

Loading…

Classes have a temporal dead zone

Class declarations are hoisted as bindings, but they cannot be used before initialization.

Loading…

Playground

Loading editor…
Console

Press Run to execute the code and see output here.

Output Prediction

Predict the output #1

javascript
1console.log(item);
2var item = 'book';
3console.log(item);

Predict the output #2

javascript
1console.log(typeof getName);
2console.log(typeof getAge);
3
4function getName() {
5 return 'Ada';
6}
7
8var getAge = function () {
9 return 42;
10};

Predict the output #3

javascript
1foo();
2
3function foo() {
4 console.log('A');
5}
6
7foo = function () {
8 console.log('B');
9};
10
11foo();

Predict the output #4

javascript
1try {
2 console.log(total);
3} catch (error) {
4 console.log(error.name);
5}
6
7let total = 1;
8console.log(total);

Coding Exercises

Refactor a hoisting trap

Medium

Rewrite reportScore so it has no hoisting surprises. It should return 'missing' when the input is null or undefined; otherwise it should return 'score: X'. Use const/let and declare values before reading them.

Interview Questions

1What is hoisting in JavaScript?

Hoisting is the observable result of the creation phase of an execution context. Declarations are processed before statements execute. var bindings are initialized to undefined; function declarations are initialized to function objects; let, const, and class bindings are created but remain uninitialized in the temporal dead zone. Assignments are not hoisted.

Asked at:GoogleAmazonMicrosoftMeta

Follow-ups

  • Are let and const hoisted?
  • Why does a function expression assigned to var throw TypeError when called early?
2Is JavaScript moving declarations to the top of the file?

No. That is a teaching shortcut, not the real model. The engine creates bindings during the creation phase, then executes code in its original order. This distinction matters because assignments, function expressions, and lexical initializations still happen where they appear.

Asked at:NetflixApple

Quiz

1. What does `console.log(x); var x = 5;` print first?

2. What happens when you call a `var` function expression before assignment?

3. Which declaration has a TDZ?

Summary

  • Hoisting means declarations are processed during creation before execution begins.
  • `var` is hoisted with value `undefined`; function declarations are hoisted as callable function objects.
  • `let`, `const`, and `class` are hoisted but inaccessible during the temporal dead zone.
  • Assignments and function-expression values are not hoisted.

Cheat Sheet

Hoisting truth: bindings are prepared early; code is not physically moved.

var x -> early value undefined

function f() {} -> early callable function

let / const / class -> TDZ until declaration executes

var f = function () {} -> f is undefined until assignment

Avoid traps: declare before use; prefer const; explain creation phase, not code movement.