看一个题，谁能帮忙解释一下？这是一个关于reduce递归
看以下题目：
```
var f = (function() {
    let r = 1;
    return function(...args){
        r *= args.reduce((p, n) => p + n);
        f.valueOf = () => r;    // 主要是这句代码，完全懵B
        return f;
    }
}());
+f(1,2,3)(2,3)(3,4,5)(6,7)
// 输出值为(1+2+3)*(2+3)*(3+4+5)*(6+7)的计算结果
```
考虑到用到的知识点

1. reduce
2. valueOf
3. 递归
4. ...（涉及的没提到的）
1  `reduce` 配合 `args` 解构用来求每一个圆括号里面的和
```
const sum = (...args) => args.reduce((i, j) => i + j)
```
2  每次圆括号执行`f`都会再返回这个`f`，保证了这个`f`后面可以跟上无限多个圆括号
```
var j = (function() {
  return function () {
    console.log('yo')
    return j
  }
}())

j()()()() // yo yo yo yo
```
3  立即执行函数保证了每有一个圆括号都立即、顺序执行
```
var f = function() {
    let r = 1
    return function f(...args){
        r *= args.reduce((p, n) => p + n)
        console.log(args) // 第一个圆括号就不执行了
        f.valueOf = () => r
        return f
    }
}
```
4  如果你只想得到返回的 `f` 函数，或者是只想让这个 `r` 存在于各个层级 `f` 的上下文中的话，`valueOf` 都没有出现的意义，但是如果你想从 `f()()()` 中把 `r` 取出来，就需要 `valueOf` 了。最后的加号会用到他，这里就返回当前上下文中的 `r`。
```
var f = (function() {
    let r = 1
    return function f(...args){
        r *= args.reduce((p, n) => p + n)
        if (args.length == 2) return r // 如果你能找另外一个方式把 r 输出也是可以的
        return f
    }
}())
console.log(f(1,2,3)(2,3,5)(3,4,5)(6,7))
```