手写一个函数实现 add(2)(3) 和 add( 2, 3 )

看到别人在网上贴出来的笔试题,觉得很有趣,研究一下~

add(2, 3)

add(2, 3) 没什么好说,就是函数内两个参数相加。

function add(x, y) {
  return x + y
}
add(2, 3) // 5

但是你这样写是没有扩展性的,如果让你实现add(2, 3, 4)的话就要修改函数了。
所以,arguments了解一下。
arguments 是对应于传递给函数的参数,它是一个类数组对象。
你可以使用arguments对象在函数中引用函数的参数。此对象包含传递给函数的每个参数的条目,第一个条目的索引从0开始。
arguments对象不是一个 Array。它类似于Array,但除了length属性和索引元素之外没有任何Array属性。例如,它没有 pop方法。但是它可以被转换为一个真正的Array
var args = Array.prototype.slice.call(arguments)
实现:

function add () {
  var res = 0
  for (var i = 0; i < arguments.length; i++) {
    res = res + arguments[i]
  }
  return res
}
add(1, 2, 3) // 6
add(2)(3)

看到add(2)(3)的时候就觉得这肯定是需要返回一个函数的,返回的函数也就是add(2),于是思来想去加上各种尝试想到了一个笨办法。

function add(x) {
  let res = 0
  res = res + x
  return function (y) {
    res = res + y
    return res
  }
}
add(2)(3) // 5

这个办法是把函数的参数相加作为结果返回,并没有延伸性,如果想要得到add(2)(3)(4)的值,这段代码就不能用了,代码要改成如下

function add(x) {
  let res = 0
  res = res + x
  return function (y) {
    res = res + y
    return function (z) {
      res = res + z
      return res
    }
  }
}
add(2)(3)(4) // 9

很明显这么写是没有尽头的,仔细观察上面的代码,我们可以发现有重复的部分,函数add不断的返回函数,然后进行参数相加。

function add(x) {
  let res = 0
  res = res + x
  return function temp(y) {
    res = res + y
    return temp
  }
}

但是console.log(add(1)(2)(3))执行后发现返回的结果是一个函数,并不是我们想要的总和。
那么怎么把结果输出呢?

第一种方法

利用我们上面学习的arguments,判断参数输入,如果没有参数输入的话,就返回总和,而不是返回函数。

function add(x) {
  let res = 0
  res = res + x
  return function temp(y) {
    if (arguments.length === 0) {
      return res
    } else {
      res = res + y
      return temp
    }
  }
}

由于最后返回的是一个函数,所以调用的时候要这么调用
add(1)(2)(3)() // 6

第二种方法

第二种方法就是重写add函数的toStringvalueOf方法

function add(x) {
  let res = 0
  res = res + x
  var temp =  function (y) {
    res = res + y
    return temp
  }
  temp.toString = temp.valueOf = function() {
    return res
  }
  return temp
}
add(1)(2)(3) // 6

关于toString和valueOf的知识,比较多而且繁杂,就下一篇文章在讲啦~

你可能感兴趣的:(手写一个函数实现 add(2)(3) 和 add( 2, 3 ))