内容简介:原文链接本文旨在对比命令式编程与函数式编程两种不同的解决问题的方式。目的并不是专门教大家函数式编程,而是介绍给大家一种区别于传统方法(循环、变换等)的不同的思考方式。在日后遇到问题时能从不同的角度去思考,同时给自己的技能树添加更多的工具。函数式编程的基础可以分为如下三个要点来阐述:
原文链接 Introduction to Functional Programming
本文旨在对比命令式编程与函数式编程两种不同的解决问题的方式。目的并不是专门教大家函数式编程,而是介绍给大家一种区别于传统方法(循环、变换等)的不同的思考方式。在日后遇到问题时能从不同的角度去思考,同时给自己的技能树添加更多的工具。
函数式编程的基础可以分为如下三个要点来阐述:
- 不可变数据结构(Immutable Data Structures)
- 纯函数(Pure Functions)
- 头等函数(First Class Functions)
让我们分别看一下每个要点吧:
不可变数据结构(Immutable Data Structures)
我们在使用像 JavaScript 这样的编程语言时,我们可以这样给变量进行赋值 let myVariable = 5; ,但是不存在任何一种机制来阻止我们在后期继续对该变量进行赋值操作,比如 myVariable = "Now I'm a string." 。这样的操作实际上很危险,如果有其他函数依赖 myVariable 这个 number 类型变量,或者是某个异步函数同时也要用到 myVariable ,这时就会遇到一些问题。
纯函数(Pure Functions)
纯函数是无副作用的。啥叫无副作用? 首先,如果一个函数的输出仅仅依赖于其输入,那么该函数就被认为是一个纯函数。如果我们的函数拿到输入后执行了数据库的更新操作,然后返回了一个值,这样的操作就称之为具有副作用,即更新了数据库。也就是说多次调用同一个函数不总是得到相同的结果(内存不足、数据库被锁等情况)。使用纯函数对于我们书写少 bug、易测试的代码很有帮助。
头等函数(First Class Functions)
「头等」这个词出现在这里可能看起来比较陌生,但是其意思是指函数可以被用做参数或者可以像其他数据类型一样使用。比如字符串类型、整型和浮点型等。支持头等函数的编程语言允许将函数作为参数传给其他函数,可以把这种方式看做依赖注入。
命令式编程和函数式编程对比
这里用下面的例子对两者进行比较,功能是求得数组 [1, 2, 3, 4] 中的数字之和。
命令式编程写法:
sum
赋了不同的值。
为了将代码改为函数式编程思想,让我们来分解一下累加和的计算过程。
首先,我们以某个值作为初始值,在我们的例子中该值为 let sum = 0; ,接下来,我们从数组中取出第一项 1 并将其累加到 sum 上。这一步我们得到了 0 + 1 = 1 。然后重复这个步骤,取出 2 将其累加到 sum 上,即 1 + 2 = 3 ,这一过程遍历到数组尾部为止。
可视化该过程:
我们可以将该算法视作两个单独的函数,首先我们需要某种方式来进行数字的相加操作:
接下来我们需要以某种方式来循环遍历数组,由于大多数函数式编程通常都使用递归来替代循环,那我们就创建一个递归函数来遍历我们的数组。来看一下该函数可能的样子:
list 是我们想要遍历的数组,
index 作为当前要遍历的起点位置,如果我们遍历到达
list 尾部,或者是给出的
list 无效,那么循环结束。否则再次调用
loop ,
index 加 1。试着在
return loop(list, index + 1) 之前添加
console.log(list[index]) ,我们应该可以看到控制台输出了
1 2 3 4
。
为了最终实现求得数组累加和,我们需要将 loop 和 add 函数结合起来,在看下面的例子时要回忆我们上面提到的算法:
loop 函数中的参数,增加了
accu ,用来保存
list 的累加和。我们直接用
add 函数计算
accu 与与
list 中当前项的和。如果我们
console.log(loop(list));
会发现控制台会输出结果 10。
现在,不如我们更进一步吧。要是我们不想求数组累加和了,改为将它们相乘呢?那现在我们要复制一份 loop 的代码,把 add 函数改成其他东西(可能是 multiply ?)?太麻烦了吧。还记得头等函数吗,我们要利用这种思想将我们的函数变的更为通用。
上面例子中唯一不同之处在于我们给 loop 函数新增了一个参数,来接收一个函数。这回我们不传 add 给它了,取而代之的是传一个函数进来,调用该函数获取最终结果。这样就能轻松的实现针对 list 的 add , multiply , subtract 等一系列操作了。
我们不再只是简单的遍历数组了,而是将数组像纸一样折起来,直到我们得到一个结果。在 JavaScript 中,我们把这种函数称之为 reduce 。
结语
我们对函数式编程进行了一些基础的概览,同时看到针对同一问题的不同拆解方式给与我们不同的解法。 reduce 可以说是其他类似 map 和 filter 这样的操作的基础。
以上所述就是小编给大家介绍的《[译] JavaScript 函数式编程指引》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- Nginx 升级 HTTP / 2 指引
- PHP环境gettext使用指引
- 你不能错过的XSS指引
- PHP 垃圾回收与内存管理指引
- 指引趋势与方向!2019开发者调查报告出炉
- 政府网站发展指引发布 奇葩政府网混不下去了
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Designing Data-Intensive Applications
Martin Kleppmann / O'Reilly Media / 2017-4-2 / USD 44.99
Data is at the center of many challenges in system design today. Difficult issues need to be figured out, such as scalability, consistency, reliability, efficiency, and maintainability. In addition, w......一起来看看 《Designing Data-Intensive Applications》 这本书的介绍吧!