回到课程

任意数量的括号求和

重要程度: 2

写一个函数 sum,它有这样的功能:

sum(1)(2) == 3; // 1 + 2
sum(1)(2)(3) == 6; // 1 + 2 + 3
sum(5)(-1)(2) == 6
sum(6)(-1)(-2)(-3) == 0
sum(0)(1)(2)(3)(4)(5) == 15

P.S. 提示:你可能需要创建自定义对象来为你的函数提供基本类型转换。

打开带有测试的沙箱。

  1. 为了使整个程序无论如何都能正常工作,sum 的结果必须是函数。
  2. 这个函数必须将两次调用之间的当前值保存在内存中。
  3. 根据这个题目,当函数被用于 == 比较时必须转换成数字。函数是对象,所以转换规则会按照 对象 —— 原始值转换 章节所讲的进行,我们可以提供自己的方法来返回数字。

代码如下:

function sum(a) {

  let currentSum = a;

  function f(b) {
    currentSum += b;
    return f;
  }

  f.toString = function() {
    return currentSum;
  };

  return f;
}

alert( sum(1)(2) ); // 3
alert( sum(5)(-1)(2) ); // 6
alert( sum(6)(-1)(-2)(-3) ); // 0
alert( sum(0)(1)(2)(3)(4)(5) ); // 15

请注意 sum 函数只工作一次,它返回了函数 f

然后,接下来的每一次子调用,f 都会把自己的参数加到求和 currentSum 上,然后 f 自身。

f 的最后一行没有递归。

递归是这样子的:

function f(b) {
  currentSum += b;
  return f(); // <-- 递归调用
}

在我们的例子中,只是返回了函数,并没有调用它:

function f(b) {
  currentSum += b;
  return f; // <-- 没有调用自己,只是返回了自己
}

这个 f 会被用于下一次调用,然后再次返回自己,按照需要重复。然后,当它被用做数字或字符串时 —— toString 返回 currentSum。我们也可以使用 Symbol.toPrimitive 或者 valueOf 来实现转换。

使用沙箱的测试功能打开解决方案。