javascript

examples

examples.js
/**
 * ============================================
 * 6.3 HOISTING DEEP DIVE - EXAMPLES
 * ============================================
 */

/**
 * EXAMPLE 1: Function Declaration Hoisting
 * ----------------------------------------
 * Function declarations are fully hoisted
 */

console.log('=== Example 1: Function Declaration Hoisting ===');

// Works because function is fully hoisted
sayHello(); // "Hello, World!"

function sayHello() {
  console.log('Hello, World!');
}

// Can also call after declaration (normal)
sayHello(); // "Hello, World!"

/**
 * EXAMPLE 2: var Hoisting
 * -----------------------
 * var declarations are hoisted, values are not
 */

console.log('\n=== Example 2: var Hoisting ===');

console.log('Before assignment, x =', x); // undefined
var x = 10;
console.log('After assignment, x =', x); // 10

// What JavaScript actually does:
// var x;                // Hoisted to top (creation phase)
// console.log(x);       // undefined
// x = 10;               // Assignment (execution phase)
// console.log(x);       // 10

/**
 * EXAMPLE 3: let and const - Temporal Dead Zone
 * ----------------------------------------------
 * let and const are hoisted but in TDZ
 */

console.log('\n=== Example 3: Temporal Dead Zone ===');

// Uncomment to see the error:
// console.log(y); // ReferenceError: Cannot access 'y' before initialization

let y = 20;
console.log('y after declaration:', y);

// Same with const:
// console.log(z); // ReferenceError
const z = 30;
console.log('z after declaration:', z);

/**
 * EXAMPLE 4: TDZ is Time-Based, Not Position-Based
 * -------------------------------------------------
 * TDZ exists from scope entry until declaration execution
 */

console.log('\n=== Example 4: TDZ Timing ===');

function demonstrateTDZ() {
  // TDZ for 'value' starts here (scope entry)

  const getValueLater = () => value; // OK to reference in a closure

  // Can't access 'value' yet:
  // console.log(value); // ReferenceError

  let value = 'Hello'; // TDZ ends here

  console.log(getValueLater()); // "Hello" - works now!
}

demonstrateTDZ();

/**
 * EXAMPLE 5: Function Expressions Are NOT Hoisted
 * ------------------------------------------------
 * Only the variable is hoisted, not the function
 */

console.log('\n=== Example 5: Function Expressions ===');

// With var: TypeError
try {
  greetVar(); // TypeError: greetVar is not a function
} catch (e) {
  console.log('greetVar error:', e.message);
}

var greetVar = function () {
  console.log('Hello from function expression!');
};

greetVar(); // Now it works

// With const: ReferenceError (because of TDZ)
// Uncomment to see:
// greetConst(); // ReferenceError

const greetConst = function () {
  console.log('Hello from const function expression!');
};

/**
 * EXAMPLE 6: Arrow Functions Are NOT Hoisted
 * ------------------------------------------
 * Same rules as function expressions
 */

console.log('\n=== Example 6: Arrow Functions ===');

// Would cause error:
// arrowFunc(); // ReferenceError (with const) or TypeError (with var)

const arrowFunc = () => {
  console.log('Arrow function works after declaration!');
};

arrowFunc();

/**
 * EXAMPLE 7: Hoisting Order - Functions Before Variables
 * -------------------------------------------------------
 * When names conflict, functions are hoisted first
 */

console.log('\n=== Example 7: Hoisting Order ===');

console.log('typeof foo:', typeof foo); // "function"

var foo = 'I am a string';

function foo() {
  return 'I am a function';
}

console.log('typeof foo after assignments:', typeof foo); // "string"

// JavaScript processes this as:
// 1. function foo() {...} hoisted
// 2. var foo ignored (foo already exists)
// 3. foo = "string" executes

/**
 * EXAMPLE 8: Multiple var Declarations
 * ------------------------------------
 * Re-declarations with var are allowed
 */

console.log('\n=== Example 8: Multiple var Declarations ===');

var count = 1;
console.log('First:', count);

var count = 2; // No error, just reassignment
console.log('Second:', count);

var count; // Declaration without value - ignored
console.log('Third:', count); // Still 2

/**
 * EXAMPLE 9: Hoisting in Conditionals
 * ------------------------------------
 * var is hoisted even from never-executed blocks
 */

console.log('\n=== Example 9: Hoisting in Conditionals ===');

function conditionalHoisting() {
  console.log('value:', value); // undefined (not error!)

  if (false) {
    var value = 'This never runs';
  }

  console.log('value still:', value); // undefined
}

conditionalHoisting();

/**
 * EXAMPLE 10: Hoisting in Loops
 * -----------------------------
 * var creates one variable for all iterations
 */

console.log('\n=== Example 10: Hoisting in Loops ===');

// Problem with var
console.log('With var:');
for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log('var i:', i), 0);
}

// Fix with let
console.log('With let:');
for (let j = 0; j < 3; j++) {
  setTimeout(() => console.log('let j:', j), 10);
}

// Output:
// var i: 3, 3, 3 (all reference the same i)
// let j: 0, 1, 2 (each iteration has its own j)

/**
 * EXAMPLE 11: Class Hoisting
 * --------------------------
 * Classes are in TDZ like let/const
 */

console.log('\n=== Example 11: Class Hoisting ===');

// Would cause error:
// const obj = new MyClass(); // ReferenceError

class MyClass {
  constructor() {
    this.name = 'MyClass';
  }
}

const obj = new MyClass();
console.log('Class instance:', obj.name);

/**
 * EXAMPLE 12: Nested Scope Hoisting
 * ---------------------------------
 * Each scope has its own hoisting
 */

console.log('\n=== Example 12: Nested Scope Hoisting ===');

var outer = 'outer';

function demo() {
  console.log('Inner outer:', outer); // undefined! (inner 'outer' hoisted)

  var outer = 'inner'; // This shadows global 'outer'

  console.log('Inner outer after:', outer); // "inner"
}

demo();
console.log('Global outer:', outer); // "outer"

/**
 * EXAMPLE 13: Named Function Expressions
 * --------------------------------------
 * Name is only available inside the function
 */

console.log('\n=== Example 13: Named Function Expressions ===');

var factorial = function calcFactorial(n) {
  if (n <= 1) return 1;
  return n * calcFactorial(n - 1); // Can use name internally
};

console.log('factorial(5):', factorial(5)); // 120

// calcFactorial is NOT available outside:
// console.log(calcFactorial); // ReferenceError

/**
 * EXAMPLE 14: IIFE and Hoisting
 * -----------------------------
 * Variables inside IIFE are isolated
 */

console.log('\n=== Example 14: IIFE and Hoisting ===');

var globalVar = 'global';

(function () {
  console.log('globalVar inside IIFE:', globalVar); // undefined!
  var globalVar = 'local'; // Shadows and is hoisted within IIFE
  console.log('After local assignment:', globalVar); // "local"
})();

console.log('globalVar outside IIFE:', globalVar); // "global"

/**
 * EXAMPLE 15: Practical Hoisting Patterns
 * ---------------------------------------
 * How to write clear code despite hoisting
 */

console.log('\n=== Example 15: Best Practices ===');

// Good: Declare at the top
function processData(data) {
  // Declarations first
  const result = [];
  let total = 0;
  const multiplier = 2;

  // Logic after
  for (const item of data) {
    total += item * multiplier;
    result.push(item * multiplier);
  }

  return { result, total };
}

console.log(processData([1, 2, 3]));

/**
 * EXAMPLE 16: Function Inside Block (Edge Case)
 * ----------------------------------------------
 * Behavior varies by strict mode and browser
 */

console.log('\n=== Example 16: Function in Block ===');

// In strict mode, function is block-scoped
// In non-strict mode, behavior is implementation-dependent

function blockFunctionDemo() {
  'use strict';

  // console.log(typeof blockFunc); // undefined or error

  if (true) {
    function blockFunc() {
      return "I'm block-scoped in strict mode";
    }
    console.log('Inside block:', blockFunc());
  }

  // console.log("Outside block:", typeof blockFunc); // undefined in strict mode
}

blockFunctionDemo();

/**
 * EXAMPLE 17: Debugging Hoisting Issues
 * -------------------------------------
 * Common bugs and how to identify them
 */

console.log('\n=== Example 17: Debugging Hoisting ===');

function buggyFunction() {
  // Bug 1: Accessing before declaration
  // console.log(data); // undefined with var, error with let

  // Bug 2: Unexpected undefined
  var data = fetchData();
  console.log('Data received:', data);

  function fetchData() {
    return 'Real data';
  }

  // Bug 3: Shadowing
  var message = 'original';
  if (true) {
    var message = 'modified'; // Same variable (var is function-scoped)
  }
  console.log('Message:', message); // "modified" - might be unexpected
}

buggyFunction();

/**
 * EXAMPLE 18: Comparison Table Demo
 * ---------------------------------
 * All hoisting behaviors in one place
 */

console.log('\n=== Example 18: Comparison Demo ===');

function hoistingComparison() {
  console.log('--- Before declarations ---');

  // Function declaration: works
  console.log('funcDeclaration():', typeof funcDeclaration, '- callable');

  // var: hoisted as undefined
  console.log('varVariable:', typeof varVariable);

  // let: TDZ
  // console.log("letVariable:", letVariable); // ReferenceError

  // const: TDZ
  // console.log("constVariable:", constVariable); // ReferenceError

  // Function expression with var
  console.log('funcExpression:', typeof funcExpression);

  console.log('\n--- Declarations ---');

  function funcDeclaration() {
    return "I'm a function declaration";
  }
  var varVariable = "I'm a var";
  let letVariable = "I'm a let";
  const constVariable = "I'm a const";
  var funcExpression = function () {
    return "I'm a function expression";
  };

  console.log('\n--- After declarations ---');
  console.log('funcDeclaration():', funcDeclaration());
  console.log('varVariable:', varVariable);
  console.log('letVariable:', letVariable);
  console.log('constVariable:', constVariable);
  console.log('funcExpression():', funcExpression());
}

hoistingComparison();

console.log('\n=== End of Examples ===');
Examples - JavaScript Tutorial | DeepML