柯里化 & 重写toString

3,229 阅读1分钟

题目

add(1)  //1
add(1)(2) //3
add(1,2)(3) //6
add(1)(2,3) //6
add(1)(2)(3) //6
//...等等,自由组合都行

解答

function add() {
  let args = [...arguments]
  let fn = function  () {
    args.push(...arguments)
    return fn
  }
  fn.toString = function () {
    return args.reduce((x,y) => x+y)
  }
  return fn
}

解析

  • 柯里化是一个逐步接收参数的过程,可以理解为提前接收部分参数,延迟执行,不立即输出结果,而是返回一个接受剩余参数的函数。
  • toString和valueOf方法在一些语境下是自动调用的

1. 根据柯里化的思想,以下实现是很容易被理解的

function add() {
    let args = [...arguments]
    let fn = function () {
        if(arguments.length > 0) {
            args.push(...arguments)
            return fn
        } else {
            // 递归函数的结束
            return args.reduce((x, y) => x + y)
        }
    }
    return fn
}

// 但是这个只能实现以()为结尾的
// 类似于add(1)()、add(1, 2)(3)()

2. 解释一下toString,valueOf类似,结合1、2就是答案的结果了

let fn = function(){}
fn.toString = function(){
    return 1
}
fn
f 1  //console控制台输出结果,可以理解为是一个‘值’为1的function

个人理解

其实我一直很疑惑答案中的递归没有结束啊,为什么可以输出结果呢???拿饭的时候突然想通了,果然唯美食不可辜负…

我个人理解的是这样:
  其实就是没有结束啊,最后返回的是一个值为 sum 的函数啊,这个函数还可以被调用,而值为sum的原因是因为string被重写了,所以就假装自己的值是1。
  根据toString方法在一些语境下的自动调用,最后返回的那个结果就以假乱真了。
  // 注:sum代表累加后的值

参考文章

柯里化-反柯里化JS类型转换