一、先搞懂:柯里化到底是什么?
核心定义:柯里化是把接收多个参数的函数,转换成一系列只接收单个参数的函数,并持续返回新函数,直到所有参数都被传入后,才执行最终逻辑并返回结果。
用 “人话” 说:原本要一次性传完所有参数的函数,现在可以 “分批传”,传一个参数就返回一个新函数等着接下一个,直到传完为止。
对比:普通函数 vs 柯里化函数
// 普通函数:一次性传所有参数
function add(a, b, c) {
return a + b + c;
}
add(1, 2, 3); // 6
// 柯里化函数:分批次传参数
function curriedAdd(a) {
return function(b) {
return function(c) {
return a + b + c;
};
};
}
curriedAdd(1)(2)(3); // 6(传一个参数,返回新函数,直到传完3个)
二、手动实现一个通用柯里化函数
你不用为每个函数单独写柯里化逻辑,这里写一个通用的 curry 工具函数,能把任意多参数函数转换成柯里化函数:
// 通用柯里化函数
function curry(fn) {
// 保存原函数的参数个数
const argsLength = fn.length;
// 递归接收参数
function curried(...args) {
// 1. 如果已传参数 >= 原函数需要的参数,执行原函数
if (args.length >= argsLength) {
return fn.apply(this, args);
}
// 2. 否则,返回新函数,继续接收参数
return function(...newArgs) {
return curried.apply(this, [...args, ...newArgs]);
};
}
return curried;
}
// 测试:给加法函数做柯里化
const add = (a, b, c) => a + b + c;
const curriedAdd = curry(add);
// 支持多种传参方式(核心优势)
console.log(curriedAdd(1)(2)(3)); // 6(逐个传)
console.log(curriedAdd(1, 2)(3)); // 6(分批传)
console.log(curriedAdd(1)(2, 3)); // 6(混合传)
console.log(curriedAdd(1, 2, 3)); // 6(一次性传)
三、柯里化的核心价值(为什么要用?)
-
参数复用:提前固定部分参数,生成新函数,避免重复传参。示例:固定 “税率” 参数,复用计算逻辑
// 原函数:计算税后价格(价格 + 税率) const calculateTax = (taxRate, price) => price * (1 + taxRate); // 柯里化后,固定税率为10% const calculateTax10 = curry(calculateTax)(0.1); // 后续只用传价格,不用重复传税率 calculateTax10(100); // 110 calculateTax10(200); // 220 -
延迟执行:先收集参数,不立即执行,等参数凑齐后再执行。示例:表单提交前收集多个字段,凑齐后再验证提交
const submitForm = (name, phone, address) => { console.log(`提交:${name} ${phone} ${address}`); }; const curriedSubmit = curry(submitForm); // 分步收集参数(比如用户分步填写表单) const step1 = curriedSubmit("张三"); // 收集姓名,未执行 const step2 = step1("13800138000"); // 收集手机号,未执行 step2("北京市"); // 收集地址,参数凑齐,执行 → 输出:提交:张三 13800138000 北京市 -
适配函数参数:把多参数函数转换成单参数函数,适配只接收单参数的场景(比如 React 的高阶组件、数组的 map/filter 等)。示例:适配数组 map 的单参数回调
// 原函数:乘以指定倍数 const multiply = (multiplier, num) => num * multiplier; const curriedMultiply = curry(multiply); // 固定倍数为2,生成单参数函数 const double = curriedMultiply(2); // 适配 map 的单参数回调 [1,2,3].map(double); // [2,4,6]
四、常见误区
❌ 误区:“柯里化就是把函数拆成只传一个参数的函数,必须链式调用 (a)(b)(c)”
✅ 纠正:柯里化的核心是 “参数分批传递 + 延迟执行”,支持任意分批方式(比如 (a,b)(c)、(a)(b,c)),不一定非要逐个传。
❌ 误区:“柯里化能提升性能”
✅ 纠正:柯里化本质是多了层函数嵌套,性能略有损耗,它的价值是提升代码复用性和可读性,而非性能。
总结
- 柯里化核心:把多参数函数转成 “单参数函数链”,支持参数分批传递,凑齐后执行;
- 实现关键:通过闭包保存已传参数,递归判断参数是否凑齐,凑齐则执行原函数;
- 核心用途:参数复用、延迟执行、适配单参数场景。