[译] JavaScript 函数式编程指引

栏目: 编程语言 · 发布时间: 5年前

内容简介:原文链接本文旨在对比命令式编程与函数式编程两种不同的解决问题的方式。目的并不是专门教大家函数式编程,而是介绍给大家一种区别于传统方法(循环、变换等)的不同的思考方式。在日后遇到问题时能从不同的角度去思考,同时给自己的技能树添加更多的工具。函数式编程的基础可以分为如下三个要点来阐述:

原文链接 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 ,这时就会遇到一些问题。

[译] JavaScript 函数式编程指引

纯函数(Pure Functions)

纯函数是无副作用的。啥叫无副作用? 首先,如果一个函数的输出仅仅依赖于其输入,那么该函数就被认为是一个纯函数。如果我们的函数拿到输入后执行了数据库的更新操作,然后返回了一个值,这样的操作就称之为具有副作用,即更新了数据库。也就是说多次调用同一个函数不总是得到相同的结果(内存不足、数据库被锁等情况)。使用纯函数对于我们书写少 bug、易测试的代码很有帮助。

[译] JavaScript 函数式编程指引

头等函数(First Class Functions)

「头等」这个词出现在这里可能看起来比较陌生,但是其意思是指函数可以被用做参数或者可以像其他数据类型一样使用。比如字符串类型、整型和浮点型等。支持头等函数的编程语言允许将函数作为参数传给其他函数,可以把这种方式看做依赖注入。

[译] JavaScript 函数式编程指引

命令式编程和函数式编程对比

这里用下面的例子对两者进行比较,功能是求得数组 [1, 2, 3, 4] 中的数字之和。

命令式编程写法:

[译] JavaScript 函数式编程指引
要将上面的代码改为函数式编程形式的话,这里有一个问题需要解决,那就是使用不可变数据结构。但是我们在每次迭代中都给 sum

赋了不同的值。

为了将代码改为函数式编程思想,让我们来分解一下累加和的计算过程。

首先,我们以某个值作为初始值,在我们的例子中该值为 let sum = 0; ,接下来,我们从数组中取出第一项 1 并将其累加到 sum 上。这一步我们得到了 0 + 1 = 1 。然后重复这个步骤,取出 2 将其累加到 sum 上,即 1 + 2 = 3 ,这一过程遍历到数组尾部为止。

可视化该过程:

[译] JavaScript 函数式编程指引

我们可以将该算法视作两个单独的函数,首先我们需要某种方式来进行数字的相加操作:

[译] JavaScript 函数式编程指引

接下来我们需要以某种方式来循环遍历数组,由于大多数函数式编程通常都使用递归来替代循环,那我们就创建一个递归函数来遍历我们的数组。来看一下该函数可能的样子:

[译] JavaScript 函数式编程指引
在这个函数中, list 是我们想要遍历的数组, index 作为当前要遍历的起点位置,如果我们遍历到达 list 尾部,或者是给出的 list 无效,那么循环结束。否则再次调用 loopindex 加 1。试着在 return loop(list, index + 1) 之前添加 console.log(list[index]) ,我们应该可以看到控制台输出了 1 2 3 4

为了最终实现求得数组累加和,我们需要将 loopadd 函数结合起来,在看下面的例子时要回忆我们上面提到的算法:

[译] JavaScript 函数式编程指引
这里改变了传入 loop 函数中的参数,增加了 accu ,用来保存 list 的累加和。我们直接用 add 函数计算 accu 与与 list 中当前项的和。如果我们 console.log(loop(list));

会发现控制台会输出结果 10。

现在,不如我们更进一步吧。要是我们不想求数组累加和了,改为将它们相乘呢?那现在我们要复制一份 loop 的代码,把 add 函数改成其他东西(可能是 multiply ?)?太麻烦了吧。还记得头等函数吗,我们要利用这种思想将我们的函数变的更为通用。

[译] JavaScript 函数式编程指引

上面例子中唯一不同之处在于我们给 loop 函数新增了一个参数,来接收一个函数。这回我们不传 add 给它了,取而代之的是传一个函数进来,调用该函数获取最终结果。这样就能轻松的实现针对 listadd , multiply , subtract 等一系列操作了。

[译] JavaScript 函数式编程指引

我们不再只是简单的遍历数组了,而是将数组像纸一样折起来,直到我们得到一个结果。在 JavaScript 中,我们把这种函数称之为 reduce

[译] JavaScript 函数式编程指引

结语

我们对函数式编程进行了一些基础的概览,同时看到针对同一问题的不同拆解方式给与我们不同的解法。 reduce 可以说是其他类似 mapfilter 这样的操作的基础。


以上所述就是小编给大家介绍的《[译] JavaScript 函数式编程指引》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

深入理解计算机系统(原书第3版)

深入理解计算机系统(原书第3版)

Randal E.Bryant、David O'Hallaron / 龚奕利、贺莲 / 机械工业出版社 / 2016-11 / 139.00元

和第2版相比,本版内容上*大的变化是,从以IA32和x86-64为基础转变为完全以x86-64为基础。主要更新如下: 基于x86-64,大量地重写代码,首次介绍对处理浮点数据的程序的机器级支持。 处理器体系结构修改为支持64位字和操作的设计。 引入更多的功能单元和更复杂的控制逻辑,使基于程序数据流表示的程序性能模型预测更加可靠。 扩充关于用GOT和PLT创建与位置无关代码的......一起来看看 《深入理解计算机系统(原书第3版)》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具