Execution Context & Hoisting
The problem
Before a single line of JavaScript runs, the engine needs to know what variables and functions exist in the current scope — without a setup phase, forward references (calling a function defined later in the file) would be impossible and scoping rules would be unpredictable.
Why now
Functions and scope already established what scope is, but treated it as if bindings simply appear the instant a line executes. JavaScript's actual behavior is more specific: it scans a scope for declarations before running any code in it, which is why some patterns work that a naive line-by-line model wouldn't predict.
Mental model
Before executing a function or script, the engine does a quick pass to register every var and function declaration in that scope — that pre-pass is 'hoisting.' Function declarations are hoisted with their full body attached (callable before their line); var is hoisted but left undefined until its assignment line actually runs; let and const are hoisted too, but sit in an inaccessible 'temporal dead zone' until their own line executes.
Requires
- Functions & ScopeProgramming Fundamentals
Execution context is the concrete runtime mechanism behind the abstract 'scope' concept already introduced; hoisting is a specific, precise refinement of when bindings within that scope actually become available.
Unlocks
Used in
- Explaining why a function can be called before its declaration appears in the file, but a const cannot
- The infamous 'undefined is not a function' bugs caused by var hoisting without its assignment
- Understanding linter rules that disallow var in favor of let/const specifically to avoid hoisting confusion
- Module-level code execution order in bundlers and build tools
Projects
- Write code that calls a function before its declaration (works) and one that reads a const before its declaration (throws), and explain the difference in terms of hoisting
- Predict, then verify, the output of a small quiz mixing var, let, and function declarations accessed before their line
Examples
- greet(); function greet() { console.log('hi'); } works because function declarations hoist with their full body
- console.log(x); let x = 5; throws a ReferenceError — x is hoisted but stuck in the temporal dead zone until its line runs
Resources
- MDN — Hoistingarticle
Mastery checklist
- I can explain what hoisting is and why it exists
- I can predict whether a given piece of code throws or runs based on var/let/const hoisting rules
- I can explain the temporal dead zone for let and const
- I can explain why relying on hoisting is considered poor practice despite being legal