概念
compose函数: 将需要嵌套执行的函数平铺。
嵌套执行指的是:一个函数的返回值将作为另一个函数的参数。
其实compose在函数式编程中,就是将几个有特点的函数拼凑在一起,让他们结合产生一个崭新的函数
compose函数作用:实现函数式编程中的Pointfree,使我们专注于转换而不是数据。
也就是说,我们可以把数据处理的过程定义成一种与参数无关的合成运算,不需要用到代表数据的那个参数,只要把一些简单的运算步骤合成在一起即可。
Pointfree指的是:不使用所要处理的值,只合成运算过程,即所谓的无参数分割
compose参数函数的调用是从右往左,webpack的loader也是从右往左,因为它使用了compose函数。
示例
我们现在有这么一个需求:求一个数值先加10再乘10 的结果。
命令式方式
let fn = x => (x + 10) * 10
console.log(fn(10)); // 200
初级FP
将所要执行的动作进行分解,动作1(add):+10,动作2(multi):*10
const add = x => x + 10
const multi = x => x * 10;
console.log(multi(add(10))) // 200
初级compose
使用compose函数将add与multi整合,并确保其从右往左执行
const add = x => x + 10
const multi = x => x * 10;
const compose = (f, g) => {
return x => {
return f(g(x))
}
}
console.log(compose(multi, add)(10)) // 200
当然这个compose函数没有通用性,只能接受两个参数,下面我们进行改造
通用compose
使用reduce函数对参数函数进行累计执行,因为是从右向左执行,所以使用reduceRight
const add = x => x + 10
const multi = x => x * 10;
const compose = function() {
const args = [].slice.call(arguments);
return function(x) {
return args.reduceRight(function(res, cb) {
return cb(res)
}, x)
}
}
console.log(compose(multi, add)(10)) // 200
终极compose
使用箭头函数对compose函数再次进行简化
const compose = function() {
const args = [ ...arguments ];
return x => args.reduceRight((res, cb) => cb(res), x)
}
注意:箭头函数与arguments
如果上边的代码写成这样,是会报错的:
const compose = () => {
const args = [ ...arguments ];
return x => args.reduceRight((res, cb) => cb(res), x)
}
因为箭头函数是没有绑定Arguments对象的,所以这里的arguments是拿不到正确的值的。
我们可以使用…剩余运算符解决这个问题:
const compose = (...args) => x => args.reduceRight((res, cb) => cb(res), x)
这就是终极compose函数。