实现一个支持柯里化的 add 函数

实现一个灵活的 add 函数,支持多种调用方式和参数累加

问题

实现一个 add 函数,满足以下功能:

add(1)(2)(3) = 6
add(1, 2, 3)(4) = 10
add(1)(2)(3)(4)(5) = 15

这道题考察的是函数柯里化(Currying)和隐式类型转换的知识。需要实现一个可以连续调用的函数,每次调用都能累加参数,最终返回总和。

解答

function add(...args) {
  // 存储所有参数的总和
  let sum = args.reduce((acc, cur) => acc + cur, 0);
  
  // 返回一个新函数,用于继续接收参数
  function fn(...newArgs) {
    // 累加新参数
    sum += newArgs.reduce((acc, cur) => acc + cur, 0);
    return fn;
  }
  
  // 重写 valueOf 方法,用于隐式类型转换
  fn.valueOf = function() {
    return sum;
  };
  
  // 重写 toString 方法,用于字符串转换
  fn.toString = function() {
    return sum.toString();
  };
  
  return fn;
}

使用示例

// 示例 1:链式调用
console.log(add(1)(2)(3).valueOf()); // 6

// 示例 2:混合调用
console.log(add(1, 2, 3)(4).valueOf()); // 10

// 示例 3:多次链式调用
console.log(add(1)(2)(3)(4)(5).valueOf()); // 15

// 示例 4:隐式类型转换
console.log(add(1)(2)(3) == 6); // true
console.log(+add(1, 2, 3, 4)); // 10

// 示例 5:字符串拼接
console.log('结果是:' + add(10)(20)(30)); // "结果是:60"

// 示例 6:单次调用多个参数
console.log(add(1, 2, 3, 4, 5).valueOf()); // 15

关键点

  • 闭包机制:利用闭包保存累加的 sum 值,使得每次调用都能访问和更新这个值

  • 函数柯里化:返回的函数可以继续接收参数并返回自身,实现链式调用

  • 隐式类型转换:重写 valueOftoString 方法,使函数在需要转换为原始值时自动返回累加结果

  • 剩余参数:使用 ...args 语法支持一次传入多个参数

  • reduce 累加:使用 reduce 方法简洁地实现参数求和

  • 返回函数本身:每次调用返回 fn 自身,保证可以继续链式调用