javascript
examples
examples.js⚡javascript
/**
* ============================================
* 2.1 Variables - Examples
* ============================================
*
* Comprehensive examples of var, let, and const
*/
// ============================================
// BASIC VARIABLE DECLARATION
// ============================================
console.log('=== BASIC VARIABLE DECLARATION ===\n');
// Declaration only
let firstName;
console.log('Declared but not initialized:', firstName); // undefined
// Declaration with initialization
let lastName = 'Doe';
console.log('Declared and initialized:', lastName); // "Doe"
// Assignment (changing value)
lastName = 'Smith';
console.log('After reassignment:', lastName); // "Smith"
// ============================================
// VAR - THE ORIGINAL WAY
// ============================================
console.log('\n=== VAR CHARACTERISTICS ===\n');
// 1. var is function scoped
function varFunctionScope() {
if (true) {
var insideIf = "I'm function scoped";
}
console.log('var inside if, accessed outside:', insideIf);
}
varFunctionScope();
// 2. var is hoisted
console.log('\nvar hoisting:');
console.log('Before declaration:', hoistedVar); // undefined, not error!
var hoistedVar = 'Now I have a value';
console.log('After declaration:', hoistedVar);
// 3. var can be redeclared
var color = 'red';
var color = 'blue'; // No error
console.log('\nvar redeclaration:', color); // "blue"
// 4. var creates global property (in browser)
var globalVar = "I'm on window object";
// console.log(window.globalVar); // Works in browser
// ============================================
// LET - THE MODERN WAY
// ============================================
console.log('\n=== LET CHARACTERISTICS ===\n');
// 1. let is block scoped
function letBlockScope() {
if (true) {
let insideIf = "I'm block scoped";
console.log('let inside if:', insideIf);
}
// console.log(insideIf); // ReferenceError!
}
letBlockScope();
console.log('let respects block scope!');
// 2. let has Temporal Dead Zone
console.log('\nlet TDZ:');
// console.log(tdzVar); // Would throw: Cannot access 'tdzVar' before initialization
let tdzVar = 'I exist now';
console.log('After declaration:', tdzVar);
// 3. let cannot be redeclared in same scope
let uniqueVar = 'first';
// let uniqueVar = "second"; // SyntaxError!
console.log('\nlet prevents redeclaration in same scope');
// But different scopes are OK
let outerLet = 'outer';
if (true) {
let outerLet = 'inner'; // Different scope, OK
console.log('Inner scope let:', outerLet);
}
console.log('Outer scope let:', outerLet);
// ============================================
// CONST - CONSTANTS
// ============================================
console.log('\n=== CONST CHARACTERISTICS ===\n');
// 1. const must be initialized
const PI = 3.14159;
console.log('PI:', PI);
// const uninitialized; // SyntaxError: Missing initializer
// 2. const cannot be reassigned
const MAX_SIZE = 100;
// MAX_SIZE = 200; // TypeError: Assignment to constant variable
console.log('MAX_SIZE:', MAX_SIZE);
// 3. const is block scoped (like let)
if (true) {
const blockConst = "I'm block scoped";
console.log('const inside block:', blockConst);
}
// console.log(blockConst); // ReferenceError!
// 4. IMPORTANT: const allows mutation of objects/arrays!
console.log('\nconst with objects (mutation allowed):');
const person = { name: 'John', age: 30 };
console.log('Before mutation:', person);
person.age = 31; // OK - mutating property
person.city = 'NYC'; // OK - adding property
console.log('After mutation:', person);
// person = {}; // TypeError - cannot reassign reference
console.log('\nconst with arrays (mutation allowed):');
const numbers = [1, 2, 3];
console.log('Before mutation:', numbers);
numbers.push(4); // OK
numbers[0] = 100; // OK
console.log('After mutation:', numbers);
// numbers = []; // TypeError - cannot reassign reference
// ============================================
// SCOPE COMPARISON
// ============================================
console.log('\n=== SCOPE COMPARISON ===\n');
function scopeTest() {
console.log('Inside function scope test:');
if (true) {
var varInBlock = 'var';
let letInBlock = 'let';
const constInBlock = 'const';
console.log(' Inside if block:');
console.log(' var:', varInBlock);
console.log(' let:', letInBlock);
console.log(' const:', constInBlock);
}
console.log(' Outside if block:');
console.log(' var:', varInBlock); // Accessible!
// console.log(" let:", letInBlock); // ReferenceError
// console.log(" const:", constInBlock); // ReferenceError
}
scopeTest();
// ============================================
// LOOP SCOPE - THE CLASSIC PROBLEM
// ============================================
console.log('\n=== LOOP SCOPE PROBLEM ===\n');
// The var problem in loops
console.log('Using var in setTimeout loop:');
for (var i = 0; i < 3; i++) {
setTimeout(function () {
console.log(' var i:', i); // All print 3!
}, 10);
}
// The let solution
console.log('Using let in setTimeout loop:');
for (let j = 0; j < 3; j++) {
setTimeout(function () {
console.log(' let j:', j); // Correctly prints 0, 1, 2
}, 20);
}
// Wait for setTimeouts to complete before continuing
setTimeout(() => {
console.log('\n=== TEMPORAL DEAD ZONE (TDZ) ===\n');
// TDZ demonstration
function tdzDemo() {
// TDZ starts for 'x'
const result = typeof undeclaredVar; // OK - not in TDZ
console.log('typeof undeclaredVar:', result); // "undefined"
// const resultX = typeof x; // ReferenceError! x is in TDZ
let x = 10; // TDZ ends for x
console.log('x after TDZ:', x);
}
tdzDemo();
// ============================================
// PRACTICAL EXAMPLES
// ============================================
console.log('\n=== PRACTICAL EXAMPLES ===\n');
// Example 1: Configuration object (use const)
const CONFIG = {
apiUrl: 'https://api.example.com',
timeout: 3000,
debug: true,
};
console.log('Config:', CONFIG);
// Can still modify properties
CONFIG.debug = false;
console.log('Modified config:', CONFIG);
// Example 2: Counter (use let)
let counter = 0;
function increment() {
counter++;
return counter;
}
console.log('\nCounter:', increment()); // 1
console.log('Counter:', increment()); // 2
console.log('Counter:', increment()); // 3
// Example 3: Constants (use const with UPPER_CASE)
const MAX_USERS = 100;
const MIN_PASSWORD_LENGTH = 8;
const API_KEY = 'abc123xyz';
console.log('\nConstants:');
console.log(' MAX_USERS:', MAX_USERS);
console.log(' MIN_PASSWORD_LENGTH:', MIN_PASSWORD_LENGTH);
// Example 4: Reference that changes (use let)
let currentUser = { name: 'John' };
console.log('\nCurrent user:', currentUser);
currentUser = { name: 'Jane' }; // Reassignment
console.log('After reassignment:', currentUser);
// Example 5: Reference that never changes (use const)
const user = { name: 'Bob' };
user.name = 'Robert'; // Mutation, not reassignment - OK
console.log('\nMutated const object:', user);
}, 100);
// ============================================
// HOISTING COMPARISON
// ============================================
console.log('\n=== HOISTING COMPARISON ===\n');
// var hoisting - accessible but undefined
console.log('var before declaration:', typeof varHoist); // "undefined"
var varHoist = 'Hello';
// let hoisting - in TDZ, typeof throws error
// console.log("let before declaration:", typeof letHoist); // ReferenceError
let letHoist = 'Hello';
// Function hoisting - fully hoisted
console.log('Function before declaration:', hoistedFunc()); // Works!
function hoistedFunc() {
return "I'm hoisted!";
}
// ============================================
// COMMON MISTAKES AND FIXES
// ============================================
console.log('\n=== COMMON MISTAKES ===\n');
// Mistake 1: Using var in loops
console.log('Mistake 1 - var in loop (creates shared variable):');
var buttons = [];
for (var k = 0; k < 3; k++) {
buttons[k] = function () {
return k;
};
}
console.log(' All buttons return:', buttons[0](), buttons[1](), buttons[2]()); // 3, 3, 3
console.log('\nFix - let in loop (creates new variable each iteration):');
let fixedButtons = [];
for (let k = 0; k < 3; k++) {
fixedButtons[k] = function () {
return k;
};
}
console.log(
' Buttons return:',
fixedButtons[0](),
fixedButtons[1](),
fixedButtons[2]()
); // 0, 1, 2
// Mistake 2: Thinking const means immutable
console.log('\nMistake 2 - Thinking const is immutable:');
const immutableMisconception = [1, 2, 3];
immutableMisconception.push(4); // This works!
console.log(" Mutated 'const' array:", immutableMisconception);
// Mistake 3: Declaring without initialization when using const
// const needsValue; // SyntaxError
console.log(
'\nMistake 3 - const needs initialization (would cause SyntaxError)'
);
// ============================================
// BEST PRACTICES SUMMARY
// ============================================
console.log('\n=== BEST PRACTICES ===\n');
console.log('1. Default to const');
const defaultToConst = 'This is the default choice';
console.log(' ', defaultToConst);
console.log('\n2. Use let only when reassignment is needed');
let needsReassignment = 'initial';
needsReassignment = 'changed';
console.log(' ', needsReassignment);
console.log('\n3. Never use var');
console.log(' var is legacy - avoid it in modern code');
console.log('\n4. One declaration per line');
const item1 = 'apple';
const item2 = 'banana';
const item3 = 'cherry';
console.log(' ', item1, item2, item3);
console.log('\n5. Use meaningful names');
const userAccountBalance = 1000;
const isUserLoggedIn = true;
const MAXIMUM_RETRY_ATTEMPTS = 3;
console.log(' Good names are self-documenting');