柯里化是将多参函数转为分步传参的形式,依靠闭包保存已传参数、fn.length判断形参个数,通过递归和参数合并实现灵活调用,支持预设参数提升复用性。

函数柯里化就是把一个接收多个参数的函数,变成可以分步传参的形式——每次只传一部分,返回新函数继续等剩下的,直到所有参数到位才真正执行。它不改原函数逻辑,只是加了一层“分批收参”的包装。
核心靠闭包和 length 判断
柯里化能逐步传参,关键在两点:一是用闭包记住已传的参数,二是靠 fn.length 知道原函数到底需要几个参数。每次调用都把新参数存起来,累计够了就用 apply 或 call 执行;不够就再返回一个函数接着等。
- fn.length 返回的是函数声明时的形参个数(不包括 rest 参数),是判断是否该执行的唯一可靠依据
- 闭包让每次嵌套函数都能访问外层已收集的参数列表,不会丢失中间状态
- 参数合并推荐用 args.concat(nextArgs),兼容单个或多个参数传入
写一个通用 curry 函数
下面这个版本支持混合调用方式,比如 f(1)(2,3)、f(1,2)(3)、f(1)(2)(3) 都能正确处理:
function curry(fn) {
return function curried(...args) {
if (args.length >= fn.length) {
return fn.apply(this, args);
}
return function(...nextArgs) {
return curried.apply(this, args.concat(nextArgs));
};
};
}
- 用 rest 参数 ...args 接收任意数量输入,更简洁安全
- 递归调用 curried 自身,保持 this 上下文和参数链完整
- 返回的函数仍可继续传参,直到参数总数 ≥ fn.length
实际用法:预设参数生成专用函数
柯里化的价值不在“能拆”,而在“提前固化常用参数”,让后续调用更专注业务本身。
- 日志封装:const logError = curry(console.error)('ERROR');,之后直接 logError('timeout')
- 接口请求:const getUser = curry(fetchUser)(baseUrl);,后续 getUser('123') 自动带 base URL
- 表单校验:const isEmail = curry(validate)(/^[^\s@]+@[^\s@]+\.[^\s@]+$/);,复用正则规则
注意边界情况
手动实现时容易忽略几个细节:
- 箭头函数没有 arguments 和 length 属性,不能直接柯里化,需先转为普通函数
- 含默认参数的函数,fn.length 只计算第一个有默认值前的参数个数,要留意实际需求数
- 生产环境建议优先用 lodash.curry,它内置占位符(_)、this 绑定和 rest 参数支持
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











