Quick Overview
The engine reserves memory for every declaration before it runs a single line, then executes. That two-phase order is why a `function` is callable above its definition while a `var` reads `undefined` there.
In JavaScript, everything happens inside an Execution Context. Think of an Execution Context as a sealed container where JavaScript evaluates and executes your code.
Understanding the 2 execution phases explains hoisting, scope boundaries, closures, call stack overflows, and how the V8 engine manages memory.
Whenever a JavaScript program runs or a function is invoked, the engine creates an Execution Context in two distinct phases:
var set to undefined) and stores full function declarations.The JS engine manages execution contexts using a LIFO (Last-In, First-Out) Call Stack. The Global Execution Context (GEC) sits at the bottom of the stack. When a function is called, a new local Execution Context is pushed onto the stack. When the function returns, its context is popped off!
[ Call Stack ]
┌─────────────────────────┐
│ calculateTax() Context │ <- Currently executing (Top of stack)
├─────────────────────────┤
│ processOrder() Context │
├─────────────────────────┤
│ Global Context (GEC) │ <- Bottom of stack
└─────────────────────────┘
var x = 2;
function square(num) {
var ans = num * num;
return ans;
}
var square2 = square(x);
x: undefined, square: [function code], square2: undefined.x = 2. Calling square(2) creates a new local context.square local context: num = 2, ans = 4. return 4 pops local context off stack and assigns 4 to square2.RangeError: Maximum call stack size exceeded.Write it yourself. The tests below run against your code.
Remember: Memory allocation happens BEFORE code execution. This leads directly to our next topic: Hoisting!
Primitives copy by value and objects copy by reference, so `b = a` duplicates a number but shares an object. That single distinction explains most surprise mutations in a codebase.
`const` prevents reassignment, not mutation: a `const` object's properties can still be changed. `let` is scoped to its block, while `var` is function-scoped and leaks out of loops.
Only backticks interpolate: `${user}` reads the variable, while the identical text in quotes prints literally. Strings are immutable, so every method returns a new one rather than editing in place.