译者团队(排名不分先后):阿希、blueken、brucecham、cfanlife、dail、kyoko-df、l3ve、lilins、LittlePineapple、MatildaJin、冬青、pobusama、Cherry、萝卜、vavd317、vivaxy、萌萌、zhouyao
关于译者:这是一个流淌着沪江血液的纯粹工程:认真,是 HTML 最坚实的梁柱;分享,是 CSS 里最闪耀的一瞥;总结,是 JavaScript 中最严谨的逻辑。经过捶打磨练,成就了本书的中文版。本书包含了函数式编程之精髓,希望可以帮助大家在学习函数式编程的道路上走的更顺畅。比心。
本书主要探索函数式编程[1](FP)的核心思想。在此过程中,作者不会执着于使用大量复杂的概念来进行诠释,这也是本书的特别之处。我们在 JavaScript 中应用的仅仅是一套基本的函数式编程概念的子集。我称之为“轻量级函数式编程(FLP)”。
注释: 题目中使用了“轻量”二字,然而这并不是一本“轻松的”“入门级”书籍。本书是严谨的,充斥着各种复杂的细节,适合拥有扎实 JS 知识基础的阅读者进行研读。“轻量”意味着范围缩小。通常来说,关于函数式编程的 JavaScript 书籍都热衷于拓展阅读者的知识面,并企图覆盖更多的知识点。而本书则对于每一个话题都进行了深入的探究,尽管这种探究是小范围进行的。
让我们面对这个事实:除非你已经是函数式编程高手中的一员(至少我不是!),否则类似“一个单子仅仅是自函子中的幺半群”这类说法对我们来说毫无意义。
这并不是说,各种复杂繁琐的概念是无意义的,更不是说,函数式编程者滥用了它们。一旦你完全掌握了轻量的函数式编程内容,你将会/但愿会想要对函数式编程的各种概念进行更正式更系统的学习,并且你一定会对它们的意义和原因有更深入的理解。
但是我更想要让你能够现在就把一些函数式编程的基础运用到 JavaScript 编程过程中去,因为我相信这会帮助你写出更优秀的,更符合逻辑的代码。
更多关于本书背后的动机和各种观点讨论,请参看[前言]。
JavaScript 轻量级函数式编程
目录
- 序言
- 前言
- 第 1 章:为什么使用函数式编程?
- 置信度
- 交流渠道
- 接受
- 你不需要它
- 资源
- 第 2 章:函数基础
- 什么是函数?
- 函数输入
- 函数输出
- 函数功能
- 句法
- 来说说 This ?
- 第 3 章:管理函数的输入(Inputs)
- 立即传参和稍后传参
- 一次传一个
- 只要一个实参
- 扩展在参数中的妙用
- 参数顺序的那些事儿
- 无形参风格
- 第 4 章:组合函数
- 输出到输入
- 重排序组合
- 抽象
- 回顾形参
- 第 5 章:减少副作用
- 什么是副作用
- 一次就好
- 纯粹的快乐
- 有或者无
- 纯化
- 第 6 章:值的不可变性
- 原始值的不可变性
- 从值到值
- 重新赋值
- 性能
- 以不可变的眼光看待数据
- 第 7 章: 闭包 vs 对象
- 达成共识
- 相像
- 同根异枝
- 第 8 章:列表操作
- 非函数式编程列表处理
- 映射
- 过滤器
- Reduce
- 高级列表操作
- 方法 vs 独立
- 查寻列表
- 融合
- 列表之外
- 第 9 章:递归
- 定义
- 声明式递归
- 栈、堆
- 重构递归
- 第 10 章:异步的函数式
- 时间状态
- 积极的 vs 惰性的
- 响应式函数式编程
- 第 11 章:融会贯通
- 准备
- 股票信息
- 股票行情界面
- 附录 A: Transducing
- 附录 B: 谦虚的 Monad
- 附录 C: 函数式编程函数库
关于出版
本书主要在 on Leanpub 平台上以电子版本的形式进行出版。我也尝试出售本书的纸质版本,但没有确定的方案。
除了购买本书以外,如果你想要对本书作一些物质上的捐赠,请在 patreon 上进行操作。本书作者感谢你的慷慨解囊。
Patreon
真人教学课程
本书内容大多源自于我教授的一个同名课程(以公司举办的公开或内部研讨会这样的形式进行)。
http://getify.me
如果你喜欢本书的内容,并希望组织此类课程,或者组织关于其他 JS/HTML5/Node.js 课程,请通过以下方式联系我:
http://getify.me
在线视频课程
我还提供一些可以在线点播的 JS 培训课程。我在 Frontend Masters 上开办课程,例如我的 Functional-Lite JS 研讨会。还有一些课程发布在 PluralSight 上。
Contributions
关于内容贡献
非常欢迎对于本书的任何内容贡献。但是在提交 PR 之前请务必认真阅读 Contributions Guidelines。
License & Copyright
版权
本书所有的材料和内容都归属 (c) 2016-2017 Kyle Simpson 所有。
本书根据Creative Commons Attribution-NonCommercial-NoDerivs 4.0 Unported License 进行授权许可.
序
众所周知,我是一个函数式编程迷。我尝试阅读最新的学术论文,业余时间乃至工作间隙研究抽象代数(译者注:抽象代数又称近世代数,是研究各种抽象公理化代数系统的数学学科,也是现代计算机理论基础之一),并四处传播函数式编程的理念和语言。我所书写的 JavaScript 代码,每一条语句都是纯的。没错,我就是一个彻头彻尾的函数式编程教条式的狂热者。关于为什么要写纯的语句,请看我写的这本书。
其实我以前并不是这样子... 我曾痴迷于面向对象,并热衷于使用面向对象的方法来构建“真实世界”。我是人造机器人的发明者,夜以继日地修正机器人以达到更高精度的控制力。我也是有意识木偶的创造者,手指在键盘上的轻舞飞扬赋予了它们生命。做为黑客界的盖比特(译者注:盖比特是玩具之父),在连续不间断的写了 5 年面向对象的代码后,我对于这些成果还是不甚满意。整个过程也并不顺利,我一直感觉自己是一个糟糕的程序员,甚至失去了信心,认为写出既简单,又灵活同时又很好扩展的代码是不可能的。
我想是时候去尝试一些新的方法了,我开始涉足函数式编程的理念,并把它用在我的代码中。我的同事对此非常惊诧,他们根本不知道我在干什么。那段时间里我写的代码非常糟糕、另人生厌、简直是垃圾。造成这样结果的原因是我缺少一个目标或者说愿景。当然现在那个会编码的蟋蟀杰明尼(译者注:原文使用 Jiminy-Coding-Cricket 迪士尼动画人物蟋蟀杰明尼来暗指之前蹩脚的自己)已经不在了。在花费了好长时间,写了好多垃圾程序后我才弄明白怎样正确进行函数式编程。
现在,经历了那些乱七八糟的探索后,我感觉到纯函数编程实现了它所承诺的代码可读性和可复用。我不再发明而是发现我的模型,我像一个正在揭开巨大阴谋的侦探,在软木板上钉满了数学证据。一个数字时代的库斯托(译者注:库斯托是个传奇式的人物,探险家、电影制片人,一个享有戴高乐将军一样世界性声誉的法国人,作者比喻自己学习函数式编程就像库斯托探索海洋一般)以科学的名义记录下了这片奇特土地的特征!虽然并不完美,仍有很多东西要学习,但我对我的工作和产出从未有过现在这般满意!
假如一开始就有这本书,我探索纯函数式编程世界的道路就会更平坦一点,而不是荆棘满地。本书有两层:第一层教会你如何在每天的编码工作中,有效地使用各种各样的函数式构造方法。另一层则更重要,本书会提供一个准星,确保你不会偏离函数式编程的原则。
函数式编程是一种编程范式,Kyle 倡导使用它来实现声明式编程和函数式编程,同时该范式还可以与 JavaScript 世界形成平衡和互动。通过学习本书,你无需彻底理解范式的一切,就能了解纯函数式编程的基础;你无需重新创造轮子,就能获得练习和探索函数式编程的技能,并让代码运行良好;你无需像我之前一样漫无目的地徘徊、甚至走回头路就能让你的职业生涯更上一层楼。你的合作者和同事们一定会欣喜若狂!
Kyle (译者注:Kyle 是火爆全球的《你不知道的 JavaScript》一书原作者)是一位伟大的老师,他对函数式编程的宏伟蓝图不懈追求,不放过任何一个角落和缝隙,同时他也苦学习者之苦。他的风格与行业产生共鸣,将大家的水平整体提高了一个档次。他的工作成果不仅出现在很多人的收藏夹中,也在 JavaScript 发展历史上占据坚实地位。Kyle 老师是绝世高手,你值得拥有。
函数式编程有很多种定义。Lisp 程序员和 Haskell 程序员对于函数式编程的定义截然不同。OCaml 和 Erlang 语言对于函数式编程范式的看法也大相径庭。即使在同一种语言 JavaScript 中,你也能看到函数式编程不同的定义。但总有一种纽带把这些不同的函数式编程连接在一起,这个纽带是一个有些模糊的“我一看就知道”的定义,这听起来有点下流(有人确实觉得函数式编程下流)。本书旨在抓住这个纽带,并不让你学习某些圈子的固定习语,而是让你获取相关知识,这些知识不论在哪个语言的函数式编程中都适用。
本书是你开启函数式编程旅途的绝佳起点。开始吧,Kyle 老师...
-Brian Lonsdorf (@drboolean)
前言
单子是自函子范畴上的一个幺半群
有晕头转向吗?不要担心,我自己也被绕晕了!对于那些已经了解函数式编程的人来说,这些专业术语才有意义,然而对于大部分人而言,它们没有任何意义。
这本书并不打算教你以上那些专业术语的具体含义。如果那正是你想查找的,请继续查阅。事实上,已经有很多从头到尾(正确的方式)介绍函数式编程的书了。如果你在深入学习函数式编程,这些专业术语有很重要的意义,你肯定会对这些专业术语越来越熟悉。
但是本书打算以另一种方式讲解函数式编程。我将从函数式编程的一些基础概念讲起,并尽可能少用晦涩难懂的专业术语。我们将尝试以更实用的方法来探讨函数式编程,而非纯粹的学术角度。毫无疑问,肯定会有专业术语。但是我将会小心谨慎的引入这些术语并解释为何它们如此重要。
可悲的是我并非酷酷的函数式编程俱乐部的一员。我从没有正式学过函数式编程。尽管我有计算机方面的教育背景并对数学有一定了解,但数学符号跟我理解的编程完全是两回事。我从来没写过一行 Scheme、Clojure 或 Haskell 代码,也不是老派的 Lisp 程序员。
我曾参加过不计其数的讨论函数式编程的会议,每次都希望能彻底搞明白函数式编程中那些神秘的概念到底是什么意思。然而每次我都失望而归,那些概念在我脑海里乱成一团,我甚至不清楚自己学了些什么。也许我学到了些东西吧,但是很长时间以来我都不能确定自己学到了什么。
通过不断的编程实践,而非站在学术的角度,我慢慢的理解了那些对函数式编程者[1]
来说很简单直白的重要概念。你是否也有类似的经历 —— 你早就知道一件事,但直到很久之后你突然发现它竟然还有一个你从来不知道的名字!?
也许你像我一样;好几年前就听说过像“map-reduce”,“big data”等这些术语,但并不懂它们的实际意义。最终我明白了map(..)函数到底做了哪些事情 —— 在我知道列表操作是通向函数式编程者之路的基石,并且为何它们如此重要之后。我知道映射很久了,甚至在我知道它叫map(..)
之前。
最终我开始整理这些想法并将它们称之为「轻量级函数式编程」(FLP)。
使命
但是,为什么学习函数式编程如此重要,即便只是学习轻量级函数式编程?
最近几年我越来越深刻的理解到编程的核心是人,而不是代码,我甚至将其视为一种信仰。我坚信代码只是人类交流的手段,只是它产生的副作用(仿佛听到了自我引用的笑声)才对电脑发出具体指令。
在我看来,函数式编程的核心在于让你在编程时使用一些广为人知、易于理解的模式。经过验证,这些模式可以有效隔离让代码难以理解的错误。所以,函数式编程 —— 咳,轻量级函数式编程 —— 是每个开发者都可以掌握的重要工具之一。
monad的含义是,一旦你搞懂了,你就无法跟别人解释什么是monad了。
Douglas Crockford 2012 "Monads and Gonads"
https://www.youtube.com/watch?v=dkZFtimgAcM
我希望这本书有可能打破上面的诅咒,尽管我们要到最后的附录部分才开始讨论「monad」。
科班出身的函数式编程者经常宣称只有 100% 使用函数式编程才算是真正地使用函数式编程:这是一种要么全有要么全无的主张。它会让人觉得如果编程时只有一部分使用了函数式编程而另一部分没用到,整个程序会被那些没有使用函数式编程的部分污染,从而认为使用函数式编程并不值得。
我想明确地说:我认为绝对主义并不存在。这没有意义,就像愚蠢地建议我只有使用完美的语法,这本书才算完美,如果犯了一点点错误,就会让整本书质量变低一样。
我写地越清楚,前后越一致,你阅读此书的体验将越好。但我不是一个完美无缺的作者。有些章节可能比另外一些写的好。但是那些有待提高的章节不会使书中写的好的部分黯然失色。
同样的道理也适用于代码。随着你越来越多的使用函数式编程的模式,你的代码质量会越来越高。25% 的时间使用它们,你会得到一些好处。80% 的时间使用它们,你将收益更多。
除了几处仅存的特例,你不会在本书里看到很多绝对的论断。我们讨论的是要追求的目标和现实中方方面面的权衡。
欢迎来到最实用的函数式编程的学习之旅。我们将共同探讨学习!
活动报名地址: http://www.huodongxing.com/event/5399668594900