请你编写一个函数,它接收一个函数数组 [f1, f2, f3,…, fn] ,并返回一个新的函数 fn ,它是函数数组的 复合函数 。
[f(x), g(x), h(x)] 的 复合函数 为 fn(x) = f(g(h(x))) 。
一个空函数列表的 复合函数 是 恒等函数 f(x) = x 。
你可以假设数组中的每个函数接受一个整型参数作为输入,并返回一个整型作为输出。
方式一
/**
* @param {Function[]} functions
* @return {Function}
*/
var compose = function(functions) {
if (functions.length === 0) {
return function(x) {
return x;
};
}
return functions.reduceRight((acc, curr) => {
return function(x) {
return curr(acc(x));
};
}, x => x);
};
/**
* const fn = compose([x => x + 1, x => 2 * x])
* fn(4) // 9
*/
方式二
/**
* @param {Function[]} functions
* @return {Function}
*/
var compose = function(functions) {
if (functions.length === 0) {
return x => x;
}
const firstFn = functions[0];
const restFunctions = functions.slice(1);
const innerCompose = compose(restFunctions);
return function(x) {
return firstFn(innerCompose(x));
};
};
// 反转函数数组以符合从右向左执行的要求
var reverseCompose = function(functions) {
return compose(functions.reverse());
};
const reversedComposedFn = reverseCompose([x => x + 1, x => x * x, x => 2 * x]);
24console.log(reversedComposedFn(4)); // 输出:65
当然,很高兴为您详细解释这些代码段:
- 第一部分:
const innerCompose = compose(restFunctions);
return function(x) {
return firstFn(innerCompose(x));
};
这部分是在递归地构建复合函数的核心逻辑。compose函数首先检查functions数组的长度,如果长度不为0,则提取第一个函数firstFn和剩余的函数数组restFunctions。然后,对restFunctions调用compose函数,生成一个内部复合函数innerCompose,这个内部复合函数代表的是除第一个函数之外的所有函数的复合结果。
之后返回一个新的匿名函数(闭包),这个匿名函数接受一个参数x,并调用innerCompose(x)得到中间结果,再将这个中间结果传递给firstFn进行计算。这样就实现了从左到右的函数组合。
- 第二部分:
var reverseCompose = function(functions) {
return compose(functions.reverse());
};
为了满足题目要求的从右向左执行函数的需求,我们新增了reverseCompose函数。这个函数接收一个函数数组functions,并对其调用数组的reverse方法,使得函数数组的顺序反转过来,即变为从后往前的顺序。
然后,对反转后的函数数组调用compose函数,这样就能保证最终生成的复合函数是从右向左执行各函数的。所以在后续的测试用例中,我们调用reverseCompose函数来创建复合函数,从而得到正确的输出结果。