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 var identifiers it reserves a slot and sets the value to undefined until an assignment runs later.
  • For function declarations 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

Step 1 / 7
Global memorynundefinedsquarefunction square { … }square2undefinedsquare4undefinedCode (global)var n = 2function square(num) { … }var square2 = square(n)var square4 = square(4)

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)

Step 1 / 5
Local memorynumundefinedansundefinedFunction bodyfunction square(num) { var ans = num * num return ans}

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

Step 1 / 6
Call stack (bottom = first pushed)GlobalSame stack idea as the event loop lesson — order of nested runs

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.
  • return passes 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: Hoistingvar / function declarations, undefined vs not defined, and function expressions.