函数组合是函数式编程中非常重要的思想,它的实现的思路也没有特别复杂。
有两种函数组合的方式,一种是pipe
,另一种是compose
。前者从左向右组合函数,后者从右向左。
compose
概念
如果一个值要经过多个函数,才能变成另外一个值,就可以把所有中间步骤合并成一个函数,这就叫函数的合成(compose)。
合成的好处显而易见,它让代码变得简单而富有可读性,同时通过不同的组合方式,我们可以轻易组合 出其他常用函数,让我们的代码更具表现力。
function f1(arg) {
console.log("f1", arg);
return arg;
}
function f2(arg) {
console.log("f2", arg);
return arg;
}
function f3(arg) {
console.log("f3", arg);
return arg;
}
function compose(...funcs) {
if (funcs.length === 0) {
return arg => arg;
}
if (funcs.length === 1) {
return funcs[0];
}
return funcs.reduce((a, b) => (...args) => a(b(...args)));
}
let res = compose(f1, f2, f3)("omg"); //f1(f2(f3("omg")));
console.log("res", res);
const add = (x, y) => x + y
const square = z => z * z
const compose = (fn1, fn2) => (...args) => fn2(fn1(...args))
const fn = compose(add, square)
const fn = (x, y) => square(add(x, y))
console.log(fn(1, 2))
// express 中间件使用 compose 函数
function compose(middlewares){
return function(){
return dispatch(0)
function dispatch(i){
let fn = middlewares[i]
if(!fn){
return Promise.resolve()
}
return Promise.resolve(
fn(function next(){
return dispatch(i + 1)
})
)
}
}
}
async function fn1(next){
console.log('fn1')
await next()
console.log('end fn1')
}
async function fn2(next){
console.log('fn2')
await delay()
await next()
console.log('end fn2')
}
function fn3(next){
console.log('fn3')
}
function delay(){
return Promise.resolve(res => {
setTimeout(() => reslove(),2000)
})
}
const middlewares = [fn1,fn2,fn3]
const finalFn = compose(middlewares)
finalFn()
pipe
// 对于pipe()函数,当我们调用pipe(x, f1, f2)时,返回f2(f1(x))
function pipe(x, ...fns){
let accu= x;
for(let f in fns){
accu= f(accu)
}
return accu;
}
1