函数组合
为什么学习函数组合?
之前我们学习的纯函数和柯里化很容易写出洋葱代码 h(g(f(x))) ;例如: 获取数组的最后一个元素再转换成大写字母, _.toUpper(_.first(_.reverse(array))) ;函数组合可以让我们把细粒度的函数重新组合生成一个新的函数 。
什么是函数组合?
函数组合
(compose)
:如果一个函数要经过多个函数处理才能得到最终值,这个时候可以把中间
过程的函数合并成一个函数
函数就像是数据的管道,函数组合就是把这些管道连接起来,让数据穿过多个管道形成最终
结果 ;
函数组合默认是从右到左执行
代码示例 实现一个获取数组最后一个元素的功能
// 组合函数
function compose (f, g) {
return function (x) {
return f(g(x))
}
}
function first (arr) {
return arr[0]
}
function reverse (arr) {
return arr.reverse()
}
// 从右到左运行
let last = compose(first, reverse)
console.log(last([1, 2, 3, 4]))
lodash中的组合函数
lodash 中组合函数
flow()
或者
flowRight()
,他们都可以组合多个函数
- flow() 是从左到右运行
- flowRight() 是从右到左运行,使用的更多一些
flowRight的应用:实现一个获取数组最后一个元素,并且转换成大写
const _ = require('lodash')
const toUpper = s => s.toUpperCase()
const reverse = arr => arr.reverse()
const first = arr => arr[0]
const f = _.flowRight(toUpper, first, reverse)
console.log(f(['one', 'two', 'three']))
组合函数的实现原理
// 多函数组合
function compose (...fns) {
return function (value) {
return fns.reverse().reduce(function (acc, fn) {
return fn(acc)
}, value)
}
}
组合函数要满足结合律
我们既可以把
g
和
h
组合,还可以把
f
和
g
组合,结果都是一样的
// 结合律(associativity)
let f = compose(f, g, h)
let associative = compose(compose(f, g), h) == compose(f, compose(g, h)) // true 1234
lodash/fp模块
- lodash 的 fp 模块提供了实用的对函数式编程友好的方法
- 提供了不可变的 auto-curried(自动柯里化) iteratee-first(遍历优先) data-lfast(数据后置) 的方法
案例: lodash和 lodash/fp 中map的区别
const _ = require('lodash')
const _fp = require('lodash/fp')
const arr = ['23', '8', '10']
// 前置知识: parseInt: 参数1是数据, 参数2是进制
// lodash map中提供的iteratee提供3个参数: value, index|key, collection
console.log(_.map(arr, parseInt)); // [ 23, NaN, 2 ]
// lodash/fp map中提供的iteratee提供1个参数: value
console.log(_fp.map(parseInt, arr)); // [ 23, 8, 10 ]