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.