Can you predict what happens when you run this code? console.log(greet()); console.log(calculateTotal());…
Can you predict what happens when you run this code? console.log(greet()); console.log(calculateTotal()); function greet() { return "Hello!"; } var calculateTotal = function() { return 100; }; If you expected both to execute or both to fail, JavaScript just gave you a surprise. Line 1 runs seamlessly: "Hello!" Line 2 crashes completely: Uncaught TypeError: calculateTotal is not a function Why does the engine execute the first function before its definition, but crash instantly on the second? Here is what happens inside the JavaScript Execution Context: 1. The Two Creation Phase Rules Before running a single line of logic, the JavaScript engine scans your file in its Creation Phase. How it handles functions depends entirely on how you declare them: Function Declarations: "function greet() { ... }" gets first-class hoisting priority. The engine stores the entire function body directly into memory during Phase 1. When Line 1 runs, the full logic is already there waiting to be called. Function Expressions: "var calculateTotal = function() { ... }" is NOT treated as a function during Phase 1. The engine treats it strictly as a variable. Since it uses "var", its memory slot is initialized with "undefined". 2. The TypeError Anatomy When Line 2 executes: calculateTotal() The engine checks what is inside "calculateTotal" at that exact moment. It finds: "undefined". So the engine attempts to execute: undefined()! Since "undefined" is a primitive data type and not a callable function, JavaScript throws a TypeError. 3. What About Arrow Functions and const? If you rewrite the expression using modern syntax: console.log(multiply(2, 4)); const multiply = (a, b) => a * b; It will not throw a TypeError. Instead, it throws: Uncaught ReferenceError: Cannot access 'multiply' before initialization. Because "const" variables sit inside the Temporal Dead Zone (TDZ) until their actual line of declaration is evaluated. 4. The Modern Production Standard While Function Declarations allow you to call functions before writing them, modern codebases (React, Next.js, Node) heavily favor Function Expressions and Arrow Functions: • Predictability: Enforces a clean top-to-bottom reading flow (declare first, execute later). • Strict Safety: Using "const fn = () => {}" leverages TDZ guardrails to catch accidental early calls at compile/run time rather than failing silently.