实现 compose 和 pipe 函数
手写函数组合 compose 和 pipe
问题
实现函数式编程中的 compose 和 pipe 函数,用于将多个函数组合成一个函数。
解答
实现 compose
compose 从右到左执行函数,即最后一个参数最先执行。
// 基础版本:使用 reduceRight
function compose(...fns) {
// 没有函数时返回恒等函数
if (fns.length === 0) return (arg) => arg;
// 只有一个函数时直接返回
if (fns.length === 1) return fns[0];
// 从右到左依次执行
return function (arg) {
return fns.reduceRight((result, fn) => fn(result), arg);
};
}
// 简洁版本
const compose2 = (...fns) =>
fns.reduceRight(
(prev, next) =>
(...args) =>
next(prev(...args)),
(x) => x
);
实现 pipe
pipe 从左到右执行函数,即第一个参数最先执行。
// 基础版本:使用 reduce
function pipe(...fns) {
if (fns.length === 0) return (arg) => arg;
if (fns.length === 1) return fns[0];
// 从左到右依次执行
return function (arg) {
return fns.reduce((result, fn) => fn(result), arg);
};
}
// 简洁版本
const pipe2 = (...fns) =>
fns.reduce(
(prev, next) =>
(...args) =>
next(prev(...args)),
(x) => x
);
使用示例
// 定义几个简单函数
const add10 = (x) => x + 10;
const multiply2 = (x) => x * 2;
const subtract5 = (x) => x - 5;
// compose: 从右到左执行
// subtract5(multiply2(add10(5))) = subtract5(multiply2(15)) = subtract5(30) = 25
const composedFn = compose(subtract5, multiply2, add10);
console.log(composedFn(5)); // 25
// pipe: 从左到右执行
// subtract5(multiply2(add10(5))) 变成 add10 -> multiply2 -> subtract5
// add10(5) = 15 -> multiply2(15) = 30 -> subtract5(30) = 25
const pipedFn = pipe(add10, multiply2, subtract5);
console.log(pipedFn(5)); // 25
支持异步的版本
// 异步 compose
const composeAsync =
(...fns) =>
(arg) =>
fns.reduceRight((promise, fn) => promise.then(fn), Promise.resolve(arg));
// 异步 pipe
const pipeAsync =
(...fns) =>
(arg) =>
fns.reduce((promise, fn) => promise.then(fn), Promise.resolve(arg));
// 使用示例
const fetchUser = async (id) => ({ id, name: 'John' });
const getName = (user) => user.name;
const toUpperCase = (str) => str.toUpperCase();
const getUserName = pipeAsync(fetchUser, getName, toUpperCase);
getUserName(1).then(console.log); // 'JOHN'
关键点
compose从右到左执行,pipe从左到右执行compose用reduceRight,pipe用reduce- 处理边界情况:空函数数组返回恒等函数
- 异步版本使用
Promise.resolve包装初始值,用.then链式调用
目录