翻译连载 | 附录 C:函数式编程函数库-《JavaScript轻量级函数式编程》 |《你不知道的JS》姊妹篇

关于译者:这是一个流淌着沪江血液的纯粹工程:认真,是 HTML 最坚实的梁柱;分享,是 CSS 里最闪耀的一瞥;总结,是 JavaScript 中最严谨的逻辑。通过捶打磨练,成就了本书的中文版。本书包含了函数式编程之精髓,但愿能够帮助你们在学习函数式编程的道路上走的更顺畅。比心。前端

译者团队(排名不分前后):阿希bluekenbrucechamcfanlifedailkyoko-dfl3velilinsLittlePineappleMatildaJin冬青pobusamaCherry萝卜vavd317vivaxy萌萌zhouyaonode

JavaScript 轻量级函数式编程

附录 C:函数式编程函数库

若是您已经从头至尾通读了此书,请花一分钟的时间停下来回顾一下从第 1 章到如今的收获。至关漫长的一段旅程,不是吗?但愿您已经收获了大量新知识,并用函数式的方式思考你的程序。git

在本书即将完结时,我想给你提供一些关于使用官方函数式编程函数库的快速指南。注意这并非一个详细的文档,而是将你在结束“轻量级函数式编程”后进军真正的函数式编程时应该注意的东西快速梳理一下。程序员

若是有可能,我建议你不要作从新造轮子这样的事情。若是你找到了一个能知足你需求的函数式编程函数库,那么用它就对了。只有在你实在找不到合适的库来应对你面临的问题时,才应该使用本书提供的辅助实用函数 —— 或者本身造轮子。github

目录

在本书第 1 章曾列出了一个函数式编程库的列表,如今咱们来扩展这个列表。咱们不会涉及全部的库(它们之中有许多重复的内容),但下面这些你应该有所关注:编程

上面的列表只列出了全部函数式编程库的一小部分,并非说没有在列表中列出的库就很差,也不是说列表中列出的就是最佳选择,总之这只是 JavaScript 函数式编程世界中的一瞥。您能够前往这里查看更完整的函数式编程资源。小程序

Fantasy Land(又名 FL)是函数式编程世界中十分重要的学习资源之一,与其说它是一个库,不如说它是一本百科全书。微信小程序

Fantasy Land 不是一份为初学者准备的轻量级读物,而是一个完整而详细的 JavaScript 函数式编程路线图。为了尽量提高互通性,FL 已经成为 JavaScript 函数式编程库遵循的实际标准。数组

Fantasy Land 与“轻量级函数式编程”的概念相反,它以火力全开的姿态进军 JavaScript 的函数式编程世界。也就是说,当你的能力超越本书时,FL 将会成为你接下来前进的方向。我建议您将其保存在收藏夹中,并在您使用本书的概念进行至少 6 个月的实战练习以后再回来。微信

Ramda (0.23.0)

摘自 Ramda 文档:

Ramda 函数自动地被柯里化。

Ramda 函数的参数通过优化,更便于柯里化。须要被操做的数据每每放在最后提供。

我认为合理的设计是 Ramda 的优点之一。值得注意的是,Ramda 的柯里化形式(彷佛大多数的库都是这种形式)是咱们在第 3 章中讨论过的“松散柯里化”。

第 3 章的最后一个例子 —— 咱们定义无值(point-free)工具函数 printIf() —— 能够在 Ramda 中这样实现:

function output(msg) {
    console.log( msg );
}

function isShortEnough(str) {
    return str.length <= 5;
}

var isLongEnough = R.complement( isShortEnough );

var printIf = R.partial( R.flip( R.when ), [output] );

var msg1 = "Hello";
var msg2 = msg1 + " World";

printIf( isShortEnough, msg1 );            // Hello
printIf( isShortEnough, msg2 );

printIf( isLongEnough, msg1 );
printIf( isLongEnough, msg2 );            // Hello World

与咱们在第 3 章中的实现相比有几处不一样:

  • 咱们使用 R.complement(..) 而不是 not(..)isShortEnough(..) 周围新建一个否认函数 isLongEnough(..)
  • 使用 R.flip(..) 而不是 reverseArgs(..) 函数,值得一提的是,R.flip(..) 仅交换头两个参数,而 reverseArgs(..) 会将全部参数反向。在这种情景下,flip(..) 更加方便,因此咱们再也不须要使用 partialRight(..) 或其余投机取巧的方式进行处理。
  • R.partial(..) 全部的后续参数以单个数组的形式存在。
  • 由于 Ramda 使用松散柯里化,所以咱们不须要使用 R.uncurryN(..) 来得到一个包含全部参数的 printIf(..)。若是咱们这样作了,就至关于使用 R.uncurryN(2, ..) 包裹 R.partial(..) 进行调用,这是彻底没有必要的。

Ramda 是一个受欢迎的、功能强大的库。若是你想要在你的代码中实践 FP,从 Ramda 开始是个不错的选择。

Lodash/fp (4.17.4)

Lodash 是整个 JS 生态系统中最受欢迎的库。Lodash 团队发布了一个“FP 友好”的 API 版本 —— "lodash/fp"

在第 8 章中,咱们讨论了合并独立列表操做(map(..)filter(..) 以及 reduce(..))。使用“lodash/fp”时,你能够这样作:

var sum = (x,y) => x + y;
var double = x => x * 2;
var isOdd = x => x % 2 == 1;

fp.compose( [
    fp.reduce( sum )( 0 ),
    fp.map( double ),
    fp.filter( isOdd )
] )
( [1,2,3,4,5] );                    // 18

与咱们所熟知的 _. 命名空间前缀不一样,“lodash/fp”将 fp. 定义为其命名空间前缀。我发现一个颇有用的区别,就是 fp._. 更容易识别。

注意 fp.compose(..)(在常规 lodash 版本中又名 _.flowRight(..))接受一个函数数组,而不是独立的函数做为参数。

lodash 拥有良好的稳定性、普遍的社区支持以及优秀的性能,是你探索 FP 世界时的坚实后盾。

Mori (0.3.2)

在第 6 章中,咱们已经快速浏览了一下 Immutable.js 库,该库多是最广为人知的不可变数据结构库了。

让咱们来看一下另外一个流行的库:Mori。Mori 设计了一套不同凡响(从表面上看更像函数式编程)的 API:它使用独立的函数而不直接在值上操做。

var state = mori.vector( 1, 2, 3, 4 );

var newState = mori.assoc(
    mori.into( state, Array.from( {length: 39} ) ),
    42,
    "meaning of life"
);

state === newState;                        // false

mori.get( state, 2 );                    // 3
mori.get( state, 42 );                    // undefined

mori.get( newState, 2 );                // 3
mori.get( newState, 42 );                // "meaning of life"

mori.toJs( newState ).slice( 1, 3 );    // [2,3]

这是一个指出关于 Mori 的一些有趣的事情的例子:

  • 使用 vector 而不是 list(你可能会想用的),主要是由于文档说它的行为更像 JavaScript 中的数组。
  • 不能像在操做原生 JavaScript 数组那样在任意位置设置值,在 vector 结构中,这将会抛出异常。所以咱们必须使用 mori.into(..),传入一个合适长度的数组来扩展 vector 的长度。在上例中,vector 有 43 个可用位置(4 + 39),因此咱们能够在最后一个位置(索引为 42)上写入 "meaning of life" 这个值。
  • 使用 mori.into(..) 建立一个较大的 vector,再用 mor.assoc(..) 根据这个 vector 建立另外一个 vector 的作法听起来效率低下。可是,不可变数据结构的好处在于数据不会进行克隆,每次“改变”发生,新的数据结构只会追踪其与旧数据结构的不一样之处。

Mori 受到 ClojureScript 极大的启发。若是您有 ClojureScript 编程经验,那您应该对 Mori 的 API 感到很是熟悉。因为我没有这种编程经验,所以我感受 Mori 中的方法名有点奇怪。

但相比于在数据上直接调用方法,我真的很喜欢调用独立方法这样的设计。Mori 还有一些自动返回原生 JavaScript 数组的方法,用起来很是方便。

总结

JavaScript 不是做为函数式编程语言来特别设计的。不过其自身的确拥有不少对函数式编程很是友好基础语法(例如可做为变量的函数、闭包等)。本章说起的库将使你更方便的进行函数式编程。

有了本书中函数式编程概念的武装,相信你已经准备好开始处理现实世界的代码了。找一个优秀的函数式编程库来用,而后练习,练习,再练习。

就是这样了。我已经将我目前所知道的知识分享给你了。我在此正式认证您为“JavaScript 轻量级函数式编程”程序员!好了,是时候结束咱们一块儿学习 FP 这部分的“章节”了,但个人学习之旅还将继续。我但愿,你也是!

【上一章】翻译连载 | 附录 B: 谦虚的 Monad-《JavaScript轻量级函数式编程》 |《你不知道的JS》姊妹篇

iKcamp原创新书《移动Web前端高效开发实战》已在亚马逊、京东、当当开售。

iKcamp官网:https://www.ikcamp.com
访问官网更快阅读所有免费分享课程:
《iKcamp出品|全网最新|微信小程序|基于最新版1.0开发者工具之初中级培训教程分享》
《iKcamp出品|基于Koa2搭建Node.js实战项目教程》
包含:文章、视频、源代码

相关文章
相关标签/搜索
本站公众号
   欢迎关注本站公众号,获取更多信息