函数柯里化是将多参函数转为单参函数链,通过闭包累加参数并延迟至参数齐备时执行;支持占位符、this绑定与显式元数指定,用于配置复用、函数组合及API构造。

函数柯里化(Currying)在 JavaScript 中的核心是:把一个接收多个参数的函数,转换为一系列每次只接收一个参数的函数,并返回下一个函数,直到所有参数都传完才真正执行原逻辑。它天然支持参数累加和延迟计算——参数不是一次性给全,而是逐步“攒起来”,最终调用时才触发计算。
参数累加:用闭包保存已传入的参数
每次调用柯里化函数,都应记住之前传过的参数,等最后一步再合并调用原函数。关键靠闭包捕获中间参数数组:
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));
};
};
}说明:
- fn.length 获取原函数期望的形参个数,作为“收尾”判断依据
- 每次调用
curried都会把当前参数args存下来,返回新函数等待更多参数 - 递归调用
curried.apply(...)实现参数持续累积,不依赖外部变量
延迟计算:真正执行发生在参数“凑够”的那一刻
柯里化本身不立即运行函数,只构建调用链。只有当累计参数数量 ≥ 原函数形参个数时,才调用原始函数并返回结果:
立即学习“Java免费学习笔记(深入)”;
const add = (a, b, c) => a + b + c; const curriedAdd = curry(add); <p>curriedAdd(1)(2)(3); // → 6(此时才真正执行 add(1,2,3)) curriedAdd(1, 2)(3); // → 6(前两次传了两个参数,第三次补足后执行) curriedAdd(1)(2, 3); // → 6(同理,参数总数达 3 即触发)
注意:延迟不是靠定时器或 Promise,而是靠“不满足条件就不调用原函数”这一逻辑实现的。
更实用的增强版:支持提前传空/undefined 并兼容 this
真实场景中可能需要绑定上下文、处理稀疏参数,或允许中途传入部分 undefined:
- 用
bind或显式传thisArg保证方法调用时的this正确 - 不依赖
fn.length判断(箭头函数、有默认值的函数会失准),改用显式指定参数数量:curry(fn, 3) - 允许
curried(1)(undefined)(3)这类调用,内部用占位符机制处理未定参数
例如简化版占位符支持:
const placeholder = Symbol('placeholder');
function curry(fn, arity = fn.length) {
return function curried(...args) {
const hasPlaceholder = args.includes(placeholder);
const filledArgs = args.map(a => a === placeholder ? undefined : a);
const pending = arity - filledArgs.filter(a => a !== undefined).length;
<pre class="brush:php;toolbar:false;">if (pending <= 0) return fn.apply(this, filledArgs);
return function(...moreArgs) {
const combined = [...args];
let i = 0;
for (const arg of moreArgs) {
while (i < combined.length && combined[i] !== placeholder) i++;
if (i < combined.length) combined[i++] = arg;
else combined.push(arg);
}
return curried.apply(this, combined);
};}; }
实际用途:配置复用 + 条件组合 + 函数式管道
柯里化不是炫技,它让函数更灵活:
-
固定部分参数生成新函数:如
const logError = curry(console.error)('ERROR:'),后续只传消息 -
与函数组合搭配:配合
compose或pipe构建数据处理流水线,每步只关心一个输入 -
按需构造 API 调用器:如
const fetchUser = curry(api.get)('/users')('id'),最后传 id 才发请求
本质上,参数累加是手段,延迟计算是效果,目标是提升函数的可复用性与组合能力。


















