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 思路
  1. 要分別執行 f1,f2,f3 函數,而這些函數在 arguments 對象中。所以可以循環執行 arguments 對象。
  2. 因爲是從右到左執行。所以索引值應該是從大到小遞減的。
  3. 因爲是高階函數,所以在 compose 中會有一個閉包。而在這個閉包中的參數就是 arguments 對象中最右邊函數所需參數。
  4. 執行完最右邊函數,將結果保存下來作爲參數執行倒數第二個函數,以此類推。
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
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章