实现一个compose函数
实现函数组合工具,将多个函数从右到左依次执行,前一个函数的返回值作为后一个函数的参数
问题
compose函数是函数式编程中的重要概念,它可以将多个函数组合成一个函数。执行顺序是从右到左,即最右边的函数先执行,其返回值作为左边函数的参数,依次类推。
例如:compose(f, g, h)(x) 等价于 f(g(h(x)))
解答
/**
* 实现compose函数 - 基础版本
* @param {...Function} fns 需要组合的函数列表
* @returns {Function} 组合后的函数
*/
function compose(...fns) {
// 边界情况:如果没有传入函数,返回一个恒等函数
if (fns.length === 0) {
return arg => arg;
}
// 如果只有一个函数,直接返回该函数
if (fns.length === 1) {
return fns[0];
}
// 使用reduce从右到左组合函数
return fns.reduce((a, b) => (...args) => a(b(...args)));
}
/**
* 实现compose函数 - 展开版本(更易理解)
*/
function compose2(...fns) {
return function(...args) {
// 从右到左执行函数
let result = fns[fns.length - 1](...args);
for (let i = fns.length - 2; i >= 0; i--) {
result = fns[i](result);
}
return result;
};
}
/**
* 实现compose函数 - reduceRight版本
*/
function compose3(...fns) {
if (fns.length === 0) {
return arg => arg;
}
if (fns.length === 1) {
return fns[0];
}
return function(...args) {
// 使用reduceRight从右到左执行
return fns.reduceRight((result, fn, index) => {
// 最右边的函数可以接收多个参数
return index === fns.length - 1 ? fn(...result) : fn(result);
}, args);
};
}
使用示例
// 示例1:基础使用
const add = x => x + 10;
const multiply = x => x * 2;
const subtract = x => x - 5;
const calculate = compose(add, multiply, subtract);
console.log(calculate(10)); // 20
// 执行过程:subtract(10) = 5 -> multiply(5) = 10 -> add(10) = 20
// 示例2:字符串处理
const toUpperCase = str => str.toUpperCase();
const exclaim = str => str + '!';
const split = str => str.split('');
const processString = compose(split, exclaim, toUpperCase);
console.log(processString('hello'));
// ['H', 'E', 'L', 'L', 'O', '!']
// 示例3:数据处理管道
const users = [
{ name: 'Alice', age: 25, active: true },
{ name: 'Bob', age: 30, active: false },
{ name: 'Charlie', age: 35, active: true }
];
const getActiveUsers = users => users.filter(u => u.active);
const getNames = users => users.map(u => u.name);
const joinWithComma = names => names.join(', ');
const getActiveUserNames = compose(
joinWithComma,
getNames,
getActiveUsers
);
console.log(getActiveUserNames(users)); // "Alice, Charlie"
// 示例4:数学运算
const double = x => x * 2;
const square = x => x * x;
const addOne = x => x + 1;
const compute = compose(square, double, addOne);
console.log(compute(3)); // 64
// 执行过程:addOne(3) = 4 -> double(4) = 8 -> square(8) = 64
关键点
-
执行顺序:compose函数从右到左执行,这与数学中的函数组合概念一致
f(g(x)) -
reduce实现:使用
reduce方法可以优雅地实现函数组合,是(a, b) => (...args) => a(b(...args)) -
参数传递:最右边的函数可以接收多个参数,中间函数只接收前一个函数的返回值
-
边界处理:需要处理没有函数或只有一个函数的情况
-
与pipe的区别:pipe函数是从左到右执行,compose是从右到左执行,两者互为镜像
-
应用场景:
- 数据处理管道
- 中间件机制(如Redux中间件)
- 函数式编程中的代码复用
- 提高代码可读性和可维护性
-
性能考虑:每次调用都会创建新的函数闭包,对于高频调用场景需要注意性能优化
目录