柯里化是将多参数函数转换为一系列单参数函数的过程,核心是参数分步传入、延迟执行;基础版手动嵌套,通用版基于fn.length递归收集参数,进阶版支持this绑定和占位符。

柯里化(Currying)是把一个接收多个参数的函数,转换成一系列只接收一个参数的函数的过程。核心思想是“参数分步传入,延迟执行”。实现的关键在于:每次调用返回一个新函数,直到参数数量满足原函数要求才真正执行。
基础实现(固定参数个数)
假设原函数有 3 个参数,我们可以手动写一个只适配它的柯里化版本:
function add(a, b, c) {
return a + b + c;
}
<p>function curryAdd(a) {
return function(b) {
return function(c) {
return add(a, b, c);
};
};
}</p><p>// 使用
curryAdd(1)(2)(3); // 6
</p>这种写法直观但不通用。实际中更常用自动推断参数长度的方式。
通用柯里化函数(基于 length)
利用函数的 length 属性(表示形参个数),递归收集参数,达到数量后执行:
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));
};
}
};
}
<p>// 使用示例
function multiply(a, b, c) {
return a <em> b </em> c;
}
const curriedMultiply = curry(multiply);
curriedMultiply(2)(3)(4); // 24
curriedMultiply(2, 3)(4); // 24
curriedMultiply(2)(3, 4); // 24
</p>支持 this 绑定与占位符(进阶版)
真实场景中常需保留原始调用上下文,并支持占位符(如 _)跳过当前参数:
- 用 bind 或显式传入 this 来维持上下文
- 引入占位符逻辑:遇到 _ 不计入已传参数数,后续补上
- 可借助闭包或额外状态记录“待填空位”
简化版带占位符示例(使用全局占位符标识):
const __ = Symbol('placeholder');
<p>function curryAdvanced(fn) {
return function curried(...args) {
const placeholders = args.filter(arg => arg === <strong>).length;
const filled = args.filter(arg => arg !== </strong>);</p><pre class="brush:php;toolbar:false;">if (filled.length >= fn.length - placeholders) {
// 构造完整参数数组,填充占位符位置
const fullArgs = [];
let argIndex = 0;
for (let i = 0; i <p>};
}
</p>注意事项与常见误区
- 箭头函数没有 arguments 和 length,不能直接用于需要自动推参的 curry;应确保传入的是普通函数
- 柯里化 ≠ 部分应用(Partial Application):后者可一次传多个参数,且不要求严格单参数调用链
- 递归深度过大可能引发栈溢出,生产环境建议限制嵌套或改用循环实现
- 注意闭包中对外部变量的引用,避免意外的内存驻留
不复杂但容易忽略细节。掌握基础版即可应对多数需求,进阶功能按需叠加。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











