JavaScript 函数式编程:从入门到精通
函数式编程(FP)是一种将计算视为数学函数求值,并避免状态改变和可变数据的编程范式。在 JavaScript (Node.js) 环境中,FP 成为创建可预测、可测试和可扩展代码的强大工具。本文将深入讲解 FP 从基础到高级技巧的核心概念,并通过实践示例加以巩固。
基础:纯函数与不可变性
FP 的核心是两大原则:纯函数 和 不可变性(数据不可变)。
纯函数 对于相同的参数始终返回相同的结果,并且没有副作用(不修改外部变量、不输出到控制台、不发起 API 请求)。
// 纯函数const add = (a, b) => a + b;
// 非纯函数(副作用——修改外部变量)let counter = 0;const increment = () => counter++;不可变性 意味着数据不会被直接修改,而是创建带有所需更改的新副本。在 JavaScript 中,通过返回新对象/数组的方法来实现。
// 不可变地更新对象const user = { name: 'Alice', age: 30 };const updatedUser = { ...user, age: 31 }; // 创建新对象
// 不可变地更新数组const numbers = [1, 2, 3];const newNumbers = [...numbers, 4]; // [1, 2, 3, 4]闭包与高阶函数
闭包 是一个即使在外部函数执行完毕后,仍能“记住”其词法环境的函数。这是许多 FP 模式的基础。
const createMultiplier = (factor) => { // 内部函数——闭包 return (number) => number * factor;};
const double = createMultiplier(2);console.log(double(5)); // 10高阶函数 是接受其他函数作为参数或返回函数的函数。经典示例包括 map、filter、reduce。
const numbers = [1, 2, 3, 4, 5];
// map —— 转换每个元素const doubled = numbers.map(n => n * 2); // [2, 4, 6, 8, 10]
// filter —— 按条件筛选元素const even = numbers.filter(n => n % 2 === 0); // [2, 4]
// reduce —— 将数组归约为单个值const sum = numbers.reduce((acc, n) => acc + n, 0); // 15函数组合与柯里化
函数组合 是将多个函数合并为一个函数,其中一个函数的结果作为下一个函数的输入。这允许从简单、可复用的模块构建复杂操作。
const compose = (...fns) => (x) => fns.reduceRight((acc, fn) => fn(acc), x);
const trim = (str) => str.trim();const toLowerCase = (str) => str.toLowerCase();const capitalize = (str) => str.charAt(0).toUpperCase() + str.slice(1);
const processName = compose(capitalize, toLowerCase, trim);console.log(processName(' JOHN DOE ')); // 'John doe'柯里化 是将一个接受多个参数的函数转换为一系列每个只接受一个参数的函数。这简化了偏函数应用和函数组合。
// 普通函数const multiply = (a, b, c) => a * b * c;
// 柯里化版本const curriedMultiply = (a) => (b) => (c) => a * b * c;
console.log(curriedMultiply(2)(3)(4)); // 24
// 偏函数应用const multiplyBy2 = curriedMultiply(2);const multiplyBy2And3 = multiplyBy2(3);console.log(multiplyBy2And3(5)); // 30