Guess the output before running this in your console: console.log(a); console.log(b); var a = 10; let b = 20;…
Guess the output before running this in your console: console.log(a); console.log(b); var a = 10; let b = 20; If you guessed: a = undefined b = 20 (or undefined) JavaScript just proved you wrong. Line 1 prints: undefined Line 2 throws: Uncaught ReferenceError: Cannot access 'b' before initialization Why does the engine happily log one variable, but crash instantly on the very next line? Here is what happens under the hood during the JavaScript Execution Context: 1. The Two-Phase Engine JavaScript does not execute code in a single sweep. It processes scripts in two distinct phases: • Phase 1: Creation Phase (Memory Allocation) • Phase 2: Execution Phase (Line-by-line Execution) Before a single line of logic runs, the V8 engine scans the entire file and reserves memory slots for your variables. 2. How 'var' Behaves (The Legacy Trap) During the Creation Phase, the engine encounters "var a". It allocates memory and immediately initializes it with a default value: "undefined". When Line 1 executes: console.log(a); The memory slot already holds "undefined". No crash. 3. How 'let' & 'const' Behave (The Modern Safety Net) During the Creation Phase, the engine also reserves memory for "let b". However, unlike "var", it DOES NOT initialize it with "undefined". From the top of the scope down to the line where "let b = 20" is declared, variable 'b' lives in a state called the Temporal Dead Zone (TDZ). If you attempt to access a variable while it resides in the TDZ: console.log(b); The engine throws a loud ReferenceError to prevent silent bugs. 4. Scope Boundaries Matter • "var" is Function-Scoped: It ignores curly braces {}. An if-statement or for-loop cannot contain it—it leaks into the outer scope. • "let" and "const" are Block-Scoped: They strictly respect {}. Once the block ends, the variables are destroyed. 5. The Industry Rule of Thumb • Default to "const" (90% of the time): Keeps references locked and state predictable. • Use "let" only when necessary (10% of the time): For loop counters and state toggles. • Avoid "var" entirely: It is a pre-2015 legacy relic that creates silent bugs and scope leakage.