前置知识:
image.png
问题:使用 JS 来实现一个无线累加函数 add,参考如下:

  1. add(1); // 1
  2. add(1)(2); // 3
  3. add(1)(2)(3); // 6
  4. add(1)(2)(3)(4); // 10
  5. // 以此类推

toString() 来实现

  1. function add(a) {
  2. // 使用闭包
  3. function sum(b) {
  4. a = b ? (b + a) : a;
  5. return sum;
  6. }
  7. // 重写 toString 方法,只在最后一次调用
  8. sum.toString = function() {
  9. return a;
  10. }
  11. // 返回一个 sum 函数
  12. return sum;
  13. }
  14. add(1)(2)(3)(4)

运行结果:
image.png
解析:

  1. add函数内部定义 sum函数并返回,实现了连续调用;
  2. sum函数形成了一个闭包,每次调用进行累加值,再返回当前函数sum
  3. add()每次都会返回一个函数sum,直到最后一个没被调用。默认会触发 toString方法,所以这里重写 toString方法,并返回累计的最终值 a

**add(1)**,返回了一个未被调用的 sum函数,这时会执行 sum.toString重写的方法,返回值为 a。这时 sum函数没有执行。
**add(1)(2)**add(1) 返回了一个未被调用的 sum函数,等价于 sum(2) ,这时会执行 sum函数,形参为 2;add(1)(2)等价于一个未被调用的 sum函数,这时会执行 sum.toString 重写的方法,返回值为 a。

柯里化来实现多参累加

  1. function add() {
  2. // 1. 将所有参数转换为数组
  3. let args = Array.prototype.slice.call(arguments)
  4. // 2. 再次调用 add 函数,传递合并当前与之前的参数
  5. let fn = function() {
  6. console.log('fn 函数。。。')
  7. let arg_fn = Array.prototype.slice.call(arguments)
  8. return add.apply(null, args.concat(arg_fn))
  9. }
  10. // 3. 最后默认调用,返回合并的值
  11. fn.toString = function() {
  12. console.log('重写方法。。。')
  13. return args.reduce((prev, cur) => prev + cur)
  14. }
  15. return fn
  16. }
  17. /* ES6 改写 */
  18. function add() {
  19. // 1. 将所有参数转换为数组
  20. let args = [...arguments]
  21. // 2. 再次调用 add 函数,传递合并当前与之前的参数
  22. let fn = function() {
  23. console.log('fn 函数。。。')
  24. return add.apply(null, args.concat([...arguments]))
  25. }
  26. // 3. 最后默认调用,返回合并的值
  27. fn.toString = () => args.reduce((prev, cur) => prev + cur)
  28. return fn
  29. }
  30. add(1)(2)(3)(4)

运行结果:
image.png