├── .gitignore ├── .nojekyll ├── 0.md ├── 1.md ├── 10.md ├── 11.md ├── 12.md ├── 13.md ├── 14.md ├── 15.md ├── 16.md ├── 17.md ├── 18.md ├── 19.md ├── 2.md ├── 20.md ├── 21.md ├── 3.md ├── 4.md ├── 404.html ├── 5.md ├── 6.md ├── 7.md ├── 8.md ├── 9.md ├── CNAME ├── Dockerfile ├── LICENSE ├── README.md ├── SUMMARY.md ├── asset ├── docsify-apachecn-footer.js ├── docsify-baidu-push.js ├── docsify-baidu-stat.js ├── docsify-clicker.js ├── docsify-cnzz.js ├── docsify-copy-code.min.js ├── docsify.min.js ├── prism-darcula.css ├── prism-javascript.min.js ├── search.min.js ├── style.css └── vue.css ├── cover.jpg ├── diff-en ├── 2ech0-3ech0.diff ├── 2ech1-3ech1.diff ├── 2ech11-3ech12.diff ├── 2ech12-3ech13.diff ├── 2ech13-3ech14.diff ├── 2ech14-3ech15.diff ├── 2ech15-3ech16.diff ├── 2ech16-3ech17.diff ├── 2ech17-3ech18a.diff ├── 2ech18-3ech18b.diff ├── 2ech2-3ech2.diff ├── 2ech20-3ech20.diff ├── 2ech21-3ech21.diff ├── 2ech3-3ech3.diff ├── 2ech4-3ech4.diff ├── 2ech5-3ech5.diff ├── 2ech6-3ech6.diff ├── 2ech8-3ech8.diff └── 2ech9-3ech9.diff ├── img ├── 0-0.jpg ├── 1-0.jpg ├── 10-0.jpg ├── 11-1.svg ├── 11-2.png ├── 12-0.jpg ├── 12-1.svg ├── 13-0.jpg ├── 14-0.jpg ├── 14-1.svg ├── 14-2.svg ├── 14-3.svg ├── 14-4.svg ├── 15-0.jpg ├── 16-0.jpg ├── 16-1.png ├── 16-2.svg ├── 17-0.jpg ├── 17-1.png ├── 17-2.svg ├── 17-3.svg ├── 17-4.png ├── 17-5.png ├── 18-0.jpg ├── 19-0.jpg ├── 19-1.png ├── 19-2.svg ├── 19-3.svg ├── 2-0.jpg ├── 2-1.png ├── 2-2.svg ├── 2-3.svg ├── 2-4.svg ├── 2-5.svg ├── 20-0.jpg ├── 21-0.jpg ├── 21-1.png ├── 3-0.jpg ├── 4-0.jpg ├── 4-1.svg ├── 4-2.jpg ├── 4-3.svg ├── 5-0.jpg ├── 5-1.png ├── 6-0.jpg ├── 6-1.svg ├── 7-0.jpg ├── 7-1.png ├── 8-0.jpg ├── 9-0.jpg ├── 9-1.svg ├── 9-2.svg ├── 9-3.svg └── qr_alipay.png ├── index.html ├── styles └── ebook.css └── update.sh /.gitignore: -------------------------------------------------------------------------------- 1 | _book 2 | Thumbs.db 3 | -------------------------------------------------------------------------------- /.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apachecn/eloquent-js-3e-zh/12ed9090d2ddb50e23255e1a3790e5fdb849979b/.nojekyll -------------------------------------------------------------------------------- /0.md: -------------------------------------------------------------------------------- 1 | # 零、前言 2 | 3 | > 原文:[Introduction](https://eloquentjavascript.net/00_intro.html) 4 | > 5 | > 译者:[飞龙](https://github.com/wizardforcel) 6 | > 7 | > 协议:[CC BY-NC-SA 4.0](http://creativecommons.org/licenses/by-nc-sa/4.0/) 8 | > 9 | > 自豪地采用[谷歌翻译](https://translate.google.cn/) 10 | > 11 | > 部分参考了[《JavaScript 编程精解(第 2 版)》](https://book.douban.com/subject/26707144/) 12 | 13 | > We think we are creating the system for our own purposes. We believe we are making it in our own image... But the computer is not really like us. It is a projection of a very slim part of ourselves: that portion devoted to logic, order, rule, and clarity. 14 | 15 | > Ellen Ullman,《Close to the Machine: Technophilia and its Discontents》 16 | 17 | ![](img/0-0.jpg) 18 | 19 | 这是一本关于指导电脑的书。时至今日,计算机就像螺丝刀一样随处可见,但相比于螺丝刀而言,计算机更复杂一些,并且,让他们做你想让他们做的事情,并不总是那么容易。 20 | 21 | 如果你让计算机执行的任务是常见的,易于理解的任务,例如向你显示你的电子邮件,或像计算器一样工作,则可以打开相应的应用并开始工作。 但对于独特的或开放式的任务,应用可能不存在。 22 | 23 | 24 | 这就是编程可能出现的地方。编程是构建一个程序的行为 - 它是一组精确的指令,告诉计算机做什么。 由于计算机是愚蠢的,迂腐的野兽,编程从根本上是乏味和令人沮丧的。 25 | 26 | 幸运的是,如果你可以克服这个事实,并且甚至可以享受愚蠢机器可以处理的严谨思维,那么编程可以是非常有益的。 它可以让你在几秒钟内完成手动操作。 这是一种方法,让你的电脑工具去做它以前做不到的事情。 它也提供了抽象思维的优秀练习。 27 | 28 | 大多数编程都是用编程语言完成的。 编程语言是一种人工构建的语言,用于指导计算机。 有趣的是,我们发现与电脑沟通的最有效的方式,与我们彼此沟通的方式相差太大。 与人类语言一样,计算机语言可以以新的方式组合词语和词组,从而可以表达新的概念。 29 | 30 | 在某种程度上,基于语言的界面,例如 80 年代和 90 年代的 BASIC 和 DOS 提示符,是与计算机交互的主要方法。 这些已经在很大程度上被视觉界面取代,这些视觉界面更容易学习,但提供更少的自由。 计算机语言仍然存在,如果你知道在哪里看到。 每种现代 Web 浏览器都内置了一种这样的语言,即 JavaScript,因此几乎可以在所有设备上使用。 31 | 32 | 本书将试图让你足够了解这门语言,从而完成有用和有趣的东西。 33 | 34 | ## 关于程序设计 35 | 36 | 除了讲解 JavaScript 之外,本书也会介绍一些程序设计的基本原则。程序设计还是比较复杂的。编程的基本规则简单清晰,但在这些基本规则之上构建的程序却容易变得复杂,导致程序产生了自己的规则和复杂性。即便程序是按照你自己的思路去构建的,你也有可能迷失在代码之间。 37 | 38 | 在阅读本书时,你有可能会觉得书中的概念难以理解。如果你刚刚开始学习编程,那么你估计还有不少东西需要掌握呢。如果你想将所学知识融会贯通,那么就需要去多参考和学习一些资料。 39 | 40 | 是否付出必要的努力完全取决于你自己。当你阅读本书的时候发现任何难点,千万不要轻易就对自己的能力下结论。只要能坚持下去,你就是好样的。稍做休息,复习一下所学的知识点,始终确保自己阅读并理解了示例程序和相关的练习。学习是一项艰巨的任务,但你掌握的所有知识都属于你自己,而且今后的学习道路会愈加轻松。 41 | 42 | > 当行动无利可图时,就收集信息;当信息无利可图时,就休息。 43 | 44 | > Ursula K. Le Guin,《The Left Hand of Darkness》 45 | 46 | 一个程序有很多含义:它是开发人员编写的一段文本、计算机执行的一段指令集合、计算机内存当中的数据以及控制内存中数据的操作集合。我们通常很难将程序与我们日常生活中熟悉的事物进行对比。有一种表面上比较恰当的比喻,即将程序视作包含许多组件的机器,为了让机器正常工作,这些组件通过内部通信来实现整个机器的正常运转。 47 | 48 | 计算机是一台物理机器,充当这些非物质机器的载体。计算机本身并不能实现多么复杂的功能,但计算机之所以有用是因为它们的运算速度非常快。而程序的作用就是将这些看似简单的动作组合起来,然后实现复杂的功能。 49 | 50 | 程序是思想的结晶。编写程序不需要什么物质投入,它很轻量级,通过我们的双手创造。 51 | 52 | 但如果不稍加注意,程序的体积和复杂度就会失去控制,甚至代码的编写者也会感到迷惑。在可控的范围内编写程序是编程过程中首要解决的问题。当程序运行时,一切都是那么美好。编程的精粹就在于如何更好地控制复杂度。质量高的程序的复杂度都不会太高。 53 | 54 | 很多开发人员认为,控制程序复杂度的最好方法就是避免使用不熟悉的技术。他们制定了严格的规则(“最佳实践”),并小心翼翼地呆在他们安全区内。 55 | 56 | 这不仅无聊,而且也是无效的。新问题往往需要新的解决方案。编程领域还很年轻,仍然在迅速发展,并且多样到足以为各种不同的方法留出空间。在程序设计中有许多可怕的错误,你应该继续犯错,以便你能理解它们。好的程序看起来是什么样的感觉,是在实践中发展的,而不是从一系列规则中学到的。 57 | 58 | ## 为什么编程语言重要 59 | 60 | 在计算技术发展伊始,并没有编程语言这个概念。程序看起来就像这样: 61 | 62 | ``` 63 | 00110001 00000000 00000000 64 | 00110001 00000001 00000001 65 | 00110011 00000001 00000010 66 | 01010001 00001011 00000010 67 | 00100010 00000010 00001000 68 | 01000011 00000001 00000000 69 | 01000001 00000001 00000001 70 | 00010000 00000010 00000000 71 | 01100010 00000000 00000000 72 | ``` 73 | 74 | 该程序计算数字 1~10 之和,并打印出结果:`1+2+...+10=55`。该程序可以运行在一个简单的机器上。在早期计算机上编程时,我们需要在正确的位置设置大量开关阵列,或在纸带上穿孔并将纸带输入计算机中。你可以想象这个过程是多么冗长乏味且易于出错。即便是编写非常简单的程序,也需要有经验的人耗费很大精力才能完成。编写复杂的程序则更是难上加难。 75 | 76 | 当然了,手动输入这些晦涩难懂的位序列(1 和 0)来编写程序的确能让程序员感到很有成就感,而且能给你的职业带来极大的满足感。 77 | 78 | 在上面的程序中,每行都包含一条指令。我们可以用中文来描述这些指令: 79 | 80 | 1. 将数字 0 存储在内存地址中的位置 0。 81 | 82 | 2. 将数字 1 存储在内存地址的位置 1。 83 | 84 | 3. 将内存地址的位置 1 中的值存储在内存地址的位置 2。 85 | 86 | 4. 将内存地址的位置 2 中的值减去数字 11。 87 | 88 | 5. 如果内存地址的位置 2 中的值是 0,则跳转到指令 9。 89 | 90 | 6. 将内存地址的位置 1 中的值加到内存地址的位置 0。 91 | 92 | 7. 将内存地址的位置 1 中的值加上数字 1。 93 | 94 | 8. 跳转到指令 3。 95 | 96 | 9. 输出内存地址的位置 0 中的值。 97 | 98 | 虽说这已经比一大堆位序列要好读了许多,但仍然不清晰。使用名称而不是数字用于指令和存储位置有所帮助: 99 | 100 | ``` 101 | Set “total” to 0. 102 | Set “count” to 1. 103 | [loop] 104 | Set “compare” to “count”. 105 | Subtract 11 from “compare”. 106 | If “compare” is zero, continue at [end]. 107 | Add “count” to “total”. 108 | Add 1 to “count”. 109 | Continue at [loop]. 110 | [end] 111 | Output “total”. 112 | ``` 113 | 114 | 现在你能看出该程序是如何工作的吗?前两行代码初始化两个内存位置的值:`total`用于保存累加计算结果,而`count`则用于记录当前数字。你可能觉得`compare`的那行代码看起来有些奇怪。程序想根据`count`是否等于 11 来决定是否应该停止运行。因为我们的机器相当原始,所以只能测试一个数字是否为 0,并根据它做出决策。因此程序用名为`compare`的内存位置存放`count–11`的值,并根据该值是否为 0 决定是否跳转。接下来两行将`count`的值累加到结果上,并将`count`加 1,直到`count`等于`11`为止。 115 | 116 | 下面使用 JavaScript 重新编写了上面的程序: 117 | 118 | ```js 119 | let total = 0, count = 1; 120 | while (count <= 10) { 121 | total += count; 122 | count += 1; 123 | } 124 | console.log(total); 125 | // → 55 126 | ``` 127 | 128 | 这个版本的程序得到了一些改进。更为重要的是,我们再也不需要指定程序如何来回跳转了,而是由`while`结构负责完成这个任务。只要我们给予的条件成立,`while`语句就会不停地执行其下方的语句块(包裹在大括号中)。而我们给予的条件是`count<=10`,意思是“`count`小于等于 10”。我们再也不需要创建临时的值并将其与 0 比较,那样的代码十分烦琐。编程语言的一项职责就是,能够帮助我们处理这些烦琐无趣的逻辑。 129 | 130 | 在程序的结尾,也就是`while`语句结束后,我们使用`console.log`操作来输出结果。 131 | 132 | 最后,我们恰好有`range`和`sum`这类方便的操作。下面代码中的`range`函数用于创建数字集合,`sum`函数用于计算数字集合之和: 133 | 134 | ```js 135 | console.log(sum(range(1, 10))); 136 | // → 55 137 | ``` 138 | 139 | 我们可以从这里了解到,同一个程序的长度可长可短,可读性可高可低。第一个版本的程序晦涩难懂,而最后一个版本的程序则接近于人类语言的表达方式:将 1~10 范围内的数字之和记录下来(我们会在后面的章节中详细介绍如何编写`sum`和`range`这样的函数)。 140 | 141 | 优秀的编程语言可以为开发人员提供更高层次的抽象,使用类似于人类语言的方式来与计算机进行交互。它有助于省略细节,提供便捷的积木(比如`while`和`console.log`),允许你定义自己的积木(比如`sum`和`range`函数),并使这些积木易于编写。。 142 | 143 | ## 什么是 JavaScript 144 | 145 | JavaScript 诞生于 1995 年。起初,Netscape Navigator 浏览器将其运用在网页上添加程序。自此以后,各类主流图形网页浏览器均采用了 JavaScript。JavaScript 使得现代网页应用程序成为可能 —— 使用 JavaScript 可以直接与用户交互,从而避免每一个动作都需要重新载入页面。但有许多传统网站也会使用 JavaScript 来提供实时交互以及更加智能的表单功能。 146 | 147 | JavaScript 其实和名为Java的程序设计语言没有任何关系。起了这么一个相似的名字完全是市场考虑使然,这并非是一个明智的决定。当 JavaScript 出现时,Java 语言已在市场上得到大力推广且拥有了极高人气,因此某些人觉得依附于 Java 的成功是个不错的主意。而我们现在已经无法摆脱这个名字了。 148 | 149 | 在 JavaScript 被广泛采用之后,ECMA 国际制订了一份标准文档来描述 JavaScript 的工作行为,以便所有声称支持 JavaScript 的软件都使用同一种语言。标准化完成后,该标准被称为 ECMAScript 标准。实际上,术语 ECMAScript 和 JavaScript 可以交换使用。它们不过是同一种语言的两个名字而已。 150 | 151 | 许多人会说 JavaScript 语言的坏话。这其中有很多这样的言论都是正确的。当被要求第一次使用 JavaScript 编写代码时,我当时就觉得这门语言难以驾驭。JavaScript 接受我输入的任何代码,但是又使用和我的想法完全不同的方式来解释代码。由于我没有任何线索知道我之前做了什么,因此我需要做出更多工作,但这也就存在一个实际问题:我们可以自由使用 JavaScript,而这种自由却几乎没有限度。这种设计其实是希望初学者更容易使用 JavaScript 编写程序。但实际上,系统不会指出我们错在何处,因此从程序中找出问题变得更加棘手。 152 | 153 | 但这种自由性也有其优势,许多技术在更为严格的语言中不可能实现,而在 JavaScript 中则留下了实现的余地,正如你看到的那样(比如第十章),有些优势可以弥补 JavaScript 的一些缺点。在正确地学习 JavaScript 并使用它工作了一段时间后,我真正喜欢上了 JavaScript。 154 | 155 | JavaScript 版本众多。大约在 2000~2010 年间,这正是 JavaScript 飞速发展的时期,浏览器支持最多的是 ECMAScript 3。在此期间,ECMA 着手制定 ECMAScript 4,这是一个雄心勃勃的版本,ECMA 计划在这个版本中加入许多彻底的改进与扩展。但由于 ECMAScript 3 被广泛使用,这种过于激进的修改必然会遭遇重重阻碍,最后 ECMA 不得不于 2008 年放弃了版本 4 的制定。这就产生了不那么雄心勃勃的版本 5,这只是一些没有争议的改进,出现在 2009 年。 然后版本 6 在 2015 年诞生,这是一个重大的更新,其中包括计划用于版本 4 的一些想法。从那以后,每年都会有新的更新。 156 | 157 | 语言不断发展的事实意味着,浏览器必须不断跟上,如果你使用的是较老的浏览器,它可能不支持每个特性。 语言设计师会注意,不要做任何可能破坏现有程序的改变,所以新的浏览器仍然可以运行旧的程序。 在本书中,我使用的是 2017 版的 JavaScript。 158 | 159 | Web 浏览器并不是唯一一个可以运行 JavaScript 的平台。有些数据库,比如 MongoDB 和 CouchDB,也使用 JavaScript 作为脚本语言和查询语言。一些桌面和服务器开发的平台,特别是 Node.js 项目(第二十章介绍),为浏览器以外的 JavaScript 编程提供了一个环境。 160 | 161 | ## 代码及相关工作 162 | 163 | 代码是程序的文本内容。本书多数章节都介绍了大量代码。我相信阅读代码和编写代码是学习编程不可或缺的部分。尝试不要仅仅看一眼示例,而应该认真阅读并理解每个示例。刚开始使用这种方式可能会速度较慢并为代码所困惑,但我坚信你很快就可以熟能生巧。对待习题的方法也应该一样。除非你确实已经编写代码解决了问题,否则不要假设你已经理解了问题。 164 | 165 | 建议读者应尝试在实际的 JavaScript 解释器中执行习题代码。这样一来,你就可以马上获知代码工作情况的反馈,而且我希望读者去做更多的试验,而不仅仅局限于习题的要求。 166 | 167 | 可以在 中查阅本书的在线版本,并运行和实验本书中的代码。也可以在在线版本中点击任何代码示例来编辑、运行并查看其产生的输出。在做习题时,你可以访问 ,该网址会提供每个习题的初始代码,让你专心于解答习题。 168 | 169 | 如果想要在本书提供的沙箱以外执行本书代码,需要稍加注意。许多的示例是独立的,而且可以在任何 JavaScript 环境下运行。但后续章节的代码大多数都是为特定环境(浏览器或者 Node.js)编写的,而且只能在这些特定环境下执行代码。此外,许多章节定义了更大的程序,这些章节中出现的代码片段会互相依赖或是依赖于一些外部文件。本书网站的沙箱提供了 zip 压缩文件的链接,该文件包含了所有运行特定章节代码所需的脚本和数据文件。 170 | 171 | ## 本书概览 172 | 173 | 本书包括三个部分。前十二章讨论 JavaScript 语言本身的一些特性。接下来的 8 章讨论网页浏览器和 JavaScript 在网页编程中的实践。最后两章专门讲解另一个使用 JavaScript 编程的环境 —— Node.js。 174 | 175 | 纵观本书,共有 5 个项目实战章,用于讲解规模较大的示例程序,你可以通过这些章来仔细品味真实的编程过程。根据项目出现次序,我们会陆续构建递送机器人(7)、程序设计语言(12)、平台游戏(16)、像素绘图程序(19)和一个动态网站(21)。 176 | 177 | 本书介绍编程语言时,首先使用4章来介绍 JavaScript 语言的基本结构,包括第二章控制结构(比如在本前言中看到的`while`单词)、第三章函数(编写你自己的积木)和第四章数据结构。此后你就可以编写简单的程序了。接下来,第五章和第六章介绍函数和对象的运用技术,以编写更加抽象的代码并以此来控制复杂度。 178 | 179 | 介绍完第一个项目实战(7)之后,将会继续讲解语言部分,例如第八章错误处理和 bug 修复、第九章正则表达式(处理文本数据的重要工具)、第十章模块化(解决复杂度的问题)以及第十一章异步编程(处理需要时间的事件)。第二个项目实战章节(12)则是对本书第一部分的总结。 180 | 181 | 第二部分(第十三章到第十九章),阐述了浏览器 JavaScript 中的一些工具。你将会学到在屏幕上显示某些元素的方法(第十四章与第十七章),响应用户输入的方法(第十五章)和通过网络通信的方法(第十八章)。这部分又有两个项目实战章节。 182 | 183 | 此后,第二十章阐述 Node.js,而第二十一章使用该工具构建一个简单的网页系统。 184 | 185 | ## 本书版式约定 186 | 187 | 本书中存在大量代码,程序(包括你迄今为止看到的一些示例)代码的字体如下所示: 188 | 189 | ```js 190 | function factorial(n) { 191 | if (n == 0) { 192 | return 1; 193 | } else { 194 | return factorial(n - 1) * n; 195 | } 196 | } 197 | ``` 198 | 199 | 为了展示程序产生的输出,本书常在代码后编写代码期望输出,输出结果前会加上两个反斜杠和一个箭头。 200 | 201 | ```js 202 | console.log(factorial(8)); 203 | // → 40320 204 | ``` 205 | 206 | 祝好运! 207 | -------------------------------------------------------------------------------- /1.md: -------------------------------------------------------------------------------- 1 | ## 一、值,类型和运算符 2 | 3 | > 原文:[Values, Types, and Operators](http://eloquentjavascript.net/01_values.html) 4 | > 5 | > 译者:[飞龙](https://github.com/wizardforcel) 6 | > 7 | > 协议:[CC BY-NC-SA 4.0](http://creativecommons.org/licenses/by-nc-sa/4.0/) 8 | > 9 | > 自豪地采用[谷歌翻译](https://translate.google.cn/) 10 | > 11 | > 部分参考了[《JavaScript 编程精解(第 2 版)》](https://book.douban.com/subject/26707144/) 12 | 13 | > 在机器的表面之下,程序在运转。 它不费力就可以扩大和缩小。 在和谐的关系中,电子散开并重新聚合。 监视器上的表格只是水面上的涟漪。 本质隐藏在下面。 14 | > 15 | > Master Yuan-Ma,《The Book of Programming》 16 | 17 | ![](img/1-0.jpg) 18 | 19 | 计算机世界里只有数据。 你可以读取数据,修改数据,创建新数据 - 但不能提及不是数据的东西。 所有这些数据都以位的长序列存储,因此基本相似。 20 | 21 | 位是任何类型的二值的东西,通常描述为零和一。 在计算机内部,他们有一些形式,例如高电荷或低电荷,强信号或弱信号,或 CD 表面上的亮斑点或暗斑点。 任何一段离散信息都可以简化为零和一的序列,从而以位表示。 22 | 23 | 例如,我们可以用位来表示数字 13。 它的原理与十进制数字相同,但不是 10 个不同的数字,而只有 2 个,每个数字的权重从右到左增加 2 倍。 以下是组成数字 13 的位,下方显示数字的权重: 24 | 25 | ``` 26 | 0 0 0 0 1 1 0 1 27 | 128 64 32 16 8 4 2 1 28 | ``` 29 | 30 | 因此,这就是二进制数`00001101`,或者`8+4+1`,即 13。 31 | 32 | ## 值 33 | 34 | 想象一下位之海 - 一片它们的海洋。 典型的现代计算机的易失性数据存储器(工作存储器)中,有超过 300 亿位。非易失性存储(硬盘或等价物)往往还有几个数量级。 35 | 36 | 为了能够在不丢失的情况下,处理这些数量的数据,我们必须将它们分成代表信息片段的块。 在 JavaScript 环境中,这些块称为值。 虽然所有值都是由位构成的,但他们起到不同的作用,每个值都有一个决定其作用的类型。 有些值是数字,有些值是文本片段,有些值是函数,等等。 37 | 38 | 要创建一个值,你只需要调用它的名字。 这很方便。 你不必为你的值收集建筑材料或为其付费。 你只需要调用它,然后刷的一下,你就有了它。 当然,它们并不是真正凭空创造的。 每个值都必须存储在某个地方,如果你想同时使用大量的值,则可能会耗尽内存。 幸运的是,只有同时需要它们时,这才是一个问题。 只要你不再使用值,它就会消失,留下它的一部分作为下一代值的建筑材料。 39 | 40 | 本章将会介绍 JavaScript 程序当中的基本元素,包括简单的值类型以及值运算符。 41 | 42 | ## 数字 43 | 44 | 数字(`Number`)类型的值即数字值。在 JavaScript 中写成如下形式: 45 | 46 | ```js 47 | 13 48 | ``` 49 | 50 | 在程序中使用这个值的时候,就会将数字 13 以位序列的方式存放在计算机的内存当中。 51 | 52 | JavaScript使用固定数量的位(64 位)来存储单个数字值。 你可以用 64 位创造很多模式,这意味着可以表示的不同数值是有限的。 对于`N`个十进制数字,可以表示的数值数量是`10^N`。 与之类似,给定 64 个二进制数字,你可以表示`2^64`个不同的数字,大约 18 亿亿(18 后面有 18 个零)。太多了。 53 | 54 | 过去计算机内存很小,人们倾向于使用一组 8 位或 16 位来表示他们的数字。 这么小的数字很容易意外地溢出,最终得到的数字不能放在给定的位数中。 今天,即使是装在口袋里的电脑也有足够的内存,所以你可以自由使用 64 位的块,只有在处理真正的天文数字时才需要担心溢出。 55 | 56 | 不过,并非所有 18 亿亿以下的整数都能放在 JavaScript 数值中。 这些位也存储负数,所以一位用于表示数字的符号。 一个更大的问题是,也必须表示非整数。 为此,一些位用于存储小数点的位置。 可以存储的实际最大整数更多地在 9000 万亿(15 个零)的范围内 - 这仍然相当多。 57 | 58 | 使用小数点来表示分数。 59 | 60 | ```js 61 | 9.81 62 | ``` 63 | 64 | 对于非常大或非常小的数字,你也可以通过输入`e`(表示指数),后面跟着指数来使用科学记数法: 65 | 66 | ```js 67 | 2.998e8 68 | ``` 69 | 70 | 即`2.998 * 10^8 = 299,800,000`。 71 | 72 | 当计算小于前文当中提到的 9000 万亿的整数时,其计算结果会十分精确,不过在计算小数的时候精度却不高。正如(`pi`)无法使用有限个数的十进制数字表示一样,在使用 64 位来存储分数时也同样会丢失一些精度。虽说如此,但这类丢失精度只会在一些特殊情况下才会出现问题。因此我们需要注意在处理分数时,将其视为近似值,而非精确值。 73 | 74 | ### 算术 75 | 76 | 与数字密切相关的就是算术。比如,加法或者乘法之类的算术运算会使用两个数值,并产生一个新的数字。JavaScript 中的算术运算如下所示: 77 | 78 | ```js 79 | 100 + 4 * 11 80 | ``` 81 | 82 | 我们把`+`和`*`符号称为运算符。第一个符号表示加法,第二个符号表示乘法。将一个运算符放在两个值之间,该运算符将会使用其旁边的两个值产生一个新值。 83 | 84 | 但是这个例子的意思是“将 4 和 100 相加,并将结果乘 11”,还是是在加法之前计算乘法? 正如你可能猜到的那样,乘法首先计算。 但是和数学一样,你可以通过将加法包在圆括号中来改变它: 85 | 86 | ```js 87 | (100 + 4) * 11 88 | ``` 89 | 90 | `–`运算符表示减法,`/`运算符则表示除法。 91 | 92 | 在运算符同时出现,并且没有括号的情况下,其运算顺序根据运算符优先级确定。示例中的乘法运算符优先级高于加法。而`/`运算符和`*`运算符优先级相同,`+`运算符和`–`运算符优先级也相同。当多个具有相同优先级的运算符相邻出现时,运算从左向右执行,比如`1–2+1`的运算顺序是`(1–2)+1`。 93 | 94 | 你无需担心这些运算符的优先级规则,不确定的时候只需要添加括号即可。 95 | 96 | 还有一个算术运算符,你可能无法立即认出。 `%`符号用于表示取余操作。 `X % Y`是`Y`除`X`的余数。 例如,`314 % 100`产生`14`,`144 % 12`产生`0`。 余数的优先级与乘法和除法的优先级相同。 你还经常会看到这个运算符被称为模运算符。 97 | 98 | ### 特殊数字 99 | 100 | 在 JavaScript 中有三个特殊的值,它们虽然是数字,但看起来却跟一般的数字不太一样。 101 | 102 | 前两个是`Infinity`和`-Infinity`,它们代表正无穷和负无穷。 “无穷减一”仍然是“无穷”,依此类推。 尽管如此,不要过分信任基于无穷大的计算。 它在数学上不合理,并且很快导致我们的下一个特殊数字:`NaN`。 103 | 104 | `NaN`代表“不是数字”,即使它是数字类型的值。 例如,当你尝试计算`0/0`(零除零),`Infinity - Infinity`或任何其他数字操作,它不会产生有意义的结果时,你将得到此结果。 105 | 106 | ## 字符串 107 | 108 | 下一个基本数据类型是字符串(`String`)。 字符串用于表示文本。 它们是用引号括起来的: 109 | 110 | ```js 111 | `Down on the sea` 112 | "Lie on the ocean" 113 | 'Float on the ocean' 114 | ``` 115 | 116 | 只要字符串开头和结尾的引号匹配,就可以使用单引号,双引号或反引号来标记字符串。 117 | 118 | 几乎所有的东西都可以放在引号之间,并且 JavaScript 会从中提取字符串值。 但少数字符更难。 你可能难以想象,如何在引号之间加引号。 当使用反引号(`` ` ``)引用字符串时,换行符(当你按回车键时获得的字符)可能会被包含,而无需转义。 119 | 120 | 若要将这些字符存入字符串,需要使用下列规则:当反斜杠(`\`)出现在引号之间的文本中时,表示紧跟在其后的字符具有特殊含义,我们将其称之为转义符。当引号紧跟在反斜杠后时,并不意味着字符串结束,而表示这个引号是字符串的一部分。当字符`n`出现在反斜杠后时,JavaScript 将其解释成换行符。以此类推,`\t`表示制表符,我们来看看下面这个字符串: 121 | 122 | ```js 123 | "This is the first line\nAnd this is the second" 124 | ``` 125 | 126 | 该字符串实际表示的文本是: 127 | 128 | ``` 129 | This is the first line 130 | And this is the second 131 | ``` 132 | 133 | 当然,在某些情况下,你希望字符串中的反斜杠只是反斜杠,而不是特殊代码。 如果两个反斜杠写在一起,它们将合并,并且只有一个将留在结果字符串值中。 这就是字符串“`A newline character is written like "\n".`”的表示方式: 134 | 135 | ```js 136 | "A newline character is written like \"\\n\"." 137 | ``` 138 | 139 | 字符串也必须建模为一系列位,以便能够存在于计算机内部。 JavaScript 执行此操作的方式基于 Unicode 标准。 该标准为你几乎需要的每个字符分配一个数字,包括来自希腊语,阿拉伯语,日语,亚美尼亚语,以及其他的字符。 如果我们为每个字符分配一个数字,则可以用一系列数字来描述一个字符串。 140 | 141 | 这就是 JavaScript 所做的。 但是有一个复杂的问题:JavaScript 的表示为每个字符串元素使用 16 位,它可以描述多达 2 的 16 次方个不同的字符。 但是,Unicode 定义的字符多于此 - 大约是此处的两倍。 所以有些字符,比如许多 emoji,在 JavaScript 字符串中占据了两个“字符位置”。 我们将在第 5 章中回来讨论。 142 | 143 | 我们不能将除法,乘法或减法运算符用于字符串,但是`+`运算符却可以。这种情况下,运算符并不表示加法,而是连接操作:将两个字符串连接到一起。以下语句可以产生字符串`"concatenate"`: 144 | 145 | ```js 146 | "con" + "cat" + "e" + "nate" 147 | ``` 148 | 149 | 字符串值有许多相关的函数(方法),可用于对它们执行其他操作。 我们将在第 4 章中回来讨论。 150 | 151 | 用单引号或双引号编写的字符串的行为非常相似 - 唯一的区别是需要在其中转义哪种类型的引号。 反引号字符串,通常称为模板字面值,可以实现更多的技巧。 除了能够跨越行之外,它们还可以嵌入其他值。 152 | 153 | ```js 154 | `half of 100 is ${100 / 2}` 155 | ``` 156 | 157 | 当你在模板字面值中的`$ {}`中写入内容时,将计算其结果,转换为字符串并包含在该位置。 这个例子产生`"half of 100 is 50"`。 158 | 159 | ## 一元运算符 160 | 161 | 并非所有的运算符都是用符号来表示,还有一些运算符是用单词表示的。比如`typeof`运算符,会产生一个字符串的值,内容是给定值的具体类型。 162 | 163 | ```js 164 | console.log(typeof 4.5) 165 | // → number 166 | console.log(typeof "x") 167 | // → string 168 | ``` 169 | 170 | 我们将在示例代码中使用`console.log`,来表示我们希望看到求值结果。更多内容请见下一章。 171 | 172 | 我们所见过的绝大多数运算符都使用两个值进行操作,而`typeof`仅接受一个值进行操作。使用两个值的运算符称为二元运算符,而使用一个值的则称为一元运算符。减号运算符既可用作一元运算符,也可用作二元运算符。 173 | 174 | ```js 175 | console.log(- (10 - 2)) 176 | // → -8 177 | ``` 178 | 179 | ## 布尔值 180 | 181 | 拥有一个值,它能区分两种可能性,通常是有用的,例如“是”和“否”或“开”和“关”。 为此,JavaScript 拥有布尔(`Boolean`)类型,它有两个值:`true`和`false`,它们就写成这些单词。 182 | 183 | ### 比较 184 | 185 | 一种产生布尔值的方法如下所示: 186 | 187 | ```js 188 | console.log(3 > 2) 189 | // → true 190 | console.log(3 < 2) 191 | // → false 192 | ``` 193 | 194 | `>`和`<`符号分别表示“大于”和“小于”。这两个符号是二元运算符,通过该运算符返回的结果是一个布尔值,表示其运算是否为真。 195 | 196 | 我们可以使用相同的方法比较字符串。 197 | 198 | ```js 199 | console.log("Aardvark" < "Zoroaster") 200 | // → true 201 | ``` 202 | 203 | 字符串排序的方式大致是字典序,但不真正是你期望从字典中看到的那样:大写字母总是比小写字母“小”,所以`"Z"<"a"`,非字母字符(`!`,`-`等)也包含在排序中。 比较字符串时,JavaScript 从左向右遍历字符,逐个比较 Unicode 代码。 204 | 205 | 其他类似的运算符则包括`>=`(大于等于),`<=`(小于等于),`==`(等于)和`!=`(不等于)。 206 | 207 | ```js 208 | console.log("Apple" == "Orange") 209 | // → false 210 | ``` 211 | 212 | 在 JavaScript 中,只有一个值不等于其自身,那就是`NaN`(Not a Number,非数值)。 213 | 214 | ```js 215 | console.log(NaN == NaN) 216 | // → false 217 | ``` 218 | 219 | `NaN`用于表示非法运算的结果,正因如此,不同的非法运算结果也不会相等。 220 | 221 | ### 逻辑运算符 222 | 223 | 还有一些运算符可以应用于布尔值上。JavaScript 支持三种逻辑运算符:与(and),或(or)和非(not)。这些运算符可以用于推理布尔值。 224 | 225 | `&&`运算符表示逻辑与,该运算符是二元运算符,只有当赋给它的两个值均为`true`时其结果才是真。 226 | 227 | ```js 228 | console.log(true && false) 229 | // → false 230 | console.log(true && true) 231 | // → true 232 | ``` 233 | 234 | `||`运算符表示逻辑或。当两个值中任意一个为`true`时,结果就为真。 235 | 236 | ```js 237 | console.log(false || true) 238 | // → true 239 | console.log(false || false) 240 | // → false 241 | ``` 242 | 243 | 感叹号(`!`)表示逻辑非,该运算符是一元运算符,用于反转给定的值,比如`!true`的结果是`false`,而`!false`结果是`true`。 244 | 245 | 在混合使用布尔运算符和其他运算符的情况下,总是很难确定什么时候需要使用括号。实际上,只要熟悉了目前为止我们介绍的运算符,这个问题就不难解决了。`||`优先级最低,其次是`&&`,接着是比较运算符(`>`,`==`等),最后是其他运算符。基于这些优先级顺序,我们在一般情况下最好还是尽量少用括号,比如说: 246 | 247 | ```js 248 | 1 + 1 == 2 && 10 * 10 > 50 249 | ``` 250 | 251 | 现在我们来讨论最后一个逻辑运算符,它既不属于一元运算符,也不属于二元运算符,而是三元运算符(同时操作三个值)。该运算符由一个问号和冒号组成,如下所示。 252 | 253 | ```js 254 | console.log(true ? 1 : 2); 255 | // → 1 256 | console.log(false ? 1 : 2); 257 | // → 2 258 | ``` 259 | 260 | 这个被称为条件运算符(或者有时候只是三元运算符,因为它是该语言中唯一的这样的运算符)。 问号左侧的值“挑选”另外两个值中的一个。 当它为真,它选择中间的值,当它为假,则是右边的值。 261 | 262 | ## 空值 263 | 264 | 有两个特殊值,写成`null`和`undefined`,用于表示不存在有意义的值。 它们本身就是值,但它们没有任何信息。 265 | 266 | 在 JavaScript 语言中,有许多操作都会产生无意义的值(我们会在后面的内容中看到实例),这些操作会得到`undefined`的结果仅仅只是因为每个操作都必须产生一个值。 267 | 268 | `undefined`和`null`之间的意义差异是 JavaScript 设计的一个意外,大多数时候它并不重要。 在你实际上不得不关注这些值的情况下,我建议将它们视为几乎可互换的。 269 | 270 | ## 自动类型转换 271 | 272 | 在引言中,我提到 JavaScript 会尽可能接受几乎所有你给他的程序,甚至是那些做些奇怪事情的程序。 以下表达式很好地证明了这一点: 273 | 274 | ```js 275 | console.log(8 * null) 276 | // → 0 277 | console.log("5" - 1) 278 | // → 4 279 | console.log("5" + 1) 280 | // → 51 281 | console.log("five" * 2) 282 | // → NaN 283 | console.log(false == 0) 284 | // → true 285 | ``` 286 | 287 | 当运算符应用于类型“错误”的值时,JavaScript 会悄悄地将该值转换为所需的类型,并使用一组通常不是你想要或期望的规则。 这称为类型转换。 第一个表达式中的`null`变为`0`,第二个表达式中的`"5"`变为`5`(从字符串到数字)。 然而在第三个表达式中,`+`在数字加法之前尝试字符串连接,所以`1`被转换为`"1"`(从数字到字符串)。 288 | 289 | 当某些不能明显映射为数字的东西(如`"five"`或`undefined`)转换为数字时,你会得到值`NaN`。 `NaN`进一步的算术运算会产生`NaN`,所以如果你发现自己在一个意想不到的地方得到了它,需要寻找意外的类型转换。 290 | 291 | 当相同类型的值之间使用`==`符号进行比较时,其运算结果很好预测:除了`NaN`这种情况,只要两个值相同,则返回`true`。但如果类型不同,JavaScript 则会使用一套复杂难懂的规则来确定输出结果。在绝大多数情况下,JavaScript 只是将其中一个值转换成另一个值的类型。但如果运算符两侧存在`null`或`undefined`,那么只有两侧均为`null`或`undefined`时结果才为`true`。 292 | 293 | ```js 294 | console.log(null == undefined); 295 | // → true 296 | console.log(null == 0); 297 | // → false 298 | ``` 299 | 300 | 这种行为通常很有用。 当你想测试一个值是否具有真值而不是`null`或`undefined`时,你可以用`==`(或`!=`)运算符将它与`null`进行比较。 301 | 302 | 但是如果你想测试某些东西是否严格为“false”呢? 字符串和数字转换为布尔值的规则表明,`0`,`NaN`和空字符串(`""`)计为`false`,而其他所有值都计为`true`。 因此,像`'0 == false'`和`"" == false`这样的表达式也是真的。 当你不希望发生自动类型转换时,还有两个额外的运算符:`===`和`!==`。 第一个测试是否严格等于另一个值,第二个测试它是否不严格相等。 所以`"" === false`如预期那样是错误的。 303 | 304 | 我建议使用三字符比较运算符来防止意外类型转换的发生,避免作茧自缚。但如果比较运算符两侧的值类型是相同的,那么使用较短的运算符也没有问题。 305 | 306 | ### 逻辑运算符的短路特性 307 | 308 | 逻辑运算符`&&`和`||`以一种特殊的方式处理不同类型的值。 他们会将其左侧的值转换为布尔型,来决定要做什么,但根据运算符和转换结果,它们将返回原始的左侧值或右侧值。 309 | 310 | 例如,当左侧值可以转换为`true`时,`||`运算符会返回它,否则返回右侧值。 当值为布尔值时,这具有预期的效果,并且对其他类型的值做类似的操作。 311 | 312 | ```js 313 | console.log(null || "user") 314 | // → user 315 | console.log("Agnes" || "user") 316 | // → Agnes 317 | ``` 318 | 319 | 我们可以此功能用作回落到默认值的方式。 如果你的一个值可能是空的,你可以把`||`和备选值放在它之后。 如果初始值可以转换为`false`,那么你将得到备选值。 320 | 321 | `&&`运算符工作方式与其相似但不相同。当左侧的值可以被转换成`false`时,`&&`运算符会返回左侧值,否则返回右侧值。 322 | 323 | 这两个运算符的另一个重要特性是,只在必要时求解其右侧的部分。 在`true || X`的情况下,不管`X`是什么 - 即使它是一个执行某些恶意操作的程序片段,结果都是`true`,并且`X`永远不会求值。 `false && X`也是一样,它是`false`的,并且忽略`X`。 这称为短路求值。 324 | 325 | 条件运算符以类似的方式工作。 在第二个和第三个值中,只有被选中的值才会求值。 326 | 327 | ## 本章小结 328 | 329 | 在本章中,我们介绍了 JavaScript 的四种类型的值:数字,字符串,布尔值和未定义值。 330 | 331 | 通过输入值的名称(`true`,`null`)或值(`13`,`"abc"`)就可以创建它们。你还可以通过运算符来对值进行合并和转换操作。本章已经介绍了算术二元运算符(`+`,`–`,`*`,`/`和`%`),字符串连接符(`+`),比较运算符(`==`,`!=`,`===`,`!==`,`<`,`>`,`<=`和`>=`),逻辑运算符(`&&`和`||`)和一些一元运算符(`–`表示负数,`!`表示逻辑非,`typeof`用于查询值的类型)。 332 | 333 | 这为你提供了足够的信息,将 JavaScript 用作便携式计算器,但并不多。 下一章将开始将这些表达式绑定到基本程序中。 334 | -------------------------------------------------------------------------------- /10.md: -------------------------------------------------------------------------------- 1 | # 十、模块 2 | 3 | > 原文:[Modules](http://eloquentjavascript.net/10_modules.html) 4 | > 5 | > 译者:[飞龙](https://github.com/wizardforcel) 6 | > 7 | > 协议:[CC BY-NC-SA 4.0](http://creativecommons.org/licenses/by-nc-sa/4.0/) 8 | > 9 | > 自豪地采用[谷歌翻译](https://translate.google.cn/) 10 | 11 | > 编写易于删除,而不是易于扩展的代码。 12 | > 13 | > Tef,《Programming is Terrible》 14 | 15 | ![](img/10-0.jpg) 16 | 17 | 理想的程序拥有清晰的结构。 它的工作方式很容易解释,每个部分都起到明确的作用。 18 | 19 | 典型的真实程序会有机地增长。 新功能随着新需求的出现而增加。 构建和维护结构是额外的工作,只有在下一次有人参与该计划时,才会得到回报。 所以它易于忽视,并让程序的各个部分变得深深地纠缠在一起。 20 | 21 | 这导致了两个实际问题。 首先,这样的系统难以理解。 如果一切都可以接触到一切其它东西,那么很难单独观察任何给定的片段。 你不得不全面理解整个东西。 其次,如果你想在另一个场景中,使用这种程序的任何功能,比起试图从它的上下文中将它分离出来,重写它可能要容易。 22 | 23 | 术语“大泥球”通常用于这种大型,无结构的程序。 一切都粘在一起,当你试图挑选出一段代码时,整个东西就会分崩离析,你的手会变脏。 24 | 25 | ## 模块 26 | 27 | 模块试图避免这些问题。 模块是一个程序片段,规定了它依赖的其他部分,以及它为其他模块提供的功能(它的接口)。 28 | 29 | 模块接口与对象接口有许多共同之处,我们在第 6 章中看到。它们向外部世界提供模块的一部分,并使其余部分保持私有。 通过限制模块彼此交互的方式,系统变得更像积木,其中的组件通过明确定义的连接器进行交互,而不像泥浆一样,一切都混在一起。 30 | 31 | 模块之间的关系称为依赖关系。 当一个模块需要另一个模块的片段时,就说它依赖于这个模块。 当模块中明确规定了这个事实时,它可以用于确定,需要哪些其他模块才能使用给定的模块,并自动加载依赖关系。 32 | 33 | 为了以这种方式分离模块,每个模块需要它自己的私有作用域。 34 | 35 | 将你的 JavaScript 代码放入不同的文件,不能满足这些要求。 这些文件仍然共享相同的全局命名空间。 他们可以有意或无意干扰彼此的绑定。 依赖性结构仍不清楚。 我们将在本章后面看到,我们可以做得更好。 36 | 37 | 合适的模块结构可能难以为程序设计。 在你还在探索这个问题的阶段,尝试不同的事情来看看什么是可行的,你可能不想过多担心它,因为这可能让你分心。 一旦你有一些感觉可靠的东西,现在是后退一步并组织它的好时机。 38 | 39 | ## 包 40 | 41 | 从单独的片段中构建一个程序,并实际上能够独立运行这些片段的一个优点是,你可能能够在不同的程序中应用相同的部分。 42 | 43 | 但如何实现呢? 假设我想在另一个程序中使用第 9 章中的`parseINI`函数。 如果清楚该函数依赖什么(在这种情况下什么都没有),我可以将所有必要的代码复制到我的新项目中并使用它。 但是,如果我在代码中发现错误,我可能会在当时正在使用的任何程序中将其修复,并忘记在其他程序中修复它。 44 | 45 | 一旦你开始复制代码,你很快就会发现,自己在浪费时间和精力来到处复制并使他们保持最新。 46 | 47 | 这就是包的登场时机。包是可分发(复制和安装)的一大块代码。 它可能包含一个或多个模块,并且具有关于它依赖于哪些其他包的信息。 一个包通常还附带说明它做什么的文档,以便那些不编写它的人仍然可以使用它。 48 | 49 | 在包中发现问题或添加新功能时,会将包更新。 现在依赖它的程序(也可能是包)可以升级到新版本。 50 | 51 | 以这种方式工作需要基础设施。 我们需要一个地方来存储和查找包,以及一个便利方式来安装和升级它们。 在 JavaScript 世界中,这个基础结构由 [NPM](https://npmjs.org) 提供。 52 | 53 | NPM 是两个东西:可下载(和上传)包的在线服务,以及可帮助你安装和管理它们的程序(与 Node.js 捆绑在一起)。 54 | 55 | 在撰写本文时,NPM 上有超过 50 万个不同的包。 其中很大一部分是垃圾,我应该提一下,但几乎所有有用的公开包都可以在那里找到。 例如,一个 INI 文件解析器,类似于我们在第 9 章中构建的那个,可以在包名称`ini`下找到。 56 | 57 | 第 20 章将介绍如何使用`npm`命令行程序在局部安装这些包。 58 | 59 | 使优质的包可供下载是非常有价值的。 这意味着我们通常可以避免重新创建一百人之前写过的程序,并在按下几个键时得到一个可靠,充分测试的实现。 60 | 61 | 软件的复制很便宜,所以一旦有人编写它,分发给其他人是一个高效的过程。但首先把它写出来是工作量,回应在代码中发现问题的人,或者想要提出新功能的人,是更大的工作量。 62 | 63 | 默认情况下,你拥有你编写的代码的版权,其他人只有经过你的许可才能使用它。但是因为有些人不错,而且由于发布好的软件可以使你在程序员中出名,所以许多包都会在许可证下发布,明确允许其他人使用它。 64 | 65 | NPM 上的大多数代码都以这种方式授权。某些许可证要求你还要在相同许可证下发布基于那个包构建的代码。其他要求不高,只是要求在分发代码时保留许可证。 JavaScript 社区主要使用后一种许可证。使用其他人的包时,请确保你留意了他们的许可证。 66 | 67 | ## 即兴的模块 68 | 69 | 2015 年之前,JavaScript 语言没有内置的模块系统。 然而,尽管人们已经用 JavaScript 构建了十多年的大型系统,他们需要模块。 70 | 71 | 所以他们在语言之上设计了自己的模块系统。 你可以使用 JavaScript 函数创建局部作用域,并使用对象来表示模块接口。 72 | 73 | 这是一个模块,用于日期名称和数字之间的转换(由`Date`的`getDay`方法返回)。 它的接口由`weekDay.name`和`weekDay.number`组成,它将局部绑定名称隐藏在立即调用的函数表达式的作用域内。 74 | 75 | ```js 76 | const weekDay = function() { 77 | const names = ["Sunday", "Monday", "Tuesday", "Wednesday", 78 | "Thursday", "Friday", "Saturday"]; 79 | return { 80 | name(number) { return names[number]; }, 81 | number(name) { return names.indexOf(name); } 82 | }; 83 | }(); 84 | 85 | console.log(weekDay.name(weekDay.number("Sunday"))); 86 | // → Sunday 87 | ``` 88 | 89 | 这种风格的模块在一定程度上提供了隔离,但它不声明依赖关系。 相反,它只是将其接口放入全局范围,并希望它的依赖关系(如果有的话)也这样做。 很长时间以来,这是 Web 编程中使用的主要方法,但现在它几乎已经过时。 90 | 91 | 如果我们想让依赖关系成为代码的一部分,我们必须控制依赖关系的加载。 实现它需要能够将字符串执行为代码。 JavaScript 可以做到这一点。 92 | 93 | ## 将数据执行为代码 94 | 95 | 有几种方法可以将数据(代码的字符串)作为当前程序的一部分运行。 96 | 97 | 最明显的方法是特殊运算符`eval`,它将在当前作用域内执行一个字符串。 这通常是一个坏主意,因为它破坏了作用域通常拥有的一些属性,比如易于预测给定名称所引用的绑定。 98 | 99 | ```js 100 | const x = 1; 101 | function evalAndReturnX(code) { 102 | eval(code); 103 | return x; 104 | } 105 | 106 | console.log(evalAndReturnX("var x = 2")); 107 | // → 2 108 | console.log(x); 109 | // → 1 110 | ``` 111 | 112 | 将数据解释为代码的不太可怕的方法,是使用`Function`构造器。 它有两个参数:一个包含逗号分隔的参数名称列表的字符串,和一个包含函数体的字符串。 它将代码封装在一个函数值中,以便它获得自己的作用域,并且不会对其他作用域做出奇怪的事情。 113 | 114 | ```py 115 | let plusOne = Function("n", "return n + 1;"); 116 | console.log(plusOne(4)); 117 | // → 5 118 | ``` 119 | 120 | 这正是我们需要的模块系统。 我们可以将模块的代码包装在一个函数中,并将该函数的作用域用作模块作用域。 121 | 122 | ## CommonJS 123 | 124 | 用于连接 JavaScript 模块的最广泛的方法称为 CommonJS 模块。 Node.js 使用它,并且是 NPM 上大多数包使用的系统。 125 | 126 | CommonJS 模块的主要概念是称为`require`的函数。 当你使用依赖项的模块名称调用这个函数时,它会确保该模块已加载并返回其接口。 127 | 128 | 由于加载器将模块代码封装在一个函数中,模块自动得到它们自己的局部作用域。 他们所要做的就是,调用`require`来访问它们的依赖关系,并将它们的接口放在绑定到`exports`的对象中。 129 | 130 | 此示例模块提供了日期格式化功能。 它使用 NPM的两个包,`ordinal`用于将数字转换为字符串,如`"1st"`和`"2nd"`,以及`date-names`用于获取星期和月份的英文名称。 它导出函数`formatDate`,它接受一个`Date`对象和一个模板字符串。 131 | 132 | 模板字符串可包含指明格式的代码,如`YYYY`用于全年,`Do`用于每月的序数日。 你可以给它一个像`"MMMM Do YYYY"`这样的字符串,来获得像`"November 22nd 2017"`这样的输出。 133 | 134 | ```js 135 | const ordinal = require("ordinal"); 136 | const {days, months} = require("date-names"); 137 | 138 | exports.formatDate = function(date, format) { 139 | return format.replace(/YYYY|M(MMM)?|Do?|dddd/g, tag => { 140 | if (tag == "YYYY") return date.getFullYear(); 141 | if (tag == "M") return date.getMonth(); 142 | if (tag == "MMMM") return months[date.getMonth()]; 143 | if (tag == "D") return date.getDate(); 144 | if (tag == "Do") return ordinal(date.getDate()); 145 | if (tag == "dddd") return days[date.getDay()]; 146 | }); 147 | }; 148 | ``` 149 | 150 | `ordinal`的接口是单个函数,而`date-names`导出包含多个东西的对象 - `days`和`months`是名称数组。 为导入的接口创建绑定时,解构是非常方便的。 151 | 152 | 该模块将其接口函数添加到`exports`,以便依赖它的模块可以访问它。 我们可以像这样使用模块: 153 | 154 | ```js 155 | const {formatDate} = require("./format-date"); 156 | 157 | console.log(formatDate(new Date(2017, 9, 13), 158 | "dddd the Do")); 159 | // → Friday the 13th 160 | ``` 161 | 162 | 我们可以用最简单的形式定义`require`,如下所示: 163 | 164 | ```js 165 | require.cache = Object.create(null); 166 | 167 | function require(name) { 168 | if (!(name in require.cache)) { 169 | let code = readFile(name); 170 | let module = {exports: {}}; 171 | require.cache[name] = module; 172 | let wrapper = Function("require, exports, module", code); 173 | wrapper(require, module.exports, module); 174 | } 175 | return require.cache[name].exports; 176 | } 177 | ``` 178 | 179 | 在这段代码中,`readFile`是一个构造函数,它读取一个文件并将其内容作为字符串返回。标准的 JavaScript 没有提供这样的功能,但是不同的 JavaScript 环境(如浏览器和 Node.js)提供了自己的访问文件的方式。这个例子只是假设`readFile`存在。 180 | 181 | 为了避免多次加载相同的模块,`require`需要保存(缓存)已经加载的模块。被调用时,它首先检查所请求的模块是否已加载,如果没有,则加载它。这涉及到读取模块的代码,将其包装在一个函数中,然后调用它。 182 | 183 | 我们之前看到的`ordinal`包的接口不是一个对象,而是一个函数。 CommonJS 模块的特点是,尽管模块系统会为你创建一个空的接口对象(绑定到`exports`),但你可以通过覆盖`module.exports`来替换它。许多模块都这么做,以便导出单个值而不是接口对象。 184 | 185 | 通过将`require`,`exports`和`module`定义为生成的包装函数的参数(并在调用它时传递适当的值),加载器确保这些绑定在模块的作用域中可用。 186 | 187 | 提供给`require`的字符串翻译为实际的文件名或网址的方式,在不同系统有所不同。 当它以`"./"`或`"../"`开头时,它通常被解释为相对于当前模块的文件名。 所以`"./format-date"`就是在同一个目录中,名为`format-date.js`的文件。 188 | 189 | 当名称不是相对的时,Node.js 将按照该名称查找已安装的包。 在本章的示例代码中,我们将把这些名称解释为 NPM 包的引用。 我们将在第 20 章详细介绍如何安装和使用 NPM 模块。 190 | 191 | 现在,我们不用编写自己的 INI 文件解析器,而是使用 NPM 中的某个: 192 | 193 | ```js 194 | const {parse} = require("ini"); 195 | 196 | console.log(parse("x = 10\ny = 20")); 197 | // → {x: "10", y: "20"} 198 | ``` 199 | 200 | ## ECMAScript 模块 201 | 202 | CommonJS 模块很好用,并且与 NPM 一起,使 JavaScript 社区开始大规模共享代码。 203 | 204 | 但他们仍然是个简单粗暴的黑魔法。 例如,表示法有点笨拙 - 添加到`exports`的内容在局部作用域中不可用。 而且因为`require`是一个正常的函数调用,接受任何类型的参数,而不仅仅是字符串字面值,所以在不运行代码就很难确定模块的依赖关系。 205 | 206 | 这就是 2015 年的 JavaScript 标准引入了自己的不同模块系统的原因。 它通常被称为 ES 模块,其中 ES 代表 ECMAScript。 依赖和接口的主要概念保持不变,但细节不同。 首先,表示法现在已整合到该语言中。 你不用调用函数来访问依赖关系,而是使用特殊的`import`关键字。 207 | 208 | ```js 209 | import ordinal from "ordinal"; 210 | import {days, months} from "date-names"; 211 | 212 | export function formatDate(date, format) { /* ... */ } 213 | ``` 214 | 215 | 同样,`export`关键字用于导出东西。 它可以出现在函数,类或绑定定义(`let`,`const`或`var`)的前面。 216 | 217 | ES 模块的接口不是单个值,而是一组命名绑定。 前面的模块将`formatDate`绑定到一个函数。 从另一个模块导入时,导入绑定而不是值,这意味着导出模块可以随时更改绑定的值,导入它的模块将看到其新值。 218 | 219 | 当有一个名为`default`的绑定时,它将被视为模块的主要导出值。 如果你在示例中导入了一个类似于`ordinal`的模块,而没有绑定名称周围的大括号,则会获得其默认绑定。 除了默认绑定之外,这些模块仍然可以以不同名称导出其他绑定。 220 | 221 | 为了创建默认导出,可以在表达式,函数声明或类声明之前编写`export default`。 222 | 223 | ```js 224 | export default ["Winter", "Spring", "Summer", "Autumn"]; 225 | ``` 226 | 227 | 可以使用单词`as`重命名导入的绑定。 228 | 229 | ```js 230 | import {days as dayNames} from "date-names"; 231 | 232 | console.log(dayNames.length); 233 | // → 7 234 | ``` 235 | 236 | 另一个重要的区别是,ES 模块的导入发生在模块的脚本开始运行之前。 这意味着`import`声明可能不会出现在函数或块中,并且依赖项的名称只能是带引号的字符串,而不是任意的表达式。 237 | 238 | 在撰写本文时,JavaScript 社区正在采用这种模块风格。 但这是一个缓慢的过程。 在规定格式之后,花了几年的时间,浏览器和 Node.js 才开始支持它。 虽然他们现在几乎都支持它,但这种支持仍然存在问题,这些模块如何通过 NPM 分发的讨论仍在进行中。 239 | 240 | 许多项目使用 ES 模块编写,然后在发布时自动转换为其他格式。 我们正处于并行使用两个不同模块系统的过渡时期,并且能够读写任何一种之中的代码都很有用。 241 | 242 | ## 构建和打包 243 | 244 | 事实上,从技术上来说,许多 JavaScript 项目都不是用 JavaScript 编写的。有一些扩展被广泛使用,例如第 8 章中提到的类型检查方言。很久以前,在语言的某个计划性扩展添加到实际运行 JavaScript 的平台之前,人们就开始使用它了。 245 | 246 | 为此,他们编译他们的代码,将其从他们选择的 JavaScript 方言翻译成普通的旧式 JavaScript,甚至是过去的 JavaScript 版本,以便旧版浏览器可以运行它。 247 | 248 | 在网页中包含由 200 个不同文件组成的模块化程序,会产生它自己的问题。如果通过网络获取单个文件需要 50 毫秒,则加载整个程序需要 10 秒,或者如果可以同时加载多个文件,则可能需要一半。这浪费了很多时间。因为抓取一个大文件往往比抓取很多小文件要快,所以 Web 程序员已经开始使用工具,将它们发布到 Web 之前,将他们(费力分割成模块)的程序回滚成单个大文件。这些工具被称为打包器。 249 | 250 | 我们可以再深入一点。 除了文件的数量之外,文件的大小也决定了它们可以通过网络传输的速度。 因此,JavaScript 社区发明了压缩器。 通过自动删除注释和空白,重命名绑定以及用占用更少空间的等效代码替换代码段,这些工具使 JavaScript 程序变得更小。 251 | 252 | 因此,你在 NPM 包中找到的代码,或运行在网页上的代码,经历了多个转换阶段 - 从现代 JavaScript 转换为历史 JavaScript,从 ES 模块格式转换为 CommonJS,打包并压缩。 我们不会在本书中详细介绍这些工具,因为它们往往很无聊,并且变化很快。 请注意,你运行的 JavaScript 代码通常不是编写的代码。 253 | 254 | ## 模块设计 255 | 256 | 使程序结构化是编程的一个微妙的方面。 任何有价值的功能都可以用各种方式建模。 257 | 258 | 良好的程序设计是主观的 - 涉及到权衡和品味问题。 了解结构良好的设计的价值的最好方法,是阅读或处理大量程序,并注意哪些是有效的,哪些不是。 不要认为一个痛苦的混乱就是“它本来的方式”。 通过多加思考,你可以改善几乎所有事物的结构。 259 | 260 | 模块设计的一个方面是易用性。 如果你正在设计一些旨在由多人使用,或者甚至是你自己的东西,在三个月之内,当你记不住你所做的细节时,如果你的接口简单且可预测,这会有所帮助。 261 | 262 | 这可能意味着遵循现有的惯例。 `ini`包是一个很好的例子。 此模块模仿标准 JSON 对象,通过提供`parse`和`stringify`(用于编写 INI 文件)函数,就像 JSON 一样,在字符串和普通对象之间进行转换。 所以接口很小且很熟悉,在你使用过一次后,你可能会记得如何使用它。 263 | 264 | 即使没有能模仿的标准函数或广泛使用的包,你也可以通过使用简单的数据结构,并执行单一的重点事项,来保持模块的可预测性。 例如,NPM 上的许多 INI 文件解析模块,提供了直接从硬盘读取文件并解析它的功能。 这使得在浏览器中不可能使用这些模块,因为我们没有文件系统的直接访问权,并且增加了复杂性,通过组合模块与某些文件读取功能,可以更好地解决它。 265 | 266 | 这指向了模块设计的另一个有用的方面 - 一些代码可以轻易与其他代码组合。比起执行带有副作用的复杂操作的更大的模块,计算值的核心模块适用于范围更广的程序。坚持从磁盘读取文件的 INI 文件读取器, 在文件内容来自其他来源的场景中是无用的。 267 | 268 | 与之相关,有状态的对象有时甚至是有用的,但是如果某件事可以用一个函数完成,就用一个函数。 NPM 上的几个 INI​​ 文件读取器提供了一种接口风格,需要你先创建一个对象,然后将该文件加载到对象中,最后使用特定方法来获取结果。这种类型的东西在面向对象的传统中很常见,而且很糟糕。你不能调用单个函数来完成,你必须执行仪式,在各种状态中移动对象。而且由于数据现在封装在一个特定的对象类型中,与它交互的所有代码都必须知道该类型,从而产生不必要的相互依赖关系。 269 | 270 | 通常,定义新的数据结构是不可避免的 - 只有少数非常基本的数据结构由语言标准提供,并且许多类型的数据一定比数组或映射更复杂。 但是当数组足够时,使用数组。 271 | 272 | 一个稍微复杂的数据结构的示例是第 7 章的图。JavaScript 中没有一种明显的表示图的方式。 在那一章中,我们使用了一个对象,其属性保存了字符串数组 - 可以从某个节点到达的其他节点。 273 | 274 | NPM 上有几种不同的寻路包,但他们都没有使用这种图的格式。 它们通常允许图的边带有权重,它是与其相关的成本或距离,这在我们的表示中是不可能的。 275 | 276 | 例如,存在`dijkstrajs`包。 一种著名的寻路方法,与我们的`findRoute`函数非常相似,它被称为迪科斯特拉(Dijkstra)算法,以首先编写它的艾兹格尔·迪科斯特拉(Edsger Dijkstra)命名。 `js`后缀通常会添加到包名称中,以表明它们用 JavaScript 编写。 这个`dijkstrajs`包使用类似于我们的图的格式,但是它不使用数组,而是使用对象,它的属性值是数字 - 边的权重。 277 | 278 | 所以如果我们想要使用这个包,我们必须确保我们的图以它期望的格式存储。 所有边的权重都相同,因为我们的简化模型将每条道路视为具有相同的成本(一个回合)。 279 | 280 | ```js 281 | const {find_path} = require("dijkstrajs"); 282 | 283 | let graph = {}; 284 | for (let node of Object.keys(roadGraph)) { 285 | let edges = graph[node] = {}; 286 | for (let dest of roadGraph[node]) { 287 | edges[dest] = 1; 288 | } 289 | } 290 | 291 | console.log(find_path(graph, "Post Office", "Cabin")); 292 | // → ["Post Office", "Alice's House", "Cabin"] 293 | ``` 294 | 295 | 这可能是组合的障碍 - 当各种包使用不同的数据结构来描述类似的事情时,将它们组合起来很困难。 因此,如果你想要设计可组合性,请查找其他人使用的数据结构,并在可能的情况下遵循他们的示例。 296 | 297 | ## 总结 298 | 299 | 通过将代码分离成具有清晰接口和依赖关系的块,模块是更大的程序结构。 接口是模块中可以从其他模块看到的部分,依赖关系是它使用的其他模块。 300 | 301 | 由于 JavaScript 历史上并没有提供模块系统,因此 CommonJS 系统建立在它之上。 然后在某个时候,它确实有了一个内置系统,它现在与 CommonJS 系统不兼容。 302 | 303 | 包是可以自行分发的一段代码。 NPM 是 JavaScript 包的仓库。 你可以从上面下载各种有用的(和无用的)包。 304 | 305 | ## 练习 306 | 307 | ### 模块化机器人 308 | 309 | 这些是第 7 章的项目所创建的约束: 310 | 311 | ``` 312 | roads 313 | buildGraph 314 | roadGraph 315 | VillageState 316 | runRobot 317 | randomPick 318 | randomRobot 319 | mailRoute 320 | routeRobot 321 | findRoute 322 | goalOrientedRobot 323 | ``` 324 | 325 | 如果你要将该项目编写为模块化程序,你会创建哪些模块? 哪个模块依赖于哪个模块,以及它们的接口是什么样的? 326 | 327 | 哪些片段可能在 NPM 上找到? 你愿意使用 NPM 包还是自己编写? 328 | 329 | ### `roads`模块 330 | 331 | 根据第 7 章中的示例编写 CommonJS 模块,该模块包含道路数组,并将表示它们的图数据结构导出为`roadGraph`。 它应该依赖于一个模块`./graph`,它导出一个函数`buildGraph`,用于构建图。 该函数接受包含两个元素的数组(道路的起点和终点)。 332 | 333 | ```js 334 | // Add dependencies and exports 335 | 336 | const roads = [ 337 | "Alice's House-Bob's House", "Alice's House-Cabin", 338 | "Alice's House-Post Office", "Bob's House-Town Hall", 339 | "Daria's House-Ernie's House", "Daria's House-Town Hall", 340 | "Ernie's House-Grete's House", "Grete's House-Farm", 341 | "Grete's House-Shop", "Marketplace-Farm", 342 | "Marketplace-Post Office", "Marketplace-Shop", 343 | "Marketplace-Town Hall", "Shop-Town Hall" 344 | ]; 345 | ``` 346 | 347 | ### 循环依赖 348 | 349 | 循环依赖是一种情况,其中模块 A 依赖于 B,并且 B 也直接或间接依赖于 A。许多模块系统完全禁止这种情况,因为无论你选择何种顺序来加载此类模块,都无法确保每个模块的依赖关系在它运行之前加载。 350 | 351 | CommonJS 模块允许有限形式的循环依赖。 只要这些模块不会替换它们的默认`exports`对象,并且在完成加载之后才能访问对方的接口,循环依赖就没有问题。 352 | 353 | 本章前面给出的`require`函数支持这种类型的循环依赖。 你能看到它如何处理循环吗? 当一个循环中的某个模块替代其默认`exports`对象时,会出现什么问题? 354 | -------------------------------------------------------------------------------- /13.md: -------------------------------------------------------------------------------- 1 | ## 十三、浏览器中的 JavaScript 2 | 3 | > 原文:[JavaScript and the Browser](https://eloquentjavascript.net/13_browser.html) 4 | > 5 | > 译者:[飞龙](https://github.com/wizardforcel) 6 | > 7 | > 协议:[CC BY-NC-SA 4.0](http://creativecommons.org/licenses/by-nc-sa/4.0/) 8 | > 9 | > 自豪地采用[谷歌翻译](https://translate.google.cn/) 10 | > 11 | > 部分参考了[《JavaScript 编程精解(第 2 版)》](https://book.douban.com/subject/26707144/) 12 | 13 | > Web 背后的梦想是公共信息空间,其中我们通过共享信息进行交流。 其普遍性至关重要:超文本链接可指向任何东西,无论是个人的,本地的还是全球的,无论是草稿还是高度润色的。 14 | > 15 | > Douglas Crockford,《JavaScript 编程语言》(视频讲座) 16 | 17 | ![](img/13-0.jpg) 18 | 19 | 本书接下来的章节将会介绍 Web 浏览器。可以说,没有浏览器,就没有 JavaScript。就算有,估计也不会有多少人去关心这门编程语言。 20 | 21 | Web 技术自出现伊始,其演变方式和技术上就是以分散的方式发展的。许多浏览器厂商专门为其开发新的功能,有时这些新功能被大众采纳,有时这些功能被其他功能所代替,最终形成了一套标准。 22 | 23 | 这种发展模式是把双刃剑。一方面,不会有一个集中式的组织来管理技术的演进,取而代之的是一个包含多方利益集团的松散协作架构(偶尔会出现对立)。另一方面,互联网这种无计划的发展方式所开发出来的系统,其内部很难实现一致性。事实上,它的一些部分令人疑惑,并且毫无设计。 24 | 25 | ## 网络和 Internet 26 | 27 | 计算机网络出现在 20 世纪 50 年代。如果在两台或多台计算机之间铺设电缆,那么你可以通过这些电缆互相收发数据,并实现一些神奇的功能。 28 | 29 | 如果通过连接同一个建筑中的两台机器就可以实现一些神奇的功能,那么如果可以连接全世界的机器,就可以完成更伟大的工作了。20 世纪 80 年代,人们开发了相关技术来实现这个愿景,我们将其产生的网络称为 Internet。而 Internet 的表现名副其实。 30 | 31 | 计算机可以使用这种网络向其他计算机发送位数据。为了在传输位数据的基础上,实现计算机之间的有效通信,网络两端的机器必须知道这些位所表达的实际含义。对于给定的位序列,其含义完全取决于位序列描述的信息类型与使用的编码机制。 32 | 33 | 网络协议描述了一种网络通信方式。网络协议非常多,其中包括邮件发送、邮件收取和邮件共享,甚至连病毒软件感染控制计算机都有相应的协议。 34 | 35 | 例如,HTTP(超文本传输协议,Hypertext Transfer Protocol)是用于检索命名资源(信息块,如网页或图片)的协议。 它指定发出请求的一方应该以这样的一行开始,命名资源和它正在尝试使用的协议的版本。 36 | 37 | ``` 38 | GET /index.html HTTP/1.1 39 | ``` 40 | 41 | 有很多规则,关于请求者在请求中包含更多信息的方式,以及另一方返回资源并打包其内容的方式。 我们将在第 18 章中更详细地观察 HTTP。 42 | 43 | 大多数协议都建立在其他协议之上。 HTTP 将网络视为一种流式设备,您可以将位放入这些设备,并使其按正确的顺序到达正确的目的地。 我们在第 11 章]中看到,确保这些事情已经是一个相当困难的问题。 44 | 45 | 46 | TCP(传输控制协议,Transmission Control Protocol)就可以帮助我们解决该问题。所有连接到互联网的设备都会使用到这种协议,而多数互联网通信都构建在这种协议之上。 47 | 48 | TCP 连接的工作方式是一台电脑必须等待或者监听,而另一台电脑则开始与之通信。一台机器为了同时监听不同类型的通信信息,会为每个监听器分配一个与之关联的数字(我们称之为端口)。大多数协议都指定了默认使用的端口。例如,当我们向使用 SMTP 协议发送一封邮件时,我们需要通过一台机器来发送邮件,而发送邮件的机器需要监听端口 25。 49 | 50 | 随后另一台机器连接到使用了正确端口号的目标机器上。如果可以连接到目标机器,而且目标机器在监听对应端口,则说明连接创建成功。负责监听的计算机名为服务器,而连接服务器的计算机名为客户端。 51 | 52 | 我们可以将该连接看成双向管道,位可以在其中流动,也就是说两端的机器都可以向连接中写入数据。当成功传输完这些位数据后,双方都可以读取另一端传来的数据。TCP 是一个非常便利的模型。我们可以说TCP就是一种网络的抽象。 53 | 54 | ## Web 55 | 56 | 万维网(World Wide Web,不要将其与 Internet 混淆)是包含一系列协议和格式的集合,允许我们通过浏览器访问网页。词组中的 Web 指的是这些页面可以轻松地链接其他网页,因此最后可以连接成一张巨大的网,用户可以在网络中浏览。 57 | 58 | 你只需将一台计算机连接到 Internet 并使用 HTTP 监听 80 端口,就可以成为 Web 的一部分。其他计算机可以通过网络,并使用 HTTP 协议获取其他计算机上的文件。 59 | 60 | 网络中的每个文件都能通过 URL(统一资源定位符,Universal Resource Locator)访问,如下所示: 61 | 62 | ``` 63 | http://eloquentjavascript.net/13_browser.html 64 | | | | | 65 | protocol server path 66 | ``` 67 | 该地址的第一部分告诉我们 URL 使用的是 HTTP 协议(加密的 HTTP 连接则使用`https://`来表示)。第二部分指的是获取文件的服务器地址。第三部分是我们想要获取的具体文件(或资源)的路径。 68 | 69 | 连接到互联网的机器获得一个 IP 地址,该地址是一个数字,可用于将消息发送到该机器的,类似于`"149.210.142.219"`或`"2001:4860:4860::8888"`。 但是或多或少的随机数字列表很难记住,而且输入起来很笨拙,所以你可以为一个特定的地址或一组地址注册一个域名。 我注册了`eloquentjavascript.net`,来指向我控制的机器的 IP 地址,因此可以使用该域名来提供网页。 70 | 71 | 如果你在浏览器地址栏中输入上面提到的 URL,浏览器会尝试获取并显示该 URL 对应的文档。首先,你的浏览器需要找出域名`eloquentjavascript.net`指向的地址。然后使用 HTTP 协议,连接到该地址处的服务器,并请求`/13_browser.html`这个资源。如果一切顺利,服务器会发回一个文档,然后您的浏览器将显示在屏幕上。 72 | 73 | ## HTML 74 | 75 | HTML,即超文本标记语言(Hypertext Markup Language),是在网页中得到广泛使用的文档格式。HTML 文档不仅包含文本,还包含了标签,用于说明文本结构,描述了诸如链接、段落、标题之类的元素。 76 | 77 | 一个简短的 HTML 文档如下所示: 78 | 79 | ```html 80 | 81 | 82 | 83 | 84 | My home page 85 | 86 | 87 |

My home page

88 |

Hello, I am Marijn and this is my home page.

89 |

I also wrote a book! Read it 90 | here.

91 | 92 | 93 | ``` 94 | 95 | 标签包裹在尖括号之间(`<`和`>`,小于和大于号),提供关于文档结构的信息。其他文本则是纯文本。 96 | 97 | 文档以``开头,告诉浏览器将页面解释为现代 HTML,以别于过去使用的各种方言。 98 | 99 | HTML 文档有头部(head)和主体(body)。头部包含了文档信息,而主体则包含文档自身。在本例中,头部将文档标题声明为`"My home page"`,并使用 UTF-8 编码,它是将 Unicode 文本编码为二进制的方式。文档的主体包含标题(`

`,表示一级标题,`

`到`

`可以产生不同等级的子标题)和两个段落(`

`)。 100 | 101 | 标签有几种形式。一个元素,比如主体、段落或链接以一个起始标签(比如`

`)开始,并以一个闭合标签(比如`

`)结束。一些起始标签,比如一个链接(``),会包含一些额外信息,其形式是`name="value"`这种键值对,我们称之为属性。在本例中,使用属性`href="http://eloquentjavascript.net"`指定链接的目标,其中`href`表示“超文本链接(Hypertext Reference)”。 102 | 103 | 某些类型的标签不会包含任何元素,这种标签不需要闭合。元数据标签``就是一个例子。 104 | 105 | > 译者注:最好还是这样闭合它们:``。 106 | 107 | 尽管 HTML 中尖括号有特殊含义,但为了在文档的文本中包含这些符号,可以引入另外一种形式的特殊标记方法。普通文本中的起始尖括号写成`<`(less than),而闭合尖括号写成`>`(greater than)。在 HTML 中,我们将一个`&`字符后跟着一个单词和分号(`;`)这种写法称为一个实体,浏览器会使用实体编码对应的字符替换它们。 108 | 109 | 与之类似的是 JavaScript 字符串中反斜杠的使用。由于 HTML 中的实体机制赋予了`&`特殊含义,因此我们需要使用`&`来表示一个`&`字符。在属性的值(包在双引号中)中使用`"`可以插入实际的引号字符。 110 | 111 | HTML 的解析过程容错性非常强。当应有的标签丢失时,浏览器会重新构建这些标签。标签的重新构建已经标准化,你可以认为所有现代浏览器的行为都是一致的。 112 | 113 | 下面的文件与之前版本显示效果相同: 114 | 115 | ```html 116 | 117 | 118 | 119 | My home page 120 | 121 |

My home page

122 |

Hello, I am Marijn and this is my home page. 123 |

I also wrote a book! Read it 124 | here. 125 | ``` 126 | 127 | ``、``和``标签可以完全丢弃。浏览器知道``和``属于头部,而`<h1>`属于主体。此外,我再也不用明确关闭某个段落,因为新段落开始或文档结束时,浏览器会隐式关闭段落标签。目标链接两边的引号也可以丢弃。 128 | 129 | 本书的示例通常都会省略`<html>`、`<head>`和`<body>`标签,以保持源代码简短,避免太过杂乱。但我会明确关闭所有标签并在属性两旁包含引号。 130 | 131 | 本书也会经常忽略`doctype`和`charset`声明。这并不是鼓励大家省略它们。当你忘记它们时,浏览器往往会做出荒谬的事情。 您应该认为`doctype`和`charset`元数据隐式出现在示例中,即使它们没有实际显示在文本中。 132 | 133 | ## HTML 和 JavaScript 134 | 135 | 对于本书来说,最重要的一个 HTML 标签是`<script>`。该标签允许我们在文档中包含一段 JavaScript 代码。 136 | 137 | ```html 138 | <h1>Testing alert</h1> 139 | <script>alert("hello!");</script> 140 | ``` 141 | 142 | 当浏览器在读取 HTML 时,一旦遇到`<script>`标签就会执行该代码。这个页面在打开时会弹出一个对话框 - `alert`函数类似`prompt`,因为它弹出一个小窗口,但只显示一条消息而不请求输入。 143 | 144 | 在 HTML 文档中包含大程序是不切实际的。`<script>`标签可以指定一个`src`属性,从一个 URL 获取脚本文件(包含 JavaScript 程序的文本文件)。 145 | 146 | ```html 147 | <h1>Testing alert</h1> 148 | <script src="code/hello.js"></script> 149 | ``` 150 | 151 | 这里包含的文件`code/hello.js`是和上文中相同的一段程序,`alert("hello")`。当一个页面将其他 URL 引用为自身的一部分时(比如图像文件或脚本),网页浏览器将会立即获取这些资源并将其包含在页面中。 152 | 153 | 即使`script`标签引用了一个文本文件,且并未包含任何代码,你也必须使用`</script>`来闭合标签。如果你忘记了这点,浏览器会将剩余的页面会作为脚本的一部分进行解析。 154 | 155 | 你可以在浏览器中加载ES模块(参见第 10 章),向脚本标签提供`type ="module"`属性。 这些模块可以依赖于其他模块,通过将相对于自己的 URL 用作`import`声明中的模块名称。 156 | 157 | 158 | 某些属性也可以包含 JavaScript 程序。下面展示的`<button>`标签(显示一个按钮)有一个`onclick`属性。该属性的值将在点击按钮时运行。 159 | 160 | ```html 161 | <button onclick="alert('Boom!');">DO NOT PRESS</button> 162 | ``` 163 | 164 | 需要注意的是,我们在`onclick`属性的字符串中使用了单引号,这是因为我们在使用了双引号来引用整个属性。我们也可以使用`"`。 165 | 166 | ## 沙箱 167 | 168 | 直接执行从因特网中下载的程序存在潜在危险。你不了解大多数的网页开发者,他们不一定都心怀善意。一旦运行某些不怀好意的人提供的程序,你的电脑可能会感染病毒,这些程序还会窃取数据会并盗走账号。 169 | 170 | 但网络的吸引力就在于你可以浏览网站,而不必要信任所有网站。这就是为什么浏览器严重限制了 JavaScript 程序的能力—— JavaScript 无法查看电脑中的任何文件,也无法修改与其所在页面无关的数据。 171 | 172 | 我们将这种隔离程序运行环境的技术称为沙箱。以该思想编写的程序在沙箱中运行,不会对计算机造成任何伤害。但是你应该想象,这种特殊的沙箱上面有一个厚钢筋笼子,所以在其中运行的程序实际上不会出去。 173 | 174 | 实现沙箱的难点是:一方面我们要给予程序一定的自由使得程序能有实际用处,但又要限制程序,防止其执行危险的行为。许多实用功能(比如与服务器通信或从剪贴板读取内容)也会存在问题,有些侵入者可以利用这些功能来侵入你的计算机。 175 | 176 | 时不时会有一些人想到新方法,突破浏览器的限制,并对你的机器造成伤害,从窃取少量的私人信息到掌握执行浏览器的整个机器。浏览器开发者的对策是修补漏洞,然后一切都恢复正常。直到下一次问题被发现并广为传播之前,某些政府或秘密组织可以私下利用这些漏洞。 177 | 178 | ## 兼容性与浏览器之争 179 | 180 | 在 Web 技术发展的早期,一款名为 Mosaic 的浏览器统治了整个市场。几年之后,这种平衡被 Netscape 公司打破,随后又被微软的 Internet Explorer 排挤出市场。无论什么时候,当一款浏览器统治了整个市场,浏览器供应商就会觉得他们有权利单方面为网络研发新的特性。由于大多数人都使用相同的浏览器,因此网站会开始使用这些独有特性,也就不再考虑其他浏览器的兼容性问题了。 181 | 182 | 这是兼容性的黑暗时代,我们通常称之为浏览器之争。网络开发者总是为缺乏统一的 Web 标准,而需要去考虑两到三种互不兼容的平台而感到烦恼。让事情变得更糟糕的是 2003 年左右使用的浏览器充满了漏洞,当然不同浏览器的漏洞都不一样。网页编写者的生活颇为艰辛。 183 | 184 | Mozilla Firefox,作为 Netscape 浏览器的非盈利性分支,在20世纪初末期开始挑战 Internet Explorer 的霸主地位。因为当时微软并未特别关心与其竞争,导致 Firefox 迅速占领了很大的市场份额。与此同时,Google 发布了它的 Chrome 浏览器,而 Apple 的 Safari 也得到普及,导致现在成为四个主要选手的竞争,而非一家独大。 185 | 186 | 新的参与者对标准有着更认真的态度,和更好的工程实践,为我们减少了不兼容性和错误。 微软看到其市场份额极速下降,在其 Edge 浏览器中采取了这些态度,取代了 Internet Explorer。 如果您今天开始学习网络开发,请认为自己是幸运的。 主流浏览器的最新版本行为非常一致,并且错误相对较少。 187 | 188 | 这并不是说就没有问题了。某些使用网络的人,出于惰性或公司政策,被迫使用旧版本的浏览器。直到这些浏览器完全退出市场之前,为旧版本浏览器编写网站仍需要掌握很多不常见的特性,了解旧浏览器的缺陷和特殊之处。本书不会讨论这些特殊的特性,而着眼于介绍现代且健全的网络程序设计风格。 189 | -------------------------------------------------------------------------------- /404.html: -------------------------------------------------------------------------------- 1 | --- 2 | permalink: /404.html 3 | --- 4 | <script>window.location.href = '/';</script> 5 | -------------------------------------------------------------------------------- /5.md: -------------------------------------------------------------------------------- 1 | ## 五、高阶函数 2 | 3 | > 原文:[Higher-Order Functions](http://eloquentjavascript.net/05_higher_order.html) 4 | > 5 | > 译者:[飞龙](https://github.com/wizardforcel) 6 | > 7 | > 协议:[CC BY-NC-SA 4.0](http://creativecommons.org/licenses/by-nc-sa/4.0/) 8 | > 9 | > 自豪地采用[谷歌翻译](https://translate.google.cn/) 10 | > 11 | > 部分参考了[《JavaScript 编程精解(第 2 版)》](https://book.douban.com/subject/26707144/) 12 | 13 | > Tzu-li and Tzu-ssu were boasting about the size of their latest programs. ‘Two-hundred thousand lines,’ said Tzu-li, ‘not counting comments!’ Tzu-ssu responded, ‘Pssh, mine is almost a million lines already.’ Master Yuan-Ma said, ‘My best program has five hundred lines.’ Hearing this, Tzu-li and Tzu-ssu were enlightened. 14 | > 15 | > Master Yuan-Ma,《The Book of Programming》 16 | > 17 | > There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. 18 | > 19 | > C.A.R. Hoare,1980 ACM Turing Award Lecture 20 | 21 | ![](img/5-0.jpg) 22 | 23 | 开发大型程序通常需要耗费大量财力和物力,这绝不仅仅是因为构建程序所花费时间的问题。大型程序的复杂程度总是很高,而这些复杂性也会给开发人员带来不少困扰,而程序错误或 bug 往往就是这些时候引入的。大型程序为这些 bug 提供了良好的藏身之所,因此我们更加难以在大型程序中找到它们。 24 | 25 | 让我们简单回顾一下前言当中的两个示例。其中第一个程序包含了 6 行代码并可以直接运行。 26 | 27 | ```js 28 | let total = 0, count = 1; 29 | while (count <= 10) { 30 | total += count; 31 | count += 1; 32 | } 33 | console.log(total); 34 | ``` 35 | 36 | 第二个程序则依赖于外部函数才能执行,且只有一行代码。 37 | 38 | ```js 39 | console.log(sum(range(1, 10))); 40 | ``` 41 | 42 | 哪一个程序更有可能含有 bug 呢? 43 | 44 | 如果算上`sum`和`range`两个函数的代码量,显然第二个程序的代码量更大。不过,我仍然觉得第二个程序包含 bug 的可能性比第一个程序低。 45 | 46 | 之所以这么说的原因是,第二个程序编写的代码很好地表达了我们期望解决的问题。对于计算一组数字之和这个操作来说,我们关注的是计算范围和求和运算,而不是循环和计数。 47 | 48 | `sum`和`range`这两个函数定义的操作当然会包含循环、计数和其他一些操作。但相比于将这些代码直接写到一起,这种表述方式更为简单,同时也易于避免错误。 49 | 50 | ## 抽象 51 | 52 | 在程序设计中,我们把这种编写代码的方式称为抽象。抽象可以隐藏底层的实现细节,从更高(或更加抽象)的层次看待我们要解决的问题。 53 | 54 | 举个例子,比较一下这两份豌豆汤的食谱: 55 | 56 | 按照每人一杯的量将脱水豌豆放入容器中。倒水直至浸没豌豆,然后至少将豌豆浸泡 12 个小时。将豌豆从水中取出沥干,倒入煮锅中,按照每人四杯水的量倒入水。将食材盖满整个锅底,并慢煮 2 个小时。按照每人半个的量加入洋葱,用刀切片,然后放入豌豆中。按照每人一根的量加入芹菜,用刀切片,然后放入豌豆当中。按照每人一根的量放入胡萝卜,用刀切片,然后放入豌豆中。最后一起煮 10 分钟以上即可。 57 | 58 | 第二份食谱: 59 | 60 | 一个人的量:一杯脱水豌豆、半个切好的洋葱、一根芹菜和一根胡萝卜。 61 | 62 | 将豌豆浸泡 12 个小时。按照每人四杯水的量倒入水,然后用文火煨 2 个小时。加入切片的蔬菜,煮 10 分钟以上即可。 63 | 64 | 相比第一份食谱,第二份食谱更简短且更易于理解。但你需要了解一些有关烹调的术语:浸泡、煨、切片,还有蔬菜。 65 | 66 | 在编程的时候,我们不能期望所有功能都是现成的。因此,你可能就会像第一份食谱那样编写你的程序,逐个编写计算机需要执行的代码和步骤,而忽略了这些步骤之上的抽象概念。 67 | 68 | 在编程时,注意你的抽象级别什么时候过低,是一项非常有用的技能。 69 | 70 | ## 重复的抽象 71 | 72 | 我们已经了解的普通函数就是一种很好的构建抽象的工具。但有些时候,光有函数也不一定能够解决我们的问题。 73 | 74 | 程序以给定次数执行某些操作很常见。 你可以为此写一个`for`循环,就像这样: 75 | 76 | ```js 77 | for (let i = 0; i < 10; i++) { 78 | console.log(i); 79 | } 80 | ``` 81 | 82 | 我们是否能够将“做某件事`N`次”抽象为函数? 编写一个调用`console.log` `N`次的函数是很容易的。 83 | 84 | ```js 85 | function repeatLog(n) { 86 | for (let i = 0; i < n; i++) { 87 | console.log(i); 88 | } 89 | } 90 | ``` 91 | 92 | 但如果我们想执行打印数字以外的操作该怎么办呢?我们可以使用函数来定义我们想做的事,而函数也是值,因此我们可以将期望执行的操作封装成函数,然后传递进来。 93 | 94 | ```js 95 | function repeat(n, action) { 96 | for (let i = 0; i < n; i++) { 97 | action(i); 98 | } 99 | } 100 | 101 | repeat(3, console.log); 102 | // → 0 103 | // → 1 104 | // → 2 105 | ``` 106 | 107 | 你不必将预定义的函数传递给`repeat`。 通常情况下,你希望原地创建一个函数值。 108 | 109 | ```js 110 | let labels = []; 111 | repeat(5, i => { 112 | labels.push(`Unit ${i + 1}`); 113 | }); 114 | console.log(labels); 115 | // → ["Unit 1", "Unit 2", "Unit 3", "Unit 4", "Unit 5"] 116 | ``` 117 | 118 | 这个结构有点像`for`循环 - 它首先描述了这种循环,然后提供了一个主体。 但是,主体现在写为一个函数值,它被包裹在`repeat`调用的括号中。 这就是它必须用右小括号和右大括号闭合的原因。 在这个例子中,主体是单个小表达式,你也可以省略大括号并将循环写成单行。 119 | 120 | ## 高阶函数 121 | 122 | 如果一个函数操作其他函数,即将其他函数作为参数或将函数作为返回值,那么我们可以将其称为高阶函数。因为我们已经看到函数就是一个普通的值,那么高阶函数也就不是什么稀奇的概念了。高阶这个术语来源于数学,在数学当中,函数和值的概念有着严格的区分。 123 | 124 | 我们可以使用高阶函数对一系列操作和值进行抽象。高阶函数有多种表现形式。比如你可以使用高阶函数来新建另一些函数。 125 | 126 | ```js 127 | function greaterThan(n) { 128 | return m => m > n; 129 | } 130 | let greaterThan10 = greaterThan(10); 131 | console.log(greaterThan10(11)); 132 | // → true 133 | ``` 134 | 135 | 你也可以使用高阶函数来修改其他的函数。 136 | 137 | ```js 138 | function noisy(f) { 139 | return (...args) => { 140 | console.log("calling with", args); 141 | let result = f(...args); 142 | console.log("called with", args, ", returned", result); 143 | return result; 144 | }; 145 | } 146 | noisy(Math.min)(3, 2, 1); 147 | // → calling with [3, 2, 1] 148 | // → called with [3, 2, 1] , returned 1 149 | ``` 150 | 151 | 你甚至可以使用高阶函数来实现新的控制流。 152 | 153 | ```js 154 | function unless(test, then) { 155 | if (!test) then(); 156 | } 157 | repeat(3, n => { 158 | unless(n % 2 == 1, () => { 159 | console.log(n, "is even"); 160 | }); 161 | }); 162 | // → 0 is even 163 | // → 2 is even 164 | ``` 165 | 166 | 有一个内置的数组方法,`forEach`,它提供了类似`for/of`循环的东西,作为一个高阶函数。 167 | 168 | ```js 169 | ["A", "B"].forEach(l => console.log(l)); 170 | // → A 171 | // → B 172 | ``` 173 | 174 | ## 脚本数据集 175 | 176 | 数据处理是高阶函数表现突出的一个领域。 为了处理数据,我们需要一些真实数据。 本章将使用脚本书写系统的数据集,例如拉丁文,西里尔文或阿拉伯文。 177 | 178 | 请记住第 1 章中的 Unicode,该系统为书面语言中的每个字符分配一个数字。 大多数这些字符都与特定的脚本相关联。 该标准包含 140 个不同的脚本 - 81 个今天仍在使用,59 个是历史性的。 179 | 180 | 虽然我只能流利地阅读拉丁字符,但我很欣赏这样一个事实,即人们使用其他至少 80 种书写系统来编写文本,其中许多我甚至不认识。 例如,以下是泰米尔语手写体的示例。 181 | 182 | ![](img/5-1.png) 183 | 184 | 示例数据集包含 Unicode 中定义的 140 个脚本的一些信息。 本章的[编码沙箱](https://eloquentjavascript.net/code#5)中提供了`SCRIPTS`绑定。 该绑定包含一组对象,其中每个对象都描述了一个脚本。 185 | 186 | ```json 187 | { 188 | name: "Coptic", 189 | ranges: [[994, 1008], [11392, 11508], [11513, 11520]], 190 | direction: "ltr", 191 | year: -200, 192 | living: false, 193 | link: "https://en.wikipedia.org/wiki/Coptic_alphabet" 194 | } 195 | ``` 196 | 197 | 这样的对象会告诉你脚本的名称,分配给它的 Unicode 范围,书写方向,(近似)起始时间,是否仍在使用以及更多信息的链接。 方向可以是从左到右的`"ltr"`,从右到左的`"rtl"`(阿拉伯语和希伯来语文字的写法),或者从上到下的`"ttb"`(蒙古文的写法)。 198 | 199 | `ranges`属性包含 Unicode 字符范围数组,每个数组都有两元素,包含下限和上限。 这些范围内的任何字符码都会分配给脚本。 下限是包括的(代码 994 是一个科普特字符),并且上限排除在外(代码 1008 不是)。 200 | 201 | ## 数组过滤 202 | 203 | 为了找到数据集中仍在使用的脚本,以下函数可能会有所帮助。 它过滤掉数组中未通过测试的元素: 204 | 205 | ```js 206 | function filter(array, test) { 207 | let passed = []; 208 | for (let element of array) { 209 | if (test(element)) { 210 | passed.push(element); 211 | } 212 | } 213 | return passed; 214 | } 215 | 216 | console.log(filter(SCRIPTS, script => script.living)); 217 | // → [{name: "Adlam", …}, …] 218 | ``` 219 | 220 | 该函数使用名为`test`的参数(一个函数值)填充计算中的“间隙” - 决定要收集哪些元素的过程。 221 | 222 | 需要注意的是,`filter`函数并没有从当前数组中删除元素,而是新建了一个数组,并将满足条件的元素存入新建的数组中。这个函数是一个“纯函数”,因为该函数并未修改给定的数组。 223 | 224 | 与`forEach`一样,`filter`函数也是标准的数组方法。本例中定义的函数只是用于展示内部实现原理。今后我们会使用以下方法来过滤数据: 225 | 226 | ```js 227 | console.log(SCRIPTS.filter(s => s.direction == "ttb")); 228 | // → [{name: "Mongolian", …}, …] 229 | ``` 230 | 231 | ## 使用`map`函数转换数组 232 | 233 | 假设我们已经通过某种方式过滤了`SCRIPTS`数组,生成一个用于表示脚本的信息数组。但我们想创建一个包含名称的数组,因为这样更加易于检查。 234 | 235 | `map`方法对数组中的每个元素调用函数,然后利用返回值来构建一个新的数组,实现转换数组的操作。新建数组的长度与输入的数组一致,但其中的内容却通过对每个元素调用的函数“映射”成新的形式。 236 | 237 | ```js 238 | function map(array, transform) { 239 | let mapped = []; 240 | for (let element of array) { 241 | mapped.push(transform(element)); 242 | } 243 | return mapped; 244 | } 245 | 246 | let rtlScripts = SCRIPTS.filter(s => s.direction == "rtl"); 247 | console.log(map(rtlScripts, s => s.name)); 248 | // → ["Adlam", "Arabic", "Imperial Aramaic", …] 249 | ``` 250 | 251 | 与`forEach`和`filter`一样,`map`也是标准的数组方法。 252 | 253 | ## 使用`reduce`汇总数据 254 | 255 | 与数组有关的另一个常见事情是从它们中计算单个值。 我们的递归示例,汇总了一系列数字,就是这样一个例子。 另一个例子是找到字符最多的脚本。 256 | 257 | 表示这种模式的高阶操作称为归约(reduce)(有时也称为折叠(fold))。 它通过反复从数组中获取单个元素,并将其与当前值合并来构建一个值。 在对数字进行求和时,首先从数字零开始,对于每个元素,将其与总和相加。 258 | 259 | `reduce`函数包含三个参数:数组、执行合并操作的函数和初始值。该函数没有`filter`和`map`那样直观,所以仔细看看: 260 | 261 | ```js 262 | function reduce(array, combine, start) { 263 | let current = start; 264 | for (let element of array) { 265 | current = combine(current, element); 266 | } 267 | return current; 268 | } 269 | 270 | console.log(reduce([1, 2, 3, 4], (a, b) => a + b, 0)); 271 | // → 10 272 | ``` 273 | 274 | 数组中有一个标准的`reduce`方法,当然和我们上面看到的那个函数一致,可以简化合并操作。如果你的数组中包含多个元素,在调用`reduce`方法的时候忽略了`start`参数,那么该方法将会使用数组中的第一个元素作为初始值,并从第二个元素开始执行合并操作。 275 | 276 | ```js 277 | console.log([1, 2, 3, 4].reduce((a, b) => a + b)); 278 | // → 10 279 | ``` 280 | 281 | 为了使用`reduce`(两次)来查找字符最多的脚本,我们可以这样写: 282 | 283 | ```js 284 | function characterCount(script) { 285 | return script.ranges.reduce((count, [from, to]) => { 286 | return count + (to - from); 287 | }, 0); 288 | } 289 | 290 | console.log(SCRIPTS.reduce((a, b) => { 291 | return characterCount(a) < characterCount(b) ? b : a; 292 | })); 293 | // → {name: "Han", …} 294 | ``` 295 | 296 | `characterCount`函数通过累加范围的大小,来减少分配给脚本的范围。 请注意归约器函数的参数列表中使用的解构。 `reduce'的第二次调用通过重复比较两个脚本并返回更大的脚本,使用它来查找最大的脚本。 297 | 298 | Unicode 标准分配了超过 89,000 个字符给汉字脚本,它成为数据集中迄今为止最大的书写系统。 汉字是一种(有时)用于中文,日文和韩文的文字。 这些语言共享很多字符,尽管他们倾向于以不同的方式写它们。 (基于美国的)Unicode 联盟决定将它们看做一个单独的书写系统来保存字符码。 这被称为中日韩越统一表意文字(Han unification),并且仍然使一些人非常生气。 299 | 300 | ## 可组合性 301 | 302 | 考虑一下,我们怎样才可以在不使用高阶函数的情况下,编写以上示例(找到最大的脚本)?代码没有那么糟糕。 303 | 304 | ```js 305 | let biggest = null; 306 | for (let script of SCRIPTS) { 307 | if (biggest == null || 308 | characterCount(biggest) < characterCount(script)) { 309 | biggest = script; 310 | } 311 | } 312 | console.log(biggest); 313 | // → {name: "Han", …} 314 | ``` 315 | 316 | 这段代码中多了一些绑定,虽然多了两行代码,但代码逻辑还是很容易让人理解的。 317 | 318 | 当你需要组合操作时,高阶函数的价值就突显出来了。举个例子,我们编写一段代码,找出数据集中男人和女人的平均年龄。 319 | 320 | ```js 321 | function average(array) { 322 | return array.reduce((a, b) => a + b) / array.length; 323 | } 324 | 325 | console.log(Math.round(average( 326 | SCRIPTS.filter(s => s.living).map(s => s.year)))); 327 | // → 1185 328 | console.log(Math.round(average( 329 | SCRIPTS.filter(s => !s.living).map(s => s.year)))); 330 | // → 209 331 | ``` 332 | 333 | 因此,Unicode 中的死亡脚本,平均比活动脚本更老。 这不是一个非常有意义或令人惊讶的统计数据。 但是我希望你会同意,用于计算它的代码不难阅读。 你可以把它看作是一个流水线:我们从所有脚本开始,过滤出活动的(或死亡的)脚本,从这些脚本中抽出时间,对它们进行平均,然后对结果进行四舍五入。 334 | 335 | 你当然也可以把这个计算写成一个大循环。 336 | 337 | ```js 338 | let total = 0, count = 0; 339 | for (let script of SCRIPTS) { 340 | if (script.living) { 341 | total += script.year; 342 | count += 1; 343 | } 344 | } 345 | console.log(Math.round(total / count)); 346 | // → 1185 347 | ``` 348 | 349 | 但很难看到正在计算什么以及如何计算。 而且由于中间结果并不表示为一致的值,因此将“平均值”之类的东西提取到单独的函数中,需要更多的工作。 350 | 351 | 就计算机实际在做什么而言,这两种方法也是完全不同的。 第一个在运行`filter`和`map`的时候会建立新的数组,而第二个只会计算一些数字,从而减少工作量。 你通常可以采用可读的方法,但是如果你正在处理巨大的数组,并且多次执行这些操作,那么抽象风格的加速就是值得的。 352 | 353 | ## 字符串和字符码 354 | 355 | 这个数据集的一种用途是确定一段文本所使用的脚本。 我们来看看执行它的程序。 356 | 357 | 请记住,每个脚本都有一组与其相关的字符码范围。 所以给定一个字符码,我们可以使用这样的函数来找到相应的脚本(如果有的话): 358 | 359 | ```js 360 | function characterScript(code) { 361 | for (let script of SCRIPTS) { 362 | if (script.ranges.some(([from, to]) => { 363 | return code >= from && code < to; 364 | })) { 365 | return script; 366 | } 367 | } 368 | return null; 369 | } 370 | 371 | console.log(characterScript(121)); 372 | // → {name: "Latin", …} 373 | ``` 374 | 375 | `some`方法是另一个高阶函数。 它需要一个测试函数,并告诉你该函数是否对数组中的任何元素返回`true`。 376 | 377 | 但是,我们如何获得字符串中的字符码? 378 | 379 | 在第一章中,我提到 JavaScript 字符串被编码为一个 16 位数字的序列。 这些被称为代码单元。 一个 Unicode 字符代码最初应该能放进这样一个单元(它给你超 65,000 个字符)。 后来人们发现它不够用了,很多人避开了为每个字符使用更多内存的需求。 为了解决这些问题,人们发明了 UTF-16,JavaScript 字符串使用的格式 。它使用单个 16 位代码单元描述了大多数常见字符,但是为其他字符使用一对两个这样的单元。 380 | 381 | 今天 UTF-16 通常被认为是一个糟糕的主意。 它似乎总是故意设计来引起错误。 很容易编写程序,假装代码单元和字符是一个东西。 如果你的语言不使用两个单位的字符,显然能正常工作。 但只要有人试图用一些不太常见的中文字符来使用这样的程序,就会中断。 幸运的是,随着 emoji 符号的出现,每个人都开始使用两个单元的字符,处理这些问题的负担更加分散。 382 | 383 | ```js 384 | // Two emoji characters, horse and shoe 385 | let horseShoe = "\ud83d\udc34\ud83d\udc5f"; 386 | console.log(horseShoe.length); 387 | // → 4 388 | console.log(horseShoe[0]); 389 | // → (Invalid half-character) 390 | console.log(horseShoe.charCodeAt(0)); 391 | // → 55357 (Code of the half-character) 392 | console.log(horseShoe.codePointAt(0)); 393 | // → 128052 (Actual code for horse emoji) 394 | ``` 395 | 396 | JavaScript的`charCodeAt`方法为你提供了一个代码单元,而不是一个完整的字符代码。 稍后添加的`codePointAt`方法确实提供了完整的 Unicode 字符。 所以我们可以使用它从字符串中获取字符。 但传递给`codePointAt`的参数仍然是代码单元序列的索引。 因此,要运行字符串中的所有字符,我们仍然需要处理一个字符占用一个还是两个代码单元的问题。 397 | 398 | 在上一章中,我提到`for/of`循环也可以用在字符串上。 像`codePointAt`一样,这种类型的循环,是在人们敏锐地意识到 UTF-16 的问题的时候引入的。 当你用它来遍历一个字符串时,它会给你真正的字符,而不是代码单元。 399 | 400 | ```js 401 | let roseDragon = "\ud83c\udf45\ud83d\udc09"; 402 | for (let char of roseDragon) { 403 | console.log(char); 404 | // → (emoji rose) 405 | // → (emoji dragon) 406 | ``` 407 | 408 | 如果你有一个字符(它是一个或两个代码单元的字符串),你可以使用`codePointAt(0)`来获得它的代码。 409 | 410 | ## 识别文本 411 | 412 | 我们有了`characterScript`函数和一种正确遍历字符的方法。 下一步将是计算属于每个脚本的字符。 下面的计数抽象会很实用: 413 | 414 | ```js 415 | function countBy(items, groupName) { 416 | let counts = []; 417 | for (let item of items) { 418 | let name = groupName(item); 419 | let known = counts.findIndex(c => c.name == name); 420 | if (known == -1) { 421 | counts.push({name, count: 1}); 422 | } else { 423 | counts[known].count++; 424 | } 425 | } 426 | return counts; 427 | } 428 | 429 | console.log(countBy([1, 2, 3, 4, 5], n => n > 2)); 430 | // → [{name: false, count: 2}, {name: true, count: 3}] 431 | ``` 432 | 433 | `countBy`函数需要一个集合(我们可以用`for/of`来遍历的任何东西)以及一个函数,它计算给定元素的组名。 它返回一个对象数组,每个对象命名一个组,并告诉你该组中找到的元素数量。 434 | 435 | 它使用另一个数组方法`findIndex`。 这个方法有点像`indexOf`,但它不是查找特定的值,而是查找给定函数返回`true`的第一个值。 像`indexOf`一样,当没有找到这样的元素时,它返回 -1。 436 | 437 | 使用`countBy`,我们可以编写一个函数,告诉我们在一段文本中使用了哪些脚本。 438 | 439 | ```js 440 | function textScripts(text) { 441 | let scripts = countBy(text, char => { 442 | let script = characterScript(char.codePointAt(0)); 443 | return script ? script.name : "none"; 444 | }).filter(({name}) => name != "none"); 445 | 446 | let total = scripts.reduce((n, {count}) => n + count, 0); 447 | if (total == 0) return "No scripts found"; 448 | 449 | return scripts.map(({name, count}) => { 450 | return `${Math.round(count * 100 / total)}% ${name}`; 451 | }).join(", "); 452 | } 453 | 454 | console.log(textScripts('英国的狗说"woof", 俄罗斯的狗说"тяв"')); 455 | // → 61% Han, 22% Latin, 17% Cyrillic 456 | ``` 457 | 458 | 该函数首先按名称对字符进行计数,使用`characterScript`为它们分配一个名称,并且对于不属于任何脚本的字符,回退到字符串`"none"`。 `filter`调用从结果数组中删除`"none"`的条目,因为我们对这些字符不感兴趣。 459 | 460 | 为了能够计算百分比,我们首先需要属于脚本的字符总数,我们可以用`reduce`来计算。 如果没有找到这样的字符,该函数将返回一个特定的字符串。 否则,它使用`map`将计数条目转换为可读的字符串,然后使用`join`合并它们。 461 | 462 | ## 本章小结 463 | 464 | 能够将函数值传递给其他函数,是 JavaScript 的一个非常有用的方面。 它允许我们编写函数,用它们中的“间隙”对计算建模。 调用这些函数的代码,可以通过提供函数值来填补间隙。 465 | 466 | 数组提供了许多有用的高阶方法。 你可以使用`forEach`来遍历数组中的元素。 `filter`方法返回一个新数组,只包含通过谓词函数的元素。 通过将函数应用于每个元素的数组转换,使用`map`来完成。 你可以使用`reduce`将数组中的所有元素合并为一个值。 `some`方法测试任何元素是否匹配给定的谓词函数。 `findIndex`找到匹配谓词的第一个元素的位置。 467 | 468 | ## 习题 469 | 470 | ### 展开 471 | 472 | 联合使用`reduce`方法和`concat`方法,将一个数组的数组“展开”成一个单个数组,包含原始数组的所有元素。 473 | 474 | ```js 475 | let arrays = [[1, 2, 3], [4, 5], [6]]; 476 | // Your code here. 477 | // → [1, 2, 3, 4, 5, 6] 478 | ``` 479 | 480 | ### 你自己的循环 481 | 482 | 编写一个高阶函数`loop`,提供类似`for`循环语句的东西。 它接受一个值,一个测试函数,一个更新函数和一个主体函数。 每次迭代中,它首先在当前循环值上运行测试函数,并在返回`false`时停止。 然后它调用主体函数,向其提供当前值。 最后,它调用`update`函数来创建一个新的值,并从头开始。 483 | 484 | 定义函数时,可以使用常规循环来执行实际循环。 485 | 486 | ```js 487 | // Your code here. 488 | 489 | loop(3, n => n > 0, n => n - 1, console.log); 490 | // → 3 491 | // → 2 492 | // → 1 493 | ``` 494 | 495 | ### `every` 496 | 497 | 类似于`some`方法,数组也有`every`方法。 当给定函数对数组中的每个元素返回`true`时,此函数返回`true`。 在某种程度上,`some`是作用于数组的`||`运算符的一个版本,`every`就像`&&`运算符。 498 | 499 | 将`every`实现为一个函数,接受一个数组和一个谓词函数作为参数。编写两个版本,一个使用循环,另一个使用`some`方法。 500 | 501 | ```js 502 | function every(array, test) { 503 | // Your code here. 504 | } 505 | 506 | console.log(every([1, 3, 5], n => n < 10)); 507 | // → true 508 | console.log(every([2, 4, 16], n => n < 10)); 509 | // → false 510 | console.log(every([], n => n < 10)); 511 | // → true 512 | ``` 513 | -------------------------------------------------------------------------------- /7.md: -------------------------------------------------------------------------------- 1 | # 七、项目:机器人 2 | 3 | > 原文:[Project: A Robot](http://eloquentjavascript.net/07_robot.html) 4 | > 5 | > 译者:[飞龙](https://github.com/wizardforcel) 6 | > 7 | > 协议:[CC BY-NC-SA 4.0](http://creativecommons.org/licenses/by-nc-sa/4.0/) 8 | > 9 | > 自豪地采用[谷歌翻译](https://translate.google.cn/) 10 | 11 | > [...] 置疑计算机能不能思考 [...] 就相当于置疑潜艇能不能游泳。 12 | > 13 | > 艾兹格尔·迪科斯特拉,《计算机科学的威胁》 14 | 15 | ![](img/7-0.jpg) 16 | 17 | 在“项目”章节中,我会在短时间内停止向你讲述新理论,相反我们会一起完成一个项目。 学习编程理论是必要的,但阅读和理解实际的计划同样重要。 18 | 19 | 我们在本章中的项目是构建一个自动机,一个在虚拟世界中执行任务的小程序。 我们的自动机将是一个接送包裹的邮件递送机器人。 20 | 21 | ## Meadowfield 22 | 23 | Meadowfield 村不是很大。 它由 11 个地点和 14 条道路组成。 它可以用`roads`数组来描述: 24 | 25 | ```js 26 | const roads = [ 27 | "Alice's House-Bob's House", "Alice's House-Cabin", 28 | "Alice's House-Post Office", "Bob's House-Town Hall", 29 | "Daria's House-Ernie's House", "Daria's House-Town Hall", 30 | "Ernie's House-Grete's House", "Grete's House-Farm", 31 | "Grete's House-Shop", "Marketplace-Farm", 32 | "Marketplace-Post Office", "Marketplace-Shop", 33 | "Marketplace-Town Hall", "Shop-Town Hall" 34 | ]; 35 | ``` 36 | 37 | ![](img/7-1.png) 38 | 39 | 村里的道路网络形成了一个图。 图是节点(村里的地点)与他们之间的边(道路)的集合。 这张图将成为我们的机器人在其中移动的世界。 40 | 41 | 字符串数组并不易于处理。 我们感兴趣的是,我们可以从特定地点到达的目的地。 让我们将道路列表转换为一个数据结构,对于每个地点,都会告诉我们从那里可以到达哪些地点。 42 | 43 | ```js 44 | function buildGraph(edges) { 45 | let graph = Object.create(null); 46 | function addEdge(from, to) { 47 | if (graph[from] == null) { 48 | graph[from] = [to]; 49 | } else { 50 | graph[from].push(to); 51 | } 52 | } 53 | for (let [from, to] of edges.map(r => r.split("-"))) { 54 | addEdge(from, to); 55 | addEdge(to, from); 56 | } 57 | return graph; 58 | } 59 | 60 | const roadGraph = buildGraph(roads); 61 | ``` 62 | 63 | 给定边的数组,`buildGraph`创建一个映射对象,该对象为每个节点存储连通节点的数组。 64 | 65 | 它使用`split`方法,将形式为`"Start-End"`的道路字符串,转换为两元素数组,包含起点和终点作为单个字符串。 66 | 67 | ## 任务 68 | 69 | 我们的机器人将在村庄周围移动。 在各个地方都有包裹,每个都寄往其他地方。 机器人在收到包裹时拾取包裹,并在抵达目的地时将其送达。 70 | 71 | 自动机必须在每个点决定下一步要去哪里。 所有包裹递送完成后,它就完成了任务。 72 | 73 | 为了能够模拟这个过程,我们必须定义一个可以描述它的虚拟世界。 这个模型告诉我们机器人在哪里以及包裹在哪里。 当机器人决定移到某处时,我们需要更新模型以反映新情况。 74 | 75 | 如果你正在考虑面向对象编程,你的第一个冲动可能是开始为世界中的各种元素定义对象。 一个机器人,一个包裹,也许还有一个地点。 然后,它们可以持有描述其当前状态的属性,例如某个位置的一堆包裹,我们可以在更新世界时改变这些属性。 76 | 77 | 这是错的。 78 | 79 | 至少,通常是这样。 一个东西听起来像一个对象,并不意味着它应该是你的程序中的一个对象。 为应用程序中的每个概念反射式编写类,往往会留下一系列互连对象,每个对象都有自己的内部的变化的状态。 这样的程序通常很难理解,因此很容易崩溃。 80 | 81 | 相反,让我们将村庄的状态压缩成定义它的值的最小集合。 机器人的当前位置和未送达的包裹集合,其中每个都拥有当前位置和目标地址。这样就够了。 82 | 83 | 当我们到达新地点时,让我们这样做,在机器人移动时不会改变这种状态,而是在移动之后为当前情况计算一个新状态。 84 | 85 | ```js 86 | class VillageState { 87 | constructor(place, parcels) { 88 | this.place = place; 89 | this.parcels = parcels; 90 | } 91 | 92 | move(destination) { 93 | if (!roadGraph[this.place].includes(destination)) { 94 | return this; 95 | } else { 96 | let parcels = this.parcels.map(p => { 97 | if (p.place != this.place) return p; 98 | return {place: destination, address: p.address}; 99 | }).filter(p => p.place != p.address); 100 | return new VillageState(destination, parcels); 101 | } 102 | } 103 | } 104 | ``` 105 | 106 | `move`方法是动作发生的地方。 它首先检查是否有当前位置到目的地的道路,如果没有,则返回旧状态,因为这不是有效的移动。 107 | 108 | 然后它创建一个新的状态,将目的地作为机器人的新地点。 但它也需要创建一套新的包裹 - 机器人携带的包裹(位于机器人当前位置)需要移动到新位置。 而要寄往新地点的包裹需要送达 - 也就是说,需要将它们从未送达的包裹中移除。 `'map'`的调用处理移动,并且`'filter'`的调用处理递送。 109 | 110 | 包裹对象在移动时不会更改,但会被重新创建。 `move`方法为我们提供新的村庄状态,但完全保留了原有的村庄状态。 111 | 112 | ```js 113 | let first = new VillageState( 114 | "Post Office", 115 | [{place: "Post Office", address: "Alice's House"}] 116 | ); 117 | let next = first.move("Alice's House"); 118 | 119 | console.log(next.place); 120 | // → Alice's House 121 | console.log(next.parcels); 122 | // → [] 123 | console.log(first.place); 124 | // → Post Office 125 | ``` 126 | 127 | `move`会使包裹被送达,并在下一个状态中反映出来。 但最初的状态仍然描述机器人在邮局并且包裹未送达的情况。 128 | 129 | ## 持久性数据 130 | 131 | 不会改变的数据结构称为不变的(immutable)或持久性的(persistent)。 他们的表现很像字符串和数字,因为他们就是他们自己,并保持这种状态,而不是在不同的时间包含不同的东西。 132 | 133 | 在 JavaScript 中,几乎所有的东西都可以改变,所以使用应该持久性的值需要一些限制。 有一个叫做`Object.freeze`的函数,它可以改变一个对象,使其忽略它的属性的写入。 如果你想要小心,你可以使用它来确保你的对象没有改变。 `freeze`确实需要计算机做一些额外的工作,忽略更新可能会让一些人迷惑,让他们做错事。 所以我通常更喜欢告诉人们,不应该弄乱给定的对象,并希望他们记住它。 134 | 135 | ```js 136 | let object = Object.freeze({value: 5}); 137 | object.value = 10; 138 | console.log(object.value); 139 | // → 5 140 | ``` 141 | 142 | 当语言显然期待我这样做时,为什么我不想改变对象? 143 | 144 | 因为它帮助我理解我的程序。 这又是关于复杂性管理。 当我的系统中的对象是固定的,稳定的东西时,我可以孤立地考虑操作它们 - 从给定的起始状态移动到爱丽丝的房子,始终会产生相同的新状态。 当对象随着时间而改变时,这就给这种推理增加了全新的复杂性。 145 | 146 | 对于小型系统,例如我们在本章中构建的东西,我们可以处理那些额外的复杂性。 但是我们可以建立什么样的系统,最重要的限制是我们能够理解多少。 任何让你的代码更容易理解的东西,都可以构建一个更加庞大的系统。 147 | 148 | 不幸的是,尽管理解构建在持久性数据结构上的系统比较容易,但设计一个,特别是当你的编程语言没有帮助时,可能会更难一些。 我们将在本书中寻找使用持久性数据结构的时机,但我们也将使用可变数据结构。 149 | 150 | ## 模拟 151 | 152 | 递送机器人观察世界并决定它想要移动的方向。 因此,我们可以说机器人是一个函数,接受`VillageState`对象并返回附近地点的名称。 153 | 154 | 因为我们希望机器人能够记住东西,以便他们可以制定和执行计划,我们也会传递他们的记忆,并让他们返回一个新的记忆。 因此,机器人返回的东西是一个对象,包含它想要移动的方向,以及下次调用时将返回给它的记忆值。 155 | 156 | ```js 157 | function runRobot(state, robot, memory) { 158 | for (let turn = 0;; turn++) { 159 | if (state.parcels.length == 0) { 160 | console.log(`Done in ${turn} turns`); 161 | break; 162 | } 163 | let action = robot(state, memory); 164 | state = state.move(action.direction); 165 | memory = action.memory; 166 | console.log(`Moved to ${action.direction}`); 167 | } 168 | } 169 | ``` 170 | 171 | 考虑一下机器人必须做些什么来“解决”一个给定的状态。 它必须通过访问拥有包裹的每个位置来拾取所有包裹,并通过访问包裹寄往的每个位置来递送,但只能在拾取包裹之后。 172 | 173 | 什么是可能有效的最愚蠢的策略? 机器人可以在每回合中,向随机方向行走。 这意味着很有可能它最终会碰到所有的包裹,然后也会在某个时候到达包裹应该送达的地方。 174 | 175 | 以下是可能的样子: 176 | 177 | ```js 178 | function randomPick(array) { 179 | let choice = Math.floor(Math.random() * array.length); 180 | return array[choice]; 181 | } 182 | 183 | function randomRobot(state) { 184 | return {direction: randomPick(roadGraph[state.place])}; 185 | } 186 | ``` 187 | 188 | 请记住,`Math.random()`返回 0 和 1 之间的数字,但总是小于 1。 将这样一个数乘以数组长度,然后将`Math.floor`应用于它,向我们提供数组的随机索引。 189 | 190 | 由于这个机器人不需要记住任何东西,所以它忽略了它的第二个参数(记住,可以使用额外的参数调用 JavaScript 函数而不会产生不良影响)并省略返回对象中的`memory`属性。 191 | 192 | 为了使这个复杂的机器人工作,我们首先需要一种方法来创建一些包裹的新状态。 静态方法(通过直接向构造函数添加一个属性来编写)是放置该功能的好地方。 193 | 194 | ```js 195 | VillageState.random = function(parcelCount = 5) { 196 | let parcels = []; 197 | for (let i = 0; i < parcelCount; i++) { 198 | let address = randomPick(Object.keys(roadGraph)); 199 | let place; 200 | do { 201 | place = randomPick(Object.keys(roadGraph)); 202 | } while (place == address); 203 | parcels.push({place, address}); 204 | } 205 | return new VillageState("Post Office", parcels); 206 | }; 207 | ``` 208 | 209 | 我们不想要发往寄出地的任何包裹。 出于这个原因,当`do`循环获取与地址相同的地方时,它会继续选择新的地方。 210 | 211 | 让我们建立一个虚拟世界。 212 | 213 | ```js 214 | runRobot(VillageState.random(), randomRobot); 215 | // → Moved to Marketplace 216 | // → Moved to Town Hall 217 | // → … 218 | // → Done in 63 turns 219 | ``` 220 | 221 | 机器人需要花费很多时间来交付包裹,因为它没有很好规划。 我们很快就会解决。 222 | 223 | 为了更好地理解模拟,你可以使用本章编程环境中提供的`runRobotAnimation`函数。 这将运行模拟,但不是输出文本,而是向你展示机器人在村庄地图上移动。 224 | 225 | ```js 226 | runRobotAnimation(VillageState.random(), randomRobot); 227 | ``` 228 | 229 | `runRobotAnimation`的实现方式现在仍然是一个谜,但是在阅读本书的后面的章节,讨论 Web 浏览器中的 JavaScript 集成之后,你将能够猜到它的工作原理。 230 | 231 | ## 邮车的路线 232 | 233 | 我们应该能够比随机机器人做得更好。 一个简单的改进就是从现实世界的邮件传递方式中获得提示。 如果我们发现一条经过村庄所有地点的路线,机器人可以通行该路线两次,此时它保证能够完成。 这是一条这样的路线(从邮局开始)。 234 | 235 | ```js 236 | const mailRoute = [ 237 | "Alice's House", "Cabin", "Alice's House", "Bob's House", 238 | "Town Hall", "Daria's House", "Ernie's House", 239 | "Grete's House", "Shop", "Grete's House", "Farm", 240 | "Marketplace", "Post Office" 241 | ]; 242 | ``` 243 | 244 | 为了实现路线跟踪机器人,我们需要利用机器人的记忆。 机器人将其路线的其余部分保存在其记忆中,并且每回合丢弃第一个元素。 245 | 246 | ```js 247 | function routeRobot(state, memory) { 248 | if (memory.length == 0) { 249 | memory = mailRoute; 250 | } 251 | return {direction: memory[0], memory: memory.slice(1)}; 252 | } 253 | ``` 254 | 255 | 这个机器人已经快了很多。 它最多需要 26 个回合(13 步的路线的两倍),但通常要少一些。 256 | 257 | ```js 258 | runRobotAnimation(VillageState.random(), routeRobot, []); 259 | ``` 260 | 261 | ## 寻路 262 | 263 | 不过,我不会盲目遵循固定的智能寻路行为。 如果机器人为需要完成的实际工作调整行为,它可以更高效地工作。 264 | 265 | 为此,它必须能够有针对性地朝着给定的包裹移动,或者朝着包裹必须送达的地点。 尽管如此,即使目标距离我们不止一步,也需要某种寻路函数。 266 | 267 | 在图上寻找路线的问题是一个典型的搜索问题。 我们可以判断一个给定的解决方案(路线)是否是一个有效的解决方案,但我们不能像 2 + 2 这样,直接计算解决方案。 相反,我们必须不断创建潜在的解决方案,直到找到有效的解决方案。 268 | 269 | 图上的可能路线是无限的。 但是当搜索`A`到`B`的路线时,我们只关注从`A`起始的路线。 我们也不关心两次访问同一地点的路线 - 这绝对不是最有效的路线。 这样可以减少查找者必须考虑的路线数量。 270 | 271 | 事实上,我们最感兴趣的是最短路线。 所以我们要确保,查看较长路线之前,我们要查看较短的路线。 一个好的方法是,从起点使路线“生长”,探索尚未到达的每个可到达的地方,直到路线到达目标。 这样,我们只探索潜在的有趣路线,并找到到目标的最短路线(或最短路线之一,如果有多条路线)。 272 | 273 | 这是一个实现它的函数: 274 | 275 | ```js 276 | function findRoute(graph, from, to) { 277 | let work = [{at: from, route: []}]; 278 | for (let i = 0; i < work.length; i++) { 279 | let {at, route} = work[i]; 280 | for (let place of graph[at]) { 281 | if (place == to) return route.concat(place); 282 | if (!work.some(w => w.at == place)) { 283 | work.push({at: place, route: route.concat(place)}); 284 | } 285 | } 286 | } 287 | } 288 | ``` 289 | 290 | 探索必须按照正确的顺序完成 - 首先到达的地方必须首先探索。 我们不能到达一个地方就立即探索,因为那样意味着,从那里到达的地方也会被立即探索,以此类推,尽管可能还有其他更短的路径尚未被探索。 291 | 292 | 因此,该函数保留一个工作列表。 这是一系列应该探索的地方,以及让我们到那里的路线。 它最开始只有起始位置和空路线。 293 | 294 | 然后,通过获取列表中的下一个项目并进行探索,来执行搜索,这意味着,会查看从该地点起始的所有道路。 如果其中之一是目标,则可以返回完成的路线。 否则,如果我们以前没有看过这个地方,就会在列表中添加一个新项目。 如果我们之前看过它,因为我们首先查看了短路线,我们发现,到达那个地方的路线较长,或者与现有路线一样长,我们不需要探索它。 295 | 296 | 你可以在视觉上将它想象成一个已知路线的网,从起始位置爬出来,在各个方向上均匀生长(但不会缠绕回去)。 只要第一条线到达目标位置,其它线就会退回起点,为我们提供路线。 297 | 298 | 我们的代码无法处理工作列表中没有更多工作项的情况,因为我们知道我们的图是连通的,这意味着可以从其他所有位置访问每个位置。 我们始终能够找到两点之间的路线,并且搜索不会失败。 299 | 300 | ```js 301 | function goalOrientedRobot({place, parcels}, route) { 302 | if (route.length == 0) { 303 | let parcel = parcels[0]; 304 | if (parcel.place != place) { 305 | route = findRoute(roadGraph, place, parcel.place); 306 | } else { 307 | route = findRoute(roadGraph, place, parcel.address); 308 | } 309 | } 310 | return {direction: route[0], memory: route.slice(1)}; 311 | } 312 | ``` 313 | 314 | 这个机器人使用它的记忆值作为移动方向的列表,就像寻路机器人一样。 无论什么时候这个列表是空的,它都必须弄清下一步该做什么。 它会取出集合中第一个未送达的包裹,如果该包裹还没有被拾取,则会绘制一条朝向它的路线。 如果包裹已经被拾取,它仍然需要送达,所以机器人会创建一个朝向递送地址的路线。 315 | 316 | 让我们看看如何实现。 317 | 318 | ```js 319 | runRobotAnimation(VillageState.random(), 320 | goalOrientedRobot, []); 321 | ``` 322 | 323 | 这个机器人通常在大约 16 个回合中,完成了送达 5 个包裹的任务。 略好于`routeRobot`,但仍然绝对不是最优的。 324 | 325 | ## 练习 326 | 327 | ### 测量机器人 328 | 329 | 很难通过让机器人解决一些场景来客观比较他们。 也许一个机器人碰巧得到了更简单的任务,或者它擅长的那种任务,而另一个没有。 330 | 331 | 编写一个`compareRobots`,接受两个机器人(和它们的起始记忆)。 它应该生成 100 个任务,并让每个机器人解决每个这些任务。 完成后,它应输出每个机器人每个任务的平均步数。 332 | 333 | 为了公平起见,请确保你将每个任务分配给两个机器人,而不是为每个机器人生成不同的任务。 334 | 335 | ```js 336 | function compareRobots(robot1, memory1, robot2, memory2) { 337 | // Your code here 338 | } 339 | 340 | compareRobots(routeRobot, [], goalOrientedRobot, []); 341 | ``` 342 | 343 | ### 机器人的效率 344 | 345 | 你能写一个机器人,比`goalOrientedRobot`更快完成递送任务吗? 如果你观察机器人的行为,它会做什么明显愚蠢的事情?如何改进它们? 346 | 347 | 如果你解决了上一个练习,你可能打算使用`compareRobots`函数来验证你是否改进了机器人。 348 | 349 | ```js 350 | // Your code here 351 | 352 | runRobotAnimation(VillageState.random(), yourRobot, memory); 353 | ``` 354 | 355 | ### 持久性分组 356 | 357 | 标准 JavaScript 环境中提供的大多数数据结构不太适合持久使用。 数组有`slice`和`concat`方法,可以让我们轻松创建新的数组而不会损坏旧数组。 但是`Set`没有添加或删除项目并创建新集合的方法。 358 | 359 | 编写一个新的类`PGroup`,类似于第六章中的`Group`类,它存储一组值。 像`Group`一样,它具有`add`,`delete`和`has`方法。 360 | 361 | 然而,它的`add`方法应该返回一个新的`PGroup`实例,并添加给定的成员,并保持旧的不变。 与之类似,`delete`创建一个没有给定成员的新实例。 362 | 363 | 该类应该适用于任何类型的值,而不仅仅是字符串。 当与大量值一起使用时,它不一定非常高效。 364 | 365 | 构造函数不应该是类接口的一部分(尽管你绝对会打算在内部使用它)。 相反,有一个空的实例`PGroup.empty`,可用作起始值。 366 | 367 | 为什么只需要一个`PGroup.empty`值,而不是每次都创建一个新的空分组? 368 | 369 | ```js 370 | class PGroup { 371 | // Your code here 372 | } 373 | 374 | let a = PGroup.empty.add("a"); 375 | let ab = a.add("b"); 376 | let b = ab.delete("a"); 377 | 378 | console.log(b.has("b")); 379 | // → true 380 | console.log(a.has("b")); 381 | // → false 382 | console.log(b.has("a")); 383 | // → false 384 | ``` 385 | -------------------------------------------------------------------------------- /CNAME: -------------------------------------------------------------------------------- 1 | eloquent-js.apachecn.org -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM httpd:2.4 2 | COPY ./ /usr/local/apache2/htdocs/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Public License (CC BY-NC-SA 4.0) 2 | 3 | Copyright © 2020 ApacheCN(apachecn@163.com) 4 | 5 | By exercising the Licensed Rights (defined below), You accept and agree to be bound by the terms and conditions of this Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Public License ("Public License"). To the extent this Public License may be interpreted as a contract, You are granted the Licensed Rights in consideration of Your acceptance of these terms and conditions, and the Licensor grants You such rights in consideration of benefits the Licensor receives from making the Licensed Material available under these terms and conditions. 6 | 7 | Section 1 – Definitions. 8 | 9 | a. Adapted Material means material subject to Copyright and Similar Rights that is derived from or based upon the Licensed Material and in which the Licensed Material is translated, altered, arranged, transformed, or otherwise modified in a manner requiring permission under the Copyright and Similar Rights held by the Licensor. For purposes of this Public License, where the Licensed Material is a musical work, performance, or sound recording, Adapted Material is always produced where the Licensed Material is synched in timed relation with a moving image. 10 | b. Adapter's License means the license You apply to Your Copyright and Similar Rights in Your contributions to Adapted Material in accordance with the terms and conditions of this Public License. 11 | c. BY-NC-SA Compatible License means a license listed at creativecommons.org/compatiblelicenses, approved by Creative Commons as essentially the equivalent of this Public License. 12 | d. Copyright and Similar Rights means copyright and/or similar rights closely related to copyright including, without limitation, performance, broadcast, sound recording, and Sui Generis Database Rights, without regard to how the rights are labeled or categorized. For purposes of this Public License, the rights specified in Section 2(b)(1)-(2) are not Copyright and Similar Rights. 13 | e. Effective Technological Measures means those measures that, in the absence of proper authority, may not be circumvented under laws fulfilling obligations under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996, and/or similar international agreements. 14 | f. Exceptions and Limitations means fair use, fair dealing, and/or any other exception or limitation to Copyright and Similar Rights that applies to Your use of the Licensed Material. 15 | g. License Elements means the license attributes listed in the name of a Creative Commons Public License. The License Elements of this Public License are Attribution, NonCommercial, and ShareAlike. 16 | h. Licensed Material means the artistic or literary work, database, or other material to which the Licensor applied this Public License. 17 | i. Licensed Rights means the rights granted to You subject to the terms and conditions of this Public License, which are limited to all Copyright and Similar Rights that apply to Your use of the Licensed Material and that the Licensor has authority to license. 18 | j. Licensor means the individual(s) or entity(ies) granting rights under this Public License. 19 | k. NonCommercial means not primarily intended for or directed towards commercial advantage or monetary compensation. For purposes of this Public License, the exchange of the Licensed Material for other material subject to Copyright and Similar Rights by digital file-sharing or similar means is NonCommercial provided there is no payment of monetary compensation in connection with the exchange. 20 | l. Share means to provide material to the public by any means or process that requires permission under the Licensed Rights, such as reproduction, public display, public performance, distribution, dissemination, communication, or importation, and to make material available to the public including in ways that members of the public may access the material from a place and at a time individually chosen by them. 21 | m. Sui Generis Database Rights means rights other than copyright resulting from Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, as amended and/or succeeded, as well as other essentially equivalent rights anywhere in the world. 22 | n. You means the individual or entity exercising the Licensed Rights under this Public License. Your has a corresponding meaning. 23 | 24 | Section 2 – Scope. 25 | 26 | a. License grant. 27 | 1. Subject to the terms and conditions of this Public License, the Licensor hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive, irrevocable license to exercise the Licensed Rights in the Licensed Material to: 28 | A. reproduce and Share the Licensed Material, in whole or in part, for NonCommercial purposes only; and 29 | B. produce, reproduce, and Share Adapted Material for NonCommercial purposes only. 30 | 2. Exceptions and Limitations. For the avoidance of doubt, where Exceptions and Limitations apply to Your use, this Public License does not apply, and You do not need to comply with its terms and conditions. 31 | 3. Term. The term of this Public License is specified in Section 6(a). 32 | 4. Media and formats; technical modifications allowed. The Licensor authorizes You to exercise the Licensed Rights in all media and formats whether now known or hereafter created, and to make technical modifications necessary to do so. The Licensor waives and/or agrees not to assert any right or authority to forbid You from making technical modifications necessary to exercise the Licensed Rights, including technical modifications necessary to circumvent Effective Technological Measures. For purposes of this Public License, simply making modifications authorized by this Section 2(a)(4) never produces Adapted Material. 33 | 5. Downstream recipients. 34 | A. Offer from the Licensor – Licensed Material. Every recipient of the Licensed Material automatically receives an offer from the Licensor to exercise the Licensed Rights under the terms and conditions of this Public License. 35 | B. Additional offer from the Licensor – Adapted Material. Every recipient of Adapted Material from You automatically receives an offer from the Licensor to exercise the Licensed Rights in the Adapted Material under the conditions of the Adapter’s License You apply. 36 | C. No downstream restrictions. You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, the Licensed Material if doing so restricts exercise of the Licensed Rights by any recipient of the Licensed Material. 37 | 6. No endorsement. Nothing in this Public License constitutes or may be construed as permission to assert or imply that You are, or that Your use of the Licensed Material is, connected with, or sponsored, endorsed, or granted official status by, the Licensor or others designated to receive attribution as provided in Section 3(a)(1)(A)(i). 38 | b. Other rights. 39 | 1. Moral rights, such as the right of integrity, are not licensed under this Public License, nor are publicity, privacy, and/or other similar personality rights; however, to the extent possible, the Licensor waives and/or agrees not to assert any such rights held by the Licensor to the limited extent necessary to allow You to exercise the Licensed Rights, but not otherwise. 40 | 2. Patent and trademark rights are not licensed under this Public License. 41 | 3. To the extent possible, the Licensor waives any right to collect royalties from You for the exercise of the Licensed Rights, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases the Licensor expressly reserves any right to collect such royalties, including when the Licensed Material is used other than for NonCommercial purposes. 42 | 43 | Section 3 – License Conditions. 44 | 45 | Your exercise of the Licensed Rights is expressly made subject to the following conditions. 46 | 47 | a. Attribution. 48 | 1. If You Share the Licensed Material (including in modified form), You must: 49 | A. retain the following if it is supplied by the Licensor with the Licensed Material: 50 | i. identification of the creator(s) of the Licensed Material and any others designated to receive attribution, in any reasonable manner requested by the Licensor (including by pseudonym if designated); 51 | ii. a copyright notice; 52 | iii. a notice that refers to this Public License; 53 | iv. a notice that refers to the disclaimer of warranties; 54 | v. a URI or hyperlink to the Licensed Material to the extent reasonably practicable; 55 | B. indicate if You modified the Licensed Material and retain an indication of any previous modifications; and 56 | C. indicate the Licensed Material is licensed under this Public License, and include the text of, or the URI or hyperlink to, this Public License. 57 | 2. You may satisfy the conditions in Section 3(a)(1) in any reasonable manner based on the medium, means, and context in which You Share the Licensed Material. For example, it may be reasonable to satisfy the conditions by providing a URI or hyperlink to a resource that includes the required information. 58 | 3. If requested by the Licensor, You must remove any of the information required by Section 3(a)(1)(A) to the extent reasonably practicable. 59 | b. ShareAlike. 60 | In addition to the conditions in Section 3(a), if You Share Adapted Material You produce, the following conditions also apply. 61 | 1. The Adapter’s License You apply must be a Creative Commons license with the same License Elements, this version or later, or a BY-NC-SA Compatible License. 62 | 2. You must include the text of, or the URI or hyperlink to, the Adapter's License You apply. You may satisfy this condition in any reasonable manner based on the medium, means, and context in which You Share Adapted Material. 63 | 3. You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, Adapted Material that restrict exercise of the rights granted under the Adapter's License You apply. 64 | 65 | Section 4 – Sui Generis Database Rights. 66 | 67 | Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material: 68 | 69 | a. for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, reuse, reproduce, and Share all or a substantial portion of the contents of the database for NonCommercial purposes only; 70 | b. if You include all or a substantial portion of the database contents in a database in which You have Sui Generis Database Rights, then the database in which You have Sui Generis Database Rights (but not its individual contents) is Adapted Material, including for purposes of Section 3(b); and 71 | c. You must comply with the conditions in Section 3(a) if You Share all or a substantial portion of the contents of the database. 72 | 73 | For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this Public License where the Licensed Rights include other Copyright and Similar Rights. 74 | 75 | Section 5 – Disclaimer of Warranties and Limitation of Liability. 76 | 77 | a. Unless otherwise separately undertaken by the Licensor, to the extent possible, the Licensor offers the Licensed Material as-is and as-available, and makes no representations or warranties of any kind concerning the Licensed Material, whether express, implied, statutory, or other. This includes, without limitation, warranties of title, merchantability, fitness for a particular purpose, non-infringement, absence of latent or other defects, accuracy, or the presence or absence of errors, whether or not known or discoverable. Where disclaimers of warranties are not allowed in full or in part, this disclaimer may not apply to You. 78 | b. To the extent possible, in no event will the Licensor be liable to You on any legal theory (including, without limitation, negligence) or otherwise for any direct, special, indirect, incidental, consequential, punitive, exemplary, or other losses, costs, expenses, or damages arising out of this Public License or use of the Licensed Material, even if the Licensor has been advised of the possibility of such losses, costs, expenses, or damages. Where a limitation of liability is not allowed in full or in part, this limitation may not apply to You. 79 | c. The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability. 80 | 81 | Section 6 – Term and Termination. 82 | 83 | a. This Public License applies for the term of the Copyright and Similar Rights licensed here. However, if You fail to comply with this Public License, then Your rights under this Public License terminate automatically. 84 | b. Where Your right to use the Licensed Material has terminated under Section 6(a), it reinstates: 85 | 1. automatically as of the date the violation is cured, provided it is cured within 30 days of Your discovery of the violation; or 86 | 2. upon express reinstatement by the Licensor. 87 | For the avoidance of doubt, this Section 6(b) does not affect any right the Licensor may have to seek remedies for Your violations of this Public License. 88 | c. For the avoidance of doubt, the Licensor may also offer the Licensed Material under separate terms or conditions or stop distributing the Licensed Material at any time; however, doing so will not terminate this Public License. 89 | d. Sections 1, 5, 6, 7, and 8 survive termination of this Public License. 90 | 91 | Section 7 – Other Terms and Conditions. 92 | 93 | a. The Licensor shall not be bound by any additional or different terms or conditions communicated by You unless expressly agreed. 94 | b. Any arrangements, understandings, or agreements regarding the Licensed Material not stated herein are separate from and independent of the terms and conditions of this Public License. 95 | 96 | Section 8 – Interpretation. 97 | 98 | a. For the avoidance of doubt, this Public License does not, and shall not be interpreted to, reduce, limit, restrict, or impose conditions on any use of the Licensed Material that could lawfully be made without permission under this Public License. 99 | b. To the extent possible, if any provision of this Public License is deemed unenforceable, it shall be automatically reformed to the minimum extent necessary to make it enforceable. If the provision cannot be reformed, it shall be severed from this Public License without affecting the enforceability of the remaining terms and conditions. 100 | c. No term or condition of this Public License will be waived and no failure to comply consented to unless expressly agreed to by the Licensor. 101 | d. Nothing in this Public License constitutes or may be interpreted as a limitation upon, or waiver of, any privileges and immunities that apply to the Licensor or You, including from the legal processes of any jurisdiction or authority. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JavaScript 编程精解 中文第三版 2 | 3 | 原书:[Eloquent JavaScript 3rd edition](http://eloquentjavascript.net/) 4 | 5 | 译者:[飞龙](https://github.com/wizardforcel) 6 | 7 | 自豪地采用[谷歌翻译](https://translate.google.cn/) 8 | 9 | 部分参考了[《JavaScript 编程精解(第 2 版)》](https://book.douban.com/subject/26707144/) 10 | 11 | + [在线阅读](https://eloquent-js.apachecn.org) 12 | + [在线阅读(Gitee)](https://apachecn.gitee.io/eloquent-js-3e-zh/) 13 | + [PDF格式](https://www.gitbook.com/download/pdf/book/wizardforcel/eloquent-js-3e) 14 | + [EPUB格式](https://www.gitbook.com/download/epub/book/wizardforcel/eloquent-js-3e) 15 | + [MOBI格式](https://www.gitbook.com/download/mobi/book/wizardforcel/eloquent-js-3e) 16 | + [代码仓库](https://github.com/wizardforcel/eloquent-js-3e-zh) 17 | 18 | 19 | ## 下载 20 | 21 | ### Docker 22 | 23 | ``` 24 | docker pull apachecn0/eloquent-js-3e-zh 25 | docker run -tid -p <port>:80 apachecn0/eloquent-js-3e-zh 26 | # 访问 http://localhost:{port} 查看文档 27 | ``` 28 | 29 | ### PYPI 30 | 31 | ``` 32 | pip install eloquent-js-3e-zh 33 | eloquent-js-3e-zh <port> 34 | # 访问 http://localhost:{port} 查看文档 35 | ``` 36 | 37 | ## 赞助我 38 | 39 | ![](img/qr_alipay.png) 40 | 41 | ## 协议 42 | 43 | [CC BY-NC-SA 4.0](http://creativecommons.org/licenses/by-nc-sa/4.0/) 44 | -------------------------------------------------------------------------------- /SUMMARY.md: -------------------------------------------------------------------------------- 1 | + [JavaScript 编程精解 中文第三版](README.md) 2 | + [零、前言](0.md) 3 | + [一、值,类型和运算符](1.md) 4 | + [二、程序结构](2.md) 5 | + [三、函数](3.md) 6 | + [四、数据结构:对象和数组](4.md) 7 | + [五、高阶函数](5.md) 8 | + [六、对象的秘密](6.md) 9 | + [七、项目:机器人](7.md) 10 | + [八、Bug 和错误](8.md) 11 | + [九、正则表达式](9.md) 12 | + [十、模块](10.md) 13 | + [十一、异步编程](11.md) 14 | + [十二、项目:编程语言](12.md) 15 | + [十三、浏览器中的 JavaScript](13.md) 16 | + [十四、文档对象模型](14.md) 17 | + [十五、处理事件](15.md) 18 | + [十六、项目:平台游戏](16.md) 19 | + [十七、在画布上绘图](17.md) 20 | + [十八、HTTP 和表单](18.md) 21 | + [十九、项目:像素艺术编辑器](19.md) 22 | + [二十、Node.js](20.md) 23 | + [二十一、项目:技能分享网站](21.md) -------------------------------------------------------------------------------- /asset/docsify-apachecn-footer.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | var footer = [ 3 | '<hr/>', 4 | '<div align="center">', 5 | ' <p><a href="http://www.apachecn.org/" target="_blank"><font face="KaiTi" size="6" color="red">我们一直在努力</font></a><p>', 6 | ' <p><a href="https://github.com/apachecn/eloquent-js-3e-zh/" target="_blank">apachecn/eloquent-js-3e-zh</a></p>', 7 | ' <p><iframe align="middle" src="https://ghbtns.com/github-btn.html?user=apachecn&repo=eloquent-js-3e-zh&type=watch&count=true&v=2" frameborder="0" scrolling="0" width="100px" height="25px"></iframe>', 8 | ' <iframe align="middle" src="https://ghbtns.com/github-btn.html?user=apachecn&repo=eloquent-js-3e-zh&type=star&count=true" frameborder="0" scrolling="0" width="100px" height="25px"></iframe>', 9 | ' <iframe align="middle" src="https://ghbtns.com/github-btn.html?user=apachecn&repo=eloquent-js-3e-zh&type=fork&count=true" frameborder="0" scrolling="0" width="100px" height="25px"></iframe>', 10 | ' <a target="_blank" href="//shang.qq.com/wpa/qunwpa?idkey=bcee938030cc9e1552deb3bd9617bbbf62d3ec1647e4b60d9cd6b6e8f78ddc03"><img border="0" src="//pub.idqqimg.com/wpa/images/group.png" alt="ML | ApacheCN" title="ML | ApacheCN"></a></p>', 11 | ' <p><span id="cnzz_stat_icon_1275211409"></span></p>', 12 | ' <div style="text-align:center;margin:0 0 10.5px;">', 13 | ' <ins class="adsbygoogle"', 14 | ' style="display:inline-block;width:728px;height:90px"', 15 | ' data-ad-client="ca-pub-3565452474788507"', 16 | ' data-ad-slot="2543897000"></ins>', 17 | ' </div>', 18 | '</div>' 19 | ].join('\n') 20 | var plugin = function(hook) { 21 | hook.afterEach(function(html) { 22 | return html + footer 23 | }) 24 | hook.doneEach(function() { 25 | (adsbygoogle = window.adsbygoogle || []).push({}) 26 | }) 27 | } 28 | var plugins = window.$docsify.plugins || [] 29 | plugins.push(plugin) 30 | window.$docsify.plugins = plugins 31 | })() -------------------------------------------------------------------------------- /asset/docsify-baidu-push.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | var plugin = function(hook) { 3 | hook.doneEach(function() { 4 | new Image().src = 5 | '//api.share.baidu.com/s.gif?r=' + 6 | encodeURIComponent(document.referrer) + 7 | "&l=" + encodeURIComponent(location.href) 8 | }) 9 | } 10 | var plugins = window.$docsify.plugins || [] 11 | plugins.push(plugin) 12 | window.$docsify.plugins = plugins 13 | })() -------------------------------------------------------------------------------- /asset/docsify-baidu-stat.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | var plugin = function(hook) { 3 | hook.doneEach(function() { 4 | window._hmt = window._hmt || [] 5 | var hm = document.createElement("script") 6 | hm.src = "https://hm.baidu.com/hm.js?" + window.$docsify.bdStatId 7 | document.querySelector("article").appendChild(hm) 8 | }) 9 | } 10 | var plugins = window.$docsify.plugins || [] 11 | plugins.push(plugin) 12 | window.$docsify.plugins = plugins 13 | })() -------------------------------------------------------------------------------- /asset/docsify-cnzz.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | var plugin = function(hook) { 3 | hook.doneEach(function() { 4 | var sc = document.createElement('script') 5 | sc.src = 'https://s5.cnzz.com/z_stat.php?id=' + 6 | window.$docsify.cnzzId + '&online=1&show=line' 7 | document.querySelector('article').appendChild(sc) 8 | }) 9 | } 10 | var plugins = window.$docsify.plugins || [] 11 | plugins.push(plugin) 12 | window.$docsify.plugins = plugins 13 | })() -------------------------------------------------------------------------------- /asset/docsify-copy-code.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * docsify-copy-code 3 | * v2.1.0 4 | * https://github.com/jperasmus/docsify-copy-code 5 | * (c) 2017-2019 JP Erasmus <jperasmus11@gmail.com> 6 | * MIT license 7 | */ 8 | !function(){"use strict";function r(o){return(r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(o){return typeof o}:function(o){return o&&"function"==typeof Symbol&&o.constructor===Symbol&&o!==Symbol.prototype?"symbol":typeof o})(o)}!function(o,e){void 0===e&&(e={});var t=e.insertAt;if(o&&"undefined"!=typeof document){var n=document.head||document.getElementsByTagName("head")[0],c=document.createElement("style");c.type="text/css","top"===t&&n.firstChild?n.insertBefore(c,n.firstChild):n.appendChild(c),c.styleSheet?c.styleSheet.cssText=o:c.appendChild(document.createTextNode(o))}}(".docsify-copy-code-button,.docsify-copy-code-button span{cursor:pointer;transition:all .25s ease}.docsify-copy-code-button{position:absolute;z-index:1;top:0;right:0;overflow:visible;padding:.65em .8em;border:0;border-radius:0;outline:0;font-size:1em;background:grey;background:var(--theme-color,grey);color:#fff;opacity:0}.docsify-copy-code-button span{border-radius:3px;background:inherit;pointer-events:none}.docsify-copy-code-button .error,.docsify-copy-code-button .success{position:absolute;z-index:-100;top:50%;left:0;padding:.5em .65em;font-size:.825em;opacity:0;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.docsify-copy-code-button.error .error,.docsify-copy-code-button.success .success{opacity:1;-webkit-transform:translate(-115%,-50%);transform:translate(-115%,-50%)}.docsify-copy-code-button:focus,pre:hover .docsify-copy-code-button{opacity:1}"),document.querySelector('link[href*="docsify-copy-code"]')&&console.warn("[Deprecation] Link to external docsify-copy-code stylesheet is no longer necessary."),window.DocsifyCopyCodePlugin={init:function(){return function(o,e){o.ready(function(){console.warn("[Deprecation] Manually initializing docsify-copy-code using window.DocsifyCopyCodePlugin.init() is no longer necessary.")})}}},window.$docsify=window.$docsify||{},window.$docsify.plugins=[function(o,s){o.doneEach(function(){var o=Array.apply(null,document.querySelectorAll("pre[data-lang]")),c={buttonText:"Copy to clipboard",errorText:"Error",successText:"Copied"};s.config.copyCode&&Object.keys(c).forEach(function(t){var n=s.config.copyCode[t];"string"==typeof n?c[t]=n:"object"===r(n)&&Object.keys(n).some(function(o){var e=-1<location.href.indexOf(o);return c[t]=e?n[o]:c[t],e})});var e=['<button class="docsify-copy-code-button">','<span class="label">'.concat(c.buttonText,"</span>"),'<span class="error">'.concat(c.errorText,"</span>"),'<span class="success">'.concat(c.successText,"</span>"),"</button>"].join("");o.forEach(function(o){o.insertAdjacentHTML("beforeend",e)})}),o.mounted(function(){document.querySelector(".content").addEventListener("click",function(o){if(o.target.classList.contains("docsify-copy-code-button")){var e="BUTTON"===o.target.tagName?o.target:o.target.parentNode,t=document.createRange(),n=e.parentNode.querySelector("code"),c=window.getSelection();t.selectNode(n),c.removeAllRanges(),c.addRange(t);try{document.execCommand("copy")&&(e.classList.add("success"),setTimeout(function(){e.classList.remove("success")},1e3))}catch(o){console.error("docsify-copy-code: ".concat(o)),e.classList.add("error"),setTimeout(function(){e.classList.remove("error")},1e3)}"function"==typeof(c=window.getSelection()).removeRange?c.removeRange(t):"function"==typeof c.removeAllRanges&&c.removeAllRanges()}})})}].concat(window.$docsify.plugins||[])}(); 9 | //# sourceMappingURL=docsify-copy-code.min.js.map 10 | -------------------------------------------------------------------------------- /asset/prism-darcula.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Darcula theme 3 | * 4 | * Adapted from a theme based on: 5 | * IntelliJ Darcula Theme (https://github.com/bulenkov/Darcula) 6 | * 7 | * @author Alexandre Paradis <service.paradis@gmail.com> 8 | * @version 1.0 9 | */ 10 | 11 | code[class*="lang-"], 12 | pre[data-lang] { 13 | color: #a9b7c6 !important; 14 | background-color: #2b2b2b !important; 15 | font-family: Consolas, Monaco, 'Andale Mono', monospace; 16 | direction: ltr; 17 | text-align: left; 18 | white-space: pre; 19 | word-spacing: normal; 20 | word-break: normal; 21 | line-height: 1.5; 22 | 23 | -moz-tab-size: 4; 24 | -o-tab-size: 4; 25 | tab-size: 4; 26 | 27 | -webkit-hyphens: none; 28 | -moz-hyphens: none; 29 | -ms-hyphens: none; 30 | hyphens: none; 31 | } 32 | 33 | pre[data-lang]::-moz-selection, pre[data-lang] ::-moz-selection, 34 | code[class*="lang-"]::-moz-selection, code[class*="lang-"] ::-moz-selection { 35 | color: inherit; 36 | background: rgba(33, 66, 131, .85); 37 | } 38 | 39 | pre[data-lang]::selection, pre[data-lang] ::selection, 40 | code[class*="lang-"]::selection, code[class*="lang-"] ::selection { 41 | color: inherit; 42 | background: rgba(33, 66, 131, .85); 43 | } 44 | 45 | /* Code blocks */ 46 | pre[data-lang] { 47 | padding: 1em; 48 | margin: .5em 0; 49 | overflow: auto; 50 | } 51 | 52 | :not(pre) > code[class*="lang-"], 53 | pre[data-lang] { 54 | background: #2b2b2b; 55 | } 56 | 57 | /* Inline code */ 58 | :not(pre) > code[class*="lang-"] { 59 | padding: .1em; 60 | border-radius: .3em; 61 | } 62 | 63 | .token.comment, 64 | .token.prolog, 65 | .token.cdata { 66 | color: #808080; 67 | } 68 | 69 | .token.delimiter, 70 | .token.boolean, 71 | .token.keyword, 72 | .token.selector, 73 | .token.important, 74 | .token.atrule { 75 | color: #cc7832; 76 | } 77 | 78 | .token.operator, 79 | .token.punctuation, 80 | .token.attr-name { 81 | color: #a9b7c6; 82 | } 83 | 84 | .token.tag, 85 | .token.tag .punctuation, 86 | .token.doctype, 87 | .token.builtin { 88 | color: #e8bf6a; 89 | } 90 | 91 | .token.entity, 92 | .token.number, 93 | .token.symbol { 94 | color: #6897bb; 95 | } 96 | 97 | .token.property, 98 | .token.constant, 99 | .token.variable { 100 | color: #9876aa; 101 | } 102 | 103 | .token.string, 104 | .token.char { 105 | color: #6a8759; 106 | } 107 | 108 | .token.attr-value, 109 | .token.attr-value .punctuation { 110 | color: #a5c261; 111 | } 112 | 113 | .token.attr-value .punctuation:first-child { 114 | color: #a9b7c6; 115 | } 116 | 117 | .token.url { 118 | color: #287bde; 119 | text-decoration: underline; 120 | } 121 | 122 | .token.function { 123 | color: #ffc66d; 124 | } 125 | 126 | .token.regex { 127 | background: #364135; 128 | } 129 | 130 | .token.bold { 131 | font-weight: bold; 132 | } 133 | 134 | .token.italic { 135 | font-style: italic; 136 | } 137 | 138 | .token.inserted { 139 | background: #294436; 140 | } 141 | 142 | .token.deleted { 143 | background: #484a4a; 144 | } 145 | 146 | code.lang-css .token.property, 147 | code.lang-css .token.property + .token.punctuation { 148 | color: #a9b7c6; 149 | } 150 | 151 | code.lang-css .token.id { 152 | color: #ffc66d; 153 | } 154 | 155 | code.lang-css .token.selector > .token.class, 156 | code.lang-css .token.selector > .token.attribute, 157 | code.lang-css .token.selector > .token.pseudo-class, 158 | code.lang-css .token.selector > .token.pseudo-element { 159 | color: #ffc66d; 160 | } -------------------------------------------------------------------------------- /asset/prism-javascript.min.js: -------------------------------------------------------------------------------- 1 | Prism.languages.javascript=Prism.languages.extend("clike",{"class-name":[Prism.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])[_$A-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\.(?:prototype|constructor))/,lookbehind:!0}],keyword:[{pattern:/((?:^|})\s*)(?:catch|finally)\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|for|from|function|(?:get|set)(?=\s*[\[$\w\xA0-\uFFFF])|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],number:/\b(?:(?:0[xX](?:[\dA-Fa-f](?:_[\dA-Fa-f])?)+|0[bB](?:[01](?:_[01])?)+|0[oO](?:[0-7](?:_[0-7])?)+)n?|(?:\d(?:_\d)?)+n|NaN|Infinity)\b|(?:\b(?:\d(?:_\d)?)+\.?(?:\d(?:_\d)?)*|\B\.(?:\d(?:_\d)?)+)(?:[Ee][+-]?(?:\d(?:_\d)?)+)?/,function:/#?[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),Prism.languages.javascript["class-name"][0].pattern=/(\b(?:class|interface|extends|implements|instanceof|new)\s+)[\w.\\]+/,Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)\/(?:\[(?:[^\]\\\r\n]|\\.)*]|\\.|[^/\\\[\r\n])+\/[gimyus]{0,6}(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/,lookbehind:!0,greedy:!0},"function-variable":{pattern:/#?[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+[_$A-Za-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)?\s*\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\))/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*=>)/i,inside:Prism.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\)\s*=>)/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:[_$A-Za-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\)\s*\{)/,lookbehind:!0,inside:Prism.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),Prism.languages.insertBefore("javascript","string",{"template-string":{pattern:/`(?:\\[\s\S]|\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}|(?!\${)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\${|}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}}}),Prism.languages.markup&&Prism.languages.markup.tag.addInlined("script","javascript"),Prism.languages.js=Prism.languages.javascript; -------------------------------------------------------------------------------- /asset/search.min.js: -------------------------------------------------------------------------------- 1 | !function(){var h={},f={EXPIRE_KEY:"docsify.search.expires",INDEX_KEY:"docsify.search.index"};function l(e){var n={"&":"&","<":"<",">":">",'"':""","'":"'"};return String(e).replace(/[&<>"']/g,function(e){return n[e]})}function p(e){return e.text||"table"!==e.type||(e.cells.unshift(e.header),e.text=e.cells.map(function(e){return e.join(" | ")}).join(" |\n ")),e.text}function u(r,e,i,o){void 0===e&&(e="");var s,n=window.marked.lexer(e),c=window.Docsify.slugify,d={};return n.forEach(function(e){if("heading"===e.type&&e.depth<=o){var n=function(e){void 0===e&&(e="");var a={};return{str:e=e&&e.replace(/^'/,"").replace(/'$/,"").replace(/(?:^|\s):([\w-]+:?)=?([\w-%]+)?/g,function(e,n,t){return-1===n.indexOf(":")?(a[n]=t&&t.replace(/"/g,"")||!0,""):e}).trim(),config:a}}(e.text),t=n.str,a=n.config;s=a.id?i.toURL(r,{id:c(a.id)}):i.toURL(r,{id:c(l(e.text))}),d[s]={slug:s,title:t,body:""}}else{if(!s)return;d[s]?d[s].body?(e.text=p(e),d[s].body+="\n"+(e.text||"")):(e.text=p(e),d[s].body=d[s].body?d[s].body+e.text:e.text):d[s]={slug:s,title:"",body:""}}}),c.clear(),d}function c(e){var r=[],i=[];Object.keys(h).forEach(function(n){i=i.concat(Object.keys(h[n]).map(function(e){return h[n][e]}))});var o=(e=e.trim()).split(/[\s\-,\\/]+/);1!==o.length&&(o=[].concat(e,o));function n(e){var n=i[e],s=0,c="",d=n.title&&n.title.trim(),p=n.body&&n.body.trim(),t=n.slug||"";if(d&&(o.forEach(function(e){var n,t=new RegExp(e.replace(/[|\\{}()[\]^$+*?.]/g,"\\$&"),"gi"),a=-1;if(n=d?d.search(t):-1,a=p?p.search(t):-1,0<=n||0<=a){s+=0<=n?3:0<=a?2:0,a<0&&(a=0);var r,i=0;i=0==(r=a<11?0:a-10)?70:a+e.length+60,p&&i>p.length&&(i=p.length);var o="..."+l(p).substring(r,i).replace(t,function(e){return'<em class="search-keyword">'+e+"</em>"})+"...";c+=o}}),0<s)){var a={title:l(d),content:p?c:"",url:t,score:s};r.push(a)}}for(var t=0;t<i.length;t++)n(t);return r.sort(function(e,n){return n.score-e.score})}function i(t,a){var e="auto"===t.paths,n=e?function(r){var i=[];return Docsify.dom.findAll(".sidebar-nav a:not(.section-link):not([data-nosearch])").forEach(function(e){var n=e.href,t=e.getAttribute("href"),a=r.parse(n).path;a&&-1===i.indexOf(a)&&!Docsify.util.isAbsolutePath(t)&&i.push(a)}),i}(a.router):t.paths,r="";if(e&&t.pathNamespaces){var i=n[0];if(Array.isArray(t.pathNamespaces))r=t.pathNamespaces.find(function(e){return i.startsWith(e)})||r;else if(t.pathNamespaces instanceof RegExp){var o=i.match(t.pathNamespaces);o&&(r=o[0])}}var s=function(e){return e?f.EXPIRE_KEY+"/"+e:f.EXPIRE_KEY}(t.namespace)+r,c=function(e){return e?f.INDEX_KEY+"/"+e:f.INDEX_KEY}(t.namespace)+r,d=localStorage.getItem(s)<Date.now();if(h=JSON.parse(localStorage.getItem(c)),d)h={};else if(!e)return;var p=n.length,l=0;n.forEach(function(n){if(h[n])return l++;Docsify.get(a.router.getFile(n),!1,a.config.requestHeaders).then(function(e){h[n]=u(n,e,a.router,t.depth),p===++l&&function(e,n,t){localStorage.setItem(n,Date.now()+e),localStorage.setItem(t,JSON.stringify(h))}(t.maxAge,s,c)})})}var d,m="";function r(e){var n=Docsify.dom.find("div.search"),t=Docsify.dom.find(n,".results-panel"),a=Docsify.dom.find(n,".clear-button"),r=Docsify.dom.find(".sidebar-nav"),i=Docsify.dom.find(".app-name");if(!e)return t.classList.remove("show"),a.classList.remove("show"),t.innerHTML="",void(d.hideOtherSidebarContent&&(r.classList.remove("hide"),i.classList.remove("hide")));var o=c(e),s="";o.forEach(function(e){s+='<div class="matching-post">\n<a href="'+e.url+'">\n<h2>'+e.title+"</h2>\n<p>"+e.content+"</p>\n</a>\n</div>"}),t.classList.add("show"),a.classList.add("show"),t.innerHTML=s||'<p class="empty">'+m+"</p>",d.hideOtherSidebarContent&&(r.classList.add("hide"),i.classList.add("hide"))}function a(e){d=e}function o(e,n){var t=n.router.parse().query.s;a(e),Docsify.dom.style("\n.sidebar {\n padding-top: 0;\n}\n\n.search {\n margin-bottom: 20px;\n padding: 6px;\n border-bottom: 1px solid #eee;\n}\n\n.search .input-wrap {\n display: flex;\n align-items: center;\n}\n\n.search .results-panel {\n display: none;\n}\n\n.search .results-panel.show {\n display: block;\n}\n\n.search input {\n outline: none;\n border: none;\n width: 100%;\n padding: 0 7px;\n line-height: 36px;\n font-size: 14px;\n border: 1px solid transparent;\n}\n\n.search input:focus {\n box-shadow: 0 0 5px var(--theme-color, #42b983);\n border: 1px solid var(--theme-color, #42b983);\n}\n\n.search input::-webkit-search-decoration,\n.search input::-webkit-search-cancel-button,\n.search input {\n -webkit-appearance: none;\n -moz-appearance: none;\n appearance: none;\n}\n.search .clear-button {\n cursor: pointer;\n width: 36px;\n text-align: right;\n display: none;\n}\n\n.search .clear-button.show {\n display: block;\n}\n\n.search .clear-button svg {\n transform: scale(.5);\n}\n\n.search h2 {\n font-size: 17px;\n margin: 10px 0;\n}\n\n.search a {\n text-decoration: none;\n color: inherit;\n}\n\n.search .matching-post {\n border-bottom: 1px solid #eee;\n}\n\n.search .matching-post:last-child {\n border-bottom: 0;\n}\n\n.search p {\n font-size: 14px;\n overflow: hidden;\n text-overflow: ellipsis;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n}\n\n.search p.empty {\n text-align: center;\n}\n\n.app-name.hide, .sidebar-nav.hide {\n display: none;\n}"),function(e){void 0===e&&(e="");var n='<div class="input-wrap">\n <input type="search" value="'+e+'" aria-label="Search text" />\n <div class="clear-button">\n <svg width="26" height="24">\n <circle cx="12" cy="12" r="11" fill="#ccc" />\n <path stroke="white" stroke-width="2" d="M8.25,8.25,15.75,15.75" />\n <path stroke="white" stroke-width="2"d="M8.25,15.75,15.75,8.25" />\n </svg>\n </div>\n </div>\n <div class="results-panel"></div>\n </div>',t=Docsify.dom.create("div",n),a=Docsify.dom.find("aside");Docsify.dom.toggleClass(t,"search"),Docsify.dom.before(a,t)}(t),function(){var e,n=Docsify.dom.find("div.search"),t=Docsify.dom.find(n,"input"),a=Docsify.dom.find(n,".input-wrap");Docsify.dom.on(n,"click",function(e){return-1===["A","H2","P","EM"].indexOf(e.target.tagName)&&e.stopPropagation()}),Docsify.dom.on(t,"input",function(n){clearTimeout(e),e=setTimeout(function(e){return r(n.target.value.trim())},100)}),Docsify.dom.on(a,"click",function(e){"INPUT"!==e.target.tagName&&(t.value="",r())})}(),t&&setTimeout(function(e){return r(t)},500)}function s(e,n){a(e),function(e,n){var t=Docsify.dom.getNode('.search input[type="search"]');if(t)if("string"==typeof e)t.placeholder=e;else{var a=Object.keys(e).filter(function(e){return-1<n.indexOf(e)})[0];t.placeholder=e[a]}}(e.placeholder,n.route.path),function(e,n){if("string"==typeof e)m=e;else{var t=Object.keys(e).filter(function(e){return-1<n.indexOf(e)})[0];m=e[t]}}(e.noData,n.route.path)}var g={placeholder:"Type to search",noData:"No Results!",paths:"auto",depth:2,maxAge:864e5,hideOtherSidebarContent:!1,namespace:void 0,pathNamespaces:void 0};$docsify.plugins=[].concat(function(e,n){var t=Docsify.util,a=n.config.search||g;Array.isArray(a)?g.paths=a:"object"==typeof a&&(g.paths=Array.isArray(a.paths)?a.paths:"auto",g.maxAge=t.isPrimitive(a.maxAge)?a.maxAge:g.maxAge,g.placeholder=a.placeholder||g.placeholder,g.noData=a.noData||g.noData,g.depth=a.depth||g.depth,g.hideOtherSidebarContent=a.hideOtherSidebarContent||g.hideOtherSidebarContent,g.namespace=a.namespace||g.namespace,g.pathNamespaces=a.pathNamespaces||g.pathNamespaces);var r="auto"===g.paths;e.mounted(function(e){o(g,n),r||i(g,n)}),e.doneEach(function(e){s(g,n),r&&i(g,n)})},$docsify.plugins)}(); 2 | -------------------------------------------------------------------------------- /asset/style.css: -------------------------------------------------------------------------------- 1 | /*隐藏头部的目录*/ 2 | #main>ul:nth-child(1) { 3 | display: none; 4 | } 5 | 6 | #main>ul:nth-child(2) { 7 | display: none; 8 | } 9 | 10 | .markdown-section h1 { 11 | margin: 3rem 0 2rem 0; 12 | } 13 | 14 | .markdown-section h2 { 15 | margin: 2rem 0 1rem; 16 | } 17 | 18 | img, 19 | pre { 20 | border-radius: 8px; 21 | } 22 | 23 | .content, 24 | .sidebar, 25 | .markdown-section, 26 | body, 27 | .search input { 28 | background-color: rgba(243, 242, 238, 1) !important; 29 | } 30 | 31 | @media (min-width:600px) { 32 | .sidebar-toggle { 33 | background-color: #f3f2ee; 34 | } 35 | } 36 | 37 | .docsify-copy-code-button { 38 | background: #f8f8f8 !important; 39 | color: #7a7a7a !important; 40 | } 41 | 42 | body { 43 | /*font-family: Microsoft YaHei, Source Sans Pro, Helvetica Neue, Arial, sans-serif !important;*/ 44 | } 45 | 46 | .markdown-section>p { 47 | font-size: 16px !important; 48 | } 49 | 50 | .markdown-section pre>code { 51 | font-family: Consolas, Roboto Mono, Monaco, courier, monospace !important; 52 | font-size: .9rem !important; 53 | 54 | } 55 | 56 | /*.anchor span { 57 | color: rgb(66, 185, 131); 58 | }*/ 59 | 60 | section.cover h1 { 61 | margin: 0; 62 | } 63 | 64 | body>section>div.cover-main>ul>li>a { 65 | color: #42b983; 66 | } 67 | 68 | .markdown-section img { 69 | box-shadow: 7px 9px 10px #aaa !important; 70 | } 71 | 72 | 73 | pre { 74 | background-color: #f3f2ee !important; 75 | } 76 | 77 | @media (min-width:600px) { 78 | pre code { 79 | /*box-shadow: 2px 1px 20px 2px #aaa;*/ 80 | /*border-radius: 10px !important;*/ 81 | padding-left: 20px !important; 82 | } 83 | } 84 | 85 | @media (max-width:600px) { 86 | pre { 87 | padding-left: 0px !important; 88 | padding-right: 0px !important; 89 | } 90 | } 91 | 92 | .markdown-section pre { 93 | padding-left: 0 !important; 94 | padding-right: 0px !important; 95 | box-shadow: 2px 1px 20px 2px #aaa; 96 | } -------------------------------------------------------------------------------- /cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apachecn/eloquent-js-3e-zh/12ed9090d2ddb50e23255e1a3790e5fdb849979b/cover.jpg -------------------------------------------------------------------------------- /img/0-0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apachecn/eloquent-js-3e-zh/12ed9090d2ddb50e23255e1a3790e5fdb849979b/img/0-0.jpg -------------------------------------------------------------------------------- /img/1-0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apachecn/eloquent-js-3e-zh/12ed9090d2ddb50e23255e1a3790e5fdb849979b/img/1-0.jpg -------------------------------------------------------------------------------- /img/10-0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apachecn/eloquent-js-3e-zh/12ed9090d2ddb50e23255e1a3790e5fdb849979b/img/10-0.jpg -------------------------------------------------------------------------------- /img/11-1.svg: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> 2 | <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="445" height="210" viewBox="-2 -2 445 210"><style type="text/css"> 3 | @font-face { 4 | font-family: 'PT Mono'; 5 | font-style: normal; 6 | font-weight: 400; 7 | src: local('PT Mono'), local('PTMono-Regular'), url(http://themes.googleusercontent.com/static/fonts/ptmono/v1/jmle3kzCPnW8O7_gZGRDlQ.woff) format('woff'); 8 | } 9 | </style> 10 | <g><text x="0" y="14" font-family="PT Mono">synchronous, single thread of control</text><path d="M 0.5 40.5 L 20.5 40.5" stroke="#44f" stroke-width="5"></path><path d="M 20 40 L 180 40" stroke="#c22" stroke-width="2"></path><ellipse cx="20" cy="40" rx="5" ry="5" fill="black" width="10" height="10"></ellipse><path d="M 180.5 40.5 L 200.5 40.5" stroke="#44f" stroke-width="5"></path><path d="M 200 40 L 400 40" stroke="#c22" stroke-width="2"></path><ellipse cx="200" cy="40" rx="5" ry="5" fill="black" width="10" height="10"></ellipse><path d="M 400.5 40.5 L 440.5 40.5" stroke="#44f" stroke-width="5"></path><text x="0" y="71" font-family="PT Mono">synchronous, two threads of control</text><path d="M 0.5 95.5 L 20.5 95.5" stroke="#44f" stroke-width="5"></path><path d="M 20 95 L 180 95" stroke="#c22" stroke-width="2"></path><ellipse cx="20" cy="95" rx="5" ry="5" fill="black" width="10" height="10"></ellipse><path d="M 220.5 95.5 L 260.5 95.5" stroke="#44f" stroke-width="5"></path><path d="M 0.5 120.5 L 20.5 120.5" stroke="#44f" stroke-width="5"></path><path d="M 20 120 L 220 120" stroke="#c22" stroke-width="2"></path><ellipse cx="20" cy="120" rx="5" ry="5" fill="black" width="10" height="10"></ellipse><path d="M 220.5 120.5 L 240.5 120.5" stroke="#44f" stroke-width="5"></path><text x="0" y="151" font-family="PT Mono">asynchronous</text><path d="M 20 175 a 30 30 0 0 0 30 30 l 82 0 a 30 30 0 0 0 30 -30" stroke="#c22" fill="none" stroke-width="2"></path><path d="M 40 175 a 15 15 0 0 0 15 15 l 152 0 a 15 15 0 0 0 15 -15" stroke="#c22" fill="none" stroke-width="2"></path><path d="M 0.5 175.5 L 60.5 175.5" stroke="#44f" stroke-width="5"></path><path d="M 20 175 L 20 175" stroke="#c22" stroke-width="2"></path><ellipse cx="20" cy="175" rx="5" ry="5" fill="black" width="10" height="10"></ellipse><path d="M 40 175 L 40 175" stroke="#c22" stroke-width="2"></path><ellipse cx="40" cy="175" rx="5" ry="5" fill="black" width="10" height="10"></ellipse><path d="M 160.5 175.5 L 180.5 175.5" stroke="#44f" stroke-width="5"></path><path d="M 220.5 175.5 L 260.5 175.5" stroke="#44f" stroke-width="5"></path></g></svg> 11 | -------------------------------------------------------------------------------- /img/11-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apachecn/eloquent-js-3e-zh/12ed9090d2ddb50e23255e1a3790e5fdb849979b/img/11-2.png -------------------------------------------------------------------------------- /img/12-0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apachecn/eloquent-js-3e-zh/12ed9090d2ddb50e23255e1a3790e5fdb849979b/img/12-0.jpg -------------------------------------------------------------------------------- /img/12-1.svg: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> 2 | <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="169" height="240" viewBox="-7 -10 169 240"><style> 3 | @font-face { 4 | font-family: 'PT Mono'; 5 | font-style: normal; 6 | font-weight: 400; 7 | src: local('PT Mono'), local('PTMono-Regular'), url(http://themes.googleusercontent.com/static/fonts/ptmono/v1/jmle3kzCPnW8O7_gZGRDlQ.woff) format('woff'); 8 | } 9 | .ast-text { font-family: "PT Mono"; font-size: 14px; stroke: none; } 10 | </style> 11 | <g><ellipse cx="0" cy="0" rx="5" ry="5" fill="black" width="10" height="10"></ellipse><text x="13" y="4.5" class="ast-text">do</text><ellipse cx="30" cy="20" rx="5" ry="5" fill="black" width="10" height="10"></ellipse><text x="43" y="24.5" class="ast-text">define</text><path d="M 0.5 5.5 L 0.5 10.5 A 10 10 0 0 0 10.5 20.5 L 25.5 20.5" stroke="black" fill="none"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(0, 0, 0)" transform="translate(25.5 20.5) rotate(90) scale(1)"></path><ellipse cx="60" cy="40" rx="5" ry="5" fill="black" width="10" height="10"></ellipse><text x="73" y="44.5" class="ast-text">x</text><path d="M 30.5 25.5 L 30.5 30.5 A 10 10 0 0 0 40.5 40.5 L 55.5 40.5" stroke="black" fill="none"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(0, 0, 0)" transform="translate(55.5 40.5) rotate(90) scale(1)"></path><ellipse cx="60" cy="60" rx="5" ry="5" fill="black" width="10" height="10"></ellipse><text x="73" y="64.5" class="ast-text">10</text><path d="M 30.5 25.5 L 30.5 50.5 A 10 10 0 0 0 40.5 60.5 L 55.5 60.5" stroke="black" fill="none"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(0, 0, 0)" transform="translate(55.5 60.5) rotate(90) scale(1)"></path><ellipse cx="30" cy="80" rx="5" ry="5" fill="black" width="10" height="10"></ellipse><text x="43" y="84.5" class="ast-text">if</text><path d="M 0.5 5.5 L 0.5 70.5 A 10 10 0 0 0 10.5 80.5 L 25.5 80.5" stroke="black" fill="none"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(0, 0, 0)" transform="translate(25.5 80.5) rotate(90) scale(1)"></path><ellipse cx="60" cy="100" rx="5" ry="5" fill="black" width="10" height="10"></ellipse><text x="73" y="104.5" class="ast-text">></text><path d="M 30.5 85.5 L 30.5 90.5 A 10 10 0 0 0 40.5 100.5 L 55.5 100.5" stroke="black" fill="none"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(0, 0, 0)" transform="translate(55.5 100.5) rotate(90) scale(1)"></path><ellipse cx="90" cy="120" rx="5" ry="5" fill="black" width="10" height="10"></ellipse><text x="103" y="124.5" class="ast-text">x</text><path d="M 60.5 105.5 L 60.5 110.5 A 10 10 0 0 0 70.5 120.5 L 85.5 120.5" stroke="black" fill="none"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(0, 0, 0)" transform="translate(85.5 120.5) rotate(90) scale(1)"></path><ellipse cx="90" cy="140" rx="5" ry="5" fill="black" width="10" height="10"></ellipse><text x="103" y="144.5" class="ast-text">5</text><path d="M 60.5 105.5 L 60.5 130.5 A 10 10 0 0 0 70.5 140.5 L 85.5 140.5" stroke="black" fill="none"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(0, 0, 0)" transform="translate(85.5 140.5) rotate(90) scale(1)"></path><ellipse cx="60" cy="160" rx="5" ry="5" fill="black" width="10" height="10"></ellipse><text x="73" y="164.5" class="ast-text">print</text><path d="M 30.5 85.5 L 30.5 150.5 A 10 10 0 0 0 40.5 160.5 L 55.5 160.5" stroke="black" fill="none"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(0, 0, 0)" transform="translate(55.5 160.5) rotate(90) scale(1)"></path><ellipse cx="90" cy="180" rx="5" ry="5" fill="black" width="10" height="10"></ellipse><text x="103" y="184.5" class="ast-text">"large"</text><path d="M 60.5 165.5 L 60.5 170.5 A 10 10 0 0 0 70.5 180.5 L 85.5 180.5" stroke="black" fill="none"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(0, 0, 0)" transform="translate(85.5 180.5) rotate(90) scale(1)"></path><ellipse cx="60" cy="200" rx="5" ry="5" fill="black" width="10" height="10"></ellipse><text x="73" y="204.5" class="ast-text">print</text><path d="M 30.5 85.5 L 30.5 190.5 A 10 10 0 0 0 40.5 200.5 L 55.5 200.5" stroke="black" fill="none"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(0, 0, 0)" transform="translate(55.5 200.5) rotate(90) scale(1)"></path><ellipse cx="90" cy="220" rx="5" ry="5" fill="black" width="10" height="10"></ellipse><text x="103" y="224.5" class="ast-text">"small"</text><path d="M 60.5 205.5 L 60.5 210.5 A 10 10 0 0 0 70.5 220.5 L 85.5 220.5" stroke="black" fill="none"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(0, 0, 0)" transform="translate(85.5 220.5) rotate(90) scale(1)"></path></g></svg> -------------------------------------------------------------------------------- /img/13-0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apachecn/eloquent-js-3e-zh/12ed9090d2ddb50e23255e1a3790e5fdb849979b/img/13-0.jpg -------------------------------------------------------------------------------- /img/14-0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apachecn/eloquent-js-3e-zh/12ed9090d2ddb50e23255e1a3790e5fdb849979b/img/14-0.jpg -------------------------------------------------------------------------------- /img/14-1.svg: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> 2 | <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="369" height="429" viewBox="-268 -358 369 429"><style type="text/css"> 3 | @font-face { 4 | font-family: 'PT Mono'; 5 | font-style: normal; 6 | font-weight: 400; 7 | src: local('PT Mono'), local('PTMono-Regular'), url(http://themes.googleusercontent.com/static/fonts/ptmono/v1/jmle3kzCPnW8O7_gZGRDlQ.woff) format('woff'); 8 | } 9 | .leaf { 10 | font-family: "Georgia"; 11 | font-size: 15px; 12 | } 13 | .wraptext { 14 | font-family: "PT Mono"; 15 | font-size: 14px; 16 | } 17 | .wrap { 18 | border-radius: 4px; 19 | stroke-width: 1px; stroke: #666; 20 | fill: none; 21 | } 22 | </style> 23 | <g><text x="0" y="16" class="leaf">here</text><text x="0" y="-11" class="wraptext">a</text><rect x="-11.5" y="-28.5" width="57" height="61" class="wrap" rx="4" ry="4"></rect><text x="57" y="16" class="leaf">.</text><text x="-230" y="16" class="leaf">I also wrote a book! Read it</text><text x="-230" y="-19.5" class="wraptext">p</text><rect x="-241.5" y="-37.5" width="316" height="82" class="wrap" rx="4" ry="4"></rect><text x="-230" y="-65.5" class="leaf">Hello, I am Marijn and this is...</text><text x="-230" y="-92.5" class="wraptext">p</text><rect x="-241.5" y="-110.5" width="316" height="61" class="wrap" rx="4" ry="4"></rect><text x="-230" y="-138.5" class="leaf">My home page</text><text x="-230" y="-165.5" class="wraptext">h1</text><rect x="-241.5" y="-183.5" width="316" height="61" class="wrap" rx="4" ry="4"></rect><text x="-241.5" y="-194.5" class="wraptext">body</text><rect x="-253.5" y="-212.5" width="340" height="269" class="wrap" rx="4" ry="4"></rect><text x="-230" y="-252.5" class="leaf">My home page</text><text x="-230" y="-279.5" class="wraptext">title</text><rect x="-241.5" y="-297.5" width="316" height="61" class="wrap" rx="4" ry="4"></rect><text x="-241.5" y="-308.5" class="wraptext">head</text><rect x="-253.5" y="-326.5" width="340" height="102" class="wrap" rx="4" ry="4"></rect><text x="-253.5" y="-337.5" class="wraptext">html</text><rect x="-265.5" y="-355.5" width="364" height="424" class="wrap" rx="4" ry="4"></rect></g></svg> 24 | -------------------------------------------------------------------------------- /img/14-2.svg: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> 2 | <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="439" height="259" viewBox="-2 -2 439 259"><style type="text/css"> 3 | @font-face { 4 | font-family: 'PT Mono'; 5 | font-style: normal; 6 | font-weight: 400; 7 | src: local('PT Mono'), local('PTMono-Regular'), url(http://themes.googleusercontent.com/static/fonts/ptmono/v1/jmle3kzCPnW8O7_gZGRDlQ.woff) format('woff'); 8 | } 9 | .box { 10 | stroke: #666; 11 | fill: url(#boxgrad); 12 | border-radius: 4px; 13 | } 14 | .leafbox { 15 | fill: url(#leafgrad); 16 | } 17 | .boxtext { 18 | font-size: 18px; 19 | font-family: "PT Mono"; 20 | stroke: none; 21 | fill: black; 22 | } 23 | .leafboxtext { font-family: "Georgia"; } 24 | .arrow { stroke: black; } 25 | </style> 26 | <defs> 27 | <linearGradient id="boxgrad" x1="0" x2="0" y1="0" y2="1"> 28 | <stop stop-color="#f8f8f8" offset="0%"></stop> 29 | <stop stop-color="#e8e8f2" offset="100%"></stop> 30 | </linearGradient> 31 | <linearGradient id="leafgrad" x1="0" x2="0" y1="0" y2="1"> 32 | <stop stop-color="#f8f8f8" offset="0%"></stop> 33 | <stop stop-color="#caf0f0" offset="100%"></stop> 34 | </linearGradient> 35 | </defs> 36 | <g><rect x="0.5" y="0.5" width="66" height="30" class="box" rx="4" ry="4"></rect><text x="9.700000000000001" y="23" class="boxtext" fill="black" stroke="none">html</text><rect x="91.5" y="0.5" width="66" height="30" class="box" rx="4" ry="4"></rect><text x="100.7" y="23" class="boxtext" fill="black" stroke="none">head</text><path d="M 66.5 15.5 L 91.5 15.5" class="arrow" fill="none"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(0, 0, 0)" transform="translate(91.5 15.5) rotate(90) scale(1)"></path><rect x="182.5" y="0.5" width="78" height="30" class="box" rx="4" ry="4"></rect><text x="191.7" y="23" class="boxtext" fill="black" stroke="none">title</text><path d="M 157.5 15.5 L 182.5 15.5" class="arrow" fill="none"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(0, 0, 0)" transform="translate(182.5 15.5) rotate(90) scale(1)"></path><rect x="285.5" y="0.5" width="149" height="29" class="box leafbox" rx="4" ry="4"></rect><text x="294.3" y="22.25" class="boxtext leafboxtext" fill="black" stroke="none">My home page</text><path d="M 260.5 15.5 L 285.5 15.5" class="arrow" fill="none"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(0, 0, 0)" transform="translate(285.5 15.5) rotate(90) scale(1)"></path><rect x="91.5" y="45.5" width="66" height="30" class="box" rx="4" ry="4"></rect><text x="100.7" y="68" class="boxtext" fill="black" stroke="none">body</text><path d="M 74.5 15.5 L 74.5 56.5 A 4 4 0 0 0 78.5 60.5 L 91.5 60.5" class="arrow" fill="none"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(0, 0, 0)" transform="translate(91.5 60.5) rotate(90) scale(1)"></path><rect x="182.5" y="45.5" width="78" height="30" class="box" rx="4" ry="4"></rect><text x="191.7" y="68" class="boxtext" width="78" fill="black" stroke="none">h1</text><path d="M 157.5 60.5 L 182.5 60.5" class="arrow" fill="none"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(0, 0, 0)" transform="translate(182.5 60.5) rotate(90) scale(1)"></path><rect x="285.5" y="45.5" width="149" height="29" class="box leafbox" rx="4" ry="4"></rect><text x="294.3" y="67.25" class="boxtext leafboxtext" fill="black" stroke="none">My home page</text><path d="M 260.5 60.5 L 285.5 60.5" class="arrow" fill="none"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(0, 0, 0)" transform="translate(285.5 60.5) rotate(90) scale(1)"></path><rect x="182.5" y="90.5" width="78" height="30" class="box" rx="4" ry="4"></rect><text x="191.7" y="113" class="boxtext" width="78" fill="black" stroke="none">p</text><path d="M 165.5 60.5 L 165.5 101.5 A 4 4 0 0 0 169.5 105.5 L 182.5 105.5" class="arrow" fill="none"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(0, 0, 0)" transform="translate(182.5 105.5) rotate(90) scale(1)"></path><rect x="285.5" y="90.5" width="149" height="29" class="box leafbox" rx="4" ry="4"></rect><text x="294.3" y="112.25" class="boxtext leafboxtext" width="149" fill="black" stroke="none">Hello! I am...</text><path d="M 260.5 105.5 L 285.5 105.5" class="arrow" fill="none"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(0, 0, 0)" transform="translate(285.5 105.5) rotate(90) scale(1)"></path><rect x="182.5" y="135.5" width="78" height="30" class="box" rx="4" ry="4"></rect><text x="191.7" y="158" class="boxtext" width="78" fill="black" stroke="none">p</text><path d="M 165.5 60.5 L 165.5 146.5 A 4 4 0 0 0 169.5 150.5 L 182.5 150.5" class="arrow" fill="none"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(0, 0, 0)" transform="translate(182.5 150.5) rotate(90) scale(1)"></path><rect x="285.5" y="135.5" width="149" height="29" class="box leafbox" rx="4" ry="4"></rect><text x="294.3" y="157.25" class="boxtext leafboxtext" width="149" fill="black" stroke="none">I also wrote...</text><path d="M 260.5 150.5 L 285.5 150.5" class="arrow" fill="none"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(0, 0, 0)" transform="translate(285.5 150.5) rotate(90) scale(1)"></path><rect x="376.5" y="180.5" width="58" height="29" class="box leafbox" rx="4" ry="4"></rect><text x="385.3" y="202.25" class="boxtext leafboxtext" fill="black" stroke="none">here</text><rect x="285.5" y="180.5" width="66" height="30" class="box" rx="4" ry="4"></rect><text x="294.7" y="203" class="boxtext" width="66" fill="black" stroke="none">a</text><path d="M 268.5 150.5 L 268.5 191.5 A 4 4 0 0 0 272.5 195.5 L 285.5 195.5" class="arrow" fill="none"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(0, 0, 0)" transform="translate(285.5 195.5) rotate(90) scale(1)"></path><path d="M 351.5 195.5 L 376.5 195.5" class="arrow" fill="none"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(0, 0, 0)" transform="translate(376.5 195.5) rotate(90) scale(1)"></path><rect x="285.5" y="225.5" width="23" height="29" class="box leafbox" rx="4" ry="4"></rect><text x="294.3" y="247.25" class="boxtext leafboxtext" fill="black" stroke="none">.</text><path d="M 268.5 150.5 L 268.5 236.5 A 4 4 0 0 0 272.5 240.5 L 285.5 240.5" class="arrow" fill="none"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(0, 0, 0)" transform="translate(285.5 240.5) rotate(90) scale(1)"></path></g></svg> 37 | -------------------------------------------------------------------------------- /img/14-3.svg: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> 2 | <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="357" height="317" viewBox="-245 -250 357 317"><style type="text/css"> 3 | @font-face { 4 | font-family: 'PT Mono'; 5 | font-style: normal; 6 | font-weight: 400; 7 | src: local('PT Mono'), local('PTMono-Regular'), url(http://themes.googleusercontent.com/static/fonts/ptmono/v1/jmle3kzCPnW8O7_gZGRDlQ.woff) format('woff'); 8 | } 9 | .leaf { 10 | font-family: "Georgia"; 11 | font-size: 17px; 12 | } 13 | .wraptext, .linktext, .index { 14 | font-family: "PT Mono"; 15 | font-size: 14px; 16 | } 17 | .wrap { 18 | border-radius: 4px; 19 | stroke: #666; 20 | fill: none; 21 | } 22 | .link { stroke: #6aa; } 23 | .linktext, .index { fill: #6aa; } 24 | </style> 25 | <g><text x="-167" y="16" class="leaf">I also wrote a book! ...</text><text x="-167" y="-11" class="wraptext">p</text><rect x="-178.5" y="-28.5" width="191" height="61" class="wrap" rx="4" ry="4"></rect><text x="-167" y="-68.5" class="leaf">Hello, I am Marijn...</text><text x="-167" y="-95.5" class="wraptext">p</text><rect x="-178.5" y="-113.5" width="191" height="61" class="wrap" rx="4" ry="4"></rect><text x="-167" y="-153.5" class="leaf">My home page</text><text x="-167" y="-180.5" class="wraptext">h1</text><rect x="-178.5" y="-198.5" width="191" height="61" class="wrap" rx="4" ry="4"></rect><text x="-178.5" y="-209.5" class="wraptext">body</text><rect x="-190.5" y="-227.5" width="215" height="272" class="wrap" rx="4" ry="4"></rect><text x="-230.5" y="-180.5" class="index">0</text><text x="-230.5" y="-95.5" class="index">1</text><text x="-230.5" y="-11" class="index">2</text><rect x="-242.5" y="-204.5" width="32" height="209" class="wrap" rx="4" ry="4"></rect><path d="M -210.5 -184.5 L -178.5 -184.5" class="link" fill="none"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(102, 170, 170)" transform="translate(-178.5 -184.5) rotate(90) scale(1)"></path><path d="M -210.5 -99.5 L -178.5 -99.5" class="link" fill="none"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(102, 170, 170)" transform="translate(-178.5 -99.5) rotate(90) scale(1)"></path><path d="M -210.5 -15.5 L -178.5 -15.5" class="link" fill="none"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(102, 170, 170)" transform="translate(-178.5 -15.5) rotate(90) scale(1)"></path><path d="M -175.5 -227.5 L -175.5 -232.5 A 7 7 0 0 0 -182.5 -239.5 L -219.5 -239.5 A 7 7 0 0 0 -226.5 -232.5 L -226.5 -204.5" class="link" fill="none"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(102, 170, 170)" transform="translate(-226.5 -204.5) rotate(180) scale(1)"></path><text x="-170.5" y="-235.5" class="linktext">childNodes</text><path d="M -42.5 -227.5 L -42.5 -232.5 A 7 7 0 0 0 -49.5 -239.5 L -55.5 -239.5 A 7 7 0 0 0 -62.5 -232.5 L -62.5 -198.5" class="link" fill="none"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(102, 170, 170)" transform="translate(-62.5 -198.5) rotate(180) scale(1)"></path><text x="-38" y="-235.5" class="linktext">firstChild</text><path d="M -42.5 44.5 L -42.5 49.5 A 7 7 0 0 1 -49.5 56.5 L -55.5 56.5 A 7 7 0 0 1 -62.5 49.5 L -62.5 32.5" class="link" fill="none"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(102, 170, 170)" transform="translate(-62.5 32.5) scale(1)"></path><text x="-38" y="61.5" class="linktext">lastChild</text><path d="M -158.5 -113.5 L -158.5 -137.5" class="link" fill="none"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(102, 170, 170)" transform="translate(-158.5 -137.5) scale(1)"></path><text x="-153.5" y="-121" class="linktext">previousSibling</text><path d="M -158.5 -52.5 L -158.5 -28.5" class="link" fill="none"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(102, 170, 170)" transform="translate(-158.5 -28.5) rotate(180) scale(1)"></path><text x="-153.5" y="-36" class="linktext">nextSibling</text><path d="M 12.5 -82.5 L 31.5 -82.5 A 7 7 0 0 0 38.5 -89.5 L 38.5 -95.5 A 7 7 0 0 0 31.5 -102.5 L 31.5 -102.5 L 24.5 -102.5" class="link" fill="none"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(102, 170, 170)" transform="translate(24.5 -102.5) rotate(270) scale(1)"></path><text x="29.5" y="-66" class="linktext">parentNode</text></g></svg> 26 | -------------------------------------------------------------------------------- /img/14-4.svg: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> 2 | <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="252" height="167" viewBox="-131 -84 252 167"><style type="text/css"> 3 | @font-face { 4 | font-family: 'PT Mono'; 5 | font-style: normal; 6 | font-weight: 400; 7 | src: local('PT Mono'), local('PTMono-Regular'), url(http://themes.googleusercontent.com/static/fonts/ptmono/v1/jmle3kzCPnW8O7_gZGRDlQ.woff) format('woff'); 8 | } 9 | .caption { font-family: 'PT Mono'; font-size: 13px; } 10 | </style> 11 | <g><path d="M 0.5 -79.5 L 0.5 80.5" stroke="black"></path><path d="M -79.5 0.5 L 80.5 0.5" stroke="black"></path><path d="M 14.7 3 A 15 15 0 1 1 10.6 -10.6" stroke="black" fill="none"></path><path d="M 12.5 -8.5 L 13.5 -7.5" stroke="black"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(0, 0, 0)" transform="translate(13.5 -7.5) rotate(135) scale(1)"></path><ellipse cx="0" cy="0" rx="60" ry="60" stroke="black" fill="none" width="120" height="120"></ellipse><ellipse cx="42.426406871192846" cy="42.426406871192846" rx="3" ry="3" fill="#44f" width="6" height="6"></ellipse><path d="M 0.5 42.5 L 39.5 42.5" stroke="#44f"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(68, 68, 255)" transform="translate(39.5 42.5) rotate(90) scale(1)"></path><path d="M 42.5 0.5 L 42.5 39.5" stroke="#44f"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(68, 68, 255)" transform="translate(42.5 39.5) rotate(180) scale(1)"></path><text x="32.426406871192846" y="64.42640687119285" class="caption" fill="#44f">cos(¼π)</text><text x="62.426406871192846" y="29.426406871192846" class="caption" fill="#44f">sin(¼π)</text><ellipse cx="-30.000000000544134" cy="-51.961524226752175" rx="3" ry="3" fill="#0a0" width="6" height="6"></ellipse><path d="M 0.5 -51.5 L -27.5 -51.5" stroke="#0a0"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(0, 170, 0)" transform="translate(-27.5 -51.5) rotate(270) scale(1)"></path><path d="M -30.5 0.5 L -30.5 -48.5" stroke="#0a0"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(0, 170, 0)" transform="translate(-30.5 -48.5) scale(1)"></path><text x="-84.00000000054413" y="-69.96152422675218" class="caption" fill="#0a0">cos(-⅔π)</text><text x="-129.00000000054413" y="-29.961524226752175" class="caption" fill="#0a0">sin(-⅔π)</text></g></svg> 12 | -------------------------------------------------------------------------------- /img/15-0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apachecn/eloquent-js-3e-zh/12ed9090d2ddb50e23255e1a3790e5fdb849979b/img/15-0.jpg -------------------------------------------------------------------------------- /img/16-0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apachecn/eloquent-js-3e-zh/12ed9090d2ddb50e23255e1a3790e5fdb849979b/img/16-0.jpg -------------------------------------------------------------------------------- /img/16-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apachecn/eloquent-js-3e-zh/12ed9090d2ddb50e23255e1a3790e5fdb849979b/img/16-1.png -------------------------------------------------------------------------------- /img/16-2.svg: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> 2 | <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="125" height="105" viewBox="-2 -2 125 105"><g><rect x="40" y="20" width="40" height="60" fill="#e0e0ff"></rect><g><path d="M 20.5 0.5 L 20.5 100.5" width="120" height="100" stroke-width="1" stroke="#888"></path><path d="M 40.5 0.5 L 40.5 100.5" width="120" height="100" stroke-width="1" stroke="#888"></path><path d="M 60.5 0.5 L 60.5 100.5" width="120" height="100" stroke-width="1" stroke="#888"></path><path d="M 80.5 0.5 L 80.5 100.5" width="120" height="100" stroke-width="1" stroke="#888"></path><path d="M 100.5 0.5 L 100.5 100.5" width="120" height="100" stroke-width="1" stroke="#888"></path><path d="M 0.5 20.5 L 120.5 20.5" width="120" height="100" stroke-width="1" stroke="#888"></path><path d="M 0.5 40.5 L 120.5 40.5" width="120" height="100" stroke-width="1" stroke="#888"></path><path d="M 0.5 60.5 L 120.5 60.5" width="120" height="100" stroke-width="1" stroke="#888"></path><path d="M 0.5 80.5 L 120.5 80.5" width="120" height="100" stroke-width="1" stroke="#888"></path></g><rect x="55" y="37" width="16" height="30" fill="#404040"></rect></g></svg> -------------------------------------------------------------------------------- /img/17-0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apachecn/eloquent-js-3e-zh/12ed9090d2ddb50e23255e1a3790e5fdb849979b/img/17-0.jpg -------------------------------------------------------------------------------- /img/17-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apachecn/eloquent-js-3e-zh/12ed9090d2ddb50e23255e1a3790e5fdb849979b/img/17-1.png -------------------------------------------------------------------------------- /img/17-2.svg: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> 2 | <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="635" height="224" viewBox="-82 -82 635 224"><style type="text/css"> 3 | @font-face { 4 | font-family: 'PT Mono'; 5 | font-style: normal; 6 | font-weight: 400; 7 | src: local('PT Mono'), local('PTMono-Regular'), url(http://themes.googleusercontent.com/static/fonts/ptmono/v1/jmle3kzCPnW8O7_gZGRDlQ.woff) format('woff'); 8 | } 9 | .caption { font-family: 'PT Mono'; font-size: 13px; } 10 | </style> 11 | <g><path d="M 0.5 -79.5 L 0.5 80.5" stroke="black"></path><path d="M -79.5 0.5 L 80.5 0.5" stroke="black"></path><path d="M 0.5 -79.5 L 0.5 80.5" stroke="#0a0" transform="translate(50 50)"></path><path d="M -79.5 0.5 L 80.5 0.5" stroke="#0a0" transform="translate(50 50)"></path><path d="M 0.5 0.5 L 50.5 50.5" stroke="#0a0"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(0, 170, 0)" transform="translate(50.5 50.5) rotate(135) scale(1)"></path><path d="M 0.5 -79.5 L 0.5 80.5" stroke="#44f" transform="translate(50 50) rotate(20)"></path><path d="M -79.5 0.5 L 80.5 0.5" stroke="#44f" transform="translate(50 50) rotate(20)"></path><path d="M 110.5 50.5 L 110.5 72.5" stroke="#44f"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(68, 68, 255)" transform="translate(110.5 72.5) rotate(180) scale(1)"></path><text x="75" y="27" fill="#0a0" class="caption">translate(50, 50)</text><text x="130" y="67" fill="#44f" class="caption">rotate(0.1*Math.PI)</text><path d="M 0.5 -79.5 L 0.5 80.5" stroke="black" transform="translate(360 0)"></path><path d="M -79.5 0.5 L 80.5 0.5" stroke="black" transform="translate(360 0)"></path><path d="M 0.5 -79.5 L 0.5 80.5" stroke="#0a0" transform="translate(360 0) rotate(20)"></path><path d="M -79.5 0.5 L 80.5 0.5" stroke="#0a0" transform="translate(360 0) rotate(20)"></path><path d="M 360.5 -59.5 L 380.5 -59.5" stroke="#0a0"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(0, 170, 0)" transform="translate(380.5 -59.5) rotate(90) scale(1)"></path><path d="M 0.5 -79.5 L 0.5 80.5" stroke="#44f" transform="translate(360 0) rotate(20) translate(50, 50)"></path><path d="M -79.5 0.5 L 80.5 0.5" stroke="#44f" transform="translate(360 0) rotate(20) translate(50, 50)"></path><path d="M 360.5 0.5 L 390.5 65.5" stroke="#44f"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(68, 68, 255)" transform="translate(390.5 65.5) rotate(155.22485943116808) scale(1)"></path><text x="390" y="-48" fill="#0a0" class="caption">rotate(0.1*Math.PI)</text><text x="415" y="57" fill="#44f" class="caption">translate(50, 50)</text></g></svg> 12 | -------------------------------------------------------------------------------- /img/17-3.svg: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> 2 | <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="324" height="152" viewBox="-62 -84 324 152"><style type="text/css"> 3 | @font-face { 4 | font-family: 'PT Mono'; 5 | font-style: normal; 6 | font-weight: 400; 7 | src: local('PT Mono'), local('PTMono-Regular'), url(http://themes.googleusercontent.com/static/fonts/ptmono/v1/jmle3kzCPnW8O7_gZGRDlQ.woff) format('woff'); 8 | } 9 | .caption { font-family: 'PT Mono'; font-size: 13px; } 10 | </style> 11 | <g><path d="M 0.5 -59.5 L 0.5 60.5" stroke="black"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(0, 0, 0)" transform="translate(0.5 60.5) rotate(180) scale(1)"></path><path d="M -59.5 0.5 L 60.5 0.5" stroke="black"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(0, 0, 0)" transform="translate(60.5 0.5) rotate(90) scale(1)"></path><path d="M 0.5 -59.5 L 0.5 60.5" stroke="black" transform="translate(200 0) scale(-1 1)"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" transform="translate(200 0) scale(-1 1) translate(0.5 60.5) rotate(180) scale(1)" stroke="none" fill="rgb(0, 0, 0)"></path><path d="M -59.5 0.5 L 60.5 0.5" stroke="black" transform="translate(200 0) scale(-1 1)"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" transform="translate(200 0) scale(-1 1) translate(60.5 0.5) rotate(90) scale(1)" stroke="none" fill="rgb(0, 0, 0)"></path><path d="M 100.5 -64.5 L 100.5 65.5" stroke="#888"></path><text x="76" y="-70" fill="#888" class="caption">mirror</text><path d="M -15 -25 L 30 0 L -15 25 z" stroke="#0a0" fill="none" transform="translate(100 0)"></path><path d="M -15 -25 L 30 0 L -15 25 z" stroke="#44f" fill="none" transform="translate(200 0)"></path><path d="M -15 -25 L 30 0 L -15 25 z" stroke="#f44" fill="none" transform="scale(-1 1)"></path><path d="M -15 -25 L 30 0 L -15 25 z" stroke="black" fill="none" transform="scale(-1 1) translate(-100 0)"></path><text x="72" y="-18" fill="#0a0" class="caption">1</text><text x="172" y="-18" fill="#44f" class="caption">2</text><text x="20" y="-18" fill="#f44" class="caption">3</text><text x="120" y="-18" fill="black" class="caption">4</text></g></svg> 12 | -------------------------------------------------------------------------------- /img/17-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apachecn/eloquent-js-3e-zh/12ed9090d2ddb50e23255e1a3790e5fdb849979b/img/17-4.png -------------------------------------------------------------------------------- /img/17-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apachecn/eloquent-js-3e-zh/12ed9090d2ddb50e23255e1a3790e5fdb849979b/img/17-5.png -------------------------------------------------------------------------------- /img/18-0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apachecn/eloquent-js-3e-zh/12ed9090d2ddb50e23255e1a3790e5fdb849979b/img/18-0.jpg -------------------------------------------------------------------------------- /img/19-0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apachecn/eloquent-js-3e-zh/12ed9090d2ddb50e23255e1a3790e5fdb849979b/img/19-0.jpg -------------------------------------------------------------------------------- /img/19-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apachecn/eloquent-js-3e-zh/12ed9090d2ddb50e23255e1a3790e5fdb849979b/img/19-1.png -------------------------------------------------------------------------------- /img/19-2.svg: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> 2 | <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="355" height="155" viewBox="-2 -2 355 155"><g><rect x="0" y="15" width="75" height="15" fill="#bbbbff"></rect><rect x="75" y="30" width="60" height="15" fill="#bbbbff"></rect><rect x="135" y="45" width="15" height="60" fill="#bbbbff"></rect><rect x="60" y="105" width="75" height="15" fill="#bbbbff"></rect><rect x="75" y="45" width="15" height="30" fill="#bbbbff"></rect><rect x="45" y="30" width="15" height="75" fill="#bbbbff"></rect><rect x="90" y="120" width="30" height="30" fill="#bbbbff"></rect><rect x="15" y="90" width="15" height="30" fill="#bbbbff"></rect><g><path d="M 15.5 0.5 L 15.5 150.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 30.5 0.5 L 30.5 150.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 45.5 0.5 L 45.5 150.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 60.5 0.5 L 60.5 150.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 75.5 0.5 L 75.5 150.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 90.5 0.5 L 90.5 150.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 105.5 0.5 L 105.5 150.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 120.5 0.5 L 120.5 150.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 135.5 0.5 L 135.5 150.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 0.5 15.5 L 150.5 15.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 0.5 30.5 L 150.5 30.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 0.5 45.5 L 150.5 45.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 0.5 60.5 L 150.5 60.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 0.5 75.5 L 150.5 75.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 0.5 90.5 L 150.5 90.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 0.5 105.5 L 150.5 105.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 0.5 120.5 L 150.5 120.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 0.5 135.5 L 150.5 135.5" width="150" height="150" stroke-width="1" stroke="#444"></path><rect x="0.5" y="0.5" width="150" height="150" stroke-width="1" stroke="#444" fill="none"></rect></g><ellipse cx="112.5" cy="67.5" rx="3.75" ry="3.75" fill="#a33" width="7.5" height="7.5"></ellipse><rect x="275" y="75" width="15" height="30" fill="#ffe6c0"></rect><rect x="290" y="45" width="45" height="60" fill="#ffe6c0"></rect><rect x="260" y="30" width="15" height="75" fill="#ffe6c0"></rect><rect x="200" y="15" width="75" height="15" fill="#bbbbff"></rect><rect x="275" y="30" width="60" height="15" fill="#bbbbff"></rect><rect x="335" y="45" width="15" height="60" fill="#bbbbff"></rect><rect x="260" y="105" width="75" height="15" fill="#bbbbff"></rect><rect x="275" y="45" width="15" height="30" fill="#bbbbff"></rect><rect x="245" y="30" width="15" height="75" fill="#bbbbff"></rect><rect x="290" y="120" width="30" height="30" fill="#bbbbff"></rect><rect x="215" y="90" width="15" height="30" fill="#bbbbff"></rect><g><path d="M 215.5 0.5 L 215.5 150.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 230.5 0.5 L 230.5 150.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 245.5 0.5 L 245.5 150.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 260.5 0.5 L 260.5 150.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 275.5 0.5 L 275.5 150.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 290.5 0.5 L 290.5 150.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 305.5 0.5 L 305.5 150.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 320.5 0.5 L 320.5 150.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 335.5 0.5 L 335.5 150.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 200.5 15.5 L 350.5 15.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 200.5 30.5 L 350.5 30.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 200.5 45.5 L 350.5 45.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 200.5 60.5 L 350.5 60.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 200.5 75.5 L 350.5 75.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 200.5 90.5 L 350.5 90.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 200.5 105.5 L 350.5 105.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 200.5 120.5 L 350.5 120.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 200.5 135.5 L 350.5 135.5" width="150" height="150" stroke-width="1" stroke="#444"></path><rect x="200.5" y="0.5" width="150" height="150" stroke-width="1" stroke="#444" fill="none"></rect></g><ellipse cx="312.5" cy="67.5" rx="3.75" ry="3.75" fill="#a33" width="7.5" height="7.5"></ellipse></g></svg> -------------------------------------------------------------------------------- /img/19-3.svg: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> 2 | <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="355" height="155" viewBox="-2 -2 355 155"><g><rect x="30" y="15" width="15" height="15" fill="#000"></rect><rect x="45" y="30" width="15" height="15" fill="#000"></rect><rect x="45" y="45" width="15" height="15" fill="#000"></rect><rect x="60" y="60" width="15" height="15" fill="#000"></rect><rect x="75" y="75" width="15" height="15" fill="#000"></rect><rect x="90" y="90" width="15" height="15" fill="#000"></rect><rect x="90" y="105" width="15" height="15" fill="#000"></rect><rect x="105" y="120" width="15" height="15" fill="#000"></rect><g><path d="M 15.5 0.5 L 15.5 150.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 30.5 0.5 L 30.5 150.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 45.5 0.5 L 45.5 150.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 60.5 0.5 L 60.5 150.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 75.5 0.5 L 75.5 150.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 90.5 0.5 L 90.5 150.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 105.5 0.5 L 105.5 150.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 120.5 0.5 L 120.5 150.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 135.5 0.5 L 135.5 150.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 0.5 15.5 L 150.5 15.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 0.5 30.5 L 150.5 30.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 0.5 45.5 L 150.5 45.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 0.5 60.5 L 150.5 60.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 0.5 75.5 L 150.5 75.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 0.5 90.5 L 150.5 90.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 0.5 105.5 L 150.5 105.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 0.5 120.5 L 150.5 120.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 0.5 135.5 L 150.5 135.5" width="150" height="150" stroke-width="1" stroke="#444"></path><rect x="0.5" y="0.5" width="150" height="150" stroke-width="1" stroke="#444" fill="none"></rect></g><ellipse cx="37.5" cy="22.5" rx="3.75" ry="3.75" fill="#fff" width="7.5" height="7.5"></ellipse><ellipse cx="112.5" cy="127.5" rx="3.75" ry="3.75" fill="#fff" width="7.5" height="7.5"></ellipse><rect x="230" y="15" width="15" height="15" fill="#000"></rect><rect x="230" y="30" width="15" height="15" fill="#000"></rect><rect x="245" y="30" width="15" height="15" fill="#000"></rect><rect x="245" y="45" width="15" height="15" fill="#000"></rect><rect x="245" y="60" width="15" height="15" fill="#000"></rect><rect x="260" y="60" width="15" height="15" fill="#000"></rect><rect x="260" y="75" width="15" height="15" fill="#000"></rect><rect x="275" y="75" width="15" height="15" fill="#000"></rect><rect x="275" y="90" width="15" height="15" fill="#000"></rect><rect x="290" y="90" width="15" height="15" fill="#000"></rect><rect x="290" y="105" width="15" height="15" fill="#000"></rect><rect x="290" y="120" width="15" height="15" fill="#000"></rect><rect x="305" y="120" width="15" height="15" fill="#000"></rect><g><path d="M 215.5 0.5 L 215.5 150.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 230.5 0.5 L 230.5 150.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 245.5 0.5 L 245.5 150.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 260.5 0.5 L 260.5 150.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 275.5 0.5 L 275.5 150.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 290.5 0.5 L 290.5 150.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 305.5 0.5 L 305.5 150.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 320.5 0.5 L 320.5 150.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 335.5 0.5 L 335.5 150.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 200.5 15.5 L 350.5 15.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 200.5 30.5 L 350.5 30.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 200.5 45.5 L 350.5 45.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 200.5 60.5 L 350.5 60.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 200.5 75.5 L 350.5 75.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 200.5 90.5 L 350.5 90.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 200.5 105.5 L 350.5 105.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 200.5 120.5 L 350.5 120.5" width="150" height="150" stroke-width="1" stroke="#444"></path><path d="M 200.5 135.5 L 350.5 135.5" width="150" height="150" stroke-width="1" stroke="#444"></path><rect x="200.5" y="0.5" width="150" height="150" stroke-width="1" stroke="#444" fill="none"></rect></g><ellipse cx="237.5" cy="22.5" rx="3.75" ry="3.75" fill="#fff" width="7.5" height="7.5"></ellipse><ellipse cx="312.5" cy="127.5" rx="3.75" ry="3.75" fill="#fff" width="7.5" height="7.5"></ellipse></g></svg> -------------------------------------------------------------------------------- /img/2-0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apachecn/eloquent-js-3e-zh/12ed9090d2ddb50e23255e1a3790e5fdb849979b/img/2-0.jpg -------------------------------------------------------------------------------- /img/2-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apachecn/eloquent-js-3e-zh/12ed9090d2ddb50e23255e1a3790e5fdb849979b/img/2-1.png -------------------------------------------------------------------------------- /img/2-2.svg: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> 2 | <!-- Created with Inkscape (http://www.inkscape.org/) --> 3 | 4 | <svg 5 | xmlns:dc="http://purl.org/dc/elements/1.1/" 6 | xmlns:cc="http://creativecommons.org/ns#" 7 | xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 8 | xmlns:svg="http://www.w3.org/2000/svg" 9 | xmlns="http://www.w3.org/2000/svg" 10 | xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" 11 | xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" 12 | width="204.48096" 13 | height="19.999929" 14 | id="svg3216" 15 | version="1.1" 16 | inkscape:version="0.48.4 r9939" 17 | sodipodi:docname="New document 8"> 18 | <defs 19 | id="defs3218"> 20 | <marker 21 | inkscape:stockid="Arrow1Send" 22 | orient="auto" 23 | refY="0" 24 | refX="0" 25 | id="Arrow1Send" 26 | style="overflow:visible"> 27 | <path 28 | id="path3774" 29 | d="M 0,0 5,-5 -12.5,0 5,5 0,0 z" 30 | style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt" 31 | transform="matrix(-0.2,0,0,-0.2,-1.2,0)" 32 | inkscape:connector-curvature="0" /> 33 | </marker> 34 | </defs> 35 | <sodipodi:namedview 36 | id="base" 37 | pagecolor="#ffffff" 38 | bordercolor="#666666" 39 | borderopacity="1.0" 40 | inkscape:pageopacity="0.0" 41 | inkscape:pageshadow="2" 42 | inkscape:zoom="0.35" 43 | inkscape:cx="156.78125" 44 | inkscape:cy="-138.56231" 45 | inkscape:document-units="px" 46 | inkscape:current-layer="layer1" 47 | showgrid="false" 48 | fit-margin-top="0" 49 | fit-margin-left="0" 50 | fit-margin-right="0" 51 | fit-margin-bottom="0" 52 | inkscape:window-width="1600" 53 | inkscape:window-height="875" 54 | inkscape:window-x="0" 55 | inkscape:window-y="25" 56 | inkscape:window-maximized="0" /> 57 | <metadata 58 | id="metadata3221"> 59 | <rdf:RDF> 60 | <cc:Work 61 | rdf:about=""> 62 | <dc:format>image/svg+xml</dc:format> 63 | <dc:type 64 | rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> 65 | <dc:title></dc:title> 66 | </cc:Work> 67 | </rdf:RDF> 68 | </metadata> 69 | <g 70 | inkscape:label="Layer 1" 71 | inkscape:groupmode="layer" 72 | id="layer1" 73 | transform="translate(-218.21875,-373.79994)"> 74 | <path 75 | style="fill:none;stroke:#000000;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)" 76 | d="m 218.236,384.24914 190.41375,0" 77 | id="path5135" 78 | inkscape:connector-curvature="0" 79 | sodipodi:nodetypes="cc" /> 80 | </g> 81 | </svg> 82 | -------------------------------------------------------------------------------- /img/2-3.svg: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> 2 | <!-- Created with Inkscape (http://www.inkscape.org/) --> 3 | 4 | <svg 5 | xmlns:dc="http://purl.org/dc/elements/1.1/" 6 | xmlns:cc="http://creativecommons.org/ns#" 7 | xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 8 | xmlns:svg="http://www.w3.org/2000/svg" 9 | xmlns="http://www.w3.org/2000/svg" 10 | xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" 11 | xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" 12 | width="205.10103" 13 | height="85.750778" 14 | id="svg3283" 15 | version="1.1" 16 | inkscape:version="0.48.4 r9939" 17 | sodipodi:docname="New document 11"> 18 | <defs 19 | id="defs3285"> 20 | <marker 21 | inkscape:stockid="Arrow1Send" 22 | orient="auto" 23 | refY="0" 24 | refX="0" 25 | id="Arrow1Send" 26 | style="overflow:visible"> 27 | <path 28 | id="path3774" 29 | d="M 0,0 5,-5 -12.5,0 5,5 0,0 z" 30 | style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt" 31 | transform="matrix(-0.2,0,0,-0.2,-1.2,0)" 32 | inkscape:connector-curvature="0" /> 33 | </marker> 34 | <marker 35 | inkscape:stockid="Arrow1Send" 36 | orient="auto" 37 | refY="0" 38 | refX="0" 39 | id="marker3266" 40 | style="overflow:visible"> 41 | <path 42 | id="path3268" 43 | d="M 0,0 5,-5 -12.5,0 5,5 0,0 z" 44 | style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt" 45 | transform="matrix(-0.2,0,0,-0.2,-1.2,0)" 46 | inkscape:connector-curvature="0" /> 47 | </marker> 48 | <marker 49 | inkscape:stockid="Arrow1Send" 50 | orient="auto" 51 | refY="0" 52 | refX="0" 53 | id="marker3270" 54 | style="overflow:visible"> 55 | <path 56 | id="path3272" 57 | d="M 0,0 5,-5 -12.5,0 5,5 0,0 z" 58 | style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt" 59 | transform="matrix(-0.2,0,0,-0.2,-1.2,0)" 60 | inkscape:connector-curvature="0" /> 61 | </marker> 62 | <marker 63 | inkscape:stockid="Arrow1Send" 64 | orient="auto" 65 | refY="0" 66 | refX="0" 67 | id="marker3274" 68 | style="overflow:visible"> 69 | <path 70 | id="path3276" 71 | d="M 0,0 5,-5 -12.5,0 5,5 0,0 z" 72 | style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt" 73 | transform="matrix(-0.2,0,0,-0.2,-1.2,0)" 74 | inkscape:connector-curvature="0" /> 75 | </marker> 76 | </defs> 77 | <sodipodi:namedview 78 | id="base" 79 | pagecolor="#ffffff" 80 | bordercolor="#666666" 81 | borderopacity="1.0" 82 | inkscape:pageopacity="0.0" 83 | inkscape:pageshadow="2" 84 | inkscape:zoom="0.35" 85 | inkscape:cx="1288.581" 86 | inkscape:cy="-271.41478" 87 | inkscape:document-units="px" 88 | inkscape:current-layer="layer1" 89 | showgrid="false" 90 | fit-margin-top="0" 91 | fit-margin-left="0" 92 | fit-margin-right="0" 93 | fit-margin-bottom="0" 94 | inkscape:window-width="1600" 95 | inkscape:window-height="875" 96 | inkscape:window-x="0" 97 | inkscape:window-y="25" 98 | inkscape:window-maximized="0" /> 99 | <metadata 100 | id="metadata3288"> 101 | <rdf:RDF> 102 | <cc:Work 103 | rdf:about=""> 104 | <dc:format>image/svg+xml</dc:format> 105 | <dc:type 106 | rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> 107 | <dc:title></dc:title> 108 | </cc:Work> 109 | </rdf:RDF> 110 | </metadata> 111 | <g 112 | inkscape:label="Layer 1" 113 | inkscape:groupmode="layer" 114 | id="layer1" 115 | transform="translate(913.58095,-175.19662)"> 116 | <g 117 | id="g3322" 118 | transform="matrix(0,-1,1,0,-1032.3622,-596.20924)"> 119 | <path 120 | style="fill:none;stroke:#000000;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)" 121 | d="m -815.78349,118.91917 1.01015,27.77919" 122 | id="path4943" 123 | inkscape:connector-curvature="0" 124 | sodipodi:nodetypes="cc" /> 125 | <path 126 | style="fill:none;stroke:#000000;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)" 127 | d="m -807.70227,168.41664 c 0,0 67.6802,38.3858 7.07106,95.9645" 128 | id="path5139" 129 | inkscape:connector-curvature="0" 130 | sodipodi:nodetypes="cc" /> 131 | <path 132 | sodipodi:nodetypes="cc" 133 | inkscape:connector-curvature="0" 134 | id="path5141" 135 | d="m -813.76319,274.48267 1.01015,35.35534" 136 | style="fill:none;stroke:#000000;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)" /> 137 | <path 138 | sodipodi:nodetypes="cc" 139 | inkscape:connector-curvature="0" 140 | id="path5159" 141 | d="m -820.86915,168.41664 c 0,0 -67.68021,38.3858 -7.07106,95.9645" 142 | style="fill:none;stroke:#000000;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)" /> 143 | <path 144 | transform="translate(-888.97485,115.42425)" 145 | d="m 80.307123,50.755318 c 0,3.347351 -2.713564,6.060915 -6.060915,6.060915 -3.347351,0 -6.060915,-2.713564 -6.060915,-6.060915 0,-3.347351 2.713564,-6.060915 6.060915,-6.060915 3.347351,0 6.060915,2.713564 6.060915,6.060915 z" 146 | sodipodi:ry="6.060915" 147 | sodipodi:rx="6.060915" 148 | sodipodi:cy="50.755318" 149 | sodipodi:cx="74.246208" 150 | id="path3001" 151 | style="fill:#ff0000;fill-opacity:1;stroke:none" 152 | sodipodi:type="arc" /> 153 | </g> 154 | </g> 155 | </svg> 156 | -------------------------------------------------------------------------------- /img/2-4.svg: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> 2 | <!-- Created with Inkscape (http://www.inkscape.org/) --> 3 | 4 | <svg 5 | xmlns:dc="http://purl.org/dc/elements/1.1/" 6 | xmlns:cc="http://creativecommons.org/ns#" 7 | xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 8 | xmlns:svg="http://www.w3.org/2000/svg" 9 | xmlns="http://www.w3.org/2000/svg" 10 | xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" 11 | xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" 12 | width="238.24316" 13 | height="104.35892" 14 | id="svg2" 15 | version="1.1" 16 | inkscape:version="0.48.4 r9939" 17 | sodipodi:docname="controlflow-nested-else.svg"> 18 | <defs 19 | id="defs4"> 20 | <marker 21 | inkscape:stockid="Arrow1Send" 22 | orient="auto" 23 | refY="0" 24 | refX="0" 25 | id="Arrow1Send" 26 | style="overflow:visible"> 27 | <path 28 | id="path3774" 29 | d="M 0,0 5,-5 -12.5,0 5,5 0,0 z" 30 | style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt" 31 | transform="matrix(-0.2,0,0,-0.2,-1.2,0)" 32 | inkscape:connector-curvature="0" /> 33 | </marker> 34 | <marker 35 | inkscape:stockid="Arrow2Mend" 36 | orient="auto" 37 | refY="0" 38 | refX="0" 39 | id="Arrow2Mend" 40 | style="overflow:visible"> 41 | <path 42 | id="path3786" 43 | style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" 44 | d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" 45 | transform="scale(-0.6,-0.6)" 46 | inkscape:connector-curvature="0" /> 47 | </marker> 48 | <marker 49 | inkscape:stockid="Arrow1Mend" 50 | orient="auto" 51 | refY="0" 52 | refX="0" 53 | id="Arrow1Mend" 54 | style="overflow:visible"> 55 | <path 56 | id="path3768" 57 | d="M 0,0 5,-5 -12.5,0 5,5 0,0 z" 58 | style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt" 59 | transform="matrix(-0.4,0,0,-0.4,-4,0)" 60 | inkscape:connector-curvature="0" /> 61 | </marker> 62 | <marker 63 | inkscape:stockid="Arrow1Lend" 64 | orient="auto" 65 | refY="0" 66 | refX="0" 67 | id="Arrow1Lend" 68 | style="overflow:visible"> 69 | <path 70 | id="path3762" 71 | d="M 0,0 5,-5 -12.5,0 5,5 0,0 z" 72 | style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt" 73 | transform="matrix(-0.8,0,0,-0.8,-10,0)" 74 | inkscape:connector-curvature="0" /> 75 | </marker> 76 | </defs> 77 | <sodipodi:namedview 78 | id="base" 79 | pagecolor="#ffffff" 80 | bordercolor="#666666" 81 | borderopacity="1.0" 82 | inkscape:pageopacity="0.0" 83 | inkscape:pageshadow="2" 84 | inkscape:zoom="2.8" 85 | inkscape:cx="182.61224" 86 | inkscape:cy="45.356254" 87 | inkscape:document-units="px" 88 | inkscape:current-layer="layer1" 89 | showgrid="false" 90 | showguides="true" 91 | inkscape:guide-bbox="true" 92 | inkscape:window-width="1600" 93 | inkscape:window-height="875" 94 | inkscape:window-x="0" 95 | inkscape:window-y="25" 96 | inkscape:window-maximized="0" 97 | fit-margin-top="0" 98 | fit-margin-left="0" 99 | fit-margin-right="3" 100 | fit-margin-bottom="0" /> 101 | <metadata 102 | id="metadata7"> 103 | <rdf:RDF> 104 | <cc:Work 105 | rdf:about=""> 106 | <dc:format>image/svg+xml</dc:format> 107 | <dc:type 108 | rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> 109 | <dc:title></dc:title> 110 | </cc:Work> 111 | </rdf:RDF> 112 | </metadata> 113 | <g 114 | inkscape:label="Layer 1" 115 | inkscape:groupmode="layer" 116 | id="layer1" 117 | transform="translate(-222.69525,-394.46429)"> 118 | <path 119 | sodipodi:nodetypes="cc" 120 | inkscape:connector-curvature="0" 121 | id="path4943" 122 | d="m 226.69525,431.70744 27.77919,1.01015" 123 | style="fill:none;stroke:#000000;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)" /> 124 | <path 125 | sodipodi:nodetypes="cc" 126 | inkscape:connector-curvature="0" 127 | id="path5139" 128 | d="m 274.76415,441.21724 c 2.14286,43.57143 36.60008,44.46591 47.39307,47.42819" 129 | style="fill:none;stroke:#000000;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)" /> 130 | <path 131 | style="fill:none;stroke:#000000;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)" 132 | d="m 411.18732,433.72774 35.35534,1.01015" 133 | id="path5141" 134 | inkscape:connector-curvature="0" 135 | sodipodi:nodetypes="cc" /> 136 | <path 137 | style="fill:none;stroke:#000000;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)" 138 | d="m 278.69272,425.19321 c 0,0 60.8858,-56.96593 122.75021,-4.57106" 139 | id="path5159" 140 | inkscape:connector-curvature="0" 141 | sodipodi:nodetypes="cc" /> 142 | <path 143 | sodipodi:type="arc" 144 | style="fill:#ff0000;fill-opacity:1;stroke:none" 145 | id="path3001" 146 | sodipodi:cx="74.246208" 147 | sodipodi:cy="50.755318" 148 | sodipodi:rx="6.060915" 149 | sodipodi:ry="6.060915" 150 | d="m 80.307123,50.755318 a 6.060915,6.060915 0 1 1 -12.12183,0 6.060915,6.060915 0 1 1 12.12183,0 z" 151 | transform="matrix(0,1,1,0,223.20033,358.51608)" /> 152 | <path 153 | transform="matrix(0,1,1,0,291.77176,418.51608)" 154 | d="m 80.307123,50.755318 a 6.060915,6.060915 0 1 1 -12.12183,0 6.060915,6.060915 0 1 1 12.12183,0 z" 155 | sodipodi:ry="6.060915" 156 | sodipodi:rx="6.060915" 157 | sodipodi:cy="50.755318" 158 | sodipodi:cx="74.246208" 159 | id="path3002" 160 | style="fill:#ff0000;fill-opacity:1;stroke:none" 161 | sodipodi:type="arc" /> 162 | <path 163 | style="fill:none;stroke:#000000;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)" 164 | d="m 341.54987,484.43152 c 0,0 0.96327,-38.82118 55.9645,-46.85751" 165 | id="path3004" 166 | inkscape:connector-curvature="0" 167 | sodipodi:nodetypes="cc" /> 168 | <path 169 | sodipodi:nodetypes="cc" 170 | inkscape:connector-curvature="0" 171 | id="path3006" 172 | d="m 350.83558,490.14581 c 24.92879,-3.90484 44.71588,-30.84607 52.03593,-41.14323" 173 | style="fill:none;stroke:#000000;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)" /> 174 | </g> 175 | </svg> 176 | -------------------------------------------------------------------------------- /img/2-5.svg: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> 2 | <!-- Created with Inkscape (http://www.inkscape.org/) --> 3 | 4 | <svg 5 | xmlns:dc="http://purl.org/dc/elements/1.1/" 6 | xmlns:cc="http://creativecommons.org/ns#" 7 | xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 8 | xmlns:svg="http://www.w3.org/2000/svg" 9 | xmlns="http://www.w3.org/2000/svg" 10 | xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" 11 | xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" 12 | width="206.31815" 13 | height="72.428215" 14 | id="svg2" 15 | version="1.1" 16 | inkscape:version="0.48.4 r9939" 17 | sodipodi:docname="controlflow-loop.svg"> 18 | <defs 19 | id="defs4"> 20 | <marker 21 | inkscape:stockid="Arrow1Send" 22 | orient="auto" 23 | refY="0" 24 | refX="0" 25 | id="Arrow1Send" 26 | style="overflow:visible"> 27 | <path 28 | id="path3774" 29 | d="M 0,0 5,-5 -12.5,0 5,5 0,0 z" 30 | style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt" 31 | transform="matrix(-0.2,0,0,-0.2,-1.2,0)" 32 | inkscape:connector-curvature="0" /> 33 | </marker> 34 | <marker 35 | inkscape:stockid="Arrow2Mend" 36 | orient="auto" 37 | refY="0" 38 | refX="0" 39 | id="Arrow2Mend" 40 | style="overflow:visible"> 41 | <path 42 | id="path3786" 43 | style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" 44 | d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" 45 | transform="scale(-0.6,-0.6)" 46 | inkscape:connector-curvature="0" /> 47 | </marker> 48 | <marker 49 | inkscape:stockid="Arrow1Mend" 50 | orient="auto" 51 | refY="0" 52 | refX="0" 53 | id="Arrow1Mend" 54 | style="overflow:visible"> 55 | <path 56 | id="path3768" 57 | d="M 0,0 5,-5 -12.5,0 5,5 0,0 z" 58 | style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt" 59 | transform="matrix(-0.4,0,0,-0.4,-4,0)" 60 | inkscape:connector-curvature="0" /> 61 | </marker> 62 | <marker 63 | inkscape:stockid="Arrow1Lend" 64 | orient="auto" 65 | refY="0" 66 | refX="0" 67 | id="Arrow1Lend" 68 | style="overflow:visible"> 69 | <path 70 | id="path3762" 71 | d="M 0,0 5,-5 -12.5,0 5,5 0,0 z" 72 | style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt" 73 | transform="matrix(-0.8,0,0,-0.8,-10,0)" 74 | inkscape:connector-curvature="0" /> 75 | </marker> 76 | </defs> 77 | <sodipodi:namedview 78 | id="base" 79 | pagecolor="#ffffff" 80 | bordercolor="#666666" 81 | borderopacity="1.0" 82 | inkscape:pageopacity="0.0" 83 | inkscape:pageshadow="2" 84 | inkscape:zoom="2.8" 85 | inkscape:cx="30.225462" 86 | inkscape:cy="52.400366" 87 | inkscape:document-units="px" 88 | inkscape:current-layer="layer1" 89 | showgrid="false" 90 | showguides="true" 91 | inkscape:guide-bbox="true" 92 | inkscape:window-width="1600" 93 | inkscape:window-height="875" 94 | inkscape:window-x="0" 95 | inkscape:window-y="25" 96 | inkscape:window-maximized="0" 97 | fit-margin-top="0" 98 | fit-margin-left="0" 99 | fit-margin-right="0" 100 | fit-margin-bottom="0" /> 101 | <metadata 102 | id="metadata7"> 103 | <rdf:RDF> 104 | <cc:Work 105 | rdf:about=""> 106 | <dc:format>image/svg+xml</dc:format> 107 | <dc:type 108 | rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> 109 | <dc:title /> 110 | </cc:Work> 111 | </rdf:RDF> 112 | </metadata> 113 | <g 114 | inkscape:label="Layer 1" 115 | inkscape:groupmode="layer" 116 | id="layer1" 117 | transform="translate(-376.5106,-433.43911)"> 118 | <path 119 | sodipodi:nodetypes="csc" 120 | inkscape:connector-curvature="0" 121 | id="path5161" 122 | d="m 478.22234,451.00514 c 29.28572,23.75 27.61731,51.59627 -8.71166,51.57646 -36.44966,-0.0199 -18.10635,-25.27225 -9.3957,-39.5054" 123 | style="fill:none;stroke:#000000;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)" /> 124 | <path 125 | style="fill:none;stroke:#000000;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)" 126 | d="m 379.43917,445.98075 73.1512,-1.01015" 127 | id="path3003" 128 | inkscape:connector-curvature="0" 129 | sodipodi:nodetypes="cc" /> 130 | <path 131 | sodipodi:nodetypes="cc" 132 | inkscape:connector-curvature="0" 133 | id="path3005" 134 | d="m 482.59676,443.96045 87.76125,-1.01015" 135 | style="fill:none;stroke:#000000;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)" /> 136 | <path 137 | transform="matrix(0,-1,1,0,422.09693,518.66704)" 138 | d="m 80.307123,50.755318 c 0,3.347351 -2.713564,6.060915 -6.060915,6.060915 -3.347351,0 -6.060915,-2.713564 -6.060915,-6.060915 0,-3.347351 2.713564,-6.060915 6.060915,-6.060915 3.347351,0 6.060915,2.713564 6.060915,6.060915 z" 139 | sodipodi:ry="6.060915" 140 | sodipodi:rx="6.060915" 141 | sodipodi:cy="50.755318" 142 | sodipodi:cx="74.246208" 143 | id="path3004" 144 | style="fill:#ff0000;fill-opacity:1;stroke:none" 145 | sodipodi:type="arc" /> 146 | </g> 147 | </svg> 148 | -------------------------------------------------------------------------------- /img/20-0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apachecn/eloquent-js-3e-zh/12ed9090d2ddb50e23255e1a3790e5fdb849979b/img/20-0.jpg -------------------------------------------------------------------------------- /img/21-0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apachecn/eloquent-js-3e-zh/12ed9090d2ddb50e23255e1a3790e5fdb849979b/img/21-0.jpg -------------------------------------------------------------------------------- /img/21-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apachecn/eloquent-js-3e-zh/12ed9090d2ddb50e23255e1a3790e5fdb849979b/img/21-1.png -------------------------------------------------------------------------------- /img/3-0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apachecn/eloquent-js-3e-zh/12ed9090d2ddb50e23255e1a3790e5fdb849979b/img/3-0.jpg -------------------------------------------------------------------------------- /img/4-0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apachecn/eloquent-js-3e-zh/12ed9090d2ddb50e23255e1a3790e5fdb849979b/img/4-0.jpg -------------------------------------------------------------------------------- /img/4-1.svg: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> 2 | <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="505" height="345" viewBox="-2 -2 505 345"><defs> 3 | <g id="squirrel"> 4 | <path d="M 30 0 C 13 0 0 14 0 31 C 0 41 5 50 13 55 C 13 55 13 55 13 54 C 13 49 17 44 22 44 C 22 44 24 44 24 45 C 26 45 29 47 30 51 C 30 55 30 60 28 63 L 28 63 C 28 64 26 65 26 67 C 26 69 25 71 25 72 C 25 73 25 73 25 73 C 25 73 25 73 25 73 C 24 85 29 96 39 99 C 42 100 43 100 46 99 C 38 94 36 83 39 74 C 42 69 46 65 50 60 C 54 56 57 50 59 44 C 59 40 61 36 61 32 C 61 32 61 32 61 32 C 61 32 61 31 61 31 C 61 14 47 0 30 0 z" fill="#ea4" stroke="none"></path> 5 | <path d="M 74 14 C 70 17 67 19 64 23 C 64 23 64 23 64 23 C 64 24 64 24 64 26 C 62 32 68 40 76 41 C 86 44 93 40 96 33 C 95 29 91 26 84 23 C 82 22 79 22 78 21 L 74 14 z M 79 26 C 80 26 82 27 82 28 C 82 29 80 31 79 31 C 78 31 76 29 76 28 C 76 27 78 26 79 26 z" fill="#ea4" stroke="none"></path> 6 | <path d="M 68 41 C 68 41 68 41 68 41 L 68 41 L 68 41 C 64 46 57 56 43 71 C 43 72 42 73 42 74 C 39 81 39 88 43 94 C 43 94 45 94 45 95 C 45 95 45 95 45 95 C 46 95 46 95 46 95 C 46 95 46 95 46 95 C 46 96 47 96 47 96 C 49 97 50 97 50 99 C 53 99 55 100 57 100 L 57 100 L 96 100 C 96 100 96 100 96 100 C 99 100 100 97 100 95 C 100 94 99 91 96 91 L 96 91 L 79 91 L 78 91 L 75 91 C 75 91 75 91 75 91 C 75 91 76 91 76 90 C 76 90 78 90 78 90 C 78 90 78 90 78 90 C 78 88 78 88 78 88 C 79 88 79 88 79 88 C 79 88 79 88 79 88 C 84 83 86 77 82 73 C 79 71 76 69 74 68 C 72 68 72 68 71 68 C 71 68 71 68 70 68 C 70 68 70 68 70 68 C 70 68 68 68 68 68 C 68 68 68 68 68 68 C 68 68 68 68 68 68 C 67 68 67 68 67 68 C 67 68 67 68 67 68 C 67 68 66 68 66 68 C 66 68 66 68 66 68 C 64 68 64 69 64 69 C 63 69 63 69 62 69 C 62 69 62 69 62 69 C 61 71 61 71 61 71 C 59 71 59 71 59 72 C 59 72 59 72 59 72 C 58 72 58 72 58 72 C 58 72 58 72 58 72 C 57 73 57 73 57 73 C 57 73 57 73 57 73 C 57 73 57 73 57 73 C 55 74 55 74 55 74 C 55 74 55 74 55 74 C 55 74 55 76 55 76 C 54 76 54 76 54 77 C 54 77 54 77 54 77 L 51 76 C 51 74 53 74 53 73 C 54 72 55 71 57 69 C 61 67 64 65 70 65 C 70 65 71 65 71 65 C 72 65 74 65 74 67 C 74 65 75 65 75 64 C 76 60 79 58 82 56 C 82 56 82 56 82 56 C 83 55 84 55 86 55 L 88 55 C 88 56 91 59 93 59 C 96 59 97 56 97 54 C 97 51 96 49 93 49 L 93 49 L 79 49 L 78 45 C 75 44 71 42 68 41 z" fill="#ea4" stroke="none"></path> 7 | </g> 8 | <g id="pizza"> 9 | <path d="M 4 96 L 74 38 A 92 92 0 0 0 4 4 Z" stroke="#b44" stroke-width="8" fill="none" stroke-linejoin="round"></path> 10 | <circle cx="20" cy="20" r="10" fill="#b44"></circle> 11 | <circle cx="40" cy="30" r="9" fill="#b44"></circle> 12 | <circle cx="15" cy="66" r="11" fill="#b44"></circle> 13 | <circle cx="12" cy="36" r="10" fill="#b44"></circle> 14 | <circle cx="37" cy="51" r="11" fill="#b44"></circle> 15 | <circle cx="62" cy="34" r="8" fill="#b44"></circle> 16 | </g> 17 | </defs> 18 | <g><g><path d="M 250 0 L 250 340" width="500" height="340" stroke-width="2" stroke="black"></path><path d="M 0 170 L 500 170" width="500" height="340" stroke-width="2" stroke="black"></path><rect x="0" y="0" width="500" height="340" stroke-width="2" stroke="black" fill="none"></rect></g><use x="150" y="20" opacity="0.3" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#pizza"></use><use x="20" y="20" opacity="0.3" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#squirrel"></use><text x="20" y="156" font-family="Georgia" font-size="17">No squirrel, no pizza</text><text x="199" y="153" font-family="Georgia" font-size="31">76</text><use x="150" y="190" opacity="0.3" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#pizza"></use><use x="20" y="190" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#squirrel"></use><text x="20" y="326" font-family="Georgia" font-size="17">Squirrel, no pizza</text><text x="214.5" y="323" font-family="Georgia" font-size="31">4</text><use x="400" y="20" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#pizza"></use><use x="270" y="20" opacity="0.3" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#squirrel"></use><text x="270" y="156" font-family="Georgia" font-size="17">No squirrel, pizza</text><text x="464.5" y="153" font-family="Georgia" font-size="31">9</text><use x="400" y="190" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#pizza"></use><use x="270" y="190" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#squirrel"></use><text x="270" y="326" font-family="Georgia" font-size="17">Squirrel, pizza</text><text x="464.5" y="323" font-family="Georgia" font-size="31">1</text></g></svg> -------------------------------------------------------------------------------- /img/4-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apachecn/eloquent-js-3e-zh/12ed9090d2ddb50e23255e1a3790e5fdb849979b/img/4-2.jpg -------------------------------------------------------------------------------- /img/4-3.svg: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> 2 | <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="393" height="76" viewBox="-2 -2 393 76"><style type="text/css"> 3 | @font-face { 4 | font-family: 'PT Mono'; 5 | font-style: normal; 6 | font-weight: 400; 7 | src: local('PT Mono'), local('PTMono-Regular'), url(http://themes.googleusercontent.com/static/fonts/ptmono/v1/jmle3kzCPnW8O7_gZGRDlQ.woff) format('woff'); 8 | } 9 | .objtext { font-family: "PT Mono"; font-size: 14px; stroke: none; } 10 | .objbox { border-radius: 2px; fill: white; stroke: black } 11 | .sep { stroke: #666 } 12 | </style> 13 | <g><g><rect x="0.5" y="0.5" width="104" height="51" class="objbox" rx="2" ry="2"></rect><text x="10" y="20" class="objtext">value: 1</text><text x="10" y="40" class="objtext">rest:</text></g><g><rect x="134.5" y="10.5" width="104" height="51" class="objbox" rx="2" ry="2"></rect><text x="144.5" y="30.5" class="objtext">value: 2</text><text x="144.5" y="50.5" class="objtext">rest:</text></g><path d="M 58.5 36.5 L 134.5 36.5" class="sep"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(102, 102, 102)" transform="translate(134.5 36.5) rotate(90) scale(1)"></path><g><rect x="268.5" y="20.5" width="120" height="51" class="objbox" rx="2" ry="2"></rect><text x="278.5" y="40.5" class="objtext">value: 3</text><text x="278.5" y="60.5" class="objtext">rest: null</text></g><path d="M 192.5 47.5 L 268.5 47.5" class="sep"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(102, 102, 102)" transform="translate(268.5 47.5) rotate(90) scale(1)"></path></g></svg> 14 | -------------------------------------------------------------------------------- /img/5-0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apachecn/eloquent-js-3e-zh/12ed9090d2ddb50e23255e1a3790e5fdb849979b/img/5-0.jpg -------------------------------------------------------------------------------- /img/5-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apachecn/eloquent-js-3e-zh/12ed9090d2ddb50e23255e1a3790e5fdb849979b/img/5-1.png -------------------------------------------------------------------------------- /img/6-0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apachecn/eloquent-js-3e-zh/12ed9090d2ddb50e23255e1a3790e5fdb849979b/img/6-0.jpg -------------------------------------------------------------------------------- /img/6-1.svg: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> 2 | <svg xmlns="http://www.w3.org/2000/svg" width="621" height="274" viewBox="-4 -82 621 274"><style> 3 | @font-face { 4 | font-family: 'PT Mono'; 5 | font-style: normal; 6 | font-weight: 400; 7 | src: local('PT Mono'), local('PTMono-Regular'), url(http://themes.googleusercontent.com/static/fonts/ptmono/v1/jmle3kzCPnW8O7_gZGRDlQ.woff) format('woff'); 8 | } 9 | .objtext { font-family: "PT Mono"; font-size: 14px; stroke: none; } 10 | .objbox { border-radius: 2px; fill: white; stroke: black } 11 | .sep { stroke: #666 } 12 | </style> 13 | <g><g><rect x="210.5" y="133.5" width="202" height="55" class="objbox"></rect><text x="221.5" y="154.5" class="objtext">toString: <function></text><text x="221.5" y="176.5" class="objtext">...</text></g><g><rect x="121.5" y="83.5" width="178" height="55" class="objbox"></rect><text x="132.5" y="104.5" class="objtext">teeth: "small"</text><text x="132.5" y="126.5" class="objtext">speak: <function></text></g><g><rect x="0.5" y="0.5" width="242" height="88" class="objbox"></rect><text x="11" y="21" class="objtext">killerRabbit</text><text x="11" y="54" class="objtext">teeth: "long, sharp, ..."</text><text x="11" y="76" class="objtext">type: "killer"</text><path d="M 0.5 33.5 L 242.5 33.5" class="sep"></path></g><g><rect x="282.5" y="-79.5" width="114" height="66" class="objbox"></rect><text x="293.5" y="-58.5" class="objtext">Rabbit</text><text x="293.5" y="-25.5" class="objtext">prototype</text><path d="M 282.5 -46.5 L 396.5 -46.5" class="sep"></path></g><path d="M 329.5 -19.5 L 259.5 83.5" class="sep"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(102, 102, 102)" transform="translate(259.5 83.5) rotate(214.20048413026853) scale(1)"></path><g><rect x="426.5" y="-9.5" width="186" height="110" class="objbox"></rect><text x="437.5" y="11.5" class="objtext">Object</text><text x="437.5" y="44.5" class="objtext">create: <function></text><text x="437.5" y="66.5" class="objtext">prototype</text><text x="437.5" y="88.5" class="objtext">...</text><path d="M 426.5 23.5 L 612.5 23.5" class="sep"></path></g><path d="M 432.5 70.5 L 331.5 133.5" class="sep"></path><path d="M 0 0 L 3 8 L 0 7 L -3 8 Z" stroke="none" fill="rgb(102, 102, 102)" transform="translate(331.5 133.5) rotate(238.0456370629486) scale(1)"></path></g></svg> 14 | -------------------------------------------------------------------------------- /img/7-0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apachecn/eloquent-js-3e-zh/12ed9090d2ddb50e23255e1a3790e5fdb849979b/img/7-0.jpg -------------------------------------------------------------------------------- /img/7-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apachecn/eloquent-js-3e-zh/12ed9090d2ddb50e23255e1a3790e5fdb849979b/img/7-1.png -------------------------------------------------------------------------------- /img/8-0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apachecn/eloquent-js-3e-zh/12ed9090d2ddb50e23255e1a3790e5fdb849979b/img/8-0.jpg -------------------------------------------------------------------------------- /img/9-0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apachecn/eloquent-js-3e-zh/12ed9090d2ddb50e23255e1a3790e5fdb849979b/img/9-0.jpg -------------------------------------------------------------------------------- /img/9-1.svg: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> 2 | <svg 3 | xmlns:svg="http://www.w3.org/2000/svg" 4 | xmlns="http://www.w3.org/2000/svg" 5 | height="166.23486" 6 | version="1.1" 7 | width="618.75934"> 8 | <path 9 | d="m 502.86787,89.225694 h 13.16396" 10 | style="fill:none;stroke:#000000;stroke-width:2.63279247" 11 | id="path4"/> 12 | <path 13 | d="m 405.45455,89.225694 h 13.16396" 14 | style="fill:none;stroke:#000000;stroke-width:2.63279247" 15 | id="path6"/> 16 | <path 17 | d="M 234.32304,89.225694 H 247.487" 18 | style="fill:none;stroke:#000000;stroke-width:2.63279247" 19 | id="path8"/> 20 | <path 21 | d="m 193.51476,89.225694 h 13.16396" 22 | style="fill:none;stroke:#000000;stroke-width:2.63279247" 23 | id="path10"/> 24 | <path 25 | d="m 110.5818,89.225694 h 13.16396" 26 | style="fill:none;stroke:#000000;stroke-width:2.63279247" 27 | id="path12"/> 28 | <path 29 | d="m 418.61851,89.225694 q 13.16396,0 13.16396,-13.16396 v -3.290991 q 0,-13.163962 13.16396,-13.163962 h 31.59351 q 13.16396,0 13.16396,13.163962 v 3.290991 q 0,13.16396 13.16397,13.16396" 30 | style="fill:none;stroke:#000000;stroke-width:2.63279247" 31 | id="path14"/> 32 | <path 33 | d="M 502.86787,89.225694 H 476.53994" 34 | style="fill:none;stroke:#000000;stroke-width:2.63279247" 35 | id="path16"/> 36 | <path 37 | d="m 418.61851,89.225694 h 26.32792" 38 | style="fill:none;stroke:#000000;stroke-width:2.63279247" 39 | id="path18"/> 40 | <path 41 | d="M 405.45455,89.225694 H 392.29059" 42 | style="fill:none;stroke:#000000;stroke-width:2.63279247" 43 | id="path20"/> 44 | <path 45 | d="m 247.487,89.225694 h 13.16396" 46 | style="fill:none;stroke:#000000;stroke-width:2.63279247" 47 | id="path22"/> 48 | <path 49 | d="m 392.29059,89.225694 q -13.16397,0 -13.16397,13.163956 v 19.74595 q 0,13.16396 -13.16396,13.16396 h 0" 50 | style="fill:none;stroke:#000000;stroke-width:2.63279247" 51 | id="path24"/> 52 | <path 53 | d="m 260.65096,89.225694 q 13.16397,0 13.16397,13.163956 v 19.74595 q 0,13.16396 13.16396,13.16396 h 0" 54 | style="fill:none;stroke:#000000;stroke-width:2.63279247" 55 | id="path26"/> 56 | <path 57 | d="m 392.29059,89.225694 c -13.16397,0 -13.16397,0 -39.49189,0" 58 | style="fill:none;stroke:#000000;stroke-width:2.63279247" 59 | id="path28"/> 60 | <path 61 | d="m 260.65096,89.225694 c 13.16397,0 13.16397,0 39.49189,0" 62 | style="fill:none;stroke:#000000;stroke-width:2.63279247" 63 | id="path30"/> 64 | <path 65 | d="m 392.29059,89.225694 q -13.16397,0 -13.16397,-13.16396 V 56.31579 q 0,-13.163962 -13.16396,-13.163962 h -16.45495" 66 | style="fill:none;stroke:#000000;stroke-width:2.63279247" 67 | id="path32"/> 68 | <path 69 | d="m 260.65096,89.225694 q 13.16397,0 13.16397,-13.16396 V 56.31579 q 0,-13.163962 13.16396,-13.163962 h 16.45495" 70 | style="fill:none;stroke:#000000;stroke-width:2.63279247" 71 | id="path34"/> 72 | <path 73 | d="m 180.3508,89.225694 q 13.16396,0 13.16396,13.163956 v 3.29099 q 0,13.16397 -13.16396,13.16397 h -43.44108 q -13.16396,0 -13.16396,-13.16397 v -3.29099 q 0,-13.163956 13.16396,-13.163956" 74 | style="fill:none;stroke:#000000;stroke-width:2.63279247" 75 | id="path36"/> 76 | <path 77 | d="M 193.51476,89.225694 H 180.3508" 78 | style="fill:none;stroke:#000000;stroke-width:2.63279247" 79 | id="path38"/> 80 | <path 81 | d="m 123.74576,89.225694 h 13.16396" 82 | style="fill:none;stroke:#000000;stroke-width:2.63279247" 83 | id="path40"/> 84 | <desc 85 | id="desc42">Created with Raphaël 2.1.0</desc> 86 | <defs 87 | id="defs44" /> 88 | <rect 89 | x="206.67871" 90 | y="72.770744" 91 | width="27.64432" 92 | height="32.909904" 93 | r="0" 94 | rx="3.9491887" 95 | ry="3.9491887" 96 | style="fill:#dae9e5;stroke:#dae9e5;stroke-width:1.31639624" 97 | id="rect46" /> 98 | <text 99 | x="220.50089" 100 | y="89.225693" 101 | font="10px "Arial"" 102 | style="font-size:15.79675484px;font-style:normal;font-variant:normal;font-weight:normal;line-height:normal;text-anchor:middle;fill:#000000;stroke:none;font-family:Arial" 103 | font-size="12px" 104 | id="text48"> 105 | <tspan 106 | dy="5.9237828" 107 | id="tspan50">" "</tspan> 108 | </text> 109 | <rect 110 | x="21.562796" 111 | y="72.66703" 112 | width="89.122711" 113 | height="33.117336" 114 | r="0" 115 | rx="2.7850847" 116 | ry="3.974081" 117 | style="fill:#bada55;stroke:#bada55;stroke-width:1.10896111" 118 | id="rect52" /> 119 | <text 120 | x="47.394775" 121 | y="89.225693" 122 | font="10px "Arial"" 123 | style="font-size:15.79675484px;font-style:normal;font-variant:normal;font-weight:normal;line-height:normal;text-anchor:middle;fill:#000000;stroke:none;font-family:Arial" 124 | font-size="12px" 125 | id="text54"> 126 | <tspan 127 | id="tspan56"></tspan> 128 | </text> 129 | <text 130 | x="66.728333" 131 | y="94.361168" 132 | font="10px "Arial"" 133 | style="font-size:15.79675484px;font-style:normal;font-variant:normal;font-weight:normal;line-height:normal;text-anchor:middle;fill:#000000;stroke:none;font-family:Arial" 134 | font-size="12px" 135 | id="text3087"> 136 | <tspan 137 | id="tspan3089">boundary</tspan> 138 | </text> 139 | <rect 140 | x="515.90363" 141 | y="72.642578" 142 | width="81.317352" 143 | height="33.166233" 144 | r="0" 145 | rx="2.5411673" 146 | ry="3.979948" 147 | style="fill:#bada55;stroke:#bada55;stroke-width:1.06006885" 148 | id="rect58" /> 149 | <text 150 | x="556.56232" 151 | y="94.663254" 152 | font="10px "Arial"" 153 | style="font-size:15.79675484px;font-style:normal;font-variant:normal;font-weight:normal;line-height:normal;text-anchor:middle;fill:#000000;stroke:none;font-family:Arial" 154 | font-size="12px" 155 | id="text60"> 156 | <tspan 157 | id="tspan62">boundary</tspan> 158 | </text> 159 | <rect 160 | x="247.487" 161 | y="13.532914" 162 | width="157.96754" 163 | height="151.38556" 164 | r="0" 165 | rx="3.9491887" 166 | ry="3.9491887" 167 | style="fill:none;stroke:#a0a0a0;stroke-width:2.63279247;stroke-dasharray:7.89837727, 2.63279242" 168 | id="rect64" /> 169 | <text 170 | x="276.44772" 171 | y="4.9763379" 172 | font="10px "Arial"" 173 | style="font-size:13.16396236px;font-style:normal;font-variant:normal;font-weight:normal;line-height:normal;text-anchor:middle;fill:#000000;stroke:none;font-family:Arial" 174 | font-size="10px" 175 | id="text66"> 176 | <tspan 177 | dy="4.6073866" 178 | id="tspan68">Group #1</tspan> 179 | </text> 180 | <rect 181 | x="286.97888" 182 | y="118.8446" 183 | width="78.983772" 184 | height="32.909904" 185 | r="0" 186 | rx="3.9491887" 187 | ry="3.9491887" 188 | style="fill:#dae9e5;stroke:#dae9e5;stroke-width:1.31639624" 189 | id="rect70" /> 190 | <text 191 | x="326.47076" 192 | y="135.29956" 193 | font="10px "Arial"" 194 | style="font-size:15.79675484px;font-style:normal;font-variant:normal;font-weight:normal;line-height:normal;text-anchor:middle;fill:#000000;stroke:none;font-family:Arial" 195 | font-size="12px" 196 | id="text72"> 197 | <tspan 198 | dy="5.9237828" 199 | id="tspan74">"chicken"</tspan> 200 | </text> 201 | <rect 202 | x="300.14285" 203 | y="72.770744" 204 | width="52.655849" 205 | height="32.909904" 206 | r="0" 207 | rx="3.9491887" 208 | ry="3.9491887" 209 | style="fill:#dae9e5;stroke:#dae9e5;stroke-width:1.31639624" 210 | id="rect76" /> 211 | <text 212 | x="326.47076" 213 | y="89.225693" 214 | font="10px "Arial"" 215 | style="font-size:15.79675484px;font-style:normal;font-variant:normal;font-weight:normal;line-height:normal;text-anchor:middle;fill:#000000;stroke:none;font-family:Arial" 216 | font-size="12px" 217 | id="text78"> 218 | <tspan 219 | dy="5.9237828" 220 | id="tspan80">"cow"</tspan> 221 | </text> 222 | <rect 223 | x="303.43384" 224 | y="26.696877" 225 | width="46.073868" 226 | height="32.909904" 227 | r="0" 228 | rx="3.9491887" 229 | ry="3.9491887" 230 | style="fill:#dae9e5;stroke:#dae9e5;stroke-width:1.31639624" 231 | id="rect82" /> 232 | <text 233 | x="326.47076" 234 | y="43.151829" 235 | font="10px "Arial"" 236 | style="font-size:15.79675484px;font-style:normal;font-variant:normal;font-weight:normal;line-height:normal;text-anchor:middle;fill:#000000;stroke:none;font-family:Arial" 237 | font-size="12px" 238 | id="text84"> 239 | <tspan 240 | dy="5.9237828" 241 | id="tspan86">"pig"</tspan> 242 | </text> 243 | <rect 244 | x="136.90971" 245 | y="72.770744" 246 | width="43.441074" 247 | height="32.909904" 248 | r="0" 249 | rx="3.9491887" 250 | ry="3.9491887" 251 | style="fill:#bada55;stroke:#bada55;stroke-width:1.31639624" 252 | id="rect88" /> 253 | <text 254 | x="158.63025" 255 | y="89.225693" 256 | font="10px "Arial"" 257 | style="font-size:15.79675484px;font-style:normal;font-variant:normal;font-weight:normal;line-height:normal;text-anchor:middle;fill:#000000;stroke:none;font-family:Arial" 258 | font-size="12px" 259 | id="text90"> 260 | <tspan 261 | dy="5.9237828" 262 | id="tspan92">digit</tspan> 263 | </text> 264 | <rect 265 | x="444.94644" 266 | y="72.770744" 267 | width="31.59351" 268 | height="32.909904" 269 | r="0" 270 | rx="3.9491887" 271 | ry="3.9491887" 272 | style="fill:#dae9e5;stroke:#dae9e5;stroke-width:1.31639624" 273 | id="rect94" /> 274 | <text 275 | x="460.74319" 276 | y="89.225693" 277 | font="10px "Arial"" 278 | style="font-size:15.79675484px;font-style:normal;font-variant:normal;font-weight:normal;line-height:normal;text-anchor:middle;fill:#000000;stroke:none;font-family:Arial" 279 | font-size="12px" 280 | id="text96"> 281 | <tspan 282 | dy="5.9237828" 283 | id="tspan98">"s"</tspan> 284 | </text> 285 | <path 286 | d="M 7.8983762,89.225694 H 21.062338" 287 | style="fill:none;stroke:#000000;stroke-width:2.63279247" 288 | id="path100"/> 289 | <circle 290 | cx="10" 291 | cy="80.5" 292 | r="5" 293 | style="fill:#6b6659;stroke:#000000;stroke-width:2" 294 | id="circle102" 295 | transform="matrix(1.3163962,0,0,1.3163962,-5.2655848,-16.744199)" /> 296 | <path 297 | d="M 610.86099,88.62152 H 597.69703" 298 | style="fill:none;stroke:#000000;stroke-width:2.63279247" 299 | id="path104"/> 300 | <circle 301 | cx="530" 302 | cy="80.5" 303 | r="5" 304 | style="fill:#6b6659;stroke:#000000;stroke-width:2" 305 | id="circle106" 306 | transform="matrix(1.3163962,0,0,1.3163962,-86.82901,-17.348373)" /> 307 | </svg> 308 | -------------------------------------------------------------------------------- /img/9-2.svg: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> 2 | <svg xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" version="1.1" width="578" height="342"> 3 | <defs> 4 | <style type="text/css">svg { 5 | background-color: #fff; } 6 | 7 | .root text, 8 | .root tspan { 9 | font: 12px Arial; } 10 | 11 | .root path { 12 | fill-opacity: 0; 13 | stroke-width: 2px; 14 | stroke: #000; } 15 | 16 | .root circle { 17 | fill: #6b6659; 18 | stroke-width: 2px; 19 | stroke: #000; } 20 | 21 | .anchor text, .any-character text { 22 | fill: #fff; } 23 | 24 | .anchor rect, .any-character rect { 25 | fill: #6b6659; } 26 | 27 | .escape text, .charset-escape text, .literal text { 28 | fill: #000; } 29 | 30 | .escape rect, .charset-escape rect { 31 | fill: #bada55; } 32 | 33 | .literal rect { 34 | fill: #dae9e5; } 35 | 36 | .charset .charset-box { 37 | fill: #cbcbba; } 38 | 39 | .subexp .subexp-label tspan, 40 | .charset .charset-label tspan, 41 | .match-fragment .repeat-label tspan { 42 | font-size: 10px; } 43 | 44 | .repeat-label { 45 | cursor: help; } 46 | 47 | .subexp .subexp-label tspan, 48 | .charset .charset-label tspan { 49 | dominant-baseline: text-after-edge; } 50 | 51 | .subexp .subexp-box { 52 | stroke: #908c83; 53 | stroke-dasharray: 6,2; 54 | stroke-width: 2px; 55 | fill-opacity: 0; } 56 | 57 | .quote { 58 | fill: #908c83; } 59 | </style> 60 | </defs> 61 | <metadata> 62 | <rdf:rdf> 63 | <cc:license rdf:about="http://creativecommons.org/licenses/by/3.0/"> 64 | <cc:permits rdf:resource="http://creativecommons.org/ns#Reproduction"></cc:permits> 65 | <cc:permits rdf:resource="http://creativecommons.org/ns#Distribution"></cc:permits> 66 | <cc:requires rdf:resource="http://creativecommons.org/ns#Notice"></cc:requires> 67 | <cc:requires rdf:resource="http://creativecommons.org/ns#Attribution"></cc:requires> 68 | <cc:permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks"></cc:permits> 69 | </cc:license> 70 | </rdf:rdf> 71 | </metadata> 72 | <desc>Created with Snap</desc><g class="root" transform="matrix(1.3,0,0,1.3,15,10)"><g class="regexp match" transform="matrix(1,0,0,1,10,0)"><path d="M92,127H112M282,127H302"></path><g class="match-fragment escape" transform="matrix(1,0,0,1,0,115)"><g class="label"><rect width="92" height="24" rx="3" ry="3"></rect><text x="0" y="0" transform="matrix(1,0,0,1,5,17)"><tspan>word boundary</tspan></text></g></g><g class="match-fragment subexp" transform="matrix(1,0,0,1,102,0)"><rect class="subexp-box" rx="3" ry="3" transform="matrix(1,0,0,1,0,11)" width="190" height="232"></rect><text x="0" y="0" class="subexp-label" transform="matrix(1,0,0,1,0,11)"><tspan>group #1</tspan></text><g class="regexp" transform="matrix(1,0,0,1,10,21)"><path d="M10,52.5q0,-10 10,-10M160,52.5q0,-10 -10,-10M10,121.5q0,10 10,10M160,121.5q0,10 -10,10M10,180q0,10 10,10M160,180q0,10 -10,10M0,106q10,0 10,-10V52.5M170,106q-10,0 -10,-10V52.5M0,106q10,0 10,10V180M170,106q-10,0 -10,10V180"></path><g class="regexp-matches" transform="matrix(1,0,0,1,20,0)"><path d="M0,42.5h27.5M112.5,42.5H130M0,131.5h10M130,131.5H130M0,190h46M79,190H130"></path><g class="match" transform="matrix(1,0,0,1,17.5,0)"><path d="M45,42.5H70"></path><g class="match-fragment" transform="matrix(1,0,0,1,0,0)"><path d="M10,42.5q-10,0 -10,10v21.5q0,10 10,10h35q10,0 10,-10v-21.5q0,-10 -10,-10M55,57.5l5,-5m-5,5l-5,-5"></path><g class="charset" transform="matrix(1,0,0,1,10,0)"><rect class="charset-box" rx="3" ry="3" transform="matrix(1,0,0,1,0,11)" width="35" height="63"></rect><text x="0" y="0" class="charset-label" transform="matrix(1,0,0,1,0,11)"><tspan>One of:</tspan></text><g transform="matrix(1,0,0,1,5,16)"><g class="literal" transform="matrix(1,0,0,1,0,0)"><g class="label"><rect width="25" height="24" rx="3" ry="3"></rect><text x="0" y="0" transform="matrix(1,0,0,1,5,17)"><tspan class="quote">“</tspan><tspan>0</tspan><tspan class="quote">”</tspan></text></g></g><g class="literal" transform="matrix(1,0,0,1,0,29)"><g class="label"><rect width="25" height="24" rx="3" ry="3"></rect><text x="0" y="0" transform="matrix(1,0,0,1,5,17)"><tspan class="quote">“</tspan><tspan>1</tspan><tspan class="quote">”</tspan></text></g></g></g></g></g><g class="match-fragment literal" transform="matrix(1,0,0,1,70,30.5)"><g class="label"><rect width="25" height="24" rx="3" ry="3"></rect><text x="0" y="0" transform="matrix(1,0,0,1,5,17)"><tspan class="quote">“</tspan><tspan>b</tspan><tspan class="quote">”</tspan></text></g></g></g><g class="match" transform="matrix(1,0,0,1,0,89)"><path d="M80,42.5H105"></path><g class="match-fragment" transform="matrix(1,0,0,1,0,0)"><path d="M10,42.5q-10,0 -10,10v21.5q0,10 10,10h70q10,0 10,-10v-21.5q0,-10 -10,-10M90,57.5l5,-5m-5,5l-5,-5"></path><g class="charset" transform="matrix(1,0,0,1,10,0)"><rect class="charset-box" rx="3" ry="3" transform="matrix(1,0,0,1,0,11)" width="70" height="63"></rect><text x="0" y="0" class="charset-label" transform="matrix(1,0,0,1,0,11)"><tspan>One of:</tspan></text><g transform="matrix(1,0,0,1,5,16)"><g class="charset-escape" transform="matrix(1,0,0,1,13.5,0)"><g class="label"><rect width="33" height="24" rx="3" ry="3"></rect><text x="0" y="0" transform="matrix(1,0,0,1,5,17)"><tspan>digit</tspan></text></g></g><g class="charset-range" transform="matrix(1,0,0,1,0,29)"><text x="0" y="0" transform="matrix(1,0,0,1,30,16)">-</text><g class="literal" transform="matrix(1,0,0,1,0,0)"><g class="label"><rect width="25" height="24" rx="3" ry="3"></rect><text x="0" y="0" transform="matrix(1,0,0,1,5,17)"><tspan class="quote">“</tspan><tspan>a</tspan><tspan class="quote">”</tspan></text></g></g><g class="literal" transform="matrix(1,0,0,1,39,0)"><g class="label"><rect width="21" height="24" rx="3" ry="3"></rect><text x="0" y="0" transform="matrix(1,0,0,1,5,17)"><tspan class="quote">“</tspan><tspan>f</tspan><tspan class="quote">”</tspan></text></g></g></g></g></g></g><g class="match-fragment literal" transform="matrix(1,0,0,1,105,30.5)"><g class="label"><rect width="25" height="24" rx="3" ry="3"></rect><text x="0" y="0" transform="matrix(1,0,0,1,5,17)"><tspan class="quote">“</tspan><tspan>h</tspan><tspan class="quote">”</tspan></text></g></g></g><g class="match match-fragment" transform="matrix(1,0,0,1,36,178)"><path d="M10,12q-10,0 -10,10v2q0,10 10,10h33q10,0 10,-10v-2q0,-10 -10,-10M53,27l5,-5m-5,5l-5,-5"></path><g class="escape" transform="matrix(1,0,0,1,10,0)"><g class="label"><rect width="33" height="24" rx="3" ry="3"></rect><text x="0" y="0" transform="matrix(1,0,0,1,5,17)"><tspan>digit</tspan></text></g></g></g></g></g></g><g class="match-fragment escape" transform="matrix(1,0,0,1,302,115)"><g class="label"><rect width="92" height="24" rx="3" ry="3"></rect><text x="0" y="0" transform="matrix(1,0,0,1,5,17)"><tspan>word boundary</tspan></text></g></g></g><path d="M10,127H0M404,127H414"></path><circle cx="0" cy="127" r="5"></circle><circle cx="414" cy="127" r="5"></circle></g></svg> 73 | -------------------------------------------------------------------------------- /img/9-3.svg: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> 2 | <svg 3 | xmlns:svg="http://www.w3.org/2000/svg" 4 | xmlns="http://www.w3.org/2000/svg" 5 | height="180.30476" 6 | version="1.1" 7 | width="217.52544"> 8 | <path 9 | d="m 149.04519,91.683302 h 13.4275" 10 | style="fill:none;stroke:#000000;stroke-width:2.68549919" 11 | id="path4"/> 12 | <path 13 | d="m 135.6177,91.683302 q 13.42749,0 13.42749,13.427498 v 60.42373 q 0,13.42749 -13.42749,13.42749 H 34.911488 q -13.427496,0 -13.427496,-13.42749 V 105.1108 q 0,-13.427498 13.427496,-13.427498" 14 | style="fill:none;stroke:#000000;stroke-width:2.68549919" 15 | id="path6"/> 16 | <path 17 | d="M 149.04519,91.683302 H 135.6177" 18 | style="fill:none;stroke:#000000;stroke-width:2.68549919" 19 | id="path8"/> 20 | <path 21 | d="M 21.483992,91.683302 H 34.911488" 22 | style="fill:none;stroke:#000000;stroke-width:2.68549919" 23 | id="path10"/> 24 | <path 25 | d="M 135.6177,91.683302 H 122.1902" 26 | style="fill:none;stroke:#000000;stroke-width:2.68549919" 27 | id="path12"/> 28 | <path 29 | d="M 34.911488,91.683302 H 48.338983" 30 | style="fill:none;stroke:#000000;stroke-width:2.68549919" 31 | id="path14"/> 32 | <path 33 | d="m 108.76272,91.683302 q 13.42748,0 13.42748,13.427498 v 33.56873 q 0,13.4275 -13.42748,13.4275 H 61.766478 q -13.427495,0 -13.427495,-13.4275 V 105.1108 q 0,-13.427498 13.427495,-13.427498" 34 | style="fill:none;stroke:#000000;stroke-width:2.68549919" 35 | id="path16"/> 36 | <path 37 | d="M 122.1902,91.683302 H 108.76272" 38 | style="fill:none;stroke:#000000;stroke-width:2.68549919" 39 | id="path18"/> 40 | <path 41 | d="M 48.338983,91.683302 H 61.766478" 42 | style="fill:none;stroke:#000000;stroke-width:2.68549919" 43 | id="path20"/> 44 | <desc 45 | id="desc22">Created with Raphaël 2.1.0</desc> 46 | <defs 47 | id="defs24" /> 48 | <rect 49 | x="162.4727" 50 | y="74.898933" 51 | width="33.568737" 52 | height="33.568737" 53 | r="0" 54 | rx="4.0282488" 55 | ry="4.0282488" 56 | style="fill:#dae9e5;stroke:#dae9e5;stroke-width:1.3427496" 57 | id="rect26" /> 58 | <text 59 | x="179.25706" 60 | y="91.683304" 61 | font="10px "Arial"" 62 | style="font-size:16.11299515px;font-style:normal;font-variant:normal;font-weight:normal;line-height:normal;text-anchor:middle;fill:#000000;stroke:none;font-family:Arial" 63 | font-size="12px" 64 | id="text28"> 65 | <tspan 66 | dy="6.0423727" 67 | id="tspan30">"b"</tspan> 68 | </text> 69 | <rect 70 | x="34.911488" 71 | y="13.803831" 72 | width="100.70621" 73 | height="151.7307" 74 | r="0" 75 | rx="4.0282488" 76 | ry="4.0282488" 77 | style="fill:none;stroke:#a0a0a0;stroke-width:2.68549919;stroke-dasharray:8.05649719, 2.68549906" 78 | id="rect32" /> 79 | <text 80 | x="64.451981" 81 | y="5.0759606" 82 | font="10px "Arial"" 83 | style="font-size:13.427495px;font-style:normal;font-variant:normal;font-weight:normal;line-height:normal;text-anchor:middle;fill:#000000;stroke:none;font-family:Arial" 84 | font-size="10px" 85 | id="text34"> 86 | <tspan 87 | dy="4.6996231" 88 | id="tspan36">Group #1</tspan> 89 | </text> 90 | <rect 91 | x="61.766479" 92 | y="44.687069" 93 | width="46.996235" 94 | height="93.99247" 95 | r="0" 96 | rx="4.0282488" 97 | ry="4.0282488" 98 | style="fill:#cbcbba;stroke:#cbcbba;stroke-width:1.3427496" 99 | id="rect38" /> 100 | <text 101 | x="85.264595" 102 | y="35.959198" 103 | font="10px "Arial"" 104 | style="font-size:13.427495px;font-style:normal;font-variant:normal;font-weight:normal;line-height:normal;text-anchor:middle;fill:#000000;stroke:none;font-family:Arial" 105 | font-size="10px" 106 | id="text40"> 107 | <tspan 108 | dy="4.6996231" 109 | id="tspan42">One of:</tspan> 110 | </text> 111 | <rect 112 | x="68.480232" 113 | y="98.397057" 114 | width="33.568737" 115 | height="33.568737" 116 | r="0" 117 | rx="4.0282488" 118 | ry="4.0282488" 119 | style="fill:#dae9e5;stroke:#dae9e5;stroke-width:1.3427496" 120 | id="rect44" /> 121 | <text 122 | x="85.264595" 123 | y="115.18143" 124 | font="10px "Arial"" 125 | style="font-size:16.11299515px;font-style:normal;font-variant:normal;font-weight:normal;line-height:normal;text-anchor:middle;fill:#000000;stroke:none;font-family:Arial" 126 | font-size="12px" 127 | id="text46"> 128 | <tspan 129 | dy="6.0423727" 130 | id="tspan48">"1"</tspan> 131 | </text> 132 | <rect 133 | x="68.480232" 134 | y="51.400818" 135 | width="33.568737" 136 | height="33.568737" 137 | r="0" 138 | rx="4.0282488" 139 | ry="4.0282488" 140 | style="fill:#dae9e5;stroke:#dae9e5;stroke-width:1.3427496" 141 | id="rect50" /> 142 | <text 143 | x="85.264595" 144 | y="68.185188" 145 | font="10px "Arial"" 146 | style="font-size:16.11299515px;font-style:normal;font-variant:normal;font-weight:normal;line-height:normal;text-anchor:middle;fill:#000000;stroke:none;font-family:Arial" 147 | font-size="12px" 148 | id="text52"> 149 | <tspan 150 | dy="6.0423727" 151 | id="tspan54">"0"</tspan> 152 | </text> 153 | <path 154 | d="M 8.0564968,91.683302 H 21.483992" 155 | style="fill:none;stroke:#000000;stroke-width:2.68549919" 156 | id="path56"/> 157 | <circle 158 | cx="10" 159 | cy="81" 160 | r="5" 161 | style="fill:#6b6659;stroke:#000000;stroke-width:2" 162 | id="circle58" 163 | transform="matrix(1.3427496,0,0,1.3427496,-5.3709984,-17.079408)" /> 164 | <path 165 | d="M 209.46892,91.683302 H 196.04143" 166 | style="fill:none;stroke:#000000;stroke-width:2.68549919" 167 | id="path60"/> 168 | <circle 169 | cx="160" 170 | cy="81" 171 | r="5" 172 | style="fill:#6b6659;stroke:#000000;stroke-width:2" 173 | id="circle62" 174 | transform="matrix(1.3427496,0,0,1.3427496,-5.3709984,-17.079408)" /> 175 | </svg> 176 | -------------------------------------------------------------------------------- /img/qr_alipay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apachecn/eloquent-js-3e-zh/12ed9090d2ddb50e23255e1a3790e5fdb849979b/img/qr_alipay.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | <!-- index.html --> 2 | 3 | <!DOCTYPE html> 4 | <html> 5 | <head> 6 | <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> 7 | <meta name="viewport" content="width=device-width,initial-scale=1"> 8 | <meta charset="UTF-8"> 9 | <link rel="stylesheet" href="asset/vue.css"> 10 | <link rel="stylesheet" href="asset/style.css"> 11 | <link rel="stylesheet" href="asset/prism-darcula.css"> 12 | 13 | <!-- google ads --> 14 | <script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script> 15 | 16 | <!-- google webmaster --> 17 | <meta name="google-site-verification" content="pyo9N70ZWyh8JB43bIu633mhxesJ1IcwWCZlM3jUfFo" /> 18 | </head> 19 | <body> 20 | <div id="app">now loading...</div> 21 | <script> 22 | window.$docsify = { 23 | loadSidebar: 'SUMMARY.md', 24 | name: 'JavaScript 编程精解中文第三版', 25 | auto2top: true, 26 | themeColor: '#DAA520', 27 | repo: 'apachecn/eloquent-js-3e-zh', 28 | plugins: [window.docsPlugin], 29 | bdStatId: '38525fdac4b5d4403900b943d4e7dd91', 30 | cnzzId: '1275211409', 31 | search: { 32 | paths: 'auto', 33 | placeholder: '搜索', 34 | noData: '没有结果', 35 | }, 36 | copyCode: { 37 | buttonText: '复制', 38 | errorText: 'Error', 39 | successText: 'OK!', 40 | }, 41 | } 42 | </script> 43 | 44 | <script src="asset/docsify.min.js"></script> 45 | <script src="asset/search.min.js"></script> 46 | <script src="asset/prism-javascript.min.js"></script> 47 | <script>Prism.languages.py = Prism.languages.python</script> 48 | <script src="asset/docsify-copy-code.min.js"></script> 49 | <script src="asset/docsify-baidu-push.js"></script> 50 | <script src="asset/docsify-baidu-stat.js"></script> 51 | <script src="asset/docsify-cnzz.js"></script> 52 | <script src="asset/docsify-apachecn-footer.js"></script> 53 | <script src="asset/docsify-clicker.js"></script> 54 | </body> 55 | </html> 56 | -------------------------------------------------------------------------------- /styles/ebook.css: -------------------------------------------------------------------------------- 1 | /* GitHub stylesheet for MarkdownPad (http://markdownpad.com) */ 2 | /* Author: Nicolas Hery - http://nicolashery.com */ 3 | /* Version: b13fe65ca28d2e568c6ed5d7f06581183df8f2ff */ 4 | /* Source: https://github.com/nicolahery/markdownpad-github */ 5 | 6 | /* RESET 7 | =============================================================================*/ 8 | 9 | html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video { 10 | margin: 0; 11 | padding: 0; 12 | border: 0; 13 | } 14 | 15 | /* BODY 16 | =============================================================================*/ 17 | 18 | body { 19 | font-family: Helvetica, arial, freesans, clean, sans-serif; 20 | font-size: 14px; 21 | line-height: 1.6; 22 | color: #333; 23 | background-color: #fff; 24 | padding: 20px; 25 | max-width: 960px; 26 | margin: 0 auto; 27 | } 28 | 29 | body>*:first-child { 30 | margin-top: 0 !important; 31 | } 32 | 33 | body>*:last-child { 34 | margin-bottom: 0 !important; 35 | } 36 | 37 | /* BLOCKS 38 | =============================================================================*/ 39 | 40 | p, blockquote, ul, ol, dl, table, pre { 41 | margin: 15px 0; 42 | } 43 | 44 | /* HEADERS 45 | =============================================================================*/ 46 | 47 | h1, h2, h3, h4, h5, h6 { 48 | margin: 20px 0 10px; 49 | padding: 0; 50 | font-weight: bold; 51 | -webkit-font-smoothing: antialiased; 52 | } 53 | 54 | h1 tt, h1 code, h2 tt, h2 code, h3 tt, h3 code, h4 tt, h4 code, h5 tt, h5 code, h6 tt, h6 code { 55 | font-size: inherit; 56 | } 57 | 58 | h1 { 59 | font-size: 24px; 60 | border-bottom: 1px solid #ccc; 61 | color: #000; 62 | } 63 | 64 | h2 { 65 | font-size: 18px; 66 | color: #000; 67 | } 68 | 69 | h3 { 70 | font-size: 14px; 71 | } 72 | 73 | h4 { 74 | font-size: 14px; 75 | } 76 | 77 | h5 { 78 | font-size: 14px; 79 | } 80 | 81 | h6 { 82 | color: #777; 83 | font-size: 14px; 84 | } 85 | 86 | body>h2:first-child, body>h1:first-child, body>h1:first-child+h2, body>h3:first-child, body>h4:first-child, body>h5:first-child, body>h6:first-child { 87 | margin-top: 0; 88 | padding-top: 0; 89 | } 90 | 91 | a:first-child h1, a:first-child h2, a:first-child h3, a:first-child h4, a:first-child h5, a:first-child h6 { 92 | margin-top: 0; 93 | padding-top: 0; 94 | } 95 | 96 | h1+p, h2+p, h3+p, h4+p, h5+p, h6+p { 97 | margin-top: 10px; 98 | } 99 | 100 | /* LINKS 101 | =============================================================================*/ 102 | 103 | a { 104 | color: #4183C4; 105 | text-decoration: none; 106 | } 107 | 108 | a:hover { 109 | text-decoration: underline; 110 | } 111 | 112 | /* LISTS 113 | =============================================================================*/ 114 | 115 | ul, ol { 116 | padding-left: 30px; 117 | } 118 | 119 | ul li > :first-child, 120 | ol li > :first-child, 121 | ul li ul:first-of-type, 122 | ol li ol:first-of-type, 123 | ul li ol:first-of-type, 124 | ol li ul:first-of-type { 125 | margin-top: 0px; 126 | } 127 | 128 | ul ul, ul ol, ol ol, ol ul { 129 | margin-bottom: 0; 130 | } 131 | 132 | dl { 133 | padding: 0; 134 | } 135 | 136 | dl dt { 137 | font-size: 14px; 138 | font-weight: bold; 139 | font-style: italic; 140 | padding: 0; 141 | margin: 15px 0 5px; 142 | } 143 | 144 | dl dt:first-child { 145 | padding: 0; 146 | } 147 | 148 | dl dt>:first-child { 149 | margin-top: 0px; 150 | } 151 | 152 | dl dt>:last-child { 153 | margin-bottom: 0px; 154 | } 155 | 156 | dl dd { 157 | margin: 0 0 15px; 158 | padding: 0 15px; 159 | } 160 | 161 | dl dd>:first-child { 162 | margin-top: 0px; 163 | } 164 | 165 | dl dd>:last-child { 166 | margin-bottom: 0px; 167 | } 168 | 169 | /* CODE 170 | =============================================================================*/ 171 | 172 | pre, code, tt { 173 | font-size: 12px; 174 | font-family: Consolas, "Liberation Mono", Courier, monospace; 175 | } 176 | 177 | code, tt { 178 | margin: 0 0px; 179 | padding: 0px 0px; 180 | white-space: nowrap; 181 | border: 1px solid #eaeaea; 182 | background-color: #f8f8f8; 183 | border-radius: 3px; 184 | } 185 | 186 | pre>code { 187 | margin: 0; 188 | padding: 0; 189 | white-space: pre; 190 | border: none; 191 | background: transparent; 192 | } 193 | 194 | pre { 195 | background-color: #f8f8f8; 196 | border: 1px solid #ccc; 197 | font-size: 13px; 198 | line-height: 19px; 199 | overflow: auto; 200 | padding: 6px 10px; 201 | border-radius: 3px; 202 | } 203 | 204 | pre code, pre tt { 205 | background-color: transparent; 206 | border: none; 207 | } 208 | 209 | kbd { 210 | -moz-border-bottom-colors: none; 211 | -moz-border-left-colors: none; 212 | -moz-border-right-colors: none; 213 | -moz-border-top-colors: none; 214 | background-color: #DDDDDD; 215 | background-image: linear-gradient(#F1F1F1, #DDDDDD); 216 | background-repeat: repeat-x; 217 | border-color: #DDDDDD #CCCCCC #CCCCCC #DDDDDD; 218 | border-image: none; 219 | border-radius: 2px 2px 2px 2px; 220 | border-style: solid; 221 | border-width: 1px; 222 | font-family: "Helvetica Neue",Helvetica,Arial,sans-serif; 223 | line-height: 10px; 224 | padding: 1px 4px; 225 | } 226 | 227 | /* QUOTES 228 | =============================================================================*/ 229 | 230 | blockquote { 231 | border-left: 4px solid #DDD; 232 | padding: 0 15px; 233 | color: #777; 234 | } 235 | 236 | blockquote>:first-child { 237 | margin-top: 0px; 238 | } 239 | 240 | blockquote>:last-child { 241 | margin-bottom: 0px; 242 | } 243 | 244 | /* HORIZONTAL RULES 245 | =============================================================================*/ 246 | 247 | hr { 248 | clear: both; 249 | margin: 15px 0; 250 | height: 0px; 251 | overflow: hidden; 252 | border: none; 253 | background: transparent; 254 | border-bottom: 4px solid #ddd; 255 | padding: 0; 256 | } 257 | 258 | /* TABLES 259 | =============================================================================*/ 260 | 261 | table th { 262 | font-weight: bold; 263 | } 264 | 265 | table th, table td { 266 | border: 1px solid #ccc; 267 | padding: 6px 13px; 268 | } 269 | 270 | table tr { 271 | border-top: 1px solid #ccc; 272 | background-color: #fff; 273 | } 274 | 275 | table tr:nth-child(2n) { 276 | background-color: #f8f8f8; 277 | } 278 | 279 | /* IMAGES 280 | =============================================================================*/ 281 | 282 | img { 283 | max-width: 100% 284 | } -------------------------------------------------------------------------------- /update.sh: -------------------------------------------------------------------------------- 1 | git add -A 2 | git commit -am "$(date "+%Y-%m-%d %H:%M:%S")" 3 | git push --------------------------------------------------------------------------------