函数式编程

81 阅读6分钟

一、高阶函数

首先要知道高阶函数的概念什么

  • 可以把函数作为参数传递给另一个函数(函数作为参数可以使函数变得更加灵活)
  • 可以把函数作为另一个函数的返回值

有了高阶函数的这两个概念下面就上代码来演示一番,看看高阶函数具体的用法和作用

  • 函数作为参数(下面我们用函数作为参数来模拟数组的forEach、filter这两个方法,此时我突然想了解下数组对象是如何实现的,近了来说上面这两个方法是如何注册进去的?)

  • 函数作为返回值(实现once函数只在第一次调用时生效)

高阶函数的意义:(函数式编程的核心思想: 对运算过程进行抽象,也就是把运算过程抽象成函数然后在任何地方都可以重用这些函数)

  • 抽象可以帮我们屏蔽实现的细节,在调用函数的时候只需关注我们的目标。
  • 高阶函数就是用来抽象通用的问题。
  • 使代码更简洁

二、闭包

闭包:

  • 函数和其周围的状态(词法环境)的引用捆绑在一起形成闭包
  • 可以在另一个作用域中调用一个函数的内部函数并访问到该函数的作用域中的成员

闭包的本质: 函数在执行的时候会放到一个执行栈上当函数执行完之后会从执行栈上移除,但是堆上的作用域成员因为被外部引用不能释放,因此被执行完的这个函数的内部函数依然可以访问到改函数的内部成员

三、纯函数

概念:相同的输入永远会得到相同的输出,而且没有任何可观察的副作用

纯函数的好处:

  • 可缓存:因为纯函数对相同的输入始终有相同的输出,所以可以把纯函数的结果缓存起来,从而提高性能
  • 可测试: 纯函数让测试更方便
  • 并行处理: 在多线程环境下并行操作共享的内存数据很可能会出现意外情况,纯函数不需要访问共享的内存数据,所以在并行情况下可以任意运行纯函数

纯函数的缺点:

纯函数相同的输入有相同的输出,如果函数依赖于外部的状态就无法保证输出相同,就会带来副作用。

所有的外部交互都可能带来副作用,副作用也使得方法通用性下降不适合扩展和可重用性,同时副作用会给程序中带来安全隐患给程序带来不确定性,但是副作用不可能完全禁止,尽可能控制他们在可控范围内发生

四、lodash

安装lodash:

  • 初始化package.json
  • npm install lodash
  • 引入lodash: const _ = require('lodash')   根据官网lodash这个对象的名字一般以下划线命名

lodash是一个现代化的实用的JavaScript库,它提供了模块化高性能以及一些附加的功能, lodash是一个功能库

lodash中的map方法有个值得注意的问题: 受保护的函数不能使用,否则会出错

受保护的方法有(注:即这些方法不能使用_.every,_.filter,_.map,_.mapValues,_.reject, 和_.some作为 iteratee 迭代函数参数) :
ary, chunk, curry, curryRight, drop, dropRight, every,fill, invert, parseInt, random, range, rangeRight, repeat,sampleSize, slice, some, sortBy, split, take, takeRight,template, trim, trimEnd, trimStart, and words

如对比lodash/fp :

lodash的使用:lodash方法库中的记忆函数memoize,memoize这个函数要接受一个纯函数作为参数,它内部会对这个纯函数进行处理,对纯函数的结果进行缓存,memoize方法会返回一个带记忆功能的函数

模拟lodash的memoize函数的实现(纯函数的好处之一可缓存,提高程序性能):

五、柯里化

柯里化的概念: 

  • 当一个函数有多个参数的时候先传递一部分参数调用它(这部分参数永远不变)
  • 然后返回一个新的函数接收剩余的参数,返回结果

柯里化可以将n元函数转换为一元函数

用柯里化解决硬编码的问题, min是基准值

lodash中提供的通用的柯里化的方法:_.curry(fn), curry方法本身是纯函数,如果fn是纯函数那么返回的也是纯函数

_.curry(fn):

  • 功能:创建一个函数, 该函数接收一个或多个fn的参数, 如果fn所需要的参数都被提供则执行fn并返回执行的结果,否则继续返回该函数并等待接收剩余参数
  • 参数: 需要柯里化的函数
  • 返回值:柯里化后的函数

实践案例,用lodash的curry方法实现过滤,过滤方法可重用

模拟curry的实现原理:

柯里化的总结:

  • 柯里化可以让我们给一个函数传递较少的参数得到一个已经记住了某些固定参数的新函数
  • 这是一种对函数参数的缓存
  • 让函数变得更灵活,让函数的粒度更小
  • 可以把多元函数转换成一个一元函数,可以组合使用函数产生强大的功能

六、函数组合

函数组合可以把多个函数组合成一个新的函数,好处之一就是让函数最大程度上被重用

编写下面的代码完成后我有个疑问: 目前我了解的函数组合似乎就是对一个输入的实参进行多次加工处理,其中每个函数就是一个工厂,那比如我first这个函数还需要其他实参,那么这个实参怎么出入呢

lodash中提供了两个组合函数,他们可以组合多个函数(函数组合要满足结合律)

  1. flow():从左往右

  2. flowRight(): 从右往左,使用更多

    模拟lodash的flowRight的实现原理

函数组合的调试

lodash/fp模块:

  • 提供了实用的对函数式编程友好的方法,lodash的fp模块中的方法都是已经被柯里化了的
  • 提供了不可变方法,如果一个方法有多个参数,并且有的函数参数的话,他会要求函数优先数据滞后 (而lodash中的方法都是数据优先函数滞后)

上面的方法用了fp模块中的方法就可以直接改写为:

总结: pointfree是一种编程风格, 函数组合算是他的一种具体实现,函数组合就是把多个函数合并到一起