今天分享一类比较容易错的题,多参数求和问题。
函数柯里化
先举个例子:要求实现下面的函数。
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
}
}
}