通用柯里化函数核心是接收原函数并返回能逐步收参的新函数,参数不足时递归返回新柯里化函数,足够时执行原函数;通过闭包保存已收集参数,支持显式指定arity提升鲁棒性。

通用柯里化函数的核心是:接收一个原函数,返回一个新函数;新函数能逐步接收参数,直到参数总数达到原函数的形参个数时才真正执行。
递归控制参数收集过程
每次调用柯里化后的函数,都检查已收集参数是否足够。不够就返回一个新的柯里化函数(继续等待参数);够了就立即调用原函数。
- 用 arguments.length 或展开的参数数组长度判断是否满足原函数要求的参数个数(fn.length)
- 不满足时,把当前传入的参数和之前累积的参数合并,再递归调用自身,生成下一层柯里化函数
- 递归基是参数数量达标,此时直接 fn(...args)
闭包保存中间状态
每次递归调用都形成一个新作用域,上层的 argsSoFar(已收集参数)被内层函数通过闭包持续持有,不会丢失。
- 外层函数(curry)初始化空数组或传入初始参数
- 内层返回的函数引用了外层的 argsSoFar,即使外层执行结束,该数组仍保留在内存中
- 多次调用同一柯里化函数(如 add5(2)(3)),每次都在同一个闭包链中追加参数
基础实现示例
以下是一个简洁、可读性强的通用柯里化函数:
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));
};
};
}
说明:
- curried 是主递归函数,每次接收一批参数
- 参数不足时,它返回一个新函数,该函数调用自身并带上已有参数(闭包捕获 args)
- fn.length 获取原函数期望的参数个数(注意:箭头函数、无名函数或含默认值/剩余参数时可能不准,生产环境建议配合预设 arity 参数增强鲁棒性)
更健壮的变体(支持显式指定参数个数)
避免依赖 fn.length 的不确定性,可增加可选参数 arity:
function curry(fn, arity = fn.length) {
return function curried(...args) {
if (args.length >= arity) {
return fn.apply(this, args);
}
return function (...moreArgs) {
return curried.apply(this, [...args, ...moreArgs]);
};
};
}
这样就能安全处理 (a, b, c = 1) => a + b + c 这类有默认值的函数,因为 fn.length 只返回 2,但你可能希望等够 3 个才执行。


















