Execution Context and the Call Stack
Every function call gets its own frame on a stack, and JavaScript only ever runs the frame on top.
Loading visual…
Definition
Every time a function is called, the engine creates a new execution context, a frame that holds that call's local variables, its arguments, and its own value of `this`. That frame is pushed onto the call stack, a last-in-first-out structure. The engine always runs the frame currently on top of the stack; if that function calls another function, a new frame goes on top of it, pausing the caller until the callee finishes. When a function returns, its frame pops off the stack and control resumes in the frame beneath it, exactly where it left off. The global context is the frame at the very bottom, created once when the program starts and never popped until the program ends. This is what a stack trace shows you: the chain of frames, bottom to top, that were active when an error was thrown.
Examples
function third() { console.trace(); }
function second() { third(); }
function first() { second(); }
first();
// stack (top to bottom): third, second, first, globalEach call pushes a new frame on top of the one that called it; console.trace prints the stack as it stood at that moment.
function factorial(n) {
if (n <= 1) return 1;
return n * factorial(n - 1);
}
factorial(3); // 6Recursion pushes one frame per call (factorial(3), factorial(2), factorial(1)) before any of them can return, then pops them off in reverse order as each multiplication resolves.
Where you see this
- Reading a stack trace in an error report to see the exact chain of calls that led to a crash.
- Understanding 'Maximum call stack size exceeded' errors from runaway or unbounded recursion.
- Reasoning about synchronous execution order before mixing in asynchronous callbacks.
- Using debugger breakpoints and the call stack panel in devtools to step back through nested calls.