闭包通过作用域链使外层变量(如args)被内层函数持续引用而不被回收,每次调用柯里化函数时手动累积参数,直到满足数量才执行原函数;关键在返回函数持有对同一闭包变量的引用。

闭包在柯里化函数中“持续累积并保存参数”,本质是利用函数作用域链 + 返回新函数 + 外层变量被内层函数引用,从而让参数像被“封存”在内存中一样逐步积累。关键不是“自动累积”,而是每次调用都返回一个记住已有参数的新函数,直到满足条件才执行最终逻辑。
闭包如何保存已传入的参数
外层函数定义参数数组(如 args),内层返回的函数通过作用域访问并修改它。由于内层函数未被释放(被持续返回或调用),JS 引擎不会回收该作用域,args 就一直存在。
- 每次调用柯里化函数时,把新参数推入 args
- 若参数数量不足,返回一个新的函数(仍引用同一份 args)
- 若参数够了,就用这个累积好的 args 调用原始函数
一个手动实现的柯里化示例(带闭包累积)
以 add(1)(2)(3) 返回 6 为例:
function add(a) {
let args = [a]; // 闭包变量:被所有后续返回的函数共享
function curried(b) {
args.push(b); // 每次调用都往同一个数组加参数
return curried;
}
curried.toString = () => args.reduce((a, b) => a + b, 0); // 用于隐式转换输出
return curried;
}
这里 args 是闭包变量,curried 函数始终能读写它。三次调用后,args = [1, 2, 3],toString 触发求和。
更通用的柯里化(支持预设参数数)
常见做法是传入原函数和期望参数个数 arity:
function curry(fn, arity = fn.length) {
return function $curry(...args) {
if (args.length >= arity) {
return fn(...args);
}
return function (...moreArgs) {
return $curry(...args, ...moreArgs); // 闭包捕获了外层的 args 和 fn、arity
};
};
}
每次递归调用 $curry 都会形成新的闭包,但当前这一层的 args 始终被下一层返回的函数“记住”。这种链式闭包让参数逐层累积,直到总数达标。
注意:闭包保存的是引用,不是拷贝
如果累积的是对象或数组,后续修改会影响所有依赖它的函数:
- 避免在柯里化过程中直接修改外部传入的数组/对象
- 需要安全累积时,建议用展开语法([...args, ...more])或 concat 创建新数组
- 否则多个柯里化实例可能意外共享同一份数据
不复杂但容易忽略:闭包本身不“做累积”,它只是提供存储空间;真正累积动作发生在每次调用时的手动拼接或 push。核心是“返回的函数还活着,所以它记得之前的一切”。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











