函数组合
函数组合(Function Composition)是将多个函数组合成一个新函数的过程,是函数式编程的核心技术之一。
什么是函数组合?
函数组合是将一个函数的输出作为另一个函数的输入,将多个简单函数组合成复杂函数。
// f(g(x)) 表示先执行 g,再执行 f
const compose = (f, g) => x => f(g(x));
// 示例
const add1 = x => x + 1;
const multiply2 = x => x * 2;
const add1ThenMultiply2 = compose(multiply2, add1);
add1ThenMultiply2(5); // (5 + 1) * 2 = 12
组合与管道
compose(从右到左)
const compose = (...fns) => x =>
fns.reduceRight((v, f) => f(v), x);
const transform = compose(
x => x.toUpperCase(),
x => x.trim(),
x => x.replace(/\s+/g, ' ')
);
transform(' hello world '); // 'HELLO WORLD'
pipe(从左到右)
const pipe = (...fns) => x =>
fns.reduce((v, f) => f(v), x);
const transform = pipe(
x => x.replace(/\s+/g, ' '),
x => x.trim(),
x => x.toUpperCase()
);
transform(' hello world '); // 'HELLO WORLD'
实际应用示例
数据处理管道
const users = [
{ name: 'John', age: 25, active: true },
{ name: 'Jane', age: 30, active: false },
{ name: 'Bob', age: 35, active: true }
];
const getActiveUsers = users => users.filter(u => u.active);
const getNames = users => users.map(u => u.name);
const sortNames = names => names.sort();
const joinNames = names => names.join(', ');
const processUsers = pipe(
getActiveUsers,
getNames,
sortNames,
joinNames
);
processUsers(users); // 'Bob, John'
验证管道
const isNotEmpty = x => x.length > 0;
const isEmail = x => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(x);
const isLongEnough = x => x.length >= 8;
const validate = pipe(
isNotEmpty,
isEmail,
isLongEnough
);
组合的优势
- 代码复用:小函数可以在多处组合使用
- 可读性:声明式代码更易理解
- 可测试性:纯函数易于单元测试
- 可维护性:修改单个函数不影响其他部分
组合的最佳实践
- 单一职责:每个函数只做一件事
- 纯函数:确保组合函数没有副作用
- 类型一致:确保函数输入输出类型匹配
- 适度组合:避免过长的组合链
Ramda 中的组合
const R = require('ramda');
const transform = R.pipe(
R.replace(/\s+/g, ' '),
R.trim,
R.toUpper
);
// 或使用 compose(从右到左)
const transform2 = R.compose(
R.toUpper,
R.trim,
R.replace(/\s+/g, ' ')
);