函数式工具库
除了原生 JavaScript 方法,还有许多优秀的函数式编程库可以简化开发。
Lodash/FP
Lodash 的函数式编程版本,所有函数都自动柯里化。
const fp = require('lodash/fp');
// 自动柯里化
const mapDouble = fp.map(x => x * 2);
mapDouble([1, 2, 3]); // [2, 4, 6]
// 数据在最后,便于组合
const process = fp.pipe(
fp.filter(x => x > 0),
fp.map(x => x * 2),
fp.sum
);
process([1, -2, 3, -4, 5]); // 18
常用函数
const fp = require('lodash/fp');
// 对象操作
fp.get('name', { name: 'John', age: 25 }); // 'John'
fp.set('age', 30, { name: 'John' }); // { name: 'John', age: 30 }
fp.pick(['name', 'email'], user);
fp.omit(['password'], user);
// 数组操作
fp.groupBy('category', items);
fp.sortBy('age', users);
fp.uniq([1, 2, 2, 3, 3, 3]); // [1, 2, 3]
fp.flatten([1, [2, 3], [4]]); // [1, 2, 3, 4]
// 函数组合
fp.pipe(f, g, h)(x); // h(g(f(x)))
fp.compose(h, g, f)(x); // h(g(f(x)))
Ramda
专门为函数式编程设计的库,所有函数都自动柯里化。
const R = require('ramda');
// 柯里化
const add = R.add;
const add5 = add(5);
add5(3); // 8
// 组合
const process = R.pipe(
R.filter(R.gt(R.__, 0)),
R.map(R.multiply(2)),
R.sum
);
process([1, -2, 3, -4, 5]); // 18
Ramda 特色
const R = require('ramda');
// 占位符 R.__
const subtract5 = R.subtract(R.__, 5);
subtract5(10); // 5
// 逻辑函数
const isAdult = R.propSatisfies(R.gte(R.__, 18), 'age');
R.filter(isAdult, users);
// 条件函数
const getStatus = R.cond([
[R.propEq('score', 100), R.always('Perfect')],
[R.propSatisfies(R.gte(R.__, 60), 'score'), R.always('Pass')],
[R.T, R.always('Fail')]
]);
// 透镜(Lens)
const nameLens = R.lensProp('name');
R.view(nameLens, { name: 'John' }); // 'John'
R.set(nameLens, 'Jane', { name: 'John' }); // { name: 'Jane' }
Immutable.js
Facebook 开发的不可变数据结构库。
const { Map, List, fromJS } = require('immutable');
// Map
const map = Map({ a: 1, b: 2 });
const newMap = map.set('b', 3);
map.get('b'); // 2 (原对象未改变)
newMap.get('b'); // 3
// List
const list = List([1, 2, 3]);
const newList = list.push(4).unshift(0);
// List [0, 1, 2, 3, 4]
// 深度转换
const deep = fromJS({ users: [{ name: 'John' }] });
deep.getIn(['users', 0, 'name']); // 'John'
const updated = deep.setIn(['users', 0, 'name'], 'Jane');
库的选择
| 库 | 特点 | 适用场景 |
|---|---|---|
| Lodash/FP | 功能全面,文档丰富 | 通用项目 |
| Ramda | 函数式优先,数学严谨 | 纯函数式编程 |
| Immutable.js | 不可变数据结构 | React/Redux 项目 |
最佳实践
- 选择合适的库 根据项目需求选择
- 学习组合模式 掌握 pipe 和 compose
- 利用柯里化 创建可复用的函数
- 保持纯函数 避免副作用