柯里化是将多参数函数转换为一系列单参数函数的技术,每次调用接收一个参数并返回新函数,直至参数收齐才执行;本质是参数分批交付,支持复用、预置与组合。

柯里化是什么:把多参数函数变成一连串单参数函数
柯里化不是语法糖,也不是 JavaScript 内置特性,而是一种函数变换策略:把 f(a, b, c) 改写成 f(a)(b)(c) 的形式。每次调用只接收一个参数,返回一个新的函数,直到参数收齐才真正执行。
它不改变原函数逻辑,只改变调用方式——本质是“参数分批交付”。这为函数复用、配置预置、逻辑组合提供了基础支撑。
手动实现一个通用 curry 函数要注意什么
常见错误是直接递归调用自身却没控制终止条件,或忽略 this 绑定、arguments 处理不当导致上下文丢失。
- 必须显式保存原始函数的
length(形参个数),作为“收齐参数”的判断依据 - 不能直接用
arguments拼接,需转成数组并用fn.apply(this, args)保证this正确 - 推荐用 rest 参数(
...args)替代arguments,更安全清晰 - 返回的中间函数应能接受任意数量参数(比如
add(1)(2, 3)也合法),否则实用性受限
简单可运行示例:
立即学习“Java免费学习笔记(深入)”;
function curry(fn) {
return function curried(...args) {
if (args.length >= fn.length) {
return fn.apply(this, args);
}
return function(...moreArgs) {
return curried.apply(this, args.concat(moreArgs));
};
};
}
lodash.curry 和手写版的关键差异在哪
lodash.curry 默认支持占位符(如 _)、自动识别 length、兼容箭头函数(虽无 this,但避免报错),还提供 curryRight 和 curry.placeholder 等扩展能力。
手写版通常只处理最简场景,遇到以下情况容易出问题:
- 原函数有默认参数(
function f(a = 1, b))→fn.length返回 1,但实际需 2 个实参 - 传入箭头函数 →
this绑定失效,但 lodash 会降级处理 - 需要提前绑定部分参数并保留占位能力 → 手写版得额外加逻辑
所以生产环境建议直接用 lodash.curry,除非你明确知道参数结构且追求极简依赖。
柯里化在函数式编程中真正起作用的场景
它本身不“函数式”,只是让函数更容易满足纯函数、不可变、组合等要求。真实价值体现在:
- 配置复用:
const httpGet = curry((baseUrl, path) => fetch(baseUrl + path)); const githubApi = httpGet('https://api.github.com'); - 与
compose/pipe配合:pipe(filter(isActive), map(getName), curry(join)(', ')) - 事件处理器预置:
button.addEventListener('click', handleClick(userId)),避免内联箭头函数闭包泄漏 - 测试桩简化:
const mockFetch = curry((status, body) => Promise.resolve({ status, body }));
注意:过度柯里化会让调用链变长、调试困难,尤其当函数本就只被调用一次时,反而增加认知负担。











