柯里化核心是闭包分步稳收参数:外层函数初始化独立storedargs数组,每次调用合并新参数,达fn.length即执行fn.apply(this, mergedargs),否则返回新函数;支持多参、零参、并发隔离与this绑定。

柯里化处理多个参数,关键不在“怎么多传”,而在“怎么分步稳收”——靠闭包把每次传入的参数安全存住,不丢、不错序、不污染上下文。它不是强行拆参数,而是让函数自己记住已有的,只等剩下的。
用数组累积参数,最直观也最可靠
闭包存储中间变量,推荐显式维护一个参数数组(storedArgs),每次调用都往里追加新参数,而不是靠递归栈或全局变量。这样顺序明确、类型保真、调试友好。
- 外层函数初始化空数组:
let storedArgs = [] - 返回的内部函数接收新参数,用
[...storedArgs, ...newArgs]合并 - 判断总长是否 ≥
fn.length,够了就fn(...merged),不够就继续返回新函数
支持一次传多个,别卡在“单参数”字面意思上
真实场景中,用户可能curry(add)(1, 2)(3),也可能curry(add)(1)(2, 3)。闭包链要能灵活合并参数,不能死守“每次只收一个”。
- 每次调用时,把
arguments或扩展运算符收集的参数统一展开 - 避免用
arguments对象(严格模式受限),改用function(...args)签名 - 合并逻辑写成
storedArgs = [...storedArgs, ...args],天然兼容多参、零参、甚至空数组
每层闭包独立,互不干扰
add(1)(2)(3)不是三个调用共享一个闭包,而是生成三个函数,各自闭包里存着[1]、[1,2]、[1,2,3]。这种隔离性是安全的来源——不同调用链不会串参数,也不用担心this或上下文错乱。
- 不要在顶层声明共享数组,否则并发调用会覆盖
- 每个柯里化实例(比如
curry(fn)(a))都应有自己专属的storedArgs - 闭包捕获的是外层函数执行时的局部变量,不是引用全局状态
执行时还原上下文,别让this丢失
原函数若依赖this(比如类方法或DOM事件处理器),直接fn(...args)会丢失绑定。闭包存参数的同时,也要存住调用时的上下文。
- 用
fn.apply(this, mergedArgs)或fn.call(this, ...mergedArgs) - 如果想支持箭头函数(无
this),可加判断:fn.bind ? fn.bind(this)(...merged) : fn(...merged) - 柯里化后的函数名建议设为
curried_${fn.name},方便调试追踪











