函數組合是函數式編程中很是重要的思想,它的實現的思路也沒有特別複雜。有兩種函數組合的方式,一種是pipe
,另外一種是compose
。前者從左向右組合函數,後者方向相反。
下面就是一個最簡單的能夠組合兩個函數的composejavascript
let compose = (f, g) => (...args) => f(g(...args));
在實際應用中,只能組合兩個函數的組合函數顯然不能知足要求,咱們須要能夠組合任意個函數的組合函數。下面提供兩種思路。java
兩種方法一種是遞歸,一種是循環,其實都是同樣的。具體的思路就是,先寫一個組合能夠兩個函數的compose2,用compose2先把傳進來的末尾的兩個函數組合了,返回一個函數func,而後再compose2把func和傳進來的下一個函數組合起來,以此類推。git
循環的方法github
let compose2 = (f, g) => (...args) => f(g(...args)); let compose = (...funcArgs) => (...args) => { let funced = funcArgs[funcArgs.length - 1]; for (let i = funcArgs.length - 2; i >= 0; i--) { if (i === 0) { return compose2(funcArgs[i], funced)(...args); } funced = compose2(funcArgs[i], funced); } } // 與compose組合方向相反的函數組合函數 let pipe = (...funcArgs) => compose(...funcArgs.reverse());
遞歸的方法編程
let compose2 = (f, g) => (...args) => f(g(...args)); let compose = (...funcArgs) => (...args) => { let [...funcArgsCopy] = funcArgs; let callSelf = func => { if (funcArgsCopy.length === 0) return func; let funced = compose2(funcArgsCopy.pop(), func); return callSelf(funced); } return callSelf(funcArgsCopy.pop())(...args); } let pipe = (...funcArgs) => compose(...funcArgs.reverse());
上面的思路仍是有點麻煩,其實不用糾結在組合,直接把前一個函數的處理參數以後的返回值傳給下一個函數就能夠了。
循環的方法數組
let compose = (...funcArgs) => (...args) => { for (let i = funcArgs.length - 1; i >= 0; i--) { args = i === funcArgs.length - 1 ? funcArgs[i](...args) : funcArgs[i](args); } return args; } let pipe = (...funcArgs) => compose(...funcArgs.reverse());
遞歸的方法函數式編程
let compose = (...funcArgs) => (...args) => { let [...funcArgsCopy] = funcArgs; let funced = (...func) => { if (funcArgsCopy.length === 0) return func[0]; func = funcArgsCopy.pop()(...func); return funced(func); } return funced(...args); } let pipe = (...funcArgs) => compose(...funcArgs.reverse());
我在github https://github.com/zhuanyongx...函數