柯里化是将多参数函数转为一系列单参数函数的过程,通过闭包保存已传参数,每次调用返回新函数直至参数满足fn.length才执行原逻辑;支持占位符增强版可跳过参数位置,闭包维持combined状态与fn引用。

JavaScript 中通过闭包实现柯里化函数,核心是让函数接收部分参数后不立即执行,而是返回一个新函数等待剩余参数,利用闭包保存已传入的参数。
什么是柯里化(Currying)
柯里化是将一个接收多个参数的函数,转换为一系列只接收单个参数的函数的过程。每次调用只传一个参数,返回下一个函数,直到所有参数就位才真正执行原逻辑。
例如:add(1, 2, 3) 柯里化后可写成 add(1)(2)(3) 或 add(1)(2)(3)()(取决于是否自动触发)。
基础闭包柯里化实现
利用闭包捕获已传参数,递归返回新函数,直到参数数量满足要求:
立即学习“Java免费学习笔记(深入)”;
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);
console.log(curriedMultiply(2)(3)(4)); // 24
console.log(curriedMultiply(2, 3)(4)); // 24
console.log(curriedMultiply(2)(3, 4)); // 24
- 闭包体现在
curried内部函数持续访问外层的args和fn -
fn.length获取原函数期望的形参个数,作为“收尾”判断依据 - 每次调用都合并参数,未满则返回新函数;满则直接执行
支持占位符与灵活调用的增强版
实际中常需支持占位符(如 _),允许跳过某些参数位置:
function curryWithPlaceholder(fn, placeholder = "_") {
return function curried(...args) {
return function(...moreArgs) {
const combined = [...args];
let i = 0;
for (const arg of moreArgs) {
while (i < combined.length && combined[i] !== placeholder) i++;
if (i < combined.length) combined[i++] = arg;
else combined.push(arg);
}
if (combined.filter(x => x !== placeholder).length >= fn.length) {
return fn.apply(this, combined.map(x => x === placeholder ? undefined : x));
}
return curried.apply(this, combined);
};
};
}
<p>// 使用示例
const add = (a, b, c) => a + b + c;
const curriedAdd = curryWithPlaceholder(add);
console.log(curriedAdd(1, _, 3)(2)); // 6 → 相当于 add(1, 2, 3)
- 占位符机制靠遍历替换,保持参数位置语义
- 闭包维持了
combined状态和fn引用 - 真正执行前会把占位符转为
undefined,避免影响原函数逻辑
注意事项与常见误区
闭包实现柯里化虽简洁,但需注意几个关键点:
- 箭头函数无法正确绑定
this,柯里化函数内部建议用普通函数确保上下文传递 -
fn.length只反映函数声明时的形参个数,对 rest 参数(...args)不敏感,动态参数场景需手动指定长度 - 多次调用同一柯里化函数会创建多个闭包,内存中保留各次已传参数,避免在循环中无节制使用
- 若原函数有默认参数,
fn.length不计入带默认值的参数,可能提前触发执行


















