compose 函数与 pine 函数
1. compose 函数
1.1 概念
compose 函数是从右往左执行。compose 函数是一个高阶函数,第一阶参数分别为不同的函数,第二阶参数为第一阶参数中最右边的函数所需参数,执行最右边函数之后,将其返回值作为参数执行右边倒数第二个函数,再将其返回值作为参数,执行右边倒数第三个函数,以此类推。直到执行完所有函数,并返回第一个函数的执行结果。
1.2 案例
如:compose(f1,f2,f3)(1,2)
function f1(a){
return a+10
}
function f2(a){
return a+10
}
function f3(a,b){
return a+b
}
1.3 分析
首先 compose 函数的第二阶参数(1,2)
作为参数调用第一阶参数最右边函数也就是f3
。返回值为3
。
其次将3
作为参数执行右边倒数第二个函数f2
。返回值为 3+10=13
;
最后将13
作为参数执行最后一个函数f1
。返回值为 13+10=23
;
1.4 实现 compose 函数
1.4.1 思路
- 要分别执行 f1,f2,f3 函数,而这些函数在 arguments 对象中。所以可以循环执行 arguments 对象。
- 因为是从右到左执行。所以索引值应该是从大到小递减的。
- 因为是高阶函数,所以在 compose 中会有一个闭包。而在这个闭包中的参数就是 arguments 对象中最右边函数所需参数。
- 执行完最右边函数,将结果保存下来作为参数执行倒数第二个函数,以此类推。
1.4.2 方案
使用循环:
function compose(...args) {
var index = args.length-1;
var result;
return function (...arg) {
result = args[index].apply(this,arg);
while (index>0){
index--;
result = args[index].apply(this,[result]);
}
return result;
}
}
使用 reduce:
function compose(...args) {
return args.reduce((a, b)=> {
//在执行 args.reduce 时分别存储了
//a(f0),b(f1) | a(f...),b(f2) | a(f...),b(f3)
//到后面的闭包内。所以执行闭包的时候最开始 b 就是f3,到最后 a 就是f0。
return function (...arg) {
return a(b(...arg));
}
})
}
2. pipe 函数
pipe 函数与 compose 函数相反,是从左到右执行。
比如当调用 pipe(x, f1, f2) 时,返回f2(f1(x))。
实现方案也有两种。
使用循环:
function pipe(x, ...fns){
let total = x;
for(let f of fns){
total = f(total)
}
return total;
}
使用 reduce:
const pipe = function(x, ...fns) {
fns.reduce((y, f) => f(y), x);
}
测试:
pipe(10, f1, f2) === 30
function f1(a){
return a+10
}
function f2(a){
return a+10
}