Back to Blog
Tutorial2025-01-22

Functional Programming in JavaScript

Learn functional programming concepts in JavaScript: pure functions, immutability, composition, currying, and more.

Core Principles

Pure Functions

A pure function always returns the same output for the same input and has no side effects.

``javascript // Pure const add = (a, b) => a + b; const toUpper = str => str.toUpperCase();

// Impure (side effects) let total = 0; const addToTotal = (n) => { total += n; return total; }; `

Immutability

Never mutate data — create new copies instead.

`javascript // Bad: Mutation const user = { name: 'Alice', age: 28 }; user.age = 29; // Mutating!

// Good: Immutable update const updatedUser = { ...user, age: 29 };

// Arrays const nums = [1, 2, 3]; const added = [...nums, 4]; // Don't push const removed = nums.filter(n => n !== 2); // Don't splice const mapped = nums.map(n => n * 2); // Don't modify in place `

Higher-Order Functions

Functions that take or return functions.

`javascript // map, filter, reduce are higher-order functions const users = [ { name: 'Alice', age: 28 }, { name: 'Bob', age: 17 }, { name: 'Charlie', age: 32 } ];

const adultNames = users .filter(u => u.age >= 18) .map(u => u.name); // ['Alice', 'Charlie']

// Creating higher-order functions const withLogging = (fn) => (...args) => { console.log('Calling with:', args); const result = fn(...args); console.log('Result:', result); return result; };

const loggedAdd = withLogging(add); loggedAdd(2, 3); // Logs: Calling with: [2, 3], Result: 5 `

Function Composition

Combine simple functions to build complex ones.

`javascript const compose = (...fns) => (x) => fns.reduceRight((acc, fn) => fn(acc), x);

const pipe = (...fns) => (x) => fns.reduce((acc, fn) => fn(acc), x);

const processName = pipe( str => str.trim(), str => str.toLowerCase(), str => str.replace(/\s+/g, '-') );

processName(' Hello World '); // 'hello-world' `

Currying

Transform a function with multiple arguments into a sequence of functions.

`javascript const curry = (fn) => { const arity = fn.length; return function curried(...args) { if (args.length >= arity) return fn(...args); return (...more) => curried(...args, ...more); }; };

const multiply = curry((a, b, c) => a * b * c); multiply(2)(3)(4); // 24 multiply(2, 3)(4); // 24 const double = multiply(2)(1); double(5); // 10 `

Practical Example: Data Pipeline

`javascript const transactions = [ { id: 1, amount: 100, category: 'food', date: '2024-01-15' }, { id: 2, amount: 250, category: 'tech', date: '2024-01-20' }, { id: 3, amount: 50, category: 'food', date: '2024-02-01' }, { id: 4, amount: 180, category: 'tech', date: '2024-02-15' }, ];

const result = pipe( txs => txs.filter(t => t.category === 'food'), txs => txs.map(t => t.amount), amounts => amounts.reduce((sum, a) => sum + a, 0) )(transactions);

console.log(result); // 150 ``

Summary

Functional programming in JavaScript leads to more predictable, testable, and maintainable code. Start with pure functions and immutability, then gradually adopt composition and currying as you get more comfortable.