1、涵盖大部分函数式编程思想
2、幽默风趣,通俗易懂
3、是Clojure风格的JavaScript
4、用JavaScript实现了很多奇技淫巧
5、所有开发者都可以在本书中找到一些启发
在后端,函数式语言层出不穷。在前端,函数式最后的边界也已经被渐渐打破。Scala的Scala.js、Clojure的ClojureScript都试图同构移向前端。然而,原生JavaScript其实也可以通过丰富的库让前端的函数式编程一样的舒适和优雅。本书涵盖了大部分函数式编程思想,包括JavaScript的函数式支持,Clojure风格的集合、递归、函数组合、宏、模式匹配、实用的Monads,以及前端的并发编程。本书适合想要了解函数式编程的JavaScript程序员或者想学习JavaScript的函数式程序员阅读。
欧阳继超,ThoughtWorks高级咨询师,活跃开源贡献者(github.com/jcouyang),热爱编程与写作,译有《函数式JavaScript》以及若干开源书籍与文档。
作为 Ramda.js 的作者之一,我非常喜欢 Braithwaite 的《JavaScript Allonge》,喜欢 Fogus 的《Functional JavaScript》,我非常激动又有一本关于JavaScript的函数式书籍,希望尽快能见到这本书的英文版。
—— CrossEye
第1章 函数式JavaScript 1
1.1 JavaScript也是函数式语言吗 1
1.1.1 编程范式 1
1.1.2 JavaScript的函数式支持 3
1.2 作为函数式语言,JavaScript还差些什么 10
1.2.1 不可变数据结构 11
1.2.2 惰性求值 11
1.2.3 函数组合 12
1.2.4 尾递归优化 13
1.3 Underscore你错了 14
1.3.1 跟大家都不一样的 map 函数 14
1.3.2 ClojureScript 16
1.3.3 Mori 17
1.4 小结 18
第2章 集合 19
2.1 集合的使用 20
2.1.1 向量(vector) 20
2.1.2 Map 23
2.1.3 函数组合子 24
2.2 持久性数据结构 27
2.2.1 向量的持久性数据结构 28
2.2.2 最后一片叶子不完整 31
2.2.3 所有叶子完整且叶子个数不大于完全树的叶子个数 32
2.2.4 所有叶子完整且叶子个数大于完全树的叶子个数 34
2.3 不可变性 35
2.3.1 致命魔术 36
2.3.2 引用透明性 38
2.3.3 函数式React 40
2.3.4 线程不安全 42
2.4 惰性序列 44
2.4.1 改良奥利奥吃法 44
2.4.2 惰性求值与及早求值 46
2.4.3 惰性求值的实现 48
2.5 小结 50
第3章 递归 51
3.1 不可变性与递归 51
3.1.1 真的需要循环吗 52
3.1.2 递归还是循环 54
3.2 柯里悖论 55
3.2.1 Y组合子 57
3.2.2 栈是多么容易爆 60
3.3 尾递归优化 62
3.4 蹦跳乐园(Trampoline) 64
3.4.1 有穷状态机(DFA) 65
3.4.2 Trampoline 67
3.5 小结 69
第4章 函数组合 70
4.1 Underscore到底做错了什么 70
4.1.1 自由(Free)变量与约束(Bound)变量 72
4.1.2 闭包 74
4.2 柯里化有什么用 75
4.3 Transducer 78
4.3.1 Reducer 79
4.3.2 来看看更好更快的解法 79
4.3.3 Reducer 80
4.3.4 Reducible 81
4.3.5 Transducer详解 82
4.3.6 跟柯里化有什么区别 83
4.4 组合与管道 84
4.4.1 管道(Pipeline) 84
4.4.2 组合与管道 86
4.4.3 管道函数 87
4.5 小结 87
第5章 Macro宏 89
5.1 什么是REPL 89
5.1.1 宏扩展器(Macro Expander) 90
5.1.2 那么前端怎么办 92
5.2 为什么要语法糖 93
5.2.1 只是为了语法漂亮吗 94
5.3 Sweet.js 94
5.3.1 Rule Macro 95
5.3.2 Case Macro 97
5.4 Infix Macro 和 Operator 104
5.4.1 Infix Macro 104
5.4.2 自定义操作符 105
5.5 小结 106
第6章 模式匹配 107
6.1 Destructure 107
6.1.1 对象 109
6.1.2 数组 109
6.1.3 函数 109
6.2 Arity 函数 110
6.3 Fizz Buzz 111
6.3.1 字面匹配(Literal Matching) 111
6.3.2 绑定 113
6.3.3 Vector与Map匹配 113
6.3.4 Guard 114
6.3.5 Sparkler 114
6.4 代数数据类型(ADT) 116
6.5 小结 118
第7章 Monadic编程 119
7.1 链式调用 119
7.1.1 Promise 120
7.1.2 高阶Promise 122
7.2 Monad 123
7.2.1 函子(Functor) 123
7.2.2 Applicative Functor 126
7.2.3 含幺半群(Monoid) 130
7.2.4 Monad就是容器界的管道 132
7.2.5 Monad就是自函子范畴上的一个幺半群 136
7.3 走钢丝 139
7.3.1 用Monad表示薛定谔猫 139
7.3.2 皮尔斯走钢丝 140
7.4 Monad在JavaScript中的应用 143
7.4.1 Promise版本的走钢丝 144
7.4.2 When 144
7.5 Reactive编程 146
7.5.1 流(Stream) 146
7.5.2 Functor 147
7.5.3 Applicative 147
7.5.4 Monad 148
7.5.5 一个“简单”的Reactive实例 149
7.6 小结 153
第8章 并发编程 154
8.1 什么是并发 154
8.1.1 异步与多线程 155
8.1.2 JavaScript的并发模型 157
8.2 通信顺序进程(CSP) 160
8.3 使用Generator实现CSP 162
8.3.1 Generator 163
8.3.2 Go Block 163
8.3.3 timeout 164
8.3.4 take <! 165
8.3.5 put >! 165
8.3.6 JavaScript CSP版本的例子 166
8.4 实战 CSP 168
8.4.1 使用移植的core.async 168
8.4.2 使用ES7中的异步函数 169
8.4.3 try catch 170
8.5 小结 173
参考资料 174
4.2 柯里化有什么用
还记得上一章提到的提出柯里悖论的 Haskell Curry 吗?这里要说到的柯里化中的 柯里,完全不是巧合,确实就是 Haskell Curry 的姓。借助于利用他的名字命名的语言 Haskell,可以更好地理解柯里化。
在 Haskell 语言中,函数是会自动柯里化的:
max 3 4
其实就是:
(max 3) 4
可以看看 max 与 max 3 函数的类型:
ghci> :t max
max :: Ord a => a -> a -> a
看明白了吗?Ord a => 表示类型约束 a 为可以比较大小的类型,因此 max 的类型可以翻译成:当给定一个 a,会得到 a -> a,即接收一个 a 类型,返回一个 a 类型。接下来再看看 max 3 的类型就好理解了。
ghci> :t max 3
(Num a, Ord a) => a -> a
左侧表示类型约束 a 可以是 Ord 或者 Num,意思是 max 3 还是一个函数,如果给定一个 Ord 或者 Num 类型的参数,则返回一个 Ord 或者 Num 类型。
现在是不是清晰了?在Haskell中,每给定一个参数,函数如果是多参数的,该函数还会返回一个处理余下参数的函数。这就是自动柯里化。
而在 JavaScript(以及大多数语言) 中则不是这样的,如果给定多参函数的部分参数,函数会默认其他参数是 undefined ,而不会返回处理剩余参数的函数。
反正最后都要计算出值,那么柯里化和一次把所有约束添加上有什么区别呢?
再回到上一节的例子,还记得我们要编写一本能拿到所有男性姓名的操作手册吧。我们把_.filter 硬是改写成了柯里化版本的Rfilter,终于可以组合我们的操作手册了:
const getMaleName = _.compose(
data => _.map(data, d => d.name), // <1>
Rfilter(d => d.sex == 'male')) // <2>
getMaleName(data)
(1)对于还没有柯里化的_.map就只能说:提取数据的名字,这里的数据等于传入的数据。
(2)我可以明确地在手册里写:过滤出数据中性别为男性的。
对比这两行明显可以看出,第一行特别啰唆,就是因为把本来应该是自由变量的data当约束变量给了_.map函数。相反,Rfilter并不需要data这个自由变量,意义却完全一样,这种方式又叫作“Pointfree”或者“Pointless”。
而且,当柯里化_.filter函数之后,我们实际上得到的是两个函数,而不只是一个。给定一个约束后得到一个新的函数,这个函数就可以拿来组合其他函数,或者再给定不同约束返回不同给定值。
当可组合的函数越多,就能够越大程度地复用现有函数,组合出更多的函数。就像乐高积木,如果买一般的通用乐高,其实可以组合出各式各样的形状,但是一旦有些积木给了一些设定,比如你买了一盒辛普森一家的乐高(图4-1),就很难和生活大爆炸的乐高(图4-2)组合到一块去,因为其中很多积木都添加了一些设定,设定越多,则离抽象越远,离具体越近,也就越难复用。
1.看本书之前你要知道
1)最好能看懂JavaScript代码
这既不是一本介绍Clojure的书,也不是一本介绍JavaScript的书,而是一本介绍如何用JavaScript函数式编程的书。其中一些函数式的思想和表现形式都借用了Clojure,因此叫作Clojure 风格的函数式JavaScript,但是并不要求在读本书前会Clojure ,而只需要能阅读JavaScript代码。如果你会Clojure,则可以完全忽略我解释Clojure代码的段落,当然JavaScript的部分才是重点。
2)你可能买错书了,如果你
想学JavaScript
这不是一本JavaScript的教科书,这里只会介绍如何用JavaScript进行函数式编程,所以如果想要系统地学习JavaScript,则学习《JavaScript语言精粹》可能已经足够了。另外,如果读者的英文水平好的话,则还有一本可以在线免费阅读的JavaScript Allonge。
想学Clojure
同样,这也不是一本Clojure的教科书,只含有一些用于阐述函数式编程思想的Clojure代码。你确实可以学到一些Clojure编程知识,但很可能是非常零碎且不完整的知识。如果想要系统地了解和学习Clojure,则非常推荐你阅读The Joy of Clojure ,另外,如果读者英文比较好,还有一本可以免费在线阅读的CLOJURE for the BRAVE and TRUE也非常不错。
是函数式编程的专家
如果你已经在日常工作或学习中使用Scala、Clojure或者Haskell等函数式语言编程的话,那么本书对你在函数式编程上的帮助不会太大。不过:这本书对缓解你从函数式语言迁移到JavaScript编程的不适应该是非常有效的。这也正是本书的目的之一。
2.准备环境
在开始阅读本书之前,如果你希望能运行书中的代码,可能需要一些环境的配置。而且书中的所有源码和运行方式都可以在本书的Github仓库 中找到。当然如果你使用Emacs(同时还配置了org babel的话)阅读本书的源码,对于大部分代码只需要光标放在代码处按c-c c-c即可。
JavaScript
原生的JavaScript没有什么好准备的,可以通过Node或者Firefox(推荐)的Console运行代码。当然第5章会有一些使用Sweet.js写的Macro,这则需要安装Sweet.js。
– 安装Node/io.js
(1)下载Node.js。
(2)如果使用Mac,可以直接用Brew安装。
brew install node
# 或者
brew install iojs
– 安装Sweet.js
在安装完Node.js之后在命令行输入:
npm install -g sweet.js
Clojure
书中的Clojure代码大都用来描述函数式编程的概念,当然如果想要运行书中的 Clojure 代码,首先需要安装JVM或者JDK ,至少需要1.6版本,推荐安装1.8版本。
– 安装 leiningen
leiningen是Clojure的包管理工具,类似于Node的Npm、Ruby的bundle、Python的pip。另外leiningen还提供脚手架的功能。可以通过官网的脚本安装 。Mac用户可以简单地使用brew install leiningen安装。
安装完成之后,就可以运行lein repl,打开repl,试试输入下列Clojure代码,你将会立马看见结果。
(+ 1 1)
;=> 2
– 编辑器
如果更喜欢使用编辑器来编辑更长的一段代码,我推荐非Emacs用户使用Light Table ,Intellij用户则使用cursive 。当然如果读者已经在使用Emacs,那就更完美了,Emacs cider mode 是Clojure编程不错的选择。
3.本书中的代码
书中的所有源码和运行方式都可以在本书的Github仓库 中找到,书中几乎所有的例子都以测试的形式完成。
4.反馈
如果你是开源贡献者,那么应该很习惯通过Github Issue9提交任何反馈,如果是Pull Request,那就更好了。当然如果没有使用过Github Issue也没有关系,这里 有非常详细的教程。
5.代码风格约定
本书的JavaScript代码都遵循Airbnb JavaScript Style Guide 中的ES5和React的风格约定。
6.本书的组织结构
第1章
将介绍JavaScript的基本函数式背景,简要地介绍为什么要关心函数式编程,为什么说Underscore不够函数式,JavaScript要作为完整的函数式语言还缺些什么?
第2章
主要介绍Clojure的集合数据结构。这是个无聊但是又很重要的章节,可以说函数式编程最基本、最重要的就是集合操作。本章会涉及如何操作集合、惰性求值与惰性序列。
第3章
在了解了持久性数据结构后,我们可能会产生疑惑,如果数据结构都是不可变的,那么循环该怎么写呢?本章就是要解开各种使用不可变数据结构的疑惑,用这些不可变数据结构可以切换一种编程的思维方式。
第4章
Underscore并不利于函数组合,但是函数组合其实是函数式编程最重要的思想。在这一章里面,我会详细介绍为什么说Underscore错了,而为什么要喜欢上柯里化,以及Clojure 1.7新推出的Transducer又是如何帮助我们更容易组合出更高效的函数的。
第5章
我特别不情愿把Macro翻译成宏。宏特别容易让人以为是 C 语言里面那个#define宏,虽然都是宏,但其实那里跟这里说的Macro不是一个级别的。Macro是Lisp语言之所以特别的原因之一。本章我们就来看看到底什么是、为什么,以及如何在JavaScript中使用Macro。
第6章
这里说的模式匹配包括两种:一种是按位置或者key匹配集合,取出相应数据。另一种是Haskell风格的对函数参数的模式匹配。本章篇幅比较小,因为模式匹配并不是Clojure(也不是JavaScript)的主要模式,尽管在一些有强大类型系统的函数式语言(Scala、Haskell)中比较重要。
第7章
Monad这个范畴论里出来的神秘玩意,但你可能没有在意,其实这在前端世界早都被玩腻了。本章将会介绍Monad和它的朋友们,并且将带你体验JavaScript的Promise,以及Reactive编程。
第8章
并发编程一直是令人头疼的编程方式,直到Clojure和Go的出现,彻底改变了我们并发编程的方式。而对于单线程的JavaScript,基于事件循环的并发模型也一直困扰着我们,到底能从Clojure学些什么,可以使我们的前端并发编程之路更顺畅一些呢?本章将带你熟悉并发、JavaScript的并发模型,以及CSP并发模型。
7.本书使用的约定
本书使用以下字体排版约定。
1)楷体
表示新的术语。
2)等宽字体
代码清单,出现在段落之内则表示变量、函数名、关键字等。
3)粗体
重点概念。
4)下画线
需要填入的词,我可能已经帮大家填上了。
5)横线
可以忽略的词。
我是一名有几年工作经验的前端工程师,一直以来,都在寻找能够让我跳出舒适区,学习新技术的契机。函数式编程这个概念,我听过很多次,也尝试过阅读一些相关的技术文章,但总觉得有些零散,缺乏一个系统性的学习路径。这本书的名字《前端函数式攻城指南》,非常准确地捕捉到了我目前的学习需求——我需要一个能够指导我“攻克”函数式编程这个技术难关的“指南”。我希望这本书的内容能够从最基础的概念讲起,但又不会停留于表面,而是能够深入到实际的应用层面。例如,它是否会详细讲解如何在JavaScript中实现高阶函数,如何利用函数组合来构建复杂的逻辑,以及如何通过不可变数据结构来避免副作用?我更期待的是,书中能够提供一些具体的代码片段,甚至是小型的项目示例,来展示函数式编程在解决实际前端开发问题时的强大威力,比如状态管理、异步操作、事件处理等等。
评分作为一名前端开发者,我一直在寻找能够提升代码质量和开发效率的方法。函数式编程的理念一直让我很感兴趣,但市面上相关的书籍大多晦涩难懂,或者过于偏重理论,难以在实际工作中找到切入点。这本书的名字——《前端函数式攻城指南》,非常直观地传达了它的核心价值。我预感它会是一本能够“实战”的教程,而不是一本“纸上谈兵”的理论手册。我希望它能通过大量的代码示例、清晰的图示以及逐步深入的讲解,帮助我理解函数式编程的各种核心概念,比如纯函数、不可变性、高阶函数、函数组合等等,并且能够教会我如何在React、Vue或其他主流前端框架中有效地运用这些概念。我尤其期待它能分享一些在实际开发中遇到的典型问题,以及如何用函数式的方式来优雅地解决它们,从而让我的代码更加健壮、易于理解,并且能够大大减少bug的产生。
评分这本书的标题《前端函数式攻城指南》让我眼前一亮,它精准地戳中了当前前端技术发展的一个重要方向。我一直认为,掌握函数式编程是成为一名优秀前端工程师的必经之路,但很多时候,对于如何将抽象的函数式概念转化为实际可操作的前端代码,感到有些迷茫。我希望这本书能够为我提供一个清晰的学习框架,从函数式编程的基础概念出发,逐步引导我理解它在前端开发中的实际应用。我期待书中能够包含一些关于如何利用函数式思维来重构现有代码、如何编写更简洁高效的UI组件、以及如何更有效地管理应用状态的实战案例。这本书如果能深入讲解如何将这些函数式编程的优点,如纯粹性、不可变性、声明式风格等,融入到日常的前端开发流程中,那将是我最大的收获。
评分对于我这种在函数式编程领域还处于探索阶段的开发者来说,这本书的出现简直是福音。我一直对函数式编程带来的那种“声明式”的美感心向往之,但每次尝试着去理解那些复杂的概念时,总会感到力不从心。我寄希望于这本书能够用一种更加清晰、更有条理的方式,将函数式编程的思想渗透到前端开发的各个方面。我期待它能够不仅仅是罗列函数式编程的特性,而是能够深入分析这些特性为何对前端开发如此重要,以及它们如何帮助我们写出更具可读性、可维护性和可扩展性的代码。也许书中会包含一些关于函数式编程在处理副作用、提升代码纯度、以及简化组件逻辑方面的具体技巧和模式。我对那些能够帮助我提升代码的“健壮性”和“可预测性”的技巧尤为感兴趣,因为这直接关系到项目的稳定性和开发效率。
评分这本书的封皮设计真是令人耳目一新,简洁却又不失专业感。我刚拿到手的时候,就被那淡淡的磨砂质感吸引了。拿到这本书,我心里就想着,终于有一本能让我系统地了解函数式编程在前端开发中的应用了。最近几年,函数式编程的概念在技术圈子里越来越火,很多大厂的招聘要求里也常常出现,但总是感觉有些玄乎,难以真正落地。这本书的出现,就像是为我打开了一扇新的大门。我期待它能用一种更加平易近人、循序渐进的方式,把我从命令式编程的思维模式中引导出来,让我领略到函数式编程带来的代码优雅、可维护性和可测试性。特别是它提到的“攻城”二字,让我感觉这本书不仅仅是理论的讲解,更像是一场实战演练,会包含很多实际的案例和解决方案,能帮助我真正掌握如何在实际项目中应用这些概念,解决那些棘手的技术难题。
评分很不错,学习啦,很不错,学习啦,很不错,学习啦,很不错,学习啦,
评分好书!
评分好书!
评分还可以吧,挺不错的
评分作者比较扯吧,感觉对不起价格,什么人都能出书了
评分过年囤书的。京东快递速度很快
评分只能说有点深澳
评分全新正版,送货及时,活动给力,蛮好。
评分不错 挺好的
本站所有内容均为互联网搜索引擎提供的公开搜索信息,本站不存储任何数据与内容,任何内容与数据均与本站无关,如有需要请联系相关搜索引擎包括但不限于百度,google,bing,sogou 等
© 2025 book.coffeedeals.club All Rights Reserved. 静流书站 版权所有