函数式编程(一)-概述
函数式编程是一种编程范式,也就是如何编写程序的方法论,其它的编程范式还有面向对象编程,过程化编程等。函数式编程并不是一个新兴的概念,而是一个存在久远的概念,随着React的兴起,函数式编程的概念又火了起来,Rxjs、lodash等库都使用了函数式编程的思想。
这个系列会从什么是函数式编程说起,讨论函数式编程的优缺点,如何使用函数式编程编写优雅的代码,最后会探讨函数式编程在Javascript中的一些最佳实践。
1. 初窥函数式编程
解释什么是函数式编程并不是个容易的事情,我也是在尝试着学习和理解。函数式编程不是用function来编程,而是一种如何使用function,才能使它具备函数式的一种方法。要了解怎么使用函数,首先我们需要了解什么是函数。
1.1 函数
这里简单回顾一下初中的数学知识,当我们看待一个函数时,它可能长这样 y = f(x)
f(x) = 2x2 + 3
可以看出函数的基本特点在于它有一个或多个输入值,并进行一定的计算,并且得到一个返回值。函数式编程中有一个术语叫做态射,来描述输入值和输出值的关系。
这里简单讨论下函数和程序的区别,这也是函数式编程的一大特性。程序是一系列指令的集合,它可能有输入值也可能没有,它可能有输出值也可能没有。而函数是接收输入值并通过计算返回输出值。
函数式编程的一大特点就是我们应该尽量的使用函数而非程序,当然在实际的开发中我们不可避免的要进行I/O操作,但是如果你的计划是使用函数式编程,那么在开发中就应该尽可能多的使用函数,而不是程序。
1.2 函数是一等公民(first class)
这是函数式编程的一个重要概念,函数与其他数据类型一样,处于平等地位,可以赋值给其他变量,也可以作为参数,传入另一个函数,或者作为别的函数的返回值。
Javascript本身不是纯的函数式编程语言,可以说是一个多范式的编程语言,但是由于其函数是一等公民特性,我们可以把函数作为参数进行传递,也可以将函数作为函数的返回值等特性,使得Javascript可以进行函数式编程。
同时这个特性是函数式编程的一些核心内容,比如闭包、高阶函数、柯里化等特性的基础
1.3 引用透明性
回到上面那个函数,根据其输入输出的值,可以形成如下的图像:
通过这个图我们可以得出两个结论:1. 函数一定有输入和输出值。 2. 函数对于相同的输入值返回相同的输出值,这个特性称为引用透明性。
引用透明性带来的巨大好处在于并发代码和结果可缓存,并发的问题在于对于全局变量的使用,需要引入锁机制来管理全局变量的使用,但是引用透明性只依赖入餐,所以线程可以自由运行。结果的可缓存也是显而易见的,对于一个输入其对应的输出也是唯一的。所以该输入的结果是可以缓存的。
1.4 纯函数
在引用透明性的基础上我们可以定义纯函数,纯函数具有引用透明性,同时任何外部变量不会影响函数内部运算的结果,同时函数内部的运算也不会影响到外部变量的值。
纯函数给我们带来的好处在于代码的可测试性的增强,当我们测试一个函数时,我们会用输入和期望的正确输出值来验证一个函数的正确性,但是当多次测试通过之后,是否就可以说我们的函数是正确的,这个是不一定。如果外部的变量被应用在了函数的运算中,那么当外部变量发生改变时,函数的计算结果也会变得不符合预期。同理,函数改变外部的值也会导致代码的无法测试。
1.5 声明式编码
与声明式编码相对应的是命令式代码,意思就是,我们通过编写一条又一条指令去让计算机执行一些动作,这其中一般都会涉及到很多繁杂的细节。
而声明式就是,我们通过写表达式的方式来声明我们想干什么,而不是通过一步一步的指示。
举个遍历的例子,命令式编程的写法是:
var array = [1,2,3];for(var i = 0; i < array.length; i++){ console.log(array[i])
}
而声明式的写法是:
array = [1, 2, 3];array.forEach((item) => { console.log(item); })
声明式的好处在于代码的编写更清晰简洁,在forEach函数为纯函数的前提下,我们不用关心函数的内部是如何实现的,开发者只需要关注眼前的事情。
2.函数式编程的优势
函数式编程根据上述的几个特性,具有以下几个优势:1. 代码的可读性更强 2. 代码的可测试性更强 3. 易于编写可缓存的代码 4. 易于并发
2.1 代码的可读性
由于函数式编程采用声明式的代码,所以代码的可读性更强,举个例子,当我们进行一个这样(1 + 2) * 3 - 4
的计算时,我们可能会写成subtract(multiply(add(1,2), 3), 4)
,对其进行声明式的改造 add(1,2).multiply(3).subtract(4)
这样我们就可以直观的看出这句表达式的含义了。
2.2 代码的可测试性
这个优势是纯函数带来的,函数与外部变量的隔离使得测试只用关心函数内部逻辑,更易进行单元测试。
2.3 可缓存和可并发编程
这两个优势是函数的引用透明性带来的,这里不再赘述。
3.总结
首先清楚地理解什么是函数:它不仅仅是一个语句或者操作的集合,而且需要一个或多个输入(理想情况下只需一个!)和一个输出。
函数是一等公民的这个特性是函数式编程的很多特性的基础,也是Javascript语言函数式编程的基础。
引用透明性和纯函数使得函数更加易于测试,同时更易于并发编程和函数的缓存。
声明式表达使得函数更易理解。
下一章我们会开始讨论如何使用函数式的思想进行编程。
以上是 函数式编程(一)-概述 的全部内容, 来源链接: utcz.com/a/27942.html