柯里化函数应在参数不足时暂存并等待,通过闭包递归累积参数,以fn.length为默认触发依据,支持多参数混用、保持this上下文与参数顺序,并需应对fn.length局限性。

参数收集不全时,柯里化函数不应报错或静默失败,而应继续等待、累积参数,直到满足触发条件再执行。核心在于“暂存”而非“丢弃”,靠闭包和递归维持状态。
用 fn.length 动态判断是否收齐
JavaScript 函数的 fn.length 返回其显式声明的形参个数(不含 rest 参数、不含带默认值的参数)。这是最常用的触发依据:
- 若已传参数总长度 ≥ fn.length → 立即用 fn.apply(this, args) 执行原函数
- 否则 → 返回新函数,把当前参数存入闭包,等待下一次调用
支持多参数混用,不能只认单个参数
真实调用场景中,用户可能一次传多个参数,比如 add(1)(2, 3) 或 add(1, 2)(3, 4, 5)。实现时需:
- 每次接收参数都用 args.concat(nextArgs) 合并,而非简单 push
- 避免假设“每次只传一个”,不依赖 arguments[0] 这类写法
- 用 Array.prototype.slice.call(arguments) 或展开运算符安全取参
保留 this 上下文和参数顺序
若原函数在对象方法中被柯里化调用(如 obj.doSomething(1)(2)),丢失 this 会导致逻辑错误:
- 必须用 fn.apply(this, mergedArgs) 而非直接 fn(...mergedArgs)
- 递归返回的新函数也要用 .apply(this, ...) 传递上下文,不能用箭头函数(无 this 绑定)
- 参数合并顺序要严格保持调用时的先后,不能颠倒
注意 fn.length 的局限性及应对方式
fn.length 不可靠 的常见情况:
- 箭头函数:length 恒为 0,无法作为判断依据
- 含默认值的函数:如 function foo(a, b = 1, c) {},length === 1,但实际至少需 1 个参数
- 含 rest 参数:如 function bar(a, ...rest) {},length === 1,无法反映动态参数需求
此时建议:
- 手动传入期望参数个数:curry(fn, 3)
- 对箭头函数或复杂签名函数,改用成熟库(如 Ramda 的 R.curry)
- 业务关键路径中,可结合 JSDoc 注释或配置项明确参数预期


















