闭包的应用--多参数求和问题

212 阅读1分钟

今天分享一类比较容易错的题,多参数求和问题。

函数柯里化

先举个例子:要求实现下面的函数。

const add=(x,y,z)=>x+y+z;
const curryAdd=curry(add)
console.log(curryAdd(2)(2,2));//6
console.log(curryAdd(2,2)(2));//6
console.log(curryAdd(2)(2)(2));//6

对于这样一道题,很明显的要使用函数柯里化,函数柯里化简单来说就是把一个多参数的函数转化为单参数的函数。

function curry(fn,...args){
    if(fn.length<=args.length){
    return fn(...args);
    }else{
        return (...rest)=>{
            return curry(fn,...args,...rest);
        }
    }
}

对于curry函数,我想介绍两个点。

函数的length

对于curry函数里的fn.length,这个意思是函数的参数个数。我们来看下面的几个例子:

function a(x, y, z) { }
console.log(a.length);

function b(x, y = 1, z) { }
console.log(b.length);

function c(x, ...args) { }
console.log(c.length);

对于这三个函数的length,你认为的答案是什么呢?

3
1
1

fn.length属性指名函数的形参个数且形参的数量不包括剩余参数个数,仅包括 “第一个具有默认值之前的参数个数”。这里做个小科普,本文的重点不在这。

curry函数哪里用到了闭包?

闭包就是一个函数可以访问甚至操作其他函数的作用域中的变量。循环调用curry时,curry有对rest的引用,这就是闭包的体现。

实现一个随意的求和函数

 console.log(sum(1,2)(3)(4)(5,6,7)());//28

这道题一上手很多人都会认为这还是函数柯里化,可是题目要求的是不限参数个数的求和函数。所以不能使用函数柯里化了,但是仍然可以使用闭包的思想。

function sum(...rest) {
  let args = rest;
  if (args.length === 0) return 0;
  return function recursionSum(...rest) {
    args = args.concat(...rest)
    if (rest.length === 0) {
      return args.reduce((pre, cur) => pre + cur)
    } else {
      return recursionSum
    }
  }
}