1. 概念
- 纯函数和柯里化很容易写出洋葱代码 h(g(f(x))) ,函数组合可以让我们把细粒度的函数重新组合生成一个新的函数
- 如果一个函数要经过多个函数处理才能得到最终值,这个时候可以把中间过程的函数合并成一个函数
- 函数就像是数据的管道,函数组合就是把这些管道连接起来,让数据穿过多个管道形成最终结果
- (当我们遇到函数比较复杂时,可以把函数拆分成很多的小函数,此时多了中间过程产生的参数)

- 函数组合默认是从右到左执行
- 案例 ```javascript // 函数组合演示 // 获取数组最后一个值
// 把函数进行组合 注意的是 函数组合默认是从右到左执行 function compose(f, g) { return function (value) { return f(g(value)) } } // 反转 function reverse(array){ return array.reverse(); } // 取第一个元素 function first(array){ return array[0]; }
const last = compose(first,reverse); console.log(last([“a”,”b”,”c”,”d”]));
<a name="SUUgx"></a>## 2. lodash中的组合函数<a name="T7uHI"></a>#### 1.lodash 中组合函数 flow() 或者 flowRight(),他们都可以组合多个函数flow() 是从左到右运行<br />flowRight() 是从右到左运行,使用的更多一些<br />案例:```javascript// lodash 中的组合函数 flowRight() 是从右到左运行const _ = require('lodash')// 翻转const reverse = arr => arr.reverse()// 求第一个元素const first = arr => arr[0]// 转大写const toUpper = str => str.toUpperCase()// 使用lodash中的flowRight 来进行组合函数const fn = _.flowRight(toUpper,first,reverse);console.log(fn(['one','tow','three']));
2.lodash_fp 模块
- 提供了实用的对函数式编程友好的方法
- 提供了不可变 auto-curried, iteratee-first, data-last 的方法
- fp中提供的方法都是柯里化的 如果有多个参数都是函数优先,数据滞后的
- 使用fp模块的示例 ```javascript // MEVER SAY DIE —-》nerver-say-die // fp中提供的方法都是柯里化的 如果有多个参数都是函数优先数据滞后的 const fp = require(‘lodash/fp’);
const fn = fp.flowRight(fp.join(‘-‘), fp.map(fp.toLower), fp.split(‘ ‘))
console.log(fn(‘MEVER SAY DIE’));
1. lodash和lodsh/fp模块中 map方法的区别```javascript// lodash和lodsh/fp模块中 map方法的区别// lodash// const _ = require('lodash');// console.log(_.map(['23','8','10'],parseInt));// // parseInt('23',0,array)// // parseInt('8',1,array)// // parseInt('10',2,array)// //parseInt 的第二个参数其实是 转化为几进制// // 23 0其实是10进制// // 8 1进制没有 所以等于NaN// // 10 二进制结果为2// // 所以 结果为[ 23, NaN, 2 ]// end// lodsh/fpconst fp = require('lodash/fp');console.log(fp.map(parseInt,['23','8','10']));// end
3. 组合函数实现原理
// 模拟 lodash中的 组合函数// 翻转const reverse = arr => arr.reverse()// 求第一个元素const first = arr => arr[0]// 转大写const toUpper = str => str.toUpperCase()// 模拟 lodash中的 flowRight 组合函数(从右到左运行)function compose(...args) {return function (value) {/*** reduce 为数组中的每一个元素依次执行回调函数* reduce() 方法接收一个函数作为累加器,* 数组中的每个值(从左到右)开始缩减,最终计算为一个值。* reduce() 可以作为一个高阶函数,用于函数的 compose。* 注意: reduce() 对于空数组是不会执行回调函数的。* reduce(函数(total:必需。初始值, 或者计算结束后的返回值* currentValue:必需。当前元素* currentIndex:可选。当前元素的索引* arr:可选。当前元素所属的数组对象。)* ,初始值(可选))*/return args.reverse().reduce(function(acc,fn){return fn(acc);},value)}}// ES6 箭头函数表示// const compose = (...args) => value => args.reverse().reduce((acc,fn)=>fn(acc),value)// 使用模拟的组合函数 来进行组合函数const fn = compose(toUpper, first, reverse);console.log(fn(['one', 'tow', 'three','aaaaa']));
4. 结合律(函数组合要满足的一个特点)
(a×b)×c=a×(b×c)
我们可以先把a和b组合 也可以先把b和c组合
结果是一样的
案例:
// lodash 中的组合函数 flowRight() 是从右到左运行const _ = require('lodash')// 使用lodash中的flowRight 来进行组合函数const fn1 = _.flowRight(_.toUpper,_.first,_.reverse);const fn2 = _.flowRight(_.flowRight(_.toUpper,_.first),_.reverse);const fn3 = _.flowRight(_.toUpper,_.flowRight(_.first,_.reverse));console.log(fn1(['one','tow','three']));console.log(fn2(['one','tow','three']));console.log(fn3(['one','tow','three']));
5. 调试
// 函数组合调试// MEVER SAY DIE ---》nerver-say-dieconst _ = require('lodash');// 调试函数 打印然后把拿到的值再输出出去(打印会不清晰没有标记tag)const log = v => {console.log(v);return v;}const trace = _.curry((tag, v) => {console.log(tag, v);return v})// 切割字符串柯里化const split = _.curry((sep, str) => _.split(str, sep));// 拼接柯里化const join = _.curry((sep, array) => _.join(array, sep));// map 对数组中的每个元素进行处理 柯里化const map = _.curry((fn, arr) => _.map(arr, fn));const fn = _.flowRight(join('-'), trace('map后'), map(_.toLower), trace('split后'), split(' '))console.log(fn('MEVER SAY DIE'));
我们可以自己写一个调试函数trace 利用 函数组合中 上一个函数返回值传递给下一个参数 我们就可以从中获取到这个参数 从而进行调试
6. PointFree
概念
- 一种编程的风格,具体实现是函数的组合,他更抽象一些
- 我们可以把数据处理的过程定义成与数据无关的合成运算,不需要用到代表数据的那个参数,只要把简单的运算步骤合成到一起,在使用这种模式之前我们需要定义一些辅助的基本运算函数。
const fp = require(‘lodash/fp’) // replace字符串中用一些字符替换另一些字符 const f = fp.flowRight(fp.replace(/\s+/g, ‘_’), fp.toLower);
console.log(f(‘Hello world’));
```javascript// point free// world wild web => W. W. Wconst fp = require('lodash/fp')// replace字符串中用一些字符替换另一些字符// const firstLetterToUpper = fp.flowRight(fp.join('. '),fp.map(fp.first),fp.map(fp.toUpper),fp.split(' '))const firstLetterToUpper = fp.flowRight(fp.join('. '),fp.map(fp.flowRight(fp.toUpper,fp.first)),fp.split(' '))console.log(firstLetterToUpper('world wild web'));

