Call stack & phases
You already know an execution context is the “box” where bindings live and code runs. This page shows how the engine builds that box in two stages, what happens when you call a function, and how the call stack keeps the order straight when contexts nest.
What happens when a script runs
As soon as the runtime begins executing a file or <script> body, it creates a global
execution context (GEC). Conceptually it still has the same two parts as everywhere
else: a memory (variable environment) for names and values, and code that runs
one line at a time.
Nothing in your source executes until those setup rules have run.
Phase 1: memory creation
First comes the memory creation phase (sometimes described as hoisting for var and
function declarations). The engine walks the program and declares bindings:
- For
varidentifiers it reserves a slot and sets the value toundefineduntil an assignment runs later. - For
functiondeclarations it stores a reference to the callable — the body is known up front, so the name resolves immediately.
For a dedicated look at var vs function vs function expressions, how that feels at
runtime, and the difference between undefined and not defined, see
Hoisting.
let and const follow different rules (temporal dead zone); this lesson sticks to
var + function so the “placeholder then assign” story matches the classic model.
Global execution context — phases
Memory creation phase: the engine registers every var and function declaration. Variables start as undefined; the function’s full callable is stored under its name.
Phase 2: code execution
In the code execution phase the engine runs top to bottom. Assignments replace
undefined with real values. A function declaration line does not do extra work at
this point — the binding was already created in phase 1.
When the line var square2 = square(n) runs, the call on the right-hand side
executes before the global binding for square2 can receive a value.
Function invocation
Each time you use () after a function, that invocation gets a new execution
context. The parameter (for example num) is a local binding; the argument
(n, or the literal 4) is the value provided at the call site.
Local execution context — square(n)
A function invocation gets its own execution context. In the local creation phase, parameters and inner var bindings exist before the body runs — both start as undefined here.
return and teardown
The return expression hands a value back to wherever the call was evaluated and ends
that invocation’s execution context. The local environment for that call goes away;
only values that were returned (or written to outer scopes you still have access to)
remain visible afterwards.
The call stack
When many contexts are active, the engine tracks them with a stack: the global context is at the bottom, and each nested call pushes a frame on top. When a function returns, its frame is popped, and control resumes in the caller.
That same structure is what people mean when they say execution context stack, program stack, or runtime stack — one idea, several names.
Call stack — push and pop
When a script starts, a global execution context is created and pushed onto the call stack — it stays until the file finishes running.
Recap
- The GEC is created in two phases: memory creation (bindings +
undefined/ function refs), then code execution (assignments and calls in order). - Each function call allocates a new context with its own locals and parameters.
returnpasses a value outward and discards that invocation’s context.- The call stack is how the engine orders nested contexts (push on call, pop on return).
✦Before: Execution context — the container model.
Next: Hoisting —var/functiondeclarations, undefined vs not defined, and function expressions.