如何实现 compose 函数,进行函数合成
更多描述 实现一个 compose 函数,进行函数合成,比如 redux 中的 compose,react 高阶组件连续调用时的 compose
const add10 = (x) => x + 10;
const mul10 = (x) => x * 10;
const add100 = (x) => x + 100;
// (10 + 100) * 10 + 10 = 1110
compose(add10, mul10, add100)(10);
Issue 欢迎在 Gtihub Issue 中回答此问题: Issue 182
Author 回答者: RainMaker-Q
function compose() {
let fns = [...arguments];
return function() {
let args = [...arguments];
let result = fns.reduce((ret, fn) => {
ret = fn.apply(this, ret);
return Array.isArray(ret) ? ret : [ret];
}, args);
return result;
}
}
let toUpperCase = (x) => x.toUpperCase();
let exclaim = (x) => x + '!';
let shout = compose(toUpperCase,exclaim);
let str = shout('hello world');
console.log(str);
第一次试着写,简单查了一下compose是什么意思,竟然拼凑出来了。请各位指正。 :smile:
Author 回答者: RainMaker-Q
看到一种新实现
function compose(...fns) {
fns.reduce( (a, b) => (...args) => a(b(...args)));
}
Author 回答者: nieyao
const compose = (…fns) => (…params) => fns.reduce((prev, current) => current(prev), …params);
Author 回答者: shfshanyue
实现一个从右向左(right to left)计算的组合函数:
const compose = (...fns) =>
// 注意 f、g 的位置,如果实现从左到右计算,则置换顺序
fns.reduce(
(f, g) =>
(...args) =>
f(g(...args)),
);
跑一个示例
const add5 = (x) => x + 5;
const multiply = (x) => x * 10;
const multiply10AndAdd5 = compose(add5, multiply);
multiply10AndAdd5(10); // 105
在 Redux
中广泛使用了 compose
函数,其中的实现如下
export default function compose(...funcs: Function[]) {
if (funcs.length === 0) {
// infer the argument type so it is usable in inference down the line
return <T>(arg: T) => arg;
}
if (funcs.length === 1) {
return funcs[0];
}
return funcs.reduce(
(a, b) =>
(...args: any) =>
a(b(...args)),
);
}
Author 回答者: shfshanyue
@nieyao params 应该置后,测试示例时没有通过
Author 回答者: nieyao
@nieyao params 应该置后,测试示例时没有通过
确实,忘了compose是从右往左执行的,那加个reverse 好了。 const compose = (…fns) => (…params) => fns.reverse().reduce((prev, current) => current(prev), …params) 或者用reduceRight const compose = (…fns) => (…params) => fns.reduceRight((prev, current) => current(prev), …params)
Author 回答者: Kiera569
function compose(...fn) {
return (...args) =>
fn
.reverse()
.slice(1)
.reduce((acc, cur) => cur(acc), fn[0](...args));
}
Author 回答者: maolovecoding
这种方式更优雅
const compose = (...fns) =>
fns.reduceRight(
(prev, next) =>
(...args) =>
prev(next(...args)),
);
Author 回答者: kirazZ1
之前看了koa的compose实现,先入为主了,感觉写的没上面的优雅,不过能过用例:
function compose(...args) {
const length = args.length;
function dispatch(index, val) {
if (index === length) return val;
else {
args = args || [];
return args[index](dispatch(index + 1, val));
}
}
return (init) => dispatch(0, init);
}
Author 回答者: Hazel-Lin
const compose =
(...fns) =>
(params) =>
fns.reduce((prev, cur) => ((prev = cur(prev ?? params)), prev), null);
看了大佬的实现,感觉我的实现突然不香了