第 1 章 二十年来的 JavaScript 1
1.1 网页中的代码 1
1.1.1 新鲜的玩意儿 1
1.1.2 写在网页中的第一段代码 2
1.1.3 最初的价值 3
1.2 用 JavaScript 来写浏览器上的应用 5
1.2.1 我要做一个聊天室 5
1.2.2 Flash 的一席之地 . 7
1.2.3 RWC 与 RIA 之争 8
1.3 没有框架与库的语言能怎样发展呢 10
1.3.1 做一个框架 .10
1.3.2 重写框架的语言层 .13
1.3.3 富浏览器端开发(RWC)与 AJAX 14
1.4 语言的进化 .16
1.4.1 Qomo 的重生 16
1.4.2 QoBean 是对语言的重新组织 .17
1.4.3 JavaScript 作为一门语言的进化 18
1.5 大型系统开发 .20
1.5.1 框架与架构是不同的 .20
1.5.2 大型系统与分布式的环境 .21
1.5.3 划时代的 ES6 23
1.6 为 JavaScript 正名 .24
1.6.1 JavaScript 25
1.6.1.1 Core JavaScript .26
1.6.1.2 SpiderMonkey JavaScript .27
1.6.1.3 JScript .27
1.6.2 ECMAScript 28
1.7 JavaScript 的应用环境 29
1.7.1 宿主环境 .30
1.7.2 外壳程序 .31
1.7.3 运行期环境 .32
1.7.4 兼容环境下的测试 .34
第 2 章 JavaScript 的语法 . 36
2.1 语法综述 .36
2.1.1 标识符所绑定的语义 .37
2.1.2 识别语法错误与运行错误 .38
2.2 JavaScript 的语法:声明 40
2.2.1 变量的数据类型 .40
2.2.1.1 基本数据类型 41
2.2.1.2 宿主定义的其他对象类型 42
2.2.1.3 值类型与引用类型 42
2.2.1.4 讨论:ECMAScript 的类型系统 43
2.2.2 变量声明 .45
2.2.2.1 块级作用域的变量声明与一般 var 声明 .47
2.2.2.2 用赋值模板声明一批变量 48
2.2.3 使用字面量风格的值 .48
2.2.3.1 字符串字面量、转义符 49
2.2.3.2 模板字面量 51
2.2.3.3 数值字面量 52
2.2.4 其他声明 .53
2.2.4.1 常量声明 53
2.2.4.2 符号声明 54
2.2.4.3 函数声明 55
2.3 JavaScript 的语法:表达式运算 56
2.3.1 一般表达式运算 .59
2.3.1.1 逻辑运算 59
2.3.1.2 字符串运算 60
2.3.1.3 数值运算 61
2.3.2 比较运算 .61
2.3.2.1 等值检测 62
2.3.2.2 序列检测 64
2.3.3 赋值运算 .67
2.3.3.1 赋值的语义 67
2.3.3.2 复合赋值运算符 68
2.3.3.3 解构赋值 68
2.3.4 函数相关的表达式 .69
2.3.4.1 匿名函数与箭头函数 70
2.3.4.2 函数调用 70
2.3.4.3 new 运算 72
2.3.5 特殊作用的运算符 .72
2.3.5.1 类型运算符(typeof) 73
2.3.5.2 展开语法(spread syntax) 74
2.3.5.3 面向表达式的运算符 74
2.3.6 运算优先级 .76
2.4 JavaScript 的语法:语句 78
2.4.1 表达式语句 .80
2.4.1.1 一般表达式语句 80
2.4.1.2 赋值语句与隐式的变量声明 81
2.4.1.3 函数调用语句 82
2.4.2 变量声明语句 .86
2.4.3 分支语句 .87
2.4.3.1 条件分支语句(if 语句) .87
2.4.3.2 多重分支语句(switch 语句) .88
2.4.4 循环语句 .89
2.4.5 流程控制:一般子句 .91
2.4.5.1 标签声明 91
2.4.5.2 break 子句 92
2.4.5.3 continue 子句 .94
2.4.5.4 return 子句 .95
2.4.6 流程控制:异常 .96
2.5 JavaScript 的语法:模块 97
2.5.1 模块的声明与加载 .98
2.5.1.1 加载模块 98
2.5.1.2 声明模块 100
2.5.2 名字空间的特殊性 .101
2.5.2.1 名字空间的创建者 102
2.5.2.2 名字空间中的名字是属性名 102
2.5.2.3 使用上的一些特殊性 103
2.6 严格模式下的语法限制 .105
2.6.1 语法限制 .106
2.6.2 执行限制 .108
2.6.3 严格模式的范围 . 110
2.6.3.1 有限范围下的严格模式 110
2.6.3.2 非严格模式的全局环境 112
2.7 运算符的二义性 . 112
2.7.1 加号“+”的二义性 . 114
2.7.2 括号“( )”的二义性 114
2.7.3 冒号“:”与标签的二义性 116
2.7.4 大括号“{ }”的二义性 . 117
2.7.4.1 复合语句/语句块 . 117
2.7.4.2 声明对象字面量 118
2.7.4.3 函数声明 119
2.7.4.4 结构化异常 119
2.7.4.5 模板中的变量引用 120
2.7.4.6 解构赋值 120
2.7.5 逗号“,”的二义性 122
2.7.6 方括号“[ ]”的二义性 123
2.7.7 语法设计中对二义性的处理 127
第 3 章 JavaScript 的面向对象语言特性 . 130
3.1 面向对象编程的语法概要 .130
3.1.1 对象声明与实例创建 .132
3.1.1.1 使用构造器创建对象实例 132
3.1.1.2 声明对象字面量 134
3.1.1.3 数组及其字面量 137
3.1.1.4 正则表达式及其字面量 138
3.1.1.5 在对象声明中使用属性存取器 141
3.1.2 使用类继承体系 .141
3.1.2.1 声明类和继承关系 141
3.1.2.2 声明属性 143
3.1.2.3 调用父类构造方法 144
3.1.2.4 调用父类方法 145
3.1.2.5 类成员(类静态成员) 146
3.1.3 对象成员 .147
3.1.3.1 成员的列举,以及可列举性 147
3.1.3.2 对象及其成员的检查 150
3.1.3.3 值的存取 153
3.1.3.4 成员的删除 154
3.1.3.5 方法的调用 157
3.1.4 使用对象自身 .157
3.1.4.1 与基础类型数据之间的运算 157
3.1.4.2 默认对象的指定 158
3.1.5 符号 .158
3.1.5.1 列举符号属性 159
3.1.5.2 改变对象内部行为 159
3.1.5.3 全局符号表 160
3.2 JavaScript 的原型继承 161
3.2.1 空(null)与空白对象(empty) .161
3.2.1.1 空白对象是所有对象的基础 162
3.2.1.2 构造复制?写时复制?还是读遍历? .163
3.2.1.3 构造过程:从函数到构造器 166
3.2.1.4 内置属性与方法 167
3.2.1.5 原型为 null:“更加空白”的对象 .170
3.2.2 原型链的维护 .171
3.2.2.1 外部原型链与 constructor 属性 172
3.2.2.2 使用内部原型链 173
3.2.3 原型继承的实质 .175
3.2.3.1 简单模型 175
3.2.3.2 基于原型继承的设计方法 177
3.2.3.3 如何理解“继承来的成员” 177
3.3 JavaScript 的类继承 179
3.3.1 类是静态的声明 .179
3.3.2 super 是全新的语法元素 181
3.3.2.1 super 的作用 181
3.3.2.2 super 指向什么 182
3.3.2.3 super 对一般属性的意义 .184
3.3.2.4 super 在两种继承关系中的矛盾 .186
3.3.2.5 super 的动态计算过程 188
3.3.3 类是用构造器(函数)来实现的 189
3.3.4 父类的默认值与 null 值 .192
3.4 JavaScript 的对象系统 196
3.4.1 封装与多态 .196
3.4.1.1 封装 196
3.4.1.2 多态 198
3.4.1.3 多态与方法继承 200
3.4.2 属性 .201
3.4.2.1 方法 201
3.4.2.2 事件 205
3.4.3 构造对象系统的方法 .206
3.4.3.1 类抄写 206
3.4.3.2 原型继承 209
3.4.3.3 类继承 210
3.4.3.4 直接创建对象 211
3.4.3.5 如何选择继承的方式 213
3.4.4 内置的对象系统 .214
3.4.4.1 早期规范(ES5 之前)中的对象 .216
3.4.4.2 集合对象 218
3.4.4.3 结构化数据对象 221
3.4.4.4 反射对象 223
3.4.4.5 其他 225
3.4.5 特殊效果的继承 .226
3.5 可定制的对象属性 .229
3.5.1 属性描述符 .230
3.5.1.1 数据描述符 230
3.5.1.2 存取描述符 231
3.5.1.3 隐式创建的描述符:字面量风格的对象或类声明 .232
3.5.2 定制对象属性 .233
3.5.2.1 给属性赋值 234
3.5.2.2 使用属性描述符 235
3.5.2.3 取属性或属性列表 237
3.5.3 属性表的状态 .239
3.6 运行期侵入与元编程系统 .242
3.6.1 关于运行期侵入 .243
3.6.1.1 运行期侵入的核心机制 243
3.6.1.2 可被符号影响的行为 244
3.6.1.3 内部方法与反射机制 251
3.6.1.4 侵入原型 255
3.6.2 类类型与元类继承 .257
3.6.2.1 原子 257
3.6.2.2 元与元类 258
3.6.2.3 类类型系统 260
3.6.2.4 类类型的检查 261
3.6.2.5 类类型的声明以及扩展特性 263
3.6.3 元编程模型 .266
第 4 章 JavaScript 语言的结构化 269
4.1 概述 .269
4.1.1 命令式语言 .270
4.1.1.1 存储与数据结构 270
4.1.1.2 结构化编程 271
4.1.1.3 结构化的疑难 272
4.1.2 面向对象语言 .275
4.1.2.1 结构化的延伸 275
4.1.2.2 更高层次的抽象:接口 278
4.1.2.3 面向接口的编程方法 280
4.1.3 再论语言的分类 .281
4.1.3.1 对语言范型的简化 281
4.1.3.2 结构化的性质 282
4.1.4 JavaScript 的语源 283
4.2 基本的组织元素 .284
4.2.1 标识符 .285
4.2.2 表达式 .286
4.2.2.1 字面量 287
4.2.2.2 初始器 287
4.2.3 语句 .288
4.2.4 模块 .289
4.2.5 组织的原则 .290
4.2.5.1 原则一:抑制数据的可变性 290
4.2.5.2 原则二:最小逻辑和最大复用 291
4.2.5.3 原则三:语法在形式上的清晰与语义一致性 .293
4.3 声明 .294
4.3.1 声明名字 .295
4.3.2 确定性 .296
4.3.3 顶层声明 .297
4.4 语句与代码分块 .300
4.4.1 块 .301
4.4.1.1 简单语句 302
4.4.1.2 单值表达式 302
4.4.2 块与语句的语法结构 .303
4.4.2.1 语义上的代码分块 303
4.4.2.2 分支逻辑中的代码分块 303
4.4.2.3 多重分支逻辑中的代码分块 304
4.4.2.4 循环逻辑中的代码分块 306
4.4.2.5 异常中的代码分块 308
4.4.3 块与声明语句 .309
4.4.3.1 只能在块中进行数据声明 309
4.4.3.2 能同时声明块的声明语句 310
4.4.3.3 声明语句与块的组织 311
4.4.4 块与语句的值 .312
4.4.4.1 语句的执行状态 314
4.4.4.2 语句无值 315
4.4.4.3 语句有值 316
4.4.5 标签化语句与块 .317
4.5 组织形式分块的方法 .318
4.5.1 词法作用域 .319
4.5.1.1 不存在“级别 1:表达式” .320
4.5.1.2 级别 2:语句 .320
4.5.1.3 级别 3:函数 .324
4.5.1.4 级别 4:模块 .325
4.5.1.5 级别 5:全局 .327
4.5.2 执行流程及其变更 .328
4.5.2.1 级别 1:可能的逃逸 .329
4.5.2.2 级别 2:“break <label>;”等语法 331
4.5.2.3 级别 3:return 子句 .333
4.5.2.4 级别 4:动态模块与 Promise 中的流程控制 .335
4.5.2.5 级别 5:throw 语句 .335
4.5.3 词法作用域之间的相关性 .336
4.5.4 执行流程变更的内涵 .337
4.6 层次结构程序设计 .340
4.6.1 属性的可见性 .341
4.6.1.1 属性在继承层次间的可见性 342
4.6.1.2 属性在继承树(子树)间的可见性 343
4.6.2 多态的逻辑 .343
4.6.2.1 super 是对多态逻辑的绑定 .344
4.6.2.2 super 是一个作用域相关的绑定 .345
4.6.3 私有作用域的提出 .347
4.7 历史遗产:变量作用域 .349
4.7.1 变量作用域 .350
4.7.1.1 级别 3:函数(局部变量) .351
4.7.1.2 级别 4:模块 .352
4.7.1.3 级别 5:全局变量 .352
4.7.2 变量的特殊性与变量作用域的关系 353
4.7.2.1 变量提升 353
4.7.2.2 变量动态声明 354
4.7.2.3 变量隐式声明(全局属性) 355
4.8 私有属性与私有字段的纷争 356
4.8.1 私有属性的提出 .357
4.8.1.1 对象字面量中的作用域问题 357
4.8.1.2 类声明中的作用域问题 359
4.8.1.3 识别“对象自己(访问)” 360
4.8.1.4 识别“对象访问(自己)” 361
4.8.2 从私有属性到私有成员 .361
4.8.2.1 私有属性与私有字段 361
4.8.2.2 私有字段与私有变量 363
4.8.2.3 再论私有成员 364
4.8.3 “类字段”提案的实现概要 364
4.8.3.1 语法设计 365
4.8.3.2 实现框架 366
4.8.3.3 概要分析 368
4.8.4 “私有属性”提案的设计与提议 368
4.8.4.1 语法设计 368
4.8.4.2 语法与语义的关系 371
4.8.5 “私有属性”提案的实现 .373
4.8.5.1 核心的实现逻辑 373
4.8.5.2 一个简短的回顾 374
4.8.5.3 保护属性的实现 375
4.8.5.4 可见性的管理(unscopables) .376
4.8.5.5 避免侵入(thisValue) .377
4.8.5.6 内部访问(internal) 378
4.8.5.7 概要分析 380
第 5 章 JavaScript 的函数式语言特性 . 381
5.1 概述 .381
5.1.1 从代码风格说起 .382
5.1.2 为什么常见的语言不赞同连续求值 383
5.1.3 函数式语言的渊源 .384
5.2 从运算式语言到函数式语言 386
5.2.1 JavaScript 中的几种连续运算 386
5.2.1.1 连续赋值 386
5.2.1.2 三元表达式的连用 387
5.2.1.3 连续逻辑运算 388
5.2.1.4 逗号运算符与连续运算 389
5.2.1.5 解构赋值 389
5.2.1.6 函数与方法的调用 390
5.2.2 如何消灭语句 .391
5.2.2.1 通过表达式消灭分支语句 391
5.2.2.2 通过函数递归消灭循环语句 393
5.2.2.3 其他可以被消灭的语句 394
5.2.3 运算式语言 .394
5.2.3.1 运算的实质是值运算 394
5.2.3.2 运算式语言的应用 396
5.2.4 重新认识函数 .397
5.2.4.1 函数是对运算式语言的补充 398
5.2.4.2 函数是代码的组织形式 398
5.2.4.3 当运算符等义于某个函数时 399
5.2.5 函数式语言 .401
5.2.5.1 “函数”===“Lambda” 402
5.2.5.2 函数是操作数 402
5.2.5.3 在函数内保存数据 403
5.2.5.4 函数内的运算对函数外无副作用 404
5.2.5.5 函数式的特性集 405
5.3 JavaScript 中的函数 405
5.3.1 参数 .405
5.3.1.1 可变参数 406
5.3.1.2 默认参数 408
5.3.1.3 剩余参数 409
5.3.1.4 模板参数 410
5.3.1.5 参数对象 411
5.3.1.6 非简单参数 413
5.3.1.7 非惰性求值 414
5.3.1.8 传值参数 416
5.3.2 函数 .418
5.3.2.1 一般函数 419
5.3.2.2 生成器函数 421
5.3.2.3 类 423
5.3.2.4 方法 425
5.3.2.5 箭头函数 426
5.3.2.6 绑定函数 427
5.3.2.7 代理函数 431
5.3.3 函数的数据性质 .431
5.3.3.1 函数是第一型 432
5.3.3.2 数据态的函数 433
5.3.3.3 类与对象态的函数 434
5.3.3.4 代理态的函数 438
5.3.4 函数与逻辑结构 .439
5.3.4.1 递归 439
5.3.4.2 函数作为构造器的递归 441
5.3.4.3 块级作用域中的函数 442
5.4 函数的行为 .443
5.4.1 构造 .444
5.4.1.1 this 引用的创建 .444
5.4.1.2 初始化 this 对象 446
5.4.2 调用 .448
5.4.2.1 不使用函数调用运算符 449
5.4.2.2 callee:我是谁 .452
5.4.2.3 caller:谁调用我 .453
5.4.3 方法调用 .455
5.4.3.1 属性存取与 this 引用的传入 .456
5.4.3.2 this 引用的使用 .457
5.4.3.3 在方法调用中理解 super .458
5.4.3.4 动态地添加方法 459
5.4.4 迭代 .461
5.4.4.1 可迭代对象与迭代 461
5.4.4.2 可迭代对象在语法层面的支持 462
5.4.4.3 迭代器的错误与异常处理 464
5.4.5 生成器中的迭代 .466
5.4.5.1 生成器对象 466
5.4.5.2 生成器的错误与异常处理 469
5.4.5.3 方法 throw()的隐式调用 .472
5.4.5.4 向生成器中传入的数据 474
5.5 闭包 .475
5.5.1 闭包与函数实例 .476
5.5.1.1 闭包与非闭包 476
5.5.1.2 什么是函数实例 477
5.5.1.3 看到闭包 478
5.5.1.4 闭包的数量 479
5.5.2 闭包的使用 .481
5.5.2.1 运行期的闭包 482
5.5.2.2 闭包中的可访问标识符 483
5.5.2.3 用户代码导致的闭包变化 484
5.5.2.4 函数表达式的特殊性 485
5.5.2.5 严格模式下的闭包 486
5.5.3 与闭包类似的实例化环境 .487
5.5.3.1 全局环境 487
5.5.3.2 模块环境 490
5.5.3.3 对象闭包 491
5.5.3.4 块 492
5.5.3.5 循环语句的特殊性 493
5.5.3.6 函数闭包与对象闭包的混用 495
5.5.4 与闭包相关的一些特性 .496
5.5.4.1 变量维护规则 496
5.5.4.2 引用与泄露 497
5.5.4.3 语句或语句块中的闭包问题 499
5.5.4.4 闭包中的标识符(变量)特例 502
5.5.4.5 函数对象的闭包及其效果 504
第 6 章 JavaScript 的动态语言特性 506
6.1 概述 .506
6.1.1 动态数据类型的起源 .507
6.1.2 动态执行系统 .507
6.1.3 脚本系统的起源 .509
6.1.4 脚本只是表现形式 .510
6.2 动态类型:对象与值类型之间的转换 512
6.2.1 包装类:面向对象的妥协 .512
6.2.1.1 显式创建 513
6.2.1.2 显式包装 514
6.2.1.3 隐式包装的过程与检测方法 514
6.2.1.4 包装值类型数据的必要性与问题 517
6.2.1.5 其他字面量与相应的构造器 519
6.2.1.6 函数特例 519
6.2.2 从对象到值 .520
6.2.2.1 对象到值的隐式转换规则 520
6.2.2.2 直接的值运算不受包装类的方法影响 .522
6.2.2.3 什么是“转换的预期” 524
6.2.2.4 深入探究 valueOf()方法 525
6.2.2.5 布尔运算的特例 527
6.2.2.6 符号 Symbol.toPrimitive 的效果 .528
6.2.3 显式的转换 .529
6.2.3.1 显式转换的语法含义 530
6.2.3.2 对“转换预期”的显式表示 531
6.2.3.3 关于符号值的补充说明 531
6.3 动态类型:值类型的转换 .532
6.3.1 值运算:类型转换的基础 .532
6.3.1.1 完整过程:运算导致的类型转换 533
6.3.1.2 语句或语义导致的类型转换 535
6.3.2 值类型之间的转换 .535
6.3.2.1 undefined 的转换 .536
6.3.2.2 number 的转换 .537
6.3.2.3 boolean 的转换 537
6.3.2.4 string 的转换 538
6.3.2.5 symbol 的转换 .539
6.3.3 值类型之间的显式转换 .540
6.3.3.1 到数值的显式转换 540
6.3.3.2 到字符串类型的显式转换 541
6.3.3.3 到 undefined 值的显式处理 544
6.3.3.4 到布尔值的显式处理 544
6.4 动态类型:对象与数组的动态特性 545
6.4.1 关联数组与索引数组 .545
6.4.2 索引数组作为对象的问题 .546
6.4.2.1 索引数组更加低效 547
6.4.2.2 属性 length 的可写性 549
6.4.2.3 类型化数组的一些性质 550
6.4.3 类数组对象:对象作为索引数组的应用 552
6.4.4 其他 .554
6.5 重写 .555
6.5.1 标识符的重写及其限制 .555
6.5.1.1 早于用户代码之前的声明与重写 556
6.5.1.2 声明对标识符可写性的影响 559
6.5.1.3 赋值操作带来的重写 560
6.5.1.4 对象内部方法对重写的影响 563
6.5.1.5 非赋值操作带来的重写 564
6.5.1.6 条件化声明中的重写 565
6.5.1.7 运算优先级与引用的暂存 566
6.5.2 原型重写 .567
6.5.3 构造器重写 .569
6.5.3.1 重写 Object() 569
6.5.3.2 使用类声明来重写 571
6.5.3.3 继承关系的丢失 572
6.5.4 对象成员的重写 .573
6.5.4.1 成员重写的检测 574
6.5.4.2 成员重写的删除 575
6.5.4.3 成员重写对作用域的影响 576
6.5.5 引擎对重写的限制 .578
6.5.5.1 this 与 super 等关键字的重写 .579
6.5.5.2 语句中的重写 580
6.5.5.3 结构化异常处理中的重写 580
6.6 动态执行 .582
6.6.1 eval()作为函数名的特殊性 582
6.6.2 eval()在不同上下文环境中的效果 584
6.6.2.1 eval 使用全局环境 584
6.6.2.2 eval 使用对象闭包或模块环境 .585
6.6.2.3 eval()使用当前函数的闭包 .585
6.6.3 Eval 环境的独特性 .586
6.6.3.1 默认继承当前环境的运行模式 587
6.6.3.2 例外:obj.eval()的特殊性 .588
6.6.3.3 执行代码可以自行决定运行模式 589
6.6.3.4 声明实例化过程与其他可执行结构不同 .591
6.6.3.5 环境的回收 592
6.6.4 动态执行过程中的语句、表达式与值 593
6.6.5 序列化与反序列化 .595
6.6.5.1 在对象与函数上的限制 596
6.6.5.2 对象深度与循环引用 597
6.6.5.3 不太现实的替代品 599
6.6.6 eval 对作用域的影响 600
6.6.7 其他的动态执行逻辑 601
6.6.7.1 动态创建的函数 601
6.6.7.2 模板与动态执行 603
6.6.7.3 宿主的动态执行逻辑 604
6.7 动态方法调用(call、apply 与 bind) 605
6.7.1 动态方法调用以及 this 引用的管理 605
6.7.2 丢失的 this 引用 608
6.7.3 bind()方法与函数的延迟调用 610
6.7.4 栈的可见与修改 612
6.7.5 严格模式中的 this 绑定问题 614
6.8 通用执行环境的实现 615
6.8.1 通用 DSL 的模型 616
6.8.1.1 概念设计 616
6.8.1.2 被依赖的基础功能 616
6.8.1.3 一个基本实现 619
6.8.1.4 应用示例 621
6.8.1.5 其他 623
6.8.2 实现 ECMAScript 引擎 624
6.8.2.1 简单入手 624
6.8.2.2 引擎中的环境 625
6.8.2.3 对用户代码的语法分析 628
6.8.2.4 执行前的准备工作 630
6.8.2.5 从语法树节点开始执行 631
6.8.2.6 数据的交换 633
6.8.2.7 上下文的使用与管理 634
6.8.3 与 DSL 的概念整合 635
第 7 章 JavaScript 的并行语言特性 638
7.1 概述 .638
7.1.1 并行计算的思想 .638
7.1.1.1 并行计算范型的抽象 639
7.1.1.2 分布与并行逻辑 639
7.1.1.3 并发的讨论背景 640
7.1.1.4 分支也可以不是时序逻辑 641
7.1.2 并行程序设计的历史 .642
7.1.2.1 从“支持并行”到并行程序语言 643
7.1.2.2 用并发思想处理数据的语言 643
7.1.2.3 多数传统程序设计语言是“伪并行”的 .644
7.1.2.4 真正的并行:在语言层面无视时间 644
7.1.3 并行语言特性在 JavaScript 中的历史 .645
7.2 Promise 的核心机制 .647
7.2.1 Promise 的核心过程 .647
7.2.1.1 Promise 的构造方法 647
7.2.1.2 需要清楚的事实:没有延时 648
7.2.1.3 Then 链 .649
7.2.1.4 Then 链中 promise2 的置值逻辑 650
7.2.1.5 Then 链对值的传递以及.catch()处理 652
7.2.2 Promise 类与对象的基本应用 654
7.2.2.1 Promise 的其他类方法 654
7.2.2.2 Promise.resolve()处理 thenable 对象的具体方法 .656
7.2.2.3 promise 对象的其他原型方法 658
7.2.2.4 未捕获异常的 promise 的检测 .660
7.2.2.5 特例:将响应函数置为非函数 662
7.2.3 Promise 的子类 .663
7.2.3.1 由 Promise()派生的子类 .663
7.2.3.2 thenable 对象或其子类 664
7.2.4 执行逻辑 .666
7.2.4.1 任务队列 666
7.2.4.2 执行栈 667
7.3 与其他语言特性的交集 .668
7.3.1 与函数式特性的交集:异步的函数 669
7.3.1.1 异步函数的引入 669
7.3.1.2 异步函数的值 670
7.3.1.3 异步函数中的 await 671
7.3.1.4 异步生成器函数 673
7.3.1.5 异步生成器函数中的 await 674
7.3.1.6 异步生成器函数与 for await .of 语句 676
7.3.2 与动态特性的交集 677
7.3.2.1 await 在语义上的特点 677
7.3.2.2 resolve 行为与类型模糊 678
7.3.2.3 then 方法的动态绑定 679
7.3.2.4 通过接口识别的类型(thenable) 680
7.3.2.5 通过动态创建函数来驱动异步特性 682
7.3.3 对结构化特性带来的冲击 683
7.3.3.1 对执行逻辑的再造 683
7.3.3.2 迟来的 finally 684
7.3.3.3 new Function()风格的异步函数创建 686
7.3.3.4 异步方法与存取器 687
7.4 JavaScript 中对并发的支持 690
7.4.1 Agent、Agent Cluster 及其工作机制 .691
7.4.1.1 工作线程及其环境 691
7.4.1.2 线程及其调度 692
7.4.1.3 与谁协商 693
7.4.1.4 多线程的可计算环境 694
7.4.1.5 通过消息通信完成协商 695
7.4.2 SharedArrayBuffer 698
7.4.3 Atomics 701
7.4.3.1 锁 701
7.4.3.2 置值:锁的状态切换 704
7.4.3.3 其他原子操作 705
7.4.3.4 原子操作中的异常与锁的释放 705
7.5 在分布式网络环境中的并行执行 706
7.5.1 分布式并行架构的实践 707
7.5.1.1 N4C 的背景 707
7.5.1.2 N4C 的架构设计 707
7.5.1.3 N4C 架构的实现 708
7.5.2 构建一个集群环境 709
7.5.2.1 N4C 集群与资源中心的基本结构 709
7.5.2.2 启动集群 711
7.5.2.3 在集群中创建任务中心 712
7.5.2.4 将计算节点加入集群 713
7.5.3 使用 PEDT 执行并行任务 713
7.5.3.1 本地任务、远程任务与并行任务 714
7.5.3.2 使用 PEDT 来管理并行任务 714
7.5.3.3 任务的执行 715
7.5.3.4 并行的方法 716
7.5.4 可参考的意义 .718
附录 A 术语表 719
附录 B 参考书目 723
附录 C 图表索引 725
附录 D 本书各版次主要修改 731
· · · · · · (
收起)