什么是函数式编程?
- 在计算机科学中,函数是编程是一种编程范例或者模式(一种构建计算机程序结构和元素的样式)
- 函数式编程将计算机运算视为数学概念中函数的计算。
- 函数式编程避免改变状态以及使用可变的数据。
其他主要的编程规范或模式:
- 过程式编程
- 面向对象的编程
- 元编程
- 命令式编程
- 声明式编程
- 命令模式关心描述程序如何运行, 由计算机执行的命令组成
- 声明模式关心程序能够做什么而无需确定程序应该如何完成。
- 函数式编程遵循声明模式。
1 | var books = [ |
- 在上面的这一段代码中, 我们对于书籍数组中的每一本书添加了一个新的属性,这个过程通过两种不同的方法执行。
- 第一段中借用
for 循环
,依据数组的长度进行迭代,接着将数组的指针计数器和数组的长度进行核对并且在每一次迭代中增加指针计数器,因此, 这更像程序/代码正在关心为了得到想要的输出结果如何进行运行操作。 - 第二段中的代码借助于原生Js数组中的 map 这个 map 方法将函数作为参数,这个函数获取到每一个元素,因此在这种情况下代码不是在描述程序如何运行,而是讨论需要达成什么 ,在这种情况后的 map 方法 关心实际的程序执行。
数学意义上的函数或者纯函数
在数学中,函数是一系列输入值和合法的输出值之间的关系,这种特性反映了每一个输入组合都关联着一个确定的输出。这函数式编程中,这种函数被称作纯函数,函数的输出结果仅仅取决于函数接收到的输入数据, 除了返回值之外, 函数不会改变输入的数据。Math.random() 不是纯函数,因为每次调用的时候总会返回一个新的值。Math.min(1, 2) 是纯函数的一个例子,对于相同的一组输入值总会返回新的值。为什么要使用函数式编程
- 函数式编程中的纯函数确保了不会改变在其范围之外的数据。
- 其减少了复杂程度, 我们不需要关心程序如何怎样做, 而只需要关心程序做了什么。
- 易于测试,因为其不会取决于应用的状态,对于结果的验证也将会变得简单。
- 让代码更具有易读性。
- 函数式编程让代码更易于理解。
函数式编程的例子
数组函数在上面的代码中, 我们试图过滤出只有活跃的 meet-ups, 我们可以看到这个功能可以使用两种不同的方法实现,在这里, 第二种方法是函数式编程,其中的 filter() 方法关心"程序如何运行",程序只关心输入也就是 meetups数组以及输出activeMeetupsFP 但是在第一种方法中程序也关心 for 循环如何运行代码。相似的,下面的这些数组方法有助于实现函数式编程,减少代码的复杂度。- find
- reduce
- map
- some
- every
函数链
函数链是用于调用多种方法的机制, 每一个方法返回一个对象, 允许在一个声明中调用链接在一起而无需变量来储存中间结果。在上面的代码片段中, 我们想要打印出所有的活跃的 meetup 用户的总人数, 考虑到可能有10%的用户重复。支持 FP 的库
下面这些库中提供了一些让代码看起来更加声明式的有用函数。- RamadaJS
- UnderscoreJS
- lodash
副作用
函数或者表达式除了返回一个值之外,在下面的几种情况下被认为产生了副作用: 如果其改变了其自身范围之外的程序状态, 或者与其调用的函数或者外部的程序有一个可以观察到的交互。1 | let meetup = {name:'JS',isActive:true,members:49}; |
不变性
在函数运行之后,不变性是十分重要的对于确保一个函数确实没有改变原来的数据而不是返回数据的新的副本。例如, 如果数组以及对象在经历过多个函数之后, 如果我们不能保持不变性, 那么函数可能不会得到数组或者对象的原始值。在可变的对象和数组的情况下,如果发生了一些错误对于我们来说是非常困难排除bug的。支持不变性的库
JavaScript默认没有对于使得对象或者数组不变提供任何的工具, 下面是一些可能帮助我们实现不变性的库:- Seamless-immutable
- Immutable JS