Functional Programming
Pure functions, immutability, composition, currying, and higher-order functions — the functional style in JavaScript.
What it is, in plain English: Functional programming (FP) is a style where you build programs by composing pure functions — functions that always return the same output for the same input and cause no side effects. JavaScript is a multi-paradigm language that supports FP natively: functions are first-class values, arrays have map/filter/reduce, and the spread operator enables immutable updates. FP principles make code more predictable, testable, and easier to reason about.
The functional style — build programs from small, reliable pieces
Functional programming is a way of writing code where every function is a pure calculation: same input always gives the same output, and nothing is modified. JavaScript isn't a purely functional language, but applying FP ideas makes code much easier to test and reason about.
Pure functions — predictable and testable
// Impure — depends on external state, unpredictable:
let tax = 0.18;
function calculateTotal(price) {
return price + price * tax; // depends on external 'tax' variable
}
// If tax changes, the function gives different results for the same price!
// Pure — all inputs are parameters, no external dependencies:
function calculateTotalPure(price, taxRate) {
return price + price * taxRate;
}
console.log(calculateTotalPure(100, 0.18)); // always 118
console.log(calculateTotalPure(100, 0.18)); // still 118
// Pure functions are trivial to test:
// test("100 at 18% = 118", () => assert(calculateTotalPure(100, 0.18) === 118))Immutability — never mutate, always return new
// Mutable (bad for FP):
function addItemMutable(cart, item) {
cart.push(item); // modifies the original — side effect!
return cart;
}
// Immutable (FP style):
function addItem(cart, item) {
return [...cart, item]; // returns a NEW array, original unchanged
}
const cart1 = ["apple", "banana"];
const cart2 = addItem(cart1, "cherry");
console.log(cart1); // ["apple", "banana"] — unchanged
console.log(cart2); // ["apple", "banana", "cherry"] — new array
// Same for objects:
const user = { name: "Alice", score: 90 };
const updated = { ...user, score: 95 }; // new object
console.log(user.score); // 90 — original safe
console.log(updated.score); // 95map / filter / reduce — the FP trinity
const products = [
{ name: "Laptop", price: 60000, inStock: true },
{ name: "Phone", price: 25000, inStock: false },
{ name: "Tablet", price: 30000, inStock: true },
{ name: "Monitor", price: 15000, inStock: true },
];
// filter — keep items matching a condition:
const available = products.filter(p => p.inStock);
// map — transform each item:
const discounted = available.map(p => ({
...p,
price: Math.round(p.price * 0.9),
discount: "10% off"
}));
// reduce — fold into a single value:
const total = discounted.reduce((sum, p) => sum + p.price, 0);
console.log(`${discounted.length} items available`);
console.log(`Total: ₹${total.toLocaleString("en-IN")}`);
// Chain them:
const totalDiscount = products
.filter(p => p.inStock)
.map(p => p.price * 0.1)
.reduce((sum, d) => sum + d, 0);
console.log(`Total savings: ₹${totalDiscount.toLocaleString("en-IN")}`);Higher-order functions — functions that work with functions
// A function that returns another function:
function multiplier(factor) {
return (n) => n * factor;
}
const double = multiplier(2);
const triple = multiplier(3);
const halve = multiplier(0.5);
console.log(double(10)); // 20
console.log(triple(10)); // 30
console.log(halve(10)); // 5
// A function that takes another function:
function applyTwice(fn, value) {
return fn(fn(value));
}
console.log(applyTwice(double, 3)); // 12 (doubled twice)
Try It Yourself
Official Sources
- MDN Web Docs — Array.prototype.map()
- MDN Web Docs — Array.prototype.reduce()
- MDN Web Docs — Closures
- Professor Frisby's Mostly Adequate Guide to FP
The Codex links only to official documentation and the ECMAScript specification. No third-party tutorials.