标准答案

  1. 柯里化可以把 fn(a, b, c) 转成 curried(a)(b)(c) 或 curried(a, b)(c) 这类调用形式。
  2. 实现核心是闭包保存已经收集的参数。
  3. 当收集参数数量达到原函数 arity 时,用这些参数调用原函数。
  4. 参数未收集够时,返回一个新函数继续收集后续参数。
  5. 实际实现还要考虑 this 绑定、默认参数、剩余参数和占位符等扩展能力。

题目解析

柯里化的本质是延迟执行和参数复用。比如固定某些通用参数后,得到一个更具体的新函数,后续调用只需要传剩下的参数。

手写题里常用 fn.length 判断需要几个参数,但它有边界:默认参数、rest 参数不会按直觉计入 length。所以回答时要说明这是常见简化版本。

柯里化和偏函数应用很接近,但不完全一样。柯里化强调把多参数函数转换成连续单参或分批传参形式,偏函数强调预先固定一部分参数。

代码示例

简化版 curry 根据 fn.length 判断参数是否收集完成。

JavaScript
function curry(fn, ...presetArgs) {
  return function curried(...nextArgs) {
    const args = [...presetArgs, ...nextArgs]

    if (args.length >= fn.length) {
      return fn.apply(this, args)
    }

    return curry(fn, ...args)
  }
}

常见误区

  • 只支持 curried(a)(b)(c),不支持 curried(a, b)(c) 这类分批传参。
  • 没有说明 fn.length 在默认参数和 rest 参数场景下的限制。
  • 实现时丢失 this,导致依赖调用上下文的函数行为变化。

作者信息