The Execution Phase
Introduction
After the memory phase prepares bindings, JavaScript enters the execution phase: statements run in order, expressions are evaluated, assignments happen, and function calls create new execution contexts.
If the creation phase explains why names exist early, the execution phase explains when values actually change.
Why This Matters
Many candidates stop at hoisting and forget that assignments are not hoisted. The execution phase is where real program state changes. It is also where call-stack growth, returns, thrown errors, and closure reads happen in a predictable order.
Theory
What happens during execution
The engine walks through executable statements in source order. During this phase it:
- evaluates expressions such as
a + band function calls, - performs assignments such as
count = 1, - initializes
let,const, andclassdeclarations when their line is reached, - creates a new function execution context for each call,
- returns values to callers and pops contexts from the stack,
- throws errors if a read hits TDZ, an undefined value is called, or another runtime rule is violated.
Assignment is not declaration
var total = 10 has two conceptual parts: declaration and assignment. The declaration was handled during creation; the assignment happens during execution. This is why reading total earlier gives undefined, not 10.
Name lookup while executing
When a statement reads an identifier, JavaScript searches the current lexical environment first, then outer environments until it reaches global scope. Assignment updates the found binding, unless it is immutable (const) or missing in strict mode.
Function calls interrupt the current line
When execution reaches a function call, the current context pauses. A new function context is pushed onto the call stack, prepared, executed, and eventually popped. Then the caller resumes with the returned value.
Run-to-completion
A running context is not preempted in the middle of a synchronous statement. Timers and promise callbacks only run after the current stack clears. This makes execution deterministic, but long synchronous work blocks everything else.
Visual Diagrams
var total = 10 Creation phase total -> undefined Execution phase run statement: total = 10 total -> 10
A declaration can be ready before its value is assigned.
global executing | | calls calculate() v +----------------------+ | calculate context | runs to return +----------------------+ | | pops and returns value v global resumes after the call
The caller waits while the callee context runs to completion.
Code Examples
Assignments happen in order
The var binding exists early, but every value change happens exactly when execution reaches the assignment statement.
A call creates a nested context
The outer function pauses while the inner function executes and returns.
Playground
Press Run to execute the code and see output here.
Output Prediction
Predict the output #1
1var value = 1;2 3function change() {4 console.log(value);5 var value = 2;6 console.log(value);7}8 9change();10console.log(value);Predict the output #2
1let count = 0;2 3function addOne() {4 count = count + 1;5 return count;6}7 8console.log(addOne());9console.log(addOne());10console.log(count);Predict the output #3
1var run = function () {2 console.log('first');3};4 5run();6 7run = function () {8 console.log('second');9};10 11run();Coding Exercises
Apply operations in execution order
EasyImplement runTransaction(balance, operations). operations is an array of objects like { type: 'deposit', amount: 10 } or { type: 'withdraw', amount: 5 }. Return an array of balances after applying each operation in order. This mirrors execution-phase state changes.
Interview Questions
1What is the difference between the creation phase and execution phase?
The creation phase prepares bindings and initial states: var as undefined, function declarations as function objects, and lexical declarations in TDZ. The execution phase runs statements in order: assignments happen, expressions are evaluated, functions are called, lexical declarations are initialized, and errors can be thrown.
Follow-ups
- Why are assignments not hoisted?
- When is a let binding initialized?
2What happens when execution reaches a function call?
The caller pauses. JavaScript creates a new function execution context, prepares its parameters and local bindings, pushes it onto the call stack, executes it, then pops it when the function returns or throws. The caller then resumes with the returned value or handles the thrown error.
Quiz
1. In `var x = 7`, which part happens during execution?
2. What happens to the caller when a function is called?
Summary
- The execution phase runs statements and expressions in source order.
- Assignments, function expressions, and lexical initializations happen during execution.
- Function calls push new contexts; returns pop them and resume the caller.
- Run-to-completion means synchronous code is not interrupted in the middle of the current stack.
Cheat Sheet
Execution phase: statements run line by line.
Happens here: assignments, expression evaluation, function calls, returns, throws, lexical initialization.
Not here: declaration discovery; that happened during creation.
Call rule: caller pauses -> callee context runs -> callee returns -> caller resumes.