我正在查看@acdlite 编写的重组库中的compose
函数来为高阶组件组合边界条件,这就是 compose 函数的样子
const compose = (...funcs) => funcs.reduce((a, b) => (...args) => a(b(...args)), arg =>参数);
不过,我试过了Eric-Elliott的一种组合方法,来自 https://medium.com/javascript-scene/reduce-composing-software-fe22f0c39a1d ,具体来说就是这段代码。
const compose = (...fns) => x => fns.reduceRight((v, f) => f(v), x);
我试过在我的 React 组件中使用这两种变体,
const ListWithConditionalRendering = compose(
withLoadingIndicator,
withDataNull,
withListEmpty
)(Users);
而且它们似乎都工作正常。我无法理解上述功能的工作方式是否有任何差异,如果有,它们是什么。
最佳答案
对于非常小众的场景,有一些差异可能有助于了解。
第一个预组合一个函数,这意味着它调用reduce()
什么时候组成而不是什么时候被调用。相反,第二种方法返回一个调用 reduceRight()
的作用域函数。当它被调用时,而不是它被组合时。
第一个方法接受数组中最后一个函数的多个参数,而第二个方法只接受一个参数:
const compose1 = (...funcs) => funcs.reduce((a, b) => (...args) => a(b(...args)), arg => arg);
const compose2 = (...fns) => x => fns.reduceRight((v, f) => f(v), x);
const f = s => (...args) => (console.log('function', s, 'length', args.length), args);
compose1(f(1), f(2), f(3))(1, 2, 3);
compose2(f(4), f(5), f(6))(1, 2, 3);
如果函数数组非常大,因为它是预组合的,第一种方法可能会导致堆栈溢出,而第二种方法(相对)†堆栈安全:
const compose1 = (...funcs) => funcs.reduce((a, b) => (...args) => a(b(...args)), arg => arg);
const compose2 = (...fns) => x => fns.reduceRight((v, f) => f(v), x);
const f = v => v;
try {
compose1.apply(null, Array.from({ length: 1e5 }, () => f))();
console.log('1 is safe');
} catch (e) {
console.log('1 failed');
}
try {
compose2.apply(null, Array.from({ length: 1e5 }, () => f))();
console.log('2 is safe');
} catch (e) {
console.log('2 failed');
}
†如果...fns
,第二种方法仍然会导致堆栈溢出。太大因为arguments
也在栈上分配。
关于javascript - recompose 库中的 Compose 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53924558/