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
}