JavaScript does not just run your code top to bottom. It first scans everything to set up memory, then goes back and executes line by line.
Save
Complete lesson & earn 250 PX
Phase 1 allocates memory for all variables (as undefined) and functions (full code). Phase 2 executes code line by line, assigning real values and running functions.
EXERCISE
1Before running any code, JavaScript does a first pass where it allocates memory for all variables and functions. Variables get a placeholder value. Functions get stored completely.
Save
Imagine a teacher walking into a classroom before the lesson starts. She writes every student name on the board (memory allocation) but leaves their grades blank (undefined). That is Phase 1.
What happens during memory creation:
var x = 7;
var y = 10;
function add(a, b) {
return a + b;
}
// PHASE 1: Memory Creation (before any code runs)
// Memory now looks like this:
// x -> undefined (NOT 7 yet!)
// y -> undefined (NOT 10 yet!)
// add -> function add(a, b) { return a + b; }
The critical rule:
// Variables: stored as undefined (placeholder)
// Functions: stored COMPLETELY (the entire code)
var name = "Zara";
// During Phase 1: name -> undefined
function sayHello() {
console.log("Hello!");
}
// During Phase 1: sayHello -> function sayHello() { ... }
// The ENTIRE function is saved, not just the name
Key Insight: This is why you can call a function before its declaration, but you cannot use a variable before its assignment. Functions are fully stored in Phase 1. Variables only get a placeholder "undefined". This behaviour is called hoisting, and you will master it in Unit 2.
EXERCISE
3Let us trace through a real program step by step and watch both phases work together, from memory creation to final output.
Save
EXERCISE
2Now JavaScript goes through your code a second time, line by line, actually running it. Variables get their real values, and functions create brand new execution contexts when called.
Save
The best way to truly understand execution contexts is to play computer. Walk through code with your finger and track what memory looks like at every step.
Full walkthrough:
var x = 1;
a();
b();
console.log(x);
function a() {
var x = 10;
console.log(x);
}
function b() {
var x = 100;
console.log(x);
}
// PHASE 1 (Memory Creation for Global Context):
// x -> undefined
// a -> function a() { ... }
// b -> function b() { ... }
// PHASE 2 (Code Execution):
// Line 1: x = 1 -> x is now 1 in global memory
// Line 2: a() is called -> NEW execution context for a()
// Phase 1 of a(): x -> undefined
// Phase 2 of a(): x = 10, console.log(x) prints 10
// a() finishes, its context is DELETED
// Line 3: b() is called -> NEW execution context for b()
// Phase 1 of b(): x -> undefined
// Phase 2 of b(): x = 100, console.log(x) prints 100
// b() finishes, its context is DELETED
// Line 4: console.log(x) -> prints 1 (global x, untouched)
// Output:
// 10
// 100
// 1
Key Insight: Each function has its own x. The x inside a() is a completely different variable from the x inside b() and the x in the global scope. They just happen to share the same name. keeps them separate because each function gets its own execution context with its own memory. This is called the Variable Environment, and it is the reason function-scoped variables stay private.
Phase 2 is when the work actually starts. goes back to line 1 and starts executing. When it hits a variable assignment, it replaces "undefined" with the actual value. When it hits a function call, something interesting happens.
Replacing undefined with real values:
var x = 7;
var y = 10;
// PHASE 1 (already done):
// x -> undefined, y -> undefined
// PHASE 2 (now running):
// Line 1: x = 7 -> Memory updates: x is now 7
// Line 2: y = 10 -> Memory updates: y is now 10
What happens when you call a function:
var result;
function multiply(a, b) {
var answer = a * b;
return answer;
}
result = multiply(3, 5);
console.log(result); // 15
// When multiply(3, 5) is called:
// 1. A BRAND NEW execution context is created
// 2. That new context has its OWN Phase 1:
// a -> undefined, b -> undefined, answer -> undefined
// 3. Then its OWN Phase 2:
// a = 3, b = 5, answer = 15
// 4. "return answer" sends 15 back to the caller
// 5. The function execution context is DELETED
Key Insight: Every function call creates its own mini-world: a new execution context with its own memory and its own code runner. When the function finishes, that mini-world is destroyed. The variables inside it? Gone. The temporary memory? Freed. This is why variables inside a function do not leak into the outside world.