JavaScript函数式编程-组合与管道05

语言: CN / TW / HK

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-引入currypartial:

当函数接收一个参数时,才能将两个函数完成组合,但是实际开发中的情况远不止如此,还存在多参数的情况。

以之前在数组的函数式编程中封装好的mapfilter函数为例,都接收两个参数:

  • 要被操作的数组
  • 操作数组的函数

```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封装成了一个只接受一个参数的数组的函数,分别是queryGoodBooksmapTitleAndAuthor
  • 需要感受的就是拼接乐高积木的感觉

2.管道pipe:

通过上面compose的封装,了解到compose函数的数据流的运行机制:从右至左

pipe是与之数据流向相反的-从左到右pipe的实现上来说,也和compose只是细微的差别:

javascript const composeN = (...funcs) => (value) => reduce(funcs,(acc,func) => func(acc),value);

  • reduce的参数funcsreverse去掉,便是pipe

  • composepipe其实做的事情基本相同,只是数据的流向相反而已

最后关于函子的部分可能就不做介绍了,后续可能会再找时间添加进来,关于函数式编程的部分就到这里了。