javascript
examples
examples.js⚡javascript
/**
* ============================================
* 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 ===');