javascript

examples

examples.js
/**
 * =====================================================
 * 5.7 HIGHER-ORDER FUNCTIONS - EXAMPLES
 * =====================================================
 * Functions that take or return functions
 */

// =====================================================
// 1. FUNCTIONS AS ARGUMENTS
// =====================================================

console.log('--- Functions as Arguments ---');

function repeat(n, action) {
  for (let i = 0; i < n; i++) {
    action(i);
  }
}

console.log('Repeat 3 times:');
repeat(3, (i) => console.log(`  Iteration ${i}`));

// Custom array processor
function processArray(arr, operation) {
  const result = [];
  for (const item of arr) {
    result.push(operation(item));
  }
  return result;
}

const numbers = [1, 2, 3, 4, 5];
console.log(
  'Doubled:',
  processArray(numbers, (n) => n * 2)
);
console.log(
  'Squared:',
  processArray(numbers, (n) => n * n)
);

// =====================================================
// 2. FUNCTIONS AS RETURN VALUES
// =====================================================

console.log('\n--- Functions as Return Values ---');

function createMultiplier(factor) {
  return function (number) {
    return number * factor;
  };
}

const double = createMultiplier(2);
const triple = createMultiplier(3);
const quadruple = createMultiplier(4);

console.log('double(5):', double(5)); // 10
console.log('triple(5):', triple(5)); // 15
console.log('quadruple(5):', quadruple(5)); // 20

// =====================================================
// 3. MAP() - TRANSFORM EACH ELEMENT
// =====================================================

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

const nums = [1, 2, 3, 4, 5];

// Basic transformation
const doubled = nums.map((n) => n * 2);
console.log('Doubled:', doubled);

// Object transformation
const users = [
  { firstName: 'Alice', lastName: 'Smith' },
  { firstName: 'Bob', lastName: 'Jones' },
  { firstName: 'Charlie', lastName: 'Brown' },
];

const fullNames = users.map((u) => `${u.firstName} ${u.lastName}`);
console.log('Full names:', fullNames);

// With index
const indexed = nums.map((n, i) => ({ index: i, value: n }));
console.log('Indexed:', indexed);

// =====================================================
// 4. FILTER() - SELECT MATCHING ELEMENTS
// =====================================================

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

const allNumbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

// Even numbers
const evens = allNumbers.filter((n) => n % 2 === 0);
console.log('Evens:', evens);

// Greater than 5
const large = allNumbers.filter((n) => n > 5);
console.log('Greater than 5:', large);

// Filter objects
const products = [
  { name: 'Apple', price: 1.5, inStock: true },
  { name: 'Banana', price: 0.75, inStock: false },
  { name: 'Orange', price: 2.0, inStock: true },
];

const available = products.filter((p) => p.inStock);
console.log('In stock:', available);

const affordable = products.filter((p) => p.price < 2);
console.log('Under $2:', affordable);

// =====================================================
// 5. REDUCE() - COMBINE INTO SINGLE VALUE
// =====================================================

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

const values = [1, 2, 3, 4, 5];

// Sum
const sum = values.reduce((acc, n) => acc + n, 0);
console.log('Sum:', sum);

// Product
const product = values.reduce((acc, n) => acc * n, 1);
console.log('Product:', product);

// Max
const max = values.reduce((acc, n) => (n > acc ? n : acc), -Infinity);
console.log('Max:', max);

// Count occurrences
const letters = ['a', 'b', 'a', 'c', 'b', 'a', 'd'];
const counts = letters.reduce((acc, letter) => {
  acc[letter] = (acc[letter] || 0) + 1;
  return acc;
}, {});
console.log('Letter counts:', counts);

// Group by property
const people = [
  { name: 'Alice', department: 'Engineering' },
  { name: 'Bob', department: 'Sales' },
  { name: 'Charlie', department: 'Engineering' },
  { name: 'Diana', department: 'Sales' },
];

const byDept = people.reduce((acc, person) => {
  const dept = person.department;
  if (!acc[dept]) acc[dept] = [];
  acc[dept].push(person.name);
  return acc;
}, {});
console.log('By department:', byDept);

// =====================================================
// 6. FOREACH() - EXECUTE FOR EACH
// =====================================================

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

const items = ['apple', 'banana', 'cherry'];

// Logging
console.log('Items:');
items.forEach((item, index) => {
  console.log(`  ${index + 1}. ${item}`);
});

// Side effects
let totalLength = 0;
items.forEach((item) => {
  totalLength += item.length;
});
console.log('Total length:', totalLength);

// =====================================================
// 7. FIND() AND FINDINDEX()
// =====================================================

console.log('\n--- find() and findIndex() ---');

const employees = [
  { id: 1, name: 'Alice', role: 'Developer' },
  { id: 2, name: 'Bob', role: 'Designer' },
  { id: 3, name: 'Charlie', role: 'Developer' },
];

// find() - returns element
const found = employees.find((e) => e.id === 2);
console.log('Found employee:', found);

// findIndex() - returns index
const index = employees.findIndex((e) => e.role === 'Designer');
console.log('Designer index:', index);

// First developer
const firstDev = employees.find((e) => e.role === 'Developer');
console.log('First developer:', firstDev);

// Not found
const notFound = employees.find((e) => e.id === 99);
console.log('Not found:', notFound); // undefined

// =====================================================
// 8. SOME() AND EVERY()
// =====================================================

console.log('\n--- some() and every() ---');

const scores = [75, 82, 93, 68, 85];

// some() - at least one
const hasHigh = scores.some((s) => s >= 90);
console.log('Has score >= 90:', hasHigh); // true

// every() - all
const allPassing = scores.every((s) => s >= 60);
console.log('All passing (>= 60):', allPassing); // true

const allExcellent = scores.every((s) => s >= 90);
console.log('All excellent (>= 90):', allExcellent); // false

// With objects
const tasks = [
  { name: 'Task 1', completed: true },
  { name: 'Task 2', completed: true },
  { name: 'Task 3', completed: false },
];

const allDone = tasks.every((t) => t.completed);
console.log('All tasks done:', allDone); // false

const anyDone = tasks.some((t) => t.completed);
console.log('Any task done:', anyDone); // true

// =====================================================
// 9. SORT()
// =====================================================

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

// Number sorting (ascending)
const unsorted = [3, 1, 4, 1, 5, 9, 2, 6];
const ascending = [...unsorted].sort((a, b) => a - b);
console.log('Ascending:', ascending);

// Descending
const descending = [...unsorted].sort((a, b) => b - a);
console.log('Descending:', descending);

// String sorting
const names = ['Charlie', 'alice', 'Bob'];
const alphabetical = [...names].sort();
console.log('Alphabetical:', alphabetical);

// Case-insensitive
const caseInsensitive = [...names].sort((a, b) =>
  a.toLowerCase().localeCompare(b.toLowerCase())
);
console.log('Case-insensitive:', caseInsensitive);

// Sort objects by property
const userList = [
  { name: 'Charlie', age: 35 },
  { name: 'Alice', age: 25 },
  { name: 'Bob', age: 30 },
];

const byAge = [...userList].sort((a, b) => a.age - b.age);
console.log(
  'By age:',
  byAge.map((u) => u.name)
);

const byName = [...userList].sort((a, b) => a.name.localeCompare(b.name));
console.log(
  'By name:',
  byName.map((u) => u.name)
);

// =====================================================
// 10. METHOD CHAINING
// =====================================================

console.log('\n--- Method Chaining ---');

const transactions = [
  { type: 'sale', amount: 100, date: '2024-01-15' },
  { type: 'refund', amount: -50, date: '2024-01-16' },
  { type: 'sale', amount: 200, date: '2024-01-17' },
  { type: 'sale', amount: 75, date: '2024-01-18' },
  { type: 'refund', amount: -25, date: '2024-01-19' },
];

// Total sales over $50
const bigSalesTotal = transactions
  .filter((t) => t.type === 'sale')
  .filter((t) => t.amount > 50)
  .map((t) => t.amount)
  .reduce((sum, a) => sum + a, 0);

console.log('Big sales total:', bigSalesTotal); // 300

// Format and display
const salesReport = transactions
  .filter((t) => t.type === 'sale')
  .map((t) => `$${t.amount} on ${t.date}`)
  .join('\n');

console.log('Sales report:\n' + salesReport);

// =====================================================
// 11. FLATMAP()
// =====================================================

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

const sentences = ['Hello world', 'JavaScript is fun'];

// Split into words (map + flat)
const words = sentences.flatMap((s) => s.split(' '));
console.log('Words:', words);

// Generate pairs
const pairs = [1, 2, 3].flatMap((n) => [n, n * 2]);
console.log('Pairs:', pairs);

// =====================================================
// 12. CUSTOM HIGHER-ORDER FUNCTIONS
// =====================================================

console.log('\n--- Custom Higher-Order Functions ---');

// Custom filter
function myFilter(arr, predicate) {
  const result = [];
  for (const item of arr) {
    if (predicate(item)) {
      result.push(item);
    }
  }
  return result;
}

console.log(
  'Custom filter:',
  myFilter([1, 2, 3, 4], (n) => n % 2 === 0)
);

// Pipe function
function pipe(...fns) {
  return function (value) {
    return fns.reduce((acc, fn) => fn(acc), value);
  };
}

const process = pipe(
  (n) => n * 2, // 5 → 10
  (n) => n + 3, // 10 → 13
  (n) => n * n // 13 → 169
);

console.log('Pipe result:', process(5));

// Compose function (right to left)
function compose(...fns) {
  return function (value) {
    return fns.reduceRight((acc, fn) => fn(acc), value);
  };
}

const calculate = compose(
  (n) => n * n, // Last: square
  (n) => n + 3, // Then: add 3
  (n) => n * 2 // First: double
);

console.log('Compose result:', calculate(5)); // ((5 * 2) + 3)² = 169

// =====================================================
// 13. PRACTICAL EXAMPLES
// =====================================================

console.log('\n--- Practical Examples ---');

// Shopping cart example
const cart = [
  { name: 'Shirt', price: 25, quantity: 2 },
  { name: 'Pants', price: 45, quantity: 1 },
  { name: 'Shoes', price: 80, quantity: 1 },
];

// Total calculation
const total = cart.reduce((sum, item) => {
  return sum + item.price * item.quantity;
}, 0);
console.log('Cart total:', total);

// Item summary
const summary = cart.map((item) => ({
  name: item.name,
  subtotal: item.price * item.quantity,
}));
console.log('Item summary:', summary);

// =====================================================
// 14. PERFORMANCE CONSIDERATIONS
// =====================================================

console.log('\n--- Performance Tips ---');

// Multiple chained operations (multiple passes)
const result1 = [1, 2, 3, 4, 5]
  .filter((n) => n > 2)
  .map((n) => n * 2)
  .filter((n) => n < 10);

// Single reduce (one pass - more efficient for large arrays)
const result2 = [1, 2, 3, 4, 5].reduce((acc, n) => {
  if (n > 2) {
    const doubled = n * 2;
    if (doubled < 10) {
      acc.push(doubled);
    }
  }
  return acc;
}, []);

console.log('Chained:', result1);
console.log('Single reduce:', result2);

// =====================================================
// SUMMARY
// =====================================================

console.log('\n--- Summary ---');
console.log(`
HIGHER-ORDER FUNCTIONS:
  • Take function as argument, OR
  • Return function as result

KEY ARRAY METHODS:
  map(fn)       → new array (transformed)
  filter(fn)    → new array (filtered)
  reduce(fn, init) → single value
  forEach(fn)   → undefined (side effects)
  find(fn)      → first match or undefined
  findIndex(fn) → index or -1
  some(fn)      → boolean (any match?)
  every(fn)     → boolean (all match?)
  sort(fn)      → sorted array (in-place)
  flatMap(fn)   → flattened mapped array

PATTERNS:
  • Function factories
  • Callbacks
  • Method chaining
  • Pipe/Compose
`);
Examples - JavaScript Tutorial | DeepML