JavaScript函数式编程核心是用map/filter/reduce替代for循环、以纯函数和不可变数据约束副作用,高阶函数与柯里化是实现该目标的关键工具而非炫技手段。

JavaScript 函数式编程不是换套语法糖,而是用 map、filter、reduce 替代 for 循环,用纯函数和不可变数据约束副作用——高阶函数和柯里化是落地这两点的关键工具,不是炫技手段。
什么时候该写高阶函数而不是普通函数
高阶函数的核心价值是「抽象行为」而非「封装逻辑」。当你发现多个函数只在某个操作细节上不同(比如校验规则、映射方式、比较条件),而其他流程完全一致,就该抽成高阶函数。
-
createValidator返回具体校验函数,而不是把正则硬编码在每个if里 -
makeApiCaller接收baseUrl和timeout,返回带默认配置的fetch封装,避免重复写fetch(url, { method: 'POST', timeout: 5000 }) - 不要为“看起来高级”而写:比如把
add(a, b)包一层返回(a) => (b) => a + b却从不复用(a) => ...部分,这只会增加调用成本
curry 不是必须手写,但得懂它怎么影响调用链
柯里化本质是把多参数函数拆成单参数函数的嵌套,关键作用是支持「提前绑定部分参数 + 延迟执行」。现代 JS 中,lodash.curry 或 ramda.curry 比手写更可靠,因为它们能处理 length、this 绑定和 rest 参数。
- 原生箭头函数无法柯里化:
const add = (a, b) => a + b的length是 2,但手动实现的 curry 通常依赖fn.length判断参数个数,遇到 rest 参数((a, ...rest))会失效 - 柯里化后函数的
toString()会变(比如显示function curried() { [native code] }),别依赖它做调试或日志输出 - 真实场景中,柯里化常配合
compose或pipe使用:pipe(validate, sanitize, save)里每个函数都应是单参数,否则链式调用断裂
用 reduce 实现柯里化时最容易漏掉的边界
手写 curry 最常见的错误不是逻辑错,而是忽略 JavaScript 的隐式转换和 this 上下文。
立即学习“Java免费学习笔记(深入)”;
- 没处理
undefined参数:当调用curried(1)(undefined)(3)时,不能把undefined当作“未传参”,需用arguments.length或显式标记占位符 - 没绑定原始函数的
this:obj.method被柯里化后直接调用会丢失this,必须用fn.bind(this)或箭头函数包裹 - 性能陷阱:每次柯里化都新建闭包,高频调用场景(如 React 渲染函数内)应预创建并缓存柯里化结果,而不是在 render 里反复
curry(fn)(a)
函数式编程的难点不在写高阶函数或柯里化,而在判断「哪里值得抽象」和「哪里该保持直白」。一个 filter 加两个三元运算符,远比强行柯里化再 compose 更可维护。真正卡住人的,永远是需求变化时哪部分该动、哪部分该稳。










