什么是柯里化函数
引用百度百科中对柯里化的解释
柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。
用经典的加法器来举例
function add(a, b) {
return a + b;
}
add(1, 2); // 3
这是一个最简单的加法函数,作用是把传入的a,b两个参数相加并把相加后的结果返回。
下面我们用柯里化的思想对这个函数进行改写。
function add(a) {
return function (b) {
return a + b;
};
}
add(1)(2); // 3
柯里化的思想就是要求我们把需要接受两个参数的函数改写成了接受一个参数并返回一个函数来接受第二个参数。
上面只是一个简单的例子,如果我们要执行add(1)(2)(3)
这样的函数呢?
实现一个通用的累加器
首先我们要实现柯里化函数就需要把之前的每个参数保存起来,上面的方法通过闭包实现了对参数的保存,下面我们需要的就是通过不断的接受参数返回函数处理剩下的参数即可。
function add(...outer) {
function innerAdd(...inner) {
return add(...outer, ...inner);
}
return innerAdd;
}
这里我们用递归的思想,创建一个innerAdd
函数,这个函数用来接受剩下的参数,并返回add
函数且将之前的参数与当前的参数合并起来执行。而add
函数则返回innerAdd
这个函数体。
举个例子
console.log(add(1)(2)(3));
// 1.add(1)
// 2.innerAdd(2)
// 3.add(1,2)
// 4.inner(3)
// 5.add(1,2,3)
// 6.inner
第一步:我们执行了add(1)
这个函数,返回结果是innerAdd
第二步:返回的innerAdd
遇到了(2)
,所以立马执行innerAdd(2)
这个函数
第三步:innerAdd(2)
执行后返回了add(1,2)
,这里用扩展运算符把上一次和本次的参数合并
第四步:add(1,2)
又返回了innerAdd
第五步:同第三步,此时返回了add(1,2,3)
第六步:add(1,2,3)
执行完后返回innerAdd
这个函数体
我们最终的目的是要将1,2,3累加起来,第六步中add的参数就是我们需要的所有值,但此时返回的是innerAdd
函数体,所有打印的结果是这个函数而不是我们想要的6。
因为返回的innerAdd
会自动的调用toString方法,所以我们可以通过改写toString来实现输出我们想要的结果。
function add(...outer) {
function innerAdd(...inner) {
return add(...outer, ...inner);
}
innerAdd.toString = function () {
let result = 0;
for (let i = 0; i < outer.length; i++) {
result += outer[i];
}
return result;
}
return innerAdd;
}
console.log(add(1)(2)(3));
我们用箭头函数和reduce函数来简化代码,最终可以把这个累加器写成下面这样
function add(...outer) {
let innerAdd = (...inner) => add(...outer, ...inner);
innerAdd.toString = () => outer.reduce((pre, cur) => pre + cur);
return innerAdd;
}