函数式编程(FP)深度解析
函数式编程核心理解
函数式编程是一种声明式编程范式,核心思想是”通过纯函数组合构建程序”,主要特点:
| 特性 |
说明 |
示例 |
| 纯函数 |
相同输入永远返回相同输出,无副作用(不改变外部状态) |
const add = (a,b) => a + b; |
| 不可变性 |
数据创建后不可修改,通过生成新数据实现变更 |
使用map代替for循环+push |
| 函数一等公民 |
函数可作为参数/返回值/变量 |
const logger = fn => (...args) => { console.log(...args); return fn(...args); } |
| 引用透明 |
函数调用可直接替换为其返回值 |
add(2,3) 可替换为 5 |
| 高阶函数 |
接收或返回函数的函数 |
map, filter, reduce |
| 函数组合 |
将多个函数组合成新函数(f(g(x))) |
const process = compose(validate, format, save); |
函数柯里化(Currying)详解
概念:将多参数函数转换为一系列单参数函数的过程
f(a, b, c) → f(a)(b)(c)
实现原理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| function curry(fn) { return function curried(...args) { if (args.length >= fn.length) { return fn.apply(this, args); } else { return (...nextArgs) => curried.apply(this, [...args, ...nextArgs]); } }; }
const sum = (a, b, c) => a + b + c; const curriedSum = curry(sum); console.log(curriedSum(1)(2)(3));
#### 柯里化特点
1. **参数延迟传递**:分步传入参数 2. **函数复用性**:基于部分参数创建新函数 3. **动态函数生成**:按需组合函数逻辑
### 实际应用场景
#### 场景1:参数复用
```javascript // 通用URL构建器 const buildUrl = curry((protocol, domain, path) => `${protocol}: );
const createHttpsUrl = buildUrl('https'); const githubUrl = createHttpsUrl('github.com'); const apiUrl = createHttpsUrl('api.example.com');
console.log(githubUrl('user/repo')); console.log(apiUrl('v1/data'));
|
场景2:事件处理
1 2 3 4 5 6 7 8 9 10 11
| const addListener = curry((eventType, element, handler) => element.addEventListener(eventType, handler) );
const addButtonListener = addListener('click')(document.querySelector('button'));
addButtonListener(handleLogin); addButtonListener(handleLogout);
|
场景3:数据校验
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| const validate = curry((rules, value) => rules.every(rule => rule(value)) );
const isString = v => typeof v === 'string'; const minLength = len => v => v.length >= len; const hasNumber = v => /\d/.test(v);
const isValidPassword = validate([ isString, minLength(8), hasNumber ]);
console.log(isValidPassword('abc123')); console.log(isValidPassword('securePwd1'));
|
场景4:React高阶组件
1 2 3 4 5 6 7 8 9 10 11 12
| const withFeatures = curry((features, Component) => props => <Component {...props} features={features} /> );
const withAnalytics = withFeatures(['analytics']); const withLogger = withFeatures(['logger']);
const DashboardWithAnalytics = withAnalytics(Dashboard); const AppWithLogger = withLogger(App);
|
函数式编程实践价值
- 可维护性:纯函数+不可变性使代码更可预测
- 可测试性:无副作用函数易于单元测试
- 并发安全:避免共享状态带来的竞态条件
- 模块化:函数组合实现高度复用
- 调试友好:引用透明性简化问题追踪
使用注意事项
现代JS中的FP支持
| 工具 |
用途 |
示例 |
| Lodash/fp |
函数式工具库 |
_.map(_.trim, strings) |
| Ramda |
纯函数式工具库 |
R.compose(R.filter(f), R.map(g)) |
| React Hooks |
函数组件+状态管理 |
useMemo, useCallback |
| Redux |
不可变状态管理 |
reducer(state, action) => newState |