在函数式编程当中有一个很重要的概念就是函数组合, 实际上就是把处理数据的函数像管道一样连接起来, 然后让数据穿过管道得到最终的结果。 例如:
const add1 = (x) => x + 1;
const mul3 = (x) => x * 3;
const div2 = (x) => x / 2;
div2(mul3(add1(0))); //=>3
而这样的写法可读性明显太差了,我们可以构建一个compose函数,它接受任意多个函数作为参数(这些函数都只接受一个参数),然后compose返回的也是一个函数,达到以下的效果:
const operate = compose(div2, mul3, add1)
operate(0) //=>相当于div2(mul3(add1(0)))
operate(2) //=>相当于div2(mul3(add1(2)))
简而言之:compose可以把类似于f(g(h(x)))这种写法简化成compose(f, g, h)(x),请你完成 compose函数的编写
练习题:
将第一个函数得到的返回值当作实参传递给第二个函数,依次这样传递下去。
const add1 = x => x + 1;
const mul3 = x => x * 3;
const div2 = x => x / 2;
var result = div2(mul3(add1(0)));
console.log(result); //->1.5
习题解析:
funcs:存储的是最后需要执行的函数及其顺序(最后传递的函数优先执行)
- 执行compose只是把最后要执行的函数及顺序事先存储起来,函数还没有执行「柯理化思想」
- 返回一个operate处理函数,执行operate,并且传递初始值,才按照之前存储的函数及顺序依次执行函数
const add1 = x => x + 1;
const mul3 = x => x * 3;
const div2 = x => x / 2;
function compose(...funcs) {
return function operate(x) {
//一个函数都不传,直接返回初始值
if (funcs.length === 0) return x;
//只传递一个参数,判断是否是函数,是函数直接执行,不是函数直接返回初始值
if (funcs.length === 1) return typeof funcs[0] === "function" ? funcs[0](x) : x;
//后传递的函数先执行,reduceRight()从右开始先循环遍历
return funcs.reduceRight(function (result, item) {
//item不是函数直接跳过,返回值
if (typeof item !== "function") return result;
//item是函数就直接将上一次的返回结果当作实参传递给当前这个item函数
return item(result);
}, x);
};
}
var operate = compose(div2, mul3, add1);
var result = operate(0);
console.log(result);//1.5
思考题:node_modules中的compose.js函数,研究这个是如何实现的
function compose(...funcs) {
if (funcs.length === 0) {
return arg => arg
}
if (funcs.length === 1) {
return funcs[0]
}
return funcs.reduce((a, b) => (...args) => a(b(...args)))
}
初步分析如下:
function compose(...funcs) {
if (funcs.length === 0) {
return arg => arg
}
if (funcs.length === 1) {
return funcs[0]
}
return funcs.reduce(function(a,b){
return function(...args){
return a(b(...args));
}
});
//return funcs.reduce((a, b) => (...args) => a(b(...args)))
}