likes
comments
collection
share

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

作者站长头像
站长
· 阅读数 29

1.组合compose:

在了解组合概念之前,先来理解Unix理念。

  • 每个程序只做好一件事情,为了完成一项新的任务,重新构建要好于在复杂的的就程序中添加新属性
  • 每个程序的输出应该是另一个尚未可知的程序的输入
JavaScript函数式编程-组合与管道05

🚀 下面来说下关于compose的具体实现:

1.1-composeN组合函数的实现思路:

  • composeN函数接收多个函数为参数,返回一个接收初始值value(作为reduce函数的初始值)的函数

  • 传入的多个函数的执行顺序为从右到左(通过funcs.reverse()来实现),然后上一次的执行函数的结果会作为下一个函数的输入继续执行...

//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:

//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函数为例,都接收两个参数:

  • 要被操作的数组
  • 操作数组的函数
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));

🚀 结果如下:

前端推荐好书的名字和作者[
    {
        title:'css',
        author:'张大'
    },
    {
        title:'vuejs',
        author:'霍三'
    }
]
  • 因为map、filter、reduce函数以及partial函数等都没有在代码中体现。
  • 组合的思想就是把小函数组合成一个大函数。
  • 对于partial,这里是通过partial将map和filter封装成了一个只接受一个参数的数组的函数,分别是queryGoodBooksmapTitleAndAuthor
  • 需要感受的就是拼接乐高积木的感觉

2.管道pipe:

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

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

const composeN = (...funcs) => (value) => reduce(funcs,(acc,func) => func(acc),value);
  • reduce的参数funcsreverse去掉,便是pipe

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

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

转载自:https://juejin.cn/post/7068902552846204965
评论
请登录