柯里化是将多参数函数转换为一系列单参数函数的过程,通过递归返回新函数并依据fn.length判断参数是否满足,支持预设参数、函数组合与上下文绑定,但不适用于rest参数或箭头函数。

柯里化(Currying)是把一个接收多个参数的函数,转换成一系列只接收一个参数的函数的过程。它不是简单地“拆分调用”,而是返回新函数,每次只传一个参数,直到参数个数满足原函数要求才真正执行。
基础柯里化实现
最简方式是手动封装,比如将 add(a, b, c) 变成 add(a)(b)(c):
function add(a, b, c) {
return a + b + c;
}
function curryAdd(a) {
return function(b) {
return function(c) {
return add(a, b, c);
};
};
}
// 使用
curryAdd(1)(2)(3); // 6
但手动写太繁琐。通用柯里化函数更实用:
function curry(fn) {
return function curried(...args) {
if (args.length >= fn.length) {
return fn.apply(this, args);
} else {
return function(...moreArgs) {
return curried.apply(this, args.concat(moreArgs));
};
}
};
}
// 使用
const curriedAdd = curry(add);
curriedAdd(1)(2)(3); // 6
curriedAdd(1, 2)(3); // 6
curriedAdd(1)(2, 3); // 6
支持 this 和多参数批次传入
上面的通用版已兼容多次传参(如 (1)(2, 3)),也保留了原始函数的 this 上下文。关键点有:
-
判断依据是
fn.length:即函数声明时的形参个数,不是实际调用时的实参个数 -
递归返回新函数:每次收集参数,不够就继续返回
curried函数本身 -
用
apply保证this正确:避免箭头函数丢失上下文问题
实际场景中的好处
柯里化不是炫技,而是为复用和配置服务:
-
预设部分参数:比如
const sendToApi = curry(fetch)(baseUrl),之后只需传路径和配置 -
配合函数式组合:和
map、filter等高阶函数搭配更自然,例如[1,2,3].map(curry(Math.pow)(2))得到平方数组 -
提升可读性与测试性:把变化的参数分离出来,固定逻辑单独测试,比如
const validateEmail = curry(isValid)(/^[^\s@]+@[^\s@]+\.[^\s@]+$/)
注意边界情况
柯里化虽好,但要注意:
-
不适用于动态参数个数的函数(如带
...rest且无固定前缀参数),因为fn.length返回 0 -
箭头函数无法被柯里化(没有
length属性,且不能用new.target或arguments) -
调试时堆栈略深:多层嵌套函数可能让错误定位变慢,生产环境建议加简单注释或使用工具库(如 Lodash 的
_.curry)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











