怎么理解函数组合
compose(f, g, t) => x => f(g(t(x))
函数组合,字面意思将多个函数有序组合起来。有序组合的原因是不同的顺序返回的函数是不同函数。
var { compose } = require('ramda')
const f = x => x + 1;
const g = x => x * 2;
const fg1 = compose(f, g);
const fg2 = compose(g, f);
console.log(fg1(4)) // 9
console.log(fg2(4)) // 10
解释一下,函数组合执行的顺序是从右向左。
fg1:(4 * 2) + 1 = 9
fg2:(4 + 1) * 2 = 10
上面的ES5代码执行
var compose = function(f,g) {
return function(x) {
return f(g(x));
};
};
当然这种写法不完善,因为只支持两个函数的输入。
手写函数组合
分解
- 返回高捷函数
- 高阶函数可以从右往左依次执行方法,并且将上一个方法的返回值传入到下一个方法中。
这个依次执行的方式可以想到的reduce和reduceRight方法,reduce方法就是将前一次循环得到的结果当成下次循环执行的参数。
手写版本
var compose = function() {
const funcArray = [...arguments];
return function () {
return funcArray.reduceRight(
(arg, fn) => {
return fn.apply(null, [].concat(arg)) // 这里使用这个是因为第一个执行的函数可能存在两个参数(最右边的函数)
},
[...arguments]
)
}
}
高颜值版本
var compose = (...fns) => (...args) => fns.reduceRight((arg, fn) => fn.apply(null, [].concat(arg)), args)
underscore 的 compose 函数
function compose() {
var args = arguments;
var start = args.length - 1;
return function() {
var i = start;
var result = args[start].apply(this, arguments);
while (i--) result = args[i].call(this, result);
return result;
};
};
redux 中 compose
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)))
}
理解一下:
function compose(...funcs) {
if (funcs.length === 0) {
return arg => arg
}
if (funcs.length === 1) {
return funcs[0]
}
return funcs.reduce((a, b) => {
return (...args) => {
return a(b(...args))
}
})
}
const f = x => x + 1;
const g = x => x * 2;
const h = x => x + 3;
let fg1 = compose(f, g, h);
let g2 = compose(h, g, f);
console.log(fg1(4))
console.log(fg2(4))
函数组合执行是从右向左的,reduce则是从左向右形成高阶函数。
let fg1 = compose(f, g, h);
return function(arg) {
return f(g(h(arg)))
}
Ramda中的pipe【从左到右的组合】
var { compose, pipe } = require('ramda')
const f = x => x + 1;
const g = x => x * 2;
const fg1 = compose(f, g);
const fg2 = pipe(g, f);
console.log(fg1(4)) // 9
console.log(fg2(4)) // 9
应用
react高阶函数使用
withRoute(observer(inject('Store')(Index)))
const enhance = compose(withRoute, observer, inject('Store'));
enhance(Index);
参照
- https://github.com/mqyqingfeng/Blog/issues/42
- https://juejin.cn/post/6844903936378273799#heading-14