JavaScript函数式编程-组合与管道05
theme: scrolls-light highlight: atelier-dune-light
这是我参与2022首次更文挑战的第5天,活动详情查看:2022首次更文挑战」
1.组合compose:
在了解组合概念之前,先来理解Unix
理念。
- 每个程序只做好一件事情,为了完成一项新的任务,
重新构建
要好于在复杂的的就程序中添加新属性
- 每个程序的
输出
应该是另一个尚未可知的程序的输入
。
🚀 下面来说下关于compose
的具体实现:
这里的reduce
是之前的数组的函数式编程中封装过得函数,如果不清楚还回看:http://juejin.cn/post/7064193474287501342
1.1-composeN组合函数的实现思路:
-
composeN
函数接收多个函数为参数,返回一个接收初始值value(作为reduce函数的初始值)
的函数 -
传入的多个函数的执行顺序为
从右到左(通过funcs.reverse()来实现)
,然后上一次的执行函数的结果
会作为下一个函数的输入
继续执行...
```javascript //reduce函数 const reduce = (array,fn,initVal)=>{ let accumlator; if(initVal !== undefined){ accumlator = initVal; }else{ accumlator = array[0]; } if(initVal === undefined){ for(let i = 1;i<array.length;i++){ accumlator = fn(accumlator,array[i]); } }else{ for (const value of array){ accumlator = fn(accumlator,value); } } return [accumlator] };
//composeN组合函数 const composeN = (...funcs) => (value) => reduce(funcs.reverse(),(acc,func) => func(acc),value); ```
1.2-compose
的使用:
🚀 例子1:
javascript
//compose组合的简单使用
let number = compose(Math.round,parseFloat);
console.log("Number is ",number("3.56"));
//控制台结果为4
- 实际上等同于
number = (value) => Math.round(parseFloat(c))
;parseFloat
执行后的结果作为了Math.round
的参数
1.3-引入curry
与partial
:
当函数接收一个参数
时,才能将两个函数完成组合,但是实际开发中的情况远不止如此,还存在多参数
的情况。
以之前在数组的函数式编程中封装好的map
和filter
函数为例,都接收两个参数
:
- 要被操作的数组
- 操作数组的函数
```javascript let books = [ { "id": 111, "title": "css", "author": "张鑫旭", "rating": [4.9], "reviews": [{good : 4 , excellent : 12}] }, { "id": 222, "title": "JavaScript悟道", "author": "道格拉斯.克罗克福德", "rating": [4.5], "reviews": [] }, { "id": 333, "title": "vuejs设计与实现", "author": "霍春阳", "rating": [4.9], "reviews": [] }, { "id": 444, "title": "javascript的设计模式与开发实践", "author": "曾探", "rating": [4.2], "reviews": [{good : 14 , excellent : 12}] } ];
//筛选过滤的条件函数 let filterOutStandingBooks = (book) => book.rating[0] === 5; let filterGoodBooks = (book) => book.rating[0] > 4.5; let filterBadBooks = (book) => book.rating[0] < 3.5;
//获取的内容函数 let projectTitleAndAuthor = (book) => { return {title: book.title,author:book.author} } let projectAuthor = (book) => { return {author:book.author} } let projectTitle = (book) => { return {title: book.title} }
//通过偏应用处理,将多参数函数处理为单参数函数 let queryGoodBooks = partial(filter,undefined,filterGoodBooks); let mapTitleAndAuthor = partial(map,undefined,projectTitleAndAuthor);
//实际使用 let titleAndAuthorForGoodBooks = compose(mapTitleAndAuthor,queryGoodBooks); console.log("前端推荐好书的名字和作者",titleAndAuthorForGoodBooks(books)); ```
🚀 结果如下:
- 因为
map、filter、reduce函数以及partial函数
等都没有在代码中体现。 - 组合的思想就是把小函数组合成一个大函数。
- 对于
partial
,这里是通过partial
将map和filter封装成了一个只接受一个参数的数组的函数,分别是queryGoodBooks
、mapTitleAndAuthor
。 - 需要感受的就是拼
接乐高积木
的感觉
2.管道pipe:
通过上面compose
的封装,了解到compose函数的数据流
的运行机制:从右至左
pipe
是与之数据流向相反的-从左到右
,pipe
的实现上来说,也和compose
只是细微的差别:
javascript
const composeN = (...funcs) => (value) => reduce(funcs,(acc,func) => func(acc),value);
-
将
reduce
的参数funcs
的reverse
去掉,便是pipe
-
compose
和pipe
其实做的事情基本相同,只是数据的流向相反
而已
最后关于函子的部分可能就不做介绍了,后续可能会再找时间添加进来,关于函数式编程的部分就到这里了。