页面模式偏好

草案 ECMA-262 / 2026年10月10日

ECMAScript® 2027 语言 规范

关于本规范

位于 https://tc39.es/ecma262/ 的文档是最准确、最新的 ECMAScript 规范。它包含最近一次年度快照的内容,以及所有已完成的提案 — 即在提案流程中已达到阶段 4 的提案,因此这些提案已在多个实现中得到实现,并将纳入下一次年度快照。历史快照可在 https://ecma-international.org/publications-and-standards/standards/ecma-262/ 获取。

本文档提供单页版本和多页版本。

为本规范做出贡献

本规范在 ECMAScript 社区的帮助下于 GitHub 上开发。可以通过多种方式为本规范的开发做出贡献:

有关本文档创建方式的更多信息,请参阅编制说明。

引言

本 Ecma 标准定义了 ECMAScript 2027 语言。这是 ECMAScript 语言规范的第十八版。ECMAScript 基于若干早期技术,其中最广为人知的是 JavaScript(Netscape)和 JScript(Microsoft)。该语言由 Netscape 的 Brendan Eich 发明,并首次出现在该公司的 Navigator 2.0 浏览器中。尽管它最为人熟知的用途是作为嵌入 Web 浏览器的语言,但它也已广泛用于浏览器之外,包括服务器和嵌入式应用,并已发展成为世界上使用最广泛的通用编程语言之一。

ECMAScript 语言规范的开发始于 1996 年 11 月。本 Ecma 标准的第一版于 1997 年 6 月获 Ecma 大会通过。

该 Ecma 标准被提交给 ISO/IEC JTC 1,以便通过快速程序采纳,并于 1998 年 4 月获批为国际标准 ISO/IEC 16262。1998 年 6 月的 Ecma 大会批准了 ECMA-262 第二版,使其与 ISO/IEC 16262 完全一致。第一版与第二版之间的更改属于编辑性更改。

本标准的第三版引入了强大的正则表达式、更好的字符串处理、新的控制语句、try/catch 异常处理、更严格的错误定义、数值输出格式化,以及为语言未来发展而做出的小幅更改。ECMAScript 标准第三版于 1999 年 12 月获 Ecma 大会通过,并于 2002 年 6 月作为 ISO/IEC 16262:2002 发布。

第三版发布后,ECMAScript 随着万维网的发展得到大规模采用,并成为几乎所有 Web 浏览器都支持的编程语言。ECMAScript 第四版的开发曾投入大量工作。然而,这些工作未能完成,也未作为 ECMAScript 第四版发布,但其中一部分被纳入了第六版的开发。

ECMAScript 第五版(以 ECMA-262 第 5版发布)将浏览器实现中已普遍采用的对语言规范的事实解释正式写入规范,并增加了对第三版发布后出现的新特性的支持。这些特性包括访问器属性、对象的反射式创建与检查、通过程序控制属性特性、额外的数组操作函数、对 JSON 对象编码格式的支持,以及提供增强错误检查和程序安全性的严格模式。第五版于 2009 年 12 月获 Ecma 大会通过。

第五版被提交给 ISO/IEC JTC 1,以便通过快速程序采纳,并获批为国际标准 ISO/IEC 16262:2011。ECMAScript 标准第 5.1 版纳入了少量修正,其文本与 ISO/IEC 16262:2011 相同。第 5.1 版于 2011 年 6 月获 Ecma 大会通过。

第六版的集中开发始于 2009 年,当时第五版正准备发布。然而,在此之前,自 1999 年第三版发布以来,已经进行了大量实验和语言增强设计工作。从切实的意义上说,第六版的完成是十五年努力的结晶。本版的目标包括为大型应用、库的创建,以及将 ECMAScript 用作其他语言的编译目标提供更好的支持。其主要增强包括模块、类声明、词法块作用域、迭代器和生成器、用于异步编程的 promise、解构模式,以及正确的尾调用。ECMAScript 内置库得到扩展,以支持更多数据抽象,包括映射、集合和二进制数值数组,并增强了对字符串和正则表达式中 Unicode 补充字符的支持。内置对象也可以通过子类化进行扩展。第六版为语言和库的定期增量增强奠定了基础。第六版于 2015 年 6 月获大会通过。

ECMAScript 2016 是按照 Ecma TC39 新的年度发布节奏和开放开发流程发布的首个 ECMAScript 版本。基于 ECMAScript 2015 源文档构建了纯文本源文档,作为完全在 GitHub 上进行后续开发的基础。在本标准开发的一年中,提交了数百个拉取请求和议题,涵盖数千项错误修复、编辑性修正和其他改进。此外,还开发了许多软件工具来协助这项工作,包括 Ecmarkup、Ecmarkdown 和 Grammarkdown。ES2016 还支持了新的求幂运算符,并为 Array.prototype 添加了名为 includes 的新方法。

ECMAScript 2017 引入了异步函数、共享内存和原子操作,同时包含较小的语言和库增强、错误修复以及编辑性更新。异步函数通过为返回 promise 的函数提供语法来改善异步编程体验。共享内存和原子操作引入了新的内存模型,使多代理程序能够使用原子操作进行通信,即使在并行 CPU 上也能确保明确定义的执行顺序。它还为 Object 添加了新的静态方法:Object.values、Object.entries 和 Object.getOwnPropertyDescriptors。

ECMAScript 2018 通过异步迭代器协议和异步生成器引入了对异步迭代的支持。它还包含四项新的正则表达式特性:dotAll 标志、具名捕获组、Unicode 属性转义和后行断言。最后,它还包含对象的剩余属性和展开属性。

ECMAScript 2019 引入了几个新的内置函数:Array.prototype 上用于展平数组的 flat 和 flatMap;用于将 Object.entries 的返回值直接转换为新 Object 的 Object.fromEntries;以及 String.prototype 上的 trimStart 和 trimEnd,作为已广泛实现但非标准的内置方法 String.prototype.trimLeft 和 trimRight 的命名更恰当的替代方法。此外,它还包含一些语法和语义方面的小幅更新。语法更新包括可选的 catch 绑定参数,以及允许在字符串字面量中使用 U+2028(行分隔符)和 U+2029(段落分隔符),以与 JSON 保持一致。其他更新包括要求 Array.prototype.sort 使用稳定排序,要求 JSON.stringify 无论输入如何都返回格式良好的 UTF-8,以及通过要求 Function.prototype.toString 返回相应的原始源文本或标准占位符来明确其行为。

ECMAScript 2020,即第 11版,为 String 引入了 matchAll 方法,用于生成遍历全局正则表达式产生的所有匹配对象的迭代器;引入了 import(),这是一种使用动态说明符异步导入模块的语法;引入了 BigInt,这是一种用于处理任意精度整数的新数值原始类型;引入了 Promise.allSettled,这是一个不会短路的 Promise 组合方法;引入了 globalThis,这是一种访问全局 this 值的通用方式;引入了在模块内使用的专用语法 export * as ns from 'module';进一步标准化了 for-in 的枚举顺序;引入了 import.meta,这是模块中可用的由宿主填充的对象,可以包含有关模块的上下文信息;并添加了两项新语法特性,以改进对“空值”(undefined 或 null)的处理:空值合并,这是一种值选择运算符;以及可选链,这是一种属性访问和函数调用运算符,当要访问或调用的值为空值时会短路。

ECMAScript 2021,即第 12版,为 String 引入了 replaceAll 方法;引入了 Promise.any,这是一个在某个输入值兑现时短路的 Promise 组合方法;引入了 AggregateError,这是一种用于同时表示多个错误的新 Error 类型;引入了逻辑赋值运算符(??=、&&=、||=);引入了 WeakRef,用于引用目标对象而不阻止其被垃圾回收,以及 FinalizationRegistry,用于管理在目标对象被垃圾回收时执行的清理操作的注册和注销;引入了数值字面量分隔符(1_000);并进一步明确了 Array.prototype.sort 的行为,减少了导致实现定义排序顺序的情况。

ECMAScript 2022,即第 13版,引入了顶层 await,允许在模块顶层使用该关键字;引入了新的类元素:公共和私有实例字段、公共和私有静态字段、私有实例方法和访问器,以及私有静态方法和访问器;引入了类内静态块,用于在每次类求值时执行初始化;引入了 #x in obj 语法,用于检查对象上是否存在私有字段;通过 /d 标志引入了正则表达式匹配索引,为匹配的子字符串提供起始和结束索引;为 Error 对象引入了 cause 属性,可用于记录错误的因果链;为 String、Array 和 TypedArray 引入了 at 方法,允许使用相对索引;并引入了 Object.hasOwn,作为 Object.prototype.hasOwnProperty 的便捷替代方法。

ECMAScript 2023,即第 14版,为 Array.prototype 和 TypedArray.prototype 引入了 toSorted、toReversed、with、findLast 和 findLastIndex 方法,并为 Array.prototype 引入了 toSpliced 方法;增加了对文件开头 #! 注释的支持,以更好地支持可执行的 ECMAScript 文件;并允许将大多数 Symbol 用作弱集合中的键。

ECMAScript 2024,即第 15版,增加了调整 ArrayBuffer 和 SharedArrayBuffer 大小以及转移它们的功能;添加了新的 RegExp /v 标志,用于创建具有更高级字符串集合处理特性的 RegExp;并引入了用于构造 Promise 的便捷方法 Promise.withResolvers、用于聚合数据的 Object.groupBy 和 Map.groupBy 方法、用于异步等待共享内存发生更改的 Atomics.waitAsync 方法,以及用于检查并确保字符串仅包含格式良好 Unicode 的 String.prototype.isWellFormed 和 String.prototype.toWellFormed 方法。

ECMAScript 2025,即第 16版,添加了新的全局 Iterator,以及用于处理迭代器的相关静态方法和原型方法;为 Set.prototype 添加了用于执行常见 Set 操作的方法;增加了对导入 JSON 模块的支持,以及用于声明导入模块特性的语法;添加了 RegExp.escape 方法,用于转义字符串,以便安全地将其用于正则表达式;添加了在正则表达式内部启用和禁用修饰符标志的语法;添加了 Promise.try 方法,用于调用可能返回或不返回 Promise 的函数,并确保结果始终为 Promise;还添加了新的 Float16Array TypedArray 种类,以及相关的 DataView.prototype.getFloat16、DataView.prototype.setFloat16 和 Math.f16round 方法。

ECMAScript 2026,即第 17版,添加了 Math.sumPrecise,用于对由不同数量级的 Number 值组成的可迭代对象求和,同时尽量减少精度损失;添加了 Iterator.concat,用于按顺序连接迭代器;添加了 Array.fromAsync,用于从异步可迭代对象和其他异步来源构造 Array;添加了 Error.isError,用于识别错误对象;为 Map.prototype 和 WeakMap.prototype 添加了方法,用于在键尚不存在时提供检索所用的默认值;为 Uint8Array 添加了方法,用于在二进制数据与其十六进制和 base64 编码的 String 值之间进行转换;为 JSON.parse 的 reviver 添加了一个参数,用于访问匹配的 JSON 源文本片段;并添加了 JSON.rawJSON,用于精细控制 JSON.stringify 对原始值的输出。

代表许多组织的数十位成员在 Ecma TC39 内为本版及先前各版的开发做出了非常重要的贡献。此外,一个充满活力的社区已经形成,为 TC39 的 ECMAScript 工作提供支持。该社区审阅了众多草案,提交了数千份错误报告,进行了实现实验,贡献了测试套件,并向全球开发者社区普及 ECMAScript。遗憾的是,无法一一列出并感谢为这项工作做出贡献的每个人和组织。

Allen Wirfs-Brock
ECMA-262,项目编辑,第 6版

Brian Terlson
ECMA-262,项目编辑,第 7版至第 10版

Jordan Harband
ECMA-262,项目编辑,第 10版至第 12版

Kevin Gibbons
ECMA-262,项目编辑,第 12版至第 17版

Shu-yu Guo
ECMA-262,项目编辑,第 12版至第 18版

Michael Ficarra
ECMA-262,项目编辑,第 12版至第 18版

Richard Gibson
ECMA-262,项目编辑,第 18版

Ron Buckton
ECMA-262,项目编辑,第 18版

Nicolò Ribaudo
ECMA-262,项目编辑,第 18版

Linus Groh
ECMA-262,项目编辑,第 18版

1 范围

本标准定义了 ECMAScript 2027 通用编程语言。

2 符合性

符合规范的 ECMAScript 实现必须提供并支持本规范描述的所有类型、值、对象、属性、函数,以及程序语法和语义。

符合规范的 ECMAScript 实现必须按照 Unicode 标准和 ISO/IEC 10646 的最新版本解释输入的源文本。

如果符合规范的 ECMAScript 实现提供了应用程序编程接口(API),以支持需要适应不同人类语言和国家所使用的语言及文化惯例的程序,则该实现必须实现与本规范兼容的最新版本 ECMA-402 所定义的接口。

符合规范的 ECMAScript 实现可以提供本规范所描述内容之外的其他类型、值、对象、属性和函数。特别是,符合规范的 ECMAScript 实现可以为本规范描述的对象提供本规范未描述的属性,以及这些属性的值。

符合规范的 ECMAScript 实现可以支持本规范未描述的程序和正则表达式语法。特别是,符合规范的 ECMAScript 实现可以支持使用本规范 12.7.2 小节中注明的任何“未来保留字”的程序语法。

符合规范的 ECMAScript 实现不得实现 17.1 小节中列为禁止扩展的任何扩展。

符合规范的 ECMAScript 实现不得重新定义任何非实现定义、非实现近似或非宿主定义的功能。

除非另有说明,符合规范的 ECMAScript 实现可以选择实现或不实现规范性可选小节。通常要求 Web 浏览器实现所有规范性可选小节。(参见附录 B。)如果实现了任何规范性可选行为,则必须实现包含该行为的规范性可选章节中的所有行为。本规范使用彩色方框中的“规范性可选”字样标示规范性可选章节,如下所示。

2.1 规范性可选章节标题示例

章节内容示例。

符合规范的 ECMAScript 实现必须实现遗留小节,除非这些小节也被标记为规范性可选。遗留小节中规定的所有语言特性和行为都具有一个或多个不理想的特征。然而,由于现有应用仍在使用它们,无法将其从本规范中移除。这些特性不被视为 ECMAScript 核心语言的一部分。程序员在编写新的 ECMAScript 代码时,不应使用这些特性和行为,也不应假定它们存在。

2.2 遗留章节标题示例

章节内容示例。

2.3 遗留规范性可选章节标题示例

章节内容示例。

3 规范性引用文件

下列引用文件对于本文档的应用不可或缺。对于注明日期的引用文件,仅所引用的版本适用。对于未注明日期的引用文件,其最新版本(包括任何修订)适用。

IEEE 754-2019,IEEE 浮点算术标准。

Unicode 标准。
https://unicode.org/versions/latest

ISO/IEC 10646,信息技术 — 通用多八位组编码字符集(UCS),以及修订 1:2005、修订 2:2006、修订 3:2008、修订 4:2008 和其他修订及勘误,或其后继标准。

ECMA-402,ECMAScript 国际化 API 规范,具体为与本规范本版对应的年度版本。
https://www.ecma-international.org/publications-and-standards/standards/ecma-402/

ECMA-404,JSON 数据交换格式。
https://www.ecma-international.org/publications-and-standards/standards/ecma-404/

4 概述

本节包含 ECMAScript 语言的非规范性概述。

ECMAScript 是一种面向对象的编程语言,用于在宿主环境中执行计算和操作计算对象。此处定义的 ECMAScript 并不打算在计算方面自给自足;事实上,本规范没有对外部数据的输入或计算结果的输出做出规定。相反,ECMAScript 程序的计算环境应当不仅提供本规范描述的对象和其他功能,还提供某些环境特有的对象;这些对象的描述和行为超出了本规范的范围,本规范仅指出,它们可以提供某些可由 ECMAScript 程序访问的属性和可由其调用的函数。

ECMAScript 最初被设计为脚本语言,但如今已被广泛用作通用编程语言。脚本语言是一种用于操作、定制现有系统的功能并使其自动化的编程语言。在这样的系统中,用户界面已经提供了有用的功能,而脚本语言则是一种将这些功能开放给程序控制的机制。因此,可以说现有系统提供了一个包含对象和功能的宿主环境,以补全脚本语言的能力。脚本语言旨在供专业和非专业程序员使用。

ECMAScript 最初被设计为一种 Web 脚本语言,提供了使浏览器中的 Web 页面具有动态效果,以及作为基于 Web 的客户端—服务器架构的一部分执行服务器计算的机制。如今,ECMAScript 被用于为各种宿主环境提供核心脚本能力。因此,本文档独立于任何特定宿主环境来规定核心语言。

ECMAScript 的用途已超出简单的脚本编写,如今被用于许多不同环境和规模中的各种编程任务。随着 ECMAScript 用途的扩展,它提供的特性和功能也不断增加。ECMAScript 如今已是一种功能完备的通用编程语言。

4.1 Web 脚本编程

Web 浏览器为客户端计算提供 ECMAScript 宿主环境,例如,其中包含表示窗口、菜单、弹出窗口、对话框、文本区域、锚点、框架、历史记录、Cookie 和输入/输出的对象。此外,宿主环境还提供了将脚本代码关联到事件的方式,这些事件包括焦点更改、页面和图像加载、卸载、错误和中止、选择、表单提交以及鼠标操作。脚本代码出现在 HTML 中,显示的页面则由用户界面元素以及固定和计算生成的文本与图像组合而成。脚本代码响应用户交互,无需主程序。

Web 服务器为服务器端计算提供不同的宿主环境,其中包括表示请求、客户端和文件的对象,以及锁定和共享数据的机制。通过结合使用浏览器端和服务器端脚本,可以在客户端与服务器之间分配计算任务,同时为基于 Web 的应用提供定制的用户界面。

每个支持 ECMAScript 的 Web 浏览器和服务器都提供自己的宿主环境,从而补全 ECMAScript 执行环境。

4.2 宿主和实现

为了便于将 ECMAScript 集成到宿主环境中,本规范将某些功能(例如抽象操作)的全部或部分定义交由本规范之外的来源提供。在编辑表述上,本规范区分以下几种定义委托方式。

实现是进一步定义附录 D 中列举的功能,或标记为实现定义或实现近似的功能的外部来源。在非正式用法中,实现指具体的软件产物,例如某个特定的 Web 浏览器。

实现定义的功能是将其定义交由外部来源提供且不做进一步限定的功能。本规范不对特定行为提出任何建议,符合规范的实现可以在本规范规定的约束范围内自由选择任何行为。

实现近似的功能是将其定义交由外部来源提供,同时建议一种理想行为的功能。尽管符合规范的实现可以在本规范规定的约束范围内自由选择任何行为,但鼓励它们尽力接近理想行为。某些数学运算,例如 Math.exp,属于实现近似的功能。

宿主是进一步定义附录 D 中所列功能,但不进一步定义其他实现定义或实现近似功能的外部来源。在非正式用法中,宿主指通过附录 D 以相同方式与本规范对接的所有实现的集合,例如所有 Web 浏览器的集合。宿主通常是一份外部规范,例如 WHATWG HTML(https://html.spec.whatwg.org/)。换言之,宿主定义的功能通常在外部规范中得到进一步定义。

宿主钩子是由外部来源全部或部分定义的抽象操作。所有宿主钩子都必须列于附录 D 中。宿主钩子至少必须满足以下要求:

宿主定义的功能是将其定义交由外部来源提供且不做进一步限定,并列于附录 D 中的功能。非宿主的实现也可以为宿主定义的功能提供定义。

宿主环境是对所有宿主定义功能的定义所做的一组特定选择。宿主环境通常包含可用于获取输入和提供输出的对象或函数,它们作为全局对象的宿主定义属性存在。

本规范遵循始终使用最具体术语的编辑惯例。例如,如果某项功能是宿主定义的,就不应将其称为实现定义的。

宿主和实现都可以通过本规范定义的语言类型、规范类型、抽象操作、语法产生式、内在对象和内在符号与本规范对接。

4.3 ECMAScript 概述

以下是 ECMAScript 的非正式概述,并未描述该语言的所有部分。本概述不属于标准的正式内容。

ECMAScript 基于对象:基本语言功能和宿主功能由对象提供,而 ECMAScript 程序则是一组相互通信的对象。在 ECMAScript 中,对象是由零个或多个属性组成的集合,每个属性都具有决定其使用方式的特性,例如,当某个属性的 Writable 特性被设置为 false 时,正在执行的 ECMAScript 代码对该属性赋予不同值的任何尝试都会失败。属性是容纳其他对象、原始值或函数的容器。原始值是以下某种内置类型的成员:Undefined、Null、Boolean、Number、BigInt、String 和 Symbol; 对象是内置类型 Object 的成员;函数是可调用的对象。通过属性与对象关联的函数称为方法。

ECMAScript 定义了一组内置对象,以补全 ECMAScript 实体的定义。这些内置对象包括全局对象;对语言运行时语义至关重要的对象,包括 Object、Function、Boolean、Symbol 和各种 Error 对象;表示和操作数值的对象,包括 Math、Number 和 Date;文本处理对象 String 和 RegExp;表示值的索引集合的对象,包括 Array 和九种不同的类型化数组,其元素均具有特定的数值数据表示;键控集合,包括 Map 和 Set 对象;支持结构化数据的对象,包括 JSON 对象、ArrayBuffer、SharedArrayBuffer 和 DataView;支持控制抽象的对象,包括生成器函数和 Promise 对象;以及反射对象,包括 Proxy 和 Reflect。

ECMAScript 还定义了一组内置运算符。ECMAScript 运算符包括各种一元运算、乘法类运算符、加法类运算符、位移运算符、关系运算符、相等运算符、二元按位运算符、二元逻辑运算符、赋值运算符和逗号运算符。

模块为大型 ECMAScript 程序提供支持,允许将程序划分为多个语句和声明序列。每个模块都明确标识其使用的、需要由其他模块提供的声明,以及自身哪些声明可供其他模块使用。

ECMAScript 的语法有意与 Java 语法相似。ECMAScript 的语法较为宽松,使其能够成为一种易于使用的脚本语言。例如,不要求声明变量的类型,属性也不关联类型,所定义函数的声明也不必在文本位置上先于对它们的调用。

4.3.1 对象

尽管 ECMAScript 包含类定义的语法,但 ECMAScript 对象在本质上并不像 C++、Smalltalk 或 Java 中的对象那样基于类。相反,可以通过多种方式创建对象,包括使用字面量表示法,或使用构造函数,后者先创建对象,再通过为对象的属性赋予初始值来执行初始化其全部或部分内容的代码。每个构造函数都是一个具有名为 "prototype" 的属性的函数,该属性用于实现基于原型的继承和共享属性。通过在 new 表达式中使用构造函数来创建对象;例如,new Date(2009, 11) 创建一个新的 Date 对象。不使用 new 调用构造函数时,其结果取决于该构造函数。例如,Date() 生成当前日期和时间的字符串表示,而不是对象。

通过构造函数创建的每个对象都具有一个指向其构造函数的 "prototype" 属性值的隐式引用(称为该对象的原型)。此外,原型还可以具有一个指向其自身原型的非 null 隐式引用,依此类推;这称为原型链。当引用对象中的某个属性时,该引用指向原型链中第一个包含该名称属性的对象上的同名属性。换言之,首先检查直接指定的对象是否具有该属性;如果该对象包含指定名称的属性,该引用就指向这个属性;如果该对象不包含指定名称的属性,则接着检查该对象的原型;依此类推。

图 1: 对象与原型的关系
由许多方框和箭头组成的图像。

在基于类的面向对象语言中,通常由实例承载状态,由类承载方法,继承仅涉及结构和行为。在 ECMAScript 中,状态和方法都由对象承载,而结构、行为和状态都会被继承。

如果对象自身不直接包含其原型所包含的某个特定属性,则所有这样的对象都会共享该属性及其值。图 1 对此进行了说明:

CF 是一个构造函数(也是一个对象)。使用 new 表达式创建了五个对象:cf1、cf2、cf3、cf4 和 cf5。这些对象各自包含名为 "q1" 和 "q2" 的属性。虚线表示隐式原型关系;因此,例如,cf3 的原型是 CFp。构造函数 CF 自身具有两个属性,分别名为 "P1" 和 "P2",它们对 CFp、cf1、cf2、cf3、cf4 或 cf5 不可见。CFp 中名为 "CFP1" 的属性由 cf1、cf2、cf3、cf4 和 cf5 共享(但不由 CF 共享),CFp 的隐式原型链中所有名称不是 "q1"、"q2" 或 "CFP1" 的属性也是如此。注意,CF 与 CFp 之间不存在隐式原型链接。

与大多数基于类的对象语言不同,可以通过赋值动态地向对象添加属性。也就是说,构造函数不必为所构造对象的所有或任何属性命名或赋值。在上图中,可以通过为 CFp 中的属性赋予一个新值,为 cf1、cf2、cf3、cf4 和 cf5 添加一个新的共享属性。

尽管 ECMAScript 对象本质上并不基于类,但基于构造函数、原型对象和方法的共同模式来定义类似类的抽象通常很方便。ECMAScript 内置对象本身也遵循这种类似类的模式。从 ECMAScript 2015 开始,ECMAScript 语言包含了类定义语法,允许程序员简洁地定义符合与内置对象相同的类式抽象模式的对象。

4.3.2 ECMAScript 的严格变体

ECMAScript 语言认识到,某些语言使用者可能希望限制自己对语言中某些可用特性的使用。他们可能出于安全考虑,为了避免他们认为容易出错的特性,为了获得增强的错误检查,或出于自行选择的其他原因而这样做。为支持这种需求,ECMAScript 定义了该语言的严格变体。该语言的严格变体排除了常规 ECMAScript 语言中的某些特定语法和语义特性,并修改了某些特性的详细语义。严格变体还规定了额外的错误条件,要求在该语言的非严格形式未规定为错误的情况下,通过抛出错误异常进行报告。

ECMAScript 的严格变体通常称为该语言的严格模式。如 11.2.2 所述,严格模式的选择以及 ECMAScript 严格模式语法和语义的使用,是在单个 ECMAScript 源文本单元级别显式确定的。由于严格模式是在语法源文本单元级别选择的,因此严格模式仅施加在该源文本单元内部局部生效的限制。严格模式不会限制或修改 ECMAScript 语义中必须在多个源文本单元之间一致运作的任何方面。完整的 ECMAScript 程序可以同时由严格模式和非严格模式的 ECMAScript 源文本单元组成。在这种情况下,严格模式仅在实际执行严格模式源文本单元中定义的代码时适用。

为符合本规范,ECMAScript 实现必须同时实现本规范所定义的完整、不受限制的 ECMAScript 语言及其严格变体。此外,实现必须支持将不受限制的源文本单元和严格模式源文本单元组合为单个复合程序。

4.4 术语和定义

以下术语和定义适用于本文档。

4.4.1 实现近似

实现近似的功能由外部来源全部或部分定义,但本规范为其建议了一种理想行为

4.4.2 实现定义

实现定义的功能由本规范之外的来源全部或部分定义

4.4.3 宿主定义

与实现定义相同

注

有关编辑表述上的区分,请参见 4.2 节。

4.4.4 类型

6 节所定义的数据值的集合

4.4.5 原始值

6 节所定义的 Undefined、Null、Boolean、Number、BigInt、Symbol 或 String 类型之一的成员

注

原始值是在语言实现的最底层直接表示的数据项。

4.4.6 对象

Object 类型的成员

注

对象是属性的集合,并具有单个原型对象。原型可以是 null。

4.4.7 构造函数

创建并初始化对象的函数对象

注

构造函数的 "prototype" 属性值是一个原型对象,用于实现继承和共享属性。

4.4.8 原型

为其他对象提供共享属性的对象

注

当构造函数创建对象时,该对象会隐式引用构造函数的 "prototype" 属性,以便解析属性引用。程序表达式 constructor.prototype 可以引用构造函数的 "prototype" 属性,而添加到对象原型上的属性会通过继承由所有共享该原型的对象共享。或者,可以使用内置函数 Object.create 创建一个具有显式指定原型的新对象。

4.4.9 普通对象

对于所有对象都必须支持的基本内部方法具有默认行为的对象

4.4.10 异质对象

对于一个或多个基本内部方法不具有默认行为的对象

注

任何不是普通对象的对象都是异质对象。

4.4.11 标准对象

其语义由本规范定义的对象

4.4.12 内置对象

由 ECMAScript 实现规定并提供的对象

注

标准内置对象由本规范定义。ECMAScript 实现可以规定并提供其他种类的内置对象。

4.4.13 undefined 值

变量尚未被赋值时使用的原始值

4.4.14 Undefined 类型

唯一值为 undefined 值的类型

4.4.15 null 值

表示有意不存在任何对象值的原始值

4.4.16 Null 类型

唯一值为 null 值的类型

4.4.17 Boolean 值

Boolean 类型的成员

注

Boolean 值只有两个:true 和 false。

4.4.18 Boolean 类型

由原始值 true 和 false 组成的类型

4.4.19 Boolean 对象

Object 类型的成员,是标准内置 Boolean 构造函数的实例

注

Boolean 对象通过在 new 表达式中使用 Boolean 构造函数并提供一个 Boolean 值作为参数来创建。生成的对象具有一个内部槽,其值为该 Boolean 值。Boolean 对象可以被强制转换为 Boolean 值。

4.4.20 String 值

由零个或多个 16 位无符号整数值组成的有限有序序列形式的原始值

注

String 值是 String 类型的成员。序列中的每个整数值通常表示 UTF-16 文本的单个 16 位单元。然而,除了要求这些值必须是 16 位无符号整数之外,ECMAScript 不对它们施加任何限制或要求。

4.4.21 String 类型

所有可能的 String 值的集合

4.4.22 String 对象

Object 类型的成员,是标准内置 String 构造函数的实例

注

String 对象通过在 new 表达式中使用 String 构造函数并提供一个 String 值作为参数来创建。生成的对象具有一个内部槽,其值为该 String 值。通过将 String 构造函数作为函数调用,可以将 String 对象强制转换为 String 值(22.1.1.1)。

4.4.23 Number 值

对应于 IEEE 754-2019 双精度 64 位二进制格式值的原始值

注

Number 值是 Number 类型的成员,是数值的直接表示。

4.4.24 Number 类型

所有可能的 Number 值的集合,包括 NaN(“非数值”)、+∞𝔽(正无穷)和 -∞𝔽(负无穷)

4.4.25 Number 对象

Object 类型的成员,是标准内置 Number 构造函数的实例

注

Number 对象通过在 new 表达式中使用 Number 构造函数并提供一个 Number 值作为参数来创建。生成的对象具有一个内部槽,其值为该 Number 值。通过将 Number 构造函数作为函数调用,可以将 Number 对象强制转换为 Number 值(21.1.1.1)。

4.4.26 Infinity

表示正无穷的 Number 值

4.4.27 NaN

表示 IEEE 754-2019 NaN(“非数值”)值的 Number 值

4.4.28 BigInt 值

对应于任意精度整数值的原始值

4.4.29 BigInt 类型

所有可能的 BigInt 值的集合

4.4.30 BigInt 对象

Object 类型的成员,是标准内置 BigInt 构造函数的实例

4.4.31 Symbol 值

表示唯一的非 String 对象属性键的原始值

4.4.32 Symbol 类型

所有可能的 Symbol 值的集合

4.4.33 Symbol 对象

Object 类型的成员,是标准内置 Symbol 构造函数的实例

4.4.34 函数

可以作为子例程调用的 Object 类型成员

注

除属性外,函数还包含可执行代码和状态,它们决定函数被调用时的行为。函数的代码可以用 ECMAScript 编写,也可以不用 ECMAScript 编写。

4.4.35 内置函数

属于函数的内置对象

注

内置函数的示例包括 parseInt 和 Math.exp。宿主或实现可以提供本规范未描述的其他内置函数。

4.4.36 内置构造函数

属于构造函数的内置函数

注

内置构造函数的示例包括 Object 和 Function。宿主或实现可以提供本规范未描述的其他内置构造函数。

4.4.37 属性

对象中将键(String 值或 Symbol 值)与值关联起来的部分

注

根据属性的形式,值可以直接表示为数据值(原始值、对象或函数对象),也可以通过一对访问器函数间接表示。

4.4.38 方法

作为属性值的函数

注

当函数作为对象的方法被调用时,该对象会作为函数的 this 值传递给函数。

4.4.39 内置方法

属于内置函数的方法

注

标准内置方法由本规范定义。宿主或实现可以提供本规范未描述的其他内置方法。

4.4.40 特性

定义属性某项特征的内部值

4.4.41 自有属性

由其所属对象直接包含的属性

4.4.42 继承属性

对象的非自有属性,而是该对象原型的属性(自有或继承)

4.5 本规范的组织结构

本规范的其余部分组织如下:

5 节定义了贯穿本规范使用的表示法约定。

6 至 10 节定义了 ECMAScript 程序运行所在的执行环境。

11 至 17 节定义了实际的 ECMAScript 编程语言,包括其语法编码和所有语言特性的执行语义。

18 至 28 节定义了 ECMAScript 标准库。其中包含 ECMAScript 程序执行时可使用的所有标准对象的定义。

29 节描述了对 SharedArrayBuffer 支持的内存进行访问时的内存一致性模型,以及 Atomics 对象的方法。

5 表示法约定

5.1 句法和词法文法

5.1.1 上下文无关文法

上下文无关文法由若干产生式组成。每个产生式的左侧是一个称为非终结符的抽象符号,其右侧是由零个或多个非终结符和终结符组成的序列。对于每种文法,终结符都取自指定的字母表。

链式产生式是右侧恰好包含一个非终结符以及零个或多个终结符的产生式。

从仅由一个称为目标符号的特定非终结符组成的句子开始,给定的上下文无关文法规定了一种语言,即通过反复将序列中的任意非终结符替换为以该非终结符为左侧的某个产生式的右侧,所能得到的所有可能终结符序列组成的集合(该集合可能无限)。

5.1.2 词法和 RegExp 文法

ECMAScript 的词法文法在 12 节中给出。该文法以符合 11.1 中 SourceCharacter 定义规则的 Unicode 码点作为终结符。它定义了一组从目标符号 InputElementDiv、InputElementTemplateTail、InputElementRegExp、InputElementRegExpOrTemplateTail 或 InputElementHashbangOrRegExp 开始的产生式,描述如何将这些码点的序列转换为输入元素序列。

除空白和注释之外的输入元素构成 ECMAScript 句法文法的终结符,称为 ECMAScript 词元。这些词元是 ECMAScript 语言的保留字、标识符、字面量和标点符号。此外,行终止符虽然不被视为词元,但也会成为输入元素流的一部分,并引导自动分号插入过程(12.10)。单纯的空白和单行注释会被丢弃,不会出现在句法文法的输入元素流中。MultiLineComment(即形式为 /*…*/ 的注释,无论是否跨越多行)如果不包含行终止符,同样会被直接丢弃;但如果 MultiLineComment 包含一个或多个行终止符,则会被替换为单个行终止符,成为句法文法输入元素流的一部分。

ECMAScript 的 RegExp 文法在 22.2.1 中给出。该文法同样以 SourceCharacter 所定义的码点作为终结符。它定义了一组从目标符号 Pattern 开始的产生式,描述如何将码点序列转换为正则表达式模式。

词法和 RegExp 文法的产生式使用两个冒号“::”作为分隔标点,以便区分。词法和 RegExp 文法共享某些产生式。

5.1.3 数值字符串文法

数值字符串文法见 7.1.4.1。它以 SourceCharacter 为终结符,用于从目标符号 StringNumericLiteral 开始将 String 值转换为数值(它与数值字面量的词法文法相似但不同)。

数值字符串文法的产生式使用三个冒号“:::”作为标点,以便区分,并且从不用于解析源文本。

5.1.4 句法文法

ECMAScript 的句法文法在 13 至 16 节中给出。该文法以词法文法定义的 ECMAScript 词元作为终结符(5.1.2)。它定义了一组从两个可选目标符号 Script 和 Module 开始的产生式,描述词元序列如何构成 ECMAScript 程序中句法正确的独立组成部分。

当要将码点流解析为 ECMAScript Script 或 Module 时,首先通过反复应用词法文法将其转换为输入元素流;然后对该输入元素流应用一次句法文法进行解析。如果输入元素流中的词元无法被解析为目标非终结符(Script 或 Module)的单个实例且不留下任何词元,则该输入流存在句法错误。

解析成功时,会构造一棵解析树,这是一种有根树结构,其中每个节点都是解析节点。每个解析节点都是文法中某个符号的实例;它表示可由该符号推导出的源文本片段。解析树的根节点表示整个源文本,是此次解析的目标符号的实例。当解析节点是某个非终结符的实例时,它也是以该非终结符为左侧的某个产生式的实例。此外,它具有零个或多个子节点,分别对应产生式右侧的每个符号:每个子节点都是相应符号的实例,即解析节点。

每次调用解析器都会实例化新的解析节点,即使源文本相同,也不会在不同解析之间复用解析节点。当且仅当解析节点表示同一源文本片段、是同一文法符号的实例,并且由同一次解析器调用产生时,才将它们视为同一解析节点。

注 1

多次解析同一个 String 值会产生不同的解析节点。例如,考虑:

let str = "1 + 1;";
eval(str);
eval(str);

每次调用 eval 都会将 str 的值转换为 ECMAScript 源文本,并执行独立的解析,创建各自独立的解析节点树。即使每次解析所处理的源文本都来自同一个 String 值,这些树仍然不同。

注 2
解析节点是规范中的概念性构造,不要求实现使用类似的数据结构。

句法文法的产生式仅使用一个冒号“:”作为标点,以便区分。

13 至 16 节给出的句法文法,并未完整说明哪些词元序列可被接受为正确的 ECMAScript Script 或 Module。某些额外的词元序列也会被接受,即只需在序列中的某些位置(例如行终止符字符之前)添加分号,就能由文法描述的序列。此外,如果行终止符字符出现在某些“不合适”的位置,即使某些词元序列由文法描述,也不被认为是可接受的。

在某些情况下,为避免歧义,句法文法使用更一般化的产生式,允许不能构成有效 ECMAScript Script 或 Module 的词元序列。例如,对象字面量和对象解构模式就使用了这种技术。在这种情况下,会提供限制更严格的补充文法,进一步限制可接受的词元序列。通常,随后会有一条提前错误规则规定,在某些上下文中,“p 必须覆盖一个 n”,其中 p 是解析节点(一般化产生式的实例),而 n 是补充文法中的非终结符。这意味着:

  1. 不对 p 或其任何后代节点应用提前错误规则。
  2. 以 n 为目标符号,重新解析最初由 p 匹配的词元序列。如果 n 接受文法参数,则将它们设置为最初解析 p 时使用的相同值。
  3. 如果该词元序列能够被解析为 n 的单个实例,且没有剩余词元,则:
    1. 我们将 n 的该实例(对于给定 p 唯一的解析节点)称为“由 p 覆盖的 n”。
    2. 对由 p 覆盖的 n 及其后代节点应用提前错误规则,并根据进一步出现的“必须覆盖”情况进行调整。
  4. 否则(如果解析失败),这是一个提前句法错误。

5.1.5 文法表示法

5.1.5.1 终结符

在 ECMAScript 文法中,某些终结符以等宽字体显示。它们必须按所写形式原样出现在源文本中。以这种方式指定的所有终结符码点都应理解为基本拉丁字母区块中的相应 Unicode 码点,而不是其他 Unicode 范围中外观相似的码点。终结符中的码点不能通过 \ UnicodeEscapeSequence 表示。

在以单个 Unicode 码点作为终结符的文法(即词法、RegExp 和数值字符串文法)中,产生式中连续出现的多个等宽码点,只是将相同码点序列写成独立终结符时的一种简写。

例如,产生式:

HexIntegerLiteral :: 0x HexDigits

是以下形式的简写:

HexIntegerLiteral :: 0 x HexDigits

相比之下,在句法文法中,一串连续的等宽码点表示单个终结符。

终结符还有另外两种形式:

  • 在词法和 RegExp 文法中,没有常规打印表示形式的 Unicode 码点改用“<ABBREV>”形式表示,其中“ABBREV”是该码点或码点集合的助记符。这些形式在 Unicode 格式控制字符、空白 和 行终止符 中定义。
  • 在句法文法中,某些终结符(例如 IdentifierName 和 RegularExpressionLiteral)以斜体显示,因为它们引用词法文法中的同名非终结符。

5.1.5.2 非终结符和产生式

非终结符以斜体显示。非终结符的定义(也称为“产生式”)以所定义的非终结符名称开头,后跟一个或多个冒号。(冒号的数量表示该产生式属于哪种文法。)随后各行列出该非终结符的一个或多个可选右侧。例如,句法定义:

WhileStatement : while ( Expression ) Statement

表明非终结符 WhileStatement 表示词元 while,后跟左括号词元,再跟一个 Expression,再跟右括号词元,最后跟一个 Statement。其中出现的 Expression 和 Statement 本身也是非终结符。再例如,句法定义:

ArgumentList : AssignmentExpression ArgumentList , AssignmentExpression

表明 ArgumentList 可以表示单个 AssignmentExpression,也可以表示一个 ArgumentList,后跟逗号,再跟一个 AssignmentExpression。ArgumentList 的这个定义是递归的,即它通过自身来定义。其结果是,ArgumentList 可以包含任意正数个参数,各参数之间用逗号分隔,其中每个参数表达式都是 AssignmentExpression。这种非终结符的递归定义很常见。

5.1.5.3 可选符号

可出现在终结符或非终结符之后的下标后缀“opt”表示可选符号。包含可选符号的候选项实际上规定了两个右侧,一个省略该可选元素,另一个包含它。这意味着:

VariableDeclaration : BindingIdentifier Initializeropt

是以下形式的便捷简写:

VariableDeclaration : BindingIdentifier BindingIdentifier Initializer

并且:

ForStatement : for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement

是以下形式的便捷简写:

ForStatement : for ( LexicalDeclaration ; Expressionopt ) Statement for ( LexicalDeclaration Expression ; Expressionopt ) Statement

而这又是以下形式的简写:

ForStatement : for ( LexicalDeclaration ; ) Statement for ( LexicalDeclaration ; Expression ) Statement for ( LexicalDeclaration Expression ; ) Statement for ( LexicalDeclaration Expression ; Expression ) Statement

因此,在此示例中,非终结符 ForStatement 实际上具有四个可选右侧。

5.1.5.4 文法参数

产生式可以通过形如“[parameters]”的下标注记进行参数化,该注记可以作为后缀出现在产生式所定义的非终结符之后。“parameters”可以是单个名称,也可以是以逗号分隔的名称列表。参数化产生式是一组产生式的简写,这组产生式通过将前置下划线的参数名称的所有组合追加到参数化非终结符后面来定义。这意味着:

StatementList[Return] : ReturnStatement ExpressionStatement

是以下形式的便捷简写:

StatementList : ReturnStatement ExpressionStatement StatementList_Return : ReturnStatement ExpressionStatement

并且:

StatementList[Return, In] : ReturnStatement ExpressionStatement

是以下形式的简写:

StatementList : ReturnStatement ExpressionStatement StatementList_Return : ReturnStatement ExpressionStatement StatementList_In : ReturnStatement ExpressionStatement StatementList_Return_In : ReturnStatement ExpressionStatement

多个参数会产生组合数量的产生式,在完整文法中不一定会引用所有这些产生式。

产生式右侧对非终结符的引用也可以参数化。例如:

StatementList : ReturnStatement ExpressionStatement[+In]

等价于:

StatementList : ReturnStatement ExpressionStatement_In

而:

StatementList : ReturnStatement ExpressionStatement[~In]

等价于:

StatementList : ReturnStatement ExpressionStatement

非终结符引用可以同时具有参数列表和“opt”后缀。例如:

VariableDeclaration : BindingIdentifier Initializer[+In]opt

是以下形式的简写:

VariableDeclaration : BindingIdentifier BindingIdentifier Initializer_In

在右侧非终结符引用中的参数名称前加上“?”,会使该参数的值取决于对当前产生式左侧符号的引用中是否出现该参数名称。例如:

VariableDeclaration[In] : BindingIdentifier Initializer[?In]

是以下形式的简写:

VariableDeclaration : BindingIdentifier Initializer VariableDeclaration_In : BindingIdentifier Initializer_In

如果某个右侧候选项以“[+parameter]”为前缀,则仅当引用该产生式的非终结符时使用了指定参数,该候选项才可用。如果某个右侧候选项以“[~parameter]”为前缀,则仅当引用该产生式的非终结符时未使用指定参数,该候选项才可用。这意味着:

StatementList[Return] : [+Return] ReturnStatement ExpressionStatement

是以下形式的简写:

StatementList : ExpressionStatement StatementList_Return : ReturnStatement ExpressionStatement

并且:

StatementList[Return] : [~Return] ReturnStatement ExpressionStatement

是以下形式的简写:

StatementList : ReturnStatement ExpressionStatement StatementList_Return : ExpressionStatement

5.1.5.5 one of

当文法定义中的冒号后出现“one of”字样时,表示后续一行或多行中的每个终结符都是一个可选定义。例如,ECMAScript 的词法文法包含以下产生式:

BinaryDigit :: one of 0 1

它只是以下形式的便捷简写:

BinaryDigit :: 0 1

5.1.5.6 [empty]

如果短语“[empty]”作为产生式的右侧出现,则表示该产生式的右侧不包含任何终结符或非终结符。

5.1.5.7 前瞻限制

如果短语“[lookahead = seq]”出现在产生式的右侧,则表示仅当词元序列 seq 是紧随其后的输入词元序列的前缀时,才可以使用该产生式。类似地,“[lookahead ∈ set]”(其中 set 是词元序列的有限非空集合)表示仅当 set 的某个元素是紧随其后的词元序列的前缀时,才可以使用该产生式。为方便起见,该集合也可以写成非终结符,在这种情况下,它表示该非终结符能够展开为的所有词元序列的集合。如果该非终结符能够展开为无限多个不同的词元序列,则视为编辑错误。

这些条件可以取反。“[lookahead ≠ seq]”表示仅当 seq 不是紧随其后的输入词元序列的前缀时,才可以使用包含它的产生式;“[lookahead ∉ set]”表示仅当 set 中没有任何元素是紧随其后的词元序列的前缀时,才可以使用该产生式。

例如,给定以下定义:

DecimalDigit :: one of 0 1 2 3 4 5 6 7 8 9 DecimalDigits :: DecimalDigit DecimalDigits DecimalDigit

以下定义:

LookaheadExample :: n [lookahead ∉ { 1, 3, 5, 7, 9 }] DecimalDigits DecimalDigit [lookahead ∉ DecimalDigit]

匹配字母 n 后跟一个或多个十进制数字且第一个数字为偶数的序列,或者匹配一个后面没有其他十进制数字的十进制数字。

注意,当这些短语用于句法文法时,可能无法明确确定紧随其后的词元序列,因为确定后续词元需要知道在后续位置应使用哪个词法目标符号。因此,当这些短语用于句法文法时,如果所选词法目标符号可能改变 seq 是否为生成的词元序列的前缀,那么让词元序列 seq 出现在前瞻限制中(包括作为序列集合的一部分)就被视为编辑错误。

5.1.5.8 [no LineTerminator here]

如果短语“[no LineTerminator here]”出现在句法文法某个产生式的右侧,则表示该产生式是受限产生式:如果输入流的指定位置出现 LineTerminator,就不得使用该产生式。例如,产生式:

ThrowStatement : throw [no LineTerminator here] Expression ;

表示如果脚本中的 throw 词元与 Expression 之间出现 LineTerminator,就不得使用该产生式。

除非受限产生式禁止出现 LineTerminator,否则输入元素流中任意两个连续词元之间都可以出现任意数量的 LineTerminator,而不影响脚本在句法上的可接受性。

5.1.5.9 but not

产生式的右侧可以使用短语“but not”并在其后指明要排除的展开形式,以规定不允许某些展开形式。例如,产生式:

Identifier :: IdentifierName but not ReservedWord

表示非终结符 Identifier 可以替换为任何能够替换 IdentifierName 的码点序列,前提是同一码点序列不能替换 ReservedWord。

5.1.5.10 描述性短语

最后,在不便列出所有候选项的情况下,少数非终结符会使用无衬线字体的描述性短语来描述:

SourceCharacter :: any Unicode code point

5.2 算法约定

本规范经常使用编号列表来规定算法中的步骤。这些算法用于精确规定 ECMAScript 语言构造所要求的语义。这些算法并不暗示应使用任何特定的实现技术。在实践中,可能存在更高效的算法来实现给定特性。

算法可以通过有序、以逗号分隔的别名序列进行显式参数化,这些别名可在算法步骤中用于引用相应位置传入的实参。可选形参使用外围方括号([ , name ])表示,在算法步骤中与必需形参没有区别。剩余形参可以出现在形参列表末尾,使用前置省略号(, ...name)表示。剩余形参将必需形参和可选形参之后提供的所有实参收集到一个列表中。如果没有这样的额外实参,该列表为空。

算法步骤可以细分为顺序执行的子步骤。子步骤使用缩进,并且自身可以进一步细分为缩进的子步骤。子步骤使用大纲编号约定标识,第一级子步骤以小写字母标记,第二级子步骤以小写罗马数字标记。如果需要超过三级,则重复这些规则,第四级使用数字标记。例如:

  1. 顶层步骤
    1. 子步骤。
    2. 子步骤。
      1. 二级子步骤。
        1. 三级子步骤
          1. 四级子步骤
            1. 五级子步骤

步骤或子步骤可以写成“如果”谓词,以对其子步骤的执行设置条件。在这种情况下,仅当谓词为真时才执行子步骤。如果步骤或子步骤以“否则”开头,则它是对同一级前一个“如果”谓词步骤的否定。

步骤可以以“对于每个”或“重复”开头,以规定迭代执行其子步骤。

以“断言:”开头的步骤断言其算法中的某个不变条件。这些断言用于显式说明原本隐含的算法不变条件。类似地,以“注:”开头的步骤为附近步骤提供相关上下文。断言步骤和注释步骤完全属于说明性内容;它们不增加任何语义要求,因此实现无需检查它们。

算法步骤可以使用“令 x 为 someValue”的形式为任何值声明具名别名。这些别名类似于引用,因为 x 和 someValue 都指向同一底层数据,对任意一方的修改对双方都可见。希望避免这种类似引用行为的算法步骤应显式复制右侧的值:“令 x 为 someValue 的副本”会创建 someValue 的浅拷贝。

别名一经声明,就可以在后续任何步骤中引用,但不得在声明之前的步骤中引用。可以使用“将 x 设置为 someOtherValue”的形式修改别名。

5.2.1 求值顺序

当算法步骤中出现复杂表达式时,应理解为按从左到右、从内到外的顺序求值。例如,步骤

  1. 返回 A(B(), C.[[D]]) + E(F())。

等价于

  1. 令 tmp1 为 B()。
  2. 令 tmp2 为 C.[[D]]。
  3. 令 tmp3 为 A(tmp1, tmp2)。
  4. 令 tmp4 为 F()。
  5. 令 tmp5 为 E(tmp4)。
  6. 令 tmp6 为 tmp3 + tmp5。
  7. 返回 tmp6。

其中,各个 tmpN 别名都是临时的,仅在这些步骤中可见。

5.2.2 抽象操作

为了便于在本规范的多个部分中使用,某些称为抽象操作的算法会被命名,并以参数化函数形式书写,从而可以在其他算法中通过名称引用。抽象操作通常使用类似 OperationName(arg1, arg2) 的函数调用形式引用。某些抽象操作被视为类式规范抽象中以多态方式分派的方法。这些类似方法的抽象操作通常使用类似 someValue.OperationName(arg1, arg2) 的方法调用形式引用。

5.2.3 语法制导操作

语法制导操作是一种具名操作,其定义由多个算法组成,每个算法都与某种 ECMAScript 文法中的一个或多个产生式相关联。具有多个可选定义的产生式通常会为每个候选项关联不同的算法。当算法与文法产生式相关联时,它可以引用该产生式候选项中的终结符和非终结符,就像它们是算法的参数一样。以这种方式使用时,非终结符指的是解析源文本时实际匹配的可选定义。文法产生式或由其派生的解析节点所匹配的源文本,是从参与匹配的第一个终结符的起始位置开始,到参与匹配的最后一个终结符的结束位置为止的源文本部分。

当算法与产生式的某个候选项相关联时,该候选项通常不带任何“[ ]”文法注记。这些注记只应影响候选项的句法识别,而不影响与该候选项关联的语义。

使用以下算法中步骤 1、3 和 4 所示的约定,可以用解析节点以及可选的其他参数调用语法制导操作:

  1. 令 status 为 SomeNonTerminal 的 SyntaxDirectedOperation。
  2. 令 someParseNode 为某段源文本的解析结果。
  3. 执行 someParseNode 的 SyntaxDirectedOperation。
  4. 以 "value" 为参数执行 someParseNode 的 SyntaxDirectedOperation。

除非另有明确规定,所有链式产生式都为可能应用于其左侧非终结符的每个操作提供隐式定义。隐式定义只是使用相同参数(如果有),将相同操作重新应用于链式产生式右侧唯一的非终结符,然后返回结果。例如,假设某个算法包含形式为“返回 Block 的 Evaluation”的步骤,并且存在以下产生式:

Block : { StatementList }

但 Evaluation 操作没有为该产生式关联算法。在这种情况下,Evaluation 操作隐式包含以下形式的关联:

Runtime Semantics: Evaluation

Block : { StatementList }
  1. 返回 StatementList 的 Evaluation。

5.2.4 运行时语义

规定必须在运行时调用的语义的算法称为运行时语义。运行时语义由抽象操作或语法制导操作定义。

5.2.4.1 Completion ( completionRecord )

抽象操作 Completion,接收参数 completionRecord (完成记录);返回值:完成记录。 它用于强调正在返回一个完成记录。 调用时执行以下步骤:

  1. 断言:completionRecord 是一个完成记录。
  2. 返回 completionRecord。

5.2.4.2 抛出

在算法步骤中,“抛出”是返回调用 ThrowCompletion 所得结果的简写。例如,

  1. 如果 result.[[Error]] 不是 none,则抛出 result.[[Error]]。

等价于

  1. 如果 result.[[Error]] 不是 none,则返回 ThrowCompletion(result.[[Error]])。

要求抛出特定类型异常的算法步骤会构造该类型的异常以供抛出。例如,

  1. 抛出一个 TypeError 异常。

等价于

  1. 返回 ThrowCompletion(一个新创建的 TypeError 对象)。

5.2.4.3 解包完成记录的简写

前缀“?”和“!”用作解包完成记录的简写。“?”用于将突然完成传播给调用者,或者在其他情况下解包正常完成。“!”用于断言完成记录是正常完成并将其解包。形式上,步骤

  1. 令 result 为 ? record。

等价于

  1. 断言:record 是一个完成记录。
  2. 如果 record 是突然完成,则返回 record。
  3. 令 result 为 record.[[Value]]。

类似地,步骤

  1. 令 result 为 ! record。

等价于

  1. 断言:record 是正常完成。
  2. 令 result 为 record.[[Value]]。

当“?”或“!”用于任何其他上下文时,先应用 求值顺序 中给出的改写,直到可以应用此规则,然后应用此规则。例如,步骤

  1. 执行 AO(? Other())。

可以改写为

  1. 令 tmp1 为 Other()。
  2. 令 tmp2 为 ? tmp1。
  3. 执行 AO(tmp2)。

随后又可展开为

  1. 令 tmp1 为 Other()。
  2. 断言:tmp1 是一个完成记录。
  3. 如果 tmp1 是突然完成,则返回 tmp1。
  4. 令 tmp2 为 tmp1.[[Value]]。
  5. 执行 AO(tmp2)。

5.2.4.4 隐式正常完成

在声明返回完成记录的抽象操作的算法中,以及所有内置函数中,返回的值会先传递给 NormalCompletion,然后改用所得结果。此规则不适用于 Completion 算法内部,也不适用于在该步骤中明确将所返回的值标记为完成记录的情况;这些情况包括:

如果通过任何其他方式从此类抽象操作返回完成记录,则属于编辑错误。例如,在这些抽象操作中,

  1. 返回 true。

与以下任一种形式具有相同含义

  1. 返回 NormalCompletion(true)。

或

  1. 令 completion 为 NormalCompletion(true)。
  2. 返回 Completion(completion)。

或

  1. 返回完成记录 { [[Type]]: normal, [[Value]]: true, [[Target]]: empty }。

注意,通过展开 ? 简写,以下示例是允许的,因为在展开后的步骤中,突然完成的情况下会直接返回应用 Completion 所得的结果,而正常完成的情况下会在解包之后隐式应用 NormalCompletion。

  1. 返回 ? completion。

以下示例属于编辑错误,因为该步骤返回了完成记录,却没有在该步骤中标明这一点。

  1. 令 completion 为 NormalCompletion(true)。
  2. 返回 completion。

5.2.5 静态语义

上下文无关文法的表达能力不足以表达所有用于确定输入元素流是否构成可求值的有效 ECMAScript Script 或 Module 的规则。在某些情况下,需要额外的规则,这些规则可以使用 ECMAScript 算法约定或文字要求来表达。此类规则始终与文法的某个产生式关联,称为该产生式的静态语义。

静态语义规则具有名称,通常使用算法定义。具名静态语义规则与文法产生式关联,对于具有多个可选定义的产生式,其每个候选项通常都会为每个适用的具名静态语义规则提供一个不同的算法。

一种特殊的静态语义规则是提前错误规则。提前错误规则定义与特定文法产生式关联的提前错误条件(参见 17 节)。本规范的算法不会显式调用大多数提前错误规则的求值。符合规范的实现必须在首次对 Script 或 Module 求值之前,验证用于解析该 Script 或 Module 的产生式的所有提前错误规则。如果违反任何提前错误规则,则该 Script 或 Module 无效,不能求值。

5.2.6 数学运算

本规范引用以下种类的数值:

在本规范的语言中,数值通过下标后缀在不同的数值种类之间加以区分。下标 𝔽 表示 Number,下标 ℤ 表示 BigInt。没有下标后缀的数值表示数学值。本规范中的大多数数值采用十进制表示;它还使用由 0x 后跟数字 0-9 或 A-F 形式组成的数值来表示十六进制值。

一般而言,当本规范引用某个数值时,例如短语“y 的长度”或“四个十六进制数字表示的整数……”,如果没有显式指定数值种类,则该短语表示数学值。引用 Number 或 BigInt 值的短语会显式注明;例如,“……中的码点数量对应的 Number 值”或“……对应的 BigInt 值”。

当本规范使用术语整数时,除非另有说明,它表示属于整数集合的数学值。当本规范使用术语整数 Number时,它表示其数学值属于整数集合的有限 Number 值。

诸如 +、×、= 和 ≥ 之类的数值运算符,根据操作数的类型表示相应的运算。当应用于数学值时,这些运算符表示通常的数学运算。当应用于扩展数学值时,这些运算符表示扩展实数上的通常数学运算;未定式未定义,在本规范中使用未定式应被视为编辑错误。当应用于 Number 时,这些运算符表示 IEEE 754-2019 中相应的运算。当应用于 BigInt 时,这些运算符表示应用于该 BigInt 数学值的通常数学运算。应用于混合类型操作数(例如一个 Number 和一个数学值)的数值运算符未定义,应被视为本规范中的编辑错误。

本文件中,数学值与 Number 或 BigInt 之间的转换始终是显式的。从数学值或扩展数学值 x 到 Number 的转换表示为“x 对应的 Number 值”或 𝔽(x),并在 6.1.6.1 中定义。从整数 x 到 BigInt 的转换表示为“x 对应的 BigInt 值”或 ℤ(x)。从 Number 或 BigInt x 到数学值的转换表示为“x 的数学值”,或 ℝ(x)。+0𝔽 和 -0𝔽 的数学值是数学值 0。非有限值的数学值未定义。x 的扩展数学值对于有限值是 x 的数学值,而对于 +∞𝔽 和 -∞𝔽 则分别是 +∞ 和 -∞;对于 NaN,其扩展数学值未定义。

数学函数 abs(x) 产生 x 的绝对值;如果 x < 0,则该值为 -x,否则为 x 本身。

数学函数 ln(x) 产生 x 的自然对数。数学函数 log10(x) 产生 x 的以 10 为底的对数。数学函数 log2(x) 产生 x 的以 2 为底的对数。

数学函数 min(x1, x2, … , xN) 产生从 x1 到 xN 中数学意义上最小的值。数学函数 max(x1, x2, ..., xN) 产生从 x1 到 xN 中数学意义上最大的值。这些数学函数的定义域和值域都是扩展数学值。

记法“x modulo y”(y 必须是有限且非零的)计算一个与 y 同号(或为零)的值 k,使得对于某个整数 q,有 abs(k) < abs(y) and x - k = q × y。

短语“将 x 限制在 lower 和 upper 之间的结果”(其中 x 是扩展数学值,lower 和 upper 是满足 lower ≤ upper 的数学值)在 x < lower 时产生 lower,在 x > upper 时产生 upper,否则产生 x。

数学函数 floor(x) 产生不大于 x 的最大整数(最接近 +∞)。

注

floor(x) = x - (x modulo 1)。

数学函数 truncate(x) 通过向零舍入来移除 x 的小数部分;如果 x < 0,则产生 -floor(-x),否则产生 floor(x)。

数学函数 min、max、abs、floor 和 truncate 未针对 Number 和 BigInt 定义,任何以非数学值作为参数使用这些方法的情况都属于本规范中的编辑错误。

从下界 a 到上界 b 的区间是由相同数值类型的数值构成的集合,该集合可能是无限的,也可能为空。每个边界都将被描述为包含或不包含,但不会同时为两者。区间有以下四种:

例如,从 1(包含)到 2(不包含)的区间由 1 和 2 之间的所有数学值组成,其中包含 1,但不包含 2。为了定义区间,-0𝔽 < +0𝔽,因此,例如,下界为 +0𝔽 的闭区间包含 +0𝔽,但不包含 -0𝔽。NaN 永远不会包含在区间中。

5.2.7 值的表示法

在本规范中,ECMAScript 语言值以粗体显示。例如 null、true 或 "hello"。它们与 Function.prototype.apply 或 let n = 42; 等 ECMAScript 源文本相区别。

5.2.8 标识

在本规范中,规范值和 ECMAScript 语言值都可以进行相等性比较。进行相等性比较时,值分为两类。如果所有固有特征都相同,例如整数的大小或序列的长度,则无标识的值与其他无标识的值相等。无需事先持有引用,只要完整描述无标识的值的特征,就可以给出该值。相比之下,每个有标识的值都是唯一的,因此仅与自身相等。有标识的值类似于无标识的值,但额外具有一个不可猜测、不可更改、全局唯一的特征,称为标识。由于标识本身无法描述,因此仅通过描述无法给出对现有有标识的值的引用;相反,必须将对这些值的引用从一个位置显式传递到另一个位置。某些有标识的值是可变的,因此可以原地更改其特征(标识除外),使该值的所有持有者都观察到新的特征。无标识的值永远不等于有标识的值。

从本规范的角度看,“是”用于比较两个值是否相等,例如“如果 bool 是 true,则 ...”;“包含”用于通过相等性比较在列表中查找值,例如“如果 list 包含一个记录 r,且 r.[[Foo]] 是 true,则 ...”。值的规范标识决定这些比较的结果,并在本规范中被视为公理性的概念。

从 ECMAScript 语言的角度看,语言值通过 SameValue 抽象操作及其传递调用的抽象操作进行相等性比较。这些比较抽象操作的算法决定 ECMAScript 语言值的语言标识。

对于规范值,没有规范标识的值的示例包括但不限于:数学值和扩展数学值;ECMAScript 源文本、代理对、指令序言等;UTF-16 码元;Unicode 码点;枚举值;抽象操作,包括语法制导操作、宿主钩子等;以及有序对。具有规范标识的规范值的示例包括但不限于:任何种类的记录,包括属性描述符、PrivateElement 等;解析节点;列表;集合和关系;抽象闭包;数据块;私有名称;执行上下文和执行上下文栈;代理标识符;以及 WaiterList 记录。

除 Symbol.for 产生的 Symbol 值之外,所有 ECMAScript 语言值的规范标识都与语言标识一致。既没有规范标识也没有语言标识的 ECMAScript 语言值包括 undefined、null、Boolean 值、String 值、Number 值和 BigInt 值。同时具有规范标识和语言标识的 ECMAScript 语言值包括非 Symbol.for 产生的 Symbol 值和对象。Symbol.for 产生的 Symbol 值具有规范标识,但没有语言标识。

6 ECMAScript 数据类型和值

本规范中的算法操作各种值,每个值都有一个关联的类型。可能的值类型恰好就是本条款中定义的那些类型。类型进一步分为 ECMAScript 语言类型和规范类型。

6.1 ECMAScript 语言类型

ECMAScript 语言类型对应于 ECMAScript 程序员使用 ECMAScript 语言直接操作的值。ECMAScript 语言类型包括 Undefined、Null、Boolean、String、Symbol、Number、BigInt 和 Object。ECMAScript 语言值是由 ECMAScript 语言类型表征的值。

6.1.1 Undefined 类型

Undefined 类型恰好有一个值,称为 undefined。任何尚未赋值的变量都具有值 undefined。

6.1.2 Null 类型

Null 类型恰好有一个值,称为 null。

6.1.3 Boolean 类型

Boolean 类型表示具有两个值的逻辑实体,这两个值称为 true 和 false。

6.1.4 String 类型

String 类型是由零个或多个 16 位无符号整数值(“元素”)组成的所有有序序列的集合,最大长度为 253 - 1 个元素。String 类型通常用于表示正在运行的 ECMAScript 程序中的文本数据,在这种情况下,String 中的每个元素都被视为一个 UTF-16 码元值。每个元素都被视为占据序列中的一个位置。这些位置使用非负整数进行索引。第一个元素(如果有)位于索引 0,下一个元素(如果有)位于索引 1,依此类推。String 的长度是其中元素(即 16 位值)的数量。空 String 的长度为零,因此不包含任何元素。

不解释 String 内容的 ECMAScript 操作不会施加进一步的语义。解释 String 值的操作会将每个元素视为单个 UTF-16 码元。然而,ECMAScript 不限制这些码元的值或它们之间的关系,因此,进一步将 String 内容解释为以 UTF-16 编码的 Unicode 码点序列的操作必须考虑格式错误的子序列。此类操作会按照以下规则,对数值处于从 0xD800 到 0xDBFF 的闭区间中的每个码元(Unicode 标准将其定义为前导代理项,或更正式地称为高代理码元)以及数值处于从 0xDC00 到 0xDFFF 的闭区间中的每个码元(定义为尾随代理项,或更正式地称为低代理码元)进行特殊处理:

函数 String.prototype.normalize(参见 22.1.3.15)可用于显式规范化 String 值。String.prototype.localeCompare(参见 22.1.3.12)会在内部规范化 String 值,但其他操作都不会隐式规范化其所操作的字符串。除非另有说明,否则操作结果不区分语言和/或区域设置。

注

这种设计背后的理由是尽可能保持 String 实现的简单和高性能。如果 ECMAScript 源文本采用规范化形式 C,则只要字符串字面量不包含任何 Unicode 转义序列,就保证它们也经过规范化。

在本规范中,短语“A、B、... 的字符串连接”(其中每个参数都是 String 值、码元或码元序列)表示这样一个 String 值:其码元序列是按照各参数的顺序,将每个参数中的码元依次连接而成的。

短语“string 从 inclusiveStart 到 exclusiveEnd 的子字符串”(其中 string 是 String 值或码元序列,而 inclusiveStart 和 exclusiveEnd 是整数)表示由 string 中从索引 inclusiveStart 开始、到索引 exclusiveEnd 之前结束的连续码元组成的 String 值(当 inclusiveStart = exclusiveEnd 时为空 String)。如果省略“到”后缀,则使用 string 的长度作为 exclusiveEnd 的值。

短语“ASCII 单词字符”表示以下 String 值,它仅由 Unicode 基本拉丁区块中的所有字母和数字以及 U+005F(LOW LINE)组成:
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_"。
由于历史原因,它对各种算法具有重要意义。

6.1.4.1 StringIndexOf ( string, searchValue, fromIndex )

抽象操作 StringIndexOf,接收参数 string (String)、searchValue (String) 和 fromIndex (非负整数);返回值:(非负整数 或 not-found)。 调用时执行以下步骤:

  1. 令 length 为 string 的长度。
  2. 如果 searchValue 是空 String 且 fromIndex ≤ length,则返回 fromIndex。
  3. 令 searchLength 为 searchValue 的长度。
  4. 对满足 fromIndex ≤ i ≤ length - searchLength 的每个整数 i,按升序执行
    1. 令 candidate 为 string 从 i 到 i + searchLength 的子字符串。
    2. 如果 candidate 是 searchValue,则返回 i。
  5. 返回 not-found。
注 1

如果 searchValue 是空 String 且 fromIndex ≤ string 的长度,则此算法返回 fromIndex。实际上,可以在字符串中的每个位置找到空 String,包括最后一个码元之后的位置。

注 2

如果 fromIndex + searchValue 的长度 > string 的长度,则此算法始终返回 not-found。

6.1.4.2 StringLastIndexOf ( string, searchValue, fromIndex )

抽象操作 StringLastIndexOf,接收参数 string (String)、searchValue (String) 和 fromIndex (非负整数);返回值:(非负整数 或 not-found)。 调用时执行以下步骤:

  1. 令 length 为 string 的长度。
  2. 令 searchLength 为 searchValue 的长度。
  3. 断言:fromIndex + searchLength ≤ length。
  4. 对满足 0 ≤ i ≤ fromIndex 的每个整数 i,按降序执行
    1. 令 candidate 为 string 从 i 到 i + searchLength 的子字符串。
    2. 如果 candidate 是 searchValue,则返回 i。
  5. 返回 not-found。
注

如果 searchValue 是空 String,则此算法返回 fromIndex。实际上,可以在字符串中的每个位置找到空 String,包括最后一个码元之后的位置。

6.1.5 Symbol 类型

Symbol 类型是所有可用作 Object 属性键的非 String 值的集合(6.1.7)。

每个 Symbol 都是唯一且不可变的。

每个 Symbol 都有一个不可变的 [[Description]] 内部槽,其值为 String 或 undefined。

6.1.5.1 知名 Symbol

知名 Symbol 是本规范算法明确引用的内置 Symbol 值。它们通常用作属性的键,而这些属性的值充当规范算法的扩展点。除非另有说明,否则所有 Realm 都共享知名 Symbol 值(9.3)。

在本规范中,使用标准内在对象表示法引用知名 Symbol,其中内在对象是 表 1 中列出的值之一。

注
本规范的早期版本使用 @@name 形式的表示法,而当前版本使用 %Symbol.name%。具体而言,曾使用以下名称:@@asyncIterator、@@hasInstance、@@isConcatSpreadable、@@iterator、@@match、@@matchAll、@@replace、@@search、@@species、@@split、@@toPrimitive、@@toStringTag 和 @@unscopables。
表 1: 知名 Symbol
规范名称 [[Description]] 值和用途
%Symbol.asyncDispose% "Symbol.asyncDispose" 在对象上异步执行资源清理的方法。当包含 AsyncDisposableStack 对象和 await using 声明的作用域完成求值时调用。
%Symbol.asyncIterator% "Symbol.asyncIterator" 返回对象默认异步迭代器的方法。由 for-await-of 语句的语义调用。
%Symbol.dispose% "Symbol.dispose" 在对象上执行显式资源清理的方法。当包含 DisposableStack 对象、AsyncDisposableStack 对象和 using 声明的作用域完成求值时调用。
%Symbol.hasInstance% "Symbol.hasInstance" 确定构造函数对象是否将某个对象识别为该构造函数实例之一的方法。由 instanceof 运算符的语义调用。
%Symbol.isConcatSpreadable% "Symbol.isConcatSpreadable" 一个 Boolean 值属性,如果为 true,则表示对象应由 Array.prototype.concat 展开为其数组元素。
%Symbol.iterator% "Symbol.iterator" 返回对象默认迭代器的方法。由 for-of 语句的语义调用。
%Symbol.match% "Symbol.match" 将正则表达式与字符串进行匹配的正则表达式方法。由 String.prototype.match 方法调用。
%Symbol.matchAll% "Symbol.matchAll" 返回一个迭代器、该迭代器生成正则表达式与字符串的匹配项的正则表达式方法。由 String.prototype.matchAll 方法调用。
%Symbol.replace% "Symbol.replace" 替换字符串中匹配子字符串的正则表达式方法。由 String.prototype.replace 方法调用。
%Symbol.search% "Symbol.search" 返回字符串中与正则表达式匹配位置的索引的正则表达式方法。由 String.prototype.search 方法调用。
%Symbol.species% "Symbol.species" 一个函数值属性,该函数是用于创建派生对象的构造函数。
%Symbol.split% "Symbol.split" 在与正则表达式匹配的索引位置拆分字符串的正则表达式方法。由 String.prototype.split 方法调用。
%Symbol.toPrimitive% "Symbol.toPrimitive" 将对象转换为相应原始值的方法。由 ToPrimitive 抽象操作调用。
%Symbol.toStringTag% "Symbol.toStringTag" 一个 String 值属性,用于创建对象的默认字符串描述。由内置方法 Object.prototype.toString 访问。
%Symbol.unscopables% "Symbol.unscopables" 一个对象值属性,其自有和继承属性名称是从关联对象的 with 环境绑定中排除的属性名称。

6.1.6 数值类型

ECMAScript 有两个内置数值类型:Number 和 BigInt。下面的抽象操作定义在这些数值类型之上。“结果”列显示返回类型,并指明该操作的某些调用是否可能返回突然完成。

表 2: 数值类型操作
操作 示例源代码 由以下项的 Evaluation 语义调用 ... 结果
Number::unaryMinus -x 一元 - 运算符 Number
BigInt::unaryMinus BigInt
Number::bitwiseNOT ~x 按位 NOT 运算符( ~ ) Number
BigInt::bitwiseNOT BigInt
Number::exponentiate x ** y 指数运算符 和 Math.pow ( base, exponent ) Number
BigInt::exponentiate 包含 BigInt 的正常完成或抛出完成
Number::multiply x * y 乘法运算符 Number
BigInt::multiply BigInt
Number::divide x / y 乘法运算符 Number
BigInt::divide 包含 BigInt 的正常完成或抛出完成
Number::remainder x % y 乘法运算符 Number
BigInt::remainder 包含 BigInt 的正常完成或抛出完成
Number::add x ++
++ x
x + y
后缀递增运算符、 前缀递增运算符 和 加法运算符( + ) Number
BigInt::add BigInt
Number::subtract x --
-- x
x - y
后缀递减运算符、 前缀递减运算符 和 减法运算符( - ) Number
BigInt::subtract BigInt
Number::leftShift x << y 左移运算符( << ) Number
BigInt::leftShift BigInt
Number::signedRightShift x >> y 有符号右移运算符( >> ) Number
BigInt::signedRightShift BigInt
Number::unsignedRightShift x >>> y 无符号右移运算符( >>> ) Number
BigInt::unsignedRightShift 抛出完成
Number::lessThan x < y
x > y
x <= y
x >= y
关系运算符, 通过 IsLessThan ( x, y, leftFirst ) Boolean 或 undefined(对于无序输入)
BigInt::lessThan Boolean
Number::equal x == y
x != y
x === y
x !== y
相等运算符, 通过 IsStrictlyEqual ( x, y ) Boolean
BigInt::equal
Number::sameValue Object.is(x, y) Object 内部方法, 通过 SameValue ( x, y ), 用于测试精确值相等性 Boolean
Number::sameValueZero [x].includes(y) 通过 SameValueZero ( x, y ), 用于测试值相等性,忽略 +0𝔽 与 -0𝔽 之间的差异,如 Array、Map 和 Set 方法中所用 Boolean
Number::bitwiseAND x & y 二元按位运算符 Number
BigInt::bitwiseAND BigInt
Number::bitwiseXOR x ^ y Number
BigInt::bitwiseXOR BigInt
Number::bitwiseOR x | y Number
BigInt::bitwiseOR BigInt
Number::toString String(x) 许多表达式和内置函数,通过 ToString ( arg ) String
BigInt::toString

由于这些数值类型通常无法在不损失精度或截断的情况下相互转换,因此 ECMAScript 语言不提供这些类型之间的隐式转换。当调用需要另一种类型的函数时,程序员必须显式调用 Number 和 BigInt 函数在类型之间进行转换。

注

ECMAScript 第一版及后续版本曾为某些运算符提供可能损失精度或发生截断的隐式数值转换。为了向后兼容,这些遗留隐式转换仍然保留,但没有为 BigInt 提供,以尽量减少程序员出错的机会,并为未来版本引入通用值类型保留可能性。

6.1.6.1 Number 类型

Number 类型恰好有 18,437,736,874,454,810,627 个(即 264 - 253 + 3)值,表示 IEEE 浮点算术标准中规定的双精度浮点 IEEE 754-2019 binary64 值,但 IEEE 标准中 9,007,199,254,740,990 个(即 253 - 2)不同的 NaN 值在 ECMAScript 中表示为单个特殊的 NaN 值。(请注意,NaN 值由程序表达式 NaN 产生。)在某些实现中,外部代码或许能够检测出不同 NaN 值之间的差异,但这种行为是实现定义的;对于 ECMAScript 代码而言,所有 NaN 值彼此无法区分。

注

将一个 Number 值存储到 ArrayBuffer(参见 25.1)或 SharedArrayBuffer(参见 25.2)后可能观察到的位模式,不一定与 ECMAScript 实现所使用的该 Number 值的内部表示相同。

还有另外两个特殊值,称为正无穷和负无穷。为简洁起见,在说明中也分别使用符号 +∞𝔽 和 -∞𝔽 来指代这些值。(请注意,这两个无穷 Number 值分别由程序表达式 +Infinity(或简称 Infinity)和 -Infinity 产生。)

其余 18,437,736,874,454,810,624 个(即 264 - 253)值中的每一个都是有限 Number。其中一半是正数,另一半是负数;对于每个正的有限 Number,都有一个大小相同的对应负 Number。

请注意,同时存在正零和负零。为简洁起见,在说明中也分别使用符号 +0𝔽 和 -0𝔽 来指代这些值。(请注意,这两个不同的零 Number 值分别由程序表达式 +0(或简称 0)和 -0 产生。)

18,437,736,874,454,810,622 个(即 264 - 253 - 2)有限非零值分为两类:

其中 18,428,729,675,200,069,632 个(即 264 - 254)是规格化的,形式为

s × m × 2e

其中 s 为 1 或 -1,m 是从 252(含)到 253(不含)区间内的整数,而 e 是从 -1074 到 971(两端均含)区间内的整数。

其余 9,007,199,254,740,990 个(即 253 - 2)值是非规格化的,形式为

s × m × 2e

其中 s 为 1 或 -1,m 是从 0(不含)到 252(不含)区间内的整数,而 e 为 -1074。

请注意,所有绝对值不大于 253 的正整数和负整数都可以在 Number 类型中表示。整数 0 在 Number 类型中有两种表示:+0𝔽 和 -0𝔽。

如果一个有限 Number 非零,并且用于表示它(采用上述两种形式之一)的整数 m 是奇数,则该有限 Number 具有奇数有效数。否则,它具有偶数有效数。

在本规范中,短语“x 的Number 值”,其中 x 表示一个精确的实数数学量(甚至可能是诸如 π 这样的无理数),是指按以下方式选出的一个 Number 值。考虑这样一个集合:由除 -0𝔽 之外的所有有限 Number 与两个不能在 Number 类型中表示的附加值的并集组成,这两个值分别是 21024(即 +1 × 253 × 2971)和 -21024(即 -1 × 253 × 2971)。选择该集合中数值最接近 x 的成员。如果集合中有两个值与 x 同样接近,则选择具有偶数有效数的那个;为此,这两个附加值 21024 和 -21024 被视为具有偶数有效数。最后,如果选择了 21024,则将其替换为 +∞𝔽;如果选择了 -21024,则将其替换为 -∞𝔽;如果选择了 +0𝔽,当且仅当 x < 0 时将其替换为 -0𝔽;其他任何选中的值均保持不变。所得结果就是 x 的 Number 值。(此过程与 IEEE 754-2019 roundTiesToEven 模式的行为完全对应。)

+∞ 的 Number 值是 +∞𝔽,而 -∞ 的 Number 值是 -∞𝔽。

某些 ECMAScript 运算符仅处理特定范围内的整数,例如从 -231 到 231 - 1 的闭区间,或从 0 到 216 - 1 的闭区间。这些运算符接受 Number 类型的任意值,但会先将每个此类值转换为预期范围内的整数值。请参见 7.1 中对数值转换操作的描述。

6.1.6.1.1 Number::unaryMinus ( number )

抽象操作 Number::unaryMinus,接收参数 number (Number);返回值:Number。 调用时执行以下步骤:

  1. 如果 number 是 NaN,则返回 NaN。
  2. 返回 number 的相反数;即计算一个大小相同但符号相反的 Number。

6.1.6.1.2 Number::bitwiseNOT ( number )

抽象操作 Number::bitwiseNOT,接收参数 number (Number);返回值:整数 Number。 调用时执行以下步骤:

  1. 令 oldValue 为 ! ToInt32(number)。
  2. 返回 oldValue 的按位补码。结果的数学值可以精确表示为 32 位二进制补码位串。

6.1.6.1.3 Number::exponentiate ( base, exponent )

抽象操作 Number::exponentiate,接收参数 base (Number) 和 exponent (Number);返回值:Number。 它返回一个实现近似值,表示 base 的 exponent 次幂的结果。 调用时执行以下步骤:

  1. 如果 exponent 是 NaN,返回 NaN。
  2. 如果 exponent 是 +0𝔽 或 -0𝔽,返回 1𝔽。
  3. 如果 base 是 NaN,返回 NaN。
  4. 如果 base 是 +∞𝔽,那么
    1. 如果 exponent > +0𝔽,返回 +∞𝔽。
    2. 返回 +0𝔽。
  5. 如果 base 是 -∞𝔽,那么
    1. 如果 exponent > +0𝔽,那么
      1. 如果 exponent 是奇数整数 Number,返回 -∞𝔽。
      2. 返回 +∞𝔽。
    2. 如果 exponent 是奇数整数 Number,返回 -0𝔽。
    3. 返回 +0𝔽。
  6. 如果 base 是 +0𝔽,那么
    1. 如果 exponent > +0𝔽,返回 +0𝔽。
    2. 返回 +∞𝔽。
  7. 如果 base 是 -0𝔽,那么
    1. 如果 exponent > +0𝔽,那么
      1. 如果 exponent 是奇数整数 Number,返回 -0𝔽。
      2. 返回 +0𝔽。
    2. 如果 exponent 是奇数整数 Number,返回 -∞𝔽。
    3. 返回 +∞𝔽。
  8. 断言:base 是有限 Number,且既不是 +0𝔽 也不是 -0𝔽。
  9. 如果 exponent 是 +∞𝔽,那么
    1. 如果 abs(ℝ(base)) > 1,返回 +∞𝔽。
    2. 如果 abs(ℝ(base)) = 1,返回 NaN。
    3. 返回 +0𝔽。
  10. 如果 exponent 是 -∞𝔽,那么
    1. 如果 abs(ℝ(base)) > 1,返回 +0𝔽。
    2. 如果 abs(ℝ(base)) = 1,返回 NaN。
    3. 返回 +∞𝔽。
  11. 断言:exponent 是有限 Number,且既不是 +0𝔽 也不是 -0𝔽。
  12. 如果 base < -0𝔽 且 exponent 不是整数 Number,返回 NaN。
  13. 返回一个由实现近似得到的 Number 值,该值表示将 ℝ(base) 提升到 ℝ(exponent) 次幂所得的结果。
注

当 base 为 1𝔽 或 -1𝔽 且 exponent 为 +∞𝔽 或 -∞𝔽,或者当 base 为 1𝔽 且 exponent 为 NaN 时,base ** exponent 的结果与 IEEE 754-2019 不同。ECMAScript 第一版规定此操作的结果为 NaN,而 IEEE 754 后续修订版规定为 1𝔽。出于兼容性原因,保留了 ECMAScript 的历史行为。

6.1.6.1.4 Number::multiply ( x, y )

抽象操作 Number::multiply,接收参数 x (Number) 和 y (Number);返回值:Number。 它按照 IEEE 754-2019 二进制双精度算术的规则执行乘法,生成 x 和 y 的乘积。 调用时执行以下步骤:

  1. 如果 x 是 NaN 或 y 是 NaN,则返回 NaN。
  2. 如果 x 是 +∞𝔽 或 -∞𝔽,则
    1. 如果 y 是 +0𝔽 或 -0𝔽,则返回 NaN。
    2. 如果 y > +0𝔽,则返回 x。
    3. 返回 -x。
  3. 如果 y 是 +∞𝔽 或 -∞𝔽,则
    1. 如果 x 是 +0𝔽 或 -0𝔽,则返回 NaN。
    2. 如果 x > +0𝔽,则返回 y。
    3. 返回 -y。
  4. 如果 x 是 -0𝔽,则
    1. 如果 y 是 -0𝔽 或 y < -0𝔽,则返回 +0𝔽。
    2. 返回 -0𝔽。
  5. 如果 y 是 -0𝔽,则
    1. 如果 x < -0𝔽,则返回 +0𝔽。
    2. 返回 -0𝔽。
  6. 返回 𝔽(ℝ(x) × ℝ(y))。
注

有限精度乘法满足交换律,但并不总是满足结合律。

6.1.6.1.5 Number::divide ( x, y )

抽象操作 Number::divide,接收参数 x (Number) 和 y (Number);返回值:Number。 它按照 IEEE 754-2019 二进制双精度算术的规则执行除法,生成 x 与 y 的商,其中 x 是被除数,y 是除数。 调用时执行以下步骤:

  1. 如果 x 是 NaN 或 y 是 NaN,则返回 NaN。
  2. 如果 x 是 +∞𝔽 或 -∞𝔽,则
    1. 如果 y 是 +∞𝔽 或 -∞𝔽,则返回 NaN。
    2. 如果 y 是 +0𝔽 或 y > +0𝔽,则返回 x。
    3. 返回 -x。
  3. 如果 y 是 +∞𝔽,则
    1. 如果 x 是 +0𝔽 或 x > +0𝔽,则返回 +0𝔽。
    2. 返回 -0𝔽。
  4. 如果 y 是 -∞𝔽,则
    1. 如果 x 是 +0𝔽 或 x > +0𝔽,则返回 -0𝔽。
    2. 返回 +0𝔽。
  5. 如果 x 是 +0𝔽 或 -0𝔽,则
    1. 如果 y 是 +0𝔽 或 -0𝔽,则返回 NaN。
    2. 如果 y > +0𝔽,则返回 x。
    3. 返回 -x。
  6. 如果 y 是 +0𝔽,则
    1. 如果 x > +0𝔽,则返回 +∞𝔽。
    2. 返回 -∞𝔽。
  7. 如果 y 是 -0𝔽,则
    1. 如果 x > +0𝔽,则返回 -∞𝔽。
    2. 返回 +∞𝔽。
  8. 返回 𝔽(ℝ(x) / ℝ(y))。

6.1.6.1.6 Number::remainder ( numerator, denominator )

抽象操作 Number::remainder,接收参数 numerator (Number) 和 denominator (Number);返回值:Number。 它产生其操作数隐含除法所得的余数,其中 numerator 是被除数,denominator 是除数。 调用时执行以下步骤:

  1. 如果 numerator 是 NaN 或 denominator 是 NaN,返回 NaN。
  2. 如果 numerator 是 +∞𝔽 或 -∞𝔽,返回 NaN。
  3. 如果 denominator 是 +∞𝔽 或 -∞𝔽,返回 numerator。
  4. 如果 denominator 是 +0𝔽 或 -0𝔽,返回 NaN。
  5. 如果 numerator 是 +0𝔽 或 -0𝔽,返回 numerator。
  6. 断言:numerator 是有限 Number,且既不是 +0𝔽 也不是 -0𝔽。
  7. 断言:denominator 是有限 Number,且既不是 +0𝔽 也不是 -0𝔽。
  8. 令 quotient 为 ℝ(numerator) / ℝ(denominator)。
  9. 令 truncatedQuotient 为 truncate(quotient)。
  10. 令 remainder 为 ℝ(numerator) - (ℝ(denominator) × truncatedQuotient)。
  11. 如果 remainder = 0 且 numerator < -0𝔽,返回 -0𝔽。
  12. 返回 𝔽(remainder)。
注 1

在 C 和 C++ 中,余数运算符仅接受整数操作数;在 ECMAScript 中,它也接受浮点操作数。

注 2
由 % 运算符计算的浮点余数运算结果与 IEEE 754-2019 定义的“余数”运算不同。IEEE 754-2019 的“余数”运算根据舍入除法计算余数,而不是截断除法,因此其行为与通常的 integer 余数运算符并不类似。相反,ECMAScript 语言将浮点运算上的 % 定义为以类似 Java integer 余数运算符的方式运行;可将其与 C 库函数 fmod 进行比较。

6.1.6.1.7 Number::add ( x, y )

抽象操作 Number::add,接收参数 x (Number) 和 y (Number);返回值:Number。 它按照 IEEE 754-2019 二进制双精度算术的规则执行加法,生成其参数之和。 调用时执行以下步骤:

  1. 如果 x 是 NaN 或 y 是 NaN,返回 NaN。
  2. 如果 x 是 +∞𝔽 且 y 是 -∞𝔽,返回 NaN。
  3. 如果 x 是 -∞𝔽 且 y 是 +∞𝔽,返回 NaN。
  4. 如果 x 是 +∞𝔽 或 -∞𝔽,返回 x。
  5. 如果 y 是 +∞𝔽 或 -∞𝔽,返回 y。
  6. 断言:x 和 y 是有限 Number。
  7. 如果 x 是 -0𝔽 且 y 是 -0𝔽,返回 -0𝔽。
  8. 返回 𝔽(ℝ(x) + ℝ(y))。
注

有限精度加法满足交换律,但并不总是满足结合律。

6.1.6.1.8 Number::subtract ( x, y )

抽象操作 Number::subtract,接收参数 x (Number) 和 y (Number);返回值:Number。 它执行减法,生成操作数之差;x 是被减数,y 是减数。 调用时执行以下步骤:

  1. 返回 Number::add(x, Number::unaryMinus(y))。
注

x - y 始终产生与 x + (-y) 相同的结果。

6.1.6.1.9 Number::leftShift ( x, y )

抽象操作 Number::leftShift,接收参数 x (Number) 和 y (Number);返回值:整数 Number。 调用时执行以下步骤:

  1. 令 leftNumber 为 ! ToInt32(x)。
  2. 令 rightNumber 为 ! ToUint32(y)。
  3. 令 shiftCount 为 ℝ(rightNumber) modulo 32。
  4. 返回将 leftNumber 左移 shiftCount 位的结果。结果的数学值可以精确表示为 32 位二进制补码位串。

6.1.6.1.10 Number::signedRightShift ( x, y )

抽象操作 Number::signedRightShift,接收参数 x (Number) 和 y (Number);返回值:整数 Number。 调用时执行以下步骤:

  1. 令 leftNumber 为 ! ToInt32(x)。
  2. 令 rightNumber 为 ! ToUint32(y)。
  3. 令 shiftCount 为 ℝ(rightNumber) modulo 32。
  4. 返回对 leftNumber 执行符号扩展右移 shiftCount 位的结果。最高有效位会被传播。结果的数学值可以精确表示为 32 位二进制补码位串。

6.1.6.1.11 Number::unsignedRightShift ( x, y )

抽象操作 Number::unsignedRightShift,接收参数 x (Number) 和 y (Number);返回值:整数 Number。 调用时执行以下步骤:

  1. 令 leftNumber 为 ! ToUint32(x)。
  2. 令 rightNumber 为 ! ToUint32(y)。
  3. 令 shiftCount 为 ℝ(rightNumber) modulo 32。
  4. 返回对 leftNumber 执行零填充右移 shiftCount 位的结果。空出的位用零填充。结果的数学值可以精确表示为 32 位无符号位串。

6.1.6.1.12 Number::lessThan ( x, y )

抽象操作 Number::lessThan,接收参数 x (Number) 和 y (Number);返回值:(Boolean 或 undefined)。 调用时执行以下步骤:

  1. 如果 x 是 NaN,返回 undefined。
  2. 如果 y 是 NaN,返回 undefined。
  3. 如果 x 是 y,返回 false。
  4. 如果 x 是 +0𝔽 且 y 是 -0𝔽,返回 false。
  5. 如果 x 是 -0𝔽 且 y 是 +0𝔽,返回 false。
  6. 如果 x 是 +∞𝔽,返回 false。
  7. 如果 y 是 +∞𝔽,返回 true。
  8. 如果 y 是 -∞𝔽,返回 false。
  9. 如果 x 是 -∞𝔽,返回 true。
  10. 断言:x 和 y 是有限 Number。
  11. 如果 ℝ(x) < ℝ(y),返回 true。
  12. 返回 false。

6.1.6.1.13 Number::equal ( x, y )

抽象操作 Number::equal,接收参数 x (Number) 和 y (Number);返回值:Boolean。 调用时执行以下步骤:

  1. 如果 x 是 NaN,则返回 false。
  2. 如果 y 是 NaN,则返回 false。
  3. 如果 x 是 y,则返回 true。
  4. 如果 x 是 +0𝔽 且 y 是 -0𝔽,则返回 true。
  5. 如果 x 是 -0𝔽 且 y 是 +0𝔽,则返回 true。
  6. 返回 false。

6.1.6.1.14 Number::sameValue ( x, y )

抽象操作 Number::sameValue,接收参数 x (Number) 和 y (Number);返回值:Boolean。 调用时执行以下步骤:

  1. 如果 x 是 NaN 且 y 是 NaN,则返回 true。
  2. 如果 x 是 +0𝔽 且 y 是 -0𝔽,则返回 false。
  3. 如果 x 是 -0𝔽 且 y 是 +0𝔽,则返回 false。
  4. 如果 x 是 y,则返回 true。
  5. 返回 false。

6.1.6.1.15 Number::sameValueZero ( x, y )

抽象操作 Number::sameValueZero,接收参数 x (Number) 和 y (Number);返回值:Boolean。 调用时执行以下步骤:

  1. 如果 x 是 NaN 且 y 是 NaN,则返回 true。
  2. 如果 x 是 +0𝔽 且 y 是 -0𝔽,则返回 true。
  3. 如果 x 是 -0𝔽 且 y 是 +0𝔽,则返回 true。
  4. 如果 x 是 y,则返回 true。
  5. 返回 false。

6.1.6.1.16 NumberBitwiseOp ( op, x, y )

抽象操作 NumberBitwiseOp,接收参数 op ((&、^ 或 |))、x (Number) 和 y (Number);返回值:整数 Number。 调用时执行以下步骤:

  1. 令 leftNumber 为 ! ToInt32(x)。
  2. 令 rightNumber 为 ! ToInt32(y)。
  3. 令 leftBits 为表示 ℝ(leftNumber) 的 32 位二进制补码位串。
  4. 令 rightBits 为表示 ℝ(rightNumber) 的 32 位二进制补码位串。
  5. 如果 op 是 &,则
    1. 令 result 为对 leftBits 和 rightBits 应用按位 AND 操作的结果。
  6. 否则如果 op 是 ^,则
    1. 令 result 为对 leftBits 和 rightBits 应用按位异或(XOR)操作的结果。
  7. 否则,
    1. 断言:op 是 |。
    2. 令 result 为对 leftBits 和 rightBits 应用按位包含 OR 操作的结果。
  8. 返回由 32 位二进制补码位串 result 表示的整数所对应的 Number 值。

6.1.6.1.17 Number::bitwiseAND ( x, y )

抽象操作 Number::bitwiseAND,接收参数 x (Number) 和 y (Number);返回值:整数 Number。 调用时执行以下步骤:

  1. 返回 NumberBitwiseOp(&, x, y)。

6.1.6.1.18 Number::bitwiseXOR ( x, y )

抽象操作 Number::bitwiseXOR,接收参数 x (Number) 和 y (Number);返回值:整数 Number。 调用时执行以下步骤:

  1. 返回 NumberBitwiseOp(^, x, y)。

6.1.6.1.19 Number::bitwiseOR ( x, y )

抽象操作 Number::bitwiseOR,接收参数 x (Number) 和 y (Number);返回值:整数 Number。 调用时执行以下步骤:

  1. 返回 NumberBitwiseOp(|, x, y)。

6.1.6.1.20 Number::toString ( x, radix )

抽象操作 Number::toString,接收参数 x (Number) 和 radix (an integer in the inclusive interval from 2 to 36);返回值:String。 它使用基数为 radix 的位置记数系统将 x 表示为 String。使用基数 r 表示数字时所用的数字,按顺序取自 "0123456789abcdefghijklmnopqrstuvwxyz" 的前 r 个码元。大小大于或等于 1𝔽 的数字表示中绝不会包含前导零。 调用时执行以下步骤:

  1. 如果 x 是 NaN,则返回 "NaN"。
  2. 如果 x 是 +0𝔽 或 -0𝔽,则返回 "0"。
  3. 如果 x < -0𝔽,则返回 "-" 与 Number::toString(-x, radix) 的字符串连接。
  4. 如果 x 是 +∞𝔽,则返回 "Infinity"。
  5. 令 n、k 和 s 为满足以下条件的整数:k ≥ 1,radixk - 1 ≤ s < radixk,𝔽(s × radixn - k) 是 x,并且 k 尽可能小。注意,k 是使用基数 radix 表示 s 时的位数,s 不能被 radix 整除,并且这些条件不一定唯一确定 s 的最低有效位。
  6. 如果 radix ≠ 10 或 n 位于从 -5 到 21 的闭区间中,则
    1. 如果 n ≥ k,则
      1. 返回以下各项的字符串连接:
        • 使用基数 radix 表示 s 时的 k 个数字的码元
        • n - k 个码元 0x0030(DIGIT ZERO)
    2. 如果 n > 0,则
      1. 返回以下各项的字符串连接:
        • 使用基数 radix 表示 s 时最高有效的 n 个数字的码元
        • 码元 0x002E(FULL STOP)
        • 使用基数 radix 表示 s 时剩余 k - n 个数字的码元
    3. 断言:n ≤ 0。
    4. 返回以下各项的字符串连接:
      • 码元 0x0030(DIGIT ZERO)
      • 码元 0x002E(FULL STOP)
      • -n 个码元 0x0030(DIGIT ZERO)
      • 使用基数 radix 表示 s 时的 k 个数字的码元
  7. 注:在这种情况下,输入将使用科学 E 记数法表示,例如 1.2e+3。
  8. 断言:radix 是 10。
  9. 如果 n < 0,则
    1. 令 exponentSign 为码元 0x002D(HYPHEN-MINUS)。
  10. 否则,
    1. 令 exponentSign 为码元 0x002B(PLUS SIGN)。
  11. 如果 k = 1,则
    1. 返回以下各项的字符串连接:
      • s 的唯一数字的码元
      • 码元 0x0065(LATIN SMALL LETTER E)
      • exponentSign
      • abs(n - 1) 的十进制表示的码元
  12. 返回以下各项的字符串连接:
    • s 的十进制表示中最高有效数字的码元
    • 码元 0x002E(FULL STOP)
    • s 的十进制表示中剩余 k - 1 个数字的码元
    • 码元 0x0065(LATIN SMALL LETTER E)
    • exponentSign
    • abs(n - 1) 的十进制表示的码元
注 1

以下观察结果可作为实现的有用指南,但不属于本标准的规范性要求:

  • 如果 x 是除 -0𝔽 以外的任意 Number 值,则 ToNumber(ToString(x)) 是 x。
  • s 的最低有效数字并不总能由步骤 5 中列出的要求唯一确定。
注 2

对于提供比上述规则所要求更精确转换的实现,建议使用步骤 5 的以下替代版本作为指南:

  1. 令 n、k 和 s 为满足以下条件的整数:k ≥ 1,radixk - 1 ≤ s < radixk,𝔽(s × radixn - k) 是 x,并且 k 尽可能小。如果 s 有多个可能值,则选择使 s × radixn - k 最接近 ℝ(x) 的 s。如果存在两个这样的 s 值,则选择偶数的那个。注意,k 是使用基数 radix 表示 s 时的位数,并且 s 不能被 radix 整除。
注 3

ECMAScript 实现者可能会发现 David M. Gay 编写的有关浮点数二进制到十进制转换的论文和代码很有用:

Gay, David M. 正确舍入的二进制-十进制和十进制-二进制转换。数值分析,手稿 90-10。AT&T 贝尔实验室(新泽西州默里山)。1990 年 11 月 30 日。可从以下位置获取
https://ampl.com/_archive/first-website/REFS/rounding.pdf。相关代码可从以下位置获取
http://netlib.sandia.gov/fp/dtoa.c 和
http://netlib.sandia.gov/fp/g_fmt.c,也可以在各个 netlib 镜像站点找到。

6.1.6.2 BigInt 类型

BigInt 类型表示整数值。该值可以具有任意大小,不受特定位宽限制。一般而言,除非另有说明,各项操作都被设计为返回数学上精确的结果。对于二元操作,BigInt 的行为类似二进制补码字符串,负数被视为其左侧无限多个位均已置位。

6.1.6.2.1 BigInt::unaryMinus ( bigint )

抽象操作 BigInt::unaryMinus,接收参数 bigint (BigInt);返回值:BigInt。 调用时执行以下步骤:

  1. 如果 bigint = 0ℤ,则返回 0ℤ。
  2. 返回 -bigint。

6.1.6.2.2 BigInt::bitwiseNOT ( bigint )

抽象操作 BigInt::bitwiseNOT,接收参数 bigint (BigInt);返回值:BigInt。 它返回 bigint 的反码。 调用时执行以下步骤:

  1. 返回 -bigint - 1ℤ。

6.1.6.2.3 BigInt::exponentiate ( base, exponent )

抽象操作 BigInt::exponentiate,接收参数 base (BigInt) 和 exponent (BigInt);返回值:(正常完成 (值:BigInt) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 exponent < 0ℤ,则抛出 RangeError 异常。
  2. 如果 base = 0ℤ 且 exponent = 0ℤ,则返回 1ℤ。
  3. 返回 base 的 exponent 次幂。

6.1.6.2.4 BigInt::multiply ( x, y )

抽象操作 BigInt::multiply,接收参数 x (BigInt) 和 y (BigInt);返回值:BigInt。 调用时执行以下步骤:

  1. 返回 x × y。
注
即使结果的位宽远大于输入,也会给出精确的数学结果。

6.1.6.2.5 BigInt::divide ( x, y )

抽象操作 BigInt::divide,接收参数 x (BigInt) 和 y (BigInt);返回值:(正常完成 (值:BigInt) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 y = 0ℤ,则抛出 RangeError 异常。
  2. 令 quotient 为 ℝ(x) / ℝ(y)。
  3. 返回 ℤ(truncate(quotient))。

6.1.6.2.6 BigInt::remainder ( numerator, denominator )

抽象操作 BigInt::remainder,接收参数 numerator (BigInt) 和 denominator (BigInt);返回值:(正常完成 (值:BigInt) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 denominator = 0ℤ,则抛出 RangeError 异常。
  2. 如果 numerator = 0ℤ,则返回 0ℤ。
  3. 令 quotient 为 ℝ(numerator) / ℝ(denominator)。
  4. 令 truncatedQuotient 为 ℤ(truncate(quotient))。
  5. 返回 numerator - (denominator × truncatedQuotient)。
注
结果的符号与被除数的符号相同。

6.1.6.2.7 BigInt::add ( x, y )

抽象操作 BigInt::add,接收参数 x (BigInt) 和 y (BigInt);返回值:BigInt。 调用时执行以下步骤:

  1. 返回 x + y。

6.1.6.2.8 BigInt::subtract ( x, y )

抽象操作 BigInt::subtract,接收参数 x (BigInt) 和 y (BigInt);返回值:BigInt。 调用时执行以下步骤:

  1. 返回 x - y。

6.1.6.2.9 BigInt::leftShift ( x, y )

抽象操作 BigInt::leftShift,接收参数 x (BigInt) 和 y (BigInt);返回值:BigInt。 调用时执行以下步骤:

  1. 如果 y < 0ℤ,则
    1. 返回 ℤ(floor(ℝ(x) / 2-ℝ(y)))。
  2. 返回 x × 2ℤy。
注
此处的语义应等同于按位移位,将 BigInt 视为无限长度的二进制补码数字字符串。

6.1.6.2.10 BigInt::signedRightShift ( x, y )

抽象操作 BigInt::signedRightShift,接收参数 x (BigInt) 和 y (BigInt);返回值:BigInt。 调用时执行以下步骤:

  1. 返回 BigInt::leftShift(x, -y)。

6.1.6.2.11 BigInt::unsignedRightShift ( x, y )

抽象操作 BigInt::unsignedRightShift,接收参数 x (BigInt) 和 y (BigInt);返回值:抛出完成。 调用时执行以下步骤:

  1. 抛出 TypeError 异常。

6.1.6.2.12 BigInt::lessThan ( x, y )

抽象操作 BigInt::lessThan,接收参数 x (BigInt) 和 y (BigInt);返回值:Boolean。 调用时执行以下步骤:

  1. 如果 ℝ(x) < ℝ(y),则返回 true。
  2. 返回 false。

6.1.6.2.13 BigInt::equal ( x, y )

抽象操作 BigInt::equal,接收参数 x (BigInt) 和 y (BigInt);返回值:Boolean。 调用时执行以下步骤:

  1. 如果 ℝ(x) = ℝ(y),则返回 true。
  2. 返回 false。

6.1.6.2.14 BinaryAnd ( x, y )

抽象操作 BinaryAnd,接收参数 x ((0 或 1)) 和 y ((0 或 1));返回值:(0 或 1)。 调用时执行以下步骤:

  1. 如果 x = 1 且 y = 1,则返回 1。
  2. 返回 0。

6.1.6.2.15 BinaryOr ( x, y )

抽象操作 BinaryOr,接收参数 x ((0 或 1)) 和 y ((0 或 1));返回值:(0 或 1)。 调用时执行以下步骤:

  1. 如果 x = 1 或 y = 1,则返回 1。
  2. 返回 0。

6.1.6.2.16 BinaryXor ( x, y )

抽象操作 BinaryXor,接收参数 x ((0 或 1)) 和 y ((0 或 1));返回值:(0 或 1)。 调用时执行以下步骤:

  1. 如果 x = 1 且 y = 0,则返回 1。
  2. 如果 x = 0 且 y = 1,则返回 1。
  3. 返回 0。

6.1.6.2.17 BigIntBitwiseOp ( op, x, y )

抽象操作 BigIntBitwiseOp,接收参数 op ((&、^ 或 |))、x (BigInt) 和 y (BigInt);返回值:BigInt。 调用时执行以下步骤:

  1. 将 x 设置为 ℝ(x)。
  2. 将 y 设置为 ℝ(y)。
  3. 令 result 为 0。
  4. 令 shift 为 0。
  5. 重复,直到 (x = 0 或 x = -1) 且 (y = 0 或 y = -1),
    1. 令 xDigit 为 x modulo 2。
    2. 令 yDigit 为 y modulo 2。
    3. 如果 op 是 &,则
      1. 将 result 设置为 result + 2shift × BinaryAnd(xDigit, yDigit)。
    4. 否则如果 op 是 |,则
      1. 将 result 设置为 result + 2shift × BinaryOr(xDigit, yDigit)。
    5. 否则,
      1. 断言:op 是 ^。
      2. 将 result 设置为 result + 2shift × BinaryXor(xDigit, yDigit)。
    6. 将 shift 设置为 shift + 1。
    7. 将 x 设置为 (x - xDigit) / 2。
    8. 将 y 设置为 (y - yDigit) / 2。
  6. 如果 op 是 &,则
    1. 令 signBit 为 BinaryAnd(x modulo 2, y modulo 2)。
  7. 否则如果 op 是 |,则
    1. 令 signBit 为 BinaryOr(x modulo 2, y modulo 2)。
  8. 否则,
    1. 断言:op 是 ^。
    2. 令 signBit 为 BinaryXor(x modulo 2, y modulo 2)。
  9. 如果 signBit ≠ 0,则
    1. 将 result 设置为 result - 2shift。
    2. 注:这会扩展符号。
  10. 返回 result 对应的 BigInt 值。

6.1.6.2.18 BigInt::bitwiseAND ( x, y )

抽象操作 BigInt::bitwiseAND,接收参数 x (BigInt) 和 y (BigInt);返回值:BigInt。 调用时执行以下步骤:

  1. 返回 BigIntBitwiseOp(&, x, y)。

6.1.6.2.19 BigInt::bitwiseXOR ( x, y )

抽象操作 BigInt::bitwiseXOR,接收参数 x (BigInt) 和 y (BigInt);返回值:BigInt。 调用时执行以下步骤:

  1. 返回 BigIntBitwiseOp(^, x, y)。

6.1.6.2.20 BigInt::bitwiseOR ( x, y )

抽象操作 BigInt::bitwiseOR,接收参数 x (BigInt) 和 y (BigInt);返回值:BigInt。 调用时执行以下步骤:

  1. 返回 BigIntBitwiseOp(|, x, y)。

6.1.6.2.21 BigInt::toString ( x, radix )

抽象操作 BigInt::toString,接收参数 x (BigInt) 和 radix (an integer in the inclusive interval from 2 to 36);返回值:String。 它使用基数为 radix 的位置记数系统将 x 表示为 String。使用基数 r 表示 BigInt 时所用的数字,按顺序取自 "0123456789abcdefghijklmnopqrstuvwxyz" 的前 r 个码元。除 0ℤ 以外的 BigInt 表示中绝不会包含前导零。 调用时执行以下步骤:

  1. 如果 x < 0ℤ,则返回 "-" 与 BigInt::toString(-x, radix) 的字符串连接。
  2. 返回由使用基数 radix 表示 x 所组成的 String 值。

6.1.7 Object 类型

Object 类型的每个实例(也简称为“Object”)都表示属性的集合。每个属性要么是数据属性,要么是访问器属性:

  • 数据属性将一个键值与一个 ECMAScript 语言值及一组 Boolean 特性关联起来。
  • 访问器属性将一个键值与一个或两个访问器函数及一组 Boolean 特性关联起来。访问器函数用于存储或检索与该属性关联的 ECMAScript 语言值。

对象的属性使用属性键进行唯一标识。属性键是 String 或 Symbol。所有 String 和 Symbol(包括空 String)都可作为有效的属性键。属性名称是 String 类型的属性键。

整数索引是这样一个属性名称 n:CanonicalNumericIndexString(n) 返回从 +0𝔽 到 𝔽(253 - 1) 的闭区间中的整数 Number。数组索引是这样一个整数索引 n:CanonicalNumericIndexString(n) 返回从 +0𝔽 到 𝔽(232 - 2) 的闭区间中的整数 Number。

注

每个非负安全整数都有一个对应的整数索引。除了 232 - 1 之外,每个 32 位无符号整数都有一个对应的数组索引。"-0" 既不是整数索引,也不是数组索引。

属性键用于访问属性及其值。属性访问有两种:get 和 set,分别对应于值检索和赋值。可通过 get 和 set 访问的属性既包括作为对象直接组成部分的自有属性,也包括通过属性继承关系由另一个关联对象提供的继承属性。继承属性可以是该关联对象的自有属性或继承属性。对象的每个自有属性都必须具有与该对象其他自有属性的键值不同的键值。

在逻辑上,所有对象都是属性的集合,但存在多种形式的对象,它们在访问和操作自身属性的语义上有所不同。有关多种对象形式的定义,请参见 6.1.7.2。

此外,某些对象是可调用的;它们称为函数或函数对象,并将在下文进一步描述。ECMAScript 中的所有函数都是 Object 类型的成员。

6.1.7.1 属性特性

本规范使用特性来定义和说明 Object 属性的状态,如 表 3 所述。除非明确规定,否则每个特性的初始值都是其默认值。

表 3: Object 属性的特性
特性名称 存在该特性的属性类型 值域 默认值 描述
[[Value]] 数据属性 ECMAScript 语言值 undefined 对该属性执行 get 访问时检索到的值。
[[Writable]] 数据属性 Boolean false 如果为 false,ECMAScript 代码尝试使用 [[Set]] 更改该属性的 [[Value]] 特性将不会成功。
[[Getter]] 访问器属性 函数对象或 undefined undefined 如果值不是 undefined,则每当对该属性执行 get 访问时,都会使用空参数列表调用其 [[Call]] 内部方法(表 5)以检索属性值。
[[Setter]] 访问器属性 函数对象或 undefined undefined 如果值不是 undefined,则每当对该属性执行 set 访问时,都会使用一个仅包含所赋值的参数列表调用其 [[Call]] 内部方法(表 5)。属性的 [[Setter]] 内部方法产生的效果可能会影响该属性的 [[Getter]] 内部方法后续调用所返回的值,但并不要求必须如此。
[[Enumerable]] 数据属性或访问器属性 Boolean false 如果为 true,则该属性会由 for-in 枚举进行枚举(参见 14.7.5)。否则,称该属性为不可枚举。
[[Configurable]] 数据属性或访问器属性 Boolean false 如果为 false,则尝试删除该属性、将其从数据属性更改为访问器属性或从访问器属性更改为数据属性,或者对其特性进行任何更改(替换现有 [[Value]] 或将 [[Writable]] 设置为 false 除外)都会失败。

6.1.7.2 Object 内部方法和内部槽

在 ECMAScript 中,对象的实际语义通过称为内部方法的算法来规定。ECMAScript 引擎中的每个对象都与一组定义其运行时行为的内部方法相关联。这些内部方法不是 ECMAScript 语言的一部分。本规范定义它们纯粹是为了说明。然而,ECMAScript 实现中的每个对象都必须按照与其关联的内部方法所规定的方式运行。具体如何实现由实现自行确定。

内部方法名称是多态的。这意味着,当在不同对象值上调用同一个内部方法名称时,它们可能执行不同的算法。实际被调用内部方法的对象是该调用的“目标”。如果在运行时,算法的实现尝试使用某个对象不支持的内部方法,则抛出 TypeError 异常。

内部槽对应于与对象、Symbol 或 Private Name 关联并由各种 ECMAScript 规范算法使用的内部状态。内部槽不是对象属性,也不会被继承。根据具体的内部槽规范,此类状态可以由任何 ECMAScript 语言类型的值或特定 ECMAScript 规范类型的值组成。除非另有明确规定,否则内部槽会作为创建 Object、Symbol 或 Private Name 过程的一部分进行分配,并且不能动态添加。除非另有规定,否则内部槽的初始值为 undefined。本规范中的各种算法会创建具有内部槽的值。然而,ECMAScript 语言没有提供直接操作内部槽的方式。

所有对象都有一个名为 [[PrivateElements]] 的内部槽,它是 PrivateElements 的 List。此 List 表示对象的私有字段、方法和访问器的值。最初,它是空 List。

本规范使用双重方括号 [[ ]] 括起来的名称来标识内部方法和内部槽。

表 4 汇总了本规范使用的、适用于由 ECMAScript 代码创建或操作的所有对象的基本内部方法。每个对象都必须为所有基本内部方法提供算法。不过,并非所有对象都必须为这些方法使用相同的算法。

普通对象是满足以下所有条件的对象:

  • 对于 表 4 中列出的内部方法,对象使用 10.1 中定义的方法。
  • 如果对象具有 [[Call]] 内部方法,则使用 10.2.1 中定义的方法或 10.3.1 中定义的方法。
  • 如果对象具有 [[Construct]] 内部方法,则使用 10.2.2 中定义的方法或 10.3.2 中定义的方法。

异质对象是任何非普通对象的对象。

本规范根据对象的内部方法识别不同种类的异质对象。一个对象即使在行为上等同于某种特定的异质对象(例如 Array 异质对象或绑定函数异质对象),但如果它不具有为该种类规定的同一组内部方法,就不会被识别为该种类的异质对象。

表 4 和其他类似表格描述每个内部方法的调用模式。调用模式始终包含一个带括号的描述性参数名称列表。

除了其参数之外,内部方法始终可以访问作为方法调用目标的对象。

内部方法隐式返回 Completion Record,它要么是包装了调用模式中所示返回类型值的正常完成,要么是抛出完成。

表 4: 基本内部方法
内部方法 描述 定义
[[GetPrototypeOf]] ( )

内部方法 [[GetPrototypeOf]],接收无参数;返回值:(正常完成 (值:(Object 或 null)) 或 抛出完成)。

它确定为此对象提供继承属性的对象。null 值表示不存在这样的对象。
在本规范中,它在以下类型中具有定义;宿主可以提供具有其自身定义的其他类型:
[[SetPrototypeOf]] ( proto )

内部方法 [[SetPrototypeOf]],接收参数 proto ((Object 或 null));返回值:(正常完成 (值:Boolean) 或 抛出完成)。

它将此对象与另一个提供继承属性的对象关联起来。传入 null 表示不存在提供继承属性的对象。返回 true 表示操作已成功完成,返回 false 表示操作未成功。
在本规范中,它在以下类型中具有定义;宿主可以提供具有其自身定义的其他类型:
[[IsExtensible]] ( )

内部方法 [[IsExtensible]],接收无参数;返回值:(正常完成 (值:Boolean) 或 抛出完成)。

它确定是否允许向此对象添加其他属性。
在本规范中,它在以下类型中具有定义;宿主可以提供具有其自身定义的其他类型:
[[PreventExtensions]] ( )

内部方法 [[PreventExtensions]],接收无参数;返回值:(正常完成 (值:Boolean) 或 抛出完成)。

它控制是否可以向此对象添加新属性。如果操作成功则返回 true,如果操作失败则返回 false。
在本规范中,它在以下类型中具有定义;宿主可以提供具有其自身定义的其他类型:
[[GetOwnProperty]] ( propertyKey )

内部方法 [[GetOwnProperty]],接收参数 propertyKey (属性键);返回值:(正常完成 (值:(属性描述符 或 undefined)) 或 抛出完成)。

它返回此对象中键为 propertyKey 的自有属性的 Property Descriptor;如果不存在这样的属性,则返回 undefined。
在本规范中,它在以下类型中具有定义;宿主可以提供具有其自身定义的其他类型:
[[DefineOwnProperty]] ( propertyKey, propertyDesc )

内部方法 [[DefineOwnProperty]],接收参数 propertyKey (属性键) 和 propertyDesc (属性描述符);返回值:(正常完成 (值:Boolean) 或 抛出完成)。

它创建或修改键为 propertyKey 的自有属性,使其具有 propertyDesc 所描述的状态。如果操作成功则返回 true;如果无法创建或更新该属性,则返回 false。
在本规范中,它在以下类型中具有定义;宿主可以提供具有其自身定义的其他类型:
[[HasProperty]] ( propertyKey )

内部方法 [[HasProperty]],接收参数 propertyKey (属性键);返回值:(正常完成 (值:Boolean) 或 抛出完成)。

它返回一个 Boolean,指示此对象是否已经具有键为 propertyKey 的自有属性或继承属性。
在本规范中,它在以下类型中具有定义;宿主可以提供具有其自身定义的其他类型:
[[Get]] ( propertyKey, receiver )

内部方法 [[Get]],接收参数 propertyKey (属性键) 和 receiver (ECMAScript 语言值);返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。

它从此对象返回键为 propertyKey 的属性值。如果为了检索属性值必须执行任何 ECMAScript 代码,则在对代码求值时使用 receiver 作为 this 值。
在本规范中,它在以下类型中具有定义;宿主可以提供具有其自身定义的其他类型:
[[Set]] ( propertyKey, value, receiver )

内部方法 [[Set]],接收参数 propertyKey (属性键)、value (ECMAScript 语言值) 和 receiver (ECMAScript 语言值);返回值:(正常完成 (值:Boolean) 或 抛出完成)。

它将键为 propertyKey 的属性值设置为 value。如果为了设置属性值必须执行任何 ECMAScript 代码,则在对代码求值时使用 receiver 作为 this 值。如果属性值已设置,则返回 true;如果无法设置,则返回 false。
在本规范中,它在以下类型中具有定义;宿主可以提供具有其自身定义的其他类型:
[[Delete]] ( propertyKey )

内部方法 [[Delete]],接收参数 propertyKey (属性键);返回值:(正常完成 (值:Boolean) 或 抛出完成)。

它从此对象中移除键为 propertyKey 的自有属性。如果该属性未被删除且仍然存在,则返回 false。如果该属性已被删除或不存在,则返回 true。
在本规范中,它在以下类型中具有定义;宿主可以提供具有其自身定义的其他类型:
[[OwnPropertyKeys]] ( )

内部方法 [[OwnPropertyKeys]],接收无参数;返回值:(正常完成 (值:列表 (元素:属性键)) 或 抛出完成)。

它返回一个 List,其元素是该对象的所有自有属性键。
在本规范中,它在以下类型中具有定义;宿主可以提供具有其自身定义的其他类型:

表 5 汇总了可作为函数调用的对象所支持的其他基本内部方法。函数对象是支持 [[Call]] 内部方法的对象。构造函数是支持 [[Construct]] 内部方法的对象。每个支持 [[Construct]] 的对象都必须支持 [[Call]];也就是说,每个构造函数都必须是函数对象。因此,构造函数也可以称为构造函数函数或构造函数函数对象。

表 5: 函数对象的附加基本内部方法
内部方法 描述 定义
[[Call]] ( thisArg, argList )

内部方法 [[Call]],接收参数 thisArg (ECMAScript 语言值) 和 argList (列表 (元素:ECMAScript 语言值));返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。

它执行与此对象关联的代码。通过函数调用表达式调用。传给内部方法的参数是一个 this 值和一个 List,该 List 的元素是调用表达式传给函数的参数。实现此内部方法的对象是可调用的。
在本规范中,它在以下类型中具有定义;宿主可以提供具有其自身定义的其他类型:
[[Construct]] ( argList, newTarget )

内部方法 [[Construct]],接收参数 argList (列表 (元素:ECMAScript 语言值)) 和 newTarget (构造函数);返回值:(正常完成 (值:Object) 或 抛出完成)。

它创建一个对象。通过 new 运算符或 super 调用来调用。内部方法的第一个参数是一个 List,其元素是构造函数调用或 super 调用的参数。第二个参数是最初应用 new 运算符的对象。实现此内部方法的对象称为构造函数。函数对象不一定是构造函数,此类非构造函数的函数对象没有 [[Construct]] 内部方法。
在本规范中,它在以下类型中具有定义;宿主可以提供具有其自身定义的其他类型:

普通对象和标准异质对象的基本内部方法语义在条款 10 中规定。如果实现不支持对异质对象内部方法的任何规定用法,则尝试该用法时必须抛出 TypeError 异常。

6.1.7.3 基本内部方法的不变量

ECMAScript 引擎中 Object 的内部方法必须符合下面规定的不变量列表。普通 ECMAScript Object 以及本规范中的所有标准异质对象都保持这些不变量。ECMAScript Proxy 对象通过对 [[ProxyHandler]] 对象上调用的陷阱结果执行运行时检查来保持这些不变量。

任何由实现提供的异质对象也必须为这些对象保持这些不变量。违反这些不变量可能导致 ECMAScript 代码出现不可预测的行为并产生安全问题。但是,违反这些不变量绝不能损害实现的内存安全性。

实现不得以任何方式允许绕过这些不变量,例如提供实现基本内部方法功能、却不强制执行其不变量的替代接口。

定义:

  • 内部方法的目标是调用该内部方法的对象。
  • 如果已观察到目标的 [[IsExtensible]] 内部方法返回 false,或者其 [[PreventExtensions]] 内部方法返回 true,则该目标是不可扩展的。
  • 不存在的属性是不可扩展目标上不存在的自有属性。
  • 所有对 SameValue 的引用都按照 SameValue 算法的定义。

返回值:

任何内部方法返回的值都必须是 Completion Record,并且满足以下两种情况之一:

  • [[Type]] = normal、[[Target]] = empty,且 [[Value]] = 下方为该内部方法显示的“正常返回类型”的值,或
  • [[Type]] = throw、[[Target]] = empty,且 [[Value]] = 任意 ECMAScript 语言值。
注 1

内部方法不得返回 continue 完成、break 完成或 return 完成。

[[GetPrototypeOf]] ( )

  • 正常返回类型是 Object 或 Null。
  • 如果目标不可扩展,并且 [[GetPrototypeOf]] 返回值 proto,则以后对 [[GetPrototypeOf]] 的任何调用都应返回与 proto SameValue 的值。
注 2

对象的原型链应具有有限长度(也就是说,从任何对象开始,递归地对其结果应用 [[GetPrototypeOf]] 内部方法最终应得到值 null)。但是,如果原型链包含任何不使用 [[GetPrototypeOf]] 普通对象定义的异质对象,则无法将此要求作为对象级不变量强制执行。这样的循环原型链可能导致访问对象属性时出现无限循环。

[[SetPrototypeOf]] ( proto )

  • 正常返回类型是 Boolean。
  • 如果目标不可扩展,则 [[SetPrototypeOf]] 必须返回 false,除非 proto 与观察到的目标 [[GetPrototypeOf]] 值 SameValue。

[[IsExtensible]] ( )

  • 正常返回类型是 Boolean。
  • 如果 [[IsExtensible]] 返回 false,则以后在目标上对 [[IsExtensible]] 的所有调用都必须返回 false。

[[PreventExtensions]] ( )

  • 正常返回类型是 Boolean。
  • 如果 [[PreventExtensions]] 返回 true,则以后在目标上对 [[IsExtensible]] 的所有调用都必须返回 false,并且目标现在被视为不可扩展。

[[GetOwnProperty]] ( propertyKey )

  • 正常返回类型是 Property Descriptor 或 Undefined。
  • 如果返回值是 Property Descriptor,则它必须是完全填充的 Property Descriptor。
  • 如果 propertyKey 被描述为不可配置、不可写的自有数据属性,则以后对 [[GetOwnProperty]] ( propertyKey ) 的所有调用都必须返回其 [[Value]] 与 propertyKey 的 [[Value]] 特性 SameValue 的 Property Descriptor。
  • 如果 propertyKey 除 [[Writable]] 和 [[Value]] 之外的特性可能随时间变化,或者该属性可能被删除,则 propertyKey 的 [[Configurable]] 特性必须为 true。
  • 如果 [[Writable]] 特性可能从 false 更改为 true,则 [[Configurable]] 特性必须为 true。
  • 如果目标不可扩展且 propertyKey 不存在,则以后在目标上对 [[GetOwnProperty]] (propertyKey) 的所有调用都必须将 propertyKey 描述为不存在(即 [[GetOwnProperty]] (propertyKey) 必须返回 undefined)。
注 3

作为第三个不变量的结果,如果一个属性被描述为数据属性并且它可能随时间返回不同的值,则即使其他基本内部方法没有公开任何更改该值的机制,[[Writable]] 和 [[Configurable]] 特性中的一个或两个也必须为 true。

[[DefineOwnProperty]] ( propertyKey, propertyDesc )

  • 正常返回类型是 Boolean。
  • 如果之前已观察到 propertyKey 是目标的不可配置自有属性,则 [[DefineOwnProperty]] 必须返回 false,除非满足以下任一条件:
    1. propertyKey 是可写数据属性。不可配置的可写数据属性可以更改为不可配置的不可写数据属性。
    2. propertyDesc 的所有特性都与 propertyKey 的相应特性 SameValue。
  • 如果目标不可扩展,并且 propertyKey 是不存在的自有属性,则 [[DefineOwnProperty]] (propertyKey, propertyDesc) 必须返回 false。也就是说,不可扩展的目标对象不能通过新属性进行扩展。

[[HasProperty]] ( propertyKey )

  • 正常返回类型是 Boolean。
  • 如果之前观察到 propertyKey 是目标的不可配置自有数据属性或访问器属性,则 [[HasProperty]] 必须返回 true。

[[Get]] ( propertyKey, receiver )

  • 正常返回类型是任意 ECMAScript 语言类型。
  • 如果之前观察到 propertyKey 是目标上值为 value 的不可配置、不可写自有数据属性,则 [[Get]] 必须返回与 value SameValue 的值。
  • 如果之前观察到 propertyKey 是目标的不可配置自有访问器属性,且其 [[Getter]] 特性为 undefined,则 [[Get]] 操作必须返回 undefined。

[[Set]] ( propertyKey, value, receiver )

  • 正常返回类型是 Boolean。
  • 如果之前观察到 propertyKey 是目标的不可配置、不可写自有数据属性,则 [[Set]] 必须返回 false,除非 value 与 propertyKey 的 [[Value]] 特性 SameValue。
  • 如果之前观察到 propertyKey 是目标的不可配置自有访问器属性,且其 [[Setter]] 特性为 undefined,则 [[Set]] 操作必须返回 false。

[[Delete]] ( propertyKey )

  • 正常返回类型是 Boolean。
  • 如果之前观察到 propertyKey 是目标的不可配置自有数据属性或访问器属性,则 [[Delete]] 必须返回 false。

[[OwnPropertyKeys]] ( )

  • 正常返回类型是 List。
  • 返回的 List 不得包含任何重复条目。
  • 返回的 List 的每个元素都必须是属性键。
  • 返回的 List 至少必须包含之前观察到的所有不可配置自有属性的键。
  • 如果目标不可扩展,则返回的 List 必须且只能包含可使用 [[GetOwnProperty]] 观察到的目标所有自有属性的键。

[[Call]] ( )

[[Construct]] ( )

  • 正常返回类型是 Object。
  • 目标还必须具有 [[Call]] 内部方法。

6.1.7.4 知名内在对象

知名内在对象是本规范算法明确引用的内置对象,并且通常具有特定于 Realm 的标识。除非另有规定,否则每个内在对象实际上对应一组相似对象,每个 Realm 一个。

在本规范中,%name% 形式的引用表示与当前 Realm 关联、对应于该名称的内在对象。%name.a.b% 形式的引用表示:如同在任何 ECMAScript 代码求值之前访问内在对象 %name% 的 "a" 属性值的 "b" 属性。当前 Realm 及其内在对象的确定方式见 9.4。知名内在对象列于 表 6。

表 6: 知名内在对象
内在对象名称 全局名称 ECMAScript 语言关联
%AggregateError% "AggregateError" AggregateError 构造函数(20.5.7.1)
%Array% "Array" Array 构造函数(23.1.1)
%ArrayBuffer% "ArrayBuffer" ArrayBuffer 构造函数(25.1.4)
%ArrayIteratorPrototype% Array Iterator 对象的原型(23.1.5)
%AsyncDisposableStack% "AsyncDisposableStack" AsyncDisposableStack 构造函数(27.4.1)
%AsyncFromSyncIteratorPrototype% Async-from-Sync Iterator 对象的原型(27.1.5)
%AsyncFunction% 异步函数对象的构造函数(27.10.1)
%AsyncGeneratorFunction% 异步生成器函数对象的构造函数(27.7.1)
%AsyncGeneratorPrototype% 异步生成器对象的原型(27.9)
%AsyncIteratorPrototype% 所有标准内置异步迭代器对象都间接继承自的对象
%Atomics% "Atomics" Atomics 对象(25.4)
%BigInt% "BigInt" BigInt 构造函数(21.2.1)
%BigInt64Array% "BigInt64Array" BigInt64Array 构造函数(23.2)
%BigUint64Array% "BigUint64Array" BigUint64Array 构造函数(23.2)
%Boolean% "Boolean" Boolean 构造函数(20.3.1)
%DataView% "DataView" DataView 构造函数(25.3.2)
%Date% "Date" Date 构造函数(21.4.2)
%decodeURI% "decodeURI" decodeURI 函数(19.2.6.1)
%decodeURIComponent% "decodeURIComponent" decodeURIComponent 函数(19.2.6.2)
%DisposableStack% "DisposableStack" DisposableStack 构造函数(27.3.1)
%encodeURI% "encodeURI" encodeURI 函数(19.2.6.3)
%encodeURIComponent% "encodeURIComponent" encodeURIComponent 函数(19.2.6.4)
%Error% "Error" Error 构造函数(20.5.1)
%eval% "eval" eval 函数(19.2.1)
%EvalError% "EvalError" EvalError 构造函数(20.5.5.1)
%FinalizationRegistry% "FinalizationRegistry" FinalizationRegistry 构造函数(26.2.1)
%Float16Array% "Float16Array" Float16Array 构造函数(23.2)
%Float32Array% "Float32Array" Float32Array 构造函数(23.2)
%Float64Array% "Float64Array" Float64Array 构造函数(23.2)
%ForInIteratorPrototype% For-In Iterator 对象的原型(14.7.5.10)
%Function% "Function" Function 构造函数(20.2.1)
%GeneratorFunction% 生成器函数对象的构造函数(27.6.1)
%GeneratorPrototype% 生成器对象的原型(27.8)
%Int8Array% "Int8Array" Int8Array 构造函数(23.2)
%Int16Array% "Int16Array" Int16Array 构造函数(23.2)
%Int32Array% "Int32Array" Int32Array 构造函数(23.2)
%isFinite% "isFinite" isFinite 函数(19.2.2)
%isNaN% "isNaN" isNaN 函数(19.2.3)
%Iterator% "Iterator" Iterator 构造函数(27.1.3.1)
%IteratorHelperPrototype% Iterator Helper 对象的原型(27.1.2.1)
%JSON% "JSON" JSON 对象(25.5)
%Map% "Map" Map 构造函数(24.1.1)
%MapIteratorPrototype% Map Iterator 对象的原型(24.1.5)
%Math% "Math" Math 对象(21.3)
%Number% "Number" Number 构造函数(21.1.1)
%Object% "Object" Object 构造函数(20.1.1)
%parseFloat% "parseFloat" parseFloat 函数(19.2.4)
%parseInt% "parseInt" parseInt 函数(19.2.5)
%Promise% "Promise" Promise 构造函数(27.5.3)
%Proxy% "Proxy" Proxy 构造函数(28.2.1)
%RangeError% "RangeError" RangeError 构造函数(20.5.5.2)
%ReferenceError% "ReferenceError" ReferenceError 构造函数(20.5.5.3)
%Reflect% "Reflect" Reflect 对象(28.1)
%RegExp% "RegExp" RegExp 构造函数(22.2.4)
%RegExpStringIteratorPrototype% RegExp String Iterator 对象的原型(22.2.9)
%Set% "Set" Set 构造函数(24.2.2)
%SetIteratorPrototype% Set Iterator 对象的原型(24.2.6)
%SharedArrayBuffer% "SharedArrayBuffer" SharedArrayBuffer 构造函数(25.2.3)
%String% "String" String 构造函数(22.1.1)
%StringIteratorPrototype% String Iterator 对象的原型(22.1.5)
%SuppressedError% "SuppressedError" SuppressedError 构造函数(20.5.8.1)
%Symbol% "Symbol" Symbol 构造函数(20.4.1)
%SyntaxError% "SyntaxError" SyntaxError 构造函数(20.5.5.4)
%ThrowTypeError% 一个无条件抛出 %TypeError% 新实例的函数对象
%TypedArray% 所有类型化 Array 构造函数的超类(23.2.1)
%TypeError% "TypeError" TypeError 构造函数(20.5.5.5)
%Uint8Array% "Uint8Array" Uint8Array 构造函数(23.2)
%Uint8ClampedArray% "Uint8ClampedArray" Uint8ClampedArray 构造函数(23.2)
%Uint16Array% "Uint16Array" Uint16Array 构造函数(23.2)
%Uint32Array% "Uint32Array" Uint32Array 构造函数(23.2)
%URIError% "URIError" URIError 构造函数(20.5.5.6)
%WeakMap% "WeakMap" WeakMap 构造函数(24.3.1)
%WeakRef% "WeakRef" WeakRef 构造函数(26.1.1)
%WeakSet% "WeakSet" WeakSet 构造函数(24.4.1)
%WrapForValidIteratorPrototype% Iterator.from 返回的包装迭代器对象的原型(27.1.3.2.2.1)
注

其他条目见 表 103。

6.2 ECMAScript 规范类型

规范类型对应于算法中用于描述 ECMAScript 语言构造和 ECMAScript 语言类型语义的元值。规范类型包括 Reference Record、List、Completion Record、Property Descriptor、Environment Record、Abstract Closure 和 Data Block。规范类型值是规范产物,不一定对应于 ECMAScript 实现中的任何特定实体。规范类型值可用于描述 ECMAScript 表达式求值的中间结果,但此类值不能存储为对象的属性或 ECMAScript 语言变量的值。

6.2.1 Enum 规范类型

Enum 是规范内部使用且无法从 ECMAScript 代码中直接观察到的值。Enum 使用 sans-serif 字体以大写 kebab case 表示。例如,Completion Record 的 [[Type]] 字段可以取 normal、return 或 throw 等值。Enum 除名称之外没有其他特征。Enum 的名称除了将其与其他 Enum 区分开之外没有其他用途,也不暗示其在上下文中的用途或含义。

6.2.2 List 和 Record 规范类型

List 类型用于说明 new 表达式、函数调用以及其他需要简单有序值列表的算法中参数列表(参见 13.3.8)的求值。List 类型的值只是由各个值组成的列表元素的有序序列。这些序列可以具有任意长度。可以使用从 0 开始的索引随机访问列表元素。为了便于表示,可以使用类似数组的语法访问 List 元素。例如,args[2] 是“List args 的第 3个元素”的简写。

当算法在未指定顺序的情况下迭代 List 的元素时,所使用的顺序就是这些元素在 List 中的顺序。

为了便于本规范中的表示,可以使用字面量语法来表示新的 List 值。例如,« 1, 2 » 定义了一个具有两个元素的 List 值,其中每个元素都初始化为特定值。新的空 List 可以表示为 « »。

在本规范中,短语“A、B、... 的列表连接”(其中每个参数都是可能为空的 List)表示一个新的 List 值,其元素是按照各参数的顺序,将每个参数中的元素依次连接而成的。

应用于 String 的 List 时,短语“按照码元字典序排序”表示:按照每个码元的数值进行排序,比较到较短字符串的长度为止;如果所有码元均相等,则将较短字符串排在较长字符串之前,如抽象操作 IsLessThan 中所述。

Record 类型用于描述本规范算法中的数据聚合。Record 类型值由一个或多个具名字段组成。每个字段的值都是 ECMAScript 语言值或规范值。字段名称始终括在双重方括号中,例如 [[Value]]。

为了便于本规范中的表示,可以使用类似对象字面量的语法来表示 Record。例如,{ [[Field1]]: 42, [[Field2]]: false, [[Field3]]: empty } 定义了一个具有三个字段的 Record,每个字段都初始化为特定值。字段名称的顺序无关紧要。任何未显式列出的字段都被视为不存在。

在规范文本和算法中,可以使用点表示法引用 Record 的特定字段。例如,如果 R 是上一段所示的 Record,则 R.[[Field2]] 是“R 中名为 [[Field2]] 的字段”的简写。

常用 Record 字段组合的模式可以命名,并且该名称可作为字面量 Record 的前缀,用于标识所描述的具体聚合种类。例如:PropertyDescriptor { [[Value]]: 42, [[Writable]]: false, [[Configurable]]: true }。

6.2.3 Set 和 Relation 规范类型

Set 类型用于说明内存模型中使用的无序元素集合。它不同于同名的 ECMAScript 集合类型。为消除歧义,本规范始终将 ECMAScript 集合的实例称为“Set 对象”。Set 类型的值是元素的简单集合,其中任何元素都不会出现多次。可以向 Set 中添加元素,也可以从 Set 中移除元素。Set 之间可以进行并集、交集或差集运算。

Relation 类型用于说明对 Set 的约束。Relation 类型的值是由其值域中的值的有序对组成的 Set。例如,Memory 事件上的 Relation 是由 Memory 事件的有序对组成的集合。对于 Relation R 以及 R 值域中的两个值 a 和 b,a R b 是“有序对 (a, b) 是 R 的成员”的简写。当一个 Relation 是满足某些条件的最小 Relation 时,它是关于这些条件的最小 Relation。

严格偏序是满足以下条件的 Relation 值 R。

  • 对于 R 的定义域中的所有 a、b 和 c:

    • 不存在 a R a,并且
    • 如果 a R b 且 b R c,则 a R c。
注 1

上述两个性质分别称为非自反性和传递性。

严格全序是满足以下条件的 Relation 值 R。

  • 对于 R 的定义域中的所有 a、b 和 c:

    • a 是 b,或者 a R b,或者 b R a,并且
    • 不存在 a R a,并且
    • 如果 a R b 且 b R c,则 a R c。
注 2

上述三个性质分别称为完全性、非自反性和传递性。

6.2.4 Completion Record 规范类型

Completion Record 规范类型用于说明值和控制流在运行时的传播,例如执行非局部控制转移的语句(break、continue、return 和 throw)的行为。

Completion Record 具有 表 7 中定义的字段。

表 7: Completion Record 字段
字段名称 值 含义
[[Type]] normal、break、continue、return 或 throw 发生的完成类型。
[[Value]] 除 Completion Record 之外的任意值 所产生的值。
[[Target]] String 或 empty 定向控制转移的目标标签。

有时使用以下简写术语来指代 Completion Record。

  • 正常完成指 [[Type]] 值为 normal 的任何 Completion Record。
  • break 完成指 [[Type]] 值为 break 的任何 Completion Record。
  • continue 完成指 [[Type]] 值为 continue 的任何 Completion Record。
  • return 完成指 [[Type]] 值为 return 的任何 Completion Record。
  • throw 完成指 [[Type]] 值为 throw 的任何 Completion Record。
  • 突然完成指 [[Type]] 值不是 normal 的任何 Completion Record。
  • 包含某种类型值的正常完成,指其 [[Value]] 字段中具有该类型值的正常完成。

本规范中定义的可调用对象只返回正常完成或抛出完成。返回任何其他类型的 Completion Record 都被视为编辑错误。

实现定义的可调用对象必须返回正常完成或抛出完成。

6.2.4.1 NormalCompletion ( value )

抽象操作 NormalCompletion,接收参数 value (any value except a Completion 记录);返回值:正常完成。 调用时执行以下步骤:

  1. 返回 Completion Record { [[Type]]: normal, [[Value]]: value, [[Target]]: empty }。

6.2.4.2 ThrowCompletion ( value )

抽象操作 ThrowCompletion,接收参数 value (ECMAScript 语言值);返回值:抛出完成。 调用时执行以下步骤:

  1. 返回 Completion Record { [[Type]]: throw, [[Value]]: value, [[Target]]: empty }。

6.2.4.3 ReturnCompletion ( value )

抽象操作 ReturnCompletion,接收参数 value (ECMAScript 语言值);返回值:返回完成。 调用时执行以下步骤:

  1. 返回 Completion Record { [[Type]]: return, [[Value]]: value, [[Target]]: empty }。

6.2.4.4 UpdateEmpty ( completionRecord, value )

抽象操作 UpdateEmpty,接收参数 completionRecord (完成记录) 和 value (any value except a Completion 记录);返回值:完成记录。 调用时执行以下步骤:

  1. 断言:如果 completionRecord 是 return 完成或 throw 完成,则 completionRecord.[[Value]] 不是 empty。
  2. 如果 completionRecord.[[Value]] 不是 empty,则返回 ? completionRecord。
  3. 返回 Completion Record { [[Type]]: completionRecord.[[Type]], [[Value]]: value, [[Target]]: completionRecord.[[Target]] }。

6.2.5 Reference Record 规范类型

Reference Record 类型用于说明 delete、typeof、赋值运算符、super 关键字以及其他语言特性等的行为。例如,赋值的左操作数应产生一个 Reference Record。

Reference Record 是已解析的名称或(可能尚未解析的)属性绑定;其字段由 表 8 定义。

表 8: Reference Record 字段
字段名称 值 含义
[[Base]] ECMAScript 语言值、Environment Record 或 unresolvable 持有该绑定的值或 Environment Record。[[Base]] 为 unresolvable 表示无法解析该绑定。
[[ReferencedName]] ECMAScript 语言值或 Private Name 绑定的名称。如果 [[Base]] 值是 Environment Record,则始终为 String。否则,在执行 ToPropertyKey 之前,可以是 String 或 Symbol 以外的 ECMAScript 语言值。
[[Strict]] Boolean 如果 Reference Record 源自严格模式代码,则为 true,否则为 false。
[[ThisValue]] ECMAScript 语言值或 empty 如果不是 empty,则 Reference Record 表示使用 super 关键字表达的属性绑定;它称为 Super Reference Record,并且其 [[Base]] 值永远不会是 Environment Record。在这种情况下,[[ThisValue]] 字段保存创建 Reference Record 时的 this 值。

本规范使用以下抽象操作来操作 Reference Record:

6.2.5.1 IsPropertyReference ( refRecord )

抽象操作 IsPropertyReference,接收参数 refRecord (Reference 记录);返回值:Boolean。 调用时执行以下步骤:

  1. 如果 refRecord.[[Base]] 是 unresolvable,则返回 false。
  2. 如果 refRecord.[[Base]] 是 Environment Record,则返回 false。
  3. 返回 true。

6.2.5.2 IsUnresolvableReference ( refRecord )

抽象操作 IsUnresolvableReference,接收参数 refRecord (Reference 记录);返回值:Boolean。 调用时执行以下步骤:

  1. 如果 refRecord.[[Base]] 是 unresolvable,则返回 true。
  2. 返回 false。

6.2.5.3 IsSuperReference ( refRecord )

抽象操作 IsSuperReference,接收参数 refRecord (Reference 记录);返回值:Boolean。 调用时执行以下步骤:

  1. 如果 refRecord.[[ThisValue]] 是 empty,则返回 false。
  2. 返回 true。

6.2.5.4 IsPrivateReference ( refRecord )

抽象操作 IsPrivateReference,接收参数 refRecord (Reference 记录);返回值:Boolean。 调用时执行以下步骤:

  1. 如果 refRecord.[[ReferencedName]] 是 Private Name,则返回 true。
  2. 返回 false。

6.2.5.5 GetValue ( refRecord )

抽象操作 GetValue,接收参数 refRecord ((Reference 记录 或 ECMAScript 语言值));返回值:(正常完成 (值:ECMAScript 语言值) 或 突兀完成)。 调用时执行以下步骤:

  1. 如果 refRecord 不是 Reference Record,则返回 refRecord。
  2. 如果 IsUnresolvableReference(refRecord) 是 true,则抛出 ReferenceError 异常。
  3. 如果 IsPropertyReference(refRecord) 是 true,则
    1. 令 baseObj 为 ? ToObject(refRecord.[[Base]])。
    2. 如果 IsPrivateReference(refRecord) 是 true,则
      1. 返回 ? PrivateGet(baseObj, refRecord.[[ReferencedName]])。
    3. 如果 refRecord.[[ReferencedName]] 不是属性键,则
      1. 将 refRecord.[[ReferencedName]] 设置为 ? ToPropertyKey(refRecord.[[ReferencedName]])。
    4. 返回 ? baseObj.[[Get]](refRecord.[[ReferencedName]], GetThisValue(refRecord))。
  4. 令 base 为 refRecord.[[Base]]。
  5. 断言:base 是 Environment Record。
  6. 返回 ? base.GetBindingValue(refRecord.[[ReferencedName]], refRecord.[[Strict]])(参见 9.1)。
注

步骤 3.a 中可能创建的对象无法在上述抽象操作和普通对象 [[Get]] 内部方法之外访问。实现可以选择避免实际创建该对象。

6.2.5.6 PutValue ( refRecord, value )

抽象操作 PutValue,接收参数 refRecord ((Reference 记录 或 ECMAScript 语言值)) 和 value (ECMAScript 语言值);返回值:(正常完成 (值:unused) 或 突兀完成)。 调用时执行以下步骤:

  1. 如果 refRecord 不是 Reference Record,则抛出 ReferenceError 异常。
  2. 如果 IsUnresolvableReference(refRecord) 是 true,则
    1. 如果 refRecord.[[Strict]] 是 true,则抛出 ReferenceError 异常。
    2. 令 globalObj 为 GetGlobalObject()。
    3. 执行 ? Set(globalObj, refRecord.[[ReferencedName]], value, false)。
    4. 返回 unused。
  3. 如果 IsPropertyReference(refRecord) 是 true,则
    1. 令 baseObj 为 ? ToObject(refRecord.[[Base]])。
    2. 如果 IsPrivateReference(refRecord) 是 true,则
      1. 返回 ? PrivateSet(baseObj, refRecord.[[ReferencedName]], value)。
    3. 如果 refRecord.[[ReferencedName]] 不是属性键,则
      1. 将 refRecord.[[ReferencedName]] 设置为 ? ToPropertyKey(refRecord.[[ReferencedName]])。
    4. 令 succeeded 为 ? baseObj.[[Set]](refRecord.[[ReferencedName]], value, GetThisValue(refRecord))。
    5. 如果 succeeded 是 false 且 refRecord.[[Strict]] 是 true,则抛出 TypeError 异常。
    6. 返回 unused。
  4. 令 base 为 refRecord.[[Base]]。
  5. 断言:base 是 Environment Record。
  6. 返回 ? base.SetMutableBinding(refRecord.[[ReferencedName]], value, refRecord.[[Strict]])(参见 9.1)。
注

步骤 3.a 中可能创建的对象无法在上述抽象操作和普通对象 [[Set]] 内部方法之外访问。实现可以选择避免实际创建该对象。

6.2.5.7 GetThisValue ( refRecord )

抽象操作 GetThisValue,接收参数 refRecord (Reference 记录);返回值:ECMAScript 语言值。 调用时执行以下步骤:

  1. 断言:IsPropertyReference(refRecord) 是 true。
  2. 如果 IsSuperReference(refRecord) 是 true,则返回 refRecord.[[ThisValue]]。
  3. 返回 refRecord.[[Base]]。

6.2.5.8 InitializeReferencedBinding ( refRecord, value )

抽象操作 InitializeReferencedBinding,接收参数 refRecord (Reference 记录) 和 value (ECMAScript 语言值);返回值:(正常完成 (值:unused) 或 突兀完成)。 调用时执行以下步骤:

  1. 断言:IsUnresolvableReference(refRecord) 是 false。
  2. 令 base 为 refRecord.[[Base]]。
  3. 断言:base 是 Environment Record。
  4. 返回 ? base.InitializeBinding(refRecord.[[ReferencedName]], value)。

6.2.5.9 MakePrivateReference ( baseValue, privateIdentifier )

抽象操作 MakePrivateReference,接收参数 baseValue (ECMAScript 语言值) 和 privateIdentifier (String);返回值:Reference 记录。 调用时执行以下步骤:

  1. 令 privateEnv 为正在运行的执行上下文的 PrivateEnvironment。
  2. 断言:privateEnv 不是 null。
  3. 令 privateName 为 ResolvePrivateIdentifier(privateEnv, privateIdentifier)。
  4. 返回 Reference Record { [[Base]]: baseValue, [[ReferencedName]]: privateName, [[Strict]]: true, [[ThisValue]]: empty }。

6.2.6 Property Descriptor 规范类型

Property Descriptor 类型用于说明 Object 属性特性的操作和具体化。Property Descriptor 是具有零个或多个字段的 Record,其中每个字段的名称都是特性名称,其值是 6.1.7.1 中规定的相应特性值。本规范中用于标记 Property Descriptor Record 字面量描述的模式名称是“PropertyDescriptor”。

根据某些字段是否存在或被使用,Property Descriptor 值还可以进一步分类为数据 Property Descriptor 和访问器 Property Descriptor。数据 Property Descriptor 是包含名为 [[Value]] 或 [[Writable]] 的任意字段的 Property Descriptor。访问器 Property Descriptor 是包含名为 [[Getter]] 或 [[Setter]] 的任意字段的 Property Descriptor。任何 Property Descriptor 都可以具有名为 [[Enumerable]] 和 [[Configurable]] 的字段。Property Descriptor 值不能同时是数据 Property Descriptor 和访问器 Property Descriptor;不过,它也可以两者都不是(在这种情况下,它是通用 Property Descriptor)。完全填充的 Property Descriptor是访问器 Property Descriptor 或数据 Property Descriptor,并且具有 表 3 中定义的所有相应字段。

本规范使用以下抽象操作来操作 Property Descriptor 值:

6.2.6.1 IsAccessorDescriptor ( propertyDesc )

抽象操作 IsAccessorDescriptor,接收参数 propertyDesc (属性描述符);返回值:Boolean。 调用时执行以下步骤:

  1. 如果 propertyDesc 具有 [[Getter]] 字段,则返回 true。
  2. 如果 propertyDesc 具有 [[Setter]] 字段,则返回 true。
  3. 返回 false。

6.2.6.2 IsDataDescriptor ( propertyDesc )

抽象操作 IsDataDescriptor,接收参数 propertyDesc (属性描述符);返回值:Boolean。 调用时执行以下步骤:

  1. 如果 propertyDesc 具有 [[Value]] 字段,则返回 true。
  2. 如果 propertyDesc 具有 [[Writable]] 字段,则返回 true。
  3. 返回 false。

6.2.6.3 IsGenericDescriptor ( propertyDesc )

抽象操作 IsGenericDescriptor,接收参数 propertyDesc (属性描述符);返回值:Boolean。 调用时执行以下步骤:

  1. 如果 IsAccessorDescriptor(propertyDesc) 是 true,则返回 false。
  2. 如果 IsDataDescriptor(propertyDesc) 是 true,则返回 false。
  3. 返回 true。

6.2.6.4 FromPropertyDescriptor ( propertyDesc )

抽象操作 FromPropertyDescriptor,接收参数 propertyDesc ((属性描述符 或 undefined));返回值:(Object 或 undefined)。 调用时执行以下步骤:

  1. 如果 propertyDesc 是 undefined,则返回 undefined。
  2. 令 obj 为 OrdinaryObjectCreate(%Object.prototype%)。
  3. 断言:obj 是没有自有属性的可扩展普通对象。
  4. 如果 propertyDesc 具有 [[Value]] 字段,则
    1. 执行 ! CreateDataPropertyOrThrow(obj, "value", propertyDesc.[[Value]])。
  5. 如果 propertyDesc 具有 [[Writable]] 字段,则
    1. 执行 ! CreateDataPropertyOrThrow(obj, "writable", propertyDesc.[[Writable]])。
  6. 如果 propertyDesc 具有 [[Getter]] 字段,则
    1. 执行 ! CreateDataPropertyOrThrow(obj, "get", propertyDesc.[[Getter]])。
  7. 如果 propertyDesc 具有 [[Setter]] 字段,则
    1. 执行 ! CreateDataPropertyOrThrow(obj, "set", propertyDesc.[[Setter]])。
  8. 如果 propertyDesc 具有 [[Enumerable]] 字段,则
    1. 执行 ! CreateDataPropertyOrThrow(obj, "enumerable", propertyDesc.[[Enumerable]])。
  9. 如果 propertyDesc 具有 [[Configurable]] 字段,则
    1. 执行 ! CreateDataPropertyOrThrow(obj, "configurable", propertyDesc.[[Configurable]])。
  10. 返回 obj。

6.2.6.5 ToPropertyDescriptor ( obj )

抽象操作 ToPropertyDescriptor,接收参数 obj (ECMAScript 语言值);返回值:(正常完成 (值:属性描述符) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 obj 不是 Object,则抛出 TypeError 异常。
  2. 令 propertyDesc 为一个最初不具有任何字段的新 Property Descriptor。
  3. 令 hasEnumerable 为 ? HasProperty(obj, "enumerable")。
  4. 如果 hasEnumerable 是 true,则
    1. 令 enumerable 为 ToBoolean(? Get(obj, "enumerable")).
    2. 将 propertyDesc.[[Enumerable]] 设置为 enumerable。
  5. 令 hasConfigurable 为 ? HasProperty(obj, "configurable")。
  6. 如果 hasConfigurable 是 true,则
    1. 令 configurable 为 ToBoolean(? Get(obj, "configurable")).
    2. 将 propertyDesc.[[Configurable]] 设置为 configurable。
  7. 令 hasValue 为 ? HasProperty(obj, "value")。
  8. 如果 hasValue 是 true,则
    1. 令 value 为 ? Get(obj, "value")。
    2. 将 propertyDesc.[[Value]] 设置为 value。
  9. 令 hasWritable 为 ? HasProperty(obj, "writable")。
  10. 如果 hasWritable 是 true,则
    1. 令 writable 为 ToBoolean(? Get(obj, "writable")).
    2. 将 propertyDesc.[[Writable]] 设置为 writable。
  11. 令 hasGet 为 ? HasProperty(obj, "get")。
  12. 如果 hasGet 是 true,则
    1. 令 getter 为 ? Get(obj, "get")。
    2. 如果 IsCallable(getter) 是 false 且 getter 不是 undefined,则抛出 TypeError 异常。
    3. 将 propertyDesc.[[Getter]] 设置为 getter。
  13. 令 hasSet 为 ? HasProperty(obj, "set")。
  14. 如果 hasSet 是 true,则
    1. 令 setter 为 ? Get(obj, "set")。
    2. 如果 IsCallable(setter) 是 false 且 setter 不是 undefined,则抛出 TypeError 异常。
    3. 将 propertyDesc.[[Setter]] 设置为 setter。
  15. 如果 propertyDesc 具有 [[Getter]] 字段或 propertyDesc 具有 [[Setter]] 字段,则
    1. 如果 propertyDesc 具有 [[Value]] 字段或 propertyDesc 具有 [[Writable]] 字段,则抛出 TypeError 异常。
  16. 返回 propertyDesc。

6.2.6.6 CompletePropertyDescriptor ( propertyDesc )

抽象操作 CompletePropertyDescriptor,接收参数 propertyDesc (属性描述符);返回值:unused。 调用时执行以下步骤:

  1. 令 like 为 Record { [[Value]]: undefined, [[Writable]]: false, [[Getter]]: undefined, [[Setter]]: undefined, [[Enumerable]]: false, [[Configurable]]: false }。
  2. 如果 IsGenericDescriptor(propertyDesc) 是 true 或 IsDataDescriptor(propertyDesc) 是 true,则
    1. 如果 propertyDesc 没有 [[Value]] 字段,则将 propertyDesc.[[Value]] 设置为 like.[[Value]]。
    2. 如果 propertyDesc 没有 [[Writable]] 字段,则将 propertyDesc.[[Writable]] 设置为 like.[[Writable]]。
  3. 否则,
    1. 如果 propertyDesc 没有 [[Getter]] 字段,则将 propertyDesc.[[Getter]] 设置为 like.[[Getter]]。
    2. 如果 propertyDesc 没有 [[Setter]] 字段,则将 propertyDesc.[[Setter]] 设置为 like.[[Setter]]。
  4. 如果 propertyDesc 没有 [[Enumerable]] 字段,则将 propertyDesc.[[Enumerable]] 设置为 like.[[Enumerable]]。
  5. 如果 propertyDesc 没有 [[Configurable]] 字段,则将 propertyDesc.[[Configurable]] 设置为 like.[[Configurable]]。
  6. 返回 unused。

6.2.7 Environment Record 规范类型

Environment Record 类型用于说明嵌套函数和块中的名称解析行为。该类型及其操作定义于 9.1。

6.2.8 Abstract Closure 规范类型

Abstract Closure 规范类型用于引用算法步骤以及一组值。Abstract Closure 是元值,并使用函数应用形式调用,例如 closure(arg1, arg2)。与抽象操作一样,调用会执行 Abstract Closure 所描述的算法步骤。

在创建 Abstract Closure 的算法步骤中,使用动词“捕获”后跟别名列表来捕获值。创建 Abstract Closure 时,它会捕获当时与每个别名关联的值。在规定调用 Abstract Closure 时所执行算法的步骤中,每个捕获值都使用捕获该值时所用的别名引用。

如果 Abstract Closure 返回 Completion Record,则该 Completion Record 必须是正常完成或抛出完成。

Abstract Closure 作为其他算法的一部分内联创建,如以下示例所示。

  1. 令 addend 为 41。
  2. 令 closure 为一个新的 Abstract Closure,它具有参数 (x),捕获 addend,并在被调用时执行以下步骤:
    1. 返回 x + addend。
  3. 令 value 为 closure(1)。
  4. 断言:value 是 42。

6.2.9 数据块

Data Block 规范类型用于描述由字节大小(8 位)的数值组成的独立且可变序列。字节值是从 0 到 255 的闭区间中的整数。创建 Data Block 值时会指定固定数量的字节,每个字节的初始值均为 0。

为了便于本规范中的表示,可以使用类似数组的语法访问 Data Block 值的各个字节。此表示法将 Data Block 值表示为从 0 开始的整数索引字节序列。例如,如果 dataBlock 是一个 5 字节的 Data Block 值,则可以使用 dataBlock[2] 访问其第 3个字节。

位于可由多个代理同时引用的内存中的数据块称为 Shared Data Block。Shared Data Block 具有一个与地址无关的标识(用于 Shared Data Block 值的相等性测试):它不绑定到该块在任何进程中映射到的虚拟地址,而是绑定到该块所表示的内存位置集合。两个数据块仅当其包含的位置集合相等时才相等;否则它们不相等,并且其包含的位置集合的交集为空。最后,可以将 Shared Data Block 与 Data Block 区分开来。

Shared Data Block 的语义由内存模型使用 Shared Data Block 事件定义。下面的抽象操作引入 Shared Data Block 事件,并充当求值语义与内存模型事件语义之间的接口。这些事件构成一个候选执行,内存模型在其上充当过滤器。完整语义请参阅内存模型。

Shared Data Block 事件由内存模型中定义的 Record 建模。

本规范使用以下抽象操作来操作 Data Block 值:

6.2.9.1 CreateByteDataBlock ( size )

抽象操作 CreateByteDataBlock,接收参数 size (非负整数);返回值:(正常完成 (值:数据块) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 size > 253 - 1,则抛出 RangeError 异常。
  2. 令 dataBlock 为一个由 size 个字节组成的新 Data Block 值。如果无法创建这样的 Data Block,则抛出 RangeError 异常。
  3. 将 dataBlock 的所有字节设置为 0。
  4. 返回 dataBlock。

6.2.9.2 CreateSharedByteDataBlock ( size )

抽象操作 CreateSharedByteDataBlock,接收参数 size (非负整数);返回值:(正常完成 (值:共享数据块) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 dataBlock 为一个由 size 个字节组成的新 Shared Data Block 值。如果无法创建这样的 Shared Data Block,则抛出 RangeError 异常。
  2. 令 agentRecord 为周围代理的 Agent Record。
  3. 令 execution 为 agentRecord.[[CandidateExecution]]。
  4. 令 eventsRecord 为 execution.[[EventsRecords]] 中 [[AgentSignifier]] 为 AgentSignifier() 的 Agent Events Record。
  5. 令 zero 为 « 0 »。
  6. 对 dataBlock 的每个索引 index,执行
    1. 将 WriteSharedMemory { [[Order]]: init, [[NoTear]]: true, [[Block]]: dataBlock, [[ByteIndex]]: index, [[ElementSize]]: 1, [[Payload]]: zero } 追加到 eventsRecord.[[EventList]]。
  7. 返回 dataBlock。

6.2.9.3 CopyDataBlockBytes ( toBlock, toIndex, fromBlock, fromIndex, count )

抽象操作 CopyDataBlockBytes,接收参数 toBlock ((数据块 或 共享数据块))、toIndex (非负整数)、fromBlock ((数据块 或 共享数据块))、fromIndex (非负整数) 和 count (非负整数);返回值:unused。 调用时执行以下步骤:

  1. 断言:fromBlock 和 toBlock 是不同的值。
  2. 令 fromSize 为 fromBlock 中的字节数。
  3. 断言:fromIndex + count ≤ fromSize。
  4. 令 toSize 为 toBlock 中的字节数。
  5. 断言:toIndex + count ≤ toSize。
  6. 当 count > 0 时,重复执行
    1. 如果 fromBlock 是 Shared Data Block,则
      1. 令 agentRecord 为周围代理的 Agent Record。
      2. 令 execution 为 agentRecord.[[CandidateExecution]]。
      3. 令 eventsRecord 为 execution.[[EventsRecords]] 中 [[AgentSignifier]] 为 AgentSignifier() 的 Agent Events Record。
      4. 令 bytes 为一个 List,其唯一元素是非确定性选择的字节值。
      5. 注:在实现中,bytes 是底层硬件上的非原子读取指令的结果。这种非确定性是内存模型的语义规定,用于描述弱一致性硬件的可观察行为。
      6. 令 readEvent 为 ReadSharedMemory { [[Order]]: unordered, [[NoTear]]: true, [[Block]]: fromBlock, [[ByteIndex]]: fromIndex, [[ElementSize]]: 1 }。
      7. 将 readEvent 追加到 eventsRecord.[[EventList]]。
      8. 将 Chosen Value Record { [[Event]]: readEvent, [[ChosenValue]]: bytes } 追加到 execution.[[ChosenValues]]。
      9. 如果 toBlock 是 Shared Data Block,则
        1. 将 WriteSharedMemory { [[Order]]: unordered, [[NoTear]]: true, [[Block]]: toBlock, [[ByteIndex]]: toIndex, [[ElementSize]]: 1, [[Payload]]: bytes } 追加到 eventsRecord.[[EventList]]。
      10. 否则,
        1. 将 toBlock[toIndex] 设置为 bytes[0]。
    2. 否则,
      1. 断言:toBlock 不是 Shared Data Block。
      2. 将 toBlock[toIndex] 设置为 fromBlock[fromIndex]。
    3. 将 toIndex 设置为 toIndex + 1。
    4. 将 fromIndex 设置为 fromIndex + 1。
    5. 将 count 设置为 count - 1。
  7. 返回 unused。

6.2.10 PrivateElement 规范类型

PrivateElement 类型是一种 Record,用于规范私有类字段、方法和访问器。尽管私有元素不与 Property Descriptor 关联,也不是属性,但引用它们的表达式的运行时语义在某些方面与不可配置属性的运行时语义相似(私有字段类似于可写数据属性,私有方法类似于不可写数据属性,私有访问器类似于访问器属性),相应的 Record 字段也用于类似的目的。

PrivateElement 类型的值是其字段由 表 9 定义的 Record。此类值称为 PrivateElement 记录。

表 9: PrivateElement 字段
字段名称 存在该字段的 [[Kind]] 字段值 值 含义
[[Key]] 全部 Private Name 字段、方法或访问器的名称。
[[Kind]] 全部 field、method 或 accessor 元素的种类。
[[Value]] field 和 method ECMAScript 语言值 字段的值。
[[Getter]] accessor 函数对象或 undefined 私有访问器的 getter。
[[Setter]] accessor 函数对象或 undefined 私有访问器的 setter。

6.2.11 ClassFieldDefinition Record 规范类型

ClassFieldDefinition 类型是用于规定类字段的 Record。

ClassFieldDefinition 类型的值是其字段由 表 10 定义的 Record。此类值称为 ClassFieldDefinition 记录。

表 10: ClassFieldDefinition Record 字段
字段名称 值 含义
[[Name]] Private Name、String 或 Symbol 字段的名称。
[[Initializer]] ECMAScript 函数对象或 empty 字段的初始化器(如果有)。

6.2.12 Private Name

Private Name 规范类型用于描述全局唯一的值(即使两个 Private Name 在其他方面无法区分,它们也彼此不同),该值表示私有类元素(字段、方法或访问器)的键。每个 Private Name 都有一个不可变的 [[Description]] 内部槽,其值为 String。可以使用 PrivateFieldAdd 或 PrivateMethodOrAccessorAdd 将 Private Name 安装到任何 ECMAScript 对象上,然后使用 PrivateGet 和 PrivateSet 读取或写入。

6.2.13 ClassStaticBlockDefinition Record 规范类型

ClassStaticBlockDefinition Record 是用于封装类静态初始化块可执行代码的 Record。

ClassStaticBlockDefinition Record 具有 表 11 中列出的字段。

表 11: ClassStaticBlockDefinition Record 字段
字段名称 值 含义
[[BodyFunction]] ECMAScript 函数对象 在类的静态初始化期间调用的函数对象。

7 抽象操作

这些操作不是 ECMAScript 语言的一部分;它们在此定义,仅用于帮助规定 ECMAScript 语言的语义。其他更专门的抽象操作在本规范各处定义。

7.1 类型转换

ECMAScript 语言会根据需要隐式执行自动类型转换。为了阐明某些构造的语义,定义一组转换抽象操作很有用。转换抽象操作是多态的;它们可以接受任何 ECMAScript 语言类型的值。但这些操作不使用任何其他规范类型。

BigInt 类型在 ECMAScript 语言中没有隐式转换;程序员必须显式调用 BigInt 才能将其他类型的值转换为 BigInt。

7.1.1 ToPrimitive ( input [ , preferredType ] )

抽象操作 ToPrimitive,接收参数 input (ECMAScript 语言值)和可选参数 preferredType ((string 或 number));返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。 它将其 input 参数转换为非 Object 类型。如果一个对象能够转换为多种原始类型,则可以使用可选提示 preferredType 来优先选择该类型。 调用时执行以下步骤:

  1. 如果 input 是 Object,则
    1. 令 exoticToPrimitive 为 ? GetMethod(input, %Symbol.toPrimitive%)。
    2. 如果 exoticToPrimitive 不是 undefined,则
      1. 如果不存在 preferredType,则
        1. 令 hint 为 "default"。
      2. 否则如果 preferredType 是 string,则
        1. 令 hint 为 "string"。
      3. 否则,
        1. 断言:preferredType 是 number。
        2. 令 hint 为 "number"。
      4. 令 result 为 ? Call(exoticToPrimitive, input, « hint »)。
      5. 如果 result 不是 Object,则返回 result。
      6. 抛出 TypeError 异常。
    3. 如果不存在 preferredType,则将 preferredType 设置为 number。
    4. 返回 ? OrdinaryToPrimitive(input, preferredType)。
  2. 返回 input。
注

当调用 ToPrimitive 时没有提供提示,它通常表现得如同提示为 number。但是,对象可以通过定义 %Symbol.toPrimitive% 方法来覆盖此行为。在本规范定义的对象中,只有 Date(参见 21.4.4.45)和 Symbol 对象(参见 20.4.3.5)会覆盖默认的 ToPrimitive 行为。Date 将缺少提示的情况视为提示为 string。

7.1.1.1 OrdinaryToPrimitive ( obj, hint )

抽象操作 OrdinaryToPrimitive,接收参数 obj (Object) 和 hint ((string 或 number));返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 hint 是 string,则
    1. 令 methodNames 为 « "toString", "valueOf" »。
  2. 否则,
    1. 令 methodNames 为 « "valueOf", "toString" »。
  3. 对 methodNames 的每个元素 name,执行
    1. 令 method 为 ? Get(obj, name)。
    2. 如果 IsCallable(method) 是 true,则
      1. 令 result 为 ? Call(method, obj)。
      2. 如果 result 不是 Object,则返回 result。
  4. 抛出 TypeError 异常。

7.1.2 ToBoolean ( arg )

抽象操作 ToBoolean,接收参数 arg (ECMAScript 语言值);返回值:Boolean。 它将 arg 转换为 Boolean 类型的值。 调用时执行以下步骤:

  1. 如果 arg 是 Boolean,则返回 arg。
  2. 如果 arg 是 undefined、null、+0𝔽、-0𝔽、NaN、0ℤ 或空 String 之一,则返回 false。
  3. Normative Optional
    如果宿主是 Web 浏览器或以其他方式支持 [[IsHTMLDDA]] 内部槽,则
    1. 如果 arg 是 Object 且 arg 具有 [[IsHTMLDDA]] 内部槽,则返回 false。
  4. 返回 true。

7.1.3 ToNumeric ( arg )

抽象操作 ToNumeric,接收参数 arg (ECMAScript 语言值);返回值:(正常完成 (值:(Number 或 BigInt)) 或 抛出完成)。 它返回转换为 Number 或 BigInt 后的 arg。 调用时执行以下步骤:

  1. 令 primitiveValue 为 ? ToPrimitive(arg, number)。
  2. 如果 primitiveValue 是 BigInt,则返回 primitiveValue。
  3. 返回 ? ToNumber(primitiveValue)。

7.1.4 ToNumber ( arg )

抽象操作 ToNumber,接收参数 arg (ECMAScript 语言值);返回值:(正常完成 (值:Number) 或 抛出完成)。 它将 arg 转换为 Number 类型的值。 调用时执行以下步骤:

  1. 如果 arg 是 Number,则返回 arg。
  2. 如果 arg 是 Symbol 或 BigInt,则抛出 TypeError 异常。
  3. 如果 arg 是 undefined,则返回 NaN。
  4. 如果 arg 是 null 或 false,则返回 +0𝔽。
  5. 如果 arg 是 true,则返回 1𝔽。
  6. 如果 arg 是 String,则返回 StringToNumber(arg)。
  7. 断言:arg 是 Object。
  8. 令 primitiveValue 为 ? ToPrimitive(arg, number)。
  9. 断言:primitiveValue 不是 Object。
  10. 返回 ? ToNumber(primitiveValue)。

7.1.4.1 应用于 String 类型的 ToNumber

抽象操作 StringToNumber 使用以下文法规定如何将 String 值转换为 Number 值。

语法

StringNumericLiteral ::: StrWhiteSpaceopt StrWhiteSpaceopt StrNumericLiteral StrWhiteSpaceopt StrWhiteSpace ::: StrWhiteSpaceChar StrWhiteSpaceopt StrWhiteSpaceChar ::: WhiteSpace LineTerminator StrNumericLiteral ::: StrDecimalLiteral NonDecimalIntegerLiteral[~Sep] StrDecimalLiteral ::: StrUnsignedDecimalLiteral + StrUnsignedDecimalLiteral - StrUnsignedDecimalLiteral StrUnsignedDecimalLiteral ::: Infinity DecimalDigits[~Sep] . DecimalDigits[~Sep]opt ExponentPart[~Sep]opt . DecimalDigits[~Sep] ExponentPart[~Sep]opt DecimalDigits[~Sep] ExponentPart[~Sep]opt

以上未显式定义的所有文法符号,都采用数值字面量词法文法(12.9.3)中使用的定义

注

应注意 StringNumericLiteral 与 NumericLiteral 的语法之间存在一些差异:

7.1.4.1.1 StringToNumber ( string )

抽象操作 StringToNumber,接收参数 string (String);返回值:Number。 调用时执行以下步骤:

  1. 令 literal 为 ParseText(string, StringNumericLiteral)。
  2. 如果 literal 是错误的 List,则返回 NaN。
  3. 返回 literal 的 StringNumericValue。

7.1.4.1.2 Runtime Semantics: StringNumericValue

语法制导操作 StringNumericValue,接收无参数;返回值:Number。

注

将 StringNumericLiteral 转换为 Number 值,在整体上类似于确定 NumericLiteral 的 NumericValue(参见 12.9.3),但某些细节有所不同。

它按以下产生式分别定义:

StringNumericLiteral ::: StrWhiteSpaceopt
  1. 返回 +0𝔽。
StringNumericLiteral ::: StrWhiteSpaceopt StrNumericLiteral StrWhiteSpaceopt
  1. 返回 StrNumericLiteral 的 StringNumericValue。
StrNumericLiteral ::: NonDecimalIntegerLiteral
  1. 返回 𝔽(NonDecimalIntegerLiteral 的 MV)。
StrDecimalLiteral ::: - StrUnsignedDecimalLiteral
  1. 令 a 为 StrUnsignedDecimalLiteral 的 StringNumericValue。
  2. 如果 a 是 +0𝔽,则返回 -0𝔽。
  3. 返回 -a。
StrUnsignedDecimalLiteral ::: Infinity
  1. 返回 +∞𝔽。
StrUnsignedDecimalLiteral ::: DecimalDigits . DecimalDigitsopt ExponentPartopt
  1. 令 a 为第一个 DecimalDigits 的 MV。
  2. 如果存在第二个 DecimalDigits,则
    1. 令 b 为第二个 DecimalDigits 的 MV。
    2. 令 n 为第二个 DecimalDigits 中的码点数。
  3. 否则,
    1. 令 b 为 0。
    2. 令 n 为 0。
  4. 如果存在 ExponentPart,则令 e 为 ExponentPart 的 MV;否则令 e 为 0。
  5. 返回 RoundMVResult((a + (b × 10-n)) × 10e)。
StrUnsignedDecimalLiteral ::: . DecimalDigits ExponentPartopt
  1. 令 b 为 DecimalDigits 的 MV。
  2. 如果存在 ExponentPart,则令 e 为 ExponentPart 的 MV;否则令 e 为 0。
  3. 令 n 为 DecimalDigits 中的码点数。
  4. 返回 RoundMVResult(b × 10e - n)。
StrUnsignedDecimalLiteral ::: DecimalDigits ExponentPartopt
  1. 令 a 为 DecimalDigits 的 MV。
  2. 如果存在 ExponentPart,则令 e 为 ExponentPart 的 MV;否则令 e 为 0。
  3. 返回 RoundMVResult(a × 10e)。

7.1.4.1.3 RoundMVResult ( n )

抽象操作 RoundMVResult,接收参数 n (数学值);返回值:Number。 它以实现定义的方式将 n 转换为 Number。对于此抽象操作,如果一个数字不为零,或者其左侧存在非零数字且其右侧也存在非零数字,则该数字是有效数字。对于此抽象操作,一个数学值表示形式“所表示的数学值”是一个数学值“十进制表示”的逆操作。 调用时执行以下步骤:

  1. 如果 n 的十进制表示具有 20 个或更少的有效数字,则返回 𝔽(n)。
  2. 令 option1 为这样一个结果所表示的数学值:将 n 的十进制表示中第 20 个之后的每个有效数字替换为数字 0。
  3. 令 option2 为这样一个结果所表示的数学值:将 n 的十进制表示中第 20 个之后的每个有效数字替换为数字 0,然后在第 20 位将其递增(必要时进行进位)。
  4. 令 chosen 为实现定义地从 option1 或 option2 中选择的一个值。
  5. 返回 𝔽(chosen)。

7.1.5 ToIntegerOrInfinity ( arg )

抽象操作 ToIntegerOrInfinity,接收参数 arg (ECMAScript 语言值);返回值:(正常完成 (值:(整数、+∞ 或 -∞)) 或 抛出完成)。 它将 arg 转换为表示其 Number 值、且小数部分被截断的整数;如果该 Number 值为无穷,则转换为 +∞ 或 -∞。 调用时执行以下步骤:

  1. 令 number 为 ? ToNumber(arg)。
  2. 如果 number 是 NaN、+0𝔽 或 -0𝔽 之一,则返回 0。
  3. 如果 number 是 +∞𝔽,则返回 +∞。
  4. 如果 number 是 -∞𝔽,则返回 -∞。
  5. 返回 truncate(ℝ(number))。
注
对于 x 的任何值,𝔽(ToIntegerOrInfinity(x)) 都不会返回 -0𝔽。小数部分的截断是在将 x 转换为数学值之后执行的。

7.1.6 SnapToInteger ( arg, nonIntHandling [ , minimum [ , maximum ] ] )

抽象操作 SnapToInteger,接收参数 arg (ECMAScript 语言值) 和 nonIntHandling ((reject 或 truncate))和可选参数 minimum (整数) 和 maximum (整数);返回值:(正常完成 (值:整数) 或 抛出完成)。 它将 arg 转换为表示其 Number 值的整数;拒绝非有限值,并通过拒绝或截断来处理有限的非整数值,还可以选择施加包含端点的约束边界。 调用时执行以下步骤:

  1. 令 number 为 ? ToNumber(arg)。
  2. 如果 number 是 NaN、+∞𝔽 或 -∞𝔽 之一,则抛出 RangeError 异常。
  3. 令 mv 为 ℝ(number)。
  4. 如果 nonIntHandling 是 truncate,则将 mv 设置为 truncate(mv)。
  5. 如果 mv 不是整数,则抛出 RangeError 异常。
  6. 如果存在 minimum 且 mv < minimum,则抛出 RangeError 异常。
  7. 如果存在 maximum 且 mv > maximum,则抛出 RangeError 异常。
  8. 返回 mv。

7.1.7 ToFixedSizeInteger ( int, signed, bitWidth )

抽象操作 ToFixedSizeInteger,接收参数 int ((整数、+∞ 或 -∞))、signed ((unsigned 或 signed)) 和 bitWidth (正整数);返回值:整数。 它将 int 映射到 2bitWidth 个整数之一:如果 signed 为 unsigned,范围是从 0 到 2bitWidth - 1 的闭区间;如果 signed 为 signed,范围是从 -2bitWidth - 1 到 2bitWidth - 1 - 1。 调用时执行以下步骤:

  1. 如果 int = +∞ 或 int = -∞,则返回 0。
  2. 令 fixedInt 为 int modulo 2bitWidth。
  3. 注:以下步骤不会改变 fixedInt 的二进制补码表示。
  4. 如果 signed 是 signed 且 fixedInt ≥ 2bitWidth - 1,则将 fixedInt 设置为 fixedInt - 2bitWidth。
  5. 返回 fixedInt。
注

ToFixedSizeInteger 是幂等的:对于任何 ECMAScript 语言值 x,ToFixedSizeInteger(ToFixedSizeInteger(x, signed, bitWidth), signed, bitWidth) 与 ToFixedSizeInteger(x, signed, bitWidth) 相同。实际上,因为 +∞ 和 -∞ 都映射为 0,即使反转 signed,此不变量仍然成立(例如,ToFixedSizeInteger(ToFixedSizeInteger(x, signed, 32), unsigned, 32) 与 ToFixedSizeInteger(x, unsigned, 32) 相同)。

7.1.8 ToInt32 ( arg )

抽象操作 ToInt32,接收参数 arg (ECMAScript 语言值);返回值:(正常完成 (值:整数 Number) 或 抛出完成)。 它将 arg 转换为从 𝔽(-231) 到 𝔽(231 - 1) 的闭区间中的 232 个整数 Number 值之一,不包括 -0𝔽。 调用时执行以下步骤:

  1. 令 int 为 ? ToIntegerOrInfinity(arg)。
  2. 返回 𝔽(ToFixedSizeInteger(int, signed, 32))。

7.1.9 ToUint32 ( arg )

抽象操作 ToUint32,接收参数 arg (ECMAScript 语言值);返回值:(正常完成 (值:整数 Number) 或 抛出完成)。 它将 arg 转换为从 +0𝔽 到 𝔽(232 - 1) 的闭区间中的 232 个整数 Number 值之一。 调用时执行以下步骤:

  1. 令 int 为 ? ToIntegerOrInfinity(arg)。
  2. 返回 𝔽(ToFixedSizeInteger(int, unsigned, 32))。

7.1.10 ToInt16 ( arg )

抽象操作 ToInt16,接收参数 arg (ECMAScript 语言值);返回值:(正常完成 (值:整数 Number) 或 抛出完成)。 它将 arg 转换为从 𝔽(-215) 到 𝔽(215 - 1) 的闭区间中的 216 个整数 Number 值之一,不包括 -0𝔽。 调用时执行以下步骤:

  1. 令 int 为 ? ToIntegerOrInfinity(arg)。
  2. 返回 𝔽(ToFixedSizeInteger(int, signed, 16))。

7.1.11 ToUint16 ( arg )

抽象操作 ToUint16,接收参数 arg (ECMAScript 语言值);返回值:(正常完成 (值:整数 Number) 或 抛出完成)。 它将 arg 转换为从 +0𝔽 到 𝔽(216 - 1) 的闭区间中的 216 个整数 Number 值之一。 调用时执行以下步骤:

  1. 令 int 为 ? ToIntegerOrInfinity(arg)。
  2. 返回 𝔽(ToFixedSizeInteger(int, unsigned, 16))。

7.1.12 ToInt8 ( arg )

抽象操作 ToInt8,接收参数 arg (ECMAScript 语言值);返回值:(正常完成 (值:整数 Number) 或 抛出完成)。 它将 arg 转换为从 -128𝔽 到 127𝔽 的闭区间中的 28 个整数 Number 值之一,不包括 -0𝔽。 调用时执行以下步骤:

  1. 令 int 为 ? ToIntegerOrInfinity(arg)。
  2. 返回 𝔽(ToFixedSizeInteger(int, signed, 8))。

7.1.13 ToUint8 ( arg )

抽象操作 ToUint8,接收参数 arg (ECMAScript 语言值);返回值:(正常完成 (值:整数 Number) 或 抛出完成)。 它将 arg 转换为从 +0𝔽 到 255𝔽 的闭区间中的 28 个整数 Number 值之一。 调用时执行以下步骤:

  1. 令 int 为 ? ToIntegerOrInfinity(arg)。
  2. 返回 𝔽(ToFixedSizeInteger(int, unsigned, 8))。

7.1.14 ToUint8Clamp ( arg )

抽象操作 ToUint8Clamp,接收参数 arg (ECMAScript 语言值);返回值:(正常完成 (值:整数 Number) 或 抛出完成)。 它将 arg 钳制并舍入为从 +0𝔽 到 255𝔽 的闭区间中的 28 个整数 Number 值之一。 调用时执行以下步骤:

  1. 令 number 为 ? ToNumber(arg)。
  2. 如果 number 是 NaN,则返回 +0𝔽。
  3. 令 mv 为 number 的扩展数学值。
  4. 令 clamped 为将 mv 钳制在 0 和 255 之间的结果。
  5. 令 f 为 floor(clamped)。
  6. 如果 clamped < f + 0.5,则返回 𝔽(f)。
  7. 如果 clamped > f + 0.5,则返回 𝔽(f + 1)。
  8. 如果 f 是偶数,则返回 𝔽(f)。
  9. 返回 𝔽(f + 1)。
注

与大多数其他 ECMAScript 整数转换操作不同,ToUint8Clamp 对非整数值进行舍入,而不是截断。它还使用“舍入到最接近值,恰好一半时舍入到偶数”的平局处理方式,这与 Math.round 使用的“恰好一半时向上舍入”不同。

7.1.15 ToBigInt ( arg )

抽象操作 ToBigInt,接收参数 arg (ECMAScript 语言值);返回值:(正常完成 (值:BigInt) 或 抛出完成)。 它将 arg 转换为 BigInt 值;如果需要从 Number 进行隐式转换,则抛出异常。 调用时执行以下步骤:

  1. 令 primitive 为 ? ToPrimitive(arg, number)。
  2. 返回 表 12 中与 primitive 对应的值。
表 12: BigInt 转换
参数类型 结果
Undefined 抛出 TypeError 异常。
Null 抛出 TypeError 异常。
Boolean 如果 primitive 是 true,则返回 1n;如果 primitive 是 false,则返回 0n。
BigInt 返回 primitive。
Number 抛出 TypeError 异常。
String
  1. 令 n 为 StringToBigInt(primitive)。
  2. 如果 n 是 undefined,则抛出 SyntaxError 异常。
  3. 返回 n。
Symbol 抛出 TypeError 异常。

7.1.16 StringToBigInt ( string )

抽象操作 StringToBigInt,接收参数 string (String);返回值:(BigInt 或 undefined)。 调用时执行以下步骤:

  1. 令 literal 为 ParseText(string, StringIntegerLiteral)。
  2. 如果 literal 是错误的 List,则返回 undefined。
  3. 令 mv 为 literal 的 MV。
  4. 断言:mv 是整数。
  5. 返回 ℤ(mv)。

7.1.16.1 StringIntegerLiteral 文法

StringToBigInt 使用以下文法。

语法

StringIntegerLiteral ::: StrWhiteSpaceopt StrWhiteSpaceopt StrIntegerLiteral StrWhiteSpaceopt StrIntegerLiteral ::: SignedInteger[~Sep] NonDecimalIntegerLiteral[~Sep]

7.1.16.2 Runtime Semantics: MV

7.1.17 ToBigInt64 ( arg )

抽象操作 ToBigInt64,接收参数 arg (ECMAScript 语言值);返回值:(正常完成 (值:BigInt) 或 抛出完成)。 它将 arg 转换为从 ℤ(-263) 到 ℤ(263 - 1) 的闭区间中的 264 个 BigInt 值之一。 调用时执行以下步骤:

  1. 令 int 为 ℝ(? ToBigInt(arg))。
  2. 返回 ℤ(ToFixedSizeInteger(int, signed, 64))。

7.1.18 ToBigUint64 ( arg )

抽象操作 ToBigUint64,接收参数 arg (ECMAScript 语言值);返回值:(正常完成 (值:BigInt) 或 抛出完成)。 它将 arg 转换为从 0ℤ 到 ℤ(264 - 1) 的闭区间中的 264 个 BigInt 值之一。 调用时执行以下步骤:

  1. 令 int 为 ℝ(? ToBigInt(arg))。
  2. 返回 ℤ(ToFixedSizeInteger(int, unsigned, 64))。

7.1.19 ToString ( arg )

抽象操作 ToString,接收参数 arg (ECMAScript 语言值);返回值:(正常完成 (值:String) 或 抛出完成)。 它将 arg 转换为 String 类型的值。 调用时执行以下步骤:

  1. 如果 arg 是 String,则返回 arg。
  2. 如果 arg 是 Symbol,则抛出 TypeError 异常。
  3. 如果 arg 是 undefined,则返回 "undefined"。
  4. 如果 arg 是 null,则返回 "null"。
  5. 如果 arg 是 true,则返回 "true"。
  6. 如果 arg 是 false,则返回 "false"。
  7. 如果 arg 是 Number,则返回 Number::toString(arg, 10)。
  8. 如果 arg 是 BigInt,则返回 BigInt::toString(arg, 10)。
  9. 断言:arg 是 Object。
  10. 令 primitiveValue 为 ? ToPrimitive(arg, string)。
  11. 断言:primitiveValue 不是 Object。
  12. 返回 ? ToString(primitiveValue)。

7.1.20 ToObject ( arg )

抽象操作 ToObject,接收参数 arg (ECMAScript 语言值);返回值:(正常完成 (值:Object) 或 抛出完成)。 它将 arg 转换为 Object 类型的值。 调用时执行以下步骤:

  1. 如果 arg 是 undefined 或 null,则抛出 TypeError 异常。
  2. 如果 arg 是 Boolean,则返回一个新的 Boolean 对象,其 [[BooleanData]] 内部槽设置为 arg。有关 Boolean 对象的描述,请参见 20.3。
  3. 如果 arg 是 Number,则返回一个新的 Number 对象,其 [[NumberData]] 内部槽设置为 arg。有关 Number 对象的描述,请参见 21.1。
  4. 如果 arg 是 String,则返回一个新的 String 对象,其 [[StringData]] 内部槽设置为 arg。有关 String 对象的描述,请参见 22.1。
  5. 如果 arg 是 Symbol,则返回一个新的 Symbol 对象,其 [[SymbolData]] 内部槽设置为 arg。有关 Symbol 对象的描述,请参见 20.4。
  6. 如果 arg 是 BigInt,则返回一个新的 BigInt 对象,其 [[BigIntData]] 内部槽设置为 arg。有关 BigInt 对象的描述,请参见 21.2。
  7. 断言:arg 是 Object。
  8. 返回 arg。

7.1.21 ToPropertyKey ( arg )

抽象操作 ToPropertyKey,接收参数 arg (ECMAScript 语言值);返回值:(正常完成 (值:属性键) 或 抛出完成)。 它将 arg 转换为可用作属性键的值。 调用时执行以下步骤:

  1. 令 key 为 ? ToPrimitive(arg, string)。
  2. 如果 key 是 Symbol,则
    1. 返回 key。
  3. 返回 ! ToString(key)。

7.1.22 ToLength ( arg )

抽象操作 ToLength,接收参数 arg (ECMAScript 语言值);返回值:(正常完成 (值:非负整数 Number) 或 抛出完成)。 它将 arg 钳制并截断为适合用作类数组对象长度的非负整数 Number。 调用时执行以下步骤:

  1. 令 length 为 ? ToIntegerOrInfinity(arg)。
  2. 令 clampedLength 为将 length 钳制在 0 和 253 - 1 之间的结果。
  3. 返回 𝔽(clampedLength)。

7.1.23 CanonicalNumericIndexString ( arg )

抽象操作 CanonicalNumericIndexString,接收参数 arg (String);返回值:(Number 或 undefined)。 如果 arg 是 "-0",或者与某个 Number 值 n 的 ToString(n) 完全匹配,则返回相应的 Number 值。否则返回 undefined。 调用时执行以下步骤:

  1. 如果 arg 是 "-0",则返回 -0𝔽。
  2. 令 n 为 ! ToNumber(arg)。
  3. 如果 ! ToString(n) 是 arg,则返回 n。
  4. 返回 undefined。

规范数值字符串是 CanonicalNumericIndexString 抽象操作不会对其返回 undefined 的任何 String。

7.1.24 ToIndex ( arg )

抽象操作 ToIndex,接收参数 arg (ECMAScript 语言值);返回值:(正常完成 (值:非负整数) 或 抛出完成)。 它将 arg 转换为整数;如果该整数非负并对应于整数索引,则返回该整数。否则抛出异常。 调用时执行以下步骤:

  1. 令 int 为 ? ToIntegerOrInfinity(arg)。
  2. 如果 int 不在从 0 到 253 - 1 的闭区间中,则抛出 RangeError 异常。
  3. 返回 int。

7.1.25 ToAbsoluteIndex ( value, length )

抽象操作 ToAbsoluteIndex,接收参数 value (ECMAScript 语言值) 和 length (非负整数);返回值:(正常完成 (值:(整数、+∞ 或 -∞)) 或 抛出完成)。 它将 value 转换为整数、+∞ 或 -∞,并相对于 length 解释负值。 调用时执行以下步骤:

  1. 令 int 为 ? ToIntegerOrInfinity(value)。
  2. 如果 int 是有限值且 int < 0,则将 int 设置为 length + int。
  3. 返回 int。

7.1.26 ToClampedIndex ( value, length )

抽象操作 ToClampedIndex,接收参数 value (ECMAScript 语言值) 和 length (非负整数);返回值:(正常完成 (值:非负整数) 或 抛出完成)。 它将 value 转换为整数(相对于 length 解释负值),并将结果钳制到从 0 到 length 的闭区间。 调用时执行以下步骤:

  1. 令 index 为 ? ToAbsoluteIndex(value, length)。
  2. 返回将 index 钳制在 0 和 length 之间的结果。

7.2 测试和比较操作

7.2.1 RequireObjectCoercible ( arg )

抽象操作 RequireObjectCoercible,接收参数 arg (ECMAScript 语言值);返回值:(正常完成 (值:unused) 或 抛出完成)。 如果 arg 是无法使用 ToObject 转换为 Object 的值,则它抛出错误。 调用时执行以下步骤:

  1. 如果 arg 是 undefined 或 null,则抛出 TypeError 异常。
  2. 返回 unused。

7.2.2 IsArray ( arg )

抽象操作 IsArray,接收参数 arg (ECMAScript 语言值);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 arg 不是 Object,则返回 false。
  2. 如果 arg 是 Array 异质对象,则返回 true。
  3. 如果 arg 是 Proxy 异质对象,则
    1. 执行 ? ValidateNonRevokedProxy(arg)。
    2. 令 proxyTarget 为 arg.[[ProxyTarget]]。
    3. 返回 ? IsArray(proxyTarget)。
  4. 返回 false。

7.2.3 IsCallable ( arg )

抽象操作 IsCallable,接收参数 arg (ECMAScript 语言值);返回值:Boolean。 它确定 arg 是否是具有 [[Call]] 内部方法的可调用函数。 调用时执行以下步骤:

  1. 如果 arg 不是 Object,则返回 false。
  2. 如果 arg 具有 [[Call]] 内部方法,则返回 true。
  3. 返回 false。

7.2.4 IsConstructor ( arg )

抽象操作 IsConstructor,接收参数 arg (ECMAScript 语言值);返回值:Boolean。 它确定 arg 是否是具有 [[Construct]] 内部方法的函数对象。 调用时执行以下步骤:

  1. 如果 arg 不是 Object,则返回 false。
  2. 如果 arg 具有 [[Construct]] 内部方法,则返回 true。
  3. 返回 false。

7.2.5 IsExtensible ( obj )

抽象操作 IsExtensible,接收参数 obj (Object);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 它用于确定是否可以向 obj 添加其他属性。 调用时执行以下步骤:

  1. 返回 ? obj.[[IsExtensible]]()。

7.2.6 IsRegExp ( arg )

抽象操作 IsRegExp,接收参数 arg (ECMAScript 语言值);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 arg 不是 Object,则返回 false。
  2. 令 matcher 为 ? Get(arg, %Symbol.match%)。
  3. 如果 matcher 不是 undefined,则返回 ToBoolean(matcher)。
  4. 如果 arg 具有 [[RegExpMatcher]] 内部槽,则返回 true。
  5. 返回 false。

7.2.7 Static Semantics: IsStringWellFormedUnicode ( string )

抽象操作 IsStringWellFormedUnicode,接收参数 string (String);返回值:Boolean。 它按照 6.1.4 中的描述,将 string 解释为 UTF-16 编码的码点序列,并确定它是否是格式良好的 UTF-16 序列。 调用时执行以下步骤:

  1. 令 length 为 string 的长度。
  2. 令 k 为 0。
  3. 当 k < length 时,重复执行
    1. 令 codePoint 为 CodePointAt(string, k)。
    2. 如果 codePoint.[[IsUnpairedSurrogate]] 是 true,则返回 false。
    3. 将 k 设置为 k + codePoint.[[CodeUnitCount]]。
  4. 返回 true。

7.2.8 SameType ( x, y )

抽象操作 SameType,接收参数 x (ECMAScript 语言值) 和 y (ECMAScript 语言值);返回值:Boolean。 它确定两个参数是否具有相同类型。 调用时执行以下步骤:

  1. 如果 x 是 undefined 且 y 是 undefined,则返回 true。
  2. 如果 x 是 null 且 y 是 null,则返回 true。
  3. 如果 x 是 Boolean 且 y 是 Boolean,则返回 true。
  4. 如果 x 是 Number 且 y 是 Number,则返回 true。
  5. 如果 x 是 BigInt 且 y 是 BigInt,则返回 true。
  6. 如果 x 是 Symbol 且 y 是 Symbol,则返回 true。
  7. 如果 x 是 String 且 y 是 String,则返回 true。
  8. 如果 x 是 Object 且 y 是 Object,则返回 true。
  9. 返回 false。

7.2.9 SameValue ( x, y )

抽象操作 SameValue,接收参数 x (ECMAScript 语言值) 和 y (ECMAScript 语言值);返回值:Boolean。 它确定两个参数是否为相同的值。 调用时执行以下步骤:

  1. 如果 SameType(x, y) 是 false,则返回 false。
  2. 如果 x 是 Number,则
    1. 返回 Number::sameValue(x, y)。
  3. 返回 SameValueNonNumber(x, y)。
注

该算法与 IsStrictlyEqual 算法不同之处在于,它将所有 NaN 值视为等价,并区分 +0𝔽 和 -0𝔽。

7.2.10 SameValueZero ( x, y )

抽象操作 SameValueZero,接收参数 x (ECMAScript 语言值) 和 y (ECMAScript 语言值);返回值:Boolean。 它确定两个参数是否为相同的值(忽略 +0𝔽 和 -0𝔽 之间的差异)。 调用时执行以下步骤:

  1. 如果 SameType(x, y) 是 false,则返回 false。
  2. 如果 x 是 Number,则
    1. 返回 Number::sameValueZero(x, y)。
  3. 返回 SameValueNonNumber(x, y)。
注

SameValueZero 与 SameValue 的唯一区别在于,它将 +0𝔽 和 -0𝔽 视为等价。

7.2.11 SameValueNonNumber ( x, y )

抽象操作 SameValueNonNumber,接收参数 x (an ECMAScript language value, but not a Number) 和 y (an ECMAScript language value, but not a Number);返回值:Boolean。 调用时执行以下步骤:

  1. 断言:SameType(x, y) 是 true。
  2. 如果 x 是 undefined 或 null,则返回 true。
  3. 如果 x 是 BigInt,则
    1. 返回 BigInt::equal(x, y)。
  4. 如果 x 是 String,则
    1. 如果 x 和 y 长度相同,并且相同位置具有相同码元,则返回 true。
    2. 返回 false。
  5. 如果 x 是 Boolean,则
    1. 如果 x 是 true 且 y 是 true,则返回 true。
    2. 如果 x 是 false 且 y 是 false,则返回 true。
    3. 返回 false。
  6. 注:所有其他 ECMAScript 语言值都按标识进行比较。
  7. 如果 x 是 y,则返回 true。
  8. 返回 false。
注 1
为了便于说明,即使没有必要,本算法中的某些情况也会单独处理。
注 2
“x 是 y”的具体含义详见 5.2.8。

7.2.12 IsLessThan ( x, y, leftFirst )

抽象操作 IsLessThan,接收参数 x (ECMAScript 语言值)、y (ECMAScript 语言值) 和 leftFirst (Boolean);返回值:(正常完成 (值:(Boolean 或 undefined)) 或 抛出完成)。 它提供比较 x < y 的语义,返回 true、false 或 undefined(后者表示操作数无法被强制转换为相同数值类型的可比较值)。leftFirst 标志用于控制对 x 和 y 执行可能具有可见副作用的操作的顺序。这是必要的,因为 ECMAScript 规定表达式从左到右求值。如果 leftFirst 是 true,则 x 参数对应的表达式位于 y 参数对应表达式的左侧。如果 leftFirst 是 false,情况相反,必须先对 y 执行操作,再对 x 执行。 调用时执行以下步骤:

  1. 如果 leftFirst 是 true,则
    1. 令 px 为 ? ToPrimitive(x, number)。
    2. 令 py 为 ? ToPrimitive(y, number)。
  2. 否则,
    1. 注:需要反转求值顺序,以保持从左到右的求值。
    2. 令 py 为 ? ToPrimitive(y, number)。
    3. 令 px 为 ? ToPrimitive(x, number)。
  3. 如果 px 是 String 且 py 是 String,则
    1. 令 lx 为 px 的长度。
    2. 令 ly 为 py 的长度。
    3. 对满足 0 ≤ i < min(lx, ly) 的每个整数 i,按升序执行
      1. 令 cx 为 px 中索引 i 处码元的数值。
      2. 令 cy 为 py 中索引 i 处码元的数值。
      3. 如果 cx < cy,则返回 true。
      4. 如果 cx > cy,则返回 false。
    4. 如果 lx < ly,则返回 true。
    5. 返回 false。
  4. 如果 px 是 BigInt 且 py 是 String,则
    1. 令 ny 为 StringToBigInt(py)。
    2. 如果 ny 是 undefined,则返回 undefined。
    3. 返回 BigInt::lessThan(px, ny)。
  5. 如果 px 是 String 且 py 是 BigInt,则
    1. 令 nx 为 StringToBigInt(px)。
    2. 如果 nx 是 undefined,则返回 undefined。
    3. 返回 BigInt::lessThan(nx, py)。
  6. 注:由于 px 和 py 是原始值,因此求值顺序不重要。
  7. 令 nx 为 ? ToNumeric(px)。
  8. 令 ny 为 ? ToNumeric(py)。
  9. 如果 SameType(nx, ny) 是 true,则
    1. 如果 nx 是 Number,则返回 Number::lessThan(nx, ny)。
    2. 断言:nx 是 BigInt。
    3. 返回 BigInt::lessThan(nx, ny)。
  10. 断言:nx 是 BigInt 且 ny 是 Number,或者 nx 是 Number 且 ny 是 BigInt。
  11. 如果 nx 是 NaN 或 ny 是 NaN,则返回 undefined。
  12. 如果 nx 是 -∞𝔽 或 ny 是 +∞𝔽,则返回 true。
  13. 如果 nx 是 +∞𝔽 或 ny 是 -∞𝔽,则返回 false。
  14. 如果 ℝ(nx) < ℝ(ny),则返回 true。
  15. 返回 false。
注 1

步骤 3 与处理加法运算符 + 的算法(13.15.3)中的步骤 1.c 不同,因为它使用逻辑与操作,而不是逻辑或操作。

注 2

String 的比较使用 UTF-16 码元值序列上的简单字典序。不会尝试使用 Unicode 规范中定义的、语义上更复杂的字符或字符串相等性以及排序顺序定义。因此,根据 Unicode 标准规范等价、但不处于相同规范化形式的 String 值可能会比较为不相等。还要注意,对于包含代理对的 String,按码元字典排序与按码点排序不同。

7.2.13 IsLooselyEqual ( x, y )

抽象操作 IsLooselyEqual,接收参数 x (ECMAScript 语言值) 和 y (ECMAScript 语言值);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 它提供 == 运算符的语义。 调用时执行以下步骤:

  1. 如果 SameType(x, y) 是 true,那么
    1. 返回 IsStrictlyEqual(x, y)。
  2. 如果 x 是 null 且 y 是 undefined,返回 true。
  3. 如果 x 是 undefined 且 y 是 null,返回 true。
  4. Normative Optional
    如果宿主是 Web 浏览器或以其他方式支持 [[IsHTMLDDA]] 内部槽,那么
    1. 如果 x 是 Object,x 具有 [[IsHTMLDDA]] 内部槽,并且 y 是 undefined 或 null,返回 true。
    2. 如果 x 是 undefined 或 null,y 是 Object,并且 y 具有 [[IsHTMLDDA]] 内部槽,返回 true。
  5. 如果 x 是 Number 且 y 是 String,返回 ! IsLooselyEqual(x, ! ToNumber(y))。
  6. 如果 x 是 String 且 y 是 Number,返回 ! IsLooselyEqual(! ToNumber(x), y)。
  7. 如果 x 是 BigInt 且 y 是 String,那么
    1. 令 n 为 StringToBigInt(y)。
    2. 如果 n 是 undefined,返回 false。
    3. 返回 ! IsLooselyEqual(x, n)。
  8. 如果 x 是 String 且 y 是 BigInt,返回 ! IsLooselyEqual(y, x)。
  9. 如果 x 是 Boolean,返回 ! IsLooselyEqual(! ToNumber(x), y)。
  10. 如果 y 是 Boolean,返回 ! IsLooselyEqual(x, ! ToNumber(y))。
  11. 如果 x 是 String、Number、BigInt 或 Symbol,且 y 是 Object,返回 ! IsLooselyEqual(x, ? ToPrimitive(y))。
  12. 如果 x 是 Object,且 y 是 String、Number、BigInt 或 Symbol,返回 ! IsLooselyEqual(? ToPrimitive(x), y)。
  13. 如果 x 是 BigInt 且 y 是有限 Number,或者 x 是有限 Number 且 y 是 BigInt,那么
    1. 如果 ℝ(x) = ℝ(y),返回 true。
    2. 返回 false。
  14. 返回 false。

7.2.14 IsStrictlyEqual ( x, y )

抽象操作 IsStrictlyEqual,接收参数 x (ECMAScript 语言值) 和 y (ECMAScript 语言值);返回值:Boolean。 它提供 === 运算符的语义。 调用时执行以下步骤:

  1. 如果 SameType(x, y) 是 false,则返回 false。
  2. 如果 x 是 Number,则
    1. 返回 Number::equal(x, y)。
  3. 返回 SameValueNonNumber(x, y)。
注

该算法与 SameValue 算法在处理有符号零和 NaN 时有所不同。

7.3 对象上的操作

7.3.1 MakeBasicObject ( internalSlotsList )

抽象操作 MakeBasicObject,接收参数 internalSlotsList (列表 (元素:内部槽名称));返回值:Object。 它是所有通过算法创建的 ECMAScript 对象(包括普通对象和异质对象)的来源。它提取创建所有对象时使用的公共步骤,并将对象创建集中在一起。 调用时执行以下步骤:

  1. 将 internalSlotsList 设置为 internalSlotsList 与 « [[PrivateElements]] » 的列表连接。
  2. 令 obj 为新创建的对象,该对象为 internalSlotsList 中的每个名称都具有一个内部槽。
  3. 注:如 Object 内部方法和内部槽 所述,除非另有规定,否则每个此类内部槽的初始值都是 undefined。
  4. 将 obj.[[PrivateElements]] 设置为新的空 List。
  5. 将 obj 的基本内部方法设置为 10.1 中规定的默认普通对象定义。
  6. 断言:如果调用方不会同时覆盖 obj 的 [[GetPrototypeOf]] 和 [[SetPrototypeOf]] 基本内部方法,则 internalSlotsList 包含 [[Prototype]]。
  7. 断言:如果调用方不会覆盖 obj 的 [[SetPrototypeOf]]、[[IsExtensible]] 和 [[PreventExtensions]] 全部三个基本内部方法,则 internalSlotsList 包含 [[Extensible]]。
  8. 如果 internalSlotsList 包含 [[Extensible]],则将 obj.[[Extensible]] 设置为 true。
  9. 返回 obj。
注

在本规范中,异质对象通过 ArrayCreate 和 BoundFunctionCreate 等抽象操作创建:首先调用 MakeBasicObject 获取基本的基础对象,然后覆盖该对象的部分或全部内部方法。为了封装异质对象的创建,对象的基本内部方法绝不会在这些操作之外被修改。

7.3.2 Get ( obj, propertyKey )

抽象操作 Get,接收参数 obj (Object) 和 propertyKey (属性键);返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。 它用于检索对象的特定属性值。 调用时执行以下步骤:

  1. 返回 ? obj.[[Get]](propertyKey, obj)。

7.3.3 GetV ( value, propertyKey )

抽象操作 GetV,接收参数 value (ECMAScript 语言值) 和 propertyKey (属性键);返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。 它用于检索 ECMAScript 语言值的特定属性值。如果该值不是对象,则使用适合该值类型的包装对象执行属性查找。 调用时执行以下步骤:

  1. 令 obj 为 ? ToObject(value)。
  2. 返回 ? obj.[[Get]](propertyKey, value)。

7.3.4 Set ( obj, propertyKey, value, throw )

抽象操作 Set,接收参数 obj (Object)、propertyKey (属性键)、value (ECMAScript 语言值) 和 throw (Boolean);返回值:(正常完成 (值:unused) 或 抛出完成)。 它用于设置对象的特定属性值。value 是该属性的新值。 调用时执行以下步骤:

  1. 令 success 为 ? obj.[[Set]](propertyKey, value, obj)。
  2. 如果 success 是 false 且 throw 是 true,则抛出 TypeError 异常。
  3. 返回 unused。

7.3.5 CreateDataProperty ( obj, propertyKey, value )

抽象操作 CreateDataProperty,接收参数 obj (Object)、propertyKey (属性键) 和 value (ECMAScript 语言值);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 它用于创建对象的新自有属性。 调用时执行以下步骤:

  1. 令 newDesc 为 PropertyDescriptor { [[Value]]: value, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true }。
  2. 返回 ? obj.[[DefineOwnProperty]](propertyKey, newDesc)。
注

此抽象操作创建一个属性,其特性设置为与 ECMAScript 语言赋值运算符创建的属性相同的默认值。通常,该属性尚不存在。如果它已经存在且不可配置,或者 obj 不可扩展,则 [[DefineOwnProperty]] 将返回 false。

7.3.6 CreateDataPropertyOrThrow ( obj, propertyKey, value )

抽象操作 CreateDataPropertyOrThrow,接收参数 obj (Object)、propertyKey (属性键) 和 value (ECMAScript 语言值);返回值:(正常完成 (值:unused) 或 抛出完成)。 它用于创建对象的新自有属性。如果无法执行所请求的属性更新,则抛出 TypeError 异常。 调用时执行以下步骤:

  1. 令 success 为 ? CreateDataProperty(obj, propertyKey, value)。
  2. 如果 success 是 false,则抛出 TypeError 异常。
  3. 返回 unused。
注

此抽象操作创建一个属性,其特性设置为与 ECMAScript 语言赋值运算符创建的属性相同的默认值。通常,该属性尚不存在。如果它已经存在且不可配置,或者 obj 不可扩展,则 [[DefineOwnProperty]] 将返回 false,从而导致此操作抛出 TypeError 异常。

7.3.7 CreateNonEnumerableDataPropertyOrThrow ( obj, propertyKey, value )

抽象操作 CreateNonEnumerableDataPropertyOrThrow,接收参数 obj (Object)、propertyKey (属性键) 和 value (ECMAScript 语言值);返回值:unused。 它用于创建普通对象的新不可枚举自有属性。 调用时执行以下步骤:

  1. 断言:obj 是普通、可扩展且没有不可配置属性的对象。
  2. 令 newDesc 为 PropertyDescriptor { [[Value]]: value, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }。
  3. 执行 ! DefinePropertyOrThrow(obj, propertyKey, newDesc)。
  4. 返回 unused。
注

此抽象操作创建一个属性,其特性设置为与 ECMAScript 语言赋值运算符创建的属性相同的默认值,但它不可枚举。通常,该属性尚不存在。如果它已经存在,则保证 DefinePropertyOrThrow 正常完成。

7.3.8 DefinePropertyOrThrow ( obj, propertyKey, propertyDesc )

抽象操作 DefinePropertyOrThrow,接收参数 obj (Object)、propertyKey (属性键) 和 propertyDesc (属性描述符);返回值:(正常完成 (值:unused) 或 抛出完成)。 它用于调用对象的 [[DefineOwnProperty]] 内部方法,并在无法执行所请求的属性更新时抛出 TypeError 异常。 调用时执行以下步骤:

  1. 令 success 为 ? obj.[[DefineOwnProperty]](propertyKey, propertyDesc)。
  2. 如果 success 是 false,则抛出 TypeError 异常。
  3. 返回 unused。

7.3.9 DeletePropertyOrThrow ( obj, propertyKey )

抽象操作 DeletePropertyOrThrow,接收参数 obj (Object) 和 propertyKey (属性键);返回值:(正常完成 (值:unused) 或 抛出完成)。 它用于移除对象的特定自有属性。如果该属性不可配置,则抛出异常。 调用时执行以下步骤:

  1. 令 success 为 ? obj.[[Delete]](propertyKey)。
  2. 如果 success 是 false,则抛出 TypeError 异常。
  3. 返回 unused。

7.3.10 GetMethod ( value, propertyKey )

抽象操作 GetMethod,接收参数 value (ECMAScript 语言值) 和 propertyKey (属性键);返回值:(正常完成 (值:(函数对象 或 undefined)) 或 抛出完成)。 当预期 ECMAScript 语言值的某个特定属性值为函数时,它用于获取该属性的值。 调用时执行以下步骤:

  1. 令 func 为 ? GetV(value, propertyKey)。
  2. 如果 func 是 undefined 或 null,则返回 undefined。
  3. 如果 IsCallable(func) 是 false,则抛出 TypeError 异常。
  4. 返回 func。

7.3.11 HasProperty ( obj, propertyKey )

抽象操作 HasProperty,接收参数 obj (Object) 和 propertyKey (属性键);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 它用于确定对象是否具有指定属性键的属性。该属性可以是自有属性,也可以是继承属性。 调用时执行以下步骤:

  1. 返回 ? obj.[[HasProperty]](propertyKey)。

7.3.12 HasOwnProperty ( obj, propertyKey )

抽象操作 HasOwnProperty,接收参数 obj (Object) 和 propertyKey (属性键);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 它用于确定对象是否具有指定属性键的自有属性。 调用时执行以下步骤:

  1. 令 propertyDesc 为 ? obj.[[GetOwnProperty]](propertyKey)。
  2. 如果 propertyDesc 是 undefined,则返回 false。
  3. 返回 true。

7.3.13 Call ( func, thisValue [ , argList ] )

抽象操作 Call,接收参数 func (ECMAScript 语言值) 和 thisValue (ECMAScript 语言值)和可选参数 argList (列表 (元素:ECMAScript 语言值));返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。 它用于调用函数对象的 [[Call]] 内部方法。func 是函数对象,thisValue 是作为 [[Call]] 的 this 值的 ECMAScript 语言值,argList 是传递给内部方法相应参数的值。如果不存在 argList,则使用新的空 List 作为其值。 调用时执行以下步骤:

  1. 如果不存在 argList,则将 argList 设置为新的空 List。
  2. 如果 IsCallable(func) 是 false,则抛出 TypeError 异常。
  3. 返回 ? func.[[Call]](thisValue, argList)。

7.3.14 Construct ( ctor [ , argList [ , newTarget ] ] )

抽象操作 Construct,接收参数 ctor (构造函数)和可选参数 argList (列表 (元素:ECMAScript 语言值)) 和 newTarget (构造函数);返回值:(正常完成 (值:Object) 或 抛出完成)。 它用于调用函数对象的 [[Construct]] 内部方法。argList 和 newTarget 是要作为内部方法相应参数传递的值。如果不存在 argList,则使用新的空 List 作为其值。如果不存在 newTarget,则使用 ctor 作为其值。 调用时执行以下步骤:

  1. 如果不存在 newTarget,则将 newTarget 设置为 ctor。
  2. 如果不存在 argList,则将 argList 设置为新的空 List。
  3. 返回 ? ctor.[[Construct]](argList, newTarget)。
注

如果不存在 newTarget,此操作等价于:new F(...argumentsList)

7.3.15 SetIntegrityLevel ( obj, level )

抽象操作 SetIntegrityLevel,接收参数 obj (Object) 和 level ((sealed 或 frozen));返回值:(正常完成 (值:Boolean) 或 抛出完成)。 它用于固定对象的自有属性集合。 调用时执行以下步骤:

  1. 令 status 为 ? obj.[[PreventExtensions]]()。
  2. 如果 status 是 false,则返回 false。
  3. 令 keys 为 ? obj.[[OwnPropertyKeys]]()。
  4. 如果 level 是 sealed,则
    1. 对 keys 的每个元素 key,执行
      1. 执行 ? DefinePropertyOrThrow(obj, key, PropertyDescriptor { [[Configurable]]: false })。
  5. 否则,
    1. 断言:level 是 frozen。
    2. 对 keys 的每个元素 key,执行
      1. 令 currentDesc 为 ? obj.[[GetOwnProperty]](key)。
      2. 如果 currentDesc 不是 undefined,则
        1. 如果 IsAccessorDescriptor(currentDesc) 是 true,则
          1. 令 propertyDesc 为 PropertyDescriptor { [[Configurable]]: false }。
        2. 否则,
          1. 令 propertyDesc 为 PropertyDescriptor { [[Configurable]]: false, [[Writable]]: false }。
        3. 执行 ? DefinePropertyOrThrow(obj, key, propertyDesc)。
  6. 返回 true。

7.3.16 TestIntegrityLevel ( obj, level )

抽象操作 TestIntegrityLevel,接收参数 obj (Object) 和 level ((sealed 或 frozen));返回值:(正常完成 (值:Boolean) 或 抛出完成)。 它用于确定对象的自有属性集合是否已固定。 调用时执行以下步骤:

  1. 令 extensible 为 ? IsExtensible(obj)。
  2. 如果 extensible 是 true,则返回 false。
  3. 注:如果对象可扩展,则不会检查其任何属性。
  4. 令 keys 为 ? obj.[[OwnPropertyKeys]]()。
  5. 对 keys 的每个元素 key,执行
    1. 令 currentDesc 为 ? obj.[[GetOwnProperty]](key)。
    2. 如果 currentDesc 不是 undefined,则
      1. 如果 currentDesc.[[Configurable]] 是 true,则返回 false。
      2. 如果 level 是 frozen 且 IsDataDescriptor(currentDesc) 是 true,则
        1. 如果 currentDesc.[[Writable]] 是 true,则返回 false。
  6. 返回 true。

7.3.17 CreateArrayFromList ( elements )

抽象操作 CreateArrayFromList,接收参数 elements (列表 (元素:ECMAScript 语言值));返回值:Array。 它用于创建一个 Array,其元素由 elements 提供。 调用时执行以下步骤:

  1. 令 array 为 ! ArrayCreate(0)。
  2. 令 n 为 0。
  3. 对 elements 的每个元素 element,执行
    1. 执行 ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(n)), element)。
    2. 将 n 设置为 n + 1。
  4. 返回 array。

7.3.18 LengthOfArrayLike ( obj )

抽象操作 LengthOfArrayLike,接收参数 obj (Object);返回值:(正常完成 (值:非负整数) 或 抛出完成)。 它返回类数组对象的 "length" 属性值。 调用时执行以下步骤:

  1. 返回 ℝ(? ToLength(? Get(obj, "length")))。

类数组对象是此操作对其返回正常完成的任何对象。

注 1
通常,类数组对象还会具有一些名称为整数索引的属性。但是,这并不是此定义的要求。
注 2
Array 和 String 对象都是类数组对象的示例。

7.3.19 CreateListFromArrayLike ( obj [ , validElementTypes ] )

抽象操作 CreateListFromArrayLike,接收参数 obj (ECMAScript 语言值)和可选参数 validElementTypes ((all 或 property-key));返回值:(正常完成 (值:列表 (元素:ECMAScript 语言值)) 或 抛出完成)。 它用于创建一个 List 值,其元素由 obj 的索引属性提供。validElementTypes 指示允许作为元素的值类型。 调用时执行以下步骤:

  1. 如果不存在 validElementTypes,则将 validElementTypes 设置为 all。
  2. 如果 obj 不是 Object,则抛出 TypeError 异常。
  3. 令 length 为 ? LengthOfArrayLike(obj)。
  4. 令 list 为新的空 List。
  5. 令 index 为 0。
  6. 当 index < length 时,重复执行
    1. 令 indexName 为 ! ToString(𝔽(index))。
    2. 令 next 为 ? Get(obj, indexName)。
    3. 如果 validElementTypes 是 property-key 且 next 不是属性键,则抛出 TypeError 异常。
    4. 将 next 追加到 list。
    5. 将 index 设置为 index + 1。
  7. 返回 list。

7.3.20 Invoke ( value, propertyKey [ , argList ] )

抽象操作 Invoke,接收参数 value (ECMAScript 语言值) 和 propertyKey (属性键)和可选参数 argList (列表 (元素:ECMAScript 语言值));返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。 它用于调用 ECMAScript 语言值的方法属性。value 既作为属性查找位置,也作为调用的 this 值。argList 是传递给该方法的参数值列表。如果不存在 argList,则使用新的空 List 作为其值。 调用时执行以下步骤:

  1. 如果不存在 argList,则将 argList 设置为新的空 List。
  2. 令 func 为 ? GetV(value, propertyKey)。
  3. 返回 ? Call(func, value, argList)。

7.3.21 OrdinaryHasInstance ( ctor, instance )

抽象操作 OrdinaryHasInstance,接收参数 ctor (ECMAScript 语言值) 和 instance (ECMAScript 语言值);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 它实现默认算法,用于确定 instance 是否继承自 ctor 提供的实例对象继承路径。 调用时执行以下步骤:

  1. 如果 IsCallable(ctor) 是 false,则返回 false。
  2. 如果 ctor 具有 [[BoundTargetFunction]] 内部槽,则
    1. 令 boundCtor 为 ctor.[[BoundTargetFunction]]。
    2. 返回 ? InstanceofOperator(instance, boundCtor)。
  3. 如果 instance 不是 Object,则返回 false。
  4. 令 proto 为 ? Get(ctor, "prototype")。
  5. 如果 proto 不是 Object,则抛出 TypeError 异常。
  6. 重复执行,
    1. 将 instance 设置为 ? instance.[[GetPrototypeOf]]()。
    2. 如果 instance 是 null,则返回 false。
    3. 如果 SameValue(proto, instance) 是 true,则返回 true。

7.3.22 SpeciesConstructor ( obj, defaultCtor )

抽象操作 SpeciesConstructor,接收参数 obj (Object) 和 defaultCtor (构造函数);返回值:(正常完成 (值:构造函数) 或 抛出完成)。 它用于检索应当用来创建从 obj 派生的新对象的构造函数。如果从 obj 开始无法找到构造函数的 %Symbol.species% 属性,则使用 defaultCtor。 调用时执行以下步骤:

  1. 令 ctor 为 ? Get(obj, "constructor")。
  2. 如果 ctor 是 undefined,则返回 defaultCtor。
  3. 如果 ctor 不是 Object,则抛出 TypeError 异常。
  4. 令 species 为 ? Get(ctor, %Symbol.species%)。
  5. 如果 species 是 undefined 或 null,则返回 defaultCtor。
  6. 如果 IsConstructor(species) 是 true,则返回 species。
  7. 抛出 TypeError 异常。

7.3.23 EnumerableOwnProperties ( obj, kind )

抽象操作 EnumerableOwnProperties,接收参数 obj (Object) 和 kind ((key、value 或 key+value));返回值:(正常完成 (值:列表 (元素:ECMAScript 语言值)) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 ownKeys 为 ? obj.[[OwnPropertyKeys]]()。
  2. 令 results 为新的空 List。
  3. 对 ownKeys 的每个元素 key,执行
    1. 如果 key 是 String,则
      1. 令 propertyDesc 为 ? obj.[[GetOwnProperty]](key)。
      2. 如果 propertyDesc 不是 undefined 且 propertyDesc.[[Enumerable]] 是 true,则
        1. 如果 kind 是 key,则
          1. 将 key 追加到 results。
        2. 否则,
          1. 令 value 为 ? Get(obj, key)。
          2. 如果 kind 是 value,则
            1. 将 value 追加到 results。
          3. 否则,
            1. 断言:kind 是 key+value。
            2. 令 entry 为 CreateArrayFromList(« key, value »)。
            3. 将 entry 追加到 results。
  4. 返回 results。

7.3.24 GetFunctionRealm ( func )

抽象操作 GetFunctionRealm,接收参数 func (函数对象);返回值:(正常完成 (值:Realm 记录) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 func 具有 [[Realm]] 内部槽,则
    1. 返回 func.[[Realm]]。
  2. 如果 func 是绑定函数异质对象,则
    1. 令 boundTargetFunc 为 func.[[BoundTargetFunction]]。
    2. 返回 ? GetFunctionRealm(boundTargetFunc)。
  3. 如果 func 是 Proxy 异质对象,则
    1. 执行 ? ValidateNonRevokedProxy(func)。
    2. 令 proxyTarget 为 func.[[ProxyTarget]]。
    3. 断言:proxyTarget 是函数对象。
    4. 返回 ? GetFunctionRealm(proxyTarget)。
  4. 返回当前 Realm Record。
注

只有当 func 是不具有 [[Realm]] 内部槽的非标准函数异质对象时,才会到达步骤 4。

7.3.25 CopyDataProperties ( target, source, excludedItems )

抽象操作 CopyDataProperties,接收参数 target (Object)、source (ECMAScript 语言值) 和 excludedItems (列表 (元素:属性键));返回值:(正常完成 (值:unused) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 source 是 undefined 或 null,则返回 unused。
  2. 令 from 为 ! ToObject(source)。
  3. 令 keys 为 ? from.[[OwnPropertyKeys]]()。
  4. 对 keys 的每个元素 nextKey,执行
    1. 令 excluded 为 false。
    2. 对 excludedItems 的每个元素 element,执行
      1. 如果 SameValue(element, nextKey) 是 true,则
        1. 将 excluded 设置为 true。
    3. 如果 excluded 是 false,则
      1. 令 propertyDesc 为 ? from.[[GetOwnProperty]](nextKey)。
      2. 如果 propertyDesc 不是 undefined 且 propertyDesc.[[Enumerable]] 是 true,则
        1. 令 propertyValue 为 ? Get(from, nextKey)。
        2. 执行 ! CreateDataPropertyOrThrow(target, nextKey, propertyValue)。
  5. 返回 unused。
注

此处传入的目标始终是新创建的对象,在抛出错误的情况下无法直接访问它。

7.3.26 PrivateElementFind ( obj, privateName )

抽象操作 PrivateElementFind,接收参数 obj (Object) 和 privateName (私有名称);返回值:(PrivateElement 或 empty)。 调用时执行以下步骤:

  1. 如果 obj.[[PrivateElements]] 包含一个 PrivateElement entry,使得 entry.[[Key]] 是 privateName,则
    1. 返回 entry。
  2. 返回 empty。

7.3.27 PrivateFieldAdd ( obj, privateName, value )

抽象操作 PrivateFieldAdd,接收参数 obj (Object)、privateName (私有名称) 和 value (ECMAScript 语言值);返回值:(正常完成 (值:unused) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果宿主是 Web 浏览器,则
    1. 执行 ? HostEnsureCanAddPrivateElement(obj)。
  2. 令 entry 为 PrivateElementFind(obj, privateName)。
  3. 如果 entry 不是 empty,则抛出 TypeError 异常。
  4. 将 PrivateElement { [[Key]]: privateName, [[Kind]]: field, [[Value]]: value } 追加到 obj.[[PrivateElements]]。
  5. 返回 unused。

7.3.28 PrivateMethodOrAccessorAdd ( obj, method )

抽象操作 PrivateMethodOrAccessorAdd,接收参数 obj (Object) 和 method (PrivateElement);返回值:(正常完成 (值:unused) 或 抛出完成)。 调用时执行以下步骤:

  1. 断言:method.[[Kind]] 是 method 或 accessor。
  2. 如果宿主是 Web 浏览器,则
    1. 执行 ? HostEnsureCanAddPrivateElement(obj)。
  3. 令 entry 为 PrivateElementFind(obj, method.[[Key]])。
  4. 如果 entry 不是 empty,则抛出 TypeError 异常。
  5. 将 method 追加到 obj.[[PrivateElements]]。
  6. 返回 unused。
注

私有方法和访问器的值在各实例之间共享。此操作不会创建方法或访问器的新副本。

7.3.29 HostEnsureCanAddPrivateElement ( obj )

宿主定义的抽象操作 HostEnsureCanAddPrivateElement,接收参数 obj (Object);返回值:(正常完成 (值:unused) 或 抛出完成)。 它允许宿主环境阻止向特定宿主定义的异质对象添加私有元素。

HostEnsureCanAddPrivateElement 的实现必须符合以下要求:

HostEnsureCanAddPrivateElement 的默认实现是返回 NormalCompletion(unused)。

只有作为 Web 浏览器的 ECMAScript 宿主才会调用此抽象操作。

7.3.30 PrivateGet ( obj, privateName )

抽象操作 PrivateGet,接收参数 obj (Object) 和 privateName (私有名称);返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 entry 为 PrivateElementFind(obj, privateName)。
  2. 如果 entry 是 empty,则抛出 TypeError 异常。
  3. 如果 entry.[[Kind]] 是 field 或 method,则
    1. 返回 entry.[[Value]]。
  4. 断言:entry.[[Kind]] 是 accessor。
  5. 如果 entry.[[Getter]] 是 undefined,则抛出 TypeError 异常。
  6. 令 getter 为 entry.[[Getter]]。
  7. 返回 ? Call(getter, obj)。

7.3.31 PrivateSet ( obj, privateName, value )

抽象操作 PrivateSet,接收参数 obj (Object)、privateName (私有名称) 和 value (ECMAScript 语言值);返回值:(正常完成 (值:unused) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 entry 为 PrivateElementFind(obj, privateName)。
  2. 如果 entry 是 empty,则抛出 TypeError 异常。
  3. 如果 entry.[[Kind]] 是 method,则抛出 TypeError 异常。
  4. 如果 entry.[[Kind]] 是 field,则
    1. 将 entry.[[Value]] 设置为 value。
  5. 否则,
    1. 断言:entry.[[Kind]] 是 accessor。
    2. 如果 entry.[[Setter]] 是 undefined,则抛出 TypeError 异常。
    3. 令 setter 为 entry.[[Setter]]。
    4. 执行 ? Call(setter, obj, « value »)。
  6. 返回 unused。

7.3.32 DefineField ( receiver, fieldRecord )

抽象操作 DefineField,接收参数 receiver (Object) 和 fieldRecord (ClassFieldDefinition 记录);返回值:(正常完成 (值:unused) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 fieldName 为 fieldRecord.[[Name]]。
  2. 令 initializer 为 fieldRecord.[[Initializer]]。
  3. 如果 initializer 不是 empty,则
    1. 令 initValue 为 ? Call(initializer, receiver)。
  4. 否则,
    1. 令 initValue 为 undefined。
  5. 如果 fieldName 是 Private Name,则
    1. 执行 ? PrivateFieldAdd(receiver, fieldName, initValue)。
  6. 否则,
    1. 断言:fieldName 是属性键。
    2. 执行 ? CreateDataPropertyOrThrow(receiver, fieldName, initValue)。
  7. 返回 unused。

7.3.33 InitializeInstanceElements ( obj, ctor )

抽象操作 InitializeInstanceElements,接收参数 obj (Object) 和 ctor ((ECMAScript 函数对象 或 内置函数对象));返回值:(正常完成 (值:unused) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 methods 为 ctor.[[PrivateMethods]]。
  2. 对 methods 的每个 PrivateElement method,执行
    1. 执行 ? PrivateMethodOrAccessorAdd(obj, method)。
  3. 令 fields 为 ctor.[[Fields]]。
  4. 对 fields 的每个元素 fieldRecord,执行
    1. 执行 ? DefineField(obj, fieldRecord)。
  5. 返回 unused。

7.3.34 AddValueToKeyedGroup ( groups, key, value )

抽象操作 AddValueToKeyedGroup,接收参数 groups (列表 (元素:记录 (字段:[[Key]] (ECMAScript 语言值), [[Elements]] (列表 (元素:ECMAScript 语言值)))))、key (ECMAScript 语言值) 和 value (ECMAScript 语言值);返回值:unused。 调用时执行以下步骤:

  1. 对 groups 的每个 Record { [[Key]], [[Elements]] } group,执行
    1. 如果 SameValue(group.[[Key]], key) 是 true,则
      1. 断言:groups 中恰好有一个元素满足此条件。
      2. 将 value 追加到 group.[[Elements]]。
      3. 返回 unused。
  2. 令 group 为 Record { [[Key]]: key, [[Elements]]: « value » }。
  3. 将 group 追加到 groups。
  4. 返回 unused。

7.3.35 GroupBy ( items, callback, keyCoercion )

抽象操作 GroupBy,接收参数 items (ECMAScript 语言值)、callback (ECMAScript 语言值) 和 keyCoercion ((property 或 collection));返回值:(正常完成 (值:列表 (元素:记录 (字段:[[Key]] (ECMAScript 语言值), [[Elements]] (列表 (元素:ECMAScript 语言值))))) 或 抛出完成)。 调用时执行以下步骤:

  1. 执行 ? RequireObjectCoercible(items)。
  2. 如果 IsCallable(callback) 是 false,则抛出 TypeError 异常。
  3. 令 groups 为新的空 List。
  4. 令 iteratorRecord 为 ? GetIterator(items, sync)。
  5. 令 k 为 0。
  6. 重复执行,
    1. 如果 k ≥ 253 - 1,则
      1. 令 error 为 ThrowCompletion(新创建的 TypeError 对象)。
      2. 返回 ? IteratorClose(iteratorRecord, error)。
    2. 令 next 为 ? IteratorStepValue(iteratorRecord)。
    3. 如果 next 是 done,则
      1. 返回 groups。
    4. 令 value 为 next。
    5. 令 key 为 Completion(Call(callback, undefined, « value, 𝔽(k) »))。
    6. IfAbruptCloseIterator(key, iteratorRecord)。
    7. 如果 keyCoercion 是 property,则
      1. 将 key 设置为 Completion(ToPropertyKey(key))。
      2. IfAbruptCloseIterator(key, iteratorRecord)。
    8. 否则,
      1. 断言:keyCoercion 是 collection。
      2. 将 key 设置为 CanonicalizeKeyedCollectionKey(key)。
    9. 执行 AddValueToKeyedGroup(groups, key, value)。
    10. 将 k 设置为 k + 1。

7.3.36 GetOptionsObject ( options )

抽象操作 GetOptionsObject,接收参数 options (ECMAScript 语言值);返回值:(正常完成 (值:Object) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 options 是 undefined,则
    1. 返回 OrdinaryObjectCreate(null)。
  2. 如果 options 是 Object,则
    1. 返回 options。
  3. 抛出 TypeError 异常。

7.3.37 SetterThatIgnoresPrototypeProperties ( thisValue, home, propertyKey, value )

抽象操作 SetterThatIgnoresPrototypeProperties,接收参数 thisValue (ECMAScript 语言值)、home (Object)、propertyKey (属性键) 和 value (ECMAScript 语言值);返回值:(正常完成 (值:unused) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 thisValue 不是 Object,则
    1. 抛出 TypeError 异常。
  2. 如果 SameValue(thisValue, home) 是 true,则
    1. 注:在此处抛出异常模拟了严格模式代码中向 home 对象上的不可写数据属性进行赋值。
    2. 抛出 TypeError 异常。
  3. 令 propertyDesc 为 ? thisValue.[[GetOwnProperty]](propertyKey)。
  4. 如果 propertyDesc 是 undefined,则
    1. 执行 ? CreateDataPropertyOrThrow(thisValue, propertyKey, value)。
  5. 否则,
    1. 执行 ? Set(thisValue, propertyKey, value, true)。
  6. 返回 unused。

7.4 迭代器对象上的操作

参见通用迭代接口(27.1)。

7.4.1 Iterator Record

Iterator Record 是用于封装迭代器或异步迭代器及其 next 方法的 Record。

Iterator Record 具有 表 13 中列出的字段。

表 13: Iterator Record 字段
字段名称 值 含义
[[Iterator]] Object 符合迭代器接口或异步迭代器接口的对象。
[[NextMethod]] ECMAScript 语言值 [[Iterator]] 对象的 next 方法。
[[Done]] Boolean 迭代器是否已经完成或关闭。

7.4.2 GetIteratorDirect ( obj )

抽象操作 GetIteratorDirect,接收参数 obj (Object);返回值:(正常完成 (值:Iterator 记录) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 nextMethod 为 ? Get(obj, "next")。
  2. 令 iteratorRecord 为 Iterator Record { [[Iterator]]: obj, [[NextMethod]]: nextMethod, [[Done]]: false }。
  3. 返回 iteratorRecord。

7.4.3 GetIteratorFromMethod ( obj, method )

抽象操作 GetIteratorFromMethod,接收参数 obj (ECMAScript 语言值) 和 method (函数对象);返回值:(正常完成 (值:Iterator 记录) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 iterator 为 ? Call(method, obj)。
  2. 如果 iterator 不是 Object,则抛出 TypeError 异常。
  3. 返回 ? GetIteratorDirect(iterator)。

7.4.4 GetIterator ( obj, kind )

抽象操作 GetIterator,接收参数 obj (ECMAScript 语言值) 和 kind ((sync 或 async));返回值:(正常完成 (值:Iterator 记录) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 kind 是 async,则
    1. 令 method 为 ? GetMethod(obj, %Symbol.asyncIterator%)。
    2. 如果 method 是 undefined,则
      1. 令 syncMethod 为 ? GetMethod(obj, %Symbol.iterator%)。
      2. 如果 syncMethod 是 undefined,则抛出 TypeError 异常。
      3. 令 syncIteratorRecord 为 ? GetIteratorFromMethod(obj, syncMethod)。
      4. 返回 CreateAsyncFromSyncIterator(syncIteratorRecord)。
  2. 否则,
    1. 令 method 为 ? GetMethod(obj, %Symbol.iterator%)。
  3. 如果 method 是 undefined,则抛出 TypeError 异常。
  4. 返回 ? GetIteratorFromMethod(obj, method)。

7.4.5 GetIteratorFlattenable ( obj, primitiveHandling )

抽象操作 GetIteratorFlattenable,接收参数 obj (ECMAScript 语言值) 和 primitiveHandling ((iterate-string-primitives 或 reject-primitives));返回值:(正常完成 (值:Iterator 记录) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 obj 不是 Object,则
    1. 如果 primitiveHandling 是 reject-primitives,则抛出 TypeError 异常。
    2. 断言:primitiveHandling 是 iterate-string-primitives。
    3. 如果 obj 不是 String,则抛出 TypeError 异常。
  2. 令 method 为 ? GetMethod(obj, %Symbol.iterator%)。
  3. 如果 method 是 undefined,则
    1. 令 iterator 为 obj。
  4. 否则,
    1. 令 iterator 为 ? Call(method, obj)。
  5. 如果 iterator 不是 Object,则抛出 TypeError 异常。
  6. 返回 ? GetIteratorDirect(iterator)。

7.4.6 IteratorNext ( iteratorRecord [ , value ] )

抽象操作 IteratorNext,接收参数 iteratorRecord (Iterator 记录)和可选参数 value (ECMAScript 语言值);返回值:(正常完成 (值:Object) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果不存在 value,则
    1. 令 result 为 Completion(Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]]))。
  2. 否则,
    1. 令 result 为 Completion(Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]], « value »))。
  3. 如果 result 是抛出完成,则
    1. 将 iteratorRecord.[[Done]] 设置为 true。
    2. 返回 ? result。
  4. 将 result 设置为 ! result。
  5. 如果 result 不是 Object,则
    1. 将 iteratorRecord.[[Done]] 设置为 true。
    2. 抛出 TypeError 异常。
  6. 返回 result。

7.4.7 IteratorComplete ( iteratorResult )

抽象操作 IteratorComplete,接收参数 iteratorResult (Object);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 返回 ToBoolean(? Get(iteratorResult, "done")).

7.4.8 IteratorValue ( iteratorResult )

抽象操作 IteratorValue,接收参数 iteratorResult (Object);返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。 调用时执行以下步骤:

  1. 返回 ? Get(iteratorResult, "value")。

7.4.9 IteratorStep ( iteratorRecord )

抽象操作 IteratorStep,接收参数 iteratorRecord (Iterator 记录);返回值:(正常完成 (值:(Object 或 done)) 或 抛出完成)。 它通过调用 iteratorRecord.[[NextMethod]] 从 iteratorRecord.[[Iterator]] 请求下一个值,并返回 done(表示迭代器已到达末尾)或在存在下一个值时返回 IteratorResult 对象。 调用时执行以下步骤:

  1. 令 result 为 ? IteratorNext(iteratorRecord)。
  2. 令 done 为 Completion(IteratorComplete(result))。
  3. 如果 done 是抛出完成,则
    1. 将 iteratorRecord.[[Done]] 设置为 true。
    2. 返回 ? done。
  4. 将 done 设置为 ! done。
  5. 如果 done 是 true,则
    1. 将 iteratorRecord.[[Done]] 设置为 true。
    2. 返回 done。
  6. 返回 result。

7.4.10 IteratorStepValue ( iteratorRecord )

抽象操作 IteratorStepValue,接收参数 iteratorRecord (Iterator 记录);返回值:(正常完成 (值:(ECMAScript 语言值 或 done)) 或 抛出完成)。 它通过调用 iteratorRecord.[[NextMethod]] 从 iteratorRecord.[[Iterator]] 请求下一个值,并返回 done(表示迭代器已到达末尾)或在存在下一个值时返回 IteratorResult 对象中的值。 调用时执行以下步骤:

  1. 令 result 为 ? IteratorStep(iteratorRecord)。
  2. 如果 result 是 done,则
    1. 返回 done。
  3. 令 value 为 Completion(IteratorValue(result))。
  4. 如果 value 是抛出完成,则
    1. 将 iteratorRecord.[[Done]] 设置为 true。
  5. 返回 ? value。

7.4.11 IteratorClose ( iteratorRecord, completion )

抽象操作 IteratorClose,接收参数 iteratorRecord (Iterator 记录) 和 completion (完成记录);返回值:完成记录。 它用于通知迭代器:应执行其在达到完成状态时通常会执行的任何操作。 调用时执行以下步骤:

  1. 断言:iteratorRecord.[[Iterator]] 是 Object。
  2. 令 iterator 为 iteratorRecord.[[Iterator]]。
  3. 令 innerResult 为 Completion(GetMethod(iterator, "return"))。
  4. 如果 innerResult 是正常完成,则
    1. 令 return 为 innerResult.[[Value]]。
    2. 如果 return 是 undefined,则返回 ? completion。
    3. 将 innerResult 设置为 Completion(Call(return, iterator))。
  5. 如果 completion 是抛出完成,则返回 ? completion。
  6. 如果 innerResult 是抛出完成,则返回 ? innerResult。
  7. 如果 innerResult.[[Value]] 不是 Object,则抛出 TypeError 异常。
  8. 返回 ? completion。

7.4.12 IteratorCloseAll ( iterators, completion )

抽象操作 IteratorCloseAll,接收参数 iterators (列表 (元素:Iterator 记录)) 和 completion (完成记录);返回值:完成记录。 调用时执行以下步骤:

  1. 对 iterators 的每个元素 iterator,按 List 的逆序执行
    1. 将 completion 设置为 Completion(IteratorClose(iterator, completion))。
  2. 返回 ? completion。

7.4.13 IfAbruptCloseIterator ( value, iteratorRecord )

IfAbruptCloseIterator 是使用 Iterator Record 的一系列算法步骤的简写。以下形式的算法步骤:

  1. IfAbruptCloseIterator(value, iteratorRecord)。

与以下内容含义相同:

  1. 断言:value 是 Completion Record。
  2. 如果 value 是突然完成,则返回 ? IteratorClose(iteratorRecord, value)。
  3. 将 value 设置为 ! value。

7.4.14 IfAbruptCloseIterators ( value, iteratorRecords )

IfAbruptCloseIterators 是使用 Iterator Record 列表的一系列算法步骤的简写。以下形式的算法步骤:

  1. IfAbruptCloseIterators(value, iteratorRecords)。

与以下内容含义相同:

  1. 断言:value 是 Completion Record。
  2. 如果 value 是突然完成,则返回 ? IteratorCloseAll(iteratorRecords, value)。
  3. 将 value 设置为 ! value。

7.4.15 AsyncIteratorClose ( iteratorRecord, completion )

抽象操作 AsyncIteratorClose,接收参数 iteratorRecord (Iterator 记录) 和 completion (完成记录);返回值:完成记录。 它用于通知异步迭代器:应执行其在达到完成状态时通常会执行的任何操作。 调用时执行以下步骤:

  1. 断言:iteratorRecord.[[Iterator]] 是 Object。
  2. 令 iterator 为 iteratorRecord.[[Iterator]]。
  3. 令 innerResult 为 Completion(GetMethod(iterator, "return"))。
  4. 如果 innerResult 是正常完成,则
    1. 令 return 为 innerResult.[[Value]]。
    2. 如果 return 是 undefined,则返回 ? completion。
    3. 将 innerResult 设置为 Completion(Call(return, iterator))。
    4. 如果 innerResult 是正常完成,则将 innerResult 设置为 Completion(Await(innerResult.[[Value]]))。
  5. 如果 completion 是抛出完成,则返回 ? completion。
  6. 如果 innerResult 是抛出完成,则返回 ? innerResult。
  7. 如果 innerResult.[[Value]] 不是 Object,则抛出 TypeError 异常。
  8. 返回 ? completion。

7.4.16 IfAbruptCloseAsyncIterator ( value, iteratorRecord )

IfAbruptCloseAsyncIterator 是使用 Iterator Record 的一系列算法步骤的简写。以下形式的算法步骤:

  1. IfAbruptCloseAsyncIterator(value, iteratorRecord)。

与以下内容含义相同:

  1. 断言:value 是 Completion Record。
  2. 如果 value 是突然完成,则返回 ? AsyncIteratorClose(iteratorRecord, value)。
  3. 将 value 设置为 ! value。

7.4.17 CreateIteratorResultObject ( value, done )

抽象操作 CreateIteratorResultObject,接收参数 value (ECMAScript 语言值) 和 done (Boolean);返回值:an Object that conforms to the IteratorResult interface。 它创建一个符合 IteratorResult 接口的对象。 调用时执行以下步骤:

  1. 令 obj 为 OrdinaryObjectCreate(%Object.prototype%)。
  2. 执行 ! CreateDataPropertyOrThrow(obj, "value", value)。
  3. 执行 ! CreateDataPropertyOrThrow(obj, "done", done)。
  4. 返回 obj。

7.4.18 CreateListIteratorRecord ( list )

抽象操作 CreateListIteratorRecord,接收参数 list (列表 (元素:ECMAScript 语言值));返回值:Iterator 记录。 它创建一个 Iterator Record,其 [[NextMethod]] 返回 list 中连续的元素。 调用时执行以下步骤:

  1. 令 closure 为一个没有参数的新 Abstract Closure,它捕获 list,并在被调用时执行以下步骤:
    1. 对 list 的每个元素 value,执行
      1. 执行 ? GeneratorYield(CreateIteratorResultObject(value, false))。
    2. 返回 NormalCompletion(undefined)。
  2. 令 iterator 为 CreateIteratorFromClosure(closure, empty, %Iterator.prototype%)。
  3. 返回 Iterator Record { [[Iterator]]: iterator, [[NextMethod]]: %GeneratorPrototype.next%, [[Done]]: false }。
注

列表迭代器对象永远无法被 ECMAScript 代码直接访问。

7.4.19 IteratorToList ( iteratorRecord )

抽象操作 IteratorToList,接收参数 iteratorRecord (Iterator 记录);返回值:(正常完成 (值:列表 (元素:ECMAScript 语言值)) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 values 为新的空 List。
  2. 重复执行,
    1. 令 next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 next 是 done,则
      1. 返回 values。
    3. 将 next 追加到 values。

7.5 可释放对象上的操作

参见通用资源管理接口(27.2.1)。

7.5.1 DisposableResource Record

DisposableResource Record 是用于封装可释放对象以及用于释放该对象的方法的 Record 值。DisposableResource Record 由 CreateDisposableResource 抽象操作产生。

DisposableResource Record 具有 表 14 中列出的字段:

表 14: DisposableResource Record 字段
字段名称 值 含义
[[ResourceValue]] Object 或 undefined 要释放的值。
[[Kind]] sync-dispose 或 async-dispose 表示资源是通过 using 声明或 DisposableStack 对象(sync-dispose)添加,还是通过 await using 声明或 AsyncDisposableStack 对象(async-dispose)添加。
[[DisposeMethod]] 函数对象或 undefined 在释放资源时,将以 [[ResourceValue]] 作为其 this 值调用的函数对象。

7.5.2 AddDisposableResource ( disposableResourceStack, value, kind [ , method ] )

抽象操作 AddDisposableResource,接收参数 disposableResourceStack (列表 (元素:DisposableResource 记录))、value (ECMAScript 语言值) 和 kind ((sync-dispose 或 async-dispose))和可选参数 method (函数对象);返回值:(正常完成 (值:unused) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果存在 method,则
    1. 断言:value 是 undefined。
    2. 令 resource 为 ? CreateDisposableResource(undefined, kind, method)。
  2. 否则,
    1. 如果 value 是 null 或 undefined,并且 kind 是 sync-dispose,则返回 unused。
    2. 注:当 value 是 null 或 undefined 且 kind 是 async-dispose 时,我们会记录该资源已被求值,以确保稍后释放资源时仍会执行一次 Await。
    3. 令 resource 为 ? CreateDisposableResource(value, kind)。
  3. 将 resource 追加到 disposableResourceStack。
  4. 返回 unused。

7.5.3 CreateDisposableResource ( value, kind [ , method ] )

抽象操作 CreateDisposableResource,接收参数 value (ECMAScript 语言值) 和 kind ((sync-dispose 或 async-dispose))和可选参数 method (函数对象);返回值:(正常完成 (值:DisposableResource 记录) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果不存在 method,则
    1. 如果 value 是 null 或 undefined,则
      1. 将 value 设置为 undefined。
      2. 将 method 设置为 undefined。
    2. 否则,
      1. 将 method 设置为 ? GetDisposeMethod(value, kind)。
      2. 如果 method 是 undefined,则抛出 TypeError 异常。
  2. 返回 DisposableResource Record { [[ResourceValue]]: value, [[Kind]]: kind, [[DisposeMethod]]: method }。

7.5.4 GetDisposeMethod ( value, kind )

抽象操作 GetDisposeMethod,接收参数 value (ECMAScript 语言值) 和 kind ((sync-dispose 或 async-dispose));返回值:(正常完成 (值:(函数对象 或 undefined)) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 value 不是 Object,则抛出 TypeError 异常。
  2. 如果 kind 是 sync-dispose,则返回 ? GetMethod(value, %Symbol.dispose%)。
  3. 断言:kind 是 async-dispose。
  4. 令 asyncMethod 为 ? GetMethod(value, %Symbol.asyncDispose%)。
  5. 如果 asyncMethod 不是 undefined,则返回 asyncMethod。
  6. 令 syncMethod 为 ? GetMethod(value, %Symbol.dispose%)。
  7. 如果 syncMethod 是 undefined,则返回 undefined。
  8. 令 closure 为一个没有参数的新 Abstract Closure,它捕获 syncMethod,并在被调用时执行以下步骤:
    1. 令 obj 为 this 值。
    2. 令 promiseCapability 为 ! NewPromiseCapability(%Promise%)。
    3. 令 result 为 Completion(Call(syncMethod, obj))。
    4. IfAbruptRejectPromise(result, promiseCapability)。
    5. 执行 ! Call(promiseCapability.[[Resolve]], undefined, « undefined »)。
    6. 返回 promiseCapability.[[Promise]]。
  9. 注:此函数对用户代码不可观察。它用于确保同步 %Symbol.dispose% 方法返回的 Promise 不会被 await,并且同步异常会被转换为被拒绝的 Promise。
  10. 返回 CreateBuiltinFunction(closure, 0, "", « »)。

7.5.5 DisposeResources ( disposableResourceStack, completion )

抽象操作 DisposeResources,接收参数 disposableResourceStack (列表 (元素:DisposableResource 记录)) 和 completion ((正常完成 (值:(ECMAScript 语言值 或 empty)) 或 突兀完成));返回值:(正常完成 (值:(ECMAScript 语言值 或 empty)) 或 突兀完成)。 调用时执行以下步骤:

  1. 令 needsAwait 为 false。
  2. 令 hasAwaited 为 false。
  3. 令 outputCompletion 为 completion。
  4. 对 disposableResourceStack 的每个元素 resource,按 List 的逆序执行
    1. 令 value 为 resource.[[ResourceValue]]。
    2. 令 kind 为 resource.[[Kind]]。
    3. 令 method 为 resource.[[DisposeMethod]]。
    4. 如果 kind 是 sync-dispose、needsAwait 是 true 且 hasAwaited 是 false,则
      1. 执行 ! Await(undefined)。
      2. 将 needsAwait 设置为 false。
    5. 如果 method 不是 undefined,则
      1. 令 result 为 Completion(Call(method, value))。
      2. 如果 result 是正常完成且 kind 是 async-dispose,则
        1. 将 result 设置为 Completion(Await(result.[[Value]]))。
        2. 将 hasAwaited 设置为 true。
      3. 如果 result 是抛出完成,则
        1. 如果 outputCompletion 是抛出完成,则
          1. 将 result 设置为 result.[[Value]]。
          2. 令 suppressed 为 outputCompletion.[[Value]]。
          3. 令 error 为新创建的 SuppressedError 对象。
          4. 执行 CreateNonEnumerableDataPropertyOrThrow(error, "error", result)。
          5. 执行 CreateNonEnumerableDataPropertyOrThrow(error, "suppressed", suppressed)。
          6. 将 outputCompletion 设置为 ThrowCompletion(error)。
        2. 否则,
          1. 将 outputCompletion 设置为 result。
    6. 否则,
      1. 断言:kind 是 async-dispose。
      2. 将 needsAwait 设置为 true。
      3. 注:这只能表示 await using 声明的初始化值为 null 或 undefined 的情况。
  5. 如果 needsAwait 是 true 且 hasAwaited 是 false,则
    1. 执行 ! Await(undefined)。
  6. 注:此时将永远不会再次使用 disposableResourceStack。实现可以丢弃 disposableResourceStack 的内容,例如通过垃圾回收。
  7. 返回 ? outputCompletion。

8 语法制导操作

除本节定义的操作外,本规范各处还定义了专门的语法制导操作。

8.1 Runtime Semantics: Evaluation

语法制导操作 Evaluation,接收无参数;返回值:完成记录。

注
此操作的定义分布在本规范的“ECMAScript 语言”各节中。每个定义都出现在相关产生式的定义出现位置之后。

8.2 作用域分析

8.2.1 Static Semantics: BoundNames

语法制导操作 BoundNames,接收无参数;返回值:列表 (元素:String)。

注

在本规范中,当模块的默认导出没有其他名称时,使用 "*default*" 作为其合成名称。会在模块的 [[Environment]] 中使用该名称创建一个条目并保存相应的值,而通过为该模块调用 ResolveExport ( exportName [ , resolveSet ] ) 来解析名为 "default" 的导出时,将返回一个 [[BindingName]] 为 "*default*" 的 ResolvedBinding Record,随后它会在模块的 [[Environment]] 中解析到上述值。这样做只是为了便于规范描述,使匿名默认导出能够像其他任何导出一样被解析。此 "*default*" 字符串永远无法由 ECMAScript 代码或模块链接算法访问。

它按以下产生式分别定义:

BindingIdentifier : Identifier
  1. 返回一个 List,其唯一元素为 Identifier 的 StringValue。
BindingIdentifier : yield
  1. 返回 « "yield" »。
BindingIdentifier : await
  1. 返回 « "await" »。
LexicalDeclaration : LetOrConst BindingList ;
  1. 返回 BindingList 的 BoundNames。
UsingDeclaration : using BindingList ; AwaitUsingDeclaration : CoverAwaitExpressionAndAwaitUsingDeclarationHead BindingList ;
  1. 返回 BindingList 的 BoundNames。
BindingList : BindingList , LexicalBinding
  1. 令 names1 为 BindingList 的 BoundNames。
  2. 令 names2 为 LexicalBinding 的 BoundNames。
  3. 返回 names1 和 names2 的列表连接。
LexicalBinding : BindingIdentifier Initializeropt
  1. 返回 BindingIdentifier 的 BoundNames。
LexicalBinding : BindingPattern Initializer
  1. 返回 BindingPattern 的 BoundNames。
VariableDeclarationList : VariableDeclarationList , VariableDeclaration
  1. 令 names1 为 VariableDeclarationList 的 BoundNames。
  2. 令 names2 为 VariableDeclaration 的 BoundNames。
  3. 返回 names1 和 names2 的列表连接。
VariableDeclaration : BindingIdentifier Initializeropt
  1. 返回 BindingIdentifier 的 BoundNames。
VariableDeclaration : BindingPattern Initializer
  1. 返回 BindingPattern 的 BoundNames。
ObjectBindingPattern : { }
  1. 返回新的空 List。
ObjectBindingPattern : { BindingPropertyList , BindingRestProperty }
  1. 令 names1 为 BindingPropertyList 的 BoundNames。
  2. 令 names2 为 BindingRestProperty 的 BoundNames。
  3. 返回 names1 和 names2 的列表连接。
ArrayBindingPattern : [ Elisionopt ]
  1. 返回新的空 List。
ArrayBindingPattern : [ Elisionopt BindingRestElement ]
  1. 返回 BindingRestElement 的 BoundNames。
ArrayBindingPattern : [ BindingElementList , Elisionopt ]
  1. 返回 BindingElementList 的 BoundNames。
ArrayBindingPattern : [ BindingElementList , Elisionopt BindingRestElement ]
  1. 令 names1 为 BindingElementList 的 BoundNames。
  2. 令 names2 为 BindingRestElement 的 BoundNames。
  3. 返回 names1 和 names2 的列表连接。
BindingPropertyList : BindingPropertyList , BindingProperty
  1. 令 names1 为 BindingPropertyList 的 BoundNames。
  2. 令 names2 为 BindingProperty 的 BoundNames。
  3. 返回 names1 和 names2 的列表连接。
BindingElementList : BindingElementList , BindingElisionElement
  1. 令 names1 为 BindingElementList 的 BoundNames。
  2. 令 names2 为 BindingElisionElement 的 BoundNames。
  3. 返回 names1 和 names2 的列表连接。
BindingElisionElement : Elisionopt BindingElement
  1. 返回 BindingElement 的 BoundNames。
BindingProperty : PropertyName : BindingElement
  1. 返回 BindingElement 的 BoundNames。
SingleNameBinding : BindingIdentifier Initializeropt
  1. 返回 BindingIdentifier 的 BoundNames。
BindingElement : BindingPattern Initializeropt
  1. 返回 BindingPattern 的 BoundNames。
ForDeclaration : LetOrConst ForBinding
  1. 返回 ForBinding 的 BoundNames。
FunctionDeclaration : function BindingIdentifier ( FormalParameters ) { FunctionBody }
  1. 返回 BindingIdentifier 的 BoundNames。
FunctionDeclaration : function ( FormalParameters ) { FunctionBody }
  1. 返回 « "*default*" »。
FormalParameters : [empty]
  1. 返回新的空 List。
FormalParameters : FormalParameterList , FunctionRestParameter
  1. 令 names1 为 FormalParameterList 的 BoundNames。
  2. 令 names2 为 FunctionRestParameter 的 BoundNames。
  3. 返回 names1 和 names2 的列表连接。
FormalParameterList : FormalParameterList , FormalParameter
  1. 令 names1 为 FormalParameterList 的 BoundNames。
  2. 令 names2 为 FormalParameter 的 BoundNames。
  3. 返回 names1 和 names2 的列表连接。
ArrowParameters : CoverParenthesizedExpressionAndArrowParameterList
  1. 令 formals 为 CoverParenthesizedExpressionAndArrowParameterList 所覆盖的 ArrowFormalParameters。
  2. 返回 formals 的 BoundNames。
GeneratorDeclaration : function * BindingIdentifier ( FormalParameters ) { GeneratorBody }
  1. 返回 BindingIdentifier 的 BoundNames。
GeneratorDeclaration : function * ( FormalParameters ) { GeneratorBody }
  1. 返回 « "*default*" »。
AsyncGeneratorDeclaration : async function * BindingIdentifier ( FormalParameters ) { AsyncGeneratorBody }
  1. 返回 BindingIdentifier 的 BoundNames。
AsyncGeneratorDeclaration : async function * ( FormalParameters ) { AsyncGeneratorBody }
  1. 返回 « "*default*" »。
ClassDeclaration : class BindingIdentifier ClassTail
  1. 返回 BindingIdentifier 的 BoundNames。
ClassDeclaration : class ClassTail
  1. 返回 « "*default*" »。
AsyncFunctionDeclaration : async function BindingIdentifier ( FormalParameters ) { AsyncFunctionBody }
  1. 返回 BindingIdentifier 的 BoundNames。
AsyncFunctionDeclaration : async function ( FormalParameters ) { AsyncFunctionBody }
  1. 返回 « "*default*" »。
CoverCallExpressionAndAsyncArrowHead : MemberExpression Arguments
  1. 令 head 为 CoverCallExpressionAndAsyncArrowHead 所覆盖的 AsyncArrowHead。
  2. 返回 head 的 BoundNames。
ImportDeclaration : import ImportClause FromClause WithClauseopt ;
  1. 返回 ImportClause 的 BoundNames。
ImportDeclaration : import ModuleSpecifier WithClauseopt ;
  1. 返回新的空 List。
ImportClause : ImportedDefaultBinding , NameSpaceImport
  1. 令 names1 为 ImportedDefaultBinding 的 BoundNames。
  2. 令 names2 为 NameSpaceImport 的 BoundNames。
  3. 返回 names1 和 names2 的列表连接。
ImportClause : ImportedDefaultBinding , NamedImports
  1. 令 names1 为 ImportedDefaultBinding 的 BoundNames。
  2. 令 names2 为 NamedImports 的 BoundNames。
  3. 返回 names1 和 names2 的列表连接。
NamedImports : { }
  1. 返回新的空 List。
ImportsList : ImportsList , ImportSpecifier
  1. 令 names1 为 ImportsList 的 BoundNames。
  2. 令 names2 为 ImportSpecifier 的 BoundNames。
  3. 返回 names1 和 names2 的列表连接。
ImportSpecifier : ModuleExportName as ImportedBinding
  1. 返回 ImportedBinding 的 BoundNames。
ExportDeclaration : export ExportFromClause FromClause WithClauseopt ; export NamedExports ;
  1. 返回新的空 List。
ExportDeclaration : export VariableStatement
  1. 返回 VariableStatement 的 BoundNames。
ExportDeclaration : export Declaration
  1. 返回 Declaration 的 BoundNames。
ExportDeclaration : export default HoistableDeclaration
  1. 令 declNames 为 HoistableDeclaration 的 BoundNames。
  2. 如果 declNames 不包含元素 "*default*",则将 "*default*" 追加到 declNames。
  3. 返回 declNames。
ExportDeclaration : export default ClassDeclaration
  1. 令 declNames 为 ClassDeclaration 的 BoundNames。
  2. 如果 declNames 不包含元素 "*default*",则将 "*default*" 追加到 declNames。
  3. 返回 declNames。
ExportDeclaration : export default AssignmentExpression ;
  1. 返回 « "*default*" »。

8.2.2 Static Semantics: DeclarationPart

语法制导操作 DeclarationPart,接收无参数;返回值:解析节点。 它按以下产生式分别定义:

HoistableDeclaration : FunctionDeclaration
  1. 返回 FunctionDeclaration。
HoistableDeclaration : GeneratorDeclaration
  1. 返回 GeneratorDeclaration。
HoistableDeclaration : AsyncFunctionDeclaration
  1. 返回 AsyncFunctionDeclaration。
HoistableDeclaration : AsyncGeneratorDeclaration
  1. 返回 AsyncGeneratorDeclaration。
Declaration : ClassDeclaration
  1. 返回 ClassDeclaration。
Declaration : LexicalDeclaration
  1. 返回 LexicalDeclaration。

8.2.3 Static Semantics: IsConstantDeclaration

语法制导操作 IsConstantDeclaration,接收无参数;返回值:Boolean。 它按以下产生式分别定义:

LexicalDeclaration : LetOrConst BindingList ;
  1. 返回 LetOrConst 的 IsConstantDeclaration。
LetOrConst : let
  1. 返回 false。
LetOrConst : const
  1. 返回 true。
UsingDeclaration : using BindingList ; AwaitUsingDeclaration : CoverAwaitExpressionAndAwaitUsingDeclarationHead BindingList ;
  1. 返回 true。
FunctionDeclaration : function BindingIdentifier ( FormalParameters ) { FunctionBody } function ( FormalParameters ) { FunctionBody } GeneratorDeclaration : function * BindingIdentifier ( FormalParameters ) { GeneratorBody } function * ( FormalParameters ) { GeneratorBody } AsyncGeneratorDeclaration : async function * BindingIdentifier ( FormalParameters ) { AsyncGeneratorBody } async function * ( FormalParameters ) { AsyncGeneratorBody } AsyncFunctionDeclaration : async function BindingIdentifier ( FormalParameters ) { AsyncFunctionBody } async function ( FormalParameters ) { AsyncFunctionBody }
  1. 返回 false。
ClassDeclaration : class BindingIdentifier ClassTail class ClassTail
  1. 返回 false。
ExportDeclaration : export ExportFromClause FromClause ; export NamedExports ; export default AssignmentExpression ;
  1. 返回 false。
注

无需将 export default AssignmentExpression 视为常量声明,因为不存在允许向用于引用模块默认对象的内部绑定名称赋值的语法。

8.2.4 Static Semantics: IsUsingDeclaration

语法制导操作 IsUsingDeclaration,接收无参数;返回值:Boolean。 它按以下产生式分别定义:

LexicalDeclaration : LetOrConst BindingList ;
  1. 返回 false。
UsingDeclaration : using BindingList ;
  1. 返回 true。
AwaitUsingDeclaration : CoverAwaitExpressionAndAwaitUsingDeclarationHead BindingList ;
  1. 返回 false。
ForDeclaration : LetOrConst ForBinding
  1. 返回 false。
ForDeclaration : using ForBinding
  1. 返回 true。
ForDeclaration : await using ForBinding
  1. 返回 false。
FunctionDeclaration : function BindingIdentifier ( FormalParameters ) { FunctionBody } function ( FormalParameters ) { FunctionBody } GeneratorDeclaration : function * BindingIdentifier ( FormalParameters ) { GeneratorBody } function * ( FormalParameters ) { GeneratorBody } AsyncGeneratorDeclaration : async function * BindingIdentifier ( FormalParameters ) { AsyncGeneratorBody } async function * ( FormalParameters ) { AsyncGeneratorBody } AsyncFunctionDeclaration : async function BindingIdentifier ( FormalParameters ) { AsyncFunctionBody } async function ( FormalParameters ) { AsyncFunctionBody }
  1. 返回 false。
ClassDeclaration : class BindingIdentifier ClassTail class ClassTail
  1. 返回 false。

8.2.5 Static Semantics: IsAwaitUsingDeclaration

语法制导操作 IsAwaitUsingDeclaration,接收无参数;返回值:Boolean。 它按以下产生式分别定义:

LexicalDeclaration : LetOrConst BindingList ;
  1. 返回 false。
UsingDeclaration : using BindingList ;
  1. 返回 false。
AwaitUsingDeclaration : CoverAwaitExpressionAndAwaitUsingDeclarationHead BindingList ;
  1. 返回 true。
ForDeclaration : LetOrConst ForBinding
  1. 返回 false。
ForDeclaration : using ForBinding
  1. 返回 false。
ForDeclaration : await using ForBinding
  1. 返回 true。
FunctionDeclaration : function BindingIdentifier ( FormalParameters ) { FunctionBody } function ( FormalParameters ) { FunctionBody } GeneratorDeclaration : function * BindingIdentifier ( FormalParameters ) { GeneratorBody } function * ( FormalParameters ) { GeneratorBody } AsyncGeneratorDeclaration : async function * BindingIdentifier ( FormalParameters ) { AsyncGeneratorBody } async function * ( FormalParameters ) { AsyncGeneratorBody } AsyncFunctionDeclaration : async function BindingIdentifier ( FormalParameters ) { AsyncFunctionBody } async function ( FormalParameters ) { AsyncFunctionBody }
  1. 返回 false。
ClassDeclaration : class BindingIdentifier ClassTail class ClassTail
  1. 返回 false。

8.2.6 Static Semantics: LexicallyDeclaredNames

语法制导操作 LexicallyDeclaredNames,接收无参数;返回值:列表 (元素:String)。 它按以下产生式分别定义:

Block : { }
  1. 返回新的空 List。
StatementList : StatementList StatementListItem
  1. 令 names1 为 StatementList 的 LexicallyDeclaredNames。
  2. 令 names2 为 StatementListItem 的 LexicallyDeclaredNames。
  3. 返回 names1 和 names2 的列表连接。
StatementListItem : Statement
  1. 如果 Statement 是 Statement : LabelledStatement ,则返回 LabelledStatement 的 LexicallyDeclaredNames。
  2. 返回新的空 List。
StatementListItem : Declaration
  1. 返回 Declaration 的 BoundNames。
CaseBlock : { }
  1. 返回新的空 List。
CaseBlock : { CaseClausesopt DefaultClause CaseClausesopt }
  1. 如果存在第一个 CaseClauses,则令 names1 为第一个 CaseClauses 的 LexicallyDeclaredNames。
  2. 否则,令 names1 为新的空 List。
  3. 令 names2 为 DefaultClause 的 LexicallyDeclaredNames。
  4. 如果存在第二个 CaseClauses,则令 names3 为第二个 CaseClauses 的 LexicallyDeclaredNames。
  5. 否则,令 names3 为新的空 List。
  6. 返回 names1、names2 和 names3 的列表连接。
CaseClauses : CaseClauses CaseClause
  1. 令 names1 为 CaseClauses 的 LexicallyDeclaredNames。
  2. 令 names2 为 CaseClause 的 LexicallyDeclaredNames。
  3. 返回 names1 和 names2 的列表连接。
CaseClause : case Expression : StatementListopt
  1. 如果存在 StatementList,则返回 StatementList 的 LexicallyDeclaredNames。
  2. 返回新的空 List。
DefaultClause : default : StatementListopt
  1. 如果存在 StatementList,则返回 StatementList 的 LexicallyDeclaredNames。
  2. 返回新的空 List。
LabelledStatement : LabelIdentifier : LabelledItem
  1. 返回 LabelledItem 的 LexicallyDeclaredNames。
LabelledItem : Statement
  1. 返回新的空 List。
LabelledItem : FunctionDeclaration
  1. 返回 FunctionDeclaration 的 BoundNames。
FunctionStatementList : [empty]
  1. 返回新的空 List。
FunctionStatementList : StatementList
  1. 返回 StatementList 的 TopLevelLexicallyDeclaredNames。
ClassStaticBlockStatementList : [empty]
  1. 返回新的空 List。
ClassStaticBlockStatementList : StatementList
  1. 返回 StatementList 的 TopLevelLexicallyDeclaredNames。
ConciseBody : ExpressionBody
  1. 返回新的空 List。
AsyncConciseBody : ExpressionBody
  1. 返回新的空 List。
Script : [empty]
  1. 返回新的空 List。
ScriptBody : StatementList
  1. 返回 StatementList 的 TopLevelLexicallyDeclaredNames。
注 1

在 Script 的顶层,函数声明被视为类似 var 声明,而不是词法声明。

注 2

Module 的 LexicallyDeclaredNames 包括其所有导入绑定的名称。

ModuleItemList : ModuleItemList ModuleItem
  1. 令 names1 为 ModuleItemList 的 LexicallyDeclaredNames。
  2. 令 names2 为 ModuleItem 的 LexicallyDeclaredNames。
  3. 返回 names1 和 names2 的列表连接。
ModuleItem : ImportDeclaration
  1. 返回 ImportDeclaration 的 BoundNames。
ModuleItem : ExportDeclaration
  1. 如果 ExportDeclaration 是 export VariableStatement,则返回新的空 List。
  2. 返回 ExportDeclaration 的 BoundNames。
ModuleItem : StatementListItem
  1. 返回 StatementListItem 的 LexicallyDeclaredNames。
注 3

在 Module 的顶层,函数声明被视为类似词法声明,而不是 var 声明。

8.2.7 Static Semantics: LexicallyScopedDeclarations

语法制导操作 LexicallyScopedDeclarations,接收无参数;返回值:列表 (元素:解析节点)。 它按以下产生式分别定义:

StatementList : StatementList StatementListItem
  1. 令 decls1 为 StatementList 的 LexicallyScopedDeclarations。
  2. 令 decls2 为 StatementListItem 的 LexicallyScopedDeclarations。
  3. 返回 decls1 和 decls2 的列表连接。
StatementListItem : Statement
  1. 如果 Statement 是 Statement : LabelledStatement ,则返回 LabelledStatement 的 LexicallyScopedDeclarations。
  2. 返回新的空 List。
StatementListItem : Declaration
  1. 返回一个 List,其唯一元素为 Declaration 的 DeclarationPart。
CaseBlock : { }
  1. 返回新的空 List。
CaseBlock : { CaseClausesopt DefaultClause CaseClausesopt }
  1. 如果存在第一个 CaseClauses,则令 decls1 为第一个 CaseClauses 的 LexicallyScopedDeclarations。
  2. 否则,令 decls1 为新的空 List。
  3. 令 decls2 为 DefaultClause 的 LexicallyScopedDeclarations。
  4. 如果存在第二个 CaseClauses,则令 decls3 为第二个 CaseClauses 的 LexicallyScopedDeclarations。
  5. 否则,令 decls3 为新的空 List。
  6. 返回 decls1、decls2 和 decls3 的列表连接。
CaseClauses : CaseClauses CaseClause
  1. 令 decls1 为 CaseClauses 的 LexicallyScopedDeclarations。
  2. 令 decls2 为 CaseClause 的 LexicallyScopedDeclarations。
  3. 返回 decls1 和 decls2 的列表连接。
CaseClause : case Expression : StatementListopt
  1. 如果存在 StatementList,则返回 StatementList 的 LexicallyScopedDeclarations。
  2. 返回新的空 List。
DefaultClause : default : StatementListopt
  1. 如果存在 StatementList,则返回 StatementList 的 LexicallyScopedDeclarations。
  2. 返回新的空 List。
LabelledStatement : LabelIdentifier : LabelledItem
  1. 返回 LabelledItem 的 LexicallyScopedDeclarations。
LabelledItem : Statement
  1. 返回新的空 List。
LabelledItem : FunctionDeclaration
  1. 返回 « FunctionDeclaration »。
FunctionStatementList : [empty]
  1. 返回新的空 List。
FunctionStatementList : StatementList
  1. 返回 StatementList 的 TopLevelLexicallyScopedDeclarations。
ClassStaticBlockStatementList : [empty]
  1. 返回新的空 List。
ClassStaticBlockStatementList : StatementList
  1. 返回 StatementList 的 TopLevelLexicallyScopedDeclarations。
ConciseBody : ExpressionBody
  1. 返回新的空 List。
AsyncConciseBody : ExpressionBody
  1. 返回新的空 List。
Script : [empty]
  1. 返回新的空 List。
ScriptBody : StatementList
  1. 返回 StatementList 的 TopLevelLexicallyScopedDeclarations。
Module : [empty]
  1. 返回新的空 List。
ModuleItemList : ModuleItemList ModuleItem
  1. 令 decls1 为 ModuleItemList 的 LexicallyScopedDeclarations。
  2. 令 decls2 为 ModuleItem 的 LexicallyScopedDeclarations。
  3. 返回 decls1 和 decls2 的列表连接。
ModuleItem : ImportDeclaration
  1. 返回新的空 List。
ExportDeclaration : export ExportFromClause FromClause WithClauseopt ; export NamedExports ; export VariableStatement
  1. 返回新的空 List。
ExportDeclaration : export Declaration
  1. 返回一个 List,其唯一元素为 Declaration 的 DeclarationPart。
ExportDeclaration : export default HoistableDeclaration
  1. 返回一个 List,其唯一元素为 HoistableDeclaration 的 DeclarationPart。
ExportDeclaration : export default ClassDeclaration
  1. 返回一个 List,其唯一元素为 ClassDeclaration。
ExportDeclaration : export default AssignmentExpression ;
  1. 返回一个 List,其唯一元素为此 ExportDeclaration。

8.2.8 Static Semantics: VarDeclaredNames

语法制导操作 VarDeclaredNames,接收无参数;返回值:列表 (元素:String)。 它按以下产生式分别定义:

Statement : EmptyStatement ExpressionStatement ContinueStatement BreakStatement ReturnStatement ThrowStatement DebuggerStatement
  1. 返回新的空 List。
Block : { }
  1. 返回新的空 List。
StatementList : StatementList StatementListItem
  1. 令 names1 为 StatementList 的 VarDeclaredNames。
  2. 令 names2 为 StatementListItem 的 VarDeclaredNames。
  3. 返回 names1 和 names2 的列表连接。
StatementListItem : Declaration
  1. 返回新的空 List。
VariableStatement : var VariableDeclarationList ;
  1. 返回 VariableDeclarationList 的 BoundNames。
IfStatement : if ( Expression ) Statement else Statement
  1. 令 names1 为第一个 Statement 的 VarDeclaredNames。
  2. 令 names2 为第二个 Statement 的 VarDeclaredNames。
  3. 返回 names1 和 names2 的列表连接。
IfStatement : if ( Expression ) Statement
  1. 返回 Statement 的 VarDeclaredNames。
DoWhileStatement : do Statement while ( Expression ) ;
  1. 返回 Statement 的 VarDeclaredNames。
WhileStatement : while ( Expression ) Statement
  1. 返回 Statement 的 VarDeclaredNames。
ForStatement : for ( Expressionopt ; Expressionopt ; Expressionopt ) Statement
  1. 返回 Statement 的 VarDeclaredNames。
ForStatement : for ( var VariableDeclarationList ; Expressionopt ; Expressionopt ) Statement
  1. 令 names1 为 VariableDeclarationList 的 BoundNames。
  2. 令 names2 为 Statement 的 VarDeclaredNames。
  3. 返回 names1 和 names2 的列表连接。
ForStatement : for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement
  1. 返回 Statement 的 VarDeclaredNames。
ForInOfStatement : for ( LeftHandSideExpression in Expression ) Statement for ( ForDeclaration in Expression ) Statement for ( LeftHandSideExpression of AssignmentExpression ) Statement for ( ForDeclaration of AssignmentExpression ) Statement for await ( LeftHandSideExpression of AssignmentExpression ) Statement for await ( ForDeclaration of AssignmentExpression ) Statement
  1. 返回 Statement 的 VarDeclaredNames。
ForInOfStatement : for ( var ForBinding in Expression ) Statement for ( var ForBinding of AssignmentExpression ) Statement for await ( var ForBinding of AssignmentExpression ) Statement
  1. 令 names1 为 ForBinding 的 BoundNames。
  2. 令 names2 为 Statement 的 VarDeclaredNames。
  3. 返回 names1 和 names2 的列表连接。
注

本节由附录 B.3.5 扩展。

WithStatement : with ( Expression ) Statement
  1. 返回 Statement 的 VarDeclaredNames。
SwitchStatement : switch ( Expression ) CaseBlock
  1. 返回 CaseBlock 的 VarDeclaredNames。
CaseBlock : { }
  1. 返回新的空 List。
CaseBlock : { CaseClausesopt DefaultClause CaseClausesopt }
  1. 如果存在第一个 CaseClauses,则令 names1 为第一个 CaseClauses 的 VarDeclaredNames。
  2. 否则,令 names1 为新的空 List。
  3. 令 names2 为 DefaultClause 的 VarDeclaredNames。
  4. 如果存在第二个 CaseClauses,则令 names3 为第二个 CaseClauses 的 VarDeclaredNames。
  5. 否则,令 names3 为新的空 List。
  6. 返回 names1、names2 和 names3 的列表连接。
CaseClauses : CaseClauses CaseClause
  1. 令 names1 为 CaseClauses 的 VarDeclaredNames。
  2. 令 names2 为 CaseClause 的 VarDeclaredNames。
  3. 返回 names1 和 names2 的列表连接。
CaseClause : case Expression : StatementListopt
  1. 如果存在 StatementList,则返回 StatementList 的 VarDeclaredNames。
  2. 返回新的空 List。
DefaultClause : default : StatementListopt
  1. 如果存在 StatementList,则返回 StatementList 的 VarDeclaredNames。
  2. 返回新的空 List。
LabelledStatement : LabelIdentifier : LabelledItem
  1. 返回 LabelledItem 的 VarDeclaredNames。
LabelledItem : FunctionDeclaration
  1. 返回新的空 List。
TryStatement : try Block Catch
  1. 令 names1 为 Block 的 VarDeclaredNames。
  2. 令 names2 为 Catch 的 VarDeclaredNames。
  3. 返回 names1 和 names2 的列表连接。
TryStatement : try Block Finally
  1. 令 names1 为 Block 的 VarDeclaredNames。
  2. 令 names2 为 Finally 的 VarDeclaredNames。
  3. 返回 names1 和 names2 的列表连接。
TryStatement : try Block Catch Finally
  1. 令 names1 为 Block 的 VarDeclaredNames。
  2. 令 names2 为 Catch 的 VarDeclaredNames。
  3. 令 names3 为 Finally 的 VarDeclaredNames。
  4. 返回 names1、names2 和 names3 的列表连接。
Catch : catch ( CatchParameter ) Block
  1. 返回 Block 的 VarDeclaredNames。
FunctionStatementList : [empty]
  1. 返回新的空 List。
FunctionStatementList : StatementList
  1. 返回 StatementList 的 TopLevelVarDeclaredNames。
ClassStaticBlockStatementList : [empty]
  1. 返回新的空 List。
ClassStaticBlockStatementList : StatementList
  1. 返回 StatementList 的 TopLevelVarDeclaredNames。
ConciseBody : ExpressionBody
  1. 返回新的空 List。
AsyncConciseBody : ExpressionBody
  1. 返回新的空 List。
Script : [empty]
  1. 返回新的空 List。
ScriptBody : StatementList
  1. 返回 StatementList 的 TopLevelVarDeclaredNames。
ModuleItemList : ModuleItemList ModuleItem
  1. 令 names1 为 ModuleItemList 的 VarDeclaredNames。
  2. 令 names2 为 ModuleItem 的 VarDeclaredNames。
  3. 返回 names1 和 names2 的列表连接。
ModuleItem : ImportDeclaration
  1. 返回新的空 List。
ModuleItem : ExportDeclaration
  1. 如果 ExportDeclaration 是 export VariableStatement,则返回 ExportDeclaration 的 BoundNames。
  2. 返回新的空 List。

8.2.9 Static Semantics: VarScopedDeclarations

语法制导操作 VarScopedDeclarations,接收无参数;返回值:列表 (元素:解析节点)。 它按以下产生式分别定义:

Statement : EmptyStatement ExpressionStatement ContinueStatement BreakStatement ReturnStatement ThrowStatement DebuggerStatement
  1. 返回新的空 List。
Block : { }
  1. 返回新的空 List。
StatementList : StatementList StatementListItem
  1. 令 decls1 为 StatementList 的 VarScopedDeclarations。
  2. 令 decls2 为 StatementListItem 的 VarScopedDeclarations。
  3. 返回 decls1 和 decls2 的列表连接。
StatementListItem : Declaration
  1. 返回新的空 List。
VariableDeclarationList : VariableDeclaration
  1. 返回 « VariableDeclaration »。
VariableDeclarationList : VariableDeclarationList , VariableDeclaration
  1. 令 decls1 为 VariableDeclarationList 的 VarScopedDeclarations。
  2. 返回 decls1 与 « VariableDeclaration » 的列表连接。
IfStatement : if ( Expression ) Statement else Statement
  1. 令 decls1 为第一个 Statement 的 VarScopedDeclarations。
  2. 令 decls2 为第二个 Statement 的 VarScopedDeclarations。
  3. 返回 decls1 和 decls2 的列表连接。
IfStatement : if ( Expression ) Statement
  1. 返回 Statement 的 VarScopedDeclarations。
DoWhileStatement : do Statement while ( Expression ) ;
  1. 返回 Statement 的 VarScopedDeclarations。
WhileStatement : while ( Expression ) Statement
  1. 返回 Statement 的 VarScopedDeclarations。
ForStatement : for ( Expressionopt ; Expressionopt ; Expressionopt ) Statement
  1. 返回 Statement 的 VarScopedDeclarations。
ForStatement : for ( var VariableDeclarationList ; Expressionopt ; Expressionopt ) Statement
  1. 令 decls1 为 VariableDeclarationList 的 VarScopedDeclarations。
  2. 令 decls2 为 Statement 的 VarScopedDeclarations。
  3. 返回 decls1 和 decls2 的列表连接。
ForStatement : for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement
  1. 返回 Statement 的 VarScopedDeclarations。
ForInOfStatement : for ( LeftHandSideExpression in Expression ) Statement for ( ForDeclaration in Expression ) Statement for ( LeftHandSideExpression of AssignmentExpression ) Statement for ( ForDeclaration of AssignmentExpression ) Statement for await ( LeftHandSideExpression of AssignmentExpression ) Statement for await ( ForDeclaration of AssignmentExpression ) Statement
  1. 返回 Statement 的 VarScopedDeclarations。
ForInOfStatement : for ( var ForBinding in Expression ) Statement for ( var ForBinding of AssignmentExpression ) Statement for await ( var ForBinding of AssignmentExpression ) Statement
  1. 令 decls1 为 « ForBinding »。
  2. 令 decls2 为 Statement 的 VarScopedDeclarations。
  3. 返回 decls1 和 decls2 的列表连接。
注

本节由附录 B.3.5 扩展。

WithStatement : with ( Expression ) Statement
  1. 返回 Statement 的 VarScopedDeclarations。
SwitchStatement : switch ( Expression ) CaseBlock
  1. 返回 CaseBlock 的 VarScopedDeclarations。
CaseBlock : { }
  1. 返回新的空 List。
CaseBlock : { CaseClausesopt DefaultClause CaseClausesopt }
  1. 如果存在第一个 CaseClauses,则令 decls1 为第一个 CaseClauses 的 VarScopedDeclarations。
  2. 否则,令 decls1 为新的空 List。
  3. 令 decls2 为 DefaultClause 的 VarScopedDeclarations。
  4. 如果存在第二个 CaseClauses,则令 decls3 为第二个 CaseClauses 的 VarScopedDeclarations。
  5. 否则,令 decls3 为新的空 List。
  6. 返回 decls1、decls2 和 decls3 的列表连接。
CaseClauses : CaseClauses CaseClause
  1. 令 decls1 为 CaseClauses 的 VarScopedDeclarations。
  2. 令 decls2 为 CaseClause 的 VarScopedDeclarations。
  3. 返回 decls1 和 decls2 的列表连接。
CaseClause : case Expression : StatementListopt
  1. 如果存在 StatementList,则返回 StatementList 的 VarScopedDeclarations。
  2. 返回新的空 List。
DefaultClause : default : StatementListopt
  1. 如果存在 StatementList,则返回 StatementList 的 VarScopedDeclarations。
  2. 返回新的空 List。
LabelledStatement : LabelIdentifier : LabelledItem
  1. 返回 LabelledItem 的 VarScopedDeclarations。
LabelledItem : FunctionDeclaration
  1. 返回新的空 List。
TryStatement : try Block Catch
  1. 令 decls1 为 Block 的 VarScopedDeclarations。
  2. 令 decls2 为 Catch 的 VarScopedDeclarations。
  3. 返回 decls1 和 decls2 的列表连接。
TryStatement : try Block Finally
  1. 令 decls1 为 Block 的 VarScopedDeclarations。
  2. 令 decls2 为 Finally 的 VarScopedDeclarations。
  3. 返回 decls1 和 decls2 的列表连接。
TryStatement : try Block Catch Finally
  1. 令 decls1 为 Block 的 VarScopedDeclarations。
  2. 令 decls2 为 Catch 的 VarScopedDeclarations。
  3. 令 decls3 为 Finally 的 VarScopedDeclarations。
  4. 返回 decls1、decls2 和 decls3 的列表连接。
Catch : catch ( CatchParameter ) Block
  1. 返回 Block 的 VarScopedDeclarations。
FunctionStatementList : [empty]
  1. 返回新的空 List。
FunctionStatementList : StatementList
  1. 返回 StatementList 的 TopLevelVarScopedDeclarations。
ClassStaticBlockStatementList : [empty]
  1. 返回新的空 List。
ClassStaticBlockStatementList : StatementList
  1. 返回 StatementList 的 TopLevelVarScopedDeclarations。
ConciseBody : ExpressionBody
  1. 返回新的空 List。
AsyncConciseBody : ExpressionBody
  1. 返回新的空 List。
Script : [empty]
  1. 返回新的空 List。
ScriptBody : StatementList
  1. 返回 StatementList 的 TopLevelVarScopedDeclarations。
Module : [empty]
  1. 返回新的空 List。
ModuleItemList : ModuleItemList ModuleItem
  1. 令 decls1 为 ModuleItemList 的 VarScopedDeclarations。
  2. 令 decls2 为 ModuleItem 的 VarScopedDeclarations。
  3. 返回 decls1 和 decls2 的列表连接。
ModuleItem : ImportDeclaration
  1. 返回新的空 List。
ModuleItem : ExportDeclaration
  1. 如果 ExportDeclaration 是 export VariableStatement,则返回 VariableStatement 的 VarScopedDeclarations。
  2. 返回新的空 List。

8.2.10 Static Semantics: TopLevelLexicallyDeclaredNames

语法制导操作 TopLevelLexicallyDeclaredNames,接收无参数;返回值:列表 (元素:String)。 它按以下产生式分别定义:

StatementList : StatementList StatementListItem
  1. 令 names1 为 StatementList 的 TopLevelLexicallyDeclaredNames。
  2. 令 names2 为 StatementListItem 的 TopLevelLexicallyDeclaredNames。
  3. 返回 names1 和 names2 的列表连接。
StatementListItem : Statement
  1. 返回新的空 List。
StatementListItem : Declaration
  1. 如果 Declaration 是 Declaration : HoistableDeclaration ,则
    1. 返回新的空 List。
  2. 返回 Declaration 的 BoundNames。
注

在函数或脚本的顶层,函数声明被视为类似 var 声明,而不是词法声明。

8.2.11 Static Semantics: TopLevelLexicallyScopedDeclarations

语法制导操作 TopLevelLexicallyScopedDeclarations,接收无参数;返回值:列表 (元素:解析节点)。 它按以下产生式分别定义:

StatementList : StatementList StatementListItem
  1. 令 decls1 为 StatementList 的 TopLevelLexicallyScopedDeclarations。
  2. 令 decls2 为 StatementListItem 的 TopLevelLexicallyScopedDeclarations。
  3. 返回 decls1 和 decls2 的列表连接。
StatementListItem : Statement
  1. 返回新的空 List。
StatementListItem : Declaration
  1. 如果 Declaration 是 Declaration : HoistableDeclaration ,则
    1. 返回新的空 List。
  2. 返回 « Declaration »。

8.2.12 Static Semantics: TopLevelVarDeclaredNames

语法制导操作 TopLevelVarDeclaredNames,接收无参数;返回值:列表 (元素:String)。 它按以下产生式分别定义:

StatementList : StatementList StatementListItem
  1. 令 names1 为 StatementList 的 TopLevelVarDeclaredNames。
  2. 令 names2 为 StatementListItem 的 TopLevelVarDeclaredNames。
  3. 返回 names1 和 names2 的列表连接。
StatementListItem : Declaration
  1. 如果 Declaration 是 Declaration : HoistableDeclaration ,则
    1. 返回 HoistableDeclaration 的 BoundNames。
  2. 返回新的空 List。
StatementListItem : Statement
  1. 如果 Statement 是 Statement : LabelledStatement ,则返回 Statement 的 TopLevelVarDeclaredNames。
  2. 返回 Statement 的 VarDeclaredNames。
注

在函数或脚本的顶层,内部函数声明被视为类似 var 声明。

LabelledStatement : LabelIdentifier : LabelledItem
  1. 返回 LabelledItem 的 TopLevelVarDeclaredNames。
LabelledItem : Statement
  1. 如果 Statement 是 Statement : LabelledStatement ,则返回 Statement 的 TopLevelVarDeclaredNames。
  2. 返回 Statement 的 VarDeclaredNames。
LabelledItem : FunctionDeclaration
  1. 返回 FunctionDeclaration 的 BoundNames。

8.2.13 Static Semantics: TopLevelVarScopedDeclarations

语法制导操作 TopLevelVarScopedDeclarations,接收无参数;返回值:列表 (元素:解析节点)。 它按以下产生式分别定义:

StatementList : StatementList StatementListItem
  1. 令 decls1 为 StatementList 的 TopLevelVarScopedDeclarations。
  2. 令 decls2 为 StatementListItem 的 TopLevelVarScopedDeclarations。
  3. 返回 decls1 和 decls2 的列表连接。
StatementListItem : Statement
  1. 如果 Statement 是 Statement : LabelledStatement ,则返回 Statement 的 TopLevelVarScopedDeclarations。
  2. 返回 Statement 的 VarScopedDeclarations。
StatementListItem : Declaration
  1. 如果 Declaration 是 Declaration : HoistableDeclaration ,则
    1. 令 decl 为 HoistableDeclaration 的 DeclarationPart。
    2. 返回 « decl »。
  2. 返回新的空 List。
LabelledStatement : LabelIdentifier : LabelledItem
  1. 返回 LabelledItem 的 TopLevelVarScopedDeclarations。
LabelledItem : Statement
  1. 如果 Statement 是 Statement : LabelledStatement ,则返回 Statement 的 TopLevelVarScopedDeclarations。
  2. 返回 Statement 的 VarScopedDeclarations。
LabelledItem : FunctionDeclaration
  1. 返回 « FunctionDeclaration »。

8.3 标签

8.3.1 Static Semantics: ContainsDuplicateLabels

语法制导操作 ContainsDuplicateLabels,接收参数 labelSet (列表 (元素:String));返回值:Boolean。 它按以下产生式分别定义:

Statement : VariableStatement EmptyStatement ExpressionStatement ContinueStatement BreakStatement ReturnStatement ThrowStatement DebuggerStatement Block : { } StatementListItem : Declaration
  1. 返回 false。
StatementList : StatementList StatementListItem
  1. 令 hasDuplicates 为以 labelSet 为参数对 StatementList 执行 ContainsDuplicateLabels 的结果。
  2. 如果 hasDuplicates 是 true,则返回 true。
  3. 返回以 labelSet 为参数对 StatementListItem 执行 ContainsDuplicateLabels 的结果。
IfStatement : if ( Expression ) Statement else Statement
  1. 令 hasDuplicate 为以 labelSet 为参数对第一个 Statement 执行 ContainsDuplicateLabels 的结果。
  2. 如果 hasDuplicate 是 true,则返回 true。
  3. 返回以 labelSet 为参数对第二个 Statement 执行 ContainsDuplicateLabels 的结果。
IfStatement : if ( Expression ) Statement
  1. 返回以 labelSet 为参数对 Statement 执行 ContainsDuplicateLabels 的结果。
DoWhileStatement : do Statement while ( Expression ) ;
  1. 返回以 labelSet 为参数对 Statement 执行 ContainsDuplicateLabels 的结果。
WhileStatement : while ( Expression ) Statement
  1. 返回以 labelSet 为参数对 Statement 执行 ContainsDuplicateLabels 的结果。
ForStatement : for ( Expressionopt ; Expressionopt ; Expressionopt ) Statement for ( var VariableDeclarationList ; Expressionopt ; Expressionopt ) Statement for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement
  1. 返回以 labelSet 为参数对 Statement 执行 ContainsDuplicateLabels 的结果。
ForInOfStatement : for ( LeftHandSideExpression in Expression ) Statement for ( var ForBinding in Expression ) Statement for ( ForDeclaration in Expression ) Statement for ( LeftHandSideExpression of AssignmentExpression ) Statement for ( var ForBinding of AssignmentExpression ) Statement for ( ForDeclaration of AssignmentExpression ) Statement for await ( LeftHandSideExpression of AssignmentExpression ) Statement for await ( var ForBinding of AssignmentExpression ) Statement for await ( ForDeclaration of AssignmentExpression ) Statement
  1. 返回以 labelSet 为参数对 Statement 执行 ContainsDuplicateLabels 的结果。
注

本节由附录 B.3.5 扩展。

WithStatement : with ( Expression ) Statement
  1. 返回以 labelSet 为参数对 Statement 执行 ContainsDuplicateLabels 的结果。
SwitchStatement : switch ( Expression ) CaseBlock
  1. 返回以 labelSet 为参数对 CaseBlock 执行 ContainsDuplicateLabels 的结果。
CaseBlock : { }
  1. 返回 false。
CaseBlock : { CaseClausesopt DefaultClause CaseClausesopt }
  1. 如果存在第一个 CaseClauses,则
    1. 如果以 labelSet 为参数对第一个 CaseClauses 执行 ContainsDuplicateLabels 的结果是 true,则返回 true。
  2. 如果以 labelSet 为参数对 DefaultClause 执行 ContainsDuplicateLabels 的结果是 true,则返回 true。
  3. 如果不存在第二个 CaseClauses,则返回 false。
  4. 返回以 labelSet 为参数对第二个 CaseClauses 执行 ContainsDuplicateLabels 的结果。
CaseClauses : CaseClauses CaseClause
  1. 令 hasDuplicates 为以 labelSet 为参数对 CaseClauses 执行 ContainsDuplicateLabels 的结果。
  2. 如果 hasDuplicates 是 true,则返回 true。
  3. 返回以 labelSet 为参数对 CaseClause 执行 ContainsDuplicateLabels 的结果。
CaseClause : case Expression : StatementListopt
  1. 如果存在 StatementList,则返回以 labelSet 为参数对 StatementList 执行 ContainsDuplicateLabels 的结果。
  2. 返回 false。
DefaultClause : default : StatementListopt
  1. 如果存在 StatementList,则返回以 labelSet 为参数对 StatementList 执行 ContainsDuplicateLabels 的结果。
  2. 返回 false。
LabelledStatement : LabelIdentifier : LabelledItem
  1. 令 label 为 LabelIdentifier 的 StringValue。
  2. 如果 labelSet 包含 label,则返回 true。
  3. 令 newLabelSet 为 labelSet 与 « label » 的列表连接。
  4. 返回以 newLabelSet 为参数对 LabelledItem 执行 ContainsDuplicateLabels 的结果。
LabelledItem : FunctionDeclaration
  1. 返回 false。
TryStatement : try Block Catch
  1. 令 hasDuplicates 为以 labelSet 为参数对 Block 执行 ContainsDuplicateLabels 的结果。
  2. 如果 hasDuplicates 是 true,则返回 true。
  3. 返回以 labelSet 为参数对 Catch 执行 ContainsDuplicateLabels 的结果。
TryStatement : try Block Finally
  1. 令 hasDuplicates 为以 labelSet 为参数对 Block 执行 ContainsDuplicateLabels 的结果。
  2. 如果 hasDuplicates 是 true,则返回 true。
  3. 返回以 labelSet 为参数对 Finally 执行 ContainsDuplicateLabels 的结果。
TryStatement : try Block Catch Finally
  1. 如果以 labelSet 为参数对 Block 执行 ContainsDuplicateLabels 的结果是 true,则返回 true。
  2. 如果以 labelSet 为参数对 Catch 执行 ContainsDuplicateLabels 的结果是 true,则返回 true。
  3. 返回以 labelSet 为参数对 Finally 执行 ContainsDuplicateLabels 的结果。
Catch : catch ( CatchParameter ) Block
  1. 返回以 labelSet 为参数对 Block 执行 ContainsDuplicateLabels 的结果。
FunctionStatementList : [empty]
  1. 返回 false。
ClassStaticBlockStatementList : [empty]
  1. 返回 false。
ModuleItemList : ModuleItemList ModuleItem
  1. 令 hasDuplicates 为以 labelSet 为参数对 ModuleItemList 执行 ContainsDuplicateLabels 的结果。
  2. 如果 hasDuplicates 是 true,则返回 true。
  3. 返回以 labelSet 为参数对 ModuleItem 执行 ContainsDuplicateLabels 的结果。
ModuleItem : ImportDeclaration ExportDeclaration
  1. 返回 false。

8.3.2 Static Semantics: ContainsUndefinedBreakTarget

语法制导操作 ContainsUndefinedBreakTarget,接收参数 labelSet (列表 (元素:String));返回值:Boolean。 它按以下产生式分别定义:

Statement : VariableStatement EmptyStatement ExpressionStatement ContinueStatement ReturnStatement ThrowStatement DebuggerStatement Block : { } StatementListItem : Declaration
  1. 返回 false。
StatementList : StatementList StatementListItem
  1. 令 hasUndefinedLabels 为以 labelSet 为参数对 StatementList 执行 ContainsUndefinedBreakTarget 的结果。
  2. 如果 hasUndefinedLabels 是 true,则返回 true。
  3. 返回以 labelSet 为参数对 StatementListItem 执行 ContainsUndefinedBreakTarget 的结果。
IfStatement : if ( Expression ) Statement else Statement
  1. 令 hasUndefinedLabels 为以 labelSet 为参数对第一个 Statement 执行 ContainsUndefinedBreakTarget 的结果。
  2. 如果 hasUndefinedLabels 是 true,则返回 true。
  3. 返回以 labelSet 为参数对第二个 Statement 执行 ContainsUndefinedBreakTarget 的结果。
IfStatement : if ( Expression ) Statement
  1. 返回以 labelSet 为参数对 Statement 执行 ContainsUndefinedBreakTarget 的结果。
DoWhileStatement : do Statement while ( Expression ) ;
  1. 返回以 labelSet 为参数对 Statement 执行 ContainsUndefinedBreakTarget 的结果。
WhileStatement : while ( Expression ) Statement
  1. 返回以 labelSet 为参数对 Statement 执行 ContainsUndefinedBreakTarget 的结果。
ForStatement : for ( Expressionopt ; Expressionopt ; Expressionopt ) Statement for ( var VariableDeclarationList ; Expressionopt ; Expressionopt ) Statement for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement
  1. 返回以 labelSet 为参数对 Statement 执行 ContainsUndefinedBreakTarget 的结果。
ForInOfStatement : for ( LeftHandSideExpression in Expression ) Statement for ( var ForBinding in Expression ) Statement for ( ForDeclaration in Expression ) Statement for ( LeftHandSideExpression of AssignmentExpression ) Statement for ( var ForBinding of AssignmentExpression ) Statement for ( ForDeclaration of AssignmentExpression ) Statement for await ( LeftHandSideExpression of AssignmentExpression ) Statement for await ( var ForBinding of AssignmentExpression ) Statement for await ( ForDeclaration of AssignmentExpression ) Statement
  1. 返回以 labelSet 为参数对 Statement 执行 ContainsUndefinedBreakTarget 的结果。
注

本节由附录 B.3.5 扩展。

BreakStatement : break ;
  1. 返回 false。
BreakStatement : break LabelIdentifier ;
  1. 如果 labelSet 包含 LabelIdentifier 的 StringValue,则返回 false。
  2. 返回 true。
WithStatement : with ( Expression ) Statement
  1. 返回以 labelSet 为参数对 Statement 执行 ContainsUndefinedBreakTarget 的结果。
SwitchStatement : switch ( Expression ) CaseBlock
  1. 返回以 labelSet 为参数对 CaseBlock 执行 ContainsUndefinedBreakTarget 的结果。
CaseBlock : { }
  1. 返回 false。
CaseBlock : { CaseClausesopt DefaultClause CaseClausesopt }
  1. 如果存在第一个 CaseClauses,则
    1. 如果以 labelSet 为参数对第一个 CaseClauses 执行 ContainsUndefinedBreakTarget 的结果是 true,则返回 true。
  2. 如果以 labelSet 为参数对 DefaultClause 执行 ContainsUndefinedBreakTarget 的结果是 true,则返回 true。
  3. 如果不存在第二个 CaseClauses,则返回 false。
  4. 返回以 labelSet 为参数对第二个 CaseClauses 执行 ContainsUndefinedBreakTarget 的结果。
CaseClauses : CaseClauses CaseClause
  1. 令 hasUndefinedLabels 为以 labelSet 为参数对 CaseClauses 执行 ContainsUndefinedBreakTarget 的结果。
  2. 如果 hasUndefinedLabels 是 true,则返回 true。
  3. 返回以 labelSet 为参数对 CaseClause 执行 ContainsUndefinedBreakTarget 的结果。
CaseClause : case Expression : StatementListopt
  1. 如果存在 StatementList,则返回以 labelSet 为参数对 StatementList 执行 ContainsUndefinedBreakTarget 的结果。
  2. 返回 false。
DefaultClause : default : StatementListopt
  1. 如果存在 StatementList,则返回以 labelSet 为参数对 StatementList 执行 ContainsUndefinedBreakTarget 的结果。
  2. 返回 false。
LabelledStatement : LabelIdentifier : LabelledItem
  1. 令 label 为 LabelIdentifier 的 StringValue。
  2. 令 newLabelSet 为 labelSet 与 « label » 的列表连接。
  3. 返回以 newLabelSet 为参数对 LabelledItem 执行 ContainsUndefinedBreakTarget 的结果。
LabelledItem : FunctionDeclaration
  1. 返回 false。
TryStatement : try Block Catch
  1. 令 hasUndefinedLabels 为以 labelSet 为参数对 Block 执行 ContainsUndefinedBreakTarget 的结果。
  2. 如果 hasUndefinedLabels 是 true,则返回 true。
  3. 返回以 labelSet 为参数对 Catch 执行 ContainsUndefinedBreakTarget 的结果。
TryStatement : try Block Finally
  1. 令 hasUndefinedLabels 为以 labelSet 为参数对 Block 执行 ContainsUndefinedBreakTarget 的结果。
  2. 如果 hasUndefinedLabels 是 true,则返回 true。
  3. 返回以 labelSet 为参数对 Finally 执行 ContainsUndefinedBreakTarget 的结果。
TryStatement : try Block Catch Finally
  1. 如果以 labelSet 为参数对 Block 执行 ContainsUndefinedBreakTarget 的结果是 true,则返回 true。
  2. 如果以 labelSet 为参数对 Catch 执行 ContainsUndefinedBreakTarget 的结果是 true,则返回 true。
  3. 返回以 labelSet 为参数对 Finally 执行 ContainsUndefinedBreakTarget 的结果。
Catch : catch ( CatchParameter ) Block
  1. 返回以 labelSet 为参数对 Block 执行 ContainsUndefinedBreakTarget 的结果。
FunctionStatementList : [empty]
  1. 返回 false。
ClassStaticBlockStatementList : [empty]
  1. 返回 false。
ModuleItemList : ModuleItemList ModuleItem
  1. 令 hasUndefinedLabels 为以 labelSet 为参数对 ModuleItemList 执行 ContainsUndefinedBreakTarget 的结果。
  2. 如果 hasUndefinedLabels 是 true,则返回 true。
  3. 返回以 labelSet 为参数对 ModuleItem 执行 ContainsUndefinedBreakTarget 的结果。
ModuleItem : ImportDeclaration ExportDeclaration
  1. 返回 false。

8.3.3 Static Semantics: ContainsUndefinedContinueTarget

语法制导操作 ContainsUndefinedContinueTarget,接收参数 iterationSet (列表 (元素:String)) 和 labelSet (列表 (元素:String));返回值:Boolean。 它按以下产生式分别定义:

Statement : VariableStatement EmptyStatement ExpressionStatement BreakStatement ReturnStatement ThrowStatement DebuggerStatement Block : { } StatementListItem : Declaration
  1. 返回 false。
Statement : BlockStatement
  1. 返回以 iterationSet 和 « » 为参数对 BlockStatement 执行 ContainsUndefinedContinueTarget 的结果。
BreakableStatement : IterationStatement
  1. 令 newIterationSet 为 iterationSet 和 labelSet 的列表连接。
  2. 返回以 newIterationSet 和 « » 为参数对 IterationStatement 执行 ContainsUndefinedContinueTarget 的结果。
StatementList : StatementList StatementListItem
  1. 令 hasUndefinedLabels 为以 iterationSet 和 « » 为参数对 StatementList 执行 ContainsUndefinedContinueTarget 的结果。
  2. 如果 hasUndefinedLabels 是 true,则返回 true。
  3. 返回以 iterationSet 和 « » 为参数对 StatementListItem 执行 ContainsUndefinedContinueTarget 的结果。
IfStatement : if ( Expression ) Statement else Statement
  1. 令 hasUndefinedLabels 为以 iterationSet 和 « » 为参数对第一个 Statement 执行 ContainsUndefinedContinueTarget 的结果。
  2. 如果 hasUndefinedLabels 是 true,则返回 true。
  3. 返回以 iterationSet 和 « » 为参数对第二个 Statement 执行 ContainsUndefinedContinueTarget 的结果。
IfStatement : if ( Expression ) Statement
  1. 返回以 iterationSet 和 « » 为参数对 Statement 执行 ContainsUndefinedContinueTarget 的结果。
DoWhileStatement : do Statement while ( Expression ) ;
  1. 返回以 iterationSet 和 « » 为参数对 Statement 执行 ContainsUndefinedContinueTarget 的结果。
WhileStatement : while ( Expression ) Statement
  1. 返回以 iterationSet 和 « » 为参数对 Statement 执行 ContainsUndefinedContinueTarget 的结果。
ForStatement : for ( Expressionopt ; Expressionopt ; Expressionopt ) Statement for ( var VariableDeclarationList ; Expressionopt ; Expressionopt ) Statement for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement
  1. 返回以 iterationSet 和 « » 为参数对 Statement 执行 ContainsUndefinedContinueTarget 的结果。
ForInOfStatement : for ( LeftHandSideExpression in Expression ) Statement for ( var ForBinding in Expression ) Statement for ( ForDeclaration in Expression ) Statement for ( LeftHandSideExpression of AssignmentExpression ) Statement for ( var ForBinding of AssignmentExpression ) Statement for ( ForDeclaration of AssignmentExpression ) Statement for await ( LeftHandSideExpression of AssignmentExpression ) Statement for await ( var ForBinding of AssignmentExpression ) Statement for await ( ForDeclaration of AssignmentExpression ) Statement
  1. 返回以 iterationSet 和 « » 为参数对 Statement 执行 ContainsUndefinedContinueTarget 的结果。
注

本节由附录 B.3.5 扩展。

ContinueStatement : continue ;
  1. 返回 false。
ContinueStatement : continue LabelIdentifier ;
  1. 如果 iterationSet 包含 LabelIdentifier 的 StringValue,则返回 false。
  2. 返回 true。
WithStatement : with ( Expression ) Statement
  1. 返回以 iterationSet 和 « » 为参数对 Statement 执行 ContainsUndefinedContinueTarget 的结果。
SwitchStatement : switch ( Expression ) CaseBlock
  1. 返回以 iterationSet 和 « » 为参数对 CaseBlock 执行 ContainsUndefinedContinueTarget 的结果。
CaseBlock : { }
  1. 返回 false。
CaseBlock : { CaseClausesopt DefaultClause CaseClausesopt }
  1. 如果存在第一个 CaseClauses,则
    1. 如果以 iterationSet 和 « » 为参数对第一个 CaseClauses 执行 ContainsUndefinedContinueTarget 的结果是 true,则返回 true。
  2. 如果以 iterationSet 和 « » 为参数对 DefaultClause 执行 ContainsUndefinedContinueTarget 的结果是 true,则返回 true。
  3. 如果不存在第二个 CaseClauses,则返回 false。
  4. 返回以 iterationSet 和 « » 为参数对第二个 CaseClauses 执行 ContainsUndefinedContinueTarget 的结果。
CaseClauses : CaseClauses CaseClause
  1. 令 hasUndefinedLabels 为以 iterationSet 和 « » 为参数对 CaseClauses 执行 ContainsUndefinedContinueTarget 的结果。
  2. 如果 hasUndefinedLabels 是 true,则返回 true。
  3. 返回以 iterationSet 和 « » 为参数对 CaseClause 执行 ContainsUndefinedContinueTarget 的结果。
CaseClause : case Expression : StatementListopt
  1. 如果存在 StatementList,则返回以 iterationSet 和 « » 为参数对 StatementList 执行 ContainsUndefinedContinueTarget 的结果。
  2. 返回 false。
DefaultClause : default : StatementListopt
  1. 如果存在 StatementList,则返回以 iterationSet 和 « » 为参数对 StatementList 执行 ContainsUndefinedContinueTarget 的结果。
  2. 返回 false。
LabelledStatement : LabelIdentifier : LabelledItem
  1. 令 label 为 LabelIdentifier 的 StringValue。
  2. 令 newLabelSet 为 labelSet 与 « label » 的列表连接。
  3. 返回以 iterationSet 和 newLabelSet 为参数对 LabelledItem 执行 ContainsUndefinedContinueTarget 的结果。
LabelledItem : FunctionDeclaration
  1. 返回 false。
TryStatement : try Block Catch
  1. 令 hasUndefinedLabels 为以 iterationSet 和 « » 为参数对 Block 执行 ContainsUndefinedContinueTarget 的结果。
  2. 如果 hasUndefinedLabels 是 true,则返回 true。
  3. 返回以 iterationSet 和 « » 为参数对 Catch 执行 ContainsUndefinedContinueTarget 的结果。
TryStatement : try Block Finally
  1. 令 hasUndefinedLabels 为以 iterationSet 和 « » 为参数对 Block 执行 ContainsUndefinedContinueTarget 的结果。
  2. 如果 hasUndefinedLabels 是 true,则返回 true。
  3. 返回以 iterationSet 和 « » 为参数对 Finally 执行 ContainsUndefinedContinueTarget 的结果。
TryStatement : try Block Catch Finally
  1. 如果以 iterationSet 和 « » 为参数对 Block 执行 ContainsUndefinedContinueTarget 的结果是 true,则返回 true。
  2. 如果以 iterationSet 和 « » 为参数对 Catch 执行 ContainsUndefinedContinueTarget 的结果是 true,则返回 true。
  3. 返回以 iterationSet 和 « » 为参数对 Finally 执行 ContainsUndefinedContinueTarget 的结果。
Catch : catch ( CatchParameter ) Block
  1. 返回以 iterationSet 和 « » 为参数对 Block 执行 ContainsUndefinedContinueTarget 的结果。
FunctionStatementList : [empty]
  1. 返回 false。
ClassStaticBlockStatementList : [empty]
  1. 返回 false。
ModuleItemList : ModuleItemList ModuleItem
  1. 令 hasUndefinedLabels 为以 iterationSet 和 « » 为参数对 ModuleItemList 执行 ContainsUndefinedContinueTarget 的结果。
  2. 如果 hasUndefinedLabels 是 true,则返回 true。
  3. 返回以 iterationSet 和 « » 为参数对 ModuleItem 执行 ContainsUndefinedContinueTarget 的结果。
ModuleItem : ImportDeclaration ExportDeclaration
  1. 返回 false。

8.4 函数名称推断

8.4.1 Static Semantics: HasName

语法制导操作 HasName,接收无参数;返回值:Boolean。 它按以下产生式分别定义:

PrimaryExpression : CoverParenthesizedExpressionAndArrowParameterList
  1. 令 expr 为 CoverParenthesizedExpressionAndArrowParameterList 所覆盖的 ParenthesizedExpression。
  2. 如果 expr 的 IsFunctionDefinition 是 false,则返回 false。
  3. 返回 expr 的 HasName。
FunctionExpression : function ( FormalParameters ) { FunctionBody } GeneratorExpression : function * ( FormalParameters ) { GeneratorBody } AsyncGeneratorExpression : async function * ( FormalParameters ) { AsyncGeneratorBody } AsyncFunctionExpression : async function ( FormalParameters ) { AsyncFunctionBody } ArrowFunction : ArrowParameters => ConciseBody AsyncArrowFunction : async AsyncArrowBindingIdentifier => AsyncConciseBody CoverCallExpressionAndAsyncArrowHead => AsyncConciseBody ClassExpression : class ClassTail
  1. 返回 false。
FunctionExpression : function BindingIdentifier ( FormalParameters ) { FunctionBody } GeneratorExpression : function * BindingIdentifier ( FormalParameters ) { GeneratorBody } AsyncGeneratorExpression : async function * BindingIdentifier ( FormalParameters ) { AsyncGeneratorBody } AsyncFunctionExpression : async function BindingIdentifier ( FormalParameters ) { AsyncFunctionBody } ClassExpression : class BindingIdentifier ClassTail
  1. 返回 true。

8.4.2 Static Semantics: IsFunctionDefinition

语法制导操作 IsFunctionDefinition,接收无参数;返回值:Boolean。 它按以下产生式分别定义:

PrimaryExpression : CoverParenthesizedExpressionAndArrowParameterList
  1. 令 expr 为 CoverParenthesizedExpressionAndArrowParameterList 所覆盖的 ParenthesizedExpression。
  2. 返回 expr 的 IsFunctionDefinition。
PrimaryExpression : this IdentifierReference Literal ArrayLiteral ObjectLiteral RegularExpressionLiteral TemplateLiteral MemberExpression : MemberExpression [ Expression ] MemberExpression . IdentifierName MemberExpression TemplateLiteral SuperProperty MetaProperty new MemberExpression Arguments MemberExpression . PrivateIdentifier NewExpression : new NewExpression LeftHandSideExpression : CallExpression OptionalExpression UpdateExpression : LeftHandSideExpression ++ LeftHandSideExpression -- ++ UnaryExpression -- UnaryExpression UnaryExpression : delete UnaryExpression void UnaryExpression typeof UnaryExpression + UnaryExpression - UnaryExpression ~ UnaryExpression ! UnaryExpression CoverAwaitExpressionAndAwaitUsingDeclarationHead ExponentiationExpression : UpdateExpression ** ExponentiationExpression MultiplicativeExpression : MultiplicativeExpression MultiplicativeOperator ExponentiationExpression AdditiveExpression : AdditiveExpression + MultiplicativeExpression AdditiveExpression - MultiplicativeExpression ShiftExpression : ShiftExpression << AdditiveExpression ShiftExpression >> AdditiveExpression ShiftExpression >>> AdditiveExpression RelationalExpression : RelationalExpression < ShiftExpression RelationalExpression > ShiftExpression RelationalExpression <= ShiftExpression RelationalExpression >= ShiftExpression RelationalExpression instanceof ShiftExpression RelationalExpression in ShiftExpression PrivateIdentifier in ShiftExpression EqualityExpression : EqualityExpression == RelationalExpression EqualityExpression != RelationalExpression EqualityExpression === RelationalExpression EqualityExpression !== RelationalExpression BitwiseANDExpression : BitwiseANDExpression & EqualityExpression BitwiseXORExpression : BitwiseXORExpression ^ BitwiseANDExpression BitwiseORExpression : BitwiseORExpression | BitwiseXORExpression LogicalANDExpression : LogicalANDExpression && BitwiseORExpression LogicalORExpression : LogicalORExpression || LogicalANDExpression CoalesceExpression : CoalesceExpressionHead ?? BitwiseORExpression ConditionalExpression : ShortCircuitExpression ? AssignmentExpression : AssignmentExpression AssignmentExpression : YieldExpression LeftHandSideExpression = AssignmentExpression LeftHandSideExpression AssignmentOperator AssignmentExpression LeftHandSideExpression &&= AssignmentExpression LeftHandSideExpression ||= AssignmentExpression LeftHandSideExpression ??= AssignmentExpression Expression : Expression , AssignmentExpression
  1. 返回 false。
AssignmentExpression : ArrowFunction AsyncArrowFunction FunctionExpression : function BindingIdentifieropt ( FormalParameters ) { FunctionBody } GeneratorExpression : function * BindingIdentifieropt ( FormalParameters ) { GeneratorBody } AsyncGeneratorExpression : async function * BindingIdentifieropt ( FormalParameters ) { AsyncGeneratorBody } AsyncFunctionExpression : async function BindingIdentifieropt ( FormalParameters ) { AsyncFunctionBody } ClassExpression : class BindingIdentifieropt ClassTail
  1. 返回 true。

8.4.3 Static Semantics: IsAnonymousFunctionDefinition ( expr )

抽象操作 IsAnonymousFunctionDefinition,接收参数 expr ((an AssignmentExpression Parse Node、an Initializer Parse Node 或 an Expression Parse Node));返回值:Boolean。 它确定其参数是否为不绑定名称的函数定义。 调用时执行以下步骤:

  1. 如果 expr 的 IsFunctionDefinition 是 false,则返回 false。
  2. 令 hasName 为 expr 的 HasName。
  3. 如果 hasName 是 true,则返回 false。
  4. 返回 true。

8.4.4 Static Semantics: IsIdentifierRef

语法制导操作 IsIdentifierRef,接收无参数;返回值:Boolean。 它按以下产生式分别定义:

PrimaryExpression : IdentifierReference
  1. 返回 true。
PrimaryExpression : this Literal ArrayLiteral ObjectLiteral FunctionExpression ClassExpression GeneratorExpression AsyncFunctionExpression AsyncGeneratorExpression RegularExpressionLiteral TemplateLiteral CoverParenthesizedExpressionAndArrowParameterList MemberExpression : MemberExpression [ Expression ] MemberExpression . IdentifierName MemberExpression TemplateLiteral SuperProperty MetaProperty new MemberExpression Arguments MemberExpression . PrivateIdentifier NewExpression : new NewExpression LeftHandSideExpression : CallExpression OptionalExpression
  1. 返回 false。

8.4.5 Runtime Semantics: NamedEvaluation

语法制导操作 NamedEvaluation,接收参数 name ((属性键 或 私有名称));返回值:(正常完成 (值:函数对象) 或 突兀完成)。 它按以下产生式分别定义:

PrimaryExpression : CoverParenthesizedExpressionAndArrowParameterList
  1. 令 expr 为 CoverParenthesizedExpressionAndArrowParameterList 所覆盖的 ParenthesizedExpression。
  2. 返回 ? 以 name 为参数对 expr 执行 NamedEvaluation 的结果。
ParenthesizedExpression : ( Expression )
  1. 断言:IsAnonymousFunctionDefinition(Expression) 是 true。
  2. 返回 ? 以 name 为参数对 Expression 执行 NamedEvaluation 的结果。
FunctionExpression : function ( FormalParameters ) { FunctionBody }
  1. 返回以 name 为参数对 FunctionExpression 执行 InstantiateOrdinaryFunctionExpression 的结果。
GeneratorExpression : function * ( FormalParameters ) { GeneratorBody }
  1. 返回以 name 为参数对 GeneratorExpression 执行 InstantiateGeneratorFunctionExpression 的结果。
AsyncGeneratorExpression : async function * ( FormalParameters ) { AsyncGeneratorBody }
  1. 返回以 name 为参数对 AsyncGeneratorExpression 执行 InstantiateAsyncGeneratorFunctionExpression 的结果。
AsyncFunctionExpression : async function ( FormalParameters ) { AsyncFunctionBody }
  1. 返回以 name 为参数对 AsyncFunctionExpression 执行 InstantiateAsyncFunctionExpression 的结果。
ArrowFunction : ArrowParameters => ConciseBody
  1. 返回以 name 为参数对 ArrowFunction 执行 InstantiateArrowFunctionExpression 的结果。
AsyncArrowFunction : async AsyncArrowBindingIdentifier => AsyncConciseBody CoverCallExpressionAndAsyncArrowHead => AsyncConciseBody
  1. 返回以 name 为参数对 AsyncArrowFunction 执行 InstantiateAsyncArrowFunctionExpression 的结果。
ClassExpression : class ClassTail
  1. 令 sourceText 为 ClassExpression 所匹配的源文本。
  2. 返回 ? 以 undefined、name 和 sourceText 为参数对 ClassTail 执行 ClassDefinitionEvaluation 的结果。

8.5 Contains

8.5.1 Static Semantics: Contains

语法制导操作 Contains,接收参数 symbol (语法符号);返回值:Boolean。

本规范中以下未列出的每个文法产生式候选项,都隐式具有以下 Contains 默认定义:

  1. 对此 Parse Node 的每个子节点 child,执行
    1. 如果 child 是 symbol 的实例,则返回 true。
    2. 如果 child 是某个非终结符的实例,则
      1. 令 contained 为 child Contains symbol 的结果。
      2. 如果 contained 是 true,则返回 true。
  2. 返回 false。
FunctionDeclaration : function BindingIdentifier ( FormalParameters ) { FunctionBody } function ( FormalParameters ) { FunctionBody } FunctionExpression : function BindingIdentifieropt ( FormalParameters ) { FunctionBody } GeneratorDeclaration : function * BindingIdentifier ( FormalParameters ) { GeneratorBody } function * ( FormalParameters ) { GeneratorBody } GeneratorExpression : function * BindingIdentifieropt ( FormalParameters ) { GeneratorBody } AsyncGeneratorDeclaration : async function * BindingIdentifier ( FormalParameters ) { AsyncGeneratorBody } async function * ( FormalParameters ) { AsyncGeneratorBody } AsyncGeneratorExpression : async function * BindingIdentifieropt ( FormalParameters ) { AsyncGeneratorBody } AsyncFunctionDeclaration : async function BindingIdentifier ( FormalParameters ) { AsyncFunctionBody } async function ( FormalParameters ) { AsyncFunctionBody } AsyncFunctionExpression : async function BindingIdentifieropt ( FormalParameters ) { AsyncFunctionBody }
  1. 返回 false。
注 1

依赖子结构的静态语义规则通常不会检查函数定义内部。

ClassTail : ClassHeritageopt { ClassBody }
  1. 如果 symbol 是 ClassBody,则返回 true。
  2. 如果 symbol 是 ClassHeritage,则
    1. 如果存在 ClassHeritage,则返回 true。
    2. 返回 false。
  3. 如果存在 ClassHeritage,则
    1. 如果 ClassHeritage Contains symbol 是 true,则返回 true。
  4. 返回以 symbol 为参数对 ClassBody 执行 ComputedPropertyContains 的结果。
注 2

依赖子结构的静态语义规则通常不会检查类主体内部,但 PropertyName 除外。

ClassStaticBlock : static { ClassStaticBlockBody }
  1. 返回 false。
注 3

依赖子结构的静态语义规则通常不会检查 static 初始化块内部。

ArrowFunction : ArrowParameters => ConciseBody
  1. 如果 symbol 不是 NewTarget、SuperProperty、SuperCall、super 或 this 之一,则返回 false。
  2. 如果 ArrowParameters Contains symbol 是 true,则返回 true。
  3. 返回 ConciseBody Contains symbol。
ArrowParameters : CoverParenthesizedExpressionAndArrowParameterList
  1. 令 formals 为 CoverParenthesizedExpressionAndArrowParameterList 所覆盖的 ArrowFormalParameters。
  2. 返回 formals Contains symbol。
AsyncArrowFunction : async AsyncArrowBindingIdentifier => AsyncConciseBody
  1. 如果 symbol 不是 NewTarget、SuperProperty、SuperCall、super 或 this 之一,则返回 false。
  2. 返回 AsyncConciseBody Contains symbol。
AsyncArrowFunction : CoverCallExpressionAndAsyncArrowHead => AsyncConciseBody
  1. 如果 symbol 不是 NewTarget、SuperProperty、SuperCall、super 或 this 之一,则返回 false。
  2. 令 head 为 CoverCallExpressionAndAsyncArrowHead 所覆盖的 AsyncArrowHead。
  3. 如果 head Contains symbol 是 true,则返回 true。
  4. 返回 AsyncConciseBody Contains symbol。
注 4

Contains 用于检测 ArrowFunction 或 AsyncArrowFunction 中对 new.target、this 和 super 的使用。

PropertyDefinition : MethodDefinition
  1. 如果 symbol 是 MethodDefinition,则返回 true。
  2. 返回以 symbol 为参数对 MethodDefinition 执行 ComputedPropertyContains 的结果。
LiteralPropertyName : IdentifierName
  1. 返回 false。
MemberExpression : MemberExpression . IdentifierName
  1. 如果 MemberExpression Contains symbol 是 true,则返回 true。
  2. 返回 false。
SuperProperty : super . IdentifierName
  1. 如果 symbol 是 ReservedWord super,则返回 true。
  2. 返回 false。
CallExpression : CallExpression . IdentifierName
  1. 如果 CallExpression Contains symbol 是 true,则返回 true。
  2. 返回 false。
OptionalChain : ?. IdentifierName
  1. 返回 false。
OptionalChain : OptionalChain . IdentifierName
  1. 如果 OptionalChain Contains symbol 是 true,则返回 true。
  2. 返回 false。

8.5.2 Static Semantics: ComputedPropertyContains

语法制导操作 ComputedPropertyContains,接收参数 symbol (语法符号);返回值:Boolean。 它按以下产生式分别定义:

ClassElementName : PrivateIdentifier PropertyName : LiteralPropertyName
  1. 返回 false。
PropertyName : ComputedPropertyName
  1. 返回 ComputedPropertyName Contains symbol 的结果。
MethodDefinition : ClassElementName ( UniqueFormalParameters ) { FunctionBody } get ClassElementName ( ) { FunctionBody } set ClassElementName ( PropertySetParameterList ) { FunctionBody }
  1. 返回以 symbol 为参数对 ClassElementName 执行 ComputedPropertyContains 的结果。
GeneratorMethod : * ClassElementName ( UniqueFormalParameters ) { GeneratorBody }
  1. 返回以 symbol 为参数对 ClassElementName 执行 ComputedPropertyContains 的结果。
AsyncGeneratorMethod : async * ClassElementName ( UniqueFormalParameters ) { AsyncGeneratorBody }
  1. 返回以 symbol 为参数对 ClassElementName 执行 ComputedPropertyContains 的结果。
ClassElementList : ClassElementList ClassElement
  1. 令 inList 为以 symbol 为参数对 ClassElementList 执行 ComputedPropertyContains 的结果。
  2. 如果 inList 是 true,则返回 true。
  3. 返回以 symbol 为参数对 ClassElement 执行 ComputedPropertyContains 的结果。
ClassElement : ClassStaticBlock
  1. 返回 false。
ClassElement : ;
  1. 返回 false。
AsyncMethod : async ClassElementName ( UniqueFormalParameters ) { AsyncFunctionBody }
  1. 返回以 symbol 为参数对 ClassElementName 执行 ComputedPropertyContains 的结果。
FieldDefinition : ClassElementName Initializeropt
  1. 返回以 symbol 为参数对 ClassElementName 执行 ComputedPropertyContains 的结果。

8.6 其他操作

这些操作在本规范中的多个位置使用。

8.6.1 Runtime Semantics: InstantiateFunctionObject

语法制导操作 InstantiateFunctionObject,接收参数 envRecord (Environment 记录) 和 privateEnv ((PrivateEnvironment 记录 或 null));返回值:ECMAScript 函数对象。 它按以下产生式分别定义:

FunctionDeclaration : function BindingIdentifier ( FormalParameters ) { FunctionBody } function ( FormalParameters ) { FunctionBody }
  1. 返回以 envRecord 和 privateEnv 为参数对 FunctionDeclaration 执行 InstantiateOrdinaryFunctionObject 的结果。
GeneratorDeclaration : function * BindingIdentifier ( FormalParameters ) { GeneratorBody } function * ( FormalParameters ) { GeneratorBody }
  1. 返回以 envRecord 和 privateEnv 为参数对 GeneratorDeclaration 执行 InstantiateGeneratorFunctionObject 的结果。
AsyncGeneratorDeclaration : async function * BindingIdentifier ( FormalParameters ) { AsyncGeneratorBody } async function * ( FormalParameters ) { AsyncGeneratorBody }
  1. 返回以 envRecord 和 privateEnv 为参数对 AsyncGeneratorDeclaration 执行 InstantiateAsyncGeneratorFunctionObject 的结果。
AsyncFunctionDeclaration : async function BindingIdentifier ( FormalParameters ) { AsyncFunctionBody } async function ( FormalParameters ) { AsyncFunctionBody }
  1. 返回以 envRecord 和 privateEnv 为参数对 AsyncFunctionDeclaration 执行 InstantiateAsyncFunctionObject 的结果。

8.6.2 Runtime Semantics: BindingInitialization

语法制导操作 BindingInitialization,接收参数 value (ECMAScript 语言值) 和 envRecord ((Environment 记录 或 undefined));返回值:(正常完成 (值:unused) 或 突兀完成)。

注

为 envRecord 传递 undefined 表示应使用 PutValue 操作来赋予初始化值。对于 var 语句和某些非严格函数的形式参数列表就是这种情况(参见 10.2.11)。在这些情况下,词法绑定会在对其初始化器求值之前被提升并预先初始化。

它按以下产生式分别定义:

BindingIdentifier : Identifier
  1. 令 name 为 Identifier 的 StringValue。
  2. 返回 ? InitializeBoundName(name, value, envRecord)。
BindingIdentifier : yield
  1. 返回 ? InitializeBoundName("yield", value, envRecord)。
BindingIdentifier : await
  1. 返回 ? InitializeBoundName("await", value, envRecord)。
BindingPattern : ObjectBindingPattern
  1. 执行 ? RequireObjectCoercible(value)。
  2. 返回 ? 以 value 和 envRecord 为参数对 ObjectBindingPattern 执行 BindingInitialization 的结果。
BindingPattern : ArrayBindingPattern
  1. 令 iteratorRecord 为 ? GetIterator(value, sync)。
  2. 令 result 为 Completion(以 iteratorRecord 和 envRecord 为参数对 ArrayBindingPattern 执行 IteratorBindingInitialization 的结果)。
  3. 如果 iteratorRecord.[[Done]] 是 false,则返回 ? IteratorClose(iteratorRecord, result)。
  4. 返回 ? result。
ObjectBindingPattern : { }
  1. 返回 unused。
ObjectBindingPattern : { BindingPropertyList ,opt }
  1. 执行 ? 以 value 和 envRecord 为参数对 BindingPropertyList 执行 PropertyBindingInitialization。
  2. 返回 unused。
ObjectBindingPattern : { BindingRestProperty }
  1. 令 excludedNames 为新的空 List。
  2. 返回 ? 以 value、envRecord 和 excludedNames 为参数对 BindingRestProperty 执行 RestBindingInitialization 的结果。
ObjectBindingPattern : { BindingPropertyList , BindingRestProperty }
  1. 令 excludedNames 为 ? 以 value 和 envRecord 为参数对 BindingPropertyList 执行 PropertyBindingInitialization 的结果。
  2. 返回 ? 以 value、envRecord 和 excludedNames 为参数对 BindingRestProperty 执行 RestBindingInitialization 的结果。

8.6.2.1 InitializeBoundName ( name, value, envRecord )

抽象操作 InitializeBoundName,接收参数 name (String)、value (ECMAScript 语言值) 和 envRecord ((Environment 记录 或 undefined));返回值:(正常完成 (值:unused) 或 突兀完成)。 调用时执行以下步骤:

  1. 如果 envRecord 不是 undefined,则
    1. 执行 ! envRecord.InitializeBinding(name, value)。
    2. 返回 unused。
  2. 令 lhs 为 ? ResolveBinding(name)。
  3. 返回 ? PutValue(lhs, value)。

8.6.3 Runtime Semantics: IteratorBindingInitialization

语法制导操作 IteratorBindingInitialization,接收参数 iteratorRecord (Iterator 记录) 和 envRecord ((Environment 记录 或 undefined));返回值:(正常完成 (值:unused) 或 突兀完成)。

注

当为 envRecord 传递 undefined 时,表示应使用 PutValue 操作来赋予初始化值。非严格函数的形式参数列表就是这种情况。在这种情况下,会预先初始化形式参数绑定,以处理存在多个同名参数的可能性。

它按以下产生式分别定义:

ArrayBindingPattern : [ ]
  1. 返回 unused。
ArrayBindingPattern : [ Elision ]
  1. 返回 ? 以 iteratorRecord 为参数对 Elision 执行 IteratorDestructuringAssignmentEvaluation 的结果。
ArrayBindingPattern : [ Elisionopt BindingRestElement ]
  1. 如果存在 Elision,则
    1. 执行 ? 以 iteratorRecord 为参数对 Elision 执行 IteratorDestructuringAssignmentEvaluation。
  2. 返回 ? 以 iteratorRecord 和 envRecord 为参数对 BindingRestElement 执行 IteratorBindingInitialization 的结果。
ArrayBindingPattern : [ BindingElementList , Elision ]
  1. 执行 ? 以 iteratorRecord 和 envRecord 为参数对 BindingElementList 执行 IteratorBindingInitialization。
  2. 返回 ? 以 iteratorRecord 为参数对 Elision 执行 IteratorDestructuringAssignmentEvaluation 的结果。
ArrayBindingPattern : [ BindingElementList , Elisionopt BindingRestElement ]
  1. 执行 ? 以 iteratorRecord 和 envRecord 为参数对 BindingElementList 执行 IteratorBindingInitialization。
  2. 如果存在 Elision,则
    1. 执行 ? 以 iteratorRecord 为参数对 Elision 执行 IteratorDestructuringAssignmentEvaluation。
  3. 返回 ? 以 iteratorRecord 和 envRecord 为参数对 BindingRestElement 执行 IteratorBindingInitialization 的结果。
BindingElementList : BindingElementList , BindingElisionElement
  1. 执行 ? 以 iteratorRecord 和 envRecord 为参数对 BindingElementList 执行 IteratorBindingInitialization。
  2. 返回 ? 以 iteratorRecord 和 envRecord 为参数对 BindingElisionElement 执行 IteratorBindingInitialization 的结果。
BindingElisionElement : Elision BindingElement
  1. 执行 ? 以 iteratorRecord 为参数对 Elision 执行 IteratorDestructuringAssignmentEvaluation。
  2. 返回 ? 以 iteratorRecord 和 envRecord 为参数对 BindingElement 执行 IteratorBindingInitialization 的结果。
SingleNameBinding : BindingIdentifier Initializeropt
  1. 令 name 为 BindingIdentifier 的 StringValue。
  2. 令 lhs 为 ? ResolveBinding(name, envRecord)。
  3. 令 value 为 undefined。
  4. 如果 iteratorRecord.[[Done]] 是 false,则
    1. 令 next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 next 不是 done,则
      1. 将 value 设置为 next。
  5. 如果存在 Initializer 且 value 是 undefined,则
    1. 如果 IsAnonymousFunctionDefinition(Initializer) 是 true,则
      1. 将 value 设置为 ? 以 name 为参数对 Initializer 执行 NamedEvaluation 的结果。
    2. 否则,
      1. 令 defaultValue 为 ? Initializer 的 Evaluation。
      2. 将 value 设置为 ? GetValue(defaultValue)。
  6. 如果 envRecord 是 undefined,则返回 ? PutValue(lhs, value)。
  7. 返回 ? InitializeReferencedBinding(lhs, value)。
BindingElement : BindingPattern Initializeropt
  1. 令 value 为 undefined。
  2. 如果 iteratorRecord.[[Done]] 是 false,则
    1. 令 next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 next 不是 done,则
      1. 将 value 设置为 next。
  3. 如果存在 Initializer 且 value 是 undefined,则
    1. 令 defaultValue 为 ? Initializer 的 Evaluation。
    2. 将 value 设置为 ? GetValue(defaultValue)。
  4. 返回 ? 以 value 和 envRecord 为参数对 BindingPattern 执行 BindingInitialization 的结果。
BindingRestElement : ... BindingIdentifier
  1. 令 lhs 为 ? ResolveBinding(BindingIdentifier 的 StringValue, envRecord)。
  2. 令 array 为 ! ArrayCreate(0)。
  3. 令 n 为 0。
  4. 重复执行,
    1. 令 next 为 done。
    2. 如果 iteratorRecord.[[Done]] 是 false,则
      1. 将 next 设置为 ? IteratorStepValue(iteratorRecord)。
    3. 如果 next 是 done,则
      1. 如果 envRecord 是 undefined,则返回 ? PutValue(lhs, array)。
      2. 返回 ? InitializeReferencedBinding(lhs, array)。
    4. 执行 ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(n)), next)。
    5. 将 n 设置为 n + 1。
BindingRestElement : ... BindingPattern
  1. 令 array 为 ! ArrayCreate(0)。
  2. 令 n 为 0。
  3. 重复执行,
    1. 令 next 为 done。
    2. 如果 iteratorRecord.[[Done]] 是 false,则
      1. 将 next 设置为 ? IteratorStepValue(iteratorRecord)。
    3. 如果 next 是 done,则
      1. 返回 ? 以 array 和 envRecord 为参数对 BindingPattern 执行 BindingInitialization 的结果。
    4. 执行 ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(n)), next)。
    5. 将 n 设置为 n + 1。
FormalParameters : [empty]
  1. 返回 unused。
FormalParameters : FormalParameterList , FunctionRestParameter
  1. 执行 ? 以 iteratorRecord 和 envRecord 为参数对 FormalParameterList 执行 IteratorBindingInitialization。
  2. 返回 ? 以 iteratorRecord 和 envRecord 为参数对 FunctionRestParameter 执行 IteratorBindingInitialization 的结果。
FormalParameterList : FormalParameterList , FormalParameter
  1. 执行 ? 以 iteratorRecord 和 envRecord 为参数对 FormalParameterList 执行 IteratorBindingInitialization。
  2. 返回 ? 以 iteratorRecord 和 envRecord 为参数对 FormalParameter 执行 IteratorBindingInitialization 的结果。
ArrowParameters : BindingIdentifier
  1. 令 value 为 undefined。
  2. 断言:iteratorRecord.[[Done]] 是 false。
  3. 令 next 为 ? IteratorStepValue(iteratorRecord)。
  4. 如果 next 不是 done,则
    1. 将 value 设置为 next。
  5. 返回 ? 以 value 和 envRecord 为参数对 BindingIdentifier 执行 BindingInitialization 的结果。
ArrowParameters : CoverParenthesizedExpressionAndArrowParameterList
  1. 令 formals 为 CoverParenthesizedExpressionAndArrowParameterList 所覆盖的 ArrowFormalParameters。
  2. 返回 ? 以 iteratorRecord 和 envRecord 为参数对 formals 执行 IteratorBindingInitialization 的结果。
AsyncArrowBindingIdentifier : BindingIdentifier
  1. 令 value 为 undefined。
  2. 断言:iteratorRecord.[[Done]] 是 false。
  3. 令 next 为 ? IteratorStepValue(iteratorRecord)。
  4. 如果 next 不是 done,则
    1. 将 value 设置为 next。
  5. 返回 ? 以 value 和 envRecord 为参数对 BindingIdentifier 执行 BindingInitialization 的结果。

8.6.4 Static Semantics: AssignmentTargetType

语法制导操作 AssignmentTargetType,接收无参数;返回值:(simple、web-compat 或 invalid)。 它按以下产生式分别定义:

IdentifierReference : Identifier
  1. 如果 IsStrict(this IdentifierReference) 是 true,并且 Identifier 的 StringValue 是 "eval" 或 "arguments",则返回 invalid。
  2. 返回 simple。
IdentifierReference : yield await CallExpression : CallExpression [ Expression ] CallExpression . IdentifierName CallExpression . PrivateIdentifier MemberExpression : MemberExpression [ Expression ] MemberExpression . IdentifierName SuperProperty MemberExpression . PrivateIdentifier
  1. 返回 simple。
PrimaryExpression : CoverParenthesizedExpressionAndArrowParameterList
  1. 令 expr 为 CoverParenthesizedExpressionAndArrowParameterList 所覆盖的 ParenthesizedExpression。
  2. 返回 expr 的 AssignmentTargetType。
CallExpression : CoverCallExpressionAndAsyncArrowHead CallExpression Arguments
  1. Normative Optional
    如果宿主是 Web 浏览器或以其他方式支持 函数调用赋值目标的运行时错误,并且 IsStrict(this CallExpression) 是 false,则
    1. 返回 web-compat。
  2. 返回 invalid。
PrimaryExpression : this Literal ArrayLiteral ObjectLiteral FunctionExpression ClassExpression GeneratorExpression AsyncFunctionExpression AsyncGeneratorExpression RegularExpressionLiteral TemplateLiteral CallExpression : SuperCall ImportCall CallExpression TemplateLiteral NewExpression : new NewExpression MemberExpression : MemberExpression TemplateLiteral new MemberExpression Arguments NewTarget : new . target ImportMeta : import . meta LeftHandSideExpression : OptionalExpression UpdateExpression : LeftHandSideExpression ++ LeftHandSideExpression -- ++ UnaryExpression -- UnaryExpression UnaryExpression : delete UnaryExpression void UnaryExpression typeof UnaryExpression + UnaryExpression - UnaryExpression ~ UnaryExpression ! UnaryExpression CoverAwaitExpressionAndAwaitUsingDeclarationHead ExponentiationExpression : UpdateExpression ** ExponentiationExpression MultiplicativeExpression : MultiplicativeExpression MultiplicativeOperator ExponentiationExpression AdditiveExpression : AdditiveExpression + MultiplicativeExpression AdditiveExpression - MultiplicativeExpression ShiftExpression : ShiftExpression << AdditiveExpression ShiftExpression >> AdditiveExpression ShiftExpression >>> AdditiveExpression RelationalExpression : RelationalExpression < ShiftExpression RelationalExpression > ShiftExpression RelationalExpression <= ShiftExpression RelationalExpression >= ShiftExpression RelationalExpression instanceof ShiftExpression RelationalExpression in ShiftExpression PrivateIdentifier in ShiftExpression EqualityExpression : EqualityExpression == RelationalExpression EqualityExpression != RelationalExpression EqualityExpression === RelationalExpression EqualityExpression !== RelationalExpression BitwiseANDExpression : BitwiseANDExpression & EqualityExpression BitwiseXORExpression : BitwiseXORExpression ^ BitwiseANDExpression BitwiseORExpression : BitwiseORExpression | BitwiseXORExpression LogicalANDExpression : LogicalANDExpression && BitwiseORExpression LogicalORExpression : LogicalORExpression || LogicalANDExpression CoalesceExpression : CoalesceExpressionHead ?? BitwiseORExpression ConditionalExpression : ShortCircuitExpression ? AssignmentExpression : AssignmentExpression AssignmentExpression : YieldExpression ArrowFunction AsyncArrowFunction LeftHandSideExpression = AssignmentExpression LeftHandSideExpression AssignmentOperator AssignmentExpression LeftHandSideExpression &&= AssignmentExpression LeftHandSideExpression ||= AssignmentExpression LeftHandSideExpression ??= AssignmentExpression Expression : Expression , AssignmentExpression
  1. 返回 invalid。

8.6.5 Static Semantics: PropName

语法制导操作 PropName,接收无参数;返回值:(String 或 empty)。 它按以下产生式分别定义:

PropertyDefinition : IdentifierReference
  1. 返回 IdentifierReference 的 StringValue。
PropertyDefinition : ... AssignmentExpression
  1. 返回 empty。
PropertyDefinition : PropertyName : AssignmentExpression
  1. 返回 PropertyName 的 PropName。
LiteralPropertyName : IdentifierName AttributeKey : IdentifierName
  1. 返回 IdentifierName 的 StringValue。
LiteralPropertyName : StringLiteral AttributeKey : StringLiteral
  1. 返回 StringLiteral 的 SV。
LiteralPropertyName : NumericLiteral
  1. 令 number 为 NumericLiteral 的 NumericValue。
  2. 返回 ! ToString(number)。
ComputedPropertyName : [ AssignmentExpression ]
  1. 返回 empty。
MethodDefinition : ClassElementName ( UniqueFormalParameters ) { FunctionBody } get ClassElementName ( ) { FunctionBody } set ClassElementName ( PropertySetParameterList ) { FunctionBody }
  1. 返回 ClassElementName 的 PropName。
GeneratorMethod : * ClassElementName ( UniqueFormalParameters ) { GeneratorBody }
  1. 返回 ClassElementName 的 PropName。
AsyncGeneratorMethod : async * ClassElementName ( UniqueFormalParameters ) { AsyncGeneratorBody }
  1. 返回 ClassElementName 的 PropName。
ClassElement : ClassStaticBlock
  1. 返回 empty。
ClassElement : ;
  1. 返回 empty。
AsyncMethod : async ClassElementName ( UniqueFormalParameters ) { AsyncFunctionBody }
  1. 返回 ClassElementName 的 PropName。
FieldDefinition : ClassElementName Initializeropt
  1. 返回 ClassElementName 的 PropName。
ClassElementName : PrivateIdentifier
  1. 返回 empty。

8.6.6 Static Semantics: ContainsUsing

语法制导操作 ContainsUsing,接收无参数;返回值:Boolean。 它按以下产生式分别定义:

StatementList : StatementList StatementListItem
  1. 如果派生的 StatementList 的 ContainsUsing 是 true,则返回 true。
  2. 如果 StatementListItem 的 ContainsUsing 是 true,则返回 true。
  3. 返回 false。
StatementListItem : Statement
  1. 返回 false。
StatementListItem : Declaration
  1. 如果 Declaration 的 IsUsingDeclaration 是 true,则返回 true。
  2. 如果 Declaration 的 IsAwaitUsingDeclaration 是 true,则返回 true。
  3. 返回 false。

9 可执行代码和执行上下文

9.1 Environment Record

Environment Record 是一种规范类型,用于根据 ECMAScript 代码的词法嵌套结构定义 Identifier 与特定变量和函数之间的关联。通常,Environment Record 与 ECMAScript 代码的某些特定句法结构相关联,例如 FunctionDeclaration、BlockStatement 或 TryStatement 的 Catch 子句。每次对此类代码求值时,都会创建一个新的 Environment Record,以记录该代码创建的标识符绑定。

每个 Environment Record 都有一个 [[OuterEnv]] 字段,其值为 null 或对外层 Environment Record 的引用。它用于对 Environment Record 的逻辑嵌套进行建模。一个(内层)Environment Record 的外层引用,是对逻辑上包围该内层 Environment Record 的 Environment Record 的引用。当然,外层 Environment Record 也可以有自己的外层 Environment Record。一个 Environment Record 可以作为多个内层 Environment Record 的外层环境。例如,如果一个 FunctionDeclaration 包含两个嵌套的 FunctionDeclaration,那么每个嵌套函数的 Environment Record 都会以包围它的函数当前求值的 Environment Record 作为其外层 Environment Record。

Environment Record 纯粹是规范机制,无需对应于 ECMAScript 实现中的任何特定产物。ECMAScript 程序无法直接访问或操作此类值。

9.1.1 Environment Record 类型层次结构

可以将 Environment Record 视为存在于一个简单的面向对象层次结构中,其中 Environment Record 是一个抽象类,具有三个具体子类:Declarative Environment Record、Object Environment Record 和 Global Environment Record。Function Environment Record 和 Module Environment Record 是 Declarative Environment Record 的子类。

Environment Record 抽象类包含 表 15 中定义的抽象规范方法。这些抽象方法在每个具体子类中都有不同的具体算法。

表 15: Environment Records的抽象方法
方法 用途 定义
HasBinding ( name )

抽象方法 HasBinding,接收参数 name (String);返回值:(正常完成 (值:Boolean) 或 抛出完成)。

它确定 Environment Record 是否具有 name 的绑定。
它在以下类型中具有具体定义:
CreateMutableBinding ( name, deletable )

抽象方法 CreateMutableBinding,接收参数 name (String) 和 deletable (Boolean);返回值:(正常完成 (值:unused) 或 抛出完成)。

它在 Environment Record 中创建一个新的、但尚未初始化的可变绑定。name 是被绑定名称的文本。如果 deletable 是 true,则该绑定随后可以被删除。
它在以下类型中具有具体定义:
CreateImmutableBinding ( name, strict )

抽象方法 CreateImmutableBinding,接收参数 name (String) 和 strict (Boolean);返回值:(正常完成 (值:unused) 或 抛出完成)。

它在 Environment Record 中创建一个新的、但尚未初始化的不可变绑定。name 是被绑定名称的文本。如果 strict 是 true,那么在该绑定初始化后尝试设置其值时,无论引用该绑定的操作是否处于严格模式,都会抛出异常。
它在以下类型中具有具体定义:
InitializeBinding ( name, value )

抽象方法 InitializeBinding,接收参数 name (String) 和 value (ECMAScript 语言值);返回值:(正常完成 (值:unused) 或 抛出完成)。

它设置 Environment Record 中已存在但尚未初始化的绑定的值。name 是被绑定名称的文本。value 是该绑定的值。
它在以下类型中具有具体定义:
SetMutableBinding ( name, value, strict )

抽象方法 SetMutableBinding,接收参数 name (String)、value (ECMAScript 语言值) 和 strict (Boolean);返回值:(正常完成 (值:unused) 或 抛出完成)。

它设置 Environment Record 中已存在的可变绑定的值。name 是被绑定名称的文本。value 是该绑定的值。如果 strict 是 true 且无法设置该绑定,则会抛出 TypeError 异常。
它在以下类型中具有具体定义:
GetBindingValue ( name, strict )

抽象方法 GetBindingValue,接收参数 name (String) 和 strict (Boolean);返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。

它从 Environment Record 中返回已存在绑定的值。name 是被绑定名称的文本。strict 用于标识源自严格模式代码或以其他方式要求严格模式引用语义的引用。如果 strict 是 true 且绑定不存在,则会抛出 ReferenceError 异常。如果绑定存在但尚未初始化,则无论 strict 的值如何,都会抛出 ReferenceError。
它在以下类型中具有具体定义:
DeleteBinding ( name )

抽象方法 DeleteBinding,接收参数 name (String);返回值:(正常完成 (值:Boolean) 或 抛出完成)。

它从 Environment Record 中删除一个绑定。name 是被绑定名称的文本。如果存在 name 的绑定,则移除该绑定并返回 true。如果绑定存在但无法移除,则返回 false。如果绑定不存在,则返回 true。
它在以下类型中具有具体定义:
HasThisBinding ( )

抽象方法 HasThisBinding,接收无参数;返回值:Boolean。

它确定 Environment Record 是否建立了 this 绑定。如果建立了则返回 true,否则返回 false。
它在以下类型中具有具体定义:
GetThisBinding ( )

抽象方法 GetThisBinding,接收无参数;返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。

它返回此 Environment Record 的 this 绑定值。如果 this 绑定尚未初始化,则抛出 ReferenceError。
它在以下类型中具有具体定义:
HasSuperBinding ( )

抽象方法 HasSuperBinding,接收无参数;返回值:Boolean。

它确定 Environment Record 是否建立了 super 方法绑定。如果建立了则返回 true,否则返回 false。如果返回 true,则意味着该 Environment Record 是 Function Environment Record,不过反过来并不成立。
它在以下类型中具有具体定义:
WithBaseObject ( )

抽象方法 WithBaseObject,接收无参数;返回值:(Object 或 undefined)。

如果此 Environment Record 与 with 语句相关联,则返回该 with 对象。否则返回 undefined。
它在以下类型中具有具体定义:

9.1.1.1 Declarative Environment Record

每个 Declarative Environment Record 都与一个 ECMAScript 程序作用域相关联,该作用域包含变量、常量、let、类、模块、导入和/或函数声明。Declarative Environment Record 绑定其作用域中所包含声明定义的一组标识符。

每个 Declarative Environment Record 还有一个 [[DisposableResourceStack]] 字段,其中包含 DisposableResource Record 的 List。此列表的元素由 using 声明和 await using 声明进行跟踪,并且必须在构造该 Environment Record 的 Evaluation 步骤完成时释放。

9.1.1.1.1 HasBinding ( name )

a Declarative Environment Record envRecord的具体方法 HasBinding,接收参数 name (String);返回值:正常完成 (值:Boolean)。 它确定参数标识符是否为该 Record 绑定的标识符之一。 调用时执行以下步骤:

  1. 如果 envRecord 具有 name 的绑定,则返回 true。
  2. 返回 false。

9.1.1.1.2 CreateMutableBinding ( name, deletable )

a Declarative Environment Record envRecord的具体方法 CreateMutableBinding,接收参数 name (String) 和 deletable (Boolean);返回值:正常完成 (值:unused)。 它为名称 name 创建一个新的、尚未初始化的可变绑定。此 Environment Record 中不得已经存在 name 的绑定。如果 deletable 是 true,则将新绑定标记为可被删除。 调用时执行以下步骤:

  1. 断言:envRecord 尚未具有 name 的绑定。
  2. 在 envRecord 中为 name 创建一个可变绑定,并记录它尚未初始化。如果 deletable 是 true,则记录新创建的绑定可以通过后续的 DeleteBinding 调用被删除。
  3. 返回 unused。

9.1.1.1.3 CreateImmutableBinding ( name, strict )

a Declarative Environment Record envRecord的具体方法 CreateImmutableBinding,接收参数 name (String) 和 strict (Boolean);返回值:正常完成 (值:unused)。 它为名称 name 创建一个新的、尚未初始化的不可变绑定。此 Environment Record 中不得已经存在 name 的绑定。如果 strict 是 true,则将新绑定标记为严格绑定。 调用时执行以下步骤:

  1. 断言:envRecord 尚未具有 name 的绑定。
  2. 在 envRecord 中为 name 创建一个不可变绑定,并记录它尚未初始化。如果 strict 是 true,则记录新创建的绑定是严格绑定。
  3. 返回 unused。

9.1.1.1.4 InitializeBinding ( name, value )

a Declarative Environment Record envRecord的具体方法 InitializeBinding,接收参数 name (String) 和 value (ECMAScript 语言值);返回值:正常完成 (值:unused)。 它用于将名称为 name 的标识符当前绑定的绑定值设置为 value。必须已经存在一个尚未初始化的 name 绑定。 调用时执行以下步骤:

  1. 断言:envRecord 必须具有一个尚未初始化的 name 绑定。
  2. 将 envRecord 中 name 的绑定值设置为 value。
  3. 记录 envRecord 中 name 的绑定已经初始化。
  4. 返回 unused。

9.1.1.1.5 SetMutableBinding ( name, value, strict )

a Declarative Environment Record envRecord的具体方法 SetMutableBinding,接收参数 name (String)、value (ECMAScript 语言值) 和 strict (Boolean);返回值:(正常完成 (值:unused) 或 抛出完成)。 它尝试将名称为 name 的标识符当前绑定的绑定值更改为 value。通常已经存在 name 的绑定,但在极少数情况下也可能不存在。如果该绑定是不可变绑定,并且 strict 是 true,则抛出 TypeError。 调用时执行以下步骤:

  1. 如果 envRecord 不具有 name 的绑定,则
    1. 如果 strict 是 true,则抛出 ReferenceError 异常。
    2. 执行 ! envRecord.CreateMutableBinding(name, true)。
    3. 执行 ! envRecord.InitializeBinding(name, value)。
    4. 返回 unused。
  2. 如果 envRecord 中 name 的绑定是严格绑定,则将 strict 设置为 true。
  3. 如果 envRecord 中 name 的绑定尚未初始化,则
    1. 抛出 ReferenceError 异常。
  4. 否则如果 envRecord 中 name 的绑定是可变绑定,则
    1. 将其绑定值更改为 value。
  5. 否则,
    1. 断言:这是一次更改不可变绑定值的尝试。
    2. 如果 strict 是 true,则抛出 TypeError 异常。
  6. 返回 unused。
注

会在步骤 1 中导致缺失绑定的 ECMAScript 代码示例如下:

function f() { eval("var x; x = (delete x, 0);"); }

9.1.1.1.6 GetBindingValue ( name, strict )

a Declarative Environment Record envRecord的具体方法 GetBindingValue,接收参数 name (String) 和 strict (Boolean);返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。 它返回名称为 name 的已绑定标识符的值。如果绑定存在但尚未初始化,则无论 strict 的值如何,都会抛出 ReferenceError。 调用时执行以下步骤:

  1. 断言:envRecord 具有 name 的绑定。
  2. 如果 envRecord 中 name 的绑定是尚未初始化的绑定,则抛出 ReferenceError 异常。
  3. 返回 envRecord 中当前绑定到 name 的值。

9.1.1.1.7 DeleteBinding ( name )

a Declarative Environment Record envRecord的具体方法 DeleteBinding,接收参数 name (String);返回值:正常完成 (值:Boolean)。 它只能删除已被明确指定为可删除的绑定。 调用时执行以下步骤:

  1. 断言:envRecord 具有 name 的绑定。
  2. 如果 envRecord 中 name 的绑定无法删除,则返回 false。
  3. 从 envRecord 中移除 name 的绑定。
  4. 返回 true。

9.1.1.1.8 HasThisBinding ( )

a Declarative Environment Record envRecord的具体方法 HasThisBinding,接收无参数;返回值:false。 调用时执行以下步骤:

  1. 返回 false。
注

普通 Declarative Environment Record(即既不是 Function Environment Record,也不是 Module Environment Record)不提供 this 绑定。

9.1.1.1.9 GetThisBinding ( )

本规范从不使用 Declarative Environment Record 的 GetThisBinding 具体方法。

9.1.1.1.10 HasSuperBinding ( )

a Declarative Environment Record envRecord的具体方法 HasSuperBinding,接收无参数;返回值:false。 调用时执行以下步骤:

  1. 返回 false。
注

普通 Declarative Environment Record(即既不是 Function Environment Record,也不是 Module Environment Record)不提供 super 绑定。

9.1.1.1.11 WithBaseObject ( )

a Declarative Environment Record envRecord的具体方法 WithBaseObject,接收无参数;返回值:undefined。 调用时执行以下步骤:

  1. 返回 undefined。

9.1.1.2 Object Environment Record

每个 Object Environment Record 都与一个称为其绑定对象的对象相关联。Object Environment Record 绑定一组字符串标识符名称,这些名称直接对应于其绑定对象的属性名称。不属于 IdentifierName 形式的 String 的属性键不包含在被绑定标识符集合中。无论属性的 [[Enumerable]] 特性如何设置,自有属性和继承属性都会包含在该集合中。由于属性可以动态添加到对象或从对象删除,因此 Object Environment Record 所绑定的标识符集合可能会因任何添加或删除属性的操作产生的副作用而发生变化。因这种副作用而创建的任何绑定都被视为可变绑定,即使对应属性的 Writable 特性是 false。Object Environment Record 不存在不可变绑定。

为 with 语句(14.11)创建的 Object Environment Record 可以将其绑定对象作为函数调用中使用的隐式 this 值。此能力由 Boolean [[IsWithEnvironment]] 字段控制。

Object Environment Record 具有 表 16 中列出的附加状态字段。

表 16: Object Environment Record 的附加字段
字段名称 值 含义
[[BindingObject]] Object 此 Environment Record 的绑定对象。
[[IsWithEnvironment]] Boolean 指示此 Environment Record 是否是为 with 语句创建的。

9.1.1.2.1 HasBinding ( name )

an Object Environment Record envRecord的具体方法 HasBinding,接收参数 name (String);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 它确定其关联的绑定对象是否具有名称为 name 的属性。 调用时执行以下步骤:

  1. 令 bindingObj 为 envRecord.[[BindingObject]]。
  2. 令 foundBinding 为 ? HasProperty(bindingObj, name)。
  3. 如果 foundBinding 是 false,则返回 false。
  4. 如果 envRecord.[[IsWithEnvironment]] 是 false,则返回 true。
  5. 令 unscopables 为 ? Get(bindingObj, %Symbol.unscopables%)。
  6. 如果 unscopables 是 Object,则
    1. 令 blocked 为 ToBoolean(? Get(unscopables, name))。
    2. 如果 blocked 是 true,则返回 false。
  7. 返回 true。

9.1.1.2.2 CreateMutableBinding ( name, deletable )

an Object Environment Record envRecord的具体方法 CreateMutableBinding,接收参数 name (String) 和 deletable (Boolean);返回值:(正常完成 (值:unused) 或 抛出完成)。 它在 Environment Record 关联的绑定对象中创建一个名称为 name 的属性,并将其初始化为值 undefined。如果 deletable 是 true,则将新属性的 [[Configurable]] 特性设置为 true;否则设置为 false。 调用时执行以下步骤:

  1. 令 bindingObj 为 envRecord.[[BindingObject]]。
  2. 执行 ? DefinePropertyOrThrow(bindingObj, name, PropertyDescriptor { [[Value]]: undefined, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: deletable })。
  3. 返回 unused。
注

通常 envRecord 不会具有 name 的绑定,但如果确实存在,DefinePropertyOrThrow 的语义可能会导致现有绑定被替换或遮蔽,也可能导致返回突然完成。

9.1.1.2.3 CreateImmutableBinding ( name, strict )

本规范从不使用 Object Environment Record 的 CreateImmutableBinding 具体方法。

9.1.1.2.4 InitializeBinding ( name, value )

an Object Environment Record envRecord的具体方法 InitializeBinding,接收参数 name (String) 和 value (ECMAScript 语言值);返回值:(正常完成 (值:unused) 或 抛出完成)。 它用于将名称为 name 的标识符当前绑定的绑定值设置为 value。 调用时执行以下步骤:

  1. 执行 ? envRecord.SetMutableBinding(name, value, false)。
  2. 返回 unused。
注

在本规范中,对 Object Environment Record 使用 CreateMutableBinding 后,都会立即针对相同名称调用 InitializeBinding。因此,本规范不会显式跟踪 Object Environment Record 中绑定的初始化状态。

9.1.1.2.5 SetMutableBinding ( name, value, strict )

an Object Environment Record envRecord的具体方法 SetMutableBinding,接收参数 name (String)、value (ECMAScript 语言值) 和 strict (Boolean);返回值:(正常完成 (值:unused) 或 抛出完成)。 它尝试将 Environment Record 关联绑定对象中名称为 name 的属性值设置为 value。通常名为 name 的属性已经存在,但如果不存在或当前不可写,则错误处理方式由 strict 决定。 调用时执行以下步骤:

  1. 令 bindingObj 为 envRecord.[[BindingObject]]。
  2. 令 stillExists 为 ? HasProperty(bindingObj, name)。
  3. 如果 stillExists 是 false 且 strict 是 true,则抛出 ReferenceError 异常。
  4. 执行 ? Set(bindingObj, name, value, strict)。
  5. 返回 unused。

9.1.1.2.6 GetBindingValue ( name, strict )

an Object Environment Record envRecord的具体方法 GetBindingValue,接收参数 name (String) 和 strict (Boolean);返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。 它返回其关联绑定对象中名称为 name 的属性值。该属性通常应当已经存在,但如果不存在,则结果取决于 strict。 调用时执行以下步骤:

  1. 令 bindingObj 为 envRecord.[[BindingObject]]。
  2. 令 value 为 ? HasProperty(bindingObj, name)。
  3. 如果 value 是 false,则
    1. 如果 strict 是 false,则返回 undefined。
    2. 抛出 ReferenceError 异常。
  4. 返回 ? Get(bindingObj, name)。

9.1.1.2.7 DeleteBinding ( name )

an Object Environment Record envRecord的具体方法 DeleteBinding,接收参数 name (String);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 它只能删除对应于环境对象中 [[Configurable]] 特性值为 true 的属性的绑定。 调用时执行以下步骤:

  1. 令 bindingObj 为 envRecord.[[BindingObject]]。
  2. 返回 ? bindingObj.[[Delete]](name)。

9.1.1.2.8 HasThisBinding ( )

an Object Environment Record envRecord的具体方法 HasThisBinding,接收无参数;返回值:false。 调用时执行以下步骤:

  1. 返回 false。
注

Object Environment Record 不提供 this 绑定。

9.1.1.2.9 GetThisBinding ( )

本规范从不使用 Object Environment Record 的 GetThisBinding 具体方法。

9.1.1.2.10 HasSuperBinding ( )

an Object Environment Record envRecord的具体方法 HasSuperBinding,接收无参数;返回值:false。 调用时执行以下步骤:

  1. 返回 false。
注

Object Environment Record 不提供 super 绑定。

9.1.1.2.11 WithBaseObject ( )

an Object Environment Record envRecord的具体方法 WithBaseObject,接收无参数;返回值:(Object 或 undefined)。 调用时执行以下步骤:

  1. 如果 envRecord.[[IsWithEnvironment]] 是 true,则返回 envRecord.[[BindingObject]]。
  2. 返回 undefined。

9.1.1.3 Function Environment Record

Function Environment Record 是一种 Declarative Environment Record,用于表示函数的顶层作用域,并且如果该函数不是 ArrowFunction 函数或 AsyncArrowFunction 函数,则提供 this 绑定。如果函数不是 ArrowFunction 函数或 AsyncArrowFunction 函数并且引用了 super,则其 Function Environment Record 还包含用于从函数内部执行 super 方法调用的状态。

Function Environment Record 具有 表 17 中列出的附加状态字段。

表 17: Function Environment Record 的附加字段
字段名称 值 含义
[[ThisValue]] ECMAScript 语言值 这是此次函数调用所使用的 this 值。
[[ThisBindingStatus]] lexical、initialized 或 uninitialized 如果值为 lexical,则这是 ArrowFunction 或 AsyncArrowFunction,并且没有局部 this 值。
[[FunctionObject]] ECMAScript 函数对象 其调用导致创建此 Environment Record 的函数对象。
[[NewTarget]] 构造函数或 undefined 如果此 Environment Record 是由 [[Construct]] 内部方法创建的,则 [[NewTarget]] 是 [[Construct]] 的 newTarget 参数值。否则,其值为 undefined。

Function Environment Record 支持 表 15 中列出的所有 Declarative Environment Record 方法,并且除 HasThisBinding、GetThisBinding 和 HasSuperBinding 外,所有这些方法都共享相同的规范。

9.1.1.3.1 BindThisValue ( envRecord, value )

抽象操作 BindThisValue,接收参数 envRecord (Function Environment 记录) 和 value (ECMAScript 语言值);返回值:(正常完成 (值:unused) 或 抛出完成)。 它设置 envRecord.[[ThisValue]],并记录它已经初始化。 调用时执行以下步骤:

  1. 断言:envRecord.[[ThisBindingStatus]] 不是 lexical。
  2. 如果 envRecord.[[ThisBindingStatus]] 是 initialized,则抛出 ReferenceError 异常。
  3. 将 envRecord.[[ThisValue]] 设置为 value。
  4. 将 envRecord.[[ThisBindingStatus]] 设置为 initialized。
  5. 返回 unused。

9.1.1.3.2 HasThisBinding ( )

a Function Environment Record envRecord的具体方法 HasThisBinding,接收无参数;返回值:Boolean。 调用时执行以下步骤:

  1. 如果 envRecord.[[ThisBindingStatus]] 是 lexical,则返回 false。
  2. 返回 true。

9.1.1.3.3 GetThisBinding ( )

a Function Environment Record envRecord的具体方法 GetThisBinding,接收无参数;返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。 调用时执行以下步骤:

  1. 断言:envRecord.[[ThisBindingStatus]] 不是 lexical。
  2. 如果 envRecord.[[ThisBindingStatus]] 是 uninitialized,则抛出 ReferenceError 异常。
  3. 返回 envRecord.[[ThisValue]]。

9.1.1.3.4 HasSuperBinding ( )

a Function Environment Record envRecord的具体方法 HasSuperBinding,接收无参数;返回值:Boolean。 调用时执行以下步骤:

  1. 如果 envRecord.[[ThisBindingStatus]] 是 lexical,则返回 false。
  2. 如果 envRecord.[[FunctionObject]].[[HomeObject]] 是 undefined,则返回 false。
  3. 返回 true。

9.1.1.3.5 GetSuperBase ( envRecord )

抽象操作 GetSuperBase,接收参数 envRecord (Function Environment 记录);返回值:(Object、null 或 undefined)。 它返回作为绑定在 envRecord 中的 super 属性访问之基对象的对象。值 undefined 表示此类访问将产生运行时错误。 调用时执行以下步骤:

  1. 令 home 为 envRecord.[[FunctionObject]].[[HomeObject]]。
  2. 如果 home 是 undefined,则返回 undefined。
  3. 断言:home 是普通对象。
  4. 返回 ! home.[[GetPrototypeOf]]()。

9.1.1.4 Global Environment Record

Global Environment Record 用于表示由在同一 Realm 中处理的所有 ECMAScript Script 元素共享的最外层作用域。Global Environment Record 为内置全局项(条款 19)、全局对象的属性,以及 Script 中出现的所有顶层声明(8.2.11、8.2.13)提供绑定。

Global Environment Record 在逻辑上是单一 Record,但规范将其定义为封装 Object Environment Record 和 Declarative Environment Record 的组合体。Object Environment Record 以关联 Realm Record 的全局对象作为其基对象。此全局对象就是 Global Environment Record 的 GetThisBinding 具体方法所返回的值。Global Environment Record 的 Object Environment Record 组成部分包含所有内置全局项(条款 19)的绑定,以及全局代码中包含的 FunctionDeclaration、GeneratorDeclaration、AsyncFunctionDeclaration、AsyncGeneratorDeclaration 或 VariableStatement 所引入的所有绑定。全局代码中所有其他 ECMAScript 声明的绑定都包含在 Global Environment Record 的 Declarative Environment Record 组成部分中。

可以直接在全局对象上创建属性。因此,Global Environment Record 的 Object Environment Record 组成部分可能同时包含由 FunctionDeclaration、GeneratorDeclaration、AsyncFunctionDeclaration、AsyncGeneratorDeclaration 或 VariableDeclaration 声明显式创建的绑定,以及作为全局对象属性隐式创建的绑定。

Global Environment Record 具有 表 18 中列出的附加字段。

表 18: Global Environment Record 的附加字段
字段名称 值 含义
[[ObjectRecord]] Object Environment Record 绑定对象是全局对象。它包含全局内置绑定,以及关联 Realm 的全局代码中的 FunctionDeclaration、GeneratorDeclaration、AsyncFunctionDeclaration、AsyncGeneratorDeclaration 和 VariableDeclaration 绑定。
[[GlobalThisValue]] Object 全局作用域中 this 返回的值。宿主可以提供任何 ECMAScript Object 值。
[[DeclarativeRecord]] Declarative Environment Record 包含关联 Realm 的全局代码中除 FunctionDeclaration、GeneratorDeclaration、AsyncFunctionDeclaration、AsyncGeneratorDeclaration 和 VariableDeclaration 绑定之外的所有声明绑定。

9.1.1.4.1 HasBinding ( name )

a Global Environment Record envRecord的具体方法 HasBinding,接收参数 name (String);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 它确定参数标识符是否为该 Record 所绑定的标识符之一。 调用时执行以下步骤:

  1. 令 declRecord 为 envRecord.[[DeclarativeRecord]]。
  2. 如果 ! declRecord.HasBinding(name) 是 true,则返回 true。
  3. 令 objRecord 为 envRecord.[[ObjectRecord]]。
  4. 返回 ? objRecord.HasBinding(name)。

9.1.1.4.2 CreateMutableBinding ( name, deletable )

a Global Environment Record envRecord的具体方法 CreateMutableBinding,接收参数 name (String) 和 deletable (Boolean);返回值:(正常完成 (值:unused) 或 抛出完成)。 它为名称 name 创建一个新的、尚未初始化的可变绑定。该绑定在关联的 DeclarativeRecord 中创建。DeclarativeRecord 中不得已经存在 name 的绑定。如果 deletable 是 true,则将新绑定标记为可被删除。 调用时执行以下步骤:

  1. 令 declRecord 为 envRecord.[[DeclarativeRecord]]。
  2. 如果 ! declRecord.HasBinding(name) 是 true,则抛出 TypeError 异常。
  3. 返回 ! declRecord.CreateMutableBinding(name, deletable)。

9.1.1.4.3 CreateImmutableBinding ( name, strict )

a Global Environment Record envRecord的具体方法 CreateImmutableBinding,接收参数 name (String) 和 strict (Boolean);返回值:(正常完成 (值:unused) 或 抛出完成)。 它为名称 name 创建一个新的、尚未初始化的不可变绑定。此 Environment Record 中不得已经存在 name 的绑定。如果 strict 是 true,则将新绑定标记为严格绑定。 调用时执行以下步骤:

  1. 令 declRecord 为 envRecord.[[DeclarativeRecord]]。
  2. 如果 ! declRecord.HasBinding(name) 是 true,则抛出 TypeError 异常。
  3. 返回 ! declRecord.CreateImmutableBinding(name, strict)。

9.1.1.4.4 InitializeBinding ( name, value )

a Global Environment Record envRecord的具体方法 InitializeBinding,接收参数 name (String) 和 value (ECMAScript 语言值);返回值:(正常完成 (值:unused) 或 抛出完成)。 它用于将名称为 name 的标识符当前绑定的绑定值设置为 value。必须已经存在一个尚未初始化的 name 绑定。 调用时执行以下步骤:

  1. 令 declRecord 为 envRecord.[[DeclarativeRecord]]。
  2. 如果 ! declRecord.HasBinding(name) 是 true,则
    1. 返回 ! declRecord.InitializeBinding(name, value)。
  3. 断言:如果绑定存在,则它必须位于 Object Environment Record 中。
  4. 令 objRecord 为 envRecord.[[ObjectRecord]]。
  5. 返回 ? objRecord.InitializeBinding(name, value)。

9.1.1.4.5 SetMutableBinding ( name, value, strict )

a Global Environment Record envRecord的具体方法 SetMutableBinding,接收参数 name (String)、value (ECMAScript 语言值) 和 strict (Boolean);返回值:(正常完成 (值:unused) 或 抛出完成)。 它尝试将名称为 name 的标识符当前绑定的绑定值更改为 value。如果绑定是不可变绑定并且 strict 是 true,则抛出 TypeError。通常名为 name 的绑定已经存在,但如果不存在或当前不可写,则错误处理方式由 strict 决定。 调用时执行以下步骤:

  1. 令 declRecord 为 envRecord.[[DeclarativeRecord]]。
  2. 如果 ! declRecord.HasBinding(name) 是 true,则
    1. 返回 ? declRecord.SetMutableBinding(name, value, strict)。
  3. 令 objRecord 为 envRecord.[[ObjectRecord]]。
  4. 返回 ? objRecord.SetMutableBinding(name, value, strict)。

9.1.1.4.6 GetBindingValue ( name, strict )

a Global Environment Record envRecord的具体方法 GetBindingValue,接收参数 name (String) 和 strict (Boolean);返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。 它返回名称为 name 的已绑定标识符的值。如果绑定是尚未初始化的绑定,则会抛出 ReferenceError 异常。通常名为 name 的绑定已经存在,但如果不存在或当前不可写,则错误处理方式由 strict 决定。 调用时执行以下步骤:

  1. 令 declRecord 为 envRecord.[[DeclarativeRecord]]。
  2. 如果 ! declRecord.HasBinding(name) 是 true,则
    1. 返回 ? declRecord.GetBindingValue(name, strict)。
  3. 令 objRecord 为 envRecord.[[ObjectRecord]]。
  4. 返回 ? objRecord.GetBindingValue(name, strict)。

9.1.1.4.7 DeleteBinding ( name )

a Global Environment Record envRecord的具体方法 DeleteBinding,接收参数 name (String);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 它只能删除已被明确指定为可删除的绑定。 调用时执行以下步骤:

  1. 令 declRecord 为 envRecord.[[DeclarativeRecord]]。
  2. 如果 ! declRecord.HasBinding(name) 是 true,则
    1. 返回 ! declRecord.DeleteBinding(name)。
  3. 令 objRecord 为 envRecord.[[ObjectRecord]]。
  4. 令 globalObj 为 objRecord.[[BindingObject]]。
  5. 令 existingProperty 为 ? HasOwnProperty(globalObj, name)。
  6. 如果 existingProperty 是 true,则
    1. 返回 ? objRecord.DeleteBinding(name)。
  7. 返回 true。

9.1.1.4.8 HasThisBinding ( )

a Global Environment Record envRecord的具体方法 HasThisBinding,接收无参数;返回值:true。 调用时执行以下步骤:

  1. 返回 true。
注

Global Environment Record 始终提供 this 绑定。

9.1.1.4.9 GetThisBinding ( )

a Global Environment Record envRecord的具体方法 GetThisBinding,接收无参数;返回值:正常完成 (值:Object)。 调用时执行以下步骤:

  1. 返回 envRecord.[[GlobalThisValue]]。

9.1.1.4.10 HasSuperBinding ( )

a Global Environment Record envRecord的具体方法 HasSuperBinding,接收无参数;返回值:false。 调用时执行以下步骤:

  1. 返回 false。
注

Global Environment Record 不提供 super 绑定。

9.1.1.4.11 WithBaseObject ( )

a Global Environment Record envRecord的具体方法 WithBaseObject,接收无参数;返回值:undefined。 调用时执行以下步骤:

  1. 返回 undefined。

9.1.1.4.12 HasLexicalDeclaration ( envRecord, name )

抽象操作 HasLexicalDeclaration,接收参数 envRecord (Global Environment 记录) 和 name (String);返回值:Boolean。 它确定参数标识符在 envRecord 中是否具有由 LexicalDeclaration 或 ClassDeclaration 等词法声明创建的绑定。 调用时执行以下步骤:

  1. 令 declRecord 为 envRecord.[[DeclarativeRecord]]。
  2. 返回 ! declRecord.HasBinding(name)。

9.1.1.4.13 HasRestrictedGlobalProperty ( envRecord, name )

抽象操作 HasRestrictedGlobalProperty,接收参数 envRecord (Global Environment 记录) 和 name (String);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 它确定参数标识符是否为全局对象上不得被全局词法绑定遮蔽的属性名称。 调用时执行以下步骤:

  1. 令 objRecord 为 envRecord.[[ObjectRecord]]。
  2. 令 globalObj 为 objRecord.[[BindingObject]]。
  3. 令 existingProperty 为 ? globalObj.[[GetOwnProperty]](name)。
  4. 如果 existingProperty 是 undefined,则返回 false。
  5. 如果 existingProperty.[[Configurable]] 是 true,则返回 false。
  6. 返回 true。
注

全局对象上可能存在直接创建而不是通过 var 或函数声明来声明的属性。不能创建与全局对象不可配置属性同名的全局词法绑定。全局属性 "undefined" 就是此类属性的一个示例。

9.1.1.4.14 CanDeclareGlobalVar ( envRecord, name )

抽象操作 CanDeclareGlobalVar,接收参数 envRecord (Global Environment 记录) 和 name (String);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 它确定如果使用相同参数 name 调用相应的 CreateGlobalVarBinding,该调用是否会成功。允许冗余的 var 声明以及针对预先存在的全局对象属性的 var 声明。 调用时执行以下步骤:

  1. 令 objRecord 为 envRecord.[[ObjectRecord]]。
  2. 令 globalObj 为 objRecord.[[BindingObject]]。
  3. 令 hasProperty 为 ? HasOwnProperty(globalObj, name)。
  4. 如果 hasProperty 是 true,则返回 true。
  5. 返回 ? IsExtensible(globalObj)。

9.1.1.4.15 CanDeclareGlobalFunction ( envRecord, name )

抽象操作 CanDeclareGlobalFunction,接收参数 envRecord (Global Environment 记录) 和 name (String);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 它确定如果使用相同参数 name 调用相应的 CreateGlobalFunctionBinding,该调用是否会成功。 调用时执行以下步骤:

  1. 令 objRecord 为 envRecord.[[ObjectRecord]]。
  2. 令 globalObj 为 objRecord.[[BindingObject]]。
  3. 令 existingProperty 为 ? globalObj.[[GetOwnProperty]](name)。
  4. 如果 existingProperty 是 undefined,则返回 ? IsExtensible(globalObj)。
  5. 如果 existingProperty.[[Configurable]] 是 true,则返回 true。
  6. 如果 IsDataDescriptor(existingProperty) 是 true,并且 existingProperty 的特性值为 { [[Writable]]: true, [[Enumerable]]: true },则返回 true。
  7. 返回 false。

9.1.1.4.16 CreateGlobalVarBinding ( envRecord, name, deletable )

抽象操作 CreateGlobalVarBinding,接收参数 envRecord (Global Environment 记录)、name (String) 和 deletable (Boolean);返回值:(正常完成 (值:unused) 或 抛出完成)。 它在关联的 Object Environment Record 中创建并初始化一个可变绑定。如果绑定已经存在,则复用该绑定,并假定它已初始化。 调用时执行以下步骤:

  1. 令 objRecord 为 envRecord.[[ObjectRecord]]。
  2. 令 globalObj 为 objRecord.[[BindingObject]]。
  3. 令 hasProperty 为 ? HasOwnProperty(globalObj, name)。
  4. 令 extensible 为 ? IsExtensible(globalObj)。
  5. 如果 hasProperty 是 false 且 extensible 是 true,则
    1. 执行 ? objRecord.CreateMutableBinding(name, deletable)。
    2. 执行 ? objRecord.InitializeBinding(name, undefined)。
  6. 返回 unused。

9.1.1.4.17 CreateGlobalFunctionBinding ( envRecord, name, value, deletable )

抽象操作 CreateGlobalFunctionBinding,接收参数 envRecord (Global Environment 记录)、name (String)、value (ECMAScript 函数对象) 和 deletable (Boolean);返回值:(正常完成 (值:unused) 或 抛出完成)。 它在关联的 Object Environment Record 中创建并初始化一个可变绑定。如果绑定已经存在,则替换该绑定。 调用时执行以下步骤:

  1. 令 objRecord 为 envRecord.[[ObjectRecord]]。
  2. 令 globalObj 为 objRecord.[[BindingObject]]。
  3. 令 existingProperty 为 ? globalObj.[[GetOwnProperty]](name)。
  4. 如果 existingProperty 是 undefined 或 existingProperty.[[Configurable]] 是 true,则
    1. 令 propertyDesc 为 PropertyDescriptor { [[Value]]: value, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: deletable }。
  5. 否则,
    1. 令 propertyDesc 为 PropertyDescriptor { [[Value]]: value }。
  6. 执行 ? DefinePropertyOrThrow(globalObj, name, propertyDesc)。
  7. 执行 ? Set(globalObj, name, value, false)。
  8. 返回 unused。
注

全局函数声明始终表示为全局对象的自有属性。如果可能,会重新配置现有自有属性,使其具有一组标准特性值。步骤 7 等价于调用 InitializeBinding 具体方法所执行的操作,并且如果 globalObj 是 Proxy,将产生相同的 Proxy 陷阱调用序列。

9.1.1.5 Module Environment Record

Module Environment Record 是一种 Declarative Environment Record,用于表示 ECMAScript Module 的外层作用域。除了普通的可变和不可变绑定之外,Module Environment Record 还提供不可变导入绑定,这类绑定会间接访问另一个 Environment Record 中存在的目标绑定。

Module Environment Record 支持 表 15 中列出的所有 Declarative Environment Record 方法,并且除 GetBindingValue、DeleteBinding、HasThisBinding 和 GetThisBinding 外,所有这些方法都共享相同的规范。

9.1.1.5.1 GetBindingValue ( name, strict )

a Module Environment Record envRecord的具体方法 GetBindingValue,接收参数 name (String) 和 strict (Boolean);返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。 它返回名称为 name 的已绑定标识符的值。但是,如果该绑定是间接绑定,则返回目标绑定的值。如果绑定存在但尚未初始化,则抛出 ReferenceError。 调用时执行以下步骤:

  1. 断言:strict 是 true。
  2. 断言:envRecord 具有 name 的绑定。
  3. 如果 name 的绑定是间接绑定,则
    1. 令 module 和 targetName 为创建 name 的此绑定时所提供的间接引用值。
    2. 令 targetEnv 为 module.[[Environment]]。
    3. 如果 targetEnv 是 empty,则抛出 ReferenceError 异常。
    4. 返回 ? targetEnv.GetBindingValue(targetName, true)。
  4. 如果 envRecord 中 name 的绑定是尚未初始化的绑定,则抛出 ReferenceError 异常。
  5. 返回 envRecord 中当前绑定到 name 的值。
注

因为 Module 始终是严格模式代码,所以 strict 始终为 true。

9.1.1.5.2 DeleteBinding ( name )

本规范从不使用 Module Environment Record 的 DeleteBinding 具体方法。

注

Module Environment Record 仅在严格模式代码中使用,并且提前错误规则会阻止在严格模式代码中将 delete 运算符应用于会解析到 Module Environment Record 绑定的 Reference Record。参见 13.5.1.1。

9.1.1.5.3 HasThisBinding ( )

a Module Environment Record envRecord的具体方法 HasThisBinding,接收无参数;返回值:true。 调用时执行以下步骤:

  1. 返回 true。
注

Module Environment Record 始终提供 this 绑定。

9.1.1.5.4 GetThisBinding ( )

a Module Environment Record envRecord的具体方法 GetThisBinding,接收无参数;返回值:正常完成 (值:undefined)。 调用时执行以下步骤:

  1. 返回 undefined。

9.1.1.5.5 CreateImportBinding ( envRecord, name, targetModule, targetName )

抽象操作 CreateImportBinding,接收参数 envRecord (Module Environment 记录)、name (String)、targetModule (Module 记录) 和 targetName (String);返回值:unused。 它为名称 name 创建一个新的、已初始化的不可变间接绑定。envRecord 中不得已经存在 name 的绑定。targetName 是 targetModule 的 Module Environment Record 中存在的绑定名称。访问新绑定的值时,将间接访问目标绑定的绑定值。 调用时执行以下步骤:

  1. 断言:envRecord 尚未具有 name 的绑定。
  2. 断言:当 targetModule.[[Environment]] 被实例化时,它将具有 targetName 的直接绑定。
  3. 在 envRecord 中为 name 创建一个不可变间接绑定,以 targetModule 和 targetName 作为其目标绑定,并记录该绑定已初始化。
  4. 返回 unused。

9.1.2 Environment Record 操作

本规范使用以下抽象操作来操作 Environment Record:

9.1.2.1 GetIdentifierReference ( envRecord, name, strict )

抽象操作 GetIdentifierReference,接收参数 envRecord ((Environment 记录 或 null))、name (String) 和 strict (Boolean);返回值:(正常完成 (值:Reference 记录) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 envRecord 是 null,则
    1. 返回 Reference Record { [[Base]]: unresolvable, [[ReferencedName]]: name, [[Strict]]: strict, [[ThisValue]]: empty }。
  2. 令 exists 为 ? envRecord.HasBinding(name)。
  3. 如果 exists 是 true,则
    1. 返回 Reference Record { [[Base]]: envRecord, [[ReferencedName]]: name, [[Strict]]: strict, [[ThisValue]]: empty }。
  4. 令 outer 为 envRecord.[[OuterEnv]]。
  5. 返回 ? GetIdentifierReference(outer, name, strict)。

9.1.2.2 NewDeclarativeEnvironment ( outerEnv )

抽象操作 NewDeclarativeEnvironment,接收参数 outerEnv ((Environment 记录 或 null));返回值:Declarative Environment 记录。 调用时执行以下步骤:

  1. 令 envRecord 为不包含任何绑定的新 Declarative Environment Record。
  2. 将 envRecord.[[OuterEnv]] 设置为 outerEnv。
  3. 将 envRecord.[[DisposableResourceStack]] 设置为新的空 List。
  4. 返回 envRecord。

9.1.2.3 NewObjectEnvironment ( obj, isWithEnv, outerEnv )

抽象操作 NewObjectEnvironment,接收参数 obj (Object)、isWithEnv (Boolean) 和 outerEnv ((Environment 记录 或 null));返回值:Object Environment 记录。 调用时执行以下步骤:

  1. 令 envRecord 为新的 Object Environment Record。
  2. 将 envRecord.[[BindingObject]] 设置为 obj。
  3. 将 envRecord.[[IsWithEnvironment]] 设置为 isWithEnv。
  4. 将 envRecord.[[OuterEnv]] 设置为 outerEnv。
  5. 返回 envRecord。

9.1.2.4 NewFunctionEnvironment ( func, newTarget )

抽象操作 NewFunctionEnvironment,接收参数 func (ECMAScript 函数对象) 和 newTarget ((Object 或 undefined));返回值:Function Environment 记录。 调用时执行以下步骤:

  1. 令 envRecord 为不包含任何绑定的新 Function Environment Record。
  2. 将 envRecord.[[FunctionObject]] 设置为 func。
  3. 如果 func.[[ThisMode]] 是 lexical,则将 envRecord.[[ThisBindingStatus]] 设置为 lexical。
  4. 否则,将 envRecord.[[ThisBindingStatus]] 设置为 uninitialized。
  5. 将 envRecord.[[NewTarget]] 设置为 newTarget。
  6. 将 envRecord.[[OuterEnv]] 设置为 func.[[Environment]]。
  7. 将 envRecord.[[DisposableResourceStack]] 设置为新的空 List。
  8. 返回 envRecord。

9.1.2.5 NewGlobalEnvironment ( obj, thisValue )

抽象操作 NewGlobalEnvironment,接收参数 obj (Object) 和 thisValue (Object);返回值:Global Environment 记录。 调用时执行以下步骤:

  1. 令 objRecord 为 NewObjectEnvironment(obj, false, null)。
  2. 令 declRecord 为 NewDeclarativeEnvironment(null)。
  3. 令 envRecord 为新的 Global Environment Record。
  4. 将 envRecord.[[ObjectRecord]] 设置为 objRecord。
  5. 将 envRecord.[[GlobalThisValue]] 设置为 thisValue。
  6. 将 envRecord.[[DeclarativeRecord]] 设置为 declRecord。
  7. 将 envRecord.[[OuterEnv]] 设置为 null。
  8. 返回 envRecord。

9.1.2.6 NewModuleEnvironment ( outerEnv )

抽象操作 NewModuleEnvironment,接收参数 outerEnv (Global Environment 记录);返回值:Module Environment 记录。 调用时执行以下步骤:

  1. 令 envRecord 为不包含任何绑定的新 Module Environment Record。
  2. 将 envRecord.[[OuterEnv]] 设置为 outerEnv。
  3. 将 envRecord.[[DisposableResourceStack]] 设置为新的空 List。
  4. 返回 envRecord。

9.2 PrivateEnvironment Record

PrivateEnvironment Record 是一种规范机制,用于根据 ECMAScript 代码中 ClassDeclaration 和 ClassExpression 的词法嵌套结构跟踪 Private Name。它们与 Environment Record 类似,但彼此不同。每个 PrivateEnvironment Record 都与一个 ClassDeclaration 或 ClassExpression 相关联。每次对此类类进行求值时,都会创建一个新的 PrivateEnvironment Record,以记录该类声明的 Private Name。

每个 PrivateEnvironment Record 都具有 表 19 中定义的字段。

表 19: PrivateEnvironment Record 字段
字段名称 值类型 含义
[[OuterPrivateEnvironment]] PrivateEnvironment Record 或 null 最近的包含类的 PrivateEnvironment Record。如果与此 PrivateEnvironment Record 关联的类未包含在任何其他类中,则为 null。
[[Names]] Private Name 的 List 此类声明的 Private Name。

9.2.1 PrivateEnvironment Record 操作

本规范使用以下抽象操作来操作 PrivateEnvironment Record:

9.2.1.1 NewPrivateEnvironment ( outerPrivateEnv )

抽象操作 NewPrivateEnvironment,接收参数 outerPrivateEnv ((PrivateEnvironment 记录 或 null));返回值:PrivateEnvironment 记录。 调用时执行以下步骤:

  1. 令 names 为新的空 List。
  2. 返回 PrivateEnvironment Record { [[OuterPrivateEnvironment]]: outerPrivateEnv, [[Names]]: names }。

9.2.1.2 ResolvePrivateIdentifier ( privateEnv, identifier )

抽象操作 ResolvePrivateIdentifier,接收参数 privateEnv (PrivateEnvironment 记录) 和 identifier (String);返回值:私有名称。 调用时执行以下步骤:

  1. 令 names 为 privateEnv.[[Names]]。
  2. 对 names 的每个 Private Name privateName,执行
    1. 如果 privateName.[[Description]] 是 identifier,则
      1. 返回 privateName。
  3. 令 outerPrivateEnv 为 privateEnv.[[OuterPrivateEnvironment]]。
  4. 断言:outerPrivateEnv 不是 null。
  5. 返回 ResolvePrivateIdentifier(outerPrivateEnv, identifier)。

9.3 Realm

所有 ECMAScript 代码在求值之前都必须与一个 Realm 相关联。从概念上讲,Realm 由一组内在对象、一个 ECMAScript 全局环境、加载到该全局环境作用域中的所有 ECMAScript 代码,以及其他关联的状态和资源组成。

本规范使用 Realm Record 来表示 Realm,其字段在 表 20 中规定:

表 20: Realm Record 字段
字段名称 值 含义
[[AgentSignifier]] 代理标识符 拥有此 Realm 的代理
[[Intrinsics]] 字段名称为内在对象键、字段值为对象的 Record 与此 Realm 关联的代码所使用的内在值
[[GlobalObject]] Object 此 Realm 的全局对象
[[GlobalEnv]] Global Environment Record 此 Realm 的全局环境
[[TemplateMap]] 字段为 [[Site]](TemplateLiteral Parse Node)和 [[Array]](Array)的 Record 的 List

每个 Realm 使用其 Realm Record 的 [[TemplateMap]] 分别对模板对象进行规范化。每个 [[Site]] 值都是一个 TemplateLiteral Parse Node。关联的 [[Array]] 值是传递给标签函数的相应模板对象。

注 1
一旦 Parse Node 变得不可达,对应的 [[Array]] 也将不可达;如果实现从 [[TemplateMap]] 列表中移除该对,则不会被观察到。
[[LoadedModules]] LoadedModuleRequest Record 的 List

从此 Realm 导入的说明符字符串到已解析 Module Record 的映射。该列表不会包含两个不同的 Record r1 和 r2,使得 ModuleRequestsEqual(r1, r2) 为 true。

注 2
如 HostLoadImportedModule(16.2.1.10 注 1)中所述,Realm Record 中的 [[LoadedModules]] 仅在没有活动脚本或模块的上下文中运行 import() 表达式时使用。
[[HostDefined]] 任意值(默认值为 undefined) 为需要将附加信息与 Realm Record 关联的宿主保留的字段。

9.3.1 InitializeHostDefinedRealm ( )

抽象操作 InitializeHostDefinedRealm,接收无参数;返回值:(正常完成 (值:unused) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 realm 为新的 Realm Record。
  2. 执行 CreateIntrinsics(realm)。
  3. 将 realm.[[AgentSignifier]] 设置为 AgentSignifier()。
  4. 将 realm.[[TemplateMap]] 设置为新的空 List。
  5. 令 newContext 为新的执行上下文。
  6. 将 newContext 的 Function 设置为 null。
  7. 将 newContext 的 Realm 设置为 realm。
  8. 将 newContext 的 ScriptOrModule 设置为 null。
  9. 将 newContext 压入执行上下文栈;newContext 现在是正在运行的执行上下文。
  10. 如果宿主要求使用特定对象作为 realm 的全局对象,则
    1. 令 global 为以宿主定义方式创建的此类对象。
  11. 否则,
    1. 令 global 为 OrdinaryObjectCreate(realm.[[Intrinsics]].[[%Object.prototype%]])。
  12. 如果宿主要求 realm 全局作用域中的 this 绑定返回一个不同于全局对象的对象,则
    1. 令 thisValue 为以宿主定义方式创建的此类对象。
  13. 否则,
    1. 令 thisValue 为 global。
  14. 将 realm.[[GlobalObject]] 设置为 global。
  15. 将 realm.[[GlobalEnv]] 设置为 NewGlobalEnvironment(global, thisValue)。
  16. 执行 ? SetDefaultGlobalBindings(realm)。
  17. 在 global 上创建任何宿主定义的全局对象属性。
  18. 返回 unused。

9.3.2 CreateIntrinsics ( realmRecord )

抽象操作 CreateIntrinsics,接收参数 realmRecord (Realm 记录);返回值:unused。 调用时执行以下步骤:

  1. 将 realmRecord.[[Intrinsics]] 设置为新的 Record。
  2. 使用 表 6 中列出的值设置 realmRecord.[[Intrinsics]] 的字段。字段名称是该表“内在对象名称”列中列出的名称。每个字段的值都是一个新的对象值,并根据条款 19 到 28 中各对象的规范,以属性值完整且递归地填充。所有对象属性值都是新创建的对象值。所有属于内置函数对象的值,都通过执行 CreateBuiltinFunction(steps, length, name, slots, realmRecord, proto, async) 创建,其中 steps 是本规范提供的该函数定义,name 是函数 "name" 属性的初始值,length 是函数 "length" 属性的初始值,slots 是函数所规定内部槽名称的列表(如果有),proto 是函数 [[Prototype]] 内部槽的规定值,而当函数被描述为“async”时 async 为 true,否则为 false。内在对象及其属性的创建必须按顺序进行,以避免依赖尚未创建的对象。
  3. 执行 AddRestrictedFunctionProperties(realmRecord.[[Intrinsics]].[[%Function.prototype%]], realmRecord)。
  4. 返回 unused。

9.3.3 SetDefaultGlobalBindings ( realmRecord )

抽象操作 SetDefaultGlobalBindings,接收参数 realmRecord (Realm 记录);返回值:(正常完成 (值:unused) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 global 为 realmRecord.[[GlobalObject]]。
  2. 对条款 19 中规定的 Global Object 的每个属性,执行
    1. 令 name 为属性名称的 String 值。
    2. 令 propertyDesc 为该属性完全填充的数据 Property Descriptor,其中包含为该属性规定的特性。对于 19.2、19.3 或 19.4 中列出的属性,[[Value]] 特性的值是 realmRecord 中对应的内在对象。
    3. 执行 ? DefinePropertyOrThrow(global, name, propertyDesc)。
  3. 返回 unused。

9.4 执行上下文

执行上下文是一种规范机制,用于跟踪 ECMAScript 实现对代码的运行时求值。在任意时刻,每个代理最多只有一个实际正在执行代码的执行上下文。它称为该代理的正在运行的执行上下文。本规范中对正在运行的执行上下文的所有引用,都表示周围代理正在运行的执行上下文。

执行上下文栈用于跟踪执行上下文。正在运行的执行上下文始终是此栈的顶部元素。每当控制从与当前正在运行的执行上下文关联的可执行代码转移到与该执行上下文不关联的可执行代码时,都会创建新的执行上下文。新创建的执行上下文会被压入栈中,并成为正在运行的执行上下文。

执行上下文包含跟踪其关联代码执行进度所需的任何实现特定状态。每个执行上下文至少具有 表 21 中列出的状态组成部分。

表 21: 所有执行上下文的状态组成部分
组成部分 用途
代码求值状态 执行、暂停和恢复与此执行上下文关联代码的求值所需的任何状态。
Function 如果此执行上下文正在对函数对象的代码求值,则此组成部分的值是该函数对象。如果该上下文正在对 Script 或 Module 的代码求值,则该值为 null。
Realm 关联代码通过其访问 ECMAScript 资源的 Realm Record。
ScriptOrModule 关联代码所源自的 Module Record 或 Script Record。如果没有源脚本或模块,例如 InitializeHostDefinedRealm 中创建的原始执行上下文,则值为 null。

正在运行的执行上下文对代码的求值可能会在本规范定义的多个位置暂停。正在运行的执行上下文暂停后,另一个执行上下文可以成为正在运行的执行上下文并开始对其代码求值。稍后,已暂停的执行上下文可以再次成为正在运行的执行上下文,并从先前暂停的位置继续对其代码求值。正在运行的执行上下文状态在各执行上下文之间的转换通常采用类似栈的后进先出方式。但是,某些 ECMAScript 特性要求正在运行的执行上下文进行非 LIFO 转换。

正在运行的执行上下文的 Realm 组成部分的值也称为当前 Realm Record。正在运行的执行上下文的 Function 组成部分的值也称为活动函数对象。

ECMAScript 代码执行上下文具有 表 22 中列出的附加状态组成部分。

表 22: ECMAScript 代码执行上下文的附加状态组成部分
组成部分 用途
LexicalEnvironment 标识用于解析此执行上下文中的代码所作标识符引用的 Environment Record。
VariableEnvironment 标识保存此执行上下文中 VariableStatement 创建的绑定的 Environment Record。
PrivateEnvironment 标识保存最近包含类中 ClassElement 创建的 Private Name 的 PrivateEnvironment Record。如果没有包含类,则为 null。

执行上下文的 LexicalEnvironment 和 VariableEnvironment 组成部分始终是 Environment Record。

表示 Generator 求值的执行上下文具有 表 23 中列出的附加状态组成部分。

表 23: Generator 执行上下文的附加状态组成部分
组成部分 用途
Generator 此执行上下文正在求值的 Generator。

在大多数情况下,本规范中的算法只会直接操作正在运行的执行上下文(执行上下文栈的顶部)。因此,当不加限定地使用“LexicalEnvironment”和“VariableEnvironment”这些术语时,它们指的是正在运行的执行上下文中的相应组成部分。

执行上下文纯粹是规范机制,无需对应于 ECMAScript 实现中的任何特定产物。ECMAScript 代码无法直接访问或观察执行上下文。

9.4.1 GetActiveScriptOrModule ( )

抽象操作 GetActiveScriptOrModule,接收无参数;返回值:(Script 记录、Module 记录 或 null)。 它用于根据正在运行的执行上下文确定正在运行的脚本或模块。 调用时执行以下步骤:

  1. 如果执行上下文栈为空,则返回 null。
  2. 令 executionContext 为执行上下文栈中 ScriptOrModule 组成部分不是 null 的最顶层执行上下文。
  3. 如果不存在这样的执行上下文,则返回 null。
  4. 返回 executionContext 的 ScriptOrModule。

9.4.2 ResolveBinding ( name [ , envRecord ] )

抽象操作 ResolveBinding,接收参数 name (String)和可选参数 envRecord ((Environment 记录 或 undefined));返回值:(正常完成 (值:Reference 记录) 或 抛出完成)。 它用于确定 name 的绑定。envRecord 可用于显式提供要在其中搜索绑定的 Environment Record。 调用时执行以下步骤:

  1. 如果不存在 envRecord 或 envRecord 是 undefined,则
    1. 将 envRecord 设置为正在运行的执行上下文的 LexicalEnvironment。
  2. 断言:envRecord 是 Environment Record。
  3. 令 strict 为 IsStrict(正在求值的句法产生式)。
  4. 返回 ? GetIdentifierReference(envRecord, name, strict)。
注

ResolveBinding 的结果始终是一个 Reference Record,其 [[ReferencedName]] 字段为 name。

9.4.3 GetThisEnvironment ( )

抽象操作 GetThisEnvironment,接收无参数;返回值:Environment 记录。 它查找当前提供关键字 this 绑定的 Environment Record。 调用时执行以下步骤:

  1. 令 envRecord 为正在运行的执行上下文的 LexicalEnvironment。
  2. 重复执行,
    1. 令 exists 为 envRecord.HasThisBinding()。
    2. 如果 exists 是 true,则返回 envRecord。
    3. 令 outer 为 envRecord.[[OuterEnv]]。
    4. 断言:outer 不是 null。
    5. 将 envRecord 设置为 outer。
注

步骤 2 中的循环始终会终止,因为环境列表始终以具有 this 绑定的全局环境结束。

9.4.4 ResolveThisBinding ( )

抽象操作 ResolveThisBinding,接收无参数;返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。 它使用正在运行的执行上下文的 LexicalEnvironment 确定关键字 this 的绑定。 调用时执行以下步骤:

  1. 令 envRecord 为 GetThisEnvironment()。
  2. 返回 ? envRecord.GetThisBinding()。

9.4.5 GetNewTarget ( )

抽象操作 GetNewTarget,接收无参数;返回值:(Object 或 undefined)。 它使用正在运行的执行上下文的 LexicalEnvironment 确定 NewTarget 值。 调用时执行以下步骤:

  1. 令 envRecord 为 GetThisEnvironment()。
  2. 断言:envRecord 具有 [[NewTarget]] 字段。
  3. 返回 envRecord.[[NewTarget]]。

9.4.6 GetGlobalObject ( )

抽象操作 GetGlobalObject,接收无参数;返回值:Object。 它返回当前正在运行的执行上下文所使用的全局对象。 调用时执行以下步骤:

  1. 令 currentRealm 为当前 Realm Record。
  2. 返回 currentRealm.[[GlobalObject]]。

9.4.7 RunSuspendedContext ( context, completionRecord )

抽象操作 RunSuspendedContext,接收参数 context (执行上下文) 和 completionRecord (完成记录);返回值:(正常完成 (值:(ECMAScript 语言值 或 unused)) 或 突兀完成)。 它恢复 context(将 completionRecord 作为恢复值传给它),并等待结果。 调用时执行以下步骤:

  1. 令 callerContext 为正在运行的执行上下文。
  2. 暂停 callerContext。
  3. 将 context 压入执行上下文栈;context 现在是正在运行的执行上下文。
  4. 恢复 context 中已暂停的求值,将 completionRecord 作为导致其暂停的操作的结果传入。令 result 为恢复后的计算传出的 Completion Record。
  5. 断言:到达此步骤时,context 已经从执行上下文栈中移除,并且 callerContext 再次成为正在运行的执行上下文。
  6. 返回 Completion(result)。

9.4.8 RunCallerContext ( value )

抽象操作 RunCallerContext,接收参数 value ((ECMAScript 语言值 或 empty));返回值:完成记录。 它恢复调用方上下文(将 value 作为恢复值传给它),并等待结果(如果有)。 调用时执行以下步骤:

  1. 令 genContext 为正在运行的执行上下文。
  2. 从执行上下文栈中移除 genContext,并将执行上下文栈顶部的执行上下文恢复为正在运行的执行上下文。
  3. 令 callerContext 为正在运行的执行上下文。
  4. 恢复 callerContext,传入 NormalCompletion(value)。
  5. 注:上述步骤将控制权转移到 callerContext 并暂停。要使其解除暂停并让控制继续执行本算法中的后续步骤,唯一的方法是再次恢复 genContext,而这可能永远不会发生。
  6. 断言:genContext 是正在运行的执行上下文。
  7. 令 result 为刚刚用于恢复 genContext 的 Completion Record。
  8. 返回 Completion(result)。

9.5 Job 和将 Job 入队的宿主操作

Job 是一个没有参数的 Abstract Closure,当当前没有其他 ECMAScript 计算正在进行时,它会启动一次 ECMAScript 计算。

Job 由 ECMAScript 宿主环境安排在特定代理中执行。本规范描述了用于安排 Job 的宿主钩子 HostEnqueueGenericJob、HostEnqueueFinalizationRegistryCleanupJob、HostEnqueuePromiseJob 和 HostEnqueueTimeoutJob。本规范中的宿主钩子按照对 Job 调度施加的附加约束进行组织。宿主可以定义其他用于安排 Job 的抽象操作。此类操作接受 Job Abstract Closure 和 Realm(Realm Record 或 null)作为参数。如果提供 Realm Record,则这些操作会安排该 Job 在将来的某个时间,在拥有该 Realm 的代理中的该 Realm 内执行。如果为 Realm 提供的是 null,则该 Job 不会对 ECMAScript 代码求值。它们的实现必须符合以下要求:

注 1
宿主环境无需在调度方面统一处理 Job。例如,Web 浏览器和 Node.js 将 Promise 处理 Job 视为比其他工作优先级更高;未来的特性可能会添加不会以如此高优先级处理的 Job。

在任意特定时刻,如果满足以下所有条件,则 scriptOrModule(Script Record、Module Record 或 null)是活动脚本或模块:

在任意特定时刻,如果满足以下所有条件,则一次执行被称为已准备好对 ECMAScript 代码求值:

注 2

宿主环境可以通过将执行上下文压入执行上下文栈,使一次执行准备好对代码求值。具体步骤由实现定义。

具体选择哪个 Realm 由宿主环境决定。这个初始执行上下文和 Realm 仅在调用任何回调函数之前使用。当调用与 Job 相关的回调函数(例如 Promise 处理器)时,该调用会压入其自己的执行上下文和 Realm。

特定种类的 Job 具有附加符合性要求。

9.5.1 JobCallback Record

JobCallback Record 是用于存储函数对象和宿主定义值的 Record。通过宿主入队的 Job 调用的函数对象可能具有附加的宿主定义上下文。为了传播该状态,Job Abstract Closure 不应直接捕获并调用函数对象。应改用 HostMakeJobCallback 和 HostCallJobCallback。

注

例如,WHATWG HTML 规范(https://html.spec.whatwg.org/)使用宿主定义值来传播 Promise 回调的 incumbent settings object。

JobCallback Record 具有 表 24 中列出的字段。

表 24: JobCallback Record 字段
字段名称 值 含义
[[Callback]] 函数对象 调用 Job 时要调用的函数。
[[HostDefined]] 任意值(默认值为 empty) 为宿主使用而保留的字段。

9.5.2 HostMakeJobCallback ( callback )

宿主定义的抽象操作 HostMakeJobCallback,接收参数 callback (函数对象);返回值:JobCallback 记录。

HostMakeJobCallback 的实现必须符合以下要求:

HostMakeJobCallback 的默认实现在被调用时执行以下步骤:

  1. 返回 JobCallback Record { [[Callback]]: callback, [[HostDefined]]: empty }。

不是 Web 浏览器的 ECMAScript 宿主必须使用 HostMakeJobCallback 的默认实现。

注

这是在回调传递给负责最终安排并运行它的函数时调用的。例如,promise.then(thenAction) 会在调用 Promise.prototype.then 时对 thenAction 调用 MakeJobCallback,而不是在安排 reaction Job 时。

9.5.3 HostCallJobCallback ( jobCallback, thisValue, argList )

宿主定义的抽象操作 HostCallJobCallback,接收参数 jobCallback (JobCallback 记录)、thisValue (ECMAScript 语言值) 和 argList (列表 (元素:ECMAScript 语言值));返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。

HostCallJobCallback 的实现必须符合以下要求:

  • 它必须执行并返回 Call(jobCallback.[[Callback]], thisValue, argList) 的结果。
注

此要求意味着宿主不能更改本规范中定义的函数对象的 [[Call]] 行为。

HostCallJobCallback 的默认实现在被调用时执行以下步骤:

  1. 断言:IsCallable(jobCallback.[[Callback]]) 是 true。
  2. 返回 ? Call(jobCallback.[[Callback]], thisValue, argList)。

不是 Web 浏览器的 ECMAScript 宿主必须使用 HostCallJobCallback 的默认实现。

9.5.4 HostEnqueueGenericJob ( job, realm )

宿主定义的抽象操作 HostEnqueueGenericJob,接收参数 job (a Job Abstract Closure) 和 realm (Realm 记录);返回值:unused。 它安排 job 在将来的某个时间,在由 realm.[[AgentSignifier]] 所指示代理中的 Realm realm 内执行。与此算法一起使用的 Abstract Closure 旨在不受优先级和顺序等附加约束地进行调度。

HostEnqueueGenericJob 的实现必须符合 9.5 中的要求。

9.5.5 HostEnqueuePromiseJob ( job, realm )

宿主定义的抽象操作 HostEnqueuePromiseJob,接收参数 job (a Job Abstract Closure) 和 realm ((Realm 记录 或 null));返回值:unused。 它安排 job 在将来的某个时间执行。与此算法一起使用的 Abstract Closure 旨在与 Promise 的处理相关,或者以与 Promise 处理操作相同的优先级进行调度。

HostEnqueuePromiseJob 的实现必须符合 9.5 中的要求以及以下要求:

注

由 NewPromiseResolveThenableJob 返回的 Job 的 realm 通常是对 then 函数对象调用 GetFunctionRealm 的结果。由 NewPromiseReactionJob 返回的 Job 的 realm 通常是当处理器不是 undefined 时对该处理器调用 GetFunctionRealm 的结果。如果处理器是 undefined,则 realm 为 null。对于这两种 Job,当 GetFunctionRealm 突然完成(即针对已撤销的 Proxy 调用)时,realm 是调用 GetFunctionRealm 时的当前 Realm Record。当 realm 为 null 时,不会对任何用户 ECMAScript 代码求值,也不会创建任何新的 ECMAScript 对象(例如 Error 对象)。例如,WHATWG HTML 规范(https://html.spec.whatwg.org/)使用 realm 来检查运行脚本的能力以及 entry 概念。

9.5.6 HostEnqueueTimeoutJob ( timeoutJob, realm, milliseconds )

宿主定义的抽象操作 HostEnqueueTimeoutJob,接收参数 timeoutJob (a Job Abstract Closure)、realm (Realm 记录) 和 milliseconds (非负有限 Number);返回值:unused。 它安排 timeoutJob 在至少 milliseconds 毫秒后,在由 realm.[[AgentSignifier]] 所指示代理中的 Realm realm 内执行。

HostEnqueueTimeoutJob 的实现必须符合 9.5 中的要求。

9.6 代理

代理由一组 ECMAScript 执行上下文、一个执行上下文栈、一个正在运行的执行上下文、一个 Agent Record 和一个执行线程组成。除执行线程外,代理的各组成部分都专属于该代理。

一个代理的执行线程独立于其他代理,对该代理的执行上下文执行算法步骤;但一个执行线程可以由多个代理共同作为其执行线程,前提是共享该线程的代理中没有任何代理的 Agent Record 的 [[CanBlock]] 字段为 true。

注 1

例如,一些 Web 浏览器会在一个浏览器窗口的多个不相关标签页之间共享单个执行线程。

当一个代理的执行线程正在执行算法步骤时,该代理就是这些步骤的周围代理。这些步骤使用周围代理来访问该代理中保存的规范级执行对象:正在运行的执行上下文、执行上下文栈以及 Agent Record 的字段。

代理标识符是用于标识 Agent 的全局唯一不透明值。

表 25: Agent Record 字段
字段名称 值 含义
[[LittleEndian]] Boolean 当算法 GetValueFromBuffer 和 SetValueInBuffer 需要 isLittleEndian 参数时,为该参数计算的默认值。该选择由实现定义,并应选择对实现而言最高效的方案。
[[CanBlock]] Boolean 确定代理是否可以阻塞。
[[Signifier]] 代理标识符 在其代理集群中唯一标识该代理。
[[IsLockFree1]] Boolean 如果对一个字节值的原子操作是无锁的,则为 true,否则为 false。
[[IsLockFree2]] Boolean 如果对两个字节值的原子操作是无锁的,则为 true,否则为 false。
[[IsLockFree8]] Boolean 如果对八个字节值的原子操作是无锁的,则为 true,否则为 false。
[[CandidateExecution]] 候选执行 Record 参见内存模型。
[[KeptAlive]] Object 或 Symbol 的 List 初始为新的空 List,表示在当前 Job 结束之前要保持存活的对象和/或 Symbol 列表
[[ModuleAsyncEvaluationCount]] 整数 初始为 0,用于为异步模块或具有异步依赖项的模块的 [[AsyncEvaluationOrder]] 字段分配唯一且递增的值。
[[GlobalSymbolRegistry]] GlobalSymbolRegistry Record 的 List 初始为新的空 List,表示由 Symbol.for 产生的 Symbol 值列表。

[[LittleEndian]]、[[Signifier]]、[[IsLockFree1]]、[[IsLockFree2]] 和 [[IsLockFree8]] 的值不能更改。

[[GlobalSymbolRegistry]] List 只能追加,且永远不会被重新赋值。

注 2

[[IsLockFree1]]、[[IsLockFree2]] 和 [[IsLockFree8]] 的值不一定由硬件决定,也可能反映实现选择,并且这些选择可能随时间和不同 ECMAScript 实现而变化。

不存在 [[IsLockFree4]] 字段:4 字节原子操作始终是无锁的。

实际上,如果原子操作使用任何类型的锁来实现,则该操作就不是无锁的。无锁并不意味着无等待:完成一个无锁原子操作可能需要多少机器步骤不存在上限。

大小为 n 的原子访问是无锁的,并不意味着大小为 n 的非原子访问的(感知)原子性具有任何性质;具体而言,非原子访问仍然可能作为多个独立内存访问的序列执行。详见 ReadSharedMemory 和 WriteSharedMemory。

注 3

代理是一种规范机制,无需对应于 ECMAScript 实现中的任何特定产物。

9.6.1 AgentSignifier ( )

抽象操作 AgentSignifier,接收无参数;返回值:an agent signifier。 调用时执行以下步骤:

  1. 令 agentRecord 为周围代理的 Agent Record。
  2. 返回 agentRecord.[[Signifier]]。

9.6.2 AgentCanSuspend ( )

抽象操作 AgentCanSuspend,接收无参数;返回值:Boolean。 调用时执行以下步骤:

  1. 令 agentRecord 为周围代理的 Agent Record。
  2. 返回 agentRecord.[[CanBlock]]。
注

在某些环境中,允许给定代理暂停可能并不合理。例如,在 Web 浏览器环境中,可以合理地禁止文档的主事件处理线程暂停,同时仍允许 worker 的事件处理线程暂停。

9.6.3 IncrementModuleAsyncEvaluationCount ( )

抽象操作 IncrementModuleAsyncEvaluationCount,接收无参数;返回值:非负整数。 调用时执行以下步骤:

  1. 令 agentRecord 为周围代理的 Agent Record。
  2. 令 count 为 agentRecord.[[ModuleAsyncEvaluationCount]]。
  3. 将 agentRecord.[[ModuleAsyncEvaluationCount]] 设置为 count + 1。
  4. 返回 count。
注

此值仅用于跟踪待处理模块之间的相对求值顺序。当没有待处理模块时,实现可以在不可观察的情况下将 [[ModuleAsyncEvaluationCount]] 重置为 0。

9.7 代理集群

代理集群是能够通过操作共享内存进行通信的代理的极大集合。

注 1

不同代理中的程序可以通过未规定的方式共享内存。至少,SharedArrayBuffer 的后备内存可以在集群中的代理之间共享。

可能存在能够通过消息传递进行通信但不能共享内存的代理;它们永远不会位于同一个代理集群中。

每个代理恰好属于一个代理集群。

注 2

集群中的所有代理不必在某个特定时刻都处于存活状态。如果代理 A 创建了另一个代理 B,随后 A 终止,而 B 创建代理 C,那么只要 A 能够与 B 共享某些内存,并且 B 能够与 C 共享某些内存,这三个代理就位于同一个集群中。

集群中的所有代理,其各自 Agent Record 中的 [[LittleEndian]] 字段必须具有相同值。

注 3

如果代理集群中的不同代理具有不同的 [[LittleEndian]] 值,则很难使用共享内存存储多字节数据。

集群中的所有代理,其各自 Agent Record 中的 [[IsLockFree1]] 字段必须具有相同值;[[IsLockFree2]] 和 [[IsLockFree8]] 字段也同样如此。

集群中的所有代理,其各自 Agent Record 中的 [[Signifier]] 字段必须具有不同值。

嵌入环境可以在代理不知情或不配合的情况下停用(停止向前进展)或激活(恢复向前进展)一个代理。如果嵌入环境这样做,则不得让集群中的某些代理保持活动,而同一集群中的其他代理被无限期停用。

注 4

上述限制的目的是避免一个代理因为另一个代理被停用而发生死锁或饥饿。例如,假设一个 HTML shared worker 的生命周期独立于任何窗口中的文档,并且允许它与这样一个独立文档的 dedicated worker 共享内存;如果在 dedicated worker 持有锁时该文档及其 dedicated worker 被停用(例如文档被压入其窗口的历史记录),然后 shared worker 尝试获取该锁,那么 shared worker 将一直被阻塞,直到 dedicated worker 再次激活——如果它还会被激活的话。与此同时,从其他窗口尝试访问该 shared worker 的其他 worker 将发生饥饿。

此限制意味着,在嵌入环境中不属于同一暂停/唤醒集合的代理之间将无法共享内存。

嵌入环境可以在代理集群中的其他代理事先不知情或不配合的情况下终止一个代理。如果代理不是因自身或集群中另一个代理的程序操作而终止,而是由集群外部力量终止,那么嵌入环境必须选择以下两种策略之一:终止集群中的所有代理;或者提供可靠的 API,使集群中的代理能够协调,从而让集群中至少一个剩余成员能够检测到该终止,并且终止数据包含足够的信息以识别被终止的代理。

注 5

此类终止的示例包括:操作系统或用户终止在独立进程中运行的代理;当按代理进行资源计量表明某代理失控时,嵌入环境自身终止与其他代理在同一进程中运行的该代理。

以下每个规范值,以及从它们传递可达的值,都恰好属于一个代理集群。

在集群中的任何代理对任何 ECMAScript 代码进行任何求值之前,集群中所有代理的 Agent Record 的 [[CandidateExecution]] 字段都设置为初始候选执行。初始候选执行是一个空候选执行,其 [[EventsRecords]] 字段是一个 List,其中针对每个代理包含一个 Agent Events Record,该 Record 的 [[AgentSignifier]] 字段是该代理的代理标识符,而其 [[EventList]] 和 [[AgentSynchronizesWith]] 字段都是空 List。

注 6

代理集群中的所有代理在其 Agent Record 的 [[CandidateExecution]] 字段中共享相同的候选执行。候选执行是内存模型使用的一种规范机制。

注 7

代理集群是一种规范机制,无需对应于 ECMAScript 实现中的任何特定产物。

9.8 向前进展

代理取得向前进展,是指它按照本规范执行一个求值步骤。

当代理正在运行的执行上下文同步且无限期地等待外部事件时,该代理变为阻塞。只有其 Agent Record 的 [[CanBlock]] 字段为 true 的代理才能在此意义上变为阻塞。未阻塞代理是指未被阻塞的代理。

实现必须确保:

  • 每个具有专用执行线程的未阻塞代理最终都会取得向前进展
  • 在一组共享执行线程的代理中,至少有一个代理最终会取得向前进展
  • 除非通过显式提供阻塞功能的 API,否则一个代理不会导致另一个代理变为阻塞。
注

这一点与内存模型中的活性保证共同确保所有 seq-cst 写入最终都能被所有代理观察到。

9.9 WeakRef 和 FinalizationRegistry 目标的处理模型

9.9.1 目标

本规范不保证任何对象或 Symbol 一定会被垃圾回收。不再存活的对象或 Symbol 可能在很长时间后才被释放,也可能永远不会被释放。因此,本规范在描述由垃圾回收触发的行为时使用“可以”一词。

WeakRef 和 FinalizationRegistry 的语义基于在特定时间点发生的两个操作:

这两个操作(ClearKeptObjects 或 CleanupFinalizationRegistry)都不能中断同步 ECMAScript 执行。由于宿主可能会组合出较长的同步 ECMAScript 执行序列,因此本规范将 ClearKeptObjects 和 CleanupFinalizationRegistry 的调度交由宿主环境处理。

某些 ECMAScript 实现包含会在后台运行的垃圾回收器实现,包括 ECMAScript 空闲时。让宿主环境调度 CleanupFinalizationRegistry,使其可以恢复 ECMAScript 执行以运行终结器工作,而这些工作可能释放所持有的值,从而降低整体内存使用量。

9.9.2 活性

对于某个对象和/或 Symbol 集合 objSet,相对于 objSet 的假想 WeakRef 无感知执行,是这样一种执行:其被引用对象属于 objSet 的 WeakRef 的抽象操作 WeakRefDeref 始终返回 undefined。

注 1
WeakRef 无感知性与活性一起刻画了两个概念。第一,WeakRef 本身不会使其被引用对象保持存活。第二,活性中的循环并不意味着一个值是存活的。具体来说,如果确定 v 的活性依赖于确定 WeakRef 被引用对象 r 的活性,那么 r 的活性不能假定 v 是存活的,因为这将形成循环推理。
注 2
WeakRef 无感知性定义在对象或 Symbol 的集合上,而不是单个值上,以考虑循环。如果定义在单个值上,那么循环中的 WeakRef 被引用对象即使其标识仅通过循环中的其他 WeakRef 被引用对象被观察到,也会被视为存活。
注 3
通俗地说,如果包含某个对象或 Symbol 的每个集合都是存活的,我们就说该对象或 Symbol 是存活的。

在求值期间的任意时刻,如果满足以下任一条件,则对象和/或 Symbol 集合 objSet 被视为存活:

  • objSet 中的任一元素包含在任一代理的 [[KeptAlive]] List 中。
  • 存在一个相对于 objSet 的有效未来假想 WeakRef 无感知执行,并且该执行观察到 objSet 中任一值的标识。
注 4
上述第二个条件旨在刻画这样一种直觉:如果一个值的标识可以通过非 WeakRef 方式观察到,则该值是存活的。可以通过观察严格相等比较,或观察该值作为 Map 中的键使用,来观察一个值的标识。
注 5

对象或 Symbol 出现在字段、内部槽或属性中,并不意味着该值是存活的。例如,如果相关值从未传回给程序,则无法被观察到。

WeakMap 中的键、WeakSet 中的成员,以及 FinalizationRegistry Cell Record 的 [[WeakRefTarget]] 和 [[UnregisterToken]] 字段都属于这种情况。

上述定义意味着,如果 WeakMap 中的键不是存活的,则其对应值也不一定是存活的。

注 6
活性是保证引擎不得清空哪些 WeakRef 的下界。这里定义的活性是不可判定的。实际上,引擎会使用诸如可达性之类的保守近似。预计实现将具有很大的自由度。

9.9.3 执行

在任意时刻,如果对象和/或 Symbol 集合 objSet 不是存活的,则 ECMAScript 实现可以原子地执行以下步骤:

  1. 对 objSet 的每个元素 value,执行
    1. 对每个满足 ref.[[WeakRefTarget]] 是 value 的 WeakRef ref,执行
      1. 将 ref.[[WeakRefTarget]] 设置为 empty。
    2. 对每个满足 finalizationRegistry.[[Cells]] 包含一个 Record cell,且 cell.[[WeakRefTarget]] 是 value 的 FinalizationRegistry finalizationRegistry,执行
      1. 将 cell.[[WeakRefTarget]] 设置为 empty。
      2. 令 enqueueCleanup 为实现定义地从 true 或 false 中选择的一个值。
      3. 如果 enqueueCleanup 是 true,则执行 HostEnqueueFinalizationRegistryCleanupJob(finalizationRegistry)。
    3. 对每个满足 map.[[WeakMapData]] 包含一个 Record entry,且 entry.[[Key]] 是 value 的 WeakMap map,执行
      1. 将 entry.[[Key]] 设置为 empty。
      2. 将 entry.[[Value]] 设置为 empty。
    4. 对每个满足 set.[[WeakSetData]] 包含 value 的 WeakSet set,执行
      1. 将 set.[[WeakSetData]] 中值为 value 的元素替换为值为 empty 的元素。
注 1

结合活性的定义,本条款规定了实现可以针对 WeakRef 应用的优化。

可以在不观察对象标识的情况下访问该对象。允许进行诸如死变量消除,以及对其标识未被观察到的非逃逸对象属性进行标量替换等优化。因此,允许这些优化以可观察方式清空指向此类对象的 WeakRef。

另一方面,如果对象的标识可观察,并且该对象位于某个 WeakRef 的 [[WeakRefTarget]] 内部槽中,则禁止进行会以可观察方式清空该 WeakRef 的重新物化等优化。

由于调用 HostEnqueueFinalizationRegistryCleanupJob 是可选的,因此在 FinalizationRegistry 中注册的对象不一定会使该 FinalizationRegistry 保持存活。实现可以因任何原因省略 FinalizationRegistry 回调,例如 FinalizationRegistry 本身已经死亡,或者应用程序正在关闭。

注 2

实现没有义务为非存活对象或 Symbol 的极大集合清空 WeakRef。

如果实现选择一个非存活集合 objSet 并在其中清空 WeakRef,则此定义要求它同时清空 objSet 中所有值对应的 WeakRef。换句话说,如果不清空指向值 v 的其他 WeakRef 可能导致某次执行观察到 v 的值,那么实现仅清空指向 v 的一个 WeakRef 而不清空那些其他 WeakRef,是不符合规范的。

9.9.4 宿主钩子

9.9.4.1 HostEnqueueFinalizationRegistryCleanupJob ( finalizationRegistry )

宿主定义的抽象操作 HostEnqueueFinalizationRegistryCleanupJob,接收参数 finalizationRegistry (FinalizationRegistry);返回值:unused。

令 cleanupJob 为一个没有参数的新 Job Abstract Closure,它捕获 finalizationRegistry,并在被调用时执行以下步骤:

  1. 令 cleanupResult 为 Completion(CleanupFinalizationRegistry(finalizationRegistry))。
  2. 如果 cleanupResult 是突然完成,则执行任何用于报告错误的宿主定义步骤。
  3. 返回 unused。

HostEnqueueFinalizationRegistryCleanupJob 的实现会在可能的情况下安排 cleanupJob 在将来的某个时间执行。它还必须符合 9.5 中的要求。

9.10 ClearKeptObjects ( )

抽象操作 ClearKeptObjects,接收无参数;返回值:unused。 ECMAScript 实现应当在 ECMAScript 执行的同步序列完成时调用 ClearKeptObjects。 调用时执行以下步骤:

  1. 令 agentRecord 为周围代理的 Agent Record。
  2. 将 agentRecord.[[KeptAlive]] 设置为新的空 List。
  3. 返回 unused。

9.11 AddToKeptObjects ( value )

抽象操作 AddToKeptObjects,接收参数 value ((Object 或 Symbol));返回值:unused。 调用时执行以下步骤:

  1. 令 agentRecord 为周围代理的 Agent Record。
  2. 将 value 追加到 agentRecord.[[KeptAlive]]。
  3. 返回 unused。
注
当使用目标对象或 Symbol 调用抽象操作 AddToKeptObjects 时,它会将目标添加到一个列表中,该列表会在调用 ClearKeptObjects 之前对目标保持强引用。

9.12 CleanupFinalizationRegistry ( finalizationRegistry )

抽象操作 CleanupFinalizationRegistry,接收参数 finalizationRegistry (FinalizationRegistry);返回值:(正常完成 (值:unused) 或 抛出完成)。 调用时执行以下步骤:

  1. 断言:finalizationRegistry 具有 [[Cells]] 和 [[CleanupCallback]] 内部槽。
  2. 令 callback 为 finalizationRegistry.[[CleanupCallback]]。
  3. 当 finalizationRegistry.[[Cells]] 包含一个 Record cell,使得 cell.[[WeakRefTarget]] 是 empty 时,实现可以执行以下步骤:
    1. 选择任意这样的 cell。
    2. 从 finalizationRegistry.[[Cells]] 中移除 cell。
    3. 执行 ? HostCallJobCallback(callback, undefined, « cell.[[HeldValue]] »)。
  4. 返回 unused。

9.13 CanBeHeldWeakly ( arg )

抽象操作 CanBeHeldWeakly,接收参数 arg (ECMAScript 语言值);返回值:Boolean。 当且仅当 arg 适合用作弱引用时,它返回 true。只有适合用作弱引用的值才能作为 WeakMap 的键、WeakSet 的元素、WeakRef 的目标,或 FinalizationRegistry 的目标之一。 调用时执行以下步骤:

  1. 如果 arg 是 Object,则返回 true。
  2. 如果 arg 是 Symbol 且 KeyForSymbol(arg) 是 undefined,则返回 true。
  3. 返回 false。
注

没有语言标识的语言值可以在没有先前引用的情况下显现,因此不适合用作弱引用。由 Symbol.for 产生的 Symbol 值与其他 Symbol 值不同,它没有语言标识,因此不适合用作弱引用。知名 Symbol 很可能永远不会被回收,但仍被视为适合用作弱引用,因为其数量有限,因此可由各种实现方式管理。不过,在存活的 WeakMap 中与知名 Symbol 关联的任何值都很可能不会被回收,并可能在实现中“泄漏”内存资源。

10 普通对象和异质对象的行为

10.1 普通对象内部方法和内部槽

所有普通对象都有一个名为 [[Prototype]] 的内部槽。此内部槽的值为 null 或对象,并用于实现继承。假设名为 propertyKey 的属性在普通对象 obj 中不存在,但存在于其 [[Prototype]] 对象上。如果 propertyKey 引用 [[Prototype]] 对象上的数据属性,则 obj 会为获取访问继承它,使其表现得就像 propertyKey 是 obj 的属性一样。如果 propertyKey 引用 [[Prototype]] 对象上的可写数据属性,则对 obj 上的 propertyKey 进行设置访问会在 obj 上创建名为 propertyKey 的新数据属性。如果 propertyKey 引用 [[Prototype]] 对象上的不可写数据属性,则对 obj 上的 propertyKey 进行设置访问会失败。如果 propertyKey 引用 [[Prototype]] 对象上的访问器属性,则该访问器会由 obj 为获取访问和设置访问同时继承。

每个普通对象都有一个 Boolean 值的 [[Extensible]] 内部槽,用于满足 6.1.7.3 中规定的与可扩展性相关的内部方法不变量。也就是说,一旦对象的 [[Extensible]] 内部槽值被设置为 false,就不再能够向该对象添加属性、修改对象的 [[Prototype]] 内部槽值,或随后将 [[Extensible]] 的值改回 true。

在以下算法描述中,假定 obj 是普通对象,propertyKey 是属性键值,value 是任意 ECMAScript 语言值,而 propertyDesc 是 Property Descriptor Record。

每个普通对象内部方法都会委托给一个名称相似的抽象操作。如果这样的抽象操作依赖另一个内部方法,则会在 obj 上调用该内部方法,而不是直接调用名称相似的抽象操作。这些语义确保在将普通对象内部方法应用于异质对象时,会调用异质对象所重写的内部方法。

10.1.1 [[GetPrototypeOf]] ( )

an ordinary object obj的内部方法 [[GetPrototypeOf]],接收无参数;返回值:正常完成 (值:(Object 或 null))。 调用时执行以下步骤:

  1. 返回 OrdinaryGetPrototypeOf(obj)。

10.1.1.1 OrdinaryGetPrototypeOf ( obj )

抽象操作 OrdinaryGetPrototypeOf,接收参数 obj (Object);返回值:(Object 或 null)。 调用时执行以下步骤:

  1. 返回 obj.[[Prototype]]。

10.1.2 [[SetPrototypeOf]] ( proto )

an ordinary object obj的内部方法 [[SetPrototypeOf]],接收参数 proto ((Object 或 null));返回值:正常完成 (值:Boolean)。 调用时执行以下步骤:

  1. 返回 OrdinarySetPrototypeOf(obj, proto)。

10.1.2.1 OrdinarySetPrototypeOf ( obj, proto )

抽象操作 OrdinarySetPrototypeOf,接收参数 obj (Object) 和 proto ((Object 或 null));返回值:Boolean。 调用时执行以下步骤:

  1. 令 current 为 obj.[[Prototype]]。
  2. 如果 SameValue(proto, current) 是 true,则返回 true。
  3. 令 extensible 为 obj.[[Extensible]]。
  4. 如果 extensible 是 false,则返回 false。
  5. 令 cursor 为 proto。
  6. 令 done 为 false。
  7. 当 done 是 false 时,重复执行,
    1. 如果 cursor 是 null,则
      1. 将 done 设置为 true。
    2. 否则如果 SameValue(cursor, obj) 是 true,则
      1. 返回 false。
    3. 否则,
      1. 如果 cursor.[[GetPrototypeOf]] 不是 10.1.1 中定义的普通对象内部方法,则将 done 设置为 true。
      2. 否则,将 cursor 设置为 cursor.[[Prototype]]。
  8. 将 obj.[[Prototype]] 设置为 proto。
  9. 返回 true。
注

步骤 7 中的循环保证,在仅包含对 [[GetPrototypeOf]] 和 [[SetPrototypeOf]] 使用普通对象定义的对象的任何原型链中都不会出现循环。

10.1.3 [[IsExtensible]] ( )

an ordinary object obj的内部方法 [[IsExtensible]],接收无参数;返回值:正常完成 (值:Boolean)。 调用时执行以下步骤:

  1. 返回 OrdinaryIsExtensible(obj)。

10.1.3.1 OrdinaryIsExtensible ( obj )

抽象操作 OrdinaryIsExtensible,接收参数 obj (Object);返回值:Boolean。 调用时执行以下步骤:

  1. 返回 obj.[[Extensible]]。

10.1.4 [[PreventExtensions]] ( )

an ordinary object obj的内部方法 [[PreventExtensions]],接收无参数;返回值:正常完成 (值:true)。 调用时执行以下步骤:

  1. 返回 OrdinaryPreventExtensions(obj)。

10.1.4.1 OrdinaryPreventExtensions ( obj )

抽象操作 OrdinaryPreventExtensions,接收参数 obj (Object);返回值:true。 调用时执行以下步骤:

  1. 将 obj.[[Extensible]] 设置为 false。
  2. 返回 true。

10.1.5 [[GetOwnProperty]] ( propertyKey )

an ordinary object obj的内部方法 [[GetOwnProperty]],接收参数 propertyKey (属性键);返回值:正常完成 (值:(属性描述符 或 undefined))。 调用时执行以下步骤:

  1. 返回 OrdinaryGetOwnProperty(obj, propertyKey)。

10.1.5.1 OrdinaryGetOwnProperty ( obj, propertyKey )

抽象操作 OrdinaryGetOwnProperty,接收参数 obj (Object) 和 propertyKey (属性键);返回值:(属性描述符 或 undefined)。 调用时执行以下步骤:

  1. 如果 obj 没有键为 propertyKey 的自有属性,则返回 undefined。
  2. 令 propertyDesc 为一个新创建且没有字段的 Property Descriptor。
  3. 令 ownProperty 为 obj 中键为 propertyKey 的自有属性。
  4. 如果 ownProperty 是数据属性,则
    1. 将 propertyDesc.[[Value]] 设置为 ownProperty 的 [[Value]] 特性的值。
    2. 将 propertyDesc.[[Writable]] 设置为 ownProperty 的 [[Writable]] 特性的值。
  5. 否则,
    1. 断言:ownProperty 是访问器属性。
    2. 将 propertyDesc.[[Getter]] 设置为 ownProperty 的 [[Getter]] 特性的值。
    3. 将 propertyDesc.[[Setter]] 设置为 ownProperty 的 [[Setter]] 特性的值。
  6. 将 propertyDesc.[[Enumerable]] 设置为 ownProperty 的 [[Enumerable]] 特性的值。
  7. 将 propertyDesc.[[Configurable]] 设置为 ownProperty 的 [[Configurable]] 特性的值。
  8. 返回 propertyDesc。

10.1.6 [[DefineOwnProperty]] ( propertyKey, propertyDesc )

an ordinary object obj的内部方法 [[DefineOwnProperty]],接收参数 propertyKey (属性键) 和 propertyDesc (属性描述符);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 返回 ? OrdinaryDefineOwnProperty(obj, propertyKey, propertyDesc)。

10.1.6.1 OrdinaryDefineOwnProperty ( obj, propertyKey, propertyDesc )

抽象操作 OrdinaryDefineOwnProperty,接收参数 obj (Object)、propertyKey (属性键) 和 propertyDesc (属性描述符);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 current 为 ? obj.[[GetOwnProperty]](propertyKey)。
  2. 令 extensible 为 ? IsExtensible(obj)。
  3. 返回 ValidateAndApplyPropertyDescriptor(obj, propertyKey, extensible, propertyDesc, current)。

10.1.6.2 IsCompatiblePropertyDescriptor ( extensible, propertyDesc, current )

抽象操作 IsCompatiblePropertyDescriptor,接收参数 extensible (Boolean)、propertyDesc (属性描述符) 和 current ((属性描述符 或 undefined));返回值:Boolean。 调用时执行以下步骤:

  1. 返回 ValidateAndApplyPropertyDescriptor(undefined, "", extensible, propertyDesc, current)。

10.1.6.3 ValidateAndApplyPropertyDescriptor ( obj, propertyKey, extensible, propertyDesc, current )

抽象操作 ValidateAndApplyPropertyDescriptor,接收参数 obj ((Object 或 undefined))、propertyKey (属性键)、extensible (Boolean)、propertyDesc (属性描述符) 和 current ((属性描述符 或 undefined));返回值:Boolean。 当且仅当 propertyDesc 能够作为具有指定 extensibility 和当前属性 current 的对象的属性应用,同时保持不变量时,它返回 true。当这种应用可行并且 obj 不是 undefined 时,会对名为 propertyKey 的属性执行该应用(必要时会创建该属性)。 调用时执行以下步骤:

  1. 断言:propertyKey 是属性键。
  2. 如果 current 是 undefined,则
    1. 如果 extensible 是 false,则返回 false。
    2. 如果 obj 是 undefined,则返回 true。
    3. 如果 IsAccessorDescriptor(propertyDesc) 是 true,则
      1. 在对象 obj 上创建名为 propertyKey 的自有访问器属性;如果 propertyDesc 具有相应字段,则其 [[Getter]]、[[Setter]]、[[Enumerable]] 和 [[Configurable]] 特性设置为 propertyDesc 中对应字段的值,否则设置为相应特性的默认值。
    4. 否则,
      1. 在对象 obj 上创建名为 propertyKey 的自有数据属性;如果 propertyDesc 具有相应字段,则其 [[Value]]、[[Writable]]、[[Enumerable]] 和 [[Configurable]] 特性设置为 propertyDesc 中对应字段的值,否则设置为相应特性的默认值。
    5. 返回 true。
  3. 断言:current 是完全填充的 Property Descriptor。
  4. 如果 propertyDesc 没有任何字段,则返回 true。
  5. 如果 current.[[Configurable]] 是 false,则
    1. 如果 propertyDesc 具有 [[Configurable]] 字段且 propertyDesc.[[Configurable]] 是 true,则返回 false。
    2. 如果 propertyDesc 具有 [[Enumerable]] 字段且 propertyDesc.[[Enumerable]] 不是 current.[[Enumerable]],则返回 false。
    3. 如果 IsGenericDescriptor(propertyDesc) 是 false 且 IsAccessorDescriptor(propertyDesc) 不等于 IsAccessorDescriptor(current),则返回 false。
    4. 如果 IsAccessorDescriptor(current) 是 true,则
      1. 如果 propertyDesc 具有 [[Getter]] 字段且 SameValue(propertyDesc.[[Getter]], current.[[Getter]]) 是 false,则返回 false。
      2. 如果 propertyDesc 具有 [[Setter]] 字段且 SameValue(propertyDesc.[[Setter]], current.[[Setter]]) 是 false,则返回 false。
    5. 否则如果 current.[[Writable]] 是 false,则
      1. 如果 propertyDesc 具有 [[Writable]] 字段且 propertyDesc.[[Writable]] 是 true,则返回 false。
      2. 注:SameValue 对可能通过其他方式区分的 NaN 值返回 true。在此处返回可确保 obj 的任何现有属性保持不变。
      3. 如果 propertyDesc 具有 [[Value]] 字段,则返回 SameValue(propertyDesc.[[Value]], current.[[Value]])。
  6. 如果 obj 不是 undefined,则
    1. 如果 IsDataDescriptor(current) 是 true 且 IsAccessorDescriptor(propertyDesc) 是 true,则
      1. 如果 propertyDesc 具有 [[Configurable]] 字段,则令 configurable 为 propertyDesc.[[Configurable]];否则令 configurable 为 current.[[Configurable]]。
      2. 如果 propertyDesc 具有 [[Enumerable]] 字段,则令 enumerable 为 propertyDesc.[[Enumerable]];否则令 enumerable 为 current.[[Enumerable]]。
      3. 将对象 obj 中名为 propertyKey 的属性替换为访问器属性,其 [[Configurable]] 和 [[Enumerable]] 特性分别设置为 configurable 和 enumerable;如果 propertyDesc 具有相应字段,则其 [[Getter]] 和 [[Setter]] 特性设置为 propertyDesc 中对应字段的值,否则设置为相应特性的默认值。
    2. 否则如果 IsAccessorDescriptor(current) 是 true 且 IsDataDescriptor(propertyDesc) 是 true,则
      1. 如果 propertyDesc 具有 [[Configurable]] 字段,则令 configurable 为 propertyDesc.[[Configurable]];否则令 configurable 为 current.[[Configurable]]。
      2. 如果 propertyDesc 具有 [[Enumerable]] 字段,则令 enumerable 为 propertyDesc.[[Enumerable]];否则令 enumerable 为 current.[[Enumerable]]。
      3. 将对象 obj 中名为 propertyKey 的属性替换为数据属性,其 [[Configurable]] 和 [[Enumerable]] 特性分别设置为 configurable 和 enumerable;如果 propertyDesc 具有相应字段,则其 [[Value]] 和 [[Writable]] 特性设置为 propertyDesc 中对应字段的值,否则设置为相应特性的默认值。
    3. 否则,
      1. 对 propertyDesc 的每个字段名称 fieldName,将对象 obj 中名为 propertyKey 的属性中名为 fieldName 的特性设置为 propertyDesc 的 fieldName 字段的值。
  7. 返回 true。

10.1.7 [[HasProperty]] ( propertyKey )

an ordinary object obj的内部方法 [[HasProperty]],接收参数 propertyKey (属性键);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 返回 ? OrdinaryHasProperty(obj, propertyKey)。

10.1.7.1 OrdinaryHasProperty ( obj, propertyKey )

抽象操作 OrdinaryHasProperty,接收参数 obj (Object) 和 propertyKey (属性键);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 hasOwn 为 ? obj.[[GetOwnProperty]](propertyKey)。
  2. 如果 hasOwn 不是 undefined,则返回 true。
  3. 令 parent 为 ? obj.[[GetPrototypeOf]]()。
  4. 如果 parent 不是 null,则
    1. 返回 ? parent.[[HasProperty]](propertyKey)。
  5. 返回 false。

10.1.8 [[Get]] ( propertyKey, receiver )

an ordinary object obj的内部方法 [[Get]],接收参数 propertyKey (属性键) 和 receiver (ECMAScript 语言值);返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。 调用时执行以下步骤:

  1. 返回 ? OrdinaryGet(obj, propertyKey, receiver)。

10.1.8.1 OrdinaryGet ( obj, propertyKey, receiver )

抽象操作 OrdinaryGet,接收参数 obj (Object)、propertyKey (属性键) 和 receiver (ECMAScript 语言值);返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 propertyDesc 为 ? obj.[[GetOwnProperty]](propertyKey)。
  2. 如果 propertyDesc 是 undefined,则
    1. 令 parent 为 ? obj.[[GetPrototypeOf]]()。
    2. 如果 parent 是 null,则返回 undefined。
    3. 返回 ? parent.[[Get]](propertyKey, receiver)。
  3. 如果 IsDataDescriptor(propertyDesc) 是 true,则返回 propertyDesc.[[Value]]。
  4. 断言:IsAccessorDescriptor(propertyDesc) 是 true。
  5. 令 getter 为 propertyDesc.[[Getter]]。
  6. 如果 getter 是 undefined,则返回 undefined。
  7. 返回 ? Call(getter, receiver)。

10.1.9 [[Set]] ( propertyKey, value, receiver )

an ordinary object obj的内部方法 [[Set]],接收参数 propertyKey (属性键)、value (ECMAScript 语言值) 和 receiver (ECMAScript 语言值);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 返回 ? OrdinarySet(obj, propertyKey, value, receiver)。

10.1.9.1 OrdinarySet ( obj, propertyKey, value, receiver )

抽象操作 OrdinarySet,接收参数 obj (Object)、propertyKey (属性键)、value (ECMAScript 语言值) 和 receiver (ECMAScript 语言值);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 ownDesc 为 ? obj.[[GetOwnProperty]](propertyKey)。
  2. 返回 ? OrdinarySetWithOwnDescriptor(obj, propertyKey, value, receiver, ownDesc)。

10.1.9.2 OrdinarySetWithOwnDescriptor ( obj, propertyKey, value, receiver, ownDesc )

抽象操作 OrdinarySetWithOwnDescriptor,接收参数 obj (Object)、propertyKey (属性键)、value (ECMAScript 语言值)、receiver (ECMAScript 语言值) 和 ownDesc ((属性描述符 或 undefined));返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 ownDesc 是 undefined,则
    1. 令 parent 为 ? obj.[[GetPrototypeOf]]()。
    2. 如果 parent 不是 null,则返回 ? parent.[[Set]](propertyKey, value, receiver)。
    3. 将 ownDesc 设置为 PropertyDescriptor { [[Value]]: undefined, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true }。
  2. 如果 IsDataDescriptor(ownDesc) 是 true,则
    1. 如果 ownDesc.[[Writable]] 是 false,则返回 false。
    2. 如果 receiver 不是 Object,则返回 false。
    3. 令 existingDesc 为 ? receiver.[[GetOwnProperty]](propertyKey)。
    4. 如果 existingDesc 是 undefined,则
      1. 断言:receiver 当前没有属性 propertyKey。
      2. 返回 ? CreateDataProperty(receiver, propertyKey, value)。
    5. 如果 IsAccessorDescriptor(existingDesc) 是 true,则返回 false。
    6. 如果 existingDesc.[[Writable]] 是 false,则返回 false。
    7. 令 valueDesc 为 PropertyDescriptor { [[Value]]: value }。
    8. 返回 ? receiver.[[DefineOwnProperty]](propertyKey, valueDesc)。
  3. 断言:IsAccessorDescriptor(ownDesc) 是 true。
  4. 令 setter 为 ownDesc.[[Setter]]。
  5. 如果 setter 是 undefined,则返回 false。
  6. 执行 ? Call(setter, receiver, « value »)。
  7. 返回 true。

10.1.10 [[Delete]] ( propertyKey )

an ordinary object obj的内部方法 [[Delete]],接收参数 propertyKey (属性键);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 返回 ? OrdinaryDelete(obj, propertyKey)。

10.1.10.1 OrdinaryDelete ( obj, propertyKey )

抽象操作 OrdinaryDelete,接收参数 obj (Object) 和 propertyKey (属性键);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 propertyDesc 为 ? obj.[[GetOwnProperty]](propertyKey)。
  2. 如果 propertyDesc 是 undefined,则返回 true。
  3. 如果 propertyDesc.[[Configurable]] 是 true,则
    1. 从 obj 中移除名为 propertyKey 的自有属性。
    2. 返回 true。
  4. 返回 false。

10.1.11 [[OwnPropertyKeys]] ( )

an ordinary object obj的内部方法 [[OwnPropertyKeys]],接收无参数;返回值:正常完成 (值:列表 (元素:属性键))。 调用时执行以下步骤:

  1. 返回 OrdinaryOwnPropertyKeys(obj)。

10.1.11.1 OrdinaryOwnPropertyKeys ( obj )

抽象操作 OrdinaryOwnPropertyKeys,接收参数 obj (Object);返回值:列表 (元素:属性键)。 调用时执行以下步骤:

  1. 令 keys 为新的空 List。
  2. 对 obj 的每个自有属性键 propertyKey,其中 propertyKey 是数组索引,按照数值索引升序执行
    1. 将 propertyKey 追加到 keys。
  3. 对 obj 的每个自有属性键 propertyKey,其中 propertyKey 是 String 且 propertyKey 不是数组索引,按照属性创建时间升序执行
    1. 将 propertyKey 追加到 keys。
  4. 对 obj 的每个自有属性键 propertyKey,其中 propertyKey 是 Symbol,按照属性创建时间升序执行
    1. 将 propertyKey 追加到 keys。
  5. 返回 keys。

10.1.12 OrdinaryObjectCreate ( proto [ , additionalInternalSlotsList ] )

抽象操作 OrdinaryObjectCreate,接收参数 proto ((Object 或 null))和可选参数 additionalInternalSlotsList (列表 (元素:内部槽名称));返回值:Object。 它用于规定新普通对象的运行时创建。additionalInternalSlotsList 包含除 [[Prototype]] 和 [[Extensible]] 之外,必须作为对象一部分定义的附加内部槽名称。如果未提供 additionalInternalSlotsList,则使用新的空 List。 调用时执行以下步骤:

  1. 令 internalSlotsList 为 « [[Prototype]], [[Extensible]] »。
  2. 如果存在 additionalInternalSlotsList,则将 internalSlotsList 设置为 internalSlotsList 和 additionalInternalSlotsList 的列表连接。
  3. 令 obj 为 MakeBasicObject(internalSlotsList)。
  4. 将 obj.[[Prototype]] 设置为 proto。
  5. 返回 obj。
注

尽管 OrdinaryObjectCreate 所做的事情几乎只是调用 MakeBasicObject,但使用它表达了创建普通对象而非异质对象的意图。因此,在本规范中,任何随后会以使结果变为非普通对象的方式修改对象内部方法的算法都不会调用它。创建异质对象的操作会直接调用 MakeBasicObject。

10.1.13 OrdinaryCreateFromConstructor ( ctor, intrinsicDefaultProto [ , internalSlotsList ] )

抽象操作 OrdinaryCreateFromConstructor,接收参数 ctor (函数对象) 和 intrinsicDefaultProto (String)和可选参数 internalSlotsList (列表 (元素:内部槽名称));返回值:(正常完成 (值:Object) 或 抛出完成)。 它创建一个普通对象;如果构造函数存在 "prototype" 属性,则从该属性取得其 [[Prototype]] 值。否则,使用由 intrinsicDefaultProto 命名的内在对象作为 [[Prototype]]。internalSlotsList 包含必须作为对象一部分定义的附加内部槽名称。如果未提供 internalSlotsList,则使用新的空 List。 调用时执行以下步骤:

  1. 断言:intrinsicDefaultProto 是本规范中某个内在对象的名称。对应对象必须是预期用作对象 [[Prototype]] 值的内在对象。
  2. 令 proto 为 ? GetPrototypeFromConstructor(ctor, intrinsicDefaultProto)。
  3. 如果存在 internalSlotsList,则令 slots 为 internalSlotsList。
  4. 否则,令 slots 为新的空 List。
  5. 返回 OrdinaryObjectCreate(proto, slots)。

10.1.14 GetPrototypeFromConstructor ( ctor, intrinsicDefaultProto )

抽象操作 GetPrototypeFromConstructor,接收参数 ctor (函数对象) 和 intrinsicDefaultProto (String);返回值:(正常完成 (值:Object) 或 抛出完成)。 它确定创建与特定构造函数对应的对象时应使用的 [[Prototype]] 值。如果构造函数存在 "prototype" 属性,则从该属性获取该值。否则,使用由 intrinsicDefaultProto 命名的内在对象作为 [[Prototype]]。 调用时执行以下步骤:

  1. 断言:intrinsicDefaultProto 是本规范中某个内在对象的名称。对应对象必须是预期用作对象 [[Prototype]] 值的内在对象。
  2. 令 proto 为 ? Get(ctor, "prototype")。
  3. 如果 proto 不是 Object,则
    1. 令 realm 为 ? GetFunctionRealm(ctor)。
    2. 将 proto 设置为 realm 中名为 intrinsicDefaultProto 的内在对象。
  4. 返回 proto。
注

如果 ctor 不提供 [[Prototype]] 值,则使用的默认值取自 ctor 函数的 Realm,而不是正在运行的执行上下文。

10.1.15 RequireInternalSlot ( obj, internalSlot )

抽象操作 RequireInternalSlot,接收参数 obj (ECMAScript 语言值) 和 internalSlot (内部槽名称);返回值:(正常完成 (值:unused) 或 抛出完成)。 除非 obj 是 Object 且具有给定内部槽,否则它会抛出异常。 调用时执行以下步骤:

  1. 如果 obj 不是 Object,则抛出 TypeError 异常。
  2. 如果 obj 没有 internalSlot 内部槽,则抛出 TypeError 异常。
  3. 返回 unused。

10.2 ECMAScript 函数对象

ECMAScript 函数对象封装了闭包于某个词法环境之上的参数化 ECMAScript 代码,并支持对该代码进行动态求值。ECMAScript 函数对象是普通对象,并具有与其他普通对象相同的内部槽和内部方法。ECMAScript 函数对象的代码可以是严格模式代码(11.2.2),也可以是非严格模式代码。其代码为严格模式代码的 ECMAScript 函数对象称为严格函数。其代码不是严格模式代码的 ECMAScript 函数对象称为非严格函数。

除 [[Extensible]] 和 [[Prototype]] 外,ECMAScript 函数对象还具有 表 26 中列出的内部槽。

表 26: ECMAScript 函数对象的内部槽
内部槽 类型 描述
[[Environment]] Environment Record 函数闭包所捕获的 Environment Record。在对函数代码求值时用作外层环境。
[[PrivateEnvironment]] PrivateEnvironment Record 或 null 函数闭包所捕获的 Private Name 对应的 PrivateEnvironment Record。如果此函数在句法上不包含在类中,则为 null。在对函数代码求值时,用作内部类的外层 PrivateEnvironment。
[[FormalParameters]] Parse Node 定义函数形式参数列表的源文本的根解析节点。
[[ECMAScriptCode]] Parse Node 定义函数主体的源文本的根解析节点。
[[ConstructorKind]] base 或 derived 函数是否为派生类构造函数。
[[Realm]] Realm Record 创建该函数的 Realm,并提供对函数求值时所访问的任何内在对象。
[[ScriptOrModule]] Script Record 或 Module Record 创建该函数的脚本或模块。
[[ThisMode]] lexical、strict 或 global 定义如何解释函数形式参数和代码主体中的 this 引用。lexical 表示 this 引用词法包围函数的 this 值。strict 表示 this 值完全按函数调用时提供的值使用。global 表示 undefined 或 null 的 this 值被解释为对全局对象的引用,而任何其他 this 值都会先传给 ToObject。
[[Strict]] Boolean 如果这是严格函数,则为 true;如果这是非严格函数,则为 false。
[[HomeObject]] Object 或 undefined 如果函数使用 super,则这是其 [[GetPrototypeOf]] 提供 super 属性查找起始对象的对象。
[[SourceText]] Unicode 码点序列 定义函数的源文本。
[[Fields]] ClassFieldDefinition Record 的 List 如果函数是类,则这是表示类的非静态字段及其对应初始化器的 Record 列表。
[[PrivateMethods]] PrivateElement 的 List 如果函数是类,则这是表示类的非静态私有方法和访问器的列表。
[[ClassFieldInitializerName]] String、Symbol、Private Name 或 empty 如果函数是作为类字段的初始化器创建的,则这是用于该字段 NamedEvaluation 的名称;否则为 empty。
[[IsClassConstructor]] Boolean 指示函数是否为类构造函数。(如果为 true,调用函数的 [[Call]] 会立即抛出 TypeError 异常。)

所有 ECMAScript 函数对象都具有此处定义的 [[Call]] 内部方法。除此之外,同时也是构造函数的 ECMAScript 函数还具有 [[Construct]] 内部方法。

10.2.1 [[Call]] ( thisArg, argList )

an ECMAScript function object func的内部方法 [[Call]],接收参数 thisArg (ECMAScript 语言值) 和 argList (列表 (元素:ECMAScript 语言值));返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 callerContext 为正在运行的执行上下文。
  2. 令 calleeContext 为 PrepareForOrdinaryCall(func, undefined)。
  3. 断言:calleeContext 现在是正在运行的执行上下文。
  4. 如果 func.[[IsClassConstructor]] 是 true,则
    1. 令 error 为新创建的 TypeError 对象。
    2. 注:error 在 calleeContext 中使用与 func 关联的 Realm Record 创建。
    3. 从执行上下文栈中移除 calleeContext,并恢复 callerContext 作为正在运行的执行上下文。
    4. 抛出 error。
  5. 执行 OrdinaryCallBindThis(func, calleeContext, thisArg)。
  6. 令 result 为 Completion(OrdinaryCallEvaluateBody(func, argList))。
  7. 从执行上下文栈中移除 calleeContext,并恢复 callerContext 作为正在运行的执行上下文。
  8. 如果 result 是抛出完成,则返回 ? result。
  9. 断言:result 是 return 完成。
  10. 返回 result.[[Value]]。
注

当步骤 7 中从执行上下文栈移除 calleeContext 时,如果它已暂停并由可访问的 Generator 保留以供以后恢复,则不得销毁它。

10.2.1.1 PrepareForOrdinaryCall ( func, newTarget )

抽象操作 PrepareForOrdinaryCall,接收参数 func (ECMAScript 函数对象) 和 newTarget ((Object 或 undefined));返回值:执行上下文。 调用时执行以下步骤:

  1. 令 callerContext 为正在运行的执行上下文。
  2. 令 calleeContext 为新的 ECMAScript 代码执行上下文。
  3. 将 calleeContext 的 Function 设置为 func。
  4. 令 calleeRealm 为 func.[[Realm]]。
  5. 将 calleeContext 的 Realm 设置为 calleeRealm。
  6. 将 calleeContext 的 ScriptOrModule 设置为 func.[[ScriptOrModule]]。
  7. 令 localEnv 为 NewFunctionEnvironment(func, newTarget)。
  8. 将 calleeContext 的 LexicalEnvironment 设置为 localEnv。
  9. 将 calleeContext 的 VariableEnvironment 设置为 localEnv。
  10. 将 calleeContext 的 PrivateEnvironment 设置为 func.[[PrivateEnvironment]]。
  11. 如果 callerContext 尚未暂停,则暂停 callerContext。
  12. 将 calleeContext 压入执行上下文栈;calleeContext 现在是正在运行的执行上下文。
  13. 注:从此处之后产生的任何异常对象都与 calleeRealm 关联。
  14. 返回 calleeContext。

10.2.1.2 OrdinaryCallBindThis ( func, calleeContext, thisArg )

抽象操作 OrdinaryCallBindThis,接收参数 func (ECMAScript 函数对象)、calleeContext (执行上下文) 和 thisArg (ECMAScript 语言值);返回值:unused。 调用时执行以下步骤:

  1. 令 thisMode 为 func.[[ThisMode]]。
  2. 如果 thisMode 是 lexical,则返回 unused。
  3. 令 calleeRealm 为 func.[[Realm]]。
  4. 令 localEnv 为 calleeContext 的 LexicalEnvironment。
  5. 如果 thisMode 是 strict,则
    1. 令 thisValue 为 thisArg。
  6. 否则,
    1. 如果 thisArg 是 undefined 或 null,则
      1. 令 globalEnv 为 calleeRealm.[[GlobalEnv]]。
      2. 断言:globalEnv 是 Global Environment Record。
      3. 令 thisValue 为 globalEnv.[[GlobalThisValue]]。
    2. 否则,
      1. 令 thisValue 为 ! ToObject(thisArg)。
      2. 注:ToObject 使用 calleeRealm 创建包装对象。
  7. 断言:localEnv 是 Function Environment Record。
  8. 断言:由于 localEnv.[[ThisBindingStatus]] 不是 initialized,所以下一步永远不会返回突然完成。
  9. 执行 ! BindThisValue(localEnv, thisValue)。
  10. 返回 unused。

10.2.1.3 Runtime Semantics: EvaluateBody

语法制导操作 EvaluateBody,接收参数 func (ECMAScript 函数对象) 和 argList (列表 (元素:ECMAScript 语言值));返回值:(返回完成 或 抛出完成)。 它按以下产生式分别定义:

FunctionBody : FunctionStatementList
  1. 返回 ? 以 func 和 argList 为参数对 FunctionBody 执行 EvaluateFunctionBody 的结果。
ConciseBody : ExpressionBody
  1. 返回 ? 以 func 和 argList 为参数对 ConciseBody 执行 EvaluateConciseBody 的结果。
GeneratorBody : FunctionBody
  1. 返回 ? 以 func 和 argList 为参数对 GeneratorBody 执行 EvaluateGeneratorBody 的结果。
AsyncGeneratorBody : FunctionBody
  1. 返回 ? 以 func 和 argList 为参数对 AsyncGeneratorBody 执行 EvaluateAsyncGeneratorBody 的结果。
AsyncFunctionBody : FunctionBody
  1. 返回 ? 以 func 和 argList 为参数对 AsyncFunctionBody 执行 EvaluateAsyncFunctionBody 的结果。
AsyncConciseBody : ExpressionBody
  1. 返回 ? 以 func 和 argList 为参数对 AsyncConciseBody 执行 EvaluateAsyncConciseBody 的结果。
Initializer : = AssignmentExpression
  1. 断言:argList 为空。
  2. 断言:func.[[ClassFieldInitializerName]] 不是 empty。
  3. 如果 IsAnonymousFunctionDefinition(AssignmentExpression) 是 true,则
    1. 令 value 为 ? 以 func.[[ClassFieldInitializerName]] 为参数对 Initializer 执行 NamedEvaluation 的结果。
  4. 否则,
    1. 令 rhs 为 ? AssignmentExpression 的 Evaluation。
    2. 令 value 为 ? GetValue(rhs)。
  5. 返回 ReturnCompletion(value)。
注

即使字段初始化器构成函数边界,调用 FunctionDeclarationInstantiation 也没有任何可观察效果,因此被省略。

ClassStaticBlockBody : ClassStaticBlockStatementList
  1. 断言:argList 为空。
  2. 返回 ? 以 func 为参数对 ClassStaticBlockBody 执行 EvaluateClassStaticBlockBody 的结果。

10.2.1.4 OrdinaryCallEvaluateBody ( func, argList )

抽象操作 OrdinaryCallEvaluateBody,接收参数 func (ECMAScript 函数对象) 和 argList (列表 (元素:ECMAScript 语言值));返回值:(返回完成 或 抛出完成)。 调用时执行以下步骤:

  1. 返回 ? 以 func 和 argList 为参数对 func.[[ECMAScriptCode]] 执行 EvaluateBody 的结果。

10.2.2 [[Construct]] ( argList, newTarget )

an ECMAScript function object func的内部方法 [[Construct]],接收参数 argList (列表 (元素:ECMAScript 语言值)) 和 newTarget (构造函数);返回值:(正常完成 (值:Object) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 callerContext 为正在运行的执行上下文。
  2. 令 kind 为 func.[[ConstructorKind]]。
  3. 如果 kind 是 base,则
    1. 令 thisArg 为 ? OrdinaryCreateFromConstructor(newTarget, "%Object.prototype%")。
  4. 令 calleeContext 为 PrepareForOrdinaryCall(func, newTarget)。
  5. 断言:calleeContext 现在是正在运行的执行上下文。
  6. 如果 kind 是 base,则
    1. 执行 OrdinaryCallBindThis(func, calleeContext, thisArg)。
    2. 令 initializeResult 为 Completion(InitializeInstanceElements(thisArg, func))。
    3. 如果 initializeResult 是突然完成,则
      1. 从执行上下文栈中移除 calleeContext,并恢复 callerContext 作为正在运行的执行上下文。
      2. 返回 ? initializeResult。
  7. 令 ctorEnv 为 calleeContext 的 LexicalEnvironment。
  8. 令 result 为 Completion(OrdinaryCallEvaluateBody(func, argList))。
  9. 从执行上下文栈中移除 calleeContext,并恢复 callerContext 作为正在运行的执行上下文。
  10. 如果 result 是抛出完成,则返回 ? result。
  11. 断言:result 是 return 完成。
  12. 如果 result.[[Value]] 是 Object,则返回 result.[[Value]]。
  13. 如果 kind 是 base,则返回 thisArg。
  14. 如果 result.[[Value]] 不是 undefined,则抛出 TypeError 异常。
  15. 令 thisBinding 为 ? ctorEnv.GetThisBinding()。
  16. 断言:thisBinding 是 Object。
  17. 返回 thisBinding。

10.2.3 OrdinaryFunctionCreate ( proto, sourceText, paramList, body, thisMode, envRecord, privateEnv )

抽象操作 OrdinaryFunctionCreate,接收参数 proto (Object)、sourceText (a sequence of Unicode code points)、paramList (解析节点)、body (解析节点)、thisMode ((lexical-this 或 non-lexical-this))、envRecord (Environment 记录) 和 privateEnv ((PrivateEnvironment 记录 或 null));返回值:ECMAScript 函数对象。 它用于规定运行时创建一个新的函数,该函数具有默认的 [[Call]] 内部方法且没有 [[Construct]] 内部方法(尽管随后可能通过 MakeConstructor 等操作添加)。sourceText 是要创建函数的句法定义的源文本。 调用时执行以下步骤:

  1. 令 internalSlotsList 为 表 26 中列出的内部槽。
  2. 令 func 为 OrdinaryObjectCreate(proto, internalSlotsList)。
  3. 将 func.[[Call]] 设置为 10.2.1 中规定的定义。
  4. 将 func.[[SourceText]] 设置为 sourceText。
  5. 将 func.[[FormalParameters]] 设置为 paramList。
  6. 将 func.[[ECMAScriptCode]] 设置为 body。
  7. 令 strict 为 IsStrict(body)。
  8. 将 func.[[Strict]] 设置为 strict。
  9. 如果 thisMode 是 lexical-this,则将 func.[[ThisMode]] 设置为 lexical。
  10. 否则如果 strict 是 true,则将 func.[[ThisMode]] 设置为 strict。
  11. 否则,将 func.[[ThisMode]] 设置为 global。
  12. 将 func.[[IsClassConstructor]] 设置为 false。
  13. 将 func.[[Environment]] 设置为 envRecord。
  14. 将 func.[[PrivateEnvironment]] 设置为 privateEnv。
  15. 将 func.[[ScriptOrModule]] 设置为 GetActiveScriptOrModule()。
  16. 将 func.[[Realm]] 设置为当前 Realm Record。
  17. 将 func.[[HomeObject]] 设置为 undefined。
  18. 将 func.[[Fields]] 设置为新的空 List。
  19. 将 func.[[PrivateMethods]] 设置为新的空 List。
  20. 将 func.[[ClassFieldInitializerName]] 设置为 empty。
  21. 令 length 为 paramList 的 ExpectedArgumentCount。
  22. 执行 SetFunctionLength(func, length)。
  23. 返回 func。

10.2.4 AddRestrictedFunctionProperties ( func, realm )

抽象操作 AddRestrictedFunctionProperties,接收参数 func (函数对象) 和 realm (Realm 记录);返回值:unused。 调用时执行以下步骤:

  1. 断言:realm.[[Intrinsics]].[[%ThrowTypeError%]] 存在且已初始化。
  2. 令 thrower 为 realm.[[Intrinsics]].[[%ThrowTypeError%]]。
  3. 执行 ! DefinePropertyOrThrow(func, "caller", PropertyDescriptor { [[Getter]]: thrower, [[Setter]]: thrower, [[Enumerable]]: false, [[Configurable]]: true })。
  4. 执行 ! DefinePropertyOrThrow(func, "arguments", PropertyDescriptor { [[Getter]]: thrower, [[Setter]]: thrower, [[Enumerable]]: false, [[Configurable]]: true })。
  5. 返回 unused。

10.2.4.1 %ThrowTypeError% ( )

此函数是 %ThrowTypeError% 内在对象。

它是一个匿名内置函数对象,每个 Realm 定义一次。

调用时,它执行以下步骤:

  1. 抛出 TypeError 异常。

此函数的 [[Extensible]] 内部槽值为 false。

此函数的 "length" 属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

此函数的 "name" 属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

10.2.5 MakeConstructor ( func [ , writableProto [ , proto ] ] )

抽象操作 MakeConstructor,接收参数 func ((ECMAScript 函数对象 或 内置函数对象))和可选参数 writableProto (Boolean) 和 proto (Object);返回值:unused。 它将 func 转换为构造函数。 调用时执行以下步骤:

  1. 如果 func 是 ECMAScript 函数对象,则
    1. 断言:IsConstructor(func) 是 false。
    2. 断言:func 是可扩展对象,并且没有 "prototype" 自有属性。
    3. 将 func.[[Construct]] 设置为 10.2.2 中规定的定义。
  2. 否则,
    1. 将 func.[[Construct]] 设置为 10.3.2 中规定的定义。
  3. 将 func.[[ConstructorKind]] 设置为 base。
  4. 如果不存在 writableProto,则将 writableProto 设置为 true。
  5. 如果不存在 proto,则
    1. 将 proto 设置为 OrdinaryObjectCreate(%Object.prototype%)。
    2. 执行 ! DefinePropertyOrThrow(proto, "constructor", PropertyDescriptor { [[Value]]: func, [[Writable]]: writableProto, [[Enumerable]]: false, [[Configurable]]: true })。
  6. 执行 ! DefinePropertyOrThrow(func, "prototype", PropertyDescriptor { [[Value]]: proto, [[Writable]]: writableProto, [[Enumerable]]: false, [[Configurable]]: false })。
  7. 返回 unused。

10.2.6 MakeClassConstructor ( func )

抽象操作 MakeClassConstructor,接收参数 func (ECMAScript 函数对象);返回值:unused。 调用时执行以下步骤:

  1. 断言:func.[[IsClassConstructor]] 是 false。
  2. 将 func.[[IsClassConstructor]] 设置为 true。
  3. 返回 unused。

10.2.7 MakeMethod ( func, homeObj )

抽象操作 MakeMethod,接收参数 func (ECMAScript 函数对象) 和 homeObj (Object);返回值:unused。 它将 func 配置为方法。 调用时执行以下步骤:

  1. 断言:homeObj 是普通对象。
  2. 将 func.[[HomeObject]] 设置为 homeObj。
  3. 返回 unused。

10.2.8 DefineMethodProperty ( homeObj, name, closure, enumerable )

抽象操作 DefineMethodProperty,接收参数 homeObj (Object)、name ((属性键 或 私有名称))、closure (函数对象) 和 enumerable (Boolean);返回值:(正常完成 (值:(PrivateElement 或 empty)) 或 突兀完成)。 调用时执行以下步骤:

  1. 断言:homeObj 是普通、可扩展对象。
  2. 如果 name 是 Private Name,则返回 PrivateElement { [[Key]]: name, [[Kind]]: method, [[Value]]: closure }。
  3. 令 propertyDesc 为 PropertyDescriptor { [[Value]]: closure, [[Writable]]: true, [[Enumerable]]: enumerable, [[Configurable]]: true }。
  4. 执行 ? DefinePropertyOrThrow(homeObj, name, propertyDesc)。
  5. 注:DefinePropertyOrThrow 仅在尝试定义 name 为 "prototype" 的类静态方法时返回突然完成。
  6. 返回 empty。

10.2.9 SetFunctionName ( func, name [ , prefix ] )

抽象操作 SetFunctionName,接收参数 func (函数对象) 和 name ((属性键 或 私有名称))和可选参数 prefix (String);返回值:unused。 它向 func 添加 "name" 属性。 调用时执行以下步骤:

  1. 断言:func 是可扩展对象,且没有 "name" 自有属性。
  2. 如果 name 是 Symbol,则
    1. 令 description 为 name.[[Description]]。
    2. 如果 description 是 undefined,则将 name 设置为空 String。
    3. 否则,将 name 设置为 "["、description 和 "]" 的字符串连接。
  3. 否则如果 name 是 Private Name,则
    1. 将 name 设置为 name.[[Description]]。
  4. 令 initialName 为 name。
  5. 如果存在 prefix,则
    1. 令 prefixedName 为 prefix、码元 0x0020 (SPACE) 和 name 的字符串连接。
    2. 将 initialName 设置为 prefixedName。
    3. Normative Optional, Legacy
      将 initialName 设置为实现定义地从 name 或 prefixedName 中选择的一个值。
    4. 将 name 设置为 prefixedName。
  6. 如果 func 具有 [[InitialName]] 内部槽,则将 func.[[InitialName]] 设置为 initialName。
  7. 执行 ! DefinePropertyOrThrow(func, "name", PropertyDescriptor { [[Value]]: name, [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true })。
  8. 返回 unused。
注

是否为 func.[[InitialName]] 使用 prefixedName 的选择会影响 Function.prototype.toString ( ) 的输出。在步骤 5.c 中针对不同内置函数做出不同选择,是不鼓励使用的遗留行为。

10.2.10 SetFunctionLength ( func, length )

抽象操作 SetFunctionLength,接收参数 func (函数对象) 和 length ((非负整数 或 +∞));返回值:unused。 它向 func 添加 "length" 属性。 调用时执行以下步骤:

  1. 断言:func 是可扩展对象,且没有 "length" 自有属性。
  2. 执行 ! DefinePropertyOrThrow(func, "length", PropertyDescriptor { [[Value]]: 𝔽(length), [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true })。
  3. 返回 unused。

10.2.11 FunctionDeclarationInstantiation ( func, argList )

抽象操作 FunctionDeclarationInstantiation,接收参数 func (ECMAScript 函数对象) 和 argList (列表 (元素:ECMAScript 语言值));返回值:(正常完成 (值:unused) 或 抛出完成)。 func 是正在为其建立执行上下文的函数对象。

注

为对 ECMAScript 函数求值而建立执行上下文时,会创建一个新的 Function Environment Record,并在该 Environment Record 中实例化每个形式参数的绑定。函数主体中的每个声明也会被实例化。如果函数的形式参数不包含任何默认值初始化器,则主体声明会在与参数相同的 Environment Record 中实例化。如果存在默认值参数初始化器,则会为主体声明创建第二个 Environment Record。形式参数和函数会作为 FunctionDeclarationInstantiation 的一部分进行初始化。所有其他绑定都会在函数主体求值期间初始化。

调用时,它执行以下步骤:

  1. 令 calleeContext 为正在运行的执行上下文。
  2. 令 code 为 func.[[ECMAScriptCode]]。
  3. 令 strict 为 func.[[Strict]]。
  4. 令 formals 为 func.[[FormalParameters]]。
  5. 令 paramNames 为 formals 的 BoundNames。
  6. 如果 paramNames 有任何重复条目,则令 hasDuplicates 为 true;否则令 hasDuplicates 为 false。
  7. 令 simpleParamList 为 formals 的 IsSimpleParameterList。
  8. 令 hasParamExprs 为 formals 的 ContainsExpression。
  9. 令 variableNames 为 code 的 VarDeclaredNames。
  10. 令 variableDecls 为 code 的 VarScopedDeclarations。
  11. 令 lexicalNames 为 code 的 LexicallyDeclaredNames。
  12. 令 funcNames 为新的空 List。
  13. 令 funcsToInitialize 为新的空 List。
  14. 对 variableDecls 的每个元素 variableDecl,按照 List 的逆序执行
    1. 如果 variableDecl 既不是 VariableDeclaration、也不是 ForBinding、也不是 BindingIdentifier,则
      1. 断言:variableDecl 是 FunctionDeclaration、GeneratorDeclaration、AsyncFunctionDeclaration 或 AsyncGeneratorDeclaration 之一。
      2. 令 funcName 为 variableDecl 的 BoundNames 的唯一元素。
      3. 如果 funcNames 不包含 funcName,则
        1. 将 funcName 插入为 funcNames 的第一个元素。
        2. 注:如果同一个名称有多个函数声明,则使用最后一个声明。
        3. 将 variableDecl 插入为 funcsToInitialize 的第一个元素。
  15. 令 argumentsObjNeeded 为 true。
  16. 如果 func.[[ThisMode]] 是 lexical,则
    1. 注:箭头函数永远没有 arguments 对象。
    2. 将 argumentsObjNeeded 设置为 false。
  17. 否则如果 paramNames 包含 "arguments",则
    1. 将 argumentsObjNeeded 设置为 false。
  18. 否则如果 hasParamExprs 是 false,则
    1. 如果 funcNames 包含 "arguments" 或 lexicalNames 包含 "arguments",则
      1. 将 argumentsObjNeeded 设置为 false。
  19. 如果 strict 是 true 或 hasParamExprs 是 false,则
    1. 注:参数只需要单个 Environment Record,因为严格模式代码中的 eval 调用无法创建在 eval 外部可见的新绑定。
    2. 令 envRecord 为 calleeContext 的 LexicalEnvironment。
  20. 否则,
    1. 注:需要单独的 Environment Record,以确保形式参数列表中的直接 eval 调用创建的绑定位于声明参数的环境之外。
    2. 令 calleeEnv 为 calleeContext 的 LexicalEnvironment。
    3. 令 envRecord 为 NewDeclarativeEnvironment(calleeEnv)。
    4. 断言:calleeContext 的 VariableEnvironment 与 calleeEnv 是同一个 Environment Record。
    5. 将 calleeContext 的 LexicalEnvironment 设置为 envRecord。
  21. 对 paramNames 的每个 String paramName,执行
    1. 令 alreadyDeclared 为 ! envRecord.HasBinding(paramName)。
    2. 注:提前错误确保,只有在没有参数默认值或剩余参数的非严格函数中才可能出现重复参数名称。
    3. 如果 alreadyDeclared 是 false,则
      1. 执行 ! envRecord.CreateMutableBinding(paramName, false)。
      2. 如果 hasDuplicates 是 true,则
        1. 执行 ! envRecord.InitializeBinding(paramName, undefined)。
  22. 如果 argumentsObjNeeded 是 true,则
    1. 如果 strict 是 true 或 simpleParamList 是 false,则
      1. 令 argumentsObj 为 CreateUnmappedArgumentsObject(argList)。
    2. 否则,
      1. 注:映射 arguments 对象仅为没有剩余参数、没有任何参数默认值初始化器、也没有任何解构参数的非严格函数提供。
      2. 令 argumentsObj 为 CreateMappedArgumentsObject(func, formals, argList, envRecord)。
    3. 如果 strict 是 true,则
      1. 执行 ! envRecord.CreateImmutableBinding("arguments", false)。
      2. 注:在严格模式代码中,提前错误会阻止尝试对此绑定进行赋值,因此其可变性不可观察。
    4. 否则,
      1. 执行 ! envRecord.CreateMutableBinding("arguments", false)。
    5. 执行 ! envRecord.InitializeBinding("arguments", argumentsObj)。
    6. 令 paramBindings 为 paramNames 与 « "arguments" » 的列表连接。
  23. 否则,
    1. 令 paramBindings 为 paramNames。
  24. 令 iteratorRecord 为 CreateListIteratorRecord(argList)。
  25. 如果 hasDuplicates 是 true,则
    1. 令 usedEnv 为 undefined。
  26. 否则,
    1. 令 usedEnv 为 envRecord。
  27. 注:以下步骤无法返回 ReturnCompletion,因为在表达式位置产生这种完成的唯一方式是使用 YieldExpression,而 15.5.1 和 15.6.1 中的提前错误规则禁止在参数列表中使用它。
  28. 执行 ? 以 iteratorRecord 和 usedEnv 为参数对 formals 执行 IteratorBindingInitialization。
  29. 如果 hasParamExprs 是 false,则
    1. 注:参数和顶层 var 只需要单个 Environment Record。
    2. 令 instantiatedVariableNames 为 List paramBindings 的副本。
    3. 对 variableNames 的每个元素 name,执行
      1. 如果 instantiatedVariableNames 不包含 name,则
        1. 将 name 追加到 instantiatedVariableNames。
        2. 执行 ! envRecord.CreateMutableBinding(name, false)。
        3. 执行 ! envRecord.InitializeBinding(name, undefined)。
    4. 令 variableEnv 为 envRecord。
  30. 否则,
    1. 注:需要单独的 Environment Record,以确保由形式参数列表中的表达式创建的闭包看不到函数主体中的声明。
    2. 令 variableEnv 为 NewDeclarativeEnvironment(envRecord)。
    3. 将 calleeContext 的 VariableEnvironment 设置为 variableEnv。
    4. 令 instantiatedVariableNames 为新的空 List。
    5. 对 variableNames 的每个元素 name,执行
      1. 如果 instantiatedVariableNames 不包含 name,则
        1. 将 name 追加到 instantiatedVariableNames。
        2. 执行 ! variableEnv.CreateMutableBinding(name, false)。
        3. 如果 paramBindings 不包含 name 或 funcNames 包含 name,则
          1. 令 initialValue 为 undefined。
        4. 否则,
          1. 令 initialValue 为 ! envRecord.GetBindingValue(name, false)。
        5. 执行 ! variableEnv.InitializeBinding(name, initialValue)。
        6. 注:与形式参数同名的 var 最初具有与对应已初始化参数相同的值。
  31. 如果 strict 是 true,则
    1. 令 lexicalEnv 为 variableEnv。
  32. 否则,
    1. Normative Optional
      如果宿主是 Web 浏览器或以其他方式支持 块级函数声明的 Web 遗留兼容性语义,则
      1. 对任何 Block、CaseClause 或 DefaultClause x 的 StatementList 中直接包含的每个 FunctionDeclaration funcDecl,且 code Contains x 是 true,执行
        1. 令 funcName 为 funcDecl 的 BindingIdentifier 的 StringValue。
        2. 如果将 FunctionDeclaration funcDecl 替换为一个以 funcName 作为 BindingIdentifier 的 VariableStatement 不会为 func 产生任何提前错误,并且 paramNames 不包含 funcName,则
          1. 注:只有当 funcName 既不是 VarDeclaredName、也不是形式参数名称、也不是另一个 FunctionDeclaration 的名称时,才会在此处为 funcName 实例化 var 绑定。
          2. 如果 instantiatedVariableNames 不包含 funcName 且 funcName 不是 "arguments",则
            1. 执行 ! variableEnv.CreateMutableBinding(funcName, false)。
            2. 执行 ! variableEnv.InitializeBinding(funcName, undefined)。
            3. 将 funcName 追加到 instantiatedVariableNames。
          3. 当对 FunctionDeclaration funcDecl 求值时,执行以下步骤,以代替 15.2.6 中提供的 FunctionDeclaration Evaluation 算法:
            1. 令 funcEnv 为正在运行的执行上下文的 VariableEnvironment。
            2. 令 blockEnv 为正在运行的执行上下文的 LexicalEnvironment。
            3. 令 funcObj 为 ! blockEnv.GetBindingValue(funcName, false)。
            4. 执行 ! funcEnv.SetMutableBinding(funcName, funcObj, false)。
            5. 返回 unused。
    2. 令 lexicalEnv 为 NewDeclarativeEnvironment(variableEnv)。
    3. 注:非严格函数为顶层词法声明使用单独的 Environment Record,以便直接 eval 能够确定 eval 代码引入的任何 var 作用域声明是否与预先存在的顶层词法作用域声明冲突。严格函数不需要这样做,因为严格模式直接 eval 始终将所有声明放入新的 Environment Record。
  33. 将 calleeContext 的 LexicalEnvironment 设置为 lexicalEnv。
  34. 令 lexicalDecls 为 code 的 LexicallyScopedDeclarations。
  35. 对 lexicalDecls 的每个元素 lexicalDecl,执行
    1. 注:词法声明名称不能与函数/生成器声明、形式参数或 var 名称相同。词法声明名称仅在此处实例化,但不初始化。
    2. 对 lexicalDecl 的 BoundNames 的每个元素 name,执行
      1. 如果 lexicalDecl 的 IsConstantDeclaration 是 true,则
        1. 执行 ! lexicalEnv.CreateImmutableBinding(name, true)。
      2. 否则,
        1. 执行 ! lexicalEnv.CreateMutableBinding(name, false)。
  36. 令 privateEnv 为 calleeContext 的 PrivateEnvironment。
  37. 对 funcsToInitialize 的每个 Parse Node funcDecl,执行
    1. 令 funcName 为 funcDecl 的 BoundNames 的唯一元素。
    2. 令 funcObj 为以 lexicalEnv 和 privateEnv 为参数对 funcDecl 执行 InstantiateFunctionObject 的结果。
    3. 执行 ! variableEnv.SetMutableBinding(funcName, funcObj, false)。
  38. 返回 unused。

10.3 内置函数对象

内置函数对象是普通对象;它必须满足 10.1 中规定的普通对象要求。

除每个普通对象所需的内部槽(参见 10.1)之外,内置函数对象还必须具有以下内部槽:

  • [[Realm]],表示创建该函数所在 Realm 的 Realm Record。
  • [[InitialName]],作为函数初始名称的 String。它由 20.2.3.5 使用。
  • [[Async]],一个 Boolean,指示该函数在 BuiltinCallOrConstruct 中是否具有异步函数调用和构造行为。

除非另有规定,内置函数对象的 [[Prototype]] 内部槽的初始值为 %Function.prototype%。

内置函数对象必须具有符合 10.3.1 中定义的 [[Call]] 内部方法。

当且仅当内置函数对象被描述为“构造函数”,或者本规范中的某个算法显式设置其 [[Construct]] 内部方法时,它才具有 [[Construct]] 内部方法。这样的 [[Construct]] 内部方法必须符合 10.3.2 中的定义。

实现可以提供本规范未定义的其他内置函数对象。

10.3.1 [[Call]] ( thisArg, argList )

a built-in function object func的内部方法 [[Call]],接收参数 thisArg (ECMAScript 语言值) 和 argList (列表 (元素:ECMAScript 语言值));返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。 调用时执行以下步骤:

  1. 返回 ? BuiltinCallOrConstruct(func, thisArg, argList, undefined)。

10.3.2 [[Construct]] ( argList, newTarget )

a built-in function object func (when the method is present)的内部方法 [[Construct]],接收参数 argList (列表 (元素:ECMAScript 语言值)) 和 newTarget (构造函数);返回值:(正常完成 (值:Object) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 result 为 ? BuiltinCallOrConstruct(func, uninitialized, argList, newTarget)。
  2. 断言:result 是 Object。
  3. 返回 result。

10.3.3 BuiltinCallOrConstruct ( func, thisArg, argList, newTarget )

抽象操作 BuiltinCallOrConstruct,接收参数 func (内置函数对象)、thisArg ((ECMAScript 语言值 或 uninitialized))、argList (列表 (元素:ECMAScript 语言值)) 和 newTarget ((构造函数 或 undefined));返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 callerContext 为正在运行的执行上下文。
  2. 如果 callerContext 尚未暂停,则暂停 callerContext。
  3. 令 calleeContext 为新的执行上下文。
  4. 将 calleeContext 的 Function 设置为 func。
  5. 令 calleeRealm 为 func.[[Realm]]。
  6. 将 calleeContext 的 Realm 设置为 calleeRealm。
  7. 将 calleeContext 的 ScriptOrModule 设置为 null。
  8. 执行对 calleeContext 所需的任何实现定义初始化。
  9. 将 calleeContext 压入执行上下文栈;calleeContext 现在是正在运行的执行上下文。
  10. 如果 func.[[Async]] 是 true,则
    1. 令 promiseCapability 为 ! NewPromiseCapability(%Promise%)。
    2. 令 resultsClosure 为一个没有参数的新 Abstract Closure,它捕获 func、thisArg、argList 和 newTarget,并在被调用时执行以下步骤:
      1. 令 result 为按照符合 func 规范的方式对 func 求值的结果所得的 Completion Record。如果 thisArg 是 uninitialized,则 this 值未初始化;否则 thisArg 提供 this 值。argList 提供具名参数。newTarget 提供 NewTarget 值。
      2. 注:如果 func 在本文档中定义,则“func 的规范”是通过算法步骤或其他方式为它规定的行为。
      3. 返回 Completion(result)。
    3. 执行 AsyncFunctionStart(promiseCapability, resultsClosure)。
    4. 从执行上下文栈中移除 calleeContext,并恢复 callerContext 作为正在运行的执行上下文。
    5. 返回 promiseCapability.[[Promise]]。
  11. 令 result 为按照符合 func 规范的方式对 func 求值的结果所得的 Completion Record。如果 thisArg 是 uninitialized,则 this 值未初始化;否则 thisArg 提供 this 值。argList 提供具名参数。newTarget 提供 NewTarget 值。
  12. 注:如果 func 在本文档中定义,则“func 的规范”是通过算法步骤或其他方式为它规定的行为。
  13. 从执行上下文栈中移除 calleeContext,并恢复 callerContext 作为正在运行的执行上下文。
  14. 返回 ? result。
注

从执行上下文栈中移除 calleeContext 时,如果它已经暂停并由可访问的 Generator 保留以便以后恢复,则不得销毁它。

10.3.4 CreateBuiltinFunction ( behaviour, length, name, additionalInternalSlotsList [ , realm [ , proto [ , prefix [ , async ] ] ] ] )

抽象操作 CreateBuiltinFunction,接收参数 behaviour ((抽象闭包、a set of algorithm steps 或 some other definition of a function's behaviour provided in this specification))、length ((非负整数 或 +∞))、name ((属性键 或 私有名称)) 和 additionalInternalSlotsList (列表 (元素:内部槽名称))和可选参数 realm (Realm 记录)、proto ((Object 或 null))、prefix (String) 和 async (Boolean);返回值:内置函数对象。 additionalInternalSlotsList 包含必须作为对象一部分定义的附加内部槽名称。此操作创建一个内置函数对象。 调用时执行以下步骤:

  1. 如果不存在 realm,则将 realm 设置为当前 Realm Record。
  2. 如果不存在 proto,则将 proto 设置为 realm.[[Intrinsics]].[[%Function.prototype%]]。
  3. 如果不存在 async,则将 async 设置为 false。
  4. 令 internalSlotsList 为一个 List,其中包含 10.3 对即将创建的内置函数对象要求的所有内部槽名称。
  5. 将 additionalInternalSlotsList 的元素追加到 internalSlotsList。
  6. 令 func 为新的内置函数对象;当被调用时,它使用所提供的参数作为 behaviour 所规定对应参数的值,执行 behaviour 所描述的操作。新函数对象具有名称为 internalSlotsList 中元素的内部槽,以及一个 [[InitialName]] 内部槽。
  7. 将 func.[[Async]] 设置为 async。
  8. 将 func.[[Prototype]] 设置为 proto。
  9. 将 func.[[Extensible]] 设置为 true。
  10. 将 func.[[Realm]] 设置为 realm。
  11. 将 func.[[InitialName]] 设置为 null。
  12. 执行 SetFunctionLength(func, length)。
  13. 如果不存在 prefix,则
    1. 执行 SetFunctionName(func, name)。
  14. 否则,
    1. 执行 SetFunctionName(func, name, prefix)。
  15. 返回 func。

本规范中定义的每个内置函数都通过调用 CreateBuiltinFunction 抽象操作创建。

10.4 内置异质对象内部方法和内部槽

本规范定义了若干种内置异质对象。这些对象通常与普通对象行为类似,仅在少数特定情况下有所不同。以下异质对象除下文明确另有规定外,都使用普通对象内部方法:

10.4.1 绑定函数异质对象

绑定函数异质对象是一种包装另一个函数对象的异质对象。绑定函数异质对象是可调用的(它具有 [[Call]] 内部方法,并且可能具有 [[Construct]] 内部方法)。调用绑定函数异质对象通常会导致调用其所包装的函数。

如果一个对象的 [[Call]] 以及(如果适用)[[Construct]] 内部方法使用以下实现,并且其其他基本内部方法使用 10.1 中的定义,则该对象是绑定函数异质对象。这些方法在 BoundFunctionCreate 中安装。

绑定函数异质对象不具有 表 26 中列出的 ECMAScript 函数对象内部槽。相反,除 [[Prototype]] 和 [[Extensible]] 外,它们还具有 表 27 中列出的内部槽。

表 27: 绑定函数异质对象的内部槽
内部槽 类型 描述
[[BoundTargetFunction]] 可调用 Object 被包装的函数对象。
[[BoundThis]] ECMAScript 语言值 调用被包装函数时始终作为 this 值传递的值。
[[BoundArguments]] ECMAScript 语言值的 List 一个值列表,其元素用作对被包装函数的任何调用中的首批参数。

10.4.1.1 [[Call]] ( thisArg, argList )

a bound function exotic object func的内部方法 [[Call]],接收参数 thisArg (ECMAScript 语言值) 和 argList (列表 (元素:ECMAScript 语言值));返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 target 为 func.[[BoundTargetFunction]]。
  2. 令 boundThis 为 func.[[BoundThis]]。
  3. 令 boundArgs 为 func.[[BoundArguments]]。
  4. 令 args 为 boundArgs 和 argList 的列表连接。
  5. 返回 ? Call(target, boundThis, args)。

10.4.1.2 [[Construct]] ( argList, newTarget )

a bound function exotic object func的内部方法 [[Construct]],接收参数 argList (列表 (元素:ECMAScript 语言值)) 和 newTarget (构造函数);返回值:(正常完成 (值:Object) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 target 为 func.[[BoundTargetFunction]]。
  2. 断言:IsConstructor(target) 是 true。
  3. 令 boundArgs 为 func.[[BoundArguments]]。
  4. 令 args 为 boundArgs 和 argList 的列表连接。
  5. 如果 SameValue(func, newTarget) 是 true,则将 newTarget 设置为 target。
  6. 返回 ? Construct(target, args, newTarget)。

10.4.1.3 BoundFunctionCreate ( targetFunc, boundThis, boundArgs )

抽象操作 BoundFunctionCreate,接收参数 targetFunc (函数对象)、boundThis (ECMAScript 语言值) 和 boundArgs (列表 (元素:ECMAScript 语言值));返回值:(正常完成 (值:函数对象) 或 抛出完成)。 它用于规定创建新的绑定函数异质对象。 调用时执行以下步骤:

  1. 令 proto 为 ? targetFunc.[[GetPrototypeOf]]()。
  2. 令 internalSlotsList 为 « [[Prototype]], [[Extensible]] » 与 表 27 中列出的内部槽的列表连接。
  3. 令 obj 为 MakeBasicObject(internalSlotsList)。
  4. 将 obj.[[Prototype]] 设置为 proto。
  5. 按 10.4.1.1 中的规定设置 obj.[[Call]]。
  6. 如果 IsConstructor(targetFunc) 是 true,则
    1. 按 10.4.1.2 中的规定设置 obj.[[Construct]]。
  7. 将 obj.[[BoundTargetFunction]] 设置为 targetFunc。
  8. 将 obj.[[BoundThis]] 设置为 boundThis。
  9. 将 obj.[[BoundArguments]] 设置为 boundArgs。
  10. 返回 obj。

10.4.2 Array 异质对象

Array 是一种对数组索引属性键(参见 6.1.7)进行特殊处理的异质对象。属性名称为数组索引的属性也称为元素。每个 Array 都有一个不可配置的 "length" 属性,其值始终是数学值严格小于 232 的非负整数 Number。"length" 属性的值在数值上大于名称为数组索引的每个自有属性的名称;每当创建或更改 Array 的自有属性时,都会根据需要调整其他属性以维持此不变量。具体而言,每当添加名称为数组索引的自有属性时,如有必要,"length" 属性的值会更改为该数组索引数值加一;而每当 "length" 属性的值发生变化时,所有名称为数组索引且其值不小于新长度的自有属性都会被删除。此约束仅适用于 Array 的自有属性,不受可能从其原型继承的 "length" 或数组索引属性影响。

如果一个对象的 [[DefineOwnProperty]] 内部方法使用以下实现,并且其其他基本内部方法使用 10.1 中的定义,则该对象是 Array 异质对象(或简称 Array)。这些方法在 ArrayCreate 中安装。

10.4.2.1 [[DefineOwnProperty]] ( propertyKey, propertyDesc )

an Array exotic object array的内部方法 [[DefineOwnProperty]],接收参数 propertyKey (属性键) 和 propertyDesc (属性描述符);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 propertyKey 是 "length",则返回 ? ArraySetLength(array, propertyDesc)。
  2. 如果 propertyKey 是数组索引,则
    1. 令 lengthDesc 为 OrdinaryGetOwnProperty(array, "length")。
    2. 断言:lengthDesc 不是 undefined。
    3. 断言:IsDataDescriptor(lengthDesc) 是 true。
    4. 断言:lengthDesc.[[Configurable]] 是 false。
    5. 令 length 为 lengthDesc.[[Value]]。
    6. 断言:length 是非负整数 Number。
    7. 令 index 为 ! ToUint32(propertyKey)。
    8. 如果 index ≥ length 且 lengthDesc.[[Writable]] 是 false,则返回 false。
    9. 令 succeeded 为 ! OrdinaryDefineOwnProperty(array, propertyKey, propertyDesc)。
    10. 如果 succeeded 是 false,则返回 false。
    11. 如果 index ≥ length,则
      1. 将 lengthDesc.[[Value]] 设置为 index + 1𝔽。
      2. 将 succeeded 设置为 ! OrdinaryDefineOwnProperty(array, "length", lengthDesc)。
      3. 断言:succeeded 是 true。
    12. 返回 true。
  3. 返回 ? OrdinaryDefineOwnProperty(array, propertyKey, propertyDesc)。

10.4.2.2 ArrayCreate ( length [ , proto ] )

抽象操作 ArrayCreate,接收参数 length (非负整数)和可选参数 proto (Object);返回值:(正常完成 (值:Array 特异对象) 或 抛出完成)。 它用于规定创建新的 Array。 调用时执行以下步骤:

  1. 如果 length > 232 - 1,则抛出 RangeError 异常。
  2. 如果不存在 proto,则将 proto 设置为 %Array.prototype%。
  3. 令 array 为 MakeBasicObject(« [[Prototype]], [[Extensible]] »)。
  4. 将 array.[[Prototype]] 设置为 proto。
  5. 按 10.4.2.1 中的规定设置 array.[[DefineOwnProperty]]。
  6. 执行 ! OrdinaryDefineOwnProperty(array, "length", PropertyDescriptor { [[Value]]: 𝔽(length), [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  7. 返回 array。

10.4.2.3 ArraySpeciesCreate ( originalArray, length )

抽象操作 ArraySpeciesCreate,接收参数 originalArray (Object) 和 length (非负整数);返回值:(正常完成 (值:Object) 或 抛出完成)。 它用于规定使用从 originalArray 派生的构造函数创建新的 Array 或类似对象。它并不强制要求该构造函数返回 Array。 调用时执行以下步骤:

  1. 令 isArray 为 ? IsArray(originalArray)。
  2. 如果 isArray 是 false,则返回 ? ArrayCreate(length)。
  3. 令 ctor 为 ? Get(originalArray, "constructor")。
  4. 如果 IsConstructor(ctor) 是 true,则
    1. 令 thisRealm 为当前 Realm Record。
    2. 令 ctorRealm 为 ? GetFunctionRealm(ctor)。
    3. 如果 thisRealm 和 ctorRealm 不是同一个 Realm Record,则
      1. 如果 SameValue(ctor, ctorRealm.[[Intrinsics]].[[%Array%]]) 是 true,则将 ctor 设置为 undefined。
  5. 如果 ctor 是 Object,则
    1. 将 ctor 设置为 ? Get(ctor, %Symbol.species%)。
    2. 如果 ctor 是 null,则将 ctor 设置为 undefined。
  6. 如果 ctor 是 undefined,则返回 ? ArrayCreate(length)。
  7. 如果 IsConstructor(ctor) 是 false,则抛出 TypeError 异常。
  8. 返回 ? Construct(ctor, « 𝔽(length) »)。
注

如果 originalArray 是使用并非正在运行的执行上下文所属 Realm 的标准内置 Array 构造函数创建的,则会使用正在运行的执行上下文所属 Realm 创建新的 Array。这维持了与 Web 浏览器历史行为的兼容性;那些现在使用 ArraySpeciesCreate 定义的 Array.prototype 方法历史上就具有这种行为。

10.4.2.4 ArraySetLength ( array, propertyDesc )

抽象操作 ArraySetLength,接收参数 array (Array) 和 propertyDesc (属性描述符);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 propertyDesc 没有 [[Value]] 字段,则
    1. 返回 ! OrdinaryDefineOwnProperty(array, "length", propertyDesc)。
  2. 令 newLengthDesc 为 propertyDesc 的副本。
  3. 令 newLength 为 ? ToUint32(propertyDesc.[[Value]])。
  4. 令 numberLength 为 ? ToNumber(propertyDesc.[[Value]])。
  5. 如果 SameValueZero(newLength, numberLength) 是 false,则抛出 RangeError 异常。
  6. 将 newLengthDesc.[[Value]] 设置为 newLength。
  7. 令 oldLengthDesc 为 OrdinaryGetOwnProperty(array, "length")。
  8. 断言:oldLengthDesc 不是 undefined。
  9. 断言:IsDataDescriptor(oldLengthDesc) 是 true。
  10. 断言:oldLengthDesc.[[Configurable]] 是 false。
  11. 令 oldLength 为 oldLengthDesc.[[Value]]。
  12. 如果 newLength ≥ oldLength,则
    1. 返回 ! OrdinaryDefineOwnProperty(array, "length", newLengthDesc)。
  13. 如果 oldLengthDesc.[[Writable]] 是 false,则返回 false。
  14. 如果 newLengthDesc 没有 [[Writable]] 字段或 newLengthDesc.[[Writable]] 是 true,则
    1. 令 newWritable 为 true。
  15. 否则,
    1. 注:将 [[Writable]] 特性设置为 false 会被延迟,以防某些元素无法删除。
    2. 令 newWritable 为 false。
    3. 将 newLengthDesc.[[Writable]] 设置为 true。
  16. 令 succeeded 为 ! OrdinaryDefineOwnProperty(array, "length", newLengthDesc)。
  17. 如果 succeeded 是 false,则返回 false。
  18. 对 array 的每个自有属性键 propertyKey,其中 propertyKey 是数组索引并且 ! ToUint32(propertyKey) ≥ newLength,按照数值索引降序执行
    1. 令 deleteSucceeded 为 ! array.[[Delete]](propertyKey)。
    2. 如果 deleteSucceeded 是 false,则
      1. 将 newLengthDesc.[[Value]] 设置为 ! ToUint32(propertyKey) + 1𝔽。
      2. 如果 newWritable 是 false,则将 newLengthDesc.[[Writable]] 设置为 false。
      3. 执行 ! OrdinaryDefineOwnProperty(array, "length", newLengthDesc)。
      4. 返回 false。
  19. 如果 newWritable 是 false,则
    1. 将 succeeded 设置为 ! OrdinaryDefineOwnProperty(array, "length", PropertyDescriptor { [[Writable]]: false })。
    2. 断言:succeeded 是 true。
  20. 返回 true。
注

在步骤 3 和 4 中,如果 propertyDesc.[[Value]] 是对象,则其 valueOf 方法会被调用两次。这是自本规范第 2版起就规定具有此效果的遗留行为。

10.4.3 String 异质对象

String 对象是一种封装 String 值并暴露与该 String 值的各个码元元素对应的虚拟整数索引数据属性的异质对象。String 异质对象始终具有名为 "length" 的数据属性,其值是所封装 String 值的长度。码元数据属性和 "length" 属性均不可写且不可配置。

如果一个对象的 [[GetOwnProperty]]、[[DefineOwnProperty]] 和 [[OwnPropertyKeys]] 内部方法使用以下实现,并且其其他基本内部方法使用 10.1 中的定义,则该对象是 String 异质对象(或简称 String 对象)。这些方法在 StringCreate 中安装。

String 异质对象具有与普通对象相同的内部槽。它们还具有 [[StringData]] 内部槽。

10.4.3.1 [[GetOwnProperty]] ( propertyKey )

a String exotic object string的内部方法 [[GetOwnProperty]],接收参数 propertyKey (属性键);返回值:正常完成 (值:(属性描述符 或 undefined))。 调用时执行以下步骤:

  1. 令 propertyDesc 为 OrdinaryGetOwnProperty(string, propertyKey)。
  2. 如果 propertyDesc 不是 undefined,则返回 propertyDesc。
  3. 返回 StringGetOwnProperty(string, propertyKey)。

10.4.3.2 [[DefineOwnProperty]] ( propertyKey, propertyDesc )

a String exotic object string的内部方法 [[DefineOwnProperty]],接收参数 propertyKey (属性键) 和 propertyDesc (属性描述符);返回值:正常完成 (值:Boolean)。 调用时执行以下步骤:

  1. 令 stringDesc 为 StringGetOwnProperty(string, propertyKey)。
  2. 如果 stringDesc 不是 undefined,则
    1. 令 extensible 为 string.[[Extensible]]。
    2. 返回 IsCompatiblePropertyDescriptor(extensible, propertyDesc, stringDesc)。
  3. 返回 ! OrdinaryDefineOwnProperty(string, propertyKey, propertyDesc)。

10.4.3.3 [[OwnPropertyKeys]] ( )

a String exotic object obj的内部方法 [[OwnPropertyKeys]],接收无参数;返回值:正常完成 (值:列表 (元素:属性键))。 调用时执行以下步骤:

  1. 令 keys 为新的空 List。
  2. 令 string 为 obj.[[StringData]]。
  3. 断言:string 是 String。
  4. 令 length 为 string 的长度。
  5. 对满足 0 ≤ i < length 的每个整数 i,按升序执行
    1. 将 ! ToString(𝔽(i)) 追加到 keys。
  6. 对 obj 的每个自有属性键 propertyKey,其中 propertyKey 是数组索引且 ! ToIntegerOrInfinity(propertyKey) ≥ length,按照数值索引升序执行
    1. 将 propertyKey 追加到 keys。
  7. 对 obj 的每个自有属性键 propertyKey,其中 propertyKey 是 String 且 propertyKey 不是数组索引,按照属性创建时间升序执行
    1. 将 propertyKey 追加到 keys。
  8. 对 obj 的每个自有属性键 propertyKey,其中 propertyKey 是 Symbol,按照属性创建时间升序执行
    1. 将 propertyKey 追加到 keys。
  9. 返回 keys。

10.4.3.4 StringCreate ( value, proto )

抽象操作 StringCreate,接收参数 value (String) 和 proto (Object);返回值:String 特异对象。 它用于规定创建新的 String 异质对象。 调用时执行以下步骤:

  1. 令 string 为 MakeBasicObject(« [[Prototype]], [[Extensible]], [[StringData]] »)。
  2. 将 string.[[Prototype]] 设置为 proto。
  3. 将 string.[[StringData]] 设置为 value。
  4. 按 10.4.3.1 中的规定设置 string.[[GetOwnProperty]]。
  5. 按 10.4.3.2 中的规定设置 string.[[DefineOwnProperty]]。
  6. 按 10.4.3.3 中的规定设置 string.[[OwnPropertyKeys]]。
  7. 令 length 为 value 的长度。
  8. 执行 ! DefinePropertyOrThrow(string, "length", PropertyDescriptor { [[Value]]: 𝔽(length), [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false })。
  9. 返回 string。

10.4.3.5 StringGetOwnProperty ( string, propertyKey )

抽象操作 StringGetOwnProperty,接收参数 string (String 特异对象) 和 propertyKey (属性键);返回值:(属性描述符 或 undefined)。 调用时执行以下步骤:

  1. 如果 propertyKey 不是 String,则返回 undefined。
  2. 令 numericIndex 为 CanonicalNumericIndexString(propertyKey)。
  3. 如果 numericIndex 不是整数 Number,则返回 undefined。
  4. 如果 numericIndex 是 -0𝔽 或 numericIndex < -0𝔽,则返回 undefined。
  5. 令 stringData 为 string.[[StringData]]。
  6. 断言:stringData 是 String。
  7. 令 length 为 stringData 的长度。
  8. 如果 ℝ(numericIndex) ≥ length,则返回 undefined。
  9. 令 resultString 为 stringData 从 ℝ(numericIndex) 到 ℝ(numericIndex) + 1 的子字符串。
  10. 返回 PropertyDescriptor { [[Value]]: resultString, [[Writable]]: false, [[Enumerable]]: true, [[Configurable]]: false }。

10.4.4 Arguments 异质对象

大多数 ECMAScript 函数都会向其代码提供 arguments 对象。根据函数定义的特征,其 arguments 对象可能是普通对象,也可能是 arguments 异质对象。arguments 异质对象是一种异质对象,其数组索引属性映射到与其关联的 ECMAScript 函数调用的形式参数绑定。

如果一个对象的内部方法使用以下实现,而此处未规定的那些内部方法使用 10.1 中的定义,则该对象是 arguments 异质对象。这些方法在 CreateMappedArgumentsObject 中安装。

注 1

尽管 CreateUnmappedArgumentsObject 被归入本条款,但它创建的是普通对象,而不是 arguments 异质对象。

Arguments 异质对象具有与普通对象相同的内部槽。它们还具有 [[ParameterMap]] 内部槽。普通 arguments 对象也具有 [[ParameterMap]] 内部槽,其值始终为 undefined。对于普通 arguments 对象,[[ParameterMap]] 内部槽仅由 Object.prototype.toString(20.1.3.6)使用,以将其识别为 arguments 对象。

注 2

arguments 异质对象中数值名称小于相应函数对象形式参数数量的整数索引数据属性,最初会与函数执行上下文中对应参数绑定共享其值。这意味着更改属性会更改参数绑定的对应值,反之亦然。如果删除此类属性后重新定义,或者将该属性更改为访问器属性,这种对应关系就会被解除。如果 arguments 对象是普通对象,则其属性值只是传给函数的参数副本,属性值与形式参数值之间不存在动态链接。

注 3

ParameterMap 对象及其属性值被用作规定 arguments 对象与参数绑定之间对应关系的机制。ECMAScript 代码无法直接观察 ParameterMap 对象以及作为其属性值的对象。ECMAScript 实现无需实际创建或使用此类对象即可实现规定的语义。

注 4

普通 arguments 对象定义了一个名为 "callee" 的不可配置访问器属性,访问该属性会抛出 TypeError 异常。"callee" 属性对于 arguments 异质对象具有更具体的含义,而 arguments 异质对象只会为某类非严格函数创建。普通变体中定义此属性,是为了确保符合规范的 ECMAScript 实现不会以其他方式定义它。

注 5

ECMAScript 对 arguments 异质对象的实现历史上曾包含一个名为 "caller" 的访问器属性。在 ECMAScript 2017 之前,本规范包含了普通 arguments 对象上会抛出异常的 "caller" 属性定义。由于实现不再包含此扩展,ECMAScript 2017 取消了会抛出异常的 "caller" 访问器要求。

10.4.4.1 [[GetOwnProperty]] ( propertyKey )

an arguments exotic object args的内部方法 [[GetOwnProperty]],接收参数 propertyKey (属性键);返回值:正常完成 (值:(属性描述符 或 undefined))。 调用时执行以下步骤:

  1. 令 propertyDesc 为 OrdinaryGetOwnProperty(args, propertyKey)。
  2. 如果 propertyDesc 是 undefined,则返回 undefined。
  3. 令 map 为 args.[[ParameterMap]]。
  4. 令 isMapped 为 ! HasOwnProperty(map, propertyKey)。
  5. 如果 isMapped 是 true,则
    1. 将 propertyDesc.[[Value]] 设置为 ! Get(map, propertyKey)。
  6. 返回 propertyDesc。

10.4.4.2 [[DefineOwnProperty]] ( propertyKey, propertyDesc )

an arguments exotic object args的内部方法 [[DefineOwnProperty]],接收参数 propertyKey (属性键) 和 propertyDesc (属性描述符);返回值:正常完成 (值:Boolean)。 调用时执行以下步骤:

  1. 令 map 为 args.[[ParameterMap]]。
  2. 令 isMapped 为 ! HasOwnProperty(map, propertyKey)。
  3. 令 newArgDesc 为 propertyDesc。
  4. 如果 isMapped 是 true 且 IsDataDescriptor(propertyDesc) 是 true,则
    1. 如果 propertyDesc 没有 [[Value]] 字段、propertyDesc 具有 [[Writable]] 字段并且 propertyDesc.[[Writable]] 是 false,则
      1. 将 newArgDesc 设置为 propertyDesc 的副本。
      2. 将 newArgDesc.[[Value]] 设置为 ! Get(map, propertyKey)。
  5. 令 allowed 为 ! OrdinaryDefineOwnProperty(args, propertyKey, newArgDesc)。
  6. 如果 allowed 是 false,则返回 false。
  7. 如果 isMapped 是 true,则
    1. 如果 IsAccessorDescriptor(propertyDesc) 是 true,则
      1. 执行 ! map.[[Delete]](propertyKey)。
    2. 否则,
      1. 如果 propertyDesc 具有 [[Value]] 字段,则
        1. 断言:以下 Set 将会成功,因为由 arguments 对象映射的形式参数始终可写。
        2. 执行 ! Set(map, propertyKey, propertyDesc.[[Value]], false)。
      2. 如果 propertyDesc 具有 [[Writable]] 字段且 propertyDesc.[[Writable]] 是 false,则
        1. 执行 ! map.[[Delete]](propertyKey)。
  8. 返回 true。

10.4.4.3 [[Get]] ( propertyKey, receiver )

an arguments exotic object args的内部方法 [[Get]],接收参数 propertyKey (属性键) 和 receiver (ECMAScript 语言值);返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 map 为 args.[[ParameterMap]]。
  2. 令 isMapped 为 ! HasOwnProperty(map, propertyKey)。
  3. 如果 isMapped 是 false,则返回 ? OrdinaryGet(args, propertyKey, receiver)。
  4. 断言:map 包含 propertyKey 的形式参数映射。
  5. 返回 ! Get(map, propertyKey)。

10.4.4.4 [[Set]] ( propertyKey, value, receiver )

an arguments exotic object args的内部方法 [[Set]],接收参数 propertyKey (属性键)、value (ECMAScript 语言值) 和 receiver (ECMAScript 语言值);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 SameValue(args, receiver) 是 false,则
    1. 令 isMapped 为 false。
  2. 否则,
    1. 令 map 为 args.[[ParameterMap]]。
    2. 令 isMapped 为 ! HasOwnProperty(map, propertyKey)。
  3. 如果 isMapped 是 true,则
    1. 断言:以下 Set 将会成功,因为由 arguments 对象映射的形式参数始终可写。
    2. 执行 ! Set(map, propertyKey, value, false)。
  4. 返回 ? OrdinarySet(args, propertyKey, value, receiver)。

10.4.4.5 [[Delete]] ( propertyKey )

an arguments exotic object args的内部方法 [[Delete]],接收参数 propertyKey (属性键);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 map 为 args.[[ParameterMap]]。
  2. 令 isMapped 为 ! HasOwnProperty(map, propertyKey)。
  3. 令 result 为 ? OrdinaryDelete(args, propertyKey)。
  4. 如果 result 是 true 且 isMapped 是 true,则
    1. 执行 ! map.[[Delete]](propertyKey)。
  5. 返回 result。

10.4.4.6 CreateUnmappedArgumentsObject ( argList )

抽象操作 CreateUnmappedArgumentsObject,接收参数 argList (列表 (元素:ECMAScript 语言值));返回值:普通对象。 调用时执行以下步骤:

  1. 令 length 为 argList 中的元素数量。
  2. 令 obj 为 OrdinaryObjectCreate(%Object.prototype%, « [[ParameterMap]] »)。
  3. 将 obj.[[ParameterMap]] 设置为 undefined。
  4. 执行 ! DefinePropertyOrThrow(obj, "length", PropertyDescriptor { [[Value]]: 𝔽(length), [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true })。
  5. 令 index 为 0。
  6. 当 index < length 时,重复执行,
    1. 令 value 为 argList[index]。
    2. 执行 ! CreateDataPropertyOrThrow(obj, ! ToString(𝔽(index)), value)。
    3. 将 index 设置为 index + 1。
  7. 执行 ! DefinePropertyOrThrow(obj, %Symbol.iterator%, PropertyDescriptor { [[Value]]: %Array.prototype.values%, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true })。
  8. 执行 ! DefinePropertyOrThrow(obj, "callee", PropertyDescriptor { [[Getter]]: %ThrowTypeError%, [[Setter]]: %ThrowTypeError%, [[Enumerable]]: false, [[Configurable]]: false })。
  9. 返回 obj。

10.4.4.7 CreateMappedArgumentsObject ( func, formals, argList, envRecord )

抽象操作 CreateMappedArgumentsObject,接收参数 func (ECMAScript 函数对象)、formals (解析节点)、argList (列表 (元素:ECMAScript 语言值)) 和 envRecord (Environment 记录);返回值:arguments 特异对象。 调用时执行以下步骤:

  1. 断言:formals 不包含剩余参数、任何绑定模式或任何初始化器。它可以包含重复标识符。
  2. 令 length 为 argList 中的元素数量。
  3. 令 obj 为 MakeBasicObject(« [[Prototype]], [[Extensible]], [[ParameterMap]] »)。
  4. 按 10.4.4.1 中的规定设置 obj.[[GetOwnProperty]]。
  5. 按 10.4.4.2 中的规定设置 obj.[[DefineOwnProperty]]。
  6. 按 10.4.4.3 中的规定设置 obj.[[Get]]。
  7. 按 10.4.4.4 中的规定设置 obj.[[Set]]。
  8. 按 10.4.4.5 中的规定设置 obj.[[Delete]]。
  9. 将 obj.[[Prototype]] 设置为 %Object.prototype%。
  10. 令 map 为 OrdinaryObjectCreate(null)。
  11. 将 obj.[[ParameterMap]] 设置为 map。
  12. 令 paramNames 为 formals 的 BoundNames。
  13. 令 paramCount 为 paramNames 中的元素数量。
  14. 令 index 为 0。
  15. 当 index < length 时,重复执行,
    1. 令 value 为 argList[index]。
    2. 执行 ! CreateDataPropertyOrThrow(obj, ! ToString(𝔽(index)), value)。
    3. 将 index 设置为 index + 1。
  16. 执行 ! DefinePropertyOrThrow(obj, "length", PropertyDescriptor { [[Value]]: 𝔽(length), [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true })。
  17. 令 mappedNames 为新的空 List。
  18. 将 index 设置为 paramCount - 1。
  19. 当 index ≥ 0 时,重复执行,
    1. 令 name 为 paramNames[index]。
    2. 如果 mappedNames 不包含 name,则
      1. 将 name 追加到 mappedNames。
      2. 如果 index < length,则
        1. 令 getter 为 MakeArgGetter(name, envRecord)。
        2. 令 setter 为 MakeArgSetter(name, envRecord)。
        3. 执行 ! map.[[DefineOwnProperty]](! ToString(𝔽(index)), PropertyDescriptor { [[Setter]]: setter, [[Getter]]: getter, [[Enumerable]]: false, [[Configurable]]: true })。
    3. 将 index 设置为 index - 1。
  20. 执行 ! DefinePropertyOrThrow(obj, %Symbol.iterator%, PropertyDescriptor { [[Value]]: %Array.prototype.values%, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true })。
  21. 执行 ! DefinePropertyOrThrow(obj, "callee", PropertyDescriptor { [[Value]]: func, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true })。
  22. 返回 obj。

10.4.4.7.1 MakeArgGetter ( name, envRecord )

抽象操作 MakeArgGetter,接收参数 name (String) 和 envRecord (Environment 记录);返回值:函数对象。 它创建一个内置函数对象,该对象在执行时返回 envRecord 中绑定到 name 的值。 调用时执行以下步骤:

  1. 令 getterClosure 为一个没有参数的新 Abstract Closure,它捕获 name 和 envRecord,并在被调用时执行以下步骤:
    1. 返回 NormalCompletion(! envRecord.GetBindingValue(name, false))。
  2. 令 getter 为 CreateBuiltinFunction(getterClosure, 0, "", « »)。
  3. 注:ECMAScript 代码永远无法直接访问 getter。
  4. 返回 getter。

10.4.4.7.2 MakeArgSetter ( name, envRecord )

抽象操作 MakeArgSetter,接收参数 name (String) 和 envRecord (Environment 记录);返回值:函数对象。 它创建一个内置函数对象,该对象在执行时设置 envRecord 中绑定到 name 的值。 调用时执行以下步骤:

  1. 令 setterClosure 为一个具有参数 (value) 的新 Abstract Closure,它捕获 name 和 envRecord,并在被调用时执行以下步骤:
    1. 返回 NormalCompletion(! envRecord.SetMutableBinding(name, value, false))。
  2. 令 setter 为 CreateBuiltinFunction(setterClosure, 1, "", « »)。
  3. 注:ECMAScript 代码永远无法直接访问 setter。
  4. 返回 setter。

10.4.5 TypedArray 异质对象

TypedArray 是一种对规范数值字符串形式的属性键进行特殊处理的异质对象:其中处于范围内的整数索引子集用于索引统一类型的元素,而其余属性则强制不存在,无需进行原型链遍历。

注

因为对于任意 Number n,ToString(n) 都是规范数值字符串,所以实现可以将 Number 作为 TypedArray 的属性键处理,而无需实际执行字符串转换。

TypedArray 具有与普通对象相同的内部槽,此外还具有 [[ViewedArrayBuffer]]、[[TypedArrayName]]、[[ContentType]]、[[ByteLength]]、[[ByteOffset]] 和 [[ArrayLength]] 内部槽。

如果一个对象的 [[PreventExtensions]]、[[GetOwnProperty]]、[[HasProperty]]、[[DefineOwnProperty]]、[[Get]]、[[Set]]、[[Delete]] 和 [[OwnPropertyKeys]] 内部方法使用本节中的定义,而其其他基本内部方法使用 10.1 中的定义,则该对象是 TypedArray。这些方法由 TypedArrayCreate 安装。

10.4.5.1 [[PreventExtensions]] ( )

a TypedArray obj的内部方法 [[PreventExtensions]],接收无参数;返回值:正常完成 (值:Boolean)。 调用时执行以下步骤:

  1. 注:6.1.7.3 中规定的可扩展性相关不变量不允许当 obj 能够获得(或失去后重新获得)属性时,此方法返回 true;当其底层缓冲区调整大小时,具有整数索引名称的属性可能会发生这种情况。
  2. 如果 IsTypedArrayFixedLength(obj) 是 false,则返回 false。
  3. 返回 OrdinaryPreventExtensions(obj)。

10.4.5.2 [[GetOwnProperty]] ( propertyKey )

a TypedArray obj的内部方法 [[GetOwnProperty]],接收参数 propertyKey (属性键);返回值:正常完成 (值:(属性描述符 或 undefined))。 调用时执行以下步骤:

  1. 如果 propertyKey 是 String,则
    1. 令 numericIndex 为 CanonicalNumericIndexString(propertyKey)。
    2. 如果 numericIndex 不是 undefined,则
      1. 令 value 为 TypedArrayGetElement(obj, numericIndex)。
      2. 如果 value 是 undefined,则返回 undefined。
      3. 返回 PropertyDescriptor { [[Value]]: value, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true }。
  2. 返回 OrdinaryGetOwnProperty(obj, propertyKey)。

10.4.5.3 [[HasProperty]] ( propertyKey )

a TypedArray obj的内部方法 [[HasProperty]],接收参数 propertyKey (属性键);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 propertyKey 是 String,则
    1. 令 numericIndex 为 CanonicalNumericIndexString(propertyKey)。
    2. 如果 numericIndex 不是 undefined,则返回 IsValidIntegerIndex(obj, numericIndex)。
  2. 返回 ? OrdinaryHasProperty(obj, propertyKey)。

10.4.5.4 [[DefineOwnProperty]] ( propertyKey, propertyDesc )

a TypedArray obj的内部方法 [[DefineOwnProperty]],接收参数 propertyKey (属性键) 和 propertyDesc (属性描述符);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 propertyKey 是 String,则
    1. 令 numericIndex 为 CanonicalNumericIndexString(propertyKey)。
    2. 如果 numericIndex 不是 undefined,则
      1. 如果 IsValidIntegerIndex(obj, numericIndex) 是 false,则返回 false。
      2. 如果 propertyDesc 具有 [[Configurable]] 字段且 propertyDesc.[[Configurable]] 是 false,则返回 false。
      3. 如果 propertyDesc 具有 [[Enumerable]] 字段且 propertyDesc.[[Enumerable]] 是 false,则返回 false。
      4. 如果 IsAccessorDescriptor(propertyDesc) 是 true,则返回 false。
      5. 如果 propertyDesc 具有 [[Writable]] 字段且 propertyDesc.[[Writable]] 是 false,则返回 false。
      6. 如果 propertyDesc 具有 [[Value]] 字段,则执行 ? TypedArraySetElement(obj, numericIndex, propertyDesc.[[Value]])。
      7. 返回 true。
  2. 返回 ! OrdinaryDefineOwnProperty(obj, propertyKey, propertyDesc)。

10.4.5.5 [[Get]] ( propertyKey, receiver )

a TypedArray obj的内部方法 [[Get]],接收参数 propertyKey (属性键) 和 receiver (ECMAScript 语言值);返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 propertyKey 是 String,则
    1. 令 numericIndex 为 CanonicalNumericIndexString(propertyKey)。
    2. 如果 numericIndex 不是 undefined,则
      1. 返回 TypedArrayGetElement(obj, numericIndex)。
  2. 返回 ? OrdinaryGet(obj, propertyKey, receiver)。

10.4.5.6 [[Set]] ( propertyKey, value, receiver )

a TypedArray obj的内部方法 [[Set]],接收参数 propertyKey (属性键)、value (ECMAScript 语言值) 和 receiver (ECMAScript 语言值);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 propertyKey 是 String,则
    1. 令 numericIndex 为 CanonicalNumericIndexString(propertyKey)。
    2. 如果 numericIndex 不是 undefined,则
      1. 如果 SameValue(obj, receiver) 是 true,则
        1. 执行 ? TypedArraySetElement(obj, numericIndex, value)。
        2. 返回 true。
      2. 如果 IsValidIntegerIndex(obj, numericIndex) 是 false,则返回 true。
  2. 返回 ? OrdinarySet(obj, propertyKey, value, receiver)。

10.4.5.7 [[Delete]] ( propertyKey )

a TypedArray obj的内部方法 [[Delete]],接收参数 propertyKey (属性键);返回值:正常完成 (值:Boolean)。 调用时执行以下步骤:

  1. 如果 propertyKey 是 String,则
    1. 令 numericIndex 为 CanonicalNumericIndexString(propertyKey)。
    2. 如果 numericIndex 不是 undefined,则
      1. 如果 IsValidIntegerIndex(obj, numericIndex) 是 false,则返回 true。
      2. 返回 false。
  2. 返回 ! OrdinaryDelete(obj, propertyKey)。

10.4.5.8 [[OwnPropertyKeys]] ( )

a TypedArray obj的内部方法 [[OwnPropertyKeys]],接收无参数;返回值:正常完成 (值:列表 (元素:属性键))。 调用时执行以下步骤:

  1. 令 taRecord 为 MakeTypedArrayWithBufferWitnessRecord(obj, seq-cst)。
  2. 令 keys 为新的空 List。
  3. 如果 IsTypedArrayOutOfBounds(taRecord) 是 false,则
    1. 令 length 为 TypedArrayLength(taRecord)。
    2. 对满足 0 ≤ i < length 的每个整数 i,按升序执行
      1. 将 ! ToString(𝔽(i)) 追加到 keys。
  4. 对 obj 的每个自有属性键 propertyKey,其中 propertyKey 是 String 且 propertyKey 不是整数索引,按照属性创建时间升序执行
    1. 将 propertyKey 追加到 keys。
  5. 对 obj 的每个自有属性键 propertyKey,其中 propertyKey 是 Symbol,按照属性创建时间升序执行
    1. 将 propertyKey 追加到 keys。
  6. 返回 keys。

10.4.5.9 TypedArray With Buffer Witness Record

TypedArray With Buffer Witness Record 是用于封装 TypedArray 以及其所查看缓冲区的缓存字节长度的 Record。它用于帮助确保当所查看的缓冲区是可增长 SharedArrayBuffer 时,只对字节长度数据块产生一次 ReadSharedMemory 事件。

TypedArray With Buffer Witness Record 具有 表 28 中列出的字段。

表 28: TypedArray With Buffer Witness Record 字段
字段名称 值 含义
[[Object]] TypedArray 加载其缓冲区字节长度的 TypedArray。
[[CachedBufferByteLength]] 非负整数或 detached 创建该 Record 时对象的 [[ViewedArrayBuffer]] 的字节长度。

10.4.5.10 MakeTypedArrayWithBufferWitnessRecord ( obj, order )

抽象操作 MakeTypedArrayWithBufferWitnessRecord,接收参数 obj (TypedArray) 和 order ((seq-cst 或 unordered));返回值:TypedArray With Buffer Witness 记录。 调用时执行以下步骤:

  1. 令 buffer 为 obj.[[ViewedArrayBuffer]]。
  2. 如果 IsDetachedBuffer(buffer) 是 true,则
    1. 令 byteLength 为 detached。
  3. 否则,
    1. 令 byteLength 为 ArrayBufferByteLength(buffer, order)。
  4. 返回 TypedArray With Buffer Witness Record { [[Object]]: obj, [[CachedBufferByteLength]]: byteLength }。

10.4.5.11 TypedArrayCreate ( proto )

抽象操作 TypedArrayCreate,接收参数 proto (Object);返回值:TypedArray。 它用于规定创建新的 TypedArray。 调用时执行以下步骤:

  1. 令 internalSlotsList 为 « [[Prototype]], [[Extensible]], [[ViewedArrayBuffer]], [[TypedArrayName]], [[ContentType]], [[ByteLength]], [[ByteOffset]], [[ArrayLength]] »。
  2. 令 ta 为 MakeBasicObject(internalSlotsList)。
  3. 按 10.4.5.1 中的规定设置 ta.[[PreventExtensions]]。
  4. 按 10.4.5.2 中的规定设置 ta.[[GetOwnProperty]]。
  5. 按 10.4.5.3 中的规定设置 ta.[[HasProperty]]。
  6. 按 10.4.5.4 中的规定设置 ta.[[DefineOwnProperty]]。
  7. 按 10.4.5.5 中的规定设置 ta.[[Get]]。
  8. 按 10.4.5.6 中的规定设置 ta.[[Set]]。
  9. 按 10.4.5.7 中的规定设置 ta.[[Delete]]。
  10. 按 10.4.5.8 中的规定设置 ta.[[OwnPropertyKeys]]。
  11. 将 ta.[[Prototype]] 设置为 proto。
  12. 返回 ta。

10.4.5.12 TypedArrayByteLength ( taRecord )

抽象操作 TypedArrayByteLength,接收参数 taRecord (TypedArray With Buffer Witness 记录);返回值:非负整数。 调用时执行以下步骤:

  1. 断言:IsTypedArrayOutOfBounds(taRecord) 是 false。
  2. 令 obj 为 taRecord.[[Object]]。
  3. 如果 obj.[[ByteLength]] 不是 auto,则返回 obj.[[ByteLength]]。
  4. 令 length 为 TypedArrayLength(taRecord)。
  5. 令 elementSize 为 TypedArrayElementSize(obj)。
  6. 注:即使底层缓冲区已调整为非 elementSize 整数倍的大小,返回的字节长度也始终是 elementSize 的整数倍。
  7. 返回 length × elementSize。

10.4.5.13 TypedArrayLength ( taRecord )

抽象操作 TypedArrayLength,接收参数 taRecord (TypedArray With Buffer Witness 记录);返回值:非负整数。 调用时执行以下步骤:

  1. 断言:IsTypedArrayOutOfBounds(taRecord) 是 false。
  2. 令 obj 为 taRecord.[[Object]]。
  3. 如果 obj.[[ArrayLength]] 不是 auto,则返回 obj.[[ArrayLength]]。
  4. 断言:IsFixedLengthArrayBuffer(obj.[[ViewedArrayBuffer]]) 是 false。
  5. 令 byteOffset 为 obj.[[ByteOffset]]。
  6. 令 elementSize 为 TypedArrayElementSize(obj)。
  7. 令 byteLength 为 taRecord.[[CachedBufferByteLength]]。
  8. 断言:byteLength 不是 detached。
  9. 返回 floor((byteLength - byteOffset) / elementSize)。

10.4.5.14 IsTypedArrayOutOfBounds ( taRecord )

抽象操作 IsTypedArrayOutOfBounds,接收参数 taRecord (TypedArray With Buffer Witness 记录);返回值:Boolean。 它检查对象的任何数值属性是否引用底层缓冲区边界之外索引处的值。 调用时执行以下步骤:

  1. 令 obj 为 taRecord.[[Object]]。
  2. 令 bufferByteLength 为 taRecord.[[CachedBufferByteLength]]。
  3. 如果 IsDetachedBuffer(obj.[[ViewedArrayBuffer]]) 是 true,则
    1. 断言:bufferByteLength 是 detached。
    2. 返回 true。
  4. 断言:bufferByteLength 是非负整数。
  5. 令 byteOffsetStart 为 obj.[[ByteOffset]]。
  6. 如果 obj.[[ArrayLength]] 是 auto,则
    1. 令 byteOffsetEnd 为 bufferByteLength。
  7. 否则,
    1. 令 elementSize 为 TypedArrayElementSize(obj)。
    2. 令 arrayByteLength 为 obj.[[ArrayLength]] × elementSize。
    3. 令 byteOffsetEnd 为 byteOffsetStart + arrayByteLength。
  8. 注:[[ByteOffset]] 等于 bufferByteLength 的 0 长度 TypedArray 不视为越界。
  9. 如果 byteOffsetStart > bufferByteLength 或 byteOffsetEnd > bufferByteLength,则返回 true。
  10. 返回 false。

10.4.5.15 IsTypedArrayFixedLength ( obj )

抽象操作 IsTypedArrayFixedLength,接收参数 obj (TypedArray);返回值:Boolean。 调用时执行以下步骤:

  1. 如果 obj.[[ArrayLength]] 是 auto,则返回 false。
  2. 令 buffer 为 obj.[[ViewedArrayBuffer]]。
  3. 如果 IsFixedLengthArrayBuffer(buffer) 是 false 且 IsSharedArrayBuffer(buffer) 是 false,则返回 false。
  4. 返回 true。

10.4.5.16 IsValidIntegerIndex ( obj, index )

抽象操作 IsValidIntegerIndex,接收参数 obj (TypedArray) 和 index (Number);返回值:Boolean。 调用时执行以下步骤:

  1. 如果 IsDetachedBuffer(obj.[[ViewedArrayBuffer]]) 是 true,则返回 false。
  2. 如果 index 不是整数 Number,则返回 false。
  3. 如果 index 是 -0𝔽 或 index < -0𝔽,则返回 false。
  4. 令 taRecord 为 MakeTypedArrayWithBufferWitnessRecord(obj, unordered)。
  5. 注:当 obj 的后备缓冲区是可增长 SharedArrayBuffer 时,边界检查不是同步操作。
  6. 如果 IsTypedArrayOutOfBounds(taRecord) 是 true,则返回 false。
  7. 令 length 为 TypedArrayLength(taRecord)。
  8. 如果 ℝ(index) ≥ length,则返回 false。
  9. 返回 true。

10.4.5.17 TypedArrayGetElement ( obj, index )

抽象操作 TypedArrayGetElement,接收参数 obj (TypedArray) 和 index (Number);返回值:(Number、BigInt 或 undefined)。 调用时执行以下步骤:

  1. 如果 IsValidIntegerIndex(obj, index) 是 false,则返回 undefined。
  2. 令 offset 为 obj.[[ByteOffset]]。
  3. 令 elementSize 为 TypedArrayElementSize(obj)。
  4. 令 byteIndexInBuffer 为 (ℝ(index) × elementSize) + offset。
  5. 令 elementType 为 TypedArrayElementType(obj)。
  6. 返回 GetValueFromBuffer(obj.[[ViewedArrayBuffer]], byteIndexInBuffer, elementType, true, unordered)。

10.4.5.18 TypedArraySetElement ( obj, index, value )

抽象操作 TypedArraySetElement,接收参数 obj (TypedArray)、index (Number) 和 value (ECMAScript 语言值);返回值:(正常完成 (值:unused) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 obj.[[ContentType]] 是 bigint,则令 number 为 ? ToBigInt(value)。
  2. 否则,令 number 为 ? ToNumber(value)。
  3. 如果 IsValidIntegerIndex(obj, index) 是 true,则
    1. 令 offset 为 obj.[[ByteOffset]]。
    2. 令 elementSize 为 TypedArrayElementSize(obj)。
    3. 令 byteIndexInBuffer 为 (ℝ(index) × elementSize) + offset。
    4. 令 elementType 为 TypedArrayElementType(obj)。
    5. 执行 SetValueInBuffer(obj.[[ViewedArrayBuffer]], byteIndexInBuffer, elementType, number, true, unordered)。
  4. 返回 unused。
注

此操作始终表现为成功,但当尝试写入超过 TypedArray 末尾的位置,或写入由已分离 ArrayBuffer 支持的 TypedArray 时,它不会产生任何效果。

10.4.5.19 IsArrayBufferViewOutOfBounds ( obj )

抽象操作 IsArrayBufferViewOutOfBounds,接收参数 obj ((TypedArray 或 DataView));返回值:Boolean。 它检查 TypedArray 的任何数值属性或 DataView 对象的方法是否能够引用底层数据块边界之外索引处的值。此抽象操作是为了方便上游规范而存在的。 调用时执行以下步骤:

  1. 如果 obj 具有 [[DataView]] 内部槽,则
    1. 令 viewRecord 为 MakeDataViewWithBufferWitnessRecord(obj, seq-cst)。
    2. 返回 IsViewOutOfBounds(viewRecord)。
  2. 令 taRecord 为 MakeTypedArrayWithBufferWitnessRecord(obj, seq-cst)。
  3. 返回 IsTypedArrayOutOfBounds(taRecord)。

10.4.6 模块命名空间异质对象

模块命名空间异质对象是一种暴露从 ECMAScript Module 导出的绑定的异质对象(参见 16.2.3)。模块命名空间异质对象的 String 键自有属性与 Module 导出的绑定名称之间存在一一对应关系。导出的绑定包括使用 export * 导出项间接导出的任何绑定。每个 String 值自有属性键都是对应导出绑定名称的 StringValue。这些是模块命名空间异质对象仅有的 String 键属性。每个此类属性都具有特性 { [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: false }。模块命名空间异质对象不可扩展。

如果一个对象的 [[GetPrototypeOf]]、[[SetPrototypeOf]]、[[IsExtensible]]、[[PreventExtensions]]、[[GetOwnProperty]]、[[DefineOwnProperty]]、[[HasProperty]]、[[Get]]、[[Set]]、[[Delete]] 和 [[OwnPropertyKeys]] 内部方法使用本节中的定义,而其其他基本内部方法使用 10.1 中的定义,则该对象是模块命名空间异质对象。这些方法由 ModuleNamespaceCreate 安装。

模块命名空间异质对象具有 表 29 中定义的内部槽。

表 29: 模块命名空间异质对象的内部槽
内部槽 类型 描述
[[Module]] Module Record 此命名空间所暴露导出的 Module Record。
[[Exports]] String 的 List 一个 List,其元素是作为此对象自有属性暴露的导出名称的 String 值。该列表按照码元字典序排序。

10.4.6.1 [[GetPrototypeOf]] ( )

a module namespace exotic object的内部方法 [[GetPrototypeOf]],接收无参数;返回值:正常完成 (值:null)。 调用时执行以下步骤:

  1. 返回 null。

10.4.6.2 [[SetPrototypeOf]] ( proto )

a module namespace exotic object obj的内部方法 [[SetPrototypeOf]],接收参数 proto ((Object 或 null));返回值:正常完成 (值:Boolean)。 调用时执行以下步骤:

  1. 返回 ! SetImmutablePrototype(obj, proto)。

10.4.6.3 [[IsExtensible]] ( )

a module namespace exotic object的内部方法 [[IsExtensible]],接收无参数;返回值:正常完成 (值:false)。 调用时执行以下步骤:

  1. 返回 false。

10.4.6.4 [[PreventExtensions]] ( )

a module namespace exotic object的内部方法 [[PreventExtensions]],接收无参数;返回值:正常完成 (值:true)。 调用时执行以下步骤:

  1. 返回 true。

10.4.6.5 [[GetOwnProperty]] ( propertyKey )

a module namespace exotic object obj的内部方法 [[GetOwnProperty]],接收参数 propertyKey (属性键);返回值:(正常完成 (值:(属性描述符 或 undefined)) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 propertyKey 是 Symbol,则返回 OrdinaryGetOwnProperty(obj, propertyKey)。
  2. 令 exports 为 obj.[[Exports]]。
  3. 如果 exports 不包含 propertyKey,则返回 undefined。
  4. 令 value 为 ? obj.[[Get]](propertyKey, obj)。
  5. 返回 PropertyDescriptor { [[Value]]: value, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: false }。

10.4.6.6 [[DefineOwnProperty]] ( propertyKey, propertyDesc )

a module namespace exotic object obj的内部方法 [[DefineOwnProperty]],接收参数 propertyKey (属性键) 和 propertyDesc (属性描述符);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 propertyKey 是 Symbol,则返回 ! OrdinaryDefineOwnProperty(obj, propertyKey, propertyDesc)。
  2. 令 current 为 ? obj.[[GetOwnProperty]](propertyKey)。
  3. 如果 current 是 undefined,则返回 false。
  4. 如果 propertyDesc 具有 [[Configurable]] 字段且 propertyDesc.[[Configurable]] 是 true,则返回 false。
  5. 如果 propertyDesc 具有 [[Enumerable]] 字段且 propertyDesc.[[Enumerable]] 是 false,则返回 false。
  6. 如果 IsAccessorDescriptor(propertyDesc) 是 true,则返回 false。
  7. 如果 propertyDesc 具有 [[Writable]] 字段且 propertyDesc.[[Writable]] 是 false,则返回 false。
  8. 如果 propertyDesc 具有 [[Value]] 字段,则返回 SameValue(propertyDesc.[[Value]], current.[[Value]])。
  9. 返回 true。

10.4.6.7 [[HasProperty]] ( propertyKey )

a module namespace exotic object obj的内部方法 [[HasProperty]],接收参数 propertyKey (属性键);返回值:正常完成 (值:Boolean)。 调用时执行以下步骤:

  1. 如果 propertyKey 是 Symbol,则返回 ! OrdinaryHasProperty(obj, propertyKey)。
  2. 令 exports 为 obj.[[Exports]]。
  3. 如果 exports 包含 propertyKey,则返回 true。
  4. 返回 false。

10.4.6.8 [[Get]] ( propertyKey, receiver )

a module namespace exotic object obj的内部方法 [[Get]],接收参数 propertyKey (属性键) 和 receiver (ECMAScript 语言值);返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 propertyKey 是 Symbol,则
    1. 返回 ! OrdinaryGet(obj, propertyKey, receiver)。
  2. 令 exports 为 obj.[[Exports]]。
  3. 如果 exports 不包含 propertyKey,则返回 undefined。
  4. 令 module 为 obj.[[Module]]。
  5. 令 binding 为 module.ResolveExport(propertyKey)。
  6. 断言:binding 是 ResolvedBinding Record。
  7. 令 targetModule 为 binding.[[Module]]。
  8. 断言:targetModule 不是 undefined。
  9. 如果 binding.[[BindingName]] 是 namespace,则
    1. 返回 GetModuleNamespace(targetModule)。
  10. 令 targetEnv 为 targetModule.[[Environment]]。
  11. 如果 targetEnv 是 empty,则抛出 ReferenceError 异常。
  12. 返回 ? targetEnv.GetBindingValue(binding.[[BindingName]], true)。
注

ResolveExport 没有副作用。每次使用特定的 exportName、resolveSet 参数对调用此操作时,它都必须返回相同结果。实现可以选择预先计算或缓存每个模块命名空间异质对象 [[Exports]] 的 ResolveExport 结果。

10.4.6.9 [[Set]] ( propertyKey, value, receiver )

a module namespace exotic object的内部方法 [[Set]],接收参数 propertyKey (属性键)、value (ECMAScript 语言值) 和 receiver (ECMAScript 语言值);返回值:正常完成 (值:false)。 调用时执行以下步骤:

  1. 返回 false。

10.4.6.10 [[Delete]] ( propertyKey )

a module namespace exotic object obj的内部方法 [[Delete]],接收参数 propertyKey (属性键);返回值:正常完成 (值:Boolean)。 调用时执行以下步骤:

  1. 如果 propertyKey 是 Symbol,则
    1. 返回 ! OrdinaryDelete(obj, propertyKey)。
  2. 令 exports 为 obj.[[Exports]]。
  3. 如果 exports 包含 propertyKey,则返回 false。
  4. 返回 true。

10.4.6.11 [[OwnPropertyKeys]] ( )

a module namespace exotic object obj的内部方法 [[OwnPropertyKeys]],接收无参数;返回值:正常完成 (值:列表 (元素:属性键))。 调用时执行以下步骤:

  1. 令 exports 为 obj.[[Exports]]。
  2. 令 symbolKeys 为 OrdinaryOwnPropertyKeys(obj)。
  3. 返回 exports 和 symbolKeys 的列表连接。

10.4.6.12 ModuleNamespaceCreate ( module, exports )

抽象操作 ModuleNamespaceCreate,接收参数 module (Module 记录) 和 exports (列表 (元素:String));返回值:module namespace 特异对象。 它用于规定创建新的模块命名空间异质对象。 调用时执行以下步骤:

  1. 断言:module.[[Namespace]] 是 empty。
  2. 令 internalSlotsList 为 表 29 中列出的内部槽。
  3. 令 namespace 为 MakeBasicObject(internalSlotsList)。
  4. 将 namespace 的基本内部方法设置为 10.4.6 中规定的定义。
  5. 将 namespace.[[Module]] 设置为 module。
  6. 令 sortedExports 为一个 List,其元素是 exports 的元素,并按照码元字典序排序。
  7. 将 namespace.[[Exports]] 设置为 sortedExports。
  8. 创建 namespace 的自有属性,对应 28.3 中的定义。
  9. 将 module.[[Namespace]] 设置为 namespace。
  10. 返回 namespace。

10.4.7 不可变原型异质对象

不可变原型异质对象是一种异质对象,它具有 [[Prototype]] 内部槽,一旦初始化后就不会再改变。

如果一个对象的 [[SetPrototypeOf]] 内部方法使用以下实现,则该对象是不可变原型异质对象。(其其他基本内部方法可以根据具体不可变原型异质对象使用任意实现。)

注

与其他异质对象不同,不可变原型异质对象没有专门提供的创建抽象操作。这是因为它们仅由 %Object.prototype% 和宿主环境使用,而在宿主环境中,相关对象可能在其他方面也是异质的,因此需要各自专用的创建操作。

10.4.7.1 [[SetPrototypeOf]] ( proto )

an immutable prototype exotic object obj的内部方法 [[SetPrototypeOf]],接收参数 proto ((Object 或 null));返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 返回 ? SetImmutablePrototype(obj, proto)。

10.4.7.2 SetImmutablePrototype ( obj, proto )

抽象操作 SetImmutablePrototype,接收参数 obj (Object) 和 proto ((Object 或 null));返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 current 为 ? obj.[[GetPrototypeOf]]()。
  2. 如果 SameValue(proto, current) 是 true,则返回 true。
  3. 返回 false。

10.5 Proxy 对象内部方法和内部槽

Proxy 对象是一种异质对象,其基本内部方法部分使用 ECMAScript 代码实现。每个 Proxy 对象都有一个名为 [[ProxyHandler]] 的内部槽。[[ProxyHandler]] 的值是一个对象(称为代理的处理器对象)或 null。处理器对象的方法(参见 表 30)可用于增强一个或多个 Proxy 对象内部方法的实现。每个 Proxy 对象还有一个名为 [[ProxyTarget]] 的内部槽,其值为对象或 null。该对象称为代理的目标对象。

如果一个对象的基本内部方法(包括适用时的 [[Call]] 和 [[Construct]])使用本节中的定义,则该对象是 Proxy 异质对象。这些内部方法在 ProxyCreate 中安装。

表 30: Proxy 处理器方法
内部方法 处理器方法
[[GetPrototypeOf]] getPrototypeOf
[[SetPrototypeOf]] setPrototypeOf
[[IsExtensible]] isExtensible
[[PreventExtensions]] preventExtensions
[[GetOwnProperty]] getOwnPropertyDescriptor
[[DefineOwnProperty]] defineProperty
[[HasProperty]] has
[[Get]] get
[[Set]] set
[[Delete]] deleteProperty
[[OwnPropertyKeys]] ownKeys
[[Call]] apply
[[Construct]] construct

当调用处理器方法来提供 Proxy 对象内部方法的实现时,会将代理的目标对象作为参数传给处理器方法。代理的处理器对象不一定具有对应每个基本内部方法的方法。如果处理器对象没有对应内部陷阱的方法,则调用代理上的内部方法会导致调用代理目标对象上的相应内部方法。

Proxy 对象的 [[ProxyHandler]] 和 [[ProxyTarget]] 内部槽在对象创建时始终会被初始化,并且通常不可修改。某些 Proxy 对象以允许随后被撤销的方式创建。当代理被撤销时,其 [[ProxyHandler]] 和 [[ProxyTarget]] 内部槽会设置为 null,从而导致随后对该 Proxy 对象调用内部方法时抛出 TypeError 异常。

由于 Proxy 对象允许由任意 ECMAScript 代码提供内部方法的实现,因此可以定义处理器方法违反 6.1.7.3 中定义不变量的 Proxy 对象。6.1.7.3 中定义的一些内部方法不变量是基本完整性不变量。这些不变量由本节规定的 Proxy 对象内部方法显式强制执行。ECMAScript 实现必须能够稳健地处理所有可能的不变量违反情况。

在以下算法描述中,假定 obj 是 ECMAScript Proxy 对象,propertyKey 是属性键值,value 是任意 ECMAScript 语言值,而 propertyDesc 是 Property Descriptor Record。

10.5.1 [[GetPrototypeOf]] ( )

a Proxy exotic object obj的内部方法 [[GetPrototypeOf]],接收无参数;返回值:(正常完成 (值:(Object 或 null)) 或 抛出完成)。 调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. 令 target 为 obj.[[ProxyTarget]]。
  3. 令 handler 为 obj.[[ProxyHandler]]。
  4. 断言:handler 是 Object。
  5. 令 trap 为 ? GetMethod(handler, "getPrototypeOf")。
  6. 如果 trap 是 undefined,则
    1. 返回 ? target.[[GetPrototypeOf]]()。
  7. 令 handlerProto 为 ? Call(trap, handler, « target »)。
  8. 如果 handlerProto 不是 Object 且 handlerProto 不是 null,则抛出 TypeError 异常。
  9. 令 extensibleTarget 为 ? IsExtensible(target)。
  10. 如果 extensibleTarget 是 true,则返回 handlerProto。
  11. 令 targetProto 为 ? target.[[GetPrototypeOf]]()。
  12. 如果 SameValue(handlerProto, targetProto) 是 false,则抛出 TypeError 异常。
  13. 返回 handlerProto。
注

Proxy 对象的 [[GetPrototypeOf]] 强制执行以下不变量:

  • [[GetPrototypeOf]] 的结果必须是 Object 或 null。
  • 如果目标对象不可扩展,则应用于 Proxy 对象的 [[GetPrototypeOf]] 必须返回与应用于 Proxy 对象目标对象的 [[GetPrototypeOf]] 相同的值。

10.5.2 [[SetPrototypeOf]] ( proto )

a Proxy exotic object obj的内部方法 [[SetPrototypeOf]],接收参数 proto ((Object 或 null));返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. 令 target 为 obj.[[ProxyTarget]]。
  3. 令 handler 为 obj.[[ProxyHandler]]。
  4. 断言:handler 是 Object。
  5. 令 trap 为 ? GetMethod(handler, "setPrototypeOf")。
  6. 如果 trap 是 undefined,则
    1. 返回 ? target.[[SetPrototypeOf]](proto)。
  7. 令 boolTrapResult 为 ToBoolean(? Call(trap, handler, « target, proto »))。
  8. 如果 boolTrapResult 是 false,则返回 false。
  9. 令 extensibleTarget 为 ? IsExtensible(target)。
  10. 如果 extensibleTarget 是 true,则返回 true。
  11. 令 targetProto 为 ? target.[[GetPrototypeOf]]()。
  12. 如果 SameValue(proto, targetProto) 是 false,则抛出 TypeError 异常。
  13. 返回 true。
注

Proxy 对象的 [[SetPrototypeOf]] 强制执行以下不变量:

  • [[SetPrototypeOf]] 的结果是 Boolean 值。
  • 如果目标对象不可扩展,则参数值必须与应用于目标对象的 [[GetPrototypeOf]] 的结果相同。

10.5.3 [[IsExtensible]] ( )

a Proxy exotic object obj的内部方法 [[IsExtensible]],接收无参数;返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. 令 target 为 obj.[[ProxyTarget]]。
  3. 令 handler 为 obj.[[ProxyHandler]]。
  4. 断言:handler 是 Object。
  5. 令 trap 为 ? GetMethod(handler, "isExtensible")。
  6. 如果 trap 是 undefined,则
    1. 返回 ? IsExtensible(target)。
  7. 令 boolTrapResult 为 ToBoolean(? Call(trap, handler, « target »))。
  8. 令 targetResult 为 ? IsExtensible(target)。
  9. 如果 boolTrapResult 不是 targetResult,则抛出 TypeError 异常。
  10. 返回 boolTrapResult。
注

Proxy 对象的 [[IsExtensible]] 强制执行以下不变量:

  • [[IsExtensible]] 的结果是 Boolean 值。
  • 应用于 Proxy 对象的 [[IsExtensible]] 必须返回与使用相同参数应用于 Proxy 对象目标对象的 [[IsExtensible]] 相同的值。

10.5.4 [[PreventExtensions]] ( )

a Proxy exotic object obj的内部方法 [[PreventExtensions]],接收无参数;返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. 令 target 为 obj.[[ProxyTarget]]。
  3. 令 handler 为 obj.[[ProxyHandler]]。
  4. 断言:handler 是 Object。
  5. 令 trap 为 ? GetMethod(handler, "preventExtensions")。
  6. 如果 trap 是 undefined,则
    1. 返回 ? target.[[PreventExtensions]]()。
  7. 令 boolTrapResult 为 ToBoolean(? Call(trap, handler, « target »))。
  8. 如果 boolTrapResult 是 true,则
    1. 令 extensibleTarget 为 ? IsExtensible(target)。
    2. 如果 extensibleTarget 是 true,则抛出 TypeError 异常。
  9. 返回 boolTrapResult。
注

Proxy 对象的 [[PreventExtensions]] 强制执行以下不变量:

  • [[PreventExtensions]] 的结果是 Boolean 值。
  • 仅当应用于 Proxy 对象目标对象的 [[IsExtensible]] 为 false 时,应用于 Proxy 对象的 [[PreventExtensions]] 才返回 true。

10.5.5 [[GetOwnProperty]] ( propertyKey )

a Proxy exotic object obj的内部方法 [[GetOwnProperty]],接收参数 propertyKey (属性键);返回值:(正常完成 (值:(属性描述符 或 undefined)) 或 抛出完成)。 调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. 令 target 为 obj.[[ProxyTarget]]。
  3. 令 handler 为 obj.[[ProxyHandler]]。
  4. 断言:handler 是 Object。
  5. 令 trap 为 ? GetMethod(handler, "getOwnPropertyDescriptor")。
  6. 如果 trap 是 undefined,则
    1. 返回 ? target.[[GetOwnProperty]](propertyKey)。
  7. 令 trapResultObj 为 ? Call(trap, handler, « target, propertyKey »)。
  8. 如果 trapResultObj 不是 Object 且 trapResultObj 不是 undefined,则抛出 TypeError 异常。
  9. 令 targetDesc 为 ? target.[[GetOwnProperty]](propertyKey)。
  10. 如果 trapResultObj 是 undefined,则
    1. 如果 targetDesc 是 undefined,则返回 undefined。
    2. 如果 targetDesc.[[Configurable]] 是 false,则抛出 TypeError 异常。
    3. 令 extensibleTarget 为 ? IsExtensible(target)。
    4. 如果 extensibleTarget 是 false,则抛出 TypeError 异常。
    5. 返回 undefined。
  11. 令 extensibleTarget 为 ? IsExtensible(target)。
  12. 令 resultDesc 为 ? ToPropertyDescriptor(trapResultObj)。
  13. 执行 CompletePropertyDescriptor(resultDesc)。
  14. 令 valid 为 IsCompatiblePropertyDescriptor(extensibleTarget, resultDesc, targetDesc)。
  15. 如果 valid 是 false,则抛出 TypeError 异常。
  16. 如果 resultDesc.[[Configurable]] 是 false,则
    1. 如果 targetDesc 是 undefined 或 targetDesc.[[Configurable]] 是 true,则
      1. 抛出 TypeError 异常。
    2. 如果 resultDesc 具有 [[Writable]] 字段且 resultDesc.[[Writable]] 是 false,则
      1. 断言:targetDesc 具有 [[Writable]] 字段。
      2. 如果 targetDesc.[[Writable]] 是 true,则抛出 TypeError 异常。
  17. 返回 resultDesc。
注

Proxy 对象的 [[GetOwnProperty]] 强制执行以下不变量:

  • [[GetOwnProperty]] 的结果必须是 Property Descriptor 或 undefined。
  • 如果属性作为目标对象的不可配置自有属性存在,则不能报告该属性不存在。
  • 如果属性作为不可扩展目标对象的自有属性存在,则不能报告该属性不存在。
  • 如果属性不作为目标对象的自有属性存在并且目标对象不可扩展,则不能报告该属性存在。
  • 除非属性作为目标对象的不可配置自有属性存在,否则不能报告该属性不可配置。
  • 除非属性作为目标对象的不可配置且不可写自有属性存在,否则不能报告该属性同时不可配置且不可写。

10.5.6 [[DefineOwnProperty]] ( propertyKey, propertyDesc )

a Proxy exotic object obj的内部方法 [[DefineOwnProperty]],接收参数 propertyKey (属性键) 和 propertyDesc (属性描述符);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. 令 target 为 obj.[[ProxyTarget]]。
  3. 令 handler 为 obj.[[ProxyHandler]]。
  4. 断言:handler 是 Object。
  5. 令 trap 为 ? GetMethod(handler, "defineProperty")。
  6. 如果 trap 是 undefined,则
    1. 返回 ? target.[[DefineOwnProperty]](propertyKey, propertyDesc)。
  7. 令 propertyDescObj 为 FromPropertyDescriptor(propertyDesc)。
  8. 令 boolTrapResult 为 ToBoolean(? Call(trap, handler, « target, propertyKey, propertyDescObj »))。
  9. 如果 boolTrapResult 是 false,则返回 false。
  10. 令 targetDesc 为 ? target.[[GetOwnProperty]](propertyKey)。
  11. 令 extensibleTarget 为 ? IsExtensible(target)。
  12. 如果 propertyDesc 具有 [[Configurable]] 字段且 propertyDesc.[[Configurable]] 是 false,则
    1. 令 settingConfigurableFalse 为 true。
  13. 否则,
    1. 令 settingConfigurableFalse 为 false。
  14. 如果 targetDesc 是 undefined,则
    1. 如果 extensibleTarget 是 false,则抛出 TypeError 异常。
    2. 如果 settingConfigurableFalse 是 true,则抛出 TypeError 异常。
  15. 否则,
    1. 如果 IsCompatiblePropertyDescriptor(extensibleTarget, propertyDesc, targetDesc) 是 false,则抛出 TypeError 异常。
    2. 如果 settingConfigurableFalse 是 true 且 targetDesc.[[Configurable]] 是 true,则抛出 TypeError 异常。
    3. 如果 IsDataDescriptor(targetDesc) 是 true、targetDesc.[[Configurable]] 是 false 且 targetDesc.[[Writable]] 是 true,则
      1. 如果 propertyDesc 具有 [[Writable]] 字段且 propertyDesc.[[Writable]] 是 false,则抛出 TypeError 异常。
  16. 返回 true。
注

Proxy 对象的 [[DefineOwnProperty]] 强制执行以下不变量:

  • [[DefineOwnProperty]] 的结果是 Boolean 值。
  • 如果目标对象不可扩展,则不能添加属性。
  • 除非目标对象存在对应的不可配置自有属性,否则属性不能是不可配置的。
  • 除非目标对象存在对应的不可配置且不可写自有属性,否则不可配置属性不能是不可写的。
  • 如果属性具有对应的目标对象属性,则使用 [[DefineOwnProperty]] 将该属性的 Property Descriptor 应用于目标对象时不会抛出异常。

10.5.7 [[HasProperty]] ( propertyKey )

a Proxy exotic object obj的内部方法 [[HasProperty]],接收参数 propertyKey (属性键);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. 令 target 为 obj.[[ProxyTarget]]。
  3. 令 handler 为 obj.[[ProxyHandler]]。
  4. 断言:handler 是 Object。
  5. 令 trap 为 ? GetMethod(handler, "has")。
  6. 如果 trap 是 undefined,则
    1. 返回 ? target.[[HasProperty]](propertyKey)。
  7. 令 boolTrapResult 为 ToBoolean(? Call(trap, handler, « target, propertyKey »))。
  8. 如果 boolTrapResult 是 false,则
    1. 令 targetDesc 为 ? target.[[GetOwnProperty]](propertyKey)。
    2. 如果 targetDesc 不是 undefined,则
      1. 如果 targetDesc.[[Configurable]] 是 false,则抛出 TypeError 异常。
      2. 令 extensibleTarget 为 ? IsExtensible(target)。
      3. 如果 extensibleTarget 是 false,则抛出 TypeError 异常。
  9. 返回 boolTrapResult。
注

Proxy 对象的 [[HasProperty]] 强制执行以下不变量:

  • [[HasProperty]] 的结果是 Boolean 值。
  • 如果属性作为目标对象的不可配置自有属性存在,则不能报告该属性不存在。
  • 如果属性作为目标对象的自有属性存在且目标对象不可扩展,则不能报告该属性不存在。

10.5.8 [[Get]] ( propertyKey, receiver )

a Proxy exotic object obj的内部方法 [[Get]],接收参数 propertyKey (属性键) 和 receiver (ECMAScript 语言值);返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。 调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. 令 target 为 obj.[[ProxyTarget]]。
  3. 令 handler 为 obj.[[ProxyHandler]]。
  4. 断言:handler 是 Object。
  5. 令 trap 为 ? GetMethod(handler, "get")。
  6. 如果 trap 是 undefined,则
    1. 返回 ? target.[[Get]](propertyKey, receiver)。
  7. 令 trapResult 为 ? Call(trap, handler, « target, propertyKey, receiver »)。
  8. 令 targetDesc 为 ? target.[[GetOwnProperty]](propertyKey)。
  9. 如果 targetDesc 不是 undefined 且 targetDesc.[[Configurable]] 是 false,则
    1. 如果 IsDataDescriptor(targetDesc) 是 true 且 targetDesc.[[Writable]] 是 false,则
      1. 如果 SameValue(trapResult, targetDesc.[[Value]]) 是 false,则抛出 TypeError 异常。
    2. 如果 IsAccessorDescriptor(targetDesc) 是 true 且 targetDesc.[[Getter]] 是 undefined,则
      1. 如果 trapResult 不是 undefined,则抛出 TypeError 异常。
  10. 返回 trapResult。
注

Proxy 对象的 [[Get]] 强制执行以下不变量:

  • 如果对应的目标对象属性是不可写、不可配置的自有数据属性,则为属性报告的值必须与对应目标对象属性的值相同。
  • 如果对应的目标对象属性是不可配置的自有访问器属性,并且其 [[Getter]] 特性为 undefined,则为该属性报告的值必须为 undefined。

10.5.9 [[Set]] ( propertyKey, value, receiver )

a Proxy exotic object obj的内部方法 [[Set]],接收参数 propertyKey (属性键)、value (ECMAScript 语言值) 和 receiver (ECMAScript 语言值);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. 令 target 为 obj.[[ProxyTarget]]。
  3. 令 handler 为 obj.[[ProxyHandler]]。
  4. 断言:handler 是 Object。
  5. 令 trap 为 ? GetMethod(handler, "set")。
  6. 如果 trap 是 undefined,则
    1. 返回 ? target.[[Set]](propertyKey, value, receiver)。
  7. 令 boolTrapResult 为 ToBoolean(? Call(trap, handler, « target, propertyKey, value, receiver »))。
  8. 如果 boolTrapResult 是 false,则返回 false。
  9. 令 targetDesc 为 ? target.[[GetOwnProperty]](propertyKey)。
  10. 如果 targetDesc 不是 undefined 且 targetDesc.[[Configurable]] 是 false,则
    1. 如果 IsDataDescriptor(targetDesc) 是 true 且 targetDesc.[[Writable]] 是 false,则
      1. 如果 SameValue(value, targetDesc.[[Value]]) 是 false,则抛出 TypeError 异常。
    2. 如果 IsAccessorDescriptor(targetDesc) 是 true,则
      1. 如果 targetDesc.[[Setter]] 是 undefined,则抛出 TypeError 异常。
  11. 返回 true。
注

Proxy 对象的 [[Set]] 强制执行以下不变量:

  • [[Set]] 的结果是 Boolean 值。
  • 如果对应目标对象属性是不可写、不可配置的自有数据属性,则不能将属性值更改为与对应目标对象属性值不同的值。
  • 如果对应目标对象属性是不可配置的自有访问器属性,并且其 [[Setter]] 特性为 undefined,则不能设置该属性的值。

10.5.10 [[Delete]] ( propertyKey )

a Proxy exotic object obj的内部方法 [[Delete]],接收参数 propertyKey (属性键);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. 令 target 为 obj.[[ProxyTarget]]。
  3. 令 handler 为 obj.[[ProxyHandler]]。
  4. 断言:handler 是 Object。
  5. 令 trap 为 ? GetMethod(handler, "deleteProperty")。
  6. 如果 trap 是 undefined,则
    1. 返回 ? target.[[Delete]](propertyKey)。
  7. 令 boolTrapResult 为 ToBoolean(? Call(trap, handler, « target, propertyKey »))。
  8. 如果 boolTrapResult 是 false,则返回 false。
  9. 令 targetDesc 为 ? target.[[GetOwnProperty]](propertyKey)。
  10. 如果 targetDesc 是 undefined,则返回 true。
  11. 如果 targetDesc.[[Configurable]] 是 false,则抛出 TypeError 异常。
  12. 令 extensibleTarget 为 ? IsExtensible(target)。
  13. 如果 extensibleTarget 是 false,则抛出 TypeError 异常。
  14. 返回 true。
注

Proxy 对象的 [[Delete]] 强制执行以下不变量:

  • [[Delete]] 的结果是 Boolean 值。
  • 如果属性作为目标对象的不可配置自有属性存在,则不能报告该属性已删除。
  • 如果属性作为目标对象的自有属性存在且目标对象不可扩展,则不能报告该属性已删除。

10.5.11 [[OwnPropertyKeys]] ( )

a Proxy exotic object obj的内部方法 [[OwnPropertyKeys]],接收无参数;返回值:(正常完成 (值:列表 (元素:属性键)) 或 抛出完成)。 调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. 令 target 为 obj.[[ProxyTarget]]。
  3. 令 handler 为 obj.[[ProxyHandler]]。
  4. 断言:handler 是 Object。
  5. 令 trap 为 ? GetMethod(handler, "ownKeys")。
  6. 如果 trap 是 undefined,则
    1. 返回 ? target.[[OwnPropertyKeys]]()。
  7. 令 trapResultArray 为 ? Call(trap, handler, « target »)。
  8. 令 trapResult 为 ? CreateListFromArrayLike(trapResultArray, property-key)。
  9. 如果 trapResult 包含任何重复条目,则抛出 TypeError 异常。
  10. 令 extensibleTarget 为 ? IsExtensible(target)。
  11. 令 targetKeys 为 ? target.[[OwnPropertyKeys]]()。
  12. 断言:targetKeys 是属性键的 List。
  13. 断言:targetKeys 不包含重复条目。
  14. 令 targetConfigurableKeys 为新的空 List。
  15. 令 targetNonconfigurableKeys 为新的空 List。
  16. 对 targetKeys 的每个元素 key,执行
    1. 令 propertyDesc 为 ? target.[[GetOwnProperty]](key)。
    2. 如果 propertyDesc 不是 undefined 且 propertyDesc.[[Configurable]] 是 false,则
      1. 将 key 追加到 targetNonconfigurableKeys。
    3. 否则,
      1. 将 key 追加到 targetConfigurableKeys。
  17. 如果 extensibleTarget 是 true 且 targetNonconfigurableKeys 为空,则
    1. 返回 trapResult。
  18. 令 uncheckedResultKeys 为一个 List,其元素是 trapResult 的元素。
  19. 对 targetNonconfigurableKeys 的每个元素 key,执行
    1. 如果 uncheckedResultKeys 不包含 key,则抛出 TypeError 异常。
    2. 从 uncheckedResultKeys 中移除 key。
  20. 如果 extensibleTarget 是 true,则返回 trapResult。
  21. 对 targetConfigurableKeys 的每个元素 key,执行
    1. 如果 uncheckedResultKeys 不包含 key,则抛出 TypeError 异常。
    2. 从 uncheckedResultKeys 中移除 key。
  22. 如果 uncheckedResultKeys 不为空,则抛出 TypeError 异常。
  23. 返回 trapResult。
注

Proxy 对象的 [[OwnPropertyKeys]] 强制执行以下不变量:

  • [[OwnPropertyKeys]] 的结果是 List。
  • 返回的 List 不包含重复条目。
  • 返回的 List 的每个元素都是属性键。
  • 结果 List 必须包含目标对象所有不可配置自有属性的键。
  • 如果目标对象不可扩展,则结果 List 必须包含目标对象所有自有属性的键,且不得包含其他值。

10.5.12 [[Call]] ( thisArg, argList )

a Proxy exotic object obj的内部方法 [[Call]],接收参数 thisArg (ECMAScript 语言值) 和 argList (列表 (元素:ECMAScript 语言值));返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。 调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. 令 target 为 obj.[[ProxyTarget]]。
  3. 令 handler 为 obj.[[ProxyHandler]]。
  4. 断言:handler 是 Object。
  5. 令 trap 为 ? GetMethod(handler, "apply")。
  6. 如果 trap 是 undefined,则
    1. 返回 ? Call(target, thisArg, argList)。
  7. 令 argArray 为 CreateArrayFromList(argList)。
  8. 返回 ? Call(trap, handler, « target, thisArg, argArray »)。
注

只有当 Proxy 异质对象的 [[ProxyTarget]] 内部槽初始值是具有 [[Call]] 内部方法的对象时,该 Proxy 异质对象才具有 [[Call]] 内部方法。

10.5.13 [[Construct]] ( argList, newTarget )

a Proxy exotic object obj的内部方法 [[Construct]],接收参数 argList (列表 (元素:ECMAScript 语言值)) 和 newTarget (构造函数);返回值:(正常完成 (值:Object) 或 抛出完成)。 调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. 令 target 为 obj.[[ProxyTarget]]。
  3. 断言:IsConstructor(target) 是 true。
  4. 令 handler 为 obj.[[ProxyHandler]]。
  5. 断言:handler 是 Object。
  6. 令 trap 为 ? GetMethod(handler, "construct")。
  7. 如果 trap 是 undefined,则
    1. 返回 ? Construct(target, argList, newTarget)。
  8. 令 argArray 为 CreateArrayFromList(argList)。
  9. 令 newObj 为 ? Call(trap, handler, « target, argArray, newTarget »)。
  10. 如果 newObj 不是 Object,则抛出 TypeError 异常。
  11. 返回 newObj。
注 1

只有当 Proxy 异质对象的 [[ProxyTarget]] 内部槽初始值是具有 [[Construct]] 内部方法的对象时,该 Proxy 异质对象才具有 [[Construct]] 内部方法。

注 2

Proxy 对象的 [[Construct]] 强制执行以下不变量:

  • [[Construct]] 的结果必须是 Object。

10.5.14 ValidateNonRevokedProxy ( proxy )

抽象操作 ValidateNonRevokedProxy,接收参数 proxy (Proxy 特异对象);返回值:(正常完成 (值:unused) 或 抛出完成)。 如果 proxy 已被撤销,则它会抛出 TypeError 异常。 调用时执行以下步骤:

  1. 如果 proxy.[[ProxyTarget]] 是 null,则抛出 TypeError 异常。
  2. 断言:proxy.[[ProxyHandler]] 不是 null。
  3. 返回 unused。

10.5.15 ProxyCreate ( target, handler )

抽象操作 ProxyCreate,接收参数 target (ECMAScript 语言值) 和 handler (ECMAScript 语言值);返回值:(正常完成 (值:Proxy 特异对象) 或 抛出完成)。 它用于规定创建新的 Proxy 对象。 调用时执行以下步骤:

  1. 如果 target 不是 Object,则抛出 TypeError 异常。
  2. 如果 handler 不是 Object,则抛出 TypeError 异常。
  3. 令 proxy 为 MakeBasicObject(« [[ProxyHandler]], [[ProxyTarget]] »)。
  4. 将 proxy 的基本内部方法([[Call]] 和 [[Construct]] 除外)设置为 10.5 中规定的定义。
  5. 如果 IsCallable(target) 是 true,则
    1. 按 10.5.12 中的规定设置 proxy.[[Call]]。
    2. 如果 IsConstructor(target) 是 true,则
      1. 按 10.5.13 中的规定设置 proxy.[[Construct]]。
  6. 将 proxy.[[ProxyTarget]] 设置为 target。
  7. 将 proxy.[[ProxyHandler]] 设置为 handler。
  8. 返回 proxy。

11 ECMAScript 语言:源文本

11.1 源文本

语法

SourceCharacter :: any Unicode code point

ECMAScript 源文本是 Unicode 码点序列。在 ECMAScript 文法允许的位置,U+0000 到 U+10FFFF 的所有 Unicode 码点值(包括代理码点)都可以出现在 ECMAScript 源文本中。用于存储和交换 ECMAScript 源文本的实际编码与本规范无关。无论外部源文本采用何种编码,符合规范的 ECMAScript 实现都会像处理等效的 SourceCharacter 值序列一样处理源文本,其中每个 SourceCharacter 都是一个 Unicode 码点。符合规范的 ECMAScript 实现不要求对源文本执行任何规范化,也不要求表现得如同对源文本执行了规范化。

组合字符序列的各组成部分会被视为独立的 Unicode 码点,即使用户可能会将整个序列视为单个字符。

注

在字符串字面量、正则表达式字面量、模板字面量和标识符中,任何 Unicode 码点也都可以使用显式表示码点数值的 Unicode 转义序列来表示。在注释中,这种转义序列实际上会作为注释的一部分而被忽略。

ECMAScript 与 Java 编程语言在 Unicode 转义序列的行为方面有所不同。例如,在 Java 程序中,如果 Unicode 转义序列 \u000A 出现在单行注释中,它会被解释为行终止符(Unicode 码点 U+000A 是 LINE FEED (LF)),因此下一个码点不属于该注释。类似地,如果 Unicode 转义序列 \u000A 出现在 Java 程序的字符串字面量中,它同样会被解释为行终止符,而字符串字面量中不允许出现行终止符——必须写成 \n 而不是 \u000A,才能让 LINE FEED (LF) 成为字符串字面量值的一部分。在 ECMAScript 程序中,出现在注释内的 Unicode 转义序列永远不会被解释,因此不会参与终止注释。类似地,出现在 ECMAScript 程序字符串字面量中的 Unicode 转义序列始终构成该字面量的一部分,绝不会被解释为行终止符,也不会被解释为可能终止该字符串字面量的码点。

11.1.1 Static Semantics: UTF16EncodeCodePoint ( codePoint )

抽象操作 UTF16EncodeCodePoint,接收参数 codePoint (Unicode 码点);返回值:String。 调用时执行以下步骤:

  1. 断言:0 ≤ codePoint ≤ 0x10FFFF。
  2. 如果 codePoint ≤ 0xFFFF,则返回由数值为 codePoint 的码元组成的 String 值。
  3. 令 cu1 为数值为 floor((codePoint - 0x10000) / 0x400) + 0xD800 的码元。
  4. 令 cu2 为数值为 ((codePoint - 0x10000) modulo 0x400) + 0xDC00 的码元。
  5. 返回 cu1 和 cu2 的字符串连接。

11.1.2 Static Semantics: CodePointsToString ( text )

抽象操作 CodePointsToString,接收参数 text (a sequence of Unicode code points);返回值:String。 它按照 6.1.4 中的描述,将 text 转换为 String 值。 调用时执行以下步骤:

  1. 令 result 为空 String。
  2. 对 text 的每个码点 codePoint,执行
    1. 将 result 设置为 result 和 UTF16EncodeCodePoint(codePoint) 的字符串连接。
  3. 返回 result。

11.1.3 Static Semantics: UTF16SurrogatePairToCodePoint ( lead, trail )

抽象操作 UTF16SurrogatePairToCodePoint,接收参数 lead (码元) 和 trail (码元);返回值:码点。 将构成 UTF-16 代理对的两个码元转换为一个码点。 调用时执行以下步骤:

  1. 断言:lead 是前导代理,trail 是尾随代理。
  2. 令 codePoint 为 (lead - 0xD800) × 0x400 + (trail - 0xDC00) + 0x10000。
  3. 返回码点 codePoint。

11.1.4 Static Semantics: CodePointAt ( string, position )

抽象操作 CodePointAt,接收参数 string (String) 和 position (非负整数);返回值:记录 (字段:[[CodePoint]] (码点), [[CodeUnitCount]] (正整数), [[IsUnpairedSurrogate]] (Boolean))。 它按照 6.1.4 中的描述,将 string 解释为 UTF-16 编码码点序列,并从索引 position 处的码元开始读取其中的单个码点。 调用时执行以下步骤:

  1. 令 size 为 string 的长度。
  2. 断言:position ≥ 0 且 position < size。
  3. 令 first 为 string 中索引 position 处的码元。
  4. 令 codePoint 为数值与 first 的数值相同的码点。
  5. 如果 first 既不是前导代理也不是尾随代理,则
    1. 返回 Record { [[CodePoint]]: codePoint, [[CodeUnitCount]]: 1, [[IsUnpairedSurrogate]]: false }。
  6. 如果 first 是尾随代理或 position + 1 = size,则
    1. 返回 Record { [[CodePoint]]: codePoint, [[CodeUnitCount]]: 1, [[IsUnpairedSurrogate]]: true }。
  7. 令 second 为 string 中索引 position + 1 处的码元。
  8. 如果 second 不是尾随代理,则
    1. 返回 Record { [[CodePoint]]: codePoint, [[CodeUnitCount]]: 1, [[IsUnpairedSurrogate]]: true }。
  9. 将 codePoint 设置为 UTF16SurrogatePairToCodePoint(first, second)。
  10. 返回 Record { [[CodePoint]]: codePoint, [[CodeUnitCount]]: 2, [[IsUnpairedSurrogate]]: false }。

11.1.5 Static Semantics: StringToCodePoints ( string )

抽象操作 StringToCodePoints,接收参数 string (String);返回值:列表 (元素:码点)。 它返回按照 6.1.4 中的描述,将 string 解释为 UTF-16 编码 Unicode 文本后得到的 Unicode 码点序列。 调用时执行以下步骤:

  1. 令 codePoints 为新的空 List。
  2. 令 size 为 string 的长度。
  3. 令 position 为 0。
  4. 当 position < size 时,重复执行,
    1. 令 codePoint 为 CodePointAt(string, position)。
    2. 将 codePoint.[[CodePoint]] 追加到 codePoints。
    3. 将 position 设置为 position + codePoint.[[CodeUnitCount]]。
  5. 返回 codePoints。

11.1.6 Static Semantics: ParseText ( sourceText, goalSymbol )

抽象操作 ParseText,接收参数 sourceText ((String 或 a sequence of Unicode code points)) 和 goalSymbol (a nonterminal in one of the ECMAScript grammars);返回值:(解析节点 或 a non-empty List of SyntaxError objects)。 调用时执行以下步骤:

  1. 如果 sourceText 是 String,则将 sourceText 设置为 StringToCodePoints(sourceText)。
  2. 尝试使用 goalSymbol 作为目标符号解析 sourceText,并分析解析结果是否存在任何提前错误条件。实现可以按实现定义的方式交错执行解析和提前错误检测。
  3. 如果解析成功且未发现提前错误,则返回解析所得解析树根部的 Parse Node(goalSymbol 的实例)。
  4. 返回由一个或多个表示解析错误和/或提前错误的 SyntaxError 对象组成的 List。如果存在多个解析错误或提前错误,则列表中错误对象的数量和顺序由实现定义,但至少必须存在一个。
注 1

考虑这样一段文本:它在某个位置存在提前错误,并且在之后的位置还存在语法错误。先执行一次解析再执行提前错误检查的实现,可能会报告语法错误而不继续执行提前错误检查。将这两项活动交错执行的实现,可能会报告提前错误而不继续寻找语法错误。第三种实现可能会同时报告两个错误。所有这些行为都符合规范。

注 2

另请参见条款 17。

11.2 源代码的类型

ECMAScript 代码有四种类型:

注 1

函数代码通常作为函数定义(15.2)、箭头函数定义(15.3)、方法定义(15.4)、生成器函数定义(15.5)、异步函数定义(15.8)、异步生成器函数定义(15.6)和异步箭头函数(15.9)的主体提供。函数代码也可以从 Function 构造函数(20.2.1.1)、GeneratorFunction 构造函数(27.6.1.1)、AsyncFunction 构造函数(27.10.1.1)和 AsyncGeneratorFunction 构造函数(27.7.1.1)的参数派生。

注 2

将 BindingIdentifier 包含在函数代码中的实际效果是:严格模式代码的提前错误会应用于这样的 BindingIdentifier——它是函数的名称,而该函数的主体包含 Use Strict 指令,即使周围代码不是严格模式代码。

11.2.1 指令序言和 Use Strict 指令

指令序言是一个 FunctionBody、ScriptBody 或 ModuleBody 开头作为初始 StatementListItem 或 ModuleItem 出现的最长 ExpressionStatement 序列,其中序列中的每个 ExpressionStatement 都完全由一个 StringLiteral 标记后跟一个分号组成。分号可以显式出现,也可以通过自动分号插入(12.10)插入。指令序言可以是空序列。

Use Strict 指令是指令序言中的一个 ExpressionStatement,其 StringLiteral 恰好是码点序列 "use strict" 或 'use strict'。Use Strict 指令不得包含 EscapeSequence 或 LineContinuation。

指令序言可以包含多个 Use Strict 指令。不过,实现可以在出现这种情况时发出警告。

注

在对包含它们的产生式求值期间,指令序言中的 ExpressionStatement 会正常求值。实现可以为出现在指令序言中且不是 Use Strict 指令的 ExpressionStatement 定义实现特定的含义。如果存在适当的通知机制,并且实现在指令序言中遇到既不是 Use Strict 指令、也没有实现所定义含义的 ExpressionStatement,则实现应当发出警告。

11.2.2 严格模式代码

ECMAScript 句法单元可以使用无限制模式或严格模式的语法和语义进行处理(4.3.2)。在以下情况下,代码被解释为严格模式代码:

不是严格模式代码的 ECMAScript 代码称为非严格代码。

11.2.2.1 Static Semantics: IsStrict ( parseNode )

抽象操作 IsStrict,接收参数 parseNode (解析节点);返回值:Boolean。 调用时执行以下步骤:

  1. 如果 parseNode 匹配的源文本是严格模式代码,则返回 true。
  2. 返回 false。

11.2.3 非 ECMAScript 函数

ECMAScript 实现可以支持对函数异质对象进行求值,而这些对象的求值行为以 ECMAScript 源文本之外某种宿主定义的可执行代码形式表示。从调用此类函数对象或被此类函数对象调用的 ECMAScript 代码角度来看,无法观察到函数对象究竟是在 ECMAScript 代码中定义的,还是内置函数。

12 ECMAScript 语言:词法文法

ECMAScript Script 或 Module 的源文本首先会转换为输入元素序列,这些输入元素是标记、行终止符、注释或空白。源文本从左向右扫描,并重复取尽可能长的码点序列作为下一个输入元素。

在若干情况下,词法输入元素的识别取决于使用这些输入元素的句法文法上下文。这就要求词法文法具有多个目标符号。InputElementHashbangOrRegExp 目标用于 Script 或 Module 的开头。InputElementRegExpOrTemplateTail 目标用于允许 RegularExpressionLiteral、TemplateMiddle 或 TemplateTail 的句法文法上下文。InputElementRegExp 目标符号用于允许 RegularExpressionLiteral、但既不允许 TemplateMiddle 也不允许 TemplateTail 的所有句法文法上下文。InputElementTemplateTail 目标用于允许 TemplateMiddle 或 TemplateTail、但不允许 RegularExpressionLiteral 的所有句法文法上下文。在所有其他上下文中,使用 InputElementDiv 作为词法目标符号。

注

使用多个词法目标可确保不存在会影响自动分号插入的词法歧义。例如,不存在同时允许开头为除法或除法赋值以及开头为 RegularExpressionLiteral 的句法文法上下文。分号插入不会改变这一点(参见 12.10);在如下示例中:

a = b
/hi/g.exec(c).map(d);

当 LineTerminator 后第一个非空白、非注释码点为 U+002F (SOLIDUS),并且句法上下文允许除法或除法赋值时,不会在该 LineTerminator 处插入分号。也就是说,上述示例的解释方式与以下代码相同:

a = b / hi / g.exec(c).map(d);

语法

InputElementDiv :: WhiteSpace LineTerminator Comment CommonToken DivPunctuator RightBracePunctuator InputElementRegExp :: WhiteSpace LineTerminator Comment CommonToken RightBracePunctuator RegularExpressionLiteral InputElementRegExpOrTemplateTail :: WhiteSpace LineTerminator Comment CommonToken RegularExpressionLiteral TemplateSubstitutionTail InputElementTemplateTail :: WhiteSpace LineTerminator Comment CommonToken DivPunctuator TemplateSubstitutionTail InputElementHashbangOrRegExp :: WhiteSpace LineTerminator Comment CommonToken HashbangComment RegularExpressionLiteral

12.1 Unicode 格式控制字符

Unicode 格式控制字符(即 Unicode 字符数据库中类别为“Cf”的字符,例如 LEFT-TO-RIGHT MARK 或 RIGHT-TO-LEFT MARK)是在缺少用于此目的的更高级协议(例如标记语言)时,用于控制一段文本格式的控制代码。

允许在源文本中使用格式控制字符有助于编辑和显示。所有格式控制字符都可以用于注释、字符串字面量、模板字面量和正则表达式字面量中。

U+FEFF (ZERO WIDTH NO-BREAK SPACE) 是一种格式控制字符,主要用于文本开头以将其标记为 Unicode,并允许检测文本的编码和字节顺序。用于此目的的 <ZWNBSP> 字符有时也可能出现在文本开头之后,例如文件连接的结果。在 ECMAScript 源文本中,位于注释、字符串字面量、模板字面量和正则表达式字面量之外的 <ZWNBSP> 码点被视为空白字符(参见 12.2)。

12.2 空白

空白码点用于提高源文本的可读性,并将标记(不可分割的词法单元)彼此分隔,但除此之外没有意义。空白码点可以出现在任意两个标记之间,也可以出现在输入的开头或结尾。空白码点可以出现在 StringLiteral、RegularExpressionLiteral、Template 或 TemplateSubstitutionTail 内,此时它们被视为构成字面量值一部分的重要码点。它们也可以出现在 Comment 内,但不能出现在任何其他类型的标记中。

ECMAScript 空白码点列于 表 31 中。

表 31: 空白码点
码点 名称 缩写
U+0009 字符制表 <TAB>
U+000B 行制表 <VT>
U+000C 换页 (FF) <FF>
U+FEFF 零宽不换行空格 <ZWNBSP>
常规类别“Space_Separator”中的任意码点 <USP>
注 1

U+0020 (SPACE) 和 U+00A0 (NO-BREAK SPACE) 码点属于 <USP>。

注 2

除 表 31 中列出的码点外,ECMAScript WhiteSpace 有意排除所有具有 Unicode “White_Space”属性、但未归类于常规类别“Space_Separator”(“Zs”)的码点。

语法

WhiteSpace :: <TAB> <VT> <FF> <ZWNBSP> <USP>

12.3 行终止符

与空白码点一样,行终止符码点用于提高源文本的可读性并将标记(不可分割的词法单元)彼此分隔。然而,与空白码点不同,行终止符对句法文法的行为具有一定影响。通常,行终止符可以出现在任意两个标记之间,但句法文法在少数位置禁止它们出现。行终止符还会影响自动分号插入过程(12.10)。除 StringLiteral、Template 或 TemplateSubstitutionTail 外,行终止符不能出现在任何标记内部。除非作为 LineContinuation 的一部分,否则 <LF> 和 <CR> 行终止符不能出现在 StringLiteral 标记中。

行终止符可以出现在 MultiLineComment 内,但不能出现在 SingleLineComment 内。

正则表达式中由 \s 类匹配的空白码点集合包含行终止符。

ECMAScript 行终止符码点列于 表 32 中。

表 32: 行终止符码点
码点 Unicode 名称 缩写
U+000A 换行 (LF) <LF>
U+000D 回车 (CR) <CR>
U+2028 行分隔符 <LS>
U+2029 段落分隔符 <PS>

只有 表 32 中的 Unicode 码点才会被视为行终止符。其他表示换行或断行的 Unicode 码点不会被视为行终止符,但如果满足 表 31 中列出的要求,则会被视为空白。

语法

LineTerminator :: <LF> <CR> <LS> <PS> LineTerminatorSequence :: <LF> <CR> [lookahead ≠ <LF>] <LS> <PS> <CR> <LF> 注

产生式 LineTerminatorSequence :: <CR> <LF> 匹配的码点序列应当整体作为单个行终止符工作,例如在诊断中报告行号时。

12.4 注释

注释可以是单行注释或多行注释。多行注释不能嵌套。

因为单行注释可以包含除 LineTerminator 码点以外的任意 Unicode 码点,并且根据标记始终尽可能长的一般规则,单行注释始终由从 // 标记到行尾的所有码点组成。但是,行尾的 LineTerminator 不被视为单行注释的一部分;词法文法会单独识别它,并使其成为供句法文法使用的输入元素流的一部分。这一点非常重要,因为它意味着是否存在单行注释不会影响自动分号插入过程(参见 12.10)。

注释的行为类似空白,通常会被丢弃;但如果 MultiLineComment 包含行终止符码点,那么在句法文法解析时,整个注释都会被视为一个 LineTerminator。

语法

Comment :: MultiLineComment SingleLineComment MultiLineComment :: /* MultiLineCommentCharsopt */ MultiLineCommentChars :: MultiLineNotAsteriskChar MultiLineCommentCharsopt * PostAsteriskCommentCharsopt PostAsteriskCommentChars :: MultiLineNotForwardSlashOrAsteriskChar MultiLineCommentCharsopt * PostAsteriskCommentCharsopt MultiLineNotAsteriskChar :: SourceCharacter but not * MultiLineNotForwardSlashOrAsteriskChar :: SourceCharacter but not one of / or * SingleLineComment :: // SingleLineCommentCharsopt SingleLineCommentChars :: SingleLineCommentChar SingleLineCommentCharsopt SingleLineCommentChar :: SourceCharacter but not LineTerminator

本节中的若干产生式在 B.1.1 节中具有替代定义

12.5 Hashbang 注释

Hashbang 注释对位置敏感,并且与其他类型的注释一样,会从句法文法的输入元素流中丢弃。

语法

HashbangComment :: #! SingleLineCommentCharsopt

12.6 标记

语法

CommonToken :: IdentifierName PrivateIdentifier Punctuator NumericLiteral StringLiteral Template 注

DivPunctuator、RegularExpressionLiteral、RightBracePunctuator 和 TemplateSubstitutionTail 产生式会派生出未包含在 CommonToken 产生式中的其他标记。

12.7 名称和关键字

IdentifierName 和 ReservedWord 是根据 Unicode 标准附录 #31《Identifier and Pattern Syntax》中给出的默认标识符语法进行解释的标记,并进行了一些小的修改。ReservedWord 是 IdentifierName 的一个枚举子集。句法文法将 Identifier 定义为不是 ReservedWord 的 IdentifierName。Unicode 标识符文法基于 Unicode 标准规定的字符属性。所有符合规范的 ECMAScript 实现都必须将最新版 Unicode 标准中指定类别里的 Unicode 码点视为属于这些类别。ECMAScript 实现可以识别 Unicode 标准后续版本中定义的标识符码点。

注 1

本标准规定了特定码点的额外允许范围:U+0024 (DOLLAR SIGN) 和 U+005F (LOW LINE) 可以出现在 IdentifierName 的任何位置。

语法

PrivateIdentifier :: # IdentifierName IdentifierName :: IdentifierStart IdentifierName IdentifierPart IdentifierStart :: IdentifierStartChar \ UnicodeEscapeSequence IdentifierPart :: IdentifierPartChar \ UnicodeEscapeSequence IdentifierStartChar :: UnicodeIDStart $ _ IdentifierPartChar :: UnicodeIDContinue $ AsciiLetter :: one of a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z UnicodeIDStart :: any Unicode code point with the Unicode property “ID_Start” UnicodeIDContinue :: any Unicode code point with the Unicode property “ID_Continue”

非终结符 UnicodeEscapeSequence 的定义见 12.9.4。

注 2

非终结符 IdentifierPart 通过 UnicodeIDContinue 派生 _。

注 3

具有 Unicode 属性“ID_Start”和“ID_Continue”的码点集合,分别包含具有 Unicode 属性“Other_ID_Start”和“Other_ID_Continue”的码点。

12.7.1 标识符名称

IdentifierName 中允许使用 Unicode 转义序列,其中每个转义序列贡献一个等于 UnicodeEscapeSequence 的 IdentifierCodePoint 的 Unicode 码点。UnicodeEscapeSequence 前面的 \ 不贡献任何码点。不能使用 UnicodeEscapeSequence 向 IdentifierName 贡献一个原本无效的码点。换句话说,如果将 \ UnicodeEscapeSequence 序列替换为其所贡献的 SourceCharacter,结果仍必须是一个有效的 IdentifierName,并且具有与原始 IdentifierName 完全相同的 SourceCharacter 元素序列。本规范对 IdentifierName 的所有解释都基于其实际码点,而不考虑某个特定码点是否是通过转义序列贡献的。

根据 Unicode 标准规范等价的两个 IdentifierName,除非在替换每个 UnicodeEscapeSequence 后由完全相同的码点序列表示,否则它们不相等。

12.7.1.1 Static Semantics: 提前错误

IdentifierStart :: \ UnicodeEscapeSequence IdentifierPart :: \ UnicodeEscapeSequence

12.7.1.2 Static Semantics: IdentifierCodePoints

语法制导操作 IdentifierCodePoints,接收无参数;返回值:列表 (元素:码点)。 它按以下产生式分别定义:

IdentifierName :: IdentifierStart
  1. 令 codePoint 为 IdentifierStart 的 IdentifierCodePoint。
  2. 返回 « codePoint »。
IdentifierName :: IdentifierName IdentifierPart
  1. 令 codePoints 为派生的 IdentifierName 的 IdentifierCodePoints。
  2. 令 codePoint 为 IdentifierPart 的 IdentifierCodePoint。
  3. 返回 codePoints 与 « codePoint » 的列表连接。

12.7.1.3 Static Semantics: IdentifierCodePoint

语法制导操作 IdentifierCodePoint,接收无参数;返回值:码点。 它按以下产生式分别定义:

IdentifierStart :: IdentifierStartChar
  1. 返回由 IdentifierStartChar 匹配的码点。
IdentifierPart :: IdentifierPartChar
  1. 返回由 IdentifierPartChar 匹配的码点。
UnicodeEscapeSequence :: u Hex4Digits
  1. 返回数值为 Hex4Digits 的 MV 的码点。
UnicodeEscapeSequence :: u{ CodePoint }
  1. 返回数值为 CodePoint 的 MV 的码点。

12.7.2 关键字和保留字

关键字是匹配 IdentifierName、同时具有句法用途的标记;也就是说,它会以 fixed width 字体按字面形式出现在某个句法产生式中。ECMAScript 的关键字包括 if、while、async、await 等许多关键字。

保留字是不能用作标识符的 IdentifierName。许多关键字是保留字,但有些不是,还有一些只在某些上下文中是保留字。if 和 while 是保留字。await 仅在异步函数和模块内部是保留字。async 不是保留字;它可以不受限制地用作变量名或语句标签。

本规范结合文法产生式和提前错误规则,规定哪些名称是有效标识符以及哪些名称是保留字。除 await 和 yield 外,下面 ReservedWord 列表中的所有标记都无条件保留。await 和 yield 的例外情况使用参数化句法产生式在 13.1 中规定。最后,若干提前错误规则会限制有效标识符集合。参见 13.1.1、14.3.1.1、14.7.5.1 和 15.7.1。总而言之,标识符名称分为五类:

  • 始终允许作为标识符且不是关键字的名称,例如 Math、window、toString 和 _;

  • 永远不允许作为标识符的名称,即下面列出的 ReservedWord 中除 await 和 yield 之外的名称;

  • 根据上下文允许作为标识符的名称,即 await 和 yield;

  • 在严格模式代码中,根据上下文不允许作为标识符的名称:let、static、implements、interface、package、private、protected 和 public;

  • 始终允许作为标识符、但也会在某些不允许 Identifier 的句法产生式位置中作为关键字出现的名称:as、async、from、get、meta、of、set 和 target。

条件关键字或上下文关键字这两个术语有时用于指代后三类关键字,因此它们在某些上下文中可以用作标识符,在其他上下文中则用作关键字。

语法

ReservedWord :: one of await break case catch class const continue debugger default delete do else enum export extends false finally for function if import in instanceof new null return super switch this throw true try typeof var void while with yield 注 1

根据 5.1.5,文法中的关键字匹配特定 SourceCharacter 元素的字面序列。关键字中的码点不能使用 \ UnicodeEscapeSequence 表示。

IdentifierName 可以包含 \ UnicodeEscapeSequence,但无法通过将其拼写为 els\u{65} 来声明名为“else”的变量。13.1.1 中的提前错误规则排除了与保留字具有相同 StringValue 的标识符。

注 2

enum 目前未在本规范中用作关键字。它是一个未来保留字,为将来的语言扩展用作关键字而保留。

类似地,implements、interface、package、private、protected 和 public 是严格模式代码中的未来保留字。

注 3

名称 arguments 和 eval 不是关键字,但在严格模式代码中受到一些限制。参见 13.1.1、8.6.4、15.2.1、15.5.1、15.6.1 和 15.8.1。

12.8 标点符号

语法

Punctuator :: OptionalChainingPunctuator OtherPunctuator OptionalChainingPunctuator :: ?. [lookahead ∉ DecimalDigit] OtherPunctuator :: one of { ( ) [ ] . ... ; , < > <= >= == != === !== + - * % ** ++ -- << >> >>> & | ^ ! ~ && || ?? ? : = += -= *= %= **= <<= >>= >>>= &= |= ^= &&= ||= ??= => DivPunctuator :: / /= RightBracePunctuator :: }

12.9 字面量

12.9.1 Null 字面量

语法

NullLiteral :: null

12.9.2 Boolean 字面量

语法

BooleanLiteral :: true false

12.9.3 数值字面量

语法

NumericLiteralSeparator :: _ NumericLiteral :: DecimalLiteral DecimalBigIntegerLiteral NonDecimalIntegerLiteral[+Sep] NonDecimalIntegerLiteral[+Sep] BigIntLiteralSuffix LegacyOctalIntegerLiteral DecimalBigIntegerLiteral :: 0 BigIntLiteralSuffix NonZeroDigit DecimalDigits[+Sep]opt BigIntLiteralSuffix NonZeroDigit NumericLiteralSeparator DecimalDigits[+Sep] BigIntLiteralSuffix NonDecimalIntegerLiteral[Sep] :: BinaryIntegerLiteral[?Sep] OctalIntegerLiteral[?Sep] HexIntegerLiteral[?Sep] BigIntLiteralSuffix :: n DecimalLiteral :: DecimalIntegerLiteral . DecimalDigits[+Sep]opt ExponentPart[+Sep]opt . DecimalDigits[+Sep] ExponentPart[+Sep]opt DecimalIntegerLiteral ExponentPart[+Sep]opt DecimalIntegerLiteral :: DecimalDigit NonZeroDigit NumericLiteralSeparatoropt DecimalDigits[+Sep] NonOctalDecimalIntegerLiteral DecimalDigits[Sep] :: DecimalDigit DecimalDigits[?Sep] DecimalDigit [+Sep] DecimalDigits[+Sep] NumericLiteralSeparator DecimalDigit DecimalDigit :: one of 0 1 2 3 4 5 6 7 8 9 NonZeroDigit :: one of 1 2 3 4 5 6 7 8 9 ExponentPart[Sep] :: ExponentIndicator SignedInteger[?Sep] ExponentIndicator :: one of e E SignedInteger[Sep] :: DecimalDigits[?Sep] + DecimalDigits[?Sep] - DecimalDigits[?Sep] BinaryIntegerLiteral[Sep] :: 0b BinaryDigits[?Sep] 0B BinaryDigits[?Sep] BinaryDigits[Sep] :: BinaryDigit BinaryDigits[?Sep] BinaryDigit [+Sep] BinaryDigits[+Sep] NumericLiteralSeparator BinaryDigit BinaryDigit :: one of 0 1 OctalIntegerLiteral[Sep] :: 0o OctalDigits[?Sep] 0O OctalDigits[?Sep] OctalDigits[Sep] :: OctalDigit OctalDigits[?Sep] OctalDigit [+Sep] OctalDigits[+Sep] NumericLiteralSeparator OctalDigit LegacyOctalIntegerLiteral :: 0 OctalDigit LegacyOctalIntegerLiteral OctalDigit NonOctalDecimalIntegerLiteral :: 0 LegacyOctalLikeDecimalDigitsopt NonOctalDigit NonOctalDecimalIntegerLiteral DecimalDigit LegacyOctalLikeDecimalDigits :: OctalDigit LegacyOctalLikeDecimalDigits OctalDigit OctalDigit :: one of 0 1 2 3 4 5 6 7 NonOctalDigit :: one of 8 9 HexIntegerLiteral[Sep] :: 0x HexDigits[?Sep] 0X HexDigits[?Sep] HexDigits[Sep] :: HexDigit HexDigits[?Sep] HexDigit [+Sep] HexDigits[+Sep] NumericLiteralSeparator HexDigit HexDigit :: one of 0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F

紧跟在 NumericLiteral 后面的 SourceCharacter 不得是 IdentifierStart 或 DecimalDigit。

注

例如:3in 是错误的,而不是两个输入元素 3 和 in。

12.9.3.1 Static Semantics: 提前错误

NumericLiteral :: LegacyOctalIntegerLiteral DecimalIntegerLiteral :: NonOctalDecimalIntegerLiteral
  • 如果 IsStrict(this production) 是 true,则为语法错误。
注
在非严格代码中,此语法是遗留语法。

12.9.3.2 Static Semantics: MV

数值字面量表示 Number 类型或 BigInt 类型的值。

12.9.3.3 Static Semantics: NumericValue

语法制导操作 NumericValue,接收无参数;返回值:(Number 或 BigInt)。 它按以下产生式分别定义:

NumericLiteral :: DecimalLiteral
  1. 返回 RoundMVResult(DecimalLiteral 的 MV)。
NumericLiteral :: NonDecimalIntegerLiteral
  1. 返回 𝔽(NonDecimalIntegerLiteral 的 MV)。
NumericLiteral :: LegacyOctalIntegerLiteral
  1. 返回 𝔽(LegacyOctalIntegerLiteral 的 MV)。
NumericLiteral :: NonDecimalIntegerLiteral BigIntLiteralSuffix
  1. 返回与 NonDecimalIntegerLiteral 的 MV 对应的 BigInt 值。
DecimalBigIntegerLiteral :: 0 BigIntLiteralSuffix
  1. 返回 0ℤ。
DecimalBigIntegerLiteral :: NonZeroDigit BigIntLiteralSuffix
  1. 返回与 NonZeroDigit 的 MV 对应的 BigInt 值。
DecimalBigIntegerLiteral :: NonZeroDigit DecimalDigits BigIntLiteralSuffix NonZeroDigit NumericLiteralSeparator DecimalDigits BigIntLiteralSuffix
  1. 令 n 为 DecimalDigits 中的码点数量,不包括所有出现的 NumericLiteralSeparator。
  2. 令 mv 为(NonZeroDigit 的 MV × 10n)+ DecimalDigits 的 MV。
  3. 返回 ℤ(mv)。

12.9.4 字符串字面量

注 1

字符串字面量是由单引号或双引号包围的 0 个或多个 Unicode 码点。Unicode 码点也可以由转义序列表示。除闭合引号码点、U+005C (REVERSE SOLIDUS)、U+000D (CARRIAGE RETURN) 和 U+000A (LINE FEED) 外,所有码点都可以按字面形式出现在字符串字面量中。任何码点都可以转义序列的形式出现。字符串字面量求值为 ECMAScript String 值。生成这些 String 值时,按照 11.1.1 中的定义对 Unicode 码点进行 UTF-16 编码。属于基本多文种平面的码点被编码为字符串中的单个码元元素。所有其他码点被编码为字符串中的两个码元元素。

语法

StringLiteral :: " DoubleStringCharactersopt " ' SingleStringCharactersopt ' DoubleStringCharacters :: DoubleStringCharacter DoubleStringCharactersopt SingleStringCharacters :: SingleStringCharacter SingleStringCharactersopt DoubleStringCharacter :: SourceCharacter but not one of " or \ or LineTerminator <LS> <PS> \ EscapeSequence LineContinuation SingleStringCharacter :: SourceCharacter but not one of ' or \ or LineTerminator <LS> <PS> \ EscapeSequence LineContinuation LineContinuation :: \ LineTerminatorSequence EscapeSequence :: CharacterEscapeSequence 0 [lookahead ∉ DecimalDigit] LegacyOctalEscapeSequence NonOctalDecimalEscapeSequence HexEscapeSequence UnicodeEscapeSequence CharacterEscapeSequence :: SingleEscapeCharacter NonEscapeCharacter SingleEscapeCharacter :: one of ' " \ b f n r t v NonEscapeCharacter :: SourceCharacter but not one of EscapeCharacter or LineTerminator EscapeCharacter :: SingleEscapeCharacter DecimalDigit x u LegacyOctalEscapeSequence :: 0 [lookahead ∈ { 8, 9 }] NonZeroOctalDigit [lookahead ∉ OctalDigit] ZeroToThree OctalDigit [lookahead ∉ OctalDigit] FourToSeven OctalDigit ZeroToThree OctalDigit OctalDigit NonZeroOctalDigit :: OctalDigit but not 0 ZeroToThree :: one of 0 1 2 3 FourToSeven :: one of 4 5 6 7 NonOctalDecimalEscapeSequence :: one of 8 9 HexEscapeSequence :: x HexDigit HexDigit UnicodeEscapeSequence :: u Hex4Digits u{ CodePoint } Hex4Digits :: HexDigit HexDigit HexDigit HexDigit

非终结符 HexDigit 的定义见 12.9.3。SourceCharacter 定义于 11.1。

注 2

除非作为 LineContinuation 的一部分以产生空码点序列,否则 <LF> 和 <CR> 不能出现在字符串字面量中。要将二者之一包含在字符串字面量的 String 值中,正确方式是使用 \n 或 \u000A 等转义序列。

12.9.4.1 Static Semantics: 提前错误

EscapeSequence :: LegacyOctalEscapeSequence NonOctalDecimalEscapeSequence
  • 如果 IsStrict(this production) 是 true,则为语法错误。
注 1
在非严格代码中,此语法是遗留语法。
注 2

字符串字面量可能出现在 Use Strict 指令之前,而该指令会使包围代码处于严格模式,实现必须注意对这些字面量强制执行上述规则。例如,以下源文本包含语法错误:

function invalid() { "\7"; "use strict"; }

12.9.4.2 Static Semantics: SV

语法制导操作 SV,接收无参数;返回值:String。

字符串字面量表示 String 类型的值。SV 通过递归应用于字符串字面量的各个部分,为字符串字面量产生 String 值。作为此过程的一部分,字符串字面量中的某些 Unicode 码点会按照下文或 12.9.3 中的描述,被解释为具有某个数学值。

表 33: String 单字符转义序列
转义序列 码元值 Unicode 字符名称 符号
\b 0x0008 退格 <BS>
\t 0x0009 字符制表 <HT>
\n 0x000A 换行 (LF) <LF>
\v 0x000B 行制表 <VT>
\f 0x000C 换页 (FF) <FF>
\r 0x000D 回车 (CR) <CR>
\" 0x0022 双引号 "
\' 0x0027 撇号 '
\\ 0x005C 反斜线 \

12.9.4.3 Static Semantics: MV

12.9.5 正则表达式字面量

注 1

正则表达式字面量是一种输入元素,每次对该字面量求值时都会转换为 RegExp 对象(参见 22.2)。程序中的两个正则表达式字面量求值为彼此永远不会通过 === 比较为相等的正则表达式对象,即使这两个字面量的内容完全相同。还可以在运行时通过 new RegExp 或将 RegExp 构造函数作为函数调用来创建 RegExp 对象(参见 22.2.4)。

下面的产生式描述正则表达式字面量的语法,并由输入元素扫描器用于寻找正则表达式字面量的结尾。随后,会使用更严格的 ECMAScript 正则表达式文法(22.2.1)再次解析构成 RegularExpressionBody 和 RegularExpressionFlags 的源文本。

实现可以扩展 22.2.1 中定义的 ECMAScript 正则表达式文法,但不得扩展下面定义的 RegularExpressionBody 和 RegularExpressionFlags 产生式,也不得扩展这些产生式所使用的产生式。

语法

RegularExpressionLiteral :: / RegularExpressionBody / RegularExpressionFlags RegularExpressionBody :: RegularExpressionFirstChar RegularExpressionChars RegularExpressionChars :: [empty] RegularExpressionChars RegularExpressionChar RegularExpressionFirstChar :: RegularExpressionNonTerminator but not one of * or \ or / or [ RegularExpressionBackslashSequence RegularExpressionClass RegularExpressionChar :: RegularExpressionNonTerminator but not one of \ or / or [ RegularExpressionBackslashSequence RegularExpressionClass RegularExpressionBackslashSequence :: \ RegularExpressionNonTerminator RegularExpressionNonTerminator :: SourceCharacter but not LineTerminator RegularExpressionClass :: [ RegularExpressionClassChars ] RegularExpressionClassChars :: [empty] RegularExpressionClassChars RegularExpressionClassChar RegularExpressionClassChar :: RegularExpressionNonTerminator but not one of ] or \ RegularExpressionBackslashSequence RegularExpressionFlags :: [empty] RegularExpressionFlags IdentifierPartChar 注 2

正则表达式字面量不能为空;码元序列 // 不表示空正则表达式字面量,而是开始一个单行注释。要指定空正则表达式,请使用:/(?:)/。

12.9.5.1 Static Semantics: BodyText

语法制导操作 BodyText,接收无参数;返回值:源文本。 它按以下产生式分别定义:

RegularExpressionLiteral :: / RegularExpressionBody / RegularExpressionFlags
  1. 返回被识别为 RegularExpressionBody 的源文本。

12.9.5.2 Static Semantics: FlagText

语法制导操作 FlagText,接收无参数;返回值:源文本。 它按以下产生式分别定义:

RegularExpressionLiteral :: / RegularExpressionBody / RegularExpressionFlags
  1. 返回被识别为 RegularExpressionFlags 的源文本。

12.9.6 模板字面量词法组成部分

语法

Template :: NoSubstitutionTemplate TemplateHead NoSubstitutionTemplate :: ` TemplateCharactersopt ` TemplateHead :: ` TemplateCharactersopt ${ TemplateSubstitutionTail :: TemplateMiddle TemplateTail TemplateMiddle :: } TemplateCharactersopt ${ TemplateTail :: } TemplateCharactersopt ` TemplateCharacters :: TemplateCharacter TemplateCharactersopt TemplateCharacter :: $ [lookahead ≠ {] \ TemplateEscapeSequence \ NotEscapeSequence LineContinuation LineTerminatorSequence SourceCharacter but not one of ` or \ or $ or LineTerminator TemplateEscapeSequence :: CharacterEscapeSequence 0 [lookahead ∉ DecimalDigit] HexEscapeSequence UnicodeEscapeSequence NotEscapeSequence :: 0 DecimalDigit DecimalDigit but not 0 x [lookahead ∉ HexDigit] x HexDigit [lookahead ∉ HexDigit] u [lookahead ∉ HexDigit] [lookahead ≠ {] u HexDigit [lookahead ∉ HexDigit] u HexDigit HexDigit [lookahead ∉ HexDigit] u HexDigit HexDigit HexDigit [lookahead ∉ HexDigit] u { [lookahead ∉ HexDigit] u { NotCodePoint [lookahead ∉ HexDigit] u { CodePoint [lookahead ∉ HexDigit] [lookahead ≠ }] NotCodePoint :: HexDigits[~Sep] but only if the MV of HexDigits > 0x10FFFF CodePoint :: HexDigits[~Sep] but only if the MV of HexDigits ≤ 0x10FFFF 注

TemplateSubstitutionTail 由 InputElementTemplateTail 替代词法目标使用。

12.9.6.1 Static Semantics: TV

语法制导操作 TV,接收无参数;返回值:(String 或 undefined)。 模板字面量组成部分由 TV 解释为 String 类型的值。TV 用于构造模板对象的索引组成部分(通俗地说,即模板值)。在 TV 中,转义序列会被替换为该转义序列所表示 Unicode 码点的 UTF-16 码元。

12.9.6.2 Static Semantics: TRV

语法制导操作 TRV,接收无参数;返回值:String。 模板字面量组成部分由 TRV 解释为 String 类型的值。TRV 用于构造模板对象的原始组成部分(通俗地说,即模板原始值)。TRV 与 TV 类似,不同之处在于,在 TRV 中,转义序列按照它们在字面量中出现的形式进行解释。

注

TV 会排除 LineContinuation 的码元,而 TRV 会包含它们。对于 TV 和 TRV,<CR><LF> 和 <CR> LineTerminatorSequence 都会规范化为 <LF>。要包含 <CR> 或 <CR><LF> 序列,需要显式使用 TemplateEscapeSequence。

12.10 自动分号插入

大多数 ECMAScript 语句和声明都必须以分号终止。这样的分号始终可以显式出现在源文本中。不过,为了方便,在某些情况下可以从源文本中省略这样的分号。这些情况通过表述为“在这些情况下,分号会自动插入源代码标记流中”来描述。

12.10.1 自动分号插入规则

在以下规则中,“标记”是指按照条款 12 中的描述,使用当前词法目标符号确定的实际已识别词法标记。

分号插入有三条基本规则:

  1. 从左向右解析源文本时,如果遇到一个文法中任何产生式都不允许的标记(称为违规标记),并且以下一个或多个条件成立,则会在该违规标记之前自动插入分号:

    • 违规标记与前一个标记之间至少由一个 LineTerminator 分隔。
    • 违规标记是 }。
    • 前一个标记是 ),并且插入的分号随后会被解析为 do-while 语句(14.7.2)的终止分号。
  2. 从左向右解析源文本时,如果遇到输入标记流的末尾,并且解析器无法将输入标记流解析为目标非终结符的单个实例,则会在输入流末尾自动插入分号。
  3. 从左向右解析源文本时,如果遇到一个某个文法产生式允许的标记,但该产生式是一个受限产生式,并且该标记将成为受限产生式中紧跟在标注“[no LineTerminator here]”后的终结符或非终结符的第一个标记(因此这样的标记称为受限标记),且该受限标记与前一个标记之间至少由一个 LineTerminator 分隔,则会在该受限标记之前自动插入分号。

不过,前述规则还受一个额外的覆盖条件限制:如果分号随后会被解析为空语句,或者该分号会成为 for 语句头部中的两个分号之一(参见 14.7.4),则绝不会自动插入分号。

注

以下是文法中仅有的受限产生式:

UpdateExpression[Yield, Await] : LeftHandSideExpression[?Yield, ?Await] [no LineTerminator here] ++ LeftHandSideExpression[?Yield, ?Await] [no LineTerminator here] -- UsingDeclaration[In, Yield, Await] : using [no LineTerminator here] BindingList[?In, ?Yield, ?Await, ~Pattern] ; ContinueStatement[Yield, Await] : continue ; continue [no LineTerminator here] LabelIdentifier[?Yield, ?Await] ; BreakStatement[Yield, Await] : break ; break [no LineTerminator here] LabelIdentifier[?Yield, ?Await] ; ReturnStatement[Yield, Await] : return ; return [no LineTerminator here] Expression[+In, ?Yield, ?Await] ; ThrowStatement[Yield, Await] : throw [no LineTerminator here] Expression[+In, ?Yield, ?Await] ; YieldExpression[In, Await] : yield yield [no LineTerminator here] AssignmentExpression[?In, +Yield, ?Await] yield [no LineTerminator here] * AssignmentExpression[?In, +Yield, ?Await] ArrowFunction[In, Yield, Await] : ArrowParameters[?Yield, ?Await] [no LineTerminator here] => ConciseBody[?In] AsyncFunctionDeclaration[Yield, Await, Default] : async [no LineTerminator here] function BindingIdentifier[?Yield, ?Await] ( FormalParameters[~Yield, +Await] ) { AsyncFunctionBody } [+Default] async [no LineTerminator here] function ( FormalParameters[~Yield, +Await] ) { AsyncFunctionBody } AsyncFunctionExpression : async [no LineTerminator here] function BindingIdentifier[~Yield, +Await]opt ( FormalParameters[~Yield, +Await] ) { AsyncFunctionBody } AsyncMethod[Yield, Await] : async [no LineTerminator here] ClassElementName[?Yield, ?Await] ( UniqueFormalParameters[~Yield, +Await] ) { AsyncFunctionBody } AsyncGeneratorDeclaration[Yield, Await, Default] : async [no LineTerminator here] function * BindingIdentifier[?Yield, ?Await] ( FormalParameters[+Yield, +Await] ) { AsyncGeneratorBody } [+Default] async [no LineTerminator here] function * ( FormalParameters[+Yield, +Await] ) { AsyncGeneratorBody } AsyncGeneratorExpression : async [no LineTerminator here] function * BindingIdentifier[+Yield, +Await]opt ( FormalParameters[+Yield, +Await] ) { AsyncGeneratorBody } AsyncGeneratorMethod[Yield, Await] : async [no LineTerminator here] * ClassElementName[?Yield, ?Await] ( UniqueFormalParameters[+Yield, +Await] ) { AsyncGeneratorBody } AsyncArrowFunction[In, Yield, Await] : async [no LineTerminator here] AsyncArrowBindingIdentifier[?Yield] [no LineTerminator here] => AsyncConciseBody[?In] CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await] [no LineTerminator here] => AsyncConciseBody[?In] AsyncArrowHead : async [no LineTerminator here] ArrowFormalParameters[~Yield, +Await]

这些受限产生式的实际效果如下:

  • 当在解析器会将其视为后缀运算符的位置遇到 ++ 或 -- 标记,并且前一个标记与 ++ 或 -- 标记之间出现了至少一个 LineTerminator 时,会在 ++ 或 -- 标记之前自动插入分号。
  • 当遇到 using 标记,并且在 IdentifierName 标记之前遇到 LineTerminator 时,会在 using 标记之后自动插入分号。
  • 当遇到 continue、break、return、throw 或 yield 标记,并且在下一个标记之前遇到 LineTerminator 时,会在 continue、break、return、throw 或 yield 标记之后自动插入分号。
  • 当箭头函数参数之后在 => 标记之前出现 LineTerminator 时,会自动插入分号,并且该标点符号会导致语法错误。
  • 当 async 标记之后在 function、IdentifierName 或 ( 标记之前出现 LineTerminator 时,会自动插入分号,并且 async 标记不会被视为与后续标记属于同一个表达式或类元素。
  • 当 async 标记之后在 * 标记之前出现 LineTerminator 时,会自动插入分号,并且该标点符号会导致语法错误。

由此给 ECMAScript 程序员带来的实际建议是:

  • 后缀 ++ 或 -- 运算符应与其操作数位于同一行。
  • using 声明中的 BindingList 应与 using 标记从同一行开始。
  • return 或 throw 语句中的 Expression,或者 yield 表达式中的 AssignmentExpression,应与 return、throw 或 yield 标记从同一行开始。
  • break 或 continue 语句中的 LabelIdentifier 应与 break 或 continue 标记位于同一行。
  • 箭头函数参数的结尾与其 => 应位于同一行。
  • 异步函数或方法之前的 async 标记应与紧跟其后的标记位于同一行。

12.10.2 自动分号插入示例

本节为非规范性内容。

源文本

{ 1 2 } 3

即使应用自动分号插入规则,也不是 ECMAScript 文法中的有效句子。相比之下,源文本

{ 1
2 } 3

同样不是有效的 ECMAScript 句子,但会通过自动分号插入转换为以下形式:

{ 1
;2 ;} 3;

它是一个有效的 ECMAScript 句子。

源文本

for (a; b
)

不是有效的 ECMAScript 句子,并且不会通过自动分号插入进行更改,因为该分号是 for 语句头部所必需的。自动分号插入永远不会插入 for 语句头部中的两个分号之一。

源文本

return
a + b

会通过自动分号插入转换为以下形式:

return;
a + b;
注 1

表达式 a + b 不会被视为 return 语句要返回的值,因为它与标记 return 之间由 LineTerminator 分隔。

源文本

a = b
++c

会通过自动分号插入转换为以下形式:

a = b;
++c;
注 2

标记 ++ 不会被视为应用于变量 b 的后缀运算符,因为 b 和 ++ 之间存在 LineTerminator。

源文本

if (a > b)
else c = d

不是有效的 ECMAScript 句子,并且不会在 else 标记之前通过自动分号插入进行更改,即使此时没有任何文法产生式适用,因为自动插入的分号随后会被解析为空语句。

源文本

a = b + c
(d + e).print()

不会通过自动分号插入进行转换,因为第二行开头的括号表达式可以被解释为函数调用的参数列表:

a = b + c(d + e).print()

如果赋值语句必须以左括号开头,那么程序员最好在前一个语句末尾显式提供分号,而不是依赖自动分号插入。

12.10.3 自动分号插入的特殊情况

本节为非规范性内容。

ECMAScript 程序可以通过依赖自动分号插入,以只使用极少分号的风格编写。如上所述,并非每个换行处都会插入分号,而且自动分号插入可能取决于跨越行终止符的多个标记。

随着新的句法特性添加到 ECMAScript 中,可能会新增文法产生式,从而导致那些依赖在其前方进行自动分号插入的代码行在解析时改为匹配不同的文法产生式。

就本节而言,如果某个位置是否插入分号取决于其前面的源文本,则该自动分号插入情况被视为特殊情况。本节其余部分描述此版本 ECMAScript 中若干自动分号插入的特殊情况。

12.10.3.1 语句列表中自动分号插入的特殊情况

在 StatementList 中,许多 StatementListItem 以分号结束,而这些分号可以使用自动分号插入省略。根据上述规则,如果一行以表达式结束,而下一行以下列任一内容开头,则行尾需要分号:

  • 左圆括号(()。如果没有分号,两行会一起被视为 CallExpression。
  • 左方括号([)。如果没有分号,两行会一起被视为属性访问,而不是 ArrayLiteral 或 ArrayAssignmentPattern。
  • 模板字面量(`)。如果没有分号,两行会一起被解释为带标签的 Template(13.3.11),并以前一个表达式作为 MemberExpression。
  • 一元 + 或 -。如果没有分号,两行会一起被解释为相应二元运算符的使用。
  • RegExp 字面量。如果没有分号,两行可能会被解析为 / MultiplicativeOperator,例如当 RegExp 带有标志时。

12.10.3.2 自动分号插入和“[no LineTerminator here]”的情况

本节为非规范性内容。

ECMAScript 包含带有“[no LineTerminator here]”的文法产生式。这些产生式有时用于在文法中提供可选操作数。在这些位置引入 LineTerminator 会通过使用不带可选操作数的文法产生式而改变源文本所匹配的文法产生式。

本节其余部分描述此版本 ECMAScript 中若干使用“[no LineTerminator here]”的产生式。

12.10.3.2.1 带可选操作数和“[no LineTerminator here]”的文法产生式列表

13 ECMAScript 语言:表达式

13.1 标识符

语法

IdentifierReference[Yield, Await] : Identifier [~Yield] yield [~Await] await BindingIdentifier[Yield, Await] : Identifier yield await LabelIdentifier[Yield, Await] : Identifier [~Yield] yield [~Await] await Identifier : IdentifierName but not ReservedWord 注

文法中允许 yield 和 await 作为 BindingIdentifier,并通过下述静态语义禁止它们,以防止在如下情况中进行自动分号插入

let
await 0;

13.1.1 Static Semantics: 提前错误

BindingIdentifier : Identifier IdentifierReference : yield BindingIdentifier : yield LabelIdentifier : yield
  • 如果 IsStrict(this production) 是 true,则为语法错误。
IdentifierReference : await BindingIdentifier : await LabelIdentifier : await BindingIdentifier[Yield, Await] : yield
  • 如果此产生式具有 [Yield] 参数,则为语法错误。
BindingIdentifier[Yield, Await] : await
  • 如果此产生式具有 [Await] 参数,则为语法错误。
IdentifierReference[Yield, Await] : Identifier BindingIdentifier[Yield, Await] : Identifier LabelIdentifier[Yield, Await] : Identifier
  • 如果此产生式具有 [Yield] 参数,并且 Identifier 的 StringValue 是 "yield",则为语法错误。
  • 如果此产生式具有 [Await] 参数,并且 Identifier 的 StringValue 是 "await",则为语法错误。
Identifier : IdentifierName but not ReservedWord 注

IdentifierName 的 StringValue 会规范化 IdentifierName 中的任何 Unicode 转义序列,因此不能使用此类转义来书写一个码点序列与 ReservedWord 相同的 Identifier。

13.1.2 Static Semantics: StringValue

语法制导操作 StringValue,接收无参数;返回值:String。 它按以下产生式分别定义:

IdentifierName :: IdentifierStart IdentifierName IdentifierPart
  1. 令 nameUnescaped 为 IdentifierName 的 IdentifierCodePoints。
  2. 返回 CodePointsToString(nameUnescaped)。
IdentifierReference : yield BindingIdentifier : yield LabelIdentifier : yield
  1. 返回 "yield"。
IdentifierReference : await BindingIdentifier : await LabelIdentifier : await
  1. 返回 "await"。
Identifier : IdentifierName but not ReservedWord
  1. 返回 IdentifierName 的 StringValue。
PrivateIdentifier :: # IdentifierName
  1. 返回 0x0023 (NUMBER SIGN) 和 IdentifierName 的 StringValue 的字符串连接。
ModuleExportName : StringLiteral
  1. 返回 StringLiteral 的 SV。

13.1.3 Runtime Semantics: Evaluation

IdentifierReference : Identifier
  1. 返回 ? ResolveBinding(Identifier 的 StringValue)。
IdentifierReference : yield
  1. 返回 ? ResolveBinding("yield")。
IdentifierReference : await
  1. 返回 ? ResolveBinding("await")。
注 1

对 IdentifierReference 求值的结果始终是 Reference 类型的值。

注 2

在非严格代码中,关键字 yield 可以用作标识符。对 IdentifierReference 求值会像它是 Identifier 一样解析 yield 的绑定。提前错误限制确保此类求值只能发生在非严格代码中。

13.2 基本表达式

语法

PrimaryExpression[Yield, Await] : this IdentifierReference[?Yield, ?Await] Literal ArrayLiteral[?Yield, ?Await] ObjectLiteral[?Yield, ?Await] FunctionExpression ClassExpression[?Yield, ?Await] GeneratorExpression AsyncFunctionExpression AsyncGeneratorExpression RegularExpressionLiteral TemplateLiteral[?Yield, ?Await, ~Tagged] CoverParenthesizedExpressionAndArrowParameterList[?Yield, ?Await] CoverParenthesizedExpressionAndArrowParameterList[Yield, Await] : ( ) ( Expression[+In, ?Yield, ?Await] ,opt ) ( ... BindingIdentifier[?Yield, ?Await] ) ( ... BindingPattern[?Yield, ?Await] ) ( Expression[+In, ?Yield, ?Await] , ... BindingIdentifier[?Yield, ?Await] ) ( Expression[+In, ?Yield, ?Await] , ... BindingPattern[?Yield, ?Await] )

补充语法

当处理产生式
PrimaryExpression[Yield, Await] : CoverParenthesizedExpressionAndArrowParameterList[?Yield, ?Await]
的实例时,使用以下文法进一步细化对 CoverParenthesizedExpressionAndArrowParameterList 的解释:

ParenthesizedExpression[Yield, Await] : ( Expression[+In, ?Yield, ?Await] )

13.2.1 this 关键字

13.2.1.1 Runtime Semantics: Evaluation

PrimaryExpression : this
  1. 返回 ? ResolveThisBinding()。

13.2.2 标识符引用

有关 IdentifierReference,参见 13.1。

13.2.3 字面量

语法

Literal : NullLiteral BooleanLiteral NumericLiteral StringLiteral

13.2.3.1 Runtime Semantics: Evaluation

Literal : NullLiteral
  1. 返回 null。
Literal : BooleanLiteral
  1. 如果 BooleanLiteral 是标记 false,则返回 false。
  2. 如果 BooleanLiteral 是标记 true,则返回 true。
Literal : NumericLiteral
  1. 返回 12.9.3 中定义的 NumericLiteral 的 NumericValue。
Literal : StringLiteral
  1. 返回 12.9.4.2 中定义的 StringLiteral 的 SV。

13.2.4 Array 初始化器

注

ArrayLiteral 是描述 Array 初始化的表达式,它使用由方括号包围的零个或多个表达式的列表,其中每个表达式表示一个数组元素。这些元素不必是字面量;每次对数组初始化器求值时都会对它们求值。

数组元素可以在元素列表的开头、中间或结尾省略。只要元素列表中的逗号之前没有 AssignmentExpression(即位于开头或另一个逗号之后的逗号),缺失的数组元素就会计入 Array 的长度,并增加后续元素的索引。被省略的数组元素不会被定义。如果在数组末尾省略一个元素,则该元素不会计入 Array 的长度。

语法

ArrayLiteral[Yield, Await] : [ Elisionopt ] [ ElementList[?Yield, ?Await] ] [ ElementList[?Yield, ?Await] , Elisionopt ] ElementList[Yield, Await] : Elisionopt AssignmentExpression[+In, ?Yield, ?Await] Elisionopt SpreadElement[?Yield, ?Await] ElementList[?Yield, ?Await] , Elisionopt AssignmentExpression[+In, ?Yield, ?Await] ElementList[?Yield, ?Await] , Elisionopt SpreadElement[?Yield, ?Await] Elision : , Elision , SpreadElement[Yield, Await] : ... AssignmentExpression[+In, ?Yield, ?Await]

13.2.4.1 Runtime Semantics: ArrayAccumulation

语法制导操作 ArrayAccumulation,接收参数 array (Array) 和 nextIndex (整数);返回值:(正常完成 (值:整数) 或 突兀完成)。 它按以下产生式分别定义:

Elision : ,
  1. 令 length 为 nextIndex + 1。
  2. 执行 ? Set(array, "length", 𝔽(length), true)。
  3. 注:如果 length 超过 232 - 1,则上述步骤会抛出异常。
  4. 返回 length。
Elision : Elision ,
  1. 返回 ? 以 array 和 (nextIndex + 1) 为参数对 Elision 执行 ArrayAccumulation 的结果。
ElementList : Elisionopt AssignmentExpression
  1. 如果存在 Elision,则
    1. 将 nextIndex 设置为 ? 以 array 和 nextIndex 为参数对 Elision 执行 ArrayAccumulation 的结果。
  2. 令 initResult 为 ? AssignmentExpression 的 Evaluation。
  3. 令 initValue 为 ? GetValue(initResult)。
  4. 执行 ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(nextIndex)), initValue)。
  5. 返回 nextIndex + 1。
ElementList : Elisionopt SpreadElement
  1. 如果存在 Elision,则
    1. 将 nextIndex 设置为 ? 以 array 和 nextIndex 为参数对 Elision 执行 ArrayAccumulation 的结果。
  2. 返回 ? 以 array 和 nextIndex 为参数对 SpreadElement 执行 ArrayAccumulation 的结果。
ElementList : ElementList , Elisionopt AssignmentExpression
  1. 将 nextIndex 设置为 ? 以 array 和 nextIndex 为参数对派生的 ElementList 执行 ArrayAccumulation 的结果。
  2. 如果存在 Elision,则
    1. 将 nextIndex 设置为 ? 以 array 和 nextIndex 为参数对 Elision 执行 ArrayAccumulation 的结果。
  3. 令 initResult 为 ? AssignmentExpression 的 Evaluation。
  4. 令 initValue 为 ? GetValue(initResult)。
  5. 执行 ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(nextIndex)), initValue)。
  6. 返回 nextIndex + 1。
ElementList : ElementList , Elisionopt SpreadElement
  1. 将 nextIndex 设置为 ? 以 array 和 nextIndex 为参数对派生的 ElementList 执行 ArrayAccumulation 的结果。
  2. 如果存在 Elision,则
    1. 将 nextIndex 设置为 ? 以 array 和 nextIndex 为参数对 Elision 执行 ArrayAccumulation 的结果。
  3. 返回 ? 以 array 和 nextIndex 为参数对 SpreadElement 执行 ArrayAccumulation 的结果。
SpreadElement : ... AssignmentExpression
  1. 令 spreadRef 为 ? AssignmentExpression 的 Evaluation。
  2. 令 spreadObj 为 ? GetValue(spreadRef)。
  3. 令 iteratorRecord 为 ? GetIterator(spreadObj, sync)。
  4. 重复执行,
    1. 令 next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 next 是 done,则返回 nextIndex。
    3. 执行 ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(nextIndex)), next)。
    4. 将 nextIndex 设置为 nextIndex + 1。
注

使用 CreateDataPropertyOrThrow 是为了确保即使标准内置 Array 原型对象已被修改,以致无法使用 [[Set]] 创建新的自有属性,仍会为数组定义自有属性。

13.2.4.2 Runtime Semantics: Evaluation

ArrayLiteral : [ Elisionopt ]
  1. 令 array 为 ! ArrayCreate(0)。
  2. 如果存在 Elision,则
    1. 执行 ? 以 array 和 0 为参数对 Elision 执行 ArrayAccumulation。
  3. 返回 array。
ArrayLiteral : [ ElementList ]
  1. 令 array 为 ! ArrayCreate(0)。
  2. 执行 ? 以 array 和 0 为参数对 ElementList 执行 ArrayAccumulation。
  3. 返回 array。
ArrayLiteral : [ ElementList , Elisionopt ]
  1. 令 array 为 ! ArrayCreate(0)。
  2. 令 nextIndex 为 ? 以 array 和 0 为参数对 ElementList 执行 ArrayAccumulation 的结果。
  3. 如果存在 Elision,则
    1. 执行 ? 以 array 和 nextIndex 为参数对 Elision 执行 ArrayAccumulation。
  4. 返回 array。

13.2.5 对象初始化器

注 1

对象初始化器是描述 Object 初始化的表达式,以类似字面量的形式书写。它是由花括号包围的零个或多个属性键及其关联值的键值对列表。这些值不必是字面量;每次对对象初始化器求值时都会对它们求值。

语法

ObjectLiteral[Yield, Await] : { } { PropertyDefinitionList[?Yield, ?Await] ,opt } PropertyDefinitionList[Yield, Await] : PropertyDefinition[?Yield, ?Await] PropertyDefinitionList[?Yield, ?Await] , PropertyDefinition[?Yield, ?Await] PropertyDefinition[Yield, Await] : IdentifierReference[?Yield, ?Await] CoverInitializedName[?Yield, ?Await] PropertyName[?Yield, ?Await] : AssignmentExpression[+In, ?Yield, ?Await] MethodDefinition[?Yield, ?Await] ... AssignmentExpression[+In, ?Yield, ?Await] PropertyName[Yield, Await] : LiteralPropertyName ComputedPropertyName[?Yield, ?Await] LiteralPropertyName : IdentifierName StringLiteral NumericLiteral ComputedPropertyName[Yield, Await] : [ AssignmentExpression[+In, ?Yield, ?Await] ] CoverInitializedName[Yield, Await] : IdentifierReference[?Yield, ?Await] Initializer[+In, ?Yield, ?Await] Initializer[In, Yield, Await] : = AssignmentExpression[?In, ?Yield, ?Await] 注 2

MethodDefinition 定义于 15.4。

注 3

有关 CoverInitializedName 的意义,参见下一节。

13.2.5.1 Static Semantics: 提前错误

ObjectLiteral : { PropertyDefinitionList ,opt } 注 1

PropertyNameList 返回的 List 不包括使用 ComputedPropertyName 定义的属性名称。

PropertyDefinition : MethodDefinition PropertyDefinition : CoverInitializedName
  • 如果有任何源文本被此产生式匹配,则为语法错误。
注 2

本规范其他位置存在提前错误规则,在某些情况下要求 LeftHandSideExpression 必须覆盖一个 AssignmentPattern。因此,ObjectLiteral 充当 ObjectAssignmentPattern 的覆盖文法。CoverInitializedName 产生式是完整覆盖 AssignmentProperty 所必需的,但在实际对象初始化器中无效。

具体而言,在期望实际 ObjectLiteral 的上下文中,上述提前错误规则会阻止使用 CoverInitializedName。但在 ObjectLiteral 被用作覆盖文法的情况下,“必须覆盖”的语义规定 ObjectLiteral 内的 Parse Node 不受提前错误规则约束,因此允许 CoverInitializedName。

例如,考虑:

let o = {f = 1};

{f = 1} 被解析为带有 CoverInitializedName 的 ObjectLiteral,因而通过此提前错误规则产生语法错误。

相比之下,考虑:

({f = 1} = {f: 2});

这里,{f = 1} 最初同样被解析为带有 CoverInitializedName 的 ObjectLiteral,但由于它是 AssignmentExpression 的 LeftHandSideExpression,所以必须覆盖一个 AssignmentPattern,因此 ObjectLiteral 和 CoverInitializedName 不受提前错误规则约束。相反,{f = 1} 会被重新解析为带有 AssignmentProperty 的 ObjectAssignmentPattern,并且不存在语法错误。

13.2.5.2 Static Semantics: IsComputedPropertyKey

语法制导操作 IsComputedPropertyKey,接收无参数;返回值:Boolean。 它按以下产生式分别定义:

PropertyName : LiteralPropertyName
  1. 返回 false。
PropertyName : ComputedPropertyName
  1. 返回 true。

13.2.5.3 Static Semantics: PropertyDefinitionNodes

语法制导操作 PropertyDefinitionNodes,接收无参数;返回值:列表 (元素:解析节点)。 它按以下产生式分别定义:

ObjectLiteral : { }
  1. 返回新的空 List。
PropertyDefinitionList : PropertyDefinition
  1. 返回 « PropertyDefinition »。
PropertyDefinitionList : PropertyDefinitionList , PropertyDefinition
  1. 令 head 为派生的 PropertyDefinitionList 的 PropertyDefinitionNodes。
  2. 返回 head 与 « PropertyDefinition » 的列表连接。

13.2.5.4 Static Semantics: PropertyNameList

语法制导操作 PropertyNameList,接收无参数;返回值:列表 (元素:String)。 它按以下产生式分别定义:

PropertyDefinitionList : PropertyDefinition
  1. 令 propertyName 为 PropertyDefinition 的 PropName。
  2. 如果 propertyName 是 empty,则返回新的空 List。
  3. 返回 « propertyName »。
PropertyDefinitionList : PropertyDefinitionList , PropertyDefinition
  1. 令 list 为 PropertyDefinitionList 的 PropertyNameList。
  2. 令 propertyName 为 PropertyDefinition 的 PropName。
  3. 如果 propertyName 是 empty,则返回 list。
  4. 返回 list 与 « propertyName » 的列表连接。

13.2.5.5 Runtime Semantics: Evaluation

ObjectLiteral : { }
  1. 返回 OrdinaryObjectCreate(%Object.prototype%)。
ObjectLiteral : { PropertyDefinitionList ,opt }
  1. 令 obj 为 OrdinaryObjectCreate(%Object.prototype%)。
  2. 执行 ? 以 obj 为参数对 PropertyDefinitionList 执行 PropertyDefinitionEvaluation。
  3. 返回 obj。
LiteralPropertyName : IdentifierName
  1. 返回 IdentifierName 的 StringValue。
LiteralPropertyName : StringLiteral
  1. 返回 StringLiteral 的 SV。
LiteralPropertyName : NumericLiteral
  1. 令 number 为 NumericLiteral 的 NumericValue。
  2. 返回 ! ToString(number)。
ComputedPropertyName : [ AssignmentExpression ]
  1. 令 exprValue 为 ? AssignmentExpression 的 Evaluation。
  2. 令 propertyName 为 ? GetValue(exprValue)。
  3. 返回 ? ToPropertyKey(propertyName)。

13.2.5.6 Runtime Semantics: PropertyDefinitionEvaluation

语法制导操作 PropertyDefinitionEvaluation,接收参数 obj (Object);返回值:(正常完成 (值:unused) 或 突兀完成)。 它按以下产生式分别定义:

PropertyDefinitionList : PropertyDefinitionList , PropertyDefinition
  1. 执行 ? 以 obj 为参数对 PropertyDefinitionList 执行 PropertyDefinitionEvaluation。
  2. 执行 ? 以 obj 为参数对 PropertyDefinition 执行 PropertyDefinitionEvaluation。
  3. 返回 unused。
PropertyDefinition : ... AssignmentExpression
  1. 令 exprValue 为 ? AssignmentExpression 的 Evaluation。
  2. 令 fromValue 为 ? GetValue(exprValue)。
  3. 令 excludedNames 为新的空 List。
  4. 执行 ? CopyDataProperties(obj, fromValue, excludedNames)。
  5. 返回 unused。
PropertyDefinition : IdentifierReference
  1. 令 propertyName 为 IdentifierReference 的 StringValue。
  2. 令 exprValue 为 ? IdentifierReference 的 Evaluation。
  3. 令 propertyValue 为 ? GetValue(exprValue)。
  4. 断言:obj 是没有不可配置属性的普通、可扩展对象。
  5. 执行 ! CreateDataPropertyOrThrow(obj, propertyName, propertyValue)。
  6. 返回 unused。
PropertyDefinition : PropertyName : AssignmentExpression
  1. 令 propertyKey 为 ? PropertyName 的 Evaluation。
  2. 如果此 PropertyDefinition 包含在正为 ParseJSON 求值的 Script 中(参见 ParseJSON 的步骤 6),则
    1. 令 isProtoSetter 为 false。
  3. 否则,如果 propertyKey 是 "__proto__" 且 PropertyName 的 IsComputedPropertyKey 是 false,则
    1. 令 isProtoSetter 为 true。
  4. 否则,
    1. 令 isProtoSetter 为 false。
  5. 如果 IsAnonymousFunctionDefinition(AssignmentExpression) 是 true 且 isProtoSetter 是 false,则
    1. 令 propertyValue 为 ? 以 propertyKey 为参数对 AssignmentExpression 执行 NamedEvaluation 的结果。
  6. 否则,
    1. 令 exprValueRef 为 ? AssignmentExpression 的 Evaluation。
    2. 令 propertyValue 为 ? GetValue(exprValueRef)。
  7. 如果 isProtoSetter 是 true,则
    1. 如果 propertyValue 是 Object 或 propertyValue 是 null,则
      1. 执行 ! obj.[[SetPrototypeOf]](propertyValue)。
    2. 返回 unused。
  8. 断言:obj 是没有不可配置属性的普通、可扩展对象。
  9. 执行 ! CreateDataPropertyOrThrow(obj, propertyKey, propertyValue)。
  10. 返回 unused。
PropertyDefinition : MethodDefinition
  1. 令 result 为 ? 以 obj 和 true 为参数对 MethodDefinition 执行 MethodDefinitionEvaluation 的结果。
  2. 断言:result 是 empty。
  3. 返回 unused。

13.2.6 函数定义表达式

有关 PrimaryExpression : FunctionExpression ,参见 15.2。

有关 PrimaryExpression : GeneratorExpression ,参见 15.5。

有关 PrimaryExpression : ClassExpression ,参见 15.7。

有关 PrimaryExpression : AsyncFunctionExpression ,参见 15.8。

有关 PrimaryExpression : AsyncGeneratorExpression ,参见 15.6。

13.2.7 正则表达式字面量

语法

参见 12.9.5。

13.2.7.1 Static Semantics: 提前错误

PrimaryExpression : RegularExpressionLiteral

13.2.7.2 Static Semantics: IsValidRegularExpressionLiteral ( literal )

抽象操作 IsValidRegularExpressionLiteral,接收参数 literal (a RegularExpressionLiteral Parse Node);返回值:Boolean。 它确定其参数是否为有效的正则表达式字面量。 调用时执行以下步骤:

  1. 令 flags 为 literal 的 FlagText。
  2. 如果 flags 包含 d、g、i、m、s、u、v 或 y 之外的任何码点,则返回 false。
  3. 如果 flags 中任何码点出现超过一次,则返回 false。
  4. 如果 flags 包含 u,则令 u 为 true;否则令 u 为 false。
  5. 如果 flags 包含 v,则令 v 为 true;否则令 v 为 false。
  6. 令 patternText 为 literal 的 BodyText。
  7. 如果 u 是 false 且 v 是 false,则
    1. 令 stringValue 为 CodePointsToString(patternText)。
    2. 将 patternText 设置为这样得到的码点序列:把 stringValue 的每个 16 位元素解释为一个 Unicode BMP 码点。不会对这些元素应用 UTF-16 解码。
  8. 令 parseResult 为 ParsePattern(patternText, u, v)。
  9. 如果 parseResult 是 Parse Node,则返回 true。
  10. 返回 false。

13.2.7.3 Runtime Semantics: Evaluation

PrimaryExpression : RegularExpressionLiteral
  1. 令 pattern 为 CodePointsToString(RegularExpressionLiteral 的 BodyText)。
  2. 令 flags 为 CodePointsToString(RegularExpressionLiteral 的 FlagText)。
  3. 返回 ! RegExpCreate(pattern, flags)。

13.2.8 模板字面量

语法

TemplateLiteral[Yield, Await, Tagged] : NoSubstitutionTemplate SubstitutionTemplate[?Yield, ?Await] SubstitutionTemplate[Yield, Await] : TemplateHead Expression[+In, ?Yield, ?Await] TemplateSpans[?Yield, ?Await] TemplateSpans[Yield, Await] : TemplateTail TemplateMiddleList[?Yield, ?Await] TemplateTail TemplateMiddleList[Yield, Await] : TemplateMiddle Expression[+In, ?Yield, ?Await] TemplateMiddleList[?Yield, ?Await] TemplateMiddle Expression[+In, ?Yield, ?Await]

13.2.8.1 Static Semantics: 提前错误

TemplateLiteral[Yield, Await, Tagged] : NoSubstitutionTemplate TemplateLiteral[Yield, Await, Tagged] : SubstitutionTemplate[?Yield, ?Await]

13.2.8.2 Static Semantics: TemplateStrings

语法制导操作 TemplateStrings,接收参数 escapes ((raw 或 cooked));返回值:列表 (元素:(String 或 undefined))。 它按以下产生式分别定义:

TemplateLiteral : NoSubstitutionTemplate
  1. 返回 « TemplateString(NoSubstitutionTemplate, escapes) »。
SubstitutionTemplate : TemplateHead Expression TemplateSpans
  1. 令 head 为 « TemplateString(TemplateHead, escapes) »。
  2. 令 tail 为以 escapes 为参数对 TemplateSpans 执行 TemplateStrings 的结果。
  3. 返回 head 和 tail 的列表连接。
TemplateSpans : TemplateTail
  1. 返回 « TemplateString(TemplateTail, escapes) »。
TemplateSpans : TemplateMiddleList TemplateTail
  1. 令 middle 为以 escapes 为参数对 TemplateMiddleList 执行 TemplateStrings 的结果。
  2. 令 tail 为 « TemplateString(TemplateTail, escapes) »。
  3. 返回 middle 和 tail 的列表连接。
TemplateMiddleList : TemplateMiddle Expression
  1. 返回 « TemplateString(TemplateMiddle, escapes) »。
TemplateMiddleList : TemplateMiddleList TemplateMiddle Expression
  1. 令 front 为以 escapes 为参数对 TemplateMiddleList 执行 TemplateStrings 的结果。
  2. 令 last 为 « TemplateString(TemplateMiddle, escapes) »。
  3. 返回 front 和 last 的列表连接。

13.2.8.3 Static Semantics: TemplateString ( templateToken, escapes )

抽象操作 TemplateString,接收参数 templateToken ((a NoSubstitutionTemplate Parse Node、a TemplateHead Parse Node、a TemplateMiddle Parse Node 或 a TemplateTail Parse Node)) 和 escapes ((raw 或 cooked));返回值:(String 或 undefined)。 调用时执行以下步骤:

  1. 如果 escapes 是 raw,则返回 templateToken 的 TRV。
  2. 返回 templateToken 的 TV。
注

如果 escapes 是 raw 且 templateToken 包含 NotEscapeSequence,此操作返回 undefined。在所有其他情况下,它返回 String。

13.2.8.4 GetTemplateObject ( templateLiteral )

抽象操作 GetTemplateObject,接收参数 templateLiteral (解析节点);返回值:Array。 调用时执行以下步骤:

  1. 令 realm 为当前 Realm Record。
  2. 令 templateRegistry 为 realm.[[TemplateMap]]。
  3. 对 templateRegistry 的每个元素 element,执行
    1. 如果 element.[[Site]] 与 templateLiteral 是同一个 Parse Node,则
      1. 返回 element.[[Array]]。
  4. 令 rawStrings 为以 raw 为参数对 templateLiteral 执行 TemplateStrings 的结果。
  5. 断言:rawStrings 是 String 的 List。
  6. 令 cookedStrings 为以 cooked 为参数对 templateLiteral 执行 TemplateStrings 的结果。
  7. 令 count 为 List cookedStrings 中的元素数量。
  8. 断言:count ≤ 232 - 1。
  9. 令 template 为 ! ArrayCreate(count)。
  10. 令 rawObj 为 ! ArrayCreate(count)。
  11. 令 index 为 0。
  12. 当 index < count 时,重复执行,
    1. 令 propertyKey 为 ! ToString(𝔽(index))。
    2. 令 cookedValue 为 cookedStrings[index]。
    3. 执行 ! DefinePropertyOrThrow(template, propertyKey, PropertyDescriptor { [[Value]]: cookedValue, [[Writable]]: false, [[Enumerable]]: true, [[Configurable]]: false })。
    4. 令 rawValue 为 String 值 rawStrings[index]。
    5. 执行 ! DefinePropertyOrThrow(rawObj, propertyKey, PropertyDescriptor { [[Value]]: rawValue, [[Writable]]: false, [[Enumerable]]: true, [[Configurable]]: false })。
    6. 将 index 设置为 index + 1。
  13. 执行 ! SetIntegrityLevel(rawObj, frozen)。
  14. 执行 ! DefinePropertyOrThrow(template, "raw", PropertyDescriptor { [[Value]]: rawObj, [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false })。
  15. 执行 ! SetIntegrityLevel(template, frozen)。
  16. 将 Record { [[Site]]: templateLiteral, [[Array]]: template } 追加到 realm.[[TemplateMap]]。
  17. 返回 template。
注 1

创建模板对象不会产生突然完成。

注 2

Realm 的程序代码中的每个 TemplateLiteral 都与一个唯一模板对象相关联,该模板对象用于带标签 Template 的求值(13.2.8.6)。模板对象是冻结的,并且每次对特定带标签 Template 求值时都会使用同一个模板对象。模板对象是在首次对 TemplateLiteral 求值时惰性创建,还是在首次求值之前急切创建,是实现选择,ECMAScript 代码无法观察到这种选择。

注 3

本规范未来的版本可能会定义模板对象的其他不可枚举属性。

13.2.8.5 Runtime Semantics: SubstitutionEvaluation

语法制导操作 SubstitutionEvaluation,接收无参数;返回值:(正常完成 (值:列表 (元素:ECMAScript 语言值)) 或 突兀完成)。 它按以下产生式分别定义:

TemplateSpans : TemplateTail
  1. 返回新的空 List。
TemplateSpans : TemplateMiddleList TemplateTail
  1. 返回 ? TemplateMiddleList 的 SubstitutionEvaluation。
TemplateMiddleList : TemplateMiddle Expression
  1. 令 subRef 为 ? Expression 的 Evaluation。
  2. 令 sub 为 ? GetValue(subRef)。
  3. 返回 « sub »。
TemplateMiddleList : TemplateMiddleList TemplateMiddle Expression
  1. 令 preceding 为 ? TemplateMiddleList 的 SubstitutionEvaluation。
  2. 令 nextRef 为 ? Expression 的 Evaluation。
  3. 令 next 为 ? GetValue(nextRef)。
  4. 返回 preceding 与 « next » 的列表连接。

13.2.8.6 Runtime Semantics: Evaluation

TemplateLiteral : NoSubstitutionTemplate
  1. 返回 12.9.6 中定义的 NoSubstitutionTemplate 的 TV。
SubstitutionTemplate : TemplateHead Expression TemplateSpans
  1. 令 head 为 12.9.6 中定义的 TemplateHead 的 TV。
  2. 令 subRef 为 ? Expression 的 Evaluation。
  3. 令 sub 为 ? GetValue(subRef)。
  4. 令 middle 为 ? ToString(sub)。
  5. 令 tail 为 ? TemplateSpans 的 Evaluation。
  6. 返回 head、middle 和 tail 的字符串连接。
注 1

应用于 Expression 值的字符串转换语义类似于 String.prototype.concat,而不是 + 运算符。

TemplateSpans : TemplateTail
  1. 返回 12.9.6 中定义的 TemplateTail 的 TV。
TemplateSpans : TemplateMiddleList TemplateTail
  1. 令 head 为 ? TemplateMiddleList 的 Evaluation。
  2. 令 tail 为 12.9.6 中定义的 TemplateTail 的 TV。
  3. 返回 head 和 tail 的字符串连接。
TemplateMiddleList : TemplateMiddle Expression
  1. 令 head 为 12.9.6 中定义的 TemplateMiddle 的 TV。
  2. 令 subRef 为 ? Expression 的 Evaluation。
  3. 令 sub 为 ? GetValue(subRef)。
  4. 令 middle 为 ? ToString(sub)。
  5. 返回 head 和 middle 的字符串连接。
注 2

应用于 Expression 值的字符串转换语义类似于 String.prototype.concat,而不是 + 运算符。

TemplateMiddleList : TemplateMiddleList TemplateMiddle Expression
  1. 令 rest 为 ? TemplateMiddleList 的 Evaluation。
  2. 令 middle 为 12.9.6 中定义的 TemplateMiddle 的 TV。
  3. 令 subRef 为 ? Expression 的 Evaluation。
  4. 令 sub 为 ? GetValue(subRef)。
  5. 令 last 为 ? ToString(sub)。
  6. 返回 rest、middle 和 last 的字符串连接。
注 3

应用于 Expression 值的字符串转换语义类似于 String.prototype.concat,而不是 + 运算符。

13.2.9 分组运算符

13.2.9.1 Static Semantics: 提前错误

PrimaryExpression : CoverParenthesizedExpressionAndArrowParameterList

13.2.9.2 Runtime Semantics: Evaluation

PrimaryExpression : CoverParenthesizedExpressionAndArrowParameterList
  1. 令 expr 为 CoverParenthesizedExpressionAndArrowParameterList 所覆盖的 ParenthesizedExpression。
  2. 返回 ? expr 的 Evaluation。
ParenthesizedExpression : ( Expression )
  1. 返回 ? Expression 的 Evaluation。其类型可能为 Reference。
注

此算法不会对 Expression 的 Evaluation 应用 GetValue。这样做的主要原因是允许将 delete 和 typeof 等运算符应用于括号表达式。

13.3 左值表达式

语法

MemberExpression[Yield, Await] : PrimaryExpression[?Yield, ?Await] MemberExpression[?Yield, ?Await] [ Expression[+In, ?Yield, ?Await] ] MemberExpression[?Yield, ?Await] . IdentifierName MemberExpression[?Yield, ?Await] TemplateLiteral[?Yield, ?Await, +Tagged] SuperProperty[?Yield, ?Await] MetaProperty new MemberExpression[?Yield, ?Await] Arguments[?Yield, ?Await] MemberExpression[?Yield, ?Await] . PrivateIdentifier SuperProperty[Yield, Await] : super [ Expression[+In, ?Yield, ?Await] ] super . IdentifierName MetaProperty : NewTarget ImportMeta NewTarget : new . target ImportMeta : import . meta NewExpression[Yield, Await] : MemberExpression[?Yield, ?Await] new NewExpression[?Yield, ?Await] CallExpression[Yield, Await] : CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await] SuperCall[?Yield, ?Await] ImportCall[?Yield, ?Await] CallExpression[?Yield, ?Await] Arguments[?Yield, ?Await] CallExpression[?Yield, ?Await] [ Expression[+In, ?Yield, ?Await] ] CallExpression[?Yield, ?Await] . IdentifierName CallExpression[?Yield, ?Await] TemplateLiteral[?Yield, ?Await, +Tagged] CallExpression[?Yield, ?Await] . PrivateIdentifier SuperCall[Yield, Await] : super Arguments[?Yield, ?Await] ImportCall[Yield, Await] : import ( AssignmentExpression[+In, ?Yield, ?Await] ,opt ) import ( AssignmentExpression[+In, ?Yield, ?Await] , AssignmentExpression[+In, ?Yield, ?Await] ,opt ) Arguments[Yield, Await] : ( ) ( ArgumentList[?Yield, ?Await] ,opt ) ArgumentList[Yield, Await] : AssignmentExpression[+In, ?Yield, ?Await] ... AssignmentExpression[+In, ?Yield, ?Await] ArgumentList[?Yield, ?Await] , AssignmentExpression[+In, ?Yield, ?Await] ArgumentList[?Yield, ?Await] , ... AssignmentExpression[+In, ?Yield, ?Await] OptionalExpression[Yield, Await] : MemberExpression[?Yield, ?Await] OptionalChain[?Yield, ?Await] CallExpression[?Yield, ?Await] OptionalChain[?Yield, ?Await] OptionalExpression[?Yield, ?Await] OptionalChain[?Yield, ?Await] OptionalChain[Yield, Await] : ?. Arguments[?Yield, ?Await] ?. [ Expression[+In, ?Yield, ?Await] ] ?. IdentifierName ?. TemplateLiteral[?Yield, ?Await, +Tagged] ?. PrivateIdentifier OptionalChain[?Yield, ?Await] Arguments[?Yield, ?Await] OptionalChain[?Yield, ?Await] [ Expression[+In, ?Yield, ?Await] ] OptionalChain[?Yield, ?Await] . IdentifierName OptionalChain[?Yield, ?Await] TemplateLiteral[?Yield, ?Await, +Tagged] OptionalChain[?Yield, ?Await] . PrivateIdentifier LeftHandSideExpression[Yield, Await] : NewExpression[?Yield, ?Await] CallExpression[?Yield, ?Await] OptionalExpression[?Yield, ?Await]

补充语法

当处理产生式
CallExpression : CoverCallExpressionAndAsyncArrowHead
的实例时,使用以下文法进一步细化对 CoverCallExpressionAndAsyncArrowHead 的解释:

CallMemberExpression[Yield, Await] : MemberExpression[?Yield, ?Await] Arguments[?Yield, ?Await]

13.3.1 静态语义

13.3.1.1 Static Semantics: 提前错误

OptionalChain : ?. TemplateLiteral OptionalChain TemplateLiteral
  • 如果有任何源文本被此产生式匹配,则为语法错误。
注

此产生式的存在是为了防止自动分号插入规则(12.10)应用于以下代码:

a?.b
`c`

从而使其被解释为两个有效语句。其目的是与没有可选链的类似代码保持一致:

a.b
`c`

后者是有效语句,并且不会应用自动分号插入。

ImportMeta : import . meta

13.3.2 属性访问器

注

属性按名称访问,可以使用点表示法:

或者使用方括号表示法:

点表示法可以通过以下句法转换来解释:

其行为等同于

MemberExpression [ <identifier-name-string> ]

类似地

其行为等同于

CallExpression [ <identifier-name-string> ]

其中 <identifier-name-string> 是 IdentifierName 的 StringValue。

13.3.2.1 Runtime Semantics: Evaluation

MemberExpression : MemberExpression [ Expression ]
  1. 令 baseRef 为 ? MemberExpression 的 Evaluation。
  2. 令 baseValue 为 ? GetValue(baseRef)。
  3. 令 strict 为 IsStrict(this MemberExpression)。
  4. 返回 ? EvaluatePropertyAccessWithExpressionKey(baseValue, Expression, strict)。
MemberExpression : MemberExpression . IdentifierName
  1. 令 baseRef 为 ? MemberExpression 的 Evaluation。
  2. 令 baseValue 为 ? GetValue(baseRef)。
  3. 令 strict 为 IsStrict(this MemberExpression)。
  4. 返回 EvaluatePropertyAccessWithIdentifierKey(baseValue, IdentifierName, strict)。
MemberExpression : MemberExpression . PrivateIdentifier
  1. 令 baseRef 为 ? MemberExpression 的 Evaluation。
  2. 令 baseValue 为 ? GetValue(baseRef)。
  3. 令 fieldNameString 为 PrivateIdentifier 的 StringValue。
  4. 返回 MakePrivateReference(baseValue, fieldNameString)。
CallExpression : CallExpression [ Expression ]
  1. 令 baseRef 为 ? CallExpression 的 Evaluation。
  2. 令 baseValue 为 ? GetValue(baseRef)。
  3. 令 strict 为 IsStrict(this CallExpression)。
  4. 返回 ? EvaluatePropertyAccessWithExpressionKey(baseValue, Expression, strict)。
CallExpression : CallExpression . IdentifierName
  1. 令 baseRef 为 ? CallExpression 的 Evaluation。
  2. 令 baseValue 为 ? GetValue(baseRef)。
  3. 令 strict 为 IsStrict(this CallExpression)。
  4. 返回 EvaluatePropertyAccessWithIdentifierKey(baseValue, IdentifierName, strict)。
CallExpression : CallExpression . PrivateIdentifier
  1. 令 baseRef 为 ? CallExpression 的 Evaluation。
  2. 令 baseValue 为 ? GetValue(baseRef)。
  3. 令 fieldNameString 为 PrivateIdentifier 的 StringValue。
  4. 返回 MakePrivateReference(baseValue, fieldNameString)。

13.3.3 EvaluatePropertyAccessWithExpressionKey ( baseValue, expr, strict )

抽象操作 EvaluatePropertyAccessWithExpressionKey,接收参数 baseValue (ECMAScript 语言值)、expr (an Expression Parse Node) 和 strict (Boolean);返回值:(正常完成 (值:Reference 记录) 或 突兀完成)。 调用时执行以下步骤:

  1. 令 propertyNameRef 为 ? expr 的 Evaluation。
  2. 令 propertyNameValue 为 ? GetValue(propertyNameRef)。
  3. 注:在大多数情况下,此步骤之后会立即对 propertyNameValue 执行 ToPropertyKey。但是,对于 a[b] = c,直到对 c 求值之后才会执行。
  4. 返回 Reference Record { [[Base]]: baseValue, [[ReferencedName]]: propertyNameValue, [[Strict]]: strict, [[ThisValue]]: empty }。

13.3.4 EvaluatePropertyAccessWithIdentifierKey ( baseValue, identifierName, strict )

抽象操作 EvaluatePropertyAccessWithIdentifierKey,接收参数 baseValue (ECMAScript 语言值)、identifierName (an IdentifierName Parse Node) 和 strict (Boolean);返回值:Reference 记录。 调用时执行以下步骤:

  1. 令 propertyNameString 为 identifierName 的 StringValue。
  2. 返回 Reference Record { [[Base]]: baseValue, [[ReferencedName]]: propertyNameString, [[Strict]]: strict, [[ThisValue]]: empty }。

13.3.5 new 运算符

13.3.5.1 Runtime Semantics: Evaluation

NewExpression : new NewExpression
  1. 返回 ? EvaluateNew(NewExpression, empty)。
MemberExpression : new MemberExpression Arguments
  1. 返回 ? EvaluateNew(MemberExpression, Arguments)。

13.3.5.1.1 EvaluateNew ( constructExpr, argumentsNode )

抽象操作 EvaluateNew,接收参数 constructExpr ((a NewExpression Parse Node 或 a MemberExpression Parse Node)) 和 argumentsNode ((empty 或 an Arguments Parse Node));返回值:(正常完成 (值:Object) 或 突兀完成)。 调用时执行以下步骤:

  1. 令 ref 为 ? constructExpr 的 Evaluation。
  2. 令 ctor 为 ? GetValue(ref)。
  3. 如果 argumentsNode 是 empty,则
    1. 令 argList 为新的空 List。
  4. 否则,
    1. 令 argList 为 ? argumentsNode 的 ArgumentListEvaluation。
  5. 如果 IsConstructor(ctor) 是 false,则抛出 TypeError 异常。
  6. 返回 ? Construct(ctor, argList)。

13.3.6 函数调用

13.3.6.1 Runtime Semantics: Evaluation

CallExpression : CoverCallExpressionAndAsyncArrowHead
  1. 令 expr 为 CoverCallExpressionAndAsyncArrowHead 所覆盖的 CallMemberExpression。
  2. 令 memberExpr 为 expr 的 MemberExpression。
  3. 令 args 为 expr 的 Arguments。
  4. 令 ref 为 ? memberExpr 的 Evaluation。
  5. 令 func 为 ? GetValue(ref)。
  6. 如果 ref 是 Reference Record、IsPropertyReference(ref) 是 false,且 ref.[[ReferencedName]] 是 "eval",则
    1. 如果 SameValue(func, %eval%) 是 true,则
      1. 令 argList 为 ? args 的 ArgumentListEvaluation。
      2. 如果 argList 没有元素,则返回 undefined。
      3. 令 evalArg 为 argList 的第一个元素。
      4. 如果 IsStrict(this CallExpression) 是 true,则令 strictCaller 为 true;否则令 strictCaller 为 false。
      5. 返回 ? PerformEval(evalArg, strictCaller, true)。
  7. 令 thisCall 为此 CallExpression。
  8. 令 tailCall 为 IsInTailPosition(thisCall)。
  9. 返回 ? EvaluateCall(func, ref, args, tailCall)。

执行步骤 6.a.v 的 CallExpression 求值称为直接 eval。

CallExpression : CallExpression Arguments
  1. 令 ref 为 ? CallExpression 的 Evaluation。
  2. 令 func 为 ? GetValue(ref)。
  3. 令 thisCall 为此 CallExpression。
  4. 令 tailCall 为 IsInTailPosition(thisCall)。
  5. 返回 ? EvaluateCall(func, ref, Arguments, tailCall)。

13.3.6.2 EvaluateCall ( func, thisValueRef, argumentListNode, tailPosition )

抽象操作 EvaluateCall,接收参数 func (ECMAScript 语言值)、thisValueRef ((ECMAScript 语言值 或 Reference 记录))、argumentListNode (解析节点) 和 tailPosition (Boolean);返回值:(正常完成 (值:ECMAScript 语言值) 或 突兀完成)。 调用时执行以下步骤:

  1. 如果 thisValueRef 是 Reference Record,则
    1. 如果 IsPropertyReference(thisValueRef) 是 true,则
      1. 令 thisValue 为 GetThisValue(thisValueRef)。
    2. 否则,
      1. 令 refEnv 为 thisValueRef.[[Base]]。
      2. 断言:refEnv 是 Environment Record。
      3. 令 thisValue 为 refEnv.WithBaseObject()。
  2. 否则,
    1. 令 thisValue 为 undefined。
  3. 令 argList 为 ? argumentListNode 的 ArgumentListEvaluation。
  4. 如果 func 不是 Object,则抛出 TypeError 异常。
  5. 如果 IsCallable(func) 是 false,则抛出 TypeError 异常。
  6. 如果 tailPosition 是 true,则执行 PrepareForTailCall()。
  7. 返回 ? Call(func, thisValue, argList)。

13.3.7 super 关键字

13.3.7.1 Runtime Semantics: Evaluation

SuperProperty : super [ Expression ]
  1. 令 envRecord 为 GetThisEnvironment()。
  2. 令 actualThis 为 ? envRecord.GetThisBinding()。
  3. 令 propertyNameRef 为 ? Expression 的 Evaluation。
  4. 令 propertyNameValue 为 ? GetValue(propertyNameRef)。
  5. 令 strict 为 IsStrict(this SuperProperty)。
  6. 注:在大多数情况下,此步骤之后会立即对 propertyNameValue 执行 ToPropertyKey。但是,对于 super[b] = c,直到对 c 求值之后才会执行。
  7. 返回 MakeSuperPropertyReference(actualThis, propertyNameValue, strict)。
SuperProperty : super . IdentifierName
  1. 令 envRecord 为 GetThisEnvironment()。
  2. 令 actualThis 为 ? envRecord.GetThisBinding()。
  3. 令 propertyKey 为 IdentifierName 的 StringValue。
  4. 令 strict 为 IsStrict(this SuperProperty)。
  5. 返回 MakeSuperPropertyReference(actualThis, propertyKey, strict)。
SuperCall : super Arguments
  1. 令 newTarget 为 GetNewTarget()。
  2. 断言:newTarget 是构造函数。
  3. 令 superCtor 为 GetSuperConstructor()。
  4. 令 argList 为 ? Arguments 的 ArgumentListEvaluation。
  5. 如果 IsConstructor(superCtor) 是 false,则抛出 TypeError 异常。
  6. 令 result 为 ? Construct(superCtor, argList, newTarget)。
  7. 令 thisER 为 GetThisEnvironment()。
  8. 断言:thisER 是 Function Environment Record。
  9. 执行 ? BindThisValue(thisER, result)。
  10. 令 funcObj 为 thisER.[[FunctionObject]]。
  11. 断言:funcObj 是 ECMAScript 函数对象。
  12. 执行 ? InitializeInstanceElements(result, funcObj)。
  13. 返回 result。

13.3.7.2 GetSuperConstructor ( )

抽象操作 GetSuperConstructor,接收无参数;返回值:(Object 或 null)。 调用时执行以下步骤:

  1. 令 envRecord 为 GetThisEnvironment()。
  2. 断言:envRecord 是 Function Environment Record。
  3. 令 activeFunc 为 envRecord.[[FunctionObject]]。
  4. 断言:activeFunc 是 ECMAScript 函数对象。
  5. 令 superCtor 为 ! activeFunc.[[GetPrototypeOf]]()。
  6. 返回 superCtor。

13.3.7.3 MakeSuperPropertyReference ( actualThis, propertyKey, strict )

抽象操作 MakeSuperPropertyReference,接收参数 actualThis (ECMAScript 语言值)、propertyKey (ECMAScript 语言值) 和 strict (Boolean);返回值:Super Reference 记录。 调用时执行以下步骤:

  1. 令 envRecord 为 GetThisEnvironment()。
  2. 断言:envRecord.HasSuperBinding() 是 true。
  3. 断言:envRecord 是 Function Environment Record。
  4. 令 baseValue 为 GetSuperBase(envRecord)。
  5. 返回 Reference Record { [[Base]]: baseValue, [[ReferencedName]]: propertyKey, [[Strict]]: strict, [[ThisValue]]: actualThis }。

13.3.8 参数列表

注

对参数列表求值会产生值的 List。

13.3.8.1 Runtime Semantics: ArgumentListEvaluation

语法制导操作 ArgumentListEvaluation,接收无参数;返回值:(正常完成 (值:列表 (元素:ECMAScript 语言值)) 或 突兀完成)。 它按以下产生式分别定义:

Arguments : ( )
  1. 返回新的空 List。
ArgumentList : AssignmentExpression
  1. 令 ref 为 ? AssignmentExpression 的 Evaluation。
  2. 令 arg 为 ? GetValue(ref)。
  3. 返回 « arg »。
ArgumentList : ... AssignmentExpression
  1. 令 list 为新的空 List。
  2. 令 spreadRef 为 ? AssignmentExpression 的 Evaluation。
  3. 令 spreadObj 为 ? GetValue(spreadRef)。
  4. 令 iteratorRecord 为 ? GetIterator(spreadObj, sync)。
  5. 重复执行,
    1. 令 next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 next 是 done,则返回 list。
    3. 将 next 追加到 list。
ArgumentList : ArgumentList , AssignmentExpression
  1. 令 precedingArgs 为 ? ArgumentList 的 ArgumentListEvaluation。
  2. 令 ref 为 ? AssignmentExpression 的 Evaluation。
  3. 令 arg 为 ? GetValue(ref)。
  4. 返回 precedingArgs 与 « arg » 的列表连接。
ArgumentList : ArgumentList , ... AssignmentExpression
  1. 令 precedingArgs 为 ? ArgumentList 的 ArgumentListEvaluation。
  2. 令 spreadRef 为 ? AssignmentExpression 的 Evaluation。
  3. 令 iteratorRecord 为 ? GetIterator(? GetValue(spreadRef), sync)。
  4. 重复执行,
    1. 令 next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 next 是 done,则返回 precedingArgs。
    3. 将 next 追加到 precedingArgs。
TemplateLiteral : NoSubstitutionTemplate
  1. 令 templateLiteral 为此 TemplateLiteral。
  2. 令 siteObj 为 GetTemplateObject(templateLiteral)。
  3. 返回 « siteObj »。
TemplateLiteral : SubstitutionTemplate
  1. 令 templateLiteral 为此 TemplateLiteral。
  2. 令 siteObj 为 GetTemplateObject(templateLiteral)。
  3. 令 remaining 为 ? SubstitutionTemplate 的 ArgumentListEvaluation。
  4. 返回 « siteObj » 和 remaining 的列表连接。
SubstitutionTemplate : TemplateHead Expression TemplateSpans
  1. 令 firstSubRef 为 ? Expression 的 Evaluation。
  2. 令 firstSub 为 ? GetValue(firstSubRef)。
  3. 令 restSub 为 ? TemplateSpans 的 SubstitutionEvaluation。
  4. 断言:restSub 是可能为空的 List。
  5. 返回 « firstSub » 和 restSub 的列表连接。

13.3.9 可选链

注
可选链是一个或多个属性访问和函数调用组成的链,其中第一个以标记 ?. 开始。

13.3.9.1 Runtime Semantics: Evaluation

OptionalExpression : MemberExpression OptionalChain
  1. 令 baseRef 为 ? MemberExpression 的 Evaluation。
  2. 令 baseValue 为 ? GetValue(baseRef)。
  3. 如果 baseValue 是 undefined 或 null,则
    1. 返回 undefined。
  4. 返回 ? 以 baseValue 和 baseRef 为参数对 OptionalChain 执行 ChainEvaluation 的结果。
OptionalExpression : CallExpression OptionalChain
  1. 令 baseRef 为 ? CallExpression 的 Evaluation。
  2. 令 baseValue 为 ? GetValue(baseRef)。
  3. 如果 baseValue 是 undefined 或 null,则
    1. 返回 undefined。
  4. 返回 ? 以 baseValue 和 baseRef 为参数对 OptionalChain 执行 ChainEvaluation 的结果。
OptionalExpression : OptionalExpression OptionalChain
  1. 令 baseRef 为 ? OptionalExpression 的 Evaluation。
  2. 令 baseValue 为 ? GetValue(baseRef)。
  3. 如果 baseValue 是 undefined 或 null,则
    1. 返回 undefined。
  4. 返回 ? 以 baseValue 和 baseRef 为参数对 OptionalChain 执行 ChainEvaluation 的结果。

13.3.9.2 Runtime Semantics: ChainEvaluation

语法制导操作 ChainEvaluation,接收参数 baseValue (ECMAScript 语言值) 和 baseRef ((ECMAScript 语言值 或 Reference 记录));返回值:(正常完成 (值:(ECMAScript 语言值 或 Reference 记录)) 或 突兀完成)。 它按以下产生式分别定义:

OptionalChain : ?. Arguments
  1. 令 thisChain 为此 OptionalChain。
  2. 令 tailCall 为 IsInTailPosition(thisChain)。
  3. 返回 ? EvaluateCall(baseValue, baseRef, Arguments, tailCall)。
OptionalChain : ?. [ Expression ]
  1. 令 strict 为 IsStrict(this OptionalChain)。
  2. 返回 ? EvaluatePropertyAccessWithExpressionKey(baseValue, Expression, strict)。
OptionalChain : ?. IdentifierName
  1. 令 strict 为 IsStrict(this OptionalChain)。
  2. 返回 EvaluatePropertyAccessWithIdentifierKey(baseValue, IdentifierName, strict)。
OptionalChain : ?. PrivateIdentifier
  1. 令 fieldNameString 为 PrivateIdentifier 的 StringValue。
  2. 返回 MakePrivateReference(baseValue, fieldNameString)。
OptionalChain : OptionalChain Arguments
  1. 令 optionalChain 为 OptionalChain。
  2. 令 newRef 为 ? 以 baseValue 和 baseRef 为参数对 optionalChain 执行 ChainEvaluation 的结果。
  3. 令 newValue 为 ? GetValue(newRef)。
  4. 令 thisChain 为此 OptionalChain。
  5. 令 tailCall 为 IsInTailPosition(thisChain)。
  6. 返回 ? EvaluateCall(newValue, newRef, Arguments, tailCall)。
OptionalChain : OptionalChain [ Expression ]
  1. 令 optionalChain 为 OptionalChain。
  2. 令 newRef 为 ? 以 baseValue 和 baseRef 为参数对 optionalChain 执行 ChainEvaluation 的结果。
  3. 令 newValue 为 ? GetValue(newRef)。
  4. 令 strict 为 IsStrict(this OptionalChain)。
  5. 返回 ? EvaluatePropertyAccessWithExpressionKey(newValue, Expression, strict)。
OptionalChain : OptionalChain . IdentifierName
  1. 令 optionalChain 为 OptionalChain。
  2. 令 newRef 为 ? 以 baseValue 和 baseRef 为参数对 optionalChain 执行 ChainEvaluation 的结果。
  3. 令 newValue 为 ? GetValue(newRef)。
  4. 令 strict 为 IsStrict(this OptionalChain)。
  5. 返回 EvaluatePropertyAccessWithIdentifierKey(newValue, IdentifierName, strict)。
OptionalChain : OptionalChain . PrivateIdentifier
  1. 令 optionalChain 为 OptionalChain。
  2. 令 newRef 为 ? 以 baseValue 和 baseRef 为参数对 optionalChain 执行 ChainEvaluation 的结果。
  3. 令 newValue 为 ? GetValue(newRef)。
  4. 令 fieldNameString 为 PrivateIdentifier 的 StringValue。
  5. 返回 MakePrivateReference(newValue, fieldNameString)。

13.3.10 Import 调用

13.3.10.1 Runtime Semantics: Evaluation

ImportCall : import ( AssignmentExpression ,opt )
  1. 返回 ? EvaluateImportCall(AssignmentExpression)。
ImportCall : import ( AssignmentExpression , AssignmentExpression ,opt )
  1. 返回 ? EvaluateImportCall(第一个 AssignmentExpression, 第二个 AssignmentExpression)。

13.3.10.2 EvaluateImportCall ( specifierExpr [ , optionsExpr ] )

抽象操作 EvaluateImportCall,接收参数 specifierExpr (解析节点)和可选参数 optionsExpr (解析节点);返回值:(正常完成 (值:Promise) 或 突兀完成)。 调用时执行以下步骤:

  1. 令 referrer 为 GetActiveScriptOrModule()。
  2. 如果 referrer 是 null,则将 referrer 设置为当前 Realm Record。
  3. 令 specifierRef 为 ? specifierExpr 的 Evaluation。
  4. 令 specifier 为 ? GetValue(specifierRef)。
  5. 如果存在 optionsExpr,则
    1. 令 optionsRef 为 ? optionsExpr 的 Evaluation。
    2. 令 options 为 ? GetValue(optionsRef)。
  6. 否则,
    1. 令 options 为 undefined。
  7. 令 promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  8. 令 specifierString 为 Completion(ToString(specifier))。
  9. IfAbruptRejectPromise(specifierString, promiseCapability)。
  10. 令 attrs 为新的空 List。
  11. 如果 options 不是 undefined,则
    1. 如果 options 不是 Object,则
      1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « 新创建的 TypeError 对象 »)。
      2. 返回 promiseCapability.[[Promise]]。
    2. 令 attrsObj 为 Completion(Get(options, "with"))
    3. IfAbruptRejectPromise(attrsObj, promiseCapability)。
    4. 如果 attrsObj 不是 undefined,则
      1. 如果 attrsObj 不是 Object,则
        1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « 新创建的 TypeError 对象 »)。
        2. 返回 promiseCapability.[[Promise]]。
      2. 令 entries 为 Completion(EnumerableOwnProperties(attrsObj, key+value))。
      3. IfAbruptRejectPromise(entries, promiseCapability)。
      4. 对 entries 的每个元素 entry,执行
        1. 令 key 为 ! Get(entry, "0")。
        2. 令 value 为 ! Get(entry, "1")。
        3. 如果 key 是 String,则
          1. 如果 value 不是 String,则
            1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « 新创建的 TypeError 对象 »)。
            2. 返回 promiseCapability.[[Promise]]。
          2. 将 ImportAttribute Record { [[Key]]: key, [[Value]]: value } 追加到 attrs。
    5. 如果 AllImportAttributesSupported(attrs) 是 false,则
      1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « 新创建的 TypeError 对象 »)。
      2. 返回 promiseCapability.[[Promise]]。
    6. 按 [[Key]] 字段的字典序对 attrs 排序,将每个此类字段的值视为 UTF-16 码元值序列。注:这种排序唯一可观察的方面,是禁止宿主根据属性枚举顺序改变行为。
  12. 令 moduleRequest 为新的 ModuleRequest Record { [[Specifier]]: specifierString, [[Attributes]]: attrs }。
  13. 执行 HostLoadImportedModule(referrer, moduleRequest, empty, promiseCapability)。
  14. 返回 promiseCapability.[[Promise]]。

13.3.10.3 ContinueDynamicImport ( promiseCapability, moduleCompletion )

抽象操作 ContinueDynamicImport,接收参数 promiseCapability (PromiseCapability 记录) 和 moduleCompletion ((正常完成 (值:Module 记录) 或 抛出完成));返回值:unused。 它完成最初由 import() 调用启动的动态导入过程,并根据情况兑现或拒绝该调用返回的 promise。 调用时执行以下步骤:

  1. 如果 moduleCompletion 是突然完成,则
    1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « moduleCompletion.[[Value]] »)。
    2. 返回 unused。
  2. 令 module 为 moduleCompletion.[[Value]]。
  3. 令 loadPromise 为 module.LoadRequestedModules()。
  4. 令 rejectedClosure 为具有参数 (reason) 的新 Abstract Closure,它捕获 promiseCapability,并在被调用时执行以下步骤:
    1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « reason »)。
    2. 返回 NormalCompletion(undefined)。
  5. 令 onRejected 为 CreateBuiltinFunction(rejectedClosure, 1, "", « »)。
  6. 令 linkAndEvaluateClosure 为一个没有参数的新 Abstract Closure,它捕获 module、promiseCapability 和 onRejected,并在被调用时执行以下步骤:
    1. 令 link 为 Completion(module.Link())。
    2. 如果 link 是突然完成,则
      1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « link.[[Value]] »)。
      2. 返回 NormalCompletion(undefined)。
    3. 令 evaluatePromise 为 module.Evaluate()。
    4. 令 fulfilledClosure 为一个没有参数的新 Abstract Closure,它捕获 module 和 promiseCapability,并在被调用时执行以下步骤:
      1. 令 namespace 为 GetModuleNamespace(module)。
      2. 执行 ! Call(promiseCapability.[[Resolve]], undefined, « namespace »)。
      3. 返回 NormalCompletion(undefined)。
    5. 令 onFulfilled 为 CreateBuiltinFunction(fulfilledClosure, 0, "", « »)。
    6. 执行 PerformPromiseThen(evaluatePromise, onFulfilled, onRejected)。
    7. 返回 unused。
  7. 令 linkAndEvaluate 为 CreateBuiltinFunction(linkAndEvaluateClosure, 0, "", « »)。
  8. 执行 PerformPromiseThen(loadPromise, linkAndEvaluate, onRejected)。
  9. 返回 unused。

13.3.11 带标签模板

注

带标签模板是一种函数调用,其调用参数派生自 TemplateLiteral(13.2.8)。实际参数包括模板对象(13.2.8.4)以及对嵌入 TemplateLiteral 中的表达式求值所产生的值。

13.3.11.1 Runtime Semantics: Evaluation

MemberExpression : MemberExpression TemplateLiteral
  1. 令 tagRef 为 ? MemberExpression 的 Evaluation。
  2. 令 tagFunc 为 ? GetValue(tagRef)。
  3. 令 thisCall 为此 MemberExpression。
  4. 令 tailCall 为 IsInTailPosition(thisCall)。
  5. 返回 ? EvaluateCall(tagFunc, tagRef, TemplateLiteral, tailCall)。
CallExpression : CallExpression TemplateLiteral
  1. 令 tagRef 为 ? CallExpression 的 Evaluation。
  2. 令 tagFunc 为 ? GetValue(tagRef)。
  3. 令 thisCall 为此 CallExpression。
  4. 令 tailCall 为 IsInTailPosition(thisCall)。
  5. 返回 ? EvaluateCall(tagFunc, tagRef, TemplateLiteral, tailCall)。

13.3.12 元属性

13.3.12.1 Runtime Semantics: Evaluation

NewTarget : new . target
  1. 返回 GetNewTarget()。
ImportMeta : import . meta
  1. 令 module 为 GetActiveScriptOrModule()。
  2. 断言:module 是 Source Text Module Record。
  3. 令 importMeta 为 module.[[ImportMeta]]。
  4. 如果 importMeta 是 empty,则
    1. 将 importMeta 设置为 OrdinaryObjectCreate(null)。
    2. 令 importMetaValues 为 HostGetImportMetaProperties(module)。
    3. 对 importMetaValues 的每个 Record { [[Key]], [[Value]] } entry,执行
      1. 执行 ! CreateDataPropertyOrThrow(importMeta, entry.[[Key]], entry.[[Value]])。
    4. 执行 HostFinalizeImportMeta(importMeta, module)。
    5. 将 module.[[ImportMeta]] 设置为 importMeta。
    6. 返回 importMeta。
  5. 断言:importMeta 是 Object。
  6. 返回 importMeta。

13.3.12.1.1 HostGetImportMetaProperties ( moduleRecord )

宿主定义的抽象操作 HostGetImportMetaProperties,接收参数 moduleRecord (Module 记录);返回值:列表 (元素:记录 (字段:[[Key]] (属性键), [[Value]] (ECMAScript 语言值)))。 它允许宿主为 import.meta 返回的对象提供属性键和值。

HostGetImportMetaProperties 的默认实现返回新的空 List。

13.3.12.1.2 HostFinalizeImportMeta ( importMeta, moduleRecord )

宿主定义的抽象操作 HostFinalizeImportMeta,接收参数 importMeta (Object) 和 moduleRecord (Module 记录);返回值:unused。 它允许宿主执行任何特殊操作,以准备 import.meta 返回的对象。

大多数宿主只需定义 HostGetImportMetaProperties,并让 HostFinalizeImportMeta 保持其默认行为即可。不过,HostFinalizeImportMeta 为需要在对象暴露给 ECMAScript 代码之前直接操作该对象的宿主提供了一个“逃生舱口”。

HostFinalizeImportMeta 的默认实现返回 unused。

13.4 更新表达式

语法

UpdateExpression[Yield, Await] : LeftHandSideExpression[?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] [no LineTerminator here] ++ LeftHandSideExpression[?Yield, ?Await] [no LineTerminator here] -- ++ UnaryExpression[?Yield, ?Await] -- UnaryExpression[?Yield, ?Await]

13.4.1 Static Semantics: 提前错误

UpdateExpression : LeftHandSideExpression ++ LeftHandSideExpression -- UpdateExpression : ++ UnaryExpression -- UnaryExpression

13.4.2 后缀递增运算符

13.4.2.1 Runtime Semantics: Evaluation

UpdateExpression : LeftHandSideExpression ++
  1. 令 lhs 为 ? LeftHandSideExpression 的 Evaluation。
  2. 如果 LeftHandSideExpression 的 AssignmentTargetType 是 web-compat,则抛出 ReferenceError 异常。
  3. 令 oldValue 为 ? ToNumeric(? GetValue(lhs))。
  4. 如果 oldValue 是 Number,则
    1. 令 newValue 为 Number::add(oldValue, 1𝔽)。
  5. 否则,
    1. 断言:oldValue 是 BigInt。
    2. 令 newValue 为 BigInt::add(oldValue, 1ℤ)。
  6. 执行 ? PutValue(lhs, newValue)。
  7. 返回 oldValue。

13.4.3 后缀递减运算符

13.4.3.1 Runtime Semantics: Evaluation

UpdateExpression : LeftHandSideExpression --
  1. 令 lhs 为 ? LeftHandSideExpression 的 Evaluation。
  2. 如果 LeftHandSideExpression 的 AssignmentTargetType 是 web-compat,则抛出 ReferenceError 异常。
  3. 令 oldValue 为 ? ToNumeric(? GetValue(lhs))。
  4. 如果 oldValue 是 Number,则
    1. 令 newValue 为 Number::subtract(oldValue, 1𝔽)。
  5. 否则,
    1. 断言:oldValue 是 BigInt。
    2. 令 newValue 为 BigInt::subtract(oldValue, 1ℤ)。
  6. 执行 ? PutValue(lhs, newValue)。
  7. 返回 oldValue。

13.4.4 前缀递增运算符

13.4.4.1 Runtime Semantics: Evaluation

UpdateExpression : ++ UnaryExpression
  1. 令 expr 为 ? UnaryExpression 的 Evaluation。
  2. 如果 UnaryExpression 的 AssignmentTargetType 是 web-compat,则抛出 ReferenceError 异常。
  3. 令 oldValue 为 ? ToNumeric(? GetValue(expr))。
  4. 如果 oldValue 是 Number,则
    1. 令 newValue 为 Number::add(oldValue, 1𝔽)。
  5. 否则,
    1. 断言:oldValue 是 BigInt。
    2. 令 newValue 为 BigInt::add(oldValue, 1ℤ)。
  6. 执行 ? PutValue(expr, newValue)。
  7. 返回 newValue。

13.4.5 前缀递减运算符

13.4.5.1 Runtime Semantics: Evaluation

UpdateExpression : -- UnaryExpression
  1. 令 expr 为 ? UnaryExpression 的 Evaluation。
  2. 如果 UnaryExpression 的 AssignmentTargetType 是 web-compat,则抛出 ReferenceError 异常。
  3. 令 oldValue 为 ? ToNumeric(? GetValue(expr))。
  4. 如果 oldValue 是 Number,则
    1. 令 newValue 为 Number::subtract(oldValue, 1𝔽)。
  5. 否则,
    1. 断言:oldValue 是 BigInt。
    2. 令 newValue 为 BigInt::subtract(oldValue, 1ℤ)。
  6. 执行 ? PutValue(expr, newValue)。
  7. 返回 newValue。

13.5 一元运算符

语法

UnaryExpression[Yield, Await] : UpdateExpression[?Yield, ?Await] delete UnaryExpression[?Yield, ?Await] void UnaryExpression[?Yield, ?Await] typeof UnaryExpression[?Yield, ?Await] + UnaryExpression[?Yield, ?Await] - UnaryExpression[?Yield, ?Await] ~ UnaryExpression[?Yield, ?Await] ! UnaryExpression[?Yield, ?Await] [+Await] CoverAwaitExpressionAndAwaitUsingDeclarationHead[?Yield] CoverAwaitExpressionAndAwaitUsingDeclarationHead[Yield] : await UnaryExpression[?Yield, +Await]

补充语法

当处理产生式
UnaryExpression : CoverAwaitExpressionAndAwaitUsingDeclarationHead
的实例时,使用以下文法进一步细化对 CoverAwaitExpressionAndAwaitUsingDeclarationHead 的解释:

AwaitExpression[Yield] : await UnaryExpression[?Yield, +Await]

13.5.1 delete 运算符

13.5.1.1 Static Semantics: 提前错误

UnaryExpression : delete UnaryExpression 注

最后一条规则意味着,诸如 delete (((foo))) 之类的表达式会由于递归应用第一条规则而产生提前错误。

13.5.1.2 Runtime Semantics: Evaluation

UnaryExpression : delete UnaryExpression
  1. 令 ref 为 ? UnaryExpression 的 Evaluation。
  2. 如果 ref 不是 Reference Record,则返回 true。
  3. 如果 IsUnresolvableReference(ref) 是 true,则
    1. 断言:ref.[[Strict]] 是 false。
    2. 返回 true。
  4. 如果 IsPropertyReference(ref) 是 true,则
    1. 断言:IsPrivateReference(ref) 是 false。
    2. 如果 IsSuperReference(ref) 是 true,则抛出 ReferenceError 异常。
    3. 令 baseObj 为 ? ToObject(ref.[[Base]])。
    4. 如果 ref.[[ReferencedName]] 不是属性键,则
      1. 将 ref.[[ReferencedName]] 设置为 ? ToPropertyKey(ref.[[ReferencedName]])。
    5. 令 deleteStatus 为 ? baseObj.[[Delete]](ref.[[ReferencedName]])。
    6. 如果 deleteStatus 是 false 且 ref.[[Strict]] 是 true,则抛出 TypeError 异常。
    7. 返回 deleteStatus。
  5. 令 base 为 ref.[[Base]]。
  6. 断言:base 是 Environment Record。
  7. 返回 ? base.DeleteBinding(ref.[[ReferencedName]])。
注 1

当 delete 运算符出现在严格模式代码中时,如果其 UnaryExpression 是对变量、函数参数或函数名称的直接引用,则抛出 SyntaxError 异常。此外,如果 delete 运算符出现在严格模式代码中,并且要删除的属性具有特性 { [[Configurable]]: false }(或因其他原因无法删除),则抛出 TypeError 异常。

注 2

在步骤 4.c 中可能创建的对象无法在上述抽象操作和普通对象 [[Delete]] 内部方法之外访问。实现可以选择避免实际创建该对象。

13.5.2 void 运算符

13.5.2.1 Runtime Semantics: Evaluation

UnaryExpression : void UnaryExpression
  1. 令 expr 为 ? UnaryExpression 的 Evaluation。
  2. 执行 ? GetValue(expr)。
  3. 返回 undefined。
注

即使不使用其值,也必须调用 GetValue,因为它可能具有可观察的副作用。

13.5.3 typeof 运算符

13.5.3.1 Runtime Semantics: Evaluation

UnaryExpression : typeof UnaryExpression
  1. 令 value 为 ? UnaryExpression 的 Evaluation。
  2. 如果 value 是 Reference Record,则
    1. 如果 IsUnresolvableReference(value) 是 true,则返回 "undefined"。
  3. 将 value 设置为 ? GetValue(value)。
  4. 如果 value 是 undefined,则返回 "undefined"。
  5. 如果 value 是 null,则返回 "object"。
  6. 如果 value 是 String,则返回 "string"。
  7. 如果 value 是 Symbol,则返回 "symbol"。
  8. 如果 value 是 Boolean,则返回 "boolean"。
  9. 如果 value 是 Number,则返回 "number"。
  10. 如果 value 是 BigInt,则返回 "bigint"。
  11. 断言:value 是 Object。
  12. Normative Optional
    如果宿主是 Web 浏览器或以其他方式支持 [[IsHTMLDDA]] 内部槽,则
    1. 如果 value 具有 [[IsHTMLDDA]] 内部槽,则返回 "undefined"。
  13. 如果 value 具有 [[Call]] 内部方法,则返回 "function"。
  14. 返回 "object"。

13.5.4 一元 + 运算符

注

一元 + 运算符将其操作数转换为 Number 类型。

13.5.4.1 Runtime Semantics: Evaluation

UnaryExpression : + UnaryExpression
  1. 令 expr 为 ? UnaryExpression 的 Evaluation。
  2. 返回 ? ToNumber(? GetValue(expr))。

13.5.5 一元 - 运算符

注

一元 - 运算符将其操作数转换为数值,然后对其取负。对 +0𝔽 取负会产生 -0𝔽,对 -0𝔽 取负会产生 +0𝔽。

13.5.5.1 Runtime Semantics: Evaluation

UnaryExpression : - UnaryExpression
  1. 令 expr 为 ? UnaryExpression 的 Evaluation。
  2. 令 oldValue 为 ? ToNumeric(? GetValue(expr))。
  3. 如果 oldValue 是 Number,则返回 Number::unaryMinus(oldValue)。
  4. 断言:oldValue 是 BigInt。
  5. 返回 BigInt::unaryMinus(oldValue)。

13.5.6 按位 NOT 运算符( ~ )

13.5.6.1 Runtime Semantics: Evaluation

UnaryExpression : ~ UnaryExpression
  1. 令 expr 为 ? UnaryExpression 的 Evaluation。
  2. 令 oldValue 为 ? ToNumeric(? GetValue(expr))。
  3. 如果 oldValue 是 Number,则返回 Number::bitwiseNOT(oldValue)。
  4. 断言:oldValue 是 BigInt。
  5. 返回 BigInt::bitwiseNOT(oldValue)。

13.5.7 逻辑 NOT 运算符( ! )

13.5.7.1 Runtime Semantics: Evaluation

UnaryExpression : ! UnaryExpression
  1. 令 expr 为 ? UnaryExpression 的 Evaluation。
  2. 令 oldValue 为 ToBoolean(? GetValue(expr))。
  3. 如果 oldValue 是 true,则返回 false。
  4. 返回 true。

13.6 指数运算符

语法

ExponentiationExpression[Yield, Await] : UnaryExpression[?Yield, ?Await] UpdateExpression[?Yield, ?Await] ** ExponentiationExpression[?Yield, ?Await]

13.6.1 Runtime Semantics: Evaluation

ExponentiationExpression : UpdateExpression ** ExponentiationExpression
  1. 返回 ? EvaluateStringOrNumericBinaryExpression(UpdateExpression, **, ExponentiationExpression)。

13.7 乘法运算符

语法

MultiplicativeExpression[Yield, Await] : ExponentiationExpression[?Yield, ?Await] MultiplicativeExpression[?Yield, ?Await] MultiplicativeOperator ExponentiationExpression[?Yield, ?Await] MultiplicativeOperator : one of * / % 注
  • * 运算符执行乘法,产生其操作数的乘积。
  • / 运算符执行除法,产生其操作数的商。
  • % 运算符产生其操作数进行隐含除法所得的余数。

13.7.1 Runtime Semantics: Evaluation

MultiplicativeExpression : MultiplicativeExpression MultiplicativeOperator ExponentiationExpression
  1. 令 opText 为 MultiplicativeOperator 匹配的源文本。
  2. 返回 ? EvaluateStringOrNumericBinaryExpression(MultiplicativeExpression, opText, ExponentiationExpression)。

13.8 加法运算符

语法

AdditiveExpression[Yield, Await] : MultiplicativeExpression[?Yield, ?Await] AdditiveExpression[?Yield, ?Await] + MultiplicativeExpression[?Yield, ?Await] AdditiveExpression[?Yield, ?Await] - MultiplicativeExpression[?Yield, ?Await]

13.8.1 加法运算符( + )

注

加法运算符执行字符串连接或数值加法。

13.8.1.1 Runtime Semantics: Evaluation

AdditiveExpression : AdditiveExpression + MultiplicativeExpression
  1. 返回 ? EvaluateStringOrNumericBinaryExpression(AdditiveExpression, +, MultiplicativeExpression)。

13.8.2 减法运算符( - )

注

- 运算符执行减法,产生其操作数之差。

13.8.2.1 Runtime Semantics: Evaluation

AdditiveExpression : AdditiveExpression - MultiplicativeExpression
  1. 返回 ? EvaluateStringOrNumericBinaryExpression(AdditiveExpression, -, MultiplicativeExpression)。

13.9 按位移位运算符

语法

ShiftExpression[Yield, Await] : AdditiveExpression[?Yield, ?Await] ShiftExpression[?Yield, ?Await] << AdditiveExpression[?Yield, ?Await] ShiftExpression[?Yield, ?Await] >> AdditiveExpression[?Yield, ?Await] ShiftExpression[?Yield, ?Await] >>> AdditiveExpression[?Yield, ?Await]

13.9.1 左移运算符( << )

注

对左操作数执行按位左移操作,移动量由右操作数指定。

13.9.1.1 Runtime Semantics: Evaluation

ShiftExpression : ShiftExpression << AdditiveExpression
  1. 返回 ? EvaluateStringOrNumericBinaryExpression(ShiftExpression, <<, AdditiveExpression)。

13.9.2 有符号右移运算符( >> )

注

对左操作数执行符号位填充的按位右移操作,移动量由右操作数指定。

13.9.2.1 Runtime Semantics: Evaluation

ShiftExpression : ShiftExpression >> AdditiveExpression
  1. 返回 ? EvaluateStringOrNumericBinaryExpression(ShiftExpression, >>, AdditiveExpression)。

13.9.3 无符号右移运算符( >>> )

注

对左操作数执行零填充的按位右移操作,移动量由右操作数指定。

13.9.3.1 Runtime Semantics: Evaluation

ShiftExpression : ShiftExpression >>> AdditiveExpression
  1. 返回 ? EvaluateStringOrNumericBinaryExpression(ShiftExpression, >>>, AdditiveExpression)。

13.10 关系运算符

注 1

对关系运算符求值的结果始终为 Boolean 类型,反映该运算符所表示的关系是否在两个操作数之间成立。

语法

RelationalExpression[In, Yield, Await] : ShiftExpression[?Yield, ?Await] RelationalExpression[?In, ?Yield, ?Await] < ShiftExpression[?Yield, ?Await] RelationalExpression[?In, ?Yield, ?Await] > ShiftExpression[?Yield, ?Await] RelationalExpression[?In, ?Yield, ?Await] <= ShiftExpression[?Yield, ?Await] RelationalExpression[?In, ?Yield, ?Await] >= ShiftExpression[?Yield, ?Await] RelationalExpression[?In, ?Yield, ?Await] instanceof ShiftExpression[?Yield, ?Await] [+In] RelationalExpression[+In, ?Yield, ?Await] in ShiftExpression[?Yield, ?Await] [+In] PrivateIdentifier in ShiftExpression[?Yield, ?Await] 注 2

需要 [In] 文法参数,以避免将关系表达式中的 in 运算符与 for 语句中的 in 运算符混淆。

13.10.1 Runtime Semantics: Evaluation

RelationalExpression : RelationalExpression < ShiftExpression
  1. 令 leftRef 为 ? RelationalExpression 的 Evaluation。
  2. 令 leftValue 为 ? GetValue(leftRef)。
  3. 令 rightRef 为 ? ShiftExpression 的 Evaluation。
  4. 令 rightValue 为 ? GetValue(rightRef)。
  5. 令 result 为 ? IsLessThan(leftValue, rightValue, true)。
  6. 如果 result 是 undefined,则返回 false。
  7. 返回 result。
RelationalExpression : RelationalExpression > ShiftExpression
  1. 令 leftRef 为 ? RelationalExpression 的 Evaluation。
  2. 令 leftValue 为 ? GetValue(leftRef)。
  3. 令 rightRef 为 ? ShiftExpression 的 Evaluation。
  4. 令 rightValue 为 ? GetValue(rightRef)。
  5. 令 result 为 ? IsLessThan(rightValue, leftValue, false)。
  6. 如果 result 是 undefined,则返回 false。
  7. 返回 result。
RelationalExpression : RelationalExpression <= ShiftExpression
  1. 令 leftRef 为 ? RelationalExpression 的 Evaluation。
  2. 令 leftValue 为 ? GetValue(leftRef)。
  3. 令 rightRef 为 ? ShiftExpression 的 Evaluation。
  4. 令 rightValue 为 ? GetValue(rightRef)。
  5. 令 result 为 ? IsLessThan(rightValue, leftValue, false)。
  6. 如果 result 是 true 或 undefined,则返回 false。
  7. 返回 true。
RelationalExpression : RelationalExpression >= ShiftExpression
  1. 令 leftRef 为 ? RelationalExpression 的 Evaluation。
  2. 令 leftValue 为 ? GetValue(leftRef)。
  3. 令 rightRef 为 ? ShiftExpression 的 Evaluation。
  4. 令 rightValue 为 ? GetValue(rightRef)。
  5. 令 result 为 ? IsLessThan(leftValue, rightValue, true)。
  6. 如果 result 是 true 或 undefined,则返回 false。
  7. 返回 true。
RelationalExpression : RelationalExpression instanceof ShiftExpression
  1. 令 leftRef 为 ? RelationalExpression 的 Evaluation。
  2. 令 leftValue 为 ? GetValue(leftRef)。
  3. 令 rightRef 为 ? ShiftExpression 的 Evaluation。
  4. 令 rightValue 为 ? GetValue(rightRef)。
  5. 返回 ? InstanceofOperator(leftValue, rightValue)。
RelationalExpression : RelationalExpression in ShiftExpression
  1. 令 leftRef 为 ? RelationalExpression 的 Evaluation。
  2. 令 leftValue 为 ? GetValue(leftRef)。
  3. 令 rightRef 为 ? ShiftExpression 的 Evaluation。
  4. 令 rightValue 为 ? GetValue(rightRef)。
  5. 如果 rightValue 不是 Object,则抛出 TypeError 异常。
  6. 返回 ? HasProperty(rightValue, ? ToPropertyKey(leftValue))。
RelationalExpression : PrivateIdentifier in ShiftExpression
  1. 令 privateIdentifier 为 PrivateIdentifier 的 StringValue。
  2. 令 rightRef 为 ? ShiftExpression 的 Evaluation。
  3. 令 rightValue 为 ? GetValue(rightRef)。
  4. 如果 rightValue 不是 Object,则抛出 TypeError 异常。
  5. 令 privateEnv 为正在运行的执行上下文的 PrivateEnvironment。
  6. 断言:privateEnv 不是 null。
  7. 令 privateName 为 ResolvePrivateIdentifier(privateEnv, privateIdentifier)。
  8. 如果 PrivateElementFind(rightValue, privateName) 是 empty,则返回 false。
  9. 返回 true。

13.10.2 InstanceofOperator ( value, target )

抽象操作 InstanceofOperator,接收参数 value (ECMAScript 语言值) 和 target (ECMAScript 语言值);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 它实现用于确定 value 是否为 target 实例的通用算法:首先查询 target 的 %Symbol.hasInstance% 方法;如果该方法不存在,则确定 target 的 "prototype" 属性值是否存在于 value 的原型链中。 调用时执行以下步骤:

  1. 如果 target 不是 Object,则抛出 TypeError 异常。
  2. 令 instOfHandler 为 ? GetMethod(target, %Symbol.hasInstance%)。
  3. 如果 instOfHandler 不是 undefined,则
    1. 返回 ToBoolean(? Call(instOfHandler, target, « value »))。
  4. 如果 IsCallable(target) 是 false,则抛出 TypeError 异常。
  5. 返回 ? OrdinaryHasInstance(target, value)。
注

步骤 4 和 5 提供了与先前 ECMAScript 版本的兼容性,这些版本没有使用 %Symbol.hasInstance% 方法定义 instanceof 运算符语义。如果对象既未定义也未继承 %Symbol.hasInstance%,则使用默认的 instanceof 语义。

13.11 相等运算符

注

对相等运算符求值的结果始终为 Boolean 类型,反映该运算符所表示的关系是否在两个操作数之间成立。

语法

EqualityExpression[In, Yield, Await] : RelationalExpression[?In, ?Yield, ?Await] EqualityExpression[?In, ?Yield, ?Await] == RelationalExpression[?In, ?Yield, ?Await] EqualityExpression[?In, ?Yield, ?Await] != RelationalExpression[?In, ?Yield, ?Await] EqualityExpression[?In, ?Yield, ?Await] === RelationalExpression[?In, ?Yield, ?Await] EqualityExpression[?In, ?Yield, ?Await] !== RelationalExpression[?In, ?Yield, ?Await]

13.11.1 Runtime Semantics: Evaluation

EqualityExpression : EqualityExpression == RelationalExpression
  1. 令 leftRef 为 ? EqualityExpression 的 Evaluation。
  2. 令 leftValue 为 ? GetValue(leftRef)。
  3. 令 rightRef 为 ? RelationalExpression 的 Evaluation。
  4. 令 rightValue 为 ? GetValue(rightRef)。
  5. 返回 ? IsLooselyEqual(rightValue, leftValue)。
EqualityExpression : EqualityExpression != RelationalExpression
  1. 令 leftRef 为 ? EqualityExpression 的 Evaluation。
  2. 令 leftValue 为 ? GetValue(leftRef)。
  3. 令 rightRef 为 ? RelationalExpression 的 Evaluation。
  4. 令 rightValue 为 ? GetValue(rightRef)。
  5. 令 result 为 ? IsLooselyEqual(rightValue, leftValue)。
  6. 如果 result 是 true,则返回 false。
  7. 返回 true。
EqualityExpression : EqualityExpression === RelationalExpression
  1. 令 leftRef 为 ? EqualityExpression 的 Evaluation。
  2. 令 leftValue 为 ? GetValue(leftRef)。
  3. 令 rightRef 为 ? RelationalExpression 的 Evaluation。
  4. 令 rightValue 为 ? GetValue(rightRef)。
  5. 返回 IsStrictlyEqual(rightValue, leftValue)。
EqualityExpression : EqualityExpression !== RelationalExpression
  1. 令 leftRef 为 ? EqualityExpression 的 Evaluation。
  2. 令 leftValue 为 ? GetValue(leftRef)。
  3. 令 rightRef 为 ? RelationalExpression 的 Evaluation。
  4. 令 rightValue 为 ? GetValue(rightRef)。
  5. 令 result 为 IsStrictlyEqual(rightValue, leftValue)。
  6. 如果 result 是 true,则返回 false。
  7. 返回 true。
注 1

相等运算符维持以下不变量:

  • A != B 等价于 !(A == B)。
  • 除 A 和 B 的求值顺序外,A == B 等价于 B == A。
注 2

相等运算符并不总是具有传递性。例如,可能存在两个不同的 String 对象,每个都表示相同的 String 值;通过 == 运算符,每个 String 对象都被视为等于该 String 值,但这两个 String 对象彼此并不相等。例如:

  • new String("a") == "a" 和 "a" == new String("a") 都是 true。
  • new String("a") == new String("a") 是 false。
注 3

String 的比较对码元值序列使用简单相等测试。不会尝试使用 Unicode 规范中定义的更复杂、面向语义的字符或字符串相等性及排序顺序定义。因此,根据 Unicode 标准规范等价的 String 值可能会比较为不相等。实际上,此算法假定两个 String 都已经处于规范化形式。

13.12 二元按位运算符

语法

BitwiseANDExpression[In, Yield, Await] : EqualityExpression[?In, ?Yield, ?Await] BitwiseANDExpression[?In, ?Yield, ?Await] & EqualityExpression[?In, ?Yield, ?Await] BitwiseXORExpression[In, Yield, Await] : BitwiseANDExpression[?In, ?Yield, ?Await] BitwiseXORExpression[?In, ?Yield, ?Await] ^ BitwiseANDExpression[?In, ?Yield, ?Await] BitwiseORExpression[In, Yield, Await] : BitwiseXORExpression[?In, ?Yield, ?Await] BitwiseORExpression[?In, ?Yield, ?Await] | BitwiseXORExpression[?In, ?Yield, ?Await]

13.12.1 Runtime Semantics: Evaluation

BitwiseANDExpression : BitwiseANDExpression & EqualityExpression
  1. 返回 ? EvaluateStringOrNumericBinaryExpression(BitwiseANDExpression, &, EqualityExpression)。
BitwiseXORExpression : BitwiseXORExpression ^ BitwiseANDExpression
  1. 返回 ? EvaluateStringOrNumericBinaryExpression(BitwiseXORExpression, ^, BitwiseANDExpression)。
BitwiseORExpression : BitwiseORExpression | BitwiseXORExpression
  1. 返回 ? EvaluateStringOrNumericBinaryExpression(BitwiseORExpression, |, BitwiseXORExpression)。

13.13 二元逻辑运算符

语法

LogicalANDExpression[In, Yield, Await] : BitwiseORExpression[?In, ?Yield, ?Await] LogicalANDExpression[?In, ?Yield, ?Await] && BitwiseORExpression[?In, ?Yield, ?Await] LogicalORExpression[In, Yield, Await] : LogicalANDExpression[?In, ?Yield, ?Await] LogicalORExpression[?In, ?Yield, ?Await] || LogicalANDExpression[?In, ?Yield, ?Await] CoalesceExpression[In, Yield, Await] : CoalesceExpressionHead[?In, ?Yield, ?Await] ?? BitwiseORExpression[?In, ?Yield, ?Await] CoalesceExpressionHead[In, Yield, Await] : CoalesceExpression[?In, ?Yield, ?Await] BitwiseORExpression[?In, ?Yield, ?Await] ShortCircuitExpression[In, Yield, Await] : LogicalORExpression[?In, ?Yield, ?Await] CoalesceExpression[?In, ?Yield, ?Await] 注

&& 或 || 运算符产生的值不一定是 Boolean 类型。产生的值始终是两个操作数表达式之一的值。

13.13.1 Runtime Semantics: Evaluation

LogicalANDExpression : LogicalANDExpression && BitwiseORExpression
  1. 令 leftRef 为 ? LogicalANDExpression 的 Evaluation。
  2. 令 leftValue 为 ? GetValue(leftRef)。
  3. 如果 ToBoolean(leftValue) 是 false,则返回 leftValue。
  4. 令 rightRef 为 ? BitwiseORExpression 的 Evaluation。
  5. 返回 ? GetValue(rightRef)。
LogicalORExpression : LogicalORExpression || LogicalANDExpression
  1. 令 leftRef 为 ? LogicalORExpression 的 Evaluation。
  2. 令 leftValue 为 ? GetValue(leftRef)。
  3. 如果 ToBoolean(leftValue) 是 true,则返回 leftValue。
  4. 令 rightRef 为 ? LogicalANDExpression 的 Evaluation。
  5. 返回 ? GetValue(rightRef)。
CoalesceExpression : CoalesceExpressionHead ?? BitwiseORExpression
  1. 令 leftRef 为 ? CoalesceExpressionHead 的 Evaluation。
  2. 令 leftValue 为 ? GetValue(leftRef)。
  3. 如果 leftValue 既不是 undefined 也不是 null,则返回 leftValue。
  4. 令 rightRef 为 ? BitwiseORExpression 的 Evaluation。
  5. 返回 ? GetValue(rightRef)。

13.14 条件运算符( ? : )

语法

ConditionalExpression[In, Yield, Await] : ShortCircuitExpression[?In, ?Yield, ?Await] ShortCircuitExpression[?In, ?Yield, ?Await] ? AssignmentExpression[+In, ?Yield, ?Await] : AssignmentExpression[?In, ?Yield, ?Await] 注

ECMAScript 中 ConditionalExpression 的文法与 C 和 Java 中的文法略有不同,后两者都允许第二个子表达式为 Expression,但限制第三个表达式必须为 ConditionalExpression。ECMAScript 中采用这种差异,是为了允许条件表达式的任一分支支配赋值表达式,并消除将逗号表达式作为中间表达式这种令人困惑且几乎无用的情况。

13.14.1 Runtime Semantics: Evaluation

ConditionalExpression : ShortCircuitExpression ? AssignmentExpression : AssignmentExpression
  1. 令 leftRef 为 ? ShortCircuitExpression 的 Evaluation。
  2. 令 leftValue 为 ToBoolean(? GetValue(leftRef))。
  3. 如果 leftValue 是 true,则
    1. 令 trueRef 为 ? 第一个 AssignmentExpression 的 Evaluation。
    2. 返回 ? GetValue(trueRef)。
  4. 令 falseRef 为 ? 第二个 AssignmentExpression 的 Evaluation。
  5. 返回 ? GetValue(falseRef)。

13.15 赋值运算符

语法

AssignmentExpression[In, Yield, Await] : ConditionalExpression[?In, ?Yield, ?Await] [+Yield] YieldExpression[?In, ?Await] ArrowFunction[?In, ?Yield, ?Await] AsyncArrowFunction[?In, ?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] = AssignmentExpression[?In, ?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] AssignmentOperator AssignmentExpression[?In, ?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] &&= AssignmentExpression[?In, ?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] ||= AssignmentExpression[?In, ?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] ??= AssignmentExpression[?In, ?Yield, ?Await] AssignmentOperator : one of *= /= %= += -= <<= >>= >>>= &= ^= |= **=

13.15.1 Static Semantics: 提前错误

AssignmentExpression : LeftHandSideExpression = AssignmentExpression AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression AssignmentExpression : LeftHandSideExpression &&= AssignmentExpression LeftHandSideExpression ||= AssignmentExpression LeftHandSideExpression ??= AssignmentExpression

13.15.2 Runtime Semantics: Evaluation

AssignmentExpression : LeftHandSideExpression = AssignmentExpression
  1. 如果 LeftHandSideExpression 既不是 ObjectLiteral 也不是 ArrayLiteral,则
    1. 令 leftRef 为 ? LeftHandSideExpression 的 Evaluation。
    2. 如果 LeftHandSideExpression 的 AssignmentTargetType 是 web-compat,则抛出 ReferenceError 异常。
    3. 如果 IsAnonymousFunctionDefinition(AssignmentExpression) 是 true 且 LeftHandSideExpression 的 IsIdentifierRef 是 true,则
      1. 令 lhs 为 LeftHandSideExpression 的 StringValue。
      2. 令 rightValue 为 ? 以 lhs 为参数对 AssignmentExpression 执行 NamedEvaluation 的结果。
    4. 否则,
      1. 令 rightRef 为 ? AssignmentExpression 的 Evaluation。
      2. 令 rightValue 为 ? GetValue(rightRef)。
    5. 执行 ? PutValue(leftRef, rightValue)。
    6. 返回 rightValue。
  2. 令 assignmentPattern 为 LeftHandSideExpression 所覆盖的 AssignmentPattern。
  3. 令 rightRef 为 ? AssignmentExpression 的 Evaluation。
  4. 令 rightValue 为 ? GetValue(rightRef)。
  5. 执行 ? 以 rightValue 为参数对 assignmentPattern 执行 DestructuringAssignmentEvaluation。
  6. 返回 rightValue。
AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression
  1. 令 leftRef 为 ? LeftHandSideExpression 的 Evaluation。
  2. 如果 LeftHandSideExpression 的 AssignmentTargetType 是 web-compat,则抛出 ReferenceError 异常。
  3. 令 leftValue 为 ? GetValue(leftRef)。
  4. 令 rightRef 为 ? AssignmentExpression 的 Evaluation。
  5. 令 rightValue 为 ? GetValue(rightRef)。
  6. 令 assignmentOpText 为 AssignmentOperator 匹配的源文本。
  7. 令 opText 为下表中与 assignmentOpText 关联的 Unicode 码点序列:
    assignmentOpText opText
    **= **
    *= *
    /= /
    %= %
    += +
    -= -
    <<= <<
    >>= >>
    >>>= >>>
    &= &
    ^= ^
    |= |
  8. 令 result 为 ? ApplyStringOrNumericBinaryOperator(leftValue, opText, rightValue)。
  9. 执行 ? PutValue(leftRef, result)。
  10. 返回 result。
AssignmentExpression : LeftHandSideExpression &&= AssignmentExpression
  1. 令 leftRef 为 ? LeftHandSideExpression 的 Evaluation。
  2. 令 leftValue 为 ? GetValue(leftRef)。
  3. 如果 ToBoolean(leftValue) 是 false,则返回 leftValue。
  4. 如果 IsAnonymousFunctionDefinition(AssignmentExpression) 是 true 且 LeftHandSideExpression 的 IsIdentifierRef 是 true,则
    1. 令 lhs 为 LeftHandSideExpression 的 StringValue。
    2. 令 rightValue 为 ? 以 lhs 为参数对 AssignmentExpression 执行 NamedEvaluation 的结果。
  5. 否则,
    1. 令 rightRef 为 ? AssignmentExpression 的 Evaluation。
    2. 令 rightValue 为 ? GetValue(rightRef)。
  6. 执行 ? PutValue(leftRef, rightValue)。
  7. 返回 rightValue。
AssignmentExpression : LeftHandSideExpression ||= AssignmentExpression
  1. 令 leftRef 为 ? LeftHandSideExpression 的 Evaluation。
  2. 令 leftValue 为 ? GetValue(leftRef)。
  3. 如果 ToBoolean(leftValue) 是 true,则返回 leftValue。
  4. 如果 IsAnonymousFunctionDefinition(AssignmentExpression) 是 true 且 LeftHandSideExpression 的 IsIdentifierRef 是 true,则
    1. 令 lhs 为 LeftHandSideExpression 的 StringValue。
    2. 令 rightValue 为 ? 以 lhs 为参数对 AssignmentExpression 执行 NamedEvaluation 的结果。
  5. 否则,
    1. 令 rightRef 为 ? AssignmentExpression 的 Evaluation。
    2. 令 rightValue 为 ? GetValue(rightRef)。
  6. 执行 ? PutValue(leftRef, rightValue)。
  7. 返回 rightValue。
AssignmentExpression : LeftHandSideExpression ??= AssignmentExpression
  1. 令 leftRef 为 ? LeftHandSideExpression 的 Evaluation。
  2. 令 leftValue 为 ? GetValue(leftRef)。
  3. 如果 leftValue 既不是 undefined 也不是 null,则返回 leftValue。
  4. 如果 IsAnonymousFunctionDefinition(AssignmentExpression) 是 true 且 LeftHandSideExpression 的 IsIdentifierRef 是 true,则
    1. 令 lhs 为 LeftHandSideExpression 的 StringValue。
    2. 令 rightValue 为 ? 以 lhs 为参数对 AssignmentExpression 执行 NamedEvaluation 的结果。
  5. 否则,
    1. 令 rightRef 为 ? AssignmentExpression 的 Evaluation。
    2. 令 rightValue 为 ? GetValue(rightRef)。
  6. 执行 ? PutValue(leftRef, rightValue)。
  7. 返回 rightValue。
注

当此表达式出现在严格模式代码中时,如果步骤 1.e、3、2、2、2 中的 leftRef 是不可解析引用,则为运行时错误。在这种情况下会抛出 ReferenceError 异常。此外,如果步骤 9、6、6、6 中的 leftRef 是对特性值为 { [[Writable]]: false } 的数据属性、特性值为 { [[Setter]]: undefined } 的访问器属性,或 IsExtensible 谓词返回 false 的对象上不存在属性的引用,则同样为运行时错误。在这些情况下会抛出 TypeError 异常。

13.15.3 ApplyStringOrNumericBinaryOperator ( leftValue, opText, rightValue )

抽象操作 ApplyStringOrNumericBinaryOperator,接收参数 leftValue (ECMAScript 语言值)、opText ((**、*、/、%、+、-、<<、>>、>>>、&、^ 或 |)) 和 rightValue (ECMAScript 语言值);返回值:(正常完成 (值:(String、BigInt 或 Number)) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 opText 是 +,则
    1. 令 leftPrimitive 为 ? ToPrimitive(leftValue)。
    2. 令 rightPrimitive 为 ? ToPrimitive(rightValue)。
    3. 如果 leftPrimitive 是 String 或 rightPrimitive 是 String,则
      1. 令 leftString 为 ? ToString(leftPrimitive)。
      2. 令 rightString 为 ? ToString(rightPrimitive)。
      3. 返回 leftString 和 rightString 的字符串连接。
    4. 将 leftValue 设置为 leftPrimitive。
    5. 将 rightValue 设置为 rightPrimitive。
  2. 注:此时它必须是数值运算。
  3. 令 leftNumber 为 ? ToNumeric(leftValue)。
  4. 令 rightNumber 为 ? ToNumeric(rightValue)。
  5. 如果 SameType(leftNumber, rightNumber) 是 false,则抛出 TypeError 异常。
  6. 如果 leftNumber 是 BigInt,则
    1. 如果 opText 是 **,则返回 ? BigInt::exponentiate(leftNumber, rightNumber)。
    2. 如果 opText 是 /,则返回 ? BigInt::divide(leftNumber, rightNumber)。
    3. 如果 opText 是 %,则返回 ? BigInt::remainder(leftNumber, rightNumber)。
    4. 如果 opText 是 >>>,则返回 ? BigInt::unsignedRightShift(leftNumber, rightNumber)。
    5. 令 operation 为下表中与 opText 关联的抽象操作:
      opText operation
      * BigInt::multiply
      + BigInt::add
      - BigInt::subtract
      << BigInt::leftShift
      >> BigInt::signedRightShift
      & BigInt::bitwiseAND
      ^ BigInt::bitwiseXOR
      | BigInt::bitwiseOR
  7. 否则,
    1. 断言:leftNumber 是 Number。
    2. 令 operation 为下表中与 opText 关联的抽象操作:
      opText operation
      ** Number::exponentiate
      * Number::multiply
      / Number::divide
      % Number::remainder
      + Number::add
      - Number::subtract
      << Number::leftShift
      >> Number::signedRightShift
      >>> Number::unsignedRightShift
      & Number::bitwiseAND
      ^ Number::bitwiseXOR
      | Number::bitwiseOR
  8. 返回 operation(leftNumber, rightNumber)。
注 1

在步骤 1.a 和 1.b 中调用 ToPrimitive 时未提供 hint。除 Date 外,所有标准对象都会像提供了 number 一样处理缺失的 hint;Date 则像提供了 string 一样处理缺失的 hint。异质对象可以以其他方式处理缺失的 hint。

注 2

步骤 1.c 与 IsLessThan 算法的步骤 3 不同,它使用逻辑或操作而不是逻辑与操作。

13.15.4 EvaluateStringOrNumericBinaryExpression ( leftOperand, opText, rightOperand )

抽象操作 EvaluateStringOrNumericBinaryExpression,接收参数 leftOperand (解析节点)、opText ((**、*、/、%、+、-、<<、>>、>>>、&、^ 或 |)) 和 rightOperand (解析节点);返回值:(正常完成 (值:(String、BigInt 或 Number)) 或 突兀完成)。 调用时执行以下步骤:

  1. 令 leftRef 为 ? leftOperand 的 Evaluation。
  2. 令 leftValue 为 ? GetValue(leftRef)。
  3. 令 rightRef 为 ? rightOperand 的 Evaluation。
  4. 令 rightValue 为 ? GetValue(rightRef)。
  5. 返回 ? ApplyStringOrNumericBinaryOperator(leftValue, opText, rightValue)。

13.15.5 解构赋值

补充语法

在某些情况下,当处理产生式
AssignmentExpression : LeftHandSideExpression = AssignmentExpression
的实例时,使用以下文法进一步细化对 LeftHandSideExpression 的解释:

AssignmentPattern[Yield, Await] : ObjectAssignmentPattern[?Yield, ?Await] ArrayAssignmentPattern[?Yield, ?Await] ObjectAssignmentPattern[Yield, Await] : { } { AssignmentRestProperty[?Yield, ?Await] } { AssignmentPropertyList[?Yield, ?Await] ,opt } { AssignmentPropertyList[?Yield, ?Await] , AssignmentRestProperty[?Yield, ?Await] } ArrayAssignmentPattern[Yield, Await] : [ Elisionopt AssignmentRestElement[?Yield, ?Await]opt ] [ AssignmentElementList[?Yield, ?Await] ] [ AssignmentElementList[?Yield, ?Await] , Elisionopt AssignmentRestElement[?Yield, ?Await]opt ] AssignmentRestProperty[Yield, Await] : ... DestructuringAssignmentTarget[?Yield, ?Await] AssignmentPropertyList[Yield, Await] : AssignmentProperty[?Yield, ?Await] AssignmentPropertyList[?Yield, ?Await] , AssignmentProperty[?Yield, ?Await] AssignmentElementList[Yield, Await] : AssignmentElisionElement[?Yield, ?Await] AssignmentElementList[?Yield, ?Await] , AssignmentElisionElement[?Yield, ?Await] AssignmentElisionElement[Yield, Await] : Elisionopt AssignmentElement[?Yield, ?Await] AssignmentProperty[Yield, Await] : IdentifierReference[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]opt PropertyName[?Yield, ?Await] : AssignmentElement[?Yield, ?Await] AssignmentElement[Yield, Await] : DestructuringAssignmentTarget[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]opt AssignmentRestElement[Yield, Await] : ... DestructuringAssignmentTarget[?Yield, ?Await] DestructuringAssignmentTarget[Yield, Await] : LeftHandSideExpression[?Yield, ?Await]

13.15.5.1 Static Semantics: 提前错误

AssignmentProperty : IdentifierReference Initializeropt AssignmentRestProperty : ... DestructuringAssignmentTarget DestructuringAssignmentTarget : LeftHandSideExpression

13.15.5.2 Runtime Semantics: DestructuringAssignmentEvaluation

语法制导操作 DestructuringAssignmentEvaluation,接收参数 value (ECMAScript 语言值);返回值:(正常完成 (值:unused) 或 突兀完成)。 它按以下产生式分别定义:

ObjectAssignmentPattern : { }
  1. 执行 ? RequireObjectCoercible(value)。
  2. 返回 unused。
ObjectAssignmentPattern : { AssignmentPropertyList ,opt }
  1. 执行 ? RequireObjectCoercible(value)。
  2. 执行 ? 以 value 为参数对 AssignmentPropertyList 执行 PropertyDestructuringAssignmentEvaluation。
  3. 返回 unused。
ObjectAssignmentPattern : { AssignmentRestProperty }
  1. 执行 ? RequireObjectCoercible(value)。
  2. 令 excludedNames 为新的空 List。
  3. 返回 ? 以 value 和 excludedNames 为参数对 AssignmentRestProperty 执行 RestDestructuringAssignmentEvaluation 的结果。
ObjectAssignmentPattern : { AssignmentPropertyList , AssignmentRestProperty }
  1. 执行 ? RequireObjectCoercible(value)。
  2. 令 excludedNames 为 ? 以 value 为参数对 AssignmentPropertyList 执行 PropertyDestructuringAssignmentEvaluation 的结果。
  3. 返回 ? 以 value 和 excludedNames 为参数对 AssignmentRestProperty 执行 RestDestructuringAssignmentEvaluation 的结果。
ArrayAssignmentPattern : [ ]
  1. 令 iteratorRecord 为 ? GetIterator(value, sync)。
  2. 返回 ? IteratorClose(iteratorRecord, NormalCompletion(unused))。
ArrayAssignmentPattern : [ Elision ]
  1. 令 iteratorRecord 为 ? GetIterator(value, sync)。
  2. 令 result 为 Completion(以 iteratorRecord 为参数对 Elision 执行 IteratorDestructuringAssignmentEvaluation 的结果)。
  3. 如果 iteratorRecord.[[Done]] 是 false,则返回 ? IteratorClose(iteratorRecord, result)。
  4. 返回 result。
ArrayAssignmentPattern : [ Elisionopt AssignmentRestElement ]
  1. 令 iteratorRecord 为 ? GetIterator(value, sync)。
  2. 如果存在 Elision,则
    1. 令 status 为 Completion(以 iteratorRecord 为参数对 Elision 执行 IteratorDestructuringAssignmentEvaluation 的结果)。
    2. 如果 status 是突然完成,则
      1. 断言:iteratorRecord.[[Done]] 是 true。
      2. 返回 ? status。
  3. 令 result 为 Completion(以 iteratorRecord 为参数对 AssignmentRestElement 执行 IteratorDestructuringAssignmentEvaluation 的结果)。
  4. 如果 iteratorRecord.[[Done]] 是 false,则返回 ? IteratorClose(iteratorRecord, result)。
  5. 返回 result。
ArrayAssignmentPattern : [ AssignmentElementList ]
  1. 令 iteratorRecord 为 ? GetIterator(value, sync)。
  2. 令 result 为 Completion(以 iteratorRecord 为参数对 AssignmentElementList 执行 IteratorDestructuringAssignmentEvaluation 的结果)。
  3. 如果 iteratorRecord.[[Done]] 是 false,则返回 ? IteratorClose(iteratorRecord, result)。
  4. 返回 result。
ArrayAssignmentPattern : [ AssignmentElementList , Elisionopt AssignmentRestElementopt ]
  1. 令 iteratorRecord 为 ? GetIterator(value, sync)。
  2. 令 status 为 Completion(以 iteratorRecord 为参数对 AssignmentElementList 执行 IteratorDestructuringAssignmentEvaluation 的结果)。
  3. 如果 status 是突然完成,则
    1. 如果 iteratorRecord.[[Done]] 是 false,则返回 ? IteratorClose(iteratorRecord, status)。
    2. 返回 ? status。
  4. 如果存在 Elision,则
    1. 将 status 设置为 Completion(以 iteratorRecord 为参数对 Elision 执行 IteratorDestructuringAssignmentEvaluation 的结果)。
    2. 如果 status 是突然完成,则
      1. 断言:iteratorRecord.[[Done]] 是 true。
      2. 返回 ? status。
  5. 如果存在 AssignmentRestElement,则
    1. 将 status 设置为 Completion(以 iteratorRecord 为参数对 AssignmentRestElement 执行 IteratorDestructuringAssignmentEvaluation 的结果)。
  6. 如果 iteratorRecord.[[Done]] 是 false,则返回 ? IteratorClose(iteratorRecord, status)。
  7. 返回 ? status。

13.15.5.3 Runtime Semantics: PropertyDestructuringAssignmentEvaluation

语法制导操作 PropertyDestructuringAssignmentEvaluation,接收参数 value (ECMAScript 语言值);返回值:(正常完成 (值:列表 (元素:属性键)) 或 突兀完成)。 它收集所有被解构属性键的列表。 它按以下产生式分别定义:

AssignmentPropertyList : AssignmentPropertyList , AssignmentProperty
  1. 令 propertyNames 为 ? 以 value 为参数对 AssignmentPropertyList 执行 PropertyDestructuringAssignmentEvaluation 的结果。
  2. 令 nextNames 为 ? 以 value 为参数对 AssignmentProperty 执行 PropertyDestructuringAssignmentEvaluation 的结果。
  3. 返回 propertyNames 和 nextNames 的列表连接。
AssignmentProperty : IdentifierReference Initializeropt
  1. 令 propertyName 为 IdentifierReference 的 StringValue。
  2. 令 leftRef 为 ? ResolveBinding(propertyName)。
  3. 将 value 设置为 ? GetV(value, propertyName)。
  4. 如果存在 Initializer 且 value 是 undefined,则
    1. 如果 IsAnonymousFunctionDefinition(Initializer) 是 true,则
      1. 将 value 设置为 ? 以 propertyName 为参数对 Initializer 执行 NamedEvaluation 的结果。
    2. 否则,
      1. 令 defaultValue 为 ? Initializer 的 Evaluation。
      2. 将 value 设置为 ? GetValue(defaultValue)。
  5. 执行 ? PutValue(leftRef, value)。
  6. 返回 « propertyName »。
AssignmentProperty : PropertyName : AssignmentElement
  1. 令 name 为 ? PropertyName 的 Evaluation。
  2. 执行 ? 以 value 和 name 为参数对 AssignmentElement 执行 KeyedDestructuringAssignmentEvaluation。
  3. 返回 « name »。

13.15.5.4 Runtime Semantics: RestDestructuringAssignmentEvaluation

语法制导操作 RestDestructuringAssignmentEvaluation,接收参数 value (ECMAScript 语言值) 和 excludedNames (列表 (元素:属性键));返回值:(正常完成 (值:unused) 或 突兀完成)。 它按以下产生式分别定义:

AssignmentRestProperty : ... DestructuringAssignmentTarget
  1. 令 leftRef 为 ? DestructuringAssignmentTarget 的 Evaluation。
  2. 令 restObj 为 OrdinaryObjectCreate(%Object.prototype%)。
  3. 执行 ? CopyDataProperties(restObj, value, excludedNames)。
  4. 返回 ? PutValue(leftRef, restObj)。

13.15.5.5 Runtime Semantics: IteratorDestructuringAssignmentEvaluation

语法制导操作 IteratorDestructuringAssignmentEvaluation,接收参数 iteratorRecord (Iterator 记录);返回值:(正常完成 (值:unused) 或 突兀完成)。 它按以下产生式分别定义:

AssignmentElementList : AssignmentElisionElement
  1. 返回 ? 以 iteratorRecord 为参数对 AssignmentElisionElement 执行 IteratorDestructuringAssignmentEvaluation 的结果。
AssignmentElementList : AssignmentElementList , AssignmentElisionElement
  1. 执行 ? 以 iteratorRecord 为参数对 AssignmentElementList 执行 IteratorDestructuringAssignmentEvaluation。
  2. 返回 ? 以 iteratorRecord 为参数对 AssignmentElisionElement 执行 IteratorDestructuringAssignmentEvaluation 的结果。
AssignmentElisionElement : AssignmentElement
  1. 返回 ? 以 iteratorRecord 为参数对 AssignmentElement 执行 IteratorDestructuringAssignmentEvaluation 的结果。
AssignmentElisionElement : Elision AssignmentElement
  1. 执行 ? 以 iteratorRecord 为参数对 Elision 执行 IteratorDestructuringAssignmentEvaluation。
  2. 返回 ? 以 iteratorRecord 为参数对 AssignmentElement 执行 IteratorDestructuringAssignmentEvaluation 的结果。
Elision : ,
  1. 如果 iteratorRecord.[[Done]] 是 false,则
    1. 执行 ? IteratorStep(iteratorRecord)。
  2. 返回 unused。
Elision : Elision ,
  1. 执行 ? 以 iteratorRecord 为参数对 Elision 执行 IteratorDestructuringAssignmentEvaluation。
  2. 如果 iteratorRecord.[[Done]] 是 false,则
    1. 执行 ? IteratorStep(iteratorRecord)。
  3. 返回 unused。
AssignmentElement : DestructuringAssignmentTarget Initializeropt
  1. 如果 DestructuringAssignmentTarget 既不是 ObjectLiteral 也不是 ArrayLiteral,则
    1. 令 leftRef 为 ? DestructuringAssignmentTarget 的 Evaluation。
  2. 令 value 为 undefined。
  3. 如果 iteratorRecord.[[Done]] 是 false,则
    1. 令 next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 next 不是 done,则
      1. 将 value 设置为 next。
  4. 如果存在 Initializer 且 value 是 undefined,则
    1. 如果 IsAnonymousFunctionDefinition(Initializer) 是 true 且 DestructuringAssignmentTarget 的 IsIdentifierRef 是 true,则
      1. 令 target 为 DestructuringAssignmentTarget 的 StringValue。
      2. 将 value 设置为 ? 以 target 为参数对 Initializer 执行 NamedEvaluation 的结果。
    2. 否则,
      1. 令 defaultValue 为 ? Initializer 的 Evaluation。
      2. 将 value 设置为 ? GetValue(defaultValue)。
  5. 如果 DestructuringAssignmentTarget 是 ObjectLiteral 或 ArrayLiteral,则
    1. 令 nestedAssignmentPattern 为 DestructuringAssignmentTarget 所覆盖的 AssignmentPattern。
    2. 返回 ? 以 value 为参数对 nestedAssignmentPattern 执行 DestructuringAssignmentEvaluation 的结果。
  6. 返回 ? PutValue(leftRef, value)。
注

通过在访问迭代器或对 Initializer 求值之前,对不是解构模式的 DestructuringAssignmentTarget 进行求值,维持从左到右的求值顺序。

AssignmentRestElement : ... DestructuringAssignmentTarget
  1. 如果 DestructuringAssignmentTarget 既不是 ObjectLiteral 也不是 ArrayLiteral,则
    1. 令 leftRef 为 ? DestructuringAssignmentTarget 的 Evaluation。
  2. 令 array 为 ! ArrayCreate(0)。
  3. 令 n 为 0。
  4. 当 iteratorRecord.[[Done]] 是 false 时,重复执行,
    1. 令 next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 next 不是 done,则
      1. 执行 ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(n)), next)。
      2. 将 n 设置为 n + 1。
  5. 如果 DestructuringAssignmentTarget 既不是 ObjectLiteral 也不是 ArrayLiteral,则
    1. 返回 ? PutValue(leftRef, array)。
  6. 令 nestedAssignmentPattern 为 DestructuringAssignmentTarget 所覆盖的 AssignmentPattern。
  7. 返回 ? 以 array 为参数对 nestedAssignmentPattern 执行 DestructuringAssignmentEvaluation 的结果。

13.15.5.6 Runtime Semantics: KeyedDestructuringAssignmentEvaluation

语法制导操作 KeyedDestructuringAssignmentEvaluation,接收参数 value (ECMAScript 语言值) 和 propertyName (属性键);返回值:(正常完成 (值:unused) 或 突兀完成)。 它按以下产生式分别定义:

AssignmentElement : DestructuringAssignmentTarget Initializeropt
  1. 如果 DestructuringAssignmentTarget 既不是 ObjectLiteral 也不是 ArrayLiteral,则
    1. 令 leftRef 为 ? DestructuringAssignmentTarget 的 Evaluation。
  2. 将 value 设置为 ? GetV(value, propertyName)。
  3. 如果存在 Initializer 且 value 是 undefined,则
    1. 如果 IsAnonymousFunctionDefinition(Initializer) 是 true 且 DestructuringAssignmentTarget 的 IsIdentifierRef 是 true,则
      1. 令 target 为 DestructuringAssignmentTarget 的 StringValue。
      2. 令 rhsValue 为 ? 以 target 为参数对 Initializer 执行 NamedEvaluation 的结果。
    2. 否则,
      1. 令 defaultValue 为 ? Initializer 的 Evaluation。
      2. 令 rhsValue 为 ? GetValue(defaultValue)。
  4. 否则,
    1. 令 rhsValue 为 value。
  5. 如果 DestructuringAssignmentTarget 是 ObjectLiteral 或 ArrayLiteral,则
    1. 令 assignmentPattern 为 DestructuringAssignmentTarget 所覆盖的 AssignmentPattern。
    2. 返回 ? 以 rhsValue 为参数对 assignmentPattern 执行 DestructuringAssignmentEvaluation 的结果。
  6. 返回 ? PutValue(leftRef, rhsValue)。

13.16 逗号运算符( , )

语法

Expression[In, Yield, Await] : AssignmentExpression[?In, ?Yield, ?Await] Expression[?In, ?Yield, ?Await] , AssignmentExpression[?In, ?Yield, ?Await]

13.16.1 Runtime Semantics: Evaluation

Expression : Expression , AssignmentExpression
  1. 令 leftRef 为 ? Expression 的 Evaluation。
  2. 执行 ? GetValue(leftRef)。
  3. 令 rightRef 为 ? AssignmentExpression 的 Evaluation。
  4. 返回 ? GetValue(rightRef)。
注

即使不使用其值,也必须调用 GetValue,因为它可能具有可观察的副作用。

14 ECMAScript 语言:语句和声明

语法

Statement[Yield, Await, Return] : BlockStatement[?Yield, ?Await, ?Return] VariableStatement[?Yield, ?Await] EmptyStatement ExpressionStatement[?Yield, ?Await] IfStatement[?Yield, ?Await, ?Return] BreakableStatement[?Yield, ?Await, ?Return] ContinueStatement[?Yield, ?Await] BreakStatement[?Yield, ?Await] [+Return] ReturnStatement[?Yield, ?Await] WithStatement[?Yield, ?Await, ?Return] LabelledStatement[?Yield, ?Await, ?Return] ThrowStatement[?Yield, ?Await] TryStatement[?Yield, ?Await, ?Return] DebuggerStatement Declaration[Yield, Await] : HoistableDeclaration[?Yield, ?Await, ~Default] ClassDeclaration[?Yield, ?Await, ~Default] LexicalDeclaration[+In, ?Yield, ?Await] HoistableDeclaration[Yield, Await, Default] : FunctionDeclaration[?Yield, ?Await, ?Default] GeneratorDeclaration[?Yield, ?Await, ?Default] AsyncFunctionDeclaration[?Yield, ?Await, ?Default] AsyncGeneratorDeclaration[?Yield, ?Await, ?Default] BreakableStatement[Yield, Await, Return] : IterationStatement[?Yield, ?Await, ?Return] SwitchStatement[?Yield, ?Await, ?Return]

14.1 语句语义

14.1.1 Runtime Semantics: Evaluation

HoistableDeclaration : GeneratorDeclaration AsyncFunctionDeclaration AsyncGeneratorDeclaration
  1. 返回 empty。
HoistableDeclaration : FunctionDeclaration
  1. 返回 ? FunctionDeclaration 的 Evaluation。
BreakableStatement : IterationStatement SwitchStatement
  1. 令 newLabelSet 为新的空 List。
  2. 返回 ? 以 newLabelSet 为参数对当前 BreakableStatement 执行 LabelledEvaluation 的结果。

14.2 块

语法

BlockStatement[Yield, Await, Return] : Block[?Yield, ?Await, ?Return] Block[Yield, Await, Return] : { StatementList[?Yield, ?Await, ?Return]opt } StatementList[Yield, Await, Return] : StatementListItem[?Yield, ?Await, ?Return] StatementList[?Yield, ?Await, ?Return] StatementListItem[?Yield, ?Await, ?Return] StatementListItem[Yield, Await, Return] : Statement[?Yield, ?Await, ?Return] Declaration[?Yield, ?Await]

14.2.1 Static Semantics: 提前错误

Block : { StatementList }

14.2.2 Runtime Semantics: Evaluation

Block : { }
  1. 返回 empty。
Block : { StatementList }
  1. 令 oldEnv 为正在运行的执行上下文的 LexicalEnvironment。
  2. 令 blockEnv 为 NewDeclarativeEnvironment(oldEnv)。
  3. 执行 BlockDeclarationInstantiation(StatementList, blockEnv)。
  4. 将正在运行的执行上下文的 LexicalEnvironment 设置为 blockEnv。
  5. 令 blockValue 为 Completion(StatementList 的 Evaluation)。
  6. 将 blockValue 设置为 Completion(DisposeResources(blockEnv.[[DisposableResourceStack]], blockValue))。
  7. 将正在运行的执行上下文的 LexicalEnvironment 设置为 oldEnv。
  8. 返回 ? blockValue。
注 1

无论控制如何离开 Block,LexicalEnvironment 始终会恢复为其先前状态。

StatementList : StatementList StatementListItem
  1. 令 sl 为 ? StatementList 的 Evaluation。
  2. 令 s 为 Completion(StatementListItem 的 Evaluation)。
  3. 返回 ? UpdateEmpty(s, sl)。
注 2

StatementList 的值是 StatementList 中最后一个产生值的项的值。例如,以下对 eval 函数的调用都返回值 1:

eval("1;;;;;")
eval("1;{}")
eval("1;var a;")

14.2.3 BlockDeclarationInstantiation ( code, envRecord )

抽象操作 BlockDeclarationInstantiation,接收参数 code (解析节点) 和 envRecord (Declarative Environment 记录);返回值:unused。 code 是与块主体对应的 Parse Node。envRecord 是将在其中创建绑定的 Environment Record。

注

当对 Block 或 CaseBlock 求值时,会创建一个新的 Declarative Environment Record,并在该 Environment Record 中实例化块内声明的每个块作用域变量、常量、函数或类的绑定。

调用时,它执行以下步骤:

  1. 令 decls 为 code 的 LexicallyScopedDeclarations。
  2. 令 privateEnv 为正在运行的执行上下文的 PrivateEnvironment。
  3. 对 decls 的每个元素 decl,执行
    1. 对 decl 的 BoundNames 的每个元素 name,执行
      1. 如果 decl 的 IsConstantDeclaration 是 true,则
        1. 执行 ! envRecord.CreateImmutableBinding(name, true)。
      2. 否则,
        1. Normative Optional
          如果宿主是 Web 浏览器或以其他方式支持 块级函数声明的 Web 遗留兼容性语义,则
          1. 如果 ! envRecord.HasBinding(name) 是 false,则
            1. 执行 ! envRecord.CreateMutableBinding(name, false)。
        2. 否则,
          1. 执行 ! envRecord.CreateMutableBinding(name, false)。
    2. 如果 decl 是 FunctionDeclaration、GeneratorDeclaration、AsyncFunctionDeclaration 或 AsyncGeneratorDeclaration 之一,则
      1. 令 funcName 为 decl 的 BoundNames 的唯一元素。
      2. 令 funcObj 为以 envRecord 和 privateEnv 为参数对 decl 执行 InstantiateFunctionObject 的结果。
      3. Normative Optional
        如果宿主是 Web 浏览器或以其他方式支持 块级函数声明的 Web 遗留兼容性语义,则
        1. 如果 envRecord 中 funcName 的绑定是尚未初始化的绑定,则
          1. 执行 ! envRecord.InitializeBinding(funcName, funcObj)。
        2. 否则,
          1. 断言:decl 是 FunctionDeclaration。
          2. 执行 ! envRecord.SetMutableBinding(funcName, funcObj, false)。
      4. 否则,
        1. 执行 ! envRecord.InitializeBinding(funcName, funcObj)。
  4. 返回 unused。

14.3 声明和变量语句

14.3.1 let、const、using 和 await using 声明

注

let、const、using 和 await using 声明定义作用域限定于正在运行的执行上下文的 LexicalEnvironment 的变量。变量在其所包含的 Environment Record 被实例化时创建,但在变量的 LexicalBinding 被求值之前,不得以任何方式访问变量。当对 LexicalBinding 求值时,由具有 Initializer 的 LexicalBinding 定义的变量会被赋予其 Initializer 的 AssignmentExpression 的值,而不是在创建变量时赋值。如果 let 声明中的 LexicalBinding 没有 Initializer,则在对 LexicalBinding 求值时,该变量被赋予值 undefined。

语法

LexicalDeclaration[In, Yield, Await] : LetOrConst BindingList[?In, ?Yield, ?Await, +Pattern] ; UsingDeclaration[?In, ?Yield, ?Await] [+Await] AwaitUsingDeclaration[?In, ?Yield] LetOrConst : let const UsingDeclaration[In, Yield, Await] : using [no LineTerminator here] BindingList[?In, ?Yield, ?Await, ~Pattern] ; AwaitUsingDeclaration[In, Yield] : CoverAwaitExpressionAndAwaitUsingDeclarationHead[?Yield] [no LineTerminator here] BindingList[?In, ?Yield, +Await, ~Pattern] ; BindingList[In, Yield, Await, Pattern] : LexicalBinding[?In, ?Yield, ?Await, ?Pattern] BindingList[?In, ?Yield, ?Await, ?Pattern] , LexicalBinding[?In, ?Yield, ?Await, ?Pattern] LexicalBinding[In, Yield, Await, Pattern] : BindingIdentifier[?Yield, ?Await] Initializer[?In, ?Yield, ?Await]opt [+Pattern] BindingPattern[?Yield, ?Await] Initializer[?In, ?Yield, ?Await]

补充语法

当处理产生式
AwaitUsingDeclaration : CoverAwaitExpressionAndAwaitUsingDeclarationHead BindingList ;
的实例时,使用以下文法进一步细化对 CoverAwaitExpressionAndAwaitUsingDeclarationHead 的解释:

AwaitUsingDeclarationHead : await [no LineTerminator here] using

14.3.1.1 Static Semantics: 提前错误

LexicalDeclaration : LetOrConst BindingList ; UsingDeclaration : using BindingList ; AwaitUsingDeclaration : CoverAwaitExpressionAndAwaitUsingDeclarationHead BindingList ; LexicalBinding : BindingIdentifier Initializeropt

14.3.1.2 Runtime Semantics: Evaluation

LexicalDeclaration : LetOrConst BindingList ;
  1. 执行 ? 以 normal 为参数对 BindingList 执行 BindingEvaluation。
  2. 返回 empty。
UsingDeclaration : using BindingList ;
  1. 执行 ? 以 sync-dispose 为参数对 BindingList 执行 BindingEvaluation。
  2. 返回 empty。
AwaitUsingDeclaration : CoverAwaitExpressionAndAwaitUsingDeclarationHead BindingList ;
  1. 执行 ? 以 async-dispose 为参数对 BindingList 执行 BindingEvaluation。
  2. 返回 empty。

14.3.1.3 Runtime Semantics: BindingEvaluation

语法制导操作 BindingEvaluation,接收参数 kind ((normal、sync-dispose 或 async-dispose));返回值:(正常完成 (值:unused) 或 突兀完成)。 它按以下产生式分别定义:

BindingList : BindingList , LexicalBinding
  1. 执行 ? 以 kind 为参数对派生的 BindingList 执行 BindingEvaluation。
  2. 返回 ? 以 kind 为参数对 LexicalBinding 执行 BindingEvaluation 的结果。
LexicalBinding : BindingIdentifier
  1. 断言:kind 是 normal。
  2. 令 lhs 为 ! ResolveBinding(BindingIdentifier 的 StringValue)。
  3. 执行 ! InitializeReferencedBinding(lhs, undefined)。
  4. 返回 unused。
注

静态语义规则确保这种形式的 LexicalBinding 永远不会出现在 const、using 或 await using 声明中。

LexicalBinding : BindingIdentifier Initializer
  1. 令 name 为 BindingIdentifier 的 StringValue。
  2. 令 lhs 为 ! ResolveBinding(name)。
  3. 如果 IsAnonymousFunctionDefinition(Initializer) 是 true,则
    1. 令 value 为 ? 以 name 为参数对 Initializer 执行 NamedEvaluation 的结果。
  4. 否则,
    1. 令 rhs 为 ? Initializer 的 Evaluation。
    2. 令 value 为 ? GetValue(rhs)。
  5. 如果 kind 不是 normal,则
    1. 断言:IsUnresolvableReference(lhs) 是 false。
    2. 令 base 为 lhs.[[Base]]。
    3. 断言:base 是 Declarative Environment Record。
    4. 执行 ? AddDisposableResource(base.[[DisposableResourceStack]], value, kind)。
  6. 执行 ? InitializeReferencedBinding(lhs, value)。
  7. 返回 unused。
LexicalBinding : BindingPattern Initializer
  1. 断言:kind 是 normal。
  2. 令 rhs 为 ? Initializer 的 Evaluation。
  3. 令 value 为 ? GetValue(rhs)。
  4. 令 envRecord 为正在运行的执行上下文的 LexicalEnvironment。
  5. 返回 ? 以 value 和 envRecord 为参数对 BindingPattern 执行 BindingInitialization 的结果。

14.3.2 变量语句

注

var 语句声明作用域限定于正在运行的执行上下文的 VariableEnvironment 的变量。var 变量在其所包含的 Environment Record 被实例化时创建,并在创建时初始化为 undefined。在任何 VariableEnvironment 的作用域内,同一个 BindingIdentifier 可以出现在多个 VariableDeclaration 中,但这些声明合起来只定义一个变量。当执行 VariableDeclaration 时,由具有 Initializer 的 VariableDeclaration 定义的变量会被赋予其 Initializer 的 AssignmentExpression 的值,而不是在创建变量时赋值。

语法

VariableStatement[Yield, Await] : var VariableDeclarationList[+In, ?Yield, ?Await] ; VariableDeclarationList[In, Yield, Await] : VariableDeclaration[?In, ?Yield, ?Await] VariableDeclarationList[?In, ?Yield, ?Await] , VariableDeclaration[?In, ?Yield, ?Await] VariableDeclaration[In, Yield, Await] : BindingIdentifier[?Yield, ?Await] Initializer[?In, ?Yield, ?Await]opt BindingPattern[?Yield, ?Await] Initializer[?In, ?Yield, ?Await]

14.3.2.1 Runtime Semantics: Evaluation

VariableStatement : var VariableDeclarationList ;
  1. 执行 ? VariableDeclarationList 的 Evaluation。
  2. 返回 empty。
VariableDeclarationList : VariableDeclarationList , VariableDeclaration
  1. 执行 ? VariableDeclarationList 的 Evaluation。
  2. 返回 ? VariableDeclaration 的 Evaluation。
VariableDeclaration : BindingIdentifier
  1. 返回 empty。
VariableDeclaration : BindingIdentifier Initializer
  1. 令 name 为 BindingIdentifier 的 StringValue。
  2. 令 lhs 为 ? ResolveBinding(name)。
  3. 如果 IsAnonymousFunctionDefinition(Initializer) 是 true,则
    1. 令 value 为 ? 以 name 为参数对 Initializer 执行 NamedEvaluation 的结果。
  4. 否则,
    1. 令 rhs 为 ? Initializer 的 Evaluation。
    2. 令 value 为 ? GetValue(rhs)。
  5. 执行 ? PutValue(lhs, value)。
  6. 返回 empty。
注

如果 VariableDeclaration 嵌套在 with 语句中,并且 VariableDeclaration 中的 BindingIdentifier 与该 with 语句的 Object Environment Record 的绑定对象的某个属性名称相同,则步骤 5 会将 value 赋给该属性,而不是赋给 Identifier 的 VariableEnvironment 绑定。

VariableDeclaration : BindingPattern Initializer
  1. 令 rhs 为 ? Initializer 的 Evaluation。
  2. 令 rightValue 为 ? GetValue(rhs)。
  3. 返回 ? 以 rightValue 和 undefined 为参数对 BindingPattern 执行 BindingInitialization 的结果。

14.3.3 解构绑定模式

语法

BindingPattern[Yield, Await] : ObjectBindingPattern[?Yield, ?Await] ArrayBindingPattern[?Yield, ?Await] ObjectBindingPattern[Yield, Await] : { } { BindingRestProperty[?Yield, ?Await] } { BindingPropertyList[?Yield, ?Await] ,opt } { BindingPropertyList[?Yield, ?Await] , BindingRestProperty[?Yield, ?Await] } ArrayBindingPattern[Yield, Await] : [ Elisionopt BindingRestElement[?Yield, ?Await]opt ] [ BindingElementList[?Yield, ?Await] ] [ BindingElementList[?Yield, ?Await] , Elisionopt BindingRestElement[?Yield, ?Await]opt ] BindingRestProperty[Yield, Await] : ... BindingIdentifier[?Yield, ?Await] BindingPropertyList[Yield, Await] : BindingProperty[?Yield, ?Await] BindingPropertyList[?Yield, ?Await] , BindingProperty[?Yield, ?Await] BindingElementList[Yield, Await] : BindingElisionElement[?Yield, ?Await] BindingElementList[?Yield, ?Await] , BindingElisionElement[?Yield, ?Await] BindingElisionElement[Yield, Await] : Elisionopt BindingElement[?Yield, ?Await] BindingProperty[Yield, Await] : SingleNameBinding[?Yield, ?Await] PropertyName[?Yield, ?Await] : BindingElement[?Yield, ?Await] BindingElement[Yield, Await] : SingleNameBinding[?Yield, ?Await] BindingPattern[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]opt SingleNameBinding[Yield, Await] : BindingIdentifier[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]opt BindingRestElement[Yield, Await] : ... BindingIdentifier[?Yield, ?Await] ... BindingPattern[?Yield, ?Await]

14.3.3.1 Runtime Semantics: PropertyBindingInitialization

语法制导操作 PropertyBindingInitialization,接收参数 value (ECMAScript 语言值) 和 envRecord ((Environment 记录 或 undefined));返回值:(正常完成 (值:列表 (元素:属性键)) 或 突兀完成)。 它收集所有已绑定属性名称的列表。 它按以下产生式分别定义:

BindingPropertyList : BindingPropertyList , BindingProperty
  1. 令 boundNames 为 ? 以 value 和 envRecord 为参数对 BindingPropertyList 执行 PropertyBindingInitialization 的结果。
  2. 令 nextNames 为 ? 以 value 和 envRecord 为参数对 BindingProperty 执行 PropertyBindingInitialization 的结果。
  3. 返回 boundNames 和 nextNames 的列表连接。
BindingProperty : SingleNameBinding
  1. 令 name 为 SingleNameBinding 的 BoundNames 的唯一元素。
  2. 执行 ? 以 value、envRecord 和 name 为参数对 SingleNameBinding 执行 KeyedBindingInitialization。
  3. 返回 « name »。
BindingProperty : PropertyName : BindingElement
  1. 令 propertyKey 为 ? PropertyName 的 Evaluation。
  2. 执行 ? 以 value、envRecord 和 propertyKey 为参数对 BindingElement 执行 KeyedBindingInitialization。
  3. 返回 « propertyKey »。

14.3.3.2 Runtime Semantics: RestBindingInitialization

语法制导操作 RestBindingInitialization,接收参数 value (ECMAScript 语言值)、envRecord ((Environment 记录 或 undefined)) 和 excludedNames (列表 (元素:属性键));返回值:(正常完成 (值:unused) 或 突兀完成)。 它按以下产生式分别定义:

BindingRestProperty : ... BindingIdentifier
  1. 令 lhs 为 ? ResolveBinding(BindingIdentifier 的 StringValue, envRecord)。
  2. 令 restObj 为 OrdinaryObjectCreate(%Object.prototype%)。
  3. 执行 ? CopyDataProperties(restObj, value, excludedNames)。
  4. 如果 envRecord 是 undefined,则返回 ? PutValue(lhs, restObj)。
  5. 返回 ? InitializeReferencedBinding(lhs, restObj)。

14.3.3.3 Runtime Semantics: KeyedBindingInitialization

语法制导操作 KeyedBindingInitialization,接收参数 value (ECMAScript 语言值)、envRecord ((Environment 记录 或 undefined)) 和 propertyName (属性键);返回值:(正常完成 (值:unused) 或 突兀完成)。

注

当为 envRecord 传入 undefined 时,表示应使用 PutValue 操作来赋予初始化值。这适用于非严格函数的形式参数列表。在这种情况下,形式参数绑定会被预先初始化,以处理多个参数具有相同名称的可能性。

它按以下产生式分别定义:

BindingElement : BindingPattern Initializeropt
  1. 将 value 设置为 ? GetV(value, propertyName)。
  2. 如果存在 Initializer 且 value 是 undefined,则
    1. 令 defaultValue 为 ? Initializer 的 Evaluation。
    2. 将 value 设置为 ? GetValue(defaultValue)。
  3. 返回 ? 以 value 和 envRecord 为参数对 BindingPattern 执行 BindingInitialization 的结果。
SingleNameBinding : BindingIdentifier Initializeropt
  1. 令 name 为 BindingIdentifier 的 StringValue。
  2. 令 lhs 为 ? ResolveBinding(name, envRecord)。
  3. 将 value 设置为 ? GetV(value, propertyName)。
  4. 如果存在 Initializer 且 value 是 undefined,则
    1. 如果 IsAnonymousFunctionDefinition(Initializer) 是 true,则
      1. 将 value 设置为 ? 以 name 为参数对 Initializer 执行 NamedEvaluation 的结果。
    2. 否则,
      1. 令 defaultValue 为 ? Initializer 的 Evaluation。
      2. 将 value 设置为 ? GetValue(defaultValue)。
  5. 如果 envRecord 是 undefined,则返回 ? PutValue(lhs, value)。
  6. 返回 ? InitializeReferencedBinding(lhs, value)。

14.4 空语句

语法

EmptyStatement : ;

14.4.1 Runtime Semantics: Evaluation

EmptyStatement : ;
  1. 返回 empty。

14.5 表达式语句

语法

ExpressionStatement[Yield, Await] : [lookahead ∉ { {, function, async [no LineTerminator here] function, class, let [ }] Expression[+In, ?Yield, ?Await] ; 注

ExpressionStatement 不能以 U+007B (LEFT CURLY BRACKET) 开头,因为这可能使其与 Block 产生歧义。ExpressionStatement 不能以 function 或 class 关键字开头,因为这会使其与 FunctionDeclaration、GeneratorDeclaration 或 ClassDeclaration 产生歧义。ExpressionStatement 不能以 async function 开头,因为这会使其与 AsyncFunctionDeclaration 或 AsyncGeneratorDeclaration 产生歧义。ExpressionStatement 不能以两个标记组成的序列 let [ 开头,因为这会使其与第一个 LexicalBinding 为 ArrayBindingPattern 的 let LexicalDeclaration 产生歧义。

14.5.1 Runtime Semantics: Evaluation

ExpressionStatement : Expression ;
  1. 令 exprRef 为 ? Expression 的 Evaluation。
  2. 返回 ? GetValue(exprRef)。

14.6 if 语句

语法

IfStatement[Yield, Await, Return] : if ( Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] else Statement[?Yield, ?Await, ?Return] if ( Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] [lookahead ≠ else] 注
前瞻限制 [lookahead ≠ else] 以通常方式解决经典的“悬空 else”问题。也就是说,当要关联的 if 在其他方面存在歧义时,else 会与候选 if 中最近(最内层)的那个关联

14.6.1 Static Semantics: 提前错误

IfStatement : if ( Expression ) Statement else Statement IfStatement : if ( Expression ) Statement 注

只有在实现了 B.3.1 中规定的扩展时,才需要应用此规则。

14.6.2 Runtime Semantics: Evaluation

IfStatement : if ( Expression ) Statement else Statement
  1. 令 exprRef 为 ? Expression 的 Evaluation。
  2. 令 exprValue 为 ToBoolean(? GetValue(exprRef))。
  3. 如果 exprValue 是 true,则
    1. 令 stmtCompletion 为 Completion(第一个 Statement 的 Evaluation)。
  4. 否则,
    1. 令 stmtCompletion 为 Completion(第二个 Statement 的 Evaluation)。
  5. 返回 ? UpdateEmpty(stmtCompletion, undefined)。
IfStatement : if ( Expression ) Statement
  1. 令 exprRef 为 ? Expression 的 Evaluation。
  2. 令 exprValue 为 ToBoolean(? GetValue(exprRef))。
  3. 如果 exprValue 是 false,则返回 undefined。
  4. 令 stmtCompletion 为 Completion(Statement 的 Evaluation)。
  5. 返回 ? UpdateEmpty(stmtCompletion, undefined)。

14.7 迭代语句

语法

IterationStatement[Yield, Await, Return] : DoWhileStatement[?Yield, ?Await, ?Return] WhileStatement[?Yield, ?Await, ?Return] ForStatement[?Yield, ?Await, ?Return] ForInOfStatement[?Yield, ?Await, ?Return]

14.7.1 语义

14.7.1.1 LoopContinues ( completion, labelSet )

抽象操作 LoopContinues,接收参数 completion (完成记录) 和 labelSet (列表 (元素:String));返回值:Boolean。 调用时执行以下步骤:

  1. 如果 completion 是正常完成,则返回 true。
  2. 如果 completion 不是 continue 完成,则返回 false。
  3. 如果 completion.[[Target]] 是 empty,则返回 true。
  4. 如果 labelSet 包含 completion.[[Target]],则返回 true。
  5. 返回 false。
注

在 IterationStatement 的 Statement 部分中,可以使用 ContinueStatement 开始新的迭代。

14.7.1.2 Runtime Semantics: LoopEvaluation

语法制导操作 LoopEvaluation,接收参数 labelSet (列表 (元素:String));返回值:(正常完成 (值:ECMAScript 语言值) 或 突兀完成)。 它按以下产生式分别定义:

IterationStatement : DoWhileStatement
  1. 返回 ? 以 labelSet 为参数对 DoWhileStatement 执行 DoWhileLoopEvaluation 的结果。
IterationStatement : WhileStatement
  1. 返回 ? 以 labelSet 为参数对 WhileStatement 执行 WhileLoopEvaluation 的结果。
IterationStatement : ForStatement
  1. 返回 ? 以 labelSet 为参数对 ForStatement 执行 ForLoopEvaluation 的结果。
IterationStatement : ForInOfStatement
  1. 返回 ? 以 labelSet 为参数对 ForInOfStatement 执行 ForInOfLoopEvaluation 的结果。

14.7.2 do-while 语句

语法

DoWhileStatement[Yield, Await, Return] : do Statement[?Yield, ?Await, ?Return] while ( Expression[+In, ?Yield, ?Await] ) ;

14.7.2.1 Static Semantics: 提前错误

DoWhileStatement : do Statement while ( Expression ) ; 注

只有在实现了 B.3.1 中规定的扩展时,才需要应用此规则。

14.7.2.2 Runtime Semantics: DoWhileLoopEvaluation

语法制导操作 DoWhileLoopEvaluation,接收参数 labelSet (列表 (元素:String));返回值:(正常完成 (值:ECMAScript 语言值) 或 突兀完成)。 它按以下产生式分别定义:

DoWhileStatement : do Statement while ( Expression ) ;
  1. 令 iterationResult 为 undefined。
  2. 重复执行,
    1. 令 stmtResult 为 Completion(Statement 的 Evaluation)。
    2. 如果 LoopContinues(stmtResult, labelSet) 是 false,则返回 ? UpdateEmpty(stmtResult, iterationResult)。
    3. 如果 stmtResult.[[Value]] 不是 empty,则将 iterationResult 设置为 stmtResult.[[Value]]。
    4. 令 exprRef 为 ? Expression 的 Evaluation。
    5. 令 exprValue 为 ? GetValue(exprRef)。
    6. 如果 ToBoolean(exprValue) 是 false,则返回 iterationResult。

14.7.3 while 语句

语法

WhileStatement[Yield, Await, Return] : while ( Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return]

14.7.3.1 Static Semantics: 提前错误

WhileStatement : while ( Expression ) Statement 注

只有在实现了 B.3.1 中规定的扩展时,才需要应用此规则。

14.7.3.2 Runtime Semantics: WhileLoopEvaluation

语法制导操作 WhileLoopEvaluation,接收参数 labelSet (列表 (元素:String));返回值:(正常完成 (值:ECMAScript 语言值) 或 突兀完成)。 它按以下产生式分别定义:

WhileStatement : while ( Expression ) Statement
  1. 令 iterationResult 为 undefined。
  2. 重复执行,
    1. 令 exprRef 为 ? Expression 的 Evaluation。
    2. 令 exprValue 为 ? GetValue(exprRef)。
    3. 如果 ToBoolean(exprValue) 是 false,则返回 iterationResult。
    4. 令 stmtResult 为 Completion(Statement 的 Evaluation)。
    5. 如果 LoopContinues(stmtResult, labelSet) 是 false,则返回 ? UpdateEmpty(stmtResult, iterationResult)。
    6. 如果 stmtResult.[[Value]] 不是 empty,则将 iterationResult 设置为 stmtResult.[[Value]]。

14.7.4 for 语句

语法

ForStatement[Yield, Await, Return] : for ( [lookahead ≠ let [] Expression[~In, ?Yield, ?Await]opt ; Expression[+In, ?Yield, ?Await]opt ; Expression[+In, ?Yield, ?Await]opt ) Statement[?Yield, ?Await, ?Return] for ( var VariableDeclarationList[~In, ?Yield, ?Await] ; Expression[+In, ?Yield, ?Await]opt ; Expression[+In, ?Yield, ?Await]opt ) Statement[?Yield, ?Await, ?Return] for ( LexicalDeclaration[~In, ?Yield, ?Await] Expression[+In, ?Yield, ?Await]opt ; Expression[+In, ?Yield, ?Await]opt ) Statement[?Yield, ?Await, ?Return]

14.7.4.1 Static Semantics: 提前错误

ForStatement : for ( Expressionopt ; Expressionopt ; Expressionopt ) Statement for ( var VariableDeclarationList ; Expressionopt ; Expressionopt ) Statement for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement 注

只有在实现了 B.3.1 中规定的扩展时,才需要应用此规则。

ForStatement : for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement

14.7.4.2 Runtime Semantics: ForLoopEvaluation

语法制导操作 ForLoopEvaluation,接收参数 labelSet (列表 (元素:String));返回值:(正常完成 (值:ECMAScript 语言值) 或 突兀完成)。 它按以下产生式分别定义:

ForStatement : for ( Expressionopt ; Expressionopt ; Expressionopt ) Statement
  1. 如果存在第一个 Expression,则
    1. 令 exprRef 为 ? 第一个 Expression 的 Evaluation。
    2. 执行 ? GetValue(exprRef)。
  2. 如果存在第二个 Expression,则令 test 为第二个 Expression;否则令 test 为 empty。
  3. 如果存在第三个 Expression,则令 increment 为第三个 Expression;否则令 increment 为 empty。
  4. 返回 ? ForBodyEvaluation(test, increment, Statement, « », labelSet)。
ForStatement : for ( var VariableDeclarationList ; Expressionopt ; Expressionopt ) Statement
  1. 执行 ? VariableDeclarationList 的 Evaluation。
  2. 如果存在第一个 Expression,则令 test 为第一个 Expression;否则令 test 为 empty。
  3. 如果存在第二个 Expression,则令 increment 为第二个 Expression;否则令 increment 为 empty。
  4. 返回 ? ForBodyEvaluation(test, increment, Statement, « », labelSet)。
ForStatement : for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement
  1. 令 oldEnv 为正在运行的执行上下文的 LexicalEnvironment。
  2. 令 loopEnv 为 NewDeclarativeEnvironment(oldEnv)。
  3. 令 isConst 为 LexicalDeclaration 的 IsConstantDeclaration。
  4. 令 boundNames 为 LexicalDeclaration 的 BoundNames。
  5. 对 boundNames 的每个元素 name,执行
    1. 如果 isConst 是 true,则
      1. 执行 ! loopEnv.CreateImmutableBinding(name, true)。
    2. 否则,
      1. 执行 ! loopEnv.CreateMutableBinding(name, false)。
  6. 将正在运行的执行上下文的 LexicalEnvironment 设置为 loopEnv。
  7. 令 forDecl 为 Completion(LexicalDeclaration 的 Evaluation)。
  8. 如果 forDecl 是突然完成,则
    1. 将 forDecl 设置为 Completion(DisposeResources(loopEnv.[[DisposableResourceStack]], forDecl))。
    2. 断言:forDecl 是突然完成。
    3. 将正在运行的执行上下文的 LexicalEnvironment 设置为 oldEnv。
    4. 返回 ? forDecl。
  9. 如果 isConst 是 false,则令 perIterationLets 为 boundNames;否则令 perIterationLets 为新的空 List。
  10. 如果存在第一个 Expression,则令 test 为第一个 Expression;否则令 test 为 empty。
  11. 如果存在第二个 Expression,则令 increment 为第二个 Expression;否则令 increment 为 empty。
  12. 令 bodyResult 为 Completion(ForBodyEvaluation(test, increment, Statement, perIterationLets, labelSet))。
  13. 将 bodyResult 设置为 Completion(DisposeResources(loopEnv.[[DisposableResourceStack]], bodyResult))。
  14. 断言:如果 bodyResult 是正常完成,则 bodyResult.[[Value]] 不是 empty。
  15. 将正在运行的执行上下文的 LexicalEnvironment 设置为 oldEnv。
  16. 返回 ? bodyResult。

14.7.4.3 ForBodyEvaluation ( test, increment, stmt, perIterationBindings, labelSet )

抽象操作 ForBodyEvaluation,接收参数 test ((an Expression Parse Node 或 empty))、increment ((an Expression Parse Node 或 empty))、stmt (a Statement Parse Node)、perIterationBindings (列表 (元素:String)) 和 labelSet (列表 (元素:String));返回值:(正常完成 (值:ECMAScript 语言值) 或 突兀完成)。 调用时执行以下步骤:

  1. 令 iterationResult 为 undefined。
  2. 执行 ? CreatePerIterationEnvironment(perIterationBindings)。
  3. 重复执行,
    1. 如果 test 不是 empty,则
      1. 令 testRef 为 ? test 的 Evaluation。
      2. 令 testValue 为 ? GetValue(testRef)。
      3. 如果 ToBoolean(testValue) 是 false,则返回 iterationResult。
    2. 令 result 为 Completion(stmt 的 Evaluation)。
    3. 如果 LoopContinues(result, labelSet) 是 false,则返回 ? UpdateEmpty(result, iterationResult)。
    4. 如果 result.[[Value]] 不是 empty,则将 iterationResult 设置为 result.[[Value]]。
    5. 执行 ? CreatePerIterationEnvironment(perIterationBindings)。
    6. 如果 increment 不是 empty,则
      1. 令 incrementRef 为 ? increment 的 Evaluation。
      2. 执行 ? GetValue(incrementRef)。

14.7.4.4 CreatePerIterationEnvironment ( perIterationBindings )

抽象操作 CreatePerIterationEnvironment,接收参数 perIterationBindings (列表 (元素:String));返回值:(正常完成 (值:unused) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 perIterationBindings 包含任何元素,则
    1. 令 lastIterationEnv 为正在运行的执行上下文的 LexicalEnvironment。
    2. 令 outer 为 lastIterationEnv.[[OuterEnv]]。
    3. 断言:outer 不是 null。
    4. 令 thisIterationEnv 为 NewDeclarativeEnvironment(outer)。
    5. 对 perIterationBindings 的每个元素 name,执行
      1. 执行 ! thisIterationEnv.CreateMutableBinding(name, false)。
      2. 令 lastValue 为 ? lastIterationEnv.GetBindingValue(name, true)。
      3. 执行 ! thisIterationEnv.InitializeBinding(name, lastValue)。
    6. 将正在运行的执行上下文的 LexicalEnvironment 设置为 thisIterationEnv。
  2. 返回 unused。

14.7.5 for-in、for-of 和 for-await-of 语句

语法

ForInOfStatement[Yield, Await, Return] : for ( [lookahead ≠ let [] LeftHandSideExpression[?Yield, ?Await] in Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] for ( var ForBinding[?Yield, ?Await, +Pattern] in Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] for ( ForDeclaration[?Yield, ?Await, ~Using] in Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] for ( [lookahead ∉ { let, async of }] LeftHandSideExpression[?Yield, ?Await] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] for ( var ForBinding[?Yield, ?Await, +Pattern] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] for ( [lookahead ≠ using of] ForDeclaration[?Yield, ?Await, +Using] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] [+Await] for await ( [lookahead ≠ let] LeftHandSideExpression[?Yield, ?Await] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] [+Await] for await ( var ForBinding[?Yield, ?Await, +Pattern] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] [+Await] for await ( [lookahead ≠ using of] ForDeclaration[?Yield, ?Await, +Using] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] ForDeclaration[Yield, Await, Using] : LetOrConst ForBinding[?Yield, ?Await, +Pattern] [+Using] using [no LineTerminator here] ForBinding[?Yield, ?Await, ~Pattern] [+Using, +Await] await [no LineTerminator here] using [no LineTerminator here] ForBinding[?Yield, +Await, ~Pattern] ForBinding[Yield, Await, Pattern] : BindingIdentifier[?Yield, ?Await] [+Pattern] BindingPattern[?Yield, ?Await] 注

本节由附录 B.3.5 扩展。

14.7.5.1 Static Semantics: 提前错误

ForInOfStatement : for ( LeftHandSideExpression in Expression ) Statement for ( var ForBinding in Expression ) Statement for ( ForDeclaration in Expression ) Statement for ( LeftHandSideExpression of AssignmentExpression ) Statement for ( var ForBinding of AssignmentExpression ) Statement for ( ForDeclaration of AssignmentExpression ) Statement for await ( LeftHandSideExpression of AssignmentExpression ) Statement for await ( var ForBinding of AssignmentExpression ) Statement for await ( ForDeclaration of AssignmentExpression ) Statement 注

只有在实现了 B.3.1 中规定的扩展时,才需要应用此规则。

ForInOfStatement : for ( LeftHandSideExpression in Expression ) Statement for ( LeftHandSideExpression of AssignmentExpression ) Statement for await ( LeftHandSideExpression of AssignmentExpression ) Statement ForInOfStatement : for ( ForDeclaration in Expression ) Statement for ( ForDeclaration of AssignmentExpression ) Statement for await ( ForDeclaration of AssignmentExpression ) Statement

14.7.5.2 Static Semantics: IsDestructuring

语法制导操作 IsDestructuring,接收无参数;返回值:Boolean。 它按以下产生式分别定义:

MemberExpression : PrimaryExpression
  1. 如果 PrimaryExpression 是 ObjectLiteral 或 ArrayLiteral,则返回 true。
  2. 返回 false。
MemberExpression : MemberExpression [ Expression ] MemberExpression . IdentifierName MemberExpression TemplateLiteral SuperProperty MetaProperty new MemberExpression Arguments MemberExpression . PrivateIdentifier NewExpression : new NewExpression LeftHandSideExpression : CallExpression OptionalExpression
  1. 返回 false。
ForDeclaration : LetOrConst ForBinding
  1. 返回 ForBinding 的 IsDestructuring。
ForBinding : BindingIdentifier
  1. 返回 false。
ForBinding : BindingPattern
  1. 返回 true。
注

本节由附录 B.3.5 扩展。

14.7.5.3 Runtime Semantics: ForDeclarationBindingInitialization

语法制导操作 ForDeclarationBindingInitialization,接收参数 value (ECMAScript 语言值) 和 envRecord (Environment 记录);返回值:(正常完成 (值:unused) 或 突兀完成)。 它按以下产生式分别定义:

ForDeclaration : LetOrConst ForBinding
  1. 返回 ? 以 value 和 envRecord 为参数对 ForBinding 执行 BindingInitialization 的结果。
ForDeclaration : using ForBinding await using ForBinding
  1. 抛出 SyntaxError 异常。

14.7.5.4 Runtime Semantics: ForDeclarationBindingInstantiation

语法制导操作 ForDeclarationBindingInstantiation,接收参数 envRecord (Declarative Environment 记录);返回值:unused。 它按以下产生式分别定义:

ForDeclaration : LetOrConst ForBinding
  1. 对 ForBinding 的 BoundNames 的每个元素 name,执行
    1. 如果 LetOrConst 的 IsConstantDeclaration 是 true,则
      1. 执行 ! envRecord.CreateImmutableBinding(name, true)。
    2. 否则,
      1. 执行 ! envRecord.CreateMutableBinding(name, false)。
  2. 返回 unused。
ForDeclaration : using ForBinding await using ForBinding
  1. 对 ForBinding 的 BoundNames 的每个元素 name,执行
    1. 执行 ! envRecord.CreateImmutableBinding(name, true)。
  2. 返回 unused。

14.7.5.5 Runtime Semantics: ForInOfLoopEvaluation

语法制导操作 ForInOfLoopEvaluation,接收参数 labelSet (列表 (元素:String));返回值:(正常完成 (值:ECMAScript 语言值) 或 突兀完成)。 它按以下产生式分别定义:

ForInOfStatement : for ( LeftHandSideExpression in Expression ) Statement
  1. 令 keyResult 为 ? ForIn/OfHeadEvaluation(« », Expression, enumerate)。
  2. 返回 ? ForIn/OfBodyEvaluation(LeftHandSideExpression, Statement, keyResult, enumerate, assignment, labelSet)。
ForInOfStatement : for ( var ForBinding in Expression ) Statement
  1. 令 keyResult 为 ? ForIn/OfHeadEvaluation(« », Expression, enumerate)。
  2. 返回 ? ForIn/OfBodyEvaluation(ForBinding, Statement, keyResult, enumerate, var-binding, labelSet)。
ForInOfStatement : for ( ForDeclaration in Expression ) Statement
  1. 令 keyResult 为 ? ForIn/OfHeadEvaluation(ForDeclaration 的 BoundNames, Expression, enumerate)。
  2. 返回 ? ForIn/OfBodyEvaluation(ForDeclaration, Statement, keyResult, enumerate, lexical-binding, labelSet)。
ForInOfStatement : for ( LeftHandSideExpression of AssignmentExpression ) Statement
  1. 令 keyResult 为 ? ForIn/OfHeadEvaluation(« », AssignmentExpression, iterate)。
  2. 返回 ? ForIn/OfBodyEvaluation(LeftHandSideExpression, Statement, keyResult, iterate, assignment, labelSet)。
ForInOfStatement : for ( var ForBinding of AssignmentExpression ) Statement
  1. 令 keyResult 为 ? ForIn/OfHeadEvaluation(« », AssignmentExpression, iterate)。
  2. 返回 ? ForIn/OfBodyEvaluation(ForBinding, Statement, keyResult, iterate, var-binding, labelSet)。
ForInOfStatement : for ( ForDeclaration of AssignmentExpression ) Statement
  1. 令 keyResult 为 ? ForIn/OfHeadEvaluation(ForDeclaration 的 BoundNames, AssignmentExpression, iterate)。
  2. 返回 ? ForIn/OfBodyEvaluation(ForDeclaration, Statement, keyResult, iterate, lexical-binding, labelSet)。
ForInOfStatement : for await ( LeftHandSideExpression of AssignmentExpression ) Statement
  1. 令 keyResult 为 ? ForIn/OfHeadEvaluation(« », AssignmentExpression, async-iterate)。
  2. 返回 ? ForIn/OfBodyEvaluation(LeftHandSideExpression, Statement, keyResult, iterate, assignment, labelSet, async)。
ForInOfStatement : for await ( var ForBinding of AssignmentExpression ) Statement
  1. 令 keyResult 为 ? ForIn/OfHeadEvaluation(« », AssignmentExpression, async-iterate)。
  2. 返回 ? ForIn/OfBodyEvaluation(ForBinding, Statement, keyResult, iterate, var-binding, labelSet, async)。
ForInOfStatement : for await ( ForDeclaration of AssignmentExpression ) Statement
  1. 令 keyResult 为 ? ForIn/OfHeadEvaluation(ForDeclaration 的 BoundNames, AssignmentExpression, async-iterate)。
  2. 返回 ? ForIn/OfBodyEvaluation(ForDeclaration, Statement, keyResult, iterate, lexical-binding, labelSet, async)。
注

本节由附录 B.3.5 扩展。

14.7.5.6 ForIn/OfHeadEvaluation ( uninitializedBoundNames, expr, iterationKind )

抽象操作 ForIn/OfHeadEvaluation,接收参数 uninitializedBoundNames (列表 (元素:String))、expr ((an Expression Parse Node 或 an AssignmentExpression Parse Node)) 和 iterationKind ((enumerate、iterate 或 async-iterate));返回值:(正常完成 (值:Iterator 记录) 或 突兀完成)。 调用时执行以下步骤:

  1. 令 oldEnv 为正在运行的执行上下文的 LexicalEnvironment。
  2. 如果 uninitializedBoundNames 不为空,则
    1. 断言:uninitializedBoundNames 不包含重复条目。
    2. 令 newEnv 为 NewDeclarativeEnvironment(oldEnv)。
    3. 对 uninitializedBoundNames 的每个 String name,执行
      1. 执行 ! newEnv.CreateMutableBinding(name, false)。
    4. 将正在运行的执行上下文的 LexicalEnvironment 设置为 newEnv。
  3. 令 exprRef 为 Completion(expr 的 Evaluation)。
  4. 将正在运行的执行上下文的 LexicalEnvironment 设置为 oldEnv。
  5. 令 exprValue 为 ? GetValue(? exprRef)。
  6. 如果 iterationKind 是 enumerate,则
    1. 如果 exprValue 是 undefined 或 null,则
      1. 返回 Completion Record { [[Type]]: break, [[Value]]: empty, [[Target]]: empty }。
    2. 令 obj 为 ! ToObject(exprValue)。
    3. 令 iterator 为 EnumerateObjectProperties(obj)。
    4. 令 nextMethod 为 ! GetV(iterator, "next")。
    5. 返回 Iterator Record { [[Iterator]]: iterator, [[NextMethod]]: nextMethod, [[Done]]: false }。
  7. 断言:iterationKind 是 iterate 或 async-iterate。
  8. 如果 iterationKind 是 async-iterate,则令 iteratorKind 为 async。
  9. 否则,令 iteratorKind 为 sync。
  10. 返回 ? GetIterator(exprValue, iteratorKind)。

14.7.5.7 ForIn/OfBodyEvaluation ( lhs, stmt, iteratorRecord, iterationKind, lhsKind, labelSet [ , iteratorKind ] )

抽象操作 ForIn/OfBodyEvaluation,接收参数 lhs (解析节点)、stmt (a Statement Parse Node)、iteratorRecord (Iterator 记录)、iterationKind ((enumerate 或 iterate))、lhsKind ((assignment、var-binding 或 lexical-binding)) 和 labelSet (列表 (元素:String))和可选参数 iteratorKind ((sync 或 async));返回值:(正常完成 (值:ECMAScript 语言值) 或 突兀完成)。 调用时执行以下步骤:

  1. 如果不存在 iteratorKind,则将 iteratorKind 设置为 sync。
  2. 令 oldEnv 为正在运行的执行上下文的 LexicalEnvironment。
  3. 令 iterationResult 为 undefined。
  4. 如果 lhsKind 是 lexical-binding,则
    1. 断言:lhs 是 ForDeclaration。
    2. 如果 lhs 的 IsAwaitUsingDeclaration 是 true,则
      1. 令 declKind 为 async-dispose。
    3. 否则如果 lhs 的 IsUsingDeclaration 是 true,则
      1. 令 declKind 为 sync-dispose。
    4. 否则,
      1. 令 declKind 为 normal。
  5. 否则,
    1. 令 declKind 为 normal。
  6. 令 destructuring 为 lhs 的 IsDestructuring。
  7. 如果 destructuring 是 true 且 lhsKind 是 assignment,则
    1. 断言:lhs 是 LeftHandSideExpression。
    2. 令 assignmentPattern 为 lhs 所覆盖的 AssignmentPattern。
  8. 重复执行,
    1. 令 nextResult 为 ? Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]])。
    2. 如果 iteratorKind 是 async,则将 nextResult 设置为 ? Await(nextResult)。
    3. 如果 nextResult 不是 Object,则抛出 TypeError 异常。
    4. 令 done 为 ? IteratorComplete(nextResult)。
    5. 如果 done 是 true,则返回 iterationResult。
    6. 令 nextValue 为 ? IteratorValue(nextResult)。
    7. 如果 lhsKind 是 assignment 或 var-binding,则
      1. 如果 destructuring 是 true,则
        1. 如果 lhsKind 是 assignment,则
          1. 令 status 为 Completion(以 nextValue 为参数对 assignmentPattern 执行 DestructuringAssignmentEvaluation 的结果)。
        2. 否则,
          1. 断言:lhsKind 是 var-binding。
          2. 断言:lhs 是 ForBinding。
          3. 令 status 为 Completion(以 nextValue 和 undefined 为参数对 lhs 执行 BindingInitialization 的结果)。
      2. 否则,
        1. 令 lhsRef 为 Completion(lhs 的 Evaluation)。(它可能被重复求值。)
        2. 如果 lhsKind 是 assignment 且 lhs 的 AssignmentTargetType 是 web-compat,则抛出 ReferenceError 异常。
        3. 如果 lhsRef 是突然完成,则
          1. 令 status 为 lhsRef。
        4. 否则,
          1. 令 status 为 Completion(PutValue(lhsRef.[[Value]], nextValue))。
      3. 令 iterationEnv 为 undefined。
    8. 否则,
      1. 断言:lhsKind 是 lexical-binding。
      2. 断言:lhs 是 ForDeclaration。
      3. 令 iterationEnv 为 NewDeclarativeEnvironment(oldEnv)。
      4. 以 iterationEnv 为参数对 lhs 执行 ForDeclarationBindingInstantiation。
      5. 将正在运行的执行上下文的 LexicalEnvironment 设置为 iterationEnv。
      6. 如果 destructuring 是 true,则
        1. 令 status 为 Completion(以 nextValue 和 iterationEnv 为参数对 lhs 执行 ForDeclarationBindingInitialization 的结果)。
      7. 否则,
        1. 断言:lhs 绑定单个名称。
        2. 令 lhsName 为 lhs 的 BoundNames 的唯一元素。
        3. 令 lhsRef 为 ! ResolveBinding(lhsName)。
        4. 如果 declKind 不是 normal,则
          1. 断言:IsUnresolvableReference(lhsRef) 是 false。
          2. 令 base 为 lhsRef.[[Base]]。
          3. 断言:base 是 Declarative Environment Record。
          4. 令 status 为 Completion(AddDisposableResource(base.[[DisposableResourceStack]], nextValue, declKind))。
        5. 否则,
          1. 令 status 为 NormalCompletion(unused)。
        6. 如果 status 是正常完成,则
          1. 将 status 设置为 Completion(InitializeReferencedBinding(lhsRef, nextValue))。
    9. 如果 status 是突然完成,则
      1. 如果 iterationEnv 不是 undefined,则
        1. 将 status 设置为 Completion(DisposeResources(iterationEnv.[[DisposableResourceStack]], status))。
        2. 断言:status 是突然完成。
      2. 将正在运行的执行上下文的 LexicalEnvironment 设置为 oldEnv。
      3. 如果 iterationKind 是 enumerate,则返回 ? status。
      4. 断言:iterationKind 是 iterate。
      5. 如果 iteratorKind 是 async,则返回 ? AsyncIteratorClose(iteratorRecord, status)。
      6. 返回 ? IteratorClose(iteratorRecord, status)。
    10. 令 result 为 Completion(stmt 的 Evaluation)。
    11. 如果 iterationEnv 不是 undefined,则
      1. 将 result 设置为 Completion(DisposeResources(iterationEnv.[[DisposableResourceStack]], result))。
    12. 将正在运行的执行上下文的 LexicalEnvironment 设置为 oldEnv。
    13. 如果 LoopContinues(result, labelSet) 是 false,则
      1. 将 status 设置为 Completion(UpdateEmpty(result, iterationResult))。
      2. 如果 iterationKind 是 enumerate,则返回 ? status。
      3. 断言:iterationKind 是 iterate。
      4. 如果 iteratorKind 是 async,则返回 ? AsyncIteratorClose(iteratorRecord, status)。
      5. 返回 ? IteratorClose(iteratorRecord, status)。
    14. 如果 result.[[Value]] 不是 empty,则将 iterationResult 设置为 result.[[Value]]。

14.7.5.8 Runtime Semantics: Evaluation

BindingIdentifier : Identifier yield await
  1. 令 name 为 BindingIdentifier 的 StringValue。
  2. 返回 ? ResolveBinding(name)。

14.7.5.9 EnumerateObjectProperties ( obj )

抽象操作 EnumerateObjectProperties,接收参数 obj (Object);返回值:迭代器对象。 调用时执行以下步骤:

  1. 返回一个迭代器对象,其 next 方法迭代 obj 的所有可枚举属性中值为 String 的键。该迭代器对象永远无法被 ECMAScript 代码直接访问。枚举属性的机制和顺序未作规定,但必须符合下述规则。

该迭代器的 throw 和 return 方法为 null,且永远不会被调用。迭代器的 next 方法处理对象属性,以确定是否应将属性键作为迭代器值返回。返回的属性键不包括 Symbol 键。目标对象的属性可以在枚举期间被删除。在迭代器的 next 方法处理某个属性之前删除该属性时,会忽略该属性。如果在枚举期间向目标对象添加新属性,则不保证在当前枚举中处理新添加的属性。在任意一次枚举中,一个属性名称最多由迭代器的 next 方法返回一次。

枚举目标对象的属性包括递归枚举其原型、原型的原型,依此类推;但如果原型的某个属性与迭代器的 next 方法已经处理过的属性具有相同名称,则不会处理该原型属性。在确定原型对象的某个属性是否已经被处理时,不考虑 [[Enumerable]] 特性的值。必须通过以原型对象为参数调用 EnumerateObjectProperties 来获取原型对象的可枚举属性名称。EnumerateObjectProperties 必须通过调用目标对象的 [[OwnPropertyKeys]] 内部方法来获取其自有属性键。目标对象的属性特性必须通过调用其 [[GetOwnProperty]] 内部方法获取。

此外,如果 obj 及其原型链中的任何对象都不是 Proxy 异质对象、TypedArray、模块命名空间异质对象或实现提供的异质对象,则在发生以下任一情况之前,该迭代器的行为必须与由 CreateForInIterator(obj) 给出的迭代器相同:

  • obj 或其原型链中某个对象的 [[Prototype]] 内部槽值发生变化,
  • 从 obj 或其原型链中的某个对象移除属性,
  • 向 obj 原型链中的某个对象添加属性,或
  • obj 或其原型链中某个对象的某个属性的 [[Enumerable]] 特性值发生变化。
注 1

ECMAScript 实现无需直接实现 14.7.5.10.2.1 中的算法。它们可以选择任何实现,只要在不违反上一段中任何约束的情况下,其行为不会偏离该算法。

以下是符合这些规则的 ECMAScript 生成器函数的非规范性定义:

function* EnumerateObjectProperties(obj) {
  const visited = new Set();
  for (const key of Reflect.ownKeys(obj)) {
    if (typeof key === "symbol") continue;
    const desc = Reflect.getOwnPropertyDescriptor(obj, key);
    if (desc) {
      visited.add(key);
      if (desc.enumerable) yield key;
    }
  }
  const proto = Reflect.getPrototypeOf(obj);
  if (proto === null) return;
  for (const protoKey of EnumerateObjectProperties(proto)) {
    if (!visited.has(protoKey)) yield protoKey;
  }
}
注 2
对于实现无需匹配 CreateForInIterator 的异质对象列表之所以如此选择,是因为历史上各实现对这些情况的行为存在差异,而对所有其他情况的行为一致。

14.7.5.10 For-In Iterator 对象

For-In Iterator 是表示对某个特定对象进行一次特定迭代的对象。For-In Iterator 对象永远无法被 ECMAScript 代码直接访问;它们仅用于说明 EnumerateObjectProperties 的行为。

14.7.5.10.1 CreateForInIterator ( obj )

抽象操作 CreateForInIterator,接收参数 obj (Object);返回值:a For-In Iterator。 它用于创建一个 For-In Iterator 对象,该对象按特定顺序迭代 obj 的自有和继承的可枚举字符串属性。 调用时执行以下步骤:

  1. 令 iterator 为 OrdinaryObjectCreate(%ForInIteratorPrototype%, « [[Object]], [[ObjectWasVisited]], [[VisitedKeys]], [[RemainingKeys]] »)。
  2. 将 iterator.[[Object]] 设置为 obj。
  3. 将 iterator.[[ObjectWasVisited]] 设置为 false。
  4. 将 iterator.[[VisitedKeys]] 设置为新的空 List。
  5. 将 iterator.[[RemainingKeys]] 设置为新的空 List。
  6. 返回 iterator。

14.7.5.10.2 %ForInIteratorPrototype% 对象

%ForInIteratorPrototype% 对象:

14.7.5.10.2.1 %ForInIteratorPrototype%.next ( )

  1. 令 iterator 为 this 值。
  2. 断言:iterator 是 Object。
  3. 断言:iterator 具有 For-In Iterator 实例的所有内部槽(14.7.5.10.3)。
  4. 令 obj 为 iterator.[[Object]]。
  5. 重复执行,
    1. 如果 iterator.[[ObjectWasVisited]] 是 false,则
      1. 令 keys 为 ? obj.[[OwnPropertyKeys]]()。
      2. 对 keys 的每个元素 key,执行
        1. 如果 key 是 String,则
          1. 将 key 追加到 iterator.[[RemainingKeys]]。
      3. 将 iterator.[[ObjectWasVisited]] 设置为 true。
    2. 当 iterator.[[RemainingKeys]] 不为空时,重复执行,
      1. 令 key 为 iterator.[[RemainingKeys]] 的第一个元素。
      2. 从 iterator.[[RemainingKeys]] 中移除第一个元素。
      3. 如果 iterator.[[VisitedKeys]] 不包含 key,则
        1. 令 propertyDesc 为 ? obj.[[GetOwnProperty]](key)。
        2. 如果 propertyDesc 不是 undefined,则
          1. 将 key 追加到 iterator.[[VisitedKeys]]。
          2. 如果 propertyDesc.[[Enumerable]] 是 true,则返回 CreateIteratorResultObject(key, false)。
    3. 将 obj 设置为 ? obj.[[GetPrototypeOf]]()。
    4. 将 iterator.[[Object]] 设置为 obj。
    5. 将 iterator.[[ObjectWasVisited]] 设置为 false。
    6. 如果 obj 是 null,则返回 CreateIteratorResultObject(undefined, true)。

14.7.5.10.3 For-In Iterator 实例的属性

For-In Iterator 实例是从 %ForInIteratorPrototype% 内在对象继承属性的普通对象。For-In Iterator 实例最初使用 表 34 中列出的内部槽创建。

表 34: For-In Iterator 实例的内部槽
内部槽 类型 描述
[[Object]] Object 正在迭代其属性的 Object 值。
[[ObjectWasVisited]] Boolean 如果迭代器已在 [[Object]] 上调用 [[OwnPropertyKeys]],则为 true;否则为 false。
[[VisitedKeys]] String 的 List 到目前为止由此迭代器发出的值。
[[RemainingKeys]] String 的 List 在迭代其原型的属性(如果其原型不是 null)之前,当前对象尚待发出的值。

14.8 continue 语句

语法

ContinueStatement[Yield, Await] : continue ; continue [no LineTerminator here] LabelIdentifier[?Yield, ?Await] ;

14.8.1 Static Semantics: 提前错误

ContinueStatement : continue ; continue LabelIdentifier ;

14.8.2 Runtime Semantics: Evaluation

ContinueStatement : continue ;
  1. 返回 Completion Record { [[Type]]: continue, [[Value]]: empty, [[Target]]: empty }。
ContinueStatement : continue LabelIdentifier ;
  1. 令 label 为 LabelIdentifier 的 StringValue。
  2. 返回 Completion Record { [[Type]]: continue, [[Value]]: empty, [[Target]]: label }。

14.9 break 语句

语法

BreakStatement[Yield, Await] : break ; break [no LineTerminator here] LabelIdentifier[?Yield, ?Await] ;

14.9.1 Static Semantics: 提前错误

BreakStatement : break ;

14.9.2 Runtime Semantics: Evaluation

BreakStatement : break ;
  1. 返回 Completion Record { [[Type]]: break, [[Value]]: empty, [[Target]]: empty }。
BreakStatement : break LabelIdentifier ;
  1. 令 label 为 LabelIdentifier 的 StringValue。
  2. 返回 Completion Record { [[Type]]: break, [[Value]]: empty, [[Target]]: label }。

14.10 return 语句

语法

ReturnStatement[Yield, Await] : return ; return [no LineTerminator here] Expression[+In, ?Yield, ?Await] ; 注

return 语句会使函数停止执行,并且在大多数情况下向调用方返回一个值。如果省略 Expression,则返回值为 undefined。否则,返回值为 Expression 的值。根据周围上下文,return 语句实际上可能不会向调用方返回值。例如,在 try 块中,return 语句的 Completion Record 可能在对 finally 块求值期间被另一个 Completion Record 替换。

14.10.1 Runtime Semantics: Evaluation

ReturnStatement : return ;
  1. 返回 ReturnCompletion(undefined)。
ReturnStatement : return Expression ;
  1. 令 exprRef 为 ? Expression 的 Evaluation。
  2. 令 exprValue 为 ? GetValue(exprRef)。
  3. 如果 GetGeneratorKind() 是 async,则将 exprValue 设置为 ? Await(exprValue)。
  4. 返回 ReturnCompletion(exprValue)。

14.11 with 语句

注 1

不鼓励在新的 ECMAScript 代码中使用旧式 with 语句。请考虑同时允许用于严格模式代码和非严格代码的替代方案,例如 解构赋值。

语法

WithStatement[Yield, Await, Return] : with ( Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] 注 2

with 语句会为计算得到的对象向正在运行的执行上下文的词法环境添加一个 Object Environment Record。然后,它使用这一扩展后的词法环境执行语句。最后,它恢复原始词法环境。

14.11.1 Static Semantics: 提前错误

WithStatement : with ( Expression ) Statement 注

只有在实现了 B.3.1 中规定的扩展时,才需要应用第二条规则。

14.11.2 Runtime Semantics: Evaluation

WithStatement : with ( Expression ) Statement
  1. 令 value 为 ? Expression 的 Evaluation。
  2. 令 obj 为 ? ToObject(? GetValue(value))。
  3. 令 oldEnv 为正在运行的执行上下文的 LexicalEnvironment。
  4. 令 newEnv 为 NewObjectEnvironment(obj, true, oldEnv)。
  5. 将正在运行的执行上下文的 LexicalEnvironment 设置为 newEnv。
  6. 令 stmtCompletion 为 Completion(Statement 的 Evaluation)。
  7. 将正在运行的执行上下文的 LexicalEnvironment 设置为 oldEnv。
  8. 返回 ? UpdateEmpty(stmtCompletion, undefined)。
注

无论控制如何离开嵌入的 Statement,无论是正常离开、通过某种形式的突然完成还是异常,LexicalEnvironment 始终都会恢复为其先前状态。

14.12 switch 语句

语法

SwitchStatement[Yield, Await, Return] : switch ( Expression[+In, ?Yield, ?Await] ) CaseBlock[?Yield, ?Await, ?Return] CaseBlock[Yield, Await, Return] : { CaseClauses[?Yield, ?Await, ?Return]opt } { CaseClauses[?Yield, ?Await, ?Return]opt DefaultClause[?Yield, ?Await, ?Return] CaseClauses[?Yield, ?Await, ?Return]opt } CaseClauses[Yield, Await, Return] : CaseClause[?Yield, ?Await, ?Return] CaseClauses[?Yield, ?Await, ?Return] CaseClause[?Yield, ?Await, ?Return] CaseClause[Yield, Await, Return] : case Expression[+In, ?Yield, ?Await] : StatementList[?Yield, ?Await, ?Return]opt DefaultClause[Yield, Await, Return] : default : StatementList[?Yield, ?Await, ?Return]opt

14.12.1 Static Semantics: 提前错误

SwitchStatement : switch ( Expression ) CaseBlock CaseClause : case Expression : StatementList DefaultClause : default : StatementList

14.12.2 Runtime Semantics: CaseBlockEvaluation

语法制导操作 CaseBlockEvaluation,接收参数 input (ECMAScript 语言值);返回值:(正常完成 (值:ECMAScript 语言值) 或 突兀完成)。 它按以下产生式分别定义:

CaseBlock : { }
  1. 返回 undefined。
CaseBlock : { CaseClauses }
  1. 令 resultValue 为 undefined。
  2. 令 caseClauses 为 CaseClauses 中按源文本顺序排列的 CaseClause 项的 List。
  3. 令 found 为 false。
  4. 对 caseClauses 的每个 CaseClause clause,执行
    1. 如果 found 是 false,则
      1. 将 found 设置为 ? CaseClauseIsSelected(clause, input)。
    2. 如果 found 是 true,则
      1. 令 completion 为 Completion(clause 的 Evaluation)。
      2. 如果 completion.[[Value]] 不是 empty,则将 resultValue 设置为 completion.[[Value]]。
      3. 如果 completion 是突然完成,则返回 ? UpdateEmpty(completion, resultValue)。
  5. 返回 resultValue。
CaseBlock : { CaseClausesopt DefaultClause CaseClausesopt }
  1. 令 resultValue 为 undefined。
  2. 如果存在第一个 CaseClauses,则
    1. 令 caseClauses 为第一个 CaseClauses 中按源文本顺序排列的 CaseClause 项的 List。
  3. 否则,
    1. 令 caseClauses 为新的空 List。
  4. 令 found 为 false。
  5. 对 caseClauses 的每个 CaseClause clause,执行
    1. 如果 found 是 false,则
      1. 将 found 设置为 ? CaseClauseIsSelected(clause, input)。
    2. 如果 found 是 true,则
      1. 令 completion 为 Completion(clause 的 Evaluation)。
      2. 如果 completion.[[Value]] 不是 empty,则将 resultValue 设置为 completion.[[Value]]。
      3. 如果 completion 是突然完成,则返回 ? UpdateEmpty(completion, resultValue)。
  6. 令 foundInB 为 false。
  7. 如果存在第二个 CaseClauses,则
    1. 令 secondCaseClauses 为第二个 CaseClauses 中按源文本顺序排列的 CaseClause 项的 List。
  8. 否则,
    1. 令 secondCaseClauses 为新的空 List。
  9. 如果 found 是 false,则
    1. 对 secondCaseClauses 的每个 CaseClause clause,执行
      1. 如果 foundInB 是 false,则
        1. 将 foundInB 设置为 ? CaseClauseIsSelected(clause, input)。
      2. 如果 foundInB 是 true,则
        1. 令 completion 为 Completion(CaseClause clause 的 Evaluation)。
        2. 如果 completion.[[Value]] 不是 empty,则将 resultValue 设置为 completion.[[Value]]。
        3. 如果 completion 是突然完成,则返回 ? UpdateEmpty(completion, resultValue)。
  10. 如果 foundInB 是 true,则返回 resultValue。
  11. 令 defaultR 为 Completion(DefaultClause 的 Evaluation)。
  12. 如果 defaultR.[[Value]] 不是 empty,则将 resultValue 设置为 defaultR.[[Value]]。
  13. 如果 defaultR 是突然完成,则返回 ? UpdateEmpty(defaultR, resultValue)。
  14. 注:以下是对第二个 CaseClauses 的另一次完整迭代。
  15. 对 secondCaseClauses 的每个 CaseClause clause,执行
    1. 令 completion 为 Completion(CaseClause clause 的 Evaluation)。
    2. 如果 completion.[[Value]] 不是 empty,则将 resultValue 设置为 completion.[[Value]]。
    3. 如果 completion 是突然完成,则返回 ? UpdateEmpty(completion, resultValue)。
  16. 返回 resultValue。

14.12.3 CaseClauseIsSelected ( caseClauseNode, input )

抽象操作 CaseClauseIsSelected,接收参数 caseClauseNode (a CaseClause Parse Node) 和 input (ECMAScript 语言值);返回值:(正常完成 (值:Boolean) 或 突兀完成)。 它确定 caseClauseNode 是否与 input 匹配。 调用时执行以下步骤:

  1. 断言:caseClauseNode 是产生式 CaseClause : case Expression : StatementListopt 的实例。
  2. 令 exprRef 为 ? caseClauseNode 的 Expression 的 Evaluation。
  3. 令 clauseSelector 为 ? GetValue(exprRef)。
  4. 返回 IsStrictlyEqual(input, clauseSelector)。
注

此操作不会执行 caseClauseNode 的 StatementList(如果存在)。CaseBlock 算法使用其返回值来确定从哪个 StatementList 开始执行。

14.12.4 Runtime Semantics: Evaluation

SwitchStatement : switch ( Expression ) CaseBlock
  1. 令 exprRef 为 ? Expression 的 Evaluation。
  2. 令 switchValue 为 ? GetValue(exprRef)。
  3. 令 oldEnv 为正在运行的执行上下文的 LexicalEnvironment。
  4. 令 blockEnv 为 NewDeclarativeEnvironment(oldEnv)。
  5. 执行 BlockDeclarationInstantiation(CaseBlock, blockEnv)。
  6. 将正在运行的执行上下文的 LexicalEnvironment 设置为 blockEnv。
  7. 令 blockResult 为 Completion(以 switchValue 为参数对 CaseBlock 执行 CaseBlockEvaluation 的结果)。
  8. 断言:blockEnv.[[DisposableResourceStack]] 是空 List。
  9. 将正在运行的执行上下文的 LexicalEnvironment 设置为 oldEnv。
  10. 返回 blockResult。
注

无论控制如何离开 SwitchStatement,LexicalEnvironment 始终都会恢复为其先前状态。

CaseClause : case Expression :
  1. 返回 empty。
CaseClause : case Expression : StatementList
  1. 返回 ? StatementList 的 Evaluation。
DefaultClause : default :
  1. 返回 empty。
DefaultClause : default : StatementList
  1. 返回 ? StatementList 的 Evaluation。

14.13 带标签语句

语法

LabelledStatement[Yield, Await, Return] : LabelIdentifier[?Yield, ?Await] : LabelledItem[?Yield, ?Await, ?Return] LabelledItem[Yield, Await, Return] : Statement[?Yield, ?Await, ?Return] FunctionDeclaration[?Yield, ?Await, ~Default] 注

Statement 可以以标签作为前缀。带标签语句仅与带标签的 break 和 continue 语句一起使用。ECMAScript 没有 goto 语句。一个 Statement 可以是 LabelledStatement 的一部分,而后者本身又可以是另一个 LabelledStatement 的一部分,依此类推。在描述各个语句的语义时,以这种方式引入的标签统称为“当前标签集”。

14.13.1 Static Semantics: 提前错误

LabelledItem : FunctionDeclaration

14.13.2 Static Semantics: IsLabelledFunction ( stmt )

抽象操作 IsLabelledFunction,接收参数 stmt (a Statement Parse Node);返回值:Boolean。 调用时执行以下步骤:

  1. 如果 stmt 不是 LabelledStatement,则返回 false。
  2. 令 item 为 stmt 的 LabelledItem。
  3. 如果 item 是 LabelledItem : FunctionDeclaration ,则返回 true。
  4. 令 subStmt 为 item 的 Statement。
  5. 返回 IsLabelledFunction(subStmt)。

14.13.3 Runtime Semantics: Evaluation

LabelledStatement : LabelIdentifier : LabelledItem
  1. 返回 ? 以 « » 为参数对当前 LabelledStatement 执行 LabelledEvaluation 的结果。

14.13.4 Runtime Semantics: LabelledEvaluation

语法制导操作 LabelledEvaluation,接收参数 labelSet (列表 (元素:String));返回值:(正常完成 (值:(ECMAScript 语言值 或 empty)) 或 突兀完成)。 它按以下产生式分别定义:

BreakableStatement : IterationStatement
  1. 令 stmtResult 为 Completion(以 labelSet 为参数对 IterationStatement 执行 LoopEvaluation 的结果)。
  2. 如果 stmtResult 是 break 完成,则
    1. 如果 stmtResult.[[Target]] 是 empty,则
      1. 如果 stmtResult.[[Value]] 是 empty,则将 stmtResult 设置为 NormalCompletion(undefined)。
      2. 否则,将 stmtResult 设置为 NormalCompletion(stmtResult.[[Value]])。
  3. 返回 ? stmtResult。
BreakableStatement : SwitchStatement
  1. 令 stmtResult 为 Completion(SwitchStatement 的 Evaluation)。
  2. 如果 stmtResult 是 break 完成,则
    1. 如果 stmtResult.[[Target]] 是 empty,则
      1. 如果 stmtResult.[[Value]] 是 empty,则将 stmtResult 设置为 NormalCompletion(undefined)。
      2. 否则,将 stmtResult 设置为 NormalCompletion(stmtResult.[[Value]])。
  3. 返回 ? stmtResult。
注 1

BreakableStatement 是可以通过无标签 BreakStatement 退出的语句。

LabelledStatement : LabelIdentifier : LabelledItem
  1. 令 label 为 LabelIdentifier 的 StringValue。
  2. 令 newLabelSet 为 labelSet 与 « label » 的列表连接。
  3. 令 stmtResult 为 Completion(以 newLabelSet 为参数对 LabelledItem 执行 LabelledEvaluation 的结果)。
  4. 如果 stmtResult 是 break 完成且 stmtResult.[[Target]] 是 label,则
    1. 将 stmtResult 设置为 NormalCompletion(stmtResult.[[Value]])。
  5. 返回 ? stmtResult。
LabelledItem : FunctionDeclaration
  1. 返回 ? FunctionDeclaration 的 Evaluation。
Statement : BlockStatement VariableStatement EmptyStatement ExpressionStatement IfStatement ContinueStatement BreakStatement ReturnStatement WithStatement ThrowStatement TryStatement DebuggerStatement
  1. 返回 ? Statement 的 Evaluation。
注 2

Statement 中只有两个产生式具有 LabelledEvaluation 的特殊语义,即 BreakableStatement 和 LabelledStatement。

14.14 throw 语句

语法

ThrowStatement[Yield, Await] : throw [no LineTerminator here] Expression[+In, ?Yield, ?Await] ;

14.14.1 Runtime Semantics: Evaluation

ThrowStatement : throw Expression ;
  1. 令 exprRef 为 ? Expression 的 Evaluation。
  2. 令 exprValue 为 ? GetValue(exprRef)。
  3. 抛出 exprValue。

14.15 try 语句

语法

TryStatement[Yield, Await, Return] : try Block[?Yield, ?Await, ?Return] Catch[?Yield, ?Await, ?Return] try Block[?Yield, ?Await, ?Return] Finally[?Yield, ?Await, ?Return] try Block[?Yield, ?Await, ?Return] Catch[?Yield, ?Await, ?Return] Finally[?Yield, ?Await, ?Return] Catch[Yield, Await, Return] : catch ( CatchParameter[?Yield, ?Await] ) Block[?Yield, ?Await, ?Return] catch Block[?Yield, ?Await, ?Return] Finally[Yield, Await, Return] : finally Block[?Yield, ?Await, ?Return] CatchParameter[Yield, Await] : BindingIdentifier[?Yield, ?Await] BindingPattern[?Yield, ?Await] 注

try 语句包围一段可能发生异常状况的代码块,例如运行时错误或 throw 语句。catch 子句提供异常处理代码。当 catch 子句捕获异常时,其 CatchParameter 会绑定到该异常。

14.15.1 Static Semantics: 提前错误

Catch : catch ( CatchParameter ) Block

14.15.2 Runtime Semantics: CatchClauseEvaluation

语法制导操作 CatchClauseEvaluation,接收参数 thrownValue (ECMAScript 语言值);返回值:(正常完成 (值:(ECMAScript 语言值 或 empty)) 或 突兀完成)。 它按以下产生式分别定义:

Catch : catch ( CatchParameter ) Block
  1. 令 oldEnv 为正在运行的执行上下文的 LexicalEnvironment。
  2. 令 catchEnv 为 NewDeclarativeEnvironment(oldEnv)。
  3. 对 CatchParameter 的 BoundNames 的每个元素 argName,执行
    1. 执行 ! catchEnv.CreateMutableBinding(argName, false)。
  4. 将正在运行的执行上下文的 LexicalEnvironment 设置为 catchEnv。
  5. 令 status 为 Completion(以 thrownValue 和 catchEnv 为参数对 CatchParameter 执行 BindingInitialization 的结果)。
  6. 如果 status 是突然完成,则
    1. 将正在运行的执行上下文的 LexicalEnvironment 设置为 oldEnv。
    2. 返回 ? status。
  7. 令 blockCompletion 为 Completion(Block 的 Evaluation)。
  8. 将正在运行的执行上下文的 LexicalEnvironment 设置为 oldEnv。
  9. 返回 ? blockCompletion。
Catch : catch Block
  1. 返回 ? Block 的 Evaluation。
注

无论控制如何离开 Block,LexicalEnvironment 始终都会恢复为其先前状态。

14.15.3 Runtime Semantics: Evaluation

TryStatement : try Block Catch
  1. 令 blockResult 为 Completion(Block 的 Evaluation)。
  2. 如果 blockResult 是抛出完成,则令 catchResult 为 Completion(以 blockResult.[[Value]] 为参数对 Catch 执行 CatchClauseEvaluation 的结果)。
  3. 否则,令 catchResult 为 blockResult。
  4. 返回 ? UpdateEmpty(catchResult, undefined)。
TryStatement : try Block Finally
  1. 令 blockResult 为 Completion(Block 的 Evaluation)。
  2. 令 finallyResult 为 Completion(Finally 的 Evaluation)。
  3. 如果 finallyResult 是正常完成,则将 finallyResult 设置为 blockResult。
  4. 返回 ? UpdateEmpty(finallyResult, undefined)。
TryStatement : try Block Catch Finally
  1. 令 blockResult 为 Completion(Block 的 Evaluation)。
  2. 如果 blockResult 是抛出完成,则令 catchResult 为 Completion(以 blockResult.[[Value]] 为参数对 Catch 执行 CatchClauseEvaluation 的结果)。
  3. 否则,令 catchResult 为 blockResult。
  4. 令 finallyResult 为 Completion(Finally 的 Evaluation)。
  5. 如果 finallyResult 是正常完成,则将 finallyResult 设置为 catchResult。
  6. 返回 ? UpdateEmpty(finallyResult, undefined)。

14.16 debugger 语句

语法

DebuggerStatement : debugger ;

14.16.1 Runtime Semantics: Evaluation

注

对 DebuggerStatement 求值时,如果在调试器下运行,实现可以触发断点。如果调试器不存在或未处于活动状态,则此语句没有可观察效果。

DebuggerStatement : debugger ;
  1. 如果实现定义的调试设施可用并且已启用,则
    1. 执行实现定义的调试操作。
    2. 返回一个新的实现定义 Completion Record。
  2. 返回 empty。

15 ECMAScript 语言:函数和类

注

各种 ECMAScript 语言元素会创建 ECMAScript 函数对象(10.2)。对此类函数的求值始于执行其 [[Call]] 内部方法(10.2.1)。

15.1 参数列表

语法

UniqueFormalParameters[Yield, Await] : FormalParameters[?Yield, ?Await] FormalParameters[Yield, Await] : [empty] FunctionRestParameter[?Yield, ?Await] FormalParameterList[?Yield, ?Await] FormalParameterList[?Yield, ?Await] , FormalParameterList[?Yield, ?Await] , FunctionRestParameter[?Yield, ?Await] FormalParameterList[Yield, Await] : FormalParameter[?Yield, ?Await] FormalParameterList[?Yield, ?Await] , FormalParameter[?Yield, ?Await] FunctionRestParameter[Yield, Await] : BindingRestElement[?Yield, ?Await] FormalParameter[Yield, Await] : BindingElement[?Yield, ?Await]

15.1.1 Static Semantics: 提前错误

UniqueFormalParameters : FormalParameters FormalParameters : FormalParameterList 注

仅当函数具有简单参数列表且未在严格模式代码中定义时,才允许在 FormalParameterList 中多次出现相同的 BindingIdentifier。

15.1.2 Static Semantics: ContainsExpression

语法制导操作 ContainsExpression,接收无参数;返回值:Boolean。 它按以下产生式分别定义:

ObjectBindingPattern : { } { BindingRestProperty }
  1. 返回 false。
ObjectBindingPattern : { BindingPropertyList , BindingRestProperty }
  1. 返回 BindingPropertyList 的 ContainsExpression。
ArrayBindingPattern : [ Elisionopt ]
  1. 返回 false。
ArrayBindingPattern : [ Elisionopt BindingRestElement ]
  1. 返回 BindingRestElement 的 ContainsExpression。
ArrayBindingPattern : [ BindingElementList , Elisionopt ]
  1. 返回 BindingElementList 的 ContainsExpression。
ArrayBindingPattern : [ BindingElementList , Elisionopt BindingRestElement ]
  1. 令 has 为 BindingElementList 的 ContainsExpression。
  2. 如果 has 是 true,则返回 true。
  3. 返回 BindingRestElement 的 ContainsExpression。
BindingPropertyList : BindingPropertyList , BindingProperty
  1. 令 has 为 BindingPropertyList 的 ContainsExpression。
  2. 如果 has 是 true,则返回 true。
  3. 返回 BindingProperty 的 ContainsExpression。
BindingElementList : BindingElementList , BindingElisionElement
  1. 令 has 为 BindingElementList 的 ContainsExpression。
  2. 如果 has 是 true,则返回 true。
  3. 返回 BindingElisionElement 的 ContainsExpression。
BindingElisionElement : Elisionopt BindingElement
  1. 返回 BindingElement 的 ContainsExpression。
BindingProperty : PropertyName : BindingElement
  1. 令 has 为 PropertyName 的 IsComputedPropertyKey。
  2. 如果 has 是 true,则返回 true。
  3. 返回 BindingElement 的 ContainsExpression。
BindingElement : BindingPattern Initializer
  1. 返回 true。
SingleNameBinding : BindingIdentifier
  1. 返回 false。
SingleNameBinding : BindingIdentifier Initializer
  1. 返回 true。
BindingRestElement : ... BindingIdentifier
  1. 返回 false。
BindingRestElement : ... BindingPattern
  1. 返回 BindingPattern 的 ContainsExpression。
FormalParameters : [empty]
  1. 返回 false。
FormalParameters : FormalParameterList , FunctionRestParameter
  1. 如果 FormalParameterList 的 ContainsExpression 是 true,则返回 true。
  2. 返回 FunctionRestParameter 的 ContainsExpression。
FormalParameterList : FormalParameterList , FormalParameter
  1. 如果 FormalParameterList 的 ContainsExpression 是 true,则返回 true。
  2. 返回 FormalParameter 的 ContainsExpression。
ArrowParameters : BindingIdentifier
  1. 返回 false。
ArrowParameters : CoverParenthesizedExpressionAndArrowParameterList
  1. 令 formals 为 CoverParenthesizedExpressionAndArrowParameterList 所覆盖的 ArrowFormalParameters。
  2. 返回 formals 的 ContainsExpression。
AsyncArrowBindingIdentifier : BindingIdentifier
  1. 返回 false。

15.1.3 Static Semantics: IsSimpleParameterList

语法制导操作 IsSimpleParameterList,接收无参数;返回值:Boolean。 它按以下产生式分别定义:

BindingElement : BindingPattern
  1. 返回 false。
BindingElement : BindingPattern Initializer
  1. 返回 false。
SingleNameBinding : BindingIdentifier
  1. 返回 true。
SingleNameBinding : BindingIdentifier Initializer
  1. 返回 false。
FormalParameters : [empty]
  1. 返回 true。
FormalParameters : FunctionRestParameter
  1. 返回 false。
FormalParameters : FormalParameterList , FunctionRestParameter
  1. 返回 false。
FormalParameterList : FormalParameterList , FormalParameter
  1. 如果 FormalParameterList 的 IsSimpleParameterList 是 false,则返回 false。
  2. 返回 FormalParameter 的 IsSimpleParameterList。
FormalParameter : BindingElement
  1. 返回 BindingElement 的 IsSimpleParameterList。
ArrowParameters : BindingIdentifier
  1. 返回 true。
ArrowParameters : CoverParenthesizedExpressionAndArrowParameterList
  1. 令 formals 为 CoverParenthesizedExpressionAndArrowParameterList 所覆盖的 ArrowFormalParameters。
  2. 返回 formals 的 IsSimpleParameterList。
AsyncArrowBindingIdentifier : BindingIdentifier
  1. 返回 true。
CoverCallExpressionAndAsyncArrowHead : MemberExpression Arguments
  1. 令 head 为 CoverCallExpressionAndAsyncArrowHead 所覆盖的 AsyncArrowHead。
  2. 返回 head 的 IsSimpleParameterList。

15.1.4 Static Semantics: HasInitializer

语法制导操作 HasInitializer,接收无参数;返回值:Boolean。 它按以下产生式分别定义:

BindingElement : BindingPattern
  1. 返回 false。
BindingElement : BindingPattern Initializer
  1. 返回 true。
SingleNameBinding : BindingIdentifier
  1. 返回 false。
SingleNameBinding : BindingIdentifier Initializer
  1. 返回 true。
FormalParameterList : FormalParameterList , FormalParameter
  1. 如果 FormalParameterList 的 HasInitializer 是 true,则返回 true。
  2. 返回 FormalParameter 的 HasInitializer。

15.1.5 Static Semantics: ExpectedArgumentCount

语法制导操作 ExpectedArgumentCount,接收无参数;返回值:非负整数。 它按以下产生式分别定义:

FormalParameters : [empty] FunctionRestParameter
  1. 返回 0。
FormalParameters : FormalParameterList , FunctionRestParameter
  1. 返回 FormalParameterList 的 ExpectedArgumentCount。
注

FormalParameterList 的 ExpectedArgumentCount 是剩余参数或第一个具有 Initializer 的 FormalParameter 左侧的 FormalParameters 数量。在第一个具有初始化器的参数之后允许出现没有初始化器的 FormalParameter,但这些参数被视为可选参数,其默认值为 undefined。

FormalParameterList : FormalParameter
  1. 如果 FormalParameter 的 HasInitializer 是 true,则返回 0。
  2. 返回 1。
FormalParameterList : FormalParameterList , FormalParameter
  1. 令 count 为 FormalParameterList 的 ExpectedArgumentCount。
  2. 如果 FormalParameterList 的 HasInitializer 是 true 或 FormalParameter 的 HasInitializer 是 true,则返回 count。
  3. 返回 count + 1。
ArrowParameters : BindingIdentifier
  1. 返回 1。
ArrowParameters : CoverParenthesizedExpressionAndArrowParameterList
  1. 令 formals 为 CoverParenthesizedExpressionAndArrowParameterList 所覆盖的 ArrowFormalParameters。
  2. 返回 formals 的 ExpectedArgumentCount。
PropertySetParameterList : FormalParameter
  1. 如果 FormalParameter 的 HasInitializer 是 true,则返回 0。
  2. 返回 1。
AsyncArrowBindingIdentifier : BindingIdentifier
  1. 返回 1。

15.2 函数定义

语法

FunctionDeclaration[Yield, Await, Default] : function BindingIdentifier[?Yield, ?Await] ( FormalParameters[~Yield, ~Await] ) { FunctionBody[~Yield, ~Await] } [+Default] function ( FormalParameters[~Yield, ~Await] ) { FunctionBody[~Yield, ~Await] } FunctionExpression : function BindingIdentifier[~Yield, ~Await]opt ( FormalParameters[~Yield, ~Await] ) { FunctionBody[~Yield, ~Await] } FunctionBody[Yield, Await] : FunctionStatementList[?Yield, ?Await] FunctionStatementList[Yield, Await] : StatementList[?Yield, ?Await, +Return]opt

15.2.1 Static Semantics: 提前错误

FunctionDeclaration : function BindingIdentifier ( FormalParameters ) { FunctionBody } function ( FormalParameters ) { FunctionBody } FunctionExpression : function BindingIdentifieropt ( FormalParameters ) { FunctionBody } 注

FunctionBody 的 LexicallyDeclaredNames 不包括使用 var 或函数声明绑定的标识符。

FunctionBody : FunctionStatementList

15.2.2 Static Semantics: FunctionBodyContainsUseStrict

语法制导操作 FunctionBodyContainsUseStrict,接收无参数;返回值:Boolean。 它按以下产生式分别定义:

FunctionBody : FunctionStatementList
  1. 如果 FunctionBody 的指令序言包含 Use Strict 指令,则返回 true。
  2. 返回 false。

15.2.3 Runtime Semantics: EvaluateFunctionBody

语法制导操作 EvaluateFunctionBody,接收参数 funcObj (ECMAScript 函数对象) 和 argList (列表 (元素:ECMAScript 语言值));返回值:(返回完成 或 抛出完成)。 它按以下产生式分别定义:

FunctionBody : FunctionStatementList
  1. 执行 ? FunctionDeclarationInstantiation(funcObj, argList)。
  2. 执行 ? FunctionStatementList 的 Evaluation。
  3. 注:如果上一步产生正常完成,则求值通过越过 FunctionStatementList 的末尾而结束。
  4. 返回 ReturnCompletion(undefined)。

15.2.4 Runtime Semantics: InstantiateOrdinaryFunctionObject

语法制导操作 InstantiateOrdinaryFunctionObject,接收参数 envRecord (Environment 记录) 和 privateEnv ((PrivateEnvironment 记录 或 null));返回值:ECMAScript 函数对象。 它按以下产生式分别定义:

FunctionDeclaration : function BindingIdentifier ( FormalParameters ) { FunctionBody }
  1. 令 name 为 BindingIdentifier 的 StringValue。
  2. 令 sourceText 为 FunctionDeclaration 匹配的源文本。
  3. 令 closure 为 OrdinaryFunctionCreate(%Function.prototype%, sourceText, FormalParameters, FunctionBody, non-lexical-this, envRecord, privateEnv)。
  4. 执行 SetFunctionName(closure, name)。
  5. 执行 MakeConstructor(closure)。
  6. 返回 closure。
FunctionDeclaration : function ( FormalParameters ) { FunctionBody }
  1. 令 sourceText 为 FunctionDeclaration 匹配的源文本。
  2. 令 closure 为 OrdinaryFunctionCreate(%Function.prototype%, sourceText, FormalParameters, FunctionBody, non-lexical-this, envRecord, privateEnv)。
  3. 执行 SetFunctionName(closure, "default")。
  4. 执行 MakeConstructor(closure)。
  5. 返回 closure。
注

匿名 FunctionDeclaration 只能作为 export default 声明的一部分出现,因此其函数代码始终是严格模式代码。

15.2.5 Runtime Semantics: InstantiateOrdinaryFunctionExpression

语法制导操作 InstantiateOrdinaryFunctionExpression,接收可选参数 name ((属性键 或 私有名称));返回值:ECMAScript 函数对象。 它按以下产生式分别定义:

FunctionExpression : function ( FormalParameters ) { FunctionBody }
  1. 如果不存在 name,则将 name 设置为空 String。
  2. 令 envRecord 为正在运行的执行上下文的 LexicalEnvironment。
  3. 令 privateEnv 为正在运行的执行上下文的 PrivateEnvironment。
  4. 令 sourceText 为 FunctionExpression 匹配的源文本。
  5. 令 closure 为 OrdinaryFunctionCreate(%Function.prototype%, sourceText, FormalParameters, FunctionBody, non-lexical-this, envRecord, privateEnv)。
  6. 执行 SetFunctionName(closure, name)。
  7. 执行 MakeConstructor(closure)。
  8. 返回 closure。
FunctionExpression : function BindingIdentifier ( FormalParameters ) { FunctionBody }
  1. 断言:不存在 name。
  2. 将 name 设置为 BindingIdentifier 的 StringValue。
  3. 令 outerEnv 为正在运行的执行上下文的 LexicalEnvironment。
  4. 令 funcEnv 为 NewDeclarativeEnvironment(outerEnv)。
  5. 执行 ! funcEnv.CreateImmutableBinding(name, false)。
  6. 令 privateEnv 为正在运行的执行上下文的 PrivateEnvironment。
  7. 令 sourceText 为 FunctionExpression 匹配的源文本。
  8. 令 closure 为 OrdinaryFunctionCreate(%Function.prototype%, sourceText, FormalParameters, FunctionBody, non-lexical-this, funcEnv, privateEnv)。
  9. 执行 SetFunctionName(closure, name)。
  10. 执行 MakeConstructor(closure)。
  11. 执行 ! funcEnv.InitializeBinding(name, closure)。
  12. 返回 closure。
注

FunctionExpression 中的 BindingIdentifier 可以从 FunctionExpression 的 FunctionBody 内部引用,从而允许函数递归调用自身。但是,与 FunctionDeclaration 不同,FunctionExpression 中的 BindingIdentifier 无法从包围该 FunctionExpression 的作用域中引用,也不会影响该作用域。

15.2.6 Runtime Semantics: Evaluation

FunctionDeclaration : function BindingIdentifier ( FormalParameters ) { FunctionBody }
  1. 返回 empty。
注 1 FunctionDeclaration : function ( FormalParameters ) { FunctionBody }
  1. 返回 empty。
FunctionExpression : function BindingIdentifieropt ( FormalParameters ) { FunctionBody }
  1. 返回 FunctionExpression 的 InstantiateOrdinaryFunctionExpression。
注 2

对于使用 FunctionDeclaration 或 FunctionExpression 定义的每个函数,都会自动创建一个 "prototype" 属性,以允许该函数可能被用作构造函数。

FunctionStatementList : [empty]
  1. 返回 undefined。
FunctionStatementList : StatementList
  1. 令 result 为 Completion(StatementList 的 Evaluation)。
  2. 令 env 为正在运行的执行上下文的 LexicalEnvironment。
  3. 断言:env 是 Declarative Environment Record。
  4. 返回 ? DisposeResources(env.[[DisposableResourceStack]], result)。

15.3 箭头函数定义

语法

ArrowFunction[In, Yield, Await] : ArrowParameters[?Yield, ?Await] [no LineTerminator here] => ConciseBody[?In] ArrowParameters[Yield, Await] : BindingIdentifier[?Yield, ?Await] CoverParenthesizedExpressionAndArrowParameterList[?Yield, ?Await] ConciseBody[In] : [lookahead ≠ {] ExpressionBody[?In, ~Await] { FunctionBody[~Yield, ~Await] } ExpressionBody[In, Await] : AssignmentExpression[?In, ~Yield, ?Await]

补充语法

当处理产生式
ArrowParameters[Yield, Await] : CoverParenthesizedExpressionAndArrowParameterList[?Yield, ?Await]
的实例时,使用以下文法进一步细化对 CoverParenthesizedExpressionAndArrowParameterList 的解释:

ArrowFormalParameters[Yield, Await] : ( UniqueFormalParameters[?Yield, ?Await] )

15.3.1 Static Semantics: 提前错误

ArrowFunction : ArrowParameters => ConciseBody ArrowParameters : CoverParenthesizedExpressionAndArrowParameterList

15.3.2 Static Semantics: ConciseBodyContainsUseStrict

语法制导操作 ConciseBodyContainsUseStrict,接收无参数;返回值:Boolean。 它按以下产生式分别定义:

ConciseBody : ExpressionBody
  1. 返回 false。
ConciseBody : { FunctionBody }
  1. 返回 FunctionBody 的 FunctionBodyContainsUseStrict。

15.3.3 Runtime Semantics: EvaluateConciseBody

语法制导操作 EvaluateConciseBody,接收参数 funcObj (ECMAScript 函数对象) 和 argList (列表 (元素:ECMAScript 语言值));返回值:(返回完成 或 抛出完成)。 它按以下产生式分别定义:

ConciseBody : ExpressionBody
  1. 执行 ? FunctionDeclarationInstantiation(funcObj, argList)。
  2. 返回 ? ExpressionBody 的 Evaluation。

15.3.4 Runtime Semantics: InstantiateArrowFunctionExpression

语法制导操作 InstantiateArrowFunctionExpression,接收可选参数 name ((属性键 或 私有名称));返回值:ECMAScript 函数对象。 它按以下产生式分别定义:

ArrowFunction : ArrowParameters => ConciseBody
  1. 如果不存在 name,则将 name 设置为空 String。
  2. 令 envRecord 为正在运行的执行上下文的 LexicalEnvironment。
  3. 令 privateEnv 为正在运行的执行上下文的 PrivateEnvironment。
  4. 令 sourceText 为 ArrowFunction 匹配的源文本。
  5. 令 closure 为 OrdinaryFunctionCreate(%Function.prototype%, sourceText, ArrowParameters, ConciseBody, lexical-this, envRecord, privateEnv)。
  6. 执行 SetFunctionName(closure, name)。
  7. 返回 closure。
注

ArrowFunction 不会为 arguments、super、this 或 new.target 定义局部绑定。ArrowFunction 内对 arguments、super、this 或 new.target 的任何引用都必须解析到词法包围环境中的绑定。通常,这会是紧邻包围函数的 Function Environment。即使 ArrowFunction 可以包含对 super 的引用,步骤 5 中创建的函数对象也不会通过执行 MakeMethod 而成为方法。引用 super 的 ArrowFunction 始终包含在某个非 ArrowFunction 中,实现 super 所需的状态可通过由 ArrowFunction 函数对象捕获的 envRecord 访问。

15.3.5 Runtime Semantics: Evaluation

ArrowFunction : ArrowParameters => ConciseBody
  1. 返回 ArrowFunction 的 InstantiateArrowFunctionExpression。
ExpressionBody : AssignmentExpression
  1. 令 exprRef 为 ? AssignmentExpression 的 Evaluation。
  2. 令 exprValue 为 ? GetValue(exprRef)。
  3. 返回 ReturnCompletion(exprValue)。

15.4 方法定义

语法

MethodDefinition[Yield, Await] : ClassElementName[?Yield, ?Await] ( UniqueFormalParameters[~Yield, ~Await] ) { FunctionBody[~Yield, ~Await] } GeneratorMethod[?Yield, ?Await] AsyncMethod[?Yield, ?Await] AsyncGeneratorMethod[?Yield, ?Await] get ClassElementName[?Yield, ?Await] ( ) { FunctionBody[~Yield, ~Await] } set ClassElementName[?Yield, ?Await] ( PropertySetParameterList ) { FunctionBody[~Yield, ~Await] } PropertySetParameterList : FormalParameter[~Yield, ~Await]

15.4.1 Static Semantics: 提前错误

MethodDefinition : ClassElementName ( UniqueFormalParameters ) { FunctionBody } MethodDefinition : set ClassElementName ( PropertySetParameterList ) { FunctionBody }

15.4.2 Static Semantics: HasDirectSuper

语法制导操作 HasDirectSuper,接收无参数;返回值:Boolean。 它按以下产生式分别定义:

MethodDefinition : ClassElementName ( UniqueFormalParameters ) { FunctionBody }
  1. 如果 UniqueFormalParameters Contains SuperCall 是 true,则返回 true。
  2. 返回 FunctionBody Contains SuperCall。
MethodDefinition : get ClassElementName ( ) { FunctionBody }
  1. 返回 FunctionBody Contains SuperCall。
MethodDefinition : set ClassElementName ( PropertySetParameterList ) { FunctionBody }
  1. 如果 PropertySetParameterList Contains SuperCall 是 true,则返回 true。
  2. 返回 FunctionBody Contains SuperCall。
GeneratorMethod : * ClassElementName ( UniqueFormalParameters ) { GeneratorBody }
  1. 如果 UniqueFormalParameters Contains SuperCall 是 true,则返回 true。
  2. 返回 GeneratorBody Contains SuperCall。
AsyncGeneratorMethod : async * ClassElementName ( UniqueFormalParameters ) { AsyncGeneratorBody }
  1. 如果 UniqueFormalParameters Contains SuperCall 是 true,则返回 true。
  2. 返回 AsyncGeneratorBody Contains SuperCall。
AsyncMethod : async ClassElementName ( UniqueFormalParameters ) { AsyncFunctionBody }
  1. 如果 UniqueFormalParameters Contains SuperCall 是 true,则返回 true。
  2. 返回 AsyncFunctionBody Contains SuperCall。

15.4.3 Static Semantics: SpecialMethod

语法制导操作 SpecialMethod,接收无参数;返回值:Boolean。 它按以下产生式分别定义:

MethodDefinition : ClassElementName ( UniqueFormalParameters ) { FunctionBody }
  1. 返回 false。
MethodDefinition : GeneratorMethod AsyncMethod AsyncGeneratorMethod get ClassElementName ( ) { FunctionBody } set ClassElementName ( PropertySetParameterList ) { FunctionBody }
  1. 返回 true。

15.4.4 Runtime Semantics: DefineMethod

语法制导操作 DefineMethod,接收参数 obj (Object)和可选参数 proto (Object);返回值:(正常完成 (值:记录 (字段:[[Key]] (属性键), [[Closure]] (ECMAScript 函数对象))) 或 突兀完成)。 它按以下产生式分别定义:

MethodDefinition : ClassElementName ( UniqueFormalParameters ) { FunctionBody }
  1. 令 propertyKey 为 ? ClassElementName 的 Evaluation。
  2. 令 envRecord 为正在运行的执行上下文的 LexicalEnvironment。
  3. 令 privateEnv 为正在运行的执行上下文的 PrivateEnvironment。
  4. 如果不存在 proto,则将 proto 设置为 %Function.prototype%。
  5. 令 sourceText 为 MethodDefinition 匹配的源文本。
  6. 令 closure 为 OrdinaryFunctionCreate(proto, sourceText, UniqueFormalParameters, FunctionBody, non-lexical-this, envRecord, privateEnv)。
  7. 执行 MakeMethod(closure, obj)。
  8. 返回 Record { [[Key]]: propertyKey, [[Closure]]: closure }。

15.4.5 Runtime Semantics: MethodDefinitionEvaluation

语法制导操作 MethodDefinitionEvaluation,接收参数 obj (Object) 和 enumerable (Boolean);返回值:(正常完成 (值:(PrivateElement 或 empty)) 或 突兀完成)。 它按以下产生式分别定义:

MethodDefinition : ClassElementName ( UniqueFormalParameters ) { FunctionBody }
  1. 令 methodDef 为 ? 以 obj 为参数对 MethodDefinition 执行 DefineMethod 的结果。
  2. 执行 SetFunctionName(methodDef.[[Closure]], methodDef.[[Key]])。
  3. 返回 ? DefineMethodProperty(obj, methodDef.[[Key]], methodDef.[[Closure]], enumerable)。
MethodDefinition : get ClassElementName ( ) { FunctionBody }
  1. 令 propertyKey 为 ? ClassElementName 的 Evaluation。
  2. 令 envRecord 为正在运行的执行上下文的 LexicalEnvironment。
  3. 令 privateEnv 为正在运行的执行上下文的 PrivateEnvironment。
  4. 令 sourceText 为 MethodDefinition 匹配的源文本。
  5. 令 formalParamList 为产生式 FormalParameters : [empty] 的一个实例。
  6. 令 closure 为 OrdinaryFunctionCreate(%Function.prototype%, sourceText, formalParamList, FunctionBody, non-lexical-this, envRecord, privateEnv)。
  7. 执行 MakeMethod(closure, obj)。
  8. 执行 SetFunctionName(closure, propertyKey, "get")。
  9. 如果 propertyKey 是 Private Name,则
    1. 返回 PrivateElement { [[Key]]: propertyKey, [[Kind]]: accessor, [[Getter]]: closure, [[Setter]]: undefined }。
  10. 令 propertyDesc 为 PropertyDescriptor { [[Getter]]: closure, [[Enumerable]]: enumerable, [[Configurable]]: true }。
  11. 执行 ? DefinePropertyOrThrow(obj, propertyKey, propertyDesc)。
  12. 返回 empty。
MethodDefinition : set ClassElementName ( PropertySetParameterList ) { FunctionBody }
  1. 令 propertyKey 为 ? ClassElementName 的 Evaluation。
  2. 令 envRecord 为正在运行的执行上下文的 LexicalEnvironment。
  3. 令 privateEnv 为正在运行的执行上下文的 PrivateEnvironment。
  4. 令 sourceText 为 MethodDefinition 匹配的源文本。
  5. 令 closure 为 OrdinaryFunctionCreate(%Function.prototype%, sourceText, PropertySetParameterList, FunctionBody, non-lexical-this, envRecord, privateEnv)。
  6. 执行 MakeMethod(closure, obj)。
  7. 执行 SetFunctionName(closure, propertyKey, "set")。
  8. 如果 propertyKey 是 Private Name,则
    1. 返回 PrivateElement { [[Key]]: propertyKey, [[Kind]]: accessor, [[Getter]]: undefined, [[Setter]]: closure }。
  9. 令 propertyDesc 为 PropertyDescriptor { [[Setter]]: closure, [[Enumerable]]: enumerable, [[Configurable]]: true }。
  10. 执行 ? DefinePropertyOrThrow(obj, propertyKey, propertyDesc)。
  11. 返回 empty。
GeneratorMethod : * ClassElementName ( UniqueFormalParameters ) { GeneratorBody }
  1. 令 propertyKey 为 ? ClassElementName 的 Evaluation。
  2. 令 envRecord 为正在运行的执行上下文的 LexicalEnvironment。
  3. 令 privateEnv 为正在运行的执行上下文的 PrivateEnvironment。
  4. 令 sourceText 为 GeneratorMethod 匹配的源文本。
  5. 令 closure 为 OrdinaryFunctionCreate(%GeneratorFunction.prototype%, sourceText, UniqueFormalParameters, GeneratorBody, non-lexical-this, envRecord, privateEnv)。
  6. 执行 MakeMethod(closure, obj)。
  7. 执行 SetFunctionName(closure, propertyKey)。
  8. 令 proto 为 OrdinaryObjectCreate(%GeneratorPrototype%)。
  9. 执行 ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: proto, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  10. 返回 ? DefineMethodProperty(obj, propertyKey, closure, enumerable)。
AsyncGeneratorMethod : async * ClassElementName ( UniqueFormalParameters ) { AsyncGeneratorBody }
  1. 令 propertyKey 为 ? ClassElementName 的 Evaluation。
  2. 令 envRecord 为正在运行的执行上下文的 LexicalEnvironment。
  3. 令 privateEnv 为正在运行的执行上下文的 PrivateEnvironment。
  4. 令 sourceText 为 AsyncGeneratorMethod 匹配的源文本。
  5. 令 closure 为 OrdinaryFunctionCreate(%AsyncGeneratorFunction.prototype%, sourceText, UniqueFormalParameters, AsyncGeneratorBody, non-lexical-this, envRecord, privateEnv)。
  6. 执行 MakeMethod(closure, obj)。
  7. 执行 SetFunctionName(closure, propertyKey)。
  8. 令 proto 为 OrdinaryObjectCreate(%AsyncGeneratorPrototype%)。
  9. 执行 ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: proto, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  10. 返回 ? DefineMethodProperty(obj, propertyKey, closure, enumerable)。
AsyncMethod : async ClassElementName ( UniqueFormalParameters ) { AsyncFunctionBody }
  1. 令 propertyKey 为 ? ClassElementName 的 Evaluation。
  2. 令 envRecord 为正在运行的执行上下文的 LexicalEnvironment。
  3. 令 privateEnv 为正在运行的执行上下文的 PrivateEnvironment。
  4. 令 sourceText 为 AsyncMethod 匹配的源文本。
  5. 令 closure 为 OrdinaryFunctionCreate(%AsyncFunction.prototype%, sourceText, UniqueFormalParameters, AsyncFunctionBody, non-lexical-this, envRecord, privateEnv)。
  6. 执行 MakeMethod(closure, obj)。
  7. 执行 SetFunctionName(closure, propertyKey)。
  8. 返回 ? DefineMethodProperty(obj, propertyKey, closure, enumerable)。

15.5 生成器函数定义

语法

GeneratorDeclaration[Yield, Await, Default] : function * BindingIdentifier[?Yield, ?Await] ( FormalParameters[+Yield, ~Await] ) { GeneratorBody } [+Default] function * ( FormalParameters[+Yield, ~Await] ) { GeneratorBody } GeneratorExpression : function * BindingIdentifier[+Yield, ~Await]opt ( FormalParameters[+Yield, ~Await] ) { GeneratorBody } GeneratorMethod[Yield, Await] : * ClassElementName[?Yield, ?Await] ( UniqueFormalParameters[+Yield, ~Await] ) { GeneratorBody } GeneratorBody : FunctionBody[+Yield, ~Await] YieldExpression[In, Await] : yield yield [no LineTerminator here] AssignmentExpression[?In, +Yield, ?Await] yield [no LineTerminator here] * AssignmentExpression[?In, +Yield, ?Await] 注 1

紧跟 yield 之后的句法上下文要求使用 InputElementRegExpOrTemplateTail 词法目标。

注 2

YieldExpression 不能在生成器函数的 FormalParameters 中使用,因为作为 FormalParameters 一部分的任何表达式都会在生成的 Generator 进入可恢复状态之前求值。

注 3

与 Generator 相关的抽象操作定义于 27.8.3。

15.5.1 Static Semantics: 提前错误

GeneratorMethod : * ClassElementName ( UniqueFormalParameters ) { GeneratorBody } GeneratorDeclaration : function * BindingIdentifier ( FormalParameters ) { GeneratorBody } function * ( FormalParameters ) { GeneratorBody } GeneratorExpression : function * BindingIdentifieropt ( FormalParameters ) { GeneratorBody }

15.5.2 Runtime Semantics: EvaluateGeneratorBody

语法制导操作 EvaluateGeneratorBody,接收参数 funcObj (ECMAScript 函数对象) 和 argList (列表 (元素:ECMAScript 语言值));返回值:(抛出完成 或 返回完成)。 它按以下产生式分别定义:

GeneratorBody : FunctionBody
  1. 执行 ? FunctionDeclarationInstantiation(funcObj, argList)。
  2. 令 gen 为 ? OrdinaryCreateFromConstructor(funcObj, "%GeneratorPrototype%", « [[GeneratorState]], [[GeneratorContext]], [[GeneratorBrand]] »)。
  3. 将 gen.[[GeneratorBrand]] 设置为 empty。
  4. 将 gen.[[GeneratorState]] 设置为 suspended-start。
  5. 执行 GeneratorStart(gen, FunctionBody)。
  6. 返回 ReturnCompletion(gen)。

15.5.3 Runtime Semantics: InstantiateGeneratorFunctionObject

语法制导操作 InstantiateGeneratorFunctionObject,接收参数 envRecord (Environment 记录) 和 privateEnv ((PrivateEnvironment 记录 或 null));返回值:ECMAScript 函数对象。 它按以下产生式分别定义:

GeneratorDeclaration : function * BindingIdentifier ( FormalParameters ) { GeneratorBody }
  1. 令 name 为 BindingIdentifier 的 StringValue。
  2. 令 sourceText 为 GeneratorDeclaration 匹配的源文本。
  3. 令 closure 为 OrdinaryFunctionCreate(%GeneratorFunction.prototype%, sourceText, FormalParameters, GeneratorBody, non-lexical-this, envRecord, privateEnv)。
  4. 执行 SetFunctionName(closure, name)。
  5. 令 proto 为 OrdinaryObjectCreate(%GeneratorPrototype%)。
  6. 执行 ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: proto, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  7. 返回 closure。
GeneratorDeclaration : function * ( FormalParameters ) { GeneratorBody }
  1. 令 sourceText 为 GeneratorDeclaration 匹配的源文本。
  2. 令 closure 为 OrdinaryFunctionCreate(%GeneratorFunction.prototype%, sourceText, FormalParameters, GeneratorBody, non-lexical-this, envRecord, privateEnv)。
  3. 执行 SetFunctionName(closure, "default")。
  4. 令 proto 为 OrdinaryObjectCreate(%GeneratorPrototype%)。
  5. 执行 ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: proto, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  6. 返回 closure。
注

匿名 GeneratorDeclaration 只能作为 export default 声明的一部分出现,因此其函数代码始终是严格模式代码。

15.5.4 Runtime Semantics: InstantiateGeneratorFunctionExpression

语法制导操作 InstantiateGeneratorFunctionExpression,接收可选参数 name ((属性键 或 私有名称));返回值:ECMAScript 函数对象。 它按以下产生式分别定义:

GeneratorExpression : function * ( FormalParameters ) { GeneratorBody }
  1. 如果不存在 name,则将 name 设置为空 String。
  2. 令 envRecord 为正在运行的执行上下文的 LexicalEnvironment。
  3. 令 privateEnv 为正在运行的执行上下文的 PrivateEnvironment。
  4. 令 sourceText 为 GeneratorExpression 匹配的源文本。
  5. 令 closure 为 OrdinaryFunctionCreate(%GeneratorFunction.prototype%, sourceText, FormalParameters, GeneratorBody, non-lexical-this, envRecord, privateEnv)。
  6. 执行 SetFunctionName(closure, name)。
  7. 令 proto 为 OrdinaryObjectCreate(%GeneratorPrototype%)。
  8. 执行 ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: proto, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  9. 返回 closure。
GeneratorExpression : function * BindingIdentifier ( FormalParameters ) { GeneratorBody }
  1. 断言:不存在 name。
  2. 将 name 设置为 BindingIdentifier 的 StringValue。
  3. 令 outerEnv 为正在运行的执行上下文的 LexicalEnvironment。
  4. 令 funcEnv 为 NewDeclarativeEnvironment(outerEnv)。
  5. 执行 ! funcEnv.CreateImmutableBinding(name, false)。
  6. 令 privateEnv 为正在运行的执行上下文的 PrivateEnvironment。
  7. 令 sourceText 为 GeneratorExpression 匹配的源文本。
  8. 令 closure 为 OrdinaryFunctionCreate(%GeneratorFunction.prototype%, sourceText, FormalParameters, GeneratorBody, non-lexical-this, funcEnv, privateEnv)。
  9. 执行 SetFunctionName(closure, name)。
  10. 令 proto 为 OrdinaryObjectCreate(%GeneratorPrototype%)。
  11. 执行 ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: proto, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  12. 执行 ! funcEnv.InitializeBinding(name, closure)。
  13. 返回 closure。
注

GeneratorExpression 中的 BindingIdentifier 可以从 GeneratorExpression 的 FunctionBody 内部引用,从而允许生成器代码递归调用自身。但是,与 GeneratorDeclaration 不同,GeneratorExpression 中的 BindingIdentifier 无法从包围该 GeneratorExpression 的作用域中引用,也不会影响该作用域。

15.5.5 Runtime Semantics: Evaluation

GeneratorExpression : function * BindingIdentifieropt ( FormalParameters ) { GeneratorBody }
  1. 返回 GeneratorExpression 的 InstantiateGeneratorFunctionExpression。
YieldExpression : yield
  1. 返回 ? Yield(undefined)。
YieldExpression : yield AssignmentExpression
  1. 令 exprRef 为 ? AssignmentExpression 的 Evaluation。
  2. 令 value 为 ? GetValue(exprRef)。
  3. 返回 ? Yield(value)。
YieldExpression : yield * AssignmentExpression
  1. 令 genKind 为 GetGeneratorKind()。
  2. 断言:genKind 是 sync 或 async。
  3. 令 exprRef 为 ? AssignmentExpression 的 Evaluation。
  4. 令 value 为 ? GetValue(exprRef)。
  5. 令 iteratorRecord 为 ? GetIterator(value, genKind)。
  6. 令 iterator 为 iteratorRecord.[[Iterator]]。
  7. 令 received 为 NormalCompletion(undefined)。
  8. 重复执行,
    1. 如果 received 是正常完成,则
      1. 令 innerResult 为 ? Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]], « received.[[Value]] »)。
      2. 如果 genKind 是 async,则将 innerResult 设置为 ? Await(innerResult)。
      3. 如果 innerResult 不是 Object,则抛出 TypeError 异常。
      4. 令 done 为 ? IteratorComplete(innerResult)。
      5. 如果 done 是 true,则
        1. 返回 ? IteratorValue(innerResult)。
      6. 如果 genKind 是 async,则将 received 设置为 Completion(AsyncGeneratorYield(? IteratorValue(innerResult)))。
      7. 否则,将 received 设置为 Completion(GeneratorYield(innerResult))。
    2. 否则如果 received 是抛出完成,则
      1. 令 throw 为 ? GetMethod(iterator, "throw")。
      2. 如果 throw 不是 undefined,则
        1. 令 innerResult 为 ? Call(throw, iterator, « received.[[Value]] »)。
        2. 如果 genKind 是 async,则将 innerResult 设置为 ? Await(innerResult)。
        3. 注:来自内部迭代器 throw 方法的异常会被传播。内部 throw 方法的正常完成会以与内部 next 类似的方式处理。
        4. 如果 innerResult 不是 Object,则抛出 TypeError 异常。
        5. 令 done 为 ? IteratorComplete(innerResult)。
        6. 如果 done 是 true,则
          1. 返回 ? IteratorValue(innerResult)。
        7. 如果 genKind 是 async,则将 received 设置为 Completion(AsyncGeneratorYield(? IteratorValue(innerResult)))。
        8. 否则,将 received 设置为 Completion(GeneratorYield(innerResult))。
      3. 否则,
        1. 注:如果 iterator 没有 throw 方法,则此抛出将终止 yield* 循环。但首先需要给 iterator 清理的机会。
        2. 令 closeCompletion 为 NormalCompletion(empty)。
        3. 如果 genKind 是 async,则执行 ? AsyncIteratorClose(iteratorRecord, closeCompletion)。
        4. 否则,执行 ? IteratorClose(iteratorRecord, closeCompletion)。
        5. 注:下一步抛出 TypeError,以表示发生了 yield* 协议违反:iterator 没有 throw 方法。
        6. 抛出 TypeError 异常。
    3. 否则,
      1. 断言:received 是 return 完成。
      2. 令 return 为 ? GetMethod(iterator, "return")。
      3. 如果 return 是 undefined,则
        1. 令 receivedValue 为 received.[[Value]]。
        2. 如果 genKind 是 async,则
          1. 将 receivedValue 设置为 ? Await(receivedValue)。
        3. 返回 ReturnCompletion(receivedValue)。
      4. 令 innerReturnResult 为 ? Call(return, iterator, « received.[[Value]] »)。
      5. 如果 genKind 是 async,则将 innerReturnResult 设置为 ? Await(innerReturnResult)。
      6. 如果 innerReturnResult 不是 Object,则抛出 TypeError 异常。
      7. 令 done 为 ? IteratorComplete(innerReturnResult)。
      8. 如果 done 是 true,则
        1. 令 returnedValue 为 ? IteratorValue(innerReturnResult)。
        2. 返回 ReturnCompletion(returnedValue)。
      9. 如果 genKind 是 async,则将 received 设置为 Completion(AsyncGeneratorYield(? IteratorValue(innerReturnResult)))。
      10. 否则,将 received 设置为 Completion(GeneratorYield(innerReturnResult))。

15.6 异步生成器函数定义

语法

AsyncGeneratorDeclaration[Yield, Await, Default] : async [no LineTerminator here] function * BindingIdentifier[?Yield, ?Await] ( FormalParameters[+Yield, +Await] ) { AsyncGeneratorBody } [+Default] async [no LineTerminator here] function * ( FormalParameters[+Yield, +Await] ) { AsyncGeneratorBody } AsyncGeneratorExpression : async [no LineTerminator here] function * BindingIdentifier[+Yield, +Await]opt ( FormalParameters[+Yield, +Await] ) { AsyncGeneratorBody } AsyncGeneratorMethod[Yield, Await] : async [no LineTerminator here] * ClassElementName[?Yield, ?Await] ( UniqueFormalParameters[+Yield, +Await] ) { AsyncGeneratorBody } AsyncGeneratorBody : FunctionBody[+Yield, +Await] 注 1

YieldExpression 和 AwaitExpression 不能在异步生成器函数的 FormalParameters 中使用,因为作为 FormalParameters 一部分的任何表达式都会在生成的 AsyncGenerator 进入可恢复状态之前求值。

注 2

与 AsyncGenerator 相关的抽象操作定义于 27.9.3。

15.6.1 Static Semantics: 提前错误

AsyncGeneratorMethod : async * ClassElementName ( UniqueFormalParameters ) { AsyncGeneratorBody } AsyncGeneratorDeclaration : async function * BindingIdentifier ( FormalParameters ) { AsyncGeneratorBody } async function * ( FormalParameters ) { AsyncGeneratorBody } AsyncGeneratorExpression : async function * BindingIdentifieropt ( FormalParameters ) { AsyncGeneratorBody }

15.6.2 Runtime Semantics: EvaluateAsyncGeneratorBody

语法制导操作 EvaluateAsyncGeneratorBody,接收参数 funcObj (ECMAScript 函数对象) 和 argList (列表 (元素:ECMAScript 语言值));返回值:(抛出完成 或 返回完成)。 它按以下产生式分别定义:

AsyncGeneratorBody : FunctionBody
  1. 执行 ? FunctionDeclarationInstantiation(funcObj, argList)。
  2. 令 gen 为 ? OrdinaryCreateFromConstructor(funcObj, "%AsyncGeneratorPrototype%", « [[AsyncGeneratorState]], [[AsyncGeneratorContext]], [[AsyncGeneratorQueue]], [[GeneratorBrand]] »)。
  3. 将 gen.[[GeneratorBrand]] 设置为 empty。
  4. 将 gen.[[AsyncGeneratorState]] 设置为 suspended-start。
  5. 执行 AsyncGeneratorStart(gen, FunctionBody)。
  6. 返回 ReturnCompletion(gen)。

15.6.3 Runtime Semantics: InstantiateAsyncGeneratorFunctionObject

语法制导操作 InstantiateAsyncGeneratorFunctionObject,接收参数 envRecord (Environment 记录) 和 privateEnv ((PrivateEnvironment 记录 或 null));返回值:ECMAScript 函数对象。 它按以下产生式分别定义:

AsyncGeneratorDeclaration : async function * BindingIdentifier ( FormalParameters ) { AsyncGeneratorBody }
  1. 令 name 为 BindingIdentifier 的 StringValue。
  2. 令 sourceText 为 AsyncGeneratorDeclaration 匹配的源文本。
  3. 令 closure 为 OrdinaryFunctionCreate(%AsyncGeneratorFunction.prototype%, sourceText, FormalParameters, AsyncGeneratorBody, non-lexical-this, envRecord, privateEnv)。
  4. 执行 SetFunctionName(closure, name)。
  5. 令 proto 为 OrdinaryObjectCreate(%AsyncGeneratorPrototype%)。
  6. 执行 ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: proto, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  7. 返回 closure。
AsyncGeneratorDeclaration : async function * ( FormalParameters ) { AsyncGeneratorBody }
  1. 令 sourceText 为 AsyncGeneratorDeclaration 匹配的源文本。
  2. 令 closure 为 OrdinaryFunctionCreate(%AsyncGeneratorFunction.prototype%, sourceText, FormalParameters, AsyncGeneratorBody, non-lexical-this, envRecord, privateEnv)。
  3. 执行 SetFunctionName(closure, "default")。
  4. 令 proto 为 OrdinaryObjectCreate(%AsyncGeneratorPrototype%)。
  5. 执行 ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: proto, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  6. 返回 closure。
注

匿名 AsyncGeneratorDeclaration 只能作为 export default 声明的一部分出现。

15.6.4 Runtime Semantics: InstantiateAsyncGeneratorFunctionExpression

语法制导操作 InstantiateAsyncGeneratorFunctionExpression,接收可选参数 name ((属性键 或 私有名称));返回值:ECMAScript 函数对象。 它按以下产生式分别定义:

AsyncGeneratorExpression : async function * ( FormalParameters ) { AsyncGeneratorBody }
  1. 如果不存在 name,则将 name 设置为空 String。
  2. 令 envRecord 为正在运行的执行上下文的 LexicalEnvironment。
  3. 令 privateEnv 为正在运行的执行上下文的 PrivateEnvironment。
  4. 令 sourceText 为 AsyncGeneratorExpression 匹配的源文本。
  5. 令 closure 为 OrdinaryFunctionCreate(%AsyncGeneratorFunction.prototype%, sourceText, FormalParameters, AsyncGeneratorBody, non-lexical-this, envRecord, privateEnv)。
  6. 执行 SetFunctionName(closure, name)。
  7. 令 proto 为 OrdinaryObjectCreate(%AsyncGeneratorPrototype%)。
  8. 执行 ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: proto, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  9. 返回 closure。
AsyncGeneratorExpression : async function * BindingIdentifier ( FormalParameters ) { AsyncGeneratorBody }
  1. 断言:不存在 name。
  2. 将 name 设置为 BindingIdentifier 的 StringValue。
  3. 令 outerEnv 为正在运行的执行上下文的 LexicalEnvironment。
  4. 令 funcEnv 为 NewDeclarativeEnvironment(outerEnv)。
  5. 执行 ! funcEnv.CreateImmutableBinding(name, false)。
  6. 令 privateEnv 为正在运行的执行上下文的 PrivateEnvironment。
  7. 令 sourceText 为 AsyncGeneratorExpression 匹配的源文本。
  8. 令 closure 为 OrdinaryFunctionCreate(%AsyncGeneratorFunction.prototype%, sourceText, FormalParameters, AsyncGeneratorBody, non-lexical-this, funcEnv, privateEnv)。
  9. 执行 SetFunctionName(closure, name)。
  10. 令 proto 为 OrdinaryObjectCreate(%AsyncGeneratorPrototype%)。
  11. 执行 ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: proto, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  12. 执行 ! funcEnv.InitializeBinding(name, closure)。
  13. 返回 closure。
注

AsyncGeneratorExpression 中的 BindingIdentifier 可以从 AsyncGeneratorExpression 的 AsyncGeneratorBody 内部引用,从而允许生成器代码递归调用自身。但是,与 AsyncGeneratorDeclaration 不同,AsyncGeneratorExpression 中的 BindingIdentifier 无法从包围该 AsyncGeneratorExpression 的作用域中引用,也不会影响该作用域。

15.6.5 Runtime Semantics: Evaluation

AsyncGeneratorExpression : async function * BindingIdentifieropt ( FormalParameters ) { AsyncGeneratorBody }
  1. 返回 AsyncGeneratorExpression 的 InstantiateAsyncGeneratorFunctionExpression。

15.7 类定义

语法

ClassDeclaration[Yield, Await, Default] : class BindingIdentifier[?Yield, ?Await] ClassTail[?Yield, ?Await] [+Default] class ClassTail[?Yield, ?Await] ClassExpression[Yield, Await] : class BindingIdentifier[?Yield, ?Await]opt ClassTail[?Yield, ?Await] ClassTail[Yield, Await] : ClassHeritage[?Yield, ?Await]opt { ClassBody[?Yield, ?Await]opt } ClassHeritage[Yield, Await] : extends LeftHandSideExpression[?Yield, ?Await] ClassBody[Yield, Await] : ClassElementList[?Yield, ?Await] ClassElementList[Yield, Await] : ClassElement[?Yield, ?Await] ClassElementList[?Yield, ?Await] ClassElement[?Yield, ?Await] ClassElement[Yield, Await] : MethodDefinition[?Yield, ?Await] static MethodDefinition[?Yield, ?Await] FieldDefinition[?Yield, ?Await] ; static FieldDefinition[?Yield, ?Await] ; ClassStaticBlock ; FieldDefinition[Yield, Await] : ClassElementName[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]opt ClassElementName[Yield, Await] : PropertyName[?Yield, ?Await] PrivateIdentifier ClassStaticBlock : static { ClassStaticBlockBody } ClassStaticBlockBody : ClassStaticBlockStatementList ClassStaticBlockStatementList : StatementList[~Yield, +Await, ~Return]opt 注

类定义始终是严格模式代码。

15.7.1 Static Semantics: 提前错误

ClassTail : ClassHeritageopt { ClassBody } ClassBody : ClassElementList ClassElement : MethodDefinition ClassElement : static MethodDefinition ClassElement : FieldDefinition ; ClassElement : static FieldDefinition ; FieldDefinition : ClassElementName Initializeropt ClassElementName : PrivateIdentifier ClassStaticBlockBody : ClassStaticBlockStatementList

15.7.2 Static Semantics: ClassElementKind

语法制导操作 ClassElementKind,接收无参数;返回值:(constructor-method、non-constructor-method 或 empty)。 它按以下产生式分别定义:

ClassElement : MethodDefinition
  1. 如果 MethodDefinition 的 PropName 是 "constructor",则返回 constructor-method。
  2. 返回 non-constructor-method。
ClassElement : static MethodDefinition FieldDefinition ; static FieldDefinition ;
  1. 返回 non-constructor-method。
ClassElement : ClassStaticBlock
  1. 返回 non-constructor-method。
ClassElement : ;
  1. 返回 empty。

15.7.3 Static Semantics: ConstructorMethod

语法制导操作 ConstructorMethod,接收无参数;返回值:(a ClassElement Parse Node 或 empty)。 它按以下产生式分别定义:

ClassElementList : ClassElement
  1. 如果 ClassElement 的 ClassElementKind 是 constructor-method,则返回 ClassElement。
  2. 返回 empty。
ClassElementList : ClassElementList ClassElement
  1. 令 head 为 ClassElementList 的 ConstructorMethod。
  2. 如果 head 不是 empty,则返回 head。
  3. 如果 ClassElement 的 ClassElementKind 是 constructor-method,则返回 ClassElement。
  4. 返回 empty。
注

提前错误规则确保只有一个名为 "constructor" 的方法定义,并且它既不是访问器属性,也不是生成器定义。

15.7.4 Static Semantics: IsStatic

语法制导操作 IsStatic,接收无参数;返回值:Boolean。 它按以下产生式分别定义:

ClassElement : MethodDefinition
  1. 返回 false。
ClassElement : static MethodDefinition
  1. 返回 true。
ClassElement : FieldDefinition ;
  1. 返回 false。
ClassElement : static FieldDefinition ;
  1. 返回 true。
ClassElement : ClassStaticBlock
  1. 返回 true。
ClassElement : ;
  1. 返回 false。

15.7.5 Static Semantics: NonConstructorElements

语法制导操作 NonConstructorElements,接收无参数;返回值:列表 (元素:ClassElement Parse Nodes)。 它按以下产生式分别定义:

ClassElementList : ClassElement
  1. 如果 ClassElement 的 ClassElementKind 是 non-constructor-method,则
    1. 返回 « ClassElement »。
  2. 返回新的空 List。
ClassElementList : ClassElementList ClassElement
  1. 令 list 为 ClassElementList 的 NonConstructorElements。
  2. 如果 ClassElement 的 ClassElementKind 是 non-constructor-method,则
    1. 将 ClassElement 追加到 list。
  3. 返回 list。

15.7.6 Static Semantics: PrototypePropertyNameList

语法制导操作 PrototypePropertyNameList,接收无参数;返回值:列表 (元素:属性键)。 它按以下产生式分别定义:

ClassElementList : ClassElement
  1. 令 propertyName 为 ClassElement 的 PropName。
  2. 如果 propertyName 是 empty,则返回新的空 List。
  3. 如果 ClassElement 的 IsStatic 是 true,则返回新的空 List。
  4. 返回 « propertyName »。
ClassElementList : ClassElementList ClassElement
  1. 令 list 为 ClassElementList 的 PrototypePropertyNameList。
  2. 令 propertyName 为 ClassElement 的 PropName。
  3. 如果 propertyName 是 empty,则返回 list。
  4. 如果 ClassElement 的 IsStatic 是 true,则返回 list。
  5. 返回 list 和 « propertyName » 的列表连接。

15.7.7 Static Semantics: AllPrivateIdentifiersValid

语法制导操作 AllPrivateIdentifiersValid,接收参数 names (列表 (元素:String));返回值:Boolean。

本规范中未在下方列出的每个文法产生式替代项,都隐式具有以下 AllPrivateIdentifiersValid 默认定义:

  1. 对此 Parse Node 的每个子节点 child,执行
    1. 如果 child 是某个非终结符的实例,则
      1. 如果以 names 为参数对 child 执行 AllPrivateIdentifiersValid 的结果是 false,则返回 false。
  2. 返回 true。
MemberExpression : MemberExpression . PrivateIdentifier
  1. 如果 names 包含 PrivateIdentifier 的 StringValue,则
    1. 返回以 names 为参数对 MemberExpression 执行 AllPrivateIdentifiersValid 的结果。
  2. 返回 false。
CallExpression : CallExpression . PrivateIdentifier
  1. 如果 names 包含 PrivateIdentifier 的 StringValue,则
    1. 返回以 names 为参数对 CallExpression 执行 AllPrivateIdentifiersValid 的结果。
  2. 返回 false。
OptionalChain : ?. PrivateIdentifier
  1. 如果 names 包含 PrivateIdentifier 的 StringValue,则返回 true。
  2. 返回 false。
OptionalChain : OptionalChain . PrivateIdentifier
  1. 如果 names 包含 PrivateIdentifier 的 StringValue,则
    1. 返回以 names 为参数对 OptionalChain 执行 AllPrivateIdentifiersValid 的结果。
  2. 返回 false。
ClassBody : ClassElementList
  1. 令 newNames 为 names 与 ClassBody 的 PrivateBoundIdentifiers 的列表连接。
  2. 返回以 newNames 为参数对 ClassElementList 执行 AllPrivateIdentifiersValid 的结果。
RelationalExpression : PrivateIdentifier in ShiftExpression
  1. 如果 names 包含 PrivateIdentifier 的 StringValue,则
    1. 返回以 names 为参数对 ShiftExpression 执行 AllPrivateIdentifiersValid 的结果。
  2. 返回 false。

15.7.8 Static Semantics: PrivateBoundIdentifiers

语法制导操作 PrivateBoundIdentifiers,接收无参数;返回值:列表 (元素:String)。 它按以下产生式分别定义:

FieldDefinition : ClassElementName Initializeropt
  1. 返回 ClassElementName 的 PrivateBoundIdentifiers。
ClassElementName : PrivateIdentifier
  1. 返回一个 List,其唯一元素是 PrivateIdentifier 的 StringValue。
ClassElementName : PropertyName ClassElement : ClassStaticBlock ;
  1. 返回新的空 List。
ClassElementList : ClassElementList ClassElement
  1. 令 names1 为 ClassElementList 的 PrivateBoundIdentifiers。
  2. 令 names2 为 ClassElement 的 PrivateBoundIdentifiers。
  3. 返回 names1 和 names2 的列表连接。
MethodDefinition : ClassElementName ( UniqueFormalParameters ) { FunctionBody } get ClassElementName ( ) { FunctionBody } set ClassElementName ( PropertySetParameterList ) { FunctionBody } GeneratorMethod : * ClassElementName ( UniqueFormalParameters ) { GeneratorBody } AsyncMethod : async ClassElementName ( UniqueFormalParameters ) { AsyncFunctionBody } AsyncGeneratorMethod : async * ClassElementName ( UniqueFormalParameters ) { AsyncGeneratorBody }
  1. 返回 ClassElementName 的 PrivateBoundIdentifiers。

15.7.9 Static Semantics: ContainsArguments

语法制导操作 ContainsArguments,接收无参数;返回值:Boolean。

本规范中未在下方列出的每个文法产生式替代项,都隐式具有以下 ContainsArguments 默认定义:

  1. 对此 Parse Node 的每个子节点 child,执行
    1. 如果 child 是某个非终结符的实例,则
      1. 如果 child 的 ContainsArguments 是 true,则返回 true。
  2. 返回 false。
IdentifierReference : Identifier
  1. 如果 Identifier 的 StringValue 是 "arguments",则返回 true。
  2. 返回 false。
FunctionDeclaration : function BindingIdentifier ( FormalParameters ) { FunctionBody } function ( FormalParameters ) { FunctionBody } FunctionExpression : function BindingIdentifieropt ( FormalParameters ) { FunctionBody } GeneratorDeclaration : function * BindingIdentifier ( FormalParameters ) { GeneratorBody } function * ( FormalParameters ) { GeneratorBody } GeneratorExpression : function * BindingIdentifieropt ( FormalParameters ) { GeneratorBody } AsyncGeneratorDeclaration : async function * BindingIdentifier ( FormalParameters ) { AsyncGeneratorBody } async function * ( FormalParameters ) { AsyncGeneratorBody } AsyncGeneratorExpression : async function * BindingIdentifieropt ( FormalParameters ) { AsyncGeneratorBody } AsyncFunctionDeclaration : async function BindingIdentifier ( FormalParameters ) { AsyncFunctionBody } async function ( FormalParameters ) { AsyncFunctionBody } AsyncFunctionExpression : async function BindingIdentifieropt ( FormalParameters ) { AsyncFunctionBody }
  1. 返回 false。
MethodDefinition : ClassElementName ( UniqueFormalParameters ) { FunctionBody } get ClassElementName ( ) { FunctionBody } set ClassElementName ( PropertySetParameterList ) { FunctionBody } GeneratorMethod : * ClassElementName ( UniqueFormalParameters ) { GeneratorBody } AsyncGeneratorMethod : async * ClassElementName ( UniqueFormalParameters ) { AsyncGeneratorBody } AsyncMethod : async ClassElementName ( UniqueFormalParameters ) { AsyncFunctionBody }
  1. 返回 ClassElementName 的 ContainsArguments。

15.7.10 Runtime Semantics: ClassFieldDefinitionEvaluation

语法制导操作 ClassFieldDefinitionEvaluation,接收参数 homeObj (Object);返回值:(正常完成 (值:ClassFieldDefinition 记录) 或 突兀完成)。 它按以下产生式分别定义:

FieldDefinition : ClassElementName Initializeropt
  1. 令 name 为 ? ClassElementName 的 Evaluation。
  2. 如果存在 Initializer,则
    1. 令 formalParamList 为产生式 FormalParameters : [empty] 的一个实例。
    2. 令 envRecord 为正在运行的执行上下文的 LexicalEnvironment。
    3. 令 privateEnv 为正在运行的执行上下文的 PrivateEnvironment。
    4. 令 sourceText 为空 Unicode 码点序列。
    5. 令 initializer 为 OrdinaryFunctionCreate(%Function.prototype%, sourceText, formalParamList, Initializer, non-lexical-this, envRecord, privateEnv)。
    6. 执行 MakeMethod(initializer, homeObj)。
    7. 将 initializer.[[ClassFieldInitializerName]] 设置为 name。
  3. 否则,
    1. 令 initializer 为 empty。
  4. 返回 ClassFieldDefinition Record { [[Name]]: name, [[Initializer]]: initializer }。
注
为 initializer 创建的函数永远无法被 ECMAScript 代码直接访问。

15.7.11 Runtime Semantics: ClassStaticBlockDefinitionEvaluation

语法制导操作 ClassStaticBlockDefinitionEvaluation,接收参数 homeObj (Object);返回值:ClassStaticBlockDefinition 记录。 它按以下产生式分别定义:

ClassStaticBlock : static { ClassStaticBlockBody }
  1. 令 lexicalEnv 为正在运行的执行上下文的 LexicalEnvironment。
  2. 令 privateEnv 为正在运行的执行上下文的 PrivateEnvironment。
  3. 令 sourceText 为空 Unicode 码点序列。
  4. 令 formalParams 为产生式 FormalParameters : [empty] 的一个实例。
  5. 令 bodyFunc 为 OrdinaryFunctionCreate(%Function.prototype%, sourceText, formalParams, ClassStaticBlockBody, non-lexical-this, lexicalEnv, privateEnv)。
  6. 执行 MakeMethod(bodyFunc, homeObj)。
  7. 返回 ClassStaticBlockDefinition Record { [[BodyFunction]]: bodyFunc }。
注
函数 bodyFunc 永远无法被 ECMAScript 代码直接访问。

15.7.12 Runtime Semantics: EvaluateClassStaticBlockBody

语法制导操作 EvaluateClassStaticBlockBody,接收参数 funcObj (ECMAScript 函数对象);返回值:(返回完成 或 抛出完成)。 它按以下产生式分别定义:

ClassStaticBlockBody : ClassStaticBlockStatementList
  1. 断言:funcObj 是由 ClassStaticBlockDefinitionEvaluation 的步骤 5 创建的合成函数。
  2. 执行 ! FunctionDeclarationInstantiation(funcObj, « »)。
  3. 令 result 为 Completion(ClassStaticBlockStatementList 的 Evaluation)。
  4. 令 envRecord 为正在运行的执行上下文的 LexicalEnvironment。
  5. 断言:envRecord 是 Declarative Environment Record。
  6. 执行 ? DisposeResources(envRecord.[[DisposableResourceStack]], result)。
  7. 返回 ReturnCompletion(undefined)。

15.7.13 Runtime Semantics: ClassElementEvaluation

语法制导操作 ClassElementEvaluation,接收参数 obj (Object);返回值:(正常完成 (值:(ClassFieldDefinition 记录、ClassStaticBlockDefinition 记录、PrivateElement 或 empty)) 或 突兀完成)。 它按以下产生式分别定义:

ClassElement : FieldDefinition ; static FieldDefinition ;
  1. 返回 ? 以 obj 为参数对 FieldDefinition 执行 ClassFieldDefinitionEvaluation 的结果。
ClassElement : MethodDefinition static MethodDefinition
  1. 返回 ? 以 obj 和 false 为参数对 MethodDefinition 执行 MethodDefinitionEvaluation 的结果。
ClassElement : ClassStaticBlock
  1. 返回以 obj 为参数对 ClassStaticBlock 执行 ClassStaticBlockDefinitionEvaluation 的结果。
ClassElement : ;
  1. 返回 empty。

15.7.14 Runtime Semantics: ClassDefinitionEvaluation

语法制导操作 ClassDefinitionEvaluation,接收参数 classBinding ((String 或 undefined))、className ((属性键 或 私有名称)) 和 sourceText (ECMAScript 源文本);返回值:(正常完成 (值:函数对象) 或 突兀完成)。

注

为了便于规范描述,私有方法和访问器与私有字段一起包含在类实例的 [[PrivateElements]] 槽中。不过,对于给定类定义的私有方法和访问器,任意给定对象要么全部具有,要么一个也没有。此特性的设计允许实现选择一种不需要单独跟踪每个方法或访问器的策略来实现私有方法和访问器。

例如,实现可以直接将实例私有方法与其对应的 Private Name 关联,并针对每个对象跟踪哪些类构造函数曾以该对象作为其 this 值运行。随后,在对象上查找实例私有方法时,只需检查定义该方法的类构造函数是否已用于初始化该对象,然后返回与 Private Name 关联的方法。

这与私有字段不同:因为字段初始化器可能在类实例化期间抛出异常,所以单个对象可能只具有给定类私有字段的某个真子集,因此通常必须单独跟踪私有字段。

它按以下产生式分别定义:

ClassTail : ClassHeritageopt { ClassBodyopt }
  1. 令 envRecord 为正在运行的执行上下文的 LexicalEnvironment。
  2. 令 classEnv 为 NewDeclarativeEnvironment(envRecord)。
  3. 如果 classBinding 不是 undefined,则
    1. 执行 ! classEnv.CreateImmutableBinding(classBinding, true)。
  4. 令 outerPrivateEnv 为正在运行的执行上下文的 PrivateEnvironment。
  5. 令 classPrivateEnv 为 NewPrivateEnvironment(outerPrivateEnv)。
  6. 如果存在 ClassBody,则
    1. 对 ClassBody 的 PrivateBoundIdentifiers 的每个 String description,执行
      1. 如果 classPrivateEnv.[[Names]] 包含一个 Private Name privateName,使得 privateName.[[Description]] 是 description,则
        1. 断言:这种情况只可能发生在 getter/setter 对上。
      2. 否则,
        1. 令 name 为一个新的 Private Name,其 [[Description]] 为 description。
        2. 将 name 追加到 classPrivateEnv.[[Names]]。
  7. 如果不存在 ClassHeritage,则
    1. 令 protoParent 为 %Object.prototype%。
    2. 令 ctorParent 为 %Function.prototype%。
  8. 否则,
    1. 将正在运行的执行上下文的 LexicalEnvironment 设置为 classEnv。
    2. 注:对 ClassHeritage 求值时,正在运行的执行上下文的 PrivateEnvironment 是 outerPrivateEnv。
    3. 令 superclassRef 为 Completion(ClassHeritage 的 Evaluation)。
    4. 将正在运行的执行上下文的 LexicalEnvironment 设置为 envRecord。
    5. 令 superclass 为 ? GetValue(? superclassRef)。
    6. 如果 superclass 是 null,则
      1. 令 protoParent 为 null。
      2. 令 ctorParent 为 %Function.prototype%。
    7. 否则如果 IsConstructor(superclass) 是 false,则
      1. 抛出 TypeError 异常。
    8. 否则,
      1. 令 protoParent 为 ? Get(superclass, "prototype")。
      2. 如果 protoParent 不是 Object 且 protoParent 不是 null,则抛出 TypeError 异常。
      3. 令 ctorParent 为 superclass。
  9. 令 proto 为 OrdinaryObjectCreate(protoParent)。
  10. 如果不存在 ClassBody,则令 ctor 为 empty。
  11. 否则,令 ctor 为 ClassBody 的 ConstructorMethod。
  12. 将正在运行的执行上下文的 LexicalEnvironment 设置为 classEnv。
  13. 将正在运行的执行上下文的 PrivateEnvironment 设置为 classPrivateEnv。
  14. 如果 ctor 是 empty,则
    1. 令 defaultCtor 为一个没有参数、且不捕获任何内容的新 Abstract Closure,它在被调用时执行以下步骤:
      1. 令 args 为通过 [[Call]] 或 [[Construct]] 传给此函数的参数 List。
      2. 如果 NewTarget 是 undefined,则抛出 TypeError 异常。
      3. 令 ctorFunc 为活动函数对象。
      4. 如果 ctorFunc.[[ConstructorKind]] 是 derived,则
        1. 注:此分支的行为类似于 constructor(...args) { super(...args); }。最显著的区别是,前述 ECMAScript 源文本会以可观察方式调用 %Array.prototype% 上的 %Symbol.iterator% 方法,而此函数不会。
        2. 令 func 为 ! ctorFunc.[[GetPrototypeOf]]()。
        3. 如果 IsConstructor(func) 是 false,则抛出 TypeError 异常。
        4. 令 result 为 ? Construct(func, args, NewTarget)。
      5. 否则,
        1. 注:此分支的行为类似于 constructor() {}。
        2. 令 result 为 ? OrdinaryCreateFromConstructor(NewTarget, "%Object.prototype%")。
      6. 执行 ? InitializeInstanceElements(result, ctorFunc)。
      7. 返回 NormalCompletion(result)。
    2. 令 ctorFunc 为 CreateBuiltinFunction(defaultCtor, 0, className, « [[ConstructorKind]], [[SourceText]], [[PrivateMethods]], [[Fields]] », 当前 Realm Record, ctorParent)。
  15. 否则,
    1. 令 ctorInfo 为 ! 以 proto 和 ctorParent 为参数对 ctor 执行 DefineMethod 的结果。
    2. 令 ctorFunc 为 ctorInfo.[[Closure]]。
    3. 执行 MakeClassConstructor(ctorFunc)。
    4. 执行 SetFunctionName(ctorFunc, className)。
  16. 将 ctorFunc.[[SourceText]] 设置为 sourceText。
  17. 执行 MakeConstructor(ctorFunc, false, proto)。
  18. 如果存在 ClassHeritage,则将 ctorFunc.[[ConstructorKind]] 设置为 derived。
  19. 执行 ! DefineMethodProperty(proto, "constructor", ctorFunc, false)。
  20. 如果不存在 ClassBody,则令 classElements 为新的空 List。
  21. 否则,令 classElements 为 ClassBody 的 NonConstructorElements。
  22. 令 instancePrivateMethods 为新的空 List。
  23. 令 staticPrivateMethods 为新的空 List。
  24. 令 instanceFields 为新的空 List。
  25. 令 staticElements 为新的空 List。
  26. 对 classElements 的每个 ClassElement classElement,执行
    1. 如果 classElement 的 IsStatic 是 false,则
      1. 令 element 为 Completion(以 proto 为参数对 classElement 执行 ClassElementEvaluation 的结果)。
    2. 否则,
      1. 令 element 为 Completion(以 ctorFunc 为参数对 classElement 执行 ClassElementEvaluation 的结果)。
    3. 如果 element 是突然完成,则
      1. 将正在运行的执行上下文的 LexicalEnvironment 设置为 envRecord。
      2. 将正在运行的执行上下文的 PrivateEnvironment 设置为 outerPrivateEnv。
      3. 返回 ? element。
    4. 将 element 设置为 ! element。
    5. 如果 element 是 PrivateElement,则
      1. 断言:element.[[Kind]] 是 method 或 accessor。
      2. 如果 classElement 的 IsStatic 是 false,则令 container 为 instancePrivateMethods。
      3. 否则,令 container 为 staticPrivateMethods。
      4. 如果 container 包含一个 PrivateElement existingElement,使得 existingElement.[[Key]] 是 element.[[Key]],则
        1. 断言:element.[[Kind]] 和 existingElement.[[Kind]] 都是 accessor。
        2. 如果 element.[[Getter]] 是 undefined,则
          1. 令 combined 为 PrivateElement { [[Key]]: element.[[Key]], [[Kind]]: accessor, [[Getter]]: existingElement.[[Getter]], [[Setter]]: element.[[Setter]] }。
        3. 否则,
          1. 令 combined 为 PrivateElement { [[Key]]: element.[[Key]], [[Kind]]: accessor, [[Getter]]: element.[[Getter]], [[Setter]]: existingElement.[[Setter]] }。
        4. 用 combined 替换 container 中的 existingElement。
      5. 否则,
        1. 将 element 追加到 container。
    6. 否则如果 element 是 ClassFieldDefinition Record,则
      1. 如果 classElement 的 IsStatic 是 false,则将 element 追加到 instanceFields。
      2. 否则,将 element 追加到 staticElements。
    7. 否则如果 element 是 ClassStaticBlockDefinition Record,则
      1. 将 element 追加到 staticElements。
    8. 否则,
      1. 断言:element 是 empty。
  27. 将正在运行的执行上下文的 LexicalEnvironment 设置为 envRecord。
  28. 如果 classBinding 不是 undefined,则
    1. 执行 ! classEnv.InitializeBinding(classBinding, ctorFunc)。
  29. 将 ctorFunc.[[PrivateMethods]] 设置为 instancePrivateMethods。
  30. 将 ctorFunc.[[Fields]] 设置为 instanceFields。
  31. 对 staticPrivateMethods 的每个 PrivateElement method,执行
    1. 执行 ! PrivateMethodOrAccessorAdd(ctorFunc, method)。
  32. 对 staticElements 的每个元素 elementRecord,执行
    1. 如果 elementRecord 是 ClassFieldDefinition Record,则
      1. 令 result 为 Completion(DefineField(ctorFunc, elementRecord))。
    2. 否则,
      1. 断言:elementRecord 是 ClassStaticBlockDefinition Record。
      2. 令 result 为 Completion(Call(elementRecord.[[BodyFunction]], ctorFunc))。
    3. 如果 result 是突然完成,则
      1. 将正在运行的执行上下文的 PrivateEnvironment 设置为 outerPrivateEnv。
      2. 返回 ? result。
  33. 将正在运行的执行上下文的 PrivateEnvironment 设置为 outerPrivateEnv。
  34. 返回 ctorFunc。

15.7.15 Runtime Semantics: BindingClassDeclarationEvaluation

语法制导操作 BindingClassDeclarationEvaluation,接收无参数;返回值:(正常完成 (值:函数对象) 或 突兀完成)。 它按以下产生式分别定义:

ClassDeclaration : class BindingIdentifier ClassTail
  1. 令 className 为 BindingIdentifier 的 StringValue。
  2. 令 sourceText 为 ClassDeclaration 匹配的源文本。
  3. 令 value 为 ? 以 className、className 和 sourceText 为参数对 ClassTail 执行 ClassDefinitionEvaluation 的结果。
  4. 令 envRecord 为正在运行的执行上下文的 LexicalEnvironment。
  5. 执行 ? InitializeBoundName(className, value, envRecord)。
  6. 返回 value。
ClassDeclaration : class ClassTail
  1. 令 sourceText 为 ClassDeclaration 匹配的源文本。
  2. 返回 ? 以 undefined、"default" 和 sourceText 为参数对 ClassTail 执行 ClassDefinitionEvaluation 的结果。
注

ClassDeclaration : class ClassTail 仅作为 ExportDeclaration 的一部分出现,并且建立其绑定的操作作为该产生式求值操作的一部分处理。参见 16.2.3.7。

15.7.16 Runtime Semantics: Evaluation

ClassDeclaration : class BindingIdentifier ClassTail
  1. 执行 ? 当前 ClassDeclaration 的 BindingClassDeclarationEvaluation。
  2. 返回 empty。
注

ClassDeclaration : class ClassTail 仅作为 ExportDeclaration 的一部分出现,绝不会被直接求值。

ClassExpression : class ClassTail
  1. 令 sourceText 为 ClassExpression 匹配的源文本。
  2. 返回 ? 以 undefined、空 String 和 sourceText 为参数对 ClassTail 执行 ClassDefinitionEvaluation 的结果。
ClassExpression : class BindingIdentifier ClassTail
  1. 令 className 为 BindingIdentifier 的 StringValue。
  2. 令 sourceText 为 ClassExpression 匹配的源文本。
  3. 返回 ? 以 className、className 和 sourceText 为参数对 ClassTail 执行 ClassDefinitionEvaluation 的结果。
ClassElementName : PrivateIdentifier
  1. 令 privateIdentifier 为 PrivateIdentifier 的 StringValue。
  2. 令 privateEnvRecord 为正在运行的执行上下文的 PrivateEnvironment。
  3. 令 names 为 privateEnvRecord.[[Names]]。
  4. 断言:names 中恰好有一个元素是 [[Description]] 为 privateIdentifier 的 Private Name。
  5. 令 privateName 为 names 中 [[Description]] 为 privateIdentifier 的 Private Name。
  6. 返回 privateName。
ClassStaticBlockStatementList : [empty]
  1. 返回 undefined。

15.8 异步函数定义

语法

AsyncFunctionDeclaration[Yield, Await, Default] : async [no LineTerminator here] function BindingIdentifier[?Yield, ?Await] ( FormalParameters[~Yield, +Await] ) { AsyncFunctionBody } [+Default] async [no LineTerminator here] function ( FormalParameters[~Yield, +Await] ) { AsyncFunctionBody } AsyncFunctionExpression : async [no LineTerminator here] function BindingIdentifier[~Yield, +Await]opt ( FormalParameters[~Yield, +Await] ) { AsyncFunctionBody } AsyncMethod[Yield, Await] : async [no LineTerminator here] ClassElementName[?Yield, ?Await] ( UniqueFormalParameters[~Yield, +Await] ) { AsyncFunctionBody } AsyncFunctionBody : FunctionBody[~Yield, +Await] AwaitExpression[Yield] : await UnaryExpression[?Yield, +Await] 注 1

当存在 [Await] 参数时,await 会被解析为 AwaitExpression 的关键字。以下上下文的顶层存在 [Await] 参数,不过取决于 FunctionBody 等非终结符,在某些上下文中该参数可能不存在:

当 Script 是句法目标符号时,如果不存在 [Await] 参数,则 await 可以被解析为标识符。这包括以下上下文:

注 2

与 YieldExpression 不同,省略 AwaitExpression 的操作数是语法错误。必须等待某个值。

15.8.1 Static Semantics: 提前错误

AsyncMethod : async ClassElementName ( UniqueFormalParameters ) { AsyncFunctionBody } AsyncFunctionDeclaration : async function BindingIdentifier ( FormalParameters ) { AsyncFunctionBody } async function ( FormalParameters ) { AsyncFunctionBody } AsyncFunctionExpression : async function BindingIdentifieropt ( FormalParameters ) { AsyncFunctionBody }

15.8.2 Runtime Semantics: InstantiateAsyncFunctionObject

语法制导操作 InstantiateAsyncFunctionObject,接收参数 envRecord (Environment 记录) 和 privateEnv ((PrivateEnvironment 记录 或 null));返回值:ECMAScript 函数对象。 它按以下产生式分别定义:

AsyncFunctionDeclaration : async function BindingIdentifier ( FormalParameters ) { AsyncFunctionBody }
  1. 令 name 为 BindingIdentifier 的 StringValue。
  2. 令 sourceText 为 AsyncFunctionDeclaration 匹配的源文本。
  3. 令 closure 为 OrdinaryFunctionCreate(%AsyncFunction.prototype%, sourceText, FormalParameters, AsyncFunctionBody, non-lexical-this, envRecord, privateEnv)。
  4. 执行 SetFunctionName(closure, name)。
  5. 返回 closure。
AsyncFunctionDeclaration : async function ( FormalParameters ) { AsyncFunctionBody }
  1. 令 sourceText 为 AsyncFunctionDeclaration 匹配的源文本。
  2. 令 closure 为 OrdinaryFunctionCreate(%AsyncFunction.prototype%, sourceText, FormalParameters, AsyncFunctionBody, non-lexical-this, envRecord, privateEnv)。
  3. 执行 SetFunctionName(closure, "default")。
  4. 返回 closure。

15.8.3 Runtime Semantics: InstantiateAsyncFunctionExpression

语法制导操作 InstantiateAsyncFunctionExpression,接收可选参数 name ((属性键 或 私有名称));返回值:ECMAScript 函数对象。 它按以下产生式分别定义:

AsyncFunctionExpression : async function ( FormalParameters ) { AsyncFunctionBody }
  1. 如果不存在 name,则将 name 设置为空 String。
  2. 令 envRecord 为正在运行的执行上下文的 LexicalEnvironment。
  3. 令 privateEnv 为正在运行的执行上下文的 PrivateEnvironment。
  4. 令 sourceText 为 AsyncFunctionExpression 匹配的源文本。
  5. 令 closure 为 OrdinaryFunctionCreate(%AsyncFunction.prototype%, sourceText, FormalParameters, AsyncFunctionBody, non-lexical-this, envRecord, privateEnv)。
  6. 执行 SetFunctionName(closure, name)。
  7. 返回 closure。
AsyncFunctionExpression : async function BindingIdentifier ( FormalParameters ) { AsyncFunctionBody }
  1. 断言:不存在 name。
  2. 将 name 设置为 BindingIdentifier 的 StringValue。
  3. 令 outerEnv 为正在运行的执行上下文的 LexicalEnvironment。
  4. 令 funcEnv 为 NewDeclarativeEnvironment(outerEnv)。
  5. 执行 ! funcEnv.CreateImmutableBinding(name, false)。
  6. 令 privateEnv 为正在运行的执行上下文的 PrivateEnvironment。
  7. 令 sourceText 为 AsyncFunctionExpression 匹配的源文本。
  8. 令 closure 为 OrdinaryFunctionCreate(%AsyncFunction.prototype%, sourceText, FormalParameters, AsyncFunctionBody, non-lexical-this, funcEnv, privateEnv)。
  9. 执行 SetFunctionName(closure, name)。
  10. 执行 ! funcEnv.InitializeBinding(name, closure)。
  11. 返回 closure。
注

AsyncFunctionExpression 中的 BindingIdentifier 可以从 AsyncFunctionExpression 的 AsyncFunctionBody 内部引用,从而允许函数递归调用自身。但是,与 FunctionDeclaration 不同,AsyncFunctionExpression 中的 BindingIdentifier 无法从包围该 AsyncFunctionExpression 的作用域中引用,也不会影响该作用域。

15.8.4 Runtime Semantics: EvaluateAsyncFunctionBody

语法制导操作 EvaluateAsyncFunctionBody,接收参数 funcObj (ECMAScript 函数对象) 和 argList (列表 (元素:ECMAScript 语言值));返回值:返回完成。 它按以下产生式分别定义:

AsyncFunctionBody : FunctionBody
  1. 令 promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  2. 令 completion 为 Completion(FunctionDeclarationInstantiation(funcObj, argList))。
  3. 如果 completion 是突然完成,则
    1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « completion.[[Value]] »)。
  4. 否则,
    1. 执行 AsyncFunctionStart(promiseCapability, FunctionBody)。
  5. 返回 ReturnCompletion(promiseCapability.[[Promise]])。

15.8.5 Runtime Semantics: Evaluation

AsyncFunctionExpression : async function BindingIdentifieropt ( FormalParameters ) { AsyncFunctionBody }
  1. 返回 AsyncFunctionExpression 的 InstantiateAsyncFunctionExpression。
UnaryExpression : CoverAwaitExpressionAndAwaitUsingDeclarationHead
  1. 令 expr 为 CoverAwaitExpressionAndAwaitUsingDeclarationHead 所覆盖的 AwaitExpression。
  2. 返回 ? expr 的 Evaluation。
AwaitExpression : await UnaryExpression
  1. 令 exprRef 为 ? UnaryExpression 的 Evaluation。
  2. 令 value 为 ? GetValue(exprRef)。
  3. 返回 ? Await(value)。

15.9 异步箭头函数定义

语法

AsyncArrowFunction[In, Yield, Await] : async [no LineTerminator here] AsyncArrowBindingIdentifier[?Yield] [no LineTerminator here] => AsyncConciseBody[?In] CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await] [no LineTerminator here] => AsyncConciseBody[?In] AsyncConciseBody[In] : [lookahead ≠ {] ExpressionBody[?In, +Await] { AsyncFunctionBody } AsyncArrowBindingIdentifier[Yield] : BindingIdentifier[?Yield, +Await] CoverCallExpressionAndAsyncArrowHead[Yield, Await] : MemberExpression[?Yield, ?Await] Arguments[?Yield, ?Await]

补充语法

当处理产生式
AsyncArrowFunction : CoverCallExpressionAndAsyncArrowHead => AsyncConciseBody
的实例时,使用以下文法进一步细化对 CoverCallExpressionAndAsyncArrowHead 的解释:

AsyncArrowHead : async [no LineTerminator here] ArrowFormalParameters[~Yield, +Await]

15.9.1 Static Semantics: 提前错误

AsyncArrowFunction : async AsyncArrowBindingIdentifier => AsyncConciseBody AsyncArrowFunction : CoverCallExpressionAndAsyncArrowHead => AsyncConciseBody

15.9.2 Static Semantics: AsyncConciseBodyContainsUseStrict

语法制导操作 AsyncConciseBodyContainsUseStrict,接收无参数;返回值:Boolean。 它按以下产生式分别定义:

AsyncConciseBody : ExpressionBody
  1. 返回 false。
AsyncConciseBody : { AsyncFunctionBody }
  1. 返回 AsyncFunctionBody 的 FunctionBodyContainsUseStrict。

15.9.3 Runtime Semantics: EvaluateAsyncConciseBody

语法制导操作 EvaluateAsyncConciseBody,接收参数 funcObj (ECMAScript 函数对象) 和 argList (列表 (元素:ECMAScript 语言值));返回值:返回完成。 它按以下产生式分别定义:

AsyncConciseBody : ExpressionBody
  1. 令 promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  2. 令 completion 为 Completion(FunctionDeclarationInstantiation(funcObj, argList))。
  3. 如果 completion 是突然完成,则
    1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « completion.[[Value]] »)。
  4. 否则,
    1. 执行 AsyncFunctionStart(promiseCapability, ExpressionBody)。
  5. 返回 ReturnCompletion(promiseCapability.[[Promise]])。

15.9.4 Runtime Semantics: InstantiateAsyncArrowFunctionExpression

语法制导操作 InstantiateAsyncArrowFunctionExpression,接收可选参数 name ((属性键 或 私有名称));返回值:ECMAScript 函数对象。 它按以下产生式分别定义:

AsyncArrowFunction : async AsyncArrowBindingIdentifier => AsyncConciseBody
  1. 如果不存在 name,则将 name 设置为空 String。
  2. 令 envRecord 为正在运行的执行上下文的 LexicalEnvironment。
  3. 令 privateEnv 为正在运行的执行上下文的 PrivateEnvironment。
  4. 令 sourceText 为 AsyncArrowFunction 匹配的源文本。
  5. 令 params 为 AsyncArrowBindingIdentifier。
  6. 令 closure 为 OrdinaryFunctionCreate(%AsyncFunction.prototype%, sourceText, params, AsyncConciseBody, lexical-this, envRecord, privateEnv)。
  7. 执行 SetFunctionName(closure, name)。
  8. 返回 closure。
AsyncArrowFunction : CoverCallExpressionAndAsyncArrowHead => AsyncConciseBody
  1. 如果不存在 name,则将 name 设置为空 String。
  2. 令 envRecord 为正在运行的执行上下文的 LexicalEnvironment。
  3. 令 privateEnv 为正在运行的执行上下文的 PrivateEnvironment。
  4. 令 sourceText 为 AsyncArrowFunction 匹配的源文本。
  5. 令 head 为 CoverCallExpressionAndAsyncArrowHead 所覆盖的 AsyncArrowHead。
  6. 令 params 为 head 的 ArrowFormalParameters。
  7. 令 closure 为 OrdinaryFunctionCreate(%AsyncFunction.prototype%, sourceText, params, AsyncConciseBody, lexical-this, envRecord, privateEnv)。
  8. 执行 SetFunctionName(closure, name)。
  9. 返回 closure。

15.9.5 Runtime Semantics: Evaluation

AsyncArrowFunction : async AsyncArrowBindingIdentifier => AsyncConciseBody CoverCallExpressionAndAsyncArrowHead => AsyncConciseBody
  1. 返回 AsyncArrowFunction 的 InstantiateAsyncArrowFunctionExpression。

15.10 尾位置调用

15.10.1 Static Semantics: IsInTailPosition ( call )

抽象操作 IsInTailPosition,接收参数 call ((a CallExpression Parse Node、a MemberExpression Parse Node 或 an OptionalChain Parse Node));返回值:Boolean。 调用时执行以下步骤:

  1. 如果 IsStrict(call) 是 false,则返回 false。
  2. 如果 call 未包含在 FunctionBody、ConciseBody 或 AsyncConciseBody 中,则返回 false。
  3. 令 body 为最紧密包含 call 的 FunctionBody、ConciseBody 或 AsyncConciseBody。
  4. 如果 body 是 GeneratorBody 的 FunctionBody,则返回 false。
  5. 如果 body 是 AsyncFunctionBody 的 FunctionBody,则返回 false。
  6. 如果 body 是 AsyncGeneratorBody 的 FunctionBody,则返回 false。
  7. 如果 body 是 AsyncConciseBody,则返回 false。
  8. 返回以 call 为参数对 body 执行 HasCallInTailPosition 的结果。
注

尾位置调用仅在严格模式代码中定义,这是因为常见的非标准语言扩展(参见 10.2.4)允许观察调用方上下文链。

15.10.2 Static Semantics: HasCallInTailPosition

语法制导操作 HasCallInTailPosition,接收参数 call ((a CallExpression Parse Node、a MemberExpression Parse Node 或 an OptionalChain Parse Node));返回值:Boolean。

注 1

call 是表示特定源文本范围的 Parse Node。当以下算法将 call 与另一个 Parse Node 比较时,测试的是它们是否表示相同的源文本。

注 2

一个潜在的尾位置调用,如果其后紧接着对调用结果执行 return GetValue,也同样是可能的尾位置调用。函数调用无法返回 Reference Record,因此这种 GetValue 操作始终返回与实际函数调用结果相同的值。

注 3

如果 using 声明或 await using 声明位于同一个 Block、ForStatement、ForInOfStatement、FunctionBody、GeneratorBody、AsyncGeneratorBody、AsyncFunctionBody 或 ClassStaticBlockBody 中某次调用之前,则会阻止该调用成为可能的尾位置调用。

它按以下产生式分别定义:

StatementList : StatementList StatementListItem
  1. 令 has 为以 call 为参数对派生的 StatementList 执行 HasCallInTailPosition 的结果。
  2. 如果 has 是 true,则返回 true。
  3. 如果派生的 StatementList 的 ContainsUsing 是 true,则返回 false。
  4. 返回以 call 为参数对 StatementListItem 执行 HasCallInTailPosition 的结果。
FunctionStatementList : [empty] StatementListItem : Declaration Statement : VariableStatement EmptyStatement ExpressionStatement ContinueStatement BreakStatement ThrowStatement DebuggerStatement Block : { } ReturnStatement : return ; LabelledItem : FunctionDeclaration ForInOfStatement : for ( LeftHandSideExpression of AssignmentExpression ) Statement for ( var ForBinding of AssignmentExpression ) Statement for ( ForDeclaration of AssignmentExpression ) Statement CaseBlock : { }
  1. 返回 false。
IfStatement : if ( Expression ) Statement else Statement
  1. 令 has 为以 call 为参数对第一个 Statement 执行 HasCallInTailPosition 的结果。
  2. 如果 has 是 true,则返回 true。
  3. 返回以 call 为参数对第二个 Statement 执行 HasCallInTailPosition 的结果。
IfStatement : if ( Expression ) Statement DoWhileStatement : do Statement while ( Expression ) ; WhileStatement : while ( Expression ) Statement ForStatement : for ( Expressionopt ; Expressionopt ; Expressionopt ) Statement for ( var VariableDeclarationList ; Expressionopt ; Expressionopt ) Statement for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement ForInOfStatement : for ( LeftHandSideExpression in Expression ) Statement for ( var ForBinding in Expression ) Statement for ( ForDeclaration in Expression ) Statement WithStatement : with ( Expression ) Statement
  1. 返回以 call 为参数对 Statement 执行 HasCallInTailPosition 的结果。
LabelledStatement : LabelIdentifier : LabelledItem
  1. 返回以 call 为参数对 LabelledItem 执行 HasCallInTailPosition 的结果。
ReturnStatement : return Expression ;
  1. 返回以 call 为参数对 Expression 执行 HasCallInTailPosition 的结果。
SwitchStatement : switch ( Expression ) CaseBlock
  1. 返回以 call 为参数对 CaseBlock 执行 HasCallInTailPosition 的结果。
CaseBlock : { CaseClausesopt DefaultClause CaseClausesopt }
  1. 令 has 为 false。
  2. 如果存在第一个 CaseClauses,则将 has 设置为以 call 为参数对第一个 CaseClauses 执行 HasCallInTailPosition 的结果。
  3. 如果 has 是 true,则返回 true。
  4. 将 has 设置为以 call 为参数对 DefaultClause 执行 HasCallInTailPosition 的结果。
  5. 如果 has 是 true,则返回 true。
  6. 如果存在第二个 CaseClauses,则将 has 设置为以 call 为参数对第二个 CaseClauses 执行 HasCallInTailPosition 的结果。
  7. 返回 has。
CaseClauses : CaseClauses CaseClause
  1. 令 has 为以 call 为参数对 CaseClauses 执行 HasCallInTailPosition 的结果。
  2. 如果 has 是 true,则返回 true。
  3. 返回以 call 为参数对 CaseClause 执行 HasCallInTailPosition 的结果。
CaseClause : case Expression : StatementListopt DefaultClause : default : StatementListopt
  1. 如果存在 StatementList,则返回以 call 为参数对 StatementList 执行 HasCallInTailPosition 的结果。
  2. 返回 false。
TryStatement : try Block Catch
  1. 返回以 call 为参数对 Catch 执行 HasCallInTailPosition 的结果。
TryStatement : try Block Finally try Block Catch Finally
  1. 返回以 call 为参数对 Finally 执行 HasCallInTailPosition 的结果。
Catch : catch ( CatchParameter ) Block
  1. 返回以 call 为参数对 Block 执行 HasCallInTailPosition 的结果。
AssignmentExpression : YieldExpression ArrowFunction AsyncArrowFunction LeftHandSideExpression = AssignmentExpression LeftHandSideExpression AssignmentOperator AssignmentExpression LeftHandSideExpression &&= AssignmentExpression LeftHandSideExpression ||= AssignmentExpression LeftHandSideExpression ??= AssignmentExpression BitwiseANDExpression : BitwiseANDExpression & EqualityExpression BitwiseXORExpression : BitwiseXORExpression ^ BitwiseANDExpression BitwiseORExpression : BitwiseORExpression | BitwiseXORExpression EqualityExpression : EqualityExpression == RelationalExpression EqualityExpression != RelationalExpression EqualityExpression === RelationalExpression EqualityExpression !== RelationalExpression RelationalExpression : RelationalExpression < ShiftExpression RelationalExpression > ShiftExpression RelationalExpression <= ShiftExpression RelationalExpression >= ShiftExpression RelationalExpression instanceof ShiftExpression RelationalExpression in ShiftExpression PrivateIdentifier in ShiftExpression ShiftExpression : ShiftExpression << AdditiveExpression ShiftExpression >> AdditiveExpression ShiftExpression >>> AdditiveExpression AdditiveExpression : AdditiveExpression + MultiplicativeExpression AdditiveExpression - MultiplicativeExpression MultiplicativeExpression : MultiplicativeExpression MultiplicativeOperator ExponentiationExpression ExponentiationExpression : UpdateExpression ** ExponentiationExpression UpdateExpression : LeftHandSideExpression ++ LeftHandSideExpression -- ++ UnaryExpression -- UnaryExpression UnaryExpression : delete UnaryExpression void UnaryExpression typeof UnaryExpression + UnaryExpression - UnaryExpression ~ UnaryExpression ! UnaryExpression CoverAwaitExpressionAndAwaitUsingDeclarationHead CallExpression : SuperCall ImportCall CallExpression [ Expression ] CallExpression . IdentifierName CallExpression . PrivateIdentifier NewExpression : new NewExpression MemberExpression : MemberExpression [ Expression ] MemberExpression . IdentifierName SuperProperty MetaProperty new MemberExpression Arguments MemberExpression . PrivateIdentifier PrimaryExpression : this IdentifierReference Literal ArrayLiteral ObjectLiteral FunctionExpression ClassExpression GeneratorExpression AsyncFunctionExpression AsyncGeneratorExpression RegularExpressionLiteral TemplateLiteral
  1. 返回 false。
Expression : AssignmentExpression Expression , AssignmentExpression
  1. 返回以 call 为参数对 AssignmentExpression 执行 HasCallInTailPosition 的结果。
ConditionalExpression : ShortCircuitExpression ? AssignmentExpression : AssignmentExpression
  1. 令 has 为以 call 为参数对第一个 AssignmentExpression 执行 HasCallInTailPosition 的结果。
  2. 如果 has 是 true,则返回 true。
  3. 返回以 call 为参数对第二个 AssignmentExpression 执行 HasCallInTailPosition 的结果。
LogicalANDExpression : LogicalANDExpression && BitwiseORExpression
  1. 返回以 call 为参数对 BitwiseORExpression 执行 HasCallInTailPosition 的结果。
LogicalORExpression : LogicalORExpression || LogicalANDExpression
  1. 返回以 call 为参数对 LogicalANDExpression 执行 HasCallInTailPosition 的结果。
CoalesceExpression : CoalesceExpressionHead ?? BitwiseORExpression
  1. 返回以 call 为参数对 BitwiseORExpression 执行 HasCallInTailPosition 的结果。
CallExpression : CoverCallExpressionAndAsyncArrowHead CallExpression Arguments CallExpression TemplateLiteral
  1. 如果此 CallExpression 是 call,则返回 true。
  2. 返回 false。
OptionalExpression : MemberExpression OptionalChain CallExpression OptionalChain OptionalExpression OptionalChain
  1. 返回以 call 为参数对 OptionalChain 执行 HasCallInTailPosition 的结果。
OptionalChain : ?. [ Expression ] ?. IdentifierName ?. PrivateIdentifier OptionalChain [ Expression ] OptionalChain . IdentifierName OptionalChain . PrivateIdentifier
  1. 返回 false。
OptionalChain : ?. Arguments OptionalChain Arguments
  1. 如果此 OptionalChain 是 call,则返回 true。
  2. 返回 false。
MemberExpression : MemberExpression TemplateLiteral
  1. 如果此 MemberExpression 是 call,则返回 true。
  2. 返回 false。
PrimaryExpression : CoverParenthesizedExpressionAndArrowParameterList
  1. 令 expr 为 CoverParenthesizedExpressionAndArrowParameterList 所覆盖的 ParenthesizedExpression。
  2. 返回以 call 为参数对 expr 执行 HasCallInTailPosition 的结果。
ParenthesizedExpression : ( Expression )
  1. 返回以 call 为参数对 Expression 执行 HasCallInTailPosition 的结果。

15.10.3 PrepareForTailCall ( )

抽象操作 PrepareForTailCall,接收无参数;返回值:unused。 调用时执行以下步骤:

  1. 断言:当前执行上下文随后不会再用于对任何 ECMAScript 代码或内置函数进行求值。在调用此抽象操作之后调用 Call 时,会在执行任何此类求值之前创建并压入新的执行上下文。
  2. 丢弃与当前执行上下文关联的所有资源。
  3. 返回 unused。

尾位置调用必须在调用目标函数之前释放与当前正在执行的函数执行上下文关联的任何临时内部资源,或者复用这些资源来支持目标函数。

注

例如,尾位置调用使实现的活动记录栈增长的量,应仅为目标函数活动记录大小超出调用函数活动记录大小的部分。如果目标函数的活动记录更小,则栈的总大小应当减小。

16 ECMAScript 语言:脚本和模块

16.1 脚本

语法

Script : ScriptBodyopt ScriptBody : StatementList[~Yield, ~Await, ~Return]

16.1.1 Static Semantics: 提前错误

Script : ScriptBody ScriptBody : StatementList

16.1.2 Static Semantics: ScriptIsStrict

语法制导操作 ScriptIsStrict,接收无参数;返回值:Boolean。 它按以下产生式分别定义:

Script : ScriptBodyopt
  1. 如果存在 ScriptBody,并且 ScriptBody 的指令序言包含 Use Strict 指令,则返回 true。
  2. 返回 false。

16.1.3 Runtime Semantics: Evaluation

Script : [empty]
  1. 返回 undefined。

16.1.4 Script Records

Script Record 封装有关正在求值的脚本的信息。每个 script record 都包含 表 35 中列出的字段。

表 35: Script Record 字段
字段名称 值类型 含义
[[Realm]] a Realm Record 创建此脚本的 realm。
[[ECMAScriptCode]] a Script Parse Node 解析此脚本源文本的结果。
[[LoadedModules]] a List of LoadedModuleRequest Records 从此脚本导入的说明符字符串到已解析 Module Record 的映射。此列表不包含两个不同的 Record r1 和 r2,使得 ModuleRequestsEqual(r1, r2) 是 true。
[[HostDefined]] anything (default value is empty) 保留给需要将附加信息与脚本关联的宿主环境使用的字段。

16.1.5 ParseScript ( sourceText, realm, hostDefined )

抽象操作 ParseScript,接收参数 sourceText ((String 或 a sequence of Unicode code points))、realm (Realm 记录) 和 hostDefined (任意值);返回值:(Script 记录 或 a non-empty List of SyntaxError objects)。 它根据将 sourceText 作为 Script 解析的结果创建 Script Record。 调用时执行以下步骤:

  1. 令 script 为 ParseText(sourceText, Script)。
  2. 如果 script 是错误的 List,则返回 script。
  3. 返回 Script Record { [[Realm]]: realm, [[ECMAScriptCode]]: script, [[LoadedModules]]: « », [[HostDefined]]: hostDefined }。
注

实现可以在对该脚本源文本执行 ParseScript 之前解析脚本源文本,并分析其中的提前错误条件。不过,任何错误的报告都必须推迟到本规范实际对该源文本执行 ParseScript 时。

16.1.6 ScriptEvaluation ( scriptRecord )

抽象操作 ScriptEvaluation,接收参数 scriptRecord (Script 记录);返回值:(正常完成 (值:ECMAScript 语言值) 或 突兀完成)。 调用时执行以下步骤:

  1. 令 globalEnv 为 scriptRecord.[[Realm]].[[GlobalEnv]]。
  2. 令 scriptContext 为新的 ECMAScript 代码执行上下文。
  3. 将 scriptContext 的 Function 设置为 null。
  4. 将 scriptContext 的 Realm 设置为 scriptRecord.[[Realm]]。
  5. 将 scriptContext 的 ScriptOrModule 设置为 scriptRecord。
  6. 将 scriptContext 的 VariableEnvironment 设置为 globalEnv。
  7. 将 scriptContext 的 LexicalEnvironment 设置为 globalEnv。
  8. 将 scriptContext 的 PrivateEnvironment 设置为 null。
  9. 挂起正在运行的执行上下文。
  10. 将 scriptContext 压入执行上下文栈;scriptContext 现在成为正在运行的执行上下文。
  11. 令 scriptNode 为 scriptRecord.[[ECMAScriptCode]]。
  12. 令 result 为 Completion(GlobalDeclarationInstantiation(scriptNode, globalEnv))。
  13. 如果 result 是正常完成,则
    1. 将 result 设置为 Completion(scriptNode 的 Evaluation)。
    2. 如果 result 是正常完成,并且 result.[[Value]] 是 empty,则
      1. 将 result 设置为 NormalCompletion(undefined)。
  14. 挂起 scriptContext 并将其从执行上下文栈中移除。
  15. 断言:执行上下文栈不为空。
  16. 恢复当前位于执行上下文栈顶部的上下文,并将其作为正在运行的执行上下文。
  17. 返回 ? result。

16.1.7 GlobalDeclarationInstantiation ( script, envRecord )

抽象操作 GlobalDeclarationInstantiation,接收参数 script (a Script Parse Node) 和 envRecord (Global Environment 记录);返回值:(正常完成 (值:unused) 或 抛出完成)。 script 是正在为其建立执行上下文的 Script。envRecord 是将在其中创建绑定的全局环境。

注 1

当为脚本求值建立执行上下文时,会在当前全局环境中实例化声明。代码中声明的每个全局绑定都会被实例化。

调用时,它执行以下步骤:

  1. 令 lexicalNames 为 script 的 LexicallyDeclaredNames。
  2. 令 variableNames 为 script 的 VarDeclaredNames。
  3. 对 lexicalNames 的每个元素 name,执行
    1. 如果 HasLexicalDeclaration(envRecord, name) 是 true,则抛出 SyntaxError 异常。
    2. 令 hasRestrictedGlobal 为 ? HasRestrictedGlobalProperty(envRecord, name)。
    3. 注:全局 var 和 function 绑定(由非严格直接 eval 引入的绑定除外)不可配置,因此属于受限全局属性。
    4. 如果 hasRestrictedGlobal 是 true,则抛出 SyntaxError 异常。
  4. 对 variableNames 的每个元素 name,执行
    1. 如果 HasLexicalDeclaration(envRecord, name) 是 true,则抛出 SyntaxError 异常。
  5. 令 variableDecls 为 script 的 VarScopedDeclarations。
  6. 令 funcsToInitialize 为新的空 List。
  7. 令 declaredFuncNames 为新的空 List。
  8. 按 List 的逆序,对 variableDecls 的每个元素 variableDecl,执行
    1. 如果 variableDecl 不是 VariableDeclaration、ForBinding 或 BindingIdentifier 中的任何一个,则
      1. 断言:variableDecl 是 FunctionDeclaration、GeneratorDeclaration、AsyncFunctionDeclaration 或 AsyncGeneratorDeclaration 之一。
      2. 注:如果同一个名称有多个函数声明,则使用最后一个声明。
      3. 令 funcName 为 variableDecl 的 BoundNames 的唯一元素。
      4. 如果 declaredFuncNames 不包含 funcName,则
        1. 令 funcDefinable 为 ? CanDeclareGlobalFunction(envRecord, funcName)。
        2. 如果 funcDefinable 是 false,则抛出 TypeError 异常。
        3. 将 funcName 追加到 declaredFuncNames。
        4. 将 variableDecl 插入为 funcsToInitialize 的第一个元素。
  9. 令 declaredVariableNames 为新的空 List。
  10. 对 variableDecls 的每个元素 variableDecl,执行
    1. 如果 variableDecl 是 VariableDeclaration、ForBinding 或 BindingIdentifier 之一,则
      1. 对 variableDecl 的 BoundNames 的每个 String name,执行
        1. 如果 declaredFuncNames 不包含 name,则
          1. 令 variableDefinable 为 ? CanDeclareGlobalVar(envRecord, name)。
          2. 如果 variableDefinable 是 false,则抛出 TypeError 异常。
          3. 如果 declaredVariableNames 不包含 name,则
            1. 将 name 追加到 declaredVariableNames。
  11. 注:如果全局对象是普通对象,则在此算法步骤之后不会发生异常终止。不过,如果全局对象是 Proxy 异质对象,则它可能表现出会导致以下某些步骤异常终止的行为。
  12. Normative Optional
    如果宿主是 Web 浏览器或以其他方式支持 块级函数声明的 Web 遗留兼容性语义,则
    1. 令 strict 为 script 的 ScriptIsStrict。
    2. 如果 strict 是 false,则
      1. 令 declaredFuncOrVariableNames 为 declaredFuncNames 和 declaredVariableNames 的列表连接。
      2. 对直接包含在任意 Block、CaseClause 或 DefaultClause x 的 StatementList 中、且 script Contains x 是 true 的每个 FunctionDeclaration funcDecl,执行
        1. 令 funcName 为 funcDecl 的 BindingIdentifier 的 StringValue。
        2. 如果将 FunctionDeclaration funcDecl 替换为以 funcName 作为 BindingIdentifier 的 VariableStatement 不会为 script 产生任何提前错误,则
          1. 如果 HasLexicalDeclaration(envRecord, funcName) 是 false,则
            1. 令 funcDefinable 为 ? CanDeclareGlobalVar(envRecord, funcName)。
            2. 如果 funcDefinable 是 true,则
              1. 注:只有当 funcName 既不是 VarDeclaredName,也不是另一个 FunctionDeclaration 的名称时,才会在这里实例化 funcName 的 var 绑定。
              2. 如果 declaredFuncOrVariableNames 不包含 funcName,则
                1. 执行 ? CreateGlobalVarBinding(envRecord, funcName, false)。
                2. 将 funcName 追加到 declaredFuncOrVariableNames。
              3. 当对 FunctionDeclaration funcDecl 求值时,执行以下步骤,以替代 15.2.6 中提供的 FunctionDeclaration Evaluation 算法:
                1. 令 globalEnv 为正在运行的执行上下文的 VariableEnvironment。
                2. 令 blockEnv 为正在运行的执行上下文的 LexicalEnvironment。
                3. 令 funcObj 为 ! blockEnv.GetBindingValue(funcName, false)。
                4. 执行 ? globalEnv.SetMutableBinding(funcName, funcObj, false)。
                5. 返回 unused。
  13. 令 lexicalDecls 为 script 的 LexicallyScopedDeclarations。
  14. 令 privateEnv 为 null。
  15. 对 lexicalDecls 的每个元素 lexicalDecl,执行
    1. 注:词法声明的名称仅在此处实例化,而不会初始化。
    2. 对 lexicalDecl 的 BoundNames 的每个元素 name,执行
      1. 如果 lexicalDecl 的 IsConstantDeclaration 是 true,则
        1. 执行 ? envRecord.CreateImmutableBinding(name, true)。
      2. 否则,
        1. 执行 ? envRecord.CreateMutableBinding(name, false)。
  16. 对 funcsToInitialize 的每个 Parse Node funcDecl,执行
    1. 令 funcName 为 funcDecl 的 BoundNames 的唯一元素。
    2. 令 funcObj 为以 envRecord 和 privateEnv 为参数对 funcDecl 执行 InstantiateFunctionObject 的结果。
    3. 执行 ? CreateGlobalFunctionBinding(envRecord, funcName, funcObj, false)。
  17. 对 declaredVariableNames 的每个 String variableName,执行
    1. 执行 ? CreateGlobalVarBinding(envRecord, variableName, false)。
  18. 返回 unused。
注 2

16.1.1 中规定的提前错误会阻止单个 Script 内函数/var 声明与 let/const/class 声明之间的名称冲突,以及 let/const/class 绑定的重复声明。不过,跨越多个 Script 的此类冲突和重复声明会在 GlobalDeclarationInstantiation 期间作为运行时错误检测。如果检测到任何此类错误,则不会为该脚本实例化任何绑定。不过,如果使用 Proxy 异质对象定义全局对象,则针对冲突声明的运行时测试可能不可靠,从而产生突然完成,并导致某些全局声明未被实例化。如果发生这种情况,则不会对 Script 的代码求值。

与显式 var 或函数声明不同,直接在全局对象上创建的属性会产生可被 let/const/class 声明遮蔽的全局绑定。

16.2 模块

语法

Module : ModuleBodyopt ModuleBody : ModuleItemList ModuleItemList : ModuleItem ModuleItemList ModuleItem ModuleItem : ImportDeclaration ExportDeclaration StatementListItem[~Yield, +Await, ~Return] ModuleExportName : IdentifierName StringLiteral

16.2.1 模块语义

16.2.1.1 Static Semantics: 提前错误

ModuleBody : ModuleItemList 注

重复 ExportedNames 规则意味着,一个 ModuleBody 中包含多个 export default ExportDeclaration 项是语法错误。与冲突或重复声明相关的其他错误条件会在对 Module 求值之前的模块链接期间检查。如果检测到任何此类错误,则不会对该 Module 求值。

ModuleExportName : StringLiteral

16.2.1.2 Static Semantics: ImportedLocalNames ( importEntries )

抽象操作 ImportedLocalNames,接收参数 importEntries (列表 (元素:ImportEntry 记录));返回值:列表 (元素:String)。 它创建由 importEntries 定义的所有局部名称绑定的 List。 调用时执行以下步骤:

  1. 令 localNames 为新的空 List。
  2. 对 importEntries 的每个 ImportEntry Record importEntry,执行
    1. 将 importEntry.[[LocalName]] 追加到 localNames。
  3. 返回 localNames。

16.2.1.3 ModuleRequest Records

ModuleRequest Record 表示使用给定导入属性导入模块的请求。它由以下字段组成:

表 36: ModuleRequest Record 字段
字段名称 值类型 含义
[[Specifier]] a String 模块说明符
[[Attributes]] a List of ImportAttribute Records 导入属性

LoadedModuleRequest Record 表示导入模块的请求以及由此得到的 Module Record。它由表 表 36 中定义的相同字段组成,并额外包含 [[Module]]:

表 37: LoadedModuleRequest Record 字段
字段名称 值类型 含义
[[Specifier]] a String 模块说明符
[[Attributes]] a List of ImportAttribute Records 导入属性
[[Module]] a Module Record 与此模块请求对应的已加载模块

ImportAttribute Record 由以下字段组成:

表 38: ImportAttribute Record 字段
字段名称 值类型 含义
[[Key]] a String 属性键
[[Value]] a String 属性值

16.2.1.3.1 ModuleRequestsEqual ( x, y )

抽象操作 ModuleRequestsEqual,接收参数 x ((ModuleRequest 记录 或 LoadedModuleRequest 记录)) 和 y ((ModuleRequest 记录 或 LoadedModuleRequest 记录));返回值:Boolean。 调用时执行以下步骤:

  1. 如果 x.[[Specifier]] 不是 y.[[Specifier]],则返回 false。
  2. 令 xAttrs 为 x.[[Attributes]]。
  3. 令 yAttrs 为 y.[[Attributes]]。
  4. 令 xAttrsCount 为 xAttrs 中的元素数量。
  5. 令 yAttrsCount 为 yAttrs 中的元素数量。
  6. 如果 xAttrsCount ≠ yAttrsCount,则返回 false。
  7. 对 xAttrs 的每个 ImportAttribute Record xAttr,执行
    1. 如果 yAttrs 不包含某个 ImportAttribute Record yAttr,使得 xAttr.[[Key]] 是 yAttr.[[Key]] 且 xAttr.[[Value]] 是 yAttr.[[Value]],则返回 false。
  8. 返回 true。

16.2.1.4 Static Semantics: ModuleRequests

语法制导操作 ModuleRequests,接收无参数;返回值:列表 (元素:ModuleRequest 记录)。 它按以下产生式分别定义:

Module : [empty]
  1. 返回新的空 List。
ModuleItemList : ModuleItem
  1. 返回 ModuleItem 的 ModuleRequests。
ModuleItemList : ModuleItemList ModuleItem
  1. 令 requests 为 ModuleItemList 的 ModuleRequests。
  2. 令 additionalRequests 为 ModuleItem 的 ModuleRequests。
  3. 对 additionalRequests 的每个 ModuleRequest Record moduleRequest,执行
    1. 如果 requests 不包含某个 ModuleRequest Record otherModuleRequest,使得 ModuleRequestsEqual(moduleRequest, otherModuleRequest) 是 true,则
      1. 将 moduleRequest 追加到 requests。
  4. 返回 requests。
ModuleItem : StatementListItem
  1. 返回新的空 List。
ImportDeclaration : import ImportClause FromClause ;
  1. 令 specifier 为 FromClause 的 SV。
  2. 返回一个 List,其唯一元素是 ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: « » }。
ImportDeclaration : import ImportClause FromClause WithClause ;
  1. 令 specifier 为 FromClause 的 SV。
  2. 令 attrs 为 WithClause 的 WithClauseToAttributes。
  3. 返回一个 List,其唯一元素是 ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: attrs }。
ImportDeclaration : import ModuleSpecifier ;
  1. 令 specifier 为 ModuleSpecifier 的 SV。
  2. 返回一个 List,其唯一元素是 ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: « » }。
ImportDeclaration : import ModuleSpecifier WithClause ;
  1. 令 specifier 为 ModuleSpecifier 的 SV。
  2. 令 attrs 为 WithClause 的 WithClauseToAttributes。
  3. 返回一个 List,其唯一元素是 ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: attrs }。
ExportDeclaration : export ExportFromClause FromClause ;
  1. 令 specifier 为 FromClause 的 SV。
  2. 返回一个 List,其唯一元素是 ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: « » }。
ExportDeclaration : export ExportFromClause FromClause WithClause ;
  1. 令 specifier 为 FromClause 的 SV。
  2. 令 attrs 为 WithClause 的 WithClauseToAttributes。
  3. 返回一个 List,其唯一元素是 ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: attrs }。
ExportDeclaration : export NamedExports ; export VariableStatement export Declaration export default HoistableDeclaration export default ClassDeclaration export default AssignmentExpression ;
  1. 返回新的空 List。

16.2.1.5 抽象 Module Records

Module Record 封装有关单个模块的导入和导出的结构信息。这些信息用于链接一组相互连接模块的导入和导出。Module Record 包含四个仅在模块求值期间使用的字段。

出于规范目的,Module Record 是 Record 规范类型的值,可以将其视为存在于简单的面向对象层次结构中,其中 Module Record 是同时具有抽象子类和具体子类的抽象类。本规范定义名为 Cyclic Module Record 的抽象子类及其名为 Source Text Module Record 的具体子类。其他规范和实现可以定义与它们所定义的替代模块定义设施相对应的其他 Module Record 子类。

Module Record 定义 表 39 中列出的字段。所有 Module Definition 子类至少都包含这些字段。Module Record 还定义 表 40 中的抽象方法列表。所有 Module definition 子类都必须提供这些抽象方法的具体实现。

表 39: Module Record 字段
字段名称 值类型 含义
[[Realm]] a Realm Record 创建此模块的 Realm。
[[Environment]] a Module Environment Record or empty 包含此模块顶层绑定的 Environment Record。此字段在模块链接时设置。
[[Namespace]] an Object or empty 如果已为此模块创建 Module Namespace Object(28.3),则为该对象。
[[HostDefined]] anything (default value is undefined) 保留给需要将附加信息与模块关联的宿主环境使用的字段。
表 40: Module Records的抽象方法
方法 用途 定义
LoadRequestedModules ( [ hostDefined ] )

抽象方法 LoadRequestedModules,接收可选参数 hostDefined (任意值);返回值:Promise。

它通过递归加载模块的所有依赖项,为模块链接做好准备。

在本规范中,它在以下类型中具有定义;宿主可以提供具有其自身定义的其他类型:
GetExportedNames ( [ exportStarSet ] )

抽象方法 GetExportedNames,接收可选参数 exportStarSet (列表 (元素:Source Text Module 记录));返回值:列表 (元素:String)。

它返回直接或间接从此模块导出的所有名称的列表。

调用此方法之前,LoadRequestedModules 必须已成功完成。

在本规范中,它在以下类型中具有定义;宿主可以提供具有其自身定义的其他类型:
ResolveExport ( exportName [ , resolveSet ] )

抽象方法 ResolveExport,接收参数 exportName (String)和可选参数 resolveSet (列表 (元素:记录 (字段:[[Module]] (Module 记录), [[ExportName]] (String))));返回值:(ResolvedBinding 记录、null 或 ambiguous)。

它返回由此模块导出的某个名称的绑定。绑定由形式为 { [[Module]]: Module Record, [[BindingName]]: String | namespace } 的 ResolvedBinding Record 表示。如果导出的是在任何模块中都没有直接绑定的 Module Namespace Object,则 [[BindingName]] 会设置为 namespace。如果无法解析该名称,则返回 null;如果找到多个绑定,则返回 ambiguous。

每次以特定的 exportName、resolveSet 参数对调用此操作时,它都必须返回相同结果。

调用此方法之前,LoadRequestedModules 必须已成功完成。

在本规范中,它在以下类型中具有定义;宿主可以提供具有其自身定义的其他类型:
Evaluate ( )

抽象方法 Evaluate,接收无参数;返回值:Promise。

它返回一个用于此模块及其依赖项求值的 promise;如果求值成功或此前已经成功求值,则该 promise 会兑现;如果发生求值错误或此前已经求值失败,则会拒绝。如果 promise 被拒绝,宿主应处理 promise 拒绝并重新抛出求值错误。除非此模块是 Cyclic Module Record,否则返回的 promise 必须已经 settled。

调用此方法之前,Link 必须已成功完成。

在本规范中,它在以下类型中具有定义;宿主可以提供具有其自身定义的其他类型:

16.2.1.5.1 EvaluateModuleSync ( module )

抽象操作 EvaluateModuleSync,接收参数 module (Module 记录);返回值:(正常完成 (值:unused) 或 抛出完成)。 只要调用方保证 module 的求值会返回已经 settled 的 promise,它就会同步求值 module。 调用时执行以下步骤:

  1. 断言:module 不是 Cyclic Module Record。
  2. 令 promise 为 module.Evaluate()。
  3. 断言:promise.[[PromiseState]] 是 fulfilled 或 rejected。
  4. 如果 promise.[[PromiseState]] 是 rejected,则
    1. 如果 promise.[[PromiseIsHandled]] 是 false,则执行 HostPromiseRejectionTracker(promise, "handle")。
    2. 将 promise.[[PromiseIsHandled]] 设置为 true。
    3. 抛出 promise.[[PromiseResult]]。
  5. 返回 unused。

16.2.1.6 Cyclic Module Records

Cyclic Module Record 用于表示有关模块的信息,该模块可以与 Cyclic Module Record 类型的其他子类模块一起参与依赖循环。不是 Cyclic Module Record 类型子类的 Module Record 不得与 Source Text Module Record 参与依赖循环。

除 表 39 中定义的字段外,Cyclic Module Record 还具有 表 41 中列出的附加字段

表 41: Cyclic Module Records 的附加字段
字段名称 值类型 含义
[[Status]] new, unlinked, linking, linked, evaluating, evaluating-async, or evaluated 初始为 new。随着模块在其生命周期中推进,依次转换为 unlinked、linking、linked、evaluating、可能的 evaluating-async、evaluated。evaluating-async 表示此模块已排队等待其异步依赖项完成后执行,或者它是 [[HasTLA]] 字段为 true、已经执行且正在等待顶层完成的模块。
[[EvaluationError]] a throw completion or empty 表示求值期间发生异常的抛出完成。如果未发生异常,或者 [[Status]] 不是 evaluated,则为 empty。
[[DFSAncestorIndex]] an integer or empty 仅在 Link 和 Evaluate 期间使用的辅助字段。如果 [[Status]] 是 linking 或 evaluating,则它是该模块的深度优先遍历索引,或者同一个强连通分量中某个“更早”模块的深度优先遍历索引。
[[RequestedModules]] a List of ModuleRequest Records 与此模块中的导入关联的 ModuleRequest Record 的 List。该 List 按导入在源文本中的出现顺序排列。
[[LoadedModules]] a List of LoadedModuleRequest Records 从此 record 所表示模块用于请求导入模块的说明符字符串及相应导入属性,到已解析 Module Record 的映射。此列表不包含两个不同的 Record r1 和 r2,使得 ModuleRequestsEqual(r1, r2) 是 true。
[[CycleRoot]] a Cyclic Module Record or empty 循环中第一个被访问的模块,即强连通分量的根 DFS 祖先。对于不在循环中的模块,这就是模块自身。Evaluate 完成后,模块的 [[DFSAncestorIndex]] 是其 [[CycleRoot]] 的深度优先遍历索引。
[[HasTLA]] a Boolean 此模块自身是否为异步模块(例如,它是包含顶层 await 的 Source Text Module Record)。具有异步依赖项并不意味着此字段为 true。模块解析后,此字段不得改变。
[[AsyncEvaluationOrder]] unset, an integer, or done 此字段最初设置为 unset,对于完全同步的模块始终保持 unset。对于自身异步或具有异步依赖项的模块,它会设置为一个整数,用于确定 16.2.1.6.1.3.4 对待执行模块进行排队的顺序。一旦待执行模块成功执行,该字段就设置为 done。
[[TopLevelCapability]] a PromiseCapability Record or empty 如果此模块是某个循环的 [[CycleRoot]],并且对该循环中的某个模块调用了 Evaluate(),则此字段包含整个求值的 PromiseCapability Record。它用于 settle 从 Evaluate() 抽象方法返回的 Promise 对象。对于该模块的任何依赖项,此字段都将为 empty,除非已经为其中某些依赖项启动了顶层 Evaluate()。
[[AsyncParentModules]] a List of Cyclic Module Records 如果此模块或某个依赖项的 [[HasTLA]] 为 true,并且正在执行,则此字段跟踪此模块在顶层执行作业中的父级导入方。这些父模块不会在此模块成功完成执行之前开始执行。
[[PendingAsyncDependencies]] an integer or empty 如果此模块具有任何异步依赖项,则此字段跟踪该模块尚待执行的异步依赖模块数量。当该字段达到 0 且不存在执行错误时,具有异步依赖项的模块将被执行。

除 表 40 中定义的方法外,Cyclic Module Record 还具有 表 42 中列出的附加方法:

表 42: Cyclic Module Records 的附加抽象方法
方法 用途 定义
InitializeEnvironment ( )

抽象方法 InitializeEnvironment,接收无参数;返回值:(正常完成 (值:unused) 或 抛出完成)。

它初始化模块的 Environment Record,包括解析所有导入绑定,并创建模块的执行上下文。
在本规范中,它在以下类型中具有定义;宿主可以提供具有其自身定义的其他类型:
ExecuteModule ( [ capability ] )

抽象方法 ExecuteModule,接收可选参数 capability (PromiseCapability 记录);返回值:(正常完成 (值:unused) 或 抛出完成)。

它在模块的执行上下文中求值模块代码。如果此模块的 [[HasTLA]] 为 true,则会将 PromiseCapability Record 作为参数传入,并且该方法应兑现或拒绝给定的 capability。在这种情况下,该方法不得抛出异常,而应在必要时拒绝 PromiseCapability Record。
在本规范中,它在以下类型中具有定义;宿主可以提供具有其自身定义的其他类型:

GraphLoadingState Record 是包含模块图加载过程相关信息的 Record。它用于在调用 HostLoadImportedModule 后继续加载。每个 GraphLoadingState Record 都具有 表 43 中定义的字段:

表 43: GraphLoadingState Record 字段
字段名称 值类型 含义
[[PromiseCapability]] a PromiseCapability Record 加载过程完成时要兑现的 promise。
[[IsLoading]] a Boolean 如果加载过程尚未完成,无论是成功还是出错,则为 true。
[[PendingModulesCount]] a non-negative integer 它跟踪待处理的 HostLoadImportedModule 调用数量。
[[Visited]] a List of Cyclic Module Records 它是当前加载过程中已经加载的 Cyclic Module Record 列表,用于避免循环依赖造成无限循环。
[[HostDefined]] anything (default value is empty) 它包含要从 LoadRequestedModules 调用方传递给 HostLoadImportedModule 的宿主定义数据。

16.2.1.6.1 Module Record 抽象方法的实现

以下是 Cyclic Module Record 的具体方法,它们实现 表 40 中定义的相应 Module Record 抽象方法。

16.2.1.6.1.1 LoadRequestedModules ( [ hostDefined ] )

a Cyclic Module Record module的具体方法 LoadRequestedModules,接收可选参数 hostDefined (任意值);返回值:Promise。 它填充 module 依赖图中所有 Module Record 的 [[LoadedModules]](大部分工作由辅助函数 InnerModuleLoading 完成)。它接受一个可选的 hostDefined 参数,该参数会传递给 HostLoadImportedModule 钩子。 调用时执行以下步骤:

  1. 如果不存在 hostDefined,则将 hostDefined 设置为 empty。
  2. 令 promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  3. 令 state 为 GraphLoadingState Record { [[IsLoading]]: true, [[PendingModulesCount]]: 1, [[Visited]]: « », [[PromiseCapability]]: promiseCapability, [[HostDefined]]: hostDefined }。
  4. 执行 InnerModuleLoading(state, module)。
  5. 返回 promiseCapability.[[Promise]]。
注
hostDefined 参数可以用于传递获取所导入模块所需的附加信息。例如,HTML 使用它为 <link rel="preload" as="..."> 标签设置正确的 fetch destination。 import() 表达式绝不会设置 hostDefined 参数。

16.2.1.6.1.1.1 InnerModuleLoading ( state, module )

抽象操作 InnerModuleLoading,接收参数 state (GraphLoadingState 记录) 和 module (Module 记录);返回值:unused。 LoadRequestedModules 使用它递归执行 module 依赖图的实际加载过程。 调用时执行以下步骤:

  1. 断言:state.[[IsLoading]] 是 true。
  2. 如果 module 是 Cyclic Module Record,module.[[Status]] 是 new,并且 state.[[Visited]] 不包含 module,则
    1. 将 module 追加到 state.[[Visited]]。
    2. 令 requestedModulesCount 为 module.[[RequestedModules]] 中的元素数量。
    3. 将 state.[[PendingModulesCount]] 设置为 state.[[PendingModulesCount]] + requestedModulesCount。
    4. 对 module.[[RequestedModules]] 的每个 ModuleRequest Record request,执行
      1. 如果 AllImportAttributesSupported(request.[[Attributes]]) 是 false,则
        1. 令 error 为 ThrowCompletion(新创建的 SyntaxError 对象)。
        2. 执行 ContinueModuleLoading(state, error)。
      2. 否则如果 module.[[LoadedModules]] 包含某个 LoadedModuleRequest Record record,使得 ModuleRequestsEqual(record, request) 是 true,则
        1. 执行 InnerModuleLoading(state, record.[[Module]])。
      3. 否则,
        1. 执行 HostLoadImportedModule(module, request, state.[[HostDefined]], state)。
        2. 注:HostLoadImportedModule 将调用 FinishLoadingImportedModule,后者通过 ContinueModuleLoading 重新进入图加载过程。
      4. 如果 state.[[IsLoading]] 是 false,则返回 unused。
  3. 断言:state.[[PendingModulesCount]] ≥ 1。
  4. 将 state.[[PendingModulesCount]] 设置为 state.[[PendingModulesCount]] - 1。
  5. 如果 state.[[PendingModulesCount]] = 0,则
    1. 将 state.[[IsLoading]] 设置为 false。
    2. 对 state.[[Visited]] 的每个 Cyclic Module Record loaded,执行
      1. 如果 loaded.[[Status]] 是 new,则将 loaded.[[Status]] 设置为 unlinked。
    3. 执行 ! Call(state.[[PromiseCapability]].[[Resolve]], undefined, « undefined »)。
  6. 返回 unused。

16.2.1.6.1.1.2 ContinueModuleLoading ( state, moduleCompletion )

抽象操作 ContinueModuleLoading,接收参数 state (GraphLoadingState 记录) 和 moduleCompletion ((正常完成 (值:Module 记录) 或 抛出完成));返回值:unused。 它用于在调用 HostLoadImportedModule 后重新进入加载过程。 调用时执行以下步骤:

  1. 如果 state.[[IsLoading]] 是 false,则返回 unused。
  2. 如果 moduleCompletion 是正常完成,则
    1. 执行 InnerModuleLoading(state, moduleCompletion.[[Value]])。
  3. 否则,
    1. 将 state.[[IsLoading]] 设置为 false。
    2. 执行 ! Call(state.[[PromiseCapability]].[[Reject]], undefined, « moduleCompletion.[[Value]] »)。
  4. 返回 unused。

16.2.1.6.1.2 Link ( )

a Cyclic Module Record module的具体方法 Link,接收无参数;返回值:(正常完成 (值:unused) 或 抛出完成)。 成功时,Link 会将此模块的 [[Status]] 从 unlinked 转换为 linked。失败时,会抛出异常,并且此模块的 [[Status]] 保持为 unlinked。(大部分工作由辅助函数 InnerModuleLinking 完成。) 调用时执行以下步骤:

  1. 断言:module.[[Status]] 是 unlinked、linked、evaluating-async 或 evaluated 之一。
  2. 令 stack 为新的空 List。
  3. 令 result 为 Completion(InnerModuleLinking(module, stack, 0))。
  4. 如果 result 是突然完成,则
    1. 对 stack 的每个 Cyclic Module Record requiredModule,执行
      1. 断言:requiredModule.[[Status]] 是 linking。
      2. 将 requiredModule.[[Status]] 设置为 unlinked。
    2. 断言:module.[[Status]] 是 unlinked。
    3. 返回 ? result。
  5. 断言:module.[[Status]] 是 linked、evaluating-async 或 evaluated 之一。
  6. 断言:stack 为空。
  7. 返回 unused。

16.2.1.6.1.2.1 InnerModuleLinking ( module, stack, index )

抽象操作 InnerModuleLinking,接收参数 module (Module 记录)、stack (列表 (元素:Cyclic Module 记录)) 和 index (非负整数);返回值:(正常完成 (值:非负整数) 或 抛出完成)。 Link 使用它为 module 执行实际链接过程,并递归处理依赖图中的所有其他模块。stack 和 index 参数以及模块的 [[DFSAncestorIndex]] 字段用于跟踪深度优先搜索(DFS)遍历。具体来说,[[DFSAncestorIndex]] 用于发现强连通分量(SCC),使得一个 SCC 中的所有模块一起转换到 linked。 调用时执行以下步骤:

  1. 如果 module 不是 Cyclic Module Record,则
    1. 执行 ? module.Link()。
    2. 返回 index。
  2. 如果 module.[[Status]] 是 linking、linked、evaluating-async 或 evaluated 之一,则
    1. 返回 index。
  3. 断言:module.[[Status]] 是 unlinked。
  4. 将 module.[[Status]] 设置为 linking。
  5. 令 moduleIndex 为 index。
  6. 将 module.[[DFSAncestorIndex]] 设置为 index。
  7. 将 index 设置为 index + 1。
  8. 将 module 追加到 stack。
  9. 对 module.[[RequestedModules]] 的每个 ModuleRequest Record request,执行
    1. 令 requiredModule 为 GetImportedModule(module, request)。
    2. 将 index 设置为 ? InnerModuleLinking(requiredModule, stack, index)。
    3. 如果 requiredModule 是 Cyclic Module Record,则
      1. 断言:requiredModule.[[Status]] 是 linking、linked、evaluating-async 或 evaluated 之一。
      2. 断言:requiredModule.[[Status]] 是 linking,当且仅当 stack 包含 requiredModule。
      3. 如果 requiredModule.[[Status]] 是 linking,则
        1. 将 module.[[DFSAncestorIndex]] 设置为 min(module.[[DFSAncestorIndex]], requiredModule.[[DFSAncestorIndex]])。
  10. 执行 ? module.InitializeEnvironment()。
  11. 断言:module 在 stack 中恰好出现一次。
  12. 断言:module.[[DFSAncestorIndex]] ≤ moduleIndex。
  13. 如果 module.[[DFSAncestorIndex]] = moduleIndex,则
    1. 令 done 为 false。
    2. 当 done 是 false 时,重复执行,
      1. 令 requiredModule 为 stack 的最后一个元素。
      2. 从 stack 中移除最后一个元素。
      3. 断言:requiredModule 是 Cyclic Module Record。
      4. 将 requiredModule.[[Status]] 设置为 linked。
      5. 如果 requiredModule 和 module 是同一个 Module Record,则将 done 设置为 true。
  14. 返回 index。

16.2.1.6.1.3 Evaluate ( )

a Cyclic Module Record module的具体方法 Evaluate,接收无参数;返回值:Promise。 Evaluate 会将此模块的 [[Status]] 从 linked 转换为 evaluating-async 或 evaluated。首次对给定强连通分量中的某个模块调用它时,Evaluate 会创建并返回一个 Promise,该 Promise 会在模块完成求值时兑现。此 Promise 存储在该分量 [[CycleRoot]] 的 [[TopLevelCapability]] 字段中。以后对该分量中任何模块调用 Evaluate 都会返回同一个 Promise。(大部分工作由辅助函数 InnerModuleEvaluation 完成。) 调用时执行以下步骤:

  1. 断言:此 Evaluate 调用没有与周围代理中的另一个 Evaluate 调用同时发生。
  2. 断言:module.[[Status]] 是 linked、evaluating-async 或 evaluated 之一。
  3. 如果 module.[[Status]] 是 evaluating-async 或 evaluated,则
    1. 如果 module.[[CycleRoot]] 不是 empty,则
      1. 将 module 设置为 module.[[CycleRoot]]。
    2. 否则,
      1. 断言:module.[[Status]] 是 evaluated,并且 module.[[EvaluationError]] 是抛出完成。
  4. 如果 module.[[TopLevelCapability]] 不是 empty,则
    1. 返回 module.[[TopLevelCapability]].[[Promise]]。
  5. 令 stack 为新的空 List。
  6. 令 promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  7. 将 module.[[TopLevelCapability]] 设置为 promiseCapability。
  8. 令 result 为 Completion(InnerModuleEvaluation(module, stack, 0))。
  9. 如果 result 是突然完成,则
    1. 对 stack 的每个 Cyclic Module Record requiredModule,执行
      1. 断言:requiredModule.[[Status]] 是 evaluating。
      2. 将 requiredModule.[[Status]] 设置为 evaluated。
      3. 将 requiredModule.[[EvaluationError]] 设置为 result。
    2. 断言:module.[[Status]] 是 evaluated。
    3. 断言:module.[[EvaluationError]] 和 result 是同一个 Completion Record。
    4. 执行 ! Call(promiseCapability.[[Reject]], undefined, « result.[[Value]] »)。
  10. 否则,
    1. 断言:module.[[Status]] 是 evaluating-async 或 evaluated。
    2. 断言:module.[[EvaluationError]] 是 empty。
    3. 如果 module.[[Status]] 是 evaluated,则
      1. 断言:module.[[AsyncEvaluationOrder]] 是 unset 或 done。
      2. 注:当且仅当 module 此前已经求值且该求值是异步的,module.[[AsyncEvaluationOrder]] 才是 done。
      3. 执行 ! Call(promiseCapability.[[Resolve]], undefined, « undefined »)。
    4. 断言:stack 为空。
  11. 返回 promiseCapability.[[Promise]]。

16.2.1.6.1.3.1 InnerModuleEvaluation ( module, stack, index )

抽象操作 InnerModuleEvaluation,接收参数 module (Module 记录)、stack (列表 (元素:Cyclic Module 记录)) 和 index (非负整数);返回值:(正常完成 (值:非负整数) 或 抛出完成)。 Evaluate 使用它为 module 执行实际求值过程,并递归处理依赖图中的所有其他模块。stack 和 index 参数以及 module 的 [[DFSAncestorIndex]] 字段的使用方式与 InnerModuleLinking 中相同。 调用时执行以下步骤:

  1. 如果 module 不是 Cyclic Module Record,则
    1. 执行 ? EvaluateModuleSync(module)。
    2. 返回 index。
  2. 如果 module.[[Status]] 是 evaluating-async 或 evaluated,则
    1. 如果 module.[[EvaluationError]] 是 empty,则返回 index。
    2. 返回 ? module.[[EvaluationError]]。
  3. 如果 module.[[Status]] 是 evaluating,则返回 index。
  4. 断言:module.[[Status]] 是 linked。
  5. 将 module.[[Status]] 设置为 evaluating。
  6. 令 moduleIndex 为 index。
  7. 将 module.[[DFSAncestorIndex]] 设置为 index。
  8. 将 module.[[PendingAsyncDependencies]] 设置为 0。
  9. 将 index 设置为 index + 1。
  10. 将 module 追加到 stack。
  11. 对 module.[[RequestedModules]] 的每个 ModuleRequest Record request,执行
    1. 令 requiredModule 为 GetImportedModule(module, request)。
    2. 将 index 设置为 ? InnerModuleEvaluation(requiredModule, stack, index)。
    3. 如果 requiredModule 是 Cyclic Module Record,则
      1. 断言:requiredModule.[[Status]] 是 evaluating、evaluating-async 或 evaluated 之一。
      2. 断言:requiredModule.[[Status]] 是 evaluating,当且仅当 stack 包含 requiredModule。
      3. 如果 requiredModule.[[Status]] 是 evaluating,则
        1. 将 module.[[DFSAncestorIndex]] 设置为 min(module.[[DFSAncestorIndex]], requiredModule.[[DFSAncestorIndex]])。
      4. 否则,
        1. 将 requiredModule 设置为 requiredModule.[[CycleRoot]]。
        2. 断言:requiredModule.[[Status]] 是 evaluating-async 或 evaluated。
        3. 如果 requiredModule.[[EvaluationError]] 不是 empty,则返回 ? requiredModule.[[EvaluationError]]。
      5. 如果 requiredModule.[[AsyncEvaluationOrder]] 是整数,则
        1. 将 module.[[PendingAsyncDependencies]] 设置为 module.[[PendingAsyncDependencies]] + 1。
        2. 将 module 追加到 requiredModule.[[AsyncParentModules]]。
  12. 如果 module.[[HasTLA]] 是 true 或 module.[[PendingAsyncDependencies]] > 0,则
    1. 断言:module.[[AsyncEvaluationOrder]] 是 unset。
    2. 将 module.[[AsyncEvaluationOrder]] 设置为 IncrementModuleAsyncEvaluationCount()。
    3. 如果 module.[[PendingAsyncDependencies]] = 0,则执行 ExecuteAsyncModule(module)。
  13. 否则,
    1. 执行 ? module.ExecuteModule()。
  14. 断言:module 在 stack 中恰好出现一次。
  15. 断言:module.[[DFSAncestorIndex]] ≤ moduleIndex。
  16. 如果 module.[[DFSAncestorIndex]] = moduleIndex,则
    1. 令 done 为 false。
    2. 当 done 是 false 时,重复执行,
      1. 令 requiredModule 为 stack 的最后一个元素。
      2. 从 stack 中移除最后一个元素。
      3. 断言:requiredModule 是 Cyclic Module Record。
      4. 断言:requiredModule.[[AsyncEvaluationOrder]] 是整数或 unset。
      5. 如果 requiredModule.[[AsyncEvaluationOrder]] 是 unset,则将 requiredModule.[[Status]] 设置为 evaluated。
      6. 否则,将 requiredModule.[[Status]] 设置为 evaluating-async。
      7. 如果 requiredModule 和 module 是同一个 Module Record,则将 done 设置为 true。
      8. 将 requiredModule.[[CycleRoot]] 设置为 module。
  17. 返回 index。
注 1

当 InnerModuleEvaluation 正在遍历模块时,该模块处于 evaluating。模块在执行完成时处于 evaluated;如果其 [[HasTLA]] 字段为 true 或具有异步依赖项,则在执行期间处于 evaluating-async。

注 2

当异步循环中的模块不处于 evaluating 时,依赖该模块的任何模块将改为通过 [[CycleRoot]] 依赖循环根的执行。这样可确保通过根模块状态将循环状态视为单个强连通分量。

16.2.1.6.1.3.2 ExecuteAsyncModule ( module )

抽象操作 ExecuteAsyncModule,接收参数 module (Cyclic Module 记录);返回值:unused。 调用时执行以下步骤:

  1. 断言:module.[[Status]] 是 evaluating 或 evaluating-async。
  2. 断言:module.[[HasTLA]] 是 true。
  3. 令 promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  4. 令 fulfilledClosure 为一个没有参数的新 Abstract Closure,它捕获 module,并在被调用时执行以下步骤:
    1. 执行 AsyncModuleExecutionFulfilled(module)。
    2. 返回 NormalCompletion(undefined)。
  5. 令 onFulfilled 为 CreateBuiltinFunction(fulfilledClosure, 0, "", « »)。
  6. 令 rejectedClosure 为一个具有参数 (error) 的新 Abstract Closure,它捕获 module,并在被调用时执行以下步骤:
    1. 执行 AsyncModuleExecutionRejected(module, error)。
    2. 返回 NormalCompletion(undefined)。
  7. 令 onRejected 为 CreateBuiltinFunction(rejectedClosure, 0, "", « »)。
  8. 执行 PerformPromiseThen(promiseCapability.[[Promise]], onFulfilled, onRejected)。
  9. 执行 ! module.ExecuteModule(promiseCapability)。
  10. 返回 unused。

16.2.1.6.1.3.3 GatherAvailableAncestors ( module, execList )

抽象操作 GatherAvailableAncestors,接收参数 module (Cyclic Module 记录) 和 execList (列表 (元素:Cyclic Module 记录));返回值:unused。 调用时执行以下步骤:

  1. 对 module.[[AsyncParentModules]] 的每个 Cyclic Module Record ancestorModule,执行
    1. 如果 execList 不包含 ancestorModule,并且 ancestorModule.[[CycleRoot]].[[EvaluationError]] 是 empty,则
      1. 断言:ancestorModule.[[Status]] 是 evaluating-async。
      2. 断言:ancestorModule.[[EvaluationError]] 是 empty。
      3. 断言:ancestorModule.[[AsyncEvaluationOrder]] 是整数。
      4. 断言:ancestorModule.[[PendingAsyncDependencies]] > 0。
      5. 将 ancestorModule.[[PendingAsyncDependencies]] 设置为 ancestorModule.[[PendingAsyncDependencies]] - 1。
      6. 如果 ancestorModule.[[PendingAsyncDependencies]] = 0,则
        1. 将 ancestorModule 追加到 execList。
        2. 如果 ancestorModule.[[HasTLA]] 是 false,则执行 GatherAvailableAncestors(ancestorModule, execList)。
  2. 返回 unused。
注

当根 module 的异步执行兑现时,此函数确定可在该完成时一起同步执行的模块列表,并将它们填充到 execList 中。

16.2.1.6.1.3.4 AsyncModuleExecutionFulfilled ( module )

抽象操作 AsyncModuleExecutionFulfilled,接收参数 module (Cyclic Module 记录);返回值:unused。 调用时执行以下步骤:

  1. 如果 module.[[Status]] 是 evaluated,则
    1. 断言:module.[[EvaluationError]] 不是 empty。
    2. 返回 unused。
  2. 断言:module.[[Status]] 是 evaluating-async。
  3. 断言:module.[[AsyncEvaluationOrder]] 是整数。
  4. 断言:module.[[EvaluationError]] 是 empty。
  5. 将 module.[[AsyncEvaluationOrder]] 设置为 done。
  6. 将 module.[[Status]] 设置为 evaluated。
  7. 如果 module.[[TopLevelCapability]] 不是 empty,则
    1. 断言:module.[[CycleRoot]] 和 module 是同一个 Module Record。
    2. 执行 ! Call(module.[[TopLevelCapability]].[[Resolve]], undefined, « undefined »)。
  8. 令 execList 为新的空 List。
  9. 执行 GatherAvailableAncestors(module, execList)。
  10. 断言:execList 的所有元素的 [[AsyncEvaluationOrder]] 字段都设置为整数,[[PendingAsyncDependencies]] 字段设置为 0,且 [[EvaluationError]] 字段设置为 empty。
  11. 令 sortedExecList 为一个 List,其元素是 execList 的元素,并按其 [[AsyncEvaluationOrder]] 字段升序排序。
  12. 对 sortedExecList 的每个 Cyclic Module Record ancestorModule,执行
    1. 如果 ancestorModule.[[Status]] 是 evaluated,则
      1. 断言:ancestorModule.[[EvaluationError]] 不是 empty。
    2. 否则如果 ancestorModule.[[HasTLA]] 是 true,则
      1. 执行 ExecuteAsyncModule(ancestorModule)。
    3. 否则,
      1. 令 result 为 Completion(ancestorModule.ExecuteModule())。
      2. 如果 result 是突然完成,则
        1. 执行 AsyncModuleExecutionRejected(ancestorModule, result.[[Value]])。
      3. 否则,
        1. 将 ancestorModule.[[AsyncEvaluationOrder]] 设置为 done。
        2. 将 ancestorModule.[[Status]] 设置为 evaluated。
        3. 如果 ancestorModule.[[TopLevelCapability]] 不是 empty,则
          1. 断言:ancestorModule.[[CycleRoot]] 和 ancestorModule 是同一个 Module Record。
          2. 执行 ! Call(ancestorModule.[[TopLevelCapability]].[[Resolve]], undefined, « undefined »)。
  13. 返回 unused。

16.2.1.6.1.3.5 AsyncModuleExecutionRejected ( module, error )

抽象操作 AsyncModuleExecutionRejected,接收参数 module (Cyclic Module 记录) 和 error (ECMAScript 语言值);返回值:unused。 调用时执行以下步骤:

  1. 如果 module.[[Status]] 是 evaluated,则
    1. 断言:module.[[EvaluationError]] 不是 empty。
    2. 返回 unused。
  2. 断言:module.[[Status]] 是 evaluating-async。
  3. 断言:module.[[AsyncEvaluationOrder]] 是整数。
  4. 断言:module.[[EvaluationError]] 是 empty。
  5. 将 module.[[EvaluationError]] 设置为 ThrowCompletion(error)。
  6. 将 module.[[Status]] 设置为 evaluated。
  7. 将 module.[[AsyncEvaluationOrder]] 设置为 done。
  8. 注:module.[[AsyncEvaluationOrder]] 被设置为 done,以与 AsyncModuleExecutionFulfilled 保持对称。在 InnerModuleEvaluation 中,当模块的 [[EvaluationError]] 内部槽不是 empty 时,不使用其 [[AsyncEvaluationOrder]] 内部槽的值。
  9. 如果 module.[[TopLevelCapability]] 不是 empty,则
    1. 断言:module.[[CycleRoot]] 和 module 是同一个 Module Record。
    2. 执行 ! Call(module.[[TopLevelCapability]].[[Reject]], undefined, « error »)。
  10. 对 module.[[AsyncParentModules]] 的每个 Cyclic Module Record ancestorModule,执行
    1. 执行 AsyncModuleExecutionRejected(ancestorModule, error)。
  11. 返回 unused。

16.2.1.6.2 Cyclic Module Record 图示例

本非规范性章节给出几个常见模块图的链接和求值示例,重点说明错误可能如何发生。

首先考虑以下简单模块图:

图 2: 一个简单的模块图
一个模块图,其中模块 A 依赖模块 B,而模块 B 依赖模块 C

首先假设不存在错误条件。当宿主首次调用 A.LoadRequestedModules() 时,根据假设,该调用会成功完成,并递归加载 B 和 C 的依赖项(分别为 C 和无),然后将 A.[[Status]] = B.[[Status]] = C.[[Status]] = unlinked。随后,当宿主调用 A.Link() 时,它也会成功完成(同样根据假设),使得 A.[[Status]] = B.[[Status]] = C.[[Status]] = linked。这些准备步骤可以在任何时间执行。之后,当宿主准备承担模块可能产生的任何副作用时,它可以调用 A.Evaluate(),该调用会成功完成,返回一个兑现为 undefined 的 Promise(同样根据假设),并递归地先求值 C,再求值 B。此时每个模块的 [[Status]] 都将是 evaluated。

接下来考虑在成功调用 A.LoadRequestedModules() 后发生链接错误的情况。如果 C 的 InnerModuleLinking 成功,但随后 B 失败,例如因为它导入了 C 未提供的内容,则最初的 A.Link() 将失败,并且 A 和 B 的 [[Status]] 都保持为 unlinked。不过,C 的 [[Status]] 已经变为 linked。

最后,考虑在成功调用 Link() 后发生求值错误的情况。如果 C 的 InnerModuleEvaluation 成功,但随后 B 失败,例如因为 B 包含抛出异常的代码,则最初的 A.Evaluate() 将失败,并返回被拒绝的 Promise。产生的异常会记录在 A 和 B 的 [[EvaluationError]] 字段中,它们的 [[Status]] 将变为 evaluated。C 也会变为 evaluated,但与 A 和 B 不同,由于其成功完成求值,它仍然没有 [[EvaluationError]]。存储该异常可确保宿主以后每次尝试通过调用 Evaluate() 方法重用 A 或 B 时,都会遇到同一个异常。(宿主不要求重用 Cyclic Module Record;同样,宿主也不要求暴露这些方法抛出的异常对象。不过,本规范允许此类用途。)

现在考虑另一种错误条件:

图 3: 包含无法解析模块的模块图
一个模块图,其中模块 A 依赖一个缺失(无法解析)的模块,以 ??? 表示

在这种场景中,模块 A 声明对另一个模块的依赖,但该模块不存在 Module Record,也就是说,当 HostLoadImportedModule 被要求加载它时,会以异常调用 FinishLoadingImportedModule。出现这种情况可能有多种原因,例如对应资源不存在,或者资源存在,但尝试解析所得源文本时 ParseModule 返回了一些错误。宿主可以选择通过传递给 FinishLoadingImportedModule 的完成来暴露失败原因。无论如何,此异常都会导致加载失败,使得 A 的 [[Status]] 保持为 new。

这里加载、链接和求值错误之间的差异源于以下特性:

  • 求值只能执行一次,因为它可能产生副作用;因此,即使求值失败,也必须记住是否已经执行过求值。(在错误情况下,同时记住异常也很合理,否则后续 Evaluate() 调用将不得不合成一个新的异常。)
  • 另一方面,链接没有副作用,因此即使失败,也可以在以后重试而不会产生问题。
  • 加载与宿主密切交互,并且某些宿主可能希望允许用户重试失败的加载(例如,如果失败是由暂时不良的网络状况引起的)。

现在,考虑具有循环的模块图:

图 4: 循环模块图
一个模块图,其中模块 A 依赖模块 B 和 C,而模块 B 也依赖模块 A

这里假设入口点是模块 A,因此宿主首先调用 A.LoadRequestedModules(),该调用对 A 执行 InnerModuleLoading。随后又对 B 和 C 调用 InnerModuleLoading。由于存在循环,这再次触发对 A 的 InnerModuleLoading,但此时它不执行任何操作,因为在此次 LoadRequestedModules 过程中,A 的依赖项加载已经被触发。当图中的所有模块都成功加载后,它们的 [[Status]] 会同时从 new 转换为 unlinked。

随后,宿主调用 A.Link(),该调用对 A 执行 InnerModuleLinking。接着对 B 执行 InnerModuleLinking。由于存在循环,这再次触发对 A 的 InnerModuleLinking,但此时它不执行任何操作,因为 A.[[Status]] 已经是 linking。当控制返回 A 并对 C 触发 InnerModuleLinking 时,B.[[Status]] 自身仍保持 linking。当此次调用返回并且 C.[[Status]] 为 linked 后,A 和 B 会一起从 linking 转换为 linked;这是有意设计的,因为它们构成一个强连通分量。之所以能够同时转换同一个 SCC 中模块的状态,是因为在这一阶段会使用深度优先搜索遍历模块图。

在成功情况下,循环模块图的求值阶段会发生类似的过程。

现在考虑 A 存在链接错误的情况;例如,它试图从 C 导入一个不存在的绑定。在这种情况下,上述步骤仍然会发生,包括第二次对 A 调用 InnerModuleLinking 时提前返回。不过,一旦我们展开回最初对 A 的 InnerModuleLinking,它就会在 InitializeEnvironment 期间失败,也就是紧接在 C.ResolveExport() 之后。抛出的 SyntaxError 异常会向上传播到 A.Link,后者会重置当前位于其 stack 上的所有模块(这些模块始终恰好是仍处于 linking 的模块)。因此,A 和 B 都会变为 unlinked。注意,C 仍保持 linked。

或者,考虑 A 存在求值错误的情况;例如,其源代码抛出异常。在这种情况下,与上述步骤对应的求值阶段仍然会发生,包括第二次对 A 调用 InnerModuleEvaluation 时提前返回。不过,一旦我们展开回最初对 A 的 InnerModuleEvaluation,根据假设它会失败。抛出的异常会向上传播到 A.Evaluate(),后者会在当前位于其 stack 上的所有模块(即仍处于 evaluating 的模块)中记录该错误;对于整个依赖图中包含顶层 await 或依赖顶层 await 的模块,还会通过 [[AsyncParentModules]] 以及 AsyncModuleExecutionRejected 算法形成的链传播。因此,A 和 B 都会变为 evaluated,并且异常会记录在 A 和 B 的 [[EvaluationError]] 字段中,而 C 保持为 evaluated 且没有 [[EvaluationError]]。

最后,考虑一个具有循环、且所有模块都异步完成的模块图:

图 5: 异步循环模块图
一个模块图,其中模块 A 依赖模块 B 和 C,模块 B 依赖模块 D,模块 C 依赖模块 D 和 E,而模块 D 依赖模块 A

加载和链接与之前一样发生,最终所有模块的 [[Status]] 都设置为 linked。

调用 A.Evaluate() 会对 A、B 和 D 调用 InnerModuleEvaluation,它们都会转换为 evaluating。随后再次对 A 调用 InnerModuleEvaluation,由于它已经是 evaluating,因此不执行任何操作。此时,D.[[PendingAsyncDependencies]] 为 0,所以调用 ExecuteAsyncModule(D),并使用一个新的 PromiseCapability 调用 D.ExecuteModule,以跟踪 D 的异步执行。我们展开回 B 的 InnerModuleEvaluation,将 B.[[PendingAsyncDependencies]] 设置为 1,并将 B.[[AsyncEvaluationOrder]] 设置为 1。然后展开回最初对 A 的 InnerModuleEvaluation,将 A.[[PendingAsyncDependencies]] 设置为 1。在遍历 A 依赖项的下一次循环迭代中,我们对 C 调用 InnerModuleEvaluation,从而又对 D(再次不执行任何操作)和 E 调用。由于 E 没有依赖项且不属于循环,因此我们以与 D 相同的方式调用 ExecuteAsyncModule(E),并立即将 E 从栈中移除。我们再次展开回 C 的 InnerModuleEvaluation,将 C.[[AsyncEvaluationOrder]] 设置为 3。现在我们完成对 A 依赖项的循环,将 A.[[AsyncEvaluationOrder]] 设置为 4,并从栈中移除整个强连通分量,同时将所有模块一次性转换为 evaluating-async。此时,模块字段如 表 44 所示。

表 44: 初始 Evaluate() 调用后的模块字段
字段
模块
A B C D E
[[DFSAncestorIndex]] 0 0 0 0 4
[[Status]] evaluating-async evaluating-async evaluating-async evaluating-async evaluating-async
[[AsyncEvaluationOrder]] 4 1 3 0 2
[[AsyncParentModules]] « » « A » « A » « B, C » « C »
[[PendingAsyncDependencies]] 2 (B 和 C) 1 (D) 2 (D 和 E) 0 0

假设 E 首先完成执行。发生这种情况时,会调用 AsyncModuleExecutionFulfilled,E.[[Status]] 设置为 evaluated,并将 C.[[PendingAsyncDependencies]] 递减为 1。更新后的模块字段如 表 45 所示。

表 45: 模块 E 完成执行后的模块字段
字段
模块
C E
[[DFSAncestorIndex]] 0 4
[[Status]] evaluating-async evaluated
[[AsyncEvaluationOrder]] 3 done
[[AsyncParentModules]] « A » « C »
[[PendingAsyncDependencies]] 1 (D) 0

接下来 D 完成执行(因为它是唯一仍在执行的模块)。发生这种情况时,再次调用 AsyncModuleExecutionFulfilled,并将 D.[[Status]] 设置为 evaluated。可供执行的祖先是 B(其 [[AsyncEvaluationOrder]] 为 1)和 C(其 [[AsyncEvaluationOrder]] 为 3),因此会首先处理 B:将 B.[[PendingAsyncDependencies]] 递减为 0,对 B 调用 ExecuteAsyncModule,并开始执行。C.[[PendingAsyncDependencies]] 也递减为 0,C 开始执行(如果 B 包含 await,则可能与 B 并行执行)。更新后的模块字段如 表 46 所示。

表 46: 模块 D 完成执行后的模块字段
字段
模块
B C D
[[DFSAncestorIndex]] 0 0 0
[[Status]] evaluating-async evaluating-async evaluated
[[AsyncEvaluationOrder]] 1 3 done
[[AsyncParentModules]] « A » « A » « B, C »
[[PendingAsyncDependencies]] 0 0 0

假设接下来 C 完成执行。发生这种情况时,再次调用 AsyncModuleExecutionFulfilled,C.[[Status]] 设置为 evaluated,并将 A.[[PendingAsyncDependencies]] 递减为 1。更新后的模块字段如 表 47 所示。

表 47: 模块 C 完成执行后的模块字段
字段
模块
A C
[[DFSAncestorIndex]] 0 0
[[Status]] evaluating-async evaluated
[[AsyncEvaluationOrder]] 4 done
[[AsyncParentModules]] « » « A »
[[PendingAsyncDependencies]] 1 (B) 0

然后,B 完成执行。发生这种情况时,再次调用 AsyncModuleExecutionFulfilled,并将 B.[[Status]] 设置为 evaluated。A.[[PendingAsyncDependencies]] 递减为 0,因此调用 ExecuteAsyncModule,A 开始执行。更新后的模块字段如 表 48 所示。

表 48: 模块 B 完成执行后的模块字段
字段
模块
A B
[[DFSAncestorIndex]] 0 0
[[Status]] evaluating-async evaluated
[[AsyncEvaluationOrder]] 4 done
[[AsyncParentModules]] « » « A »
[[PendingAsyncDependencies]] 0 0

最后,A 完成执行。发生这种情况时,再次调用 AsyncModuleExecutionFulfilled,并将 A.[[Status]] 设置为 evaluated。此时,A.[[TopLevelCapability]] 中的 Promise(它由 A.Evaluate() 返回)会被兑现,从而结束对该模块图的处理。更新后的模块字段如 表 49 所示。

表 49: 模块 A 完成执行后的模块字段
字段
模块
A
[[DFSAncestorIndex]] 0
[[Status]] evaluated
[[AsyncEvaluationOrder]] done
[[AsyncParentModules]] « »
[[PendingAsyncDependencies]] 0

或者,考虑失败情况:C 执行失败,并在 B 完成执行之前返回错误。发生这种情况时,会调用 AsyncModuleExecutionRejected,将 C.[[Status]] 设置为 evaluated,并将 C.[[EvaluationError]] 设置为该错误。然后,它通过对所有 AsyncParentModules 执行 AsyncModuleExecutionRejected,将此错误传播给它们。更新后的模块字段如 表 50 所示。

表 50: 模块 C 以错误结束后的模块字段
字段
模块
A C
[[DFSAncestorIndex]] 0 0
[[Status]] evaluated evaluated
[[AsyncEvaluationOrder]] done done
[[AsyncParentModules]] « » « A »
[[PendingAsyncDependencies]] 1 (B) 0
[[EvaluationError]] empty C 的求值错误

A 将以与 C 相同的错误被拒绝,因为 C 会以 C 的错误对 A 调用 AsyncModuleExecutionRejected。A.[[Status]] 设置为 evaluated。此时,A.[[TopLevelCapability]] 中的 Promise(它由 A.Evaluate() 返回)被拒绝。更新后的模块字段如 表 51 所示。

表 51: 模块 A 被拒绝后的模块字段
字段
模块
A
[[DFSAncestorIndex]] 0
[[Status]] evaluated
[[AsyncEvaluationOrder]] done
[[AsyncParentModules]] « »
[[PendingAsyncDependencies]] 0
[[EvaluationError]] C 的求值错误

然后,B 在没有错误的情况下完成执行。发生这种情况时,再次调用 AsyncModuleExecutionFulfilled,并将 B.[[Status]] 设置为 evaluated。对 B 调用 GatherAvailableAncestors。不过,A.[[CycleRoot]] 是 A,而 A 存在求值错误,因此它不会被加入返回的 sortedExecList,AsyncModuleExecutionFulfilled 会在不进一步处理的情况下返回。以后任何导入 B 的模块,都会根据循环根 A 上由 C 设置的求值错误,从 B.[[CycleRoot]].[[EvaluationError]] 得到拒绝。更新后的模块字段如 表 52 所示。

表 52: 存在错误的模块图中模块 B 完成执行后的模块字段
字段
模块
A B
[[DFSAncestorIndex]] 0 0
[[Status]] evaluated evaluated
[[AsyncEvaluationOrder]] 4 1
[[AsyncParentModules]] « » « A »
[[PendingAsyncDependencies]] 0 0
[[EvaluationError]] C 的求值错误 empty

16.2.1.7 Source Text Module Records

Source Text Module Record 用于表示有关模块的信息,该模块由使用目标符号 Module 解析的 ECMAScript 源文本(11)定义。其字段包含有关模块所导入和导出名称的归纳信息,其具体方法使用这些归纳信息来链接和求值模块。

Source Text Module Record 可以与抽象 Module Record 类型的其他子类共同存在于一个模块图中,并且可以与 Cyclic Module Record 类型的其他子类参与循环。

除 表 41 中定义的字段外,Source Text Module Record 还具有 表 53 中列出的附加字段。每个字段最初都在 ParseModule 中设置。

表 53: Source Text Module Records 的附加字段
字段名称 值类型 含义
[[ECMAScriptCode]] a Parse Node 使用 Module 作为目标符号解析此模块源文本的结果。
[[Context]] an ECMAScript code execution context or empty 与此模块关联的执行上下文。在模块环境初始化之前,它为 empty。
[[ImportMeta]] an Object or empty 通过 import.meta 元属性暴露的对象。在 ECMAScript 代码访问它之前,它为 empty。
[[ImportEntries]] a List of ImportEntry Records 从此模块代码派生的 ImportEntry record 的 List。
[[LocalExportEntries]] a List of ExportEntry Records 从此模块代码派生的 ExportEntry record 的 List,这些 record 对应于模块内部出现的声明。
[[IndirectExportEntries]] a List of ExportEntry Records 从此模块代码派生的 ExportEntry record 的 List,这些 record 对应于模块内部出现的重新导出的导入,或者来自 export * as namespace 声明的导出。
[[StarExportEntries]] a List of ExportEntry Records 从此模块代码派生的 ExportEntry record 的 List,这些 record 对应于模块内部出现的 export * 声明,但不包括 export * as namespace 声明。

ImportEntry Record 是归纳单个声明式导入相关信息的 Record。每个 ImportEntry Record 都具有 表 54 中定义的字段:

表 54: ImportEntry Record 字段
字段名称 值类型 含义
[[ModuleRequest]] a ModuleRequest Record 表示 ImportDeclaration 的 ModuleSpecifier 和导入属性的 ModuleRequest Record。
[[ImportName]] a String or namespace 由 [[ModuleRequest]] 标识的模块导出所需绑定时使用的名称。值 namespace 表示导入请求针对目标模块的命名空间对象。
[[LocalName]] a String 在导入模块内部用于局部访问所导入值的名称。
注 1

表 55 给出了用于表示句法导入形式的 ImportEntry record 字段示例:

表 55 (资料性): 导入形式到 ImportEntry Records 的映射
导入语句形式 [[ModuleRequest]] [[ImportName]] [[LocalName]]
import v from "mod"; "mod" "default" "v"
import * as ns from "mod"; "mod" namespace "ns"
import {x} from "mod"; "mod" "x" "x"
import {x as v} from "mod"; "mod" "x" "v"
import "mod"; 不创建 ImportEntry Record。

ExportEntry Record 是归纳单个声明式导出相关信息的 Record。每个 ExportEntry Record 都具有 表 56 中定义的字段:

表 56: ExportEntry Record 字段
字段名称 值类型 含义
[[ExportName]] a String or null 此模块用于导出该绑定的名称。
[[ModuleRequest]] a ModuleRequest Record or null 表示 ExportDeclaration 的 ModuleSpecifier 和导入属性的 ModuleRequest Record。如果 ExportDeclaration 没有 ModuleSpecifier,则为 null。
[[ImportName]] a String, null, namespace, or all-but-default 由 [[ModuleRequest]] 标识的模块导出所需绑定时使用的名称。如果 ExportDeclaration 没有 ModuleSpecifier,则为 null。namespace 用于 export * as ns from "mod" 声明。all-but-default 用于 export * from "mod" 声明。
[[LocalName]] a String or null 在导入模块内部用于局部访问所导出值的名称。如果无法从模块内部局部访问导出的值,则为 null。
注 2

表 57 给出了用于表示句法导出形式的 ExportEntry record 字段示例:

表 57 (资料性): 导出形式到 ExportEntry Records 的映射
导出语句形式 [[ExportName]] [[ModuleRequest]] [[ImportName]] [[LocalName]]
export var v; "v" null null "v"
export default function f() {} "default" null null "f"
export default function () {} "default" null null "*default*"
export default 42; "default" null null "*default*"
export {x}; "x" null null "x"
export {v as x}; "x" null null "v"
export {x} from "mod"; "x" "mod" "x" null
export {v as x} from "mod"; "x" "mod" "v" null
export * from "mod"; null "mod" all-but-default null
export * as ns from "mod"; "ns" "mod" namespace null

以下定义规定 Source Text Module Record 所需的具体方法和其他抽象操作

16.2.1.7.1 ParseModule ( sourceText, realm, hostDefined )

抽象操作 ParseModule,接收参数 sourceText ((String 或 a sequence of Unicode code points))、realm (Realm 记录) 和 hostDefined (任意值);返回值:(Source Text Module 记录 或 a non-empty List of SyntaxError objects)。 它根据将 sourceText 作为 Module 解析的结果创建 Source Text Module Record。 调用时执行以下步骤:

  1. 令 body 为 ParseText(sourceText, Module)。
  2. 如果 body 是错误的 List,则返回 body。
  3. 令 requestedModules 为 body 的 ModuleRequests。
  4. 令 importEntries 为 body 的 ImportEntries。
  5. 令 importedBoundNames 为 ImportedLocalNames(importEntries)。
  6. 令 indirectExportEntries 为新的空 List。
  7. 令 localExportEntries 为新的空 List。
  8. 令 starExportEntries 为新的空 List。
  9. 令 exportEntries 为 body 的 ExportEntries。
  10. 对 exportEntries 的每个 ExportEntry Record exportEntry,执行
    1. 如果 exportEntry.[[ModuleRequest]] 是 null,则
      1. 如果 importedBoundNames 不包含 exportEntry.[[LocalName]],则
        1. 将 exportEntry 追加到 localExportEntries。
      2. 否则,
        1. 注:当导出最初从另一个模块导入的绑定或命名空间对象时,会重写 ExportEntry Record,使其形式与直接从原始模块重新导出该绑定或命名空间对象时的形式相同,而不是先导入再导出。这样,通过 export * from 以同一名称两次导出同一绑定或命名空间所产生的冲突就可以被忽略,而不是在 Source Text Module Records 的 ResolveExport 具体方法的步骤 9.e.iii 中被视为歧义。
        2. 令 importEntry 为 importEntries 中 [[LocalName]] 是 exportEntry.[[LocalName]] 的元素。
        3. 将 ExportEntry Record { [[ModuleRequest]]: importEntry.[[ModuleRequest]], [[ImportName]]: importEntry.[[ImportName]], [[LocalName]]: null, [[ExportName]]: exportEntry.[[ExportName]] } 追加到 indirectExportEntries。
    2. 否则如果 exportEntry.[[ImportName]] 是 all-but-default,则
      1. 断言:exportEntry.[[ExportName]] 是 null。
      2. 将 exportEntry 追加到 starExportEntries。
    3. 否则,
      1. 将 exportEntry 追加到 indirectExportEntries。
  11. 令 async 为 body Contains await。
  12. 返回 Source Text Module Record { [[Realm]]: realm, [[Environment]]: empty, [[Namespace]]: empty, [[CycleRoot]]: empty, [[HasTLA]]: async, [[AsyncEvaluationOrder]]: unset, [[TopLevelCapability]]: empty, [[AsyncParentModules]]: « », [[PendingAsyncDependencies]]: empty, [[Status]]: new, [[EvaluationError]]: empty, [[HostDefined]]: hostDefined, [[ECMAScriptCode]]: body, [[Context]]: empty, [[ImportMeta]]: empty, [[RequestedModules]]: requestedModules, [[LoadedModules]]: « », [[ImportEntries]]: importEntries, [[LocalExportEntries]]: localExportEntries, [[IndirectExportEntries]]: indirectExportEntries, [[StarExportEntries]]: starExportEntries, [[DFSAncestorIndex]]: empty }。
注

实现可以在对该模块源文本执行 ParseModule 之前解析模块源文本,并分析其中的提前错误条件。不过,任何错误的报告都必须推迟到本规范实际对该源文本执行 ParseModule 时。

16.2.1.7.2 Module Record 抽象方法的实现

以下是 Source Text Module Record 的具体方法,它们实现 表 40 中定义的相应 Module Record 抽象方法。

16.2.1.7.2.1 GetExportedNames ( [ exportStarSet ] )

a Source Text Module Record module的具体方法 GetExportedNames,接收可选参数 exportStarSet (列表 (元素:Source Text Module 记录));返回值:列表 (元素:String)。 调用时执行以下步骤:

  1. 断言:module.[[Status]] 不是 new。
  2. 如果不存在 exportStarSet,则将 exportStarSet 设置为新的空 List。
  3. 如果 exportStarSet 包含 module,则
    1. 断言:我们已到达 export * 循环的起点。
    2. 返回新的空 List。
  4. 将 module 追加到 exportStarSet。
  5. 令 exportedNames 为新的空 List。
  6. 对 module.[[LocalExportEntries]] 的每个 ExportEntry Record exportEntry,执行
    1. 断言:module 为此导出提供直接绑定。
    2. 断言:exportEntry.[[ExportName]] 不是 null。
    3. 将 exportEntry.[[ExportName]] 追加到 exportedNames。
  7. 对 module.[[IndirectExportEntries]] 的每个 ExportEntry Record exportEntry,执行
    1. 断言:module 为此导出导入特定绑定。
    2. 断言:exportEntry.[[ExportName]] 不是 null。
    3. 将 exportEntry.[[ExportName]] 追加到 exportedNames。
  8. 对 module.[[StarExportEntries]] 的每个 ExportEntry Record exportEntry,执行
    1. 断言:exportEntry.[[ModuleRequest]] 不是 null。
    2. 令 requestedModule 为 GetImportedModule(module, exportEntry.[[ModuleRequest]])。
    3. 令 starNames 为 requestedModule.GetExportedNames(exportStarSet)。
    4. 对 starNames 的每个元素 name,执行
      1. 如果 name 不是 "default",则
        1. 如果 exportedNames 不包含 name,则
          1. 将 name 追加到 exportedNames。
  9. 返回 exportedNames。
注

GetExportedNames 不会过滤具有歧义星号导出绑定的名称,也不会为其抛出异常。

16.2.1.7.2.2 ResolveExport ( exportName [ , resolveSet ] )

a Source Text Module Record module的具体方法 ResolveExport,接收参数 exportName (String)和可选参数 resolveSet (列表 (元素:记录 (字段:[[Module]] (Module 记录), [[ExportName]] (String))));返回值:(ResolvedBinding 记录、null 或 ambiguous)。

ResolveExport 尝试将导入绑定解析到实际定义它的模块和局部绑定名称。定义模块可以是调用此方法的 Module Record 所表示的模块,也可以是该模块导入的其他模块。参数 resolveSet 用于检测无法解析的循环导入/导出路径。如果到达由特定 Module Record 和 exportName 组成、且已经存在于 resolveSet 中的二元组,则说明遇到了导入循环。在递归调用 ResolveExport 之前,会将由 module 和 exportName 组成的二元组添加到 resolveSet。

如果找到定义模块,则返回 ResolvedBinding Record { [[Module]], [[BindingName]] }。除非这是没有局部绑定的命名空间导出,否则此 record 标识最初请求的导出的已解析绑定。在这种情况下,[[BindingName]] 将设置为 namespace。如果没有找到定义或发现请求是循环的,则返回 null。如果发现请求存在歧义,则返回 ambiguous。

调用时执行以下步骤:

  1. 断言:module.[[Status]] 不是 new。
  2. 如果不存在 resolveSet,则将 resolveSet 设置为新的空 List。
  3. 对 resolveSet 的每个 Record { [[Module]], [[ExportName]] } record,执行
    1. 如果 module 和 record.[[Module]] 是同一个 Module Record,并且 exportName 是 record.[[ExportName]],则
      1. 断言:这是循环导入请求。
      2. 返回 null。
  4. 将 Record { [[Module]]: module, [[ExportName]]: exportName } 追加到 resolveSet。
  5. 对 module.[[LocalExportEntries]] 的每个 ExportEntry Record exportEntry,执行
    1. 如果 exportEntry.[[ExportName]] 是 exportName,则
      1. 断言:module 为此导出提供直接绑定。
      2. 返回 ResolvedBinding Record { [[Module]]: module, [[BindingName]]: exportEntry.[[LocalName]] }。
  6. 对 module.[[IndirectExportEntries]] 的每个 ExportEntry Record exportEntry,执行
    1. 如果 exportEntry.[[ExportName]] 是 exportName,则
      1. 断言:exportEntry.[[ModuleRequest]] 不是 null。
      2. 令 importedModule 为 GetImportedModule(module, exportEntry.[[ModuleRequest]])。
      3. 如果 exportEntry.[[ImportName]] 是 namespace,则
        1. 断言:module 不为此导出提供直接绑定。
        2. 返回 ResolvedBinding Record { [[Module]]: importedModule, [[BindingName]]: namespace }。
      4. 断言:module 为此导出导入特定绑定。
      5. 断言:exportEntry.[[ImportName]] 是 String。
      6. 返回 importedModule.ResolveExport(exportEntry.[[ImportName]], resolveSet)。
  7. 如果 exportName 是 "default",则
    1. 断言:此模块未显式定义 default 导出。
    2. 返回 null。
    3. 注:default 导出无法由 export * from "mod" 声明提供。
  8. 令 starResolution 为 null。
  9. 对 module.[[StarExportEntries]] 的每个 ExportEntry Record exportEntry,执行
    1. 断言:exportEntry.[[ModuleRequest]] 不是 null。
    2. 令 importedModule 为 GetImportedModule(module, exportEntry.[[ModuleRequest]])。
    3. 令 resolution 为 importedModule.ResolveExport(exportName, resolveSet)。
    4. 如果 resolution 是 ambiguous,则返回 ambiguous。
    5. 如果 resolution 不是 null,则
      1. 断言:resolution 是 ResolvedBinding Record。
      2. 如果 starResolution 是 null,则
        1. 将 starResolution 设置为 resolution。
      3. 否则,
        1. 断言:有不止一个 * 导出包含请求的名称。
        2. 如果 resolution.[[Module]] 和 starResolution.[[Module]] 不是同一个 Module Record,则返回 ambiguous。
        3. 如果 resolution.[[BindingName]] 不是 starResolution.[[BindingName]],则返回 ambiguous。
  10. 返回 starResolution。

16.2.1.7.3 Cyclic Module Record 抽象方法的实现

以下是 Source Text Module Record 的具体方法,它们实现 表 42 中定义的相应 Cyclic Module Record 抽象方法。

16.2.1.7.3.1 InitializeEnvironment ( )

a Source Text Module Record module的具体方法 InitializeEnvironment,接收无参数;返回值:(正常完成 (值:unused) 或 抛出完成)。 调用时执行以下步骤:

  1. 对 module.[[IndirectExportEntries]] 的每个 ExportEntry Record exportEntry,执行
    1. 断言:exportEntry.[[ExportName]] 不是 null。
    2. 令 resolution 为 module.ResolveExport(exportEntry.[[ExportName]])。
    3. 如果 resolution 是 null 或 ambiguous,则抛出 SyntaxError 异常。
    4. 断言:resolution 是 ResolvedBinding Record。
  2. 断言:来自 module 的所有具名导出都可解析。
  3. 令 realm 为 module.[[Realm]]。
  4. 断言:realm 不是 undefined。
  5. 令 envRecord 为 NewModuleEnvironment(realm.[[GlobalEnv]])。
  6. 将 module.[[Environment]] 设置为 envRecord。
  7. 对 module.[[ImportEntries]] 的每个 ImportEntry Record importEntry,执行
    1. 令 importedModule 为 GetImportedModule(module, importEntry.[[ModuleRequest]])。
    2. 如果 importEntry.[[ImportName]] 是 namespace,则
      1. 令 namespace 为 GetModuleNamespace(importedModule)。
      2. 执行 ! envRecord.CreateImmutableBinding(importEntry.[[LocalName]], true)。
      3. 执行 ! envRecord.InitializeBinding(importEntry.[[LocalName]], namespace)。
    3. 否则,
      1. 断言:importEntry.[[ImportName]] 是 String。
      2. 令 resolution 为 importedModule.ResolveExport(importEntry.[[ImportName]])。
      3. 如果 resolution 是 null 或 ambiguous,则抛出 SyntaxError 异常。
      4. 如果 resolution.[[BindingName]] 是 namespace,则
        1. 令 namespace 为 GetModuleNamespace(resolution.[[Module]])。
        2. 执行 ! envRecord.CreateImmutableBinding(importEntry.[[LocalName]], true)。
        3. 执行 ! envRecord.InitializeBinding(importEntry.[[LocalName]], namespace)。
      5. 否则,
        1. 执行 CreateImportBinding(envRecord, importEntry.[[LocalName]], resolution.[[Module]], resolution.[[BindingName]])。
  8. 令 moduleContext 为新的 ECMAScript 代码执行上下文。
  9. 将 moduleContext 的 Function 设置为 null。
  10. 断言:module.[[Realm]] 不是 undefined。
  11. 将 moduleContext 的 Realm 设置为 module.[[Realm]]。
  12. 将 moduleContext 的 ScriptOrModule 设置为 module。
  13. 将 moduleContext 的 VariableEnvironment 设置为 module.[[Environment]]。
  14. 将 moduleContext 的 LexicalEnvironment 设置为 module.[[Environment]]。
  15. 将 moduleContext 的 PrivateEnvironment 设置为 null。
  16. 将 module.[[Context]] 设置为 moduleContext。
  17. 将 moduleContext 压入执行上下文栈;moduleContext 现在成为正在运行的执行上下文。
  18. 令 code 为 module.[[ECMAScriptCode]]。
  19. 令 variableDecls 为 code 的 VarScopedDeclarations。
  20. 令 declaredVariableNames 为新的空 List。
  21. 对 variableDecls 的每个元素 variableDecl,执行
    1. 对 variableDecl 的 BoundNames 的每个元素 name,执行
      1. 如果 declaredVariableNames 不包含 name,则
        1. 执行 ! envRecord.CreateMutableBinding(name, false)。
        2. 执行 ! envRecord.InitializeBinding(name, undefined)。
        3. 将 name 追加到 declaredVariableNames。
  22. 令 lexicalDecls 为 code 的 LexicallyScopedDeclarations。
  23. 令 privateEnv 为 null。
  24. 对 lexicalDecls 的每个元素 lexicalDecl,执行
    1. 对 lexicalDecl 的 BoundNames 的每个元素 name,执行
      1. 如果 lexicalDecl 的 IsConstantDeclaration 是 true,则
        1. 执行 ! envRecord.CreateImmutableBinding(name, true)。
      2. 否则,
        1. 执行 ! envRecord.CreateMutableBinding(name, false)。
      3. 如果 lexicalDecl 是 FunctionDeclaration、GeneratorDeclaration、AsyncFunctionDeclaration 或 AsyncGeneratorDeclaration 之一,则
        1. 令 funcObj 为以 envRecord 和 privateEnv 为参数对 lexicalDecl 执行 InstantiateFunctionObject 的结果。
        2. 执行 ! envRecord.InitializeBinding(name, funcObj)。
  25. 从执行上下文栈中移除 moduleContext。
  26. 返回 unused。

16.2.1.7.3.2 ExecuteModule ( [ capability ] )

a Source Text Module Record module的具体方法 ExecuteModule,接收可选参数 capability (PromiseCapability 记录);返回值:(正常完成 (值:unused) 或 抛出完成)。 调用时执行以下步骤:

  1. 断言:module 已被链接,并且其模块环境中的声明已被实例化。
  2. 令 moduleContext 为 module.[[Context]]。
  3. 如果 module.[[HasTLA]] 是 false,则
    1. 断言:不存在 capability。
    2. 令 env 为 module.[[Environment]]。
    3. 挂起正在运行的执行上下文。
    4. 将 moduleContext 压入执行上下文栈;moduleContext 现在成为正在运行的执行上下文。
    5. 令 result 为 Completion(module.[[ECMAScriptCode]] 的 Evaluation)。
    6. 将 result 设置为 Completion(DisposeResources(env.[[DisposableResourceStack]], result))。
    7. 挂起 moduleContext 并将其从执行上下文栈中移除。
    8. 恢复当前位于执行上下文栈顶部的上下文,并将其作为正在运行的执行上下文。
    9. 如果 result 是突然完成,则
      1. 返回 ? result。
  4. 否则,
    1. 断言:capability 是 PromiseCapability Record。
    2. 执行 AsyncBlockStart(capability, module.[[ECMAScriptCode]], moduleContext)。
  5. 返回 unused。

16.2.1.8 Synthetic Module Records

Synthetic Module Record 用于表示由规范定义的模块相关信息。其导出名称在创建时静态定义,而对应值可以随时间通过 SetSyntheticModuleExport 更改。它没有导入或依赖项。

注
Synthetic Module Record 可用于定义各种模块类型:例如 JSON 模块或 CSS 模块。

除 表 39 中定义的字段外,Synthetic Module Record 还具有 表 58 中列出的附加字段。

表 58: Synthetic Module Records 的附加字段
字段名称 值类型 含义
[[ExportNames]] a List of Strings 模块的导出名称。此列表不包含重复项。
[[EvaluationSteps]] an Abstract Closure 对模块求值时要执行的初始化逻辑,以 Synthetic Module Record 作为其唯一参数。它不得修改 [[ExportNames]]。它可以返回突然完成。

16.2.1.8.1 CreateDefaultExportSyntheticModule ( defaultExport )

抽象操作 CreateDefaultExportSyntheticModule,接收参数 defaultExport (ECMAScript 语言值);返回值:Synthetic Module 记录。 它创建一个默认导出为 defaultExport 的 Synthetic Module Record。 调用时执行以下步骤:

  1. 令 realm 为当前 Realm Record。
  2. 令 setDefaultExport 为一个具有参数 (module) 的新 Abstract Closure,它捕获 defaultExport,并在被调用时执行以下步骤:
    1. 执行 SetSyntheticModuleExport(module, "default", defaultExport)。
    2. 返回 NormalCompletion(unused)。
  3. 返回 Synthetic Module Record { [[Realm]]: realm, [[Environment]]: empty, [[Namespace]]: empty, [[HostDefined]]: undefined, [[ExportNames]]: « "default" », [[EvaluationSteps]]: setDefaultExport }。

16.2.1.8.2 ParseJSONModule ( source )

抽象操作 ParseJSONModule,接收参数 source (String);返回值:(正常完成 (值:Synthetic Module 记录) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 parseResult 为 ? ParseJSON(source)。
  2. 返回 CreateDefaultExportSyntheticModule(parseResult.[[Value]])。

16.2.1.8.3 SetSyntheticModuleExport ( module, exportName, exportValue )

抽象操作 SetSyntheticModuleExport,接收参数 module (Synthetic Module 记录)、exportName (String) 和 exportValue (ECMAScript 语言值);返回值:unused。 它可用于设置或更改 Synthetic Module Record 的现有导出的导出值。 调用时执行以下步骤:

  1. 断言:module.[[ExportNames]] 包含 exportName。
  2. 令 envRecord 为 module.[[Environment]]。
  3. 断言:envRecord 不是 empty。
  4. 执行 ! envRecord.SetMutableBinding(exportName, exportValue, true)。
  5. 返回 unused。

16.2.1.8.4 Module Record 抽象方法的实现

以下是 Synthetic Module Record 的具体方法,它们实现 表 40 中定义的相应 Module Record 抽象方法。

16.2.1.8.4.1 LoadRequestedModules ( [ hostDefined ] )

a Synthetic Module Record module的具体方法 LoadRequestedModules,接收可选参数 hostDefined (任意值);返回值:Promise。 调用时执行以下步骤:

  1. 注:此 LoadRequestedModules 实现不使用 hostDefined。
  2. 返回 ! PromiseResolve(%Promise%, undefined)。
注
Synthetic Module Record 没有依赖项。

16.2.1.8.4.2 GetExportedNames ( [ exportStarSet ] )

a Synthetic Module Record module的具体方法 GetExportedNames,接收可选参数 exportStarSet (列表 (元素:Source Text Module 记录));返回值:列表 (元素:String)。 调用时执行以下步骤:

  1. 注:此 GetExportedNames 实现不使用 exportStarSet。
  2. 返回 module.[[ExportNames]]。

16.2.1.8.4.3 ResolveExport ( exportName [ , resolveSet ] )

a Synthetic Module Record module的具体方法 ResolveExport,接收参数 exportName (String)和可选参数 resolveSet (列表 (元素:记录 (字段:[[Module]] (Module 记录), [[ExportName]] (String))));返回值:(ResolvedBinding 记录、null 或 ambiguous)。 调用时执行以下步骤:

  1. 注:此 ResolveExport 实现不使用 resolveSet。
  2. 如果 module.[[ExportNames]] 不包含 exportName,则返回 null。
  3. 返回 ResolvedBinding Record { [[Module]]: module, [[BindingName]]: exportName }。

16.2.1.8.4.4 Link ( )

a Synthetic Module Record module的具体方法 Link,接收无参数;返回值:正常完成 (值:unused)。 调用时执行以下步骤:

  1. 令 realm 为 module.[[Realm]]。
  2. 令 envRecord 为 NewModuleEnvironment(realm.[[GlobalEnv]])。
  3. 将 module.[[Environment]] 设置为 envRecord。
  4. 对 module.[[ExportNames]] 的每个 String exportName,执行
    1. 执行 ! envRecord.CreateMutableBinding(exportName, false)。
    2. 执行 ! envRecord.InitializeBinding(exportName, undefined)。
  5. 返回 NormalCompletion(unused)。

16.2.1.8.4.5 Evaluate ( )

a Synthetic Module Record module的具体方法 Evaluate,接收无参数;返回值:Promise。 调用时执行以下步骤:

  1. 令 moduleContext 为新的 ECMAScript 代码执行上下文。
  2. 将 moduleContext 的 Function 设置为 null。
  3. 将 moduleContext 的 Realm 设置为 module.[[Realm]]。
  4. 将 moduleContext 的 ScriptOrModule 设置为 module。
  5. 将 moduleContext 的 VariableEnvironment 设置为 module.[[Environment]]。
  6. 将 moduleContext 的 LexicalEnvironment 设置为 module.[[Environment]]。
  7. 挂起正在运行的执行上下文。
  8. 将 moduleContext 压入执行上下文栈;moduleContext 现在成为正在运行的执行上下文。
  9. 令 steps 为 module.[[EvaluationSteps]]。
  10. 令 result 为 Completion(steps(module))。
  11. 挂起 moduleContext 并将其从执行上下文栈中移除。
  12. 恢复当前位于执行上下文栈顶部的上下文,并将其作为正在运行的执行上下文。
  13. 令 promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  14. IfAbruptRejectPromise(result, promiseCapability)。
  15. 执行 ! Call(promiseCapability.[[Resolve]], undefined, « undefined »)。
  16. 返回 promiseCapability.[[Promise]]。

16.2.1.9 GetImportedModule ( referrer, request )

抽象操作 GetImportedModule,接收参数 referrer (Cyclic Module 记录) 和 request (ModuleRequest 记录);返回值:Module 记录。 调用时执行以下步骤:

  1. 令 records 为一个 List,它由 referrer.[[LoadedModules]] 的每个 LoadedModuleRequest Record r 组成,其中 ModuleRequestsEqual(r, request) 是 true。
  2. 断言:records 恰好有一个元素,因为在调用此抽象操作之前,LoadRequestedModules 已经在 referrer 上成功完成。
  3. 令 record 为 records 的唯一元素。
  4. 返回 record.[[Module]]。

16.2.1.10 HostLoadImportedModule ( referrer, moduleRequest, hostDefined, payload )

宿主定义的抽象操作 HostLoadImportedModule,接收参数 referrer ((Script 记录、Cyclic Module 记录 或 Realm 记录))、moduleRequest (ModuleRequest 记录)、hostDefined (任意值) 和 payload ((GraphLoadingState 记录 或 PromiseCapability 记录));返回值:unused。

注 1

referrer 可以是 Realm Record 的一个示例出现在 Web 浏览器宿主中。在那里,如果用户点击由以下代码给出的控件

<button type="button" onclick="import('./foo.mjs')">点击我</button>

那么在 import() 表达式运行时将没有活动的 script 或 module。更一般地说,在宿主将 ScriptOrModule 组成部分为 null 的执行上下文压入执行上下文栈的任何情况下,都可能发生这种情况。

HostLoadImportedModule 的实现必须符合以下要求:

实际执行的过程由宿主定义,但通常包括执行加载相应 Module Record 所需的任何 I/O 操作。多个不同的 (referrer, moduleRequest.[[Specifier]], moduleRequest.[[Attributes]]) 三元组可以映射到同一个 Module Record 实例。实际映射语义由宿主定义,但通常在映射过程中会对 specifier 应用规范化过程。典型的规范化过程包括展开相对路径和缩写路径说明符等操作。

注 2

上述文本要求宿主在使用 type: "json" 导入时支持 JSON 模块(并且 HostLoadImportedModule 正常完成),但并不禁止宿主在未使用 type: "json" 导入时支持 JSON 模块。

16.2.1.11 FinishLoadingImportedModule ( referrer, moduleRequest, payload, result )

抽象操作 FinishLoadingImportedModule,接收参数 referrer ((Script 记录、Cyclic Module 记录 或 Realm 记录))、moduleRequest (ModuleRequest 记录)、payload ((GraphLoadingState 记录 或 PromiseCapability 记录)) 和 result ((正常完成 (值:Module 记录) 或 抛出完成));返回值:unused。 调用时执行以下步骤:

  1. 如果 result 是正常完成,则
    1. 如果 referrer.[[LoadedModules]] 包含某个 LoadedModuleRequest Record record,使得 ModuleRequestsEqual(record, moduleRequest) 是 true,则
      1. 断言:record.[[Module]] 和 result.[[Value]] 是同一个 Module Record。
    2. 否则,
      1. 将 LoadedModuleRequest Record { [[Specifier]]: moduleRequest.[[Specifier]], [[Attributes]]: moduleRequest.[[Attributes]], [[Module]]: result.[[Value]] } 追加到 referrer.[[LoadedModules]]。
  2. 如果 payload 是 GraphLoadingState Record,则
    1. 执行 ContinueModuleLoading(payload, result)。
  3. 否则,
    1. 执行 ContinueDynamicImport(payload, result)。
  4. 返回 unused。

16.2.1.12 AllImportAttributesSupported ( attrs )

抽象操作 AllImportAttributesSupported,接收参数 attrs (列表 (元素:ImportAttribute 记录));返回值:Boolean。 调用时执行以下步骤:

  1. 令 supported 为 HostGetSupportedImportAttributes()。
  2. 对 attrs 的每个 ImportAttribute Record attr,执行
    1. 如果 supported 不包含 attr.[[Key]],则返回 false。
  3. 返回 true。

16.2.1.12.1 HostGetSupportedImportAttributes ( )

宿主定义的抽象操作 HostGetSupportedImportAttributes,接收无参数;返回值:列表 (元素:String)。 它允许宿主环境指定其支持哪些导入属性。只有键受支持的属性才会提供给宿主。

HostGetSupportedImportAttributes 的实现必须符合以下要求:

  • 它必须返回 String 的 List,每个 String 表示一个受支持的属性。
  • 每次调用此操作时,都必须返回内容相同、顺序相同的同一个 List。

HostGetSupportedImportAttributes 的默认实现是返回新的空 List。

注
要求宿主指定其支持的导入属性,而不是将所有属性传递给宿主再由宿主选择要处理哪些属性,其目的是确保不同宿主以一致方式处理不受支持的属性。

16.2.1.13 GetModuleNamespace ( module )

抽象操作 GetModuleNamespace,接收参数 module (instance of a concrete subclass of Module 记录);返回值:a Module Namespace Object。 它获取表示 module 导出的 Module Namespace Object,在首次请求时惰性创建该对象,并将其存储在 module.[[Namespace]] 中以供将来获取。 调用时执行以下步骤:

  1. 断言:如果 module 是 Cyclic Module Record,则 module.[[Status]] 不是 new 或 unlinked。
  2. 令 namespace 为 module.[[Namespace]]。
  3. 如果 namespace 是 empty,则
    1. 令 exportedNames 为 module.GetExportedNames()。
    2. 令 unambiguousNames 为新的空 List。
    3. 对 exportedNames 的每个元素 name,执行
      1. 令 resolution 为 module.ResolveExport(name)。
      2. 如果 resolution 是 ResolvedBinding Record,则将 name 追加到 unambiguousNames。
    4. 将 namespace 设置为 ModuleNamespaceCreate(module, unambiguousNames)。
  4. 返回 namespace。
注

GetModuleNamespace 永远不会抛出异常。相反,无法解析的名称此时会直接从命名空间中排除。除非它们全都是未在任何地方被显式请求的歧义星号导出,否则它们之后会导致真正的链接错误。

16.2.1.14 Runtime Semantics: Evaluation

Module : [empty]
  1. 返回 undefined。
ModuleBody : ModuleItemList
  1. 令 result 为 Completion(ModuleItemList 的 Evaluation)。
  2. 如果 result 是正常完成且 result.[[Value]] 是 empty,则
    1. 返回 undefined。
  3. 返回 ? result。
ModuleItemList : ModuleItemList ModuleItem
  1. 令 sl 为 ? ModuleItemList 的 Evaluation。
  2. 令 s 为 Completion(ModuleItem 的 Evaluation)。
  3. 返回 ? UpdateEmpty(s, sl)。
注

ModuleItemList 的值是 ModuleItemList 中最后一个产生值的项的值。

ModuleItem : ImportDeclaration
  1. 返回 empty。

16.2.2 导入

语法

ImportDeclaration : import ImportClause FromClause WithClauseopt ; import ModuleSpecifier WithClauseopt ; ImportClause : ImportedDefaultBinding NameSpaceImport NamedImports ImportedDefaultBinding , NameSpaceImport ImportedDefaultBinding , NamedImports ImportedDefaultBinding : ImportedBinding NameSpaceImport : * as ImportedBinding NamedImports : { } { ImportsList ,opt } FromClause : from ModuleSpecifier ImportsList : ImportSpecifier ImportsList , ImportSpecifier ImportSpecifier : ImportedBinding ModuleExportName as ImportedBinding ModuleSpecifier : StringLiteral ImportedBinding : BindingIdentifier[~Yield, +Await] WithClause : with { } with { WithEntries ,opt } WithEntries : AttributeKey : StringLiteral AttributeKey : StringLiteral , WithEntries AttributeKey : IdentifierName StringLiteral

16.2.2.1 Static Semantics: 提前错误

ModuleItem : ImportDeclaration WithClause : with { WithEntries ,opt }

16.2.2.2 Static Semantics: ImportEntries

语法制导操作 ImportEntries,接收无参数;返回值:列表 (元素:ImportEntry 记录)。 它按以下产生式分别定义:

Module : [empty]
  1. 返回新的空 List。
ModuleItemList : ModuleItemList ModuleItem
  1. 令 entries1 为 ModuleItemList 的 ImportEntries。
  2. 令 entries2 为 ModuleItem 的 ImportEntries。
  3. 返回 entries1 和 entries2 的列表连接。
ModuleItem : ExportDeclaration StatementListItem
  1. 返回新的空 List。
ImportDeclaration : import ImportClause FromClause WithClauseopt ;
  1. 令 module 为 ImportDeclaration 的 ModuleRequests 的唯一元素。
  2. 返回以 module 为参数对 ImportClause 执行 ImportEntriesForModule 的结果。
ImportDeclaration : import ModuleSpecifier WithClauseopt ;
  1. 返回新的空 List。

16.2.2.3 Static Semantics: ImportEntriesForModule

语法制导操作 ImportEntriesForModule,接收参数 module (ModuleRequest 记录);返回值:列表 (元素:ImportEntry 记录)。 它按以下产生式分别定义:

ImportClause : ImportedDefaultBinding , NameSpaceImport
  1. 令 entries1 为以 module 为参数对 ImportedDefaultBinding 执行 ImportEntriesForModule 的结果。
  2. 令 entries2 为以 module 为参数对 NameSpaceImport 执行 ImportEntriesForModule 的结果。
  3. 返回 entries1 和 entries2 的列表连接。
ImportClause : ImportedDefaultBinding , NamedImports
  1. 令 entries1 为以 module 为参数对 ImportedDefaultBinding 执行 ImportEntriesForModule 的结果。
  2. 令 entries2 为以 module 为参数对 NamedImports 执行 ImportEntriesForModule 的结果。
  3. 返回 entries1 和 entries2 的列表连接。
ImportedDefaultBinding : ImportedBinding
  1. 令 localName 为 ImportedBinding 的 BoundNames 的唯一元素。
  2. 令 defaultEntry 为 ImportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: "default", [[LocalName]]: localName }。
  3. 返回 « defaultEntry »。
NameSpaceImport : * as ImportedBinding
  1. 令 localName 为 ImportedBinding 的 StringValue。
  2. 令 entry 为 ImportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: namespace, [[LocalName]]: localName }。
  3. 返回 « entry »。
NamedImports : { }
  1. 返回新的空 List。
ImportsList : ImportsList , ImportSpecifier
  1. 令 specs1 为以 module 为参数对 ImportsList 执行 ImportEntriesForModule 的结果。
  2. 令 specs2 为以 module 为参数对 ImportSpecifier 执行 ImportEntriesForModule 的结果。
  3. 返回 specs1 和 specs2 的列表连接。
ImportSpecifier : ImportedBinding
  1. 令 localName 为 ImportedBinding 的 BoundNames 的唯一元素。
  2. 令 entry 为 ImportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: localName, [[LocalName]]: localName }。
  3. 返回 « entry »。
ImportSpecifier : ModuleExportName as ImportedBinding
  1. 令 importName 为 ModuleExportName 的 StringValue。
  2. 令 localName 为 ImportedBinding 的 StringValue。
  3. 令 entry 为 ImportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: importName, [[LocalName]]: localName }。
  4. 返回 « entry »。

16.2.2.4 Static Semantics: WithClauseToAttributes

语法制导操作 WithClauseToAttributes,接收无参数;返回值:列表 (元素:ImportAttribute 记录)。 它按以下产生式分别定义:

WithClause : with { }
  1. 返回新的空 List。
WithClause : with { WithEntries ,opt }
  1. 令 attrs 为 WithEntries 的 WithClauseToAttributes。
  2. 按 [[Key]] 字段的字典序对 attrs 排序,将每个此类字段的值视为 UTF-16 码元值序列。注:这种排序唯一可观察的方面,是禁止宿主根据属性枚举顺序改变行为。
  3. 返回 attrs。
WithEntries : AttributeKey : StringLiteral
  1. 令 key 为 AttributeKey 的 PropName。
  2. 令 entry 为 ImportAttribute Record { [[Key]]: key, [[Value]]: StringLiteral 的 SV }。
  3. 返回 « entry »。
WithEntries : AttributeKey : StringLiteral , WithEntries
  1. 令 key 为 AttributeKey 的 PropName。
  2. 令 entry 为 ImportAttribute Record { [[Key]]: key, [[Value]]: StringLiteral 的 SV }。
  3. 令 rest 为 WithEntries 的 WithClauseToAttributes。
  4. 返回 « entry » 和 rest 的列表连接。

16.2.3 导出

语法

ExportDeclaration : export ExportFromClause FromClause WithClauseopt ; export NamedExports ; export VariableStatement[~Yield, +Await] export [lookahead ∉ { using, await }] Declaration[~Yield, +Await] export default HoistableDeclaration[~Yield, +Await, +Default] export default ClassDeclaration[~Yield, +Await, +Default] export default [lookahead ∉ { function, async [no LineTerminator here] function, class }] AssignmentExpression[+In, ~Yield, +Await] ; ExportFromClause : * * as ModuleExportName NamedExports NamedExports : { } { ExportsList ,opt } ExportsList : ExportSpecifier ExportsList , ExportSpecifier ExportSpecifier : ModuleExportName ModuleExportName as ModuleExportName

16.2.3.1 Static Semantics: 提前错误

ExportDeclaration : export NamedExports ; 注

上述规则意味着,NamedExports 的每个 ReferencedBindings 都被视为 IdentifierReference。

16.2.3.2 Static Semantics: ExportedBindings

语法制导操作 ExportedBindings,接收无参数;返回值:列表 (元素:String)。

注

ExportedBindings 是与 Module 的 ExportedNames 显式关联的局部绑定名称。

它按以下产生式分别定义:

ModuleItemList : ModuleItemList ModuleItem
  1. 令 names1 为 ModuleItemList 的 ExportedBindings。
  2. 令 names2 为 ModuleItem 的 ExportedBindings。
  3. 返回 names1 和 names2 的列表连接。
ModuleItem : ImportDeclaration StatementListItem
  1. 返回新的空 List。
ExportDeclaration : export ExportFromClause FromClause WithClauseopt ;
  1. 返回新的空 List。
ExportDeclaration : export NamedExports ;
  1. 返回 NamedExports 的 ExportedBindings。
ExportDeclaration : export VariableStatement
  1. 返回 VariableStatement 的 BoundNames。
ExportDeclaration : export Declaration
  1. 返回 Declaration 的 BoundNames。
ExportDeclaration : export default HoistableDeclaration export default ClassDeclaration export default AssignmentExpression ;
  1. 返回此 ExportDeclaration 的 BoundNames。
NamedExports : { }
  1. 返回新的空 List。
ExportsList : ExportsList , ExportSpecifier
  1. 令 names1 为 ExportsList 的 ExportedBindings。
  2. 令 names2 为 ExportSpecifier 的 ExportedBindings。
  3. 返回 names1 和 names2 的列表连接。
ExportSpecifier : ModuleExportName
  1. 返回一个 List,其唯一元素是 ModuleExportName 的 StringValue。
ExportSpecifier : ModuleExportName as ModuleExportName
  1. 返回一个 List,其唯一元素是第一个 ModuleExportName 的 StringValue。

16.2.3.3 Static Semantics: ExportedNames

语法制导操作 ExportedNames,接收无参数;返回值:列表 (元素:String)。

注

ExportedNames 是 Module 显式映射到其某个局部名称绑定的外部可见名称。

它按以下产生式分别定义:

ModuleItemList : ModuleItemList ModuleItem
  1. 令 names1 为 ModuleItemList 的 ExportedNames。
  2. 令 names2 为 ModuleItem 的 ExportedNames。
  3. 返回 names1 和 names2 的列表连接。
ModuleItem : ExportDeclaration
  1. 返回 ExportDeclaration 的 ExportedNames。
ModuleItem : ImportDeclaration StatementListItem
  1. 返回新的空 List。
ExportDeclaration : export ExportFromClause FromClause WithClauseopt ;
  1. 返回 ExportFromClause 的 ExportedNames。
ExportFromClause : *
  1. 返回新的空 List。
ExportFromClause : * as ModuleExportName
  1. 返回一个 List,其唯一元素是 ModuleExportName 的 StringValue。
ExportFromClause : NamedExports
  1. 返回 NamedExports 的 ExportedNames。
ExportDeclaration : export VariableStatement
  1. 返回 VariableStatement 的 BoundNames。
ExportDeclaration : export Declaration
  1. 返回 Declaration 的 BoundNames。
ExportDeclaration : export default HoistableDeclaration export default ClassDeclaration export default AssignmentExpression ;
  1. 返回 « "default" »。
NamedExports : { }
  1. 返回新的空 List。
ExportsList : ExportsList , ExportSpecifier
  1. 令 names1 为 ExportsList 的 ExportedNames。
  2. 令 names2 为 ExportSpecifier 的 ExportedNames。
  3. 返回 names1 和 names2 的列表连接。
ExportSpecifier : ModuleExportName
  1. 返回一个 List,其唯一元素是 ModuleExportName 的 StringValue。
ExportSpecifier : ModuleExportName as ModuleExportName
  1. 返回一个 List,其唯一元素是第二个 ModuleExportName 的 StringValue。

16.2.3.4 Static Semantics: ExportEntries

语法制导操作 ExportEntries,接收无参数;返回值:列表 (元素:ExportEntry 记录)。 它按以下产生式分别定义:

Module : [empty]
  1. 返回新的空 List。
ModuleItemList : ModuleItemList ModuleItem
  1. 令 entries1 为 ModuleItemList 的 ExportEntries。
  2. 令 entries2 为 ModuleItem 的 ExportEntries。
  3. 返回 entries1 和 entries2 的列表连接。
ModuleItem : ImportDeclaration StatementListItem
  1. 返回新的空 List。
ExportDeclaration : export ExportFromClause FromClause WithClauseopt ;
  1. 令 module 为 ExportDeclaration 的 ModuleRequests 的唯一元素。
  2. 返回以 module 为参数对 ExportFromClause 执行 ExportEntriesForModule 的结果。
ExportDeclaration : export NamedExports ;
  1. 返回以 null 为参数对 NamedExports 执行 ExportEntriesForModule 的结果。
ExportDeclaration : export VariableStatement
  1. 令 entries 为新的空 List。
  2. 令 names 为 VariableStatement 的 BoundNames。
  3. 对 names 的每个元素 name,执行
    1. 将 ExportEntry Record { [[ModuleRequest]]: null, [[ImportName]]: null, [[LocalName]]: name, [[ExportName]]: name } 追加到 entries。
  4. 返回 entries。
ExportDeclaration : export Declaration
  1. 令 entries 为新的空 List。
  2. 令 names 为 Declaration 的 BoundNames。
  3. 对 names 的每个元素 name,执行
    1. 将 ExportEntry Record { [[ModuleRequest]]: null, [[ImportName]]: null, [[LocalName]]: name, [[ExportName]]: name } 追加到 entries。
  4. 返回 entries。
ExportDeclaration : export default HoistableDeclaration
  1. 令 names 为 HoistableDeclaration 的 BoundNames。
  2. 令 localName 为 names 的唯一元素。
  3. 返回一个 List,其唯一元素是新的 ExportEntry Record { [[ModuleRequest]]: null, [[ImportName]]: null, [[LocalName]]: localName, [[ExportName]]: "default" }。
ExportDeclaration : export default ClassDeclaration
  1. 令 names 为 ClassDeclaration 的 BoundNames。
  2. 令 localName 为 names 的唯一元素。
  3. 返回一个 List,其唯一元素是新的 ExportEntry Record { [[ModuleRequest]]: null, [[ImportName]]: null, [[LocalName]]: localName, [[ExportName]]: "default" }。
ExportDeclaration : export default AssignmentExpression ;
  1. 令 entry 为 ExportEntry Record { [[ModuleRequest]]: null, [[ImportName]]: null, [[LocalName]]: "*default*", [[ExportName]]: "default" }。
  2. 返回 « entry »。
注

本规范使用 "*default*" 作为匿名默认导出值的合成名称。有关更多详细信息,请参见此注释。

16.2.3.5 Static Semantics: ExportEntriesForModule

语法制导操作 ExportEntriesForModule,接收参数 module ((ModuleRequest 记录 或 null));返回值:列表 (元素:ExportEntry 记录)。 它按以下产生式分别定义:

ExportFromClause : *
  1. 令 entry 为 ExportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: all-but-default, [[LocalName]]: null, [[ExportName]]: null }。
  2. 返回 « entry »。
ExportFromClause : * as ModuleExportName
  1. 令 exportName 为 ModuleExportName 的 StringValue。
  2. 令 entry 为 ExportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: namespace, [[LocalName]]: null, [[ExportName]]: exportName }。
  3. 返回 « entry »。
NamedExports : { }
  1. 返回新的空 List。
ExportsList : ExportsList , ExportSpecifier
  1. 令 specs1 为以 module 为参数对 ExportsList 执行 ExportEntriesForModule 的结果。
  2. 令 specs2 为以 module 为参数对 ExportSpecifier 执行 ExportEntriesForModule 的结果。
  3. 返回 specs1 和 specs2 的列表连接。
ExportSpecifier : ModuleExportName
  1. 令 sourceName 为 ModuleExportName 的 StringValue。
  2. 如果 module 是 null,则
    1. 令 localName 为 sourceName。
    2. 令 importName 为 null。
  3. 否则,
    1. 令 localName 为 null。
    2. 令 importName 为 sourceName。
  4. 返回一个 List,其唯一元素是新的 ExportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: importName, [[LocalName]]: localName, [[ExportName]]: sourceName }。
ExportSpecifier : ModuleExportName as ModuleExportName
  1. 令 sourceName 为第一个 ModuleExportName 的 StringValue。
  2. 令 exportName 为第二个 ModuleExportName 的 StringValue。
  3. 如果 module 是 null,则
    1. 令 localName 为 sourceName。
    2. 令 importName 为 null。
  4. 否则,
    1. 令 localName 为 null。
    2. 令 importName 为 sourceName。
  5. 返回一个 List,其唯一元素是新的 ExportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: importName, [[LocalName]]: localName, [[ExportName]]: exportName }。

16.2.3.6 Static Semantics: ReferencedBindings

语法制导操作 ReferencedBindings,接收无参数;返回值:列表 (元素:解析节点)。 它按以下产生式分别定义:

NamedExports : { }
  1. 返回新的空 List。
ExportsList : ExportsList , ExportSpecifier
  1. 令 names1 为 ExportsList 的 ReferencedBindings。
  2. 令 names2 为 ExportSpecifier 的 ReferencedBindings。
  3. 返回 names1 和 names2 的列表连接。
ExportSpecifier : ModuleExportName as ModuleExportName
  1. 返回第一个 ModuleExportName 的 ReferencedBindings。
ModuleExportName : IdentifierName
  1. 返回一个 List,其唯一元素是 IdentifierName。
ModuleExportName : StringLiteral
  1. 返回一个 List,其唯一元素是 StringLiteral。

16.2.3.7 Runtime Semantics: Evaluation

ExportDeclaration : export ExportFromClause FromClause WithClauseopt ; export NamedExports ;
  1. 返回 empty。
ExportDeclaration : export VariableStatement
  1. 返回 ? VariableStatement 的 Evaluation。
ExportDeclaration : export Declaration
  1. 返回 ? Declaration 的 Evaluation。
ExportDeclaration : export default HoistableDeclaration
  1. 返回 ? HoistableDeclaration 的 Evaluation。
ExportDeclaration : export default ClassDeclaration
  1. 令 value 为 ? ClassDeclaration 的 BindingClassDeclarationEvaluation。
  2. 令 className 为 ClassDeclaration 的 BoundNames 的唯一元素。
  3. 如果 className 是 "*default*",则
    1. 令 envRecord 为正在运行的执行上下文的 LexicalEnvironment。
    2. 执行 ? InitializeBoundName("*default*", value, envRecord)。
  4. 返回 empty。
ExportDeclaration : export default AssignmentExpression ;
  1. 如果 IsAnonymousFunctionDefinition(AssignmentExpression) 是 true,则
    1. 令 value 为 ? 以 "default" 为参数对 AssignmentExpression 执行 NamedEvaluation 的结果。
  2. 否则,
    1. 令 rhs 为 ? AssignmentExpression 的 Evaluation。
    2. 令 value 为 ? GetValue(rhs)。
  3. 令 envRecord 为正在运行的执行上下文的 LexicalEnvironment。
  4. 执行 ? InitializeBoundName("*default*", value, envRecord)。
  5. 返回 empty。

17 错误处理和语言扩展

实现必须在相关 ECMAScript 语言构造被求值时报告大多数错误。提前错误是可以在对包含该错误的 Script 中的任何构造求值之前检测并报告的错误。提前错误的存在会阻止对该构造求值。实现必须在 ParseScript 中解析 Script 时报告其中的提前错误。Module 中的提前错误会在该 Module 本应求值时报告,并且该 Module 永远不会被初始化。eval 代码中的提前错误会在调用 eval 时报告,并阻止对 eval 代码求值。所有非提前错误都是运行时错误。

对于本规范“Static Semantics: Early Errors”子条款中列出的任何条件,实现都必须将其出现报告为提前错误。

即使编译器能够证明某个构造在任何情况下执行都必然出错,实现也不得将其他种类的错误视为提前错误。在这种情况下,实现可以提前发出警告,但在相关构造实际执行之前不应报告该错误。

除以下情况外,实现应按规定报告所有错误:

17.1 禁止的扩展

实现不得以下列方式扩展本规范:

18 ECMAScript 标准内置对象

每当 ECMAScript Script 或 Module 开始执行时,都有某些内置对象可用。其中一个是全局对象,它是正在执行程序的全局环境的一部分。其他对象可作为全局对象的初始属性直接访问,或者作为可访问内置对象的属性间接访问。

除非另有规定,可作为函数调用的内置对象都是具有 10.3 中所述特征的内置函数对象。除非另有规定,内置对象的 [[Extensible]] 内部槽初始值为 true。每个内置函数对象都具有 [[Realm]] 内部槽,其值是最初创建该对象的 realm 的 Realm Record。

许多内置对象都是函数:可以使用参数调用它们。其中一些还是构造函数:它们是旨在与 new 运算符一起使用的函数。对于每个内置函数,本规范描述该函数所需的参数以及该函数对象的属性。对于每个内置构造函数,本规范还描述该构造函数的原型对象的属性,以及调用该构造函数的 new 表达式所返回的特定对象实例的属性。

除非特定函数的描述中另有规定,如果为内置函数或构造函数提供的参数少于规定所需数量,则该函数或构造函数的行为应与为其提供了足够的额外参数完全相同,并且每个此类参数的值都是 undefined。这些缺失的参数被视为“不存在”,规范算法可以按这种方式识别它们。在特定函数的描述中,术语“this value”和“NewTarget”具有 10.3 中给出的含义。

除非特定函数的描述中另有规定,如果向所描述的内置函数或构造函数提供的参数多于规定允许的数量,则调用会对额外参数求值,然后函数会忽略它们。不过,实现可以定义与这些参数相关的实现特定行为,只要该行为不是仅仅因为存在额外参数而抛出 TypeError 异常。

注 1

鼓励向内置函数集合添加额外能力的实现通过添加新函数来实现,而不是向现有函数添加新参数。

除非另有规定,每个内置函数和每个内置构造函数的 [[Prototype]] 内部槽值都是 Function 原型对象,即表达式 Function.prototype 的初始值(20.2.3)。

除非另有规定,每个内置原型对象的 [[Prototype]] 内部槽值都是 Object 原型对象,即表达式 Object.prototype 的初始值(20.1.3),Object 原型对象自身除外。

如果本规范通过算法步骤定义某个内置构造函数的行为,那么出于 [[Call]] 和 [[Construct]] 两种用途,该算法即为其行为。如果此类算法需要区分这两种情况,它会检查 NewTarget 是否为 undefined,这表示一次 [[Call]] 调用。

除非特定函数的描述中另有规定,未被标识为构造函数的内置函数对象不实现 [[Construct]] 内部方法。

除非特定函数的描述中另有规定,不是构造函数的内置函数对象不具有 "prototype" 属性。

本规范中定义的每个内置函数都是通过调用 CreateBuiltinFunction 抽象操作(10.3.4)创建的。length 和 name 参数的值是下文讨论的 "length" 和 "name" 属性的初始值。prefix 参数的值也在下文讨论。

每个内置函数对象(包括构造函数)都具有 "length" 属性,其值是非负整数 Number。除非另有规定,该值是函数描述子条款标题中显示的必需参数数量。可选参数和剩余参数不计入参数数量。

注 2

例如,Array 原型对象的 "map" 属性的初始值所对应的函数对象,在子条款标题 «Array.prototype.map (callback [ , thisArg])» 下描述,其中显示了两个具名参数 callback 和 thisArg,后者是可选参数;因此该函数对象的 "length" 属性值为 1𝔽。

除非另有规定,内置函数对象的 "length" 属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

每个内置函数对象(包括构造函数)都具有 "name" 属性,其值是 String。除非另有规定,该值是本规范中赋予函数的名称。被标识为匿名函数的函数使用空 String 作为 "name" 属性的值。对于规定为对象属性的函数,名称值是用于访问该函数的属性名称字符串。规定为内置属性的 get 或 set 访问器函数的函数,在调用 CreateBuiltinFunction 时会将 "get" 或 "set"(分别)传给 prefix 参数。

对于属性键是 Symbol 值的每个内置函数,其 "name" 属性的值都会显式规定。如果此类显式规定的值以 "get " 或 "set " 前缀开头,并且所规定的函数是内置属性的 get 或 set 访问器函数,则去掉前缀后的值会传给 name 参数,而值 "get" 或 "set"(分别)会在调用 CreateBuiltinFunction 时传给 prefix 参数。

除非另有规定,内置函数对象的 "name" 属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

除非另有规定,条款 19 到 28 以及附录 B.2 中描述的所有其他数据属性都具有特性 { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }。

除非另有规定,条款 19 到 28 以及附录 B.2 中描述的每个访问器属性都具有特性 { [[Enumerable]]: false, [[Configurable]]: true }。如果只描述了 get 访问器函数,则 set 访问器函数为默认值 undefined。如果只描述了 set 访问器,则 get 访问器为默认值 undefined。

19 全局对象

全局对象:

19.1 全局对象的值属性

19.1.1 globalThis

在 Realm Record realm 中,全局对象的 "globalThis" 属性的初始值是 realm.[[GlobalEnv]].[[GlobalThisValue]]。

此属性具有特性 { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }。

19.1.2 Infinity

全局对象的 "Infinity" 属性的初始值是 +∞𝔽(参见 6.1.6.1)。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

19.1.3 NaN

全局对象的 "NaN" 属性的初始值是 NaN(参见 6.1.6.1)。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

19.1.4 undefined

全局对象的 "undefined" 属性的初始值是 undefined(参见 6.1.1)。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

19.2 全局对象的函数属性

19.2.1 eval ( source )

此函数是 %eval% 内在对象。

调用时,它执行以下步骤:

  1. 返回 ? PerformEval(source, false, false)。

19.2.1.1 PerformEval ( source, strictCaller, direct )

抽象操作 PerformEval,接收参数 source (ECMAScript 语言值)、strictCaller (Boolean) 和 direct (Boolean);返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。 调用时执行以下步骤:

  1. 断言:如果 direct 是 false,则 strictCaller 也是 false。
  2. 如果 source 不是 String,则返回 source。
  3. 令 evalRealm 为当前 Realm Record。
  4. 注:对于直接 eval,evalRealm 同时是 eval 调用方和 eval 函数自身所在的 realm。
  5. 执行 ? HostEnsureCanCompileStrings(evalRealm, « », source, direct)。
  6. 令 inFunc 为 false。
  7. 令 inMethod 为 false。
  8. 令 inDerivedCtor 为 false。
  9. 令 inClassFieldInitializer 为 false。
  10. 如果 direct 是 true,则
    1. 令 thisEnvRecord 为 GetThisEnvironment()。
    2. 如果 thisEnvRecord 是 Function Environment Record,则
      1. 令 func 为 thisEnvRecord.[[FunctionObject]]。
      2. 将 inFunc 设置为 true。
      3. 将 inMethod 设置为 thisEnvRecord.HasSuperBinding()。
      4. 如果 func.[[ConstructorKind]] 是 derived,则将 inDerivedCtor 设置为 true。
      5. 令 classFieldInitializerName 为 func.[[ClassFieldInitializerName]]。
      6. 如果 classFieldInitializerName 不是 empty,则将 inClassFieldInitializer 设置为 true。
  11. 按实现定义的顺序执行以下子步骤,可以交错进行解析和错误检测:
    1. 令 script 为 ParseText(source, Script)。
    2. 如果 script 是错误的 List,则抛出 SyntaxError 异常。
    3. 如果 script Contains ScriptBody 是 false,则返回 undefined。
    4. 令 body 为 script 的 ScriptBody。
    5. 如果 inFunc 是 false 且 body Contains NewTarget,则抛出 SyntaxError 异常。
    6. 如果 inMethod 是 false 且 body Contains SuperProperty,则抛出 SyntaxError 异常。
    7. 如果 inDerivedCtor 是 false 且 body Contains SuperCall,则抛出 SyntaxError 异常。
    8. 如果 inClassFieldInitializer 是 true 且 body 的 ContainsArguments 是 true,则抛出 SyntaxError 异常。
  12. 如果 strictCaller 是 true,则令 strictEval 为 true。
  13. 否则,令 strictEval 为 script 的 ScriptIsStrict。
  14. 令 runningContext 为正在运行的执行上下文。
  15. 注:如果 direct 是 true,runningContext 将是执行直接 eval 的执行上下文。如果 direct 是 false,runningContext 将是调用 eval 函数的执行上下文。
  16. 如果 direct 是 true,则
    1. 令 lexicalEnv 为 NewDeclarativeEnvironment(runningContext 的 LexicalEnvironment)。
    2. 令 variableEnv 为 runningContext 的 VariableEnvironment。
    3. 令 privateEnv 为 runningContext 的 PrivateEnvironment。
  17. 否则,
    1. 令 lexicalEnv 为 NewDeclarativeEnvironment(evalRealm.[[GlobalEnv]])。
    2. 令 variableEnv 为 evalRealm.[[GlobalEnv]]。
    3. 令 privateEnv 为 null。
  18. 如果 strictEval 是 true,则将 variableEnv 设置为 lexicalEnv。
  19. 如果 runningContext 尚未挂起,则挂起 runningContext。
  20. 令 evalContext 为新的 ECMAScript 代码执行上下文。
  21. 将 evalContext 的 Function 设置为 null。
  22. 将 evalContext 的 Realm 设置为 evalRealm。
  23. 将 evalContext 的 ScriptOrModule 设置为 runningContext 的 ScriptOrModule。
  24. 将 evalContext 的 VariableEnvironment 设置为 variableEnv。
  25. 将 evalContext 的 LexicalEnvironment 设置为 lexicalEnv。
  26. 将 evalContext 的 PrivateEnvironment 设置为 privateEnv。
  27. 将 evalContext 压入执行上下文栈;evalContext 现在成为正在运行的执行上下文。
  28. 令 result 为 Completion(EvalDeclarationInstantiation(body, variableEnv, lexicalEnv, privateEnv, strictEval))。
  29. 如果 result 是正常完成,则
    1. 将 result 设置为 Completion(body 的 Evaluation)。
  30. 如果 result 是正常完成且 result.[[Value]] 是 empty,则
    1. 将 result 设置为 NormalCompletion(undefined)。
  31. 挂起 evalContext 并将其从执行上下文栈中移除。
  32. 恢复当前位于执行上下文栈顶部的上下文,并将其作为正在运行的执行上下文。
  33. 返回 ? result。
注

如果调用 eval 的调用上下文代码或 eval 代码中任一者是严格模式代码,则 eval 代码不能在调用上下文的变量环境中实例化变量或函数绑定。相反,这些绑定会实例化在仅 eval 代码可访问的新 VariableEnvironment 中。由 let、const 或 class 声明引入的绑定始终会实例化在新的 LexicalEnvironment 中。

19.2.1.2 HostEnsureCanCompileStrings ( calleeRealm, paramStrings, bodyString, direct )

宿主定义的抽象操作 HostEnsureCanCompileStrings,接收参数 calleeRealm (Realm 记录)、paramStrings (列表 (元素:String))、bodyString (String) 和 direct (Boolean);返回值:(正常完成 (值:unused) 或 抛出完成)。 它允许宿主环境阻止某些允许开发者将字符串解释并求值为 ECMAScript 代码的 ECMAScript 函数。

paramStrings 表示在使用某个函数构造函数时,将连接起来构建参数列表的字符串。bodyString 表示函数体或传递给 eval 调用的字符串。 direct 表示该求值是否为直接 eval。

HostEnsureCanCompileStrings 的默认实现是返回 NormalCompletion(unused)。

19.2.1.3 EvalDeclarationInstantiation ( body, variableEnv, lexicalEnv, privateEnv, strict )

抽象操作 EvalDeclarationInstantiation,接收参数 body (a ScriptBody Parse Node)、variableEnv (Environment 记录)、lexicalEnv (Declarative Environment 记录)、privateEnv ((PrivateEnvironment 记录 或 null)) 和 strict (Boolean);返回值:(正常完成 (值:unused) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 variableNames 为 body 的 VarDeclaredNames。
  2. 令 variableDecls 为 body 的 VarScopedDeclarations。
  3. 如果 strict 是 false,则
    1. 如果 variableEnv 是 Global Environment Record,则
      1. 对 variableNames 的每个元素 name,执行
        1. 如果 HasLexicalDeclaration(variableEnv, name) 是 true,则抛出 SyntaxError 异常。
        2. 注:eval 不会创建会被全局词法声明遮蔽的全局 var 声明。
    2. 令 thisEnv 为 lexicalEnv。
    3. 断言:以下循环将终止。
    4. 当 thisEnv 和 variableEnv 不是同一个 Environment Record 时,重复执行,
      1. 如果 thisEnv 不是 Object Environment Record,则
        1. 注:with 语句的环境不能包含任何词法声明,因此无需检查其 var/let 提升冲突。
        2. 对 variableNames 的每个元素 name,执行
          1. 如果 ! thisEnv.HasBinding(name) 是 true,则
            1. Normative Optional
              如果宿主是 Web 浏览器或以其他方式支持 Catch 块中的 VariableStatement,则
              1. 如果 thisEnv 不是 Catch 子句的 Environment Record,则抛出 SyntaxError 异常。
            2. 否则,
              1. 抛出 SyntaxError 异常。
          2. 注:直接 eval 不会将 var 声明提升到同名词法声明之上。
      2. 将 thisEnv 设置为 thisEnv.[[OuterEnv]]。
  4. 令 privateIdentifiers 为新的空 List。
  5. 令 pointer 为 privateEnv。
  6. 当 pointer 不是 null 时,重复执行,
    1. 对 pointer.[[Names]] 的每个 Private Name binding,执行
      1. 如果 privateIdentifiers 不包含 binding.[[Description]],则将 binding.[[Description]] 追加到 privateIdentifiers。
    2. 将 pointer 设置为 pointer.[[OuterPrivateEnvironment]]。
  7. 如果以 privateIdentifiers 为参数对 body 执行 AllPrivateIdentifiersValid 的结果是 false,则抛出 SyntaxError 异常。
  8. 令 funcsToInitialize 为新的空 List。
  9. 令 declaredFuncNames 为新的空 List。
  10. 按 List 的逆序,对 variableDecls 的每个元素 variableDecl,执行
    1. 如果 variableDecl 不是 VariableDeclaration、ForBinding 或 BindingIdentifier 中的任何一个,则
      1. 断言:variableDecl 是 FunctionDeclaration、GeneratorDeclaration、AsyncFunctionDeclaration 或 AsyncGeneratorDeclaration 之一。
      2. 注:如果同一个名称存在多个函数声明,则使用最后一个声明。
      3. 令 funcName 为 variableDecl 的 BoundNames 的唯一元素。
      4. 如果 declaredFuncNames 不包含 funcName,则
        1. 如果 variableEnv 是 Global Environment Record,则
          1. 令 funcDefinable 为 ? CanDeclareGlobalFunction(variableEnv, funcName)。
          2. 如果 funcDefinable 是 false,则抛出 TypeError 异常。
        2. 将 funcName 追加到 declaredFuncNames。
        3. 将 variableDecl 插入为 funcsToInitialize 的第一个元素。
  11. 令 declaredVariableNames 为新的空 List。
  12. 对 variableDecls 的每个元素 variableDecl,执行
    1. 如果 variableDecl 是 VariableDeclaration、ForBinding 或 BindingIdentifier 之一,则
      1. 对 variableDecl 的 BoundNames 的每个 String name,执行
        1. 如果 declaredFuncNames 不包含 name,则
          1. 如果 variableEnv 是 Global Environment Record,则
            1. 令 variableDefinable 为 ? CanDeclareGlobalVar(variableEnv, name)。
            2. 如果 variableDefinable 是 false,则抛出 TypeError 异常。
          2. 如果 declaredVariableNames 不包含 name,则
            1. 将 name 追加到 declaredVariableNames。
  13. Normative Optional
    如果 strict 是 false,并且宿主是 Web 浏览器或以其他方式支持 块级函数声明的 Web 遗留兼容性语义,则
    1. 令 declaredFuncOrVariableNames 为 declaredFuncNames 和 declaredVariableNames 的列表连接。
    2. 对直接包含在任意 Block、CaseClause 或 DefaultClause x 的 StatementList 中、且 body Contains x 是 true 的每个 FunctionDeclaration funcDecl,执行
      1. 令 funcName 为 funcDecl 的 BindingIdentifier 的 StringValue。
      2. 如果将 FunctionDeclaration funcDecl 替换为以 funcName 作为 BindingIdentifier 的 VariableStatement 不会为 body 产生任何提前错误,则
        1. 令 bindingExists 为 false。
        2. 将 thisEnv 设置为 lexicalEnv。
        3. 断言:以下循环将终止。
        4. 当 thisEnv 不是 variableEnv 时,重复执行,
          1. 如果 thisEnv 不是 Object Environment Record,则
            1. 如果 ! thisEnv.HasBinding(funcName) 是 true,则
              1. Normative Optional
                如果宿主是 Web 浏览器或以其他方式支持 Catch 块中的 VariableStatement,则
                1. 如果 thisEnv 不是 Catch 子句的 Environment Record,则将 bindingExists 设置为 true。
              2. 否则,
                1. 将 bindingExists 设置为 true。
          2. 将 thisEnv 设置为 thisEnv.[[OuterEnv]]。
        5. 如果 bindingExists 是 false 且 variableEnv 是 Global Environment Record,则
          1. 如果 HasLexicalDeclaration(variableEnv, funcName) 是 false,则
            1. 令 funcDefinable 为 ? CanDeclareGlobalVar(variableEnv, funcName)。
          2. 否则,
            1. 令 funcDefinable 为 false。
        6. 否则,
          1. 令 funcDefinable 为 true。
        7. 如果 bindingExists 是 false 且 funcDefinable 是 true,则
          1. 如果 declaredFuncOrVariableNames 不包含 funcName,则
            1. 如果 variableEnv 是 Global Environment Record,则
              1. 执行 ? CreateGlobalVarBinding(variableEnv, funcName, true)。
            2. 否则,
              1. 将 bindingExists 设置为 ! variableEnv.HasBinding(funcName)。
              2. 如果 bindingExists 是 false,则
                1. 执行 ! variableEnv.CreateMutableBinding(funcName, true)。
                2. 执行 ! variableEnv.InitializeBinding(funcName, undefined)。
            3. 将 funcName 追加到 declaredFuncOrVariableNames。
          2. 当对 FunctionDeclaration funcDecl 求值时,执行以下步骤,以替代 15.2.6 中提供的 FunctionDeclaration Evaluation 算法:
            1. 令 globalEnv 为正在运行的执行上下文的 VariableEnvironment。
            2. 令 blockEnv 为正在运行的执行上下文的 LexicalEnvironment。
            3. 令 funcObj 为 ! blockEnv.GetBindingValue(funcName, false)。
            4. 执行 ? globalEnv.SetMutableBinding(funcName, funcObj, false)。
            5. 返回 unused。
  14. 注:除非 variableEnv 是 Global Environment Record 且全局对象是 Proxy 异质对象,否则在此算法步骤之后不会发生异常终止。
  15. 令 lexicalDecls 为 body 的 LexicallyScopedDeclarations。
  16. 对 lexicalDecls 的每个元素 lexicalDecl,执行
    1. 注:词法声明的名称仅在此处实例化,而不会初始化。
    2. 对 lexicalDecl 的 BoundNames 的每个元素 name,执行
      1. 如果 lexicalDecl 的 IsConstantDeclaration 是 true,则
        1. 执行 ? lexicalEnv.CreateImmutableBinding(name, true)。
      2. 否则,
        1. 执行 ? lexicalEnv.CreateMutableBinding(name, false)。
  17. 对 funcsToInitialize 的每个 Parse Node funcDecl,执行
    1. 令 funcName 为 funcDecl 的 BoundNames 的唯一元素。
    2. 令 funcObj 为以 lexicalEnv 和 privateEnv 为参数对 funcDecl 执行 InstantiateFunctionObject 的结果。
    3. 如果 variableEnv 是 Global Environment Record,则
      1. 执行 ? CreateGlobalFunctionBinding(variableEnv, funcName, funcObj, true)。
    4. 否则,
      1. 令 bindingExists 为 ! variableEnv.HasBinding(funcName)。
      2. 如果 bindingExists 是 false,则
        1. 注:由于步骤 14 之前的验证,以下调用不可能返回突然完成。
        2. 执行 ! variableEnv.CreateMutableBinding(funcName, true)。
        3. 执行 ! variableEnv.InitializeBinding(funcName, funcObj)。
      3. 否则,
        1. 执行 ! variableEnv.SetMutableBinding(funcName, funcObj, false)。
  18. 对 declaredVariableNames 的每个 String variableName,执行
    1. 如果 variableEnv 是 Global Environment Record,则
      1. 执行 ? CreateGlobalVarBinding(variableEnv, variableName, true)。
    2. 否则,
      1. 令 bindingExists 为 ! variableEnv.HasBinding(variableName)。
      2. 如果 bindingExists 是 false,则
        1. 注:由于步骤 14 之前的验证,以下调用不可能返回突然完成。
        2. 执行 ! variableEnv.CreateMutableBinding(variableName, true)。
        3. 执行 ! variableEnv.InitializeBinding(variableName, undefined)。
  19. 返回 unused。

19.2.2 isFinite ( value )

此函数是 %isFinite% 内在对象。

调用时,它执行以下步骤:

  1. 令 number 为 ? ToNumber(value)。
  2. 如果 number 是有限 Number,返回 true。
  3. 返回 false。

19.2.3 isNaN ( value )

此函数是 %isNaN% 内在对象。

调用时,它执行以下步骤:

  1. 令 number 为 ? ToNumber(value)。
  2. 如果 number 是 NaN,则返回 true。
  3. 返回 false。
注

ECMAScript 代码可靠测试值 X 是否为 NaN 的一种方法是使用形式为 X !== X 的表达式。当且仅当 X 是 NaN 时,结果为 true。

19.2.4 parseFloat ( string )

此函数通过将 string 参数的内容解释为十进制字面量来生成 Number 值。

它是 %parseFloat% 内在对象。

调用时,它执行以下步骤:

  1. 令 inputString 为 ? ToString(string)。
  2. 令 trimmedString 为 ! TrimString(inputString, start)。
  3. 令 trimmed 为 StringToCodePoints(trimmedString)。
  4. 令 trimmedPrefix 为 trimmed 中满足 StrDecimalLiteral 语法的最长前缀,它可能就是 trimmed 自身。如果不存在这样的前缀,则返回 NaN。
  5. 令 parsedNumber 为 ParseText(trimmedPrefix, StrDecimalLiteral)。
  6. 断言:parsedNumber 是 Parse Node。
  7. 返回 parsedNumber 的 StringNumericValue。
注

此函数可能只将 string 的开头部分解释为 Number 值;它会忽略无法解释为十进制字面量表示法一部分的任何码元,并且不会指示这些码元已被忽略。

19.2.5 parseInt ( string, radix )

此函数根据指定的 radix 解释 string 的内容并生成整数 Number。string 开头的空白会被忽略。如果 radix 强制转换为 0(例如其值为 undefined 时),则假定其为 10,但如果数字表示以 "0x" 或 "0X" 开头,则假定为 16。如果 radix 为 16,则数字表示可以选择以 "0x" 或 "0X" 开头。

它是 %parseInt% 内在对象。

调用时,它执行以下步骤:

  1. 令 inputString 为 ? ToString(string)。
  2. 令 radixMV 为 ℝ(? ToInt32(radix))。
  3. 如果 radixMV ≠ 0 且 radixMV 不在从 2 到 36 的闭区间内,则返回 NaN。
  4. 令 trimmedString 为 ! TrimString(inputString, start)。
  5. 如果 trimmedString 是空 String,则返回 NaN。
  6. 令 sign 为 1。
  7. 如果 trimmedString 的第一个码元是码元 0x002D (HYPHEN-MINUS),则
    1. 将 sign 设置为 -1。
    2. 将 trimmedString 设置为 trimmedString 从 1 开始的子字符串。
  8. 否则如果 trimmedString 的第一个码元是码元 0x002B (PLUS SIGN),则
    1. 将 trimmedString 设置为 trimmedString 从 1 开始的子字符串。
  9. 如果 radixMV = 0 或 radixMV = 16,则
    1. 如果 trimmedString 的长度 ≥ 2,并且 trimmedString 从 0 到 2 的子字符串是 "0x" 或 "0X",则
      1. 将 trimmedString 设置为 trimmedString 从 2 开始的子字符串。
      2. 将 radixMV 设置为 16。
  10. 如果 radixMV = 0,则将 radixMV 设置为 10。
  11. 如果 trimmedString 包含不是基数 radixMV 数字的码元,则令 end 为 trimmedString 中第一个此类码元的索引;否则令 end 为 trimmedString 的长度。
  12. 令 numberString 为 trimmedString 从 0 到 end 的子字符串。
  13. 如果 numberString 为空,则返回 NaN。
  14. 令 mathInt 为 numberString 以基数 radixMV 表示法所表示的整数值,其中使用字母 A 到 Z 以及 a 到 z 表示值为 10 到 35 的数字。(不过,如果 radixMV = 10 且 numberString 包含超过 20 个有效数字,则由实现选择,第 20 个之后的每个有效数字都可以替换为数字 0;如果 radixMV 不是 2、4、8、10、16 或 32 之一,则 mathInt 可以是表示 numberString 以基数 radixMV 表示法所表示整数值的实现近似整数。)
  15. 如果 sign = -1 且 mathInt = 0,则返回 -0𝔽。
  16. 返回 𝔽(sign × mathInt)。
注

此函数可能只将 string 的开头部分解释为整数值;它会忽略无法解释为整数表示法一部分的任何码元,并且不会指示这些码元已被忽略。

19.2.6 URI 处理函数

统一资源标识符(Uniform Resource Identifier,URI)是用于标识 Internet 上的资源(例如网页或文件)以及访问这些资源所使用的传输协议(例如 HTTP 或 FTP)的 String。ECMAScript 语言自身不提供使用 URI 的任何支持,除了本节所述的 URI 编码和解码函数。encodeURI 和 decodeURI 旨在处理完整 URI;它们假定所有保留字符都有特殊含义(例如作为分隔符),因此不会对这些字符编码。encodeURIComponent 和 decodeURIComponent 旨在处理 URI 的各个组成部分;它们假定所有保留字符都表示文本,并且在该组成部分成为完整 URI 的一部分时,必须对这些字符编码以避免特殊含义。

注 1

保留字符集合基于 RFC 2396,并未反映较新的 RFC 3986 引入的变更。

注 2

许多 ECMAScript 实现提供操作网页的其他函数和方法;这些函数超出本标准的范围。

19.2.6.1 decodeURI ( encodedURI )

此函数计算 URI 的新版本,其中每个可能由 encodeURI 函数引入的转义序列和 UTF-8 编码都被替换为它所表示码点的 UTF-16 编码。无法由 encodeURI 引入的转义序列不会被替换。

它是 %decodeURI% 内在对象。

调用时,它执行以下步骤:

  1. 令 uriString 为 ? ToString(encodedURI)。
  2. 令 preserveEscapeSet 为 ";/?:@&=+$,#"。
  3. 返回 ? Decode(uriString, preserveEscapeSet)。

19.2.6.2 decodeURIComponent ( encodedURIComponent )

此函数计算 URI 的新版本,其中每个可能由 encodeURIComponent 函数引入的转义序列和 UTF-8 编码都被替换为它所表示码点的 UTF-16 编码。

它是 %decodeURIComponent% 内在对象。

调用时,它执行以下步骤:

  1. 令 componentString 为 ? ToString(encodedURIComponent)。
  2. 令 preserveEscapeSet 为空 String。
  3. 返回 ? Decode(componentString, preserveEscapeSet)。

19.2.6.3 encodeURI ( uri )

此函数计算 UTF-16 编码(6.1.4)URI 的新版本,其中某些码点的每个实例都会替换为一个、两个、三个或四个表示该码点 UTF-8 编码的转义序列。

它是 %encodeURI% 内在对象。

调用时,它执行以下步骤:

  1. 令 uriString 为 ? ToString(uri)。
  2. 令 extraUnescaped 为 ";/?:@&=+$,#"。
  3. 返回 ? Encode(uriString, extraUnescaped)。

19.2.6.4 encodeURIComponent ( uriComponent )

此函数计算 UTF-16 编码(6.1.4)URI 的新版本,其中某些码点的每个实例都会替换为一个、两个、三个或四个表示该码点 UTF-8 编码的转义序列。

它是 %encodeURIComponent% 内在对象。

调用时,它执行以下步骤:

  1. 令 componentString 为 ? ToString(uriComponent)。
  2. 令 extraUnescaped 为空 String。
  3. 返回 ? Encode(componentString, extraUnescaped)。

19.2.6.5 Encode ( string, extraUnescaped )

抽象操作 Encode,接收参数 string (String) 和 extraUnescaped (String);返回值:(正常完成 (值:String) 或 抛出完成)。 它执行 URI 编码和转义,将 string 按照 6.1.4 中的说明解释为 UTF-16 编码码点序列。如果字符在 RFC 2396 中被标识为未保留字符,或出现在 extraUnescaped 中,则不会对其转义。 调用时执行以下步骤:

  1. 令 length 为 string 的长度。
  2. 令 result 为空 String。
  3. 令 alwaysUnescaped 为 ASCII 单词字符与 "-.!~*'()" 的字符串连接。
  4. 令 unescapedSet 为 alwaysUnescaped 和 extraUnescaped 的字符串连接。
  5. 令 k 为 0。
  6. 当 k < length 时,重复执行,
    1. 令 codeUnit 为 string 中索引 k 处的码元。
    2. 如果 unescapedSet 包含 codeUnit,则
      1. 将 k 设置为 k + 1。
      2. 将 result 设置为 result 和 codeUnit 的字符串连接。
    3. 否则,
      1. 令 codePoint 为 CodePointAt(string, k)。
      2. 如果 codePoint.[[IsUnpairedSurrogate]] 是 true,则抛出 URIError 异常。
      3. 将 k 设置为 k + codePoint.[[CodeUnitCount]]。
      4. 令 octets 为对 codePoint.[[CodePoint]] 应用 UTF-8 转换所得的八位字节 List。
      5. 对 octets 的每个元素 octet,执行
        1. 令 hex 为 octet 的 String 表示,并格式化为大写十六进制数。
        2. 将 result 设置为 result、"%" 和 StringPad(hex, 2, "0", start) 的字符串连接。
  7. 返回 result。
注

由于百分号编码用于表示单个八位字节,因此单个码点可能表示为多个连续的转义序列(其每个 8 位 UTF-8 码元对应一个)。

19.2.6.6 Decode ( string, preserveEscapeSet )

抽象操作 Decode,接收参数 string (String) 和 preserveEscapeSet (String);返回值:(正常完成 (值:String) 或 抛出完成)。 它执行 URI 反转义和解码,同时保留与 preserveEscapeSet 中基本拉丁字符对应的任何转义序列。 调用时执行以下步骤:

  1. 令 length 为 string 的长度。
  2. 令 result 为空 String。
  3. 令 k 为 0。
  4. 当 k < length 时,重复执行,
    1. 令 codeUnit 为 string 中索引 k 处的码元。
    2. 令 segment 为 codeUnit。
    3. 如果 codeUnit 是码元 0x0025 (PERCENT SIGN),则
      1. 如果 k + 3 > length,则抛出 URIError 异常。
      2. 令 escape 为 string 从 k 到 k + 3 的子字符串。
      3. 令 firstOctet 为 ParseHexOctet(string, k + 1)。
      4. 如果 firstOctet 不是整数,则抛出 URIError 异常。
      5. 将 k 设置为 k + 2。
      6. 令 n 为 firstOctet 中前导 1 位的数量。
      7. 如果 n = 0,则
        1. 令 asciiChar 为数值等于 firstOctet 的码元。
        2. 如果 preserveEscapeSet 包含 asciiChar,则将 segment 设置为 escape;否则将 segment 设置为 asciiChar。
      8. 否则,
        1. 如果 n = 1 或 n > 4,则抛出 URIError 异常。
        2. 令 octets 为 « firstOctet »。
        3. 令 j 为 1。
        4. 当 j < n 时,重复执行,
          1. 将 k 设置为 k + 1。
          2. 如果 k + 3 > length,则抛出 URIError 异常。
          3. 如果 string 中索引 k 处的码元不是码元 0x0025 (PERCENT SIGN),则抛出 URIError 异常。
          4. 令 continuationByte 为 ParseHexOctet(string, k + 1)。
          5. 如果 continuationByte 不是整数,则抛出 URIError 异常。
          6. 将 continuationByte 追加到 octets。
          7. 将 k 设置为 k + 2。
          8. 将 j 设置为 j + 1。
        5. 断言:octets 的长度为 n。
        6. 如果 octets 不包含 Unicode 码点的有效 UTF-8 编码,则抛出 URIError 异常。
        7. 令 codePoint 为通过对 octets 应用 UTF-8 转换得到的码点,即将八位字节 List 转换为 21 位值。
        8. 将 segment 设置为 UTF16EncodeCodePoint(codePoint)。
    4. 将 result 设置为 result 和 segment 的字符串连接。
    5. 将 k 设置为 k + 1。
  5. 返回 result。
注

RFC 3629 禁止解码无效的 UTF-8 八位字节序列。例如,无效序列 0xC0 0x80 不得解码为码元 0x0000。Decode 算法的实现遇到此类无效序列时必须抛出 URIError。

19.2.6.7 ParseHexOctet ( string, position )

抽象操作 ParseHexOctet,接收参数 string (String) 和 position (非负整数);返回值:(非负整数 或 a non-empty List of SyntaxError objects)。 它将 string 中指定 position 处的两个十六进制字符序列解析为无符号 8 位整数。 调用时执行以下步骤:

  1. 令 length 为 string 的长度。
  2. 断言:position + 2 ≤ length。
  3. 令 hexDigits 为 string 从 position 到 position + 2 的子字符串。
  4. 令 parseResult 为 ParseText(hexDigits, HexDigits[~Sep])。
  5. 如果 parseResult 不是 Parse Node,则返回 parseResult。
  6. 令 n 为 parseResult 的 MV。
  7. 断言:n 在从 0 到 255 的闭区间内。
  8. 返回 n。

19.3 全局对象的构造函数属性

19.3.1 AggregateError ( . . . )

参见 20.5.7.1。

19.3.2 Array ( . . . )

参见 23.1.1。

19.3.3 ArrayBuffer ( . . . )

参见 25.1.4。

19.3.4 AsyncDisposableStack ( . . . )

参见 27.4.1。

19.3.5 BigInt ( . . . )

参见 21.2.1。

19.3.6 BigInt64Array ( . . . )

参见 23.2.5。

19.3.7 BigUint64Array ( . . . )

参见 23.2.5。

19.3.8 Boolean ( . . . )

参见 20.3.1。

19.3.9 DataView ( . . . )

参见 25.3.2。

19.3.10 Date ( . . . )

参见 21.4.2。

19.3.11 DisposableStack ( . . . )

参见 27.3.1。

19.3.12 Error ( . . . )

参见 20.5.1。

19.3.13 EvalError ( . . . )

参见 20.5.5.1。

19.3.14 FinalizationRegistry ( . . . )

参见 26.2.1。

19.3.15 Float16Array ( . . . )

参见 23.2.5。

19.3.16 Float32Array ( . . . )

参见 23.2.5。

19.3.17 Float64Array ( . . . )

参见 23.2.5。

19.3.18 Function ( . . . )

参见 20.2.1。

19.3.19 Int8Array ( . . . )

参见 23.2.5。

19.3.20 Int16Array ( . . . )

参见 23.2.5。

19.3.21 Int32Array ( . . . )

参见 23.2.5。

19.3.22 Iterator ( . . . )

参见 27.1.3.1。

19.3.23 Map ( . . . )

参见 24.1.1。

19.3.24 Number ( . . . )

参见 21.1.1。

19.3.25 Object ( . . . )

参见 20.1.1。

19.3.26 Promise ( . . . )

参见 27.5.3。

19.3.27 Proxy ( . . . )

参见 28.2.1。

19.3.28 RangeError ( . . . )

参见 20.5.5.2。

19.3.29 ReferenceError ( . . . )

参见 20.5.5.3。

19.3.30 RegExp ( . . . )

参见 22.2.4。

19.3.31 Set ( . . . )

参见 24.2.2。

19.3.32 SharedArrayBuffer ( . . . )

参见 25.2.3。

19.3.33 String ( . . . )

参见 22.1.1。

19.3.34 SuppressedError ( . . . )

参见 20.5.8.1。

19.3.35 Symbol ( . . . )

参见 20.4.1。

19.3.36 SyntaxError ( . . . )

参见 20.5.5.4。

19.3.37 TypeError ( . . . )

参见 20.5.5.5。

19.3.38 Uint8Array ( . . . )

参见 23.2.5。

19.3.39 Uint8ClampedArray ( . . . )

参见 23.2.5。

19.3.40 Uint16Array ( . . . )

参见 23.2.5。

19.3.41 Uint32Array ( . . . )

参见 23.2.5。

19.3.42 URIError ( . . . )

参见 20.5.5.6。

19.3.43 WeakMap ( . . . )

参见 24.3.1。

19.3.44 WeakRef ( . . . )

参见 26.1.1。

19.3.45 WeakSet ( . . . )

参见 24.4。

19.4 全局对象的其他属性

19.4.1 Atomics

参见 25.4。

19.4.2 JSON

参见 25.5。

19.4.3 Math

参见 21.3。

19.4.4 Reflect

参见 28.1。

20 基本对象

20.1 Object 对象

20.1.1 Object 构造函数

Object 构造函数:

20.1.1.1 Object ( value )

调用时,此函数执行以下步骤:

  1. 如果 NewTarget 既不是 undefined 也不是活动函数对象,则
    1. 返回 ? OrdinaryCreateFromConstructor(NewTarget, "%Object.prototype%")。
  2. 如果 value 是 undefined 或 null,则返回 OrdinaryObjectCreate(%Object.prototype%)。
  3. 返回 ! ToObject(value)。

20.1.2 Object 构造函数的属性

Object 构造函数:

20.1.2.1 Object.assign ( target, ...sources )

此函数将一个或多个源对象的所有可枚举自有属性值复制到 target 对象。

调用时,此函数执行以下步骤:

  1. 令 targetObj 为 ? ToObject(target)。
  2. 如果只传递了一个参数,则返回 targetObj。
  3. 对 sources 的每个元素 nextSource,执行
    1. 如果 nextSource 既不是 undefined 也不是 null,则
      1. 令 from 为 ! ToObject(nextSource)。
      2. 令 keys 为 ? from.[[OwnPropertyKeys]]()。
      3. 对 keys 的每个元素 nextKey,执行
        1. 令 propertyDesc 为 ? from.[[GetOwnProperty]](nextKey)。
        2. 如果 propertyDesc 不是 undefined 且 propertyDesc.[[Enumerable]] 是 true,则
          1. 令 propertyValue 为 ? Get(from, nextKey)。
          2. 执行 ? Set(targetObj, nextKey, propertyValue, true)。
  4. 返回 targetObj。

此函数的 "length" 属性为 2𝔽。

20.1.2.2 Object.create ( proto, properties )

此函数使用指定的原型创建新对象。

调用时,此函数执行以下步骤:

  1. 如果 proto 不是 Object 且 proto 不是 null,则抛出 TypeError 异常。
  2. 令 obj 为 OrdinaryObjectCreate(proto)。
  3. 如果 properties 不是 undefined,则
    1. 返回 ? ObjectDefineProperties(obj, properties)。
  4. 返回 obj。

20.1.2.3 Object.defineProperties ( obj, properties )

此函数添加自有属性和/或更新对象现有自有属性的特性。

调用时,此函数执行以下步骤:

  1. 如果 obj 不是 Object,则抛出 TypeError 异常。
  2. 返回 ? ObjectDefineProperties(obj, properties)。

20.1.2.3.1 ObjectDefineProperties ( obj, properties )

抽象操作 ObjectDefineProperties,接收参数 obj (Object) 和 properties (ECMAScript 语言值);返回值:(正常完成 (值:Object) 或 抛出完成)。 调用时执行以下步骤:

  1. 将 properties 设置为 ? ToObject(properties)。
  2. 令 keys 为 ? properties.[[OwnPropertyKeys]]()。
  3. 令 propertyDescs 为新的空 List。
  4. 对 keys 的每个元素 nextKey,执行
    1. 令 currentPropertyDesc 为 ? properties.[[GetOwnProperty]](nextKey)。
    2. 如果 currentPropertyDesc 不是 undefined 且 currentPropertyDesc.[[Enumerable]] 是 true,则
      1. 令 propertyDescObj 为 ? Get(properties, nextKey)。
      2. 令 propertyDesc 为 ? ToPropertyDescriptor(propertyDescObj)。
      3. 将 Record { [[Key]]: nextKey, [[Descriptor]]: propertyDesc } 追加到 propertyDescs。
  5. 对 propertyDescs 的每个元素 property,执行
    1. 执行 ? DefinePropertyOrThrow(obj, property.[[Key]], property.[[Descriptor]])。
  6. 返回 obj。

20.1.2.4 Object.defineProperty ( obj, key, attrs )

此函数添加自有属性和/或更新对象现有自有属性的特性。

调用时,此函数执行以下步骤:

  1. 如果 obj 不是 Object,则抛出 TypeError 异常。
  2. 令 propertyKey 为 ? ToPropertyKey(key)。
  3. 令 propertyDesc 为 ? ToPropertyDescriptor(attrs)。
  4. 执行 ? DefinePropertyOrThrow(obj, propertyKey, propertyDesc)。
  5. 返回 obj。

20.1.2.5 Object.entries ( obj )

调用时,此函数执行以下步骤:

  1. 令 coerced 为 ? ToObject(obj)。
  2. 令 entryList 为 ? EnumerableOwnProperties(coerced, key+value)。
  3. 返回 CreateArrayFromList(entryList)。

20.1.2.6 Object.freeze ( obj )

调用时,此函数执行以下步骤:

  1. 如果 obj 不是 Object,则返回 obj。
  2. 令 status 为 ? SetIntegrityLevel(obj, frozen)。
  3. 如果 status 是 false,则抛出 TypeError 异常。
  4. 返回 obj。

20.1.2.7 Object.fromEntries ( iterable )

调用时,此函数执行以下步骤:

  1. 执行 ? RequireObjectCoercible(iterable)。
  2. 令 obj 为 OrdinaryObjectCreate(%Object.prototype%)。
  3. 断言:obj 是没有自有属性的可扩展普通对象。
  4. 令 closure 为具有参数 (key, value) 的新 Abstract Closure,它捕获 obj,并在被调用时执行以下步骤:
    1. 令 propertyKey 为 ? ToPropertyKey(key)。
    2. 执行 ! CreateDataPropertyOrThrow(obj, propertyKey, value)。
    3. 返回 NormalCompletion(undefined)。
  5. 令 adder 为 CreateBuiltinFunction(closure, 2, "", « »)。
  6. 返回 ? AddEntriesFromIterable(obj, iterable, adder)。
注
为 adder 创建的函数永远无法被 ECMAScript 代码直接访问。

20.1.2.8 Object.getOwnPropertyDescriptor ( obj, key )

调用时,此函数执行以下步骤:

  1. 令 coerced 为 ? ToObject(obj)。
  2. 令 propertyKey 为 ? ToPropertyKey(key)。
  3. 令 propertyDesc 为 ? coerced.[[GetOwnProperty]](propertyKey)。
  4. 返回 FromPropertyDescriptor(propertyDesc)。

20.1.2.9 Object.getOwnPropertyDescriptors ( obj )

调用时,此函数执行以下步骤:

  1. 令 coerced 为 ? ToObject(obj)。
  2. 令 ownKeys 为 ? coerced.[[OwnPropertyKeys]]()。
  3. 令 descs 为 OrdinaryObjectCreate(%Object.prototype%)。
  4. 对 ownKeys 的每个元素 key,执行
    1. 令 propertyDesc 为 ? coerced.[[GetOwnProperty]](key)。
    2. 令 propertyDescObj 为 FromPropertyDescriptor(propertyDesc)。
    3. 如果 propertyDescObj 不是 undefined,则执行 ! CreateDataPropertyOrThrow(descs, key, propertyDescObj)。
  5. 返回 descs。

20.1.2.10 Object.getOwnPropertyNames ( obj )

调用时,此函数执行以下步骤:

  1. 返回 CreateArrayFromList(? GetOwnPropertyKeys(obj, string))。

20.1.2.11 Object.getOwnPropertySymbols ( obj )

调用时,此函数执行以下步骤:

  1. 返回 CreateArrayFromList(? GetOwnPropertyKeys(obj, symbol))。

20.1.2.11.1 GetOwnPropertyKeys ( value, type )

抽象操作 GetOwnPropertyKeys,接收参数 value (ECMAScript 语言值) 和 type ((string 或 symbol));返回值:(正常完成 (值:列表 (元素:属性键)) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 obj 为 ? ToObject(value)。
  2. 令 keys 为 ? obj.[[OwnPropertyKeys]]()。
  3. 令 nameList 为新的空 List。
  4. 对 keys 的每个元素 nextKey,执行
    1. 如果 nextKey 是 Symbol 且 type 是 symbol,或者 nextKey 是 String 且 type 是 string,则
      1. 将 nextKey 追加到 nameList。
  5. 返回 nameList。

20.1.2.12 Object.getPrototypeOf ( obj )

调用时,此函数执行以下步骤:

  1. 令 coerced 为 ? ToObject(obj)。
  2. 返回 ? coerced.[[GetPrototypeOf]]()。

20.1.2.13 Object.groupBy ( items, callback )

注

callback 应是接受两个参数的函数。groupBy 按升序对 items 中的每个元素调用一次 callback,并构造一个新对象。callback 返回的每个值都会强制转换为属性键。对于每个这样的属性键,结果对象都具有一个属性,其键是该属性键,其值是包含所有 callback 返回值强制转换为该键的元素的数组。

调用 callback 时传递两个参数:元素的值和元素的索引。

groupBy 的返回值是不从 %Object.prototype% 继承的对象。

调用时,此函数执行以下步骤:

  1. 令 groups 为 ? GroupBy(items, callback, property)。
  2. 令 obj 为 OrdinaryObjectCreate(null)。
  3. 对 groups 的每个 Record { [[Key]], [[Elements]] } group,执行
    1. 令 elements 为 CreateArrayFromList(group.[[Elements]])。
    2. 执行 ! CreateDataPropertyOrThrow(obj, group.[[Key]], elements)。
  4. 返回 obj。

20.1.2.14 Object.hasOwn ( obj, key )

调用时,此函数执行以下步骤:

  1. 令 coerced 为 ? ToObject(obj)。
  2. 令 propertyKey 为 ? ToPropertyKey(key)。
  3. 返回 ? HasOwnProperty(coerced, propertyKey)。

20.1.2.15 Object.is ( value1, value2 )

调用时,此函数执行以下步骤:

  1. 返回 SameValue(value1, value2)。

20.1.2.16 Object.isExtensible ( obj )

调用时,此函数执行以下步骤:

  1. 如果 obj 不是 Object,则返回 false。
  2. 返回 ? IsExtensible(obj)。

20.1.2.17 Object.isFrozen ( obj )

调用时,此函数执行以下步骤:

  1. 如果 obj 不是 Object,则返回 true。
  2. 返回 ? TestIntegrityLevel(obj, frozen)。

20.1.2.18 Object.isSealed ( obj )

调用时,此函数执行以下步骤:

  1. 如果 obj 不是 Object,则返回 true。
  2. 返回 ? TestIntegrityLevel(obj, sealed)。

20.1.2.19 Object.keys ( obj )

调用时,此函数执行以下步骤:

  1. 令 coerced 为 ? ToObject(obj)。
  2. 令 keyList 为 ? EnumerableOwnProperties(coerced, key)。
  3. 返回 CreateArrayFromList(keyList)。

20.1.2.20 Object.preventExtensions ( obj )

调用时,此函数执行以下步骤:

  1. 如果 obj 不是 Object,则返回 obj。
  2. 令 status 为 ? obj.[[PreventExtensions]]()。
  3. 如果 status 是 false,则抛出 TypeError 异常。
  4. 返回 obj。

20.1.2.21 Object.prototype

Object.prototype 的初始值是 Object 原型对象。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.1.2.22 Object.seal ( obj )

调用时,此函数执行以下步骤:

  1. 如果 obj 不是 Object,则返回 obj。
  2. 令 status 为 ? SetIntegrityLevel(obj, sealed)。
  3. 如果 status 是 false,则抛出 TypeError 异常。
  4. 返回 obj。

20.1.2.23 Object.setPrototypeOf ( obj, proto )

调用时,此函数执行以下步骤:

  1. 执行 ? RequireObjectCoercible(obj)。
  2. 如果 proto 不是 Object 且 proto 不是 null,则抛出 TypeError 异常。
  3. 如果 obj 不是 Object,则返回 obj。
  4. 令 status 为 ? obj.[[SetPrototypeOf]](proto)。
  5. 如果 status 是 false,则抛出 TypeError 异常。
  6. 返回 obj。

20.1.2.24 Object.values ( obj )

调用时,此函数执行以下步骤:

  1. 令 coerced 为 ? ToObject(obj)。
  2. 令 valueList 为 ? EnumerableOwnProperties(coerced, value)。
  3. 返回 CreateArrayFromList(valueList)。

20.1.3 Object 原型对象的属性

Object 原型对象:

  • 是 %Object.prototype%。
  • 具有 [[Extensible]] 内部槽,其值是 true。
  • 具有为普通对象定义的内部方法,但 [[SetPrototypeOf]] 方法除外,该方法定义于 10.4.7.1。(因此,它是不可变原型异质对象。)
  • 具有 [[Prototype]] 内部槽,其值是 null。

20.1.3.1 Object.prototype.constructor

Object.prototype.constructor 的初始值是 %Object%。

20.1.3.2 Object.prototype.hasOwnProperty ( value )

调用时,此方法执行以下步骤:

  1. 令 propertyKey 为 ? ToPropertyKey(value)。
  2. 令 obj 为 ? ToObject(this value)。
  3. 返回 ? HasOwnProperty(obj, propertyKey)。
注

步骤 1 和 2 的顺序是有意选择的,以确保即使 this value 是 undefined 或 null,在本规范早期版本中本应由步骤 1 抛出的任何异常仍会继续抛出。

20.1.3.3 Object.prototype.isPrototypeOf ( value )

调用时,此方法执行以下步骤:

  1. 如果 value 不是 Object,则返回 false。
  2. 令 obj 为 ? ToObject(this value)。
  3. 重复执行,
    1. 将 value 设置为 ? value.[[GetPrototypeOf]]()。
    2. 如果 value 是 null,则返回 false。
    3. 如果 SameValue(obj, value) 是 true,则返回 true。
注

步骤 1 和 2 的顺序保留了本规范早期版本在 value 不是对象且 this value 是 undefined 或 null 时规定的行为。

20.1.3.4 Object.prototype.propertyIsEnumerable ( value )

调用时,此方法执行以下步骤:

  1. 令 propertyKey 为 ? ToPropertyKey(value)。
  2. 令 obj 为 ? ToObject(this value)。
  3. 令 propertyDesc 为 ? obj.[[GetOwnProperty]](propertyKey)。
  4. 如果 propertyDesc 是 undefined,则返回 false。
  5. 返回 propertyDesc.[[Enumerable]]。
注 1

此方法不考虑原型链中的对象。

注 2

步骤 1 和 2 的顺序是有意选择的,以确保即使 this value 是 undefined 或 null,在本规范早期版本中本应由步骤 1 抛出的任何异常仍会继续抛出。

20.1.3.5 Object.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] )

调用时,此方法执行以下步骤:

  1. 令 thisValue 为 this value。
  2. 返回 ? Invoke(thisValue, "toString")。

此方法的可选参数不会被使用,但旨在对应 ECMA-402 toLocaleString 方法使用的参数模式。不包含 ECMA-402 支持的实现不得将这些参数位置用于其他目的。

注 1

此方法为没有区域设置敏感 toString 行为的对象提供通用的 toLocaleString 实现。Array、Number、Date 和 %TypedArray% 提供各自的区域设置敏感 toLocaleString 方法。

注 2

ECMA-402 有意不为此默认实现提供替代方案。

20.1.3.6 Object.prototype.toString ( )

调用时,此方法执行以下步骤:

  1. 如果 this value 是 undefined,则返回 "[object Undefined]"。
  2. 如果 this value 是 null,则返回 "[object Null]"。
  3. 令 obj 为 ! ToObject(this value)。
  4. 令 isArray 为 ? IsArray(obj)。
  5. 如果 isArray 是 true,则令 builtinTag 为 "Array"。
  6. 否则如果 obj 具有 [[ParameterMap]] 内部槽,则令 builtinTag 为 "Arguments"。
  7. 否则如果 obj 具有 [[Call]] 内部方法,则令 builtinTag 为 "Function"。
  8. 否则如果 obj 具有 [[ErrorData]] 内部槽,则令 builtinTag 为 "Error"。
  9. 否则如果 obj 具有 [[BooleanData]] 内部槽,则令 builtinTag 为 "Boolean"。
  10. 否则如果 obj 具有 [[NumberData]] 内部槽,则令 builtinTag 为 "Number"。
  11. 否则如果 obj 具有 [[StringData]] 内部槽,则令 builtinTag 为 "String"。
  12. 否则如果 obj 具有 [[DateValue]] 内部槽,则令 builtinTag 为 "Date"。
  13. 否则如果 obj 具有 [[RegExpMatcher]] 内部槽,则令 builtinTag 为 "RegExp"。
  14. 否则,令 builtinTag 为 "Object"。
  15. 令 tag 为 ? Get(obj, %Symbol.toStringTag%)。
  16. 如果 tag 不是 String,则将 tag 设置为 builtinTag。
  17. 返回 "[object "、tag 和 "]" 的字符串连接。
注

从历史上看,此方法偶尔用于访问 [[Class]] 内部槽的 String 值,该内部槽在本规范早期版本中用作各种内置对象的名义类型标签。上述 toString 定义为使用 toString 测试这些特定内置对象种类的旧代码保留了兼容性。对于其他种类的内置对象或程序定义对象,它并不能提供可靠的类型测试机制。此外,程序可以以某些方式使用 %Symbol.toStringTag%,从而使此类旧式类型测试失去可靠性。

20.1.3.7 Object.prototype.valueOf ( )

调用时,此方法执行以下步骤:

  1. 返回 ? ToObject(this value)。

20.1.3.8 Object.prototype.__proto__

Object.prototype.__proto__ 是访问器属性,具有特性 { [[Enumerable]]: false, [[Configurable]]: true }。[[Getter]] 和 [[Setter]] 特性定义如下:

20.1.3.8.1 get Object.prototype.__proto__

[[Getter]] 特性的值是一个不需要参数的内置函数。调用时,它执行以下步骤:

  1. 令 obj 为 ? ToObject(this value)。
  2. 返回 ? obj.[[GetPrototypeOf]]()。

20.1.3.8.2 set Object.prototype.__proto__

[[Setter]] 特性的值是接受参数 proto 的内置函数。调用时,它执行以下步骤:

  1. 令 thisValue 为 this value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. 如果 proto 不是 Object 且 proto 不是 null,则返回 undefined。
  4. 如果 thisValue 不是 Object,则返回 undefined。
  5. 令 status 为 ? thisValue.[[SetPrototypeOf]](proto)。
  6. 如果 status 是 false,则抛出 TypeError 异常。
  7. 返回 undefined。

20.1.3.9 旧式 Object.prototype 访问器方法

20.1.3.9.1 Object.prototype.__defineGetter__ ( key, getter )

调用时,此方法执行以下步骤:

  1. 令 obj 为 ? ToObject(this value)。
  2. 如果 IsCallable(getter) 是 false,则抛出 TypeError 异常。
  3. 令 propertyDesc 为 PropertyDescriptor { [[Getter]]: getter, [[Enumerable]]: true, [[Configurable]]: true }。
  4. 令 propertyKey 为 ? ToPropertyKey(key)。
  5. 执行 ? DefinePropertyOrThrow(obj, propertyKey, propertyDesc)。
  6. 返回 undefined。

20.1.3.9.2 Object.prototype.__defineSetter__ ( key, setter )

调用时,此方法执行以下步骤:

  1. 令 obj 为 ? ToObject(this value)。
  2. 如果 IsCallable(setter) 是 false,则抛出 TypeError 异常。
  3. 令 propertyDesc 为 PropertyDescriptor { [[Setter]]: setter, [[Enumerable]]: true, [[Configurable]]: true }。
  4. 令 propertyKey 为 ? ToPropertyKey(key)。
  5. 执行 ? DefinePropertyOrThrow(obj, propertyKey, propertyDesc)。
  6. 返回 undefined。

20.1.3.9.3 Object.prototype.__lookupGetter__ ( key )

调用时,此方法执行以下步骤:

  1. 令 obj 为 ? ToObject(this value)。
  2. 令 propertyKey 为 ? ToPropertyKey(key)。
  3. 重复执行,
    1. 令 propertyDesc 为 ? obj.[[GetOwnProperty]](propertyKey)。
    2. 如果 propertyDesc 不是 undefined,则
      1. 如果 IsAccessorDescriptor(propertyDesc) 是 true,则返回 propertyDesc.[[Getter]]。
      2. 返回 undefined。
    3. 将 obj 设置为 ? obj.[[GetPrototypeOf]]()。
    4. 如果 obj 是 null,则返回 undefined。

20.1.3.9.4 Object.prototype.__lookupSetter__ ( key )

调用时,此方法执行以下步骤:

  1. 令 obj 为 ? ToObject(this value)。
  2. 令 propertyKey 为 ? ToPropertyKey(key)。
  3. 重复执行,
    1. 令 propertyDesc 为 ? obj.[[GetOwnProperty]](propertyKey)。
    2. 如果 propertyDesc 不是 undefined,则
      1. 如果 IsAccessorDescriptor(propertyDesc) 是 true,则返回 propertyDesc.[[Setter]]。
      2. 返回 undefined。
    3. 将 obj 设置为 ? obj.[[GetPrototypeOf]]()。
    4. 如果 obj 是 null,则返回 undefined。

20.1.4 Object 实例的属性

Object 实例除了从 Object 原型对象继承的属性外,没有特殊属性。

20.2 Function 对象

20.2.1 Function 构造函数

Function 构造函数:

  • 是 %Function%。
  • 是全局对象的 "Function" 属性的初始值。
  • 作为函数而不是构造函数调用时,会创建并初始化新的函数对象。因此,函数调用 Function(…) 等价于使用相同参数的对象创建表达式 new Function(…)。
  • 可以用作类定义的 extends 子句的值。希望继承指定 Function 行为的子类构造函数,必须包含对 Function 构造函数的 super 调用,以创建并初始化具有内置函数行为所需内部槽的子类实例。所有用于定义函数对象的 ECMAScript 句法形式都会创建 Function 的实例。除内置的 GeneratorFunction、AsyncFunction 和 AsyncGeneratorFunction 子类之外,没有句法方式可以创建 Function 子类的实例。

20.2.1.1 Function ( ...paramArgs, bodyArg )

最后一个参数(如果存在)指定函数的主体(可执行代码);此前的任何参数指定形式参数。

调用时,此函数执行以下步骤:

  1. 令 ctor 为活动函数对象。
  2. 如果不存在 bodyArg,则将 bodyArg 设置为空 String。
  3. 返回 ? CreateDynamicFunction(ctor, NewTarget, normal, paramArgs, bodyArg)。
注

允许但不要求为每个要指定的形式参数分别提供一个参数。例如,以下三个表达式都产生相同结果:

new Function("a", "b", "c", "return a+b+c")
new Function("a, b, c", "return a+b+c")
new Function("a,b", "c", "return a+b+c")

20.2.1.1.1 CreateDynamicFunction ( ctor, newTarget, kind, paramArgs, bodyArg )

抽象操作 CreateDynamicFunction,接收参数 ctor (构造函数)、newTarget ((构造函数 或 undefined))、kind ((normal、generator、async 或 async-generator))、paramArgs (列表 (元素:ECMAScript 语言值)) 和 bodyArg (ECMAScript 语言值);返回值:(正常完成 (值:ECMAScript 函数对象) 或 抛出完成)。 ctor 是执行此操作的构造函数。newTarget 是最初对其应用 new 的构造函数。paramArgs 和 bodyArg 反映传递给 ctor 的参数值。 调用时执行以下步骤:

  1. 如果 newTarget 是 undefined,则将 newTarget 设置为 ctor。
  2. 如果 kind 是 normal,则
    1. 令 prefix 为 "function"。
    2. 令 exprGrammar 为文法符号 FunctionExpression。
    3. 令 bodyGrammar 为文法符号 FunctionBody[~Yield, ~Await]。
    4. 令 paramGrammar 为文法符号 FormalParameters[~Yield, ~Await]。
    5. 令 fallbackProto 为 "%Function.prototype%"。
  3. 否则如果 kind 是 generator,则
    1. 令 prefix 为 "function*"。
    2. 令 exprGrammar 为文法符号 GeneratorExpression。
    3. 令 bodyGrammar 为文法符号 GeneratorBody。
    4. 令 paramGrammar 为文法符号 FormalParameters[+Yield, ~Await]。
    5. 令 fallbackProto 为 "%GeneratorFunction.prototype%"。
  4. 否则如果 kind 是 async,则
    1. 令 prefix 为 "async function"。
    2. 令 exprGrammar 为文法符号 AsyncFunctionExpression。
    3. 令 bodyGrammar 为文法符号 AsyncFunctionBody。
    4. 令 paramGrammar 为文法符号 FormalParameters[~Yield, +Await]。
    5. 令 fallbackProto 为 "%AsyncFunction.prototype%"。
  5. 否则,
    1. 断言:kind 是 async-generator。
    2. 令 prefix 为 "async function*"。
    3. 令 exprGrammar 为文法符号 AsyncGeneratorExpression。
    4. 令 bodyGrammar 为文法符号 AsyncGeneratorBody。
    5. 令 paramGrammar 为文法符号 FormalParameters[+Yield, +Await]。
    6. 令 fallbackProto 为 "%AsyncGeneratorFunction.prototype%"。
  6. 令 argCount 为 paramArgs 中的元素数量。
  7. 令 paramStrings 为新的空 List。
  8. 对 paramArgs 的每个元素 arg,执行
    1. 将 ? ToString(arg) 追加到 paramStrings。
  9. 令 bodyString 为 ? ToString(bodyArg)。
  10. 令 currentRealm 为当前 Realm Record。
  11. 执行 ? HostEnsureCanCompileStrings(currentRealm, paramStrings, bodyString, false)。
  12. 令 paramString 为空 String。
  13. 如果 argCount > 0,则
    1. 将 paramString 设置为 paramStrings[0]。
    2. 令 k 为 1。
    3. 当 k < argCount 时,重复执行,
      1. 令 nextArgString 为 paramStrings[k]。
      2. 将 paramString 设置为 paramString、","(逗号)和 nextArgString 的字符串连接。
      3. 将 k 设置为 k + 1。
  14. 令 bodyParseString 为 0x000A (LINE FEED)、bodyString 和 0x000A (LINE FEED) 的字符串连接。
  15. 令 sourceString 为 prefix、" anonymous("、paramString、0x000A (LINE FEED)、") {"、bodyParseString 和 "}" 的字符串连接。
  16. 令 sourceText 为 StringToCodePoints(sourceString)。
  17. 令 params 为 ParseText(paramString, paramGrammar)。
  18. 如果 params 是错误的 List,则抛出 SyntaxError 异常。
  19. 令 body 为 ParseText(bodyParseString, bodyGrammar)。
  20. 如果 body 是错误的 List,则抛出 SyntaxError 异常。
  21. 注:参数和函数体会分别解析,以确保它们各自单独有效。例如,new Function("/*", "*/ ) {") 不会求值为函数。
  22. 注:如果执行到此步骤,sourceText 必须具有 exprGrammar 的语法(尽管反向推论不成立)。接下来的两个步骤用于强制执行直接适用于 exprGrammar 的任何提前错误规则。
  23. 令 expr 为 ParseText(sourceText, exprGrammar)。
  24. 如果 expr 是错误的 List,则抛出 SyntaxError 异常。
  25. 令 funcProto 为 ? GetPrototypeFromConstructor(newTarget, fallbackProto)。
  26. 令 envRecord 为 currentRealm.[[GlobalEnv]]。
  27. 令 privateEnv 为 null。
  28. 令 func 为 OrdinaryFunctionCreate(funcProto, sourceText, params, body, non-lexical-this, envRecord, privateEnv)。
  29. 执行 SetFunctionName(func, "anonymous")。
  30. 如果 kind 是 generator,则
    1. 令 protoProto 为 OrdinaryObjectCreate(%GeneratorPrototype%)。
    2. 执行 ! DefinePropertyOrThrow(func, "prototype", PropertyDescriptor { [[Value]]: protoProto, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  31. 否则如果 kind 是 async-generator,则
    1. 令 protoProto 为 OrdinaryObjectCreate(%AsyncGeneratorPrototype%)。
    2. 执行 ! DefinePropertyOrThrow(func, "prototype", PropertyDescriptor { [[Value]]: protoProto, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  32. 否则如果 kind 是 normal,则
    1. 执行 MakeConstructor(func)。
  33. 注:kind 为 async 的函数不可构造,并且没有 [[Construct]] 内部方法或 "prototype" 属性。
  34. 返回 func。
注

CreateDynamicFunction 会在其创建的、kind 不是 async 的任何函数上定义 "prototype" 属性,以便支持该函数可能被用作构造函数。

20.2.2 Function 构造函数的属性

Function 构造函数:

  • 自身是内置函数对象。
  • 具有 [[Prototype]] 内部槽,其值是 %Function.prototype%。
  • 具有 "length" 属性,其值是 1𝔽。
  • 具有以下属性:

20.2.2.1 Function.prototype

Function.prototype 的值是 Function 原型对象。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.2.3 Function 原型对象的属性

Function 原型对象:

  • 是 %Function.prototype%。
  • 自身是内置函数对象。
  • 调用时接受任意参数并返回 undefined。
  • 没有 [[Construct]] 内部方法;不能通过 new 运算符将其用作构造函数。
  • 具有 [[Prototype]] 内部槽,其值是 %Object.prototype%。
  • 没有 "prototype" 属性。
  • 具有 "length" 属性,其值是 +0𝔽。
  • 具有 "name" 属性,其值是空 String。
注

Function 原型对象被规定为函数对象,以确保与 ECMAScript 2015 规范之前创建的 ECMAScript 代码保持兼容。

20.2.3.1 Function.prototype.apply ( thisArg, argArray )

调用时,此方法执行以下步骤:

  1. 令 func 为 this value。
  2. 如果 IsCallable(func) 是 false,则抛出 TypeError 异常。
  3. 如果 argArray 是 undefined 或 null,则
    1. 执行 PrepareForTailCall()。
    2. 返回 ? Call(func, thisArg)。
  4. 令 argList 为 ? CreateListFromArrayLike(argArray)。
  5. 执行 PrepareForTailCall()。
  6. 返回 ? Call(func, thisArg, argList)。
注 1

thisArg 值未经修改直接作为 this value 传递。这与第 3 版不同,在第 3 版中,undefined 或 null 的 thisArg 会被替换为全局对象,并对所有其他值应用 ToObject,然后将该结果作为 this value 传递。尽管 thisArg 未经修改传递,非严格函数在进入函数时仍会执行这些转换。

注 2

如果 func 是箭头函数或绑定函数异质对象,则函数 [[Call]] 会在步骤 6 中忽略 thisArg。

20.2.3.2 Function.prototype.bind ( thisArg, ...args )

调用时,此方法执行以下步骤:

  1. 令 target 为 this value。
  2. 如果 IsCallable(target) 是 false,则抛出 TypeError 异常。
  3. 令 boundFunc 为 ? BoundFunctionCreate(target, thisArg, args)。
  4. 令 length 为 0。
  5. 令 targetHasLength 为 ? HasOwnProperty(target, "length")。
  6. 如果 targetHasLength 是 true,则
    1. 令 targetLength 为 ? Get(target, "length")。
    2. 如果 targetLength 是 Number,则
      1. 令 targetLengthAsInt 为 ! ToIntegerOrInfinity(targetLength)。
      2. 如果 targetLengthAsInt = +∞,则
        1. 将 length 设置为 +∞。
      3. 否则如果 targetLengthAsInt = -∞,则
        1. 将 length 设置为 0。
      4. 否则,
        1. 令 argCount 为 args 中的元素数量。
        2. 将 length 设置为 max(targetLengthAsInt - argCount, 0)。
  7. 执行 SetFunctionLength(boundFunc, length)。
  8. 令 targetName 为 ? Get(target, "name")。
  9. 如果 targetName 不是 String,则将 targetName 设置为空 String。
  10. 执行 SetFunctionName(boundFunc, targetName, "bound")。
  11. 返回 boundFunc。
注 1

使用 Function.prototype.bind 创建的函数对象是异质对象。它们也没有 "prototype" 属性。

注 2

如果 target 是箭头函数或绑定函数异质对象,则传递给此方法的 thisArg 不会被随后对 func 的调用使用。

20.2.3.3 Function.prototype.call ( thisArg, ...args )

调用时,此方法执行以下步骤:

  1. 令 func 为 this value。
  2. 如果 IsCallable(func) 是 false,则抛出 TypeError 异常。
  3. 执行 PrepareForTailCall()。
  4. 返回 ? Call(func, thisArg, args)。
注 1

thisArg 值未经修改直接作为 this value 传递。这与第 3 版不同,在第 3 版中,undefined 或 null 的 thisArg 会被替换为全局对象,并对所有其他值应用 ToObject,然后将该结果作为 this value 传递。尽管 thisArg 未经修改传递,非严格函数在进入函数时仍会执行这些转换。

注 2

如果 func 是箭头函数或绑定函数异质对象,则函数 [[Call]] 会在步骤 4 中忽略 thisArg。

20.2.3.4 Function.prototype.constructor

Function.prototype.constructor 的初始值是 %Function%。

20.2.3.5 Function.prototype.toString ( )

调用时,此方法执行以下步骤:

  1. 令 func 为 this value。
  2. 如果 func 是 Object,func 具有 [[SourceText]] 内部槽,func.[[SourceText]] 是 Unicode 码点序列,并且 HostHasSourceTextAvailable(func) 是 true,则
    1. 返回 CodePointsToString(func.[[SourceText]])。
  3. 如果 func 是内置函数对象,则返回 func 的实现定义 String 源代码表示。该表示必须具有 NativeFunction 的语法。此外,如果 func 具有 [[InitialName]] 内部槽并且 func.[[InitialName]] 是 String,则返回 String 中由 NativeFunctionAccessoropt PropertyName 匹配的部分必须是 func.[[InitialName]]。
  4. 如果 func 是 Object 且 IsCallable(func) 是 true,则返回 func 的实现定义 String 源代码表示。该表示必须具有 NativeFunction 的语法。
  5. 抛出 TypeError 异常。
NativeFunction : function NativeFunctionAccessoropt PropertyName[~Yield, ~Await]opt ( FormalParameters[~Yield, ~Await] ) { [ native code ] } NativeFunctionAccessor : get set

20.2.3.6 Function.prototype [ %Symbol.hasInstance% ] ( value )

调用时,此方法执行以下步骤:

  1. 令 thisValue 为 this value。
  2. 返回 ? OrdinaryHasInstance(thisValue, value)。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

注

这是大多数函数继承的 %Symbol.hasInstance% 默认实现。instanceof 运算符会调用 %Symbol.hasInstance% 来确定某个值是否为特定构造函数的实例。例如表达式

v instanceof F

求值方式等同于

F[%Symbol.hasInstance%](v)

构造函数可以通过在函数上暴露不同的 %Symbol.hasInstance% 方法,控制 instanceof 将哪些对象识别为其实例。

此属性不可写且不可配置,以防止可能用于全局暴露绑定函数目标函数的篡改。

此方法的 "name" 属性值是 "[Symbol.hasInstance]"。

20.2.4 Function 实例

每个 Function 实例都是 ECMAScript 函数对象,并具有 表 26 中列出的内部槽。使用 Function.prototype.bind 方法(20.2.3.2)创建的 Function 对象具有 表 27 中列出的内部槽。

Function 实例具有以下属性:

20.2.4.1 length

"length" 属性的值是整数 Number,表示函数通常期望的参数数量。不过,该语言允许使用其他数量的参数调用函数。当使用与其 "length" 属性所指定数量不同的参数数量调用函数时,其行为取决于该函数。此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

20.2.4.2 name

"name" 属性的值是描述函数的 String。该名称没有语义意义,但通常是在 ECMAScript 源文本中函数定义位置用于引用该函数的变量名或属性名。此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

本规范未为其关联上下文名称的匿名函数对象使用空 String 作为 "name" 属性的值。

20.2.4.3 prototype

可用作构造函数的 Function 实例具有 "prototype" 属性。每当创建此类 Function 实例时,还会创建另一个普通对象,并将其作为该函数 "prototype" 属性的初始值。除非另有规定,当该函数作为构造函数调用时,"prototype" 属性的值用于初始化所创建对象的 [[Prototype]] 内部槽。

此属性具有特性 { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }。

注

使用 Function.prototype.bind 创建的函数对象,或通过求值 MethodDefinition(不是 GeneratorMethod 或 AsyncGeneratorMethod)或 ArrowFunction 创建的函数对象,都没有 "prototype" 属性。

20.2.5 HostHasSourceTextAvailable ( func )

宿主定义的抽象操作 HostHasSourceTextAvailable,接收参数 func (函数对象);返回值:Boolean。 它允许宿主环境阻止为 func 提供源文本。

HostHasSourceTextAvailable 的实现必须符合以下要求:

  • 相对于其参数,它必须是确定性的。每次以特定 func 作为参数调用时,都必须返回相同结果。

HostHasSourceTextAvailable 的默认实现是返回 true。

20.3 Boolean 对象

20.3.1 Boolean 构造函数

Boolean 构造函数:

  • 是 %Boolean%。
  • 是全局对象的 "Boolean" 属性的初始值。
  • 作为构造函数调用时,创建并初始化新的 Boolean 对象。
  • 作为函数而不是构造函数调用时执行类型转换。
  • 可以用作类定义的 extends 子句的值。希望继承指定 Boolean 行为的子类构造函数必须包含对 Boolean 构造函数的 super 调用,以创建并初始化具有 [[BooleanData]] 内部槽的子类实例。

20.3.1.1 Boolean ( value )

调用时,此函数执行以下步骤:

  1. 令 bool 为 ToBoolean(value)。
  2. 如果 NewTarget 是 undefined,则返回 bool。
  3. 令 obj 为 ? OrdinaryCreateFromConstructor(NewTarget, "%Boolean.prototype%", « [[BooleanData]] »)。
  4. 将 obj.[[BooleanData]] 设置为 bool。
  5. 返回 obj。

20.3.2 Boolean 构造函数的属性

Boolean 构造函数:

20.3.2.1 Boolean.prototype

Boolean.prototype 的初始值是 Boolean 原型对象。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.3.3 Boolean 原型对象的属性

Boolean 原型对象:

  • 是 %Boolean.prototype%。
  • 是普通对象。
  • 自身是 Boolean 对象;它具有 [[BooleanData]] 内部槽,其值是 false。
  • 具有 [[Prototype]] 内部槽,其值是 %Object.prototype%。

20.3.3.1 Boolean.prototype.constructor

Boolean.prototype.constructor 的初始值是 %Boolean%。

20.3.3.2 Boolean.prototype.toString ( )

调用时,此方法执行以下步骤:

  1. 令 bool 为 ? ThisBooleanValue(this value)。
  2. 如果 bool 是 true,则返回 "true"。
  3. 返回 "false"。

20.3.3.3 Boolean.prototype.valueOf ( )

调用时,此方法执行以下步骤:

  1. 返回 ? ThisBooleanValue(this value)。

20.3.3.3.1 ThisBooleanValue ( arg )

抽象操作 ThisBooleanValue,接收参数 arg (ECMAScript 语言值);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 arg 是 Boolean,则返回 arg。
  2. 如果 arg 是 Object 且 arg 具有 [[BooleanData]] 内部槽,则
    1. 令 bool 为 arg.[[BooleanData]]。
    2. 断言:bool 是 Boolean。
    3. 返回 bool。
  3. 抛出 TypeError 异常。

20.3.4 Boolean 实例的属性

Boolean 实例是从 Boolean 原型对象继承属性的普通对象。Boolean 实例具有 [[BooleanData]] 内部槽。[[BooleanData]] 内部槽是此 Boolean 对象表示的 Boolean 值。

20.4 Symbol 对象

20.4.1 Symbol 构造函数

Symbol 构造函数:

  • 是 %Symbol%。
  • 是全局对象的 "Symbol" 属性的初始值。
  • 作为函数调用时返回新的 Symbol 值。
  • 不旨在与 new 运算符一起使用。
  • 不旨在被子类化。
  • 可以用作类定义的 extends 子句的值,但对它进行 super 调用会导致异常。

20.4.1.1 Symbol ( [ description ] )

调用时,此函数执行以下步骤:

  1. 如果 NewTarget 不是 undefined,则抛出 TypeError 异常。
  2. 如果 description 是 undefined,则令 descString 为 undefined。
  3. 否则,令 descString 为 ? ToString(description)。
  4. 返回一个新的 Symbol,其 [[Description]] 为 descString。

20.4.2 Symbol 构造函数的属性

Symbol 构造函数:

20.4.2.1 Symbol.asyncDispose

Symbol.asyncDispose 的初始值是众所周知的 symbol %Symbol.asyncDispose%(表 1)。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.2 Symbol.asyncIterator

Symbol.asyncIterator 的初始值是众所周知的 symbol %Symbol.asyncIterator%(表 1)。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.3 Symbol.dispose

Symbol.dispose 的初始值是众所周知的 symbol %Symbol.dispose%(表 1)。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.4 Symbol.for ( key )

调用时,此函数执行以下步骤:

  1. 令 stringKey 为 ? ToString(key)。
  2. 令 agentRecord 为周围代理的 Agent Record。
  3. 令 globalSymbolRegistry 为 agentRecord.[[GlobalSymbolRegistry]]。
  4. 对 globalSymbolRegistry 的每个元素 element,执行
    1. 如果 element.[[Key]] 是 stringKey,则返回 element.[[Symbol]]。
  5. 断言:globalSymbolRegistry 当前不包含 stringKey 的条目。
  6. 令 newSymbol 为一个新的 Symbol,其 [[Description]] 为 stringKey。
  7. 将 GlobalSymbolRegistry Record { [[Key]]: stringKey, [[Symbol]]: newSymbol } 追加到 globalSymbolRegistry。
  8. 返回 newSymbol。

20.4.2.5 Symbol.hasInstance

Symbol.hasInstance 的初始值是众所周知的 symbol %Symbol.hasInstance%(表 1)。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.6 Symbol.isConcatSpreadable

Symbol.isConcatSpreadable 的初始值是众所周知的 symbol %Symbol.isConcatSpreadable%(表 1)。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.7 Symbol.iterator

Symbol.iterator 的初始值是众所周知的 symbol %Symbol.iterator%(表 1)。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.8 Symbol.keyFor ( symbol )

调用时,此函数执行以下步骤:

  1. 如果 symbol 不是 Symbol,则抛出 TypeError 异常。
  2. 返回 KeyForSymbol(symbol)。

20.4.2.9 Symbol.match

Symbol.match 的初始值是众所周知的 symbol %Symbol.match%(表 1)。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.10 Symbol.matchAll

Symbol.matchAll 的初始值是众所周知的 symbol %Symbol.matchAll%(表 1)。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.11 Symbol.prototype

Symbol.prototype 的初始值是 Symbol 原型对象。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.12 Symbol.replace

Symbol.replace 的初始值是众所周知的 symbol %Symbol.replace%(表 1)。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.13 Symbol.search

Symbol.search 的初始值是众所周知的 symbol %Symbol.search%(表 1)。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.14 Symbol.species

Symbol.species 的初始值是众所周知的 symbol %Symbol.species%(表 1)。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.15 Symbol.split

Symbol.split 的初始值是众所周知的 symbol %Symbol.split%(表 1)。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.16 Symbol.toPrimitive

Symbol.toPrimitive 的初始值是众所周知的 symbol %Symbol.toPrimitive%(表 1)。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.17 Symbol.toStringTag

Symbol.toStringTag 的初始值是众所周知的 symbol %Symbol.toStringTag%(表 1)。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.18 Symbol.unscopables

Symbol.unscopables 的初始值是众所周知的 symbol %Symbol.unscopables%(表 1)。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.3 Symbol 原型对象的属性

Symbol 原型对象:

  • 是 %Symbol.prototype%。
  • 是普通对象。
  • 不是 Symbol 实例,并且没有 [[SymbolData]] 内部槽。
  • 具有 [[Prototype]] 内部槽,其值是 %Object.prototype%。

20.4.3.1 Symbol.prototype.constructor

Symbol.prototype.constructor 的初始值是 %Symbol%。

20.4.3.2 get Symbol.prototype.description

Symbol.prototype.description 是访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数在调用时执行以下步骤:

  1. 令 symbol 为 ? ThisSymbolValue(this value)。
  2. 返回 symbol.[[Description]]。

20.4.3.3 Symbol.prototype.toString ( )

调用时,此方法执行以下步骤:

  1. 令 symbol 为 ? ThisSymbolValue(this value)。
  2. 返回 SymbolDescriptiveString(symbol)。

20.4.3.3.1 SymbolDescriptiveString ( symbol )

抽象操作 SymbolDescriptiveString,接收参数 symbol (Symbol);返回值:String。 调用时执行以下步骤:

  1. 令 description 为 symbol.[[Description]]。
  2. 如果 description 是 undefined,则将 description 设置为空 String。
  3. 断言:description 是 String。
  4. 返回 "Symbol("、description 和 ")" 的字符串连接。

20.4.3.4 Symbol.prototype.valueOf ( )

调用时,此方法执行以下步骤:

  1. 返回 ? ThisSymbolValue(this value)。

20.4.3.4.1 ThisSymbolValue ( arg )

抽象操作 ThisSymbolValue,接收参数 arg (ECMAScript 语言值);返回值:(正常完成 (值:Symbol) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 arg 是 Symbol,则返回 arg。
  2. 如果 arg 是 Object 且 arg 具有 [[SymbolData]] 内部槽,则
    1. 令 symbol 为 arg.[[SymbolData]]。
    2. 断言:symbol 是 Symbol。
    3. 返回 symbol。
  3. 抛出 TypeError 异常。

20.4.3.5 Symbol.prototype [ %Symbol.toPrimitive% ] ( hint )

ECMAScript 语言运算符会调用此方法,将 Symbol 对象转换为原始值。

调用时,它执行以下步骤:

  1. 返回 ? ThisSymbolValue(this value)。
注

该参数会被忽略。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

此方法的 "name" 属性值是 "[Symbol.toPrimitive]"。

20.4.3.6 Symbol.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "Symbol"。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

20.4.4 Symbol 实例的属性

Symbol 实例是从 Symbol 原型对象继承属性的普通对象。Symbol 实例具有 [[SymbolData]] 内部槽。[[SymbolData]] 内部槽是此 Symbol 对象表示的 Symbol 值。

20.4.5 Symbol 的抽象操作

20.4.5.1 GlobalSymbolRegistry Records

GlobalSymbolRegistry Record 是用于将 String 键与通过 Symbol.for 注册的 Symbol 值关联起来的 Record。

GlobalSymbolRegistry Record 具有 表 59 中列出的字段。

表 59: GlobalSymbolRegistry Record 字段
字段名称 值 用途
[[Key]] a String 用于全局标识 Symbol 的字符串键。
[[Symbol]] a Symbol 可以从任意 realm 获取的 symbol。

20.4.5.2 KeyForSymbol ( symbol )

抽象操作 KeyForSymbol,接收参数 symbol (Symbol);返回值:(String 或 undefined)。 如果 symbol 位于周围代理的 [[GlobalSymbolRegistry]] List 中,则返回用于注册 symbol 的 String。 调用时执行以下步骤:

  1. 令 agentRecord 为周围代理的 Agent Record。
  2. 令 globalSymbolRegistry 为 agentRecord.[[GlobalSymbolRegistry]]。
  3. 对 globalSymbolRegistry 的每个元素 element,执行
    1. 如果 SameValue(element.[[Symbol]], symbol) 是 true,则返回 element.[[Key]]。
  4. 断言:globalSymbolRegistry 当前不包含 symbol 的条目。
  5. 返回 undefined。

20.5 Error 对象

发生运行时错误时,会将 Error 对象的实例作为异常抛出。Error 对象也可以作为用户定义异常类的基对象。

当 ECMAScript 实现检测到运行时错误时,它会抛出 20.5.5 中定义的某个 NativeError 对象的新实例,或者 20.5.7 中定义的 AggregateError 对象或 20.5.8 中定义的 SuppressedError 对象的新实例。这些对象都具有下述结构,区别仅在于用作构造函数名称而不是 NativeError 的名称、原型对象的 "name" 属性、原型对象的实现定义 "message" 属性,以及是否存在 %AggregateError% 特有的 "errors" 属性或 %SuppressedError% 特有的 "error" 和 "suppressed" 属性。

20.5.1 Error 构造函数

Error 构造函数:

  • 是 %Error%。
  • 是全局对象的 "Error" 属性的初始值。
  • 作为函数而不是构造函数调用时,创建并初始化新的 Error 对象。因此,函数调用 Error(…) 等价于使用相同参数的对象创建表达式 new Error(…)。
  • 可以用作类定义的 extends 子句的值。希望继承指定 Error 行为的子类构造函数必须包含对 Error 构造函数的 super 调用,以创建并初始化具有 [[ErrorData]] 内部槽的子类实例。

20.5.1.1 Error ( message [ , options ] )

调用时,此函数执行以下步骤:

  1. 如果 NewTarget 是 undefined,则令 newTarget 为活动函数对象;否则令 newTarget 为 NewTarget。
  2. 令 obj 为 ? OrdinaryCreateFromConstructor(newTarget, "%Error.prototype%", « [[ErrorData]] »)。
  3. 如果 message 不是 undefined,则
    1. 令 messageString 为 ? ToString(message)。
    2. 执行 CreateNonEnumerableDataPropertyOrThrow(obj, "message", messageString)。
  4. 执行 ? InstallErrorCause(obj, options)。
  5. 返回 obj。

20.5.2 Error 构造函数的属性

Error 构造函数:

20.5.2.1 Error.isError ( arg )

调用时,此函数执行以下步骤:

  1. 如果 arg 不是 Object,则返回 false。
  2. 如果 arg 没有 [[ErrorData]] 内部槽,则返回 false。
  3. 返回 true。

20.5.2.2 Error.prototype

Error.prototype 的初始值是 Error 原型对象。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.5.3 Error 原型对象的属性

Error 原型对象:

  • 是 %Error.prototype%。
  • 是普通对象。
  • 不是 Error 实例,并且没有 [[ErrorData]] 内部槽。
  • 具有 [[Prototype]] 内部槽,其值是 %Object.prototype%。

20.5.3.1 Error.prototype.constructor

Error.prototype.constructor 的初始值是 %Error%。

20.5.3.2 Error.prototype.message

Error.prototype.message 的初始值是空 String。

20.5.3.3 Error.prototype.name

Error.prototype.name 的初始值是 "Error"。

20.5.3.4 Error.prototype.toString ( )

调用时,此方法执行以下步骤:

  1. 令 obj 为 this value。
  2. 如果 obj 不是 Object,则抛出 TypeError 异常。
  3. 令 name 为 ? Get(obj, "name")。
  4. 如果 name 是 undefined,则将 name 设置为 "Error";否则将 name 设置为 ? ToString(name)。
  5. 令 message 为 ? Get(obj, "message")。
  6. 如果 message 是 undefined,则将 message 设置为空 String;否则将 message 设置为 ? ToString(message)。
  7. 如果 name 是空 String,则返回 message。
  8. 如果 message 是空 String,则返回 name。
  9. 返回 name、码元 0x003A (COLON)、码元 0x0020 (SPACE) 和 message 的字符串连接。

20.5.4 Error 实例的属性

Error 实例是从 Error 原型对象继承属性并具有 [[ErrorData]] 内部槽的普通对象,该内部槽的值是 undefined。[[ErrorData]] 唯一规定的用途是在 Object.prototype.toString 和 Error.isError 中将 Error、AggregateError、SuppressedError 和 NativeError 实例识别为 Error 对象。

20.5.5 本标准中使用的原生错误类型

检测到运行时错误时,会抛出下列某个 NativeError 对象的新实例,或 AggregateError 对象或 SuppressedError 对象的新实例。所有 NativeError 对象共享相同结构,如 20.5.6 中所述。

20.5.5.1 EvalError

EvalError 构造函数是 %EvalError%。

本规范目前未使用此异常。保留此对象是为了与本规范早期版本保持兼容。

20.5.5.2 RangeError

RangeError 构造函数是 %RangeError%。

表示某个值不在允许值的集合或范围内。

20.5.5.3 ReferenceError

ReferenceError 构造函数是 %ReferenceError%。

表示检测到了无效引用。

20.5.5.4 SyntaxError

SyntaxError 构造函数是 %SyntaxError%。

表示发生了解析错误。

20.5.5.5 TypeError

TypeError 构造函数是 %TypeError%。

当其他 NativeError 对象都不能恰当地表示失败原因时,TypeError 用于表示操作未成功。

20.5.5.6 URIError

URIError 构造函数是 %URIError%。

表示某个全局 URI 处理函数以与其定义不兼容的方式使用。

20.5.6 NativeError 对象结构

这些对象都具有下述结构,区别仅在于用作构造函数名称的名称以及原型对象的 "name" 属性。

对于每个错误对象,定义中对 NativeError 的引用都应替换为 20.5.5 中相应的错误对象名称。

20.5.6.1 NativeError 构造函数

每个 NativeError 构造函数:

  • 作为函数而不是构造函数调用时,创建并初始化新的 NativeError 对象。将该对象作为函数调用,等价于使用相同参数将其作为构造函数调用。因此,函数调用 NativeError(…) 等价于使用相同参数的对象创建表达式 new NativeError(…)。
  • 可以用作类定义的 extends 子句的值。希望继承指定 NativeError 行为的子类构造函数必须包含对 NativeError 构造函数的 super 调用,以创建并初始化具有 [[ErrorData]] 内部槽的子类实例。

20.5.6.1.1 NativeError ( message [ , options ] )

调用时,每个 NativeError 函数执行以下步骤:

  1. 如果 NewTarget 是 undefined,则令 newTarget 为活动函数对象;否则令 newTarget 为 NewTarget。
  2. 令 obj 为 ? OrdinaryCreateFromConstructor(newTarget, "%NativeError.prototype%", « [[ErrorData]] »)。
  3. 如果 message 不是 undefined,则
    1. 令 messageString 为 ? ToString(message)。
    2. 执行 CreateNonEnumerableDataPropertyOrThrow(obj, "message", messageString)。
  4. 执行 ? InstallErrorCause(obj, options)。
  5. 返回 obj。

步骤 2 中传递的字符串实际值是 "%EvalError.prototype%"、"%RangeError.prototype%"、"%ReferenceError.prototype%"、"%SyntaxError.prototype%"、"%TypeError.prototype%" 或 "%URIError.prototype%" 之一,具体取决于正在定义哪个 NativeError 构造函数。

20.5.6.2 NativeError 构造函数的属性

每个 NativeError 构造函数:

  • 具有 [[Prototype]] 内部槽,其值是 %Error%。
  • 具有 "name" 属性,其值是 String 值 "NativeError"。
  • 具有以下属性:

20.5.6.2.1 NativeError.prototype

NativeError.prototype 的初始值是 NativeError 原型对象(20.5.6.3)。每个 NativeError 构造函数都有不同的原型对象。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.5.6.3 NativeError 原型对象的属性

每个 NativeError 原型对象:

  • 是普通对象。
  • 不是 Error 实例,并且没有 [[ErrorData]] 内部槽。
  • 具有 [[Prototype]] 内部槽,其值是 %Error.prototype%。

20.5.6.3.1 NativeError.prototype.constructor

对于给定的 NativeError 构造函数,其原型的 "constructor" 属性的初始值是该构造函数自身。

20.5.6.3.2 NativeError.prototype.message

对于给定的 NativeError 构造函数,其原型的 "message" 属性的初始值是空 String。

20.5.6.3.3 NativeError.prototype.name

对于给定的 NativeError 构造函数,其原型的 "name" 属性的初始值是由构造函数名称(用来替代 NativeError 的名称)组成的 String 值。

20.5.6.4 NativeError 实例的属性

NativeError 实例是从其 NativeError 原型对象继承属性并具有 [[ErrorData]] 内部槽的普通对象,该内部槽的值是 undefined。[[ErrorData]] 唯一规定的用途是供 Object.prototype.toString(20.1.3.6)和 Error.isError(20.5.2.1)将 Error、AggregateError、SuppressedError 或 NativeError 实例识别出来。

20.5.7 AggregateError 对象

20.5.7.1 AggregateError 构造函数

AggregateError 构造函数:

  • 是 %AggregateError%。
  • 是全局对象的 "AggregateError" 属性的初始值。
  • 作为函数而不是构造函数调用时,创建并初始化新的 AggregateError 对象。因此,函数调用 AggregateError(…) 等价于使用相同参数的对象创建表达式 new AggregateError(…)。
  • 可以用作类定义的 extends 子句的值。希望继承指定 AggregateError 行为的子类构造函数必须包含对 AggregateError 构造函数的 super 调用,以创建并初始化具有 [[ErrorData]] 内部槽的子类实例。

20.5.7.1.1 AggregateError ( errors, message [ , options ] )

调用时,此函数执行以下步骤:

  1. 如果 NewTarget 是 undefined,则令 newTarget 为活动函数对象;否则令 newTarget 为 NewTarget。
  2. 令 obj 为 ? OrdinaryCreateFromConstructor(newTarget, "%AggregateError.prototype%", « [[ErrorData]] »)。
  3. 如果 message 不是 undefined,则
    1. 令 messageString 为 ? ToString(message)。
    2. 执行 CreateNonEnumerableDataPropertyOrThrow(obj, "message", messageString)。
  4. 执行 ? InstallErrorCause(obj, options)。
  5. 令 errorsList 为 ? IteratorToList(? GetIterator(errors, sync))。
  6. 执行 ! DefinePropertyOrThrow(obj, "errors", PropertyDescriptor { [[Configurable]]: true, [[Enumerable]]: false, [[Writable]]: true, [[Value]]: CreateArrayFromList(errorsList) })。
  7. 返回 obj。

20.5.7.2 AggregateError 构造函数的属性

AggregateError 构造函数:

  • 具有 [[Prototype]] 内部槽,其值是 %Error%。
  • 具有以下属性:

20.5.7.2.1 AggregateError.prototype

AggregateError.prototype 的初始值是 %AggregateError.prototype%。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.5.7.3 AggregateError 原型对象的属性

AggregateError 原型对象:

  • 是 %AggregateError.prototype%。
  • 是普通对象。
  • 既不是 Error 实例也不是 AggregateError 实例,并且没有 [[ErrorData]] 内部槽。
  • 具有 [[Prototype]] 内部槽,其值是 %Error.prototype%。

20.5.7.3.1 AggregateError.prototype.constructor

AggregateError.prototype.constructor 的初始值是 %AggregateError%。

20.5.7.3.2 AggregateError.prototype.message

AggregateError.prototype.message 的初始值是空 String。

20.5.7.3.3 AggregateError.prototype.name

AggregateError.prototype.name 的初始值是 "AggregateError"。

20.5.7.4 AggregateError 实例的属性

AggregateError 实例是从其 AggregateError 原型对象继承属性并具有 [[ErrorData]] 内部槽的普通对象,该内部槽的值是 undefined。[[ErrorData]] 唯一规定的用途是供 Object.prototype.toString(20.1.3.6)和 Error.isError(20.5.2.1)将 Error、AggregateError、SuppressedError 或 NativeError 实例识别出来。

20.5.8 SuppressedError 对象

20.5.8.1 SuppressedError 构造函数

SuppressedError 构造函数:

  • 是 %SuppressedError%。
  • 是全局对象的 "SuppressedError" 属性的初始值。
  • 作为函数而不是构造函数调用时,创建并初始化新的 SuppressedError 对象。因此,函数调用 SuppressedError(…) 等价于使用相同参数的对象创建表达式 new SuppressedError(…)。
  • 可以用作类定义的 extends 子句的值。希望继承指定 SuppressedError 行为的子类构造函数必须包含对 SuppressedError 构造函数的 super 调用,以创建并初始化具有 [[ErrorData]] 内部槽的子类实例。

20.5.8.1.1 SuppressedError ( error, suppressed, message )

调用时,此函数执行以下步骤:

  1. 如果 NewTarget 是 undefined,则令 newTarget 为活动函数对象;否则令 newTarget 为 NewTarget。
  2. 令 obj 为 ? OrdinaryCreateFromConstructor(newTarget, "%SuppressedError.prototype%", « [[ErrorData]] »)。
  3. 如果 message 不是 undefined,则
    1. 令 messageString 为 ? ToString(message)。
    2. 执行 CreateNonEnumerableDataPropertyOrThrow(obj, "message", messageString)。
  4. 执行 CreateNonEnumerableDataPropertyOrThrow(obj, "error", error)。
  5. 执行 CreateNonEnumerableDataPropertyOrThrow(obj, "suppressed", suppressed)。
  6. 返回 obj。

20.5.8.2 SuppressedError 构造函数的属性

SuppressedError 构造函数:

  • 具有 [[Prototype]] 内部槽,其值是 %Error%。
  • 具有以下属性:

20.5.8.2.1 SuppressedError.prototype

SuppressedError.prototype 的初始值是 SuppressedError 原型对象。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.5.8.3 SuppressedError 原型对象的属性

SuppressedError 原型对象:

  • 是 %SuppressedError.prototype%。
  • 是普通对象。
  • 既不是 Error 实例也不是 SuppressedError 实例,并且没有 [[ErrorData]] 内部槽。
  • 具有 [[Prototype]] 内部槽,其值是 %Error.prototype%。

20.5.8.3.1 SuppressedError.prototype.constructor

SuppressedError.prototype.constructor 的初始值是 %SuppressedError%。

20.5.8.3.2 SuppressedError.prototype.message

SuppressedError.prototype.message 的初始值是空 String。

20.5.8.3.3 SuppressedError.prototype.name

SuppressedError.prototype.name 的初始值是 "SuppressedError"。

20.5.8.4 SuppressedError 实例的属性

SuppressedError 实例是从其 SuppressedError 原型对象继承属性并具有 [[ErrorData]] 内部槽的普通对象,该内部槽的值是 undefined。[[ErrorData]] 唯一规定的用途是在 Object.prototype.toString 和 Error.isError 中将 Error、AggregateError、SuppressedError 和 NativeError 实例识别为 Error 对象。

20.5.9 Error 对象的抽象操作

20.5.9.1 InstallErrorCause ( obj, options )

抽象操作 InstallErrorCause,接收参数 obj (Object) 和 options (ECMAScript 语言值);返回值:(正常完成 (值:unused) 或 抛出完成)。 当 options 上存在 "cause" 属性时,它用于在 obj 上创建 "cause" 属性。 调用时执行以下步骤:

  1. 如果 options 是 Object 且 ? HasProperty(options, "cause") 是 true,则
    1. 令 cause 为 ? Get(options, "cause")。
    2. 执行 CreateNonEnumerableDataPropertyOrThrow(obj, "cause", cause)。
  2. 返回 unused。

21 数字和日期

21.1 Number 对象

21.1.1 Number 构造函数

Number 构造函数:

  • 是 %Number%。
  • 是全局对象的 "Number" 属性的初始值。
  • 作为构造函数调用时,创建并初始化新的 Number 对象。
  • 作为函数而不是构造函数调用时执行类型转换。
  • 可以用作类定义的 extends 子句的值。希望继承指定 Number 行为的子类构造函数必须包含对 Number 构造函数的 super 调用,以创建并初始化具有 [[NumberData]] 内部槽的子类实例。

21.1.1.1 Number ( value )

调用时,此函数执行以下步骤:

  1. 如果存在 value,则
    1. 令 primitive 为 ? ToNumeric(value)。
    2. 如果 primitive 是 BigInt,则令 n 为 𝔽(ℝ(primitive))。
    3. 否则,令 n 为 primitive。
  2. 否则,
    1. 令 n 为 +0𝔽。
  3. 如果 NewTarget 是 undefined,则返回 n。
  4. 令 obj 为 ? OrdinaryCreateFromConstructor(NewTarget, "%Number.prototype%", « [[NumberData]] »)。
  5. 将 obj.[[NumberData]] 设置为 n。
  6. 返回 obj。

21.1.2 Number 构造函数的属性

Number 构造函数:

21.1.2.1 Number.EPSILON

Number.EPSILON 的值是 1 与可表示为 Number 值且大于 1 的最小值之间差值的 Number 值,其约为 2.2204460492503130808472633361816 × 10-16。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.1.2.2 Number.isFinite ( number )

此函数被调用时执行以下步骤:

  1. 如果 number 是有限 Number,返回 true。
  2. 返回 false。

21.1.2.3 Number.isInteger ( number )

此函数被调用时执行以下步骤:

  1. 如果 number 是整数 Number,返回 true。
  2. 返回 false。

21.1.2.4 Number.isNaN ( number )

此函数被调用时执行以下步骤:

  1. 如果 number 不是 Number,返回 false。
  2. 如果 number 是 NaN,返回 true。
  3. 返回 false。
注

此函数与全局 isNaN 函数(19.2.3)的不同之处在于,它在确定其实参是否为 NaN 之前,不会将其实参转换为 Number。

21.1.2.5 Number.isSafeInteger ( number )

注

当且仅当整数 n 的 Number 值不是任何其他整数的 Number 值时,整数 n 才是“安全整数”。

此函数被调用时执行以下步骤:

  1. 如果 number 是整数 Number,那么
    1. 如果 abs(ℝ(number)) ≤ 253 - 1,返回 true。
  2. 返回 false。

21.1.2.6 Number.MAX_SAFE_INTEGER

注

由于 IEEE 754-2019 的精度限制所必需的舍入行为,每个大于 Number.MAX_SAFE_INTEGER 的整数的 Number 值都至少与另一个整数共享。因此,这类绝对值很大的整数不是安全的,不能保证能够精确表示为 Number 值,甚至不能保证彼此可区分。例如,9007199254740992 和 9007199254740993 的求值结果都是 Number 值 9007199254740992𝔽。

Number.MAX_SAFE_INTEGER 的值是 9007199254740991𝔽(𝔽(253 - 1))。

此属性具有属性特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.1.2.7 Number.MAX_VALUE

Number.MAX_VALUE 的值是最大的正有限 Number,约为 1.7976931348623157 × 10308。

此属性具有属性特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.1.2.8 Number.MIN_SAFE_INTEGER

注

由于 IEEE 754-2019 的精度限制所必需的舍入行为,每个小于 Number.MIN_SAFE_INTEGER 的整数的 Number 值都至少与另一个整数共享。因此,这类绝对值很大的整数不是安全的,不能保证能够精确表示为 Number 值,甚至不能保证彼此可区分。例如,-9007199254740992 和 -9007199254740993 的求值结果都是 Number 值 -9007199254740992𝔽。

Number.MIN_SAFE_INTEGER 的值是 -9007199254740991𝔽(𝔽(-(253 - 1)))。

此属性具有属性特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.1.2.9 Number.MIN_VALUE

Number.MIN_VALUE 的值是 Number 类型中最小的正值,约为 5 × 10-324。

在 IEEE 754-2019 双精度二进制表示中,可能的最小值是非规格化数。如果某个实现不支持非规格化值,则 Number.MIN_VALUE 的值必须是该实现实际能够表示的最小非零正值。

此属性具有属性特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.1.2.10 Number.NaN

Number.NaN 的值是 NaN。

此属性具有属性特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.1.2.11 Number.NEGATIVE_INFINITY

Number.NEGATIVE_INFINITY 的值是 -∞𝔽。

此属性具有属性特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.1.2.12 Number.parseFloat ( string )

"parseFloat" 属性的初始值是 %parseFloat%。

21.1.2.13 Number.parseInt ( string, radix )

"parseInt" 属性的初始值是 %parseInt%。

21.1.2.14 Number.POSITIVE_INFINITY

Number.POSITIVE_INFINITY 的值是 +∞𝔽。

此属性具有属性特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.1.2.15 Number.prototype

Number.prototype 的初始值是 Number 原型对象。

此属性具有属性特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.1.3 Number 原型对象的属性

Number 原型对象:

  • 是 %Number.prototype%。
  • 是普通对象。
  • 其自身是 Number 对象;它具有值为 +0𝔽 的 [[NumberData]] 内部槽。
  • 具有值为 %Object.prototype% 的 [[Prototype]] 内部槽。

除非另有明确说明,否则下面定义的 Number 原型对象的方法不是泛型方法,并且传递给它们的 this 值必须是 Number 值,或者是具有已初始化为 Number 值的 [[NumberData]] 内部槽的对象。

在方法规范中,短语“此 Number 值”是指以方法调用的 this 值作为实参调用抽象操作 ThisNumberValue 所返回的结果。

21.1.3.1 Number.prototype.constructor

Number.prototype.constructor 的初始值是 %Number%。

21.1.3.2 Number.prototype.toExponential ( fractionDigits )

此方法返回一个 String,其中包含以十进制指数记数法表示的此 Number 值,有效数的小数点前有一位数字,小数点后有 fractionDigits 位数字。如果 fractionDigits 是 undefined,则它包含唯一指定该 Number 所需的尽可能多的有效数数字(与 ToString 中一样,只是在这种情况下 Number 总是以指数记数法输出)。

它被调用时执行以下步骤:

  1. 令 number 为 ? ThisNumberValue(this value)。
  2. 令 fractionCount 为 ? ToIntegerOrInfinity(fractionDigits)。
  3. 断言:如果 fractionDigits 是 undefined,那么 fractionCount 是 0。
  4. 如果 number 不是有限 Number,返回 Number::toString(number, 10)。
  5. 如果 fractionCount 不是整数,抛出 RangeError 异常。
  6. 如果 fractionCount < 0 或 fractionCount > 100,抛出 RangeError 异常。
  7. 将 number 设置为 ℝ(number)。
  8. 令 sign 为空 String。
  9. 如果 number < 0,那么
    1. 将 sign 设置为 "-"。
    2. 将 number 设置为 -number。
  10. 如果 number = 0,那么
    1. 令 significand 为由 fractionCount + 1 个码元 0x0030 (DIGIT ZERO) 组成的 String 值。
    2. 令 exponent 为 0。
  11. 否则,
    1. 如果 fractionDigits 不是 undefined,那么
      1. 令 exponent 和 intSignificand 为满足 10fractionCount ≤ intSignificand < 10fractionCount + 1 且使 intSignificand × 10exponent - fractionCount - number 尽可能接近零的整数。如果有两组这样的 exponent 和 intSignificand,选择使 intSignificand × 10exponent - fractionCount 较大的那组 exponent 和 intSignificand。
    2. 否则,
      1. 令 exponent、intSignificand 和 ff 为满足 ff ≥ 0、10ff ≤ intSignificand < 10ff + 1、𝔽(intSignificand × 10exponent - ff) 是 𝔽(number),且 ff 尽可能小的整数。请注意,intSignificand 的十进制表示有 ff + 1 位数字,intSignificand 不能被 10 整除,并且根据这些条件,intSignificand 的最低有效位数字不一定唯一确定。
      2. 将 fractionCount 设置为 ff。
    3. 令 significand 为由 intSignificand 的十进制表示的数字(按顺序且无前导零)组成的 String 值。
  12. 如果 fractionCount ≠ 0,那么
    1. 令 intPart 为 significand 的第一个码元。
    2. 令 fractionalPart 为 significand 的其余 fractionCount 个码元。
    3. 将 significand 设置为 intPart、"." 和 fractionalPart 的字符串连接。
  13. 如果 exponent = 0,那么
    1. 令 exponentSign 为 "+"。
    2. 令 exponentDigits 为 "0"。
  14. 否则,
    1. 如果 exponent > 0,那么
      1. 令 exponentSign 为 "+"。
    2. 否则,
      1. 断言:exponent < 0。
      2. 令 exponentSign 为 "-"。
      3. 将 exponent 设置为 -exponent。
    3. 令 exponentDigits 为由 exponent 的十进制表示的数字(按顺序且无前导零)组成的 String 值。
  15. 将 significand 设置为 significand、"e"、exponentSign 和 exponentDigits 的字符串连接。
  16. 返回 sign 和 significand 的字符串连接。
注

对于提供比上述规则所要求的转换更精确的实现,建议使用步骤 11.b.i 的以下替代版本作为指导:

  1. 令 exponent、intSignificand 和 ff 为满足 ff ≥ 0、10ff ≤ intSignificand < 10ff + 1、𝔽(intSignificand × 10exponent - ff) 是 𝔽(number),且 ff 尽可能小的整数。如果 intSignificand 有多个可能值,则选择使 𝔽(intSignificand × 10exponent - ff) 最接近 𝔽(number) 的 intSignificand。如果有两个这样的 intSignificand 可能值,则选择其中的偶数。

21.1.3.3 Number.prototype.toFixed ( fractionDigits )

注 1

此方法返回一个 String,其中包含以十进制定点记数法表示的此 Number 值,小数点后有 fractionDigits 位数字。如果 fractionDigits 是 undefined,则假定为 0。

它被调用时执行以下步骤:

  1. 令 number 为 ? ThisNumberValue(this value)。
  2. 令 fractionCount 为 ? ToIntegerOrInfinity(fractionDigits)。
  3. 断言:如果 fractionDigits 是 undefined,那么 fractionCount 是 0。
  4. 如果 fractionCount 不是整数,抛出 RangeError 异常。
  5. 如果 fractionCount < 0 或 fractionCount > 100,抛出 RangeError 异常。
  6. 如果 number 不是有限 Number,返回 Number::toString(number, 10)。
  7. 将 number 设置为 ℝ(number)。
  8. 令 sign 为空 String。
  9. 如果 number < 0,那么
    1. 将 sign 设置为 "-"。
    2. 将 number 设置为 -number。
  10. 如果 number ≥ 1021,那么
    1. 令 digitString 为 ! ToString(𝔽(number))。
  11. 否则,
    1. 令 intValue 为使 intValue / 10fractionCount - number 尽可能接近零的整数。如果有两个这样的 intValue,选择较大的 intValue。
    2. 如果 intValue = 0,令 digitString 为 "0";否则令 digitString 为由 intValue 的十进制表示的数字(按顺序且无前导零)组成的 String 值。
    3. 如果 fractionCount ≠ 0,那么
      1. 令 digitCount 为 digitString 的长度。
      2. 如果 digitCount ≤ fractionCount,那么
        1. 令 zeroPad 为由 fractionCount + 1 - digitCount 个码元 0x0030 (DIGIT ZERO) 组成的 String 值。
        2. 将 digitString 设置为 zeroPad 和 digitString 的字符串连接。
        3. 将 digitCount 设置为 fractionCount + 1。
      3. 令 intPart 为 digitString 的前 digitCount - fractionCount 个码元。
      4. 令 fractionalPart 为 digitString 的其余 fractionCount 个码元。
      5. 将 digitString 设置为 intPart、"." 和 fractionalPart 的字符串连接。
  12. 返回 sign 和 digitString 的字符串连接。
注 2

对于某些值,toFixed 的输出可能比 toString 更精确,因为 toString 只打印足以将该数与相邻 Number 值区分开的有效数字。例如,

(1000000000000000128).toString() 返回 "1000000000000000100",而
(1000000000000000128).toFixed(0) 返回 "1000000000000000128"。

21.1.3.4 Number.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] )

包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按照 ECMA-402 中的规定实现此方法。否则,使用此方法的以下规范:

此方法产生一个 String 值,表示根据宿主环境当前区域设置的约定格式化的此 Number 值。此方法是实现定义的,允许但不鼓励它返回与 toString 相同的结果。

此方法可选参数的含义在 ECMA-402 中定义;不包含 ECMA-402 支持的实现不得将这些参数位置用于其他用途。

21.1.3.5 Number.prototype.toPrecision ( precision )

此方法返回一个 String,其中包含以十进制指数记数法表示的此 Number 值,有效数的小数点前有一位数字,小数点后有 precision - 1 位数字;或者以十进制定点记数法表示,具有 precision 位有效数字。如果 precision 是 undefined,则改为调用 ToString。

它被调用时执行以下步骤:

  1. 令 number 为 ? ThisNumberValue(this value)。
  2. 如果 precision 是 undefined,返回 ! ToString(number)。
  3. 令 precisionCount 为 ? ToIntegerOrInfinity(precision)。
  4. 如果 number 不是有限 Number,返回 Number::toString(number, 10)。
  5. 如果 precisionCount 不是整数,抛出 RangeError 异常。
  6. 如果 precisionCount < 1 或 precisionCount > 100,抛出 RangeError 异常。
  7. 将 number 设置为 ℝ(number)。
  8. 令 sign 为空 String。
  9. 如果 number < 0,那么
    1. 将 sign 设置为码元 0x002D (HYPHEN-MINUS)。
    2. 将 number 设置为 -number。
  10. 如果 number = 0,那么
    1. 令 significand 为由 precisionCount 个码元 0x0030 (DIGIT ZERO) 组成的 String 值。
    2. 令 exponent 为 0。
  11. 否则,
    1. 令 exponent 和 intSignificand 为满足 10precisionCount - 1 ≤ intSignificand < 10precisionCount 且使 intSignificand × 10exponent - precisionCount + 1 - number 尽可能接近零的整数。如果有两组这样的 exponent 和 intSignificand,选择使 intSignificand × 10exponent - precisionCount + 1 较大的那组 exponent 和 intSignificand。
    2. 令 significand 为由 intSignificand 的十进制表示的数字(按顺序且无前导零)组成的 String 值。
    3. 如果 exponent < -6 或 exponent ≥ precisionCount,那么
      1. 断言:exponent ≠ 0。
      2. 如果 precisionCount ≠ 1,那么
        1. 令 intPart 为 significand 的第一个码元。
        2. 令 fractionalPart 为 significand 的其余 precisionCount - 1 个码元。
        3. 将 significand 设置为 intPart、"." 和 fractionalPart 的字符串连接。
      3. 如果 exponent > 0,那么
        1. 令 exponentSign 为码元 0x002B (PLUS SIGN)。
      4. 否则,
        1. 断言:exponent < 0。
        2. 令 exponentSign 为码元 0x002D (HYPHEN-MINUS)。
        3. 将 exponent 设置为 -exponent。
      5. 令 exponentDigits 为由 exponent 的十进制表示的数字(按顺序且无前导零)组成的 String 值。
      6. 返回 sign、significand、码元 0x0065 (LATIN SMALL LETTER E)、exponentSign 和 exponentDigits 的字符串连接。
  12. 如果 exponent = precisionCount - 1,返回 sign 和 significand 的字符串连接。
  13. 如果 exponent ≥ 0,那么
    1. 将 significand 设置为 significand 的前 exponent + 1 个码元、码元 0x002E (FULL STOP) 和其余 precisionCount - (exponent + 1) 个码元的字符串连接。
  14. 否则,
    1. 将 significand 设置为码元 0x0030 (DIGIT ZERO)、码元 0x002E (FULL STOP)、-(exponent + 1) 个码元 0x0030 (DIGIT ZERO) 和 String significand 的字符串连接。
  15. 返回 sign 和 significand 的字符串连接。

21.1.3.6 Number.prototype.toString ( [ radix ] )

注

可选的 radix 应当是从 2𝔽 到 36𝔽 的闭区间内的整数 Number 值。如果 radix 是 undefined,则使用 10𝔽 作为 radix 的值。

此方法被调用时执行以下步骤:

  1. 令 x 为 ? ThisNumberValue(this value)。
  2. 如果 radix 是 undefined,令 radixMV 为 10。
  3. 否则,令 radixMV 为 ? SnapToInteger(radix, truncate, 2, 36)。
  4. 返回 Number::toString(x, radixMV)。

此方法不是泛型方法;如果其 this 值不是 Number 或 Number 对象,它会抛出 TypeError 异常。因此,不能将它转移到其他种类的对象上作为方法使用。

此方法的 "length" 属性是 1𝔽。

21.1.3.7 Number.prototype.valueOf ( )

  1. 返回 ? ThisNumberValue(this value)。

21.1.3.7.1 ThisNumberValue ( arg )

抽象操作 ThisNumberValue,接收参数 arg (一个 ECMAScript 语言值,);返回值:包含 Number 的正常完成或抛出完成。 调用时执行以下步骤:

  1. 如果 arg 是 Number,返回 arg。
  2. 如果 arg 是 Object 且 arg 具有 [[NumberData]] 内部槽,那么
    1. 令 number 为 arg.[[NumberData]]。
    2. 断言:number 是 Number。
    3. 返回 number。
  3. 抛出 TypeError 异常。

21.1.4 Number 实例的属性

Number 实例是从 Number 原型对象继承属性的普通对象。Number 实例还具有 [[NumberData]] 内部槽。[[NumberData]] 内部槽是此 Number 对象所表示的 Number 值。

21.2 BigInt 对象

21.2.1 BigInt 构造函数

BigInt 构造函数:

  • 是 %BigInt%。
  • 是全局对象的 "BigInt" 属性的初始值。
  • 作为函数而不是构造函数调用时执行类型转换。
  • 不旨在与 new 运算符一起使用或被子类化。它可以用作类定义的 extends 子句的值,但对 BigInt 构造函数的 super 调用将导致异常。

21.2.1.1 BigInt ( value )

此函数被调用时执行以下步骤:

  1. 如果 NewTarget 不是 undefined,抛出 TypeError 异常。
  2. 令 primitive 为 ? ToPrimitive(value, number)。
  3. 如果 primitive 是 Number,返回 ? NumberToBigInt(primitive)。
  4. 返回 ? ToBigInt(primitive)。

21.2.1.1.1 NumberToBigInt ( number )

抽象操作 NumberToBigInt,接收参数 number (一个 Number,);返回值:包含 BigInt 的正常完成或抛出完成。 调用时执行以下步骤:

  1. 如果 number 不是整数 Number,抛出 RangeError 异常。
  2. 返回 ℤ(ℝ(number))。

21.2.2 BigInt 构造函数的属性

BigInt 构造函数:

21.2.2.1 BigInt.asIntN ( bits, bigint )

此函数被调用时执行以下步骤:

  1. 将 bits 设置为 ? ToIndex(bits)。
  2. 将 bigint 设置为 ? ToBigInt(bigint)。
  3. 令 remainder 为 ℝ(bigint) modulo 2bits。
  4. 如果 remainder ≥ 2bits - 1,返回 ℤ(remainder - 2bits)。
  5. 返回 ℤ(remainder)。

21.2.2.2 BigInt.asUintN ( bits, bigint )

此函数被调用时执行以下步骤:

  1. 将 bits 设置为 ? ToIndex(bits)。
  2. 将 bigint 设置为 ? ToBigInt(bigint)。
  3. 返回 ℤ(ℝ(bigint) modulo 2bits)。

21.2.2.3 BigInt.prototype

BigInt.prototype 的初始值是 BigInt 原型对象。

此属性具有属性特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.2.3 BigInt 原型对象的属性

BigInt 原型对象:

  • 是 %BigInt.prototype%。
  • 是普通对象。
  • 不是 BigInt 对象;它没有 [[BigIntData]] 内部槽。
  • 具有值为 %Object.prototype% 的 [[Prototype]] 内部槽。

在方法规范中,短语“此 BigInt 值”是指以方法调用的 this 值作为实参调用抽象操作 ThisBigIntValue 所返回的结果。

21.2.3.1 BigInt.prototype.constructor

BigInt.prototype.constructor 的初始值是 %BigInt%。

21.2.3.2 BigInt.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] )

包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按照 ECMA-402 中的规定实现此方法。否则,使用此方法的以下规范:

此方法产生一个 String 值,表示根据宿主环境当前区域设置的约定格式化的此 BigInt 值。此方法是实现定义的,允许但不鼓励它返回与 toString 相同的结果。

此方法可选参数的含义在 ECMA-402 中定义;不包含 ECMA-402 支持的实现不得将这些参数位置用于其他用途。

21.2.3.3 BigInt.prototype.toString ( [ radix ] )

注

可选的 radix 应当是从 2𝔽 到 36𝔽 的闭区间内的整数 Number 值。如果 radix 是 undefined,则使用 10𝔽 作为 radix 的值。

此方法被调用时执行以下步骤:

  1. 令 x 为 ? ThisBigIntValue(this value)。
  2. 如果 radix 是 undefined,令 radixMV 为 10。
  3. 否则,令 radixMV 为 ? SnapToInteger(radix, truncate, 2, 36)。
  4. 返回 BigInt::toString(x, radixMV)。

此方法不是泛型方法;如果其 this 值不是 BigInt 或 BigInt 对象,它会抛出 TypeError 异常。因此,不能将它转移到其他种类的对象上作为方法使用。

21.2.3.4 BigInt.prototype.valueOf ( )

  1. 返回 ? ThisBigIntValue(this value)。

21.2.3.4.1 ThisBigIntValue ( arg )

抽象操作 ThisBigIntValue,接收参数 arg (一个 ECMAScript 语言值,);返回值:包含 BigInt 的正常完成或抛出完成。 调用时执行以下步骤:

  1. 如果 arg 是 BigInt,返回 arg。
  2. 如果 arg 是 Object 且 arg 具有 [[BigIntData]] 内部槽,那么
    1. 断言:arg.[[BigIntData]] 是 BigInt。
    2. 返回 arg.[[BigIntData]]。
  3. 抛出 TypeError 异常。

21.2.3.5 BigInt.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "BigInt"。

此属性具有属性特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

21.2.4 BigInt 实例的属性

BigInt 实例是从 BigInt 原型对象继承属性的普通对象。BigInt 实例还具有 [[BigIntData]] 内部槽。[[BigIntData]] 内部槽是此 BigInt 对象所表示的 BigInt 值。

21.3 Math 对象

Math 对象:

注

在本规范中,短语“x 的 Number 值”具有在 6.1.6.1 中定义的技术含义。

21.3.1 Math 对象的值属性

21.3.1.1 Math.E

自然对数底数 e 的 Number 值,约为 2.7182818284590452354。

此属性具有属性特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.3.1.2 Math.LN10

10 的自然对数的 Number 值,约为 2.302585092994046。

此属性具有属性特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.3.1.3 Math.LN2

2 的自然对数的 Number 值,约为 0.6931471805599453。

此属性具有属性特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.3.1.4 Math.LOG10E

自然对数底数 e 的以 10 为底的对数的 Number 值;此值约为 0.4342944819032518。

此属性具有属性特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

注

Math.LOG10E 的值约为 Math.LN10 的值的倒数。

21.3.1.5 Math.LOG2E

自然对数底数 e 的以 2 为底的对数的 Number 值;此值约为 1.4426950408889634。

此属性具有属性特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

注

Math.LOG2E 的值约为 Math.LN2 的值的倒数。

21.3.1.6 Math.PI

π(圆的周长与其直径之比)的 Number 值,约为 3.1415926535897932。

此属性具有属性特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.3.1.7 Math.SQRT1_2

½ 的平方根的 Number 值,约为 0.7071067811865476。

此属性具有属性特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

注

Math.SQRT1_2 的值约为 Math.SQRT2 的值的倒数。

21.3.1.8 Math.SQRT2

2 的平方根的 Number 值,约为 1.4142135623730951。

此属性具有属性特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.3.1.9 Math [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "Math"。

此属性具有属性特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

21.3.2 Math 对象的函数属性

注

这里没有精确定义函数 acos、acosh、asin、asinh、atan、atanh、atan2、cbrt、cos、cosh、exp、expm1、hypot、log、log1p、log2、log10、pow、random、sin、sinh、tan 和 tanh 的行为,只要求它们针对表示所关注边界情况的某些实参值产生特定结果。对于其他实参值,这些函数旨在计算熟悉的数学函数结果的近似值,但允许在近似算法的选择上有一定余地。总体意图是,实现者应当能够在给定硬件平台上为 ECMAScript 使用该平台上 C 程序员可用的同一数学库。

虽然算法的选择留给实现,但建议(本标准并未规定)实现使用 Sun Microsystems 的可自由分发数学库 fdlibm 中包含的 IEEE 754-2019 算术近似算法(http://www.netlib.org/fdlibm)。

21.3.2.1 Math.abs ( x )

此函数返回 x 的绝对值;结果与 x 大小相同,但符号为正。

它被调用时执行以下步骤:

  1. 令 n 为 ? ToNumber(x)。
  2. 如果 n 是 NaN,返回 NaN。
  3. 如果 n 是 -0𝔽,返回 +0𝔽。
  4. 如果 n 是 -∞𝔽,返回 +∞𝔽。
  5. 如果 n < -0𝔽,返回 -n。
  6. 返回 n。

21.3.2.2 Math.acos ( x )

此函数返回 x 的反余弦。结果以弧度表示,并位于从 +0𝔽 到 𝔽(π) 的闭区间内。

它被调用时执行以下步骤:

  1. 令 n 为 ? ToNumber(x)。
  2. 如果 n 是 NaN、n > 1𝔽 或 n < -1𝔽,返回 NaN。
  3. 如果 n 是 1𝔽,返回 +0𝔽。
  4. 返回一个由实现近似得到的 Number 值,该值表示 ℝ(n) 的反余弦。

21.3.2.3 Math.acosh ( x )

此函数返回 x 的反双曲余弦。

它被调用时执行以下步骤:

  1. 令 n 为 ? ToNumber(x)。
  2. 如果 n 是 NaN 或 +∞𝔽,返回 n。
  3. 如果 n 是 1𝔽,返回 +0𝔽。
  4. 如果 n < 1𝔽,返回 NaN。
  5. 返回一个由实现近似得到的 Number 值,该值表示 ℝ(n) 的反双曲余弦。

21.3.2.4 Math.asin ( x )

此函数返回 x 的反正弦。结果以弧度表示,并位于从 𝔽(-π / 2) 到 𝔽(π / 2) 的闭区间内。

它被调用时执行以下步骤:

  1. 令 n 为 ? ToNumber(x)。
  2. 如果 n 是 NaN、+0𝔽 或 -0𝔽 之一,返回 n。
  3. 如果 n > 1𝔽 或 n < -1𝔽,返回 NaN。
  4. 返回一个由实现近似得到的 Number 值,该值表示 ℝ(n) 的反正弦。

21.3.2.5 Math.asinh ( x )

此函数返回 x 的反双曲正弦。

它被调用时执行以下步骤:

  1. 令 n 为 ? ToNumber(x)。
  2. 如果 n 不是有限 Number,或 n 是 +0𝔽 或 -0𝔽,返回 n。
  3. 返回一个由实现近似得到的 Number 值,该值表示 ℝ(n) 的反双曲正弦。

21.3.2.6 Math.atan ( x )

此函数返回 x 的反正切。结果以弧度表示,并位于从 𝔽(-π / 2) 到 𝔽(π / 2) 的闭区间内。

它被调用时执行以下步骤:

  1. 令 n 为 ? ToNumber(x)。
  2. 如果 n 是 NaN、+0𝔽 或 -0𝔽 之一,返回 n。
  3. 如果 n 是 +∞𝔽,返回一个由实现近似得到的 Number 值,该值表示 π / 2。
  4. 如果 n 是 -∞𝔽,返回一个由实现近似得到的 Number 值,该值表示 -π / 2。
  5. 返回一个由实现近似得到的 Number 值,该值表示 ℝ(n) 的反正切。

21.3.2.7 Math.atanh ( x )

此函数返回 x 的反双曲正切。

它被调用时执行以下步骤:

  1. 令 n 为 ? ToNumber(x)。
  2. 如果 n 是 NaN、+0𝔽 或 -0𝔽 之一,返回 n。
  3. 如果 n > 1𝔽 或 n < -1𝔽,返回 NaN。
  4. 如果 n 是 1𝔽,返回 +∞𝔽。
  5. 如果 n 是 -1𝔽,返回 -∞𝔽。
  6. 返回一个由实现近似得到的 Number 值,该值表示 ℝ(n) 的反双曲正切。

21.3.2.8 Math.atan2 ( y, x )

此函数返回实参 y 和 x 的商 y / x 的反正切,其中使用 y 和 x 的符号来确定结果所在的象限。请注意,对于双实参反正切函数,将名为 y 的实参置于第一位而将名为 x 的实参置于第二位是有意且符合传统的。结果以弧度表示,并位于从 -π 到 +π 的闭区间内。

它被调用时执行以下步骤:

  1. 令 ny 为 ? ToNumber(y)。
  2. 令 nx 为 ? ToNumber(x)。
  3. 如果 ny 是 NaN 或 nx 是 NaN,返回 NaN。
  4. 如果 ny 是 +∞𝔽,那么
    1. 如果 nx 是 +∞𝔽,返回一个由实现近似得到的 Number 值,该值表示 π / 4。
    2. 如果 nx 是 -∞𝔽,返回一个由实现近似得到的 Number 值,该值表示 3π / 4。
    3. 返回一个由实现近似得到的 Number 值,该值表示 π / 2。
  5. 如果 ny 是 -∞𝔽,那么
    1. 如果 nx 是 +∞𝔽,返回一个由实现近似得到的 Number 值,该值表示 -π / 4。
    2. 如果 nx 是 -∞𝔽,返回一个由实现近似得到的 Number 值,该值表示 -3π / 4。
    3. 返回一个由实现近似得到的 Number 值,该值表示 -π / 2。
  6. 如果 ny 是 +0𝔽,那么
    1. 如果 nx > +0𝔽 或 nx 是 +0𝔽,返回 +0𝔽。
    2. 返回一个由实现近似得到的 Number 值,该值表示 π。
  7. 如果 ny 是 -0𝔽,那么
    1. 如果 nx > +0𝔽 或 nx 是 +0𝔽,返回 -0𝔽。
    2. 返回一个由实现近似得到的 Number 值,该值表示 -π。
  8. 断言:ny 是有限 Number,且既不是 +0𝔽 也不是 -0𝔽。
  9. 如果 ny > +0𝔽,那么
    1. 如果 nx 是 +∞𝔽,返回 +0𝔽。
    2. 如果 nx 是 -∞𝔽,返回一个由实现近似得到的 Number 值,该值表示 π。
    3. 如果 nx 是 +0𝔽 或 -0𝔽,返回一个由实现近似得到的 Number 值,该值表示 π / 2。
  10. 如果 ny < -0𝔽,那么
    1. 如果 nx 是 +∞𝔽,返回 -0𝔽。
    2. 如果 nx 是 -∞𝔽,返回一个由实现近似得到的 Number 值,该值表示 -π。
    3. 如果 nx 是 +0𝔽 或 -0𝔽,返回一个由实现近似得到的 Number 值,该值表示 -π / 2。
  11. 断言:nx 是有限 Number,且既不是 +0𝔽 也不是 -0𝔽。
  12. 令 result 为 abs(ℝ(ny) / ℝ(nx)) 的反正切。
  13. 如果 nx < -0𝔽,那么
    1. 如果 ny > +0𝔽,将 result 设置为 π - result。
    2. 否则,将 result 设置为 -π + result。
  14. 否则,
    1. 如果 ny < -0𝔽,将 result 设置为 -result。
  15. 返回一个由实现近似得到的 Number 值,该值表示 result。

21.3.2.9 Math.cbrt ( x )

此函数返回 x 的立方根。

它被调用时执行以下步骤:

  1. 令 n 为 ? ToNumber(x)。
  2. 如果 n 不是有限 Number,或 n 是 +0𝔽 或 -0𝔽,返回 n。
  3. 返回一个由实现近似得到的 Number 值,该值表示 ℝ(n) 的立方根。

21.3.2.10 Math.ceil ( x )

此函数返回不小于 x 的最小(最接近 -∞ 的)整数 Number 值。如果 x 已经是整数 Number,则结果为 x。

它被调用时执行以下步骤:

  1. 令 n 为 ? ToNumber(x)。
  2. 如果 n 不是有限 Number,或 n 是 +0𝔽 或 -0𝔽,返回 n。
  3. 如果 n < -0𝔽 且 n > -1𝔽,返回 -0𝔽。
  4. 如果 n 是整数 Number,返回 n。
  5. 返回不小于 n 的最小(最接近 -∞ 的)整数 Number 值。
注

Math.ceil(x) 的值与 -Math.floor(-x) 的值相同。

21.3.2.11 Math.clz32 ( x )

此函数被调用时执行以下步骤:

  1. 令 n 为 ? ToUint32(x)。
  2. 令 p 为 n 的无符号 32 位二进制表示中的前导零位数。
  3. 返回 𝔽(p)。
注

如果 n 是 +0𝔽 或 -0𝔽,此方法返回 32𝔽。如果 n 的 32 位二进制编码的最高有效位是 1,此方法返回 +0𝔽。

21.3.2.12 Math.cos ( x )

此函数返回 x 的余弦。实参以弧度表示。

它被调用时执行以下步骤:

  1. 令 n 为 ? ToNumber(x)。
  2. 如果 n 不是有限 Number,返回 NaN。
  3. 如果 n 是 +0𝔽 或 -0𝔽,返回 1𝔽。
  4. 返回一个由实现近似得到的 Number 值,该值表示 ℝ(n) 的余弦。

21.3.2.13 Math.cosh ( x )

此函数返回 x 的双曲余弦。

它被调用时执行以下步骤:

  1. 令 n 为 ? ToNumber(x)。
  2. 如果 n 是 NaN,返回 NaN。
  3. 如果 n 是 +∞𝔽 或 -∞𝔽,返回 +∞𝔽。
  4. 如果 n 是 +0𝔽 或 -0𝔽,返回 1𝔽。
  5. 返回一个由实现近似得到的 Number 值,该值表示 ℝ(n) 的双曲余弦。
注

Math.cosh(x) 的值与 (Math.exp(x) + Math.exp(-x)) / 2 的值相同。

21.3.2.14 Math.exp ( x )

此函数返回 x 的指数函数(e 的 x 次幂,其中 e 是自然对数的底数)。

它被调用时执行以下步骤:

  1. 令 n 为 ? ToNumber(x)。
  2. 如果 n 是 NaN 或 +∞𝔽,返回 n。
  3. 如果 n 是 +0𝔽 或 -0𝔽,返回 1𝔽。
  4. 如果 n 是 -∞𝔽,返回 +0𝔽。
  5. 返回一个由实现近似得到的 Number 值,该值表示 ℝ(n) 的指数函数。

21.3.2.15 Math.expm1 ( x )

此函数返回从 x 的指数函数(e 的 x 次幂,其中 e 是自然对数的底数)中减去 1 的结果。即使 x 的值接近 0,结果也以保持精确的方式计算。

它被调用时执行以下步骤:

  1. 令 n 为 ? ToNumber(x)。
  2. 如果 n 是 NaN、+0𝔽、-0𝔽 或 +∞𝔽 之一,返回 n。
  3. 如果 n 是 -∞𝔽,返回 -1𝔽。
  4. 令 exp 为 ℝ(n) 的指数函数。
  5. 返回一个由实现近似得到的 Number 值,该值表示 exp - 1。

21.3.2.16 Math.floor ( x )

此函数返回不大于 x 的最大(最接近 +∞ 的)整数 Number 值。如果 x 已经是整数 Number,则结果为 x。

它被调用时执行以下步骤:

  1. 令 n 为 ? ToNumber(x)。
  2. 如果 n 不是有限 Number,或 n 是 +0𝔽 或 -0𝔽,返回 n。
  3. 如果 n < 1𝔽 且 n > +0𝔽,返回 +0𝔽。
  4. 如果 n 是整数 Number,返回 n。
  5. 返回不大于 n 的最大(最接近 +∞ 的)整数 Number 值。
注

Math.floor(x) 的值与 -Math.ceil(-x) 的值相同。

21.3.2.17 Math.fround ( x )

此函数被调用时执行以下步骤:

  1. 令 n 为 ? ToNumber(x)。
  2. 如果 n 是 NaN,返回 NaN。
  3. 如果 n 是 +0𝔽、-0𝔽、+∞𝔽 或 -∞𝔽 之一,返回 n。
  4. 令 n32 为使用 roundTiesToEven 模式将 n 转换为 IEEE 754-2019 binary32 格式的结果。
  5. 令 n64 为将 n32 转换为 IEEE 754-2019 binary64 格式的结果。
  6. 返回与 n64 对应的 ECMAScript Number 值。

21.3.2.18 Math.f16round ( x )

此函数被调用时执行以下步骤:

  1. 令 n 为 ? ToNumber(x)。
  2. 如果 n 是 NaN,返回 NaN。
  3. 如果 n 是 +0𝔽、-0𝔽、+∞𝔽 或 -∞𝔽 之一,返回 n。
  4. 令 n16 为使用 roundTiesToEven 模式将 n 转换为 IEEE 754-2019 binary16 格式的结果。
  5. 令 n64 为将 n16 转换为 IEEE 754-2019 binary64 格式的结果。
  6. 返回与 n64 对应的 ECMAScript Number 值。
注

由于可能发生双重舍入,此操作与先转换为 binary32 再转换为 binary16 并不相同:例如,考虑数 k = 1.00048828125000022204𝔽,对于它,Math.f16round(k) 是 1.0009765625𝔽,但 Math.f16round(Math.fround(k)) 是 1𝔽。

并非所有平台都提供从 binary64 转换为 binary16 的原生支持。有各种库可以提供此功能,包括采用 MIT 许可证的 half 库。另一种方法是,首先在 roundTiesToEven 下从 binary64 转换为 binary32,然后检查结果是否可能导致错误的双重舍入。可以通过调整 binary32 值的尾数来显式处理这些情况,使其成为在 roundTiesToOdd 下执行初始转换时会产生的值。随后在 roundTiesToEven 下将调整后的值转换为 binary16,即可产生正确的值。

21.3.2.19 Math.hypot ( ...args )

给定零个或多个实参,此函数返回其实参平方和的平方根。

它被调用时执行以下步骤:

  1. 令 coerced 为一个新的空 List。
  2. 对 args 的每个元素 arg,执行
    1. 令 n 为 ? ToNumber(arg)。
    2. 将 n 追加到 coerced。
  3. 对 coerced 的每个元素 number,执行
    1. 如果 number 是 +∞𝔽 或 -∞𝔽,返回 +∞𝔽。
  4. 令 onlyZero 为 true。
  5. 对 coerced 的每个元素 number,执行
    1. 如果 number 是 NaN,返回 NaN。
    2. 如果 number 既不是 +0𝔽 也不是 -0𝔽,将 onlyZero 设置为 false。
  6. 如果 onlyZero 是 true,返回 +0𝔽。
  7. 返回一个由实现近似得到的 Number 值,该值表示 coerced 中各元素的数学值的平方和的平方根。

此函数的 "length" 属性是 2𝔽。

注

当使用两个或更多实参调用此函数时,实现应当注意避免朴素实现中容易发生的上溢和下溢所导致的精度损失。

21.3.2.20 Math.imul ( x, y )

此函数被调用时执行以下步骤:

  1. 令 a 为 ℝ(? ToUint32(x))。
  2. 令 b 为 ℝ(? ToUint32(y))。
  3. 令 product 为 (a × b) modulo 232。
  4. 如果 product ≥ 231,返回 𝔽(product - 232)。
  5. 返回 𝔽(product)。

21.3.2.21 Math.log ( x )

此函数返回 x 的自然对数。

它被调用时执行以下步骤:

  1. 令 n 为 ? ToNumber(x)。
  2. 如果 n 是 NaN 或 +∞𝔽,返回 n。
  3. 如果 n 是 1𝔽,返回 +0𝔽。
  4. 如果 n 是 +0𝔽 或 -0𝔽,返回 -∞𝔽。
  5. 如果 n < -0𝔽,返回 NaN。
  6. 返回一个由实现近似得到的 Number 值,该值表示 ln(ℝ(n))。

21.3.2.22 Math.log1p ( x )

此函数返回 1 + x 的自然对数。即使 x 的值接近零,结果也以保持精确的方式计算。

它被调用时执行以下步骤:

  1. 令 n 为 ? ToNumber(x)。
  2. 如果 n 是 NaN、+0𝔽、-0𝔽 或 +∞𝔽 之一,返回 n。
  3. 如果 n 是 -1𝔽,返回 -∞𝔽。
  4. 如果 n < -1𝔽,返回 NaN。
  5. 返回一个由实现近似得到的 Number 值,该值表示 ln(1 + ℝ(n))。

21.3.2.23 Math.log10 ( x )

此函数返回 x 的以 10 为底的对数。

它被调用时执行以下步骤:

  1. 令 n 为 ? ToNumber(x)。
  2. 如果 n 是 NaN 或 +∞𝔽,返回 n。
  3. 如果 n 是 1𝔽,返回 +0𝔽。
  4. 如果 n 是 +0𝔽 或 -0𝔽,返回 -∞𝔽。
  5. 如果 n < -0𝔽,返回 NaN。
  6. 返回一个由实现近似得到的 Number 值,该值表示 log10(ℝ(n))。

21.3.2.24 Math.log2 ( x )

此函数返回 x 的以 2 为底的对数。

它被调用时执行以下步骤:

  1. 令 n 为 ? ToNumber(x)。
  2. 如果 n 是 NaN 或 +∞𝔽,返回 n。
  3. 如果 n 是 1𝔽,返回 +0𝔽。
  4. 如果 n 是 +0𝔽 或 -0𝔽,返回 -∞𝔽。
  5. 如果 n < -0𝔽,返回 NaN。
  6. 返回一个由实现近似得到的 Number 值,该值表示 log2(ℝ(n))。

21.3.2.25 Math.max ( ...args )

给定零个或多个实参,此函数对每个实参调用 ToNumber,并返回所得值中的最大值。

它被调用时执行以下步骤:

  1. 令 coerced 为一个新的空 List。
  2. 对 args 的每个元素 arg,执行
    1. 令 n 为 ? ToNumber(arg)。
    2. 将 n 追加到 coerced。
  3. 令 highest 为 -∞𝔽。
  4. 对 coerced 的每个元素 number,执行
    1. 如果 number 是 NaN,返回 NaN。
    2. 如果 number 是 +0𝔽 且 highest 是 -0𝔽,将 highest 设置为 +0𝔽。
    3. 如果 number > highest,将 highest 设置为 number。
  5. 返回 highest。
注

用于确定最大值的值比较使用 IsLessThan 算法完成,但 +0𝔽 被视为大于 -0𝔽。

此函数的 "length" 属性是 2𝔽。

21.3.2.26 Math.min ( ...args )

给定零个或多个实参,此函数对每个实参调用 ToNumber,并返回所得值中的最小值。

它被调用时执行以下步骤:

  1. 令 coerced 为一个新的空 List。
  2. 对 args 的每个元素 arg,执行
    1. 令 n 为 ? ToNumber(arg)。
    2. 将 n 追加到 coerced。
  3. 令 lowest 为 +∞𝔽。
  4. 对 coerced 的每个元素 number,执行
    1. 如果 number 是 NaN,返回 NaN。
    2. 如果 number 是 -0𝔽 且 lowest 是 +0𝔽,将 lowest 设置为 -0𝔽。
    3. 如果 number < lowest,将 lowest 设置为 number。
  5. 返回 lowest。
注

用于确定最小值的值比较使用 IsLessThan 算法完成,但 +0𝔽 被视为大于 -0𝔽。

此函数的 "length" 属性是 2𝔽。

21.3.2.27 Math.pow ( base, exponent )

此函数被调用时执行以下步骤:

  1. 将 base 设置为 ? ToNumber(base)。
  2. 将 exponent 设置为 ? ToNumber(exponent)。
  3. 返回 Number::exponentiate(base, exponent)。

21.3.2.28 Math.random ( )

此函数返回一个正号 Number 值,该值大于或等于 +0𝔽 但严格小于 1𝔽,使用实现定义的算法或策略,以在该范围内近似均匀分布的方式随机或伪随机地选取。

为不同 realm 创建的每个 Math.random 函数,必须从连续调用中产生不同的值序列。

21.3.2.29 Math.round ( x )

此函数返回最接近 x 且为整数的 Number 值。如果两个整数 Number 与 x 同样接近,则结果为更接近 +∞ 的 Number 值。如果 x 已经是整数,则结果为 x。

它被调用时执行以下步骤:

  1. 令 n 为 ? ToNumber(x)。
  2. 如果 n 不是有限 Number 或 n 是整数 Number,返回 n。
  3. 如果 n < 0.5𝔽 且 n > +0𝔽,返回 +0𝔽。
  4. 如果 n < -0𝔽 且 n ≥ -0.5𝔽,返回 -0𝔽。
  5. 返回最接近 n 的整数 Number;如果出现平局,则优先选择更接近 +∞ 的 Number。
注 1

Math.round(3.5) 返回 4,但 Math.round(-3.5) 返回 -3。

注 2

Math.round(x) 的值并不总是与 Math.floor(x + 0.5) 的值相同。当 x 是 -0𝔽,或 x 小于 -0𝔽 但大于或等于 -0.5𝔽 时,Math.round(x) 返回 -0𝔽,而 Math.floor(x + 0.5) 返回 +0𝔽。由于计算 x + 0.5 时发生的内部舍入,Math.round(x) 也可能与 Math.floor(x + 0.5) 的值不同。

21.3.2.30 Math.sign ( x )

此函数返回 x 的符号,指示 x 是正数、负数还是零。

它被调用时执行以下步骤:

  1. 令 n 为 ? ToNumber(x)。
  2. 如果 n 是 NaN、+0𝔽 或 -0𝔽 之一,返回 n。
  3. 如果 n < -0𝔽,返回 -1𝔽。
  4. 返回 1𝔽。

21.3.2.31 Math.sin ( x )

此函数返回 x 的正弦。实参以弧度表示。

它被调用时执行以下步骤:

  1. 令 n 为 ? ToNumber(x)。
  2. 如果 n 是 NaN、+0𝔽 或 -0𝔽 之一,返回 n。
  3. 如果 n 是 +∞𝔽 或 -∞𝔽,返回 NaN。
  4. 返回一个由实现近似得到的 Number 值,该值表示 ℝ(n) 的正弦。

21.3.2.32 Math.sinh ( x )

此函数返回 x 的双曲正弦。

它被调用时执行以下步骤:

  1. 令 n 为 ? ToNumber(x)。
  2. 如果 n 不是有限 Number,或 n 是 +0𝔽 或 -0𝔽,返回 n。
  3. 返回一个由实现近似得到的 Number 值,该值表示 ℝ(n) 的双曲正弦。
注

Math.sinh(x) 的值与 (Math.exp(x) - Math.exp(-x)) / 2 的值相同。

21.3.2.33 Math.sqrt ( x )

此函数返回 x 的平方根。

它被调用时执行以下步骤:

  1. 令 n 为 ? ToNumber(x)。
  2. 如果 n 是 NaN、+0𝔽、-0𝔽 或 +∞𝔽 之一,返回 n。
  3. 如果 n < -0𝔽,返回 NaN。
  4. 返回 𝔽(ℝ(n) 的平方根)。

21.3.2.34 Math.sumPrecise ( items )

给定一个 Number 的可迭代对象,此函数对可迭代对象中的每个值求和并返回它们的和。如果任何值不是 Number,则抛出 TypeError 异常。

它被调用时执行以下步骤:

  1. 执行 ? RequireObjectCoercible(items)。
  2. 令 iteratorRecord 为 ? GetIterator(items, sync)。
  3. 令 state 为 minus-zero。
  4. 令 sum 为 0。
  5. 令 count 为 0。
  6. 令 next 为 not-started。
  7. 重复,只要 next 不是 done,
    1. 将 next 设置为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 next 不是 done,那么
      1. 如果 count ≥ 253 - 1,那么
        1. NOTE:在实践中预计不会到达此步骤,包含此步骤仅是为了使实现可以依赖输入“具有合理大小”而不违反本规范。
        2. 令 error 为 ThrowCompletion(一个新创建的 RangeError 对象)。
        3. 返回 ? IteratorClose(iteratorRecord, error)。
      2. 如果 next 不是 Number,那么
        1. 令 error 为 ThrowCompletion(一个新创建的 TypeError 对象)。
        2. 返回 ? IteratorClose(iteratorRecord, error)。
      3. 令 n 为 next。
      4. 如果 state 不是 not-a-number,那么
        1. 如果 n 是 NaN,那么
          1. 将 state 设置为 not-a-number。
        2. 否则,如果 n 是 +∞𝔽,那么
          1. 如果 state 是 minus-infinity,将 state 设置为 not-a-number。
          2. 否则,将 state 设置为 plus-infinity。
        3. 否则,如果 n 是 -∞𝔽,那么
          1. 如果 state 是 plus-infinity,将 state 设置为 not-a-number。
          2. 否则,将 state 设置为 minus-infinity。
        4. 否则,如果 n 不是 -0𝔽 且 state 是 minus-zero 或 finite,那么
          1. 将 state 设置为 finite。
          2. 将 sum 设置为 sum + ℝ(n)。
      5. 将 count 设置为 count + 1。
  8. 如果 state 是 not-a-number,返回 NaN。
  9. 如果 state 是 plus-infinity,返回 +∞𝔽。
  10. 如果 state 是 minus-infinity,返回 -∞𝔽。
  11. 如果 state 是 minus-zero,返回 -0𝔽。
  12. 返回 𝔽(sum)。
注

可以通过多种算法在不使用任意精度算术的情况下计算 sum 的值。其中一种是 Jonathan Richard Shewchuk 在 Adaptive Precision Floating-Point Arithmetic and Fast Robust Geometric Predicates 中给出的“Grow-Expansion”算法。更新的一种算法在“使用小型和大型超级累加器进行快速精确求和”中给出,其代码可在 https://gitlab.com/radfordneal/xsum 获取。

21.3.2.35 Math.tan ( x )

此函数返回 x 的正切。实参以弧度表示。

它被调用时执行以下步骤:

  1. 令 n 为 ? ToNumber(x)。
  2. 如果 n 是 NaN、+0𝔽 或 -0𝔽 之一,返回 n。
  3. 如果 n 是 +∞𝔽 或 -∞𝔽,返回 NaN。
  4. 返回一个由实现近似得到的 Number 值,该值表示 ℝ(n) 的正切。

21.3.2.36 Math.tanh ( x )

此函数返回 x 的双曲正切。

它被调用时执行以下步骤:

  1. 令 n 为 ? ToNumber(x)。
  2. 如果 n 是 NaN、+0𝔽 或 -0𝔽 之一,返回 n。
  3. 如果 n 是 +∞𝔽,返回 1𝔽。
  4. 如果 n 是 -∞𝔽,返回 -1𝔽。
  5. 返回一个由实现近似得到的 Number 值,该值表示 ℝ(n) 的双曲正切。
注

Math.tanh(x) 的值与 (Math.exp(x) - Math.exp(-x)) / (Math.exp(x) + Math.exp(-x)) 的值相同。

21.3.2.37 Math.trunc ( x )

此函数返回数 x 的整数部分,移除所有小数位。如果 x 已经是整数,则结果为 x。

它被调用时执行以下步骤:

  1. 令 n 为 ? ToNumber(x)。
  2. 如果 n 不是有限 Number,或 n 是 +0𝔽 或 -0𝔽,返回 n。
  3. 如果 n < 1𝔽 且 n > +0𝔽,返回 +0𝔽。
  4. 如果 n < -0𝔽 且 n > -1𝔽,返回 -0𝔽。
  5. 返回沿 +0𝔽 方向最接近 n 的整数 Number。

21.4 Date 对象

21.4.1 Date 对象概述和抽象操作定义

以下抽象操作对时间值(定义于 21.4.1.1)进行操作。注意,在任何情况下,如果这些函数的任一参数是 NaN,则结果都会是 NaN。

21.4.1.1 时间值和时间范围

ECMAScript 中的时间测量类似于 POSIX 中的时间测量,尤其是都以外推格里高利历为基础进行定义,以 1970 年 1 月 1 日 UTC 零时为纪元,并将每一天精确计为 86,400 秒(每秒为 1000 毫秒)。

ECMAScript 时间值是一个 Number,它要么是表示精确到毫秒的某个时刻的整数 Number(称为有限时间值),要么是表示没有特定时刻的 NaN。作为 MillisecondsPerDay 整数倍的有限时间值(即对于某个整数 d,其值为 MillisecondsPerDay × d)表示这样一个时刻:从纪元起经过 d 个完整 UTC 日后(当 d 为负数时则在纪元之前)的 UTC 日开始时刻。其他每个有限时间值 tv 都相对于其之前满足这种倍数关系的最大有限时间值 s 来定义,并表示与 s 位于同一 UTC 日内、但比它晚 (tv - s) 毫秒的时刻。

时间值不考虑 UTC 闰秒——没有表示正闰秒期间时刻的时间值,而被负闰秒从 UTC 时间线中移除的时刻仍有相应时间值。不过,时间值的定义仍会与 UTC 分段对齐,只有在闰秒边界处存在不连续,并且在闰秒之外差值为零。

Number 可以精确表示从 -9,007,199,254,740,992 到 9,007,199,254,740,992 的所有整数(21.1.2.8 和 21.1.2.6)。时间值支持稍小的范围,即 -8,640,000,000,000,000 到 8,640,000,000,000,000 毫秒。这使得相对于 1970 年 1 月 1 日 UTC 零时,支持的时间值范围恰好为 -100,000,000 天到 100,000,000 天。

1970 年 1 月 1 日 UTC 零时这一精确时刻由时间值 +0𝔽 表示。

注

在外推格里高利历中,闰年恰好是能被 4 整除,并且要么能被 400 整除、要么不能被 100 整除的年份。

外推格里高利历的 400 年周期包含 97 个闰年。这得到平均每年 365.2425 天,即 31,556,952,000 毫秒。因此,Number 能够以毫秒精度精确表示的最大范围,相对于 1970 年约为 -285,426 年到 285,426 年。本节规定的时间值支持的较小范围,相对于 1970 年约为 -273,790 年到 273,790 年。

21.4.1.2 时间相关常量

以下各节中的算法会引用这些常量。

HoursPerDay = 24
MinutesPerHour = 60
SecondsPerMinute = 60
MillisecondsPerSecond = 1000
MillisecondsPerMinute = 60000 = MillisecondsPerSecond × SecondsPerMinute
MillisecondsPerHour = 3600000 = MillisecondsPerMinute × MinutesPerHour
MillisecondsPerDay = 86400000 = MillisecondsPerHour × HoursPerDay
NanosecondsPerDay = 106 × MillisecondsPerDay = 8.64 × 1013
NanosecondsPerSecond = 106 × MillisecondsPerSecond = 109
NanosecondsPerMillisecond = 106
NanosecondsPerMicrosecond = 103
MaxEpochNanoseconds = 108 × NanosecondsPerDay = 8.64 × 1021
MinEpochNanoseconds = -MaxEpochNanoseconds = -8.64 × 1021

21.4.1.3 Day ( tv )

抽象操作 Day,接收参数 tv (a finite time value);返回值:整数。 它返回 tv 所在日期的日编号。 调用时执行以下步骤:

  1. 返回 floor(ℝ(tv) / MillisecondsPerDay)。

21.4.1.4 TimeWithinDay ( tv )

抽象操作 TimeWithinDay,接收参数 tv (a finite time value);返回值:an integer in the interval from 0 (inclusive) to MillisecondsPerDay (exclusive)。 它返回自 tv 所在日期开始以来经过的毫秒数。 调用时执行以下步骤:

  1. 返回 ℝ(tv) modulo MillisecondsPerDay。

21.4.1.5 DayFromYear ( y )

抽象操作 DayFromYear,接收参数 y (整数);返回值:整数。 它返回年份 y 第一天的日编号。 调用时执行以下步骤:

  1. 注:在以下步骤中,numberYears1、numberYears4、numberYears100 和 numberYears400 分别表示在纪元与年份 y 开始之间出现的可被 1、4、100 和 400 整除的年份数量。如果 y 位于纪元之前,则该数量为负。
  2. 令 numberYears1 为 (y - 1970)。
  3. 令 numberYears4 为 floor((y - 1969) / 4)。
  4. 令 numberYears100 为 floor((y - 1901) / 100)。
  5. 令 numberYears400 为 floor((y - 1601) / 400)。
  6. 返回 365 × numberYears1 + numberYears4 - numberYears100 + numberYears400。

21.4.1.6 TimeFromYear ( y )

抽象操作 TimeFromYear,接收参数 y (整数);返回值:a time value。 它返回年份 y 开始时的时间值。 调用时执行以下步骤:

  1. 返回 𝔽(MillisecondsPerDay × DayFromYear(y))。

21.4.1.7 YearFromTime ( tv )

抽象操作 YearFromTime,接收参数 tv (a finite time value);返回值:整数。 它返回 tv 所在的年份。 调用时执行以下步骤:

  1. 返回满足 TimeFromYear(y) ≤ tv 的最大整数 y(最接近 +∞)。

21.4.1.8 DayWithinYear ( tv )

抽象操作 DayWithinYear,接收参数 tv (a finite time value);返回值:an integer in the inclusive interval from 0 to 365。 调用时执行以下步骤:

  1. 返回 Day(tv) - DayFromYear(YearFromTime(tv))。

21.4.1.9 InLeapYear ( tv )

抽象操作 InLeapYear,接收参数 tv (a finite time value);返回值:(0 或 1)。 如果 tv 位于闰年中,则返回 1,否则返回 0。 调用时执行以下步骤:

  1. 令 y 为 YearFromTime(tv)。
  2. 如果 (y modulo 400) = 0,则返回 1。
  3. 如果 (y modulo 100) = 0,则返回 0。
  4. 如果 (y modulo 4) = 0,则返回 1。
  5. 返回 0。

21.4.1.10 MonthFromTime ( tv )

抽象操作 MonthFromTime,接收参数 tv (a finite time value);返回值:an integer in the inclusive interval from 0 to 11。 它返回一个整数,用于标识 tv 所在的月份。月份值 0 表示一月;1 表示二月;2 表示三月;3 表示四月;4 表示五月;5 表示六月;6 表示七月;7 表示八月;8 表示九月;9 表示十月;10 表示十一月;11 表示十二月。注意,MonthFromTime(+0𝔽) = 0,对应 1970 年 1 月 1 日星期四。 调用时执行以下步骤:

  1. 令 inLeapYear 为 InLeapYear(tv)。
  2. 令 dayWithinYear 为 DayWithinYear(tv)。
  3. 如果 dayWithinYear < 31,则返回 0。
  4. 如果 dayWithinYear < 59 + inLeapYear,则返回 1。
  5. 如果 dayWithinYear < 90 + inLeapYear,则返回 2。
  6. 如果 dayWithinYear < 120 + inLeapYear,则返回 3。
  7. 如果 dayWithinYear < 151 + inLeapYear,则返回 4。
  8. 如果 dayWithinYear < 181 + inLeapYear,则返回 5。
  9. 如果 dayWithinYear < 212 + inLeapYear,则返回 6。
  10. 如果 dayWithinYear < 243 + inLeapYear,则返回 7。
  11. 如果 dayWithinYear < 273 + inLeapYear,则返回 8。
  12. 如果 dayWithinYear < 304 + inLeapYear,则返回 9。
  13. 如果 dayWithinYear < 334 + inLeapYear,则返回 10。
  14. 断言:dayWithinYear < 365 + inLeapYear。
  15. 返回 11。

21.4.1.11 DateFromTime ( tv )

抽象操作 DateFromTime,接收参数 tv (a finite time value);返回值:an integer in the inclusive interval from 1 to 31。 它返回 tv 所在月份中的日期。 调用时执行以下步骤:

  1. 令 inLeapYear 为 InLeapYear(tv)。
  2. 令 dayWithinYear 为 DayWithinYear(tv)。
  3. 令 month 为 MonthFromTime(tv)。
  4. 如果 month = 0,则返回 dayWithinYear + 1。
  5. 如果 month = 1,则返回 dayWithinYear - 30。
  6. 如果 month = 2,则返回 dayWithinYear - 58 - inLeapYear。
  7. 如果 month = 3,则返回 dayWithinYear - 89 - inLeapYear。
  8. 如果 month = 4,则返回 dayWithinYear - 119 - inLeapYear。
  9. 如果 month = 5,则返回 dayWithinYear - 150 - inLeapYear。
  10. 如果 month = 6,则返回 dayWithinYear - 180 - inLeapYear。
  11. 如果 month = 7,则返回 dayWithinYear - 211 - inLeapYear。
  12. 如果 month = 8,则返回 dayWithinYear - 242 - inLeapYear。
  13. 如果 month = 9,则返回 dayWithinYear - 272 - inLeapYear。
  14. 如果 month = 10,则返回 dayWithinYear - 303 - inLeapYear。
  15. 断言:month = 11。
  16. 返回 dayWithinYear - 333 - inLeapYear。

21.4.1.12 WeekDay ( tv )

抽象操作 WeekDay,接收参数 tv (a finite time value);返回值:an integer in the inclusive interval from 0 to 6。 它返回一个整数,用于标识 tv 所在的是一周中的哪一天。星期值 0 表示星期日;1 表示星期一;2 表示星期二;3 表示星期三;4 表示星期四;5 表示星期五;6 表示星期六。注意,WeekDay(+0𝔽) = 4,对应 1970 年 1 月 1 日星期四。 调用时执行以下步骤:

  1. 返回 (Day(tv) + 4) modulo 7。

21.4.1.13 HourFromTime ( tv )

抽象操作 HourFromTime,接收参数 tv (a finite time value);返回值:an integer in the inclusive interval from 0 to 23。 它返回 tv 所在一天中的小时。 调用时执行以下步骤:

  1. 返回 floor(ℝ(tv) / MillisecondsPerHour) modulo HoursPerDay。

21.4.1.14 MinuteFromTime ( tv )

抽象操作 MinuteFromTime,接收参数 tv (a finite time value);返回值:an integer in the inclusive interval from 0 to 59。 它返回 tv 所在小时中的分钟。 调用时执行以下步骤:

  1. 返回 floor(ℝ(tv) / MillisecondsPerMinute) modulo MinutesPerHour。

21.4.1.15 SecondFromTime ( tv )

抽象操作 SecondFromTime,接收参数 tv (a finite time value);返回值:an integer in the inclusive interval from 0 to 59。 它返回 tv 所在分钟中的秒。 调用时执行以下步骤:

  1. 返回 floor(ℝ(tv) / MillisecondsPerSecond) modulo SecondsPerMinute。

21.4.1.16 MillisecondFromTime ( tv )

抽象操作 MillisecondFromTime,接收参数 tv (a finite time value);返回值:an integer in the inclusive interval from 0 to 999。 它返回 tv 所在秒中的毫秒。 调用时执行以下步骤:

  1. 返回 ℝ(tv) modulo MillisecondsPerSecond。

21.4.1.17 纪元纳秒和范围

纪元纳秒计数是表示具有纳秒精度时间瞬间的整数。它支持与时间值相同的范围,但以纳秒表示,从 MinEpochNanoseconds 到 MaxEpochNanoseconds。不存在与时间值 NaN 等价的纳秒表示;没有用于表示无特定时间瞬间的表示。

1970 年 1 月 1 日 UTC 零时这一精确时刻由值 0 表示。最大值是 MaxEpochNanoseconds,最小值是 MinEpochNanoseconds。

21.4.1.18 GetUTCEpochNanoseconds ( year, month, day, hour, minute, second, millisecond, microsecond, nanosecond )

抽象操作 GetUTCEpochNanoseconds,接收参数 year (整数)、month (an integer in the inclusive interval from 1 to 12)、day (an integer in the inclusive interval from 1 to 31)、hour (an integer in the inclusive interval from 0 to 23)、minute (an integer in the inclusive interval from 0 to 59)、second (an integer in the inclusive interval from 0 to 59)、millisecond (an integer in the inclusive interval from 0 to 999)、microsecond (an integer in the inclusive interval from 0 to 999) 和 nanosecond (an integer in the inclusive interval from 0 to 999);返回值:an epoch nanoseconds count。 返回值是与给定 UTC 中的 ISO 8601 日历日期和墙上时钟时间相对应的纪元纳秒计数。 调用时执行以下步骤:

  1. 令 date 为 MakeDay(𝔽(year), 𝔽(month - 1), 𝔽(day))。
  2. 令 time 为 MakeTime(𝔽(hour), 𝔽(minute), 𝔽(second), 𝔽(millisecond))。
  3. 令 epochMilliseconds 为 MakeDate(date, time)。
  4. 断言:epochMilliseconds 是整数 Number。
  5. 返回 ℝ(epochMilliseconds) × NanosecondsPerMillisecond + microsecond × NanosecondsPerMicrosecond + nanosecond。

21.4.1.19 时区标识符

ECMAScript 中的时区由时区标识符表示,它们是完全由从 0x0000 到 0x007F 闭区间中的码元组成的 String。 ECMAScript 实现支持的时区可以是可用命名时区,由 AvailableNamedTimeZoneIdentifiers 返回的 Time Zone Identifier Record 的 [[Identifier]] 字段表示;也可以是偏移时区,由使 IsTimeZoneOffsetString 返回 true 的 String 表示。

主时区标识符是可用命名时区的首选标识符。 非主时区标识符是可用命名时区的标识符,但不是主时区标识符。 可用命名时区标识符要么是主时区标识符,要么是非主时区标识符。 每个可用命名时区标识符都恰好与一个可用命名时区关联。 每个可用命名时区都恰好与一个主时区标识符以及零个或多个非主时区标识符关联。

ECMAScript 实现必须支持标识符为 "UTC" 的可用命名时区,该标识符必须是 UTC 时区的主时区标识符。 此外,实现可以支持任意数量的其他可用命名时区。

遵循 ECMA-402 国际化 API 规范中所述时区要求的实现称为时区感知实现。 时区感知实现必须支持与 IANA 时区数据库中的“Zone”和“Link”名称对应的可用命名时区,并且只能支持这些名称。 在时区感知实现中,除 ECMA-402 中规定的 AvailableNamedTimeZoneIdentifiers 明确覆盖的情况外,主时区标识符和非主时区标识符分别是 IANA 时区数据库中的“Zone”名称和“Link”名称。 不支持完整 IANA 时区数据库的实现仍建议使用 IANA 时区数据库名称作为表示时区的标识符。

21.4.1.20 GetNamedTimeZoneEpochNanoseconds ( timeZoneIdentifier, year, month, day, hour, minute, second, millisecond, microsecond, nanosecond )

实现定义的抽象操作 GetNamedTimeZoneEpochNanoseconds,接收参数 timeZoneIdentifier (String)、year (整数)、month (an integer in the inclusive interval from 1 to 12)、day (an integer in the inclusive interval from 1 to 31)、hour (an integer in the inclusive interval from 0 to 23)、minute (an integer in the inclusive interval from 0 to 59)、second (an integer in the inclusive interval from 0 to 59)、millisecond (an integer in the inclusive interval from 0 to 999)、microsecond (an integer in the inclusive interval from 0 to 999) 和 nanosecond (an integer in the inclusive interval from 0 to 999);返回值:列表 (元素:epoch nanoseconds counts)。 返回 List 中的每个值都表示一个纪元纳秒计数,该计数与由 timeZoneIdentifier 标识的命名时区中的给定 ISO 8601 日历日期和墙上时钟时间相对应。

当输入表示因负向时区转换而出现多次的本地时间时(例如夏令时结束,或因时区规则变更而减小时区偏移),返回的 List 将包含多个元素,并按数值升序排序。 当输入表示因正向时区转换而被跳过的本地时间时(例如夏令时开始,或因时区规则变更而增大时区偏移),返回的 List 将为空。 否则,返回的 List 将包含一个元素。

用于不包含任何时区本地政治规则的 ECMAScript 实现的 GetNamedTimeZoneEpochNanoseconds 默认实现,在调用时执行以下步骤:

  1. 断言:timeZoneIdentifier 是 "UTC"。
  2. 令 epochNanoseconds 为 GetUTCEpochNanoseconds(year, month, day, hour, minute, second, millisecond, microsecond, nanosecond)。
  3. 返回 « epochNanoseconds »。
注

要求时区感知实现(并建议所有其他实现)使用 IANA 时区数据库中的时区信息。

America/New_York 中 2017 年 11 月 5 日凌晨 1:30 会重复两次,因此 GetNamedTimeZoneEpochNanoseconds("America/New_York", 2017, 11, 5, 1, 30, 0, 0, 0, 0) 将返回长度为 2 的 List,其中第一个元素表示 UTC 05:30(对应 UTC 偏移 -04:00 的美国东部夏令时间 01:30),第二个元素表示 UTC 06:30(对应 UTC 偏移 -05:00 的美国东部标准时间 01:30)。

America/New_York 中 2017 年 3 月 12 日凌晨 2:30 不存在,因此 GetNamedTimeZoneEpochNanoseconds("America/New_York", 2017, 3, 12, 2, 30, 0, 0, 0, 0) 将返回空 List。

21.4.1.21 GetNamedTimeZoneOffsetNanoseconds ( timeZoneIdentifier, epochNanoseconds )

实现定义的抽象操作 GetNamedTimeZoneOffsetNanoseconds,接收参数 timeZoneIdentifier (String) 和 epochNanoseconds (an epoch nanoseconds count);返回值:整数。

返回的整数表示由 timeZoneIdentifier 标识的命名时区,在与纪元纳秒计数 epochNanoseconds 对应的时刻相对于 UTC 的偏移,以纳秒为单位。

用于不包含任何时区本地政治规则的 ECMAScript 实现的 GetNamedTimeZoneOffsetNanoseconds 默认实现,在调用时执行以下步骤:

  1. 断言:timeZoneIdentifier 是 "UTC"。
  2. 返回 0。
注

时区偏移值可以为正或为负。

21.4.1.22 Time Zone Identifier Record

Time Zone Identifier Record 是用于描述可用命名时区标识符及其对应主时区标识符的 Record。

Time Zone Identifier Record 具有 表 60 中列出的字段。

表 60: Time Zone Identifier Record 字段
字段名称 值 含义
[[Identifier]] a String 实现支持的可用命名时区标识符。
[[PrimaryIdentifier]] a String [[Identifier]] 解析到的主时区标识符。
注

如果 [[Identifier]] 是主时区标识符,则 [[Identifier]] 就是 [[PrimaryIdentifier]]。

21.4.1.23 AvailableNamedTimeZoneIdentifiers ( )

实现定义的抽象操作 AvailableNamedTimeZoneIdentifiers,接收无参数;返回值:列表 (元素:Time Zone Identifier 记录)。 其结果描述此实现中的所有可用命名时区标识符,以及与每个可用命名时区标识符对应的主时区标识符。 该 List 按每个 Time Zone Identifier Record 的 [[Identifier]] 字段排序。

时区感知实现(包括所有实现 ECMA-402 国际化 API 的实现)必须按照 ECMA-402 的规定实现 AvailableNamedTimeZoneIdentifiers 抽象操作。 否则,AvailableNamedTimeZoneIdentifiers 在调用时执行以下步骤:

  1. 如果实现不包含任何时区的本地政治规则,则
    1. 返回 « Time Zone Identifier Record { [[Identifier]]: "UTC", [[PrimaryIdentifier]]: "UTC" } »。
  2. 令 identifiers 为唯一可用命名时区标识符的 List,按字典序码元顺序排序。
  3. 令 result 为新的空 List。
  4. 对 identifiers 的每个元素 identifier,执行
    1. 令 primary 为 identifier。
    2. 如果 identifier 是此实现中的非主时区标识符且 identifier 不是 "UTC",则
      1. 将 primary 设置为与 identifier 关联的主时区标识符。
      2. 注:实现可能需要迭代解析 identifier,以获得主时区标识符。
    3. 令 record 为 Time Zone Identifier Record { [[Identifier]]: identifier, [[PrimaryIdentifier]]: primary }。
    4. 将 record 追加到 result。
  5. 断言:result 包含一个 Time Zone Identifier Record record,使得 record.[[Identifier]] 是 "UTC" 且 record.[[PrimaryIdentifier]] 是 "UTC"。
  6. 返回 result。

21.4.1.24 SystemTimeZoneIdentifier ( )

实现定义的抽象操作 SystemTimeZoneIdentifier,接收无参数;返回值:String。 它返回表示宿主环境当前时区的 String,该 String 要么表示一个使 IsTimeZoneOffsetString 返回 true 的 UTC 偏移,要么是主时区标识符。 调用时执行以下步骤:

  1. 如果实现仅支持 UTC 时区,则返回 "UTC"。
  2. 令 systemTimeZoneString 为表示宿主环境当前时区的 String,它要么是主时区标识符,要么是偏移时区标识符。
  3. 返回 systemTimeZoneString。
注

为确保实现通常在 Date 对象方法中提供的功能级别,如果存在与宿主环境时区设置对应的 IANA 时区名称,建议 SystemTimeZoneIdentifier 返回该名称。 如果该时区存在标准时间和夏令时的本地政治规则,则 GetNamedTimeZoneEpochNanoseconds 和 GetNamedTimeZoneOffsetNanoseconds 必须反映这些规则。

例如,如果宿主环境是在用户选择美国东部时间作为时区的系统上运行的浏览器,则 SystemTimeZoneIdentifier 返回 "America/New_York"。

21.4.1.25 LocalTime ( tv )

抽象操作 LocalTime,接收参数 tv (a finite time value);返回值:整数 Number。 它将 tv 从 UTC 转换为本地时间。 应按照本节规定的方式,使用在 tv 时有效的标准时间和夏令时本地政治规则来确定结果。 调用时执行以下步骤:

  1. 令 systemTimeZoneIdentifier 为 SystemTimeZoneIdentifier()。
  2. 如果 IsTimeZoneOffsetString(systemTimeZoneIdentifier) 是 true,则
    1. 令 offsetNanoseconds 为 ParseTimeZoneOffsetString(systemTimeZoneIdentifier)。
  3. 否则,
    1. 令 offsetNanoseconds 为 GetNamedTimeZoneOffsetNanoseconds(systemTimeZoneIdentifier, ℝ(tv) × NanosecondsPerMillisecond)。
  4. 令 offsetMilliseconds 为 truncate(offsetNanoseconds / NanosecondsPerMillisecond)。
  5. 返回 tv + 𝔽(offsetMilliseconds)。
注 1

如果实现中没有本地时间 tv 的政治规则,则结果为 tv,因为 SystemTimeZoneIdentifier 返回 "UTC",GetNamedTimeZoneOffsetNanoseconds 返回 0。

注 2

要求时区感知实现(并建议所有其他实现)使用 IANA 时区数据库 https://www.iana.org/time-zones/ 中的时区信息。

注 3

在负向时区转换中存在重复时间时(例如夏令时结束或时区调整减小时),两个不同的输入时间值 tvUTC 会被转换为同一个本地时间 tlocal。

LocalTime(UTC(tvlocal)) 不一定始终等于 tvlocal。相应地,UTC(LocalTime(tvUTC)) 也不一定始终等于 tvUTC。

21.4.1.26 UTC ( t )

抽象操作 UTC,接收参数 t (Number);返回值:a time value。 它将 t 从本地时间转换为 UTC 时间值。 应按照本节规定的方式,使用在 t 时有效的标准时间和夏令时本地政治规则来确定结果。 调用时执行以下步骤:

  1. 如果 t 不是有限 Number,返回 NaN。
  2. 令 systemTimeZoneIdentifier 为 SystemTimeZoneIdentifier()。
  3. 如果 IsTimeZoneOffsetString(systemTimeZoneIdentifier) 是 true,则
    1. 令 offsetNanoseconds 为 ParseTimeZoneOffsetString(systemTimeZoneIdentifier)。
  4. 否则,
    1. 令 possibleInstants 为 GetNamedTimeZoneEpochNanoseconds(systemTimeZoneIdentifier, YearFromTime(t), MonthFromTime(t) + 1, DateFromTime(t), HourFromTime(t), MinuteFromTime(t), SecondFromTime(t), MillisecondFromTime(t), 0, 0)。
    2. 注:以下步骤确保,当 t 表示在负向时区转换时重复多次的本地时间(例如夏令时结束,或因时区规则变更而减小时区偏移),或者表示在正向时区转换时被跳过的本地时间(例如夏令时开始,或因时区规则变更而增大时区偏移)时,使用转换之前的时区偏移来解释 t。
    3. 如果 possibleInstants 非空,则
      1. 令 disambiguatedInstant 为 possibleInstants[0]。
    4. 否则,
      1. 注:t 表示在正向时区转换时被跳过的本地时间(例如因夏令时开始或时区规则变更增大 UTC 偏移)。
      2. 令 possibleInstantsBefore 为 GetNamedTimeZoneEpochNanoseconds(systemTimeZoneIdentifier, YearFromTime(tBefore), MonthFromTime(tBefore) + 1, DateFromTime(tBefore), HourFromTime(tBefore), MinuteFromTime(tBefore), SecondFromTime(tBefore), MillisecondFromTime(tBefore), 0, 0),其中 tBefore 是满足 possibleInstantsBefore 非空的最大整数 Number < t(即 tBefore 表示转换之前的最后一个本地时间)。
      3. 令 disambiguatedInstant 为 possibleInstantsBefore 的最后一个元素。
    5. 令 offsetNanoseconds 为 GetNamedTimeZoneOffsetNanoseconds(systemTimeZoneIdentifier, disambiguatedInstant)。
  5. 令 offsetMilliseconds 为 truncate(offsetNanoseconds / NanosecondsPerMillisecond)。
  6. 返回 t - 𝔽(offsetMilliseconds)。

输入 t 名义上是时间值,但可以是任意 Number 值。 算法不得将 t 限制在时间值范围内,从而无论本地 UTC 偏移如何,都能支持与时间值范围边界对应的输入。 例如,最大时间值为 8.64 × 1015,对应 "+275760-09-13T00:00:00Z"。 在该时刻本地时区偏移比 UTC 快 1 小时的环境中,它由较大的输入 8.64 × 1015 + 3.6 × 106 表示,对应 "+275760-09-13T01:00:00+01:00"。

如果实现中没有本地时间 t 的政治规则,则结果为 t,因为 SystemTimeZoneIdentifier 返回 "UTC",GetNamedTimeZoneOffsetNanoseconds 返回 0。

注 1

要求时区感知实现(并建议所有其他实现)使用 IANA 时区数据库中的时区信息。

America/New_York 中 2017 年 11 月 5 日凌晨 1:30 会重复两次(时钟向后调整),但必须将其解释为 UTC-04 的凌晨 1:30,而不是 UTC-05 的凌晨 1:30。 在 UTC(TimeClip(MakeDate(MakeDay(2017, 10, 5), MakeTime(1, 30, 0, 0)))) 中,offsetMilliseconds 的值是 -4 × MillisecondsPerHour。

America/New_York 中 2017 年 3 月 12 日凌晨 2:30 不存在,但必须将其解释为 UTC-05 的凌晨 2:30(等价于 UTC-04 的凌晨 3:30)。 在 UTC(TimeClip(MakeDate(MakeDay(2017, 2, 12), MakeTime(2, 30, 0, 0)))) 中,offsetMilliseconds 的值是 -5 × MillisecondsPerHour。

注 2

UTC(LocalTime(tUTC)) 不一定始终等于 tUTC。相应地,LocalTime(UTC(tlocal)) 也不一定始终等于 tlocal。

21.4.1.27 MakeTime ( hour, minute, second, millisecond )

抽象操作 MakeTime,接收参数 hour (Number)、minute (Number)、second (Number) 和 millisecond (Number);返回值:Number。 它计算毫秒数。 调用时执行以下步骤:

  1. 如果 hour 不是有限 Number,minute 不是有限 Number,second 不是有限 Number,或 millisecond 不是有限 Number,返回 NaN。
  2. 令 hourMV 为 ! ToIntegerOrInfinity(hour)。
  3. 令 minuteMV 为 ! ToIntegerOrInfinity(minute)。
  4. 令 secondMV 为 ! ToIntegerOrInfinity(second)。
  5. 令 millisecondMV 为 ! ToIntegerOrInfinity(millisecond)。
  6. 返回 ((𝔽(hourMV) × 𝔽(MillisecondsPerHour) + 𝔽(minuteMV) × 𝔽(MillisecondsPerMinute)) + 𝔽(secondMV) × 𝔽(MillisecondsPerSecond)) + 𝔽(millisecondMV)。
注

MakeTime 中的算术是浮点算术,它不满足结合律,因此必须按正确顺序执行运算。

21.4.1.28 MakeDay ( year, month, day )

抽象操作 MakeDay,接收参数 year (Number)、month (Number) 和 day (Number);返回值:(a finite Number 或 NaN)。 它计算天数。 调用时执行以下步骤:

  1. 如果 year 不是有限 Number,month 不是有限 Number,或 day 不是有限 Number,返回 NaN。
  2. 令 yearMV 为 ! ToIntegerOrInfinity(year)。
  3. 令 monthMV 为 ! ToIntegerOrInfinity(month)。
  4. 令 dayMV 为 ! ToIntegerOrInfinity(day)。
  5. 令 balancedYear 为 𝔽(yearMV) + 𝔽(floor(monthMV / 12))。
  6. 如果 balancedYear 不是有限 Number,返回 NaN。
  7. 令 balancedMonthMV 为 monthMV modulo 12。
  8. 找到一个有限时间值 tv,使得 YearFromTime(tv) = ℝ(balancedYear)、MonthFromTime(tv) = balancedMonthMV 且 DateFromTime(tv) = 1;但如果无法做到这一点(因为某个实参超出范围),返回 NaN。
  9. 返回 𝔽(Day(tv)) + 𝔽(dayMV) - 1𝔽。

21.4.1.29 MakeDate ( day, time )

抽象操作 MakeDate,接收参数 day (Number) 和 time (Number);返回值:(a finite Number 或 NaN)。 它计算毫秒数。 调用时执行以下步骤:

  1. 如果 day 不是有限 Number 或 time 不是有限 Number,返回 NaN。
  2. 令 tv 为 day × 𝔽(MillisecondsPerDay) + time。
  3. 如果 tv 不是有限 Number,返回 NaN。
  4. 返回 tv。

21.4.1.30 MakeFullYear ( year )

抽象操作 MakeFullYear,接收参数 year (Number);返回值:(整数 Number 或 NaN)。 它返回与 year 整数部分关联的完整年份,并将从 0 到 99 的闭区间内的任何值解释为自 1900 年开始以来经过的年数。为了与外推格里高利历对齐,“完整年份”定义为自年份 0(公元前 1 年)开始以来完整年份的带符号计数。 调用时执行以下步骤:

  1. 如果 year 是 NaN、+∞𝔽 或 -∞𝔽 之一,则返回 NaN。
  2. 令 truncated 为 ! ToIntegerOrInfinity(year)。
  3. 如果 truncated 位于从 0 到 99 的闭区间内,则返回 1900𝔽 + 𝔽(truncated)。
  4. 返回 𝔽(truncated)。

21.4.1.31 TimeClip ( time )

抽象操作 TimeClip,接收参数 time (Number);返回值:a time value。 它计算毫秒数。 调用时执行以下步骤:

  1. 如果 time 不是有限 Number,返回 NaN。
  2. 如果 abs(ℝ(time)) > 8.64 × 1015,返回 NaN。
  3. 返回 𝔽(! ToIntegerOrInfinity(time))。

21.4.1.32 日期时间字符串格式

ECMAScript 定义了一种日期时间字符串交换格式,它改编自 ISO 8601 日历日期扩展格式。其格式如下:YYYY-MM-DDTHH:mm:ss.sssZ

其中各元素如下:

YYYY 是外推格里高利历中的年份,表示为从 0000 到 9999 的四位十进制数字,或者表示为扩展年份,即 "+" 或 "-" 后跟六位十进制数字。
- "-"(连字符)在字符串中字面出现两次。
MM 是一年中的月份,以两位十进制数字表示,从 01(一月)到 12(十二月)。
DD 是一个月中的日期,以从 01 到 31 的两位十进制数字表示。
T "T" 在字符串中字面出现,用于表示时间元素的开始。
HH 是自午夜以来已经完整经过的小时数,以从 00 到 24 的两位十进制数字表示。
: ":"(冒号)在字符串中字面出现两次。
mm 是自该小时开始以来已经完整经过的分钟数,以从 00 到 59 的两位十进制数字表示。
ss 是自该分钟开始以来已经完整经过的秒数,以从 00 到 59 的两位十进制数字表示。
. "."(点)在字符串中字面出现。
sss 是自该秒开始以来已经完整经过的毫秒数,以三位十进制数字表示。
Z 是 UTC 偏移表示,规定为 "Z"(表示无偏移的 UTC),或者为 "+" 或 "-" 后跟时间表达式 HH:mm(时区偏移字符串格式的子集),分别用于表示本地时间领先或落后于 UTC

此格式包括仅日期形式:

YYYY
YYYY-MM
YYYY-MM-DD
        

它还包括“日期时间”形式,由上述某一种仅日期形式紧接以下某一种时间形式组成,并可在末尾附加可选的 UTC 偏移表示:

THH:mm
THH:mm:ss
THH:mm:ss.sss
        

包含越界或不符合要求元素的字符串不是此格式的有效实例。

注 1

由于每一天都以午夜开始并以午夜结束,因此可以使用 00:00 和 24:00 两种表示法来区分可与同一个日期关联的两个午夜。这意味着以下两种表示法指向完全相同的时间点:1995-02-04T24:00 和 1995-02-05T00:00。

注 2

此格式不支持 RFC 9557 中定义的带时区名称注解,仅支持时区偏移的数字表示。

21.4.1.32.1 扩展年份

为了覆盖相对于 1970 年 1 月 1 日向前或向后约 273,790 年的完整时间值范围(21.4.1.1),需要表示 0 年之前或 9999 年之后的年份。ISO 8601 允许扩展年份表示,但仅限信息交换双方共同约定的情况下。在简化的 ECMAScript 格式中,此类扩展年份表示应具有 6 位数字,并且始终以 + 或 - 符号作为前缀。年份 0 被视为正数,必须以 + 符号作为前缀。将年份 0 表示为 -000000 是无效的。与日期时间字符串格式匹配、但其扩展年份所表示的时间瞬间超出时间值范围的字符串,会被 Date.parse 视为不可识别,并使该函数返回 NaN,而不会回退到实现特定的行为或启发式处理。

注

具有扩展年份的日期时间值示例:

-271821-04-20T00:00:00Z 公元前 271822 年
-000001-01-01T00:00:00Z 公元前 2 年
+000000-01-01T00:00:00Z 公元前 1 年
+000001-01-01T00:00:00Z 公元 1 年
+001970-01-01T00:00:00Z 公元 1970 年
+002009-12-15T00:00:00Z 公元 2009 年
+275760-09-13T00:00:00Z 公元 275760 年

21.4.1.33 时区偏移字符串格式

ECMAScript 定义了一种派生自 ISO 8601 的 UTC 偏移字符串交换格式。 该格式由以下文法描述。

语法

UTCOffset ::: ASCIISign Hour ASCIISign Hour HourSubcomponents[+Extended] ASCIISign Hour HourSubcomponents[~Extended] ASCIISign ::: one of + - Hour ::: 0 DecimalDigit 1 DecimalDigit 20 21 22 23 HourSubcomponents[Extended] ::: TimeSeparator[?Extended] MinuteSecond TimeSeparator[?Extended] MinuteSecond TimeSeparator[?Extended] MinuteSecond TemporalDecimalFractionopt TimeSeparator[Extended] ::: [+Extended] : [~Extended] [empty] MinuteSecond ::: 0 DecimalDigit 1 DecimalDigit 2 DecimalDigit 3 DecimalDigit 4 DecimalDigit 5 DecimalDigit TemporalDecimalFraction ::: TemporalDecimalSeparator DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator ::: one of . ,

21.4.1.33.1 IsTimeZoneOffsetString ( offsetString )

抽象操作 IsTimeZoneOffsetString,接收参数 offsetString (String);返回值:Boolean。 返回值表示 offsetString 是否符合 UTCOffset 给出的文法。 调用时执行以下步骤:

  1. 令 parseResult 为 ParseText(offsetString, UTCOffset)。
  2. 如果 parseResult 是错误的 List,则返回 false。
  3. 返回 true。

21.4.1.33.2 ParseTimeZoneOffsetString ( offsetString )

抽象操作 ParseTimeZoneOffsetString,接收参数 offsetString (String);返回值:整数。 返回值是与 String offsetString 对应的 UTC 偏移,以纳秒数表示。 调用时执行以下步骤:

  1. 令 parseResult 为 ParseText(offsetString, UTCOffset)。
  2. 断言:parseResult 不是错误的 List。
  3. 断言:parseResult 包含 ASCIISign Parse Node。
  4. 令 parsedSign 为 parseResult 中包含的 ASCIISign Parse Node 所匹配的源文本。
  5. 如果 parsedSign 是单个码点 U+002D (HYPHEN-MINUS),则
    1. 令 sign 为 -1。
  6. 否则,
    1. 令 sign 为 1。
  7. 注:下面对 StringToNumber 的应用不会丢失精度,因为每个解析值都保证是足够短的十进制数字字符串。
  8. 断言:parseResult 包含 Hour Parse Node。
  9. 令 parsedHours 为 parseResult 中包含的 Hour Parse Node 所匹配的源文本。
  10. 令 hours 为 ℝ(StringToNumber(CodePointsToString(parsedHours)))。
  11. 如果 parseResult 不包含 MinuteSecond Parse Node,则
    1. 令 minutes 为 0。
  12. 否则,
    1. 令 parsedMinutes 为 parseResult 中包含的第一个 MinuteSecond Parse Node 所匹配的源文本。
    2. 令 minutes 为 ℝ(StringToNumber(CodePointsToString(parsedMinutes)))。
  13. 如果 parseResult 不包含两个 MinuteSecond Parse Node,则
    1. 令 seconds 为 0。
  14. 否则,
    1. 令 parsedSeconds 为 parseResult 中包含的第二个 MinuteSecond Parse Node 所匹配的源文本。
    2. 令 seconds 为 ℝ(StringToNumber(CodePointsToString(parsedSeconds)))。
  15. 如果 parseResult 不包含 TemporalDecimalFraction Parse Node,则
    1. 令 nanoseconds 为 0。
  16. 否则,
    1. 令 parsedFraction 为 parseResult 中包含的 TemporalDecimalFraction Parse Node 所匹配的源文本。
    2. 令 fraction 为 CodePointsToString(parsedFraction) 和 "000000000" 的字符串连接。
    3. 令 nanosecondsString 为 fraction 从 1 到 10 的子字符串。
    4. 令 nanoseconds 为 ℝ(StringToNumber(nanosecondsString))。
  17. 返回 sign × (((hours × MinutesPerHour + minutes) × SecondsPerMinute + seconds) × NanosecondsPerSecond + nanoseconds)。

21.4.2 Date 构造函数

Date 构造函数:

  • 是 %Date%。
  • 是全局对象的 "Date" 属性的初始值。
  • 作为构造函数调用时,创建并初始化新的 Date。
  • 作为函数而不是构造函数调用时,返回表示当前时间(UTC)的 String。
  • 是一个其行为根据参数数量和类型而不同的函数。
  • 可以用作类定义的 extends 子句的值。希望继承指定 Date 行为的子类构造函数必须包含对 Date 构造函数的 super 调用,以创建并初始化具有 [[DateValue]] 内部槽的子类实例。

21.4.2.1 Date ( ...values )

调用时,此函数执行以下步骤:

  1. 如果 NewTarget 是 undefined,则
    1. 令 now 为标识当前时间的时间值(UTC)。
    2. 返回 ToDateString(now)。
  2. 令 numberOfArgs 为 values 中的元素数量。
  3. 如果 numberOfArgs = 0,则
    1. 令 dv 为标识当前时间的时间值(UTC)。
  4. 否则如果 numberOfArgs = 1,则
    1. 令 value 为 values[0]。
    2. 如果 value 是 Object 且 value 具有 [[DateValue]] 内部槽,则
      1. 令 tv 为 value.[[DateValue]]。
    3. 否则,
      1. 令 primitive 为 ? ToPrimitive(value)。
      2. 如果 primitive 是 String,则
        1. 断言:由于 primitive 是 String,下一步绝不会返回突然完成。
        2. 令 tv 为将 primitive 解析为日期的结果,解析方式与 parse 方法(21.4.3.2)完全相同。
      3. 否则,
        1. 令 tv 为 ? ToNumber(primitive)。
    4. 令 dv 为 TimeClip(tv)。
  5. 否则,
    1. 断言:numberOfArgs ≥ 2。
    2. 令 yearNumber 为 ? ToNumber(values[0])。
    3. 令 monthNumber 为 ? ToNumber(values[1])。
    4. 如果 numberOfArgs > 2,则令 dayNumber 为 ? ToNumber(values[2]);否则令 dayNumber 为 1𝔽。
    5. 如果 numberOfArgs > 3,则令 hourNumber 为 ? ToNumber(values[3]);否则令 hourNumber 为 +0𝔽。
    6. 如果 numberOfArgs > 4,则令 minuteNumber 为 ? ToNumber(values[4]);否则令 minuteNumber 为 +0𝔽。
    7. 如果 numberOfArgs > 5,则令 secondNumber 为 ? ToNumber(values[5]);否则令 secondNumber 为 +0𝔽。
    8. 如果 numberOfArgs > 6,则令 millisecondNumber 为 ? ToNumber(values[6]);否则令 millisecondNumber 为 +0𝔽。
    9. 将 yearNumber 设置为 MakeFullYear(yearNumber)。
    10. 令 finalDate 为 MakeDate(MakeDay(yearNumber, monthNumber, dayNumber), MakeTime(hourNumber, minuteNumber, secondNumber, millisecondNumber))。
    11. 令 dv 为 TimeClip(UTC(finalDate))。
  6. 令 obj 为 ? OrdinaryCreateFromConstructor(NewTarget, "%Date.prototype%", « [[DateValue]] »)。
  7. 将 obj.[[DateValue]] 设置为 dv。
  8. 返回 obj。

21.4.3 Date 构造函数的属性

Date 构造函数:

  • 具有 [[Prototype]] 内部槽,其值是 %Function.prototype%。
  • 具有 "length" 属性,其值是 7𝔽。
  • 具有以下属性:

21.4.3.1 Date.now ( )

此函数返回表示其调用发生时 UTC 日期和时间的时间值。

21.4.3.2 Date.parse ( string )

此函数对其参数应用 ToString 运算符。如果 ToString 导致突然完成,则立即返回该 Completion Record。否则,此函数将所得 String 解释为日期和时间;它返回一个 Number,即与该日期和时间对应的 UTC 时间值。根据 String 的内容,可以将该 String 解释为本地时间、UTC 时间或其他时区中的时间。此函数首先尝试按照日期时间字符串格式(21.4.1.32)中描述的格式(包括扩展年份)解析 String。如果 String 不符合该格式,则函数可以回退到任何实现特定的启发式处理或实现特定的日期格式。无法识别的 String 或包含越界格式元素值的 String 应使此函数返回 NaN。

如果 String 符合日期时间字符串格式,则使用替代值代替缺失的格式元素。当 MM 或 DD 元素缺失时,使用 "01"。当 HH、mm 或 ss 元素缺失时,使用 "00"。当 sss 元素缺失时,使用 "000"。当 UTC 偏移表示缺失时,仅日期形式被解释为 UTC 时间,而日期时间形式被解释为本地时间。

如果 x 是在特定 ECMAScript 实现中其毫秒部分为零的任意 Date,并且引用的所有属性都具有其初始值,则以下所有表达式在该实现中都应产生相同的数值:

x.valueOf()
Date.parse(x.toString())
Date.parse(x.toUTCString())
Date.parse(x.toISOString())

不过,表达式

Date.parse(x.toLocaleString())

不要求产生与前述三个表达式相同的 Number 值;一般而言,当为此函数提供任何不符合日期时间字符串格式(21.4.1.32)、并且无法由该实现中的 toString 或 toUTCString 方法产生的 String 值时,其产生的值由实现定义。

21.4.3.3 Date.prototype

Date.prototype 的初始值是 Date 原型对象。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.4.3.4 Date.UTC ( year [ , month [ , day [ , hour [ , minute [ , second [ , millisecond ] ] ] ] ] ] )

调用时,此函数执行以下步骤:

  1. 令 yearNumber 为 ? ToNumber(year)。
  2. 如果存在 month,则令 monthNumber 为 ? ToNumber(month);否则令 monthNumber 为 +0𝔽。
  3. 如果存在 day,则令 dayNumber 为 ? ToNumber(day);否则令 dayNumber 为 1𝔽。
  4. 如果存在 hour,则令 hourNumber 为 ? ToNumber(hour);否则令 hourNumber 为 +0𝔽。
  5. 如果存在 minute,则令 minuteNumber 为 ? ToNumber(minute);否则令 minuteNumber 为 +0𝔽。
  6. 如果存在 second,则令 secondNumber 为 ? ToNumber(second);否则令 secondNumber 为 +0𝔽。
  7. 如果存在 millisecond,则令 millisecondNumber 为 ? ToNumber(millisecond);否则令 millisecondNumber 为 +0𝔽。
  8. 将 yearNumber 设置为 MakeFullYear(yearNumber)。
  9. 返回 TimeClip(MakeDate(MakeDay(yearNumber, monthNumber, dayNumber), MakeTime(hourNumber, minuteNumber, secondNumber, millisecondNumber)))。

此函数的 "length" 属性是 7𝔽。

注

此函数与 Date 构造函数有两点不同:它返回 Number 形式的时间值,而不是创建 Date;并且它将参数解释为 UTC 时间,而不是本地时间。

21.4.4 Date 原型对象的属性

Date 原型对象:

  • 是 %Date.prototype%。
  • 自身是普通对象。
  • 不是 Date 实例,并且没有 [[DateValue]] 内部槽。
  • 具有 [[Prototype]] 内部槽,其值是 %Object.prototype%。

除非另有明确规定,下面定义的 Date 原型对象的方法不是通用方法,传递给它们的 this value 必须是具有已初始化为时间值的 [[DateValue]] 内部槽的对象。

21.4.4.1 Date.prototype.constructor

Date.prototype.constructor 的初始值是 %Date%。

21.4.4.2 Date.prototype.getDate ( )

调用时,此方法执行以下步骤:

  1. 令 dateObj 为 this value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. 令 tv 为 dateObj.[[DateValue]]。
  4. 如果 tv 是 NaN,则返回 NaN。
  5. 返回 𝔽(DateFromTime(LocalTime(tv)))。

21.4.4.3 Date.prototype.getDay ( )

调用时,此方法执行以下步骤:

  1. 令 dateObj 为 this value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. 令 tv 为 dateObj.[[DateValue]]。
  4. 如果 tv 是 NaN,则返回 NaN。
  5. 返回 𝔽(WeekDay(LocalTime(tv)))。

21.4.4.4 Date.prototype.getFullYear ( )

调用时,此方法执行以下步骤:

  1. 令 dateObj 为 this value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. 令 tv 为 dateObj.[[DateValue]]。
  4. 如果 tv 是 NaN,则返回 NaN。
  5. 返回 𝔽(YearFromTime(LocalTime(tv)))。

21.4.4.5 Date.prototype.getHours ( )

调用时,此方法执行以下步骤:

  1. 令 dateObj 为 this value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. 令 tv 为 dateObj.[[DateValue]]。
  4. 如果 tv 是 NaN,则返回 NaN。
  5. 返回 𝔽(HourFromTime(LocalTime(tv)))。

21.4.4.6 Date.prototype.getMilliseconds ( )

调用时,此方法执行以下步骤:

  1. 令 dateObj 为 this value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. 令 tv 为 dateObj.[[DateValue]]。
  4. 如果 tv 是 NaN,则返回 NaN。
  5. 返回 𝔽(MillisecondFromTime(LocalTime(tv)))。

21.4.4.7 Date.prototype.getMinutes ( )

调用时,此方法执行以下步骤:

  1. 令 dateObj 为 this value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. 令 tv 为 dateObj.[[DateValue]]。
  4. 如果 tv 是 NaN,则返回 NaN。
  5. 返回 𝔽(MinuteFromTime(LocalTime(tv)))。

21.4.4.8 Date.prototype.getMonth ( )

调用时,此方法执行以下步骤:

  1. 令 dateObj 为 this value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. 令 tv 为 dateObj.[[DateValue]]。
  4. 如果 tv 是 NaN,则返回 NaN。
  5. 返回 𝔽(MonthFromTime(LocalTime(tv)))。

21.4.4.9 Date.prototype.getSeconds ( )

调用时,此方法执行以下步骤:

  1. 令 dateObj 为 this value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. 令 tv 为 dateObj.[[DateValue]]。
  4. 如果 tv 是 NaN,则返回 NaN。
  5. 返回 𝔽(SecondFromTime(LocalTime(tv)))。

21.4.4.10 Date.prototype.getTime ( )

调用时,此方法执行以下步骤:

  1. 令 dateObj 为 this value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. 返回 dateObj.[[DateValue]]。

21.4.4.11 Date.prototype.getTimezoneOffset ( )

调用时,此方法执行以下步骤:

  1. 令 dateObj 为 this value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. 令 tv 为 dateObj.[[DateValue]]。
  4. 如果 tv 是 NaN,则返回 NaN。
  5. 返回 (tv - LocalTime(tv)) / 𝔽(MillisecondsPerMinute)。

21.4.4.12 Date.prototype.getUTCDate ( )

调用时,此方法执行以下步骤:

  1. 令 dateObj 为 this value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. 令 tv 为 dateObj.[[DateValue]]。
  4. 如果 tv 是 NaN,则返回 NaN。
  5. 返回 𝔽(DateFromTime(tv))。

21.4.4.13 Date.prototype.getUTCDay ( )

调用时,此方法执行以下步骤:

  1. 令 dateObj 为 this value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. 令 tv 为 dateObj.[[DateValue]]。
  4. 如果 tv 是 NaN,则返回 NaN。
  5. 返回 𝔽(WeekDay(tv))。

21.4.4.14 Date.prototype.getUTCFullYear ( )

调用时,此方法执行以下步骤:

  1. 令 dateObj 为 this value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. 令 tv 为 dateObj.[[DateValue]]。
  4. 如果 tv 是 NaN,则返回 NaN。
  5. 返回 𝔽(YearFromTime(tv))。

21.4.4.15 Date.prototype.getUTCHours ( )

调用时,此方法执行以下步骤:

  1. 令 dateObj 为 this value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. 令 tv 为 dateObj.[[DateValue]]。
  4. 如果 tv 是 NaN,则返回 NaN。
  5. 返回 𝔽(HourFromTime(tv))。

21.4.4.16 Date.prototype.getUTCMilliseconds ( )

调用时,此方法执行以下步骤:

  1. 令 dateObj 为 this value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. 令 tv 为 dateObj.[[DateValue]]。
  4. 如果 tv 是 NaN,则返回 NaN。
  5. 返回 𝔽(MillisecondFromTime(tv))。

21.4.4.17 Date.prototype.getUTCMinutes ( )

调用时,此方法执行以下步骤:

  1. 令 dateObj 为 this value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. 令 tv 为 dateObj.[[DateValue]]。
  4. 如果 tv 是 NaN,则返回 NaN。
  5. 返回 𝔽(MinuteFromTime(tv))。

21.4.4.18 Date.prototype.getUTCMonth ( )

调用时,此方法执行以下步骤:

  1. 令 dateObj 为 this value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. 令 tv 为 dateObj.[[DateValue]]。
  4. 如果 tv 是 NaN,则返回 NaN。
  5. 返回 𝔽(MonthFromTime(tv))。

21.4.4.19 Date.prototype.getUTCSeconds ( )

调用时,此方法执行以下步骤:

  1. 令 dateObj 为 this value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. 令 tv 为 dateObj.[[DateValue]]。
  4. 如果 tv 是 NaN,则返回 NaN。
  5. 返回 𝔽(SecondFromTime(tv))。

21.4.4.20 Date.prototype.setDate ( day )

调用时,此方法执行以下步骤:

  1. 令 dateObj 为 this value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. 令 tv 为 dateObj.[[DateValue]]。
  4. 令 dayNumber 为 ? ToNumber(day)。
  5. 如果 tv 是 NaN,则返回 NaN。
  6. 将 tv 设置为 LocalTime(tv)。
  7. 令 newDate 为 MakeDate(MakeDay(𝔽(YearFromTime(tv)), 𝔽(MonthFromTime(tv)), dayNumber), 𝔽(TimeWithinDay(tv)))。
  8. 令 u 为 TimeClip(UTC(newDate))。
  9. 将 dateObj.[[DateValue]] 设置为 u。
  10. 返回 u。

21.4.4.21 Date.prototype.setFullYear ( year [ , month [ , day ] ] )

调用时,此方法执行以下步骤:

  1. 令 dateObj 为 this value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. 令 tv 为 dateObj.[[DateValue]]。
  4. 令 yearNumber 为 ? ToNumber(year)。
  5. 如果 tv 是 NaN,则将 tv 设置为 +0𝔽;否则将 tv 设置为 LocalTime(tv)。
  6. 如果存在 month,则令 monthNumber 为 ? ToNumber(month);否则令 monthNumber 为 𝔽(MonthFromTime(tv))。
  7. 如果存在 day,则令 dayNumber 为 ? ToNumber(day);否则令 dayNumber 为 𝔽(DateFromTime(tv))。
  8. 令 newDate 为 MakeDate(MakeDay(yearNumber, monthNumber, dayNumber), 𝔽(TimeWithinDay(tv)))。
  9. 令 u 为 TimeClip(UTC(newDate))。
  10. 将 dateObj.[[DateValue]] 设置为 u。
  11. 返回 u。

此方法的 "length" 属性是 3𝔽。

注

如果不存在 month,则此方法的行为如同 month 存在且值为 getMonth()。如果不存在 day,则其行为如同 day 存在且值为 getDate()。

21.4.4.22 Date.prototype.setHours ( hour [ , minute [ , second [ , millisecond ] ] ] )

调用时,此方法执行以下步骤:

  1. 令 dateObj 为 this value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. 令 tv 为 dateObj.[[DateValue]]。
  4. 令 hourNumber 为 ? ToNumber(hour)。
  5. 如果存在 minute,则令 minuteNumber 为 ? ToNumber(minute)。
  6. 如果存在 second,则令 secondNumber 为 ? ToNumber(second)。
  7. 如果存在 millisecond,则令 millisecondNumber 为 ? ToNumber(millisecond)。
  8. 如果 tv 是 NaN,则返回 NaN。
  9. 将 tv 设置为 LocalTime(tv)。
  10. 如果不存在 minute,则令 minuteNumber 为 𝔽(MinuteFromTime(tv))。
  11. 如果不存在 second,则令 secondNumber 为 𝔽(SecondFromTime(tv))。
  12. 如果不存在 millisecond,则令 millisecondNumber 为 𝔽(MillisecondFromTime(tv))。
  13. 令 date 为 MakeDate(𝔽(Day(tv)), MakeTime(hourNumber, minuteNumber, secondNumber, millisecondNumber))。
  14. 令 u 为 TimeClip(UTC(date))。
  15. 将 dateObj.[[DateValue]] 设置为 u。
  16. 返回 u。

此方法的 "length" 属性是 4𝔽。

注

如果不存在 minute,则此方法的行为如同 minute 存在且值为 getMinutes()。如果不存在 second,则其行为如同 second 存在且值为 getSeconds()。如果不存在 millisecond,则其行为如同 millisecond 存在且值为 getMilliseconds()。

21.4.4.23 Date.prototype.setMilliseconds ( millisecond )

调用时,此方法执行以下步骤:

  1. 令 dateObj 为 this value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. 令 tv 为 dateObj.[[DateValue]]。
  4. 令 millisecondNumber 为 ? ToNumber(millisecond)。
  5. 如果 tv 是 NaN,则返回 NaN。
  6. 将 tv 设置为 LocalTime(tv)。
  7. 令 time 为 MakeTime(𝔽(HourFromTime(tv)), 𝔽(MinuteFromTime(tv)), 𝔽(SecondFromTime(tv)), millisecondNumber)。
  8. 令 u 为 TimeClip(UTC(MakeDate(𝔽(Day(tv)), time)))。
  9. 将 dateObj.[[DateValue]] 设置为 u。
  10. 返回 u。

21.4.4.24 Date.prototype.setMinutes ( minute [ , second [ , millisecond ] ] )

调用时,此方法执行以下步骤:

  1. 令 dateObj 为 this value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. 令 tv 为 dateObj.[[DateValue]]。
  4. 令 minuteNumber 为 ? ToNumber(minute)。
  5. 如果存在 second,则令 secondNumber 为 ? ToNumber(second)。
  6. 如果存在 millisecond,则令 millisecondNumber 为 ? ToNumber(millisecond)。
  7. 如果 tv 是 NaN,则返回 NaN。
  8. 将 tv 设置为 LocalTime(tv)。
  9. 如果不存在 second,则令 secondNumber 为 𝔽(SecondFromTime(tv))。
  10. 如果不存在 millisecond,则令 millisecondNumber 为 𝔽(MillisecondFromTime(tv))。
  11. 令 date 为 MakeDate(𝔽(Day(tv)), MakeTime(𝔽(HourFromTime(tv)), minuteNumber, secondNumber, millisecondNumber))。
  12. 令 u 为 TimeClip(UTC(date))。
  13. 将 dateObj.[[DateValue]] 设置为 u。
  14. 返回 u。

此方法的 "length" 属性是 3𝔽。

注

如果不存在 second,则此方法的行为如同 second 存在且值为 getSeconds()。如果不存在 millisecond,则其行为如同 millisecond 存在且值为 getMilliseconds()。

21.4.4.25 Date.prototype.setMonth ( month [ , day ] )

调用时,此方法执行以下步骤:

  1. 令 dateObj 为 this value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. 令 tv 为 dateObj.[[DateValue]]。
  4. 令 monthNumber 为 ? ToNumber(month)。
  5. 如果存在 day,则令 dayNumber 为 ? ToNumber(day)。
  6. 如果 tv 是 NaN,则返回 NaN。
  7. 将 tv 设置为 LocalTime(tv)。
  8. 如果不存在 day,则令 dayNumber 为 𝔽(DateFromTime(tv))。
  9. 令 newDate 为 MakeDate(MakeDay(𝔽(YearFromTime(tv)), monthNumber, dayNumber), 𝔽(TimeWithinDay(tv)))。
  10. 令 u 为 TimeClip(UTC(newDate))。
  11. 将 dateObj.[[DateValue]] 设置为 u。
  12. 返回 u。

此方法的 "length" 属性是 2𝔽。

注

如果不存在 day,则此方法的行为如同 day 存在且值为 getDate()。

21.4.4.26 Date.prototype.setSeconds ( second [ , millisecond ] )

调用时,此方法执行以下步骤:

  1. 令 dateObj 为 this value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. 令 tv 为 dateObj.[[DateValue]]。
  4. 令 secondNumber 为 ? ToNumber(second)。
  5. 如果存在 millisecond,则令 millisecondNumber 为 ? ToNumber(millisecond)。
  6. 如果 tv 是 NaN,则返回 NaN。
  7. 将 tv 设置为 LocalTime(tv)。
  8. 如果不存在 millisecond,则令 millisecondNumber 为 𝔽(MillisecondFromTime(tv))。
  9. 令 date 为 MakeDate(𝔽(Day(tv)), MakeTime(𝔽(HourFromTime(tv)), 𝔽(MinuteFromTime(tv)), secondNumber, millisecondNumber))。
  10. 令 u 为 TimeClip(UTC(date))。
  11. 将 dateObj.[[DateValue]] 设置为 u。
  12. 返回 u。

此方法的 "length" 属性是 2𝔽。

注

如果不存在 millisecond,则此方法的行为如同 millisecond 存在且值为 getMilliseconds()。

21.4.4.27 Date.prototype.setTime ( time )

调用时,此方法执行以下步骤:

  1. 令 dateObj 为 this value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. 令 t 为 ? ToNumber(time)。
  4. 令 v 为 TimeClip(t)。
  5. 将 dateObj.[[DateValue]] 设置为 v。
  6. 返回 v。

21.4.4.28 Date.prototype.setUTCDate ( day )

调用时,此方法执行以下步骤:

  1. 令 dateObj 为 this value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. 令 tv 为 dateObj.[[DateValue]]。
  4. 令 dayNumber 为 ? ToNumber(day)。
  5. 如果 tv 是 NaN,则返回 NaN。
  6. 令 newDate 为 MakeDate(MakeDay(𝔽(YearFromTime(tv)), 𝔽(MonthFromTime(tv)), dayNumber), 𝔽(TimeWithinDay(tv)))。
  7. 令 v 为 TimeClip(newDate)。
  8. 将 dateObj.[[DateValue]] 设置为 v。
  9. 返回 v。

21.4.4.29 Date.prototype.setUTCFullYear ( year [ , month [ , day ] ] )

调用时,此方法执行以下步骤:

  1. 令 dateObj 为 this value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. 令 tv 为 dateObj.[[DateValue]]。
  4. 如果 tv 是 NaN,则将 tv 设置为 +0𝔽。
  5. 令 yearNumber 为 ? ToNumber(year)。
  6. 如果存在 month,则令 monthNumber 为 ? ToNumber(month);否则令 monthNumber 为 𝔽(MonthFromTime(tv))。
  7. 如果存在 day,则令 dayNumber 为 ? ToNumber(day);否则令 dayNumber 为 𝔽(DateFromTime(tv))。
  8. 令 newDate 为 MakeDate(MakeDay(yearNumber, monthNumber, dayNumber), 𝔽(TimeWithinDay(tv)))。
  9. 令 v 为 TimeClip(newDate)。
  10. 将 dateObj.[[DateValue]] 设置为 v。
  11. 返回 v。

此方法的 "length" 属性是 3𝔽。

注

如果不存在 month,则此方法的行为如同 month 存在且值为 getUTCMonth()。如果不存在 day,则其行为如同 day 存在且值为 getUTCDate()。

21.4.4.30 Date.prototype.setUTCHours ( hour [ , minute [ , second [ , millisecond ] ] ] )

调用时,此方法执行以下步骤:

  1. 令 dateObj 为 this value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. 令 tv 为 dateObj.[[DateValue]]。
  4. 令 hourNumber 为 ? ToNumber(hour)。
  5. 如果存在 minute,则令 minuteNumber 为 ? ToNumber(minute)。
  6. 如果存在 second,则令 secondNumber 为 ? ToNumber(second)。
  7. 如果存在 millisecond,则令 millisecondNumber 为 ? ToNumber(millisecond)。
  8. 如果 tv 是 NaN,则返回 NaN。
  9. 如果不存在 minute,则令 minuteNumber 为 𝔽(MinuteFromTime(tv))。
  10. 如果不存在 second,则令 secondNumber 为 𝔽(SecondFromTime(tv))。
  11. 如果不存在 millisecond,则令 millisecondNumber 为 𝔽(MillisecondFromTime(tv))。
  12. 令 date 为 MakeDate(𝔽(Day(tv)), MakeTime(hourNumber, minuteNumber, secondNumber, millisecondNumber))。
  13. 令 v 为 TimeClip(date)。
  14. 将 dateObj.[[DateValue]] 设置为 v。
  15. 返回 v。

此方法的 "length" 属性是 4𝔽。

注

如果不存在 minute,则此方法的行为如同 minute 存在且值为 getUTCMinutes()。如果不存在 second,则其行为如同 second 存在且值为 getUTCSeconds()。如果不存在 millisecond,则其行为如同 millisecond 存在且值为 getUTCMilliseconds()。

21.4.4.31 Date.prototype.setUTCMilliseconds ( millisecond )

调用时,此方法执行以下步骤:

  1. 令 dateObj 为 this value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. 令 tv 为 dateObj.[[DateValue]]。
  4. 令 millisecondNumber 为 ? ToNumber(millisecond)。
  5. 如果 tv 是 NaN,则返回 NaN。
  6. 令 time 为 MakeTime(𝔽(HourFromTime(tv)), 𝔽(MinuteFromTime(tv)), 𝔽(SecondFromTime(tv)), millisecondNumber)。
  7. 令 v 为 TimeClip(MakeDate(𝔽(Day(tv)), time))。
  8. 将 dateObj.[[DateValue]] 设置为 v。
  9. 返回 v。

21.4.4.32 Date.prototype.setUTCMinutes ( minute [ , second [ , millisecond ] ] )

调用时,此方法执行以下步骤:

  1. 令 dateObj 为 this value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. 令 tv 为 dateObj.[[DateValue]]。
  4. 令 minuteNumber 为 ? ToNumber(minute)。
  5. 如果存在 second,则令 secondNumber 为 ? ToNumber(second)。
  6. 如果存在 millisecond,则令 millisecondNumber 为 ? ToNumber(millisecond)。
  7. 如果 tv 是 NaN,则返回 NaN。
  8. 如果不存在 second,则令 secondNumber 为 𝔽(SecondFromTime(tv))。
  9. 如果不存在 millisecond,则令 millisecondNumber 为 𝔽(MillisecondFromTime(tv))。
  10. 令 date 为 MakeDate(𝔽(Day(tv)), MakeTime(𝔽(HourFromTime(tv)), minuteNumber, secondNumber, millisecondNumber))。
  11. 令 v 为 TimeClip(date)。
  12. 将 dateObj.[[DateValue]] 设置为 v。
  13. 返回 v。

此方法的 "length" 属性是 3𝔽。

注

如果不存在 second,则此方法的行为如同 second 存在且值为 getUTCSeconds()。如果不存在 millisecond,则其行为如同 millisecond 存在且值为 getUTCMilliseconds() 的返回值。

21.4.4.33 Date.prototype.setUTCMonth ( month [ , day ] )

调用时,此方法执行以下步骤:

  1. 令 dateObj 为 this value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. 令 tv 为 dateObj.[[DateValue]]。
  4. 令 monthNumber 为 ? ToNumber(month)。
  5. 如果存在 day,则令 dayNumber 为 ? ToNumber(day)。
  6. 如果 tv 是 NaN,则返回 NaN。
  7. 如果不存在 day,则令 dayNumber 为 𝔽(DateFromTime(tv))。
  8. 令 newDate 为 MakeDate(MakeDay(𝔽(YearFromTime(tv)), monthNumber, dayNumber), 𝔽(TimeWithinDay(tv)))。
  9. 令 v 为 TimeClip(newDate)。
  10. 将 dateObj.[[DateValue]] 设置为 v。
  11. 返回 v。

此方法的 "length" 属性是 2𝔽。

注

如果不存在 day,则此方法的行为如同 day 存在且值为 getUTCDate()。

21.4.4.34 Date.prototype.setUTCSeconds ( second [ , millisecond ] )

调用时,此方法执行以下步骤:

  1. 令 dateObj 为 this value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. 令 tv 为 dateObj.[[DateValue]]。
  4. 令 secondNumber 为 ? ToNumber(second)。
  5. 如果存在 millisecond,则令 millisecondNumber 为 ? ToNumber(millisecond)。
  6. 如果 tv 是 NaN,则返回 NaN。
  7. 如果不存在 millisecond,则令 millisecondNumber 为 𝔽(MillisecondFromTime(tv))。
  8. 令 date 为 MakeDate(𝔽(Day(tv)), MakeTime(𝔽(HourFromTime(tv)), 𝔽(MinuteFromTime(tv)), secondNumber, millisecondNumber))。
  9. 令 v 为 TimeClip(date)。
  10. 将 dateObj.[[DateValue]] 设置为 v。
  11. 返回 v。

此方法的 "length" 属性是 2𝔽。

注

如果不存在 millisecond,则此方法的行为如同 millisecond 存在且值为 getUTCMilliseconds()。

21.4.4.35 Date.prototype.toDateString ( )

调用时,此方法执行以下步骤:

  1. 令 dateObj 为 this value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. 令 tv 为 dateObj.[[DateValue]]。
  4. 如果 tv 是 NaN,则返回 "Invalid Date"。
  5. 令 t 为 LocalTime(tv)。
  6. 返回 DateString(t)。

21.4.4.36 Date.prototype.toISOString ( )

调用时,此方法执行以下步骤:

  1. 令 dateObj 为 this value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. 令 tv 为 dateObj.[[DateValue]]。
  4. 如果 tv 是 NaN,则抛出 RangeError 异常。
  5. 断言:tv 是整数 Number。
  6. 如果 tv 对应于无法在日期时间字符串格式中表示的年份,则抛出 RangeError 异常。
  7. 返回 tv 在 UTC 时间尺度上采用日期时间字符串格式的 String 表示,包括所有格式元素以及 UTC 偏移表示 "Z"。

21.4.4.37 Date.prototype.toJSON ( key )

此方法提供用于 JSON.stringify(25.5.4)的 Date 的 String 表示。

调用时,它执行以下步骤:

  1. 令 obj 为 ? ToObject(this value)。
  2. 令 tv 为 ? ToPrimitive(obj, number)。
  3. 如果 tv 是 Number 且 tv 不是有限 Number,返回 null。
  4. 返回 ? Invoke(obj, "toISOString")。
注 1

该参数会被忽略。

注 2

此方法有意设计为通用方法;它不要求其 this value 是 Date。因此,它可以被转移到其他种类的对象上用作方法。不过,它要求任何此类对象都具有 toISOString 方法。

21.4.4.38 Date.prototype.toLocaleDateString ( [ reserved1 [ , reserved2 ] ] )

包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按照 ECMA-402 的规定实现此方法。否则,使用以下此方法的规范:

此方法返回一个 String 值。该 String 的内容由实现定义,但旨在以方便、人类可读且符合宿主环境当前区域设置惯例的形式,表示当前时区中 Date 的“日期”部分。

此方法可选参数的含义定义于 ECMA-402;不包含 ECMA-402 支持的实现不得将这些参数位置用于其他用途。

21.4.4.39 Date.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] )

包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按照 ECMA-402 的规定实现此方法。否则,使用以下此方法的规范:

此方法返回一个 String 值。该 String 的内容由实现定义,但旨在以方便、人类可读且符合宿主环境当前区域设置惯例的形式,表示当前时区中的 Date。

此方法可选参数的含义定义于 ECMA-402;不包含 ECMA-402 支持的实现不得将这些参数位置用于其他用途。

21.4.4.40 Date.prototype.toLocaleTimeString ( [ reserved1 [ , reserved2 ] ] )

包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按照 ECMA-402 的规定实现此方法。否则,使用以下此方法的规范:

此方法返回一个 String 值。该 String 的内容由实现定义,但旨在以方便、人类可读且符合宿主环境当前区域设置惯例的形式,表示当前时区中 Date 的“时间”部分。

此方法可选参数的含义定义于 ECMA-402;不包含 ECMA-402 支持的实现不得将这些参数位置用于其他用途。

21.4.4.41 Date.prototype.toString ( )

调用时,此方法执行以下步骤:

  1. 令 dateObj 为 this value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. 令 tv 为 dateObj.[[DateValue]]。
  4. 返回 ToDateString(tv)。
注 1

对于任何满足 d.[[DateValue]] 能被 1000 整除的 Date d,Date.parse(d.toString()) 的结果 = d.valueOf()。参见 21.4.3.2。

注 2

此方法不是通用方法;如果其 this value 不是 Date,则会抛出 TypeError 异常。因此,它不能被转移到其他种类的对象上用作方法。

21.4.4.41.1 TimeString ( tv )

抽象操作 TimeString,接收参数 tv (a Number, but not NaN);返回值:String。 调用时执行以下步骤:

  1. 令 hour 为 ToZeroPaddedDecimalString(HourFromTime(tv), 2)。
  2. 令 minute 为 ToZeroPaddedDecimalString(MinuteFromTime(tv), 2)。
  3. 令 second 为 ToZeroPaddedDecimalString(SecondFromTime(tv), 2)。
  4. 返回 hour、":"、minute、":"、second、码元 0x0020 (SPACE) 和 "GMT" 的字符串连接。

21.4.4.41.2 DateString ( tv )

抽象操作 DateString,接收参数 tv (a Number, but not NaN);返回值:String。 调用时执行以下步骤:

  1. 令 weekday 为 表 61 中 WeekDay Index = WeekDay(tv) 的条目的 Name。
  2. 令 month 为 表 62 中 Month Index = MonthFromTime(tv) 的条目的 Name。
  3. 令 day 为 ToZeroPaddedDecimalString(DateFromTime(tv), 2)。
  4. 令 yv 为 YearFromTime(tv)。
  5. 如果 yv ≥ 0,则令 yearSign 为空 String;否则令 yearSign 为 "-"。
  6. 令 paddedYear 为 ToZeroPaddedDecimalString(abs(yv), 4)。
  7. 返回 weekday、码元 0x0020 (SPACE)、month、码元 0x0020 (SPACE)、day、码元 0x0020 (SPACE)、yearSign 和 paddedYear 的字符串连接。
表 61: 一周各日的名称
WeekDay 索引 名称
0 "Sun"
1 "Mon"
2 "Tue"
3 "Wed"
4 "Thu"
5 "Fri"
6 "Sat"
表 62: 一年各月的名称
Month 索引 名称
0 "Jan"
1 "Feb"
2 "Mar"
3 "Apr"
4 "May"
5 "Jun"
6 "Jul"
7 "Aug"
8 "Sep"
9 "Oct"
10 "Nov"
11 "Dec"

21.4.4.41.3 TimeZoneString ( tv )

抽象操作 TimeZoneString,接收参数 tv (整数 Number);返回值:String。 调用时执行以下步骤:

  1. 令 systemTimeZoneIdentifier 为 SystemTimeZoneIdentifier()。
  2. 如果 IsTimeZoneOffsetString(systemTimeZoneIdentifier) 是 true,则
    1. 令 offsetNanoseconds 为 ParseTimeZoneOffsetString(systemTimeZoneIdentifier)。
  3. 否则,
    1. 令 offsetNanoseconds 为 GetNamedTimeZoneOffsetNanoseconds(systemTimeZoneIdentifier, ℝ(tv) × NanosecondsPerMillisecond)。
  4. 令 offsetMilliseconds 为 truncate(offsetNanoseconds / NanosecondsPerMillisecond)。
  5. 如果 offsetMilliseconds ≥ 0,则
    1. 令 offsetSign 为 "+"。
    2. 令 absOffsetMilliseconds 为 offsetMilliseconds。
  6. 否则,
    1. 令 offsetSign 为 "-"。
    2. 令 absOffsetMilliseconds 为 -offsetMilliseconds。
  7. 令 offsetMinute 为 ToZeroPaddedDecimalString(MinuteFromTime(𝔽(absOffsetMilliseconds)), 2)。
  8. 令 offsetHour 为 ToZeroPaddedDecimalString(HourFromTime(𝔽(absOffsetMilliseconds)), 2)。
  9. 令 timeZoneName 为实现定义的字符串,它要么是空 String,要么是码元 0x0020 (SPACE)、码元 0x0028 (LEFT PARENTHESIS)、实现定义的时区名称和码元 0x0029 (RIGHT PARENTHESIS) 的字符串连接。
  10. 返回 offsetSign、offsetHour、offsetMinute 和 timeZoneName 的字符串连接。

21.4.4.41.4 ToDateString ( tv )

抽象操作 ToDateString,接收参数 tv ((整数 Number 或 NaN));返回值:String。 调用时执行以下步骤:

  1. 如果 tv 是 NaN,则返回 "Invalid Date"。
  2. 令 localTime 为 LocalTime(tv)。
  3. 返回 DateString(localTime)、码元 0x0020 (SPACE)、TimeString(localTime) 和 TimeZoneString(tv) 的字符串连接。

21.4.4.42 Date.prototype.toTimeString ( )

调用时,此方法执行以下步骤:

  1. 令 dateObj 为 this value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. 令 tv 为 dateObj.[[DateValue]]。
  4. 如果 tv 是 NaN,则返回 "Invalid Date"。
  5. 令 localTime 为 LocalTime(tv)。
  6. 返回 TimeString(localTime) 和 TimeZoneString(tv) 的字符串连接。

21.4.4.43 Date.prototype.toUTCString ( )

此方法返回表示与 this value 对应的时间瞬间的 String 值。该 String 的格式基于 RFC 7231 中的 HTTP-date,并推广为支持 ECMAScript Date 所支持的完整时间范围。

调用时,它执行以下步骤:

  1. 令 dateObj 为 this value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. 令 tv 为 dateObj.[[DateValue]]。
  4. 如果 tv 是 NaN,则返回 "Invalid Date"。
  5. 令 weekday 为 表 61 中 WeekDay Index = WeekDay(tv) 的条目的 Name。
  6. 令 month 为 表 62 中 Month Index = MonthFromTime(tv) 的条目的 Name。
  7. 令 day 为 ToZeroPaddedDecimalString(DateFromTime(tv), 2)。
  8. 令 yv 为 YearFromTime(tv)。
  9. 如果 yv ≥ 0,则令 yearSign 为空 String;否则令 yearSign 为 "-"。
  10. 令 paddedYear 为 ToZeroPaddedDecimalString(abs(yv), 4)。
  11. 返回 weekday、","、码元 0x0020 (SPACE)、day、码元 0x0020 (SPACE)、month、码元 0x0020 (SPACE)、yearSign、paddedYear、码元 0x0020 (SPACE) 和 TimeString(tv) 的字符串连接。

21.4.4.44 Date.prototype.valueOf ( )

调用时,此方法执行以下步骤:

  1. 令 dateObj 为 this value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. 返回 dateObj.[[DateValue]]。

21.4.4.45 Date.prototype [ %Symbol.toPrimitive% ] ( hint )

ECMAScript 语言运算符会调用此方法,将 Date 转换为原始值。hint 允许的值是 "default"、"number" 和 "string"。Date 在内置 ECMAScript 对象中是独特的,因为它们将 "default" 视为等价于 "string";所有其他内置 ECMAScript 对象都将 "default" 视为等价于 "number"。

调用时,它执行以下步骤:

  1. 令 obj 为 this value。
  2. 如果 obj 不是 Object,则抛出 TypeError 异常。
  3. 如果 hint 是 "string" 或 "default",则
    1. 令 tryFirst 为 string。
  4. 否则如果 hint 是 "number",则
    1. 令 tryFirst 为 number。
  5. 否则,
    1. 抛出 TypeError 异常。
  6. 返回 ? OrdinaryToPrimitive(obj, tryFirst)。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

此方法的 "name" 属性值是 "[Symbol.toPrimitive]"。

21.4.5 Date 实例的属性

Date 实例是从 Date 原型对象继承属性的普通对象。Date 实例还具有 [[DateValue]] 内部槽。[[DateValue]] 内部槽是此 Date 表示的时间值。

22 文本处理

22.1 String 对象

22.1.1 String 构造函数

String 构造函数:

  • 是 %String%。
  • 是全局对象的 "String" 属性的初始值。
  • 作为构造函数调用时,创建并初始化新的 String 对象。
  • 作为函数而不是构造函数调用时执行类型转换。
  • 可以用作类定义的 extends 子句的值。希望继承指定 String 行为的子类构造函数必须包含对 String 构造函数的 super 调用,以创建并初始化具有 [[StringData]] 内部槽的子类实例。

22.1.1.1 String ( value )

调用时,此函数执行以下步骤:

  1. 如果不存在 value,则
    1. 令 string 为空 String。
  2. 否则,
    1. 如果 NewTarget 是 undefined 且 value 是 Symbol,则返回 SymbolDescriptiveString(value)。
    2. 令 string 为 ? ToString(value)。
  3. 如果 NewTarget 是 undefined,则返回 string。
  4. 返回 StringCreate(string, ? GetPrototypeFromConstructor(NewTarget, "%String.prototype%"))。

22.1.2 String 构造函数的属性

String 构造函数:

22.1.2.1 String.fromCharCode ( ...codeUnits )

可以使用任意数量的参数调用此函数,这些参数构成剩余参数 codeUnits。

调用时,它执行以下步骤:

  1. 令 result 为空 String。
  2. 对 codeUnits 的每个元素 next,执行
    1. 令 nextCU 为数值等于 ℝ(? ToUint16(next)) 的码元。
    2. 将 result 设置为 result 和 nextCU 的字符串连接。
  3. 返回 result。

此函数的 "length" 属性是 1𝔽。

22.1.2.2 String.fromCodePoint ( ...codePoints )

可以使用任意数量的参数调用此函数,这些参数构成剩余参数 codePoints。

调用时,它执行以下步骤:

  1. 令 result 为空 String。
  2. 对 codePoints 的每个元素 next,执行
    1. 令 nextCP 为 ? ToNumber(next)。
    2. 如果 nextCP 不是整数 Number,则抛出 RangeError 异常。
    3. 如果 ℝ(nextCP) < 0 或 ℝ(nextCP) > 0x10FFFF,则抛出 RangeError 异常。
    4. 将 result 设置为 result 和 UTF16EncodeCodePoint(ℝ(nextCP)) 的字符串连接。
  3. 断言:如果 codePoints 为空,则 result 为空 String。
  4. 返回 result。

此函数的 "length" 属性是 1𝔽。

22.1.2.3 String.prototype

String.prototype 的初始值是 String 原型对象。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

22.1.2.4 String.raw ( template, ...substitutions )

可以使用可变数量的参数调用此函数。第一个参数是 template,其余参数构成 List substitutions。

调用时,它执行以下步骤:

  1. 令 substitutionCount 为 substitutions 中的元素数量。
  2. 令 cooked 为 ? ToObject(template)。
  3. 令 literals 为 ? ToObject(? Get(cooked, "raw")).
  4. 令 literalCount 为 ? LengthOfArrayLike(literals)。
  5. 如果 literalCount ≤ 0,则返回空 String。
  6. 令 result 为空 String。
  7. 令 nextIndex 为 0。
  8. 重复执行,
    1. 令 nextLiteralValue 为 ? Get(literals, ! ToString(𝔽(nextIndex)))。
    2. 令 nextLiteral 为 ? ToString(nextLiteralValue)。
    3. 将 result 设置为 result 和 nextLiteral 的字符串连接。
    4. 如果 nextIndex + 1 = literalCount,则返回 result。
    5. 如果 nextIndex < substitutionCount,则
      1. 令 nextSubValue 为 substitutions[nextIndex]。
      2. 令 nextSub 为 ? ToString(nextSubValue)。
      3. 将 result 设置为 result 和 nextSub 的字符串连接。
    6. 将 nextIndex 设置为 nextIndex + 1。
注

此函数旨在用作带标签模板(13.3.11)的标签函数。以这种方式调用时,第一个参数将是格式良好的模板对象,而剩余参数将包含替换值。

22.1.3 String 原型对象的属性

String 原型对象:

  • 是 %String.prototype%。
  • 是 String 异质对象,并具有为此类对象规定的内部方法。
  • 具有 [[StringData]] 内部槽,其值为空 String。
  • 具有 "length" 属性,其初始值为 +0𝔽,并具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。
  • 具有 [[Prototype]] 内部槽,其值是 %Object.prototype%。

除非另有明确说明,下面定义的 String 原型对象的方法不是通用方法,传递给它们的 this value 必须是 String 值,或者是具有已初始化为 String 值的 [[StringData]] 内部槽的对象。

22.1.3.1 String.prototype.at ( index )

  1. 令 thisValue 为 this value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. 令 string 为 ? ToString(thisValue)。
  4. 令 length 为 string 的长度。
  5. 令 k 为 ? ToAbsoluteIndex(index, length)。
  6. 如果 k < 0 或 k ≥ length,则返回 undefined。
  7. 返回 string 从 k 到 k + 1 的子字符串。

22.1.3.2 String.prototype.charAt ( position )

注 1

此方法返回一个单元素 String,其中包含将此对象转换为 String 后所得 String 值中索引 position 处的码元。如果该索引处没有元素,则结果为空 String。结果是 String 值,而不是 String 对象。

如果 pos 是整数 Number,则 x.charAt(pos) 的结果等价于 x.substring(pos, pos + 1) 的结果。

调用时,此方法执行以下步骤:

  1. 令 thisValue 为 this value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. 令 string 为 ? ToString(thisValue)。
  4. 将 position 设置为 ? ToIntegerOrInfinity(position)。
  5. 令 size 为 string 的长度。
  6. 如果 position < 0 或 position ≥ size,则返回空 String。
  7. 返回 string 从 position 到 position + 1 的子字符串。
注 2

此方法有意设计为通用方法;它不要求其 this value 是 String 对象。因此,它可以被转移到其他种类的对象上用作方法。

22.1.3.3 String.prototype.charCodeAt ( position )

注 1

此方法返回一个 Number(小于 216 的非负整数 Number),它是将此对象转换为 String 后所得 String 中索引 position 处码元的数值。如果该索引处没有元素,则结果是 NaN。

调用时,此方法执行以下步骤:

  1. 令 thisValue 为 this value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. 令 string 为 ? ToString(thisValue)。
  4. 将 position 设置为 ? ToIntegerOrInfinity(position)。
  5. 令 size 为 string 的长度。
  6. 如果 position < 0 或 position ≥ size,则返回 NaN。
  7. 返回 String string 中索引 position 处码元数值的 Number 值。
注 2

此方法有意设计为通用方法;它不要求其 this value 是 String 对象。因此,它可以被转移到其他种类的对象上用作方法。

22.1.3.4 String.prototype.codePointAt ( position )

注 1

此方法返回一个不大于 0x10FFFF𝔽 的非负整数 Number,它是从将此对象转换为 String 后所得 String 中索引 position 处字符串元素开始的 UTF-16 编码码点(6.1.4)的数值。如果该索引处没有元素,则结果是 undefined。如果有效的 UTF-16 代理对没有从 position 开始,则结果是 position 处的码元。

调用时,此方法执行以下步骤:

  1. 令 thisValue 为 this value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. 令 string 为 ? ToString(thisValue)。
  4. 将 position 设置为 ? ToIntegerOrInfinity(position)。
  5. 令 size 为 string 的长度。
  6. 如果 position < 0 或 position ≥ size,则返回 undefined。
  7. 令 codePoint 为 CodePointAt(string, position)。
  8. 返回 𝔽(codePoint.[[CodePoint]])。
注 2

此方法有意设计为通用方法;它不要求其 this value 是 String 对象。因此,它可以被转移到其他种类的对象上用作方法。

22.1.3.5 String.prototype.concat ( ...args )

注 1

调用此方法时,它返回由 this value(转换为 String)的码元,后接转换为 String 的每个参数的码元所组成的 String 值。结果是 String 值,而不是 String 对象。

调用时,此方法执行以下步骤:

  1. 令 thisValue 为 this value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. 令 string 为 ? ToString(thisValue)。
  4. 令 result 为 string。
  5. 对 args 的每个元素 next,执行
    1. 令 nextString 为 ? ToString(next)。
    2. 将 result 设置为 result 和 nextString 的字符串连接。
  6. 返回 result。

此方法的 "length" 属性是 1𝔽。

注 2

此方法有意设计为通用方法;它不要求其 this value 是 String 对象。因此,它可以被转移到其他种类的对象上用作方法。

22.1.3.6 String.prototype.constructor

String.prototype.constructor 的初始值是 %String%。

22.1.3.7 String.prototype.endsWith ( searchString [ , endPosition ] )

调用时,此方法执行以下步骤:

  1. 令 thisValue 为 this value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. 令 string 为 ? ToString(thisValue)。
  4. 令 isRegexp 为 ? IsRegExp(searchString)。
  5. 如果 isRegexp 是 true,则抛出 TypeError 异常。
  6. 将 searchString 设置为 ? ToString(searchString)。
  7. 令 length 为 string 的长度。
  8. 如果 endPosition 是 undefined,则令 end 为 length;否则令 end 为将 ? ToIntegerOrInfinity(endPosition) 限制在 0 和 length 之间的结果。
  9. 令 searchLength 为 searchString 的长度。
  10. 如果 searchLength = 0,则返回 true。
  11. 令 start 为 end - searchLength。
  12. 如果 start < 0,则返回 false。
  13. 令 substring 为 string 从 start 到 end 的子字符串。
  14. 如果 substring 是 searchString,则返回 true。
  15. 返回 false。
注 1

规定当第一个参数是 RegExp 时抛出异常,是为了允许未来版本定义允许此类参数值的扩展。

注 2

此方法有意设计为通用方法;它不要求其 this value 是 String 对象。因此,它可以被转移到其他种类的对象上用作方法。

22.1.3.8 String.prototype.includes ( searchString [ , position ] )

调用时,此方法执行以下步骤:

  1. 令 thisValue 为 this value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. 令 string 为 ? ToString(thisValue)。
  4. 令 isRegexp 为 ? IsRegExp(searchString)。
  5. 如果 isRegexp 是 true,则抛出 TypeError 异常。
  6. 将 searchString 设置为 ? ToString(searchString)。
  7. 令 length 为 string 的长度。
  8. 令 start 为将 ? ToIntegerOrInfinity(position) 限制在 0 和 length 之间的结果。
  9. 断言:如果 position 是 undefined,则 start 为 0。
  10. 令 index 为 StringIndexOf(string, searchString, start)。
  11. 如果 index 是 not-found,则返回 false。
  12. 返回 true。
注 1

如果 searchString 作为将此对象转换为 String 所得结果的子字符串,出现在一个或多个大于或等于 position 的索引处,则此函数返回 true;否则返回 false。如果 position 是 undefined,则假定为 0,从而搜索整个 String。

注 2

规定当第一个参数是 RegExp 时抛出异常,是为了允许未来版本定义允许此类参数值的扩展。

注 3

此方法有意设计为通用方法;它不要求其 this value 是 String 对象。因此,它可以被转移到其他种类的对象上用作方法。

22.1.3.9 String.prototype.indexOf ( searchString [ , position ] )

注 1

如果 searchString 作为将此对象转换为 String 所得结果的子字符串,出现在一个或多个大于或等于 position 的索引处,则返回其中最小的索引;否则返回 -1𝔽。如果 position 是 undefined,则假定为 +0𝔽,从而搜索整个 String。

调用时,此方法执行以下步骤:

  1. 令 thisValue 为 this value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. 令 string 为 ? ToString(thisValue)。
  4. 将 searchString 设置为 ? ToString(searchString)。
  5. 令 length 为 string 的长度。
  6. 令 start 为将 ? ToIntegerOrInfinity(position) 限制在 0 和 length 之间的结果。
  7. 断言:如果 position 是 undefined,则 start 为 0。
  8. 令 result 为 StringIndexOf(string, searchString, start)。
  9. 如果 result 是 not-found,则返回 -1𝔽。
  10. 返回 𝔽(result)。
注 2

此方法有意设计为通用方法;它不要求其 this value 是 String 对象。因此,它可以被转移到其他种类的对象上用作方法。

22.1.3.10 String.prototype.isWellFormed ( )

调用时,此方法执行以下步骤:

  1. 令 thisValue 为 this value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. 令 string 为 ? ToString(thisValue)。
  4. 返回 IsStringWellFormedUnicode(string)。

22.1.3.11 String.prototype.lastIndexOf ( searchString [ , position ] )

注 1

如果 searchString 作为将此对象转换为 String 所得结果的子字符串,出现在一个或多个小于或等于 position 的索引处,则返回其中最大的索引;否则返回 -1𝔽。如果 position 是 undefined,则假定为 String 值的长度,从而搜索整个 String。

调用时,此方法执行以下步骤:

  1. 令 thisValue 为 this value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. 令 string 为 ? ToString(thisValue)。
  4. 将 searchString 设置为 ? ToString(searchString)。
  5. 令 numberPosition 为 ? ToNumber(position)。
  6. 令 length 为 string 的长度。
  7. 令 searchLength 为 searchString 的长度。
  8. 令 maxStart 为 length - searchLength。
  9. 如果 maxStart < 0,则返回 -1𝔽。
  10. 如果 numberPosition 是 NaN,则令 start 为 maxStart;否则令 start 为将 ! ToIntegerOrInfinity(numberPosition) 限制在 0 和 maxStart 之间的结果。
  11. 断言:如果 position 是 undefined,则 start 是 maxStart。
  12. 令 result 为 StringLastIndexOf(string, searchString, start)。
  13. 如果 result 是 not-found,则返回 -1𝔽。
  14. 返回 𝔽(result)。
注 2

此方法有意设计为通用方法;它不要求其 this value 是 String 对象。因此,它可以被转移到其他种类的对象上用作方法。

22.1.3.12 String.prototype.localeCompare ( that [ , reserved1 [ , reserved2 ] ] )

包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按照 ECMA-402 的规定实现此方法。否则,使用以下此方法的规范:

此方法返回一个不是 NaN 的 Number,用于表示 this value(转换为 String string)与 that(转换为 String thatValue)之间由实现定义、对区域设置敏感的 String 比较结果。结果旨在对应根据宿主环境当前区域设置惯例对 String 值进行的排序顺序;当 string 排在 thatValue 之前时结果为负,当 string 排在 thatValue 之后时结果为正,在其他所有情况下结果为零(表示 string 与 thatValue 之间没有相对排序)。

执行比较之前,此方法执行以下步骤来准备 Strings:

  1. 令 thisValue 为 this value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. 令 string 为 ? ToString(thisValue)。
  4. 令 thatValue 为 ? ToString(that)。

此方法第二个和第三个可选参数的含义定义于 ECMA-402;不包含 ECMA-402 支持的实现不得为这些参数位置赋予任何其他解释。

实际返回值由实现定义,以允许在其中编码其他信息;但将此方法视为接受两个参数的方法时,要求它是一个一致的比较器,在所有 String 的集合上定义全序。还要求此方法识别并遵守 Unicode 标准中的规范等价,包括在比较可区分但规范等价的 Strings 时返回 +0𝔽。

注 1

此方法本身并不直接适合作为 Array.prototype.sort 的参数,因为后者要求一个接受两个参数的函数。

注 2

此方法可以依赖 ECMAScript 环境从宿主环境获得的任何语言和/或区域设置敏感比较功能,并旨在按照宿主环境当前区域设置的惯例进行比较。不过,无论比较能力如何,此方法都必须按照 Unicode 标准识别并遵守规范等价——例如,以下比较都必须返回 +0𝔽:

// Å ANGSTROM SIGN 与
// Å LATIN CAPITAL LETTER A + COMBINING RING ABOVE
"\u212B".localeCompare("A\u030A")

// Ω OHM SIGN 与
// Ω GREEK CAPITAL LETTER OMEGA
"\u2126".localeCompare("\u03A9")

// ṩ LATIN SMALL LETTER S WITH DOT BELOW AND DOT ABOVE 与
// ṩ LATIN SMALL LETTER S + COMBINING DOT ABOVE + COMBINING DOT BELOW
"\u1E69".localeCompare("s\u0307\u0323")

// ḍ̇ LATIN SMALL LETTER D WITH DOT ABOVE + COMBINING DOT BELOW 与
// ḍ̇ LATIN SMALL LETTER D WITH DOT BELOW + COMBINING DOT ABOVE
"\u1E0B\u0323".localeCompare("\u1E0D\u0307")

// 가 HANGUL CHOSEONG KIYEOK + HANGUL JUNGSEONG A 与
// 가 HANGUL SYLLABLE GA
"\u1100\u1161".localeCompare("\uAC00")

有关规范等价的定义和讨论,请参见 Unicode 标准第 2 章和第 3 章,以及 Unicode Standard Annex #15, Unicode Normalization Forms 和 Unicode Technical Note #5, Canonical Equivalence in Applications。另请参见 Unicode Technical Standard #10, Unicode Collation Algorithm。

建议此方法不遵守 Unicode 标准第 3 章第 3.7 节所定义的 Unicode 兼容等价或兼容分解。

注 3

此方法有意设计为通用方法;它不要求其 this value 是 String 对象。因此,它可以被转移到其他种类的对象上用作方法。

22.1.3.13 String.prototype.match ( regexpOrPattern )

调用时,此方法执行以下步骤:

  1. 令 thisValue 为 this value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. 如果 regexpOrPattern 是 Object,则
    1. 令 matcher 为 ? GetMethod(regexpOrPattern, %Symbol.match%)。
    2. 如果 matcher 不是 undefined,则
      1. 返回 ? Call(matcher, regexpOrPattern, « thisValue »)。
  4. 令 string 为 ? ToString(thisValue)。
  5. 令 regexp 为 ? RegExpCreate(regexpOrPattern, undefined)。
  6. 返回 ? Invoke(regexp, %Symbol.match%, « string »)。
注

此方法有意设计为通用方法;它不要求其 this value 是 String 对象。因此,它可以被转移到其他种类的对象上用作方法。

22.1.3.14 String.prototype.matchAll ( regexpOrPattern )

此方法使用 regexpOrPattern 对表示 this value 的 String 执行正则表达式匹配,并返回一个生成匹配结果的迭代器。每个匹配结果都是一个 Array,第一个元素是 String 中匹配的部分,后续元素是任何捕获组所匹配的部分。如果正则表达式从未匹配,则返回的迭代器不会生成任何匹配结果。

调用时,它执行以下步骤:

  1. 令 thisValue 为 this value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. 如果 regexpOrPattern 是 Object,则
    1. 令 isRegexp 为 ? IsRegExp(regexpOrPattern)。
    2. 如果 isRegexp 是 true,则
      1. 令 flags 为 ? Get(regexpOrPattern, "flags")。
      2. 执行 ? RequireObjectCoercible(flags)。
      3. 如果 ? ToString(flags) 不包含 "g",则抛出 TypeError 异常。
    3. 令 matcher 为 ? GetMethod(regexpOrPattern, %Symbol.matchAll%)。
    4. 如果 matcher 不是 undefined,则
      1. 返回 ? Call(matcher, regexpOrPattern, « thisValue »)。
  4. 令 string 为 ? ToString(thisValue)。
  5. 令 regexp 为 ? RegExpCreate(regexpOrPattern, "g")。
  6. 返回 ? Invoke(regexp, %Symbol.matchAll%, « string »)。
注 1
此方法有意设计为通用方法,它不要求其 this value 是 String 对象。因此,它可以被转移到其他种类的对象上用作方法。
注 2
与 String.prototype.split 类似,String.prototype.matchAll 被设计为通常不会修改其输入。

22.1.3.15 String.prototype.normalize ( [ form ] )

调用时,此方法执行以下步骤:

  1. 令 thisValue 为 this value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. 令 string 为 ? ToString(thisValue)。
  4. 如果 form 是 undefined,则将 form 设置为 "NFC"。
  5. 否则,将 form 设置为 ? ToString(form)。
  6. 如果 form 不是 "NFC"、"NFD"、"NFKC" 或 "NFKD" 之一,则抛出 RangeError 异常。
  7. 令 normal 为按照最新 Unicode 标准,Normalization Forms 中的规定,将 string 规范化为由 form 命名的规范化形式所得的 String 值。
  8. 返回 normal。
注

此方法有意设计为通用方法;它不要求其 this value 是 String 对象。因此,它可以被转移到其他种类的对象上用作方法。

22.1.3.16 String.prototype.padEnd ( maxLength [ , fillString ] )

调用时,此方法执行以下步骤:

  1. 令 thisValue 为 this value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. 返回 ? StringPaddingBuiltinsImpl(thisValue, maxLength, fillString, end)。

22.1.3.17 String.prototype.padStart ( maxLength [ , fillString ] )

调用时,此方法执行以下步骤:

  1. 令 thisValue 为 this value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. 返回 ? StringPaddingBuiltinsImpl(thisValue, maxLength, fillString, start)。

22.1.3.17.1 StringPaddingBuiltinsImpl ( thisValue, maxLength, fillString, placement )

抽象操作 StringPaddingBuiltinsImpl,接收参数 thisValue (ECMAScript 语言值)、maxLength (ECMAScript 语言值)、fillString (ECMAScript 语言值) 和 placement ((start 或 end));返回值:(正常完成 (值:String) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 string 为 ? ToString(thisValue)。
  2. 令 intMaxLength 为 ℝ(? ToLength(maxLength))。
  3. 令 stringLength 为 string 的长度。
  4. 如果 intMaxLength ≤ stringLength,则返回 string。
  5. 如果 fillString 是 undefined,则将 fillString 设置为仅由码元 0x0020 (SPACE) 组成的 String 值。
  6. 否则,将 fillString 设置为 ? ToString(fillString)。
  7. 返回 StringPad(string, intMaxLength, fillString, placement)。

22.1.3.17.2 StringPad ( string, maxLength, fillString, placement )

抽象操作 StringPad,接收参数 string (String)、maxLength (非负整数)、fillString (String) 和 placement ((start 或 end));返回值:String。 调用时执行以下步骤:

  1. 令 stringLength 为 string 的长度。
  2. 如果 maxLength ≤ stringLength,则返回 string。
  3. 如果 fillString 是空 String,则返回 string。
  4. 令 fillLength 为 maxLength - stringLength。
  5. 令 truncatedStringFiller 为由 fillString 的重复连接组成并截断到长度 fillLength 的 String 值。
  6. 如果 placement 是 start,则返回 truncatedStringFiller 和 string 的字符串连接。
  7. 返回 string 和 truncatedStringFiller 的字符串连接。
注 1

参数 maxLength 将被限制,使其不能小于 string 的长度。

注 2

参数 fillString 默认为 " "(由码元 0x0020 SPACE 组成的 String 值)。

22.1.3.17.3 ToZeroPaddedDecimalString ( n, minLength )

抽象操作 ToZeroPaddedDecimalString,接收参数 n (非负整数) 和 minLength (非负整数);返回值:String。 调用时执行以下步骤:

  1. 令 string 为 n 的 String 表示,并格式化为十进制数。
  2. 返回 StringPad(string, minLength, "0", start)。

22.1.3.18 String.prototype.repeat ( count )

调用时,此方法执行以下步骤:

  1. 令 thisValue 为 this value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. 令 string 为 ? ToString(thisValue)。
  4. 令 n 为 ? ToIntegerOrInfinity(count)。
  5. 如果 n < 0 或 n = +∞,则抛出 RangeError 异常。
  6. 如果 n = 0,则返回空 String。
  7. 返回由 n 份 string 依次追加组成的 String 值。
注 1

此方法创建由 this value(转换为 String)的码元重复 count 次组成的 String 值。

注 2

此方法有意设计为通用方法;它不要求其 this value 是 String 对象。因此,它可以被转移到其他种类的对象上用作方法。

22.1.3.19 String.prototype.replace ( searchValue, replaceValue )

调用时,此方法执行以下步骤:

  1. 令 thisValue 为 this value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. 如果 searchValue 是 Object,则
    1. 令 replacer 为 ? GetMethod(searchValue, %Symbol.replace%)。
    2. 如果 replacer 不是 undefined,则
      1. 返回 ? Call(replacer, searchValue, « thisValue, replaceValue »)。
  4. 令 string 为 ? ToString(thisValue)。
  5. 令 searchString 为 ? ToString(searchValue)。
  6. 令 functionalReplace 为 IsCallable(replaceValue)。
  7. 如果 functionalReplace 是 false,则
    1. 将 replaceValue 设置为 ? ToString(replaceValue)。
  8. 令 searchLength 为 searchString 的长度。
  9. 令 position 为 StringIndexOf(string, searchString, 0)。
  10. 如果 position 是 not-found,则返回 string。
  11. 令 preceding 为 string 从 0 到 position 的子字符串。
  12. 令 following 为 string 从 position + searchLength 开始的子字符串。
  13. 如果 functionalReplace 是 true,则
    1. 令 replacement 为 ? ToString(? Call(replaceValue, undefined, « searchString, 𝔽(position), string »))。
  14. 否则,
    1. 断言:replaceValue 是 String。
    2. 令 captures 为新的空 List。
    3. 令 replacement 为 ! GetSubstitution(searchString, string, position, captures, undefined, replaceValue)。
  15. 返回 preceding、replacement 和 following 的字符串连接。
注

此方法有意设计为通用方法;它不要求其 this value 是 String 对象。因此,它可以被转移到其他种类的对象上用作方法。

22.1.3.19.1 GetSubstitution ( matched, string, position, captures, namedCaptures, replacementTemplate )

抽象操作 GetSubstitution,接收参数 matched (String)、string (String)、position (非负整数)、captures (列表 (元素:(String 或 undefined)))、namedCaptures ((Object 或 undefined)) 和 replacementTemplate (String);返回值:(正常完成 (值:String) 或 抛出完成)。 就此抽象操作而言,十进制数字是从 0x0030 (DIGIT ZERO) 到 0x0039 (DIGIT NINE) 闭区间内的码元。 调用时执行以下步骤:

  1. 令 stringLength 为 string 的长度。
  2. 断言:position ≤ stringLength。
  3. 令 result 为空 String。
  4. 令 templateRemainder 为 replacementTemplate。
  5. 当 templateRemainder 不是空 String 时,重复执行,
    1. 注:以下步骤会分离出 ref(templateRemainder 的一个前缀),确定 refReplacement(其替换值),然后将该替换值追加到 result。
    2. 如果 templateRemainder 以 "$$" 开头,则
      1. 令 ref 为 "$$"。
      2. 令 refReplacement 为 "$"。
    3. 否则如果 templateRemainder 以 "$`" 开头,则
      1. 令 ref 为 "$`"。
      2. 令 refReplacement 为 string 从 0 到 position 的子字符串。
    4. 否则如果 templateRemainder 以 "$&" 开头,则
      1. 令 ref 为 "$&"。
      2. 令 refReplacement 为 matched。
    5. 否则如果 templateRemainder 以 "$'"(0x0024 (DOLLAR SIGN) 后跟 0x0027 (APOSTROPHE))开头,则
      1. 令 ref 为 "$'"。
      2. 令 matchLength 为 matched 的长度。
      3. 令 tailPosition 为 position + matchLength。
      4. 令 refReplacement 为 string 从 min(tailPosition, stringLength) 开始的子字符串。
      5. 注:只有当此抽象操作由对某对象调用 %RegExp.prototype% 的内在 %Symbol.replace% 方法,而该对象的 "exec" 属性不是内在 %RegExp.prototype.exec% 时,tailPosition 才可能超过 stringLength。
    6. 否则如果 templateRemainder 以 "$" 后跟 1 个或多个十进制数字开头,则
      1. 如果 templateRemainder 以 "$" 后跟 2 个或更多十进制数字开头,则令 digitCount 为 2;否则令 digitCount 为 1。
      2. 令 digits 为 templateRemainder 从 1 到 1 + digitCount 的子字符串。
      3. 令 index 为 ℝ(StringToNumber(digits))。
      4. 断言:0 ≤ index ≤ 99。
      5. 令 captureLength 为 captures 中的元素数量。
      6. 如果 index > captureLength 且 digitCount = 2,则
        1. 注:当两位替换模式指定的索引超过捕获组数量时,它会被视为一位替换模式,后跟一个字面数字。
        2. 将 digitCount 设置为 1。
        3. 将 digits 设置为 digits 从 0 到 1 的子字符串。
        4. 将 index 设置为 ℝ(StringToNumber(digits))。
      7. 令 ref 为 templateRemainder 从 0 到 1 + digitCount 的子字符串。
      8. 如果 1 ≤ index ≤ captureLength,则
        1. 令 capture 为 captures[index - 1]。
        2. 如果 capture 是 undefined,则
          1. 令 refReplacement 为空 String。
        3. 否则,
          1. 令 refReplacement 为 capture。
      9. 否则,
        1. 令 refReplacement 为 ref。
    7. 否则如果 templateRemainder 以 "$<" 开头,则
      1. 令 gtPosition 为 StringIndexOf(templateRemainder, ">", 0)。
      2. 如果 gtPosition 是 not-found 或 namedCaptures 是 undefined,则
        1. 令 ref 为 "$<"。
        2. 令 refReplacement 为 ref。
      3. 否则,
        1. 令 ref 为 templateRemainder 从 0 到 gtPosition + 1 的子字符串。
        2. 令 groupName 为 templateRemainder 从 2 到 gtPosition 的子字符串。
        3. 断言:namedCaptures 是 Object。
        4. 令 capture 为 ? Get(namedCaptures, groupName)。
        5. 如果 capture 是 undefined,则
          1. 令 refReplacement 为空 String。
        6. 否则,
          1. 令 refReplacement 为 ? ToString(capture)。
    8. 否则,
      1. 令 ref 为 templateRemainder 从 0 到 1 的子字符串。
      2. 令 refReplacement 为 ref。
    9. 令 refLength 为 ref 的长度。
    10. 将 templateRemainder 设置为 templateRemainder 从 refLength 开始的子字符串。
    11. 将 result 设置为 result 和 refReplacement 的字符串连接。
  6. 返回 result。

22.1.3.20 String.prototype.replaceAll ( searchValue, replaceValue )

调用时,此方法执行以下步骤:

  1. 令 thisValue 为 this value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. 如果 searchValue 是 Object,则
    1. 令 isRegexp 为 ? IsRegExp(searchValue)。
    2. 如果 isRegexp 是 true,则
      1. 令 flags 为 ? Get(searchValue, "flags")。
      2. 执行 ? RequireObjectCoercible(flags)。
      3. 如果 ? ToString(flags) 不包含 "g",则抛出 TypeError 异常。
    3. 令 replacer 为 ? GetMethod(searchValue, %Symbol.replace%)。
    4. 如果 replacer 不是 undefined,则
      1. 返回 ? Call(replacer, searchValue, « thisValue, replaceValue »)。
  4. 令 string 为 ? ToString(thisValue)。
  5. 令 searchString 为 ? ToString(searchValue)。
  6. 令 functionalReplace 为 IsCallable(replaceValue)。
  7. 如果 functionalReplace 是 false,则
    1. 将 replaceValue 设置为 ? ToString(replaceValue)。
  8. 令 searchLength 为 searchString 的长度。
  9. 令 advanceBy 为 max(1, searchLength)。
  10. 令 matchPositions 为新的空 List。
  11. 令 position 为 StringIndexOf(string, searchString, 0)。
  12. 当 position 不是 not-found 时,重复执行,
    1. 将 position 追加到 matchPositions。
    2. 将 position 设置为 StringIndexOf(string, searchString, position + advanceBy)。
  13. 令 endOfLastMatch 为 0。
  14. 令 result 为空 String。
  15. 对 matchPositions 的每个元素 matchPosition,执行
    1. 令 preserved 为 string 从 endOfLastMatch 到 matchPosition 的子字符串。
    2. 如果 functionalReplace 是 true,则
      1. 令 replacement 为 ? ToString(? Call(replaceValue, undefined, « searchString, 𝔽(matchPosition), string »))。
    3. 否则,
      1. 断言:replaceValue 是 String。
      2. 令 captures 为新的空 List。
      3. 令 replacement 为 ! GetSubstitution(searchString, string, matchPosition, captures, undefined, replaceValue)。
    4. 将 result 设置为 result、preserved 和 replacement 的字符串连接。
    5. 将 endOfLastMatch 设置为 matchPosition + searchLength。
  16. 如果 endOfLastMatch < string 的长度,则
    1. 将 result 设置为 result 和 string 从 endOfLastMatch 开始的子字符串的字符串连接。
  17. 返回 result。

22.1.3.21 String.prototype.search ( regexpOrPattern )

调用时,此方法执行以下步骤:

  1. 令 thisValue 为 this value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. 如果 regexpOrPattern 是 Object,则
    1. 令 searcher 为 ? GetMethod(regexpOrPattern, %Symbol.search%)。
    2. 如果 searcher 不是 undefined,则
      1. 返回 ? Call(searcher, regexpOrPattern, « thisValue »)。
  4. 令 string 为 ? ToString(thisValue)。
  5. 令 regexp 为 ? RegExpCreate(regexpOrPattern, undefined)。
  6. 返回 ? Invoke(regexp, %Symbol.search%, « string »)。
注

此方法有意设计为通用方法;它不要求其 this value 是 String 对象。因此,它可以被转移到其他种类的对象上用作方法。

22.1.3.22 String.prototype.slice ( start, end )

此方法返回将此对象转换为 String 所得结果的一个子字符串,从索引 start 开始,到 String 的索引 end 之前结束(如果 end 是 undefined,则一直到 String 末尾)。如果 start 为负,则将其视为 sourceLength + start,其中 sourceLength 是 String 的长度。如果 end 为负,则将其视为 sourceLength + end,其中 sourceLength 是 String 的长度。结果是 String 值,而不是 String 对象。

调用时,它执行以下步骤:

  1. 令 thisValue 为 this value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. 令 string 为 ? ToString(thisValue)。
  4. 令 length 为 string 的长度。
  5. 令 from 为 ? ToClampedIndex(start, length)。
  6. 如果 end 是 undefined,则令 to 为 length;否则令 to 为 ? ToClampedIndex(end, length)。
  7. 如果 from ≥ to,则返回空 String。
  8. 返回 string 从 from 到 to 的子字符串。
注

此方法有意设计为通用方法;它不要求其 this value 是 String 对象。因此,它可以被转移到其他种类的对象上用作方法。

22.1.3.23 String.prototype.split ( separator, limit )

此方法返回一个 Array,其中存储了将此对象转换为 String 所得结果的子字符串。通过从左到右搜索 separator 的出现位置来确定这些子字符串;这些出现位置不属于返回数组中的任何 String,而是用于分割 String 值。separator 的值可以是任意长度的 String,也可以是具有 %Symbol.split% 方法的对象,例如 RegExp。

调用时,它执行以下步骤:

  1. 令 thisValue 为 this value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. 如果 separator 是 Object,则
    1. 令 splitter 为 ? GetMethod(separator, %Symbol.split%)。
    2. 如果 splitter 不是 undefined,则
      1. 返回 ? Call(splitter, separator, « thisValue, limit »)。
  4. 令 string 为 ? ToString(thisValue)。
  5. 如果 limit 是 undefined,则令 lim 为 232 - 1;否则令 lim 为 ℝ(? ToUint32(limit))。
  6. 令 separatorString 为 ? ToString(separator)。
  7. 如果 lim = 0,则
    1. 返回 CreateArrayFromList(« »)。
  8. 如果 separator 是 undefined,则
    1. 返回 CreateArrayFromList(« string »)。
  9. 令 separatorLength 为 separatorString 的长度。
  10. 如果 separatorLength = 0,则
    1. 令 stringLength 为 string 的长度。
    2. 令 outLength 为将 lim 限制在 0 和 stringLength 之间的结果。
    3. 令 head 为 string 从 0 到 outLength 的子字符串。
    4. 令 codeUnits 为由 head 的元素所组成的码元序列构成的 List。
    5. 返回 CreateArrayFromList(codeUnits)。
  11. 如果 string 是空 String,则返回 CreateArrayFromList(« string »)。
  12. 令 substrings 为新的空 List。
  13. 令 searchStart 为 0。
  14. 令 matchIndex 为 StringIndexOf(string, separatorString, 0)。
  15. 当 matchIndex 不是 not-found 时,重复执行,
    1. 令 substring 为 string 从 searchStart 到 matchIndex 的子字符串。
    2. 将 substring 追加到 substrings。
    3. 如果 substrings 中的元素数量是 lim,则返回 CreateArrayFromList(substrings)。
    4. 将 searchStart 设置为 matchIndex + separatorLength。
    5. 将 matchIndex 设置为 StringIndexOf(string, separatorString, searchStart)。
  16. 令 substring 为 string 从 searchStart 开始的子字符串。
  17. 将 substring 追加到 substrings。
  18. 返回 CreateArrayFromList(substrings)。
注 1

separator 的值可以是空 String。在这种情况下,separator 不匹配输入 String 开头或末尾的空子字符串,也不匹配上一个分隔符匹配末尾的空子字符串。如果 separator 是空 String,则 String 会被拆分为单独的码元元素;结果数组的长度等于 String 的长度,并且每个子字符串包含一个码元。

如果 this value 是空 String(或转换为后是空 String),则结果取决于 separator 是否能匹配空 String。如果可以,则结果数组不包含任何元素。否则,结果数组包含一个元素,即空 String。

如果 separator 是 undefined,则结果数组只包含一个 String,即 this value(转换为 String)。如果 limit 不是 undefined,则输出数组会被截断,使其包含的元素不超过 limit 个。

注 2

此方法有意设计为通用方法;它不要求其 this value 是 String 对象。因此,它可以被转移到其他种类的对象上用作方法。

22.1.3.24 String.prototype.startsWith ( searchString [ , position ] )

调用时,此方法执行以下步骤:

  1. 令 thisValue 为 this value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. 令 string 为 ? ToString(thisValue)。
  4. 令 isRegexp 为 ? IsRegExp(searchString)。
  5. 如果 isRegexp 是 true,则抛出 TypeError 异常。
  6. 将 searchString 设置为 ? ToString(searchString)。
  7. 令 length 为 string 的长度。
  8. 令 start 为将 ? ToIntegerOrInfinity(position) 限制在 0 和 length 之间的结果。
  9. 断言:如果 position 是 undefined,则 start 为 0。
  10. 令 searchLength 为 searchString 的长度。
  11. 如果 searchLength = 0,则返回 true。
  12. 令 end 为 start + searchLength。
  13. 如果 end > length,则返回 false。
  14. 令 substring 为 string 从 start 到 end 的子字符串。
  15. 如果 substring 是 searchString,则返回 true。
  16. 返回 false。
注 1

规定当第一个参数是 RegExp 时抛出异常,是为了允许未来版本定义允许此类参数值的扩展。

注 2

此方法有意设计为通用方法;它不要求其 this value 是 String 对象。因此,它可以被转移到其他种类的对象上用作方法。

22.1.3.25 String.prototype.substring ( start, end )

此方法返回将此对象转换为 String 所得结果的一个子字符串,从索引 start 开始,到 String 的索引 end 之前结束(如果 end 是 undefined,则一直到 String 末尾)。结果是 String 值,而不是 String 对象。

如果任一参数是 NaN 或负数,则替换为零;如果任一参数严格大于 String 的长度,则替换为 String 的长度。

如果 start 严格大于 end,则交换它们。

调用时,它执行以下步骤:

  1. 令 thisValue 为 this value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. 令 string 为 ? ToString(thisValue)。
  4. 令 length 为 string 的长度。
  5. 令 finalStart 为将 ? ToIntegerOrInfinity(start) 限制在 0 和 length 之间的结果。
  6. 断言:如果 start 是 undefined,则 finalStart 为 0。
  7. 如果 end 是 undefined,则令 finalEnd 为 length;否则令 finalEnd 为将 ? ToIntegerOrInfinity(end) 限制在 0 和 length 之间的结果。
  8. 令 from 为 min(finalStart, finalEnd)。
  9. 令 to 为 max(finalStart, finalEnd)。
  10. 返回 string 从 from 到 to 的子字符串。
注

此方法有意设计为通用方法;它不要求其 this value 是 String 对象。因此,它可以被转移到其他种类的对象上用作方法。

22.1.3.26 String.prototype.toLocaleLowerCase ( [ reserved1 [ , reserved2 ] ] )

包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按照 ECMA-402 的规定实现此方法。否则,使用以下此方法的规范:

此方法按照 6.1.4 中的说明,将 String 值解释为 UTF-16 编码码点序列。

它的工作方式与 toLowerCase 完全相同,只是旨在产生符合宿主环境当前区域设置惯例的区域设置敏感结果。只有在少数情况下(例如土耳其语),当该语言的规则与常规 Unicode 大小写映射冲突时,结果才会有所不同。

此方法可选参数的含义定义于 ECMA-402;不包含 ECMA-402 支持的实现不得将这些参数位置用于其他用途。

注

此方法有意设计为通用方法;它不要求其 this value 是 String 对象。因此,它可以被转移到其他种类的对象上用作方法。

22.1.3.27 String.prototype.toLocaleUpperCase ( [ reserved1 [ , reserved2 ] ] )

包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按照 ECMA-402 的规定实现此方法。否则,使用以下此方法的规范:

此方法按照 6.1.4 中的说明,将 String 值解释为 UTF-16 编码码点序列。

它的工作方式与 toUpperCase 完全相同,只是旨在产生符合宿主环境当前区域设置惯例的区域设置敏感结果。只有在少数情况下(例如土耳其语),当该语言的规则与常规 Unicode 大小写映射冲突时,结果才会有所不同。

此方法可选参数的含义定义于 ECMA-402;不包含 ECMA-402 支持的实现不得将这些参数位置用于其他用途。

注

此方法有意设计为通用方法;它不要求其 this value 是 String 对象。因此,它可以被转移到其他种类的对象上用作方法。

22.1.3.28 String.prototype.toLowerCase ( )

此方法按照 6.1.4 中的说明,将 String 值解释为 UTF-16 编码码点序列。

调用时,它执行以下步骤:

  1. 令 thisValue 为 this value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. 令 string 为 ? ToString(thisValue)。
  4. 令 sText 为 StringToCodePoints(string)。
  5. 令 lowerText 为根据 Unicode Default Case Conversion 算法的 toLowercase(sText)。
  6. 令 lowercaseString 为 CodePointsToString(lowerText)。
  7. 返回 lowercaseString。

结果必须根据 Unicode Character Database 中与区域设置无关的大小写映射得出(这明确不仅包括文件 UnicodeData.txt,还包括随附文件 SpecialCasing.txt 中所有与区域设置无关的映射)。

注 1

某些码点的大小写映射可能产生多个码点。在这种情况下,结果 String 的长度可能与源 String 不同。由于 toUpperCase 和 toLowerCase 都具有上下文敏感行为,因此这些方法并不对称。换句话说,s.toUpperCase().toLowerCase() 不一定等于 s.toLowerCase()。

注 2

此方法有意设计为通用方法;它不要求其 this value 是 String 对象。因此,它可以被转移到其他种类的对象上用作方法。

22.1.3.29 String.prototype.toString ( )

调用时,此方法执行以下步骤:

  1. 返回 ? ThisStringValue(this value)。
注

对于 String 对象,此方法碰巧返回与 valueOf 方法相同的内容。

22.1.3.30 String.prototype.toUpperCase ( )

此方法按照 6.1.4 中的说明,将 String 值解释为 UTF-16 编码码点序列。

它的行为与 String.prototype.toLowerCase 完全相同,只是 String 使用 Unicode Default Case Conversion 的 toUppercase 算法进行映射。

注

此方法有意设计为通用方法;它不要求其 this value 是 String 对象。因此,它可以被转移到其他种类的对象上用作方法。

22.1.3.31 String.prototype.toWellFormed ( )

此方法返回此对象的 String 表示,其中所有不属于代理对的前导代理项和尾随代理项都会替换为 U+FFFD (REPLACEMENT CHARACTER)。

调用时,它执行以下步骤:

  1. 令 thisValue 为 this value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. 令 string 为 ? ToString(thisValue)。
  4. 令 stringLength 为 string 的长度。
  5. 令 k 为 0。
  6. 令 result 为空 String。
  7. 当 k < stringLength 时,重复执行,
    1. 令 codePoint 为 CodePointAt(string, k)。
    2. 如果 codePoint.[[IsUnpairedSurrogate]] 是 true,则
      1. 将 result 设置为 result 和 0xFFFD (REPLACEMENT CHARACTER) 的字符串连接。
    3. 否则,
      1. 将 result 设置为 result 和 UTF16EncodeCodePoint(codePoint.[[CodePoint]]) 的字符串连接。
    4. 将 k 设置为 k + codePoint.[[CodeUnitCount]]。
  8. 返回 result。

22.1.3.32 String.prototype.trim ( )

此方法按照 6.1.4 中的说明,将 String 值解释为 UTF-16 编码码点序列。

调用时,它执行以下步骤:

  1. 令 thisValue 为 this value。
  2. 返回 ? TrimString(thisValue, start+end)。
注

此方法有意设计为通用方法;它不要求其 this value 是 String 对象。因此,它可以被转移到其他种类的对象上用作方法。

22.1.3.32.1 TrimString ( arg, where )

抽象操作 TrimString,接收参数 arg (ECMAScript 语言值) 和 where ((start、end 或 start+end));返回值:(正常完成 (值:String) 或 抛出完成)。 它按照 6.1.4 中的说明,将 arg 解释为 UTF-16 编码码点序列。 调用时执行以下步骤:

  1. 执行 ? RequireObjectCoercible(arg)。
  2. 令 string 为 ? ToString(arg)。
  3. 如果 where 是 start,则
    1. 令 trimmedString 为移除 string 前导空白后的副本 String 值。
  4. 否则如果 where 是 end,则
    1. 令 trimmedString 为移除 string 尾随空白后的副本 String 值。
  5. 否则,
    1. 断言:where 是 start+end。
    2. 令 trimmedString 为同时移除 string 前导和尾随空白后的副本 String 值。
  6. 返回 trimmedString。

空白的定义是 WhiteSpace 和 LineTerminator 的并集。在确定 Unicode 码点是否属于 Unicode 通用类别“Space_Separator”(“Zs”)时,码元序列按照 6.1.4 中的规定解释为 UTF-16 编码码点序列。

22.1.3.33 String.prototype.trimEnd ( )

此方法按照 6.1.4 中的说明,将 String 值解释为 UTF-16 编码码点序列。

调用时,它执行以下步骤:

  1. 令 string 为 this value。
  2. 返回 ? TrimString(string, end)。
注

此方法有意设计为通用方法;它不要求其 this value 是 String 对象。因此,它可以被转移到其他种类的对象上用作方法。

22.1.3.34 String.prototype.trimStart ( )

此方法按照 6.1.4 中的说明,将 String 值解释为 UTF-16 编码码点序列。

调用时,它执行以下步骤:

  1. 令 string 为 this value。
  2. 返回 ? TrimString(string, start)。
注

此方法有意设计为通用方法;它不要求其 this value 是 String 对象。因此,它可以被转移到其他种类的对象上用作方法。

22.1.3.35 String.prototype.valueOf ( )

调用时,此方法执行以下步骤:

  1. 返回 ? ThisStringValue(this value)。

22.1.3.35.1 ThisStringValue ( arg )

抽象操作 ThisStringValue,接收参数 arg (ECMAScript 语言值);返回值:(正常完成 (值:String) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 arg 是 String,则返回 arg。
  2. 如果 arg 是 Object 且 arg 具有 [[StringData]] 内部槽,则
    1. 令 string 为 arg.[[StringData]]。
    2. 断言:string 是 String。
    3. 返回 string。
  3. 抛出 TypeError 异常。

22.1.3.36 String.prototype [ %Symbol.iterator% ] ( )

此方法返回一个迭代器对象,用于迭代 String 值的码点,并将每个码点作为 String 值返回。

调用时,它执行以下步骤:

  1. 令 string 为 this value。
  2. 执行 ? RequireObjectCoercible(string)。
  3. 将 string 设置为 ? ToString(string)。
  4. 令 closure 为不带参数的新 Abstract Closure,它捕获 string,并在被调用时执行以下步骤:
    1. 令 length 为 string 的长度。
    2. 令 position 为 0。
    3. 当 position < length 时,重复执行,
      1. 令 codePoint 为 CodePointAt(string, position)。
      2. 令 nextIndex 为 position + codePoint.[[CodeUnitCount]]。
      3. 令 resultString 为 string 从 position 到 nextIndex 的子字符串。
      4. 将 position 设置为 nextIndex。
      5. 执行 ? GeneratorYield(CreateIteratorResultObject(resultString, false))。
    4. 返回 NormalCompletion(unused)。
  5. 返回 CreateIteratorFromClosure(closure, "%StringIteratorPrototype%", %StringIteratorPrototype%)。

此方法的 "name" 属性值是 "[Symbol.iterator]"。

22.1.4 String 实例的属性

String 实例是 String 异质对象,并具有为此类对象规定的内部方法。String 实例从 String 原型对象继承属性。String 实例还具有 [[StringData]] 内部槽。[[StringData]] 内部槽是此 String 对象表示的 String 值。

String 实例具有 "length" 属性,以及一组名称为整数索引的可枚举属性。

22.1.4.1 length

此 String 对象所表示的 String 值中的元素数量。

一旦 String 对象初始化,此属性便不会改变。它具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

22.1.5 String 迭代器对象

String Iterator 是表示对某个特定 String 实例对象进行某次特定迭代的对象。String Iterator 对象没有具名构造函数。相反,String Iterator 对象通过调用 String 实例对象的某些方法创建。

22.1.5.1 %StringIteratorPrototype% 对象

%StringIteratorPrototype% 对象:

22.1.5.1.1 %StringIteratorPrototype%.next ( )

  1. 返回 ? GeneratorResume(this value, empty, "%StringIteratorPrototype%")。

22.1.5.1.2 %StringIteratorPrototype% [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "String Iterator"。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

22.2 RegExp(正则表达式)对象

RegExp 对象包含一个正则表达式及其相关标志。

注

正则表达式的形式和功能以 Perl 5 编程语言中的正则表达式机制为模型。

22.2.1 模式

RegExp 构造函数将以下文法应用于输入模式 String。如果文法无法将该 String 解释为 Pattern 的展开,则发生错误。

语法

Pattern[UnicodeMode, UnicodeSetsMode, NamedCaptureGroups] :: Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Disjunction[UnicodeMode, UnicodeSetsMode, NamedCaptureGroups] :: Alternative[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Alternative[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] | Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Alternative[UnicodeMode, UnicodeSetsMode, NamedCaptureGroups] :: [empty] Alternative[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Term[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Term[UnicodeMode, UnicodeSetsMode, NamedCaptureGroups] :: Assertion[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Atom[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Atom[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Quantifier Assertion[UnicodeMode, UnicodeSetsMode, NamedCaptureGroups] :: ^ $ \b \B (?= Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) (?! Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) (?<= Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) (?<! Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) Quantifier :: QuantifierPrefix QuantifierPrefix ? QuantifierPrefix :: * + ? { DecimalDigits[~Sep] } { DecimalDigits[~Sep] ,} { DecimalDigits[~Sep] , DecimalDigits[~Sep] } Atom[UnicodeMode, UnicodeSetsMode, NamedCaptureGroups] :: PatternCharacter . \ AtomEscape[?UnicodeMode, ?NamedCaptureGroups] CharacterClass[?UnicodeMode, ?UnicodeSetsMode] ( GroupSpecifier[?UnicodeMode]opt Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) (? RegularExpressionModifiers : Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) (? RegularExpressionModifiers - RegularExpressionModifiers : Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) RegularExpressionModifiers :: [empty] RegularExpressionModifiers RegularExpressionModifier RegularExpressionModifier :: one of i m s SyntaxCharacter :: one of ^ $ \ . * + ? ( ) [ ] { } | PatternCharacter :: SourceCharacter but not SyntaxCharacter AtomEscape[UnicodeMode, NamedCaptureGroups] :: DecimalEscape CharacterClassEscape[?UnicodeMode] CharacterEscape[?UnicodeMode] [+NamedCaptureGroups] k GroupName[?UnicodeMode] CharacterEscape[UnicodeMode] :: ControlEscape c AsciiLetter 0 [lookahead ∉ DecimalDigit] HexEscapeSequence RegExpUnicodeEscapeSequence[?UnicodeMode] IdentityEscape[?UnicodeMode] ControlEscape :: one of f n r t v GroupSpecifier[UnicodeMode] :: ? GroupName[?UnicodeMode] GroupName[UnicodeMode] :: < RegExpIdentifierName[?UnicodeMode] > RegExpIdentifierName[UnicodeMode] :: RegExpIdentifierStart[?UnicodeMode] RegExpIdentifierName[?UnicodeMode] RegExpIdentifierPart[?UnicodeMode] RegExpIdentifierStart[UnicodeMode] :: IdentifierStartChar \ RegExpUnicodeEscapeSequence[+UnicodeMode] [~UnicodeMode] UnicodeLeadSurrogate UnicodeTrailSurrogate RegExpIdentifierPart[UnicodeMode] :: IdentifierPartChar \ RegExpUnicodeEscapeSequence[+UnicodeMode] [~UnicodeMode] UnicodeLeadSurrogate UnicodeTrailSurrogate RegExpUnicodeEscapeSequence[UnicodeMode] :: [+UnicodeMode] u HexLeadSurrogate \u HexTrailSurrogate [+UnicodeMode] u HexLeadSurrogate [+UnicodeMode] u HexTrailSurrogate [+UnicodeMode] u HexNonSurrogate [~UnicodeMode] u Hex4Digits [+UnicodeMode] u{ CodePoint } UnicodeLeadSurrogate :: any Unicode code point in the inclusive interval from U+D800 to U+DBFF UnicodeTrailSurrogate :: any Unicode code point in the inclusive interval from U+DC00 to U+DFFF

对于每个 \u HexTrailSurrogate,如果其关联 u HexLeadSurrogate 的选择存在歧义,则应将其与最近的、否则将没有对应 \u HexTrailSurrogate 的可能 u HexLeadSurrogate 关联。

HexLeadSurrogate :: Hex4Digits but only if the MV of Hex4Digits is in the inclusive interval from 0xD800 to 0xDBFF HexTrailSurrogate :: Hex4Digits but only if the MV of Hex4Digits is in the inclusive interval from 0xDC00 to 0xDFFF HexNonSurrogate :: Hex4Digits but only if the MV of Hex4Digits is not in the inclusive interval from 0xD800 to 0xDFFF IdentityEscape[UnicodeMode] :: [+UnicodeMode] SyntaxCharacter [+UnicodeMode] / [~UnicodeMode] SourceCharacter but not UnicodeIDContinue DecimalEscape :: NonZeroDigit DecimalDigits[~Sep]opt [lookahead ∉ DecimalDigit] CharacterClassEscape[UnicodeMode] :: d D s S w W [+UnicodeMode] p{ UnicodePropertyValueExpression } [+UnicodeMode] P{ UnicodePropertyValueExpression } UnicodePropertyValueExpression :: UnicodePropertyName = UnicodePropertyValue LoneUnicodePropertyNameOrValue UnicodePropertyName :: UnicodePropertyNameCharacters UnicodePropertyNameCharacters :: UnicodePropertyNameCharacter UnicodePropertyNameCharactersopt UnicodePropertyValue :: UnicodePropertyValueCharacters LoneUnicodePropertyNameOrValue :: UnicodePropertyValueCharacters UnicodePropertyValueCharacters :: UnicodePropertyValueCharacter UnicodePropertyValueCharactersopt UnicodePropertyValueCharacter :: UnicodePropertyNameCharacter DecimalDigit UnicodePropertyNameCharacter :: AsciiLetter _ CharacterClass[UnicodeMode, UnicodeSetsMode] :: [ [lookahead ≠ ^] ClassContents[?UnicodeMode, ?UnicodeSetsMode] ] [^ ClassContents[?UnicodeMode, ?UnicodeSetsMode] ] ClassContents[UnicodeMode, UnicodeSetsMode] :: [empty] [~UnicodeSetsMode] NonemptyClassRanges[?UnicodeMode] [+UnicodeSetsMode] ClassSetExpression NonemptyClassRanges[UnicodeMode] :: ClassAtom[?UnicodeMode] ClassAtom[?UnicodeMode] NonemptyClassRangesNoDash[?UnicodeMode] ClassAtom[?UnicodeMode] - ClassAtom[?UnicodeMode] ClassContents[?UnicodeMode, ~UnicodeSetsMode] NonemptyClassRangesNoDash[UnicodeMode] :: ClassAtom[?UnicodeMode] ClassAtomNoDash[?UnicodeMode] NonemptyClassRangesNoDash[?UnicodeMode] ClassAtomNoDash[?UnicodeMode] - ClassAtom[?UnicodeMode] ClassContents[?UnicodeMode, ~UnicodeSetsMode] ClassAtom[UnicodeMode] :: - ClassAtomNoDash[?UnicodeMode] ClassAtomNoDash[UnicodeMode] :: SourceCharacter but not one of \ or ] or - \ ClassEscape[?UnicodeMode] ClassEscape[UnicodeMode] :: b [+UnicodeMode] - CharacterClassEscape[?UnicodeMode] CharacterEscape[?UnicodeMode] ClassSetExpression :: ClassUnion ClassIntersection ClassSubtraction ClassUnion :: ClassSetRange ClassUnionopt ClassSetOperand ClassUnionopt ClassIntersection :: ClassSetOperand && [lookahead ≠ &] ClassSetOperand ClassIntersection && [lookahead ≠ &] ClassSetOperand ClassSubtraction :: ClassSetOperand -- ClassSetOperand ClassSubtraction -- ClassSetOperand ClassSetRange :: ClassSetCharacter - ClassSetCharacter ClassSetOperand :: NestedClass ClassStringDisjunction ClassSetCharacter NestedClass :: [ [lookahead ≠ ^] ClassContents[+UnicodeMode, +UnicodeSetsMode] ] [^ ClassContents[+UnicodeMode, +UnicodeSetsMode] ] \ CharacterClassEscape[+UnicodeMode] 注 1

这里的前两行等价于 CharacterClass。

ClassStringDisjunction :: \q{ ClassStringDisjunctionContents } ClassStringDisjunctionContents :: ClassString ClassString | ClassStringDisjunctionContents ClassString :: [empty] NonEmptyClassString NonEmptyClassString :: ClassSetCharacter NonEmptyClassStringopt ClassSetCharacter :: [lookahead ∉ ClassSetReservedDoublePunctuator] SourceCharacter but not ClassSetSyntaxCharacter \ CharacterEscape[+UnicodeMode] \ ClassSetReservedPunctuator \b ClassSetReservedDoublePunctuator :: one of && !! ## $$ %% ** ++ ,, .. :: ;; << == >> ?? @@ ^^ `` ~~ ClassSetSyntaxCharacter :: one of ( ) [ ] { } / - \ | ClassSetReservedPunctuator :: one of & - ! # % , : ; < = > @ ` ~ 注 2

本节中的若干产生式在 B.1.2 中给出了替代定义。

22.2.1.1 Static Semantics: 提前错误

注

本节在 B.1.2.1 中进行了修订。

Pattern :: Disjunction QuantifierPrefix :: { DecimalDigits , DecimalDigits } Atom :: (? RegularExpressionModifiers : Disjunction ) Atom :: (? RegularExpressionModifiers - RegularExpressionModifiers : Disjunction ) AtomEscape :: k GroupName AtomEscape :: DecimalEscape NonemptyClassRanges :: ClassAtom - ClassAtom ClassContents NonemptyClassRangesNoDash :: ClassAtomNoDash - ClassAtom ClassContents RegExpIdentifierStart :: \ RegExpUnicodeEscapeSequence RegExpIdentifierStart :: UnicodeLeadSurrogate UnicodeTrailSurrogate RegExpIdentifierPart :: \ RegExpUnicodeEscapeSequence RegExpIdentifierPart :: UnicodeLeadSurrogate UnicodeTrailSurrogate UnicodePropertyValueExpression :: UnicodePropertyName = UnicodePropertyValue UnicodePropertyValueExpression :: LoneUnicodePropertyNameOrValue CharacterClassEscape :: P{ UnicodePropertyValueExpression } CharacterClass :: [^ ClassContents ] NestedClass :: [^ ClassContents ] ClassSetRange :: ClassSetCharacter - ClassSetCharacter

22.2.1.2 Static Semantics: CountLeftCapturingParensWithin ( parseNode )

抽象操作 CountLeftCapturingParensWithin,接收参数 parseNode (解析节点);返回值:非负整数。 它返回 parseNode 中左捕获括号的数量。左捕获括号是由 Atom :: ( GroupSpecifieropt Disjunction ) 产生式的 ( 终结符匹配的任何 ( 模式字符。

注

本节在 B.1.2.2 中进行了修订。

调用时执行以下步骤:

  1. 断言:parseNode 是 RegExp Pattern 文法中某个产生式的实例。
  2. 返回 parseNode 中包含的 Atom :: ( GroupSpecifieropt Disjunction ) Parse Node 的数量。

22.2.1.3 Static Semantics: CountLeftCapturingParensBefore ( parseNode )

抽象操作 CountLeftCapturingParensBefore,接收参数 parseNode (解析节点);返回值:非负整数。 它返回外围模式中位于 parseNode 左侧的左捕获括号数量。

注

本节在 B.1.2.2 中进行了修订。

调用时执行以下步骤:

  1. 断言:parseNode 是 RegExp Pattern 文法中某个产生式的实例。
  2. 令 pattern 为包含 parseNode 的 Pattern。
  3. 返回 pattern 中包含的、要么出现在 parseNode 之前,要么包含 parseNode 的 Atom :: ( GroupSpecifieropt Disjunction ) Parse Node 的数量。

22.2.1.4 Static Semantics: MightBothParticipate ( x, y )

抽象操作 MightBothParticipate,接收参数 x (解析节点) 和 y (解析节点);返回值:Boolean。 调用时执行以下步骤:

  1. 断言:x 和 y 具有相同的外围 Pattern。
  2. 如果外围 Pattern 包含一个 Disjunction :: Alternative | Disjunction Parse Node,并且 x 包含在 Alternative 中且 y 包含在派生的 Disjunction 中,或者 x 包含在派生的 Disjunction 中且 y 包含在 Alternative 中,则返回 false。
  3. 返回 true。

22.2.1.5 Static Semantics: CapturingGroupNumber

语法制导操作 CapturingGroupNumber,接收无参数;返回值:正整数。

注

本节在 B.1.2.1 中进行了修订。

它按以下产生式分别定义:

DecimalEscape :: NonZeroDigit
  1. 返回 NonZeroDigit 的 MV。
DecimalEscape :: NonZeroDigit DecimalDigits
  1. 令 n 为 DecimalDigits 中的码点数量。
  2. 返回(NonZeroDigit 的 MV × 10n 加上 DecimalDigits 的 MV)。

“NonZeroDigit 的 MV”和“DecimalDigits 的 MV”的定义见 12.9.3。

22.2.1.6 Static Semantics: IsCharacterClass

语法制导操作 IsCharacterClass,接收无参数;返回值:Boolean。

注

本节在 B.1.2.3 中进行了修订。

它按以下产生式分别定义:

ClassAtom :: - ClassAtomNoDash :: SourceCharacter but not one of \ or ] or - ClassEscape :: b - CharacterEscape
  1. 返回 false。
ClassEscape :: CharacterClassEscape
  1. 返回 true。

22.2.1.7 Static Semantics: CharacterValue

语法制导操作 CharacterValue,接收无参数;返回值:非负整数。

注 1

本节在 B.1.2.4 中进行了修订。

它按以下产生式分别定义:

ClassAtom :: -
  1. 返回 U+002D (HYPHEN-MINUS) 的数值。
ClassAtomNoDash :: SourceCharacter but not one of \ or ] or -
  1. 令 codePoint 为 SourceCharacter 所匹配的码点。
  2. 返回 codePoint 的数值。
ClassEscape :: b
  1. 返回 U+0008 (BACKSPACE) 的数值。
ClassEscape :: -
  1. 返回 U+002D (HYPHEN-MINUS) 的数值。
CharacterEscape :: ControlEscape
  1. 按照 表 63 返回数值。
表 63: ControlEscape 码点值
ControlEscape 数值 码点 Unicode 名称 符号
t 9 U+0009 CHARACTER TABULATION <HT>
n 10 U+000A LINE FEED (LF) <LF>
v 11 U+000B LINE TABULATION <VT>
f 12 U+000C FORM FEED (FF) <FF>
r 13 U+000D CARRIAGE RETURN (CR) <CR>
CharacterEscape :: c AsciiLetter
  1. 令 codePoint 为 AsciiLetter 所匹配的码点。
  2. 令 i 为 codePoint 的数值。
  3. 返回 i 除以 32 的余数。
CharacterEscape :: 0 [lookahead ∉ DecimalDigit]
  1. 返回 U+0000 (NULL) 的数值。
注 2

\0 表示 <NUL> 字符,并且后面不能跟十进制数字。

CharacterEscape :: HexEscapeSequence
  1. 返回 HexEscapeSequence 的 MV。
RegExpUnicodeEscapeSequence :: u HexLeadSurrogate \u HexTrailSurrogate
  1. 令 lead 为 CharacterValue of HexLeadSurrogate。
  2. 令 trail 为 CharacterValue of HexTrailSurrogate。
  3. 令 codePoint 为 UTF16SurrogatePairToCodePoint(lead, trail)。
  4. 返回 codePoint 的数值。
RegExpUnicodeEscapeSequence :: u Hex4Digits
  1. 返回 Hex4Digits 的 MV。
RegExpUnicodeEscapeSequence :: u{ CodePoint }
  1. 返回 CodePoint 的 MV。
HexLeadSurrogate :: Hex4Digits HexTrailSurrogate :: Hex4Digits HexNonSurrogate :: Hex4Digits
  1. 返回 Hex4Digits 的 MV。
CharacterEscape :: IdentityEscape
  1. 令 codePoint 为 IdentityEscape 所匹配的码点。
  2. 返回 codePoint 的数值。
ClassSetCharacter :: SourceCharacter but not ClassSetSyntaxCharacter
  1. 令 codePoint 为 SourceCharacter 所匹配的码点。
  2. 返回 codePoint 的数值。
ClassSetCharacter :: \ ClassSetReservedPunctuator
  1. 令 codePoint 为 ClassSetReservedPunctuator 所匹配的码点。
  2. 返回 codePoint 的数值。
ClassSetCharacter :: \b
  1. 返回 U+0008 (BACKSPACE) 的数值。

22.2.1.8 Static Semantics: MayContainStrings

语法制导操作 MayContainStrings,接收无参数;返回值:Boolean。 它按以下产生式分别定义:

CharacterClassEscape :: d D s S w W P{ UnicodePropertyValueExpression } UnicodePropertyValueExpression :: UnicodePropertyName = UnicodePropertyValue NestedClass :: [^ ClassContents ] ClassContents :: [empty] NonemptyClassRanges ClassSetOperand :: ClassSetCharacter
  1. 返回 false。
UnicodePropertyValueExpression :: LoneUnicodePropertyNameOrValue
  1. 如果 LoneUnicodePropertyNameOrValue 所匹配的源文本是 表 67 的“Property name”列中列出的字符串二元属性,则返回 true。
  2. 返回 false。
ClassUnion :: ClassSetRange ClassUnionopt
  1. 如果存在 ClassUnion,则返回 MayContainStrings of the ClassUnion。
  2. 返回 false。
ClassUnion :: ClassSetOperand ClassUnionopt
  1. 如果 MayContainStrings of the ClassSetOperand 是 true,则返回 true。
  2. 如果存在 ClassUnion,则返回 MayContainStrings of the ClassUnion。
  3. 返回 false。
ClassIntersection :: ClassSetOperand && ClassSetOperand
  1. 如果 MayContainStrings of the first ClassSetOperand 是 false,则返回 false。
  2. 如果 MayContainStrings of the second ClassSetOperand 是 false,则返回 false。
  3. 返回 true。
ClassIntersection :: ClassIntersection && ClassSetOperand
  1. 如果 MayContainStrings of the ClassIntersection 是 false,则返回 false。
  2. 如果 MayContainStrings of the ClassSetOperand 是 false,则返回 false。
  3. 返回 true。
ClassSubtraction :: ClassSetOperand -- ClassSetOperand
  1. 返回 MayContainStrings of the first ClassSetOperand。
ClassSubtraction :: ClassSubtraction -- ClassSetOperand
  1. 返回 MayContainStrings of the ClassSubtraction。
ClassStringDisjunctionContents :: ClassString | ClassStringDisjunctionContents
  1. 如果 MayContainStrings of the ClassString 是 true,则返回 true。
  2. 返回 MayContainStrings of the ClassStringDisjunctionContents。
ClassString :: [empty]
  1. 返回 true。
ClassString :: NonEmptyClassString
  1. 返回 MayContainStrings of the NonEmptyClassString。
NonEmptyClassString :: ClassSetCharacter NonEmptyClassStringopt
  1. 如果存在 NonEmptyClassString,则返回 true。
  2. 返回 false。

22.2.1.9 Static Semantics: GroupSpecifiersThatMatch ( thisGroupName )

抽象操作 GroupSpecifiersThatMatch,接收参数 thisGroupName (a GroupName Parse Node);返回值:列表 (元素:GroupSpecifier Parse Nodes)。 调用时执行以下步骤:

  1. 令 name 为 CapturingGroupName of thisGroupName。
  2. 令 pattern 为包含 thisGroupName 的 Pattern。
  3. 令 result 为新的空 List。
  4. 对 pattern 包含的每个 GroupSpecifier groupSpecifier,执行
    1. 如果 CapturingGroupName of groupSpecifier 是 name,则
      1. 将 groupSpecifier 追加到 result。
  5. 返回 result。

22.2.1.10 Static Semantics: CapturingGroupName

语法制导操作 CapturingGroupName,接收无参数;返回值:String。 它按以下产生式分别定义:

GroupName :: < RegExpIdentifierName >
  1. 令 nameUnescaped 为 RegExpIdentifierCodePoints of RegExpIdentifierName。
  2. 返回 CodePointsToString(nameUnescaped)。

22.2.1.11 Static Semantics: RegExpIdentifierCodePoints

语法制导操作 RegExpIdentifierCodePoints,接收无参数;返回值:列表 (元素:码点)。 它按以下产生式分别定义:

RegExpIdentifierName :: RegExpIdentifierStart
  1. 令 codePoint 为 RegExpIdentifierCodePoint of RegExpIdentifierStart。
  2. 返回 « codePoint »。
RegExpIdentifierName :: RegExpIdentifierName RegExpIdentifierPart
  1. 令 codePoints 为 RegExpIdentifierCodePoints of the derived RegExpIdentifierName。
  2. 令 codePoint 为 RegExpIdentifierCodePoint of RegExpIdentifierPart。
  3. 返回 codePoints 和 « codePoint » 的列表连接。

22.2.1.12 Static Semantics: RegExpIdentifierCodePoint

语法制导操作 RegExpIdentifierCodePoint,接收无参数;返回值:码点。 它按以下产生式分别定义:

RegExpIdentifierStart :: IdentifierStartChar
  1. 返回 IdentifierStartChar 所匹配的码点。
RegExpIdentifierPart :: IdentifierPartChar
  1. 返回 IdentifierPartChar 所匹配的码点。
RegExpIdentifierStart :: \ RegExpUnicodeEscapeSequence RegExpIdentifierPart :: \ RegExpUnicodeEscapeSequence
  1. 返回数值等于 CharacterValue of RegExpUnicodeEscapeSequence 的码点。
RegExpIdentifierStart :: UnicodeLeadSurrogate UnicodeTrailSurrogate RegExpIdentifierPart :: UnicodeLeadSurrogate UnicodeTrailSurrogate
  1. 令 lead 为数值等于 UnicodeLeadSurrogate 所匹配码点数值的码元。
  2. 令 trail 为数值等于 UnicodeTrailSurrogate 所匹配码点数值的码元。
  3. 返回 UTF16SurrogatePairToCodePoint(lead, trail)。

22.2.2 模式语义

正则表达式模式通过下面描述的过程转换为 Abstract Closure。只要结果相同,鼓励实现使用比下面列出的算法更高效的算法。该 Abstract Closure 用作 RegExp 对象的 [[RegExpMatcher]] 内部槽的值。

如果一个 Pattern 的相关标志既不包含 u 也不包含 v,则它是 BMP 模式。否则,它是 Unicode 模式。BMP 模式与被解释为由基本多文种平面范围内 Unicode 码点的 16 位值序列组成的 String 进行匹配。Unicode 模式与被解释为由使用 UTF-16 编码的 Unicode 码点组成的 String 进行匹配。在描述 BMP 模式行为的上下文中,“字符”表示单个 16 位 Unicode BMP 码点。在描述 Unicode 模式行为的上下文中,“字符”表示 UTF-16 编码的码点(6.1.4)。在任一上下文中,“字符值”表示相应未编码码点的数值。

Pattern 的语法和语义定义为如同 Pattern 的源文本是 SourceCharacter 值的 List,其中每个 SourceCharacter 对应一个 Unicode 码点。如果 BMP 模式包含非 BMP SourceCharacter,则整个模式使用 UTF-16 编码,并将该编码的各个码元用作 List 的元素。

注

例如,考虑一个在源文本中表示为单个非 BMP 字符 U+1D11E (MUSICAL SYMBOL G CLEF) 的模式。解释为 Unicode 模式时,它将是一个单元素(字符)List,其中包含单个码点 U+1D11E。不过,解释为 BMP 模式时,会先使用 UTF-16 编码,产生由码元 0xD834 和 0xDD1E 组成的双元素 List。

模式作为 ECMAScript String 值传递给 RegExp 构造函数,其中非 BMP 字符使用 UTF-16 编码。例如,表示为 String 值的单字符 MUSICAL SYMBOL G CLEF 模式是一个长度为 2 的 String,其元素是码元 0xD834 和 0xDD1E。因此,将其作为由两个模式字符组成的 BMP 模式处理时,不需要进一步转换该字符串。不过,要将其作为 Unicode 模式处理,必须使用 UTF16SurrogatePairToCodePoint 来生成一个 List,其唯一元素是单个模式字符,即码点 U+1D11E。

实现实际上可以不执行与 UTF-16 之间的此类转换,但本规范的语义要求模式匹配的结果如同执行了此类转换。

22.2.2.1 记号

以下描述使用下列内部数据结构:

  • CharSetElement 是以下两种实体之一:
    • 如果 regexpRecord.[[UnicodeSets]] 是 false,则 CharSetElement 是上述模式语义意义上的字符。
    • 如果 regexpRecord.[[UnicodeSets]] 是 true,则 CharSetElement 是一个序列,其元素是上述模式语义意义上的字符。这包括空序列、单字符序列以及多字符序列。为方便起见,在处理此类 CharSetElement 时,单个字符与单字符序列可互换使用。
  • CharSet 是 CharSetElement 的数学集合。
  • CaptureRange 是 Record { [[StartIndex]], [[EndIndex]] },表示捕获中所包含字符的范围,其中 [[StartIndex]] 是表示该范围在 input 中起始索引(包含)的整数,[[EndIndex]] 是表示该范围在 input 中结束索引(不包含)的整数。对于任何 CaptureRange,这些索引都必须满足 [[StartIndex]] ≤ [[EndIndex]] 这一不变量。
  • MatchState 是 Record { [[Input]], [[EndIndex]], [[Captures]] },其中 [[Input]] 是表示正在匹配的 String 的字符 List,[[EndIndex]] 是整数,[[Captures]] 是值的 List,模式中的每个左捕获括号对应一个值。MatchState 用于表示正则表达式匹配算法中的部分匹配状态。[[EndIndex]] 是模式迄今所匹配最后一个输入字符的索引加一,而 [[Captures]] 保存捕获括号的结果。[[Captures]] 的第 nth 个元素要么是表示第 nth 组捕获括号捕获字符范围的 CaptureRange,要么在尚未到达第 nth 组捕获括号时为 undefined。由于回溯,在匹配过程中任意时刻都可能同时使用许多 MatchState。
  • MatcherContinuation 是一个接受一个 MatchState 参数,并返回 MatchState 或 failure 的 Abstract Closure。MatcherContinuation 尝试从其 MatchState 参数给出的中间状态开始,将模式的剩余部分(由闭包捕获的值指定)与 input 进行匹配。如果匹配成功,MatcherContinuation 返回其到达的最终 MatchState;如果匹配失败,则 MatcherContinuation 返回 failure。
  • Matcher 是一个接受两个参数——MatchState 和 MatcherContinuation——并返回 MatchState 或 failure 的 Abstract Closure。Matcher 尝试从其 MatchState 参数给出的中间状态开始,将模式的中间子模式(由闭包捕获的值指定)与该 MatchState 的 [[Input]] 进行匹配。MatcherContinuation 参数应是一个用于匹配模式剩余部分的闭包。在匹配模式的子模式并得到新的 MatchState 后,Matcher 随后使用该新 MatchState 调用 MatcherContinuation,以测试模式的其余部分是否也能匹配。如果可以,Matcher 返回 MatcherContinuation 返回的 MatchState;如果不可以,Matcher 可以在其选择点尝试不同选择,反复调用 MatcherContinuation,直到成功或所有可能性都已穷尽。

22.2.2.1.1 RegExp Record

RegExp Record 是用于存储编译期间以及可能在匹配期间所需 RegExp 信息的 Record。

它具有以下字段:

表 64: RegExp Record 字段
字段名称 值 含义
[[IgnoreCase]] a Boolean 表示 "i" 是否出现在 RegExp 的标志中
[[Multiline]] a Boolean 表示 "m" 是否出现在 RegExp 的标志中
[[DotAll]] a Boolean 表示 "s" 是否出现在 RegExp 的标志中
[[Unicode]] a Boolean 表示 "u" 是否出现在 RegExp 的标志中
[[UnicodeSets]] a Boolean 表示 "v" 是否出现在 RegExp 的标志中
[[CapturingGroupsCount]] a non-negative integer RegExp 模式中左捕获括号的数量

22.2.2.2 Runtime Semantics: CompilePattern

语法制导操作 CompilePattern,接收参数 regexpRecord (RegExp 记录);返回值:an Abstract Closure that takes a List of characters and a non-negative integer and returns either a MatchState or failure。 它按以下产生式分别定义:

Pattern :: Disjunction
  1. 令 m 为 CompileSubpattern of Disjunction with arguments regexpRecord and forward。
  2. 返回一个参数为 (input, index) 的新 Abstract Closure,它捕获 regexpRecord 和 m,并在被调用时执行以下步骤:
    1. 断言:input 是字符 List。
    2. 断言:0 ≤ index ≤ input 中的元素数量。
    3. 令 c 为参数为 (y) 的新 MatcherContinuation,它不捕获任何内容,并在被调用时执行以下步骤:
      1. 断言:y 是 MatchState。
      2. 返回 y。
    4. 令 capability 为由 regexpRecord.[[CapturingGroupsCount]] 个 undefined 值组成的 List,索引从 1 到 regexpRecord.[[CapturingGroupsCount]]。
    5. 令 x 为 MatchState { [[Input]]: input, [[EndIndex]]: index, [[Captures]]: capability }。
    6. 返回 m(x, c)。
注

Pattern 会编译为 Abstract Closure 值。随后,RegExpBuiltinExec 可以将此过程应用于字符 List 和该 List 中的偏移量,以确定模式是否恰好从该偏移量开始匹配;如果匹配,则确定捕获括号的值。22.2.2 中的算法被设计为:编译模式可能抛出 SyntaxError 异常;另一方面,一旦模式成功编译,将所得 Abstract Closure 应用于字符 List 以查找匹配时不会抛出异常(除了任何可能在任意位置发生的实现定义异常,例如内存不足)。

22.2.2.3 Runtime Semantics: CompileSubpattern

语法制导操作 CompileSubpattern,接收参数 regexpRecord (RegExp 记录) 和 direction ((forward 或 backward));返回值:Matcher。

注 1

本节在 B.1.2.5 中进行了修订。

它按以下产生式分别定义:

Disjunction :: Alternative | Disjunction
  1. 令 m1 为 CompileSubpattern of Alternative with arguments regexpRecord and direction。
  2. 令 m2 为 CompileSubpattern of Disjunction with arguments regexpRecord and direction。
  3. 返回 MatchTwoAlternatives(m1, m2)。
注 2

| 正则表达式运算符分隔两个备选项。模式首先尝试匹配左侧 Alternative(后接正则表达式的后续部分);如果失败,则尝试匹配右侧 Disjunction(后接正则表达式的后续部分)。如果左侧 Alternative、右侧 Disjunction 和后续部分都有选择点,则在转到左侧 Alternative 中的下一个选择之前,会先尝试后续部分中的所有选择。如果左侧 Alternative 中的选择已经穷尽,则会尝试右侧 Disjunction,而不是左侧 Alternative。由 | 跳过的模式部分中的任何捕获括号都会产生 undefined 值而不是 Strings。因此,例如,

/a|ab/.exec("abc")

返回结果 "a",而不是 "ab"。此外,

/((a)|(ab))((c)|(bc))/.exec("abc")

返回数组

["abc", "a", "a", undefined, "bc", undefined, "bc"]

而不是

["abc", "ab", undefined, "ab", "c", "c", undefined]

尝试两个备选项的顺序与 direction 的值无关。

Alternative :: [empty]
  1. 返回 EmptyMatcher()。
Alternative :: Alternative Term
  1. 令 m1 为 CompileSubpattern of Alternative with arguments regexpRecord and direction。
  2. 令 m2 为 CompileSubpattern of Term with arguments regexpRecord and direction。
  3. 返回 MatchSequence(m1, m2, direction)。
注 3

连续的 Term 会尝试同时匹配 input 中连续的部分。当 direction 是 forward 时,如果左侧 Alternative、右侧 Term 和正则表达式的后续部分都有选择点,则在转到右侧 Term 中的下一个选择之前,会先尝试后续部分中的所有选择,而在转到左侧 Alternative 中的下一个选择之前,会尝试右侧 Term 中的所有选择。当 direction 是 backward 时,Alternative 和 Term 的求值顺序相反。

Term :: Assertion
  1. 返回 CompileAssertion of Assertion with argument regexpRecord。
注 4

所得 Matcher 与 direction 无关。

Term :: Atom
  1. 返回 CompileAtom of Atom with arguments regexpRecord and direction。
Term :: Atom Quantifier
  1. 令 m 为 CompileAtom of Atom with arguments regexpRecord and direction。
  2. 令 q 为 CompileQuantifier of Quantifier。
  3. 断言:q.[[Min]] ≤ q.[[Max]]。
  4. 令 parenIndex 为 CountLeftCapturingParensBefore(Term)。
  5. 令 parenCount 为 CountLeftCapturingParensWithin(Atom)。
  6. 返回一个参数为 (x, c) 的新 Matcher,它捕获 m、q、parenIndex 和 parenCount,并在被调用时执行以下步骤:
    1. 断言:x 是 MatchState。
    2. 断言:c 是 MatcherContinuation。
    3. 返回 RepeatMatcher(m, q.[[Min]], q.[[Max]], q.[[Greedy]], x, c, parenIndex, parenCount)。

22.2.2.3.1 RepeatMatcher ( m, min, max, greedy, matchState, continue, parenIndex, parenCount )

抽象操作 RepeatMatcher,接收参数 m (Matcher)、min (非负整数)、max ((非负整数 或 +∞))、greedy (Boolean)、matchState (MatchState)、continue (MatcherContinuation)、parenIndex (非负整数) 和 parenCount (非负整数);返回值:(MatchState 或 failure)。 调用时执行以下步骤:

  1. 如果 max = 0,则返回 continue(matchState)。
  2. 令 d 为参数为 (y) 的新 MatcherContinuation,它捕获 m、min、max、greedy、matchState、continue、parenIndex 和 parenCount,并在被调用时执行以下步骤:
    1. 断言:y 是 MatchState。
    2. 如果 min = 0 且 y.[[EndIndex]] = matchState.[[EndIndex]],则返回 failure。
    3. 如果 min = 0,则令 min2 为 0;否则令 min2 为 min - 1。
    4. 如果 max = +∞,则令 max2 为 +∞;否则令 max2 为 max - 1。
    5. 返回 RepeatMatcher(m, min2, max2, greedy, y, continue, parenIndex, parenCount)。
  3. 令 capability 为 matchState.[[Captures]] 的副本。
  4. 对从 parenIndex + 1 到 parenIndex + parenCount 闭区间内的每个整数 k,将 capability[k] 设置为 undefined。
  5. 令 input 为 matchState.[[Input]]。
  6. 令 e 为 matchState.[[EndIndex]]。
  7. 令 xr 为 MatchState { [[Input]]: input, [[EndIndex]]: e, [[Captures]]: capability }。
  8. 如果 min ≠ 0,则返回 m(xr, d)。
  9. 如果 greedy 是 false,则
    1. 令 z 为 continue(matchState)。
    2. 如果 z 不是 failure,则返回 z。
    3. 返回 m(xr, d)。
  10. 令 z 为 m(xr, d)。
  11. 如果 z 不是 failure,则返回 z。
  12. 返回 continue(matchState)。
注 1

后跟 Quantifier 的 Atom 会按 Quantifier 指定的次数重复。Quantifier 可以是非贪婪的,在这种情况下,Atom 模式会在仍能匹配后续部分的前提下尽可能少地重复;也可以是贪婪的,在这种情况下,Atom 模式会在仍能匹配后续部分的前提下尽可能多地重复。重复的是 Atom 模式,而不是它所匹配的输入字符序列,因此 Atom 的不同重复可以匹配不同的输入子字符串。

注 2

如果 Atom 和正则表达式的后续部分都有选择点,则首先尽可能多次(若为非贪婪则尽可能少次)匹配 Atom。在转到 Atom 最后一次重复中的下一个选择之前,会先尝试后续部分中的所有选择。在转到 Atom 倒数第二次(第 (n - 1)st 次)重复中的下一个选择之前,会先尝试 Atom 最后一次(第 nth 次)重复中的所有选择;此时可能会发现现在可以进行更多或更少的 Atom 重复;在转到第 (n - 1)st 次 Atom 重复中的下一个选择之前,会再次穷尽这些可能性(仍从尽可能少或尽可能多开始),依此类推。

比较

/a[a-z]{2,4}/.exec("abcdefghi")

它返回 "abcde",与

/a[a-z]{2,4}?/.exec("abcdefghi")

相比,后者返回 "abc"。

还可考虑

/(aa|aabaac|ba|b|c)*/.exec("aabaac")

根据上述选择点顺序,它返回数组

["aaba", "ba"]

而不是以下任何一个:

["aabaac", "aabaac"]
["aabaac", "c"]

上述选择点顺序可以用于编写一个正则表达式,计算两个数字(用一元表示法表示)的最大公约数。以下示例计算 10 和 15 的最大公约数:

"aaaaaaaaaa,aaaaaaaaaaaaaaa".replace(/^(a+)\1*,\1+$/, "$1")

它以一元表示法返回最大公约数 "aaaaa"。

注 3

RepeatMatcher 的步骤 4 会在每次重复 Atom 时清除 Atom 的捕获。我们可以在以下正则表达式中观察其行为

/(z)((a+)?(b+)?(c))*/.exec("zaacbbbcac")

它返回数组

["zaacbbbcac", "z", "ac", "a", undefined, "c"]

而不是

["zaacbbbcac", "z", "ac", "a", "bbb", "c"]

因为最外层 * 的每次迭代都会清除量化 Atom 中包含的所有捕获 String,在本例中包括编号 2、3、4 和 5 的捕获 String。

注 4

RepeatMatcher 的步骤 2.b 规定,一旦满足最小重复次数,就不再考虑与空字符序列匹配的 Atom 的更多展开来进行后续重复。这可以防止正则表达式引擎在如下模式上陷入无限循环:

/(a*)*/.exec("b")

或者稍微复杂一点的:

/(a*)b\1+/.exec("baaaac")

它返回数组

["b", ""]

22.2.2.3.2 EmptyMatcher ( )

抽象操作 EmptyMatcher,接收无参数;返回值:Matcher。 调用时执行以下步骤:

  1. 返回一个参数为 (matchState, continue) 的新 Matcher,它不捕获任何内容,并在被调用时执行以下步骤:
    1. 断言:matchState 是 MatchState。
    2. 断言:continue 是 MatcherContinuation。
    3. 返回 continue(matchState)。

22.2.2.3.3 MatchTwoAlternatives ( m1, m2 )

抽象操作 MatchTwoAlternatives,接收参数 m1 (Matcher) 和 m2 (Matcher);返回值:Matcher。 调用时执行以下步骤:

  1. 返回一个参数为 (matchState, continue) 的新 Matcher,它捕获 m1 和 m2,并在被调用时执行以下步骤:
    1. 断言:matchState 是 MatchState。
    2. 断言:continue 是 MatcherContinuation。
    3. 令 result 为 m1(matchState, continue)。
    4. 如果 result 不是 failure,则返回 result。
    5. 返回 m2(matchState, continue)。

22.2.2.3.4 MatchSequence ( m1, m2, direction )

抽象操作 MatchSequence,接收参数 m1 (Matcher)、m2 (Matcher) 和 direction ((forward 或 backward));返回值:Matcher。 调用时执行以下步骤:

  1. 如果 direction 是 forward,则
    1. 返回一个参数为 (matchState, continue) 的新 Matcher,它捕获 m1 和 m2,并在被调用时执行以下步骤:
      1. 断言:matchState 是 MatchState。
      2. 断言:continue 是 MatcherContinuation。
      3. 令 d 为参数为 (y) 的新 MatcherContinuation,它捕获 continue 和 m2,并在被调用时执行以下步骤:
        1. 断言:y 是 MatchState。
        2. 返回 m2(y, continue)。
      4. 返回 m1(matchState, d)。
  2. 断言:direction 是 backward。
  3. 返回一个参数为 (matchState, continue) 的新 Matcher,它捕获 m1 和 m2,并在被调用时执行以下步骤:
    1. 断言:matchState 是 MatchState。
    2. 断言:continue 是 MatcherContinuation。
    3. 令 d 为参数为 (y) 的新 MatcherContinuation,它捕获 continue 和 m1,并在被调用时执行以下步骤:
      1. 断言:y 是 MatchState。
      2. 返回 m1(y, continue)。
    4. 返回 m2(matchState, d)。

22.2.2.4 Runtime Semantics: CompileAssertion

语法制导操作 CompileAssertion,接收参数 regexpRecord (RegExp 记录);返回值:Matcher。

注 1

本节在 B.1.2.6 中进行了修订。

它按以下产生式分别定义:

Assertion :: ^
  1. 返回一个参数为 (matchState, continue) 的新 Matcher,它捕获 regexpRecord,并在被调用时执行以下步骤:
    1. 断言:matchState 是 MatchState。
    2. 断言:continue 是 MatcherContinuation。
    3. 令 input 为 matchState.[[Input]]。
    4. 令 e 为 matchState.[[EndIndex]]。
    5. 如果 e = 0,或者 regexpRecord.[[Multiline]] 是 true 且字符 input[e - 1] 被 LineTerminator 匹配,则
      1. 返回 continue(matchState)。
    6. 返回 failure。
注 2

即使模式使用 y 标志,^ 仍始终只在 input 的开头匹配,或者(如果 regexpRecord.[[Multiline]] 是 true)在某行开头匹配。

Assertion :: $
  1. 返回一个参数为 (matchState, continue) 的新 Matcher,它捕获 regexpRecord,并在被调用时执行以下步骤:
    1. 断言:matchState 是 MatchState。
    2. 断言:continue 是 MatcherContinuation。
    3. 令 input 为 matchState.[[Input]]。
    4. 令 e 为 matchState.[[EndIndex]]。
    5. 令 inputLength 为 input 中的元素数量。
    6. 如果 e = inputLength,或者 regexpRecord.[[Multiline]] 是 true 且字符 input[e] 被 LineTerminator 匹配,则
      1. 返回 continue(matchState)。
    7. 返回 failure。
Assertion :: \b
  1. 返回一个参数为 (matchState, continue) 的新 Matcher,它捕获 regexpRecord,并在被调用时执行以下步骤:
    1. 断言:matchState 是 MatchState。
    2. 断言:continue 是 MatcherContinuation。
    3. 令 input 为 matchState.[[Input]]。
    4. 令 e 为 matchState.[[EndIndex]]。
    5. 令 a 为 IsWordChar(regexpRecord, input, e - 1)。
    6. 令 b 为 IsWordChar(regexpRecord, input, e)。
    7. 如果 a 是 true 且 b 是 false,或者 a 是 false 且 b 是 true,则返回 continue(matchState)。
    8. 返回 failure。
Assertion :: \B
  1. 返回一个参数为 (matchState, continue) 的新 Matcher,它捕获 regexpRecord,并在被调用时执行以下步骤:
    1. 断言:matchState 是 MatchState。
    2. 断言:continue 是 MatcherContinuation。
    3. 令 input 为 matchState.[[Input]]。
    4. 令 e 为 matchState.[[EndIndex]]。
    5. 令 a 为 IsWordChar(regexpRecord, input, e - 1)。
    6. 令 b 为 IsWordChar(regexpRecord, input, e)。
    7. 如果 a 是 true 且 b 是 true,或者 a 是 false 且 b 是 false,则返回 continue(matchState)。
    8. 返回 failure。
Assertion :: (?= Disjunction )
  1. 令 m 为 CompileSubpattern of Disjunction with arguments regexpRecord and forward。
  2. 返回一个参数为 (matchState, continue) 的新 Matcher,它捕获 m,并在被调用时执行以下步骤:
    1. 断言:matchState 是 MatchState。
    2. 断言:continue 是 MatcherContinuation。
    3. 令 d 为参数为 (y) 的新 MatcherContinuation,它不捕获任何内容,并在被调用时执行以下步骤:
      1. 断言:y 是 MatchState。
      2. 返回 y。
    4. 令 result 为 m(matchState, d)。
    5. 如果 result 是 failure,则返回 failure。
    6. 断言:result 是 MatchState。
    7. 令 capability 为 result.[[Captures]]。
    8. 令 input 为 matchState.[[Input]]。
    9. 令 xe 为 matchState.[[EndIndex]]。
    10. 令 z 为 MatchState { [[Input]]: input, [[EndIndex]]: xe, [[Captures]]: capability }。
    11. 返回 continue(z)。
注 3

形式 (?= Disjunction ) 指定零宽正向先行断言。要使其成功,Disjunction 内的模式必须在当前位置匹配,但在匹配后续部分之前不会推进当前位置。如果 Disjunction 能以多种方式在当前位置匹配,只尝试第一种。与其他正则表达式运算符不同,不会回溯进入 (?= 形式(这种不寻常的行为继承自 Perl)。只有当 Disjunction 包含捕获括号且模式的后续部分包含对这些捕获的反向引用时,这一点才有影响。

例如,

/(?=(a+))/.exec("baaabac")

会匹配第一个 b 之后紧接的空 String,因此返回数组:

["", "aaa"]

为说明先行断言中不会发生回溯,请考虑:

/(?=(a+))a*b\1/.exec("baaabac")

此表达式返回

["aba", "a"]

而不是:

["aaaba", "a"]
Assertion :: (?! Disjunction )
  1. 令 m 为 CompileSubpattern of Disjunction with arguments regexpRecord and forward。
  2. 返回一个参数为 (matchState, continue) 的新 Matcher,它捕获 m,并在被调用时执行以下步骤:
    1. 断言:matchState 是 MatchState。
    2. 断言:continue 是 MatcherContinuation。
    3. 令 d 为参数为 (y) 的新 MatcherContinuation,它不捕获任何内容,并在被调用时执行以下步骤:
      1. 断言:y 是 MatchState。
      2. 返回 y。
    4. 令 result 为 m(matchState, d)。
    5. 如果 result 不是 failure,则返回 failure。
    6. 返回 continue(matchState)。
注 4

形式 (?! Disjunction ) 指定零宽负向先行断言。要使其成功,Disjunction 内的模式必须无法在当前位置匹配。在匹配后续部分之前不会推进当前位置。Disjunction 可以包含捕获括号,但对它们的反向引用只有从 Disjunction 自身内部使用才有意义。模式中其他位置对这些捕获括号的反向引用始终返回 undefined,因为负向先行断言必须失败,整个模式才能成功。例如,

/(.*?)a(?!(a+)b\2c)\2(.*)/.exec("baaabaac")

会查找一个 a,其后不能紧跟某个正整数 n 个 a、一个 b、另一个 n 个 a(由第一个 \2 指定)以及一个 c。第二个 \2 位于负向先行断言之外,因此它与 undefined 匹配,从而始终成功。整个表达式返回数组:

["baaabaac", "ba", undefined, "abaac"]
Assertion :: (?<= Disjunction )
  1. 令 m 为 CompileSubpattern of Disjunction with arguments regexpRecord and backward。
  2. 返回一个参数为 (matchState, continue) 的新 Matcher,它捕获 m,并在被调用时执行以下步骤:
    1. 断言:matchState 是 MatchState。
    2. 断言:continue 是 MatcherContinuation。
    3. 令 d 为参数为 (y) 的新 MatcherContinuation,它不捕获任何内容,并在被调用时执行以下步骤:
      1. 断言:y 是 MatchState。
      2. 返回 y。
    4. 令 result 为 m(matchState, d)。
    5. 如果 result 是 failure,则返回 failure。
    6. 断言:result 是 MatchState。
    7. 令 capability 为 result.[[Captures]]。
    8. 令 input 为 matchState.[[Input]]。
    9. 令 xe 为 matchState.[[EndIndex]]。
    10. 令 z 为 MatchState { [[Input]]: input, [[EndIndex]]: xe, [[Captures]]: capability }。
    11. 返回 continue(z)。
Assertion :: (?<! Disjunction )
  1. 令 m 为 CompileSubpattern of Disjunction with arguments regexpRecord and backward。
  2. 返回一个参数为 (matchState, continue) 的新 Matcher,它捕获 m,并在被调用时执行以下步骤:
    1. 断言:matchState 是 MatchState。
    2. 断言:continue 是 MatcherContinuation。
    3. 令 d 为参数为 (y) 的新 MatcherContinuation,它不捕获任何内容,并在被调用时执行以下步骤:
      1. 断言:y 是 MatchState。
      2. 返回 y。
    4. 令 result 为 m(matchState, d)。
    5. 如果 result 不是 failure,则返回 failure。
    6. 返回 continue(matchState)。

22.2.2.4.1 IsWordChar ( regexpRecord, input, e )

抽象操作 IsWordChar,接收参数 regexpRecord (RegExp 记录)、input (列表 (元素:字符)) 和 e (整数);返回值:Boolean。 调用时执行以下步骤:

  1. 令 inputLength 为 input 中的元素数量。
  2. 如果 e = -1 或 e = inputLength,则返回 false。
  3. 令 char 为字符 input[e]。
  4. 如果 WordCharacters(regexpRecord) 包含 char,则返回 true。
  5. 返回 false。

22.2.2.5 Runtime Semantics: CompileQuantifier

语法制导操作 CompileQuantifier,接收无参数;返回值:记录 (字段:[[Min]] (非负整数), [[Max]] ((非负整数 或 +∞)), [[Greedy]] (Boolean))。 它按以下产生式分别定义:

Quantifier :: QuantifierPrefix
  1. 令 qp 为 CompileQuantifierPrefix of QuantifierPrefix。
  2. 返回 Record { [[Min]]: qp.[[Min]], [[Max]]: qp.[[Max]], [[Greedy]]: true }。
Quantifier :: QuantifierPrefix ?
  1. 令 qp 为 CompileQuantifierPrefix of QuantifierPrefix。
  2. 返回 Record { [[Min]]: qp.[[Min]], [[Max]]: qp.[[Max]], [[Greedy]]: false }。

22.2.2.6 Runtime Semantics: CompileQuantifierPrefix

语法制导操作 CompileQuantifierPrefix,接收无参数;返回值:记录 (字段:[[Min]] (非负整数), [[Max]] ((非负整数 或 +∞)))。 它按以下产生式分别定义:

QuantifierPrefix :: *
  1. 返回 Record { [[Min]]: 0, [[Max]]: +∞ }。
QuantifierPrefix :: +
  1. 返回 Record { [[Min]]: 1, [[Max]]: +∞ }。
QuantifierPrefix :: ?
  1. 返回 Record { [[Min]]: 0, [[Max]]: 1 }。
QuantifierPrefix :: { DecimalDigits }
  1. 令 i 为 DecimalDigits 的 MV(参见 12.9.3)。
  2. 返回 Record { [[Min]]: i, [[Max]]: i }。
QuantifierPrefix :: { DecimalDigits ,}
  1. 令 i 为 DecimalDigits 的 MV。
  2. 返回 Record { [[Min]]: i, [[Max]]: +∞ }。
QuantifierPrefix :: { DecimalDigits , DecimalDigits }
  1. 令 i 为第一个 DecimalDigits 的 MV。
  2. 令 j 为第二个 DecimalDigits 的 MV。
  3. 返回 Record { [[Min]]: i, [[Max]]: j }。

22.2.2.7 Runtime Semantics: CompileAtom

语法制导操作 CompileAtom,接收参数 regexpRecord (RegExp 记录) 和 direction ((forward 或 backward));返回值:Matcher。

注 1

本节在 B.1.2.7 中进行了修订。

它按以下产生式分别定义:

Atom :: PatternCharacter
  1. 令 char 为 PatternCharacter 所匹配的字符。
  2. 令 charSet 为包含字符 char 的单元素 CharSet。
  3. 返回 CharacterSetMatcher(regexpRecord, charSet, false, direction)。
Atom :: .
  1. 令 charSet 为 AllCharacters(regexpRecord)。
  2. 如果 regexpRecord.[[DotAll]] 不是 true,则
    1. 从 charSet 中移除与 LineTerminator 产生式右侧码点对应的所有字符。
  3. 返回 CharacterSetMatcher(regexpRecord, charSet, false, direction)。
Atom :: CharacterClass
  1. 令 cc 为 CompileCharacterClass of CharacterClass with argument regexpRecord。
  2. 令 cs 为 cc.[[CharSet]]。
  3. 如果 regexpRecord.[[UnicodeSets]] 是 false,或者 cs 的每个 CharSetElement 都由单个字符组成(包括 cs 为空的情况),则返回 CharacterSetMatcher(regexpRecord, cs, cc.[[Invert]], direction)。
  4. 断言:cc.[[Invert]] 是 false。
  5. 令 listOfMatchers 为空的 Matcher List。
  6. 令 csSequences 为新的空 List。
  7. 对 cs 的每个 CharSetElement s,执行
    1. 如果 s 的长度 > 1,则将 s 追加到 csSequences。
  8. 按每个 CharSetElement 的长度降序对 csSequences 排序。
  9. 对 csSequences 的每个 CharSetElement s,执行
    1. 断言:s 是由 2 个或更多码点组成的序列。
    2. 令 remaining 为由 s 的码点组成的 List。
    3. 令 cs2 为包含 remaining 最后一个元素的单元素 CharSet。
    4. 令 m2 为 CharacterSetMatcher(regexpRecord, cs2, false, direction)。
    5. 移除 remaining 的最后一个元素。
    6. 按 List 逆序,对 remaining 的每个码点 c1,执行
      1. 令 cs1 为包含 c1 的单元素 CharSet。
      2. 令 m1 为 CharacterSetMatcher(regexpRecord, cs1, false, direction)。
      3. 将 m2 设置为 MatchSequence(m1, m2, direction)。
    7. 将 m2 追加到 listOfMatchers。
  10. 令 singles 为由 cs 中所有只包含单个字符的 CharSetElement 组成的 CharSet。
  11. 将 CharacterSetMatcher(regexpRecord, singles, false, direction) 追加到 listOfMatchers。
  12. 如果 cs 包含空字符序列,则将 EmptyMatcher() 追加到 listOfMatchers。
  13. 令 m2 为 listOfMatchers 中最后一个 Matcher。
  14. 从倒数第二个元素开始反向迭代,对 listOfMatchers 的每个 Matcher m1,执行
    1. 将 m2 设置为 MatchTwoAlternatives(m1, m2)。
  15. 返回 m2。
Atom :: ( GroupSpecifieropt Disjunction )
  1. 令 m 为 CompileSubpattern of Disjunction with arguments regexpRecord and direction。
  2. 令 parenIndex 为 CountLeftCapturingParensBefore(Atom)。
  3. 返回一个参数为 (x, c) 的新 Matcher,它捕获 direction、m 和 parenIndex,并在被调用时执行以下步骤:
    1. 断言:x 是 MatchState。
    2. 断言:c 是 MatcherContinuation。
    3. 令 d 为参数为 (y) 的新 MatcherContinuation,它捕获 x、c、direction 和 parenIndex,并在被调用时执行以下步骤:
      1. 断言:y 是 MatchState。
      2. 令 capability 为 y.[[Captures]] 的副本。
      3. 令 input 为 x.[[Input]]。
      4. 令 xe 为 x.[[EndIndex]]。
      5. 令 ye 为 y.[[EndIndex]]。
      6. 如果 direction 是 forward,则
        1. 断言:xe ≤ ye。
        2. 令 r 为 CaptureRange { [[StartIndex]]: xe, [[EndIndex]]: ye }。
      7. 否则,
        1. 断言:direction 是 backward。
        2. 断言:ye ≤ xe。
        3. 令 r 为 CaptureRange { [[StartIndex]]: ye, [[EndIndex]]: xe }。
      8. 将 capability[parenIndex + 1] 设置为 r。
      9. 令 z 为 MatchState { [[Input]]: input, [[EndIndex]]: ye, [[Captures]]: capability }。
      10. 返回 c(z)。
    4. 返回 m(x, d)。
注 2

形式 ( Disjunction ) 的括号既用于将 Disjunction 模式的组成部分组合在一起,也用于保存匹配结果。该结果可以用于反向引用(\ 后跟非零十进制数)、在替换 String 中引用,或者作为正则表达式匹配 Abstract Closure 返回的数组的一部分。要抑制括号的捕获行为,请改用形式 (?: Disjunction )。

Atom :: (? RegularExpressionModifiers : Disjunction )
  1. 令 addModifiers 为 RegularExpressionModifiers 所匹配的源文本。
  2. 令 removeModifiers 为空 String。
  3. 令 modifiedRer 为 UpdateModifiers(regexpRecord, CodePointsToString(addModifiers), removeModifiers)。
  4. 返回 CompileSubpattern of Disjunction with arguments modifiedRer and direction。
Atom :: (? RegularExpressionModifiers - RegularExpressionModifiers : Disjunction )
  1. 令 addModifiers 为第一个 RegularExpressionModifiers 所匹配的源文本。
  2. 令 removeModifiers 为第二个 RegularExpressionModifiers 所匹配的源文本。
  3. 令 modifiedRer 为 UpdateModifiers(regexpRecord, CodePointsToString(addModifiers), CodePointsToString(removeModifiers))。
  4. 返回 CompileSubpattern of Disjunction with arguments modifiedRer and direction。
AtomEscape :: DecimalEscape
  1. 令 n 为 CapturingGroupNumber of DecimalEscape。
  2. 断言:n ≤ regexpRecord.[[CapturingGroupsCount]]。
  3. 返回 BackreferenceMatcher(regexpRecord, « n », direction)。
注 3

形式为 \ 后跟非零十进制数 n 的转义序列会匹配第 nth 组捕获括号(22.2.2.1)的结果。如果正则表达式的捕获括号少于 n 个,则这是错误。如果正则表达式有 n 个或更多捕获括号,但第 nth 个因为尚未捕获任何内容而是 undefined,则反向引用始终成功。

AtomEscape :: CharacterEscape
  1. 令 charValue 为 CharacterValue of CharacterEscape。
  2. 令 char 为字符值等于 charValue 的字符。
  3. 令 charSet 为包含字符 char 的单元素 CharSet。
  4. 返回 CharacterSetMatcher(regexpRecord, charSet, false, direction)。
AtomEscape :: CharacterClassEscape
  1. 令 cs 为 CompileToCharSet of CharacterClassEscape with argument regexpRecord。
  2. 如果 regexpRecord.[[UnicodeSets]] 是 false,或者 cs 的每个 CharSetElement 都由单个字符组成(包括 cs 为空的情况),则返回 CharacterSetMatcher(regexpRecord, cs, false, direction)。
  3. 令 listOfMatchers 为空的 Matcher List。
  4. 令 csSequences 为新的空 List。
  5. 对 cs 的每个 CharSetElement s,执行
    1. 如果 s 的长度 > 1,则将 s 追加到 csSequences。
  6. 按每个 CharSetElement 的长度降序对 csSequences 排序。
  7. 对 csSequences 的每个 CharSetElement s,执行
    1. 断言:s 是由 2 个或更多码点组成的序列。
    2. 令 remaining 为由 s 的码点组成的 List。
    3. 令 cs2 为包含 remaining 最后一个元素的单元素 CharSet。
    4. 令 m2 为 CharacterSetMatcher(regexpRecord, cs2, false, direction)。
    5. 移除 remaining 的最后一个元素。
    6. 按 List 逆序,对 remaining 的每个码点 c1,执行
      1. 令 cs1 为包含 c1 的单元素 CharSet。
      2. 令 m1 为 CharacterSetMatcher(regexpRecord, cs1, false, direction)。
      3. 将 m2 设置为 MatchSequence(m1, m2, direction)。
    7. 将 m2 追加到 listOfMatchers。
  8. 令 singles 为由 cs 中所有只包含单个字符的 CharSetElement 组成的 CharSet。
  9. 将 CharacterSetMatcher(regexpRecord, singles, false, direction) 追加到 listOfMatchers。
  10. 如果 cs 包含空字符序列,则将 EmptyMatcher() 追加到 listOfMatchers。
  11. 令 m2 为 listOfMatchers 中最后一个 Matcher。
  12. 从倒数第二个元素开始反向迭代,对 listOfMatchers 的每个 Matcher m1,执行
    1. 将 m2 设置为 MatchTwoAlternatives(m1, m2)。
  13. 返回 m2。
AtomEscape :: k GroupName
  1. 令 matchingGroupSpecifiers 为 GroupSpecifiersThatMatch(GroupName)。
  2. 令 parenIndices 为新的空 List。
  3. 对 matchingGroupSpecifiers 的每个 GroupSpecifier groupSpecifier,执行
    1. 令 parenIndex 为 CountLeftCapturingParensBefore(groupSpecifier)。
    2. 将 parenIndex 追加到 parenIndices。
  4. 返回 BackreferenceMatcher(regexpRecord, parenIndices, direction)。

22.2.2.7.1 CharacterSetMatcher ( regexpRecord, charSet, invert, direction )

抽象操作 CharacterSetMatcher,接收参数 regexpRecord (RegExp 记录)、charSet (CharSet)、invert (Boolean) 和 direction ((forward 或 backward));返回值:Matcher。 调用时执行以下步骤:

  1. 如果 regexpRecord.[[UnicodeSets]] 是 true,则
    1. 断言:invert 是 false。
    2. 断言:charSet 的每个 CharSetElement 都由单个字符组成。
  2. 返回一个参数为 (x, c) 的新 Matcher,它捕获 regexpRecord、charSet、invert 和 direction,并在被调用时执行以下步骤:
    1. 断言:x 是 MatchState。
    2. 断言:c 是 MatcherContinuation。
    3. 令 input 为 x.[[Input]]。
    4. 令 endIndex 为 x.[[EndIndex]]。
    5. 如果 direction 是 forward,则令 f 为 endIndex + 1。
    6. 否则,令 f 为 endIndex - 1。
    7. 令 inputLength 为 input 中的元素数量。
    8. 如果 f < 0 或 f > inputLength,则返回 failure。
    9. 令 index 为 min(endIndex, f)。
    10. 令 char 为字符 input[index]。
    11. 令 cc 为 Canonicalize(regexpRecord, char)。
    12. 如果 charSet 中存在一个只包含一个字符 a 的 CharSetElement,且 Canonicalize(regexpRecord, a) 是 cc,则令 found 为 true;否则令 found 为 false。
    13. 如果 invert 是 false 且 found 是 false,则返回 failure。
    14. 如果 invert 是 true 且 found 是 true,则返回 failure。
    15. 令 capability 为 x.[[Captures]]。
    16. 令 y 为 MatchState { [[Input]]: input, [[EndIndex]]: f, [[Captures]]: capability }。
    17. 返回 c(y)。

22.2.2.7.2 BackreferenceMatcher ( regexpRecord, ns, direction )

抽象操作 BackreferenceMatcher,接收参数 regexpRecord (RegExp 记录)、ns (列表 (元素:正整数)) 和 direction ((forward 或 backward));返回值:Matcher。 调用时执行以下步骤:

  1. 返回一个参数为 (x, c) 的新 Matcher,它捕获 regexpRecord、ns 和 direction,并在被调用时执行以下步骤:
    1. 断言:x 是 MatchState。
    2. 断言:c 是 MatcherContinuation。
    3. 令 input 为 x.[[Input]]。
    4. 令 capability 为 x.[[Captures]]。
    5. 令 r 为 undefined。
    6. 对 ns 的每个整数 n,执行
      1. 如果 capability[n] 不是 undefined,则
        1. 断言:r 是 undefined。
        2. 将 r 设置为 capability[n]。
    7. 如果 r 是 undefined,则返回 c(x)。
    8. 令 endIndex 为 x.[[EndIndex]]。
    9. 令 rs 为 r.[[StartIndex]]。
    10. 令 re 为 r.[[EndIndex]]。
    11. 令 length 为 re - rs。
    12. 如果 direction 是 forward,则令 f 为 endIndex + length。
    13. 否则,令 f 为 endIndex - length。
    14. 令 inputLength 为 input 中的元素数量。
    15. 如果 f < 0 或 f > inputLength,则返回 failure。
    16. 令 g 为 min(endIndex, f)。
    17. 如果存在从 0(包含)到 length(不包含)区间内的整数 i,使得 Canonicalize(regexpRecord, input[rs + i]) 不是 Canonicalize(regexpRecord, input[g + i]),则返回 failure。
    18. 令 y 为 MatchState { [[Input]]: input, [[EndIndex]]: f, [[Captures]]: capability }。
    19. 返回 c(y)。

22.2.2.7.3 Canonicalize ( regexpRecord, char )

抽象操作 Canonicalize,接收参数 regexpRecord (RegExp 记录) 和 char (字符);返回值:字符。 调用时执行以下步骤:

  1. 如果 HasEitherUnicodeFlag(regexpRecord) 是 true 且 regexpRecord.[[IgnoreCase]] 是 true,则
    1. 如果 Unicode Character Database 的文件 CaseFolding.txt 为 char 提供了简单或通用大小写折叠映射,则返回将该映射应用于 char 的结果。
    2. 返回 char。
  2. 如果 regexpRecord.[[IgnoreCase]] 是 false,则返回 char。
  3. 断言:char 是 UTF-16 码元。
  4. 令 codePoint 为数值等于 char 数值的码点。
  5. 令 mappedCodePoints 为根据 Unicode Default Case Conversion 算法的 toUppercase(« codePoint »)。
  6. 如果 CodePointsToString(mappedCodePoints) 的长度 ≠ 1,则返回 char。
  7. 断言:mappedCodePoints 中的元素数量为 1。
  8. 令 mappedCodePoint 为 mappedCodePoints 中唯一的码点元素。
  9. 如果 char 的数值 ≥ 128 且 mappedCodePoint 的数值 < 128,则返回 char。
  10. 返回数值等于 mappedCodePoint 数值的码元。
注

在 HasEitherUnicodeFlag(regexpRecord) 是 true 的不区分大小写匹配中,所有字符在比较之前都会隐式使用 Unicode 标准提供的简单映射进行大小写折叠。简单映射始终映射到单个码点,因此例如不会将 ß (U+00DF LATIN SMALL LETTER SHARP S) 映射为 ss 或 SS。不过,它可以将 Basic Latin 块之外的码点映射到其中的码点——例如,ſ (U+017F LATIN SMALL LETTER LONG S) 大小写折叠为 s (U+0073 LATIN SMALL LETTER S),而 K (U+212A KELVIN SIGN) 大小写折叠为 k (U+006B LATIN SMALL LETTER K)。包含这些码点的 Strings 会被 /[a-z]/ui 等正则表达式匹配。

在 HasEitherUnicodeFlag(regexpRecord) 是 false 的不区分大小写匹配中,映射基于 Unicode Default Case Conversion 算法 toUppercase,而不是 toCasefold,这会产生一些细微差异。例如,Ω (U+2126 OHM SIGN) 由 toUppercase 映射为自身,但由 toCasefold 与 Ω (U+03A9 GREEK CAPITAL LETTER OMEGA) 一起映射为 ω (U+03C9 GREEK SMALL LETTER OMEGA),因此 "\u2126" 会被 /[ω]/ui 和 /[\u03A9]/ui 匹配,但不会被 /[ω]/i 或 /[\u03A9]/i 匹配。此外,Basic Latin 块之外的码点不会映射到其中的码点,因此 "\u017F ſ" 和 "\u212A K" 等字符串不会被 /[a-z]/i 匹配。

22.2.2.7.4 UpdateModifiers ( regexpRecord, add, remove )

抽象操作 UpdateModifiers,接收参数 regexpRecord (RegExp 记录)、add (String) 和 remove (String);返回值:RegExp 记录。 调用时执行以下步骤:

  1. 断言:add 和 remove 没有共同元素。
  2. 令 ignoreCase 为 regexpRecord.[[IgnoreCase]]。
  3. 令 multiline 为 regexpRecord.[[Multiline]]。
  4. 令 dotAll 为 regexpRecord.[[DotAll]]。
  5. 令 unicode 为 regexpRecord.[[Unicode]]。
  6. 令 unicodeSets 为 regexpRecord.[[UnicodeSets]]。
  7. 令 capturingGroupsCount 为 regexpRecord.[[CapturingGroupsCount]]。
  8. 如果 remove 包含 "i",则将 ignoreCase 设置为 false。
  9. 否则如果 add 包含 "i",则将 ignoreCase 设置为 true。
  10. 如果 remove 包含 "m",则将 multiline 设置为 false。
  11. 否则如果 add 包含 "m",则将 multiline 设置为 true。
  12. 如果 remove 包含 "s",则将 dotAll 设置为 false。
  13. 否则如果 add 包含 "s",则将 dotAll 设置为 true。
  14. 返回 RegExp Record { [[IgnoreCase]]: ignoreCase, [[Multiline]]: multiline, [[DotAll]]: dotAll, [[Unicode]]: unicode, [[UnicodeSets]]: unicodeSets, [[CapturingGroupsCount]]: capturingGroupsCount }。

22.2.2.8 Runtime Semantics: CompileCharacterClass

语法制导操作 CompileCharacterClass,接收参数 regexpRecord (RegExp 记录);返回值:记录 (字段:[[CharSet]] (CharSet), [[Invert]] (Boolean))。 它按以下产生式分别定义:

CharacterClass :: [ ClassContents ]
  1. 令 charSet 为 CompileToCharSet of ClassContents with argument regexpRecord。
  2. 返回 Record { [[CharSet]]: charSet, [[Invert]]: false }。
CharacterClass :: [^ ClassContents ]
  1. 令 charSet 为 CompileToCharSet of ClassContents with argument regexpRecord。
  2. 如果 regexpRecord.[[UnicodeSets]] 是 true,则
    1. 返回 Record { [[CharSet]]: CharacterComplement(regexpRecord, charSet), [[Invert]]: false }。
  3. 返回 Record { [[CharSet]]: charSet, [[Invert]]: true }。

22.2.2.9 Runtime Semantics: CompileToCharSet

语法制导操作 CompileToCharSet,接收参数 regexpRecord (RegExp 记录);返回值:CharSet。

注 1

本节在 B.1.2.8 中进行了修订。

它按以下产生式分别定义:

ClassContents :: [empty]
  1. 返回空 CharSet。
NonemptyClassRanges :: ClassAtom NonemptyClassRangesNoDash
  1. 令 charSet 为 CompileToCharSet of ClassAtom with argument regexpRecord。
  2. 令 otherSet 为 CompileToCharSet of NonemptyClassRangesNoDash with argument regexpRecord。
  3. 返回 CharSet charSet 和 otherSet 的并集。
NonemptyClassRanges :: ClassAtom - ClassAtom ClassContents
  1. 令 charSet 为 CompileToCharSet of the first ClassAtom with argument regexpRecord。
  2. 令 otherSet 为 CompileToCharSet of the second ClassAtom with argument regexpRecord。
  3. 令 remainingSet 为 CompileToCharSet of ClassContents with argument regexpRecord。
  4. 令 rangeSet 为 CharacterRange(charSet, otherSet)。
  5. 返回 rangeSet 和 remainingSet 的并集。
NonemptyClassRangesNoDash :: ClassAtomNoDash NonemptyClassRangesNoDash
  1. 令 charSet 为 CompileToCharSet of ClassAtomNoDash with argument regexpRecord。
  2. 令 otherSet 为 CompileToCharSet of NonemptyClassRangesNoDash with argument regexpRecord。
  3. 返回 CharSet charSet 和 otherSet 的并集。
NonemptyClassRangesNoDash :: ClassAtomNoDash - ClassAtom ClassContents
  1. 令 charSet 为 CompileToCharSet of ClassAtomNoDash with argument regexpRecord。
  2. 令 otherSet 为 CompileToCharSet of ClassAtom with argument regexpRecord。
  3. 令 remainingSet 为 CompileToCharSet of ClassContents with argument regexpRecord。
  4. 令 rangeSet 为 CharacterRange(charSet, otherSet)。
  5. 返回 rangeSet 和 remainingSet 的并集。
注 2

ClassContents 可以展开为单个 ClassAtom 和/或由连字符分隔的两个 ClassAtom 的范围。在后一种情况下,ClassContents 包括第一个 ClassAtom 与第二个 ClassAtom 之间(包含两端)的所有字符;如果任一 ClassAtom 不表示单个字符(例如其中一个是 \w),或者第一个 ClassAtom 的字符值严格大于第二个 ClassAtom 的字符值,则发生错误。

注 3

即使模式忽略大小写,范围两端的大小写仍会影响哪些字符属于该范围。因此,例如,模式 /[E-F]/i 只匹配字母 E、F、e 和 f,而模式 /[E-f]/i 会匹配 Unicode Basic Latin 块中的所有大写和小写字母,以及符号 [、\、]、^、_ 和 `。

注 4

- 字符可以按字面处理,也可以表示范围。如果它是 ClassContents 的第一个或最后一个字符、范围规范的开始或结束边界,或者紧跟在范围规范之后,则按字面处理。

ClassAtom :: -
  1. 返回包含单个字符 - U+002D (HYPHEN-MINUS) 的 CharSet。
ClassAtomNoDash :: SourceCharacter but not one of \ or ] or -
  1. 返回包含 SourceCharacter 所匹配字符的 CharSet。
ClassEscape :: b - CharacterEscape
  1. 令 charValue 为 CharacterValue of this ClassEscape。
  2. 令 char 为字符值等于 charValue 的字符。
  3. 返回包含单个字符 char 的 CharSet。
注 5

ClassAtom 可以使用正则表达式其余部分允许的任何转义序列,但 \b、\B 和反向引用除外。在 CharacterClass 内,\b 表示退格字符,而 \B 和反向引用会引发错误。在 ClassAtom 内使用反向引用会导致错误。

CharacterClassEscape :: d
  1. 返回包含字符 0、1、2、3、4、5、6、7、8 和 9 的十元素 CharSet。
CharacterClassEscape :: D
  1. 令 charSet 为由 CharacterClassEscape :: d 返回的 CharSet。
  2. 返回 CharacterComplement(regexpRecord, charSet)。
CharacterClassEscape :: s
  1. 返回包含与 WhiteSpace 或 LineTerminator 产生式右侧码点对应的所有字符的 CharSet。
CharacterClassEscape :: S
  1. 令 charSet 为由 CharacterClassEscape :: s 返回的 CharSet。
  2. 返回 CharacterComplement(regexpRecord, charSet)。
CharacterClassEscape :: w
  1. 返回 MaybeSimpleCaseFolding(regexpRecord, WordCharacters(regexpRecord))。
CharacterClassEscape :: W
  1. 令 charSet 为由 CharacterClassEscape :: w 返回的 CharSet。
  2. 返回 CharacterComplement(regexpRecord, charSet)。
CharacterClassEscape :: p{ UnicodePropertyValueExpression }
  1. 返回 CompileToCharSet of UnicodePropertyValueExpression with argument regexpRecord。
CharacterClassEscape :: P{ UnicodePropertyValueExpression }
  1. 令 charSet 为 CompileToCharSet of UnicodePropertyValueExpression with argument regexpRecord。
  2. 断言:charSet 只包含单个码点。
  3. 返回 CharacterComplement(regexpRecord, charSet)。
UnicodePropertyValueExpression :: UnicodePropertyName = UnicodePropertyValue
  1. 令 ps 为 UnicodePropertyName 所匹配的源文本。
  2. 令 p 为 UnicodeMatchProperty(regexpRecord, ps)。
  3. 断言:p 是 表 65 的“Property name and aliases”列中列出的Unicode 属性名称或属性别名。
  4. 令 vs 为 UnicodePropertyValue 所匹配的源文本。
  5. 令 v 为 UnicodeMatchPropertyValue(p, vs)。
  6. 令 charSet 为包含所有其字符数据库定义中属性 p 的值为 v 的 Unicode 码点的 CharSet。
  7. 返回 MaybeSimpleCaseFolding(regexpRecord, charSet)。
UnicodePropertyValueExpression :: LoneUnicodePropertyNameOrValue
  1. 令 s 为 LoneUnicodePropertyNameOrValue 所匹配的源文本。
  2. 如果 UnicodeMatchPropertyValue(General_Category, s) 是 PropertyValueAliases.txt 中为 General_Category (gc) 属性列出的 Unicode 属性值或属性值别名,则
    1. 返回包含所有其字符数据库定义中属性“General_Category”的值为 s 的 Unicode 码点的 CharSet。
  3. 令 p 为 UnicodeMatchProperty(regexpRecord, s)。
  4. 断言:p 是 表 66 的“Property name and aliases”列中列出的二元 Unicode 属性或二元属性别名,或者是 表 67 的“Property name”列中列出的字符串二元 Unicode 属性。
  5. 令 charSet 为包含所有其字符数据库定义中属性 p 的值为“True”的 CharSetElement 的 CharSet。
  6. 返回 MaybeSimpleCaseFolding(regexpRecord, charSet)。
ClassUnion :: ClassSetRange ClassUnionopt
  1. 令 charSet 为 CompileToCharSet of ClassSetRange with argument regexpRecord。
  2. 如果存在 ClassUnion,则
    1. 令 otherSet 为 CompileToCharSet of ClassUnion with argument regexpRecord。
    2. 返回 CharSet charSet 和 otherSet 的并集。
  3. 返回 charSet。
ClassUnion :: ClassSetOperand ClassUnionopt
  1. 令 charSet 为 CompileToCharSet of ClassSetOperand with argument regexpRecord。
  2. 如果存在 ClassUnion,则
    1. 令 otherSet 为 CompileToCharSet of ClassUnion with argument regexpRecord。
    2. 返回 CharSet charSet 和 otherSet 的并集。
  3. 返回 charSet。
ClassIntersection :: ClassSetOperand && ClassSetOperand
  1. 令 charSet 为 CompileToCharSet of the first ClassSetOperand with argument regexpRecord。
  2. 令 otherSet 为 CompileToCharSet of the second ClassSetOperand with argument regexpRecord。
  3. 返回 CharSet charSet 和 otherSet 的交集。
ClassIntersection :: ClassIntersection && ClassSetOperand
  1. 令 charSet 为 CompileToCharSet of the ClassIntersection with argument regexpRecord。
  2. 令 otherSet 为 CompileToCharSet of the ClassSetOperand with argument regexpRecord。
  3. 返回 CharSet charSet 和 otherSet 的交集。
ClassSubtraction :: ClassSetOperand -- ClassSetOperand
  1. 令 charSet 为 CompileToCharSet of the first ClassSetOperand with argument regexpRecord。
  2. 令 otherSet 为 CompileToCharSet of the second ClassSetOperand with argument regexpRecord。
  3. 返回包含 charSet 中不同时也是 otherSet 的 CharSetElement 的所有 CharSetElement 的 CharSet。
ClassSubtraction :: ClassSubtraction -- ClassSetOperand
  1. 令 charSet 为 CompileToCharSet of the ClassSubtraction with argument regexpRecord。
  2. 令 otherSet 为 CompileToCharSet of the ClassSetOperand with argument regexpRecord。
  3. 返回包含 charSet 中不同时也是 otherSet 的 CharSetElement 的所有 CharSetElement 的 CharSet。
ClassSetRange :: ClassSetCharacter - ClassSetCharacter
  1. 令 charSet 为 CompileToCharSet of the first ClassSetCharacter with argument regexpRecord。
  2. 令 otherSet 为 CompileToCharSet of the second ClassSetCharacter with argument regexpRecord。
  3. 返回 MaybeSimpleCaseFolding(regexpRecord, CharacterRange(charSet, otherSet))。
注 6

结果通常会由两个或更多范围组成。当 UnicodeSets 是 true 且 IgnoreCase 是 true 时,MaybeSimpleCaseFolding(regexpRecord, [Ā-č]) 将只包含该范围内编号为奇数的码点。

ClassSetOperand :: ClassSetCharacter
  1. 令 charSet 为 CompileToCharSet of ClassSetCharacter with argument regexpRecord。
  2. 返回 MaybeSimpleCaseFolding(regexpRecord, charSet)。
ClassSetOperand :: ClassStringDisjunction
  1. 令 charSet 为 CompileToCharSet of ClassStringDisjunction with argument regexpRecord。
  2. 返回 MaybeSimpleCaseFolding(regexpRecord, charSet)。
ClassSetOperand :: NestedClass
  1. 返回 CompileToCharSet of NestedClass with argument regexpRecord。
NestedClass :: [ ClassContents ]
  1. 返回 CompileToCharSet of ClassContents with argument regexpRecord。
NestedClass :: [^ ClassContents ]
  1. 令 charSet 为 CompileToCharSet of ClassContents with argument regexpRecord。
  2. 返回 CharacterComplement(regexpRecord, charSet)。
NestedClass :: \ CharacterClassEscape
  1. 返回 CompileToCharSet of CharacterClassEscape with argument regexpRecord。
ClassStringDisjunction :: \q{ ClassStringDisjunctionContents }
  1. 返回 CompileToCharSet of ClassStringDisjunctionContents with argument regexpRecord。
ClassStringDisjunctionContents :: ClassString
  1. 令 s 为 CompileClassSetString of ClassString with argument regexpRecord。
  2. 返回包含唯一字符串 s 的 CharSet。
ClassStringDisjunctionContents :: ClassString | ClassStringDisjunctionContents
  1. 令 s 为 CompileClassSetString of ClassString with argument regexpRecord。
  2. 令 charSet 为包含唯一字符串 s 的 CharSet。
  3. 令 otherSet 为 CompileToCharSet of ClassStringDisjunctionContents with argument regexpRecord。
  4. 返回 CharSet charSet 和 otherSet 的并集。
ClassSetCharacter :: SourceCharacter but not ClassSetSyntaxCharacter \ CharacterEscape \ ClassSetReservedPunctuator
  1. 令 charValue 为 CharacterValue of this ClassSetCharacter。
  2. 令 char 为字符值等于 charValue 的字符。
  3. 返回包含单个字符 char 的 CharSet。
ClassSetCharacter :: \b
  1. 返回包含单个字符 U+0008 (BACKSPACE) 的 CharSet。

22.2.2.9.1 CharacterRange ( charSet, otherSet )

抽象操作 CharacterRange,接收参数 charSet (CharSet) 和 otherSet (CharSet);返回值:CharSet。 调用时执行以下步骤:

  1. 断言:charSet 和 otherSet 各自恰好包含一个字符。
  2. 令 a 为 CharSet charSet 中的唯一字符。
  3. 令 b 为 CharSet otherSet 中的唯一字符。
  4. 令 i 为字符 a 的字符值。
  5. 令 j 为字符 b 的字符值。
  6. 断言:i ≤ j。
  7. 返回包含字符值位于从 i 到 j 闭区间内的所有字符的 CharSet。

22.2.2.9.2 HasEitherUnicodeFlag ( regexpRecord )

抽象操作 HasEitherUnicodeFlag,接收参数 regexpRecord (RegExp 记录);返回值:Boolean。 调用时执行以下步骤:

  1. 如果 regexpRecord.[[Unicode]] 是 true 或 regexpRecord.[[UnicodeSets]] 是 true,则返回 true。
  2. 返回 false。

22.2.2.9.3 WordCharacters ( regexpRecord )

抽象操作 WordCharacters,接收参数 regexpRecord (RegExp 记录);返回值:CharSet。 返回一个 CharSet,其中包含为了 \b、\B、\w 和 \W 而被视为“单词字符”的字符。 调用时执行以下步骤:

  1. 令 basicWordChars 为包含 ASCII 单词字符中每个字符的 CharSet。
  2. 令 extraWordChars 为包含所有满足以下条件的字符 c 的 CharSet:c 不在 basicWordChars 中,但 Canonicalize(regexpRecord, c) 在 basicWordChars 中。
  3. 断言:除非 HasEitherUnicodeFlag(regexpRecord) 是 true 且 regexpRecord.[[IgnoreCase]] 是 true,否则 extraWordChars 为空。
  4. 返回 basicWordChars 和 extraWordChars 的并集。

22.2.2.9.4 AllCharacters ( regexpRecord )

抽象操作 AllCharacters,接收参数 regexpRecord (RegExp 记录);返回值:CharSet。 根据正则表达式标志返回“所有字符”的集合。 调用时执行以下步骤:

  1. 如果 regexpRecord.[[UnicodeSets]] 是 true 且 regexpRecord.[[IgnoreCase]] 是 true,则
    1. 返回包含所有没有 Simple Case Folding 映射(即 scf(c)=c)的 Unicode 码点 c 的 CharSet。
  2. 如果 HasEitherUnicodeFlag(regexpRecord) 是 true,则
    1. 返回包含所有码点值的 CharSet。
  3. 返回包含所有码元值的 CharSet。

22.2.2.9.5 MaybeSimpleCaseFolding ( regexpRecord, charSet )

抽象操作 MaybeSimpleCaseFolding,接收参数 regexpRecord (RegExp 记录) 和 charSet (CharSet);返回值:CharSet。 如果 regexpRecord.[[UnicodeSets]] 是 false 或 regexpRecord.[[IgnoreCase]] 是 false,则返回 charSet。否则,它使用 Unicode Character Database 的文件 CaseFolding.txt 中的 Simple Case Folding(scf(codePoint))定义(每个定义都将单个码点映射到另一个单个码点),逐字符地将 charSet 的每个 CharSetElement 映射为规范形式,并返回所得 CharSet。 调用时执行以下步骤:

  1. 如果 regexpRecord.[[UnicodeSets]] 是 false 或 regexpRecord.[[IgnoreCase]] 是 false,则返回 charSet。
  2. 令 otherSet 为新的空 CharSet。
  3. 对 charSet 的每个 CharSetElement s,执行
    1. 令 t 为空字符序列。
    2. 对 s 的每个单一码点 codePoint,执行
      1. 将 scf(codePoint) 追加到 t。
    3. 将 t 添加到 otherSet。
  4. 返回 otherSet。

22.2.2.9.6 CharacterComplement ( regexpRecord, complement )

抽象操作 CharacterComplement,接收参数 regexpRecord (RegExp 记录) 和 complement (CharSet);返回值:CharSet。 调用时执行以下步骤:

  1. 令 charSet 为 AllCharacters(regexpRecord)。
  2. 返回包含 charSet 中不同时也是 complement 的 CharSetElement 的所有 CharSetElement 的 CharSet。

22.2.2.9.7 UnicodeMatchProperty ( regexpRecord, p )

抽象操作 UnicodeMatchProperty,接收参数 regexpRecord (RegExp 记录) 和 p (ECMAScript 源文本);返回值:a Unicode property name。 调用时执行以下步骤:

  1. 如果 regexpRecord.[[UnicodeSets]] 是 true,并且 p 是 表 67 的“Property name”列中列出的Unicode 属性名称,则
    1. 返回 Unicode 码点 List p。
  2. 断言:p 是 表 65 或 表 66 的“Property name and aliases”列中列出的Unicode 属性名称或属性别名。
  3. 令 c 为相应行的“Canonical property name”列中给出的 p 的规范属性名称。
  4. 返回 Unicode 码点 List c。

实现必须支持 表 65、表 66 和 表 67 中列出的Unicode 属性名称和别名。为确保互操作性,实现不得支持任何其他属性名称或别名。

注 1

例如,Script_Extensions(属性名称)和 scx(属性别名)有效,但 script_extensions 或 Scx 无效。

注 2

列出的属性构成 UTS18 RL1.2 所要求内容的超集。

注 3

这些表中条目的拼写(包括大小写)与 Unicode Character Database 中 PropertyAliases.txt 文件使用的拼写一致。该文件中的精确拼写保证保持稳定。

表 65: Non-binary Unicode property aliases and their canonical property names
Property name and aliases Canonical property name
General_Category General_Category
gc
Script Script
sc
Script_Extensions Script_Extensions
scx
表 66: Binary Unicode property aliases and their canonical property names
Property name and aliases Canonical property name
ASCII ASCII
ASCII_Hex_Digit ASCII_Hex_Digit
AHex
Alphabetic Alphabetic
Alpha
Any Any
Assigned Assigned
Bidi_Control Bidi_Control
Bidi_C
Bidi_Mirrored Bidi_Mirrored
Bidi_M
Case_Ignorable Case_Ignorable
CI
Cased Cased
Changes_When_Casefolded Changes_When_Casefolded
CWCF
Changes_When_Casemapped Changes_When_Casemapped
CWCM
Changes_When_Lowercased Changes_When_Lowercased
CWL
Changes_When_NFKC_Casefolded Changes_When_NFKC_Casefolded
CWKCF
Changes_When_Titlecased Changes_When_Titlecased
CWT
Changes_When_Uppercased Changes_When_Uppercased
CWU
Dash Dash
Default_Ignorable_Code_Point Default_Ignorable_Code_Point
DI
Deprecated Deprecated
Dep
Diacritic Diacritic
Dia
Emoji Emoji
Emoji_Component Emoji_Component
EComp
Emoji_Modifier Emoji_Modifier
EMod
Emoji_Modifier_Base Emoji_Modifier_Base
EBase
Emoji_Presentation Emoji_Presentation
EPres
Extended_Pictographic Extended_Pictographic
ExtPict
Extender Extender
Ext
Grapheme_Base Grapheme_Base
Gr_Base
Grapheme_Extend Grapheme_Extend
Gr_Ext
Hex_Digit Hex_Digit
Hex
IDS_Binary_Operator IDS_Binary_Operator
IDSB
IDS_Trinary_Operator IDS_Trinary_Operator
IDST
ID_Continue ID_Continue
IDC
ID_Start ID_Start
IDS
Ideographic Ideographic
Ideo
Join_Control Join_Control
Join_C
Logical_Order_Exception Logical_Order_Exception
LOE
Lowercase Lowercase
Lower
Math Math
Noncharacter_Code_Point Noncharacter_Code_Point
NChar
Pattern_Syntax Pattern_Syntax
Pat_Syn
Pattern_White_Space Pattern_White_Space
Pat_WS
Quotation_Mark Quotation_Mark
QMark
Radical Radical
Regional_Indicator Regional_Indicator
RI
Sentence_Terminal Sentence_Terminal
STerm
Soft_Dotted Soft_Dotted
SD
Terminal_Punctuation Terminal_Punctuation
Term
Unified_Ideograph Unified_Ideograph
UIdeo
Uppercase Uppercase
Upper
Variation_Selector Variation_Selector
VS
White_Space White_Space
space
XID_Continue XID_Continue
XIDC
XID_Start XID_Start
XIDS
表 67: Binary Unicode properties of strings
Property name
Basic_Emoji
Emoji_Keycap_Sequence
RGI_Emoji_Modifier_Sequence
RGI_Emoji_Flag_Sequence
RGI_Emoji_Tag_Sequence
RGI_Emoji_ZWJ_Sequence
RGI_Emoji

22.2.2.9.8 UnicodeMatchPropertyValue ( p, v )

抽象操作 UnicodeMatchPropertyValue,接收参数 p (ECMAScript 源文本) 和 v (ECMAScript 源文本);返回值:a Unicode property value。 调用时执行以下步骤:

  1. 断言:p 是 表 65 的“Canonical property name”列中列出的规范、无别名的Unicode 属性名称。
  2. 断言:v 是 PropertyValueAliases.txt 中为 Unicode 属性 p 列出的属性值或属性值别名。
  3. 令 value 为相应行的“Canonical property value”列中给出的 v 的规范属性值。
  4. 返回 Unicode 码点 List value。

实现必须支持 PropertyValueAliases.txt 中为 表 65 所列属性提供的 Unicode 属性值和属性值别名。为确保互操作性,实现不得支持任何其他属性值或属性值别名。

注 1

例如,Xpeo 和 Old_Persian 是有效的 Script_Extensions 值,但 xpeo 和 Old Persian 无效。

注 2

此算法与 UAX44 中列出的符号值匹配规则不同:不会忽略大小写、空白、U+002D (HYPHEN-MINUS) 和 U+005F (LOW LINE),并且不支持 Is 前缀。

22.2.2.10 Runtime Semantics: CompileClassSetString

语法制导操作 CompileClassSetString,接收参数 regexpRecord (RegExp 记录);返回值:a sequence of characters。 它按以下产生式分别定义:

ClassString :: [empty]
  1. 返回空字符序列。
ClassString :: NonEmptyClassString
  1. 返回 CompileClassSetString of NonEmptyClassString with argument regexpRecord。
NonEmptyClassString :: ClassSetCharacter NonEmptyClassStringopt
  1. 令 cs 为 CompileToCharSet of ClassSetCharacter with argument regexpRecord。
  2. 令 s1 为 cs 中唯一 CharSetElement 所组成的字符序列。
  3. 如果存在 NonEmptyClassString,则
    1. 令 s2 为 CompileClassSetString of NonEmptyClassString with argument regexpRecord。
    2. 返回 s1 和 s2 的连接。
  4. 返回 s1。

22.2.3 RegExp 创建的抽象操作

22.2.3.1 RegExpCreate ( pattern, flags )

抽象操作 RegExpCreate,接收参数 pattern (ECMAScript 语言值) 和 flags ((String 或 undefined));返回值:(正常完成 (值:Object) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 obj 为 ! RegExpAlloc(%RegExp%)。
  2. 返回 ? RegExpInitialize(obj, pattern, flags)。

22.2.3.2 RegExpAlloc ( newTarget )

抽象操作 RegExpAlloc,接收参数 newTarget (构造函数);返回值:(正常完成 (值:Object) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 obj 为 ? OrdinaryCreateFromConstructor(newTarget, "%RegExp.prototype%", « [[OriginalSource]], [[OriginalFlags]], [[RegExpRecord]], [[RegExpMatcher]] »)。
  2. 执行 ! DefinePropertyOrThrow(obj, "lastIndex", PropertyDescriptor { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  3. 返回 obj。

22.2.3.3 RegExpInitialize ( obj, pattern, flags )

抽象操作 RegExpInitialize,接收参数 obj (Object)、pattern (ECMAScript 语言值) 和 flags (ECMAScript 语言值);返回值:(正常完成 (值:Object) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 pattern 是 undefined,则将 pattern 设置为空 String。
  2. 否则,将 pattern 设置为 ? ToString(pattern)。
  3. 如果 flags 是 undefined,则将 flags 设置为空 String。
  4. 否则,将 flags 设置为 ? ToString(flags)。
  5. 如果 flags 包含除 "d"、"g"、"i"、"m"、"s"、"u"、"v" 或 "y" 之外的任何码元,则抛出 SyntaxError 异常。
  6. 如果 flags 多次包含任何码元,则抛出 SyntaxError 异常。
  7. 如果 flags 包含 "i",则令 i 为 true;否则令 i 为 false。
  8. 如果 flags 包含 "m",则令 m 为 true;否则令 m 为 false。
  9. 如果 flags 包含 "s",则令 s 为 true;否则令 s 为 false。
  10. 如果 flags 包含 "u",则令 u 为 true;否则令 u 为 false。
  11. 如果 flags 包含 "v",则令 v 为 true;否则令 v 为 false。
  12. 如果 u 是 true 或 v 是 true,则
    1. 令 patternText 为 StringToCodePoints(pattern)。
  13. 否则,
    1. 令 patternText 为将 pattern 的每个 16 位元素解释为 Unicode BMP 码点所得的结果。不会对这些元素应用 UTF-16 解码。
  14. 令 parseResult 为 ParsePattern(patternText, u, v)。
  15. 如果 parseResult 是非空的 SyntaxError 对象 List,则抛出 SyntaxError 异常。
  16. 断言:parseResult 是 Pattern Parse Node。
  17. 将 obj.[[OriginalSource]] 设置为 pattern。
  18. 将 obj.[[OriginalFlags]] 设置为 flags。
  19. 令 capturingGroupsCount 为 CountLeftCapturingParensWithin(parseResult)。
  20. 令 regexpRecord 为 RegExp Record { [[IgnoreCase]]: i, [[Multiline]]: m, [[DotAll]]: s, [[Unicode]]: u, [[UnicodeSets]]: v, [[CapturingGroupsCount]]: capturingGroupsCount }。
  21. 将 obj.[[RegExpRecord]] 设置为 regexpRecord。
  22. 将 obj.[[RegExpMatcher]] 设置为 CompilePattern of parseResult with argument regexpRecord。
  23. 执行 ? Set(obj, "lastIndex", +0𝔽, true)。
  24. 返回 obj。

22.2.3.4 Static Semantics: ParsePattern ( patternText, u, v )

抽象操作 ParsePattern,接收参数 patternText (a sequence of Unicode code points)、u (Boolean) 和 v (Boolean);返回值:(解析节点 或 a non-empty List of SyntaxError objects)。

注

本节在 B.1.2.9 中进行了修订。

调用时执行以下步骤:

  1. 如果 v 是 true 且 u 是 true,则
    1. 令 parseResult 为包含一个或多个 SyntaxError 对象的 List。
  2. 否则如果 v 是 true,则
    1. 令 parseResult 为 ParseText(patternText, Pattern[+UnicodeMode, +UnicodeSetsMode, +NamedCaptureGroups])。
  3. 否则如果 u 是 true,则
    1. 令 parseResult 为 ParseText(patternText, Pattern[+UnicodeMode, ~UnicodeSetsMode, +NamedCaptureGroups])。
  4. 否则,
    1. 令 parseResult 为 ParseText(patternText, Pattern[~UnicodeMode, ~UnicodeSetsMode, +NamedCaptureGroups])。
  5. 返回 parseResult。

22.2.4 RegExp 构造函数

RegExp 构造函数:

  • 是 %RegExp%。
  • 是全局对象的 "RegExp" 属性的初始值。
  • 作为构造函数调用时,创建并初始化新的 RegExp 对象。
  • 作为函数而不是构造函数调用时,要么返回新的 RegExp 对象,要么如果唯一参数是 RegExp 对象,则返回该参数本身。
  • 可以用作类定义的 extends 子句的值。希望继承指定 RegExp 行为的子类构造函数必须包含对 RegExp 构造函数的 super 调用,以创建并初始化具有必要内部槽的子类实例。

22.2.4.1 RegExp ( patternOrRegexp, flags )

调用时,此函数执行以下步骤:

  1. 令 patternIsRegExp 为 ? IsRegExp(patternOrRegexp)。
  2. 如果 NewTarget 是 undefined,则
    1. 令 newTarget 为活动函数对象。
    2. 如果 patternIsRegExp 是 true 且 flags 是 undefined,则
      1. 令 patternCtor 为 ? Get(patternOrRegexp, "constructor")。
      2. 如果 SameValue(newTarget, patternCtor) 是 true,则返回 patternOrRegexp。
  3. 否则,
    1. 令 newTarget 为 NewTarget。
  4. 如果 patternOrRegexp 是 Object 且 patternOrRegexp 具有 [[RegExpMatcher]] 内部槽,则
    1. 令 patternSource 为 patternOrRegexp.[[OriginalSource]]。
    2. 如果 flags 是 undefined,则将 flags 设置为 patternOrRegexp.[[OriginalFlags]]。
  5. 否则如果 patternIsRegExp 是 true,则
    1. 令 patternSource 为 ? Get(patternOrRegexp, "source")。
    2. 如果 flags 是 undefined,则
      1. 将 flags 设置为 ? Get(patternOrRegexp, "flags")。
  6. 否则,
    1. 令 patternSource 为 patternOrRegexp。
  7. 令 obj 为 ? RegExpAlloc(newTarget)。
  8. 返回 ? RegExpInitialize(obj, patternSource, flags)。
注

如果使用 StringLiteral 提供 pattern,则在该 String 被此函数处理之前会执行通常的转义序列替换。如果 pattern 必须包含此函数要识别的转义序列,则任何 U+005C (REVERSE SOLIDUS) 码点都必须在 StringLiteral 中进行转义,以防止它们在形成 StringLiteral 内容时被移除。

22.2.5 RegExp 构造函数的属性

RegExp 构造函数:

22.2.5.1 RegExp.escape ( string )

此函数返回 string 的副本,其中在正则表达式 Pattern 中可能具有特殊含义的字符被替换为等价的转义序列。

调用时,它执行以下步骤:

  1. 如果 string 不是 String,则抛出 TypeError 异常。
  2. 令 escaped 为空 String。
  3. 令 codePointList 为 StringToCodePoints(string)。
  4. 对 codePointList 的每个码点 codePoint,执行
    1. 如果 escaped 是空 String,且 codePoint 被 DecimalDigit 或 AsciiLetter 匹配,则
      1. 注:对前导数字进行转义可确保输出与可能用于 \0 字符转义或 \1 等 DecimalEscape 之后的模式文本相对应,并且仍匹配 string,而不是被解释为前一个转义序列的扩展。对前导 ASCII 字母进行转义,在 \c 之后的上下文中具有相同作用。
      2. 令 numericValue 为 codePoint 的数值。
      3. 令 hex 为 Number::toString(𝔽(numericValue), 16)。
      4. 断言:hex 的长度为 2。
      5. 将 escaped 设置为码元 0x005C (REVERSE SOLIDUS)、"x" 和 hex 的字符串连接。
    2. 否则,
      1. 将 escaped 设置为 escaped 和 EncodeForRegExpEscape(codePoint) 的字符串连接。
  5. 返回 escaped。
注

尽管名称相似,EscapeRegExpPattern 和 RegExp.escape 执行的操作并不相似。前者转义模式以便表示为字符串,而此函数转义字符串以便在模式内部表示。

22.2.5.1.1 EncodeForRegExpEscape ( codePoint )

抽象操作 EncodeForRegExpEscape,接收参数 codePoint (码点);返回值:String。 它返回一个表示用于匹配 codePoint 的 Pattern 的 String。如果 codePoint 是空白或 ASCII 标点符号,则返回值是转义序列。否则,返回值是 codePoint 本身的 String 表示。 调用时执行以下步骤:

  1. 如果 codePoint 被 SyntaxCharacter 匹配,或者 codePoint 是 U+002F (SOLIDUS),则
    1. 返回 0x005C (REVERSE SOLIDUS) 和 UTF16EncodeCodePoint(codePoint) 的字符串连接。
  2. 如果 codePoint 是 表 63 的“Code Point”列中列出的码点,则
    1. 返回 0x005C (REVERSE SOLIDUS) 与该表中“Code Point”列包含 codePoint 的行的“ControlEscape”列中的字符串的字符串连接。
  3. 令 otherPunctuators 为 ",-=<>#&!%:;@~'`" 与码元 0x0022 (QUOTATION MARK) 的字符串连接。
  4. 令 toEscape 为 StringToCodePoints(otherPunctuators)。
  5. 如果 toEscape 包含 codePoint、codePoint 被 WhiteSpace 或 LineTerminator 匹配,或者 codePoint 的数值与前导代理项或尾随代理项相同,则
    1. 令 codePointNumber 为 codePoint 的数值。
    2. 如果 codePointNumber ≤ 0xFF,则
      1. 令 hex 为 Number::toString(𝔽(codePointNumber), 16)。
      2. 返回码元 0x005C (REVERSE SOLIDUS)、"x" 和 StringPad(hex, 2, "0", start) 的字符串连接。
    3. 令 escaped 为空 String。
    4. 令 codeUnits 为 UTF16EncodeCodePoint(codePoint)。
    5. 对 codeUnits 的每个码元 codeUnit,执行
      1. 将 escaped 设置为 escaped 和 UnicodeEscape(codeUnit) 的字符串连接。
    6. 返回 escaped。
  6. 返回 UTF16EncodeCodePoint(codePoint)。

22.2.5.2 RegExp.prototype

RegExp.prototype 的初始值是 RegExp 原型对象。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

22.2.5.3 get RegExp [ %Symbol.species% ]

RegExp[%Symbol.species%] 是访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数在调用时执行以下步骤:

  1. 返回 this value。

此函数的 "name" 属性值是 "get [Symbol.species]"。

注

RegExp 原型方法通常使用其 this value 的构造函数创建派生对象。不过,子类构造函数可以通过重新定义其 %Symbol.species% 属性来覆盖该默认行为。

22.2.6 RegExp 原型对象的属性

RegExp 原型对象:

  • 是 %RegExp.prototype%。
  • 是普通对象。
  • 不是 RegExp 实例,并且没有 [[RegExpMatcher]] 内部槽或 RegExp 实例对象的任何其他内部槽。
  • 具有 [[Prototype]] 内部槽,其值是 %Object.prototype%。
注

RegExp 原型对象没有自己的 "valueOf" 属性;不过,它从 Object 原型对象继承 "valueOf" 属性。

22.2.6.1 RegExp.prototype.constructor

RegExp.prototype.constructor 的初始值是 %RegExp%。

22.2.6.2 RegExp.prototype.exec ( string )

此方法在 string 中搜索正则表达式模式的出现位置,并返回包含匹配结果的 Array;如果 string 没有匹配,则返回 null。

调用时,它执行以下步骤:

  1. 令 regexp 为 this value。
  2. 执行 ? RequireInternalSlot(regexp, [[RegExpMatcher]])。
  3. 将 string 设置为 ? ToString(string)。
  4. 返回 ? RegExpBuiltinExec(regexp, string)。

22.2.6.3 get RegExp.prototype.dotAll

RegExp.prototype.dotAll 是访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数在调用时执行以下步骤:

  1. 令 regexp 为 this value。
  2. 令 codeUnit 为码元 0x0073 (LATIN SMALL LETTER S)。
  3. 返回 ? RegExpHasFlag(regexp, codeUnit)。

22.2.6.4 get RegExp.prototype.flags

RegExp.prototype.flags 是访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数在调用时执行以下步骤:

  1. 令 regexp 为 this value。
  2. 如果 regexp 不是 Object,则抛出 TypeError 异常。
  3. 令 codeUnits 为新的空 List。
  4. 令 hasIndices 为 ToBoolean(? Get(regexp, "hasIndices")).
  5. 如果 hasIndices 是 true,则将码元 0x0064 (LATIN SMALL LETTER D) 追加到 codeUnits。
  6. 令 global 为 ToBoolean(? Get(regexp, "global")).
  7. 如果 global 是 true,则将码元 0x0067 (LATIN SMALL LETTER G) 追加到 codeUnits。
  8. 令 ignoreCase 为 ToBoolean(? Get(regexp, "ignoreCase")).
  9. 如果 ignoreCase 是 true,则将码元 0x0069 (LATIN SMALL LETTER I) 追加到 codeUnits。
  10. 令 multiline 为 ToBoolean(? Get(regexp, "multiline")).
  11. 如果 multiline 是 true,则将码元 0x006D (LATIN SMALL LETTER M) 追加到 codeUnits。
  12. 令 dotAll 为 ToBoolean(? Get(regexp, "dotAll")).
  13. 如果 dotAll 是 true,则将码元 0x0073 (LATIN SMALL LETTER S) 追加到 codeUnits。
  14. 令 unicode 为 ToBoolean(? Get(regexp, "unicode")).
  15. 如果 unicode 是 true,则将码元 0x0075 (LATIN SMALL LETTER U) 追加到 codeUnits。
  16. 令 unicodeSets 为 ToBoolean(? Get(regexp, "unicodeSets")).
  17. 如果 unicodeSets 是 true,则将码元 0x0076 (LATIN SMALL LETTER V) 追加到 codeUnits。
  18. 令 sticky 为 ToBoolean(? Get(regexp, "sticky")).
  19. 如果 sticky 是 true,则将码元 0x0079 (LATIN SMALL LETTER Y) 追加到 codeUnits。
  20. 返回其码元为 List codeUnits 中各元素的 String 值。如果 codeUnits 没有元素,则返回空 String。

22.2.6.4.1 RegExpHasFlag ( regexp, codeUnit )

抽象操作 RegExpHasFlag,接收参数 regexp (ECMAScript 语言值) 和 codeUnit (码元);返回值:(正常完成 (值:(Boolean 或 undefined)) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 regexp 不是 Object,则抛出 TypeError 异常。
  2. 如果 regexp 没有 [[OriginalFlags]] 内部槽,则
    1. 如果 SameValue(regexp, %RegExp.prototype%) 是 true,则返回 undefined。
    2. 抛出 TypeError 异常。
  3. 令 flags 为 regexp.[[OriginalFlags]]。
  4. 如果 flags 包含 codeUnit,则返回 true。
  5. 返回 false。

22.2.6.5 get RegExp.prototype.global

RegExp.prototype.global 是访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数在调用时执行以下步骤:

  1. 令 regexp 为 this value。
  2. 令 codeUnit 为码元 0x0067 (LATIN SMALL LETTER G)。
  3. 返回 ? RegExpHasFlag(regexp, codeUnit)。

22.2.6.6 get RegExp.prototype.hasIndices

RegExp.prototype.hasIndices 是访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数在调用时执行以下步骤:

  1. 令 regexp 为 this value。
  2. 令 codeUnit 为码元 0x0064 (LATIN SMALL LETTER D)。
  3. 返回 ? RegExpHasFlag(regexp, codeUnit)。

22.2.6.7 get RegExp.prototype.ignoreCase

RegExp.prototype.ignoreCase 是访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数在调用时执行以下步骤:

  1. 令 regexp 为 this value。
  2. 令 codeUnit 为码元 0x0069 (LATIN SMALL LETTER I)。
  3. 返回 ? RegExpHasFlag(regexp, codeUnit)。

22.2.6.8 RegExp.prototype [ %Symbol.match% ] ( string )

调用时,此方法执行以下步骤:

  1. 令 regexp 为 this value。
  2. 如果 regexp 不是 Object,则抛出 TypeError 异常。
  3. 将 string 设置为 ? ToString(string)。
  4. 令 flags 为 ? ToString(? Get(regexp, "flags")).
  5. 如果 flags 不包含 "g",则返回 ? RegExpExec(regexp, string)。
  6. 如果 flags 包含 "u" 或 flags 包含 "v",则令 fullUnicode 为 true;否则令 fullUnicode 为 false。
  7. 执行 ? Set(regexp, "lastIndex", +0𝔽, true)。
  8. 令 array 为 ! ArrayCreate(0)。
  9. 令 matchCount 为 0。
  10. 重复执行,
    1. 令 result 为 ? RegExpExec(regexp, string)。
    2. 如果 result 是 null,则
      1. 如果 matchCount = 0,则返回 null。
      2. 返回 array。
    3. 令 matchString 为 ? ToString(? Get(result, "0")).
    4. 执行 ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(matchCount)), matchString)。
    5. 如果 matchString 是空 String,则
      1. 令 thisIndex 为 ℝ(? ToLength(? Get(regexp, "lastIndex")))。
      2. 令 nextIndex 为 AdvanceStringIndex(string, thisIndex, fullUnicode)。
      3. 执行 ? Set(regexp, "lastIndex", 𝔽(nextIndex), true)。
    6. 将 matchCount 设置为 matchCount + 1。

此方法的 "name" 属性值是 "[Symbol.match]"。

注

%Symbol.match% 属性由 IsRegExp 抽象操作用于识别具有正则表达式基本行为的对象。缺少 %Symbol.match% 属性,或者存在该属性但其值进行 Boolean 强制转换后不为 true,表示该对象并非旨在用作正则表达式对象。

22.2.6.9 RegExp.prototype [ %Symbol.matchAll% ] ( string )

调用时,此方法执行以下步骤:

  1. 令 regexp 为 this value。
  2. 如果 regexp 不是 Object,则抛出 TypeError 异常。
  3. 将 string 设置为 ? ToString(string)。
  4. 令 speciesCtor 为 ? SpeciesConstructor(regexp, %RegExp%)。
  5. 令 flags 为 ? ToString(? Get(regexp, "flags")).
  6. 令 matcher 为 ? Construct(speciesCtor, « regexp, flags »)。
  7. 令 lastIndex 为 ? ToLength(? Get(regexp, "lastIndex")).
  8. 执行 ? Set(matcher, "lastIndex", lastIndex, true)。
  9. 如果 flags 包含 "g",则令 global 为 true。
  10. 否则,令 global 为 false。
  11. 如果 flags 包含 "u" 或 flags 包含 "v",则令 fullUnicode 为 true。
  12. 否则,令 fullUnicode 为 false。
  13. 返回 CreateRegExpStringIterator(matcher, string, global, fullUnicode)。

此方法的 "name" 属性值是 "[Symbol.matchAll]"。

22.2.6.10 get RegExp.prototype.multiline

RegExp.prototype.multiline 是访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数在调用时执行以下步骤:

  1. 令 regexp 为 this value。
  2. 令 codeUnit 为码元 0x006D (LATIN SMALL LETTER M)。
  3. 返回 ? RegExpHasFlag(regexp, codeUnit)。

22.2.6.11 RegExp.prototype [ %Symbol.replace% ] ( string, replaceValue )

调用时,此方法执行以下步骤:

  1. 令 regexp 为 this value。
  2. 如果 regexp 不是 Object,则抛出 TypeError 异常。
  3. 将 string 设置为 ? ToString(string)。
  4. 令 stringLength 为 string 的长度。
  5. 令 functionalReplace 为 IsCallable(replaceValue)。
  6. 如果 functionalReplace 是 false,则
    1. 将 replaceValue 设置为 ? ToString(replaceValue)。
  7. 令 flags 为 ? ToString(? Get(regexp, "flags")).
  8. 如果 flags 包含 "g",则令 global 为 true;否则令 global 为 false。
  9. 如果 global 是 true,则
    1. 执行 ? Set(regexp, "lastIndex", +0𝔽, true)。
  10. 令 results 为新的空 List。
  11. 令 done 为 false。
  12. 当 done 是 false 时,重复执行,
    1. 令 result 为 ? RegExpExec(regexp, string)。
    2. 如果 result 是 null,则
      1. 将 done 设置为 true。
    3. 否则,
      1. 将 result 追加到 results。
      2. 如果 global 是 false,则
        1. 将 done 设置为 true。
      3. 否则,
        1. 令 matchString 为 ? ToString(? Get(result, "0")).
        2. 如果 matchString 是空 String,则
          1. 令 thisIndex 为 ℝ(? ToLength(? Get(regexp, "lastIndex")))。
          2. 如果 flags 包含 "u" 或 flags 包含 "v",则令 fullUnicode 为 true;否则令 fullUnicode 为 false。
          3. 令 nextIndex 为 AdvanceStringIndex(string, thisIndex, fullUnicode)。
          4. 执行 ? Set(regexp, "lastIndex", 𝔽(nextIndex), true)。
  13. 令 accumulatedResult 为空 String。
  14. 令 nextSourcePosition 为 0。
  15. 对 results 的每个元素 result,执行
    1. 令 resultLength 为 ? LengthOfArrayLike(result)。
    2. 令 capturesCount 为 max(resultLength - 1, 0)。
    3. 令 matched 为 ? ToString(? Get(result, "0")).
    4. 令 matchLength 为 matched 的长度。
    5. 令 position 为 ? ToIntegerOrInfinity(? Get(result, "index")).
    6. 将 position 设置为将 position 限制在 0 和 stringLength 之间的结果。
    7. 令 captures 为新的空 List。
    8. 令 captureNumber 为 1。
    9. 当 captureNumber ≤ capturesCount 时,重复执行,
      1. 令 capture 为 ? Get(result, ! ToString(𝔽(captureNumber)))。
      2. 如果 capture 不是 undefined,则
        1. 将 capture 设置为 ? ToString(capture)。
      3. 将 capture 追加到 captures。
      4. 注:当 captureNumber = 1 时,前一步会将第一个元素放入 captures(索引 0)。更一般地,第 captureNumberth 个捕获(由第 captureNumberth 组捕获括号捕获的字符)位于 captures[captureNumber - 1]。
      5. 将 captureNumber 设置为 captureNumber + 1。
    10. 令 namedCaptures 为 ? Get(result, "groups")。
    11. 如果 functionalReplace 是 true,则
      1. 令 replacerArgs 为 « matched »、captures 和 « 𝔽(position), string » 的列表连接。
      2. 如果 namedCaptures 不是 undefined,则
        1. 将 namedCaptures 追加到 replacerArgs。
      3. 令 replacementValue 为 ? Call(replaceValue, undefined, replacerArgs)。
      4. 令 replacementString 为 ? ToString(replacementValue)。
    12. 否则,
      1. 如果 namedCaptures 不是 undefined,则
        1. 将 namedCaptures 设置为 ? ToObject(namedCaptures)。
      2. 令 replacementString 为 ? GetSubstitution(matched, string, position, captures, namedCaptures, replaceValue)。
    13. 如果 position ≥ nextSourcePosition,则
      1. 注:position 通常不应向后移动。如果发生这种情况,则表明存在行为不当的 RegExp 子类,或者使用由访问触发的副作用改变 regexp 的 global 标志或其他特征。在这种情况下,相应的替换会被忽略。
      2. 将 accumulatedResult 设置为 accumulatedResult、string 从 nextSourcePosition 到 position 的子字符串以及 replacementString 的字符串连接。
      3. 将 nextSourcePosition 设置为 position + matchLength。
  16. 如果 nextSourcePosition ≥ stringLength,则返回 accumulatedResult。
  17. 返回 accumulatedResult 和 string 从 nextSourcePosition 开始的子字符串的字符串连接。

此方法的 "name" 属性值是 "[Symbol.replace]"。

22.2.6.12 RegExp.prototype [ %Symbol.search% ] ( string )

调用时,此方法执行以下步骤:

  1. 令 regexp 为 this value。
  2. 如果 regexp 不是 Object,则抛出 TypeError 异常。
  3. 将 string 设置为 ? ToString(string)。
  4. 令 previousLastIndex 为 ? Get(regexp, "lastIndex")。
  5. 如果 previousLastIndex 不是 +0𝔽,则
    1. 执行 ? Set(regexp, "lastIndex", +0𝔽, true)。
  6. 令 result 为 ? RegExpExec(regexp, string)。
  7. 令 currentLastIndex 为 ? Get(regexp, "lastIndex")。
  8. 如果 SameValue(currentLastIndex, previousLastIndex) 是 false,则
    1. 执行 ? Set(regexp, "lastIndex", previousLastIndex, true)。
  9. 如果 result 是 null,则返回 -1𝔽。
  10. 返回 ? Get(result, "index")。

此方法的 "name" 属性值是 "[Symbol.search]"。

注

执行搜索时,会忽略此 RegExp 对象的 "lastIndex" 和 "global" 属性。"lastIndex" 属性保持不变。

22.2.6.13 get RegExp.prototype.source

RegExp.prototype.source 是访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数在调用时执行以下步骤:

  1. 令 regexp 为 this value。
  2. 如果 regexp 不是 Object,则抛出 TypeError 异常。
  3. 如果 regexp 没有 [[OriginalSource]] 内部槽,则
    1. 如果 SameValue(regexp, %RegExp.prototype%) 是 true,则返回 "(?:)"。
    2. 抛出 TypeError 异常。
  4. 断言:regexp 具有 [[OriginalFlags]] 内部槽。
  5. 令 source 为 regexp.[[OriginalSource]]。
  6. 令 flags 为 regexp.[[OriginalFlags]]。
  7. 返回 EscapeRegExpPattern(source, flags)。

22.2.6.13.1 EscapeRegExpPattern ( pattern, flags )

抽象操作 EscapeRegExpPattern,接收参数 pattern (String) 和 flags (String);返回值:String。 调用时执行以下步骤:

  1. 如果 flags 包含 "v",则
    1. 令 patternSymbol 为 Pattern[+UnicodeMode, +UnicodeSetsMode]。
  2. 否则如果 flags 包含 "u",则
    1. 令 patternSymbol 为 Pattern[+UnicodeMode, ~UnicodeSetsMode]。
  3. 否则,
    1. 令 patternSymbol 为 Pattern[~UnicodeMode, ~UnicodeSetsMode]。
  4. 令 escapedPattern 为形式为 patternSymbol 的 String,它等价于将 pattern 解释为 UTF-16 编码 Unicode 码点(6.1.4),其中某些码点按下述方式进行转义。escapedPattern 可以与 pattern 相同,也可以不同;不过,将 escapedPattern 作为 patternSymbol 求值所得的 Abstract Closure 必须与构造对象的 [[RegExpMatcher]] 内部槽所给出的 Abstract Closure 行为完全相同。使用相同 pattern 和 flags 值多次调用此抽象操作时,必须产生相同结果。
  5. 模式中出现的码点 / 或任何 LineTerminator 都应在 escapedPattern 中按需要进行转义,以确保 "/"、escapedPattern、"/" 和 flags 的字符串连接可以(在适当的词法上下文中)解析为行为与所构造正则表达式完全相同的 RegularExpressionLiteral。例如,如果 pattern 是 "/",则 escapedPattern 可以是 "\/" 或 "\u002F" 等,但不能是 "/",因为 /// 后跟 flags 会被解析为 SingleLineComment,而不是 RegularExpressionLiteral。如果 pattern 是空 String,则可以令 escapedPattern 为 "(?:)" 来满足本规范。
  6. 返回 escapedPattern。
注

尽管名称相似,RegExp.escape 和 EscapeRegExpPattern 执行的操作并不相似。前者转义字符串以便在模式内部表示,而此函数转义模式以便表示为字符串。

22.2.6.14 RegExp.prototype [ %Symbol.split% ] ( string, limit )

注 1

此方法返回一个 Array,其中存储了将 string 转换为 String 所得结果的子字符串。这些子字符串通过从左到右搜索 this value 正则表达式的匹配来确定;这些出现位置不属于返回数组中的任何 String,而是用于分割 String 值。

this value 可以是空正则表达式,也可以是能够匹配空 String 的正则表达式。在这种情况下,正则表达式不匹配输入 String 开头或末尾的空子字符串,也不匹配上一个分隔符匹配末尾的空子字符串。(例如,如果正则表达式匹配空 String,则 String 会被拆分成单独的码元元素;结果数组的长度等于 String 的长度,并且每个子字符串包含一个码元。)在 String 的给定索引处只考虑第一次匹配,即使回溯可以在该索引处得到非空子字符串匹配。(例如,/a*?/[Symbol.split]("ab") 求值为数组 ["a", "b"],而 /a*/[Symbol.split]("ab") 求值为数组 ["","b"]。)

如果 string 是空 String(或转换为后是空 String),则结果取决于正则表达式是否能够匹配空 String。如果可以,则结果数组不包含任何元素。否则,结果数组包含一个元素,即空 String。

如果正则表达式包含捕获括号,则每次匹配 separator 时,捕获括号的结果(包括任何 undefined 结果)都会插入输出数组。例如,

/<(\/)?([^<>]+)>/[Symbol.split]("A<B>bold</B>and<CODE>coded</CODE>")

求值为数组

["A", undefined, "B", "bold", "/", "B", "and", undefined, "CODE", "coded", "/", "CODE", ""]

如果 limit 不是 undefined,则输出数组会被截断,使其包含的元素不超过 limit 个。

调用时,此方法执行以下步骤:

  1. 令 regexp 为 this value。
  2. 如果 regexp 不是 Object,则抛出 TypeError 异常。
  3. 将 string 设置为 ? ToString(string)。
  4. 令 speciesCtor 为 ? SpeciesConstructor(regexp, %RegExp%)。
  5. 令 flags 为 ? ToString(? Get(regexp, "flags")).
  6. 如果 flags 包含 "u" 或 flags 包含 "v",则令 unicodeMatching 为 true。
  7. 否则,令 unicodeMatching 为 false。
  8. 如果 flags 包含 "y",则令 newFlags 为 flags。
  9. 否则,令 newFlags 为 flags 和 "y" 的字符串连接。
  10. 令 splitter 为 ? Construct(speciesCtor, « regexp, newFlags »)。
  11. 令 array 为 ! ArrayCreate(0)。
  12. 令 lengthA 为 0。
  13. 如果 limit 是 undefined,则令 lim 为 232 - 1;否则令 lim 为 ℝ(? ToUint32(limit))。
  14. 如果 lim = 0,则返回 array。
  15. 如果 string 是空 String,则
    1. 令 matchResult 为 ? RegExpExec(splitter, string)。
    2. 如果 matchResult 不是 null,则返回 array。
    3. 执行 ! CreateDataPropertyOrThrow(array, "0", string)。
    4. 返回 array。
  16. 令 size 为 string 的长度。
  17. 令 lastMatchEnd 为 0。
  18. 令 searchIndex 为 lastMatchEnd。
  19. 当 searchIndex < size 时,重复执行,
    1. 执行 ? Set(splitter, "lastIndex", 𝔽(searchIndex), true)。
    2. 令 matchResult 为 ? RegExpExec(splitter, string)。
    3. 如果 matchResult 是 null,则
      1. 将 searchIndex 设置为 AdvanceStringIndex(string, searchIndex, unicodeMatching)。
    4. 否则,
      1. 令 matchEnd 为 ℝ(? ToLength(? Get(splitter, "lastIndex")))。
      2. 将 matchEnd 设置为 min(matchEnd, size)。
      3. 如果 matchEnd = lastMatchEnd,则
        1. 将 searchIndex 设置为 AdvanceStringIndex(string, searchIndex, unicodeMatching)。
      4. 否则,
        1. 令 substring 为 string 从 lastMatchEnd 到 searchIndex 的子字符串。
        2. 执行 ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(lengthA)), substring)。
        3. 将 lengthA 设置为 lengthA + 1。
        4. 如果 lengthA = lim,则返回 array。
        5. 将 lastMatchEnd 设置为 matchEnd。
        6. 令 numberOfCaptures 为 ? LengthOfArrayLike(matchResult)。
        7. 将 numberOfCaptures 设置为 max(numberOfCaptures - 1, 0)。
        8. 令 captureIndex 为 1。
        9. 当 captureIndex ≤ numberOfCaptures 时,重复执行,
          1. 令 nextCapture 为 ? Get(matchResult, ! ToString(𝔽(captureIndex)))。
          2. 执行 ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(lengthA)), nextCapture)。
          3. 将 captureIndex 设置为 captureIndex + 1。
          4. 将 lengthA 设置为 lengthA + 1。
          5. 如果 lengthA = lim,则返回 array。
        10. 将 searchIndex 设置为 lastMatchEnd。
  20. 令 substring 为 string 从 lastMatchEnd 到 size 的子字符串。
  21. 执行 ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(lengthA)), substring)。
  22. 返回 array。

此方法的 "name" 属性值是 "[Symbol.split]"。

注 2

此方法忽略该 RegExp 对象的 "global" 和 "sticky" 属性值。

22.2.6.15 get RegExp.prototype.sticky

RegExp.prototype.sticky 是访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数在调用时执行以下步骤:

  1. 令 regexp 为 this value。
  2. 令 codeUnit 为码元 0x0079 (LATIN SMALL LETTER Y)。
  3. 返回 ? RegExpHasFlag(regexp, codeUnit)。

22.2.6.16 RegExp.prototype.test ( string )

调用时,此方法执行以下步骤:

  1. 令 regexp 为 this value。
  2. 如果 regexp 不是 Object,则抛出 TypeError 异常。
  3. 将 string 设置为 ? ToString(string)。
  4. 令 match 为 ? RegExpExec(regexp, string)。
  5. 如果 match 是 null,则返回 false。
  6. 返回 true。

22.2.6.17 RegExp.prototype.toString ( )

  1. 令 regexp 为 this value。
  2. 如果 regexp 不是 Object,则抛出 TypeError 异常。
  3. 令 pattern 为 ? ToString(? Get(regexp, "source")).
  4. 令 flags 为 ? ToString(? Get(regexp, "flags")).
  5. 令 result 为 "/"、pattern、"/" 和 flags 的字符串连接。
  6. 返回 result。
注

返回的 String 具有 RegularExpressionLiteral 的形式,其求值会产生另一个与此对象行为相同的 RegExp 对象。

22.2.6.18 get RegExp.prototype.unicode

RegExp.prototype.unicode 是访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数在调用时执行以下步骤:

  1. 令 regexp 为 this value。
  2. 令 codeUnit 为码元 0x0075 (LATIN SMALL LETTER U)。
  3. 返回 ? RegExpHasFlag(regexp, codeUnit)。

22.2.6.19 get RegExp.prototype.unicodeSets

RegExp.prototype.unicodeSets 是访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数在调用时执行以下步骤:

  1. 令 regexp 为 this value。
  2. 令 codeUnit 为码元 0x0076 (LATIN SMALL LETTER V)。
  3. 返回 ? RegExpHasFlag(regexp, codeUnit)。

22.2.7 RegExp 匹配的抽象操作

22.2.7.1 RegExpExec ( regexp, string )

抽象操作 RegExpExec,接收参数 regexp (Object) 和 string (String);返回值:(正常完成 (值:(Object 或 null)) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 exec 为 ? Get(regexp, "exec")。
  2. 如果 IsCallable(exec) 是 true,则
    1. 令 result 为 ? Call(exec, regexp, « string »)。
    2. 如果 result 不是 Object 且 result 不是 null,则抛出 TypeError 异常。
    3. 返回 result。
  3. 执行 ? RequireInternalSlot(regexp, [[RegExpMatcher]])。
  4. 返回 ? RegExpBuiltinExec(regexp, string)。
注

如果未找到可调用的 "exec" 属性,此算法会回退到尝试使用内置 RegExp 匹配算法。这为针对早期版本编写的代码提供兼容行为;在那些版本中,大多数使用正则表达式的内置算法不会动态查找 "exec" 属性。

22.2.7.2 RegExpBuiltinExec ( regexp, string )

抽象操作 RegExpBuiltinExec,接收参数 regexp (an initialized RegExp instance) 和 string (String);返回值:(正常完成 (值:(Array 特异对象 或 null)) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 length 为 string 的长度。
  2. 令 lastIndex 为 ℝ(? ToLength(! Get(regexp, "lastIndex")))。
  3. 令 flags 为 regexp.[[OriginalFlags]]。
  4. 如果 flags 包含 "g",则令 global 为 true;否则令 global 为 false。
  5. 如果 flags 包含 "y",则令 sticky 为 true;否则令 sticky 为 false。
  6. 如果 flags 包含 "d",则令 hasIndices 为 true;否则令 hasIndices 为 false。
  7. 如果 global 是 false 且 sticky 是 false,则将 lastIndex 设置为 0。
  8. 令 matcher 为 regexp.[[RegExpMatcher]]。
  9. 如果 flags 包含 "u" 或 flags 包含 "v",则令 fullUnicode 为 true;否则令 fullUnicode 为 false。
  10. 令 matchSucceeded 为 false。
  11. 如果 fullUnicode 是 true,则令 input 为 StringToCodePoints(string);否则令 input 为一个 List,其元素是 string 的元素码元。
  12. 注:input 的每个元素都被视为一个字符。
  13. 当 matchSucceeded 是 false 时,重复执行,
    1. 如果 lastIndex > length,则
      1. 如果 global 是 true 或 sticky 是 true,则
        1. 执行 ? Set(regexp, "lastIndex", +0𝔽, true)。
      2. 返回 null。
    2. 令 inputIndex 为 input 中与 string 的元素 lastIndex 所得到字符对应的索引。
    3. 令 result 为 matcher(input, inputIndex)。
    4. 如果 result 是 failure,则
      1. 如果 sticky 是 true,则
        1. 执行 ? Set(regexp, "lastIndex", +0𝔽, true)。
        2. 返回 null。
      2. 将 lastIndex 设置为 AdvanceStringIndex(string, lastIndex, fullUnicode)。
    5. 否则,
      1. 断言:result 是 MatchState。
      2. 将 matchSucceeded 设置为 true。
  14. 令 endIndex 为 result.[[EndIndex]]。
  15. 如果 fullUnicode 是 true,则将 endIndex 设置为 GetStringIndex(string, endIndex)。
  16. 如果 global 是 true 或 sticky 是 true,则
    1. 执行 ? Set(regexp, "lastIndex", 𝔽(endIndex), true)。
  17. 令 capturingGroupsCount 为 result.[[Captures]] 中的元素数量。
  18. 断言:capturingGroupsCount = regexp.[[RegExpRecord]].[[CapturingGroupsCount]]。
  19. 断言:capturingGroupsCount < 232 - 1。
  20. 令 array 为 ! ArrayCreate(capturingGroupsCount + 1)。
  21. 断言:array 的 "length" 属性的数学值为 capturingGroupsCount + 1。
  22. 执行 ! CreateDataPropertyOrThrow(array, "index", 𝔽(lastIndex))。
  23. 执行 ! CreateDataPropertyOrThrow(array, "input", string)。
  24. 令 match 为 Match Record { [[StartIndex]]: lastIndex, [[EndIndex]]: endIndex }。
  25. 令 indices 为新的空 List。
  26. 令 groupNames 为新的空 List。
  27. 将 match 追加到 indices。
  28. 令 matchedSubstring 为 GetMatchString(string, match)。
  29. 执行 ! CreateDataPropertyOrThrow(array, "0", matchedSubstring)。
  30. 如果 regexp 包含任何 GroupName,则
    1. 令 groups 为 OrdinaryObjectCreate(null)。
    2. 令 hasGroups 为 true。
  31. 否则,
    1. 令 groups 为 undefined。
    2. 令 hasGroups 为 false。
  32. 执行 ! CreateDataPropertyOrThrow(array, "groups", groups)。
  33. 令 matchedGroupNames 为新的空 List。
  34. 按升序,对于满足 1 ≤ i ≤ capturingGroupsCount 的每个整数 i,执行
    1. 令 capture 为 result.[[Captures]] 的第 ith 个元素。
    2. 如果 capture 是 undefined,则
      1. 令 capturedValue 为 undefined。
      2. 将 undefined 追加到 indices。
    3. 否则,
      1. 令 captureStart 为 capture.[[StartIndex]]。
      2. 令 captureEnd 为 capture.[[EndIndex]]。
      3. 如果 fullUnicode 是 true,则
        1. 将 captureStart 设置为 GetStringIndex(string, captureStart)。
        2. 将 captureEnd 设置为 GetStringIndex(string, captureEnd)。
      4. 令 captureRecord 为 Match Record { [[StartIndex]]: captureStart, [[EndIndex]]: captureEnd }。
      5. 令 capturedValue 为 GetMatchString(string, captureRecord)。
      6. 将 captureRecord 追加到 indices。
    4. 执行 ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(i)), capturedValue)。
    5. 如果 regexp 的第 ith 个捕获使用 GroupName 定义,则
      1. 令 groupName 为 CapturingGroupName of that GroupName。
      2. 如果 matchedGroupNames 包含 groupName,则
        1. 断言:capturedValue 是 undefined。
        2. 将 undefined 追加到 groupNames。
      3. 否则,
        1. 如果 capturedValue 不是 undefined,则将 groupName 追加到 matchedGroupNames。
        2. 注:如果存在多个名为 groupName 的组,则此时 groups 可能已经具有 groupName 属性。不过,由于 groups 是一个其属性均为可写数据属性的普通对象,因此对 CreateDataPropertyOrThrow 的调用仍保证成功。
        3. 执行 ! CreateDataPropertyOrThrow(groups, groupName, capturedValue)。
        4. 将 groupName 追加到 groupNames。
    6. 否则,
      1. 将 undefined 追加到 groupNames。
  35. 如果 hasIndices 是 true,则
    1. 令 indicesArray 为 MakeMatchIndicesIndexPairArray(string, indices, groupNames, hasGroups)。
    2. 执行 ! CreateDataPropertyOrThrow(array, "indices", indicesArray)。
  36. 返回 array。

22.2.7.3 AdvanceStringIndex ( string, index, unicode )

抽象操作 AdvanceStringIndex,接收参数 string (String)、index (非负整数) 和 unicode (Boolean);返回值:非负整数。 调用时执行以下步骤:

  1. 断言:index ≤ 253 - 1。
  2. 如果 unicode 是 false,则返回 index + 1。
  3. 令 length 为 string 的长度。
  4. 如果 index + 1 ≥ length,则返回 index + 1。
  5. 令 codePoint 为 CodePointAt(string, index)。
  6. 返回 index + codePoint.[[CodeUnitCount]]。

22.2.7.4 GetStringIndex ( string, codePointIndex )

抽象操作 GetStringIndex,接收参数 string (String) 和 codePointIndex (非负整数);返回值:非负整数。 它按照 6.1.4 中的说明,将 string 解释为 UTF-16 编码码点序列,并在存在相应索引时返回与码点索引 codePointIndex 对应的码元索引。否则,它返回 string 的长度。 调用时执行以下步骤:

  1. 如果 string 是空 String,则返回 0。
  2. 令 length 为 string 的长度。
  3. 令 codeUnitCount 为 0。
  4. 令 codePointCount 为 0。
  5. 当 codeUnitCount < length 时,重复执行,
    1. 如果 codePointCount = codePointIndex,则返回 codeUnitCount。
    2. 令 codePoint 为 CodePointAt(string, codeUnitCount)。
    3. 将 codeUnitCount 设置为 codeUnitCount + codePoint.[[CodeUnitCount]]。
    4. 将 codePointCount 设置为 codePointCount + 1。
  6. 返回 length。

22.2.7.5 Match Record

Match Record 是用于封装正则表达式匹配或捕获的起始和结束索引的 Record。

Match Record 具有 表 68 中列出的字段。

表 68: Match Record 字段
字段名称 值 含义
[[StartIndex]] a non-negative integer 从字符串开头到匹配开始位置(包含)的码元数量。
[[EndIndex]] an integer ≥ [[StartIndex]] 从字符串开头到匹配结束位置(不包含)的码元数量。

22.2.7.6 GetMatchString ( string, match )

抽象操作 GetMatchString,接收参数 string (String) 和 match (Match 记录);返回值:String。 调用时执行以下步骤:

  1. 断言:match.[[StartIndex]] ≤ match.[[EndIndex]] ≤ string 的长度。
  2. 返回 string 从 match.[[StartIndex]] 到 match.[[EndIndex]] 的子字符串。

22.2.7.7 GetMatchIndexPair ( string, match )

抽象操作 GetMatchIndexPair,接收参数 string (String) 和 match (Match 记录);返回值:Array。 调用时执行以下步骤:

  1. 断言:match.[[StartIndex]] ≤ match.[[EndIndex]] ≤ string 的长度。
  2. 返回 CreateArrayFromList(« 𝔽(match.[[StartIndex]]), 𝔽(match.[[EndIndex]]) »)。

22.2.7.8 MakeMatchIndicesIndexPairArray ( string, indices, groupNames, hasGroups )

抽象操作 MakeMatchIndicesIndexPairArray,接收参数 string (String)、indices (列表 (元素:(Match 记录 或 undefined)))、groupNames (列表 (元素:(String 或 undefined))) 和 hasGroups (Boolean);返回值:Array。 调用时执行以下步骤:

  1. 令 n 为 indices 中的元素数量。
  2. 断言:n < 232 - 1。
  3. 断言:groupNames 有 n - 1 个元素。
  4. 注:groupNames List 包含从 indices[1] 开始与 indices List 对齐的元素。
  5. 令 array 为 ! ArrayCreate(n)。
  6. 如果 hasGroups 是 true,则
    1. 令 groups 为 OrdinaryObjectCreate(null)。
  7. 否则,
    1. 令 groups 为 undefined。
  8. 执行 ! CreateDataPropertyOrThrow(array, "groups", groups)。
  9. 按升序,对于满足 0 ≤ i < n 的每个整数 i,执行
    1. 令 matchIndices 为 indices[i]。
    2. 如果 matchIndices 不是 undefined,则
      1. 令 matchIndexPair 为 GetMatchIndexPair(string, matchIndices)。
    3. 否则,
      1. 令 matchIndexPair 为 undefined。
    4. 执行 ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(i)), matchIndexPair)。
    5. 如果 i > 0,则
      1. 令 name 为 groupNames[i - 1]。
      2. 如果 name 不是 undefined,则
        1. 断言:groups 不是 undefined。
        2. 注:如果存在多个名为 name 的组,则此时 groups 可能已经具有 name 属性。不过,由于 groups 是一个其属性均为可写数据属性的普通对象,因此对 CreateDataPropertyOrThrow 的调用仍保证成功。
        3. 执行 ! CreateDataPropertyOrThrow(groups, name, matchIndexPair)。
  10. 返回 array。

22.2.8 RegExp 实例的属性

RegExp 实例是从 RegExp 原型对象继承属性的普通对象。RegExp 实例具有内部槽 [[OriginalSource]]、[[OriginalFlags]]、[[RegExpRecord]] 和 [[RegExpMatcher]]。[[RegExpMatcher]] 内部槽的值是 RegExp 对象的 Pattern 的 Abstract Closure 表示。

注

在 ECMAScript 2015 之前,RegExp 实例被规定具有自有数据属性 "source"、"global"、"ignoreCase" 和 "multiline"。这些属性现在被规定为 RegExp.prototype 的访问器属性。

RegExp 实例还具有以下属性:

22.2.8.1 lastIndex

"lastIndex" 属性的值指定开始下一次匹配的 String 索引。使用时会将其强制转换为整数 Number(参见 22.2.7.2)。此属性应具有特性 { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }。

22.2.9 RegExp String 迭代器对象

RegExp String Iterator 是表示对某个特定 String 实例对象进行某次特定迭代,同时与某个特定 RegExp 实例对象进行匹配的对象。RegExp String Iterator 对象没有具名构造函数。相反,RegExp String Iterator 对象通过调用 RegExp 实例对象的某些方法创建。

22.2.9.1 CreateRegExpStringIterator ( regexp, string, global, fullUnicode )

抽象操作 CreateRegExpStringIterator,接收参数 regexp (Object)、string (String)、global (Boolean) 和 fullUnicode (Boolean);返回值:Object。 调用时执行以下步骤:

  1. 令 iterator 为 OrdinaryObjectCreate(%RegExpStringIteratorPrototype%, « [[IteratingRegExp]], [[IteratedString]], [[Global]], [[Unicode]], [[Done]] »)。
  2. 将 iterator.[[IteratingRegExp]] 设置为 regexp。
  3. 将 iterator.[[IteratedString]] 设置为 string。
  4. 将 iterator.[[Global]] 设置为 global。
  5. 将 iterator.[[Unicode]] 设置为 fullUnicode。
  6. 将 iterator.[[Done]] 设置为 false。
  7. 返回 iterator。

22.2.9.2 %RegExpStringIteratorPrototype% 对象

%RegExpStringIteratorPrototype% 对象:

22.2.9.2.1 %RegExpStringIteratorPrototype%.next ( )

  1. 令 iteratorObj 为 this value。
  2. 如果 iteratorObj 不是 Object,则抛出 TypeError 异常。
  3. 如果 iteratorObj 不具有 RegExp String Iterator Object Instance 的所有内部槽(参见 22.2.9.3),则抛出 TypeError 异常。
  4. 如果 iteratorObj.[[Done]] 是 true,则
    1. 返回 CreateIteratorResultObject(undefined, true)。
  5. 令 regexp 为 iteratorObj.[[IteratingRegExp]]。
  6. 令 string 为 iteratorObj.[[IteratedString]]。
  7. 令 global 为 iteratorObj.[[Global]]。
  8. 令 fullUnicode 为 iteratorObj.[[Unicode]]。
  9. 令 match 为 ? RegExpExec(regexp, string)。
  10. 如果 match 是 null,则
    1. 将 iteratorObj.[[Done]] 设置为 true。
    2. 返回 CreateIteratorResultObject(undefined, true)。
  11. 如果 global 是 false,则
    1. 将 iteratorObj.[[Done]] 设置为 true。
    2. 返回 CreateIteratorResultObject(match, false)。
  12. 令 matchString 为 ? ToString(? Get(match, "0")).
  13. 如果 matchString 是空 String,则
    1. 令 thisIndex 为 ℝ(? ToLength(? Get(regexp, "lastIndex")))。
    2. 令 nextIndex 为 AdvanceStringIndex(string, thisIndex, fullUnicode)。
    3. 执行 ? Set(regexp, "lastIndex", 𝔽(nextIndex), true)。
  14. 返回 CreateIteratorResultObject(match, false)。

22.2.9.2.2 %RegExpStringIteratorPrototype% [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "RegExp String Iterator"。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

22.2.9.3 RegExp String Iterator 实例的属性

RegExp String Iterator 实例是从 %RegExpStringIteratorPrototype% 内在对象继承属性的普通对象。RegExp String Iterator 实例最初创建时具有 表 69 中列出的内部槽。

表 69: RegExp String Iterator 实例的内部槽
内部槽 类型 描述
[[IteratingRegExp]] an Object 用于迭代的正则表达式。IsRegExp([[IteratingRegExp]]) 的初始值是 true。
[[IteratedString]] a String 正在被迭代的 String 值。
[[Global]] a Boolean 表示 [[IteratingRegExp]] 是否为全局正则表达式。
[[Unicode]] a Boolean 表示 [[IteratingRegExp]] 是否处于 Unicode 模式。
[[Done]] a Boolean 表示迭代是否完成。

23 索引集合

23.1 Array 对象

Array 是一种异质对象,会对某一类属性名称进行特殊处理。有关这种特殊处理的定义,请参见 10.4.2。

23.1.1 Array 构造函数

Array 构造函数:

  • 是 %Array%。
  • 是全局对象的 "Array" 属性的初始值。
  • 作为构造函数调用时,创建并初始化新的 Array。
  • 作为函数而不是构造函数调用时,也会创建并初始化新的 Array。因此,函数调用 Array(…) 等价于使用相同参数的对象创建表达式 new Array(…)。
  • 是一个行为会根据其参数数量和类型而有所不同的函数。
  • 可以用作类定义的 extends 子句的值。希望继承异质 Array 行为的子类构造函数必须包含对 Array 构造函数的 super 调用,以初始化作为 Array 异质对象的子类实例。不过,大多数 Array.prototype 方法都是通用方法,并不依赖其 this value 是 Array 异质对象。

23.1.1.1 Array ( ...values )

调用时,此函数执行以下步骤:

  1. 如果 NewTarget 是 undefined,则令 newTarget 为活动函数对象;否则令 newTarget 为 NewTarget。
  2. 令 proto 为 ? GetPrototypeFromConstructor(newTarget, "%Array.prototype%")。
  3. 令 numberOfArgs 为 values 中的元素数量。
  4. 如果 numberOfArgs = 0,则返回 ! ArrayCreate(0, proto)。
  5. 如果 numberOfArgs = 1,则
    1. 令 length 为 values[0]。
    2. 令 array 为 ! ArrayCreate(0, proto)。
    3. 如果 length 不是 Number,则
      1. 执行 ! CreateDataPropertyOrThrow(array, "0", length)。
      2. 令 intLength 为 1𝔽。
    4. 否则,
      1. 令 intLength 为 ! ToUint32(length)。
      2. 如果 SameValueZero(intLength, length) 是 false,则抛出 RangeError 异常。
    5. 执行 ! Set(array, "length", intLength, true)。
    6. 返回 array。
  6. 断言:numberOfArgs ≥ 2。
  7. 令 array 为 ? ArrayCreate(numberOfArgs, proto)。
  8. 令 k 为 0。
  9. 当 k < numberOfArgs 时,重复执行,
    1. 令 propertyKey 为 ! ToString(𝔽(k))。
    2. 令 itemK 为 values[k]。
    3. 执行 ! CreateDataPropertyOrThrow(array, propertyKey, itemK)。
    4. 将 k 设置为 k + 1。
  10. 断言:array 的 "length" 属性的数学值是 numberOfArgs。
  11. 返回 array。

23.1.2 Array 构造函数的属性

Array 构造函数:

  • 具有 [[Prototype]] 内部槽,其值是 %Function.prototype%。
  • 具有 "length" 属性,其值是 1𝔽。
  • 具有以下属性:

23.1.2.1 Array.from ( items [ , mapper [ , thisArg ] ] )

调用时,此函数执行以下步骤:

  1. 令 ctor 为 this value。
  2. 如果 mapper 是 undefined,则
    1. 令 mapping 为 false。
  3. 否则,
    1. 如果 IsCallable(mapper) 是 false,则抛出 TypeError 异常。
    2. 令 mapping 为 true。
  4. 令 usingIterator 为 ? GetMethod(items, %Symbol.iterator%)。
  5. 如果 usingIterator 不是 undefined,则
    1. 如果 IsConstructor(ctor) 是 true,则
      1. 令 array 为 ? Construct(ctor)。
    2. 否则,
      1. 令 array 为 ! ArrayCreate(0)。
    3. 令 iteratorRecord 为 ? GetIteratorFromMethod(items, usingIterator)。
    4. 令 k 为 0。
    5. 重复执行,
      1. 如果 k ≥ 253 - 1,则
        1. 令 error 为 ThrowCompletion(a newly created TypeError object)。
        2. 返回 ? IteratorClose(iteratorRecord, error)。
      2. 令 propertyKey 为 ! ToString(𝔽(k))。
      3. 令 next 为 ? IteratorStepValue(iteratorRecord)。
      4. 如果 next 是 done,则
        1. 执行 ? Set(array, "length", 𝔽(k), true)。
        2. 返回 array。
      5. 如果 mapping 是 true,则
        1. 令 mappedValue 为 Completion(Call(mapper, thisArg, « next, 𝔽(k) »))。
        2. IfAbruptCloseIterator(mappedValue, iteratorRecord)。
      6. 否则,
        1. 令 mappedValue 为 next。
      7. 令 defineStatus 为 Completion(CreateDataPropertyOrThrow(array, propertyKey, mappedValue))。
      8. IfAbruptCloseIterator(defineStatus, iteratorRecord)。
      9. 将 k 设置为 k + 1。
  6. 注:items 不可迭代,因此假定它是类数组对象。
  7. 令 arrayLike 为 ! ToObject(items)。
  8. 令 length 为 ? LengthOfArrayLike(arrayLike)。
  9. 如果 IsConstructor(ctor) 是 true,则
    1. 令 array 为 ? Construct(ctor, « 𝔽(length) »)。
  10. 否则,
    1. 令 array 为 ? ArrayCreate(length)。
  11. 令 k 为 0。
  12. 当 k < length 时,重复执行,
    1. 令 propertyKey 为 ! ToString(𝔽(k))。
    2. 令 kValue 为 ? Get(arrayLike, propertyKey)。
    3. 如果 mapping 是 true,则
      1. 令 mappedValue 为 ? Call(mapper, thisArg, « kValue, 𝔽(k) »)。
    4. 否则,
      1. 令 mappedValue 为 kValue。
    5. 执行 ? CreateDataPropertyOrThrow(array, propertyKey, mappedValue)。
    6. 将 k 设置为 k + 1。
  13. 执行 ? Set(array, "length", 𝔽(length), true)。
  14. 返回 array。
注

此方法有意设计为通用工厂方法;它不要求其 this value 是 Array 构造函数。因此,它可以被转移给或由任何其他可使用单个数值参数调用的构造函数继承。

23.1.2.2 Array.fromAsync ( items [ , mapper [ , thisArg ] ] )

调用时,此异步函数执行以下步骤:

  1. 令 ctor 为 this value。
  2. 令 mapping 为 false。
  3. 如果 mapper 不是 undefined,则
    1. 如果 IsCallable(mapper) 是 false,则抛出 TypeError 异常。
    2. 将 mapping 设置为 true。
  4. 令 iteratorRecord 为 undefined。
  5. 令 usingAsyncIterator 为 ? GetMethod(items, %Symbol.asyncIterator%)。
  6. 如果 usingAsyncIterator 是 undefined,则
    1. 令 usingSyncIterator 为 ? GetMethod(items, %Symbol.iterator%)。
    2. 如果 usingSyncIterator 不是 undefined,则
      1. 将 iteratorRecord 设置为 CreateAsyncFromSyncIterator(? GetIteratorFromMethod(items, usingSyncIterator))。
  7. 否则,
    1. 将 iteratorRecord 设置为 ? GetIteratorFromMethod(items, usingAsyncIterator)。
  8. 如果 iteratorRecord 不是 undefined,则
    1. 如果 IsConstructor(ctor) 是 true,则
      1. 令 array 为 ? Construct(ctor)。
    2. 否则,
      1. 令 array 为 ! ArrayCreate(0)。
    3. 令 k 为 0。
    4. 重复执行,
      1. 如果 k ≥ 253 - 1,则
        1. 令 error 为 ThrowCompletion(a newly created TypeError object)。
        2. 返回 ? AsyncIteratorClose(iteratorRecord, error)。
      2. 令 propertyKey 为 ! ToString(𝔽(k))。
      3. 令 nextResult 为 ? Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]])。
      4. 将 nextResult 设置为 ? Await(nextResult)。
      5. 如果 nextResult 不是 Object,则抛出 TypeError 异常。
      6. 令 done 为 ? IteratorComplete(nextResult)。
      7. 如果 done 是 true,则
        1. 执行 ? Set(array, "length", 𝔽(k), true)。
        2. 返回 array。
      8. 令 nextValue 为 ? IteratorValue(nextResult)。
      9. 如果 mapping 是 true,则
        1. 令 mappedValue 为 Completion(Call(mapper, thisArg, « nextValue, 𝔽(k) »))。
        2. IfAbruptCloseAsyncIterator(mappedValue, iteratorRecord)。
        3. 将 mappedValue 设置为 Completion(Await(mappedValue))。
        4. IfAbruptCloseAsyncIterator(mappedValue, iteratorRecord)。
      10. 否则,
        1. 令 mappedValue 为 nextValue。
      11. 令 defineStatus 为 Completion(CreateDataPropertyOrThrow(array, propertyKey, mappedValue))。
      12. IfAbruptCloseAsyncIterator(defineStatus, iteratorRecord)。
      13. 将 k 设置为 k + 1。
  9. 否则,
    1. 注:items 既不是异步可迭代对象,也不是可迭代对象,因此假定它是类数组对象。
    2. 令 arrayLike 为 ! ToObject(items)。
    3. 令 length 为 ? LengthOfArrayLike(arrayLike)。
    4. 如果 IsConstructor(ctor) 是 true,则
      1. 令 array 为 ? Construct(ctor, « 𝔽(length) »)。
    5. 否则,
      1. 令 array 为 ? ArrayCreate(length)。
    6. 令 k 为 0。
    7. 当 k < length 时,重复执行,
      1. 令 propertyKey 为 ! ToString(𝔽(k))。
      2. 令 kValue 为 ? Get(arrayLike, propertyKey)。
      3. 将 kValue 设置为 ? Await(kValue)。
      4. 如果 mapping 是 true,则
        1. 令 mappedValue 为 ? Call(mapper, thisArg, « kValue, 𝔽(k) »)。
        2. 将 mappedValue 设置为 ? Await(mappedValue)。
      5. 否则,
        1. 令 mappedValue 为 kValue。
      6. 执行 ? CreateDataPropertyOrThrow(array, propertyKey, mappedValue)。
      7. 将 k 设置为 k + 1。
    8. 执行 ? Set(array, "length", 𝔽(length), true)。
    9. 返回 array。
注

此方法有意设计为通用工厂方法;它不要求其 this value 是 Array 构造函数。因此,它可以被转移给或由任何其他可使用单个数值参数调用的构造函数继承。

23.1.2.3 Array.isArray ( arg )

调用时,此函数执行以下步骤:

  1. 返回 ? IsArray(arg)。

23.1.2.4 Array.of ( ...items )

调用时,此方法执行以下步骤:

  1. 令 length 为 items 中的元素数量。
  2. 令 lengthNumber 为 𝔽(length)。
  3. 令 ctor 为 this value。
  4. 如果 IsConstructor(ctor) 是 true,则
    1. 令 array 为 ? Construct(ctor, « lengthNumber »)。
  5. 否则,
    1. 令 array 为 ? ArrayCreate(length)。
  6. 令 k 为 0。
  7. 当 k < length 时,重复执行,
    1. 令 kValue 为 items[k]。
    2. 令 propertyKey 为 ! ToString(𝔽(k))。
    3. 执行 ? CreateDataPropertyOrThrow(array, propertyKey, kValue)。
    4. 将 k 设置为 k + 1。
  8. 执行 ? Set(array, "length", lengthNumber, true)。
  9. 返回 array。
注

此方法有意设计为通用工厂方法;它不要求其 this value 是 Array 构造函数。因此,它可以被转移给或由其他可使用单个数值参数调用的构造函数继承。

23.1.2.5 Array.prototype

Array.prototype 的值是 Array 原型对象。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

23.1.2.6 get Array [ %Symbol.species% ]

Array[%Symbol.species%] 是访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数在调用时执行以下步骤:

  1. 返回 this value。

此函数的 "name" 属性值是 "get [Symbol.species]"。

注

Array 原型方法通常使用其 this value 的构造函数创建派生对象。不过,子类构造函数可以通过重新定义其 %Symbol.species% 属性来覆盖该默认行为。

23.1.3 Array 原型对象的属性

Array 原型对象:

  • 是 %Array.prototype%。
  • 是 Array 异质对象,并具有为此类对象规定的内部方法。
  • 具有 "length" 属性,其初始值是 +0𝔽,并且其特性为 { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }。
  • 具有 [[Prototype]] 内部槽,其值是 %Object.prototype%。
注

将 Array 原型对象规定为 Array 异质对象,是为了确保与 ECMAScript 2015 规范之前创建的 ECMAScript 代码兼容。

23.1.3.1 Array.prototype.at ( index )

  1. 令 obj 为 ? ToObject(this value)。
  2. 令 length 为 ? LengthOfArrayLike(obj)。
  3. 令 k 为 ? ToAbsoluteIndex(index, length)。
  4. 如果 k < 0 或 k ≥ length,则返回 undefined。
  5. 返回 ? Get(obj, ! ToString(𝔽(k)))。

23.1.3.2 Array.prototype.concat ( ...items )

此方法返回一个数组,其中包含该对象的数组元素,后跟每个参数的数组元素。

调用时,它执行以下步骤:

  1. 令 obj 为 ? ToObject(this value)。
  2. 令 array 为 ? ArraySpeciesCreate(obj, 0)。
  3. 令 nextIndex 为 0。
  4. 将 obj 前置到 items。
  5. 对 items 的每个元素 item,执行
    1. 令 spreadable 为 ? IsConcatSpreadable(item)。
    2. 如果 spreadable 是 true,则
      1. 令 length 为 ? LengthOfArrayLike(item)。
      2. 如果 nextIndex + length > 253 - 1,则抛出 TypeError 异常。
      3. 令 sourceIndex 为 0。
      4. 当 sourceIndex < length 时,重复执行,
        1. 令 propertyKey 为 ! ToString(𝔽(sourceIndex))。
        2. 令 exists 为 ? HasProperty(item, propertyKey)。
        3. 如果 exists 是 true,则
          1. 令 subElement 为 ? Get(item, propertyKey)。
          2. 执行 ? CreateDataPropertyOrThrow(array, ! ToString(𝔽(nextIndex)), subElement)。
        4. 将 nextIndex 设置为 nextIndex + 1。
        5. 将 sourceIndex 设置为 sourceIndex + 1。
    3. 否则,
      1. 注:item 作为单个项目添加,而不是展开。
      2. 如果 nextIndex ≥ 253 - 1,则抛出 TypeError 异常。
      3. 执行 ? CreateDataPropertyOrThrow(array, ! ToString(𝔽(nextIndex)), item)。
      4. 将 nextIndex 设置为 nextIndex + 1。
  6. 执行 ? Set(array, "length", 𝔽(nextIndex), true)。
  7. 返回 array。

此方法的 "length" 属性是 1𝔽。

注 1

在步骤 6 中显式设置 "length" 属性,是为了确保当 items 中最后一个非空元素尾部存在空位,或者 array 不是内置 Array 时,长度仍然正确。

注 2

此方法有意设计为通用方法;它不要求其 this value 是 Array。因此,它可以被转移到其他种类的对象上用作方法。

23.1.3.2.1 IsConcatSpreadable ( obj )

抽象操作 IsConcatSpreadable,接收参数 obj (ECMAScript 语言值);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 obj 不是 Object,则返回 false。
  2. 令 spreadable 为 ? Get(obj, %Symbol.isConcatSpreadable%)。
  3. 如果 spreadable 不是 undefined,则返回 ToBoolean(spreadable)。
  4. 返回 ? IsArray(obj)。

23.1.3.3 Array.prototype.constructor

Array.prototype.constructor 的初始值是 %Array%。

23.1.3.4 Array.prototype.copyWithin ( target, start [ , end ] )

注 1

end 参数是可选的。如果未提供,则使用 this value 的长度。

注 2

如果 target 为负,则将其视为 length + target,其中 length 是数组的长度。如果 start 为负,则将其视为 length + start。如果 end 为负,则将其视为 length + end。

调用时,此方法执行以下步骤:

  1. 令 obj 为 ? ToObject(this value)。
  2. 令 length 为 ? LengthOfArrayLike(obj)。
  3. 令 to 为 ? ToClampedIndex(target, length)。
  4. 令 from 为 ? ToClampedIndex(start, length)。
  5. 如果 end 是 undefined,则令 final 为 length;否则令 final 为 ? ToClampedIndex(end, length)。
  6. 令 count 为 min(final - from, length - to)。
  7. 如果 from < to 且 to < from + count,则
    1. 令 direction 为 -1。
    2. 将 from 设置为 from + count - 1。
    3. 将 to 设置为 to + count - 1。
  8. 否则,
    1. 令 direction 为 1。
  9. 当 count > 0 时,重复执行,
    1. 令 fromKey 为 ! ToString(𝔽(from))。
    2. 令 toKey 为 ! ToString(𝔽(to))。
    3. 令 fromPresent 为 ? HasProperty(obj, fromKey)。
    4. 如果 fromPresent 是 true,则
      1. 令 fromValue 为 ? Get(obj, fromKey)。
      2. 执行 ? Set(obj, toKey, fromValue, true)。
    5. 否则,
      1. 断言:fromPresent 是 false。
      2. 执行 ? DeletePropertyOrThrow(obj, toKey)。
    6. 将 from 设置为 from + direction。
    7. 将 to 设置为 to + direction。
    8. 将 count 设置为 count - 1。
  10. 返回 obj。
注 3

此方法有意设计为通用方法;它不要求其 this value 是 Array。因此,它可以被转移到其他种类的对象上用作方法。

23.1.3.5 Array.prototype.entries ( )

调用时,此方法执行以下步骤:

  1. 令 obj 为 ? ToObject(this value)。
  2. 返回 CreateArrayIterator(obj, key+value)。

23.1.3.6 Array.prototype.every ( callback [ , thisArg ] )

注 1

callback 应当是一个接受三个参数并返回可强制转换为 Boolean 值的值的函数。every 按升序对数组中实际存在的每个元素调用一次 callback,直到找到一个使 callback 返回 false 的元素。如果找到这样的元素,every 会立即返回 false。否则,every 返回 true。callback 只会针对数组中实际存在的元素调用;不会针对数组中缺失的元素调用。

如果提供了 thisArg 参数,则每次调用 callback 时都会将其用作 this value。如果未提供,则改用 undefined。

调用 callback 时会传入三个参数:元素的值、元素的索引以及正在遍历的对象。

every 不会直接修改调用它的对象,但对 callback 的调用可能会修改该对象。

every 处理的元素范围在第一次调用 callback 之前确定。调用 every 开始后追加到数组中的元素不会被 callback 访问。如果数组中已有元素发生变化,则传递给 callback 的值是在 every 访问该元素时的值;在调用 every 开始后且被访问之前删除的元素不会被访问。every 的作用类似于数学中的“对所有”量词。特别地,对于空数组,它返回 true。

调用时,此方法执行以下步骤:

  1. 令 obj 为 ? ToObject(this value)。
  2. 令 length 为 ? LengthOfArrayLike(obj)。
  3. 如果 IsCallable(callback) 是 false,则抛出 TypeError 异常。
  4. 令 k 为 0。
  5. 当 k < length 时,重复执行,
    1. 令 propertyKey 为 ! ToString(𝔽(k))。
    2. 令 kPresent 为 ? HasProperty(obj, propertyKey)。
    3. 如果 kPresent 是 true,则
      1. 令 kValue 为 ? Get(obj, propertyKey)。
      2. 令 testResult 为 ToBoolean(? Call(callback, thisArg, « kValue, 𝔽(k), obj »))。
      3. 如果 testResult 是 false,则返回 false。
    4. 将 k 设置为 k + 1。
  6. 返回 true。
注 2

此方法有意设计为通用方法;它不要求其 this value 是 Array。因此,它可以被转移到其他种类的对象上用作方法。

23.1.3.7 Array.prototype.fill ( value [ , start [ , end ] ] )

注 1

start 参数是可选的。如果未提供,则使用 +0𝔽。

end 参数是可选的。如果未提供,则使用 this value 的长度。

注 2

如果 start 为负,则将其视为 length + start,其中 length 是数组的长度。如果 end 为负,则将其视为 length + end。

调用时,此方法执行以下步骤:

  1. 令 obj 为 ? ToObject(this value)。
  2. 令 length 为 ? LengthOfArrayLike(obj)。
  3. 令 k 为 ? ToClampedIndex(start, length)。
  4. 如果 end 是 undefined,则令 final 为 length;否则令 final 为 ? ToClampedIndex(end, length)。
  5. 当 k < final 时,重复执行,
    1. 令 propertyKey 为 ! ToString(𝔽(k))。
    2. 执行 ? Set(obj, propertyKey, value, true)。
    3. 将 k 设置为 k + 1。
  6. 返回 obj。
注 3

此方法有意设计为通用方法;它不要求其 this value 是 Array。因此,它可以被转移到其他种类的对象上用作方法。

23.1.3.8 Array.prototype.filter ( callback [ , thisArg ] )

注 1

callback 应当是一个接受三个参数并返回可强制转换为 Boolean 值的值的函数。filter 按升序对数组中的每个元素调用一次 callback,并构造一个新数组,其中包含所有使 callback 返回 true 的值。callback 只会针对数组中实际存在的元素调用;不会针对数组中缺失的元素调用。

如果提供了 thisArg 参数,则每次调用 callback 时都会将其用作 this value。如果未提供,则改用 undefined。

调用 callback 时会传入三个参数:元素的值、元素的索引以及正在遍历的对象。

filter 不会直接修改调用它的对象,但对 callback 的调用可能会修改该对象。

filter 处理的元素范围在第一次调用 callback 之前确定。调用 filter 开始后追加到数组中的元素不会被 callback 访问。如果数组中已有元素发生变化,则传递给 callback 的值是在 filter 访问该元素时的值;在调用 filter 开始后且被访问之前删除的元素不会被访问。

调用时,此方法执行以下步骤:

  1. 令 obj 为 ? ToObject(this value)。
  2. 令 length 为 ? LengthOfArrayLike(obj)。
  3. 如果 IsCallable(callback) 是 false,则抛出 TypeError 异常。
  4. 令 array 为 ? ArraySpeciesCreate(obj, 0)。
  5. 令 k 为 0。
  6. 令 to 为 0。
  7. 当 k < length 时,重复执行,
    1. 令 propertyKey 为 ! ToString(𝔽(k))。
    2. 令 kPresent 为 ? HasProperty(obj, propertyKey)。
    3. 如果 kPresent 是 true,则
      1. 令 kValue 为 ? Get(obj, propertyKey)。
      2. 令 selected 为 ToBoolean(? Call(callback, thisArg, « kValue, 𝔽(k), obj »))。
      3. 如果 selected 是 true,则
        1. 执行 ? CreateDataPropertyOrThrow(array, ! ToString(𝔽(to)), kValue)。
        2. 将 to 设置为 to + 1。
    4. 将 k 设置为 k + 1。
  8. 返回 array。
注 2

此方法有意设计为通用方法;它不要求其 this value 是 Array。因此,它可以被转移到其他种类的对象上用作方法。

23.1.3.9 Array.prototype.find ( predicate [ , thisArg ] )

注 1

此方法按索引升序对数组的每个元素调用一次 predicate,直到找到一个使 predicate 返回可强制转换为 true 的值的元素。如果找到这样的元素,find 会立即返回该元素值。否则,find 返回 undefined。

有关更多信息,请参见 FindViaPredicate。

调用时,此方法执行以下步骤:

  1. 令 obj 为 ? ToObject(this value)。
  2. 令 length 为 ? LengthOfArrayLike(obj)。
  3. 令 findRecord 为 ? FindViaPredicate(obj, length, ascending, predicate, thisArg)。
  4. 返回 findRecord.[[Value]]。
注 2

此方法有意设计为通用方法;它不要求其 this value 是 Array。因此,它可以被转移到其他种类的对象上用作方法。

23.1.3.10 Array.prototype.findIndex ( predicate [ , thisArg ] )

注 1

此方法按索引升序对数组的每个元素调用一次 predicate,直到找到一个使 predicate 返回可强制转换为 true 的值的元素。如果找到这样的元素,findIndex 会立即返回该元素值的索引。否则,findIndex 返回 -1。

有关更多信息,请参见 FindViaPredicate。

调用时,此方法执行以下步骤:

  1. 令 obj 为 ? ToObject(this value)。
  2. 令 length 为 ? LengthOfArrayLike(obj)。
  3. 令 findRecord 为 ? FindViaPredicate(obj, length, ascending, predicate, thisArg)。
  4. 返回 findRecord.[[Index]]。
注 2

此方法有意设计为通用方法;它不要求其 this value 是 Array。因此,它可以被转移到其他种类的对象上用作方法。

23.1.3.11 Array.prototype.findLast ( predicate [ , thisArg ] )

注 1

此方法按索引降序对数组的每个元素调用一次 predicate,直到找到一个使 predicate 返回可强制转换为 true 的值的元素。如果找到这样的元素,findLast 会立即返回该元素值。否则,findLast 返回 undefined。

有关更多信息,请参见 FindViaPredicate。

调用时,此方法执行以下步骤:

  1. 令 obj 为 ? ToObject(this value)。
  2. 令 length 为 ? LengthOfArrayLike(obj)。
  3. 令 findRecord 为 ? FindViaPredicate(obj, length, descending, predicate, thisArg)。
  4. 返回 findRecord.[[Value]]。
注 2

此方法有意设计为通用方法;它不要求其 this value 是 Array 对象。因此,它可以被转移到其他种类的对象上用作方法。

23.1.3.12 Array.prototype.findLastIndex ( predicate [ , thisArg ] )

注 1

此方法按索引降序对数组的每个元素调用一次 predicate,直到找到一个使 predicate 返回可强制转换为 true 的值的元素。如果找到这样的元素,findLastIndex 会立即返回该元素值的索引。否则,findLastIndex 返回 -1。

有关更多信息,请参见 FindViaPredicate。

调用时,此方法执行以下步骤:

  1. 令 obj 为 ? ToObject(this value)。
  2. 令 length 为 ? LengthOfArrayLike(obj)。
  3. 令 findRecord 为 ? FindViaPredicate(obj, length, descending, predicate, thisArg)。
  4. 返回 findRecord.[[Index]]。
注 2

此方法有意设计为通用方法;它不要求其 this value 是 Array 对象。因此,它可以被转移到其他种类的对象上用作方法。

23.1.3.12.1 FindViaPredicate ( obj, length, direction, predicate, thisArg )

抽象操作 FindViaPredicate,接收参数 obj (Object)、length (非负整数)、direction ((ascending 或 descending))、predicate (ECMAScript 语言值) 和 thisArg (ECMAScript 语言值);返回值:(正常完成 (值:记录 (字段:[[Index]] (整数 Number), [[Value]] (ECMAScript 语言值))) 或 抛出完成)。

obj 应当是类数组对象或 TypedArray。此操作按索引升序或降序(由 direction 指示)对 obj 的每个元素调用一次 predicate,直到找到一个使 predicate 返回可强制转换为 true 的值的元素。此时,此操作返回一个给出所找到元素的索引和值的 Record。如果未找到这样的元素,则此操作返回一个 Record,其中索引指定为 -1𝔽,值指定为 undefined。

predicate 应当是一个函数。针对数组的某个元素调用时,会向其传递三个参数:元素的值、元素的索引以及正在遍历的对象。其返回值将被强制转换为 Boolean 值。

每次调用 predicate 时,thisArg 都将用作 this value。

此操作不会直接修改调用它的对象,但对 predicate 的调用可能会修改该对象。

所处理元素的范围在第一次调用 predicate 之前、遍历开始前确定。此后追加到数组中的元素不会被 predicate 访问。如果数组中已有元素发生变化,则传递给 predicate 的值是在此操作访问该元素时的值。在遍历开始后且被访问之前删除的元素仍然会被访问,并且要么从原型中查找,要么为 undefined。

调用时执行以下步骤:

  1. 如果 IsCallable(predicate) 是 false,则抛出 TypeError 异常。
  2. 如果 direction 是 ascending,则
    1. 令 indices 为从 0(包含)到 length(不包含)区间内按升序排列的整数 List。
  3. 否则,
    1. 令 indices 为从 0(包含)到 length(不包含)区间内按降序排列的整数 List。
  4. 对 indices 的每个整数 k,执行
    1. 令 propertyKey 为 ! ToString(𝔽(k))。
    2. 注:如果 obj 是 TypedArray,则以下 Get 调用将返回正常完成。
    3. 令 kValue 为 ? Get(obj, propertyKey)。
    4. 令 testResult 为 ? Call(predicate, thisArg, « kValue, 𝔽(k), obj »)。
    5. 如果 ToBoolean(testResult) 是 true,则返回 Record { [[Index]]: 𝔽(k), [[Value]]: kValue }。
  5. 返回 Record { [[Index]]: -1𝔽, [[Value]]: undefined }。

23.1.3.13 Array.prototype.flat ( [ depth ] )

调用时,此方法执行以下步骤:

  1. 令 obj 为 ? ToObject(this value)。
  2. 令 sourceLength 为 ? LengthOfArrayLike(obj)。
  3. 令 depthNumber 为 1。
  4. 如果 depth 不是 undefined,则
    1. 将 depthNumber 设置为 ? ToIntegerOrInfinity(depth)。
    2. 如果 depthNumber < 0,则将 depthNumber 设置为 0。
  5. 令 array 为 ? ArraySpeciesCreate(obj, 0)。
  6. 执行 ? FlattenIntoArray(array, obj, sourceLength, 0, depthNumber)。
  7. 返回 array。

23.1.3.13.1 FlattenIntoArray ( target, source, sourceLength, start, depth [ , mapperFunc [ , thisArg ] ] )

抽象操作 FlattenIntoArray,接收参数 target (Object)、source (Object)、sourceLength (非负整数)、start (非负整数) 和 depth ((非负整数 或 +∞))和可选参数 mapperFunc (函数对象) 和 thisArg (ECMAScript 语言值);返回值:(正常完成 (值:非负整数) 或 抛出完成)。 调用时执行以下步骤:

  1. 断言:如果存在 mapperFunc,则 IsCallable(mapperFunc) 是 true,存在 thisArg,并且 depth 是 1。
  2. 令 targetIndex 为 start。
  3. 令 sourceIndex 为 0。
  4. 当 sourceIndex < sourceLength 时,重复执行,
    1. 令 propertyKey 为 ! ToString(𝔽(sourceIndex))。
    2. 令 exists 为 ? HasProperty(source, propertyKey)。
    3. 如果 exists 是 true,则
      1. 令 element 为 ? Get(source, propertyKey)。
      2. 如果存在 mapperFunc,则
        1. 将 element 设置为 ? Call(mapperFunc, thisArg, « element, 𝔽(sourceIndex), source »)。
      3. 令 shouldFlatten 为 false。
      4. 如果 depth > 0,则
        1. 将 shouldFlatten 设置为 ? IsArray(element)。
      5. 如果 shouldFlatten 是 true,则
        1. 如果 depth = +∞,则令 newDepth 为 +∞。
        2. 否则,令 newDepth 为 depth - 1。
        3. 令 elementLength 为 ? LengthOfArrayLike(element)。
        4. 将 targetIndex 设置为 ? FlattenIntoArray(target, element, elementLength, targetIndex, newDepth)。
      6. 否则,
        1. 如果 targetIndex ≥ 253 - 1,则抛出 TypeError 异常。
        2. 执行 ? CreateDataPropertyOrThrow(target, ! ToString(𝔽(targetIndex)), element)。
        3. 将 targetIndex 设置为 targetIndex + 1。
    4. 将 sourceIndex 设置为 sourceIndex + 1。
  5. 返回 targetIndex。

23.1.3.14 Array.prototype.flatMap ( mapperFunc [ , thisArg ] )

调用时,此方法执行以下步骤:

  1. 令 obj 为 ? ToObject(this value)。
  2. 令 sourceLength 为 ? LengthOfArrayLike(obj)。
  3. 如果 IsCallable(mapperFunc) 是 false,则抛出 TypeError 异常。
  4. 令 array 为 ? ArraySpeciesCreate(obj, 0)。
  5. 执行 ? FlattenIntoArray(array, obj, sourceLength, 0, 1, mapperFunc, thisArg)。
  6. 返回 array。

23.1.3.15 Array.prototype.forEach ( callback [ , thisArg ] )

注 1

callback 应当是一个接受三个参数的函数。forEach 按升序对数组中实际存在的每个元素调用一次 callback。callback 只会针对数组中实际存在的元素调用;不会针对数组中缺失的元素调用。

如果提供了 thisArg 参数,则每次调用 callback 时都会将其用作 this value。如果未提供,则改用 undefined。

调用 callback 时会传入三个参数:元素的值、元素的索引以及正在遍历的对象。

forEach 不会直接修改调用它的对象,但对 callback 的调用可能会修改该对象。

forEach 处理的元素范围在第一次调用 callback 之前确定。调用 forEach 开始后追加到数组中的元素不会被 callback 访问。如果数组中已有元素发生变化,则传递给 callback 的值是在 forEach 访问该元素时的值;在调用 forEach 开始后且被访问之前删除的元素不会被访问。

调用时,此方法执行以下步骤:

  1. 令 obj 为 ? ToObject(this value)。
  2. 令 length 为 ? LengthOfArrayLike(obj)。
  3. 如果 IsCallable(callback) 是 false,则抛出 TypeError 异常。
  4. 令 k 为 0。
  5. 当 k < length 时,重复执行,
    1. 令 propertyKey 为 ! ToString(𝔽(k))。
    2. 令 kPresent 为 ? HasProperty(obj, propertyKey)。
    3. 如果 kPresent 是 true,则
      1. 令 kValue 为 ? Get(obj, propertyKey)。
      2. 执行 ? Call(callback, thisArg, « kValue, 𝔽(k), obj »)。
    4. 将 k 设置为 k + 1。
  6. 返回 undefined。
注 2

此方法有意设计为通用方法;它不要求其 this value 是 Array。因此,它可以被转移到其他种类的对象上用作方法。

23.1.3.16 Array.prototype.includes ( searchElement [ , fromIndex ] )

注 1

此方法使用 SameValueZero 算法按升序将 searchElement 与数组元素进行比较,如果在任意位置找到,则返回 true;否则返回 false。

可选的第二个参数 fromIndex 默认为 +0𝔽(即搜索整个数组)。如果它大于或等于数组长度,则返回 false,即不会搜索数组。如果它小于 -0𝔽,则将其用作从数组末尾开始的偏移量来计算 fromIndex。如果计算出的索引小于或等于 +0𝔽,则会搜索整个数组。

调用时,此方法执行以下步骤:

  1. 令 obj 为 ? ToObject(this value)。
  2. 令 length 为 ? LengthOfArrayLike(obj)。
  3. 如果 length = 0,则返回 false。
  4. 令 k 为 ? ToClampedIndex(fromIndex, length)。
  5. 当 k < length 时,重复执行,
    1. 令 elementK 为 ? Get(obj, ! ToString(𝔽(k)))。
    2. 如果 SameValueZero(searchElement, elementK) 是 true,则返回 true。
    3. 将 k 设置为 k + 1。
  6. 返回 false。
注 2

此方法有意设计为通用方法;它不要求其 this value 是 Array。因此,它可以被转移到其他种类的对象上用作方法。

注 3

此方法有意在两个方面与类似的 indexOf 方法不同。第一,它使用 SameValueZero 算法而不是 IsStrictlyEqual,因此能够检测 NaN 数组元素。第二,它不会跳过缺失的数组元素,而是将其视为 undefined。

23.1.3.17 Array.prototype.indexOf ( searchElement [ , fromIndex ] )

此方法使用 IsStrictlyEqual 算法按升序将 searchElement 与数组元素进行比较,如果在一个或多个索引处找到,则返回其中最小的索引;否则返回 -1𝔽。

注 1

可选的第二个参数 fromIndex 默认为 +0𝔽(即搜索整个数组)。如果它大于或等于数组长度,则返回 -1𝔽,即不会搜索数组。如果它小于 -0𝔽,则使用它计算从数组末尾开始的偏移量。如果计算出的索引小于或等于 +0𝔽,则会搜索整个数组。

调用时,此方法执行以下步骤:

  1. 令 obj 为 ? ToObject(this value)。
  2. 令 length 为 ? LengthOfArrayLike(obj)。
  3. 如果 length = 0,则返回 -1𝔽。
  4. 令 k 为 ? ToClampedIndex(fromIndex, length)。
  5. 当 k < length 时,重复执行,
    1. 令 propertyKey 为 ! ToString(𝔽(k))。
    2. 令 kPresent 为 ? HasProperty(obj, propertyKey)。
    3. 如果 kPresent 是 true,则
      1. 令 elementK 为 ? Get(obj, propertyKey)。
      2. 如果 IsStrictlyEqual(searchElement, elementK) 是 true,则返回 𝔽(k)。
    4. 将 k 设置为 k + 1。
  6. 返回 -1𝔽。
注 2

此方法有意设计为通用方法;它不要求其 this value 是 Array。因此,它可以被转移到其他种类的对象上用作方法。

23.1.3.18 Array.prototype.join ( separator )

此方法将数组元素转换为 Strings,然后连接这些 Strings,并在它们之间插入 separator。如果未提供分隔符,则使用单个逗号作为分隔符。

调用时,它执行以下步骤:

  1. 令 obj 为 ? ToObject(this value)。
  2. 令 length 为 ? LengthOfArrayLike(obj)。
  3. 如果 separator 是 undefined,则令 separatorString 为 ","。
  4. 否则,令 separatorString 为 ? ToString(separator)。
  5. 令 result 为空 String。
  6. 令 k 为 0。
  7. 当 k < length 时,重复执行,
    1. 如果 k > 0,则将 result 设置为 result 和 separatorString 的字符串连接。
    2. 令 element 为 ? Get(obj, ! ToString(𝔽(k)))。
    3. 如果 element 既不是 undefined 也不是 null,则
      1. 令 elementString 为 ? ToString(element)。
      2. 将 result 设置为 result 和 elementString 的字符串连接。
    4. 将 k 设置为 k + 1。
  8. 返回 result。
注

此方法有意设计为通用方法;它不要求其 this value 是 Array。因此,它可以被转移到其他种类的对象上用作方法。

23.1.3.19 Array.prototype.keys ( )

调用时,此方法执行以下步骤:

  1. 令 obj 为 ? ToObject(this value)。
  2. 返回 CreateArrayIterator(obj, key)。

23.1.3.20 Array.prototype.lastIndexOf ( searchElement [ , fromIndex ] )

注 1

此方法使用 IsStrictlyEqual 算法按降序将 searchElement 与数组元素进行比较,如果在一个或多个索引处找到,则返回其中最大的索引;否则返回 -1𝔽。

可选的第二个参数 fromIndex 默认为数组长度减一(即搜索整个数组)。如果它大于或等于数组长度,则会搜索整个数组。如果它小于 -0𝔽,则使用它计算从数组末尾开始的偏移量。如果计算出的索引小于 -0𝔽,则返回 -1𝔽。

调用时,此方法执行以下步骤:

  1. 令 obj 为 ? ToObject(this value)。
  2. 令 length 为 ? LengthOfArrayLike(obj)。
  3. 如果 length = 0,则返回 -1𝔽。
  4. 如果不存在 fromIndex,则令 k 为 length - 1;否则令 k 为 min(? ToAbsoluteIndex(fromIndex, length), length - 1)。
  5. 当 k ≥ 0 时,重复执行,
    1. 令 propertyKey 为 ! ToString(𝔽(k))。
    2. 令 kPresent 为 ? HasProperty(obj, propertyKey)。
    3. 如果 kPresent 是 true,则
      1. 令 elementK 为 ? Get(obj, propertyKey)。
      2. 如果 IsStrictlyEqual(searchElement, elementK) 是 true,则返回 𝔽(k)。
    4. 将 k 设置为 k - 1。
  6. 返回 -1𝔽。
注 2

此方法有意设计为通用方法;它不要求其 this value 是 Array。因此,它可以被转移到其他种类的对象上用作方法。

23.1.3.21 Array.prototype.map ( callback [ , thisArg ] )

注 1

callback 应当是一个接受三个参数的函数。map 按升序对数组中的每个元素调用一次 callback,并根据结果构造一个新的 Array。callback 只会针对数组中实际存在的元素调用;不会针对数组中缺失的元素调用。

如果提供了 thisArg 参数,则每次调用 callback 时都会将其用作 this value。如果未提供,则改用 undefined。

调用 callback 时会传入三个参数:元素的值、元素的索引以及正在遍历的对象。

map 不会直接修改调用它的对象,但对 callback 的调用可能会修改该对象。

map 处理的元素范围在第一次调用 callback 之前确定。调用 map 开始后追加到数组中的元素不会被 callback 访问。如果数组中已有元素发生变化,则传递给 callback 的值是在 map 访问该元素时的值;在调用 map 开始后且被访问之前删除的元素不会被访问。

调用时,此方法执行以下步骤:

  1. 令 obj 为 ? ToObject(this value)。
  2. 令 length 为 ? LengthOfArrayLike(obj)。
  3. 如果 IsCallable(callback) 是 false,则抛出 TypeError 异常。
  4. 令 array 为 ? ArraySpeciesCreate(obj, length)。
  5. 令 k 为 0。
  6. 当 k < length 时,重复执行,
    1. 令 propertyKey 为 ! ToString(𝔽(k))。
    2. 令 kPresent 为 ? HasProperty(obj, propertyKey)。
    3. 如果 kPresent 是 true,则
      1. 令 kValue 为 ? Get(obj, propertyKey)。
      2. 令 mappedValue 为 ? Call(callback, thisArg, « kValue, 𝔽(k), obj »)。
      3. 执行 ? CreateDataPropertyOrThrow(array, propertyKey, mappedValue)。
    4. 将 k 设置为 k + 1。
  7. 返回 array。
注 2

此方法有意设计为通用方法;它不要求其 this value 是 Array。因此,它可以被转移到其他种类的对象上用作方法。

23.1.3.22 Array.prototype.pop ( )

注 1

此方法移除数组的最后一个元素并返回该元素。

调用时,此方法执行以下步骤:

  1. 令 obj 为 ? ToObject(this value)。
  2. 令 length 为 ? LengthOfArrayLike(obj)。
  3. 如果 length = 0,则
    1. 执行 ? Set(obj, "length", +0𝔽, true)。
    2. 返回 undefined。
  4. 断言:length > 0。
  5. 令 newLength 为 𝔽(length - 1)。
  6. 令 index 为 ! ToString(newLength)。
  7. 令 element 为 ? Get(obj, index)。
  8. 执行 ? DeletePropertyOrThrow(obj, index)。
  9. 执行 ? Set(obj, "length", newLength, true)。
  10. 返回 element。
注 2

此方法有意设计为通用方法;它不要求其 this value 是 Array。因此,它可以被转移到其他种类的对象上用作方法。

23.1.3.23 Array.prototype.push ( ...items )

注 1

此方法按参数出现的顺序将它们追加到数组末尾。它返回数组的新长度。

调用时,此方法执行以下步骤:

  1. 令 obj 为 ? ToObject(this value)。
  2. 令 length 为 ? LengthOfArrayLike(obj)。
  3. 令 argCount 为 items 中的元素数量。
  4. 如果 length + argCount > 253 - 1,则抛出 TypeError 异常。
  5. 对 items 的每个元素 item,执行
    1. 执行 ? Set(obj, ! ToString(𝔽(length)), item, true)。
    2. 将 length 设置为 length + 1。
  6. 执行 ? Set(obj, "length", 𝔽(length), true)。
  7. 返回 𝔽(length)。

此方法的 "length" 属性是 1𝔽。

注 2

此方法有意设计为通用方法;它不要求其 this value 是 Array。因此,它可以被转移到其他种类的对象上用作方法。

23.1.3.24 Array.prototype.reduce ( callback [ , initialValue ] )

注 1

callback 应当是一个接受四个参数的函数。reduce 按升序对数组中实际存在的每个元素调用一次 callback,除非提供了 initialValue,否则会跳过第一个元素。

调用 callback 时会传入四个参数:previousValue(上一次调用 callback 的值)、currentValue(当前元素的值)、currentIndex 以及正在遍历的对象。第一次调用 callback 时,previousValue 和 currentValue 可以有两种取值。如果调用 reduce 时提供了 initialValue,则 previousValue 将为 initialValue,而 currentValue 将为数组中的第一个值。如果未提供 initialValue,则 previousValue 将为数组中的第一个值,而 currentValue 将为第二个值。如果数组不包含任何元素且未提供 initialValue,则为 TypeError。

reduce 不会直接修改调用它的对象,但对 callback 的调用可能会修改该对象。

reduce 处理的元素范围在第一次调用 callback 之前确定。调用 reduce 开始后追加到数组中的元素不会被 callback 访问。如果数组中已有元素发生变化,则传递给 callback 的值是在 reduce 访问该元素时的值;在调用 reduce 开始后且被访问之前删除的元素不会被访问。

调用时,此方法执行以下步骤:

  1. 令 obj 为 ? ToObject(this value)。
  2. 令 length 为 ? LengthOfArrayLike(obj)。
  3. 如果 IsCallable(callback) 是 false,则抛出 TypeError 异常。
  4. 如果 length = 0 且不存在 initialValue,则抛出 TypeError 异常。
  5. 令 k 为 0。
  6. 令 accumulator 为 undefined。
  7. 如果存在 initialValue,则
    1. 将 accumulator 设置为 initialValue。
  8. 否则,
    1. 令 kPresent 为 false。
    2. 当 kPresent 是 false 且 k < length 时,重复执行,
      1. 令 propertyKey 为 ! ToString(𝔽(k))。
      2. 将 kPresent 设置为 ? HasProperty(obj, propertyKey)。
      3. 如果 kPresent 是 true,则
        1. 将 accumulator 设置为 ? Get(obj, propertyKey)。
      4. 将 k 设置为 k + 1。
    3. 如果 kPresent 是 false,则抛出 TypeError 异常。
  9. 当 k < length 时,重复执行,
    1. 令 propertyKey 为 ! ToString(𝔽(k))。
    2. 令 kPresent 为 ? HasProperty(obj, propertyKey)。
    3. 如果 kPresent 是 true,则
      1. 令 kValue 为 ? Get(obj, propertyKey)。
      2. 将 accumulator 设置为 ? Call(callback, undefined, « accumulator, kValue, 𝔽(k), obj »)。
    4. 将 k 设置为 k + 1。
  10. 返回 accumulator。
注 2

此方法有意设计为通用方法;它不要求其 this value 是 Array。因此,它可以被转移到其他种类的对象上用作方法。

23.1.3.25 Array.prototype.reduceRight ( callback [ , initialValue ] )

注 1

callback 应当是一个接受四个参数的函数。reduceRight 按降序对数组中实际存在的每个元素调用一次 callback,除非提供了 initialValue,否则会跳过第一次调用。

调用 callback 时会传入四个参数:previousValue(上一次调用 callback 的值)、currentValue(当前元素的值)、currentIndex 以及正在遍历的对象。第一次调用该函数时,previousValue 和 currentValue 可以有两种取值。如果调用 reduceRight 时提供了 initialValue,则 previousValue 将为 initialValue,而 currentValue 将为数组中的最后一个值。如果未提供 initialValue,则 previousValue 将为数组中的最后一个值,而 currentValue 将为倒数第二个值。如果数组不包含任何元素且未提供 initialValue,则为 TypeError。

reduceRight 不会直接修改调用它的对象,但对 callback 的调用可能会修改该对象。

reduceRight 处理的元素范围在第一次调用 callback 之前确定。调用 reduceRight 开始后追加到数组中的元素不会被 callback 访问。如果数组中已有元素被 callback 修改,则传递给 callback 的值是在 reduceRight 访问该元素时的值;在调用 reduceRight 开始后且被访问之前删除的元素不会被访问。

调用时,此方法执行以下步骤:

  1. 令 obj 为 ? ToObject(this value)。
  2. 令 length 为 ? LengthOfArrayLike(obj)。
  3. 如果 IsCallable(callback) 是 false,则抛出 TypeError 异常。
  4. 如果 length = 0 且不存在 initialValue,则抛出 TypeError 异常。
  5. 令 k 为 length - 1。
  6. 令 accumulator 为 undefined。
  7. 如果存在 initialValue,则
    1. 将 accumulator 设置为 initialValue。
  8. 否则,
    1. 令 kPresent 为 false。
    2. 当 kPresent 是 false 且 k ≥ 0 时,重复执行,
      1. 令 propertyKey 为 ! ToString(𝔽(k))。
      2. 将 kPresent 设置为 ? HasProperty(obj, propertyKey)。
      3. 如果 kPresent 是 true,则
        1. 将 accumulator 设置为 ? Get(obj, propertyKey)。
      4. 将 k 设置为 k - 1。
    3. 如果 kPresent 是 false,则抛出 TypeError 异常。
  9. 当 k ≥ 0 时,重复执行,
    1. 令 propertyKey 为 ! ToString(𝔽(k))。
    2. 令 kPresent 为 ? HasProperty(obj, propertyKey)。
    3. 如果 kPresent 是 true,则
      1. 令 kValue 为 ? Get(obj, propertyKey)。
      2. 将 accumulator 设置为 ? Call(callback, undefined, « accumulator, kValue, 𝔽(k), obj »)。
    4. 将 k 设置为 k - 1。
  10. 返回 accumulator。
注 2

此方法有意设计为通用方法;它不要求其 this value 是 Array。因此,它可以被转移到其他种类的对象上用作方法。

23.1.3.26 Array.prototype.reverse ( )

注 1

此方法重新排列数组元素以反转其顺序。它返回反转后的数组。

调用时,此方法执行以下步骤:

  1. 令 obj 为 ? ToObject(this value)。
  2. 令 length 为 ? LengthOfArrayLike(obj)。
  3. 令 middle 为 floor(length / 2)。
  4. 令 lower 为 0。
  5. 当 lower ≠ middle 时,重复执行,
    1. 令 upper 为 length - lower - 1。
    2. 令 upperP 为 ! ToString(𝔽(upper))。
    3. 令 lowerP 为 ! ToString(𝔽(lower))。
    4. 令 lowerExists 为 ? HasProperty(obj, lowerP)。
    5. 如果 lowerExists 是 true,则
      1. 令 lowerValue 为 ? Get(obj, lowerP)。
    6. 令 upperExists 为 ? HasProperty(obj, upperP)。
    7. 如果 upperExists 是 true,则
      1. 令 upperValue 为 ? Get(obj, upperP)。
    8. 如果 lowerExists 是 true 且 upperExists 是 true,则
      1. 执行 ? Set(obj, lowerP, upperValue, true)。
      2. 执行 ? Set(obj, upperP, lowerValue, true)。
    9. 否则如果 lowerExists 是 false 且 upperExists 是 true,则
      1. 执行 ? Set(obj, lowerP, upperValue, true)。
      2. 执行 ? DeletePropertyOrThrow(obj, upperP)。
    10. 否则如果 lowerExists 是 true 且 upperExists 是 false,则
      1. 执行 ? DeletePropertyOrThrow(obj, lowerP)。
      2. 执行 ? Set(obj, upperP, lowerValue, true)。
    11. 否则,
      1. 断言:lowerExists 和 upperExists 都是 false。
      2. 注:无需执行任何操作。
    12. 将 lower 设置为 lower + 1。
  6. 返回 obj。
注 2

此方法有意设计为通用方法;它不要求其 this value 是 Array。因此,它可以被转移到其他种类的对象上用作方法。

23.1.3.27 Array.prototype.shift ( )

此方法移除数组的第一个元素并返回该元素。

调用时,它执行以下步骤:

  1. 令 obj 为 ? ToObject(this value)。
  2. 令 length 为 ? LengthOfArrayLike(obj)。
  3. 如果 length = 0,则
    1. 执行 ? Set(obj, "length", +0𝔽, true)。
    2. 返回 undefined。
  4. 令 first 为 ? Get(obj, "0")。
  5. 令 k 为 1。
  6. 当 k < length 时,重复执行,
    1. 令 from 为 ! ToString(𝔽(k))。
    2. 令 to 为 ! ToString(𝔽(k - 1))。
    3. 令 fromPresent 为 ? HasProperty(obj, from)。
    4. 如果 fromPresent 是 true,则
      1. 令 fromValue 为 ? Get(obj, from)。
      2. 执行 ? Set(obj, to, fromValue, true)。
    5. 否则,
      1. 断言:fromPresent 是 false。
      2. 执行 ? DeletePropertyOrThrow(obj, to)。
    6. 将 k 设置为 k + 1。
  7. 执行 ? DeletePropertyOrThrow(obj, ! ToString(𝔽(length - 1)))。
  8. 执行 ? Set(obj, "length", 𝔽(length - 1), true)。
  9. 返回 first。
注

此方法有意设计为通用方法;它不要求其 this value 是 Array。因此,它可以被转移到其他种类的对象上用作方法。

23.1.3.28 Array.prototype.slice ( start, end )

此方法返回一个数组,其中包含从元素 start 开始到元素 end 之前(如果 end 是 undefined,则一直到数组末尾)的数组元素。如果 start 为负,则将其视为 length + start,其中 length 是数组的长度。如果 end 为负,则将其视为 length + end,其中 length 是数组的长度。

调用时,它执行以下步骤:

  1. 令 obj 为 ? ToObject(this value)。
  2. 令 length 为 ? LengthOfArrayLike(obj)。
  3. 令 k 为 ? ToClampedIndex(start, length)。
  4. 如果 end 是 undefined,则令 final 为 length;否则令 final 为 ? ToClampedIndex(end, length)。
  5. 令 count 为 max(final - k, 0)。
  6. 令 array 为 ? ArraySpeciesCreate(obj, count)。
  7. 令 resultIndex 为 0。
  8. 当 k < final 时,重复执行,
    1. 令 propertyKey 为 ! ToString(𝔽(k))。
    2. 令 kPresent 为 ? HasProperty(obj, propertyKey)。
    3. 如果 kPresent 是 true,则
      1. 令 kValue 为 ? Get(obj, propertyKey)。
      2. 执行 ? CreateDataPropertyOrThrow(array, ! ToString(𝔽(resultIndex)), kValue)。
    4. 将 k 设置为 k + 1。
    5. 将 resultIndex 设置为 resultIndex + 1。
  9. 执行 ? Set(array, "length", 𝔽(resultIndex), true)。
  10. 返回 array。
注 1

在步骤 9 中显式设置 "length" 属性,是为了确保即使 array 不是内置 Array,长度仍然正确。

注 2

此方法有意设计为通用方法;它不要求其 this value 是 Array。因此,它可以被转移到其他种类的对象上用作方法。

23.1.3.29 Array.prototype.some ( callback [ , thisArg ] )

注 1

callback 应当是一个接受三个参数并返回可强制转换为 Boolean 值的值的函数。some 按升序对数组中实际存在的每个元素调用一次 callback,直到找到一个使 callback 返回 true 的元素。如果找到这样的元素,some 会立即返回 true。否则,some 返回 false。callback 只会针对数组中实际存在的元素调用;不会针对数组中缺失的元素调用。

如果提供了 thisArg 参数,则每次调用 callback 时都会将其用作 this value。如果未提供,则改用 undefined。

调用 callback 时会传入三个参数:元素的值、元素的索引以及正在遍历的对象。

some 不会直接修改调用它的对象,但对 callback 的调用可能会修改该对象。

some 处理的元素范围在第一次调用 callback 之前确定。调用 some 开始后追加到数组中的元素不会被 callback 访问。如果数组中已有元素发生变化,则传递给 callback 的值是在 some 访问该元素时的值;在调用 some 开始后且被访问之前删除的元素不会被访问。some 的作用类似于数学中的“存在”量词。特别地,对于空数组,它返回 false。

调用时,此方法执行以下步骤:

  1. 令 obj 为 ? ToObject(this value)。
  2. 令 length 为 ? LengthOfArrayLike(obj)。
  3. 如果 IsCallable(callback) 是 false,则抛出 TypeError 异常。
  4. 令 k 为 0。
  5. 当 k < length 时,重复执行,
    1. 令 propertyKey 为 ! ToString(𝔽(k))。
    2. 令 kPresent 为 ? HasProperty(obj, propertyKey)。
    3. 如果 kPresent 是 true,则
      1. 令 kValue 为 ? Get(obj, propertyKey)。
      2. 令 testResult 为 ToBoolean(? Call(callback, thisArg, « kValue, 𝔽(k), obj »))。
      3. 如果 testResult 是 true,则返回 true。
    4. 将 k 设置为 k + 1。
  6. 返回 false。
注 2

此方法有意设计为通用方法;它不要求其 this value 是 Array。因此,它可以被转移到其他种类的对象上用作方法。

23.1.3.30 Array.prototype.sort ( comparator )

此方法对该数组的元素进行排序。如果 comparator 不是 undefined,它应当是一个接受两个参数 x 和 y 的函数;如果 x < y,返回负 Number;如果 x > y,返回正 Number;否则返回零。

调用时,它执行以下步骤:

  1. 如果 comparator 不是 undefined 且 IsCallable(comparator) 是 false,则抛出 TypeError 异常。
  2. 令 obj 为 ? ToObject(this value)。
  3. 令 length 为 ? LengthOfArrayLike(obj)。
  4. 令 sortCompare 为参数为 (x, y) 的新 Abstract Closure,它捕获 comparator,并在被调用时执行以下步骤:
    1. 返回 ? CompareArrayElements(x, y, comparator)。
  5. 令 sortedList 为 ? SortIndexedProperties(obj, length, sortCompare, skip-holes)。
  6. 令 itemCount 为 sortedList 中的元素数量。
  7. 令 j 为 0。
  8. 当 j < itemCount 时,重复执行,
    1. 执行 ? Set(obj, ! ToString(𝔽(j)), sortedList[j], true)。
    2. 将 j 设置为 j + 1。
  9. 注:步骤 5 中对 SortIndexedProperties 的调用使用 skip-holes。剩余索引会被删除,以保留检测到并从排序中排除的空位数量。
  10. 当 j < length 时,重复执行,
    1. 执行 ? DeletePropertyOrThrow(obj, ! ToString(𝔽(j)))。
    2. 将 j 设置为 j + 1。
  11. 返回 obj。
注 1

由于不存在的属性值始终比较为大于 undefined 属性值,而 undefined 始终比较为大于任何其他值(参见 CompareArrayElements),因此 undefined 属性值总是排序到结果末尾,之后才是不存在的属性值。

注 2

步骤 5 和 6 中 ToString 抽象操作执行的方法调用可能导致 sortCompare 无法表现为一致比较器。

注 3

此方法有意设计为通用方法;它不要求其 this value 是 Array。因此,它可以被转移到其他种类的对象上用作方法。

23.1.3.30.1 SortIndexedProperties ( obj, length, sortCompare, holes )

抽象操作 SortIndexedProperties,接收参数 obj (Object)、length (非负整数)、sortCompare (有两个参数的抽象闭包) 和 holes ((skip-holes 或 read-through-holes));返回值:(正常完成 (值:列表 (元素:ECMAScript 语言值)) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 items 为新的空 List。
  2. 令 k 为 0。
  3. 当 k < length 时,重复执行,
    1. 令 propertyKey 为 ! ToString(𝔽(k))。
    2. 如果 holes 是 skip-holes,则
      1. 令 kRead 为 ? HasProperty(obj, propertyKey)。
    3. 否则,
      1. 断言:holes 是 read-through-holes。
      2. 令 kRead 为 true。
    4. 如果 kRead 是 true,则
      1. 令 kValue 为 ? Get(obj, propertyKey)。
      2. 将 kValue 追加到 items。
    5. 将 k 设置为 k + 1。
  4. 使用由实现定义的 对 sortCompare 的调用序列对 items 排序。如果任何此类调用返回突然完成,则在进一步调用 sortCompare 之前停止,并返回该 Completion Record。
  5. 返回 items。

排序顺序是上述算法的步骤 4 完成后 items 的顺序。如果 sortCompare 对 items 的元素而言不是一致比较器,则排序顺序由实现定义。当 SortIndexedProperties 由 Array.prototype.sort 或 Array.prototype.toSorted 调用时,如果 comparator 是 undefined,并且对作为参数传递给 sortCompare 的某个特定值应用 ToString 时并非总是产生相同结果,则排序顺序也由实现定义。

除非规定排序顺序由实现定义,否则它必须满足以下所有条件:

  • 必须存在一个小于 itemCount 的非负整数的数学排列 π,使得对于每个小于 itemCount 的非负整数 j,元素 old[j] 与 new[π(j)] 完全相同。
  • 那么,对于所有均小于 itemCount 的非负整数 j 和 k,如果 ℝ(sortCompare(old[j], old[k])) < 0,则 π(j) < π(k)。
  • 并且对于所有满足 j < k < itemCount 的非负整数 j 和 k,如果 ℝ(sortCompare(old[j], old[k])) = 0,则 π(j) < π(k);即排序是稳定的。

这里使用记号 old[j] 指代执行步骤 4 之前的 items[j],并使用记号 new[j] 指代执行步骤 4 之后的 items[j]。

如果对于集合 values 中的所有值 a、b 和 c(它们可能是同一个值)都满足以下所有要求,则 Abstract Closure 或函数 comparator 是值集合 values 的一致比较器:记号 a <C b 表示 ℝ(comparator(a, b)) < 0;a =C b 表示 ℝ(comparator(a, b)) = 0;而 a >C b 表示 ℝ(comparator(a, b)) > 0。

  • 当将特定的一对值 a 和 b 作为两个参数传入时,调用 comparator(a, b) 总是返回相同的值 v。此外,v 是 Number,且 v 不是 NaN。注意,这意味着对于给定的一对 a 和 b,a <C b、a =C b 和 a >C b 中恰好有一个为真。
  • 调用 comparator(a, b) 不会修改 obj 或 obj 原型链上的任何对象。
  • a =C a(自反性)
  • 如果 a =C b,则 b =C a(对称性)
  • 如果 a =C b 且 b =C c,则 a =C c(=C 的传递性)
  • 如果 a <C b 且 b <C c,则 a <C c(<C 的传递性)
  • 如果 a >C b 且 b >C c,则 a >C c(>C 的传递性)
注

上述条件是确保 comparator 将集合 values 划分为等价类,并使这些等价类具有全序关系的充要条件。

23.1.3.30.2 CompareArrayElements ( x, y, comparator )

抽象操作 CompareArrayElements,接收参数 x (ECMAScript 语言值)、y (ECMAScript 语言值) 和 comparator ((函数对象 或 undefined));返回值:(正常完成 (值:Number) 或 突兀完成)。 调用时执行以下步骤:

  1. 如果 x 是 undefined 且 y 是 undefined,则返回 +0𝔽。
  2. 如果 x 是 undefined,则返回 1𝔽。
  3. 如果 y 是 undefined,则返回 -1𝔽。
  4. 如果 comparator 不是 undefined,则
    1. 令 result 为 ? ToNumber(? Call(comparator, undefined, « x, y »))。
    2. 如果 result 是 NaN,则返回 +0𝔽。
    3. 返回 result。
  5. 令 xString 为 ? ToString(x)。
  6. 令 yString 为 ? ToString(y)。
  7. 令 xSmaller 为 ! IsLessThan(xString, yString, true)。
  8. 如果 xSmaller 是 true,则返回 -1𝔽。
  9. 令 ySmaller 为 ! IsLessThan(yString, xString, true)。
  10. 如果 ySmaller 是 true,则返回 1𝔽。
  11. 返回 +0𝔽。

23.1.3.31 Array.prototype.splice ( start, deleteCount, ...items )

注 1

此方法从整数索引 start 开始删除数组中的 deleteCount 个元素,并用 items 的元素替换它们。它返回一个包含已删除元素(如果有)的 Array。

调用时,此方法执行以下步骤:

  1. 令 obj 为 ? ToObject(this value)。
  2. 令 length 为 ? LengthOfArrayLike(obj)。
  3. 令 actualStart 为 ? ToClampedIndex(start, length)。
  4. 令 itemCount 为 items 中的元素数量。
  5. 如果不存在 start,则
    1. 令 actualDeleteCount 为 0。
  6. 否则如果不存在 deleteCount,则
    1. 令 actualDeleteCount 为 length - actualStart。
    2. 断言:actualDeleteCount ≥ 0。
  7. 否则,
    1. 令 dc 为 ? ToIntegerOrInfinity(deleteCount)。
    2. 令 actualDeleteCount 为将 dc 限制在 0 和 length - actualStart 之间的结果。
  8. 如果 length + itemCount - actualDeleteCount > 253 - 1,则抛出 TypeError 异常。
  9. 令 deletedArray 为 ? ArraySpeciesCreate(obj, actualDeleteCount)。
  10. 令 k 为 0。
  11. 当 k < actualDeleteCount 时,重复执行,
    1. 令 from 为 ! ToString(𝔽(actualStart + k))。
    2. 如果 ? HasProperty(obj, from) 是 true,则
      1. 令 fromValue 为 ? Get(obj, from)。
      2. 执行 ? CreateDataPropertyOrThrow(deletedArray, ! ToString(𝔽(k)), fromValue)。
    3. 将 k 设置为 k + 1。
  12. 执行 ? Set(deletedArray, "length", 𝔽(actualDeleteCount), true)。
  13. 如果 itemCount < actualDeleteCount,则
    1. 将 k 设置为 actualStart。
    2. 当 k < (length - actualDeleteCount) 时,重复执行,
      1. 令 from 为 ! ToString(𝔽(k + actualDeleteCount))。
      2. 令 to 为 ! ToString(𝔽(k + itemCount))。
      3. 如果 ? HasProperty(obj, from) 是 true,则
        1. 令 fromValue 为 ? Get(obj, from)。
        2. 执行 ? Set(obj, to, fromValue, true)。
      4. 否则,
        1. 执行 ? DeletePropertyOrThrow(obj, to)。
      5. 将 k 设置为 k + 1。
    3. 将 k 设置为 length。
    4. 当 k > (length - actualDeleteCount + itemCount) 时,重复执行,
      1. 执行 ? DeletePropertyOrThrow(obj, ! ToString(𝔽(k - 1)))。
      2. 将 k 设置为 k - 1。
  14. 否则如果 itemCount > actualDeleteCount,则
    1. 将 k 设置为 (length - actualDeleteCount)。
    2. 当 k > actualStart 时,重复执行,
      1. 令 from 为 ! ToString(𝔽(k + actualDeleteCount - 1))。
      2. 令 to 为 ! ToString(𝔽(k + itemCount - 1))。
      3. 如果 ? HasProperty(obj, from) 是 true,则
        1. 令 fromValue 为 ? Get(obj, from)。
        2. 执行 ? Set(obj, to, fromValue, true)。
      4. 否则,
        1. 执行 ? DeletePropertyOrThrow(obj, to)。
      5. 将 k 设置为 k - 1。
  15. 将 k 设置为 actualStart。
  16. 对 items 的每个元素 item,执行
    1. 执行 ? Set(obj, ! ToString(𝔽(k)), item, true)。
    2. 将 k 设置为 k + 1。
  17. 执行 ? Set(obj, "length", 𝔽(length - actualDeleteCount + itemCount), true)。
  18. 返回 deletedArray。
注 2

在步骤 12 和 17 中显式设置 "length" 属性,是为了确保即使这些对象不是内置 Array,长度仍然正确。

注 3

此方法有意设计为通用方法;它不要求其 this value 是 Array。因此,它可以被转移到其他种类的对象上用作方法。

23.1.3.32 Array.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] )

包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按照 ECMA-402 中的规定实现此方法。否则,使用以下此方法的规范。

注 1

ECMA-402 第一版未包含此方法的替代规范。

此方法可选参数的含义定义于 ECMA-402;不包含 ECMA-402 支持的实现不得将这些参数位置用于其他用途。

调用时,此方法执行以下步骤:

  1. 令 array 为 ? ToObject(this value)。
  2. 令 length 为 ? LengthOfArrayLike(array)。
  3. 令 separator 为适合宿主环境当前区域设置的、由实现定义的列表分隔符 String 值(例如 ", ")。
  4. 令 result 为空 String。
  5. 令 k 为 0。
  6. 当 k < length 时,重复执行,
    1. 如果 k > 0,则将 result 设置为 result 和 separator 的字符串连接。
    2. 令 element 为 ? Get(array, ! ToString(𝔽(k)))。
    3. 如果 element 既不是 undefined 也不是 null,则
      1. 令 elementString 为 ? ToString(? Invoke(element, "toLocaleString")).
      2. 将 result 设置为 result 和 elementString 的字符串连接。
    4. 将 k 设置为 k + 1。
  7. 返回 result。
注 2

此方法使用数组元素各自的 toLocaleString 方法将它们转换为 Strings,然后连接这些 Strings,并在它们之间插入由实现定义、对区域设置敏感的分隔符 String。此方法类似于 toString,只是它旨在产生符合宿主环境当前区域设置惯例的区域设置敏感结果。

注 3

此方法有意设计为通用方法;它不要求其 this value 是 Array。因此,它可以被转移到其他种类的对象上用作方法。

23.1.3.33 Array.prototype.toReversed ( )

调用时,此方法执行以下步骤:

  1. 令 obj 为 ? ToObject(this value)。
  2. 令 length 为 ? LengthOfArrayLike(obj)。
  3. 令 array 为 ? ArrayCreate(length)。
  4. 令 k 为 0。
  5. 当 k < length 时,重复执行,
    1. 令 from 为 ! ToString(𝔽(length - k - 1))。
    2. 令 propertyKey 为 ! ToString(𝔽(k))。
    3. 令 fromValue 为 ? Get(obj, from)。
    4. 执行 ! CreateDataPropertyOrThrow(array, propertyKey, fromValue)。
    5. 将 k 设置为 k + 1。
  6. 返回 array。

23.1.3.34 Array.prototype.toSorted ( comparator )

调用时,此方法执行以下步骤:

  1. 如果 comparator 不是 undefined 且 IsCallable(comparator) 是 false,则抛出 TypeError 异常。
  2. 令 obj 为 ? ToObject(this value)。
  3. 令 length 为 ? LengthOfArrayLike(obj)。
  4. 令 array 为 ? ArrayCreate(length)。
  5. 令 sortCompare 为参数为 (x, y) 的新 Abstract Closure,它捕获 comparator,并在被调用时执行以下步骤:
    1. 返回 ? CompareArrayElements(x, y, comparator)。
  6. 令 sortedList 为 ? SortIndexedProperties(obj, length, sortCompare, read-through-holes)。
  7. 令 j 为 0。
  8. 当 j < length 时,重复执行,
    1. 执行 ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(j)), sortedList[j])。
    2. 将 j 设置为 j + 1。
  9. 返回 array。

23.1.3.35 Array.prototype.toSpliced ( start, skipCount, ...items )

调用时,此方法执行以下步骤:

  1. 令 obj 为 ? ToObject(this value)。
  2. 令 length 为 ? LengthOfArrayLike(obj)。
  3. 令 actualStart 为 ? ToClampedIndex(start, length)。
  4. 令 insertCount 为 items 中的元素数量。
  5. 令 maxSkipCount 为 length - actualStart。
  6. 如果不存在 start,则
    1. 令 actualSkipCount 为 0。
  7. 否则如果不存在 skipCount,则
    1. 令 actualSkipCount 为 maxSkipCount。
  8. 否则,
    1. 令 actualSkipCount 为将 ? ToIntegerOrInfinity(skipCount) 限制在 0 和 maxSkipCount 之间的结果。
  9. 令 newLength 为 length + insertCount - actualSkipCount。
  10. 断言:newLength ≥ 0。
  11. 如果 newLength > 253 - 1,则抛出 TypeError 异常。
  12. 令 newArray 为 ? ArrayCreate(newLength)。
  13. 令 writeIndex 为 0。
  14. 令 readIndex 为 actualStart + actualSkipCount。
  15. 当 writeIndex < actualStart 时,重复执行,
    1. 令 propertyKey 为 ! ToString(𝔽(writeIndex))。
    2. 令 iValue 为 ? Get(obj, propertyKey)。
    3. 执行 ! CreateDataPropertyOrThrow(newArray, propertyKey, iValue)。
    4. 将 writeIndex 设置为 writeIndex + 1。
  16. 对 items 的每个元素 item,执行
    1. 令 propertyKey 为 ! ToString(𝔽(writeIndex))。
    2. 执行 ! CreateDataPropertyOrThrow(newArray, propertyKey, item)。
    3. 将 writeIndex 设置为 writeIndex + 1。
  17. 当 writeIndex < newLength 时,重复执行,
    1. 令 propertyKey 为 ! ToString(𝔽(writeIndex))。
    2. 令 from 为 ! ToString(𝔽(readIndex))。
    3. 令 fromValue 为 ? Get(obj, from)。
    4. 执行 ! CreateDataPropertyOrThrow(newArray, propertyKey, fromValue)。
    5. 将 writeIndex 设置为 writeIndex + 1。
    6. 将 readIndex 设置为 readIndex + 1。
  18. 返回 newArray。

23.1.3.36 Array.prototype.toString ( )

调用时,此方法执行以下步骤:

  1. 令 array 为 ? ToObject(this value)。
  2. 令 func 为 ? Get(array, "join")。
  3. 如果 IsCallable(func) 是 false,则将 func 设置为内在函数 %Object.prototype.toString%。
  4. 返回 ? Call(func, array)。
注

此方法有意设计为通用方法;它不要求其 this value 是 Array。因此,它可以被转移到其他种类的对象上用作方法。

23.1.3.37 Array.prototype.unshift ( ...items )

此方法将参数前置到数组开头,使它们在数组中的顺序与它们在参数列表中出现的顺序相同。

调用时,它执行以下步骤:

  1. 令 obj 为 ? ToObject(this value)。
  2. 令 length 为 ? LengthOfArrayLike(obj)。
  3. 令 argCount 为 items 中的元素数量。
  4. 如果 argCount > 0,则
    1. 如果 length + argCount > 253 - 1,则抛出 TypeError 异常。
    2. 令 k 为 length。
    3. 当 k > 0 时,重复执行,
      1. 令 from 为 ! ToString(𝔽(k - 1))。
      2. 令 to 为 ! ToString(𝔽(k + argCount - 1))。
      3. 令 fromPresent 为 ? HasProperty(obj, from)。
      4. 如果 fromPresent 是 true,则
        1. 令 fromValue 为 ? Get(obj, from)。
        2. 执行 ? Set(obj, to, fromValue, true)。
      5. 否则,
        1. 断言:fromPresent 是 false。
        2. 执行 ? DeletePropertyOrThrow(obj, to)。
      6. 将 k 设置为 k - 1。
    4. 令 j 为 0。
    5. 对 items 的每个元素 item,执行
      1. 执行 ? Set(obj, ! ToString(𝔽(j)), item, true)。
      2. 将 j 设置为 j + 1。
  5. 执行 ? Set(obj, "length", 𝔽(length + argCount), true)。
  6. 返回 𝔽(length + argCount)。

此方法的 "length" 属性是 1𝔽。

注

此方法有意设计为通用方法;它不要求其 this value 是 Array。因此,它可以被转移到其他种类的对象上用作方法。

23.1.3.38 Array.prototype.values ( )

调用时,此方法执行以下步骤:

  1. 令 obj 为 ? ToObject(this value)。
  2. 返回 CreateArrayIterator(obj, value)。

23.1.3.39 Array.prototype.with ( index, value )

调用时,此方法执行以下步骤:

  1. 令 obj 为 ? ToObject(this value)。
  2. 令 length 为 ? LengthOfArrayLike(obj)。
  3. 令 actualIndex 为 ? ToAbsoluteIndex(index, length)。
  4. 如果 actualIndex < 0 或 actualIndex ≥ length,则抛出 RangeError 异常。
  5. 令 array 为 ? ArrayCreate(length)。
  6. 令 k 为 0。
  7. 当 k < length 时,重复执行,
    1. 令 propertyKey 为 ! ToString(𝔽(k))。
    2. 如果 k = actualIndex,则令 fromValue 为 value。
    3. 否则,令 fromValue 为 ? Get(obj, propertyKey)。
    4. 执行 ! CreateDataPropertyOrThrow(array, propertyKey, fromValue)。
    5. 将 k 设置为 k + 1。
  8. 返回 array。

23.1.3.40 Array.prototype [ %Symbol.iterator% ] ( )

%Symbol.iterator% 属性的初始值是 23.1.3.38 中定义的 %Array.prototype.values%。

23.1.3.41 Array.prototype [ %Symbol.unscopables% ]

%Symbol.unscopables% 数据属性的初始值是由以下步骤创建的对象:

  1. 令 unscopableList 为 OrdinaryObjectCreate(null)。
  2. 执行 ! CreateDataPropertyOrThrow(unscopableList, "at", true)。
  3. 执行 ! CreateDataPropertyOrThrow(unscopableList, "copyWithin", true)。
  4. 执行 ! CreateDataPropertyOrThrow(unscopableList, "entries", true)。
  5. 执行 ! CreateDataPropertyOrThrow(unscopableList, "fill", true)。
  6. 执行 ! CreateDataPropertyOrThrow(unscopableList, "find", true)。
  7. 执行 ! CreateDataPropertyOrThrow(unscopableList, "findIndex", true)。
  8. 执行 ! CreateDataPropertyOrThrow(unscopableList, "findLast", true)。
  9. 执行 ! CreateDataPropertyOrThrow(unscopableList, "findLastIndex", true)。
  10. 执行 ! CreateDataPropertyOrThrow(unscopableList, "flat", true)。
  11. 执行 ! CreateDataPropertyOrThrow(unscopableList, "flatMap", true)。
  12. 执行 ! CreateDataPropertyOrThrow(unscopableList, "includes", true)。
  13. 执行 ! CreateDataPropertyOrThrow(unscopableList, "keys", true)。
  14. 执行 ! CreateDataPropertyOrThrow(unscopableList, "toReversed", true)。
  15. 执行 ! CreateDataPropertyOrThrow(unscopableList, "toSorted", true)。
  16. 执行 ! CreateDataPropertyOrThrow(unscopableList, "toSpliced", true)。
  17. 执行 ! CreateDataPropertyOrThrow(unscopableList, "values", true)。
  18. 返回 unscopableList。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

注

此对象的自有属性名称,是在 ECMAScript 2015 规范之前未作为 Array.prototype 标准属性包含的属性名称。为了保留现有代码的行为,对于 with 语句绑定,会忽略这些名称;现有代码可能在外层作用域中使用其中某个名称作为绑定,而该绑定会被绑定对象为 Array 的 with 语句遮蔽。

"with" 未包含在 unscopableList 中,是因为它已经是保留字。

23.1.4 Array 实例的属性

Array 实例是 Array 异质对象,并具有为此类对象规定的内部方法。Array 实例从 Array 原型对象继承属性。

Array 实例具有 "length" 属性,以及一组以数组索引为名称的可枚举属性。

23.1.4.1 length

Array 实例的 "length" 属性是数据属性,其值在数值上始终大于名称为数组索引的每个可配置自有属性的名称。

"length" 属性最初具有特性 { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }。

注

减小 "length" 属性的值具有删除数组索引位于旧长度值和新长度值之间的自有数组元素的副作用。不过,不可配置属性不能被删除。尝试将 Array 的 "length" 属性设置为一个在数值上小于或等于数组中现有不可配置数组索引属性的最大数值自有属性名称的值,将导致长度被设置为比该不可配置数值自有属性名称大一的数值。参见 10.4.2.1。

23.1.5 Array 迭代器对象

Array Iterator 是表示对某个特定 Array 实例对象进行某次特定迭代的对象。Array Iterator 对象没有具名构造函数。相反,Array Iterator 对象通过调用 Array 实例对象的某些方法创建。

23.1.5.1 CreateArrayIterator ( array, kind )

抽象操作 CreateArrayIterator,接收参数 array (Object) 和 kind ((key+value、key 或 value));返回值:Object。 它用于为返回此类迭代器的 Array 方法创建迭代器对象。 调用时执行以下步骤:

  1. 令 iterator 为 OrdinaryObjectCreate(%ArrayIteratorPrototype%, « [[IteratedArrayLike]], [[ArrayLikeNextIndex]], [[ArrayLikeIterationKind]] »)。
  2. 将 iterator.[[IteratedArrayLike]] 设置为 array。
  3. 将 iterator.[[ArrayLikeNextIndex]] 设置为 0。
  4. 将 iterator.[[ArrayLikeIterationKind]] 设置为 kind。
  5. 返回 iterator。

23.1.5.2 %ArrayIteratorPrototype% 对象

%ArrayIteratorPrototype% 对象:

23.1.5.2.1 %ArrayIteratorPrototype%.next ( )

  1. 令 iteratorObj 为 this value。
  2. 如果 iteratorObj 不是 Object,则抛出 TypeError 异常。
  3. 如果 iteratorObj 不具有 Array Iterator Instance 的所有内部槽(23.1.5.3),则抛出 TypeError 异常。
  4. 令 array 为 iteratorObj.[[IteratedArrayLike]]。
  5. 如果 array 是 undefined,则返回 CreateIteratorResultObject(undefined, true)。
  6. 令 index 为 iteratorObj.[[ArrayLikeNextIndex]]。
  7. 令 kind 为 iteratorObj.[[ArrayLikeIterationKind]]。
  8. 如果 array 具有 [[TypedArrayName]] 内部槽,则
    1. 令 taRecord 为 ? ValidateTypedArrayBounds(array, seq-cst)。
    2. 令 length 为 TypedArrayLength(taRecord)。
  9. 否则,
    1. 令 length 为 ? LengthOfArrayLike(array)。
  10. 如果 index ≥ length,则
    1. 将 iteratorObj.[[IteratedArrayLike]] 设置为 undefined。
    2. 返回 CreateIteratorResultObject(undefined, true)。
  11. 将 iteratorObj.[[ArrayLikeNextIndex]] 设置为 index + 1。
  12. 令 indexNumber 为 𝔽(index)。
  13. 如果 kind 是 key,则
    1. 令 result 为 indexNumber。
  14. 否则,
    1. 令 elementKey 为 ! ToString(indexNumber)。
    2. 令 elementValue 为 ? Get(array, elementKey)。
    3. 如果 kind 是 value,则
      1. 令 result 为 elementValue。
    4. 否则,
      1. 断言:kind 是 key+value。
      2. 令 result 为 CreateArrayFromList(« indexNumber, elementValue »)。
  15. 返回 CreateIteratorResultObject(result, false)。

23.1.5.2.2 %ArrayIteratorPrototype% [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "Array Iterator"。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

23.1.5.3 Array Iterator 实例的属性

Array Iterator 实例是从 %ArrayIteratorPrototype% 内在对象继承属性的普通对象。Array Iterator 实例最初创建时具有 表 70 中列出的内部槽。

表 70: Array Iterator 实例的内部槽
内部槽 类型 描述
[[IteratedArrayLike]] an Object or undefined 正在被迭代的类数组对象。
[[ArrayLikeNextIndex]] a non-negative integer 此迭代器下一次要检查的元素的整数索引。
[[ArrayLikeIterationKind]] key+value, key, or value 标识迭代中每个元素返回内容的值。

23.2 TypedArray 对象

TypedArray 提供底层二进制数据缓冲区(25.1)的类数组视图。TypedArray 元素类型是 TypedArray 实例的所有元素所具有的底层二进制标量数据类型。对于每种受支持的元素类型,都有一个不同的 TypedArray 构造函数,列于 表 71。表 71 中的每个构造函数都有一个与之对应的不同原型对象。

表 71: TypedArray 构造函数
构造函数名称和内在对象 元素类型 元素大小 转换操作 描述
Int8Array
%Int8Array%
int8 1 ToInt8 8 位二进制补码有符号整数
Uint8Array
%Uint8Array%
uint8 1 ToUint8 8 位无符号整数
Uint8ClampedArray
%Uint8ClampedArray%
uint8clamped 1 ToUint8Clamp 8 位无符号整数(钳制转换)
Int16Array
%Int16Array%
int16 2 ToInt16 16 位二进制补码有符号整数
Uint16Array
%Uint16Array%
uint16 2 ToUint16 16 位无符号整数
Int32Array
%Int32Array%
int32 4 ToInt32 32 位二进制补码有符号整数
Uint32Array
%Uint32Array%
uint32 4 ToUint32 32 位无符号整数
BigInt64Array
%BigInt64Array%
bigint64 8 ToBigInt64 64 位二进制补码有符号整数
BigUint64Array
%BigUint64Array%
biguint64 8 ToBigUint64 64 位无符号整数
Float16Array
%Float16Array%
float16 2 16 位 IEEE 浮点数
Float32Array
%Float32Array%
float32 4 32 位 IEEE 浮点数
Float64Array
%Float64Array%
float64 8 64 位 IEEE 浮点数

在以下定义中,对 TypedArray 的引用应替换为上表中适当的构造函数名称。

23.2.1 %TypedArray% 内在对象

%TypedArray% 内在对象:

  • 是所有 TypedArray 构造函数对象所继承自的构造函数对象。
  • 与其对应的原型对象一起,提供由所有 TypedArray 构造函数及其实例继承的通用属性。
  • 没有全局名称,也不会作为全局对象的属性出现。
  • 充当各种 TypedArray 构造函数的抽象超类。
  • 调用时会抛出错误,因为它是抽象类构造函数。TypedArray 构造函数不会对它执行 super 调用。

23.2.1.1 %TypedArray% ( )

调用时,此函数执行以下步骤:

  1. 抛出 TypeError 异常。

此函数的 "length" 属性是 +0𝔽。

23.2.2 %TypedArray% 内在对象的属性

%TypedArray% 内在对象:

  • 具有 [[Prototype]] 内部槽,其值是 %Function.prototype%。
  • 具有 "name" 属性,其值是 "TypedArray"。
  • 具有以下属性:

23.2.2.1 %TypedArray%.from ( source [ , mapper [ , thisArg ] ] )

调用时,此方法执行以下步骤:

  1. 令 ctor 为 this value。
  2. 如果 IsConstructor(ctor) 是 false,则抛出 TypeError 异常。
  3. 如果 mapper 是 undefined,则
    1. 令 mapping 为 false。
  4. 否则,
    1. 如果 IsCallable(mapper) 是 false,则抛出 TypeError 异常。
    2. 令 mapping 为 true。
  5. 令 usingIterator 为 ? GetMethod(source, %Symbol.iterator%)。
  6. 如果 usingIterator 不是 undefined,则
    1. 令 values 为 ? IteratorToList(? GetIteratorFromMethod(source, usingIterator))。
    2. 令 length 为 values 中的元素数量。
    3. 令 targetObj 为 ? TypedArrayCreateFromConstructor(ctor, « 𝔽(length) »)。
    4. 令 k 为 0。
    5. 当 k < length 时,重复执行,
      1. 令 kValue 为 values[k]。
      2. 如果 mapping 是 true,则
        1. 令 mappedValue 为 ? Call(mapper, thisArg, « kValue, 𝔽(k) »)。
      3. 否则,
        1. 令 mappedValue 为 kValue。
      4. 执行 ? TypedArraySetElement(targetObj, 𝔽(k), mappedValue)。
      5. 将 k 设置为 k + 1。
    6. 返回 targetObj。
  7. 注:source 不是可迭代对象,因此假定它已经是类数组对象。
  8. 令 arrayLike 为 ! ToObject(source)。
  9. 令 length 为 ? LengthOfArrayLike(arrayLike)。
  10. 令 targetObj 为 ? TypedArrayCreateFromConstructor(ctor, « 𝔽(length) »)。
  11. 令 k 为 0。
  12. 当 k < length 时,重复执行,
    1. 令 propertyKey 为 ! ToString(𝔽(k))。
    2. 令 kValue 为 ? Get(arrayLike, propertyKey)。
    3. 如果 mapping 是 true,则
      1. 令 mappedValue 为 ? Call(mapper, thisArg, « kValue, 𝔽(k) »)。
    4. 否则,
      1. 令 mappedValue 为 kValue。
    5. 执行 ? TypedArraySetElement(targetObj, 𝔽(k), mappedValue)。
    6. 将 k 设置为 k + 1。
  13. 返回 targetObj。

23.2.2.2 %TypedArray%.of ( ...items )

调用时,此方法执行以下步骤:

  1. 令 length 为 items 中的元素数量。
  2. 令 ctor 为 this value。
  3. 如果 IsConstructor(ctor) 是 false,则抛出 TypeError 异常。
  4. 令 newObj 为 ? TypedArrayCreateFromConstructor(ctor, « 𝔽(length) »)。
  5. 令 k 为 0。
  6. 当 k < length 时,重复执行,
    1. 令 kValue 为 items[k]。
    2. 执行 ? TypedArraySetElement(newObj, 𝔽(k), kValue)。
    3. 将 k 设置为 k + 1。
  7. 返回 newObj。

23.2.2.3 %TypedArray%.prototype

%TypedArray%.prototype 的初始值是 %TypedArray% 原型对象。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

23.2.2.4 get %TypedArray% [ %Symbol.species% ]

%TypedArray%[%Symbol.species%] 是访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数在调用时执行以下步骤:

  1. 返回 this value。

此函数的 "name" 属性值是 "get [Symbol.species]"。

注

%TypedArray.prototype% 方法通常使用其 this value 的构造函数创建派生对象。不过,子类构造函数可以通过重新定义其 %Symbol.species% 属性来覆盖该默认行为。

23.2.3 %TypedArray% 原型对象的属性

%TypedArray% 原型对象:

  • 具有 [[Prototype]] 内部槽,其值是 %Object.prototype%。
  • 是 %TypedArray.prototype%。
  • 是普通对象。
  • 不具有 [[ViewedArrayBuffer]],也不具有任何其他 TypedArray 实例对象特有的内部槽。

23.2.3.1 %TypedArray%.prototype.at ( index )

  1. 令 obj 为 this value。
  2. 令 taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. 令 length 为 TypedArrayLength(taRecord)。
  4. 令 k 为 ? ToAbsoluteIndex(index, length)。
  5. 如果 k < 0 或 k ≥ length,则返回 undefined。
  6. 返回 TypedArrayGetElement(obj, 𝔽(k))。

23.2.3.2 get %TypedArray%.prototype.buffer

%TypedArray%.prototype.buffer 是访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数在调用时执行以下步骤:

  1. 令 obj 为 this value。
  2. 执行 ? RequireInternalSlot(obj, [[TypedArrayName]])。
  3. 断言:obj 具有 [[ViewedArrayBuffer]] 内部槽。
  4. 令 buffer 为 obj.[[ViewedArrayBuffer]]。
  5. 返回 buffer。

23.2.3.3 get %TypedArray%.prototype.byteLength

%TypedArray%.prototype.byteLength 是访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数在调用时执行以下步骤:

  1. 令 obj 为 this value。
  2. 执行 ? RequireInternalSlot(obj, [[TypedArrayName]])。
  3. 断言:obj 具有 [[ViewedArrayBuffer]] 内部槽。
  4. 令 taRecord 为 MakeTypedArrayWithBufferWitnessRecord(obj, seq-cst)。
  5. 如果 IsTypedArrayOutOfBounds(taRecord) 是 true,则返回 +0𝔽。
  6. 令 size 为 TypedArrayByteLength(taRecord)。
  7. 返回 𝔽(size)。

23.2.3.4 get %TypedArray%.prototype.byteOffset

%TypedArray%.prototype.byteOffset 是访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数在调用时执行以下步骤:

  1. 令 obj 为 this value。
  2. 执行 ? RequireInternalSlot(obj, [[TypedArrayName]])。
  3. 断言:obj 具有 [[ViewedArrayBuffer]] 内部槽。
  4. 令 taRecord 为 MakeTypedArrayWithBufferWitnessRecord(obj, seq-cst)。
  5. 如果 IsTypedArrayOutOfBounds(taRecord) 是 true,则返回 +0𝔽。
  6. 令 offset 为 obj.[[ByteOffset]]。
  7. 返回 𝔽(offset)。

23.2.3.5 %TypedArray%.prototype.constructor

%TypedArray%.prototype.constructor 的初始值是 %TypedArray%。

23.2.3.6 %TypedArray%.prototype.copyWithin ( target, start [ , end ] )

此方法参数的解释和使用方式与 23.1.3.4 中定义的 Array.prototype.copyWithin 相同。

调用时,此方法执行以下步骤:

  1. 令 obj 为 this value。
  2. 令 taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. 令 length 为 TypedArrayLength(taRecord)。
  4. 令 targetIndex 为 ? ToClampedIndex(target, length)。
  5. 令 startIndex 为 ? ToClampedIndex(start, length)。
  6. 如果 end 是 undefined,则令 endIndex 为 length;否则令 endIndex 为 ? ToClampedIndex(end, length)。
  7. 令 count 为 min(endIndex - startIndex, length - targetIndex)。
  8. 如果 count > 0,则
    1. 注:复制必须以保留源数据位级编码的方式执行。
    2. 令 buffer 为 obj.[[ViewedArrayBuffer]]。
    3. 将 taRecord 设置为 ? ValidateTypedArrayBounds(obj, seq-cst)。
    4. 将 length 设置为 TypedArrayLength(taRecord)。
    5. 注:上述步骤的副作用可能已经减小了 obj 的大小,在这种情况下,应使用仍然适用的最长前缀继续复制。
    6. 将 count 设置为 min(count, length - startIndex, length - targetIndex)。
    7. 令 elementSize 为 TypedArrayElementSize(obj)。
    8. 令 byteOffset 为 obj.[[ByteOffset]]。
    9. 令 toByteIndex 为 (targetIndex × elementSize) + byteOffset。
    10. 令 fromByteIndex 为 (startIndex × elementSize) + byteOffset。
    11. 令 countBytes 为 count × elementSize。
    12. 如果 fromByteIndex < toByteIndex 且 toByteIndex < fromByteIndex + countBytes,则
      1. 令 direction 为 -1。
      2. 将 fromByteIndex 设置为 fromByteIndex + countBytes - 1。
      3. 将 toByteIndex 设置为 toByteIndex + countBytes - 1。
    13. 否则,
      1. 令 direction 为 1。
    14. 当 countBytes > 0 时,重复执行,
      1. 断言:fromByteIndex ≥ 0 且 toByteIndex ≥ 0。
      2. 令 value 为 GetValueFromBuffer(buffer, fromByteIndex, uint8, true, unordered)。
      3. 执行 SetValueInBuffer(buffer, toByteIndex, uint8, value, true, unordered)。
      4. 将 fromByteIndex 设置为 fromByteIndex + direction。
      5. 将 toByteIndex 设置为 toByteIndex + direction。
      6. 将 countBytes 设置为 countBytes - 1。
  9. 返回 obj。

23.2.3.7 %TypedArray%.prototype.entries ( )

调用时,此方法执行以下步骤:

  1. 令 obj 为 this value。
  2. 执行 ? ValidateTypedArray(obj, seq-cst)。
  3. 返回 CreateArrayIterator(obj, key+value)。

23.2.3.8 %TypedArray%.prototype.every ( callback [ , thisArg ] )

此方法参数的解释和使用方式与 23.1.3.6 中定义的 Array.prototype.every 相同。

调用时,此方法执行以下步骤:

  1. 令 obj 为 this value。
  2. 令 taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. 令 length 为 TypedArrayLength(taRecord)。
  4. 如果 IsCallable(callback) 是 false,则抛出 TypeError 异常。
  5. 令 k 为 0。
  6. 当 k < length 时,重复执行,
    1. 令 kValue 为 TypedArrayGetElement(obj, 𝔽(k))。
    2. 令 testResult 为 ToBoolean(? Call(callback, thisArg, « kValue, 𝔽(k), obj »))。
    3. 如果 testResult 是 false,则返回 false。
    4. 将 k 设置为 k + 1。
  7. 返回 true。

此方法不是通用方法。this value 必须是具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.9 %TypedArray%.prototype.fill ( value [ , start [ , end ] ] )

此方法参数的解释和使用方式与 23.1.3.7 中定义的 Array.prototype.fill 相同。

调用时,此方法执行以下步骤:

  1. 令 obj 为 this value。
  2. 令 taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. 令 length 为 TypedArrayLength(taRecord)。
  4. 如果 obj.[[ContentType]] 是 bigint,则将 value 设置为 ? ToBigInt(value)。
  5. 否则,将 value 设置为 ? ToNumber(value)。
  6. 令 startIndex 为 ? ToClampedIndex(start, length)。
  7. 如果 end 是 undefined,则令 endIndex 为 length;否则令 endIndex 为 ? ToClampedIndex(end, length)。
  8. 将 taRecord 设置为 ? ValidateTypedArrayBounds(obj, seq-cst)。
  9. 将 length 设置为 TypedArrayLength(taRecord)。
  10. 将 endIndex 设置为 min(endIndex, length)。
  11. 令 k 为 startIndex。
  12. 当 k < endIndex 时,重复执行,
    1. 执行 ! TypedArraySetElement(obj, 𝔽(k), value)。
    2. 将 k 设置为 k + 1。
  13. 返回 obj。

23.2.3.10 %TypedArray%.prototype.filter ( callback [ , thisArg ] )

此方法参数的解释和使用方式与 23.1.3.8 中定义的 Array.prototype.filter 相同。

调用时,此方法执行以下步骤:

  1. 令 obj 为 this value。
  2. 令 taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. 令 length 为 TypedArrayLength(taRecord)。
  4. 如果 IsCallable(callback) 是 false,则抛出 TypeError 异常。
  5. 令 kept 为新的空 List。
  6. 令 captured 为 0。
  7. 令 k 为 0。
  8. 当 k < length 时,重复执行,
    1. 令 kValue 为 TypedArrayGetElement(obj, 𝔽(k))。
    2. 令 selected 为 ToBoolean(? Call(callback, thisArg, « kValue, 𝔽(k), obj »))。
    3. 如果 selected 是 true,则
      1. 将 kValue 追加到 kept。
      2. 将 captured 设置为 captured + 1。
    4. 将 k 设置为 k + 1。
  9. 令 result 为 ? TypedArraySpeciesCreate(obj, « 𝔽(captured) »)。
  10. 令 n 为 0。
  11. 对 kept 的每个元素 element,执行
    1. 执行 ! TypedArraySetElement(result, 𝔽(n), element)。
    2. 将 n 设置为 n + 1。
  12. 返回 result。

此方法不是通用方法。this value 必须是具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.11 %TypedArray%.prototype.find ( predicate [ , thisArg ] )

此方法参数的解释和使用方式与 23.1.3.9 中定义的 Array.prototype.find 相同。

调用时,此方法执行以下步骤:

  1. 令 obj 为 this value。
  2. 令 taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. 令 length 为 TypedArrayLength(taRecord)。
  4. 令 findRecord 为 ? FindViaPredicate(obj, length, ascending, predicate, thisArg)。
  5. 返回 findRecord.[[Value]]。

此方法不是通用方法。this value 必须是具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.12 %TypedArray%.prototype.findIndex ( predicate [ , thisArg ] )

此方法参数的解释和使用方式与 23.1.3.10 中定义的 Array.prototype.findIndex 相同。

调用时,此方法执行以下步骤:

  1. 令 obj 为 this value。
  2. 令 taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. 令 length 为 TypedArrayLength(taRecord)。
  4. 令 findRecord 为 ? FindViaPredicate(obj, length, ascending, predicate, thisArg)。
  5. 返回 findRecord.[[Index]]。

此方法不是通用方法。this value 必须是具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.13 %TypedArray%.prototype.findLast ( predicate [ , thisArg ] )

此方法参数的解释和使用方式与 23.1.3.11 中定义的 Array.prototype.findLast 相同。

调用时,此方法执行以下步骤:

  1. 令 obj 为 this value。
  2. 令 taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. 令 length 为 TypedArrayLength(taRecord)。
  4. 令 findRecord 为 ? FindViaPredicate(obj, length, descending, predicate, thisArg)。
  5. 返回 findRecord.[[Value]]。

此方法不是通用方法。this value 必须是具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.14 %TypedArray%.prototype.findLastIndex ( predicate [ , thisArg ] )

此方法参数的解释和使用方式与 23.1.3.12 中定义的 Array.prototype.findLastIndex 相同。

调用时,此方法执行以下步骤:

  1. 令 obj 为 this value。
  2. 令 taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. 令 length 为 TypedArrayLength(taRecord)。
  4. 令 findRecord 为 ? FindViaPredicate(obj, length, descending, predicate, thisArg)。
  5. 返回 findRecord.[[Index]]。

此方法不是通用方法。this value 必须是具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.15 %TypedArray%.prototype.forEach ( callback [ , thisArg ] )

此方法参数的解释和使用方式与 23.1.3.15 中定义的 Array.prototype.forEach 相同。

调用时,此方法执行以下步骤:

  1. 令 obj 为 this value。
  2. 令 taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. 令 length 为 TypedArrayLength(taRecord)。
  4. 如果 IsCallable(callback) 是 false,则抛出 TypeError 异常。
  5. 令 k 为 0。
  6. 当 k < length 时,重复执行,
    1. 令 kValue 为 TypedArrayGetElement(obj, 𝔽(k))。
    2. 执行 ? Call(callback, thisArg, « kValue, 𝔽(k), obj »)。
    3. 将 k 设置为 k + 1。
  7. 返回 undefined。

此方法不是通用方法。this value 必须是具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.16 %TypedArray%.prototype.includes ( searchElement [ , fromIndex ] )

此方法参数的解释和使用方式与 23.1.3.16 中定义的 Array.prototype.includes 相同。

调用时,此方法执行以下步骤:

  1. 令 obj 为 this value。
  2. 令 taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. 令 length 为 TypedArrayLength(taRecord)。
  4. 如果 length = 0,则返回 false。
  5. 令 k 为 ? ToClampedIndex(fromIndex, length)。
  6. 当 k < length 时,重复执行,
    1. 令 elementK 为 TypedArrayGetElement(obj, 𝔽(k))。
    2. 如果 SameValueZero(searchElement, elementK) 是 true,则返回 true。
    3. 将 k 设置为 k + 1。
  7. 返回 false。

此方法不是通用方法。this value 必须是具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.17 %TypedArray%.prototype.indexOf ( searchElement [ , fromIndex ] )

此方法参数的解释和使用方式与 23.1.3.17 中定义的 Array.prototype.indexOf 相同。

调用时,此方法执行以下步骤:

  1. 令 obj 为 this value。
  2. 令 taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. 令 length 为 TypedArrayLength(taRecord)。
  4. 如果 length = 0,则返回 -1𝔽。
  5. 令 k 为 ? ToClampedIndex(fromIndex, length)。
  6. 当 k < length 时,重复执行,
    1. 令 propertyKey 为 ! ToString(𝔽(k))。
    2. 令 kPresent 为 ! HasProperty(obj, propertyKey)。
    3. 如果 kPresent 是 true,则
      1. 令 elementK 为 TypedArrayGetElement(obj, 𝔽(k))。
      2. 如果 IsStrictlyEqual(searchElement, elementK) 是 true,则返回 𝔽(k)。
    4. 将 k 设置为 k + 1。
  7. 返回 -1𝔽。

此方法不是通用方法。this value 必须是具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.18 %TypedArray%.prototype.join ( separator )

此方法参数的解释和使用方式与 23.1.3.18 中定义的 Array.prototype.join 相同。

调用时,此方法执行以下步骤:

  1. 令 obj 为 this value。
  2. 令 taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. 令 length 为 TypedArrayLength(taRecord)。
  4. 如果 separator 是 undefined,则令 separatorString 为 ","。
  5. 否则,令 separatorString 为 ? ToString(separator)。
  6. 令 result 为空 String。
  7. 令 k 为 0。
  8. 当 k < length 时,重复执行,
    1. 如果 k > 0,则将 result 设置为 result 和 separatorString 的字符串连接。
    2. 令 element 为 TypedArrayGetElement(obj, 𝔽(k))。
    3. 如果 element 不是 undefined,则
      1. 令 elementString 为 ! ToString(element)。
      2. 将 result 设置为 result 和 elementString 的字符串连接。
    4. 将 k 设置为 k + 1。
  9. 返回 result。

此方法不是通用方法。this value 必须是具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.19 %TypedArray%.prototype.keys ( )

调用时,此方法执行以下步骤:

  1. 令 obj 为 this value。
  2. 执行 ? ValidateTypedArray(obj, seq-cst)。
  3. 返回 CreateArrayIterator(obj, key)。

23.2.3.20 %TypedArray%.prototype.lastIndexOf ( searchElement [ , fromIndex ] )

此方法参数的解释和使用方式与 23.1.3.20 中定义的 Array.prototype.lastIndexOf 相同。

调用时,此方法执行以下步骤:

  1. 令 obj 为 this value。
  2. 令 taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. 令 length 为 TypedArrayLength(taRecord)。
  4. 如果 length = 0,则返回 -1𝔽。
  5. 如果不存在 fromIndex,则令 k 为 length - 1;否则令 k 为 min(? ToAbsoluteIndex(fromIndex, length), length - 1)。
  6. 当 k ≥ 0 时,重复执行,
    1. 令 propertyKey 为 ! ToString(𝔽(k))。
    2. 令 kPresent 为 ! HasProperty(obj, propertyKey)。
    3. 如果 kPresent 是 true,则
      1. 令 elementK 为 TypedArrayGetElement(obj, 𝔽(k))。
      2. 如果 IsStrictlyEqual(searchElement, elementK) 是 true,则返回 𝔽(k)。
    4. 将 k 设置为 k - 1。
  7. 返回 -1𝔽。

此方法不是通用方法。this value 必须是具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.21 get %TypedArray%.prototype.length

%TypedArray%.prototype.length 是访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数在调用时执行以下步骤:

  1. 令 obj 为 this value。
  2. 执行 ? RequireInternalSlot(obj, [[TypedArrayName]])。
  3. 断言:obj 具有 [[ViewedArrayBuffer]] 和 [[ArrayLength]] 内部槽。
  4. 令 taRecord 为 MakeTypedArrayWithBufferWitnessRecord(obj, seq-cst)。
  5. 如果 IsTypedArrayOutOfBounds(taRecord) 是 true,则返回 +0𝔽。
  6. 令 length 为 TypedArrayLength(taRecord)。
  7. 返回 𝔽(length)。

此函数不是通用函数。this value 必须是具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.22 %TypedArray%.prototype.map ( callback [ , thisArg ] )

此方法参数的解释和使用方式与 23.1.3.21 中定义的 Array.prototype.map 相同。

调用时,此方法执行以下步骤:

  1. 令 obj 为 this value。
  2. 令 taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. 令 length 为 TypedArrayLength(taRecord)。
  4. 如果 IsCallable(callback) 是 false,则抛出 TypeError 异常。
  5. 令 result 为 ? TypedArraySpeciesCreate(obj, « 𝔽(length) »)。
  6. 令 k 为 0。
  7. 当 k < length 时,重复执行,
    1. 令 kValue 为 TypedArrayGetElement(obj, 𝔽(k))。
    2. 令 mappedValue 为 ? Call(callback, thisArg, « kValue, 𝔽(k), obj »)。
    3. 执行 ? TypedArraySetElement(result, 𝔽(k), mappedValue)。
    4. 将 k 设置为 k + 1。
  8. 返回 result。

此方法不是通用方法。this value 必须是具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.23 %TypedArray%.prototype.reduce ( callback [ , initialValue ] )

此方法参数的解释和使用方式与 23.1.3.24 中定义的 Array.prototype.reduce 相同。

调用时,此方法执行以下步骤:

  1. 令 obj 为 this value。
  2. 令 taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. 令 length 为 TypedArrayLength(taRecord)。
  4. 如果 IsCallable(callback) 是 false,则抛出 TypeError 异常。
  5. 如果 length = 0 且不存在 initialValue,则抛出 TypeError 异常。
  6. 令 k 为 0。
  7. 令 accumulator 为 undefined。
  8. 如果存在 initialValue,则
    1. 将 accumulator 设置为 initialValue。
  9. 否则,
    1. 将 accumulator 设置为 TypedArrayGetElement(obj, 𝔽(k))。
    2. 将 k 设置为 k + 1。
  10. 当 k < length 时,重复执行,
    1. 令 kValue 为 TypedArrayGetElement(obj, 𝔽(k))。
    2. 将 accumulator 设置为 ? Call(callback, undefined, « accumulator, kValue, 𝔽(k), obj »)。
    3. 将 k 设置为 k + 1。
  11. 返回 accumulator。

此方法不是通用方法。this value 必须是具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.24 %TypedArray%.prototype.reduceRight ( callback [ , initialValue ] )

此方法参数的解释和使用方式与 23.1.3.25 中定义的 Array.prototype.reduceRight 相同。

调用时,此方法执行以下步骤:

  1. 令 obj 为 this value。
  2. 令 taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. 令 length 为 TypedArrayLength(taRecord)。
  4. 如果 IsCallable(callback) 是 false,则抛出 TypeError 异常。
  5. 如果 length = 0 且不存在 initialValue,则抛出 TypeError 异常。
  6. 令 k 为 length - 1。
  7. 令 accumulator 为 undefined。
  8. 如果存在 initialValue,则
    1. 将 accumulator 设置为 initialValue。
  9. 否则,
    1. 将 accumulator 设置为 TypedArrayGetElement(obj, 𝔽(k))。
    2. 将 k 设置为 k - 1。
  10. 当 k ≥ 0 时,重复执行,
    1. 令 kValue 为 TypedArrayGetElement(obj, 𝔽(k))。
    2. 将 accumulator 设置为 ? Call(callback, undefined, « accumulator, kValue, 𝔽(k), obj »)。
    3. 将 k 设置为 k - 1。
  11. 返回 accumulator。

此方法不是通用方法。this value 必须是具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.25 %TypedArray%.prototype.reverse ( )

此方法参数的解释和使用方式与 23.1.3.26 中定义的 Array.prototype.reverse 相同。

调用时,此方法执行以下步骤:

  1. 令 obj 为 this value。
  2. 令 taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. 令 length 为 TypedArrayLength(taRecord)。
  4. 令 middle 为 floor(length / 2)。
  5. 令 lower 为 0。
  6. 当 lower ≠ middle 时,重复执行,
    1. 令 upper 为 length - lower - 1。
    2. 令 lowerValue 为 TypedArrayGetElement(obj, 𝔽(lower))。
    3. 令 upperValue 为 TypedArrayGetElement(obj, 𝔽(upper))。
    4. 执行 ! TypedArraySetElement(obj, 𝔽(lower), upperValue)。
    5. 执行 ! TypedArraySetElement(obj, 𝔽(upper), lowerValue)。
    6. 将 lower 设置为 lower + 1。
  7. 返回 obj。

此方法不是通用方法。this value 必须是具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.26 %TypedArray%.prototype.set ( source [ , offset ] )

此方法从 source 读取值,并在此 TypedArray 中设置多个值。具体细节取决于 source 的类型。可选的 offset 值表示此 TypedArray 中写入值的第一个元素索引。如果省略,则假定为 0。

调用时,它执行以下步骤:

  1. 令 target 为 this value。
  2. 执行 ? RequireInternalSlot(target, [[TypedArrayName]])。
  3. 断言:target 具有 [[ViewedArrayBuffer]] 内部槽。
  4. 令 targetOffset 为 ? ToIntegerOrInfinity(offset)。
  5. 如果 targetOffset < 0,则抛出 RangeError 异常。
  6. 如果 source 是具有 [[TypedArrayName]] 内部槽的 Object,则
    1. 执行 ? SetTypedArrayFromTypedArray(target, targetOffset, source)。
  7. 否则,
    1. 执行 ? SetTypedArrayFromArrayLike(target, targetOffset, source)。
  8. 返回 undefined。

此方法不是通用方法。this value 必须是具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.26.1 SetTypedArrayFromArrayLike ( target, targetOffset, source )

抽象操作 SetTypedArrayFromArrayLike,接收参数 target (TypedArray)、targetOffset ((非负整数 或 +∞)) 和 source (an ECMAScript language value, but not a TypedArray);返回值:(正常完成 (值:unused) 或 抛出完成)。 它从 source 读取值,从索引 targetOffset 开始在 target 中设置多个值。 调用时执行以下步骤:

  1. 令 targetRecord 为 ? ValidateTypedArrayBounds(target, seq-cst)。
  2. 令 targetLength 为 TypedArrayLength(targetRecord)。
  3. 将 source 设置为 ? ToObject(source)。
  4. 令 sourceLength 为 ? LengthOfArrayLike(source)。
  5. 如果 targetOffset = +∞,则抛出 RangeError 异常。
  6. 如果 sourceLength + targetOffset > targetLength,则抛出 RangeError 异常。
  7. 令 k 为 0。
  8. 当 k < sourceLength 时,重复执行,
    1. 令 propertyKey 为 ! ToString(𝔽(k))。
    2. 令 value 为 ? Get(source, propertyKey)。
    3. 令 targetIndex 为 𝔽(targetOffset + k)。
    4. 执行 ? TypedArraySetElement(target, targetIndex, value)。
    5. 将 k 设置为 k + 1。
  9. 返回 unused。

23.2.3.26.2 SetTypedArrayFromTypedArray ( target, targetOffset, source )

抽象操作 SetTypedArrayFromTypedArray,接收参数 target (TypedArray)、targetOffset ((非负整数 或 +∞)) 和 source (TypedArray);返回值:(正常完成 (值:unused) 或 抛出完成)。 它从 source 读取值,从索引 targetOffset 开始在 target 中设置多个值。 调用时执行以下步骤:

  1. 令 targetBuffer 为 target.[[ViewedArrayBuffer]]。
  2. 令 targetRecord 为 ? ValidateTypedArrayBounds(target, seq-cst)。
  3. 令 targetLength 为 TypedArrayLength(targetRecord)。
  4. 令 sourceBuffer 为 source.[[ViewedArrayBuffer]]。
  5. 令 sourceRecord 为 ? ValidateTypedArrayBounds(source, seq-cst)。
  6. 令 sourceLength 为 TypedArrayLength(sourceRecord)。
  7. 令 targetType 为 TypedArrayElementType(target)。
  8. 令 targetElementSize 为 TypedArrayElementSize(target)。
  9. 令 targetByteOffset 为 target.[[ByteOffset]]。
  10. 令 sourceType 为 TypedArrayElementType(source)。
  11. 令 sourceElementSize 为 TypedArrayElementSize(source)。
  12. 令 sourceByteOffset 为 source.[[ByteOffset]]。
  13. 如果 targetOffset = +∞,则抛出 RangeError 异常。
  14. 如果 sourceLength + targetOffset > targetLength,则抛出 RangeError 异常。
  15. 如果 target.[[ContentType]] 不是 source.[[ContentType]],则抛出 TypeError 异常。
  16. 如果 IsSharedArrayBuffer(sourceBuffer) 是 true、IsSharedArrayBuffer(targetBuffer) 是 true,并且 sourceBuffer.[[ArrayBufferData]] 是 targetBuffer.[[ArrayBufferData]],则令 sameSharedArrayBuffer 为 true;否则令 sameSharedArrayBuffer 为 false。
  17. 如果 SameValue(sourceBuffer, targetBuffer) 是 true 或 sameSharedArrayBuffer 是 true,则
    1. 令 sourceByteLength 为 TypedArrayByteLength(sourceRecord)。
    2. 将 sourceBuffer 设置为 ? CloneArrayBuffer(sourceBuffer, sourceByteOffset, sourceByteLength)。
    3. 令 sourceByteIndex 为 0。
  18. 否则,
    1. 令 sourceByteIndex 为 sourceByteOffset。
  19. 令 targetByteIndex 为 (targetOffset × targetElementSize) + targetByteOffset。
  20. 令 limit 为 targetByteIndex + (targetElementSize × sourceLength)。
  21. 如果 sourceType 是 targetType,则
    1. 注:传输必须以保留源数据位级编码的方式执行。
    2. 当 targetByteIndex < limit 时,重复执行,
      1. 令 value 为 GetValueFromBuffer(sourceBuffer, sourceByteIndex, uint8, true, unordered)。
      2. 执行 SetValueInBuffer(targetBuffer, targetByteIndex, uint8, value, true, unordered)。
      3. 将 sourceByteIndex 设置为 sourceByteIndex + 1。
      4. 将 targetByteIndex 设置为 targetByteIndex + 1。
  22. 否则,
    1. 当 targetByteIndex < limit 时,重复执行,
      1. 令 value 为 GetValueFromBuffer(sourceBuffer, sourceByteIndex, sourceType, true, unordered)。
      2. 执行 SetValueInBuffer(targetBuffer, targetByteIndex, targetType, value, true, unordered)。
      3. 将 sourceByteIndex 设置为 sourceByteIndex + sourceElementSize。
      4. 将 targetByteIndex 设置为 targetByteIndex + targetElementSize。
  23. 返回 unused。

23.2.3.27 %TypedArray%.prototype.slice ( start, end )

此方法参数的解释和使用方式与 23.1.3.28 中定义的 Array.prototype.slice 相同。

调用时,此方法执行以下步骤:

  1. 令 obj 为 this value。
  2. 令 taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. 令 sourceArrayLength 为 TypedArrayLength(taRecord)。
  4. 令 startIndex 为 ? ToClampedIndex(start, sourceArrayLength)。
  5. 如果 end 是 undefined,则令 endIndex 为 sourceArrayLength;否则令 endIndex 为 ? ToClampedIndex(end, sourceArrayLength)。
  6. 令 countBytes 为 max(endIndex - startIndex, 0)。
  7. 令 resultArray 为 ? TypedArraySpeciesCreate(obj, « 𝔽(countBytes) »)。
  8. 如果 countBytes > 0,则
    1. 将 taRecord 设置为 ? ValidateTypedArrayBounds(obj, seq-cst)。
    2. 将 endIndex 设置为 min(endIndex, TypedArrayLength(taRecord))。
    3. 将 countBytes 设置为 max(endIndex - startIndex, 0)。
    4. 令 sourceType 为 TypedArrayElementType(obj)。
    5. 令 targetType 为 TypedArrayElementType(resultArray)。
    6. 如果 sourceType 是 targetType,则
      1. 注:传输必须以保留源数据位级编码的方式执行。
      2. 令 sourceBuffer 为 obj.[[ViewedArrayBuffer]]。
      3. 令 targetBuffer 为 resultArray.[[ViewedArrayBuffer]]。
      4. 令 elementSize 为 TypedArrayElementSize(obj)。
      5. 令 sourceByteOffset 为 obj.[[ByteOffset]]。
      6. 令 sourceByteIndex 为 (startIndex × elementSize) + sourceByteOffset。
      7. 令 targetByteIndex 为 resultArray.[[ByteOffset]]。
      8. 令 endByteIndex 为 targetByteIndex + (countBytes × elementSize)。
      9. 当 targetByteIndex < endByteIndex 时,重复执行,
        1. 令 value 为 GetValueFromBuffer(sourceBuffer, sourceByteIndex, uint8, true, unordered)。
        2. 执行 SetValueInBuffer(targetBuffer, targetByteIndex, uint8, value, true, unordered)。
        3. 将 sourceByteIndex 设置为 sourceByteIndex + 1。
        4. 将 targetByteIndex 设置为 targetByteIndex + 1。
    7. 否则,
      1. 令 n 为 0。
      2. 令 k 为 startIndex。
      3. 当 k < endIndex 时,重复执行,
        1. 令 kValue 为 TypedArrayGetElement(obj, 𝔽(k))。
        2. 执行 ! TypedArraySetElement(resultArray, 𝔽(n), kValue)。
        3. 将 k 设置为 k + 1。
        4. 将 n 设置为 n + 1。
  9. 返回 resultArray。

此方法不是通用方法。this value 必须是具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.28 %TypedArray%.prototype.some ( callback [ , thisArg ] )

此方法参数的解释和使用方式与 23.1.3.29 中定义的 Array.prototype.some 相同。

调用时,此方法执行以下步骤:

  1. 令 obj 为 this value。
  2. 令 taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. 令 length 为 TypedArrayLength(taRecord)。
  4. 如果 IsCallable(callback) 是 false,则抛出 TypeError 异常。
  5. 令 k 为 0。
  6. 当 k < length 时,重复执行,
    1. 令 kValue 为 TypedArrayGetElement(obj, 𝔽(k))。
    2. 令 testResult 为 ToBoolean(? Call(callback, thisArg, « kValue, 𝔽(k), obj »))。
    3. 如果 testResult 是 true,则返回 true。
    4. 将 k 设置为 k + 1。
  7. 返回 false。

此方法不是通用方法。this value 必须是具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.29 %TypedArray%.prototype.sort ( comparator )

这是一个独立的方法,除下述内容外,它实现与 23.1.3.30 中定义的 Array.prototype.sort 相同的要求。实现可以利用 this value 是具有固定长度且整数索引属性不稀疏的对象这一事实来优化此方法。

此方法不是通用方法。this value 必须是具有 [[TypedArrayName]] 内部槽的对象。

调用时,它执行以下步骤:

  1. 如果 comparator 不是 undefined 且 IsCallable(comparator) 是 false,则抛出 TypeError 异常。
  2. 令 obj 为 this value。
  3. 令 taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  4. 令 length 为 TypedArrayLength(taRecord)。
  5. 注:以下闭包执行数值比较,而不是 23.1.3.30 中使用的字符串比较。
  6. 令 sortCompare 为参数为 (x, y) 的新 Abstract Closure,它捕获 comparator,并在被调用时执行以下步骤:
    1. 返回 ? CompareTypedArrayElements(x, y, comparator)。
  7. 令 sortedList 为 ? SortIndexedProperties(obj, length, sortCompare, read-through-holes)。
  8. 令 j 为 0。
  9. 当 j < length 时,重复执行,
    1. 执行 ! TypedArraySetElement(obj, 𝔽(j), sortedList[j])。
    2. 将 j 设置为 j + 1。
  10. 返回 obj。
注

由于 NaN 始终比较为大于任何其他值(参见 CompareTypedArrayElements),因此在未提供 comparator 时,NaN 属性值总是排序到结果末尾。

23.2.3.30 %TypedArray%.prototype.subarray ( start, end )

此方法返回新的 TypedArray,其元素类型与此 TypedArray 的元素类型相同,其 ArrayBuffer 是此 TypedArray 的 ArrayBuffer,并引用从 start(包含)到 end(不包含)区间内的元素。如果 start 或 end 为负,则它表示从数组末尾而不是开头起算的索引。

调用时,它执行以下步骤:

  1. 令 obj 为 this value。
  2. 执行 ? RequireInternalSlot(obj, [[TypedArrayName]])。
  3. 断言:obj 具有 [[ViewedArrayBuffer]] 内部槽。
  4. 令 buffer 为 obj.[[ViewedArrayBuffer]]。
  5. 令 sourceRecord 为 MakeTypedArrayWithBufferWitnessRecord(obj, seq-cst)。
  6. 如果 IsTypedArrayOutOfBounds(sourceRecord) 是 true,则
    1. 令 sourceLength 为 0。
  7. 否则,
    1. 令 sourceLength 为 TypedArrayLength(sourceRecord)。
  8. 令 startIndex 为 ? ToClampedIndex(start, sourceLength)。
  9. 令 elementSize 为 TypedArrayElementSize(obj)。
  10. 令 sourceByteOffset 为 obj.[[ByteOffset]]。
  11. 令 beginByteOffset 为 sourceByteOffset + (startIndex × elementSize)。
  12. 如果 obj.[[ArrayLength]] 是 auto 且 end 是 undefined,则
    1. 返回 ? TypedArraySpeciesCreate(obj, « buffer, 𝔽(beginByteOffset) »)。
  13. 如果 end 是 undefined,则令 endIndex 为 sourceLength;否则令 endIndex 为 ? ToClampedIndex(end, sourceLength)。
  14. 令 newLength 为 max(endIndex - startIndex, 0)。
  15. 返回 ? TypedArraySpeciesCreate(obj, « buffer, 𝔽(beginByteOffset), 𝔽(newLength) »)。

此方法不是通用方法。this value 必须是具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.31 %TypedArray%.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] )

这是一个独立的方法,它实现与 23.1.3.32 中定义的 Array.prototype.toLocaleString 相同的算法,但使用 TypedArrayLength 替代对 "length" 执行 [[Get]]。当底层缓冲区不可调整大小时,可以利用 this value 具有固定长度且其整数索引属性不稀疏这一事实优化该算法的实现。不过,此类优化不得对算法规定的行为引入任何可观察的变化。

此方法不是通用方法。在求值该算法之前,会以 this value 和 seq-cst 作为参数调用 ValidateTypedArray。如果其结果是突然完成,则会抛出该异常,而不是求值该算法。

注

如果 ECMAScript 实现包含 ECMA-402 国际化 API,则此方法基于 ECMA-402 中的 Array.prototype.toLocaleString 算法。

23.2.3.32 %TypedArray%.prototype.toReversed ( )

调用时,此方法执行以下步骤:

  1. 令 obj 为 this value。
  2. 令 taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. 令 length 为 TypedArrayLength(taRecord)。
  4. 令 resultArray 为 ? TypedArrayCreateSameType(obj, length)。
  5. 令 k 为 0。
  6. 当 k < length 时,重复执行,
    1. 令 from 为 length - k - 1。
    2. 令 fromValue 为 TypedArrayGetElement(obj, 𝔽(from))。
    3. 执行 ! TypedArraySetElement(resultArray, 𝔽(k), fromValue)。
    4. 将 k 设置为 k + 1。
  7. 返回 resultArray。

23.2.3.33 %TypedArray%.prototype.toSorted ( comparator )

调用时,此方法执行以下步骤:

  1. 如果 comparator 不是 undefined 且 IsCallable(comparator) 是 false,则抛出 TypeError 异常。
  2. 令 obj 为 this value。
  3. 令 taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  4. 令 length 为 TypedArrayLength(taRecord)。
  5. 令 resultArray 为 ? TypedArrayCreateSameType(obj, length)。
  6. 注:以下闭包执行数值比较,而不是 23.1.3.34 中使用的字符串比较。
  7. 令 sortCompare 为参数为 (x, y) 的新 Abstract Closure,它捕获 comparator,并在被调用时执行以下步骤:
    1. 返回 ? CompareTypedArrayElements(x, y, comparator)。
  8. 令 sortedList 为 ? SortIndexedProperties(obj, length, sortCompare, read-through-holes)。
  9. 令 j 为 0。
  10. 当 j < length 时,重复执行,
    1. 执行 ! TypedArraySetElement(resultArray, 𝔽(j), sortedList[j])。
    2. 将 j 设置为 j + 1。
  11. 返回 resultArray。

23.2.3.34 %TypedArray%.prototype.toString ( )

"toString" 属性的初始值是 23.1.3.36 中定义的 %Array.prototype.toString%。

23.2.3.35 %TypedArray%.prototype.values ( )

调用时,此方法执行以下步骤:

  1. 令 obj 为 this value。
  2. 执行 ? ValidateTypedArray(obj, seq-cst)。
  3. 返回 CreateArrayIterator(obj, value)。

23.2.3.36 %TypedArray%.prototype.with ( index, value )

调用时,此方法执行以下步骤:

  1. 令 obj 为 this value。
  2. 令 taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. 令 length 为 TypedArrayLength(taRecord)。
  4. 令 actualIndex 为 ? ToAbsoluteIndex(index, length)。
  5. 如果 obj.[[ContentType]] 是 bigint,则令 numericValue 为 ? ToBigInt(value)。
  6. 否则,令 numericValue 为 ? ToNumber(value)。
  7. 如果 IsValidIntegerIndex(obj, 𝔽(actualIndex)) 是 false,则抛出 RangeError 异常。
  8. 令 resultArray 为 ? TypedArrayCreateSameType(obj, length)。
  9. 令 k 为 0。
  10. 当 k < length 时,重复执行,
    1. 如果 k = actualIndex,则令 fromValue 为 numericValue。
    2. 否则,令 fromValue 为 TypedArrayGetElement(obj, 𝔽(k))。
    3. 执行 ! TypedArraySetElement(resultArray, 𝔽(k), fromValue)。
    4. 将 k 设置为 k + 1。
  11. 返回 resultArray。

23.2.3.37 %TypedArray%.prototype [ %Symbol.iterator% ] ( )

%Symbol.iterator% 属性的初始值是 23.2.3.35 中定义的 %TypedArray.prototype.values%。

23.2.3.38 get %TypedArray%.prototype [ %Symbol.toStringTag% ]

%TypedArray%.prototype[%Symbol.toStringTag%] 是访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数在调用时执行以下步骤:

  1. 令 obj 为 this value。
  2. 如果 obj 不是 Object,则返回 undefined。
  3. 如果 obj 不具有 [[TypedArrayName]] 内部槽,则返回 undefined。
  4. 令 name 为 obj.[[TypedArrayName]]。
  5. 断言:name 是 String。
  6. 返回 name。

此属性具有特性 { [[Enumerable]]: false, [[Configurable]]: true }。

此函数的 "name" 属性的初始值是 "get [Symbol.toStringTag]"。

23.2.4 TypedArray 对象的抽象操作

23.2.4.1 TypedArrayCreateFromConstructor ( ctor, argList )

抽象操作 TypedArrayCreateFromConstructor,接收参数 ctor (构造函数) 和 argList (列表 (元素:ECMAScript 语言值));返回值:(正常完成 (值:TypedArray) 或 抛出完成)。 它用于规定使用构造函数创建新的 TypedArray。 调用时执行以下步骤:

  1. 令 ta 为 ? Construct(ctor, argList)。
  2. 令 taRecord 为 ? ValidateTypedArray(ta, seq-cst)。
  3. 断言:ta 具有 TypedArray 实例的属性 中提到的所有内部槽。
  4. 如果 argList 中的元素数量为 1 且 argList[0] 是 Number,则
    1. 如果 IsTypedArrayOutOfBounds(taRecord) 是 true,则抛出 TypeError 异常。
    2. 令 length 为 TypedArrayLength(taRecord)。
    3. 如果 length < ℝ(argList[0]),则抛出 TypeError 异常。
  5. 返回 ta。

23.2.4.2 TypedArrayCreateSameType ( exemplar, length )

抽象操作 TypedArrayCreateSameType,接收参数 exemplar (TypedArray) 和 length (非负整数);返回值:(正常完成 (值:TypedArray) 或 抛出完成)。 它用于规定使用从 exemplar 派生的构造函数创建新的 TypedArray。与可以通过使用 %Symbol.species% 构造自定义 TypedArray 子类的 TypedArraySpeciesCreate 不同,此操作始终使用某个内置 TypedArray 构造函数。 调用时执行以下步骤:

  1. 令 ctor 为 表 71 中与构造函数名称 exemplar.[[TypedArrayName]] 关联的内在对象。
  2. 令 result 为 ? TypedArrayCreateFromConstructor(ctor, « 𝔽(length) »)。
  3. 断言:result 具有 [[TypedArrayName]] 和 [[ContentType]] 内部槽。
  4. 断言:result.[[ContentType]] 是 exemplar.[[ContentType]]。
  5. 返回 result。

23.2.4.3 TypedArraySpeciesCreate ( exemplar, argList )

抽象操作 TypedArraySpeciesCreate,接收参数 exemplar (TypedArray) 和 argList (列表 (元素:ECMAScript 语言值));返回值:(正常完成 (值:TypedArray) 或 抛出完成)。 它用于规定使用从 exemplar 派生的构造函数创建新的 TypedArray。与可以通过使用 %Symbol.species% 创建非 Array 对象的 ArraySpeciesCreate 不同,此操作强制要求构造函数创建实际的 TypedArray。 调用时执行以下步骤:

  1. 令 defaultCtor 为 表 71 中与构造函数名称 exemplar.[[TypedArrayName]] 关联的内在对象。
  2. 令 ctor 为 ? SpeciesConstructor(exemplar, defaultCtor)。
  3. 令 result 为 ? TypedArrayCreateFromConstructor(ctor, argList)。
  4. 如果 result.[[ContentType]] 不是 exemplar.[[ContentType]],则抛出 TypeError 异常。
  5. 返回 result。

23.2.4.4 ValidateTypedArray ( obj, order )

抽象操作 ValidateTypedArray,接收参数 obj (ECMAScript 语言值) 和 order ((seq-cst 或 unordered));返回值:(正常完成 (值:TypedArray With Buffer Witness 记录) 或 抛出完成)。 调用时执行以下步骤:

  1. 执行 ? RequireInternalSlot(obj, [[TypedArrayName]])。
  2. 断言:obj 具有 [[ViewedArrayBuffer]] 内部槽。
  3. 返回 ? ValidateTypedArrayBounds(obj, order)。

23.2.4.5 ValidateTypedArrayBounds ( ta, order )

抽象操作 ValidateTypedArrayBounds,接收参数 ta (TypedArray) 和 order ((seq-cst 或 unordered));返回值:(正常完成 (值:TypedArray With Buffer Witness 记录) 或 抛出完成)。 它验证 ta 是否未超出其后备缓冲区的边界。 调用时执行以下步骤:

  1. 令 taRecord 为 MakeTypedArrayWithBufferWitnessRecord(ta, order)。
  2. 如果 IsTypedArrayOutOfBounds(taRecord) 是 true,则抛出 TypeError 异常。
  3. 返回 taRecord。

23.2.4.6 TypedArrayElementSize ( obj )

抽象操作 TypedArrayElementSize,接收参数 obj (TypedArray);返回值:非负整数。 调用时执行以下步骤:

  1. 返回 表 71 中为 obj.[[TypedArrayName]] 指定的 Element Size 值。

23.2.4.7 TypedArrayElementType ( obj )

抽象操作 TypedArrayElementType,接收参数 obj (TypedArray);返回值:TypedArray 元素类型。 调用时执行以下步骤:

  1. 返回 表 71 中为 obj.[[TypedArrayName]] 指定的 Element Type 值。

23.2.4.8 CompareTypedArrayElements ( x, y, comparator )

抽象操作 CompareTypedArrayElements,接收参数 x ((Number 或 BigInt))、y ((Number 或 BigInt)) 和 comparator ((函数对象 或 undefined));返回值:(正常完成 (值:Number) 或 突兀完成)。 调用时执行以下步骤:

  1. 断言:x 是 Number 且 y 是 Number,或者 x 是 BigInt 且 y 是 BigInt。
  2. 如果 comparator 不是 undefined,则
    1. 令 result 为 ? ToNumber(? Call(comparator, undefined, « x, y »))。
    2. 如果 result 是 NaN,则返回 +0𝔽。
    3. 返回 result。
  3. 如果 x 是 NaN 且 y 是 NaN,则返回 +0𝔽。
  4. 如果 x 是 NaN,则返回 1𝔽。
  5. 如果 y 是 NaN,则返回 -1𝔽。
  6. 如果 x < y,则返回 -1𝔽。
  7. 如果 x > y,则返回 1𝔽。
  8. 如果 x 是 -0𝔽 且 y 是 +0𝔽,则返回 -1𝔽。
  9. 如果 x 是 +0𝔽 且 y 是 -0𝔽,则返回 1𝔽。
  10. 返回 +0𝔽。
注
这里执行数值比较,而不是 23.1.3.30.2 中使用的字符串比较。

23.2.5 TypedArray 构造函数

每个 TypedArray 构造函数:

  • 都是具有下述结构的内在对象,除了另有说明之处外,仅在 表 71 中用作构造函数名称而不是 TypedArray 的名称有所不同。
  • 是一个行为会根据其参数数量和类型而有所不同的函数。对 TypedArray 的实际调用行为取决于传递给它的参数数量和种类。
  • 不旨在作为函数调用,并且以这种方式调用时会抛出异常。
  • 可以用作类定义的 extends 子句的值。希望继承指定 TypedArray 行为的子类构造函数必须包含对 TypedArray 构造函数的 super 调用,以创建并初始化具有支持 %TypedArray%.prototype 内置方法所必需内部状态的子类实例。

23.2.5.1 TypedArray ( ...args )

调用时,每个 TypedArray 构造函数执行以下步骤:

  1. 如果 NewTarget 是 undefined,则抛出 TypeError 异常。
  2. 令 ctorName 为 表 71 中为此 TypedArray 构造函数指定的 Constructor Name 值的 String 值。
  3. 令 proto 为 "%TypedArray.prototype%"。
  4. 令 numberOfArgs 为 args 中的元素数量。
  5. 如果 numberOfArgs = 0,则返回 ? AllocateTypedArray(ctorName, NewTarget, proto, 0)。
  6. 令 firstArg 为 args[0]。
  7. 如果 firstArg 是 Object,则
    1. 令 obj 为 ? AllocateTypedArray(ctorName, NewTarget, proto)。
    2. 如果 firstArg 具有 [[TypedArrayName]] 内部槽,则
      1. 执行 ? InitializeTypedArrayFromTypedArray(obj, firstArg)。
    3. 否则如果 firstArg 具有 [[ArrayBufferData]] 内部槽,则
      1. 如果 numberOfArgs > 1,则令 byteOffset 为 args[1];否则令 byteOffset 为 undefined。
      2. 如果 numberOfArgs > 2,则令 length 为 args[2];否则令 length 为 undefined。
      3. 执行 ? InitializeTypedArrayFromArrayBuffer(obj, firstArg, byteOffset, length)。
    4. 否则,
      1. 断言:firstArg 是 Object,并且 firstArg 既没有 [[TypedArrayName]] 内部槽,也没有 [[ArrayBufferData]] 内部槽。
      2. 令 usingIterator 为 ? GetMethod(firstArg, %Symbol.iterator%)。
      3. 如果 usingIterator 不是 undefined,则
        1. 令 values 为 ? IteratorToList(? GetIteratorFromMethod(firstArg, usingIterator))。
        2. 执行 ? InitializeTypedArrayFromList(obj, values)。
      4. 否则,
        1. 注:firstArg 不是可迭代对象,因此假定它已经是类数组对象。
        2. 执行 ? InitializeTypedArrayFromArrayLike(obj, firstArg)。
    5. 返回 obj。
  8. 断言:firstArg 不是 Object。
  9. 令 elementLength 为 ? ToIndex(firstArg)。
  10. 返回 ? AllocateTypedArray(ctorName, NewTarget, proto, elementLength)。

23.2.5.1.1 AllocateTypedArray ( ctorName, newTarget, defaultProto [ , length ] )

抽象操作 AllocateTypedArray,接收参数 ctorName (a String which is the name of a TypedArray constructor in 表 71)、newTarget (构造函数) 和 defaultProto (String)和可选参数 length (非负整数);返回值:(正常完成 (值:TypedArray) 或 抛出完成)。 它用于验证并创建 TypedArray 构造函数的实例。如果传入 length 参数,还会分配具有该长度的 ArrayBuffer,并将其与新的 TypedArray 实例关联。AllocateTypedArray 提供由 TypedArray 使用的通用语义。 调用时执行以下步骤:

  1. 令 proto 为 ? GetPrototypeFromConstructor(newTarget, defaultProto)。
  2. 令 obj 为 TypedArrayCreate(proto)。
  3. 断言:obj.[[ViewedArrayBuffer]] 是 undefined。
  4. 将 obj.[[TypedArrayName]] 设置为 ctorName。
  5. 如果 ctorName 是 "BigInt64Array" 或 "BigUint64Array",则将 obj.[[ContentType]] 设置为 bigint。
  6. 否则,将 obj.[[ContentType]] 设置为 number。
  7. 如果不存在 length,则
    1. 将 obj.[[ByteLength]] 设置为 0。
    2. 将 obj.[[ByteOffset]] 设置为 0。
    3. 将 obj.[[ArrayLength]] 设置为 0。
  8. 否则,
    1. 执行 ? AllocateTypedArrayBuffer(obj, length)。
  9. 返回 obj。

23.2.5.1.2 InitializeTypedArrayFromTypedArray ( obj, sourceArray )

抽象操作 InitializeTypedArrayFromTypedArray,接收参数 obj (TypedArray) 和 sourceArray (TypedArray);返回值:(正常完成 (值:unused) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 sourceData 为 sourceArray.[[ViewedArrayBuffer]]。
  2. 令 elementType 为 TypedArrayElementType(obj)。
  3. 令 elementSize 为 TypedArrayElementSize(obj)。
  4. 令 sourceType 为 TypedArrayElementType(sourceArray)。
  5. 令 sourceElementSize 为 TypedArrayElementSize(sourceArray)。
  6. 令 sourceByteOffset 为 sourceArray.[[ByteOffset]]。
  7. 令 sourceRecord 为 ? ValidateTypedArrayBounds(sourceArray, seq-cst)。
  8. 令 elementLength 为 TypedArrayLength(sourceRecord)。
  9. 令 byteLength 为 elementSize × elementLength。
  10. 如果 elementType 是 sourceType,则
    1. 令 data 为 ? CloneArrayBuffer(sourceData, sourceByteOffset, byteLength)。
  11. 否则,
    1. 令 data 为 ? AllocateArrayBuffer(%ArrayBuffer%, byteLength)。
    2. 如果 sourceArray.[[ContentType]] 不是 obj.[[ContentType]],则抛出 TypeError 异常。
    3. 令 sourceByteIndex 为 sourceByteOffset。
    4. 令 targetByteIndex 为 0。
    5. 令 count 为 elementLength。
    6. 当 count > 0 时,重复执行,
      1. 令 value 为 GetValueFromBuffer(sourceData, sourceByteIndex, sourceType, true, unordered)。
      2. 执行 SetValueInBuffer(data, targetByteIndex, elementType, value, true, unordered)。
      3. 将 sourceByteIndex 设置为 sourceByteIndex + sourceElementSize。
      4. 将 targetByteIndex 设置为 targetByteIndex + elementSize。
      5. 将 count 设置为 count - 1。
  12. 将 obj.[[ViewedArrayBuffer]] 设置为 data。
  13. 将 obj.[[ByteLength]] 设置为 byteLength。
  14. 将 obj.[[ByteOffset]] 设置为 0。
  15. 将 obj.[[ArrayLength]] 设置为 elementLength。
  16. 返回 unused。

23.2.5.1.3 InitializeTypedArrayFromArrayBuffer ( obj, buffer, byteOffset, length )

抽象操作 InitializeTypedArrayFromArrayBuffer,接收参数 obj (TypedArray)、buffer ((ArrayBuffer 或 SharedArrayBuffer))、byteOffset (ECMAScript 语言值) 和 length (ECMAScript 语言值);返回值:(正常完成 (值:unused) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 elementSize 为 TypedArrayElementSize(obj)。
  2. 令 offset 为 ? ToIndex(byteOffset)。
  3. 如果 offset modulo elementSize ≠ 0,则抛出 RangeError 异常。
  4. 令 bufferIsFixedLength 为 IsFixedLengthArrayBuffer(buffer)。
  5. 如果 length 不是 undefined,则
    1. 令 newLength 为 ? ToIndex(length)。
  6. 如果 IsDetachedBuffer(buffer) 是 true,则抛出 TypeError 异常。
  7. 令 bufferByteLength 为 ArrayBufferByteLength(buffer, seq-cst)。
  8. 如果 length 是 undefined 且 bufferIsFixedLength 是 false,则
    1. 如果 offset > bufferByteLength,则抛出 RangeError 异常。
    2. 将 obj.[[ByteLength]] 设置为 auto。
    3. 将 obj.[[ArrayLength]] 设置为 auto。
  9. 否则,
    1. 如果 length 是 undefined,则
      1. 如果 bufferByteLength modulo elementSize ≠ 0,则抛出 RangeError 异常。
      2. 令 newByteLength 为 bufferByteLength - offset。
      3. 如果 newByteLength < 0,则抛出 RangeError 异常。
    2. 否则,
      1. 令 newByteLength 为 newLength × elementSize。
      2. 如果 offset + newByteLength > bufferByteLength,则抛出 RangeError 异常。
    3. 将 obj.[[ByteLength]] 设置为 newByteLength。
    4. 将 obj.[[ArrayLength]] 设置为 newByteLength / elementSize。
  10. 将 obj.[[ViewedArrayBuffer]] 设置为 buffer。
  11. 将 obj.[[ByteOffset]] 设置为 offset。
  12. 返回 unused。

23.2.5.1.4 InitializeTypedArrayFromList ( obj, values )

抽象操作 InitializeTypedArrayFromList,接收参数 obj (TypedArray) 和 values (列表 (元素:ECMAScript 语言值));返回值:(正常完成 (值:unused) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 length 为 values 中的元素数量。
  2. 执行 ? AllocateTypedArrayBuffer(obj, length)。
  3. 令 k 为 0。
  4. 当 k < length 时,重复执行,
    1. 令 kValue 为 values[k]。
    2. 执行 ? TypedArraySetElement(obj, 𝔽(k), kValue)。
    3. 将 k 设置为 k + 1。
  5. 返回 unused。

23.2.5.1.5 InitializeTypedArrayFromArrayLike ( obj, arrayLike )

抽象操作 InitializeTypedArrayFromArrayLike,接收参数 obj (TypedArray) 和 arrayLike (an Object, but not a TypedArray or an ArrayBuffer);返回值:(正常完成 (值:unused) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 length 为 ? LengthOfArrayLike(arrayLike)。
  2. 执行 ? AllocateTypedArrayBuffer(obj, length)。
  3. 令 k 为 0。
  4. 当 k < length 时,重复执行,
    1. 令 propertyKey 为 ! ToString(𝔽(k))。
    2. 令 kValue 为 ? Get(arrayLike, propertyKey)。
    3. 执行 ? TypedArraySetElement(obj, 𝔽(k), kValue)。
    4. 将 k 设置为 k + 1。
  5. 返回 unused。

23.2.5.1.6 AllocateTypedArrayBuffer ( obj, length )

抽象操作 AllocateTypedArrayBuffer,接收参数 obj (TypedArray) 和 length (非负整数);返回值:(正常完成 (值:unused) 或 抛出完成)。 它分配一个 ArrayBuffer 并将其与 obj 关联。 调用时执行以下步骤:

  1. 断言:obj.[[ViewedArrayBuffer]] 是 undefined。
  2. 令 elementSize 为 TypedArrayElementSize(obj)。
  3. 令 byteLength 为 elementSize × length。
  4. 令 data 为 ? AllocateArrayBuffer(%ArrayBuffer%, byteLength)。
  5. 将 obj.[[ViewedArrayBuffer]] 设置为 data。
  6. 将 obj.[[ByteLength]] 设置为 byteLength。
  7. 将 obj.[[ByteOffset]] 设置为 0。
  8. 将 obj.[[ArrayLength]] 设置为 length。
  9. 返回 unused。

23.2.6 TypedArray 构造函数的属性

每个 TypedArray 构造函数:

  • 具有 [[Prototype]] 内部槽,其值是 %TypedArray%。
  • 具有 "length" 属性,其值是 3𝔽。
  • 具有 "name" 属性,其值是 表 71 中为其指定的构造函数名称的 String 值。
  • 具有以下属性:

23.2.6.1 TypedArray.BYTES_PER_ELEMENT

TypedArray.BYTES_PER_ELEMENT 的值是 表 71 中为 TypedArray 指定的 Element Size 值。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

23.2.6.2 TypedArray.prototype

TypedArray.prototype 的初始值是对应的 TypedArray 原型内在对象(23.2.7)。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

23.2.7 TypedArray 原型对象的属性

每个 TypedArray 原型对象:

  • 具有 [[Prototype]] 内部槽,其值是 %TypedArray.prototype%。
  • 是普通对象。
  • 不具有 [[ViewedArrayBuffer]],也不具有任何其他 TypedArray 实例对象特有的内部槽。

23.2.7.1 TypedArray.prototype.BYTES_PER_ELEMENT

TypedArray.prototype.BYTES_PER_ELEMENT 的值是 表 71 中为 TypedArray 指定的 Element Size 值。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

23.2.7.2 TypedArray.prototype.constructor

给定 TypedArray 构造函数的原型的 "constructor" 属性的初始值是该构造函数本身。

23.2.8 TypedArray 实例的属性

TypedArray 实例是 TypedArray。每个 TypedArray 实例都从对应的 TypedArray 原型对象继承属性。每个 TypedArray 实例都具有以下内部槽:[[ViewedArrayBuffer]]、[[TypedArrayName]]、[[ContentType]]、[[ByteLength]]、[[ByteOffset]] 和 [[ArrayLength]]。

23.3 Uint8Array 对象

Uint8Array 是上述 TypedArray 的一种特定类型。此外,Uint8Array 构造函数(23.3.1)和 Uint8Array 原型对象(23.3.2)还具有其他方法。

23.3.1 Uint8Array 构造函数的其他属性

23.3.1.1 Uint8Array.fromBase64 ( string [ , options ] )

  1. 如果 string 不是 String,则抛出 TypeError 异常。
  2. 令 optionsObj 为 ? GetOptionsObject(options)。
  3. 令 alphabet 为 ? Get(optionsObj, "alphabet")。
  4. 如果 alphabet 是 undefined,则将 alphabet 设置为 "base64"。
  5. 如果 alphabet 既不是 "base64" 也不是 "base64url",则抛出 TypeError 异常。
  6. 令 lastChunkHandling 为 ? Get(optionsObj, "lastChunkHandling")。
  7. 如果 lastChunkHandling 是 undefined,则将 lastChunkHandling 设置为 "loose"。
  8. 如果 lastChunkHandling 不是 "loose"、"strict" 或 "stop-before-partial" 之一,则抛出 TypeError 异常。
  9. 令 result 为 FromBase64(string, alphabet, lastChunkHandling)。
  10. 如果 result.[[Error]] 不是 none,则
    1. 抛出 result.[[Error]]。
  11. 令 resultLength 为 result.[[Bytes]] 中的元素数量。
  12. 令 ta 为 ? AllocateTypedArray("Uint8Array", %Uint8Array%, "%Uint8Array.prototype%", resultLength)。
  13. 断言:ta.[[ViewedArrayBuffer]].[[ArrayBufferByteLength]] 是 result.[[Bytes]] 中的元素数量。
  14. 将 ta.[[ViewedArrayBuffer]].[[ArrayBufferData]] 的每个索引处的值设置为 result.[[Bytes]] 对应索引处的值。
  15. 返回 ta。

23.3.1.2 Uint8Array.fromHex ( string )

  1. 如果 string 不是 String,则抛出 TypeError 异常。
  2. 令 result 为 FromHex(string)。
  3. 如果 result.[[Error]] 不是 none,则
    1. 抛出 result.[[Error]]。
  4. 令 resultLength 为 result.[[Bytes]] 中的元素数量。
  5. 令 ta 为 ? AllocateTypedArray("Uint8Array", %Uint8Array%, "%Uint8Array.prototype%", resultLength)。
  6. 断言:ta.[[ViewedArrayBuffer]].[[ArrayBufferByteLength]] 是 result.[[Bytes]] 中的元素数量。
  7. 将 ta.[[ViewedArrayBuffer]].[[ArrayBufferData]] 的每个索引处的值设置为 result.[[Bytes]] 对应索引处的值。
  8. 返回 ta。

23.3.2 Uint8Array 原型对象的其他属性

23.3.2.1 Uint8Array.prototype.setFromBase64 ( string [ , options ] )

  1. 令 into 为 this value。
  2. 执行 ? ValidateUint8Array(into)。
  3. 如果 string 不是 String,则抛出 TypeError 异常。
  4. 令 optionsObj 为 ? GetOptionsObject(options)。
  5. 令 alphabet 为 ? Get(optionsObj, "alphabet")。
  6. 如果 alphabet 是 undefined,则将 alphabet 设置为 "base64"。
  7. 如果 alphabet 既不是 "base64" 也不是 "base64url",则抛出 TypeError 异常。
  8. 令 lastChunkHandling 为 ? Get(optionsObj, "lastChunkHandling")。
  9. 如果 lastChunkHandling 是 undefined,则将 lastChunkHandling 设置为 "loose"。
  10. 如果 lastChunkHandling 不是 "loose"、"strict" 或 "stop-before-partial" 之一,则抛出 TypeError 异常。
  11. 令 taRecord 为 ? ValidateTypedArrayBounds(into, seq-cst)。
  12. 令 byteLength 为 TypedArrayLength(taRecord)。
  13. 令 result 为 FromBase64(string, alphabet, lastChunkHandling, byteLength)。
  14. 令 bytes 为 result.[[Bytes]]。
  15. 令 written 为 bytes 中的元素数量。
  16. 注:FromBase64 不会调用任何用户代码,因此作为 into 后备存储的 ArrayBuffer 不可能已被分离或缩小。
  17. 断言:written ≤ byteLength。
  18. 执行 SetUint8ArrayBytes(into, bytes)。
  19. 如果 result.[[Error]] 不是 none,则
    1. 抛出 result.[[Error]]。
  20. 令 resultObj 为 OrdinaryObjectCreate(%Object.prototype%)。
  21. 执行 ! CreateDataPropertyOrThrow(resultObj, "read", 𝔽(result.[[Read]]))。
  22. 执行 ! CreateDataPropertyOrThrow(resultObj, "written", 𝔽(written))。
  23. 返回 resultObj。

23.3.2.2 Uint8Array.prototype.setFromHex ( string )

  1. 令 into 为 this value。
  2. 执行 ? ValidateUint8Array(into)。
  3. 如果 string 不是 String,则抛出 TypeError 异常。
  4. 令 taRecord 为 ? ValidateTypedArrayBounds(into, seq-cst)。
  5. 令 byteLength 为 TypedArrayLength(taRecord)。
  6. 令 result 为 FromHex(string, byteLength)。
  7. 令 bytes 为 result.[[Bytes]]。
  8. 令 written 为 bytes 中的元素数量。
  9. 注:FromHex 不会调用任何用户代码,因此作为 into 后备存储的 ArrayBuffer 不可能已被分离或缩小。
  10. 断言:written ≤ byteLength。
  11. 执行 SetUint8ArrayBytes(into, bytes)。
  12. 如果 result.[[Error]] 不是 none,则
    1. 抛出 result.[[Error]]。
  13. 令 resultObj 为 OrdinaryObjectCreate(%Object.prototype%)。
  14. 执行 ! CreateDataPropertyOrThrow(resultObj, "read", 𝔽(result.[[Read]]))。
  15. 执行 ! CreateDataPropertyOrThrow(resultObj, "written", 𝔽(written))。
  16. 返回 resultObj。

23.3.2.3 Uint8Array.prototype.toBase64 ( [ options ] )

  1. 令 obj 为 this value。
  2. 执行 ? ValidateUint8Array(obj)。
  3. 令 optionsObj 为 ? GetOptionsObject(options)。
  4. 令 alphabet 为 ? Get(optionsObj, "alphabet")。
  5. 如果 alphabet 是 undefined,则将 alphabet 设置为 "base64"。
  6. 如果 alphabet 既不是 "base64" 也不是 "base64url",则抛出 TypeError 异常。
  7. 令 omitPadding 为 ToBoolean(? Get(optionsObj, "omitPadding")).
  8. 令 toEncode 为 ? GetUint8ArrayBytes(obj)。
  9. 如果 alphabet 是 "base64",则
    1. 令 outAscii 为根据 RFC 4648 第 4 节规定的 base64 编码对 toEncode 进行编码所得的码点序列。当且仅当 omitPadding 是 false 时包含填充。
  10. 否则,
    1. 断言:alphabet 是 "base64url"。
    2. 令 outAscii 为根据 RFC 4648 第 5 节规定的 base64url 编码对 toEncode 进行编码所得的码点序列。当且仅当 omitPadding 是 false 时包含填充。
  11. 返回 CodePointsToString(outAscii)。

23.3.2.4 Uint8Array.prototype.toHex ( )

  1. 令 obj 为 this value。
  2. 执行 ? ValidateUint8Array(obj)。
  3. 令 toEncode 为 ? GetUint8ArrayBytes(obj)。
  4. 令 out 为空 String。
  5. 对 toEncode 的每个字节 byte,执行
    1. 令 hex 为 Number::toString(𝔽(byte), 16)。
    2. 将 hex 设置为 StringPad(hex, 2, "0", start)。
    3. 将 out 设置为 out 和 hex 的字符串连接。
  6. 返回 out。

23.3.3 Uint8Array 对象的抽象操作

23.3.3.1 ValidateUint8Array ( ta )

抽象操作 ValidateUint8Array,接收参数 ta (ECMAScript 语言值);返回值:(正常完成 (值:unused) 或 抛出完成)。 调用时执行以下步骤:

  1. 执行 ? RequireInternalSlot(ta, [[TypedArrayName]])。
  2. 如果 ta.[[TypedArrayName]] 不是 "Uint8Array",则抛出 TypeError 异常。
  3. 返回 unused。

23.3.3.2 GetUint8ArrayBytes ( ta )

抽象操作 GetUint8ArrayBytes,接收参数 ta (Uint8Array);返回值:(正常完成 (值:列表 (元素:字节值)) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 buffer 为 ta.[[ViewedArrayBuffer]]。
  2. 令 taRecord 为 ? ValidateTypedArrayBounds(ta, seq-cst)。
  3. 令 length 为 TypedArrayLength(taRecord)。
  4. 令 byteOffset 为 ta.[[ByteOffset]]。
  5. 令 bytes 为新的空 List。
  6. 令 index 为 0。
  7. 当 index < length 时,重复执行,
    1. 令 byteIndex 为 byteOffset + index。
    2. 令 byte 为 ℝ(GetValueFromBuffer(buffer, byteIndex, uint8, true, unordered))。
    3. 将 byte 追加到 bytes。
    4. 将 index 设置为 index + 1。
  8. 返回 bytes。

23.3.3.3 SetUint8ArrayBytes ( into, bytes )

抽象操作 SetUint8ArrayBytes,接收参数 into (Uint8Array) 和 bytes (列表 (元素:字节值));返回值:unused。 调用时执行以下步骤:

  1. 令 offset 为 into.[[ByteOffset]]。
  2. 令 length 为 bytes 中的元素数量。
  3. 令 index 为 0。
  4. 当 index < length 时,重复执行,
    1. 令 byte 为 bytes[index]。
    2. 令 byteIndexInBuffer 为 index + offset。
    3. 执行 SetValueInBuffer(into.[[ViewedArrayBuffer]], byteIndexInBuffer, uint8, 𝔽(byte), true, unordered)。
    4. 将 index 设置为 index + 1。
  5. 返回 unused。

23.3.3.4 SkipAsciiWhitespace ( string, index )

抽象操作 SkipAsciiWhitespace,接收参数 string (String) 和 index (非负整数);返回值:非负整数。 调用时执行以下步骤:

  1. 令 length 为 string 的长度。
  2. 当 index < length 时,重复执行,
    1. 令 char 为 string 中索引 index 处的码元。
    2. 如果 char 不是 0x0009 (TAB)、0x000A (LF)、0x000C (FF)、0x000D (CR) 或 0x0020 (SPACE) 之一,则
      1. 返回 index。
    3. 将 index 设置为 index + 1。
  3. 返回 index。

23.3.3.5 DecodeFinalBase64Chunk ( chunk, throwOnExtraBits )

抽象操作 DecodeFinalBase64Chunk,接收参数 chunk ((a String of length 2 或 3)) 和 throwOnExtraBits (Boolean);返回值:(正常完成 (值:列表 (元素:字节值)) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 chunkLength 为 chunk 的长度。
  2. 如果 chunkLength = 2,则
    1. 将 chunk 设置为 chunk 和 "AA" 的字符串连接。
  3. 否则,
    1. 断言:chunkLength 是 3。
    2. 将 chunk 设置为 chunk 和 "A" 的字符串连接。
  4. 令 bytes 为 DecodeFullLengthBase64Chunk(chunk)。
  5. 如果 chunkLength = 2,则
    1. 如果 throwOnExtraBits 是 true 且 bytes[1] ≠ 0,则抛出 SyntaxError 异常。
    2. 返回 « bytes[0] »。
  6. 如果 throwOnExtraBits 是 true 且 bytes[2] ≠ 0,则抛出 SyntaxError 异常。
  7. 返回 « bytes[0], bytes[1] »。

23.3.3.6 DecodeFullLengthBase64Chunk ( chunk )

抽象操作 DecodeFullLengthBase64Chunk,接收参数 chunk (a String of length 4);返回值:列表 (元素:byte values of length 3)。

标准 base64 字母表是 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",即其元素是与 Unicode Basic Latin 块中的每个字母和数字以及 "+" 和 "/" 对应的码元的 String。

  1. 令 byteSequence 为将 chunk 作为 base64 解码所得的唯一 3 字节序列(即,将 RFC 4648 第 4 节规定的 base64 编码应用于 byteSequence 会产生 chunk 的序列)。
  2. 返回一个 List,其元素依次为 byteSequence 的各个元素。

23.3.3.7 FromBase64 ( string, alphabet, lastChunkHandling [ , maxLength ] )

抽象操作 FromBase64,接收参数 string (String)、alphabet (("base64" 或 "base64url")) 和 lastChunkHandling (("loose"、"strict" 或 "stop-before-partial"))和可选参数 maxLength (非负整数);返回值:记录 (字段:[[Read]] (整数), [[Bytes]] (列表 (元素:字节值)), [[Error]] ((a SyntaxError object 或 none)))。 调用时执行以下步骤:

  1. 如果不存在 maxLength,则
    1. 将 maxLength 设置为 253 - 1。
    2. 注:由于输入是 String,Strings 的长度限制为 253 - 1 个字符,并且输出所需的字节数不会超过输入的字符数,因此永远无法达到此限制。不过,为 maxLength 使用有限值在编辑上更方便。
  2. 注:以下算法中验证和解码的顺序不可观察。鼓励实现以最高效的任意顺序执行它们,并且可以将验证与解码交错进行。
  3. 如果 maxLength = 0,则
    1. 返回 Record { [[Read]]: 0, [[Bytes]]: « », [[Error]]: none }。
  4. 令 read 为 0。
  5. 令 bytes 为新的空 List。
  6. 令 chunk 为空 String。
  7. 令 chunkLength 为 0。
  8. 令 index 为 0。
  9. 令 length 为 string 的长度。
  10. 重复执行,
    1. 断言:bytes 中的元素数量可以被 3 整除。
    2. 将 index 设置为 SkipAsciiWhitespace(string, index)。
    3. 如果 index = length,则
      1. 如果 chunkLength > 0,则
        1. 如果 lastChunkHandling 是 "stop-before-partial",则
          1. 返回 Record { [[Read]]: read, [[Bytes]]: bytes, [[Error]]: none }。
        2. 如果 lastChunkHandling 是 "strict",则
          1. 令 error 为新创建的 SyntaxError 对象。
          2. 返回 Record { [[Read]]: read, [[Bytes]]: bytes, [[Error]]: error }。
        3. 断言:lastChunkHandling 是 "loose"。
        4. 如果 chunkLength = 1,则
          1. 令 error 为新创建的 SyntaxError 对象。
          2. 返回 Record { [[Read]]: read, [[Bytes]]: bytes, [[Error]]: error }。
        5. 将 bytes 设置为 bytes 和 ! DecodeFinalBase64Chunk(chunk, false) 的列表连接。
      2. 返回 Record { [[Read]]: length, [[Bytes]]: bytes, [[Error]]: none }。
    4. 令 char 为 string 从 index 到 index + 1 的子字符串。
    5. 将 index 设置为 index + 1。
    6. 如果 char 是 "=",则
      1. 如果 chunkLength < 2,则
        1. 令 error 为新创建的 SyntaxError 对象。
        2. 返回 Record { [[Read]]: read, [[Bytes]]: bytes, [[Error]]: error }。
      2. 将 index 设置为 SkipAsciiWhitespace(string, index)。
      3. 如果 chunkLength = 2,则
        1. 如果 index = length,则
          1. 如果 lastChunkHandling 是 "stop-before-partial",则
            1. 返回 Record { [[Read]]: read, [[Bytes]]: bytes, [[Error]]: none }。
          2. 令 error 为新创建的 SyntaxError 对象。
          3. 返回 Record { [[Read]]: read, [[Bytes]]: bytes, [[Error]]: error }。
        2. 将 char 设置为 string 从 index 到 index + 1 的子字符串。
        3. 如果 char 是 "=",则
          1. 将 index 设置为 SkipAsciiWhitespace(string, index + 1)。
      4. 如果 index < length,则
        1. 令 error 为新创建的 SyntaxError 对象。
        2. 返回 Record { [[Read]]: read, [[Bytes]]: bytes, [[Error]]: error }。
      5. 如果 lastChunkHandling 是 "strict",则令 throwOnExtraBits 为 true;否则令 throwOnExtraBits 为 false。
      6. 令 decodeResult 为 Completion(DecodeFinalBase64Chunk(chunk, throwOnExtraBits))。
      7. 如果 decodeResult 是突然完成,则
        1. 令 error 为 decodeResult.[[Value]]。
        2. 返回 Record { [[Read]]: read, [[Bytes]]: bytes, [[Error]]: error }。
      8. 将 bytes 设置为 bytes 和 ! decodeResult 的列表连接。
      9. 返回 Record { [[Read]]: length, [[Bytes]]: bytes, [[Error]]: none }。
    7. 如果 alphabet 是 "base64url",则
      1. 如果 char 是 "+" 或 "/",则
        1. 令 error 为新创建的 SyntaxError 对象。
        2. 返回 Record { [[Read]]: read, [[Bytes]]: bytes, [[Error]]: error }。
      2. 否则如果 char 是 "-",则
        1. 将 char 设置为 "+"。
      3. 否则如果 char 是 "_",则
        1. 将 char 设置为 "/"。
    8. 如果 char 的唯一一个码元不是标准 base64 字母表中的元素,则
      1. 令 error 为新创建的 SyntaxError 对象。
      2. 返回 Record { [[Read]]: read, [[Bytes]]: bytes, [[Error]]: error }。
    9. 令 remaining 为 maxLength - bytes 中的元素数量。
    10. 如果 remaining = 1 且 chunkLength = 2,或者 remaining = 2 且 chunkLength = 3,则
      1. 返回 Record { [[Read]]: read, [[Bytes]]: bytes, [[Error]]: none }。
    11. 将 chunk 设置为 chunk 和 char 的字符串连接。
    12. 将 chunkLength 设置为 chunk 的长度。
    13. 如果 chunkLength = 4,则
      1. 将 bytes 设置为 bytes 和 DecodeFullLengthBase64Chunk(chunk) 的列表连接。
      2. 将 chunk 设置为空 String。
      3. 将 chunkLength 设置为 0。
      4. 将 read 设置为 index。
      5. 如果 bytes 中的元素数量 = maxLength,则
        1. 返回 Record { [[Read]]: read, [[Bytes]]: bytes, [[Error]]: none }。

23.3.3.8 FromHex ( string [ , maxLength ] )

抽象操作 FromHex,接收参数 string (String)和可选参数 maxLength (非负整数);返回值:记录 (字段:[[Read]] (整数), [[Bytes]] (列表 (元素:字节值)), [[Error]] ((a SyntaxError object 或 none)))。 调用时执行以下步骤:

  1. 如果不存在 maxLength,则将 maxLength 设置为 253 - 1。
  2. 令 length 为 string 的长度。
  3. 令 bytes 为新的空 List。
  4. 令 read 为 0。
  5. 如果 length modulo 2 ≠ 0,则
    1. 令 error 为新创建的 SyntaxError 对象。
    2. 返回 Record { [[Read]]: read, [[Bytes]]: bytes, [[Error]]: error }。
  6. 当 read < length 且 bytes 中的元素数量 < maxLength 时,重复执行,
    1. 令 hexits 为 string 从 read 到 read + 2 的子字符串。
    2. 如果 hexits 包含任何不在 "0123456789abcdefABCDEF" 中的码元,则
      1. 令 error 为新创建的 SyntaxError 对象。
      2. 返回 Record { [[Read]]: read, [[Bytes]]: bytes, [[Error]]: error }。
    3. 将 read 设置为 read + 2。
    4. 令 byte 为 hexits 以十六进制表示法所表示的整数值,其中使用字母 A 到 F 和 a 到 f 表示值为 10 到 15 的数字。
    5. 将 byte 追加到 bytes。
  7. 返回 Record { [[Read]]: read, [[Bytes]]: bytes, [[Error]]: none }。

24 键控集合

24.1 Map 对象

Map 是键/值对的集合,其中键和值都可以是任意 ECMAScript 语言值。在 Map 的集合中,一个不同的键值只能出现在一个键/值对中。不同的键值使用 SameValueZero 比较算法的语义进行区分。

Map 必须使用哈希表或其他机制实现,这些机制提供的平均访问时间相对于集合中的元素数量是次线性的。本规范中使用的数据结构仅用于描述 Map 所要求的可观察语义。它并不旨在作为可行的实现模型。

24.1.1 Map 构造函数

Map 构造函数:

  • 是 %Map%。
  • 是全局对象的 "Map" 属性的初始值。
  • 作为构造函数调用时,创建并初始化新的 Map。
  • 不旨在作为函数调用,并且以这种方式调用时会抛出异常。
  • 可以用作类定义的 extends 子句中的值。希望继承指定 Map 行为的子类构造函数必须包含对 Map 构造函数的 super 调用,以创建并初始化具有支持 Map.prototype 内置方法所必需内部状态的子类实例。

24.1.1.1 Map ( [ iterable ] )

调用时,此函数执行以下步骤:

  1. 如果 NewTarget 是 undefined,则抛出 TypeError 异常。
  2. 令 map 为 ? OrdinaryCreateFromConstructor(NewTarget, "%Map.prototype%", « [[MapData]] »)。
  3. 将 map.[[MapData]] 设置为新的空 List。
  4. 如果 iterable 是 undefined 或 null,则返回 map。
  5. 令 adder 为 ? Get(map, "set")。
  6. 如果 IsCallable(adder) 是 false,则抛出 TypeError 异常。
  7. 返回 ? AddEntriesFromIterable(map, iterable, adder)。
注

如果存在参数 iterable,则预期它是一个实现了 %Symbol.iterator% 方法的对象,该方法返回一个迭代器对象,此迭代器对象会生成一个包含两个元素的类数组对象,其中第一个元素是将用作 Map 键的值,第二个元素是要与该键关联的值。

24.1.1.2 AddEntriesFromIterable ( target, iterable, adder )

抽象操作 AddEntriesFromIterable,接收参数 target (Object)、iterable (an ECMAScript language value, but not undefined or null) 和 adder (函数对象);返回值:(正常完成 (值:Object) 或 抛出完成)。 将以 target 作为接收者调用 adder。 调用时执行以下步骤:

  1. 令 iteratorRecord 为 ? GetIterator(iterable, sync)。
  2. 重复执行,
    1. 令 next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 next 是 done,则返回 target。
    3. 如果 next 不是 Object,则
      1. 令 error 为 ThrowCompletion(a newly created TypeError object)。
      2. 返回 ? IteratorClose(iteratorRecord, error)。
    4. 令 key 为 Completion(Get(next, "0")).
    5. IfAbruptCloseIterator(key, iteratorRecord)。
    6. 令 value 为 Completion(Get(next, "1")).
    7. IfAbruptCloseIterator(value, iteratorRecord)。
    8. 令 status 为 Completion(Call(adder, target, « key, value »)).
    9. IfAbruptCloseIterator(status, iteratorRecord)。
注

参数 iterable 预期是一个实现了 %Symbol.iterator% 方法的对象,该方法返回一个迭代器对象,此迭代器对象会生成一个包含两个元素的类数组对象,其中第一个元素是将用作 Map 键的值,第二个元素是要与该键关联的值。

24.1.2 Map 构造函数的属性

Map 构造函数:

24.1.2.1 Map.groupBy ( items, callback )

注

callback 应当是一个接受两个参数的函数。groupBy 按升序对 items 中的每个元素调用一次 callback,并构造一个新的 Map。callback 返回的每个值都用作 Map 中的键。对于每个这样的键,结果 Map 都有一个条目,其键是该键,其值是一个包含所有使 callback 返回该键的元素的数组。

调用 callback 时会传入两个参数:元素的值和元素的索引。

groupBy 的返回值是一个 Map。

调用时,此函数执行以下步骤:

  1. 令 groups 为 ? GroupBy(items, callback, collection)。
  2. 令 map 为 ! Construct(%Map%)。
  3. 对 groups 的每个 Record { [[Key]], [[Elements]] } group,执行
    1. 令 elements 为 CreateArrayFromList(group.[[Elements]])。
    2. 令 entry 为 Record { [[Key]]: group.[[Key]], [[Value]]: elements }。
    3. 将 entry 追加到 map.[[MapData]]。
  4. 返回 map。

24.1.2.2 Map.prototype

Map.prototype 的初始值是 Map 原型对象。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

24.1.2.3 get Map [ %Symbol.species% ]

Map[%Symbol.species%] 是访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数在调用时执行以下步骤:

  1. 返回 this value。

此函数的 "name" 属性的值是 "get [Symbol.species]"。

注

创建派生集合对象的方法应调用 %Symbol.species% 来确定用于创建派生对象的构造函数。子类构造函数可以覆盖 %Symbol.species% 以更改默认构造函数的指定。

24.1.3 Map 原型对象的属性

Map 原型对象:

24.1.3.1 Map.prototype.clear ( )

调用时,此方法执行以下步骤:

  1. 令 map 为 this value。
  2. 执行 ? RequireInternalSlot(map, [[MapData]])。
  3. 对 map.[[MapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 将 entry.[[Key]] 设置为 empty。
    2. 将 entry.[[Value]] 设置为 empty。
  4. 返回 undefined。
注

会保留现有的 [[MapData]] List,因为可能存在已在遍历该 List 的中途暂停的 Map Iterator 对象。

24.1.3.2 Map.prototype.constructor

Map.prototype.constructor 的初始值是 %Map%。

24.1.3.3 Map.prototype.delete ( key )

调用时,此方法执行以下步骤:

  1. 令 map 为 this value。
  2. 执行 ? RequireInternalSlot(map, [[MapData]])。
  3. 将 key 设置为 CanonicalizeKeyedCollectionKey(key)。
  4. 对 map.[[MapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 empty 且 SameValue(entry.[[Key]], key) 是 true,则
      1. 将 entry.[[Key]] 设置为 empty。
      2. 将 entry.[[Value]] 设置为 empty。
      3. 返回 true。
  5. 返回 false。
注

值 empty 用作规范机制,以指示某个条目已被删除。实际实现可以采取其他操作,例如从内部数据结构中物理删除该条目。

24.1.3.4 Map.prototype.entries ( )

调用时,此方法执行以下步骤:

  1. 令 map 为 this value。
  2. 返回 ? CreateMapIterator(map, key+value)。

24.1.3.5 Map.prototype.forEach ( callback [ , thisArg ] )

调用时,此方法执行以下步骤:

  1. 令 map 为 this value。
  2. 执行 ? RequireInternalSlot(map, [[MapData]])。
  3. 如果 IsCallable(callback) 是 false,则抛出 TypeError 异常。
  4. 令 entries 为 map.[[MapData]]。
  5. 令 entriesCount 为 entries 中的元素数量。
  6. 令 index 为 0。
  7. 当 index < entriesCount 时,重复执行,
    1. 令 entry 为 entries[index]。
    2. 将 index 设置为 index + 1。
    3. 如果 entry.[[Key]] 不是 empty,则
      1. 执行 ? Call(callback, thisArg, « entry.[[Value]], entry.[[Key]], map »)。
      2. 注:在执行 callback 期间,entries 中的元素数量可能已经增加。
      3. 将 entriesCount 设置为 entries 中的元素数量。
  8. 返回 undefined。
注

callback 应当是一个接受三个参数的函数。forEach 按键插入顺序,对 Map 中存在的每个键/值对调用一次 callback。callback 只会针对 Map 中实际存在的键调用;不会针对已从 Map 中删除的键调用。

如果提供了 thisArg 参数,则每次调用 callback 时都会将其用作 this value。如果未提供,则改用 undefined。

调用 callback 时会传入三个参数:条目的值、条目的键,以及正在遍历的 Map。

forEach 不会直接修改调用它的对象,但对 callback 的调用可能会修改该对象。Map 的 [[MapData]] 中的每个条目只会被访问一次。调用 forEach 开始后添加的新键会被访问。如果一个键在被访问后被删除,然后在 forEach 调用完成前重新添加,则该键会被再次访问。调用 forEach 开始后且被访问之前删除的键不会被访问,除非该键在 forEach 调用完成前再次添加。

24.1.3.6 Map.prototype.get ( key )

调用时,此方法执行以下步骤:

  1. 令 map 为 this value。
  2. 执行 ? RequireInternalSlot(map, [[MapData]])。
  3. 将 key 设置为 CanonicalizeKeyedCollectionKey(key)。
  4. 对 map.[[MapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 empty 且 SameValue(entry.[[Key]], key) 是 true,则返回 entry.[[Value]]。
  5. 返回 undefined。

24.1.3.7 Map.prototype.getOrInsert ( key, value )

调用时,此方法执行以下步骤:

  1. 令 map 为 this value。
  2. 执行 ? RequireInternalSlot(map, [[MapData]])。
  3. 将 key 设置为 CanonicalizeKeyedCollectionKey(key)。
  4. 对 map.[[MapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 empty 且 SameValue(entry.[[Key]], key) 是 true,则返回 entry.[[Value]]。
  5. 令 entry 为 Record { [[Key]]: key, [[Value]]: value }。
  6. 将 entry 追加到 map.[[MapData]]。
  7. 返回 value。

24.1.3.8 Map.prototype.getOrInsertComputed ( key, callback )

调用时,此方法执行以下步骤:

  1. 令 map 为 this value。
  2. 执行 ? RequireInternalSlot(map, [[MapData]])。
  3. 如果 IsCallable(callback) 是 false,则抛出 TypeError 异常。
  4. 将 key 设置为 CanonicalizeKeyedCollectionKey(key)。
  5. 对 map.[[MapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 empty 且 SameValue(entry.[[Key]], key) 是 true,则返回 entry.[[Value]]。
  6. 令 value 为 ? Call(callback, undefined, « key »)。
  7. 注:在执行 callback 期间,Map 可能已经被修改。
  8. 对 map.[[MapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 empty 且 SameValue(entry.[[Key]], key) 是 true,则
      1. 将 entry.[[Value]] 设置为 value。
      2. 返回 value。
  9. 令 entry 为 Record { [[Key]]: key, [[Value]]: value }。
  10. 将 entry 追加到 map.[[MapData]]。
  11. 返回 value。

24.1.3.9 Map.prototype.has ( key )

调用时,此方法执行以下步骤:

  1. 令 map 为 this value。
  2. 执行 ? RequireInternalSlot(map, [[MapData]])。
  3. 将 key 设置为 CanonicalizeKeyedCollectionKey(key)。
  4. 对 map.[[MapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 empty 且 SameValue(entry.[[Key]], key) 是 true,则返回 true。
  5. 返回 false。

24.1.3.10 Map.prototype.keys ( )

调用时,此方法执行以下步骤:

  1. 令 map 为 this value。
  2. 返回 ? CreateMapIterator(map, key)。

24.1.3.11 Map.prototype.set ( key, value )

调用时,此方法执行以下步骤:

  1. 令 map 为 this value。
  2. 执行 ? RequireInternalSlot(map, [[MapData]])。
  3. 将 key 设置为 CanonicalizeKeyedCollectionKey(key)。
  4. 对 map.[[MapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 empty 且 SameValue(entry.[[Key]], key) 是 true,则
      1. 将 entry.[[Value]] 设置为 value。
      2. 返回 map。
  5. 令 entry 为 Record { [[Key]]: key, [[Value]]: value }。
  6. 将 entry 追加到 map.[[MapData]]。
  7. 返回 map。

24.1.3.12 get Map.prototype.size

Map.prototype.size 是访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数在调用时执行以下步骤:

  1. 令 map 为 this value。
  2. 执行 ? RequireInternalSlot(map, [[MapData]])。
  3. 令 count 为 0。
  4. 对 map.[[MapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 empty,则将 count 设置为 count + 1。
  5. 返回 𝔽(count)。

24.1.3.13 Map.prototype.values ( )

调用时,此方法执行以下步骤:

  1. 令 map 为 this value。
  2. 返回 ? CreateMapIterator(map, value)。

24.1.3.14 Map.prototype [ %Symbol.iterator% ] ( )

%Symbol.iterator% 属性的初始值是 24.1.3.4 中定义的 %Map.prototype.entries%。

24.1.3.15 Map.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "Map"。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

24.1.4 Map 实例的属性

Map 实例是从 Map 原型对象继承属性的普通对象。Map 实例还具有 [[MapData]] 内部槽。

24.1.5 Map 迭代器对象

Map Iterator 是表示对某个特定 Map 实例对象进行某次特定迭代的对象。Map Iterator 对象没有具名构造函数。相反,Map Iterator 对象通过调用 Map 实例对象的某些方法创建。

24.1.5.1 CreateMapIterator ( map, kind )

抽象操作 CreateMapIterator,接收参数 map (ECMAScript 语言值) 和 kind ((key+value、key 或 value));返回值:(正常完成 (值:Generator) 或 抛出完成)。 它用于为返回此类迭代器的 Map 方法创建迭代器对象。 调用时执行以下步骤:

  1. 执行 ? RequireInternalSlot(map, [[MapData]])。
  2. 令 closure 为不带参数的新 Abstract Closure,它捕获 map 和 kind,并在被调用时执行以下步骤:
    1. 令 entries 为 map.[[MapData]]。
    2. 令 index 为 0。
    3. 令 entriesCount 为 entries 中的元素数量。
    4. 当 index < entriesCount 时,重复执行,
      1. 令 entry 为 entries[index]。
      2. 将 index 设置为 index + 1。
      3. 如果 entry.[[Key]] 不是 empty,则
        1. 如果 kind 是 key,则
          1. 令 result 为 entry.[[Key]]。
        2. 否则如果 kind 是 value,则
          1. 令 result 为 entry.[[Value]]。
        3. 否则,
          1. 断言:kind 是 key+value。
          2. 令 result 为 CreateArrayFromList(« entry.[[Key]], entry.[[Value]] »)。
        4. 执行 ? GeneratorYield(CreateIteratorResultObject(result, false))。
        5. 注:当此抽象操作的执行被 GeneratorYield 暂停时,entries 中的元素数量可能已经增加。
        6. 将 entriesCount 设置为 entries 中的元素数量。
    5. 返回 NormalCompletion(unused)。
  3. 返回 CreateIteratorFromClosure(closure, "%MapIteratorPrototype%", %MapIteratorPrototype%)。

24.1.5.2 %MapIteratorPrototype% 对象

%MapIteratorPrototype% 对象:

24.1.5.2.1 %MapIteratorPrototype%.next ( )

  1. 返回 ? GeneratorResume(this value, empty, "%MapIteratorPrototype%")。

24.1.5.2.2 %MapIteratorPrototype% [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "Map Iterator"。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

24.2 Set 对象

Set 对象是 ECMAScript 语言值的集合。Set 最多只能包含每个不同的值一次。不同的值使用 SameValueZero 比较算法的语义进行区分。

Set 对象必须使用哈希表或其他机制实现,这些机制提供的平均访问时间相对于集合中的元素数量是次线性的。本规范中使用的数据结构仅用于描述 Set 对象所要求的可观察语义。它并不旨在作为可行的实现模型。

24.2.1 Set 对象的抽象操作

24.2.1.1 Set Record

Set Record 是用于封装 Set 或类似对象接口的 Record。

Set Record 具有 表 72 中列出的字段。

表 72: Set Record 字段
字段名称 值 含义
[[SetObject]] an Object Set 或类似对象。
[[Size]] a non-negative integer or +∞ 对象所报告的大小。
[[Has]] a function object 对象的 has 方法。
[[Keys]] a function object 对象的 keys 方法。

24.2.1.2 GetSetRecord ( obj )

抽象操作 GetSetRecord,接收参数 obj (ECMAScript 语言值);返回值:(正常完成 (值:Set 记录) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 obj 不是 Object,则抛出 TypeError 异常。
  2. 令 rawSize 为 ? Get(obj, "size")。
  3. 令 numberSize 为 ? ToNumber(rawSize)。
  4. 注:如果 rawSize 是 undefined,则 numberSize 将是 NaN。
  5. 如果 numberSize 是 NaN,则抛出 TypeError 异常。
  6. 令 intSize 为 ! ToIntegerOrInfinity(numberSize)。
  7. 如果 intSize < 0,则抛出 RangeError 异常。
  8. 令 has 为 ? Get(obj, "has")。
  9. 如果 IsCallable(has) 是 false,则抛出 TypeError 异常。
  10. 令 keys 为 ? Get(obj, "keys")。
  11. 如果 IsCallable(keys) 是 false,则抛出 TypeError 异常。
  12. 返回新的 Set Record { [[SetObject]]: obj, [[Size]]: intSize, [[Has]]: has, [[Keys]]: keys }。

24.2.1.3 SetDataHas ( setData, value )

抽象操作 SetDataHas,接收参数 setData (列表 (元素:(ECMAScript 语言值 或 empty))) 和 value (ECMAScript 语言值);返回值:Boolean。 调用时执行以下步骤:

  1. 如果 SetDataIndex(setData, value) 是 not-found,则返回 false。
  2. 返回 true。

24.2.1.4 SetDataIndex ( setData, value )

抽象操作 SetDataIndex,接收参数 setData (列表 (元素:(ECMAScript 语言值 或 empty))) 和 value (ECMAScript 语言值);返回值:(非负整数 或 not-found)。 调用时执行以下步骤:

  1. 将 value 设置为 CanonicalizeKeyedCollectionKey(value)。
  2. 令 size 为 setData 中的元素数量。
  3. 令 index 为 0。
  4. 当 index < size 时,重复执行,
    1. 令 element 为 setData[index]。
    2. 如果 element 不是 empty 且 element 是 value,则
      1. 返回 index。
    3. 将 index 设置为 index + 1。
  5. 返回 not-found。

24.2.1.5 SetDataSize ( setData )

抽象操作 SetDataSize,接收参数 setData (列表 (元素:(ECMAScript 语言值 或 empty)));返回值:非负整数。 调用时执行以下步骤:

  1. 令 count 为 0。
  2. 对 setData 的每个元素 element,执行
    1. 如果 element 不是 empty,则将 count 设置为 count + 1。
  3. 返回 count。

24.2.2 Set 构造函数

Set 构造函数:

  • 是 %Set%。
  • 是全局对象的 "Set" 属性的初始值。
  • 作为构造函数调用时,创建并初始化新的 Set 对象。
  • 不旨在作为函数调用,并且以这种方式调用时会抛出异常。
  • 可以用作类定义的 extends 子句中的值。希望继承指定 Set 行为的子类构造函数必须包含对 Set 构造函数的 super 调用,以创建并初始化具有支持 Set.prototype 内置方法所必需内部状态的子类实例。

24.2.2.1 Set ( [ iterable ] )

调用时,此函数执行以下步骤:

  1. 如果 NewTarget 是 undefined,则抛出 TypeError 异常。
  2. 令 set 为 ? OrdinaryCreateFromConstructor(NewTarget, "%Set.prototype%", « [[SetData]] »)。
  3. 将 set.[[SetData]] 设置为新的空 List。
  4. 如果 iterable 是 undefined 或 null,则返回 set。
  5. 令 adder 为 ? Get(set, "add")。
  6. 如果 IsCallable(adder) 是 false,则抛出 TypeError 异常。
  7. 令 iteratorRecord 为 ? GetIterator(iterable, sync)。
  8. 重复执行,
    1. 令 next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 next 是 done,则返回 set。
    3. 令 status 为 Completion(Call(adder, set, « next »)).
    4. IfAbruptCloseIterator(status, iteratorRecord)。

24.2.3 Set 构造函数的属性

Set 构造函数:

24.2.3.1 Set.prototype

Set.prototype 的初始值是 Set 原型对象。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

24.2.3.2 get Set [ %Symbol.species% ]

Set[%Symbol.species%] 是访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数在调用时执行以下步骤:

  1. 返回 this value。

此函数的 "name" 属性的值是 "get [Symbol.species]"。

注

创建派生集合对象的方法应调用 %Symbol.species% 来确定用于创建派生对象的构造函数。子类构造函数可以覆盖 %Symbol.species% 以更改默认构造函数的指定。

24.2.4 Set 原型对象的属性

Set 原型对象:

24.2.4.1 Set.prototype.add ( value )

调用时,此方法执行以下步骤:

  1. 令 set 为 this value。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. 将 value 设置为 CanonicalizeKeyedCollectionKey(value)。
  4. 对 set.[[SetData]] 的每个元素 entry,执行
    1. 如果 entry 不是 empty 且 SameValue(entry, value) 是 true,则
      1. 返回 set。
  5. 将 value 追加到 set.[[SetData]]。
  6. 返回 set。

24.2.4.2 Set.prototype.clear ( )

调用时,此方法执行以下步骤:

  1. 令 set 为 this value。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. 对 set.[[SetData]] 的每个元素 entry,执行
    1. 将 set.[[SetData]] 中值为 entry 的元素替换为值为 empty 的元素。
  4. 返回 undefined。
注

会保留现有的 [[SetData]] List,因为可能存在已在遍历该 List 的中途暂停的 Set Iterator 对象。

24.2.4.3 Set.prototype.constructor

Set.prototype.constructor 的初始值是 %Set%。

24.2.4.4 Set.prototype.delete ( value )

调用时,此方法执行以下步骤:

  1. 令 set 为 this value。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. 将 value 设置为 CanonicalizeKeyedCollectionKey(value)。
  4. 对 set.[[SetData]] 的每个元素 entry,执行
    1. 如果 entry 不是 empty 且 SameValue(entry, value) 是 true,则
      1. 将 set.[[SetData]] 中值为 entry 的元素替换为值为 empty 的元素。
      2. 返回 true。
  5. 返回 false。
注

值 empty 用作规范机制,以指示某个条目已被删除。实际实现可以采取其他操作,例如从内部数据结构中物理删除该条目。

24.2.4.5 Set.prototype.difference ( other )

调用时,此方法执行以下步骤:

  1. 令 set 为 this value。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. 令 otherRecord 为 ? GetSetRecord(other)。
  4. 令 resultSetData 为 set.[[SetData]] 的副本。
  5. 如果 SetDataSize(set.[[SetData]]) ≤ otherRecord.[[Size]],则
    1. 令 thisSize 为 set.[[SetData]] 中的元素数量。
    2. 令 index 为 0。
    3. 当 index < thisSize 时,重复执行,
      1. 令 entry 为 resultSetData[index]。
      2. 如果 entry 不是 empty,则
        1. 令 inOther 为 ToBoolean(? Call(otherRecord.[[Has]], otherRecord.[[SetObject]], « entry »))。
        2. 如果 inOther 是 true,则
          1. 将 resultSetData[index] 设置为 empty。
      3. 将 index 设置为 index + 1。
  6. 否则,
    1. 令 keysIterator 为 ? GetIteratorFromMethod(otherRecord.[[SetObject]], otherRecord.[[Keys]])。
    2. 令 next 为 not-started。
    3. 当 next 不是 done 时,重复执行,
      1. 将 next 设置为 ? IteratorStepValue(keysIterator)。
      2. 如果 next 不是 done,则
        1. 将 next 设置为 CanonicalizeKeyedCollectionKey(next)。
        2. 令 valueIndex 为 SetDataIndex(resultSetData, next)。
        3. 如果 valueIndex 不是 not-found,则
          1. 将 resultSetData[valueIndex] 设置为 empty。
  7. 令 result 为 OrdinaryObjectCreate(%Set.prototype%, « [[SetData]] »)。
  8. 将 result.[[SetData]] 设置为 resultSetData。
  9. 返回 result。

24.2.4.6 Set.prototype.entries ( )

调用时,此方法执行以下步骤:

  1. 令 set 为 this value。
  2. 返回 ? CreateSetIterator(set, key+value)。
注

就迭代而言,Set 看起来类似于 Map,其中每个条目的键和值具有相同的值。

24.2.4.7 Set.prototype.forEach ( callback [ , thisArg ] )

调用时,此方法执行以下步骤:

  1. 令 set 为 this value。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. 如果 IsCallable(callback) 是 false,则抛出 TypeError 异常。
  4. 令 entries 为 set.[[SetData]]。
  5. 令 entriesCount 为 entries 中的元素数量。
  6. 令 index 为 0。
  7. 当 index < entriesCount 时,重复执行,
    1. 令 entry 为 entries[index]。
    2. 将 index 设置为 index + 1。
    3. 如果 entry 不是 empty,则
      1. 执行 ? Call(callback, thisArg, « entry, entry, set »)。
      2. 注:在执行 callback 期间,entries 中的元素数量可能已经增加。
      3. 将 entriesCount 设置为 entries 中的元素数量。
  8. 返回 undefined。
注

callback 应当是一个接受三个参数的函数。forEach 按值插入顺序,对 Set 对象中存在的每个值调用一次 callback。callback 只会针对 Set 中实际存在的值调用;不会针对已从 Set 中删除的键调用。

如果提供了 thisArg 参数,则每次调用 callback 时都会将其用作 this value。如果未提供,则改用 undefined。

调用 callback 时会传入三个参数:前两个参数都是 Set 中包含的值。两个参数会传入相同的值。第三个参数是正在遍历的 Set 对象。

使用三个参数调用 callback,是为了与 Map 和 Array 的 forEach 方法所使用的回调函数保持一致。对于 Set,每个条目的值同时被视为键和值。

forEach 不会直接修改调用它的对象,但对 callback 的调用可能会修改该对象。

通常每个值只会被访问一次。不过,如果一个值在被访问后被删除,然后在 forEach 调用完成前重新添加,则该值会被再次访问。调用 forEach 开始后且被访问之前删除的值不会被访问,除非该值在 forEach 调用完成前再次添加。调用 forEach 开始后添加的新值会被访问。

24.2.4.8 Set.prototype.has ( value )

调用时,此方法执行以下步骤:

  1. 令 set 为 this value。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. 将 value 设置为 CanonicalizeKeyedCollectionKey(value)。
  4. 对 set.[[SetData]] 的每个元素 entry,执行
    1. 如果 entry 不是 empty 且 SameValue(entry, value) 是 true,则返回 true。
  5. 返回 false。

24.2.4.9 Set.prototype.intersection ( other )

调用时,此方法执行以下步骤:

  1. 令 set 为 this value。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. 令 otherRecord 为 ? GetSetRecord(other)。
  4. 令 resultSetData 为新的空 List。
  5. 如果 SetDataSize(set.[[SetData]]) ≤ otherRecord.[[Size]],则
    1. 令 thisSize 为 set.[[SetData]] 中的元素数量。
    2. 令 index 为 0。
    3. 当 index < thisSize 时,重复执行,
      1. 令 entry 为 set.[[SetData]][index]。
      2. 将 index 设置为 index + 1。
      3. 如果 entry 不是 empty,则
        1. 令 inOther 为 ToBoolean(? Call(otherRecord.[[Has]], otherRecord.[[SetObject]], « entry »))。
        2. 如果 inOther 是 true,则
          1. 注:先前对 otherRecord.[[Has]] 的调用可能会删除并重新添加 set.[[SetData]] 的某个元素,这可能导致同一个元素在此次迭代期间被访问两次。
          2. 如果 SetDataHas(resultSetData, entry) 是 false,则
            1. 将 entry 追加到 resultSetData。
        3. 注:在执行 otherRecord.[[Has]] 期间,set.[[SetData]] 中的元素数量可能已经增加。
        4. 将 thisSize 设置为 set.[[SetData]] 中的元素数量。
  6. 否则,
    1. 令 keysIterator 为 ? GetIteratorFromMethod(otherRecord.[[SetObject]], otherRecord.[[Keys]])。
    2. 令 next 为 not-started。
    3. 当 next 不是 done 时,重复执行,
      1. 将 next 设置为 ? IteratorStepValue(keysIterator)。
      2. 如果 next 不是 done,则
        1. 将 next 设置为 CanonicalizeKeyedCollectionKey(next)。
        2. 令 inThis 为 SetDataHas(set.[[SetData]], next)。
        3. 如果 inThis 是 true,则
          1. 注:由于 other 是任意对象,其 "keys" 迭代器可能会多次生成相同的值。
          2. 如果 SetDataHas(resultSetData, next) 是 false,则
            1. 将 next 追加到 resultSetData。
  7. 令 result 为 OrdinaryObjectCreate(%Set.prototype%, « [[SetData]] »)。
  8. 将 result.[[SetData]] 设置为 resultSetData。
  9. 返回 result。

24.2.4.10 Set.prototype.isDisjointFrom ( other )

调用时,此方法执行以下步骤:

  1. 令 set 为 this value。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. 令 otherRecord 为 ? GetSetRecord(other)。
  4. 如果 SetDataSize(set.[[SetData]]) ≤ otherRecord.[[Size]],则
    1. 令 thisSize 为 set.[[SetData]] 中的元素数量。
    2. 令 index 为 0。
    3. 当 index < thisSize 时,重复执行,
      1. 令 entry 为 set.[[SetData]][index]。
      2. 将 index 设置为 index + 1。
      3. 如果 entry 不是 empty,则
        1. 令 inOther 为 ToBoolean(? Call(otherRecord.[[Has]], otherRecord.[[SetObject]], « entry »))。
        2. 如果 inOther 是 true,则返回 false。
        3. 注:在执行 otherRecord.[[Has]] 期间,set.[[SetData]] 中的元素数量可能已经增加。
        4. 将 thisSize 设置为 set.[[SetData]] 中的元素数量。
  5. 否则,
    1. 令 keysIterator 为 ? GetIteratorFromMethod(otherRecord.[[SetObject]], otherRecord.[[Keys]])。
    2. 令 next 为 not-started。
    3. 当 next 不是 done 时,重复执行,
      1. 将 next 设置为 ? IteratorStepValue(keysIterator)。
      2. 如果 next 不是 done,则
        1. 如果 SetDataHas(set.[[SetData]], next) 是 true,则
          1. 执行 ? IteratorClose(keysIterator, NormalCompletion(unused))。
          2. 返回 false。
  6. 返回 true。

24.2.4.11 Set.prototype.isSubsetOf ( other )

调用时,此方法执行以下步骤:

  1. 令 set 为 this value。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. 令 otherRecord 为 ? GetSetRecord(other)。
  4. 如果 SetDataSize(set.[[SetData]]) > otherRecord.[[Size]],则返回 false。
  5. 令 thisSize 为 set.[[SetData]] 中的元素数量。
  6. 令 index 为 0。
  7. 当 index < thisSize 时,重复执行,
    1. 令 entry 为 set.[[SetData]][index]。
    2. 将 index 设置为 index + 1。
    3. 如果 entry 不是 empty,则
      1. 令 inOther 为 ToBoolean(? Call(otherRecord.[[Has]], otherRecord.[[SetObject]], « entry »))。
      2. 如果 inOther 是 false,则返回 false。
      3. 注:在执行 otherRecord.[[Has]] 期间,set.[[SetData]] 中的元素数量可能已经增加。
      4. 将 thisSize 设置为 set.[[SetData]] 中的元素数量。
  8. 返回 true。

24.2.4.12 Set.prototype.isSupersetOf ( other )

调用时,此方法执行以下步骤:

  1. 令 set 为 this value。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. 令 otherRecord 为 ? GetSetRecord(other)。
  4. 如果 SetDataSize(set.[[SetData]]) < otherRecord.[[Size]],则返回 false。
  5. 令 keysIterator 为 ? GetIteratorFromMethod(otherRecord.[[SetObject]], otherRecord.[[Keys]])。
  6. 令 next 为 not-started。
  7. 当 next 不是 done 时,重复执行,
    1. 将 next 设置为 ? IteratorStepValue(keysIterator)。
    2. 如果 next 不是 done,则
      1. 如果 SetDataHas(set.[[SetData]], next) 是 false,则
        1. 执行 ? IteratorClose(keysIterator, NormalCompletion(unused))。
        2. 返回 false。
  8. 返回 true。

24.2.4.13 Set.prototype.keys ( )

"keys" 属性的初始值是 24.2.4.17 中定义的 %Set.prototype.values%。

注

就迭代而言,Set 看起来类似于 Map,其中每个条目的键和值具有相同的值。

24.2.4.14 get Set.prototype.size

Set.prototype.size 是访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数在调用时执行以下步骤:

  1. 令 set 为 this value。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. 令 size 为 SetDataSize(set.[[SetData]])。
  4. 返回 𝔽(size)。

24.2.4.15 Set.prototype.symmetricDifference ( other )

调用时,此方法执行以下步骤:

  1. 令 set 为 this value。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. 令 otherRecord 为 ? GetSetRecord(other)。
  4. 令 keysIterator 为 ? GetIteratorFromMethod(otherRecord.[[SetObject]], otherRecord.[[Keys]])。
  5. 令 resultSetData 为 set.[[SetData]] 的副本。
  6. 令 next 为 not-started。
  7. 当 next 不是 done 时,重复执行,
    1. 将 next 设置为 ? IteratorStepValue(keysIterator)。
    2. 如果 next 不是 done,则
      1. 将 next 设置为 CanonicalizeKeyedCollectionKey(next)。
      2. 令 resultIndex 为 SetDataIndex(resultSetData, next)。
      3. 如果 resultIndex 是 not-found,则令 alreadyInResult 为 false;否则令 alreadyInResult 为 true。
      4. 如果 SetDataHas(set.[[SetData]], next) 是 true,则
        1. 如果 alreadyInResult 是 true,则将 resultSetData[resultIndex] 设置为 empty。
      5. 否则,
        1. 如果 alreadyInResult 是 false,则将 next 追加到 resultSetData。
  8. 令 result 为 OrdinaryObjectCreate(%Set.prototype%, « [[SetData]] »)。
  9. 将 result.[[SetData]] 设置为 resultSetData。
  10. 返回 result。

24.2.4.16 Set.prototype.union ( other )

调用时,此方法执行以下步骤:

  1. 令 set 为 this value。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. 令 otherRecord 为 ? GetSetRecord(other)。
  4. 令 keysIterator 为 ? GetIteratorFromMethod(otherRecord.[[SetObject]], otherRecord.[[Keys]])。
  5. 令 resultSetData 为 set.[[SetData]] 的副本。
  6. 令 next 为 not-started。
  7. 当 next 不是 done 时,重复执行,
    1. 将 next 设置为 ? IteratorStepValue(keysIterator)。
    2. 如果 next 不是 done,则
      1. 将 next 设置为 CanonicalizeKeyedCollectionKey(next)。
      2. 如果 SetDataHas(resultSetData, next) 是 false,则
        1. 将 next 追加到 resultSetData。
  8. 令 result 为 OrdinaryObjectCreate(%Set.prototype%, « [[SetData]] »)。
  9. 将 result.[[SetData]] 设置为 resultSetData。
  10. 返回 result。

24.2.4.17 Set.prototype.values ( )

调用时,此方法执行以下步骤:

  1. 令 set 为 this value。
  2. 返回 ? CreateSetIterator(set, value)。

24.2.4.18 Set.prototype [ %Symbol.iterator% ] ( )

%Symbol.iterator% 属性的初始值是 24.2.4.17 中定义的 %Set.prototype.values%。

24.2.4.19 Set.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "Set"。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

24.2.5 Set 实例的属性

Set 实例是从 Set 原型对象继承属性的普通对象。Set 实例还具有 [[SetData]] 内部槽。

24.2.6 Set 迭代器对象

Set Iterator 是具有下述结构的普通对象,表示对某个特定 Set 实例对象进行某次特定迭代。Set Iterator 对象没有具名构造函数。相反,Set Iterator 对象通过调用 Set 实例对象的某些方法创建。

24.2.6.1 CreateSetIterator ( set, kind )

抽象操作 CreateSetIterator,接收参数 set (ECMAScript 语言值) 和 kind ((key+value 或 value));返回值:(正常完成 (值:Generator) 或 抛出完成)。 它用于为返回此类迭代器的 Set 方法创建迭代器对象。 调用时执行以下步骤:

  1. 执行 ? RequireInternalSlot(set, [[SetData]])。
  2. 令 closure 为不带参数的新 Abstract Closure,它捕获 set 和 kind,并在被调用时执行以下步骤:
    1. 令 index 为 0。
    2. 令 entries 为 set.[[SetData]]。
    3. 令 entriesCount 为 entries 中的元素数量。
    4. 当 index < entriesCount 时,重复执行,
      1. 令 entry 为 entries[index]。
      2. 将 index 设置为 index + 1。
      3. 如果 entry 不是 empty,则
        1. 如果 kind 是 key+value,则
          1. 令 result 为 CreateArrayFromList(« entry, entry »)。
          2. 执行 ? GeneratorYield(CreateIteratorResultObject(result, false))。
        2. 否则,
          1. 断言:kind 是 value。
          2. 执行 ? GeneratorYield(CreateIteratorResultObject(entry, false))。
        3. 注:当此抽象操作的执行被 GeneratorYield 暂停时,entries 中的元素数量可能已经增加。
        4. 将 entriesCount 设置为 entries 中的元素数量。
    5. 返回 NormalCompletion(unused)。
  3. 返回 CreateIteratorFromClosure(closure, "%SetIteratorPrototype%", %SetIteratorPrototype%)。

24.2.6.2 %SetIteratorPrototype% 对象

%SetIteratorPrototype% 对象:

24.2.6.2.1 %SetIteratorPrototype%.next ( )

  1. 返回 ? GeneratorResume(this value, empty, "%SetIteratorPrototype%")。

24.2.6.2.2 %SetIteratorPrototype% [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "Set Iterator"。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

24.3 WeakMap 对象

WeakMap 是键/值对的集合,其中键是对象和/或符号,而值可以是任意 ECMAScript 语言值。可以查询 WeakMap 是否包含具有特定键的键/值对,但没有提供枚举其作为键保存的值的机制。在某些条件下,不再存活的值会从 WeakMap 键中移除,如 9.9.3 所述。

实现可以在 WeakMap 的某个键/值对变得不可访问的时间与该键/值对从 WeakMap 中移除的时间之间施加任意确定的延迟。如果 ECMAScript 程序能够观察到这种延迟,它将成为可能影响程序执行的不确定性来源。因此,ECMAScript 实现不得提供任何方式来观察 WeakMap 的某个键,除非观察者必须提供被观察的键。

WeakMap 必须使用哈希表或其他机制实现,这些机制提供的平均访问时间相对于集合中的键/值对数量是次线性的。本规范中使用的数据结构仅用于描述 WeakMap 所要求的可观察语义。它并不旨在作为可行的实现模型。

注

WeakMap 和 WeakSet 旨在提供一种动态地将状态与对象或符号关联的机制,并且当不存在 WeakMap 或 WeakSet 实例时,如果该对象或符号原本会变得不可访问并由实现的垃圾回收机制回收资源,则不会“泄漏”内存资源。可以通过使用反向的每对象/符号映射,将 WeakMap 或 WeakSet 实例映射到键,从而实现此特性。或者,每个 WeakMap 或 WeakSet 实例可以在内部存储其键和值数据,但这种方法要求 WeakMap 或 WeakSet 实现与垃圾回收器之间进行协调。以下参考资料描述了可能对 WeakMap 和 WeakSet 实现有用的机制:

Barry Hayes. 1997. Ephemerons: a new finalization mechanism. In Proceedings of the 12th ACM SIGPLAN conference on Object-oriented programming, systems, languages, and applications (OOPSLA '97), A. Michael Berman (Ed.). ACM, New York, NY, USA, 176-183, http://doi.acm.org/10.1145/263698.263733.

Alexandra Barros, Roberto Ierusalimschy, Eliminating Cycles in Weak Tables. Journal of Universal Computer Science - J.UCS, vol. 14, no. 21, pp. 3481-3497, 2008, http://www.jucs.org/jucs_14_21/eliminating_cycles_in_weak

24.3.1 WeakMap 构造函数

WeakMap 构造函数:

  • 是 %WeakMap%。
  • 是全局对象的 "WeakMap" 属性的初始值。
  • 作为构造函数调用时,创建并初始化新的 WeakMap。
  • 不旨在作为函数调用,并且以这种方式调用时会抛出异常。
  • 可以用作类定义的 extends 子句中的值。希望继承指定 WeakMap 行为的子类构造函数必须包含对 WeakMap 构造函数的 super 调用,以创建并初始化具有支持 WeakMap.prototype 内置方法所必需内部状态的子类实例。

24.3.1.1 WeakMap ( [ iterable ] )

调用时,此函数执行以下步骤:

  1. 如果 NewTarget 是 undefined,则抛出 TypeError 异常。
  2. 令 map 为 ? OrdinaryCreateFromConstructor(NewTarget, "%WeakMap.prototype%", « [[WeakMapData]] »)。
  3. 将 map.[[WeakMapData]] 设置为新的空 List。
  4. 如果 iterable 是 undefined 或 null,则返回 map。
  5. 令 adder 为 ? Get(map, "set")。
  6. 如果 IsCallable(adder) 是 false,则抛出 TypeError 异常。
  7. 返回 ? AddEntriesFromIterable(map, iterable, adder)。
注

如果存在参数 iterable,则预期它是一个实现了 %Symbol.iterator% 方法的对象,该方法返回一个迭代器对象,此迭代器对象会生成一个包含两个元素的类数组对象,其中第一个元素是将用作 WeakMap 键的值,第二个元素是要与该键关联的值。

24.3.2 WeakMap 构造函数的属性

WeakMap 构造函数:

24.3.2.1 WeakMap.prototype

WeakMap.prototype 的初始值是 WeakMap 原型对象。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

24.3.3 WeakMap 原型对象的属性

WeakMap 原型对象:

  • 是 %WeakMap.prototype%。
  • 具有 [[Prototype]] 内部槽,其值是 %Object.prototype%。
  • 是普通对象。
  • 不具有 [[WeakMapData]] 内部槽。

24.3.3.1 WeakMap.prototype.constructor

WeakMap.prototype.constructor 的初始值是 %WeakMap%。

24.3.3.2 WeakMap.prototype.delete ( key )

调用时,此方法执行以下步骤:

  1. 令 weakMap 为 this value。
  2. 执行 ? RequireInternalSlot(weakMap, [[WeakMapData]])。
  3. 如果 CanBeHeldWeakly(key) 是 false,则返回 false。
  4. 对 weakMap.[[WeakMapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 empty 且 SameValue(entry.[[Key]], key) 是 true,则
      1. 将 entry.[[Key]] 设置为 empty。
      2. 将 entry.[[Value]] 设置为 empty。
      3. 返回 true。
  5. 返回 false。
注

值 empty 用作规范机制,以指示某个条目已被删除。实际实现可以采取其他操作,例如从内部数据结构中物理删除该条目。

24.3.3.3 WeakMap.prototype.get ( key )

调用时,此方法执行以下步骤:

  1. 令 weakMap 为 this value。
  2. 执行 ? RequireInternalSlot(weakMap, [[WeakMapData]])。
  3. 如果 CanBeHeldWeakly(key) 是 false,则返回 undefined。
  4. 对 weakMap.[[WeakMapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 empty 且 SameValue(entry.[[Key]], key) 是 true,则返回 entry.[[Value]]。
  5. 返回 undefined。

24.3.3.4 WeakMap.prototype.getOrInsert ( key, value )

调用时,此方法执行以下步骤:

  1. 令 weakMap 为 this value。
  2. 执行 ? RequireInternalSlot(weakMap, [[WeakMapData]])。
  3. 如果 CanBeHeldWeakly(key) 是 false,则抛出 TypeError 异常。
  4. 对 weakMap.[[WeakMapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 empty 且 SameValue(entry.[[Key]], key) 是 true,则返回 entry.[[Value]]。
  5. 令 entry 为 Record { [[Key]]: key, [[Value]]: value }。
  6. 将 entry 追加到 weakMap.[[WeakMapData]]。
  7. 返回 value。

24.3.3.5 WeakMap.prototype.getOrInsertComputed ( key, callback )

调用时,此方法执行以下步骤:

  1. 令 weakMap 为 this value。
  2. 执行 ? RequireInternalSlot(weakMap, [[WeakMapData]])。
  3. 如果 CanBeHeldWeakly(key) 是 false,则抛出 TypeError 异常。
  4. 如果 IsCallable(callback) 是 false,则抛出 TypeError 异常。
  5. 对 weakMap.[[WeakMapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 empty 且 SameValue(entry.[[Key]], key) 是 true,则返回 entry.[[Value]]。
  6. 令 value 为 ? Call(callback, undefined, « key »)。
  7. 注:在执行 callback 期间,WeakMap 可能已经被修改。
  8. 对 weakMap.[[WeakMapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 empty 且 SameValue(entry.[[Key]], key) 是 true,则
      1. 将 entry.[[Value]] 设置为 value。
      2. 返回 value。
  9. 令 entry 为 Record { [[Key]]: key, [[Value]]: value }。
  10. 将 entry 追加到 weakMap.[[WeakMapData]]。
  11. 返回 value。

24.3.3.6 WeakMap.prototype.has ( key )

调用时,此方法执行以下步骤:

  1. 令 weakMap 为 this value。
  2. 执行 ? RequireInternalSlot(weakMap, [[WeakMapData]])。
  3. 如果 CanBeHeldWeakly(key) 是 false,则返回 false。
  4. 对 weakMap.[[WeakMapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 empty 且 SameValue(entry.[[Key]], key) 是 true,则返回 true。
  5. 返回 false。

24.3.3.7 WeakMap.prototype.set ( key, value )

调用时,此方法执行以下步骤:

  1. 令 weakMap 为 this value。
  2. 执行 ? RequireInternalSlot(weakMap, [[WeakMapData]])。
  3. 如果 CanBeHeldWeakly(key) 是 false,则抛出 TypeError 异常。
  4. 对 weakMap.[[WeakMapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 empty 且 SameValue(entry.[[Key]], key) 是 true,则
      1. 将 entry.[[Value]] 设置为 value。
      2. 返回 weakMap。
  5. 令 entry 为 Record { [[Key]]: key, [[Value]]: value }。
  6. 将 entry 追加到 weakMap.[[WeakMapData]]。
  7. 返回 weakMap。

24.3.3.8 WeakMap.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "WeakMap"。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

24.3.4 WeakMap 实例的属性

WeakMap 实例是从 WeakMap 原型对象继承属性的普通对象。WeakMap 实例还具有 [[WeakMapData]] 内部槽。

24.4 WeakSet 对象

WeakSet 是对象和/或符号的集合。一个不同的对象或符号在 WeakSet 的集合中只能作为元素出现一次。可以查询 WeakSet 是否包含某个特定值,但没有提供枚举其所保存值的机制。在某些条件下,不再存活的值会从 WeakSet 元素中移除,如 9.9.3 所述。

实现可以在 WeakSet 中包含的某个值变得不可访问的时间与该值从 WeakSet 中移除的时间之间施加任意确定的延迟。如果 ECMAScript 程序能够观察到这种延迟,它将成为可能影响程序执行的不确定性来源。因此,ECMAScript 实现不得提供任何方式来确定 WeakSet 是否包含某个特定值,除非观察者必须提供被观察的值。

WeakSet 必须使用哈希表或其他机制实现,这些机制提供的平均访问时间相对于集合中的元素数量是次线性的。本规范中使用的数据结构仅用于描述 WeakSet 所要求的可观察语义。它并不旨在作为可行的实现模型。

注

参见 24.3 中的注。

24.4.1 WeakSet 构造函数

WeakSet 构造函数:

  • 是 %WeakSet%。
  • 是全局对象的 "WeakSet" 属性的初始值。
  • 作为构造函数调用时,创建并初始化新的 WeakSet。
  • 不旨在作为函数调用,并且以这种方式调用时会抛出异常。
  • 可以用作类定义的 extends 子句中的值。希望继承指定 WeakSet 行为的子类构造函数必须包含对 WeakSet 构造函数的 super 调用,以创建并初始化具有支持 WeakSet.prototype 内置方法所必需内部状态的子类实例。

24.4.1.1 WeakSet ( [ iterable ] )

调用时,此函数执行以下步骤:

  1. 如果 NewTarget 是 undefined,则抛出 TypeError 异常。
  2. 令 set 为 ? OrdinaryCreateFromConstructor(NewTarget, "%WeakSet.prototype%", « [[WeakSetData]] »)。
  3. 将 set.[[WeakSetData]] 设置为新的空 List。
  4. 如果 iterable 是 undefined 或 null,则返回 set。
  5. 令 adder 为 ? Get(set, "add")。
  6. 如果 IsCallable(adder) 是 false,则抛出 TypeError 异常。
  7. 令 iteratorRecord 为 ? GetIterator(iterable, sync)。
  8. 重复执行,
    1. 令 next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 next 是 done,则返回 set。
    3. 令 status 为 Completion(Call(adder, set, « next »)).
    4. IfAbruptCloseIterator(status, iteratorRecord)。

24.4.2 WeakSet 构造函数的属性

WeakSet 构造函数:

24.4.2.1 WeakSet.prototype

WeakSet.prototype 的初始值是 WeakSet 原型对象。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

24.4.3 WeakSet 原型对象的属性

WeakSet 原型对象:

  • 是 %WeakSet.prototype%。
  • 具有 [[Prototype]] 内部槽,其值是 %Object.prototype%。
  • 是普通对象。
  • 不具有 [[WeakSetData]] 内部槽。

24.4.3.1 WeakSet.prototype.add ( value )

调用时,此方法执行以下步骤:

  1. 令 weakSet 为 this value。
  2. 执行 ? RequireInternalSlot(weakSet, [[WeakSetData]])。
  3. 如果 CanBeHeldWeakly(value) 是 false,则抛出 TypeError 异常。
  4. 对 weakSet.[[WeakSetData]] 的每个元素 entry,执行
    1. 如果 entry 不是 empty 且 SameValue(entry, value) 是 true,则
      1. 返回 weakSet。
  5. 将 value 追加到 weakSet.[[WeakSetData]]。
  6. 返回 weakSet。

24.4.3.2 WeakSet.prototype.constructor

WeakSet.prototype.constructor 的初始值是 %WeakSet%。

24.4.3.3 WeakSet.prototype.delete ( value )

调用时,此方法执行以下步骤:

  1. 令 weakSet 为 this value。
  2. 执行 ? RequireInternalSlot(weakSet, [[WeakSetData]])。
  3. 如果 CanBeHeldWeakly(value) 是 false,则返回 false。
  4. 对 weakSet.[[WeakSetData]] 的每个元素 entry,执行
    1. 如果 entry 不是 empty 且 SameValue(entry, value) 是 true,则
      1. 将 weakSet.[[WeakSetData]] 中值为 entry 的元素替换为值为 empty 的元素。
      2. 返回 true。
  5. 返回 false。
注

值 empty 用作规范机制,以指示某个条目已被删除。实际实现可以采取其他操作,例如从内部数据结构中物理删除该条目。

24.4.3.4 WeakSet.prototype.has ( value )

调用时,此方法执行以下步骤:

  1. 令 weakSet 为 this value。
  2. 执行 ? RequireInternalSlot(weakSet, [[WeakSetData]])。
  3. 如果 CanBeHeldWeakly(value) 是 false,则返回 false。
  4. 对 weakSet.[[WeakSetData]] 的每个元素 entry,执行
    1. 如果 entry 不是 empty 且 SameValue(entry, value) 是 true,则返回 true。
  5. 返回 false。

24.4.3.5 WeakSet.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "WeakSet"。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

24.4.4 WeakSet 实例的属性

WeakSet 实例是从 WeakSet 原型对象继承属性的普通对象。WeakSet 实例还具有 [[WeakSetData]] 内部槽。

24.5 键控集合的抽象操作

24.5.1 CanonicalizeKeyedCollectionKey ( key )

抽象操作 CanonicalizeKeyedCollectionKey,接收参数 key (ECMAScript 语言值);返回值:ECMAScript 语言值。 调用时执行以下步骤:

  1. 如果 key 是 -0𝔽,则返回 +0𝔽。
  2. 返回 key。

25 结构化数据

25.1 ArrayBuffer 对象

25.1.1 记号

本节、25.4 和 29 中的以下描述使用读-修改-写修改函数内部数据结构。

读-修改-写修改函数是一个数学函数,表示为接受两个字节值 List 作为参数并返回一个字节值 List 的 Abstract Closure。这些 Abstract Closure 满足以下所有属性:

  • 它们以原子方式执行其所有算法步骤。
  • 它们的各个算法步骤不可观察。
注

为了帮助验证读-修改-写修改函数的算法步骤构成纯数学函数,建议遵循以下编辑约定:

25.1.2 固定长度和可调整大小的 ArrayBuffer 对象

固定长度 ArrayBuffer 是创建后字节长度不能改变的 ArrayBuffer。

可调整大小的 ArrayBuffer 是创建后可以通过调用 ArrayBuffer.prototype.resize ( newLength ) 改变字节长度的 ArrayBuffer。

创建的 ArrayBuffer 对象种类取决于传递给 ArrayBuffer ( length [ , options ] ) 的参数。

25.1.3 ArrayBuffer 对象的抽象操作

25.1.3.1 AllocateArrayBuffer ( ctor, byteLength [ , maxByteLength ] )

抽象操作 AllocateArrayBuffer,接收参数 ctor (构造函数) 和 byteLength (非负整数)和可选参数 maxByteLength ((非负整数 或 empty));返回值:(正常完成 (值:ArrayBuffer) 或 抛出完成)。 它用于创建 ArrayBuffer。 调用时执行以下步骤:

  1. 令 slots 为 « [[ArrayBufferData]], [[ArrayBufferByteLength]], [[ArrayBufferDetachKey]] »。
  2. 如果存在 maxByteLength 且 maxByteLength 不是 empty,则令 allocatingResizableBuffer 为 true;否则令 allocatingResizableBuffer 为 false。
  3. 如果 allocatingResizableBuffer 是 true,则
    1. 如果 byteLength > maxByteLength,则抛出 RangeError 异常。
    2. 将 [[ArrayBufferMaxByteLength]] 追加到 slots。
  4. 令 obj 为 ? OrdinaryCreateFromConstructor(ctor, "%ArrayBuffer.prototype%", slots)。
  5. 令 block 为 ? CreateByteDataBlock(byteLength)。
  6. 将 obj.[[ArrayBufferData]] 设置为 block。
  7. 将 obj.[[ArrayBufferByteLength]] 设置为 byteLength。
  8. 如果 allocatingResizableBuffer 是 true,则
    1. 如果无法创建由 maxByteLength 个字节组成的 Data Block block,则抛出 RangeError 异常。
    2. 注:可调整大小的 ArrayBuffer 被设计为可通过原地增长实现。例如,如果无法预先保留虚拟内存,实现可以抛出异常。
    3. 将 obj.[[ArrayBufferMaxByteLength]] 设置为 maxByteLength。
  9. 返回 obj。

25.1.3.2 ArrayBufferByteLength ( arrayBuffer, order )

抽象操作 ArrayBufferByteLength,接收参数 arrayBuffer ((ArrayBuffer 或 SharedArrayBuffer)) 和 order ((seq-cst 或 unordered));返回值:非负整数。 调用时执行以下步骤:

  1. 如果 IsGrowableSharedArrayBuffer(arrayBuffer) 是 true,则
    1. 令 bufferByteLengthBlock 为 arrayBuffer.[[ArrayBufferByteLengthData]]。
    2. 令 rawLength 为 GetRawBytesFromSharedBlock(bufferByteLengthBlock, 0, biguint64, true, order)。
    3. 令 agentRecord 为周围代理的 Agent Record。
    4. 令 isLittleEndian 为 agentRecord.[[LittleEndian]]。
    5. 返回 ℝ(RawBytesToNumeric(biguint64, rawLength, isLittleEndian))。
  2. 断言:IsDetachedBuffer(arrayBuffer) 是 false。
  3. 返回 arrayBuffer.[[ArrayBufferByteLength]]。

25.1.3.3 ArrayBufferCopyAndDetach ( arrayBuffer, newLength, preserveResizability )

抽象操作 ArrayBufferCopyAndDetach,接收参数 arrayBuffer (ECMAScript 语言值)、newLength (ECMAScript 语言值) 和 preserveResizability ((preserve-resizability 或 fixed-length));返回值:(正常完成 (值:ArrayBuffer) 或 抛出完成)。 调用时执行以下步骤:

  1. 执行 ? RequireInternalSlot(arrayBuffer, [[ArrayBufferData]])。
  2. 如果 IsSharedArrayBuffer(arrayBuffer) 是 true,则抛出 TypeError 异常。
  3. 如果 newLength 是 undefined,则
    1. 令 newByteLength 为 arrayBuffer.[[ArrayBufferByteLength]]。
  4. 否则,
    1. 令 newByteLength 为 ? ToIndex(newLength)。
  5. 如果 IsDetachedBuffer(arrayBuffer) 是 true,则抛出 TypeError 异常。
  6. 如果 preserveResizability 是 preserve-resizability 且 IsFixedLengthArrayBuffer(arrayBuffer) 是 false,则
    1. 令 newMaxByteLength 为 arrayBuffer.[[ArrayBufferMaxByteLength]]。
  7. 否则,
    1. 令 newMaxByteLength 为 empty。
  8. 如果 arrayBuffer.[[ArrayBufferDetachKey]] 不是 undefined,则抛出 TypeError 异常。
  9. 令 newBuffer 为 ? AllocateArrayBuffer(%ArrayBuffer%, newByteLength, newMaxByteLength)。
  10. 令 copyLength 为 min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]])。
  11. 令 fromBlock 为 arrayBuffer.[[ArrayBufferData]]。
  12. 令 toBlock 为 newBuffer.[[ArrayBufferData]]。
  13. 执行 CopyDataBlockBytes(toBlock, 0, fromBlock, 0, copyLength)。
  14. 注:创建新的 Data Block 和从旧 Data Block 复制都不可观察。实现可以将此方法实现为零复制移动或 realloc。
  15. 执行 ! DetachArrayBuffer(arrayBuffer)。
  16. 返回 newBuffer。

25.1.3.4 IsDetachedBuffer ( arrayBuffer )

抽象操作 IsDetachedBuffer,接收参数 arrayBuffer ((ArrayBuffer 或 SharedArrayBuffer));返回值:Boolean。 调用时执行以下步骤:

  1. 如果 arrayBuffer.[[ArrayBufferData]] 是 null,则返回 true。
  2. 返回 false。

25.1.3.5 DetachArrayBuffer ( arrayBuffer [ , key ] )

抽象操作 DetachArrayBuffer,接收参数 arrayBuffer (ArrayBuffer)和可选参数 key (任意值);返回值:(正常完成 (值:unused) 或 抛出完成)。 调用时执行以下步骤:

  1. 断言:IsSharedArrayBuffer(arrayBuffer) 是 false。
  2. 如果不存在 key,则将 key 设置为 undefined。
  3. 如果 arrayBuffer.[[ArrayBufferDetachKey]] 不是 key,则抛出 TypeError 异常。
  4. 将 arrayBuffer.[[ArrayBufferData]] 设置为 null。
  5. 将 arrayBuffer.[[ArrayBufferByteLength]] 设置为 0。
  6. 返回 unused。
注

分离 ArrayBuffer 实例会将用作其后备存储的 Data Block 与该实例解除关联,并将缓冲区的字节长度设置为 0。

25.1.3.6 CloneArrayBuffer ( sourceBuffer, sourceByteOffset, sourceLength )

抽象操作 CloneArrayBuffer,接收参数 sourceBuffer ((ArrayBuffer 或 SharedArrayBuffer))、sourceByteOffset (非负整数) 和 sourceLength (非负整数);返回值:(正常完成 (值:ArrayBuffer) 或 抛出完成)。 它创建一个新的 ArrayBuffer,其数据是 sourceBuffer 数据中从 sourceByteOffset 开始并持续 sourceLength 个字节范围的副本。 调用时执行以下步骤:

  1. 断言:IsDetachedBuffer(sourceBuffer) 是 false。
  2. 令 targetBuffer 为 ? AllocateArrayBuffer(%ArrayBuffer%, sourceLength)。
  3. 令 sourceBlock 为 sourceBuffer.[[ArrayBufferData]]。
  4. 令 targetBlock 为 targetBuffer.[[ArrayBufferData]]。
  5. 执行 CopyDataBlockBytes(targetBlock, 0, sourceBlock, sourceByteOffset, sourceLength)。
  6. 返回 targetBuffer。

25.1.3.7 GetArrayBufferMaxByteLengthOption ( options )

抽象操作 GetArrayBufferMaxByteLengthOption,接收参数 options (ECMAScript 语言值);返回值:(正常完成 (值:(非负整数 或 empty)) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 options 不是 Object,则返回 empty。
  2. 令 maxByteLength 为 ? Get(options, "maxByteLength")。
  3. 如果 maxByteLength 是 undefined,则返回 empty。
  4. 返回 ? ToIndex(maxByteLength)。

25.1.3.8 HostResizeArrayBuffer ( buffer, newByteLength )

宿主定义的抽象操作 HostResizeArrayBuffer,接收参数 buffer (ArrayBuffer) 和 newByteLength (非负整数);返回值:(正常完成 (值:(handled 或 unhandled)) 或 抛出完成)。 它为宿主提供执行由实现定义的 buffer 大小调整的机会。如果宿主选择不处理 buffer 的大小调整,则可以返回 unhandled 以使用默认行为。

HostResizeArrayBuffer 的实现必须符合以下要求:

HostResizeArrayBuffer 的默认实现是返回 NormalCompletion(unhandled)。

25.1.3.9 IsFixedLengthArrayBuffer ( arrayBuffer )

抽象操作 IsFixedLengthArrayBuffer,接收参数 arrayBuffer ((ArrayBuffer 或 SharedArrayBuffer));返回值:Boolean。 调用时执行以下步骤:

  1. 如果 arrayBuffer 具有 [[ArrayBufferMaxByteLength]] 内部槽,则返回 false。
  2. 返回 true。

25.1.3.10 IsUnsignedElementType ( type )

抽象操作 IsUnsignedElementType,接收参数 type (TypedArray 元素类型);返回值:Boolean。 它验证参数 type 是否为无符号 TypedArray 元素类型。 调用时执行以下步骤:

  1. 如果 type 是 uint8、uint8clamped、uint16、uint32 或 biguint64 之一,则返回 true。
  2. 返回 false。

25.1.3.11 IsUnclampedIntegerElementType ( type )

抽象操作 IsUnclampedIntegerElementType,接收参数 type (TypedArray 元素类型);返回值:Boolean。 它验证参数 type 是否为不包括 uint8clamped 的整数 TypedArray 元素类型。 调用时执行以下步骤:

  1. 如果 type 是 int8、uint8、int16、uint16、int32 或 uint32 之一,则返回 true。
  2. 返回 false。

25.1.3.12 IsBigIntElementType ( type )

抽象操作 IsBigIntElementType,接收参数 type (TypedArray 元素类型);返回值:Boolean。 它验证参数 type 是否为 BigInt TypedArray 元素类型。 调用时执行以下步骤:

  1. 如果 type 是 biguint64 或 bigint64,则返回 true。
  2. 返回 false。

25.1.3.13 IsNoTearConfiguration ( type, order )

抽象操作 IsNoTearConfiguration,接收参数 type (TypedArray 元素类型) 和 order ((seq-cst、unordered 或 init));返回值:Boolean。 调用时执行以下步骤:

  1. 如果 IsUnclampedIntegerElementType(type) 是 true,则返回 true。
  2. 如果 IsBigIntElementType(type) 是 true 且 order 是 seq-cst,则返回 true。
  3. 返回 false。

25.1.3.14 RawBytesToNumeric ( type, rawBytes, isLittleEndian )

抽象操作 RawBytesToNumeric,接收参数 type (TypedArray 元素类型)、rawBytes (列表 (元素:字节值)) 和 isLittleEndian (Boolean);返回值:(Number 或 BigInt)。 调用时执行以下步骤:

  1. 令 elementSize 为 表 71 中为 Element Type type 指定的 Element Size 值。
  2. 如果 isLittleEndian 是 false,则反转 rawBytes 中元素的顺序。
  3. 如果 type 是 float16,则
    1. 令 value 为将 rawBytes 的字节元素连接起来,并解释为 IEEE 754-2019 binary16 值的小端位字符串编码。
    2. 如果 value 是 NaN,则返回 NaN。
    3. 返回与 value 对应的 Number 值。
  4. 如果 type 是 float32,则
    1. 令 value 为将 rawBytes 的字节元素连接起来,并解释为 IEEE 754-2019 binary32 值的小端位字符串编码。
    2. 如果 value 是 NaN,则返回 NaN。
    3. 返回与 value 对应的 Number 值。
  5. 如果 type 是 float64,则
    1. 令 value 为将 rawBytes 的字节元素连接起来,并解释为 IEEE 754-2019 binary64 值的小端位字符串编码。
    2. 如果 value 是 NaN,则返回 NaN。
    3. 返回与 value 对应的 Number 值。
  6. 如果 IsUnsignedElementType(type) 是 true,则
    1. 令 intValue 为将 rawBytes 的字节元素连接起来,并解释为无符号小端二进制数的位字符串编码。
  7. 否则,
    1. 令 intValue 为将 rawBytes 的字节元素连接起来,并解释为位长度为 elementSize × 8 的二进制小端二进制补码数的位字符串编码。
  8. 如果 IsBigIntElementType(type) 是 true,则返回与 intValue 对应的 BigInt 值。
  9. 返回与 intValue 对应的 Number 值。

25.1.3.15 GetRawBytesFromSharedBlock ( block, byteIndex, type, isTypedArray, order )

抽象操作 GetRawBytesFromSharedBlock,接收参数 block (共享数据块)、byteIndex (非负整数)、type (TypedArray 元素类型)、isTypedArray (Boolean) 和 order ((seq-cst 或 unordered));返回值:列表 (元素:字节值)。 调用时执行以下步骤:

  1. 令 elementSize 为 表 71 中为 Element Type type 指定的 Element Size 值。
  2. 令 agentRecord 为周围代理的 Agent Record。
  3. 令 execution 为 agentRecord.[[CandidateExecution]]。
  4. 令 eventsRecord 为 execution.[[EventsRecords]] 中 [[AgentSignifier]] 为 AgentSignifier() 的 Agent Events Record。
  5. 如果 isTypedArray 是 true 且 IsNoTearConfiguration(type, order) 是 true,则令 noTear 为 true;否则令 noTear 为 false。
  6. 令 rawValue 为长度为 elementSize 的 List,其元素是非确定性选择的字节值。
  7. 注:在实现中,rawValue 是底层硬件上的非原子或原子读取指令的结果。非确定性是内存模型的语义规定,用于描述弱一致性硬件的可观察行为。
  8. 令 readEvent 为 ReadSharedMemory { [[Order]]: order, [[NoTear]]: noTear, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize }。
  9. 将 readEvent 追加到 eventsRecord.[[EventList]]。
  10. 将 Chosen Value Record { [[Event]]: readEvent, [[ChosenValue]]: rawValue } 追加到 execution.[[ChosenValues]]。
  11. 返回 rawValue。

25.1.3.16 GetValueFromBuffer ( arrayBuffer, byteIndex, type, isTypedArray, order [ , isLittleEndian ] )

抽象操作 GetValueFromBuffer,接收参数 arrayBuffer ((ArrayBuffer 或 SharedArrayBuffer))、byteIndex (非负整数)、type (TypedArray 元素类型)、isTypedArray (Boolean) 和 order ((seq-cst 或 unordered))和可选参数 isLittleEndian (Boolean);返回值:(Number 或 BigInt)。 调用时执行以下步骤:

  1. 断言:IsDetachedBuffer(arrayBuffer) 是 false。
  2. 断言:arrayBuffer 中从 byteIndex 开始有足够的字节来表示 type 的值。
  3. 令 block 为 arrayBuffer.[[ArrayBufferData]]。
  4. 令 elementSize 为 表 71 中为 Element Type type 指定的 Element Size 值。
  5. 如果 IsSharedArrayBuffer(arrayBuffer) 是 true,则
    1. 断言:block 是 Shared Data Block。
    2. 令 rawValue 为 GetRawBytesFromSharedBlock(block, byteIndex, type, isTypedArray, order)。
  6. 否则,
    1. 令 rawValue 为一个 List,其元素是 block 中索引位于从 byteIndex(包含)到 byteIndex + elementSize(不包含)区间内的字节。
  7. 断言:rawValue 中的元素数量是 elementSize。
  8. 如果不存在 isLittleEndian,则
    1. 令 agentRecord 为周围代理的 Agent Record。
    2. 将 isLittleEndian 设置为 agentRecord.[[LittleEndian]]。
  9. 返回 RawBytesToNumeric(type, rawValue, isLittleEndian)。

25.1.3.17 NumericToRawBytes ( type, value, isLittleEndian )

抽象操作 NumericToRawBytes,接收参数 type (TypedArray 元素类型)、value ((Number 或 BigInt)) 和 isLittleEndian (Boolean);返回值:列表 (元素:字节值)。 调用时执行以下步骤:

  1. 如果 type 是 float16,则
    1. 令 rawBytes 为一个 List,其元素是使用 roundTiesToEven 模式将 value 转换为 IEEE 754-2019 binary16 格式所得的 2 个字节。这些字节按小端顺序排列。如果 value 是 NaN,则 rawBytes 可以设置为实现选择的任意 IEEE 754-2019 binary16 格式 NaN 编码。对于每个实现可区分的 NaN 值,实现必须始终选择相同的编码。
  2. 否则如果 type 是 float32,则
    1. 令 rawBytes 为一个 List,其元素是使用 roundTiesToEven 模式将 value 转换为 IEEE 754-2019 binary32 格式所得的 4 个字节。这些字节按小端顺序排列。如果 value 是 NaN,则 rawBytes 可以设置为实现选择的任意 IEEE 754-2019 binary32 格式 NaN 编码。对于每个实现可区分的 NaN 值,实现必须始终选择相同的编码。
  3. 否则如果 type 是 float64,则
    1. 令 rawBytes 为一个 List,其元素是 value 的 IEEE 754-2019 binary64 格式编码的 8 个字节。这些字节按小端顺序排列。如果 value 是 NaN,则 rawBytes 可以设置为实现选择的任意 IEEE 754-2019 binary64 格式 NaN 编码。对于每个实现可区分的 NaN 值,实现必须始终选择相同的编码。
  4. 否则,
    1. 令 n 为 表 71 中为 Element Type type 指定的 Element Size 值。
    2. 令 conversionOperation 为 表 71 中 Element Type type 对应行的 “Conversion Operation” 列中命名的抽象操作。
    3. 令 intValue 为 ℝ(! conversionOperation(value))。
    4. 如果 intValue ≥ 0,则
      1. 令 rawBytes 为一个 List,其元素是 intValue 的 n 字节二进制编码。这些字节按小端顺序排列。
    5. 否则,
      1. 令 rawBytes 为一个 List,其元素是 intValue 的 n 字节二进制补码编码。这些字节按小端顺序排列。
  5. 如果 isLittleEndian 是 false,则反转 rawBytes 中元素的顺序。
  6. 返回 rawBytes。

25.1.3.18 SetValueInBuffer ( arrayBuffer, byteIndex, type, value, isTypedArray, order [ , isLittleEndian ] )

抽象操作 SetValueInBuffer,接收参数 arrayBuffer ((ArrayBuffer 或 SharedArrayBuffer))、byteIndex (非负整数)、type (TypedArray 元素类型)、value ((Number 或 BigInt))、isTypedArray (Boolean) 和 order ((seq-cst、unordered 或 init))和可选参数 isLittleEndian (Boolean);返回值:unused。 调用时执行以下步骤:

  1. 断言:IsDetachedBuffer(arrayBuffer) 是 false。
  2. 断言:arrayBuffer 中从 byteIndex 开始有足够的字节来表示 type 的值。
  3. 断言:如果 IsBigIntElementType(type) 是 true,则 value 是 BigInt;否则,value 是 Number。
  4. 令 block 为 arrayBuffer.[[ArrayBufferData]]。
  5. 令 elementSize 为 表 71 中为 Element Type type 指定的 Element Size 值。
  6. 令 agentRecord 为周围代理的 Agent Record。
  7. 如果不存在 isLittleEndian,则
    1. 将 isLittleEndian 设置为 agentRecord.[[LittleEndian]]。
  8. 令 rawBytes 为 NumericToRawBytes(type, value, isLittleEndian)。
  9. 如果 IsSharedArrayBuffer(arrayBuffer) 是 true,则
    1. 令 execution 为 agentRecord.[[CandidateExecution]]。
    2. 令 eventsRecord 为 execution.[[EventsRecords]] 中 [[AgentSignifier]] 为 AgentSignifier() 的 Agent Events Record。
    3. 如果 isTypedArray 是 true 且 IsNoTearConfiguration(type, order) 是 true,则令 noTear 为 true;否则令 noTear 为 false。
    4. 将 WriteSharedMemory { [[Order]]: order, [[NoTear]]: noTear, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes } 追加到 eventsRecord.[[EventList]]。
  10. 否则,
    1. 从 block[byteIndex] 开始,将 rawBytes 的各个字节存储到 block 中。
  11. 返回 unused。

25.1.3.19 GetModifySetValueInBuffer ( arrayBuffer, byteIndex, type, value, op )

抽象操作 GetModifySetValueInBuffer,接收参数 arrayBuffer ((ArrayBuffer 或 SharedArrayBuffer))、byteIndex (非负整数)、type (TypedArray 元素类型)、value ((Number 或 BigInt)) 和 op (a read-modify-write modification function);返回值:(Number 或 BigInt)。 调用时执行以下步骤:

  1. 断言:IsDetachedBuffer(arrayBuffer) 是 false。
  2. 断言:arrayBuffer 中从 byteIndex 开始有足够的字节来表示 type 的值。
  3. 断言:如果 IsBigIntElementType(type) 是 true,则 value 是 BigInt;否则,value 是 Number。
  4. 令 block 为 arrayBuffer.[[ArrayBufferData]]。
  5. 令 elementSize 为 表 71 中为 Element Type type 指定的 Element Size 值。
  6. 令 agentRecord 为周围代理的 Agent Record。
  7. 令 isLittleEndian 为 agentRecord.[[LittleEndian]]。
  8. 令 rawBytes 为 NumericToRawBytes(type, value, isLittleEndian)。
  9. 如果 IsSharedArrayBuffer(arrayBuffer) 是 true,则
    1. 令 execution 为 agentRecord.[[CandidateExecution]]。
    2. 令 eventsRecord 为 execution.[[EventsRecords]] 中 [[AgentSignifier]] 为 AgentSignifier() 的 Agent Events Record。
    3. 令 rawBytesRead 为长度为 elementSize 的 List,其元素是非确定性选择的字节值。
    4. 注:在实现中,rawBytesRead 是底层硬件上的 load-link、load-exclusive 或读-修改-写指令的操作数的结果。非确定性是内存模型的语义规定,用于描述弱一致性硬件的可观察行为。
    5. 令 rmwEvent 为 ReadModifyWriteSharedMemory { [[Order]]: seq-cst, [[NoTear]]: true, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes, [[ModifyOp]]: op }。
    6. 将 rmwEvent 追加到 eventsRecord.[[EventList]]。
    7. 将 Chosen Value Record { [[Event]]: rmwEvent, [[ChosenValue]]: rawBytesRead } 追加到 execution.[[ChosenValues]]。
  10. 否则,
    1. 令 rawBytesRead 为长度为 elementSize 的 List,其元素是从 block[byteIndex] 开始的 elementSize 个字节序列。
    2. 令 rawBytesModified 为 op(rawBytesRead, rawBytes)。
    3. 从 block[byteIndex] 开始,将 rawBytesModified 的各个字节存储到 block 中。
  11. 返回 RawBytesToNumeric(type, rawBytesRead, isLittleEndian)。

25.1.4 ArrayBuffer 构造函数

ArrayBuffer 构造函数:

  • 是 %ArrayBuffer%。
  • 是全局对象的 "ArrayBuffer" 属性的初始值。
  • 作为构造函数调用时,创建并初始化新的 ArrayBuffer。
  • 不旨在作为函数调用,并且以这种方式调用时会抛出异常。
  • 可以用作类定义的 extends 子句的值。希望继承指定 ArrayBuffer 行为的子类构造函数必须包含对 ArrayBuffer 构造函数的 super 调用,以创建并初始化具有支持 ArrayBuffer.prototype 内置方法所必需内部状态的子类实例。

25.1.4.1 ArrayBuffer ( length [ , options ] )

调用时,此函数执行以下步骤:

  1. 如果 NewTarget 是 undefined,则抛出 TypeError 异常。
  2. 令 byteLength 为 ? ToIndex(length)。
  3. 令 requestedMaxByteLength 为 ? GetArrayBufferMaxByteLengthOption(options)。
  4. 返回 ? AllocateArrayBuffer(NewTarget, byteLength, requestedMaxByteLength)。

25.1.5 ArrayBuffer 构造函数的属性

ArrayBuffer 构造函数:

25.1.5.1 ArrayBuffer.isView ( arg )

调用时,此函数执行以下步骤:

  1. 如果 arg 不是 Object,则返回 false。
  2. 如果 arg 具有 [[ViewedArrayBuffer]] 内部槽,则返回 true。
  3. 返回 false。

25.1.5.2 ArrayBuffer.prototype

ArrayBuffer.prototype 的初始值是 ArrayBuffer 原型对象。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

25.1.5.3 get ArrayBuffer [ %Symbol.species% ]

ArrayBuffer[%Symbol.species%] 是访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数在调用时执行以下步骤:

  1. 返回 this value。

此函数的 "name" 属性的值是 "get [Symbol.species]"。

注

ArrayBuffer.prototype.slice ( start, end ) 通常使用其 this value 的构造函数创建派生对象。不过,子类构造函数可以通过重新定义其 %Symbol.species% 属性,覆盖 ArrayBuffer.prototype.slice ( start, end ) 方法的默认行为。

25.1.6 ArrayBuffer 原型对象的属性

ArrayBuffer 原型对象:

  • 是 %ArrayBuffer.prototype%。
  • 具有 [[Prototype]] 内部槽,其值是 %Object.prototype%。
  • 是普通对象。
  • 不具有 [[ArrayBufferData]] 或 [[ArrayBufferByteLength]] 内部槽。

25.1.6.1 get ArrayBuffer.prototype.byteLength

ArrayBuffer.prototype.byteLength 是访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数在调用时执行以下步骤:

  1. 令 obj 为 this value。
  2. 执行 ? RequireInternalSlot(obj, [[ArrayBufferData]])。
  3. 如果 IsSharedArrayBuffer(obj) 是 true,则抛出 TypeError 异常。
  4. 如果 IsDetachedBuffer(obj) 是 true,则返回 +0𝔽。
  5. 令 length 为 obj.[[ArrayBufferByteLength]]。
  6. 返回 𝔽(length)。

25.1.6.2 ArrayBuffer.prototype.constructor

ArrayBuffer.prototype.constructor 的初始值是 %ArrayBuffer%。

25.1.6.3 get ArrayBuffer.prototype.detached

ArrayBuffer.prototype.detached 是访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数在调用时执行以下步骤:

  1. 令 obj 为 this value。
  2. 执行 ? RequireInternalSlot(obj, [[ArrayBufferData]])。
  3. 如果 IsSharedArrayBuffer(obj) 是 true,则抛出 TypeError 异常。
  4. 返回 IsDetachedBuffer(obj)。

25.1.6.4 get ArrayBuffer.prototype.maxByteLength

ArrayBuffer.prototype.maxByteLength 是访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数在调用时执行以下步骤:

  1. 令 obj 为 this value。
  2. 执行 ? RequireInternalSlot(obj, [[ArrayBufferData]])。
  3. 如果 IsSharedArrayBuffer(obj) 是 true,则抛出 TypeError 异常。
  4. 如果 IsDetachedBuffer(obj) 是 true,则返回 +0𝔽。
  5. 如果 IsFixedLengthArrayBuffer(obj) 是 true,则
    1. 令 length 为 obj.[[ArrayBufferByteLength]]。
  6. 否则,
    1. 令 length 为 obj.[[ArrayBufferMaxByteLength]]。
  7. 返回 𝔽(length)。

25.1.6.5 get ArrayBuffer.prototype.resizable

ArrayBuffer.prototype.resizable 是访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数在调用时执行以下步骤:

  1. 令 obj 为 this value。
  2. 执行 ? RequireInternalSlot(obj, [[ArrayBufferData]])。
  3. 如果 IsSharedArrayBuffer(obj) 是 true,则抛出 TypeError 异常。
  4. 如果 IsFixedLengthArrayBuffer(obj) 是 false,则返回 true。
  5. 返回 false。

25.1.6.6 ArrayBuffer.prototype.resize ( newLength )

调用时,此方法执行以下步骤:

  1. 令 obj 为 this value。
  2. 执行 ? RequireInternalSlot(obj, [[ArrayBufferMaxByteLength]])。
  3. 如果 IsSharedArrayBuffer(obj) 是 true,则抛出 TypeError 异常。
  4. 令 newByteLength 为 ? ToIndex(newLength)。
  5. 如果 IsDetachedBuffer(obj) 是 true,则抛出 TypeError 异常。
  6. 如果 newByteLength > obj.[[ArrayBufferMaxByteLength]],则抛出 RangeError 异常。
  7. 令 hostHandled 为 ? HostResizeArrayBuffer(obj, newByteLength)。
  8. 如果 hostHandled 是 handled,则返回 undefined。
  9. 令 oldBlock 为 obj.[[ArrayBufferData]]。
  10. 令 newBlock 为 ? CreateByteDataBlock(newByteLength)。
  11. 令 copyLength 为 min(newByteLength, obj.[[ArrayBufferByteLength]])。
  12. 执行 CopyDataBlockBytes(newBlock, 0, oldBlock, 0, copyLength)。
  13. 注:创建新的 Data Block 和从旧 Data Block 复制都不可观察。实现可以将此方法实现为原地增长或缩小。
  14. 将 obj.[[ArrayBufferData]] 设置为 newBlock。
  15. 将 obj.[[ArrayBufferByteLength]] 设置为 newByteLength。
  16. 返回 undefined。

25.1.6.7 ArrayBuffer.prototype.slice ( start, end )

调用时,此方法执行以下步骤:

  1. 令 obj 为 this value。
  2. 执行 ? RequireInternalSlot(obj, [[ArrayBufferData]])。
  3. 如果 IsSharedArrayBuffer(obj) 是 true,则抛出 TypeError 异常。
  4. 如果 IsDetachedBuffer(obj) 是 true,则抛出 TypeError 异常。
  5. 令 length 为 obj.[[ArrayBufferByteLength]]。
  6. 令 first 为 ? ToClampedIndex(start, length)。
  7. 如果 end 是 undefined,则令 final 为 length;否则令 final 为 ? ToClampedIndex(end, length)。
  8. 令 newLength 为 max(final - first, 0)。
  9. 令 ctor 为 ? SpeciesConstructor(obj, %ArrayBuffer%)。
  10. 令 new 为 ? Construct(ctor, « 𝔽(newLength) »)。
  11. 执行 ? RequireInternalSlot(new, [[ArrayBufferData]])。
  12. 如果 IsSharedArrayBuffer(new) 是 true,则抛出 TypeError 异常。
  13. 如果 IsDetachedBuffer(new) 是 true,则抛出 TypeError 异常。
  14. 如果 SameValue(new, obj) 是 true,则抛出 TypeError 异常。
  15. 如果 new.[[ArrayBufferByteLength]] < newLength,则抛出 TypeError 异常。
  16. 注:上述步骤的副作用可能已经分离或调整了 obj 的大小。
  17. 如果 IsDetachedBuffer(obj) 是 true,则抛出 TypeError 异常。
  18. 令 fromBlock 为 obj.[[ArrayBufferData]]。
  19. 令 toBlock 为 new.[[ArrayBufferData]]。
  20. 令 currentLength 为 obj.[[ArrayBufferByteLength]]。
  21. 令 maxCount 为 currentLength - first。
  22. 如果 maxCount > 0,则
    1. 令 count 为 min(newLength, maxCount)。
    2. 执行 CopyDataBlockBytes(toBlock, 0, fromBlock, first, count)。
  23. 返回 new。

25.1.6.8 ArrayBuffer.prototype.transfer ( [ newLength ] )

调用时,此方法执行以下步骤:

  1. 令 obj 为 this value。
  2. 返回 ? ArrayBufferCopyAndDetach(obj, newLength, preserve-resizability)。

25.1.6.9 ArrayBuffer.prototype.transferToFixedLength ( [ newLength ] )

调用时,此方法执行以下步骤:

  1. 令 obj 为 this value。
  2. 返回 ? ArrayBufferCopyAndDetach(obj, newLength, fixed-length)。

25.1.6.10 ArrayBuffer.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "ArrayBuffer"。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

25.1.7 ArrayBuffer 实例的属性

ArrayBuffer 实例从 ArrayBuffer 原型对象继承属性。每个 ArrayBuffer 实例都具有 [[ArrayBufferData]] 内部槽、[[ArrayBufferByteLength]] 内部槽和 [[ArrayBufferDetachKey]] 内部槽。每个可调整大小的 ArrayBuffer 实例还具有 [[ArrayBufferMaxByteLength]] 内部槽。

[[ArrayBufferData]] 为 null 的 ArrayBuffer 实例被视为已分离,并且所有访问或修改 ArrayBuffer 实例中所含数据的操作都将失败。

[[ArrayBufferDetachKey]] 被设置为 undefined 以外值的 ArrayBuffer 实例,要求所有 DetachArrayBuffer 调用都将同一个“分离键”作为参数传递,否则会产生 TypeError。此内部槽仅由某些嵌入环境设置,而不会由本规范中的算法设置。

25.1.8 可调整大小 ArrayBuffer 指南

注 1

以下是供使用可调整大小 ArrayBuffer 的 ECMAScript 程序员参考的指南。

建议尽可能在程序的部署环境中对其进行测试。不同硬件设备之间可用的物理内存量差异很大。同样,不同硬件设备以及不同操作系统之间的虚拟内存子系统也有很大差异。在 64 位桌面 Web 浏览器上运行而不出现内存不足错误的应用程序,可能会在 32 位移动 Web 浏览器上耗尽内存。

为可调整大小 ArrayBuffer 的 "maxByteLength" 选项选择值时,建议选择应用程序所需的尽可能小的大小。建议 "maxByteLength" 不超过 1,073,741,824(230 字节或 1GiB)。

请注意,成功构造具有特定最大大小的可调整大小 ArrayBuffer,并不能保证未来的大小调整也会成功。

注 2

以下是供实现可调整大小 ArrayBuffer 的 ECMAScript 实现者参考的指南。

可调整大小 ArrayBuffer 可以通过调整大小时进行复制、通过预先保留虚拟内存实现原地增长,或者针对构造函数 "maxByteLength" 选项的不同值结合使用这两种方式来实现。

如果宿主是多租户的(即同时运行许多 ECMAScript 应用程序),例如 Web 浏览器,并且其实现选择通过保留虚拟内存来实现原地增长,则建议 32 位和 64 位实现都针对 "maxByteLength" ≥ 1GiB 到 1.5GiB 的值抛出异常。这是为了降低单个应用程序耗尽虚拟内存地址空间的可能性,并降低互操作性风险。

如果宿主没有虚拟内存,例如运行在没有 MMU 的嵌入式设备上的宿主,或者宿主只通过复制实现大小调整,则它可以接受 "maxByteLength" 选项的任何 Number 值。不过,如果永远无法分配所请求大小的内存块,建议抛出 RangeError。例如,如果请求的大小大于设备上的最大可用内存量。

25.2 SharedArrayBuffer 对象

25.2.1 固定长度和可增长的 SharedArrayBuffer 对象

固定长度 SharedArrayBuffer 是创建后字节长度不能改变的 SharedArrayBuffer。

可增长的 SharedArrayBuffer 是创建后可以通过调用 SharedArrayBuffer.prototype.grow ( newLength ) 增加字节长度的 SharedArrayBuffer。

创建的 SharedArrayBuffer 对象种类取决于传递给 SharedArrayBuffer ( length [ , options ] ) 的参数。

25.2.2 SharedArrayBuffer 对象的抽象操作

25.2.2.1 AllocateSharedArrayBuffer ( ctor, byteLength [ , maxByteLength ] )

抽象操作 AllocateSharedArrayBuffer,接收参数 ctor (构造函数) 和 byteLength (非负整数)和可选参数 maxByteLength ((非负整数 或 empty));返回值:(正常完成 (值:SharedArrayBuffer) 或 抛出完成)。 它用于创建 SharedArrayBuffer。 调用时执行以下步骤:

  1. 令 slots 为 « [[ArrayBufferData]] »。
  2. 如果存在 maxByteLength 且 maxByteLength 不是 empty,则令 allocatingGrowableBuffer 为 true;否则令 allocatingGrowableBuffer 为 false。
  3. 如果 allocatingGrowableBuffer 是 true,则
    1. 如果 byteLength > maxByteLength,则抛出 RangeError 异常。
    2. 将 [[ArrayBufferByteLengthData]] 和 [[ArrayBufferMaxByteLength]] 追加到 slots。
  4. 否则,
    1. 将 [[ArrayBufferByteLength]] 追加到 slots。
  5. 令 obj 为 ? OrdinaryCreateFromConstructor(ctor, "%SharedArrayBuffer.prototype%", slots)。
  6. 如果 allocatingGrowableBuffer 是 true,则令 allocationLength 为 maxByteLength;否则令 allocationLength 为 byteLength。
  7. 令 block 为 ? CreateSharedByteDataBlock(allocationLength)。
  8. 将 obj.[[ArrayBufferData]] 设置为 block。
  9. 如果 allocatingGrowableBuffer 是 true,则
    1. 断言:byteLength ≤ maxByteLength。
    2. 令 byteLengthBlock 为 ? CreateSharedByteDataBlock(8)。
    3. 执行 SetValueInBuffer(byteLengthBlock, 0, biguint64, ℤ(byteLength), true, seq-cst)。
    4. 将 obj.[[ArrayBufferByteLengthData]] 设置为 byteLengthBlock。
    5. 将 obj.[[ArrayBufferMaxByteLength]] 设置为 maxByteLength。
  10. 否则,
    1. 将 obj.[[ArrayBufferByteLength]] 设置为 byteLength。
  11. 返回 obj。

25.2.2.2 IsSharedArrayBuffer ( obj )

抽象操作 IsSharedArrayBuffer,接收参数 obj ((ArrayBuffer 或 SharedArrayBuffer));返回值:Boolean。 它测试对象是否为 SharedArrayBuffer。 调用时执行以下步骤:

  1. 如果 obj.[[ArrayBufferData]] 是 Shared Data Block,则返回 true。
  2. 返回 false。

25.2.2.3 IsGrowableSharedArrayBuffer ( obj )

抽象操作 IsGrowableSharedArrayBuffer,接收参数 obj ((ArrayBuffer 或 SharedArrayBuffer));返回值:Boolean。 它测试对象是否为可增长的 SharedArrayBuffer。 调用时执行以下步骤:

  1. 如果 IsSharedArrayBuffer(obj) 是 true 且 obj 具有 [[ArrayBufferByteLengthData]] 内部槽,则返回 true。
  2. 返回 false。

25.2.2.4 HostGrowSharedArrayBuffer ( buffer, newByteLength )

宿主定义的抽象操作 HostGrowSharedArrayBuffer,接收参数 buffer (SharedArrayBuffer) 和 newByteLength (非负整数);返回值:(正常完成 (值:(handled 或 unhandled)) 或 抛出完成)。 它为宿主提供执行由实现定义的 buffer 增长的机会。如果宿主选择不处理 buffer 的增长,则可以返回 unhandled 以使用默认行为。

HostGrowSharedArrayBuffer 的实现必须符合以下要求:

注

上述第二项要求有意没有明确规定如何或何时读取 buffer 的当前字节长度。由于字节长度必须通过底层硬件上的原子读-修改-写操作进行更新,使用 load-link/store-conditional 或 load-exclusive/store-exclusive 指令对的架构可能希望在指令流中让成对指令彼此靠近。因此,SharedArrayBuffer.prototype.grow ( newLength ) 本身不会在调用 HostGrowSharedArrayBuffer 之前对 newByteLength 进行边界检查,也没有规定何时读取当前字节长度。

这与 HostResizeArrayBuffer 不同,后者保证 0 ≤ newByteLength ≤ buffer.[[ArrayBufferMaxByteLength]]。

HostGrowSharedArrayBuffer 的默认实现是返回 NormalCompletion(unhandled)。

25.2.3 SharedArrayBuffer 构造函数

SharedArrayBuffer 构造函数:

  • 是 %SharedArrayBuffer%。
  • 如果存在全局对象的 "SharedArrayBuffer" 属性(见下文),则是该属性的初始值。
  • 作为构造函数调用时,创建并初始化新的 SharedArrayBuffer。
  • 不旨在作为函数调用,并且以这种方式调用时会抛出异常。
  • 可以用作类定义的 extends 子句的值。希望继承指定 SharedArrayBuffer 行为的子类构造函数必须包含对 SharedArrayBuffer 构造函数的 super 调用,以创建并初始化具有支持 SharedArrayBuffer.prototype 内置方法所必需内部状态的子类实例。

当宿主不提供对 SharedArrayBuffer 的并发访问时,它可以省略全局对象的 "SharedArrayBuffer" 属性。

注

与 ArrayBuffer 不同,SharedArrayBuffer 无法被分离,并且其内部 [[ArrayBufferData]] 槽永远不会是 null。

25.2.3.1 SharedArrayBuffer ( length [ , options ] )

调用时,此函数执行以下步骤:

  1. 如果 NewTarget 是 undefined,则抛出 TypeError 异常。
  2. 令 byteLength 为 ? ToIndex(length)。
  3. 令 requestedMaxByteLength 为 ? GetArrayBufferMaxByteLengthOption(options)。
  4. 返回 ? AllocateSharedArrayBuffer(NewTarget, byteLength, requestedMaxByteLength)。

25.2.4 SharedArrayBuffer 构造函数的属性

SharedArrayBuffer 构造函数:

25.2.4.1 SharedArrayBuffer.prototype

SharedArrayBuffer.prototype 的初始值是 SharedArrayBuffer 原型对象。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

25.2.4.2 get SharedArrayBuffer [ %Symbol.species% ]

SharedArrayBuffer[%Symbol.species%] 是访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数在调用时执行以下步骤:

  1. 返回 this value。

此函数的 "name" 属性的值是 "get [Symbol.species]"。

25.2.5 SharedArrayBuffer 原型对象的属性

SharedArrayBuffer 原型对象:

  • 是 %SharedArrayBuffer.prototype%。
  • 具有 [[Prototype]] 内部槽,其值是 %Object.prototype%。
  • 是普通对象。
  • 不具有 [[ArrayBufferData]] 或 [[ArrayBufferByteLength]] 内部槽。

25.2.5.1 get SharedArrayBuffer.prototype.byteLength

SharedArrayBuffer.prototype.byteLength 是访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数在调用时执行以下步骤:

  1. 令 obj 为 this value。
  2. 执行 ? RequireInternalSlot(obj, [[ArrayBufferData]])。
  3. 如果 IsSharedArrayBuffer(obj) 是 false,则抛出 TypeError 异常。
  4. 令 length 为 ArrayBufferByteLength(obj, seq-cst)。
  5. 返回 𝔽(length)。

25.2.5.2 SharedArrayBuffer.prototype.constructor

SharedArrayBuffer.prototype.constructor 的初始值是 %SharedArrayBuffer%。

25.2.5.3 SharedArrayBuffer.prototype.grow ( newLength )

调用时,此方法执行以下步骤:

  1. 令 obj 为 this value。
  2. 执行 ? RequireInternalSlot(obj, [[ArrayBufferMaxByteLength]])。
  3. 如果 IsSharedArrayBuffer(obj) 是 false,则抛出 TypeError 异常。
  4. 令 newByteLength 为 ? ToIndex(newLength)。
  5. 令 hostHandled 为 ? HostGrowSharedArrayBuffer(obj, newByteLength)。
  6. 如果 hostHandled 是 handled,则返回 undefined。
  7. 令 agentRecord 为周围代理的 Agent Record。
  8. 令 isLittleEndian 为 agentRecord.[[LittleEndian]]。
  9. 令 byteLengthBlock 为 obj.[[ArrayBufferByteLengthData]]。
  10. 令 currentByteLengthRawBytes 为 GetRawBytesFromSharedBlock(byteLengthBlock, 0, biguint64, true, seq-cst)。
  11. 令 newByteLengthRawBytes 为 NumericToRawBytes(biguint64, ℤ(newByteLength), isLittleEndian)。
  12. 重复执行,
    1. 注:这是一个比较并交换循环,用于确保对同一缓冲区的并行、竞争增长操作具有全序、不会丢失,也不会悄无声息地不执行任何操作。如果它能够在没有竞争的情况下尝试增长,则循环退出。
    2. 令 currentByteLength 为 ℝ(RawBytesToNumeric(biguint64, currentByteLengthRawBytes, isLittleEndian))。
    3. 如果 newByteLength = currentByteLength,则返回 undefined。
    4. 如果 newByteLength < currentByteLength 或 newByteLength > obj.[[ArrayBufferMaxByteLength]],则抛出 RangeError 异常。
    5. 令 byteLengthDelta 为 newByteLength - currentByteLength。
    6. 如果无法创建由 byteLengthDelta 个字节组成的新 Shared Data Block 值,则抛出 RangeError 异常。
    7. 注:这里不会构造和使用新的 Shared Data Block。可增长 SharedArrayBuffer 的可观察行为通过在构造时分配最大大小的 Shared Data Block 来规定,而此步骤体现了实现耗尽内存时必须抛出 RangeError 的要求。
    8. 令 readByteLengthRawBytes 为 AtomicCompareExchangeInSharedBlock(byteLengthBlock, 0, 8, currentByteLengthRawBytes, newByteLengthRawBytes)。
    9. 如果 ByteListEqual(readByteLengthRawBytes, currentByteLengthRawBytes) 是 true,则返回 undefined。
    10. 将 currentByteLengthRawBytes 设置为 readByteLengthRawBytes。
注

禁止比较交换更新长度时出现虚假失败。如果新长度的边界检查通过且实现未耗尽内存,则始终会向候选执行中添加一个 ReadModifyWriteSharedMemory 事件(即成功的比较交换)。

对 SharedArrayBuffer.prototype.grow 的并行调用具有全序。例如,考虑两个竞争调用:sab.grow(10) 和 sab.grow(20)。两个调用中的一个必定会赢得竞争。即使 sab.grow(20) 先发生,sab.grow(10) 调用也绝不会缩小 sab;在这种情况下,它会改为抛出 RangeError。

25.2.5.4 get SharedArrayBuffer.prototype.growable

SharedArrayBuffer.prototype.growable 是访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数在调用时执行以下步骤:

  1. 令 obj 为 this value。
  2. 执行 ? RequireInternalSlot(obj, [[ArrayBufferData]])。
  3. 如果 IsSharedArrayBuffer(obj) 是 false,则抛出 TypeError 异常。
  4. 如果 IsFixedLengthArrayBuffer(obj) 是 false,则返回 true。
  5. 返回 false。

25.2.5.5 get SharedArrayBuffer.prototype.maxByteLength

SharedArrayBuffer.prototype.maxByteLength 是访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数在调用时执行以下步骤:

  1. 令 obj 为 this value。
  2. 执行 ? RequireInternalSlot(obj, [[ArrayBufferData]])。
  3. 如果 IsSharedArrayBuffer(obj) 是 false,则抛出 TypeError 异常。
  4. 如果 IsFixedLengthArrayBuffer(obj) 是 true,则
    1. 令 length 为 obj.[[ArrayBufferByteLength]]。
  5. 否则,
    1. 令 length 为 obj.[[ArrayBufferMaxByteLength]]。
  6. 返回 𝔽(length)。

25.2.5.6 SharedArrayBuffer.prototype.slice ( start, end )

调用时,此方法执行以下步骤:

  1. 令 obj 为 this value。
  2. 执行 ? RequireInternalSlot(obj, [[ArrayBufferData]])。
  3. 如果 IsSharedArrayBuffer(obj) 是 false,则抛出 TypeError 异常。
  4. 令 length 为 ArrayBufferByteLength(obj, seq-cst)。
  5. 令 first 为 ? ToClampedIndex(start, length)。
  6. 如果 end 是 undefined,则令 final 为 length;否则令 final 为 ? ToClampedIndex(end, length)。
  7. 令 newLength 为 max(final - first, 0)。
  8. 令 ctor 为 ? SpeciesConstructor(obj, %SharedArrayBuffer%)。
  9. 令 new 为 ? Construct(ctor, « 𝔽(newLength) »)。
  10. 执行 ? RequireInternalSlot(new, [[ArrayBufferData]])。
  11. 如果 IsSharedArrayBuffer(new) 是 false,则抛出 TypeError 异常。
  12. 如果 new.[[ArrayBufferData]] 是 obj.[[ArrayBufferData]],则抛出 TypeError 异常。
  13. 如果 ArrayBufferByteLength(new, seq-cst) < newLength,则抛出 TypeError 异常。
  14. 令 fromBlock 为 obj.[[ArrayBufferData]]。
  15. 令 toBlock 为 new.[[ArrayBufferData]]。
  16. 执行 CopyDataBlockBytes(toBlock, 0, fromBlock, first, newLength)。
  17. 返回 new。

25.2.5.7 SharedArrayBuffer.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "SharedArrayBuffer"。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

25.2.6 SharedArrayBuffer 实例的属性

SharedArrayBuffer 实例从 SharedArrayBuffer 原型对象继承属性。每个 SharedArrayBuffer 实例都具有 [[ArrayBufferData]] 内部槽。每个不可增长的 SharedArrayBuffer 实例都具有 [[ArrayBufferByteLength]] 内部槽。每个可增长的 SharedArrayBuffer 实例都具有 [[ArrayBufferByteLengthData]] 内部槽和 [[ArrayBufferMaxByteLength]] 内部槽。

注

与 ArrayBuffer 实例不同,SharedArrayBuffer 实例永远不会被分离。

25.2.7 可增长 SharedArrayBuffer 指南

注 1

以下是供使用可增长 SharedArrayBuffer 的 ECMAScript 程序员参考的指南。

建议尽可能在程序的部署环境中对其进行测试。不同硬件设备之间可用的物理内存量差异很大。同样,不同硬件设备以及不同操作系统之间的虚拟内存子系统也有很大差异。在 64 位桌面 Web 浏览器上运行而不出现内存不足错误的应用程序,可能会在 32 位移动 Web 浏览器上耗尽内存。

为可增长 SharedArrayBuffer 的 "maxByteLength" 选项选择值时,建议选择应用程序所需的尽可能小的大小。建议 "maxByteLength" 不超过 1073741824,即 1GiB。

请注意,成功构造具有特定最大大小的可增长 SharedArrayBuffer,并不能保证未来的增长也会成功。

并非对可增长 SharedArrayBuffer 长度的所有加载都是同步的 seq-cst 加载。用于对整数索引属性访问(例如 u8[idx])进行边界检查的长度加载不是同步操作。通常,在没有显式同步的情况下,一次属性访问位于边界内,并不意味着同一代理中随后的一次属性访问也位于边界内。相比之下,通过 SharedArrayBuffer、%TypedArray%.prototype 和 DataView.prototype 上的 length 和 byteLength getter 显式加载长度是同步操作。内置方法为检查 TypedArray 是否完全越界而执行的长度加载也是同步操作。

注 2

以下是供实现可增长 SharedArrayBuffer 的 ECMAScript 实现者参考的指南。

建议通过预先保留虚拟内存实现原地增长的方式实现可增长 SharedArrayBuffer。

由于增长操作可以与对可增长 SharedArrayBuffer 的内存访问并行发生,内存模型的约束要求即使无序访问也不能发生“撕裂”(其值的位不会混合)。实际上,这意味着可增长 SharedArrayBuffer 的底层数据块不能通过复制进行增长,除非停止整个世界。我们不建议将停止整个世界作为实现策略,因为它会引入串行化点且速度很慢。

增长后的内存从创建的那一刻起就必须表现为已清零,包括对任何并行竞争访问也是如此。这可以通过按需填零的虚拟内存页实现,或者在手动清零内存时通过谨慎同步实现。

可增长 SharedArrayBuffer 的 TypedArray 视图上的整数索引属性访问,应当能够像不可增长 SharedArrayBuffer 的 TypedArray 视图上的访问一样进行优化,因为整数索引属性加载不会在底层缓冲区的长度上进行同步(参见上面的程序员指南)。例如,属性访问的边界检查仍然可以提升到循环之外。

在没有虚拟内存的宿主上,例如运行在没有 MMU 的嵌入式设备上的宿主,实际上很难通过复制实现可增长 SharedArrayBuffer。此类宿主上可增长 SharedArrayBuffer 的内存使用行为可能与具有虚拟内存的宿主有显著差异。此类宿主应向用户明确说明内存使用预期。

25.3 DataView 对象

25.3.1 DataView 对象的抽象操作

25.3.1.1 DataView With Buffer Witness Record

DataView With Buffer Witness Record 是用于封装 DataView 以及所查看缓冲区的缓存字节长度的 Record。当所查看的缓冲区是可增长 SharedArrayBuffer 时,它用于帮助确保字节长度数据块只有一个 ReadSharedMemory 事件。

DataView With Buffer Witness Record 具有 表 73 中列出的字段。

表 73: DataView With Buffer Witness Record 字段
字段名称 值 含义
[[Object]] a DataView 其缓冲区字节长度被加载的 DataView 对象。
[[CachedBufferByteLength]] a non-negative integer or detached 创建 Record 时对象的 [[ViewedArrayBuffer]] 的字节长度。

25.3.1.2 MakeDataViewWithBufferWitnessRecord ( obj, order )

抽象操作 MakeDataViewWithBufferWitnessRecord,接收参数 obj (DataView) 和 order ((seq-cst 或 unordered));返回值:DataView With Buffer Witness 记录。 调用时执行以下步骤:

  1. 令 buffer 为 obj.[[ViewedArrayBuffer]]。
  2. 如果 IsDetachedBuffer(buffer) 是 true,则
    1. 令 byteLength 为 detached。
  3. 否则,
    1. 令 byteLength 为 ArrayBufferByteLength(buffer, order)。
  4. 返回 DataView With Buffer Witness Record { [[Object]]: obj, [[CachedBufferByteLength]]: byteLength }。

25.3.1.3 GetViewByteLength ( viewRecord )

抽象操作 GetViewByteLength,接收参数 viewRecord (DataView With Buffer Witness 记录);返回值:非负整数。 调用时执行以下步骤:

  1. 断言:IsViewOutOfBounds(viewRecord) 是 false。
  2. 令 view 为 viewRecord.[[Object]]。
  3. 如果 view.[[ByteLength]] 不是 auto,则返回 view.[[ByteLength]]。
  4. 断言:IsFixedLengthArrayBuffer(view.[[ViewedArrayBuffer]]) 是 false。
  5. 令 byteOffset 为 view.[[ByteOffset]]。
  6. 令 byteLength 为 viewRecord.[[CachedBufferByteLength]]。
  7. 断言:byteLength 不是 detached。
  8. 返回 byteLength - byteOffset。

25.3.1.4 IsViewOutOfBounds ( viewRecord )

抽象操作 IsViewOutOfBounds,接收参数 viewRecord (DataView With Buffer Witness 记录);返回值:Boolean。 调用时执行以下步骤:

  1. 令 view 为 viewRecord.[[Object]]。
  2. 令 bufferByteLength 为 viewRecord.[[CachedBufferByteLength]]。
  3. 如果 IsDetachedBuffer(view.[[ViewedArrayBuffer]]) 是 true,则
    1. 断言:bufferByteLength 是 detached。
    2. 返回 true。
  4. 断言:bufferByteLength 是非负整数。
  5. 令 byteOffsetStart 为 view.[[ByteOffset]]。
  6. 如果 view.[[ByteLength]] 是 auto,则
    1. 令 byteOffsetEnd 为 bufferByteLength。
  7. 否则,
    1. 令 byteOffsetEnd 为 byteOffsetStart + view.[[ByteLength]]。
  8. 注:[[ByteOffset]] 为 bufferByteLength 的 0 长度 DataView 不被视为越界。
  9. 如果 byteOffsetStart > bufferByteLength 或 byteOffsetEnd > bufferByteLength,则返回 true。
  10. 返回 false。

25.3.1.5 GetViewValue ( view, requestIndex, isLittleEndian, type )

抽象操作 GetViewValue,接收参数 view (ECMAScript 语言值)、requestIndex (ECMAScript 语言值)、isLittleEndian (ECMAScript 语言值) 和 type (TypedArray 元素类型);返回值:(正常完成 (值:(Number 或 BigInt)) 或 抛出完成)。 它由 DataView 实例上的函数使用,以从视图的缓冲区中检索值。 调用时执行以下步骤:

  1. 执行 ? RequireInternalSlot(view, [[DataView]])。
  2. 断言:view 具有 [[ViewedArrayBuffer]] 内部槽。
  3. 令 getIndex 为 ? ToIndex(requestIndex)。
  4. 将 isLittleEndian 设置为 ToBoolean(isLittleEndian)。
  5. 令 viewOffset 为 view.[[ByteOffset]]。
  6. 令 viewRecord 为 MakeDataViewWithBufferWitnessRecord(view, unordered)。
  7. 注:当 view 的后备缓冲区是可增长 SharedArrayBuffer 时,边界检查不是同步操作。
  8. 如果 IsViewOutOfBounds(viewRecord) 是 true,则抛出 TypeError 异常。
  9. 令 viewSize 为 GetViewByteLength(viewRecord)。
  10. 令 elementSize 为 表 71 中为 Element Type type 指定的 Element Size 值。
  11. 如果 getIndex + elementSize > viewSize,则抛出 RangeError 异常。
  12. 令 bufferIndex 为 getIndex + viewOffset。
  13. 返回 GetValueFromBuffer(view.[[ViewedArrayBuffer]], bufferIndex, type, false, unordered, isLittleEndian)。

25.3.1.6 SetViewValue ( view, requestIndex, isLittleEndian, type, value )

抽象操作 SetViewValue,接收参数 view (ECMAScript 语言值)、requestIndex (ECMAScript 语言值)、isLittleEndian (ECMAScript 语言值)、type (TypedArray 元素类型) 和 value (ECMAScript 语言值);返回值:(正常完成 (值:unused) 或 抛出完成)。 它由 DataView 实例上的函数使用,以将值存储到视图的缓冲区中。 调用时执行以下步骤:

  1. 执行 ? RequireInternalSlot(view, [[DataView]])。
  2. 断言:view 具有 [[ViewedArrayBuffer]] 内部槽。
  3. 令 getIndex 为 ? ToIndex(requestIndex)。
  4. 如果 IsBigIntElementType(type) 是 true,则令 number 为 ? ToBigInt(value)。
  5. 否则,令 number 为 ? ToNumber(value)。
  6. 将 isLittleEndian 设置为 ToBoolean(isLittleEndian)。
  7. 令 viewOffset 为 view.[[ByteOffset]]。
  8. 令 viewRecord 为 MakeDataViewWithBufferWitnessRecord(view, unordered)。
  9. 注:当 view 的后备缓冲区是可增长 SharedArrayBuffer 时,边界检查不是同步操作。
  10. 如果 IsViewOutOfBounds(viewRecord) 是 true,则抛出 TypeError 异常。
  11. 令 viewSize 为 GetViewByteLength(viewRecord)。
  12. 令 elementSize 为 表 71 中为 Element Type type 指定的 Element Size 值。
  13. 如果 getIndex + elementSize > viewSize,则抛出 RangeError 异常。
  14. 令 bufferIndex 为 getIndex + viewOffset。
  15. 执行 SetValueInBuffer(view.[[ViewedArrayBuffer]], bufferIndex, type, number, false, unordered, isLittleEndian)。
  16. 返回 unused。

25.3.2 DataView 构造函数

DataView 构造函数:

  • 是 %DataView%。
  • 是全局对象的 "DataView" 属性的初始值。
  • 作为构造函数调用时,创建并初始化新的 DataView。
  • 不旨在作为函数调用,并且以这种方式调用时会抛出异常。
  • 可以用作类定义的 extends 子句的值。希望继承指定 DataView 行为的子类构造函数必须包含对 DataView 构造函数的 super 调用,以创建并初始化具有支持 DataView.prototype 内置方法所必需内部状态的子类实例。

25.3.2.1 DataView ( buffer [ , byteOffset [ , byteLength ] ] )

调用时,此函数执行以下步骤:

  1. 如果 NewTarget 是 undefined,则抛出 TypeError 异常。
  2. 执行 ? RequireInternalSlot(buffer, [[ArrayBufferData]])。
  3. 令 offset 为 ? ToIndex(byteOffset)。
  4. 如果 IsDetachedBuffer(buffer) 是 true,则抛出 TypeError 异常。
  5. 令 bufferByteLength 为 ArrayBufferByteLength(buffer, seq-cst)。
  6. 如果 offset > bufferByteLength,则抛出 RangeError 异常。
  7. 令 bufferIsFixedLength 为 IsFixedLengthArrayBuffer(buffer)。
  8. 如果 byteLength 是 undefined,则
    1. 如果 bufferIsFixedLength 是 true,则
      1. 令 viewByteLength 为 bufferByteLength - offset。
    2. 否则,
      1. 令 viewByteLength 为 auto。
  9. 否则,
    1. 令 viewByteLength 为 ? ToIndex(byteLength)。
    2. 如果 offset + viewByteLength > bufferByteLength,则抛出 RangeError 异常。
  10. 令 obj 为 ? OrdinaryCreateFromConstructor(NewTarget, "%DataView.prototype%", « [[DataView]], [[ViewedArrayBuffer]], [[ByteLength]], [[ByteOffset]] »)。
  11. 如果 IsDetachedBuffer(buffer) 是 true,则抛出 TypeError 异常。
  12. 将 bufferByteLength 设置为 ArrayBufferByteLength(buffer, seq-cst)。
  13. 如果 offset > bufferByteLength,则抛出 RangeError 异常。
  14. 如果 byteLength 不是 undefined,则
    1. 如果 offset + viewByteLength > bufferByteLength,则抛出 RangeError 异常。
  15. 将 obj.[[ViewedArrayBuffer]] 设置为 buffer。
  16. 将 obj.[[ByteLength]] 设置为 viewByteLength。
  17. 将 obj.[[ByteOffset]] 设置为 offset。
  18. 返回 obj。

25.3.3 DataView 构造函数的属性

DataView 构造函数:

25.3.3.1 DataView.prototype

DataView.prototype 的初始值是 DataView 原型对象。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

25.3.4 DataView 原型对象的属性

DataView 原型对象:

  • 是 %DataView.prototype%。
  • 具有 [[Prototype]] 内部槽,其值是 %Object.prototype%。
  • 是普通对象。
  • 不具有 [[DataView]]、[[ViewedArrayBuffer]]、[[ByteLength]] 或 [[ByteOffset]] 内部槽。

25.3.4.1 get DataView.prototype.buffer

DataView.prototype.buffer 是访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数在调用时执行以下步骤:

  1. 令 obj 为 this value。
  2. 执行 ? RequireInternalSlot(obj, [[DataView]])。
  3. 断言:obj 具有 [[ViewedArrayBuffer]] 内部槽。
  4. 令 buffer 为 obj.[[ViewedArrayBuffer]]。
  5. 返回 buffer。

25.3.4.2 get DataView.prototype.byteLength

DataView.prototype.byteLength 是访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数在调用时执行以下步骤:

  1. 令 obj 为 this value。
  2. 执行 ? RequireInternalSlot(obj, [[DataView]])。
  3. 断言:obj 具有 [[ViewedArrayBuffer]] 内部槽。
  4. 令 viewRecord 为 MakeDataViewWithBufferWitnessRecord(obj, seq-cst)。
  5. 如果 IsViewOutOfBounds(viewRecord) 是 true,则抛出 TypeError 异常。
  6. 令 size 为 GetViewByteLength(viewRecord)。
  7. 返回 𝔽(size)。

25.3.4.3 get DataView.prototype.byteOffset

DataView.prototype.byteOffset 是访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数在调用时执行以下步骤:

  1. 令 obj 为 this value。
  2. 执行 ? RequireInternalSlot(obj, [[DataView]])。
  3. 断言:obj 具有 [[ViewedArrayBuffer]] 内部槽。
  4. 令 viewRecord 为 MakeDataViewWithBufferWitnessRecord(obj, seq-cst)。
  5. 如果 IsViewOutOfBounds(viewRecord) 是 true,则抛出 TypeError 异常。
  6. 令 offset 为 obj.[[ByteOffset]]。
  7. 返回 𝔽(offset)。

25.3.4.4 DataView.prototype.constructor

DataView.prototype.constructor 的初始值是 %DataView%。

25.3.4.5 DataView.prototype.getBigInt64 ( byteOffset [ , littleEndian ] )

调用时,此方法执行以下步骤:

  1. 令 view 为 this value。
  2. 返回 ? GetViewValue(view, byteOffset, littleEndian, bigint64)。

25.3.4.6 DataView.prototype.getBigUint64 ( byteOffset [ , littleEndian ] )

调用时,此方法执行以下步骤:

  1. 令 view 为 this value。
  2. 返回 ? GetViewValue(view, byteOffset, littleEndian, biguint64)。

25.3.4.7 DataView.prototype.getFloat16 ( byteOffset [ , littleEndian ] )

调用时,此方法执行以下步骤:

  1. 令 view 为 this value。
  2. 如果不存在 littleEndian,则将 littleEndian 设置为 false。
  3. 返回 ? GetViewValue(view, byteOffset, littleEndian, float16)。

25.3.4.8 DataView.prototype.getFloat32 ( byteOffset [ , littleEndian ] )

调用时,此方法执行以下步骤:

  1. 令 view 为 this value。
  2. 如果不存在 littleEndian,则将 littleEndian 设置为 false。
  3. 返回 ? GetViewValue(view, byteOffset, littleEndian, float32)。

25.3.4.9 DataView.prototype.getFloat64 ( byteOffset [ , littleEndian ] )

调用时,此方法执行以下步骤:

  1. 令 view 为 this value。
  2. 如果不存在 littleEndian,则将 littleEndian 设置为 false。
  3. 返回 ? GetViewValue(view, byteOffset, littleEndian, float64)。

25.3.4.10 DataView.prototype.getInt8 ( byteOffset )

调用时,此方法执行以下步骤:

  1. 令 view 为 this value。
  2. 返回 ? GetViewValue(view, byteOffset, true, int8)。

25.3.4.11 DataView.prototype.getInt16 ( byteOffset [ , littleEndian ] )

调用时,此方法执行以下步骤:

  1. 令 view 为 this value。
  2. 如果不存在 littleEndian,则将 littleEndian 设置为 false。
  3. 返回 ? GetViewValue(view, byteOffset, littleEndian, int16)。

25.3.4.12 DataView.prototype.getInt32 ( byteOffset [ , littleEndian ] )

调用时,此方法执行以下步骤:

  1. 令 view 为 this value。
  2. 如果不存在 littleEndian,则将 littleEndian 设置为 false。
  3. 返回 ? GetViewValue(view, byteOffset, littleEndian, int32)。

25.3.4.13 DataView.prototype.getUint8 ( byteOffset )

调用时,此方法执行以下步骤:

  1. 令 view 为 this value。
  2. 返回 ? GetViewValue(view, byteOffset, true, uint8)。

25.3.4.14 DataView.prototype.getUint16 ( byteOffset [ , littleEndian ] )

调用时,此方法执行以下步骤:

  1. 令 view 为 this value。
  2. 如果不存在 littleEndian,则将 littleEndian 设置为 false。
  3. 返回 ? GetViewValue(view, byteOffset, littleEndian, uint16)。

25.3.4.15 DataView.prototype.getUint32 ( byteOffset [ , littleEndian ] )

调用时,此方法执行以下步骤:

  1. 令 view 为 this value。
  2. 如果不存在 littleEndian,则将 littleEndian 设置为 false。
  3. 返回 ? GetViewValue(view, byteOffset, littleEndian, uint32)。

25.3.4.16 DataView.prototype.setBigInt64 ( byteOffset, value [ , littleEndian ] )

调用时,此方法执行以下步骤:

  1. 令 view 为 this value。
  2. 执行 ? SetViewValue(view, byteOffset, littleEndian, bigint64, value)。
  3. 返回 undefined。

25.3.4.17 DataView.prototype.setBigUint64 ( byteOffset, value [ , littleEndian ] )

调用时,此方法执行以下步骤:

  1. 令 view 为 this value。
  2. 执行 ? SetViewValue(view, byteOffset, littleEndian, biguint64, value)。
  3. 返回 undefined。

25.3.4.18 DataView.prototype.setFloat16 ( byteOffset, value [ , littleEndian ] )

调用时,此方法执行以下步骤:

  1. 令 view 为 this value。
  2. 如果不存在 littleEndian,则将 littleEndian 设置为 false。
  3. 执行 ? SetViewValue(view, byteOffset, littleEndian, float16, value)。
  4. 返回 undefined。

25.3.4.19 DataView.prototype.setFloat32 ( byteOffset, value [ , littleEndian ] )

调用时,此方法执行以下步骤:

  1. 令 view 为 this value。
  2. 如果不存在 littleEndian,则将 littleEndian 设置为 false。
  3. 执行 ? SetViewValue(view, byteOffset, littleEndian, float32, value)。
  4. 返回 undefined。

25.3.4.20 DataView.prototype.setFloat64 ( byteOffset, value [ , littleEndian ] )

调用时,此方法执行以下步骤:

  1. 令 view 为 this value。
  2. 如果不存在 littleEndian,则将 littleEndian 设置为 false。
  3. 执行 ? SetViewValue(view, byteOffset, littleEndian, float64, value)。
  4. 返回 undefined。

25.3.4.21 DataView.prototype.setInt8 ( byteOffset, value )

调用时,此方法执行以下步骤:

  1. 令 view 为 this value。
  2. 执行 ? SetViewValue(view, byteOffset, true, int8, value)。
  3. 返回 undefined。

25.3.4.22 DataView.prototype.setInt16 ( byteOffset, value [ , littleEndian ] )

调用时,此方法执行以下步骤:

  1. 令 view 为 this value。
  2. 如果不存在 littleEndian,则将 littleEndian 设置为 false。
  3. 执行 ? SetViewValue(view, byteOffset, littleEndian, int16, value)。
  4. 返回 undefined。

25.3.4.23 DataView.prototype.setInt32 ( byteOffset, value [ , littleEndian ] )

调用时,此方法执行以下步骤:

  1. 令 view 为 this value。
  2. 如果不存在 littleEndian,则将 littleEndian 设置为 false。
  3. 执行 ? SetViewValue(view, byteOffset, littleEndian, int32, value)。
  4. 返回 undefined。

25.3.4.24 DataView.prototype.setUint8 ( byteOffset, value )

调用时,此方法执行以下步骤:

  1. 令 view 为 this value。
  2. 执行 ? SetViewValue(view, byteOffset, true, uint8, value)。
  3. 返回 undefined。

25.3.4.25 DataView.prototype.setUint16 ( byteOffset, value [ , littleEndian ] )

调用时,此方法执行以下步骤:

  1. 令 view 为 this value。
  2. 如果不存在 littleEndian,则将 littleEndian 设置为 false。
  3. 执行 ? SetViewValue(view, byteOffset, littleEndian, uint16, value)。
  4. 返回 undefined。

25.3.4.26 DataView.prototype.setUint32 ( byteOffset, value [ , littleEndian ] )

调用时,此方法执行以下步骤:

  1. 令 view 为 this value。
  2. 如果不存在 littleEndian,则将 littleEndian 设置为 false。
  3. 执行 ? SetViewValue(view, byteOffset, littleEndian, uint32, value)。
  4. 返回 undefined。

25.3.4.27 DataView.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "DataView"。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

25.3.5 DataView 实例的属性

DataView 实例是从 DataView 原型对象继承属性的普通对象。每个 DataView 实例都具有 [[DataView]]、[[ViewedArrayBuffer]]、[[ByteLength]] 和 [[ByteOffset]] 内部槽。

注

本规范中不使用 [[DataView]] 内部槽的值。在规范中,仅通过该内部槽的存在来识别使用 DataView 构造函数创建的对象。

25.4 Atomics 对象

Atomics 对象:

  • 是 %Atomics%。
  • 是全局对象的 "Atomics" 属性的初始值。
  • 是普通对象。
  • 具有 [[Prototype]] 内部槽,其值是 %Object.prototype%。
  • 不具有 [[Construct]] 内部方法;不能与 new 运算符一起用作构造函数。
  • 不具有 [[Call]] 内部方法;不能作为函数调用。

Atomics 对象提供以不可分割方式(原子方式)操作共享内存数组单元的函数,以及允许代理等待和分派原始事件的函数。如果正确使用,Atomics 函数允许通过共享内存通信的多代理程序,即使在并行 CPU 上也能以明确可理解的顺序执行。控制共享内存通信的规则由下文定义的内存模型提供。

注

有关在 ECMAScript 中编程和实现共享内存的信息性指南,请参见内存模型一节末尾的注。

25.4.1 Waiter Record

Waiter Record 是用于表示对 Atomics.wait 或 Atomics.waitAsync 的某次特定调用的 Record。

Waiter Record 具有 表 74 中列出的字段。

表 74: Waiter Record 字段
字段名称 值 含义
[[AgentSignifier]] an agent signifier 调用 Atomics.wait 或 Atomics.waitAsync 的代理。
[[PromiseCapability]] a PromiseCapability Record or blocking 如果表示对 Atomics.waitAsync 的调用,则为产生的 promise,否则为 blocking。
[[TimeoutTime]] a non-negative extended mathematical value 可能触发超时的最早时间;使用时间值计算。
[[Result]] "ok" or "timed-out" 调用的返回值。

25.4.2 WaiterList Record

WaiterList Record 用于说明通过 Atomics.wait、Atomics.waitAsync 和 Atomics.notify 等待和通知代理。

WaiterList Record 具有 表 75 中列出的字段。

表 75: WaiterList Record 字段
字段名称 值 含义
[[Waiters]] a List of Waiter Records 正在与此 WaiterList 关联的位置上等待的 Atomics.wait 或 Atomics.waitAsync 调用。
[[MostRecentLeaveEvent]] a Synchronize event or empty 最近一次离开其临界区的事件;如果其临界区从未被进入,则为 empty。

一个 WaiterList 中可以有多个具有相同代理标识符的 Waiter Record。

代理集群具有一个 WaiterList Record 存储;该存储由 (block, i) 索引,其中 block 是 Shared Data Block,i 是 block 内存中的字节偏移量。WaiterList Record 与代理无关:在代理集群中的任何代理中,通过 (block, i) 在 WaiterList Record 存储中查找都会得到同一个 WaiterList Record。

每个 WaiterList Record 都有一个临界区,用于在求值期间控制对该 WaiterList Record 的排他访问。同一时间只能有一个代理进入 WaiterList Record 的临界区。进入和离开 WaiterList Record 的临界区由抽象操作 EnterCriticalSection 和 LeaveCriticalSection 控制。对 WaiterList Record 的操作——添加和移除等待代理、遍历代理列表、挂起和通知列表中的代理、设置和检索 Synchronize 事件——只能由已经进入 WaiterList Record 临界区的代理执行。

25.4.3 Atomics 的抽象操作

25.4.3.1 ValidateIntegerTypedArray ( ta, waitable )

抽象操作 ValidateIntegerTypedArray,接收参数 ta (ECMAScript 语言值) 和 waitable (Boolean);返回值:(正常完成 (值:TypedArray With Buffer Witness 记录) 或 抛出完成)。 它用于约束可与 %Atomics% 函数一起使用的 TypedArray,尤其是能够保证与共享内存进行原子交互的 TypedArray。 调用时执行以下步骤:

  1. 注:当 ta 的后备缓冲区是可增长 SharedArrayBuffer 时,边界检查不是同步操作。
  2. 令 taRecord 为 ? ValidateTypedArray(ta, unordered)。
  3. 令 elementType 为 TypedArrayElementType(ta)。
  4. 如果 IsNoTearConfiguration(elementType, seq-cst) 是 false,则抛出 TypeError 异常。
  5. 如果 waitable 是 true 且 elementType 既不是 int32 也不是 bigint64,则抛出 TypeError 异常。
  6. 返回 taRecord。

25.4.3.2 ValidateAtomicAccess ( taRecord, requestIndex )

抽象操作 ValidateAtomicAccess,接收参数 taRecord (TypedArray With Buffer Witness 记录) 和 requestIndex (ECMAScript 语言值);返回值:(正常完成 (值:非负整数) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 length 为 TypedArrayLength(taRecord)。
  2. 令 accessIndex 为 ? ToIndex(requestIndex)。
  3. 断言:accessIndex ≥ 0。
  4. 如果 accessIndex ≥ length,则抛出 RangeError 异常。
  5. 令 ta 为 taRecord.[[Object]]。
  6. 令 elementSize 为 TypedArrayElementSize(ta)。
  7. 令 offset 为 ta.[[ByteOffset]]。
  8. 返回 (accessIndex × elementSize) + offset。

25.4.3.3 ValidateAtomicAccessOnIntegerTypedArray ( ta, requestIndex )

抽象操作 ValidateAtomicAccessOnIntegerTypedArray,接收参数 ta (ECMAScript 语言值) 和 requestIndex (ECMAScript 语言值);返回值:(正常完成 (值:非负整数) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 taRecord 为 ? ValidateIntegerTypedArray(ta, false)。
  2. 返回 ? ValidateAtomicAccess(taRecord, requestIndex)。

25.4.3.4 RevalidateAtomicAccess ( ta, byteIndexInBuffer )

抽象操作 RevalidateAtomicAccess,接收参数 ta (TypedArray) 和 byteIndexInBuffer (非负整数);返回值:(正常完成 (值:unused) 或 抛出完成)。 此操作在 Atomics 方法中完成所有参数强制转换之后,重新验证原子操作在后备缓冲区中的索引,因为参数强制转换可能具有任意副作用,从而可能导致缓冲区越界。当 ta 的后备缓冲区是 SharedArrayBuffer 时,此操作不会抛出异常。 调用时执行以下步骤:

  1. 注意:当 ta 的后备缓冲区是可增长的 SharedArrayBuffer 时,边界检查不是同步操作。
  2. 令 taRecord 为 ? ValidateTypedArrayBounds(ta, unordered)。
  3. 断言:byteIndexInBuffer ≥ ta.[[ByteOffset]]。
  4. 令 elementSize 为 TypedArrayElementSize(ta)。
  5. 令 elementLastByteIndex 为 byteIndexInBuffer + elementSize - 1。
  6. 如果 elementLastByteIndex ≥ taRecord.[[CachedBufferByteLength]],则抛出 RangeError 异常。
  7. 返回 unused。

25.4.3.5 GetWaiterList ( block, i )

抽象操作 GetWaiterList,接收参数 block (共享数据块) 和 i (a non-negative integer that is evenly divisible by 4);返回值:WaiterList 记录。 调用时执行以下步骤:

  1. 断言:i 和 i + 3 是 block 内存中的有效字节偏移量。
  2. 返回由 (block, i) 对引用的 WaiterList Record。

25.4.3.6 EnterCriticalSection ( waiterList )

抽象操作 EnterCriticalSection,接收参数 waiterList (WaiterList 记录);返回值:unused。 调用时执行以下步骤:

  1. 断言:周围代理不在任何 WaiterList Record 的临界区中。
  2. 等待直到没有代理位于 waiterList 的临界区中,然后进入 waiterList 的临界区(不允许任何其他代理进入)。
  3. 如果 waiterList.[[MostRecentLeaveEvent]] 不是 empty,则
    1. 注:其临界区至少进入过一次的 waiterList 具有由 LeaveCriticalSection 设置的 Synchronize 事件。
    2. 令 agentRecord 为周围代理的 Agent Record。
    3. 令 execution 为 agentRecord.[[CandidateExecution]]。
    4. 令 eventsRecord 为 execution.[[EventsRecords]] 中 [[AgentSignifier]] 为 AgentSignifier() 的 Agent Events Record。
    5. 令 enterEvent 为新的 Synchronize 事件。
    6. 将 enterEvent 追加到 eventsRecord.[[EventList]]。
    7. 将 (waiterList.[[MostRecentLeaveEvent]], enterEvent) 追加到 eventsRecord.[[AgentSynchronizesWith]]。
  4. 返回 unused。

当尝试进入临界区的代理必须等待另一个代理离开临界区时,EnterCriticalSection 会发生争用。当不存在争用时,EnterCriticalSection 调用的 FIFO 顺序是可观察的。当存在争用时,实现可以选择任意顺序,但不得导致某个代理无限期等待。

25.4.3.7 LeaveCriticalSection ( waiterList )

抽象操作 LeaveCriticalSection,接收参数 waiterList (WaiterList 记录);返回值:unused。 调用时执行以下步骤:

  1. 断言:周围代理位于 waiterList 的临界区中。
  2. 令 agentRecord 为周围代理的 Agent Record。
  3. 令 execution 为 agentRecord.[[CandidateExecution]]。
  4. 令 eventsRecord 为 execution.[[EventsRecords]] 中 [[AgentSignifier]] 为 AgentSignifier() 的 Agent Events Record。
  5. 令 leaveEvent 为新的 Synchronize 事件。
  6. 将 leaveEvent 追加到 eventsRecord.[[EventList]]。
  7. 将 waiterList.[[MostRecentLeaveEvent]] 设置为 leaveEvent。
  8. 离开 waiterList 的临界区。
  9. 返回 unused。

25.4.3.8 AddWaiter ( waiterList, waiterRecord )

抽象操作 AddWaiter,接收参数 waiterList (WaiterList 记录) 和 waiterRecord (Waiter 记录);返回值:unused。 调用时执行以下步骤:

  1. 断言:周围代理位于 waiterList 的临界区中。
  2. 断言:waiterList.[[Waiters]] 中不存在 [[PromiseCapability]] 字段为 waiterRecord.[[PromiseCapability]] 且 [[AgentSignifier]] 字段为 waiterRecord.[[AgentSignifier]] 的 Waiter Record。
  3. 将 waiterRecord 追加到 waiterList.[[Waiters]]。
  4. 返回 unused。

25.4.3.9 RemoveWaiter ( waiterList, waiterRecord )

抽象操作 RemoveWaiter,接收参数 waiterList (WaiterList 记录) 和 waiterRecord (Waiter 记录);返回值:unused。 调用时执行以下步骤:

  1. 断言:周围代理位于 waiterList 的临界区中。
  2. 断言:waiterList.[[Waiters]] 包含 waiterRecord。
  3. 从 waiterList.[[Waiters]] 中移除 waiterRecord。
  4. 返回 unused。

25.4.3.10 RemoveWaiters ( waiterList, count )

抽象操作 RemoveWaiters,接收参数 waiterList (WaiterList 记录) 和 count ((非负整数 或 +∞));返回值:列表 (元素:Waiter 记录)。 调用时执行以下步骤:

  1. 断言:周围代理位于 waiterList 的临界区中。
  2. 令 length 为 waiterList.[[Waiters]] 中的元素数量。
  3. 将 count 设置为 min(count, length)。
  4. 令 waiters 为一个 List,其元素是 waiterList.[[Waiters]] 的前 count 个元素。
  5. 从 waiterList.[[Waiters]] 中移除前 count 个元素。
  6. 返回 waiters。

25.4.3.11 SuspendThisAgent ( waiterList, waiterRecord )

抽象操作 SuspendThisAgent,接收参数 waiterList (WaiterList 记录) 和 waiterRecord (Waiter 记录);返回值:unused。 调用时执行以下步骤:

  1. 断言:周围代理位于 waiterList 的临界区中。
  2. 断言:waiterList.[[Waiters]] 包含 waiterRecord。
  3. 令 thisAgent 为 AgentSignifier()。
  4. 断言:waiterRecord.[[AgentSignifier]] 是 thisAgent。
  5. 断言:waiterRecord.[[PromiseCapability]] 是 blocking。
  6. 断言:AgentCanSuspend() 是 true。
  7. 执行 LeaveCriticalSection(waiterList) 并挂起周围代理,直到时间达到 waiterRecord.[[TimeoutTime]],以这样的方式执行组合操作:在退出临界区之后但挂起生效之前到达的通知不会丢失。周围代理只能由于超时,或者由于另一个代理以 waiterList 和 thisAgent 作为参数调用 NotifyWaiter(即通过调用 Atomics.notify)而从挂起中唤醒。
  8. 执行 EnterCriticalSection(waiterList)。
  9. 返回 unused。

25.4.3.12 NotifyWaiter ( waiterList, waiterRecord )

抽象操作 NotifyWaiter,接收参数 waiterList (WaiterList 记录) 和 waiterRecord (Waiter 记录);返回值:unused。 调用时执行以下步骤:

  1. 断言:周围代理位于 waiterList 的临界区中。
  2. 如果 waiterRecord.[[PromiseCapability]] 是 blocking,则
    1. 将标识符为 waiterRecord.[[AgentSignifier]] 的代理从挂起中唤醒。
    2. 注:这会使该代理在 SuspendThisAgent 中恢复执行。
  3. 否则如果 AgentSignifier() 是 waiterRecord.[[AgentSignifier]],则
    1. 令 promiseCapability 为 waiterRecord.[[PromiseCapability]]。
    2. 执行 ! Call(promiseCapability.[[Resolve]], undefined, « waiterRecord.[[Result]] »)。
  4. 否则,
    1. 执行 EnqueueResolveInAgentJob(waiterRecord.[[AgentSignifier]], waiterRecord.[[PromiseCapability]], waiterRecord.[[Result]])。
  5. 返回 unused。
注

除将另一个代理的 promise capability 传递给宿主之外,代理不得以任何方式访问另一个代理的 promise capability。

25.4.3.13 EnqueueResolveInAgentJob ( agentSignifier, promiseCapability, resolution )

抽象操作 EnqueueResolveInAgentJob,接收参数 agentSignifier (an agent signifier)、promiseCapability (PromiseCapability 记录) 和 resolution (("ok" 或 "timed-out"));返回值:unused。 调用时执行以下步骤:

  1. 令 resolveJob 为不带参数的新 Job Abstract Closure,它捕获 agentSignifier、promiseCapability 和 resolution,并在被调用时执行以下步骤:
    1. 断言:AgentSignifier() 是 agentSignifier。
    2. 执行 ! Call(promiseCapability.[[Resolve]], undefined, « resolution »)。
    3. 返回 unused。
  2. 令 realmInTargetAgent 为 ! GetFunctionRealm(promiseCapability.[[Resolve]])。
  3. 断言:agentSignifier 是 realmInTargetAgent.[[AgentSignifier]]。
  4. 执行 HostEnqueueGenericJob(resolveJob, realmInTargetAgent)。
  5. 返回 unused。

25.4.3.14 DoWait ( mode, ta, index, value, timeout )

抽象操作 DoWait,接收参数 mode ((sync 或 async))、ta (ECMAScript 语言值)、index (ECMAScript 语言值)、value (ECMAScript 语言值) 和 timeout (ECMAScript 语言值);返回值:(正常完成 (值:(Object、"not-equal"、"timed-out" 或 "ok")) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 taRecord 为 ? ValidateIntegerTypedArray(ta, true)。
  2. 令 buffer 为 taRecord.[[Object]].[[ViewedArrayBuffer]]。
  3. 如果 IsSharedArrayBuffer(buffer) 是 false,则抛出 TypeError 异常。
  4. 令 byteIndexInBuffer 为 ? ValidateAtomicAccess(taRecord, index)。
  5. 令 elementType 为 TypedArrayElementType(ta)。
  6. 断言:elementType 是 bigint64 或 int32。
  7. 如果 elementType 是 bigint64,则令 expected 为 ? ToBigInt64(value);否则令 expected 为 ? ToInt32(value)。
  8. 令 timeoutNumber 为 ? ToNumber(timeout)。
  9. 如果 timeoutNumber 是 NaN 或 +∞𝔽,则令 realTimeout 为 +∞。
  10. 否则如果 timeoutNumber 是 -∞𝔽,则令 realTimeout 为 0。
  11. 否则,令 realTimeout 为 max(ℝ(timeoutNumber), 0)。
  12. 如果 mode 是 sync 且 AgentCanSuspend() 是 false,则抛出 TypeError 异常。
  13. 令 block 为 buffer.[[ArrayBufferData]]。
  14. 令 waiterList 为 GetWaiterList(block, byteIndexInBuffer)。
  15. 如果 mode 是 sync,则
    1. 令 promiseCapability 为 blocking。
    2. 令 resultObj 为 undefined。
  16. 否则,
    1. 令 promiseCapability 为 ! NewPromiseCapability(%Promise%)。
    2. 令 resultObj 为 OrdinaryObjectCreate(%Object.prototype%)。
  17. 执行 EnterCriticalSection(waiterList)。
  18. 令 witness 为 GetValueFromBuffer(buffer, byteIndexInBuffer, elementType, true, seq-cst)。
  19. 如果 expected ≠ witness,则
    1. 执行 LeaveCriticalSection(waiterList)。
    2. 如果 mode 是 sync,则返回 "not-equal"。
    3. 执行 ! CreateDataPropertyOrThrow(resultObj, "async", false)。
    4. 执行 ! CreateDataPropertyOrThrow(resultObj, "value", "not-equal")。
    5. 返回 resultObj。
  20. 如果 realTimeout = 0 且 mode 是 async,则
    1. 注:同步立即超时没有特殊处理。异步立即超时具有特殊处理,以便快速失败并避免不必要的 Promise job。
    2. 执行 LeaveCriticalSection(waiterList)。
    3. 执行 ! CreateDataPropertyOrThrow(resultObj, "async", false)。
    4. 执行 ! CreateDataPropertyOrThrow(resultObj, "value", "timed-out")。
    5. 返回 resultObj。
  21. 令 thisAgent 为 AgentSignifier()。
  22. 令 now 为标识当前时间的时间值(UTC)。
  23. 令 additionalTimeout 为由实现定义的非负数学值。
  24. 令 timeoutTime 为 ℝ(now) + realTimeout + additionalTimeout。
  25. 注:当 realTimeout 是 +∞ 时,timeoutTime 也是 +∞。
  26. 令 waiterRecord 为新的 Waiter Record { [[AgentSignifier]]: thisAgent, [[PromiseCapability]]: promiseCapability, [[TimeoutTime]]: timeoutTime, [[Result]]: "ok" }。
  27. 执行 AddWaiter(waiterList, waiterRecord)。
  28. 如果 mode 是 sync,则
    1. 执行 SuspendThisAgent(waiterList, waiterRecord)。
  29. 否则如果 timeoutTime 是有限值,则
    1. 执行 EnqueueAtomicsWaitAsyncTimeoutJob(waiterList, waiterRecord)。
  30. 执行 LeaveCriticalSection(waiterList)。
  31. 如果 mode 是 sync,则返回 waiterRecord.[[Result]]。
  32. 执行 ! CreateDataPropertyOrThrow(resultObj, "async", true)。
  33. 执行 ! CreateDataPropertyOrThrow(resultObj, "value", promiseCapability.[[Promise]])。
  34. 返回 resultObj。
注

additionalTimeout 允许实现根据需要延长超时,例如为了降低功耗或降低计时器分辨率以缓解时序攻击。DoWait 的每次调用中,此值都可能不同。

25.4.3.15 EnqueueAtomicsWaitAsyncTimeoutJob ( waiterList, waiterRecord )

抽象操作 EnqueueAtomicsWaitAsyncTimeoutJob,接收参数 waiterList (WaiterList 记录) 和 waiterRecord (Waiter 记录);返回值:unused。 调用时执行以下步骤:

  1. 令 timeoutJob 为不带参数的新 Job Abstract Closure,它捕获 waiterList 和 waiterRecord,并在被调用时执行以下步骤:
    1. 执行 EnterCriticalSection(waiterList)。
    2. 如果 waiterList.[[Waiters]] 包含 waiterRecord,则
      1. 令 timeOfJobExecution 为标识当前时间的时间值(UTC)。
      2. 断言:ℝ(timeOfJobExecution) ≥ waiterRecord.[[TimeoutTime]](忽略时间值潜在的非单调性)。
      3. 将 waiterRecord.[[Result]] 设置为 "timed-out"。
      4. 执行 RemoveWaiter(waiterList, waiterRecord)。
      5. 执行 NotifyWaiter(waiterList, waiterRecord)。
    3. 执行 LeaveCriticalSection(waiterList)。
    4. 返回 unused。
  2. 令 now 为标识当前时间的时间值(UTC)。
  3. 令 currentRealm 为当前 Realm Record。
  4. 执行 HostEnqueueTimeoutJob(timeoutJob, currentRealm, 𝔽(waiterRecord.[[TimeoutTime]]) - now)。
  5. 返回 unused。

25.4.3.16 AtomicCompareExchangeInSharedBlock ( block, byteIndexInBuffer, elementSize, expectedBytes, replacementBytes )

抽象操作 AtomicCompareExchangeInSharedBlock,接收参数 block (共享数据块)、byteIndexInBuffer (整数)、elementSize (非负整数)、expectedBytes (列表 (元素:字节值)) 和 replacementBytes (列表 (元素:字节值));返回值:列表 (元素:字节值)。 调用时执行以下步骤:

  1. 令 agentRecord 为周围代理的 Agent Record。
  2. 令 execution 为 agentRecord.[[CandidateExecution]]。
  3. 令 eventsRecord 为 execution.[[EventsRecords]] 中 [[AgentSignifier]] 为 AgentSignifier() 的 Agent Events Record。
  4. 令 rawBytesRead 为长度为 elementSize 的 List,其元素是非确定性选择的字节值。
  5. 注:在实现中,rawBytesRead 是底层硬件上的 load-link、load-exclusive 或读-修改-写指令的操作数的结果。非确定性是内存模型的语义规定,用于描述弱一致性硬件的可观察行为。
  6. 注:预期值和读取值的比较在读-修改-写修改函数之外执行,以避免在预期值不等于读取值时产生不必要的强同步。
  7. 如果 ByteListEqual(rawBytesRead, expectedBytes) 是 true,则
    1. 令 second 为参数为 (oldBytes, newBytes) 且不捕获任何内容的新读-修改-写修改函数,它在被调用时以原子方式执行以下步骤:
      1. 返回 newBytes。
    2. 令 event 为 ReadModifyWriteSharedMemory { [[Order]]: seq-cst, [[NoTear]]: true, [[Block]]: block, [[ByteIndex]]: byteIndexInBuffer, [[ElementSize]]: elementSize, [[Payload]]: replacementBytes, [[ModifyOp]]: second }。
  8. 否则,
    1. 令 event 为 ReadSharedMemory { [[Order]]: seq-cst, [[NoTear]]: true, [[Block]]: block, [[ByteIndex]]: byteIndexInBuffer, [[ElementSize]]: elementSize }。
  9. 将 event 追加到 eventsRecord.[[EventList]]。
  10. 将 Chosen Value Record { [[Event]]: event, [[ChosenValue]]: rawBytesRead } 追加到 execution.[[ChosenValues]]。
  11. 返回 rawBytesRead。

25.4.3.17 AtomicReadModifyWrite ( ta, index, value, op )

抽象操作 AtomicReadModifyWrite,接收参数 ta (ECMAScript 语言值)、index (ECMAScript 语言值)、value (ECMAScript 语言值) 和 op (a read-modify-write modification function);返回值:(正常完成 (值:(Number 或 BigInt)) 或 抛出完成)。 op 接受两个字节值 List 参数并返回一个字节值 List。此操作以原子方式加载一个值,将其与另一个值组合,并存储组合结果。它返回加载的值。 调用时执行以下步骤:

  1. 令 byteIndexInBuffer 为 ? ValidateAtomicAccessOnIntegerTypedArray(ta, index)。
  2. 如果 ta.[[ContentType]] 是 bigint,则令 coerced 为 ? ToBigInt(value)。
  3. 否则,令 coerced 为 𝔽(? ToIntegerOrInfinity(value))。
  4. 执行 ? RevalidateAtomicAccess(ta, byteIndexInBuffer)。
  5. 令 buffer 为 ta.[[ViewedArrayBuffer]]。
  6. 令 elementType 为 TypedArrayElementType(ta)。
  7. 返回 GetModifySetValueInBuffer(buffer, byteIndexInBuffer, elementType, coerced, op)。

25.4.3.18 ByteListBitwiseOp ( op, xBytes, yBytes )

抽象操作 ByteListBitwiseOp,接收参数 op ((&、^ 或 |))、xBytes (列表 (元素:字节值)) 和 yBytes (列表 (元素:字节值));返回值:列表 (元素:字节值)。 此操作以原子方式对参数的所有字节值执行按位操作,并返回一个字节值 List。 调用时执行以下步骤:

  1. 断言:xBytes 和 yBytes 具有相同的元素数量。
  2. 令 result 为新的空 List。
  3. 令 i 为 0。
  4. 对 xBytes 的每个元素 xByte,执行
    1. 令 yByte 为 yBytes[i]。
    2. 如果 op 是 &,则
      1. 令 resultByte 为对 xByte 和 yByte 应用按位 AND 操作的结果。
    3. 否则如果 op 是 ^,则
      1. 令 resultByte 为对 xByte 和 yByte 应用按位异或(XOR)操作的结果。
    4. 否则,
      1. 断言:op 是 |。
      2. 令 resultByte 为对 xByte 和 yByte 应用按位包含 OR 操作的结果。
    5. 将 i 设置为 i + 1。
    6. 将 resultByte 追加到 result。
  5. 返回 result。

25.4.3.19 ByteListEqual ( xBytes, yBytes )

抽象操作 ByteListEqual,接收参数 xBytes (列表 (元素:字节值)) 和 yBytes (列表 (元素:字节值));返回值:Boolean。 调用时执行以下步骤:

  1. 如果 xBytes 和 yBytes 不具有相同的元素数量,则返回 false。
  2. 令 i 为 0。
  3. 对 xBytes 的每个元素 xByte,执行
    1. 令 yByte 为 yBytes[i]。
    2. 如果 xByte ≠ yByte,则返回 false。
    3. 将 i 设置为 i + 1。
  4. 返回 true。

25.4.4 Atomics.add ( ta, index, value )

调用时,此函数执行以下步骤:

  1. 令 add 为参数为 (xBytes, yBytes) 的新读-修改-写修改函数,它捕获 ta,并在被调用时以原子方式执行以下步骤:
    1. 令 type 为 TypedArrayElementType(ta)。
    2. 令 agentRecord 为周围代理的 Agent Record。
    3. 令 isLittleEndian 为 agentRecord.[[LittleEndian]]。
    4. 令 x 为 RawBytesToNumeric(type, xBytes, isLittleEndian)。
    5. 令 y 为 RawBytesToNumeric(type, yBytes, isLittleEndian)。
    6. 如果 x 是 Number,则
      1. 令 sum 为 Number::add(x, y)。
    7. 否则,
      1. 断言:x 是 BigInt。
      2. 令 sum 为 BigInt::add(x, y)。
    8. 令 sumBytes 为 NumericToRawBytes(type, sum, isLittleEndian)。
    9. 断言:sumBytes、xBytes 和 yBytes 具有相同的元素数量。
    10. 返回 sumBytes。
  2. 返回 ? AtomicReadModifyWrite(ta, index, value, add)。

25.4.5 Atomics.and ( ta, index, value )

调用时,此函数执行以下步骤:

  1. 令 and 为参数为 (xBytes, yBytes) 且不捕获任何内容的新读-修改-写修改函数,它在被调用时以原子方式执行以下步骤:
    1. 返回 ByteListBitwiseOp(&, xBytes, yBytes)。
  2. 返回 ? AtomicReadModifyWrite(ta, index, value, and)。

25.4.6 Atomics.compareExchange ( ta, index, expectedValue, replacementValue )

调用时,此函数执行以下步骤:

  1. 令 byteIndexInBuffer 为 ? ValidateAtomicAccessOnIntegerTypedArray(ta, index)。
  2. 令 buffer 为 ta.[[ViewedArrayBuffer]]。
  3. 令 block 为 buffer.[[ArrayBufferData]]。
  4. 如果 ta.[[ContentType]] 是 bigint,则
    1. 令 expected 为 ? ToBigInt(expectedValue)。
    2. 令 replacement 为 ? ToBigInt(replacementValue)。
  5. 否则,
    1. 令 expected 为 𝔽(? ToIntegerOrInfinity(expectedValue))。
    2. 令 replacement 为 𝔽(? ToIntegerOrInfinity(replacementValue))。
  6. 执行 ? RevalidateAtomicAccess(ta, byteIndexInBuffer)。
  7. 令 elementType 为 TypedArrayElementType(ta)。
  8. 令 elementSize 为 TypedArrayElementSize(ta)。
  9. 令 agentRecord 为周围代理的 Agent Record。
  10. 令 isLittleEndian 为 agentRecord.[[LittleEndian]]。
  11. 令 expectedBytes 为 NumericToRawBytes(elementType, expected, isLittleEndian)。
  12. 令 replacementBytes 为 NumericToRawBytes(elementType, replacement, isLittleEndian)。
  13. 如果 IsSharedArrayBuffer(buffer) 是 true,则
    1. 令 rawBytesRead 为 AtomicCompareExchangeInSharedBlock(block, byteIndexInBuffer, elementSize, expectedBytes, replacementBytes)。
  14. 否则,
    1. 令 rawBytesRead 为长度为 elementSize 的 List,其元素是从 block[byteIndexInBuffer] 开始的 elementSize 个字节序列。
    2. 如果 ByteListEqual(rawBytesRead, expectedBytes) 是 true,则
      1. 从 block[byteIndexInBuffer] 开始,将 replacementBytes 的各个字节存储到 block 中。
  15. 返回 RawBytesToNumeric(elementType, rawBytesRead, isLittleEndian)。

25.4.7 Atomics.exchange ( ta, index, value )

调用时,此函数执行以下步骤:

  1. 令 second 为参数为 (oldBytes, newBytes) 且不捕获任何内容的新读-修改-写修改函数,它在被调用时以原子方式执行以下步骤:
    1. 返回 newBytes。
  2. 返回 ? AtomicReadModifyWrite(ta, index, value, second)。

25.4.8 Atomics.isLockFree ( size )

调用时,此函数执行以下步骤:

  1. 令 n 为 ? ToIntegerOrInfinity(size)。
  2. 令 agentRecord 为周围代理的 Agent Record。
  3. 如果 n = 1,则返回 agentRecord.[[IsLockFree1]]。
  4. 如果 n = 2,则返回 agentRecord.[[IsLockFree2]]。
  5. 如果 n = 4,则返回 true。
  6. 如果 n = 8,则返回 agentRecord.[[IsLockFree8]]。
  7. 返回 false。
注

此函数是一种优化原语。直观来说,如果在大小为 n 字节的数据上执行某个原子原语(compareExchange、load、store、add、sub、and、or、xor 或 exchange)的原子步骤时,周围代理无需获取组成该数据的 n 字节之外的锁,则 Atomics.isLockFree(n) 将返回 true。高性能算法会使用此函数来确定在临界区中是使用锁还是原子操作。如果某个原子原语不是无锁的,那么算法自行提供锁通常效率更高。

Atomics.isLockFree(4) 始终返回 true,因为所有已知相关硬件都可以支持这一点。能够假定这一点通常会简化程序。

无论此函数返回什么值,所有原子操作都保证是原子的。例如,它们绝不会在操作中间发生可见操作(例如“撕裂”)。

25.4.9 Atomics.load ( ta, index )

调用时,此函数执行以下步骤:

  1. 令 byteIndexInBuffer 为 ? ValidateAtomicAccessOnIntegerTypedArray(ta, index)。
  2. 执行 ? RevalidateAtomicAccess(ta, byteIndexInBuffer)。
  3. 令 buffer 为 ta.[[ViewedArrayBuffer]]。
  4. 令 elementType 为 TypedArrayElementType(ta)。
  5. 返回 GetValueFromBuffer(buffer, byteIndexInBuffer, elementType, true, seq-cst)。

25.4.10 Atomics.notify ( ta, index, count )

此函数通知等待队列中处于睡眠状态的一些代理。

调用时,它执行以下步骤:

  1. 令 taRecord 为 ? ValidateIntegerTypedArray(ta, true)。
  2. 令 byteIndexInBuffer 为 ? ValidateAtomicAccess(taRecord, index)。
  3. 如果 count 是 undefined,则
    1. 将 count 设置为 +∞。
  4. 否则,
    1. 令 intCount 为 ? ToIntegerOrInfinity(count)。
    2. 将 count 设置为 max(intCount, 0)。
  5. 令 buffer 为 ta.[[ViewedArrayBuffer]]。
  6. 如果 IsSharedArrayBuffer(buffer) 是 false,则返回 +0𝔽。
  7. 令 block 为 buffer.[[ArrayBufferData]]。
  8. 令 waiterList 为 GetWaiterList(block, byteIndexInBuffer)。
  9. 执行 EnterCriticalSection(waiterList)。
  10. 令 waiters 为 RemoveWaiters(waiterList, count)。
  11. 对于 waiters 中的每个元素 waiterRecord,执行
    1. 执行 NotifyWaiter(waiterList, waiterRecord)。
  12. 执行 LeaveCriticalSection(waiterList)。
  13. 令 waitersCount 为 waiters 中的元素数量。
  14. 返回 𝔽(waitersCount)。

25.4.11 Atomics.or ( ta, index, value )

调用时,此函数执行以下步骤:

  1. 令 or 为参数为 (xBytes, yBytes) 且不捕获任何内容的新读-修改-写修改函数,它在被调用时以原子方式执行以下步骤:
    1. 返回 ByteListBitwiseOp(|, xBytes, yBytes)。
  2. 返回 ? AtomicReadModifyWrite(ta, index, value, or)。

25.4.12 Atomics.pause ( )

此函数向 CPU 提供提示,表明程序正在等待某个值时进行自旋循环。

调用时,它执行以下步骤:

  1. 如果 ECMAScript 实现的执行环境支持向操作系统或 CPU 发出信号,表明当前执行的代码处于自旋等待循环中,则发送该信号。
  2. 返回 undefined。
注 1

此方法专为实现自旋等待循环的程序而设计,例如互斥锁中的自旋锁快速路径,用于向 CPU 提供提示,表明程序正在等待某个值时自旋。除了计时之外,它没有可观察行为。

如果底层架构的最佳实践建议在自旋循环中使用暂停或让出指令,则预期实现采用此类指令。例如,Intel Optimization Manual 建议使用 pause 指令。

鼓励实现在内部将最大暂停时间设定一个上限,大约为几十到几百纳秒。

注 2

由于函数调用存在开销,优化编译器中的内联调用与非内联调用等待不同的时间量是合理的。

25.4.13 Atomics.store ( ta, index, value )

调用时,此函数执行以下步骤:

  1. 令 byteIndexInBuffer 为 ? ValidateAtomicAccessOnIntegerTypedArray(ta, index)。
  2. 如果 ta.[[ContentType]] 是 bigint,则令 coerced 为 ? ToBigInt(value)。
  3. 否则,令 coerced 为 𝔽(? ToIntegerOrInfinity(value))。
  4. 执行 ? RevalidateAtomicAccess(ta, byteIndexInBuffer)。
  5. 令 buffer 为 ta.[[ViewedArrayBuffer]]。
  6. 令 elementType 为 TypedArrayElementType(ta)。
  7. 执行 SetValueInBuffer(buffer, byteIndexInBuffer, elementType, coerced, true, seq-cst)。
  8. 返回 coerced。

25.4.14 Atomics.sub ( ta, index, value )

调用时,此函数执行以下步骤:

  1. 令 subtract 为参数为 (xBytes, yBytes) 的新读-修改-写修改函数,它捕获 ta,并在被调用时以原子方式执行以下步骤:
    1. 令 type 为 TypedArrayElementType(ta)。
    2. 令 agentRecord 为周围代理的 Agent Record。
    3. 令 isLittleEndian 为 agentRecord.[[LittleEndian]]。
    4. 令 x 为 RawBytesToNumeric(type, xBytes, isLittleEndian)。
    5. 令 y 为 RawBytesToNumeric(type, yBytes, isLittleEndian)。
    6. 如果 x 是 Number,则
      1. 令 difference 为 Number::subtract(x, y)。
    7. 否则,
      1. 断言:x 是 BigInt。
      2. 令 difference 为 BigInt::subtract(x, y)。
    8. 令 differenceBytes 为 NumericToRawBytes(type, difference, isLittleEndian)。
    9. 断言:differenceBytes、xBytes 和 yBytes 具有相同的元素数量。
    10. 返回 differenceBytes。
  2. 返回 ? AtomicReadModifyWrite(ta, index, value, subtract)。

25.4.15 Atomics.wait ( ta, index, value, timeout )

此函数将周围代理放入等待队列并挂起它,直到收到通知或等待超时,并返回一个区分这些情况的 String。

调用时,它执行以下步骤:

  1. 返回 ? DoWait(sync, ta, index, value, timeout)。

25.4.16 Atomics.waitAsync ( ta, index, value, timeout )

此函数返回一个 Promise,该 Promise 在调用代理收到通知或达到超时时间时被解决。

调用时,它执行以下步骤:

  1. 返回 ? DoWait(async, ta, index, value, timeout)。

25.4.17 Atomics.xor ( ta, index, value )

调用时,此函数执行以下步骤:

  1. 令 xor 为参数为 (xBytes, yBytes) 且不捕获任何内容的新读-修改-写修改函数,它在被调用时以原子方式执行以下步骤:
    1. 返回 ByteListBitwiseOp(^, xBytes, yBytes)。
  2. 返回 ? AtomicReadModifyWrite(ta, index, value, xor)。

25.4.18 Atomics [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "Atomics"。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

25.5 JSON 对象

JSON 对象:

  • 是 %JSON%。
  • 是全局对象的 "JSON" 属性的初始值。
  • 是普通对象。
  • 包含两个函数 parse 和 stringify,用于解析和构造 JSON 文本。
  • 具有 [[Prototype]] 内部槽,其值是 %Object.prototype%。
  • 不具有 [[Construct]] 内部方法;不能与 new 运算符一起用作构造函数。
  • 不具有 [[Call]] 内部方法;不能作为函数调用。

JSON 数据交换格式定义于 ECMA-404。本规范使用的 JSON 交换格式与 ECMA-404 所述完全相同。符合规范的 JSON.parse 和 JSON.stringify 实现必须支持 ECMA-404 中描述的精确交换格式,不得对该格式进行任何删减或扩展。

25.5.1 JSON.isRawJSON ( obj )

调用时,此函数执行以下步骤:

  1. 如果 obj 是 Object 且 obj 具有 [[IsRawJSON]] 内部槽,则返回 true。
  2. 返回 false。

25.5.2 JSON.parse ( text [ , reviver ] )

此函数解析 JSON 文本(JSON 格式的 String)并生成 ECMAScript 语言值。JSON 格式使用与 ECMAScript 字面量、Array Initializer 和 Object Initializer 的语法相似的语法表示字面量、数组和对象。解析后,JSON 对象实现为 ECMAScript 对象。JSON 数组实现为 ECMAScript Array 实例。JSON 字符串、数字、布尔值和 null 分别实现为 ECMAScript String、Number、Boolean 和 null。

可选参数 reviver 是一个可以过滤和转换结果的函数。对于解析产生的每个值,都会使用三个参数(关联的属性键、该值和一个上下文对象)调用 reviver。如果属性未经修改且其值是原始值,则提供的上下文对象具有一个 "source" 属性,其中包含对应 Parse Node 的源文本。如果调用返回 undefined,则删除该属性。否则,重新定义该属性以使用返回值。

  1. 令 jsonString 为 ? ToString(text)。
  2. 令 parseResult 为 ? ParseJSON(jsonString)。
  3. 令 unfiltered 为 parseResult.[[Value]]。
  4. 如果 IsCallable(reviver) 是 false,则返回 unfiltered。
  5. 令 root 为 OrdinaryObjectCreate(%Object.prototype%)。
  6. 令 rootName 为空 String。
  7. 执行 ! CreateDataPropertyOrThrow(root, rootName, unfiltered)。
  8. 令 snapshot 为 CreateJSONParseRecord(parseResult.[[ParseNode]], rootName, unfiltered)。
  9. 返回 ? InternalizeJSONProperty(root, rootName, reviver, snapshot)。

此函数的 "length" 属性是 2𝔽。

25.5.2.1 ParseJSON ( text )

抽象操作 ParseJSON,接收参数 text (String);返回值:(正常完成 (值:记录 (字段:[[ParseNode]] (解析节点), [[Value]] (ECMAScript 语言值))) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 StringToCodePoints(text) 不是 ECMA-404 中规定的有效 JSON 文本,则抛出 SyntaxError 异常。
  2. 令 scriptString 为 "("、text 和 ");" 的字符串连接。
  3. 令 script 为 ParseText(scriptString, Script)。
  4. 注:13.2.5.1 中定义的提前错误规则对上述 ParseText 调用具有特殊处理。
  5. 断言:script 是 Parse Node。
  6. 令 result 为 ! Evaluation of script。
  7. 注:13.2.5.6 中定义的 PropertyDefinitionEvaluation 语义对上述求值具有特殊处理。
  8. 断言:result 是 String、Number、Boolean、由 ArrayLiteral 或 ObjectLiteral 定义的 Object,或者 null。
  9. 返回 Record { [[ParseNode]]: script, [[Value]]: result }。

符合规范的 JSON.parse 实现不得扩展 JSON 文法。如果实现希望支持修改或扩展的 JSON 交换格式,则必须通过定义不同的解析函数来实现。

注 1

有效 JSON 文本是 ECMAScript PrimaryExpression 语法的子集。步骤 1 验证 jsonString 是否符合该子集,步骤 8 则断言求值返回适当类型的值。

不过,由于 13.2.5.6 在 ParseJSON 期间的行为不同,因此同一源文本在作为 PrimaryExpression 而不是 JSON 求值时可能产生不同的结果。此外,对对象字面量中重复 "__proto__" 属性的提前错误同样不适用于 ParseJSON,这意味着尽管匹配文法,并非所有被 ParseJSON 接受的文本作为 PrimaryExpression 都是有效的。

注 2

如果对象中存在重复的名称 String,则词法上靠前的同键值应被覆盖。

25.5.2.2 JSON Parse Record

JSON Parse Record 是用于描述从 JSON 文本解析出的值的初始状态的 Record。

JSON Parse Record 具有 表 76 中列出的字段。

表 76: JSON Parse Record 字段
字段名称 值 含义
[[ParseNode]] a Parse Node 上下文 Parse Node。
[[Key]] a property name 与 [[Value]] 关联的属性名称。
[[Value]] an ECMAScript language value 对 [[ParseNode]] 求值产生的值。
[[Elements]] a List of JSON Parse Records 如果 [[Value]] 是 Array,则其中包含与 [[Value]] 元素对应的 JSON Parse Record。否则,这是空 List。
[[Entries]] a List of JSON Parse Records 如果 [[Value]] 是非 Array 的 Object,则其中包含与 [[Value]] 条目对应的 JSON Parse Record。否则,这是空 List。

25.5.2.3 CreateJSONParseRecord ( parseNode, key, value )

抽象操作 CreateJSONParseRecord,接收参数 parseNode (解析节点)、key (属性名) 和 value (ECMAScript 语言值);返回值:JSON Parse 记录。 它以递归方式将从 JSON 文本解析出的 parseNode 与其求值产生的 value 组合起来。 调用时执行以下步骤:

  1. 令 typedValueNode 为 ShallowestContainedJSONValue(parseNode)。
  2. 断言:typedValueNode 不是 empty。
  3. 令 elements 为新的空 List。
  4. 令 entries 为新的空 List。
  5. 如果 value 是 Object,则
    1. 令 isArray 为 ! IsArray(value)。
    2. 如果 isArray 是 true,则
      1. 断言:typedValueNode 是 ArrayLiteral Parse Node。
      2. 令 contentNodes 为 the JSONArrayLiteralContentNodes of typedValueNode。
      3. 令 length 为 contentNodes 中的元素数量。
      4. 令 valueLength 为 ! LengthOfArrayLike(value)。
      5. 断言:valueLength 是 length。
      6. 令 index 为 0。
      7. 当 index < length 时,重复执行,
        1. 令 propertyName 为 ! ToString(𝔽(index))。
        2. 令 elementParseRecord 为 CreateJSONParseRecord(contentNodes[index], propertyName, ! Get(value, propertyName))。
        3. 将 elementParseRecord 追加到 elements。
        4. 将 index 设置为 index + 1。
    3. 否则,
      1. 断言:typedValueNode 是 ObjectLiteral Parse Node。
      2. 令 propertyNodes 为 the PropertyDefinitionNodes of typedValueNode。
      3. 注:由于 value 由 JSON 文本产生且尚未被修改,因此其所有属性键都是 String,并且会被完整枚举。
      4. 令 keys 为 ! EnumerableOwnProperties(value, key)。
      5. 对 keys 的每个 String propertyKey,执行
        1. 注:如果 JSON 文本为单个对象指定了多个具有相同名称的名称/值对(例如 {"a":"lost","a":"kept"}),则结果 ECMAScript 对象对应属性的值由具有该名称的最后一对指定。
        2. 令 propertyDefinition 为 empty。
        3. 对 propertyNodes 的每个 Parse Node propertyNode,执行
          1. 令 propertyName 为 the PropName of propertyNode。
          2. 如果 propertyName 是 propertyKey,则将 propertyDefinition 设置为 propertyNode。
        4. 断言:propertyDefinition 是 PropertyDefinition : PropertyName : AssignmentExpression 。
        5. 令 propertyValueNode 为 the AssignmentExpression of propertyDefinition。
        6. 令 entryParseRecord 为 CreateJSONParseRecord(propertyValueNode, propertyKey, ! Get(value, propertyKey))。
        7. 将 entryParseRecord 追加到 entries。
  6. 否则,
    1. 断言:typedValueNode 既不是 ArrayLiteral Parse Node,也不是 ObjectLiteral Parse Node。
  7. 返回 JSON Parse Record { [[ParseNode]]: typedValueNode, [[Key]]: key, [[Value]]: value, [[Elements]]: elements, [[Entries]]: entries }。

25.5.2.4 InternalizeJSONProperty ( holder, name, reviver, parseRecord )

抽象操作 InternalizeJSONProperty,接收参数 holder (Object)、name (String)、reviver (函数对象) 和 parseRecord ((JSON Parse 记录 或 empty));返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。

注

如果 [[Delete]] 或 CreateDataProperty 返回 false,此算法有意不抛出异常。

调用时,它执行以下步骤:

  1. 令 value 为 ? Get(holder, name)。
  2. 令 context 为 OrdinaryObjectCreate(%Object.prototype%)。
  3. 如果 parseRecord 是 JSON Parse Record 且 SameValue(parseRecord.[[Value]], value) 是 true,则
    1. 如果 value 不是 Object,则
      1. 令 parseNode 为 parseRecord.[[ParseNode]]。
      2. 断言:parseNode 既不是 ArrayLiteral Parse Node,也不是 ObjectLiteral Parse Node。
      3. 令 sourceText 为 parseNode 匹配的源文本。
      4. 执行 ! CreateDataPropertyOrThrow(context, "source", CodePointsToString(sourceText))。
    2. 令 elementRecords 为 parseRecord.[[Elements]]。
    3. 令 entryRecords 为 parseRecord.[[Entries]]。
  4. 否则,
    1. 令 elementRecords 为新的空 List。
    2. 令 entryRecords 为新的空 List。
  5. 如果 value 是 Object,则
    1. 令 isArray 为 ? IsArray(value)。
    2. 如果 isArray 是 true,则
      1. 令 elementRecordsLength 为 elementRecords 中的元素数量。
      2. 令 length 为 ? LengthOfArrayLike(value)。
      3. 令 index 为 0。
      4. 当 index < length 时,重复执行,
        1. 令 propertyKey 为 ! ToString(𝔽(index))。
        2. 如果 index < elementRecordsLength,则令 elementRecord 为 elementRecords[index];否则令 elementRecord 为 empty。
        3. 令 newElement 为 ? InternalizeJSONProperty(value, propertyKey, reviver, elementRecord)。
        4. 如果 newElement 是 undefined,则
          1. 执行 ? value.[[Delete]](propertyKey)。
        5. 否则,
          1. 执行 ? CreateDataProperty(value, propertyKey, newElement)。
        6. 将 index 设置为 index + 1。
    3. 否则,
      1. 令 keys 为 ? EnumerableOwnProperties(value, key)。
      2. 对 keys 的每个 String propertyKey,执行
        1. 如果 entryRecords 中存在元素 entry,使得 entry.[[Key]] 是 propertyKey,则令 entryRecord 为 entry;否则令 entryRecord 为 empty。
        2. 令 newElement 为 ? InternalizeJSONProperty(value, propertyKey, reviver, entryRecord)。
        3. 如果 newElement 是 undefined,则
          1. 执行 ? value.[[Delete]](propertyKey)。
        4. 否则,
          1. 执行 ? CreateDataProperty(value, propertyKey, newElement)。
  6. 返回 ? Call(reviver, holder, « name, value, context »)。

25.5.2.5 Static Semantics: ShallowestContainedJSONValue ( root )

抽象操作 ShallowestContainedJSONValue,接收参数 root (解析节点);返回值:(解析节点 或 empty)。 它对以 root 为根的解析树执行广度优先搜索,并返回第一个属于与 JSON 值对应的非终结符实例的节点;如果不存在此类节点,则返回 empty。 调用时执行以下步骤:

  1. 令 activeFunc 为活动函数对象。
  2. 断言:activeFunc 是 JSON.parse 内置函数对象(参见 JSON.parse)。
  3. 令 types 为 « NullLiteral, BooleanLiteral, NumericLiteral, StringLiteral, ArrayLiteral, ObjectLiteral, UnaryExpression »。
  4. 令 unaryExpr 为 empty。
  5. 令 queue 为 « root »。
  6. 当 queue 非空时,重复执行,
    1. 令 candidate 为 queue 的第一个元素。
    2. 从 queue 中移除第一个元素。
    3. 令 queuedChildren 为 false。
    4. 对 types 的每个非终结符 type,执行
      1. 如果 candidate 是 type 的实例,则
        1. 注:在 JSON 文法中,number token 可以表示负值。在 ECMAScript 中,取负表示为一元操作,其中 UnaryExpression 解析为 - 后跟派生的 UnaryExpression。
        2. 如果 type 是 UnaryExpression,则
          1. 如果 candidate 的父节点不是 UnaryExpression Parse Node,则将 unaryExpr 设置为 candidate。
        3. 否则如果 type 是 NumericLiteral,则
          1. 断言:candidate 包含在 unaryExpr 中。
          2. 返回 unaryExpr。
        4. 否则,
          1. 返回 candidate。
      2. 如果 queuedChildren 是 false,candidate 是某个非终结符的实例,并且 candidate Contains type 是 true,则
        1. 令 children 为一个 List,其中按顺序包含 candidate 的每个子节点。
        2. 将 queue 设置为 queue 和 children 的列表连接。
        3. 将 queuedChildren 设置为 true。
  7. 返回 empty。

25.5.2.6 Static Semantics: JSONArrayLiteralContentNodes

语法制导操作 JSONArrayLiteralContentNodes,接收无参数;返回值:列表 (元素:解析节点)。 它按以下产生式分别定义:

ArrayLiteral : [ Elisionopt ] [ ElementList ] [ ElementList , Elisionopt ]
  1. 断言:不存在 Elision。
  2. 如果不存在 ElementList,则返回新的空 List。
  3. 返回 the JSONArrayLiteralContentNodes of ElementList。
ElementList : Elisionopt AssignmentExpression
  1. 断言:不存在 Elision。
  2. 返回 « AssignmentExpression »。
ElementList : ElementList , Elisionopt AssignmentExpression
  1. 断言:不存在 Elision。
  2. 令 elements 为 the JSONArrayLiteralContentNodes of the derived ElementList。
  3. 返回 elements 和 « AssignmentExpression » 的列表连接。
ElementList : Elisionopt SpreadElement ElementList , Elisionopt SpreadElement
  1. 注:ECMA-404 中规定的 JSON 文本不包含 SpreadElement。
  2. 断言:永远不会到达此步骤。

25.5.3 JSON.rawJSON ( text )

此函数返回一个对象,表示字符串、数字、布尔值或 null 值的原始 JSON 文本。

  1. 令 jsonString 为 ? ToString(text)。
  2. 如果 jsonString 是空 String,则抛出 SyntaxError 异常。
  3. 如果 jsonString 的第一个码元既不是 ASCII 小写字母码元(0x0061 到 0x007A,包含端点)、ASCII 数字码元(0x0030 到 0x0039,包含端点)、0x0022 (QUOTATION MARK),也不是 0x002D (HYPHEN-MINUS),则抛出 SyntaxError 异常。
  4. 如果 jsonString 的最后一个码元既不是 ASCII 小写字母码元(0x0061 到 0x007A,包含端点)、ASCII 数字码元(0x0030 到 0x0039,包含端点),也不是 0x0022 (QUOTATION MARK),则抛出 SyntaxError 异常。
  5. 令 parseResult 为 ? ParseJSON(jsonString)。
  6. 断言:parseResult.[[Value]] 是 String、Number、Boolean 或 null。
  7. 令 internalSlotsList 为 « [[IsRawJSON]] »。
  8. 令 obj 为 OrdinaryObjectCreate(null, internalSlotsList)。
  9. 执行 ! CreateDataPropertyOrThrow(obj, "rawJSON", jsonString)。
  10. 执行 ! SetIntegrityLevel(obj, frozen)。
  11. 返回 obj。

25.5.4 JSON.stringify ( value [ , replacer [ , space ] ] )

此函数返回一个以 UTF-16 编码的 JSON 格式表示 ECMAScript 语言值的 String,或者返回 undefined。它可以接受三个参数。value 参数是 ECMAScript 语言值,通常是对象或数组,但也可以是 String、Boolean、Number 或 null。可选参数 replacer 要么是改变对象和数组字符串化方式的函数,要么是充当包含列表的 String 和 Number 数组,用于选择要字符串化的对象属性。可选参数 space 是 String 或 Number,它允许向结果中插入空白以提高人类可读性。

调用时,它执行以下步骤:

  1. 令 stack 为新的空 List。
  2. 令 indent 为空 String。
  3. 令 propertyList 为 undefined。
  4. 令 replacerFunc 为 undefined。
  5. 如果 replacer 是 Object,则
    1. 如果 IsCallable(replacer) 是 true,则
      1. 将 replacerFunc 设置为 replacer。
    2. 否则,
      1. 令 isArray 为 ? IsArray(replacer)。
      2. 如果 isArray 是 true,则
        1. 将 propertyList 设置为新的空 List。
        2. 令 length 为 ? LengthOfArrayLike(replacer)。
        3. 令 k 为 0。
        4. 当 k < length 时,重复执行,
          1. 令 propertyKey 为 ! ToString(𝔽(k))。
          2. 令 propertyValue 为 ? Get(replacer, propertyKey)。
          3. 令 item 为 undefined。
          4. 如果 propertyValue 是 String,则
            1. 将 item 设置为 propertyValue。
          5. 否则如果 propertyValue 是 Number,则
            1. 将 item 设置为 ! ToString(propertyValue)。
          6. 否则如果 propertyValue 是 Object,则
            1. 如果 propertyValue 具有 [[StringData]] 或 [[NumberData]] 内部槽,则将 item 设置为 ? ToString(propertyValue)。
          7. 如果 item 不是 undefined 且 propertyList 不包含 item,则
            1. 将 item 追加到 propertyList。
          8. 将 k 设置为 k + 1。
  6. 如果 space 是 Object,则
    1. 如果 space 具有 [[NumberData]] 内部槽,则
      1. 将 space 设置为 ? ToNumber(space)。
    2. 否则如果 space 具有 [[StringData]] 内部槽,则
      1. 将 space 设置为 ? ToString(space)。
  7. 如果 space 是 Number,则
    1. 令 spaceMV 为 ! ToIntegerOrInfinity(space)。
    2. 将 spaceMV 设置为 min(10, spaceMV)。
    3. 如果 spaceMV < 1,则令 gap 为空 String;否则令 gap 为包含 spaceMV 个码元 0x0020 (SPACE) 的 String 值。
  8. 否则如果 space 是 String,则
    1. 如果 space 的长度 ≤ 10,则令 gap 为 space;否则令 gap 为 space 从 0 到 10 的子字符串。
  9. 否则,
    1. 令 gap 为空 String。
  10. 令 wrapper 为 OrdinaryObjectCreate(%Object.prototype%)。
  11. 执行 ! CreateDataPropertyOrThrow(wrapper, the empty String, value)。
  12. 令 state 为 JSON Serialization Record { [[ReplacerFunction]]: replacerFunc, [[Stack]]: stack, [[Indent]]: indent, [[Gap]]: gap, [[PropertyList]]: propertyList }。
  13. 返回 ? SerializeJSONProperty(state, the empty String, wrapper)。

此函数的 "length" 属性是 3𝔽。

注 1

JSON 结构允许嵌套到任意深度,但必须是无环的。如果 value 是循环结构或包含循环结构,则此函数必须抛出 TypeError 异常。以下是一个无法字符串化的值的示例:

a = [];
a[0] = a;
my_text = JSON.stringify(a); // 这里必须抛出 TypeError。
注 2

符号原始值按如下方式呈现:

  • null 值在 JSON 文本中呈现为 String 值 "null"。
  • undefined 值不会被呈现。
  • true 值在 JSON 文本中呈现为 String 值 "true"。
  • false 值在 JSON 文本中呈现为 String 值 "false"。
注 3

String 值由 QUOTATION MARK (") 码元包围。码元 " 和 \ 使用 \ 前缀进行转义。控制字符码元被替换为转义序列 \uHHHH,或者替换为更短的形式 \b (BACKSPACE)、\f (FORM FEED)、\n (LINE FEED)、\r (CARRIAGE RETURN)、\t (CHARACTER TABULATION)。

注 4

每个有限 Number 都如同通过调用 ToString(number) 一样被字符串化。NaN、+∞𝔽 和 -∞𝔽 表示为 String 值 "null"。

注 5

没有 JSON 表示的值(例如 undefined 和函数)不会产生 String。相反,它们产生 undefined 值。在数组中,这些值表示为 String 值 "null"。在对象中,无法表示的值会导致该属性被排除在字符串化之外。

注 6

对象呈现为 U+007B (LEFT CURLY BRACKET),后跟零个或多个属性,属性之间以 U+002C (COMMA) 分隔,并以 U+007D (RIGHT CURLY BRACKET) 结束。属性由表示属性名称的带引号 String、一个 U+003A (COLON),以及随后字符串化的属性值组成。数组呈现为开头的 U+005B (LEFT SQUARE BRACKET),后跟零个或多个值,值之间以 U+002C (COMMA) 分隔,并以 U+005D (RIGHT SQUARE BRACKET) 结束。

25.5.4.1 JSON Serialization Record

JSON Serialization Record 是用于实现序列化为 JSON 格式的 Record。

JSON Serialization Record 具有 表 77 中列出的字段。

表 77: JSON Serialization Record 字段
字段名称 值 含义
[[ReplacerFunction]] a function object or undefined 可以为对象属性提供替换值的函数(来自 JSON.stringify 的 replacer 参数)。
[[PropertyList]] either a List of Strings or undefined 序列化非数组对象时要包含的属性名称(来自 JSON.stringify 的 replacer 参数)。
[[Gap]] a String 缩进单位(来自 JSON.stringify 的 space 参数)。
[[Stack]] a List of Objects 正在序列化的嵌套对象集合。用于检测循环结构。
[[Indent]] a String 当前缩进。

25.5.4.2 SerializeJSONProperty ( state, key, holder )

抽象操作 SerializeJSONProperty,接收参数 state (JSON Serialization 记录)、key (String) 和 holder (Object);返回值:(正常完成 (值:(String 或 undefined)) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 value 为 ? Get(holder, key)。
  2. 如果 value 是 Object 或 value 是 BigInt,那么
    1. 令 toJSON 为 ? GetV(value, "toJSON")。
    2. 如果 IsCallable(toJSON) 是 true,那么
      1. 将 value 设置为 ? Call(toJSON, value, « key »)。
  3. 如果 state.[[ReplacerFunction]] 不是 undefined,那么
    1. 将 value 设置为 ? Call(state.[[ReplacerFunction]], holder, « key, value »)。
  4. 如果 value 是 Object,那么
    1. 如果 value 具有 [[IsRawJSON]] 内部槽,那么
      1. 令 rawJSON 为 ! Get(value, "rawJSON")。
      2. 断言:rawJSON 是 String。
      3. 返回 rawJSON。
    2. 如果 value 具有 [[NumberData]] 内部槽,那么
      1. 将 value 设置为 ? ToNumber(value)。
    3. 否则,如果 value 具有 [[StringData]] 内部槽,那么
      1. 将 value 设置为 ? ToString(value)。
    4. 否则,如果 value 具有 [[BooleanData]] 内部槽,那么
      1. 将 value 设置为 value.[[BooleanData]]。
    5. 否则,如果 value 具有 [[BigIntData]] 内部槽,那么
      1. 将 value 设置为 value.[[BigIntData]]。
  5. 如果 value 是 null,返回 "null"。
  6. 如果 value 是 true,返回 "true"。
  7. 如果 value 是 false,返回 "false"。
  8. 如果 value 是 String,返回 QuoteJSONString(value)。
  9. 如果 value 是 Number,那么
    1. 如果 value 是有限 Number,返回 ! ToString(value)。
    2. 返回 "null"。
  10. 如果 value 是 BigInt,抛出 TypeError 异常。
  11. 如果 value 是 Object 且 IsCallable(value) 是 false,那么
    1. 令 isArray 为 ? IsArray(value)。
    2. 如果 isArray 是 true,那么
      1. 返回 ? SerializeJSONArray(state, value)。
    3. 返回 ? SerializeJSONObject(state, value)。
  12. 返回 undefined。

25.5.4.3 QuoteJSONString ( value )

抽象操作 QuoteJSONString,接收参数 value (String);返回值:String。 它使用 0x0022 (QUOTATION MARK) 码元包围 value,并转义其中的某些其他码元。此操作将 value 解释为 UTF-16 编码的码点序列,如 6.1.4 所述。 调用时执行以下步骤:

  1. 令 product 为仅由码元 0x0022 (QUOTATION MARK) 组成的 String 值。
  2. 对 StringToCodePoints(value) 的每个码点 codePoint,执行
    1. 如果 codePoint 列在 表 78 的 “Code Point” 列中,则
      1. 将 product 设置为 product 与对应行 “Escape Sequence” 列中为 codePoint 指定的转义序列的字符串连接。
    2. 否则如果 codePoint 的数值小于 0x0020 (SPACE),或者 codePoint 的数值与前导代理或尾随代理的数值相同,则
      1. 令 unit 为其数值等于 codePoint 数值的码元。
      2. 将 product 设置为 product 和 UnicodeEscape(unit) 的字符串连接。
    3. 否则,
      1. 将 product 设置为 product 和 UTF16EncodeCodePoint(codePoint) 的字符串连接。
  3. 将 product 设置为 product 和码元 0x0022 (QUOTATION MARK) 的字符串连接。
  4. 返回 product。
表 78: JSON 单字符转义序列
码点 Unicode 字符名称 转义序列
U+0008 BACKSPACE \b
U+0009 CHARACTER TABULATION \t
U+000A LINE FEED (LF) \n
U+000C FORM FEED (FF) \f
U+000D CARRIAGE RETURN (CR) \r
U+0022 QUOTATION MARK \"
U+005C REVERSE SOLIDUS \\

25.5.4.4 UnicodeEscape ( codeUnit )

抽象操作 UnicodeEscape,接收参数 codeUnit (码元);返回值:String。 它将 codeUnit 表示为 Unicode 转义序列。 调用时执行以下步骤:

  1. 令 n 为 codeUnit 的数值。
  2. 断言:n ≤ 0xFFFF。
  3. 令 hex 为 n 的 String 表示,格式化为小写十六进制数。
  4. 返回码元 0x005C (REVERSE SOLIDUS)、"u" 和 StringPad(hex, 4, "0", start) 的字符串连接。

25.5.4.5 SerializeJSONObject ( state, value )

抽象操作 SerializeJSONObject,接收参数 state (JSON Serialization 记录) 和 value (Object);返回值:(正常完成 (值:String) 或 抛出完成)。 它序列化一个对象。 调用时执行以下步骤:

  1. 如果 state.[[Stack]] 包含 value,则由于该结构是循环的而抛出 TypeError 异常。
  2. 将 value 追加到 state.[[Stack]]。
  3. 令 stepBack 为 state.[[Indent]]。
  4. 将 state.[[Indent]] 设置为 state.[[Indent]] 和 state.[[Gap]] 的字符串连接。
  5. 如果 state.[[PropertyList]] 不是 undefined,则
    1. 令 keys 为 state.[[PropertyList]]。
  6. 否则,
    1. 令 keys 为 ? EnumerableOwnProperties(value, key)。
  7. 令 partial 为新的空 List。
  8. 对 keys 的每个元素 propertyKey,执行
    1. 令 stringP 为 ? SerializeJSONProperty(state, propertyKey, value)。
    2. 如果 stringP 不是 undefined,则
      1. 令 member 为 QuoteJSONString(propertyKey)。
      2. 将 member 设置为 member 和 ":" 的字符串连接。
      3. 如果 state.[[Gap]] 不是空 String,则
        1. 将 member 设置为 member 和码元 0x0020 (SPACE) 的字符串连接。
      4. 将 member 设置为 member 和 stringP 的字符串连接。
      5. 将 member 追加到 partial。
  9. 如果 partial 为空,则
    1. 令 final 为 "{}"。
  10. 否则,
    1. 如果 state.[[Gap]] 是空 String,则
      1. 令 properties 为通过连接 partial 的所有元素 String 形成的 String 值,每对相邻 String 之间以码元 0x002C (COMMA) 分隔。第一个 String 之前和最后一个 String 之后都不会插入逗号。
      2. 令 final 为 "{"、properties 和 "}" 的字符串连接。
    2. 否则,
      1. 令 separator 为码元 0x002C (COMMA)、码元 0x000A (LINE FEED) 和 state.[[Indent]] 的字符串连接。
      2. 令 properties 为通过连接 partial 的所有元素 String 形成的 String 值,每对相邻 String 之间以 separator 分隔。第一个 String 之前和最后一个 String 之后都不会插入 separator String。
      3. 令 final 为 "{"、码元 0x000A (LINE FEED)、state.[[Indent]]、properties、码元 0x000A (LINE FEED)、stepBack 和 "}" 的字符串连接。
  11. 移除 state.[[Stack]] 的最后一个元素。
  12. 将 state.[[Indent]] 设置为 stepBack。
  13. 返回 final。

25.5.4.6 SerializeJSONArray ( state, value )

抽象操作 SerializeJSONArray,接收参数 state (JSON Serialization 记录) 和 value (Object);返回值:(正常完成 (值:String) 或 抛出完成)。 它序列化一个数组。 调用时执行以下步骤:

  1. 如果 state.[[Stack]] 包含 value,则由于该结构是循环的而抛出 TypeError 异常。
  2. 将 value 追加到 state.[[Stack]]。
  3. 令 stepBack 为 state.[[Indent]]。
  4. 将 state.[[Indent]] 设置为 state.[[Indent]] 和 state.[[Gap]] 的字符串连接。
  5. 令 partial 为新的空 List。
  6. 令 length 为 ? LengthOfArrayLike(value)。
  7. 令 index 为 0。
  8. 当 index < length 时,重复执行,
    1. 令 stringP 为 ? SerializeJSONProperty(state, ! ToString(𝔽(index)), value)。
    2. 如果 stringP 是 undefined,则
      1. 将 "null" 追加到 partial。
    3. 否则,
      1. 将 stringP 追加到 partial。
    4. 将 index 设置为 index + 1。
  9. 如果 partial 为空,则
    1. 令 final 为 "[]"。
  10. 否则,
    1. 如果 state.[[Gap]] 是空 String,则
      1. 令 properties 为通过连接 partial 的所有元素 String 形成的 String 值,每对相邻 String 之间以码元 0x002C (COMMA) 分隔。第一个 String 之前和最后一个 String 之后都不会插入逗号。
      2. 令 final 为 "["、properties 和 "]" 的字符串连接。
    2. 否则,
      1. 令 separator 为码元 0x002C (COMMA)、码元 0x000A (LINE FEED) 和 state.[[Indent]] 的字符串连接。
      2. 令 properties 为通过连接 partial 的所有元素 String 形成的 String 值,每对相邻 String 之间以 separator 分隔。第一个 String 之前和最后一个 String 之后都不会插入 separator String。
      3. 令 final 为 "["、码元 0x000A (LINE FEED)、state.[[Indent]]、properties、码元 0x000A (LINE FEED)、stepBack 和 "]" 的字符串连接。
  11. 移除 state.[[Stack]] 的最后一个元素。
  12. 将 state.[[Indent]] 设置为 stepBack。
  13. 返回 final。
注

数组的表示仅包括从 +0𝔽(包含)到 array.length(不包含)区间内的元素。键不是数组索引的属性会被排除在字符串化之外。数组被字符串化为开头的 LEFT SQUARE BRACKET、以 COMMA 分隔的元素以及结尾的 RIGHT SQUARE BRACKET。

25.5.5 JSON [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "JSON"。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

26 内存管理

26.1 WeakRef 对象

WeakRef 是一种用于引用目标对象或符号而不会阻止其被垃圾回收的对象。如果目标尚未被垃圾回收回收,则可以对 WeakRef 进行解引用以访问目标值。

26.1.1 WeakRef 构造函数

WeakRef 构造函数:

  • 是 %WeakRef%。
  • 是全局对象的 "WeakRef" 属性的初始值。
  • 作为构造函数调用时,创建并初始化新的 WeakRef。
  • 不旨在作为函数调用,并且以这种方式调用时会抛出异常。
  • 可以用作类定义的 extends 子句中的值。希望继承指定 WeakRef 行为的子类构造函数必须包含对 WeakRef 构造函数的 super 调用,以创建并初始化具有支持 WeakRef.prototype 内置方法所必需内部状态的子类实例。

26.1.1.1 WeakRef ( target )

调用时,此函数执行以下步骤:

  1. 如果 NewTarget 是 undefined,则抛出 TypeError 异常。
  2. 如果 CanBeHeldWeakly(target) 是 false,则抛出 TypeError 异常。
  3. 令 weakRef 为 ? OrdinaryCreateFromConstructor(NewTarget, "%WeakRef.prototype%", « [[WeakRefTarget]] »)。
  4. 执行 AddToKeptObjects(target)。
  5. 将 weakRef.[[WeakRefTarget]] 设置为 target。
  6. 返回 weakRef。

26.1.2 WeakRef 构造函数的属性

WeakRef 构造函数:

26.1.2.1 WeakRef.prototype

WeakRef.prototype 的初始值是 WeakRef 原型对象。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

26.1.3 WeakRef 原型对象的属性

WeakRef 原型对象:

  • 是 %WeakRef.prototype%。
  • 具有 [[Prototype]] 内部槽,其值是 %Object.prototype%。
  • 是普通对象。
  • 不具有 [[WeakRefTarget]] 内部槽。

26.1.3.1 WeakRef.prototype.constructor

WeakRef.prototype.constructor 的初始值是 %WeakRef%。

26.1.3.2 WeakRef.prototype.deref ( )

调用时,此方法执行以下步骤:

  1. 令 weakRef 为 this value。
  2. 执行 ? RequireInternalSlot(weakRef, [[WeakRefTarget]])。
  3. 返回 WeakRefDeref(weakRef)。
注

如果 WeakRef 返回的 target 值不是 undefined,那么在当前 ECMAScript 代码执行完成之前,不应对该 target 值进行垃圾回收。AddToKeptObjects 操作用于确保保持读取一致性。

let target = { foo() {} };
let weakRef = new WeakRef(target);

// ... 稍后 ...

if (weakRef.deref()) {
  weakRef.deref().foo();
}

在上述示例中,如果第一次 deref 的求值结果不是 undefined,那么第二次 deref 的求值结果也不可能是 undefined。

26.1.3.3 WeakRef.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "WeakRef"。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

26.1.4 WeakRef 抽象操作

26.1.4.1 WeakRefDeref ( weakRef )

抽象操作 WeakRefDeref,接收参数 weakRef (WeakRef);返回值:ECMAScript 语言值。 调用时执行以下步骤:

  1. 令 target 为 weakRef.[[WeakRefTarget]]。
  2. 如果 target 不是 empty,则
    1. 执行 AddToKeptObjects(target)。
    2. 返回 target。
  3. 返回 undefined。
注

此抽象操作与 WeakRef.prototype.deref 分开定义,仅仅是为了能够简洁地定义活性。

26.1.5 WeakRef 实例的属性

WeakRef 实例是从 WeakRef 原型对象继承属性的普通对象。WeakRef 实例还具有 [[WeakRefTarget]] 内部槽。

26.2 FinalizationRegistry 对象

FinalizationRegistry 是一种管理清理操作的注册和取消注册的对象,这些清理操作会在目标对象和符号被垃圾回收时执行。

26.2.1 FinalizationRegistry 构造函数

FinalizationRegistry 构造函数:

  • 是 %FinalizationRegistry%。
  • 是全局对象的 "FinalizationRegistry" 属性的初始值。
  • 作为构造函数调用时,创建并初始化新的 FinalizationRegistry。
  • 不旨在作为函数调用,并且以这种方式调用时会抛出异常。
  • 可以用作类定义的 extends 子句中的值。希望继承指定 FinalizationRegistry 行为的子类构造函数必须包含对 FinalizationRegistry 构造函数的 super 调用,以创建并初始化具有支持 FinalizationRegistry.prototype 内置方法所必需内部状态的子类实例。

26.2.1.1 FinalizationRegistry ( cleanupCallback )

调用时,此函数执行以下步骤:

  1. 如果 NewTarget 是 undefined,则抛出 TypeError 异常。
  2. 如果 IsCallable(cleanupCallback) 是 false,则抛出 TypeError 异常。
  3. 令 finalizationRegistry 为 ? OrdinaryCreateFromConstructor(NewTarget, "%FinalizationRegistry.prototype%", « [[Realm]], [[CleanupCallback]], [[Cells]] »)。
  4. 令 activeFunc 为活动函数对象。
  5. 将 finalizationRegistry.[[Realm]] 设置为 activeFunc.[[Realm]]。
  6. 将 finalizationRegistry.[[CleanupCallback]] 设置为 HostMakeJobCallback(cleanupCallback)。
  7. 将 finalizationRegistry.[[Cells]] 设置为新的空 List。
  8. 返回 finalizationRegistry。

26.2.2 FinalizationRegistry 构造函数的属性

FinalizationRegistry 构造函数:

26.2.2.1 FinalizationRegistry.prototype

FinalizationRegistry.prototype 的初始值是 FinalizationRegistry 原型对象。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

26.2.3 FinalizationRegistry 原型对象的属性

FinalizationRegistry 原型对象:

  • 是 %FinalizationRegistry.prototype%。
  • 具有 [[Prototype]] 内部槽,其值是 %Object.prototype%。
  • 是普通对象。
  • 不具有 [[Cells]] 和 [[CleanupCallback]] 内部槽。

26.2.3.1 FinalizationRegistry.prototype.constructor

FinalizationRegistry.prototype.constructor 的初始值是 %FinalizationRegistry%。

26.2.3.2 FinalizationRegistry.prototype.register ( target, heldValue [ , unregisterToken ] )

调用时,此方法执行以下步骤:

  1. 令 finalizationRegistry 为 this value。
  2. 执行 ? RequireInternalSlot(finalizationRegistry, [[Cells]])。
  3. 如果 CanBeHeldWeakly(target) 是 false,则抛出 TypeError 异常。
  4. 如果 SameValue(target, heldValue) 是 true,则抛出 TypeError 异常。
  5. 如果 CanBeHeldWeakly(unregisterToken) 是 false,则
    1. 如果 unregisterToken 不是 undefined,则抛出 TypeError 异常。
    2. 将 unregisterToken 设置为 empty。
  6. 令 cell 为 Record { [[WeakRefTarget]]: target, [[HeldValue]]: heldValue, [[UnregisterToken]]: unregisterToken }。
  7. 将 cell 追加到 finalizationRegistry.[[Cells]]。
  8. 返回 undefined。
注

根据本规范中的算法和定义,当 finalizationRegistry.[[Cells]] 包含 cell 时,cell.[[HeldValue]] 是存活的;不过,这并不一定意味着 cell.[[UnregisterToken]] 或 cell.[[Target]] 是存活的。例如,将对象自身注册为其取消注册 token 并不会使该对象永远保持存活。

26.2.3.3 FinalizationRegistry.prototype.unregister ( unregisterToken )

调用时,此方法执行以下步骤:

  1. 令 finalizationRegistry 为 this value。
  2. 执行 ? RequireInternalSlot(finalizationRegistry, [[Cells]])。
  3. 如果 CanBeHeldWeakly(unregisterToken) 是 false,则抛出 TypeError 异常。
  4. 令 removed 为 false。
  5. 对 finalizationRegistry.[[Cells]] 的每个 Record { [[WeakRefTarget]], [[HeldValue]], [[UnregisterToken]] } cell,执行
    1. 如果 cell.[[UnregisterToken]] 不是 empty 且 SameValue(cell.[[UnregisterToken]], unregisterToken) 是 true,则
      1. 从 finalizationRegistry.[[Cells]] 中移除 cell。
      2. 将 removed 设置为 true。
  6. 返回 removed。

26.2.3.4 FinalizationRegistry.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "FinalizationRegistry"。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

26.2.4 FinalizationRegistry 实例的属性

FinalizationRegistry 实例是从 FinalizationRegistry 原型对象继承属性的普通对象。FinalizationRegistry 实例还具有 [[Cells]] 和 [[CleanupCallback]] 内部槽。

27 控制抽象对象

27.1 迭代

27.1.1 通用迭代接口

接口是一组属性键,其关联值符合特定规范。任何提供接口规范所描述全部属性的对象都符合该接口。接口并不由某个独立对象表示。可能有许多分别实现的对象符合任意一个接口。单个对象可以符合多个接口。

27.1.1.1 Iterable 接口

iterable 接口包含 表 79 中描述的属性:

表 79: Iterable 接口必需属性
属性 值 要求
%Symbol.iterator% a function that returns an iterator object 返回的对象必须符合 iterator 接口。

27.1.1.2 Iterator 接口

实现 iterator 接口的对象必须包含 表 80 中的属性。此类对象还可以实现 表 81 中的属性。

表 80: Iterator 接口必需属性
属性 值 要求
"next" a function that returns an IteratorResult object 返回的对象必须符合 IteratorResult 接口。如果先前对某个 iterator 的 next 方法的调用已经返回了一个 "done" 属性为 true 的 IteratorResult 对象,那么对该对象的所有后续 next 方法调用也应返回 "done" 属性为 true 的 IteratorResult 对象。不过,此要求不会被强制执行。
注 1

可以向 next 函数传递参数,但这些参数的解释和有效性取决于目标 iterator。for-of 语句和 iterator 的其他常见使用者不会传递任何参数,因此预期以这种方式使用的 iterator 对象必须能够处理无参数调用。

表 81: Iterator 接口可选属性
属性 值 要求
"return" a function that returns an IteratorResult object 返回的对象必须符合 IteratorResult 接口。调用此方法会通知 iterator 对象,调用者不打算再对该 iterator 进行任何 next 方法调用。返回的 IteratorResult 对象通常具有值为 true 的 "done" 属性,以及一个 "value" 属性,其值为作为 return 方法参数传入的值。不过,此要求不会被强制执行。
"throw" a function that returns an IteratorResult object 返回的对象必须符合 IteratorResult 接口。调用此方法会通知 iterator 对象,调用者检测到了错误条件。参数可以用于标识错误条件,通常会是异常对象。典型响应是 throw 作为参数传入的值。如果该方法没有 throw,则返回的 IteratorResult 对象通常具有值为 true 的 "done" 属性。
注 2

通常,这些方法的调用者在调用它们之前应检查它们是否存在。包括 for-of、yield* 和数组解构在内的某些 ECMAScript 语言特性会在执行存在性检查后调用这些方法。大多数接受 iterable 对象作为参数的 ECMAScript 库函数也会有条件地调用它们。

27.1.1.3 Async Iterable 接口

async iterable 接口包含 表 82 中描述的属性:

表 82: Async Iterable 接口必需属性
属性 值 要求
%Symbol.asyncIterator% a function that returns an async iterator object 返回的对象必须符合 async iterator 接口。

27.1.1.4 Async Iterator 接口

实现 async iterator 接口的对象必须包含 表 83 中的属性。此类对象还可以实现 表 84 中的属性。

表 83: Async Iterator 接口必需属性
属性 值 要求
"next" a function that returns a promise for an IteratorResult object

返回的 promise 在兑现时,必须以符合 IteratorResult 接口的对象作为兑现值。如果先前对 async iterator 的 next 方法的调用已经返回了一个 promise,该 promise 对应的 IteratorResult 对象的 "done" 属性为 true,那么对该对象的所有后续 next 方法调用也应返回一个 promise,该 promise 对应的 IteratorResult 对象的 "done" 属性为 true。不过,此要求不会被强制执行。

此外,用作兑现值的 IteratorResult 对象应具有一个 "value" 属性,其值不是 promise(或“thenable”)。不过,此要求同样不会被强制执行。

注 1

可以向 next 函数传递参数,但这些参数的解释和有效性取决于目标 async iterator。for-await-of 语句和 async iterator 的其他常见使用者不会传递任何参数,因此预期以这种方式使用的 async iterator 对象必须能够处理无参数调用。

表 84: Async Iterator 接口可选属性
属性 值 要求
"return" a function that returns a promise for an IteratorResult object

返回的 promise 在兑现时,必须以符合 IteratorResult 接口的对象作为兑现值。调用此方法会通知 async iterator 对象,调用者不打算再对该 async iterator 进行任何 next 方法调用。返回的 promise 会以 IteratorResult 对象兑现,该对象通常具有值为 true 的 "done" 属性,以及一个 "value" 属性,其值为作为 return 方法参数传入的值。不过,此要求不会被强制执行。

此外,用作兑现值的 IteratorResult 对象应具有一个 "value" 属性,其值不是 promise(或“thenable”)。如果参数值以典型方式使用,那么如果它是被拒绝的 promise,则应返回一个以相同原因被拒绝的 promise;如果它是已兑现的 promise,则其兑现值应被用作返回 promise 的 IteratorResult 对象兑现值的 "value" 属性。不过,这些要求同样不会被强制执行。

"throw" a function that returns a promise for an IteratorResult object

返回的 promise 在兑现时,必须以符合 IteratorResult 接口的对象作为兑现值。调用此方法会通知 async iterator 对象,调用者检测到了错误条件。参数可以用于标识错误条件,通常会是异常对象。典型响应是返回一个以作为参数传入的值作为拒绝原因的被拒绝 promise。

如果返回的 promise 被兑现,则作为兑现值的 IteratorResult 对象通常具有值为 true 的 "done" 属性。此外,它还应具有一个 "value" 属性,其值不是 promise(或“thenable”),但此要求不会被强制执行。

注 2

通常,这些方法的调用者在调用它们之前应检查它们是否存在。包括 for-await-of 和 yield* 在内的某些 ECMAScript 语言特性会在执行存在性检查后调用这些方法。

27.1.1.5 IteratorResult 接口

IteratorResult 接口包含 表 85 中列出的属性:

表 85: IteratorResult 接口属性
属性 值 要求
"done" a Boolean 这是 iterator 的 next 方法调用的结果状态。如果已经到达 iterator 的末尾,则 "done" 为 true。如果尚未到达末尾,则 "done" 为 false,并且存在可用值。如果不存在 "done" 属性(无论是自有属性还是继承属性),则认为其值为 false。
"value" an ECMAScript language value 如果 done 为 false,则这是当前迭代元素的值。如果 done 为 true,则这是 iterator 的返回值(如果它提供了返回值)。如果 iterator 没有返回值,则 "value" 为 undefined。在这种情况下,如果符合要求的对象没有继承显式的 "value" 属性,则可以不存在 "value" 属性。

27.1.2 Iterator Helper 对象

Iterator Helper 对象是表示对某个特定源 iterator 对象进行惰性转换的普通对象。Iterator Helper 对象没有具名构造函数。相反,Iterator Helper 对象通过调用 Iterator 实例对象的某些方法创建。

27.1.2.1 %IteratorHelperPrototype% 对象

%IteratorHelperPrototype% 对象:

27.1.2.1.1 %IteratorHelperPrototype%.next ( )

  1. 返回 ? GeneratorResume(this value, undefined, "Iterator Helper")。

27.1.2.1.2 %IteratorHelperPrototype%.return ( )

  1. 令 obj 为 this value。
  2. 执行 ? RequireInternalSlot(obj, [[UnderlyingIterators]])。
  3. 断言:obj 具有 [[GeneratorState]] 内部槽。
  4. 如果 obj.[[GeneratorState]] 是 suspended-start,则
    1. 将 obj.[[GeneratorState]] 设置为 completed。
    2. 注:一旦 generator 进入 completed 状态,它就永远不会离开该状态,并且其关联的执行上下文永远不会恢复。此时可以丢弃与 obj 关联的任何执行状态。
    3. 执行 ? IteratorCloseAll(obj.[[UnderlyingIterators]], NormalCompletion(unused))。
    4. 返回 CreateIteratorResultObject(undefined, true)。
  5. 令 completion 为 ReturnCompletion(undefined)。
  6. 返回 ? GeneratorResumeAbrupt(obj, completion, "Iterator Helper")。

27.1.2.1.3 %IteratorHelperPrototype% [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "Iterator Helper"。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

27.1.3 Iterator 对象

27.1.3.1 Iterator 构造函数

Iterator 构造函数:

  • 是 %Iterator%。
  • 是全局对象的 "Iterator" 属性的初始值。
  • 被设计为可被子类化。它可以用作类定义的 extends 子句的值。

27.1.3.1.1 Iterator ( )

调用时,此函数执行以下步骤:

  1. 如果 NewTarget 是 undefined 或活动函数对象,则抛出 TypeError 异常。
  2. 返回 ? OrdinaryCreateFromConstructor(NewTarget, "%Iterator.prototype%")。

27.1.3.2 Iterator 构造函数的属性

Iterator 构造函数:

27.1.3.2.1 Iterator.concat ( ...items )

  1. 令 iterables 为新的空 List。
  2. 对 items 的每个元素 item,执行
    1. 如果 item 不是 Object,则抛出 TypeError 异常。
    2. 令 method 为 ? GetMethod(item, %Symbol.iterator%)。
    3. 如果 method 是 undefined,则抛出 TypeError 异常。
    4. 将 Record { [[OpenMethod]]: method, [[Iterable]]: item } 追加到 iterables。
  3. 令 closure 为不带参数的新 Abstract Closure,它捕获 iterables,并在被调用时执行以下步骤:
    1. 对 iterables 的每个 Record iterable,执行
      1. 令 iterator 为 ? Call(iterable.[[OpenMethod]], iterable.[[Iterable]])。
      2. 如果 iterator 不是 Object,则抛出 TypeError 异常。
      3. 令 iteratorRecord 为 ? GetIteratorDirect(iterator)。
      4. 令 innerAlive 为 true。
      5. 当 innerAlive 是 true 时,重复执行,
        1. 令 innerValue 为 ? IteratorStepValue(iteratorRecord)。
        2. 如果 innerValue 是 done,则
          1. 将 innerAlive 设置为 false。
        3. 否则,
          1. 令 completion 为 Completion(Yield(innerValue))。
          2. 如果 completion 是突然完成,则
            1. 返回 ? IteratorClose(iteratorRecord, completion)。
    2. 返回 ReturnCompletion(undefined)。
  4. 令 gen 为 CreateIteratorFromClosure(closure, "Iterator Helper", %IteratorHelperPrototype%, « [[UnderlyingIterators]] »)。
  5. 将 gen.[[UnderlyingIterators]] 设置为新的空 List。
  6. 返回 gen。

27.1.3.2.2 Iterator.from ( obj )

  1. 令 iteratorRecord 为 ? GetIteratorFlattenable(obj, iterate-string-primitives)。
  2. 令 hasInstance 为 ? OrdinaryHasInstance(%Iterator%, iteratorRecord.[[Iterator]])。
  3. 如果 hasInstance 是 true,则
    1. 返回 iteratorRecord.[[Iterator]]。
  4. 令 wrapper 为 OrdinaryObjectCreate(%WrapForValidIteratorPrototype%, « [[Iterated]] »)。
  5. 将 wrapper.[[Iterated]] 设置为 iteratorRecord。
  6. 返回 wrapper。

27.1.3.2.2.1 %WrapForValidIteratorPrototype% 对象

%WrapForValidIteratorPrototype% 对象:

27.1.3.2.2.1.1 %WrapForValidIteratorPrototype%.next ( )

  1. 令 obj 为 this value。
  2. 执行 ? RequireInternalSlot(obj, [[Iterated]])。
  3. 令 iteratorRecord 为 obj.[[Iterated]]。
  4. 返回 ? Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]])。

27.1.3.2.2.1.2 %WrapForValidIteratorPrototype%.return ( )

  1. 令 obj 为 this value。
  2. 执行 ? RequireInternalSlot(obj, [[Iterated]])。
  3. 令 iterator 为 obj.[[Iterated]].[[Iterator]]。
  4. 断言:iterator 是 Object。
  5. 令 returnMethod 为 ? GetMethod(iterator, "return")。
  6. 如果 returnMethod 是 undefined,则
    1. 返回 CreateIteratorResultObject(undefined, true)。
  7. 返回 ? Call(returnMethod, iterator)。

27.1.3.2.3 Iterator.prototype

Iterator.prototype 的初始值是 Iterator 原型对象。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

27.1.3.2.4 Iterator.zip ( iterables [ , options ] )

调用时,此函数执行以下步骤:

  1. 如果 iterables 不是 Object,则抛出 TypeError 异常。
  2. 将 options 设置为 ? GetOptionsObject(options)。
  3. 令 mode 为 ? Get(options, "mode")。
  4. 如果 mode 是 undefined,则将 mode 设置为 "shortest"。
  5. 如果 mode 不是 "shortest"、"longest" 或 "strict" 之一,则抛出 TypeError 异常。
  6. 令 paddingOption 为 undefined。
  7. 如果 mode 是 "longest",则
    1. 将 paddingOption 设置为 ? Get(options, "padding")。
    2. 如果 paddingOption 不是 undefined 且 paddingOption 不是 Object,则抛出 TypeError 异常。
  8. 令 iters 为新的空 List。
  9. 令 padding 为新的空 List。
  10. 令 inputIter 为 ? GetIterator(iterables, sync)。
  11. 令 next 为 not-started。
  12. 当 next 不是 done 时,重复执行,
    1. 将 next 设置为 Completion(IteratorStepValue(inputIter))。
    2. IfAbruptCloseIterators(next, iters)。
    3. 如果 next 不是 done,则
      1. 令 iter 为 Completion(GetIteratorFlattenable(next, reject-primitives))。
      2. 令 needClosing 为 « inputIter » 和 iters 的列表连接。
      3. IfAbruptCloseIterators(iter, needClosing)。
      4. 将 iter 追加到 iters。
  13. 令 iterCount 为 iters 中的元素数量。
  14. 如果 mode 是 "longest",则
    1. 如果 paddingOption 是 undefined,则
      1. 重复 iterCount 次:
        1. 将 undefined 追加到 padding。
    2. 否则,
      1. 令 paddingIter 为 Completion(GetIterator(paddingOption, sync))。
      2. IfAbruptCloseIterators(paddingIter, iters)。
      3. 令 usingIterator 为 true。
      4. 重复 iterCount 次:
        1. 如果 usingIterator 是 true,则
          1. 将 next 设置为 Completion(IteratorStepValue(paddingIter))。
          2. IfAbruptCloseIterators(next, iters)。
          3. 如果 next 是 done,则
            1. 将 usingIterator 设置为 false。
          4. 否则,
            1. 将 next 追加到 padding。
        2. 如果 usingIterator 是 false,则将 undefined 追加到 padding。
      5. 如果 usingIterator 是 true,则
        1. 令 completion 为 Completion(IteratorClose(paddingIter, NormalCompletion(unused)))。
        2. IfAbruptCloseIterators(completion, iters)。
  15. 令 finishResults 为参数为 (results) 且不捕获任何内容的新 Abstract Closure,它在被调用时执行以下步骤:
    1. 返回 CreateArrayFromList(results)。
  16. 返回 IteratorZip(iters, mode, padding, finishResults)。

27.1.3.2.5 Iterator.zipKeyed ( iterables [ , options ] )

调用时,此函数执行以下步骤:

  1. 如果 iterables 不是 Object,则抛出 TypeError 异常。
  2. 将 options 设置为 ? GetOptionsObject(options)。
  3. 令 mode 为 ? Get(options, "mode")。
  4. 如果 mode 是 undefined,则将 mode 设置为 "shortest"。
  5. 如果 mode 不是 "shortest"、"longest" 或 "strict" 之一,则抛出 TypeError 异常。
  6. 令 paddingOption 为 undefined。
  7. 如果 mode 是 "longest",则
    1. 将 paddingOption 设置为 ? Get(options, "padding")。
    2. 如果 paddingOption 不是 undefined 且 paddingOption 不是 Object,则抛出 TypeError 异常。
  8. 令 iters 为新的空 List。
  9. 令 padding 为新的空 List。
  10. 令 allKeys 为 ? iterables.[[OwnPropertyKeys]]()。
  11. 令 keys 为新的空 List。
  12. 对 allKeys 的每个元素 key,执行
    1. 令 propertyDesc 为 Completion(iterables.[[GetOwnProperty]](key))。
    2. IfAbruptCloseIterators(propertyDesc, iters)。
    3. 如果 propertyDesc 不是 undefined 且 propertyDesc.[[Enumerable]] 是 true,则
      1. 令 value 为 Completion(Get(iterables, key))。
      2. IfAbruptCloseIterators(value, iters)。
      3. 如果 value 不是 undefined,则
        1. 将 key 追加到 keys。
        2. 令 iter 为 Completion(GetIteratorFlattenable(value, reject-primitives))。
        3. IfAbruptCloseIterators(iter, iters)。
        4. 将 iter 追加到 iters。
  13. 令 iterCount 为 iters 中的元素数量。
  14. 如果 mode 是 "longest",则
    1. 如果 paddingOption 是 undefined,则
      1. 重复 iterCount 次:
        1. 将 undefined 追加到 padding。
    2. 否则,
      1. 对 keys 的每个元素 key,执行
        1. 令 value 为 Completion(Get(paddingOption, key))。
        2. IfAbruptCloseIterators(value, iters)。
        3. 将 value 追加到 padding。
  15. 令 finishResults 为参数为 (results) 的新 Abstract Closure,它捕获 keys 和 iterCount,并在被调用时执行以下步骤:
    1. 令 obj 为 OrdinaryObjectCreate(null)。
    2. 对满足 0 ≤ i < iterCount 的每个整数 i,按升序执行
      1. 执行 ! CreateDataPropertyOrThrow(obj, keys[i], results[i])。
    3. 返回 obj。
  16. 返回 IteratorZip(iters, mode, padding, finishResults)。

27.1.3.3 Iterator 原型对象的属性

Iterator 原型对象:

注

本规范中定义的所有实现 iterator 接口的对象也都继承自 %Iterator.prototype%。ECMAScript 代码也可以定义继承自 %Iterator.prototype% 的对象。%Iterator.prototype% 提供了一个可以添加适用于所有 iterator 对象的其他方法的位置。

以下表达式是 ECMAScript 代码访问 %Iterator.prototype% 对象的一种方式:

Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()))

27.1.3.3.1 Iterator.prototype.constructor

Iterator.prototype.constructor 是访问器属性,具有特性 { [[Enumerable]]: false, [[Configurable]]: true }。[[Getter]] 和 [[Setter]] 特性定义如下:

27.1.3.3.1.1 get Iterator.prototype.constructor

[[Getter]] 特性的值是一个无需参数的内置函数。调用时,它执行以下步骤:

  1. 返回 %Iterator%。

27.1.3.3.1.2 set Iterator.prototype.constructor

[[Setter]] 特性的值是一个接受参数 v 的内置函数。调用时,它执行以下步骤:

  1. 执行 ? SetterThatIgnoresPrototypeProperties(this value, %Iterator.prototype%, "constructor", v)。
  2. 返回 undefined。
注

与大多数内置原型上的 "constructor" 属性不同,出于 Web 兼容性原因,此属性必须是访问器。

27.1.3.3.2 Iterator.prototype.drop ( limit )

调用时,此方法执行以下步骤:

  1. 令 obj 为 this value。
  2. 如果 obj 不是 Object,则抛出 TypeError 异常。
  3. 令 iterated 为 Iterator Record { [[Iterator]]: obj, [[NextMethod]]: undefined, [[Done]]: false }。
  4. 令 numberLimit 为 Completion(ToNumber(limit))。
  5. IfAbruptCloseIterator(numberLimit, iterated)。
  6. 如果 numberLimit 是 NaN,则
    1. 令 error 为 ThrowCompletion(a newly created RangeError object)。
    2. 返回 ? IteratorClose(iterated, error)。
  7. 如果 numberLimit 是有限值且 numberLimit > 𝔽(253 - 1),则
    1. 令 error 为 ThrowCompletion(a newly created RangeError object)。
    2. 返回 ? IteratorClose(iterated, error)。
  8. 令 intLimit 为 ! ToIntegerOrInfinity(numberLimit)。
  9. 如果 intLimit < 0,则
    1. 令 error 为 ThrowCompletion(a newly created RangeError object)。
    2. 返回 ? IteratorClose(iterated, error)。
  10. 将 iterated 设置为 ? GetIteratorDirect(obj)。
  11. 令 closure 为不带参数的新 Abstract Closure,它捕获 iterated 和 intLimit,并在被调用时执行以下步骤:
    1. 令 remaining 为 𝔽(intLimit)。
    2. 当 remaining > +0𝔽 时,重复执行,
      1. 将 remaining 设置为 remaining - 1𝔽。
      2. 令 next 为 ? IteratorStep(iterated)。
      3. 如果 next 是 done,则返回 ReturnCompletion(undefined)。
    3. 重复执行,
      1. 令 value 为 ? IteratorStepValue(iterated)。
      2. 如果 value 是 done,则返回 ReturnCompletion(undefined)。
      3. 令 completion 为 Completion(Yield(value))。
      4. IfAbruptCloseIterator(completion, iterated)。
  12. 令 result 为 CreateIteratorFromClosure(closure, "Iterator Helper", %IteratorHelperPrototype%, « [[UnderlyingIterators]] »)。
  13. 将 result.[[UnderlyingIterators]] 设置为 « iterated »。
  14. 返回 result。

27.1.3.3.3 Iterator.prototype.every ( predicate )

调用时,此方法执行以下步骤:

  1. 令 obj 为 this value。
  2. 如果 obj 不是 Object,则抛出 TypeError 异常。
  3. 令 iterated 为 Iterator Record { [[Iterator]]: obj, [[NextMethod]]: undefined, [[Done]]: false }。
  4. 如果 IsCallable(predicate) 是 false,则
    1. 令 error 为 ThrowCompletion(a newly created TypeError object)。
    2. 返回 ? IteratorClose(iterated, error)。
  5. 将 iterated 设置为 ? GetIteratorDirect(obj)。
  6. 令 counter 为 +0𝔽。
  7. 重复执行,
    1. 令 value 为 ? IteratorStepValue(iterated)。
    2. 如果 value 是 done,则返回 true。
    3. 令 result 为 Completion(Call(predicate, undefined, « value, counter »))。
    4. IfAbruptCloseIterator(result, iterated)。
    5. 如果 ToBoolean(result) 是 false,则返回 ? IteratorClose(iterated, NormalCompletion(false))。
    6. 注:一旦 counter 达到 253𝔽,以下步骤将不再改变 counter。
    7. 将 counter 设置为 counter + 1𝔽。

27.1.3.3.4 Iterator.prototype.filter ( predicate )

调用时,此方法执行以下步骤:

  1. 令 obj 为 this value。
  2. 如果 obj 不是 Object,则抛出 TypeError 异常。
  3. 令 iterated 为 Iterator Record { [[Iterator]]: obj, [[NextMethod]]: undefined, [[Done]]: false }。
  4. 如果 IsCallable(predicate) 是 false,则
    1. 令 error 为 ThrowCompletion(a newly created TypeError object)。
    2. 返回 ? IteratorClose(iterated, error)。
  5. 将 iterated 设置为 ? GetIteratorDirect(obj)。
  6. 令 closure 为不带参数的新 Abstract Closure,它捕获 iterated 和 predicate,并在被调用时执行以下步骤:
    1. 令 counter 为 +0𝔽。
    2. 重复执行,
      1. 令 value 为 ? IteratorStepValue(iterated)。
      2. 如果 value 是 done,则返回 ReturnCompletion(undefined)。
      3. 令 selected 为 Completion(Call(predicate, undefined, « value, counter »))。
      4. IfAbruptCloseIterator(selected, iterated)。
      5. 如果 ToBoolean(selected) 是 true,则
        1. 令 completion 为 Completion(Yield(value))。
        2. IfAbruptCloseIterator(completion, iterated)。
      6. 注:一旦 counter 达到 253𝔽,以下步骤将不再改变 counter。
      7. 将 counter 设置为 counter + 1𝔽。
  7. 令 result 为 CreateIteratorFromClosure(closure, "Iterator Helper", %IteratorHelperPrototype%, « [[UnderlyingIterators]] »)。
  8. 将 result.[[UnderlyingIterators]] 设置为 « iterated »。
  9. 返回 result。

27.1.3.3.5 Iterator.prototype.find ( predicate )

调用时,此方法执行以下步骤:

  1. 令 obj 为 this value。
  2. 如果 obj 不是 Object,则抛出 TypeError 异常。
  3. 令 iterated 为 Iterator Record { [[Iterator]]: obj, [[NextMethod]]: undefined, [[Done]]: false }。
  4. 如果 IsCallable(predicate) 是 false,则
    1. 令 error 为 ThrowCompletion(a newly created TypeError object)。
    2. 返回 ? IteratorClose(iterated, error)。
  5. 将 iterated 设置为 ? GetIteratorDirect(obj)。
  6. 令 counter 为 +0𝔽。
  7. 重复执行,
    1. 令 value 为 ? IteratorStepValue(iterated)。
    2. 如果 value 是 done,则返回 undefined。
    3. 令 result 为 Completion(Call(predicate, undefined, « value, counter »))。
    4. IfAbruptCloseIterator(result, iterated)。
    5. 如果 ToBoolean(result) 是 true,则返回 ? IteratorClose(iterated, NormalCompletion(value))。
    6. 注:一旦 counter 达到 253𝔽,以下步骤将不再改变 counter。
    7. 将 counter 设置为 counter + 1𝔽。

27.1.3.3.6 Iterator.prototype.flatMap ( mapper )

调用时,此方法执行以下步骤:

  1. 令 obj 为 this value。
  2. 如果 obj 不是 Object,则抛出 TypeError 异常。
  3. 令 iterated 为 Iterator Record { [[Iterator]]: obj, [[NextMethod]]: undefined, [[Done]]: false }。
  4. 如果 IsCallable(mapper) 是 false,则
    1. 令 error 为 ThrowCompletion(a newly created TypeError object)。
    2. 返回 ? IteratorClose(iterated, error)。
  5. 将 iterated 设置为 ? GetIteratorDirect(obj)。
  6. 令 closure 为不带参数的新 Abstract Closure,它捕获 iterated 和 mapper,并在被调用时执行以下步骤:
    1. 令 counter 为 +0𝔽。
    2. 重复执行,
      1. 令 value 为 ? IteratorStepValue(iterated)。
      2. 如果 value 是 done,则返回 ReturnCompletion(undefined)。
      3. 令 mapped 为 Completion(Call(mapper, undefined, « value, counter »))。
      4. IfAbruptCloseIterator(mapped, iterated)。
      5. 令 innerIterator 为 Completion(GetIteratorFlattenable(mapped, reject-primitives))。
      6. IfAbruptCloseIterator(innerIterator, iterated)。
      7. 令 innerAlive 为 true。
      8. 当 innerAlive 是 true 时,重复执行,
        1. 令 innerValue 为 Completion(IteratorStepValue(innerIterator))。
        2. IfAbruptCloseIterator(innerValue, iterated)。
        3. 如果 innerValue 是 done,则
          1. 将 innerAlive 设置为 false。
        4. 否则,
          1. 令 completion 为 Completion(Yield(innerValue))。
          2. 如果 completion 是突然完成,则
            1. 令 backupCompletion 为 Completion(IteratorClose(innerIterator, completion))。
            2. IfAbruptCloseIterator(backupCompletion, iterated)。
            3. 返回 ? IteratorClose(iterated, completion)。
      9. 注:一旦 counter 达到 253𝔽,以下步骤将不再改变 counter。
      10. 将 counter 设置为 counter + 1𝔽。
  7. 令 result 为 CreateIteratorFromClosure(closure, "Iterator Helper", %IteratorHelperPrototype%, « [[UnderlyingIterators]] »)。
  8. 将 result.[[UnderlyingIterators]] 设置为 « iterated »。
  9. 返回 result。

27.1.3.3.7 Iterator.prototype.forEach ( procedure )

调用时,此方法执行以下步骤:

  1. 令 obj 为 this value。
  2. 如果 obj 不是 Object,则抛出 TypeError 异常。
  3. 令 iterated 为 Iterator Record { [[Iterator]]: obj, [[NextMethod]]: undefined, [[Done]]: false }。
  4. 如果 IsCallable(procedure) 是 false,则
    1. 令 error 为 ThrowCompletion(a newly created TypeError object)。
    2. 返回 ? IteratorClose(iterated, error)。
  5. 将 iterated 设置为 ? GetIteratorDirect(obj)。
  6. 令 counter 为 +0𝔽。
  7. 重复执行,
    1. 令 value 为 ? IteratorStepValue(iterated)。
    2. 如果 value 是 done,则返回 undefined。
    3. 令 result 为 Completion(Call(procedure, undefined, « value, counter »))。
    4. IfAbruptCloseIterator(result, iterated)。
    5. 注:一旦 counter 达到 253𝔽,以下步骤将不再改变 counter。
    6. 将 counter 设置为 counter + 1𝔽。

27.1.3.3.8 Iterator.prototype.join ( separator )

此方法将迭代器的值转换为字符串,然后连接这些字符串,并在它们之间插入 separator。如果未提供分隔符,则使用单个逗号作为分隔符。

调用时,它执行以下步骤:

  1. 令 obj 为 this 值。
  2. 如果 obj 不是 Object,则抛出 TypeError 异常。
  3. 令 iterated 为迭代器记录 { [[Iterator]]: obj, [[NextMethod]]: undefined, [[Done]]: false }。
  4. 如果 separator 为 undefined,则
    1. 令 separatorString 为 ","。
  5. 否则,
    1. 令 separatorString 为 Completion(ToString(separator))。
    2. IfAbruptCloseIterator(separatorString, iterated)。
  6. 将 iterated 设置为 ? GetIteratorDirect(obj)。
  7. 令 result 为空字符串。
  8. 令 first 为 true。
  9. 重复,
    1. 令 value 为 ? IteratorStepValue(iterated)。
    2. 如果 value 为 done,返回 result。
    3. 如果 first 为 true,则
      1. 将 first 设置为 false。
    4. 否则,
      1. 将 result 设置为 result 和 separatorString 的字符串连接结果。
    5. 如果 value 既不是 undefined 也不是 null,则
      1. 令 valueString 为 Completion(ToString(value))。
      2. IfAbruptCloseIterator(valueString, iterated)。
      3. 将 result 设置为 result 和 valueString 的字符串连接结果。

27.1.3.3.9 Iterator.prototype.map ( mapper )

调用时,此方法执行以下步骤:

  1. 令 obj 为 this value。
  2. 如果 obj 不是 Object,则抛出 TypeError 异常。
  3. 令 iterated 为 Iterator Record { [[Iterator]]: obj, [[NextMethod]]: undefined, [[Done]]: false }。
  4. 如果 IsCallable(mapper) 是 false,则
    1. 令 error 为 ThrowCompletion(a newly created TypeError object)。
    2. 返回 ? IteratorClose(iterated, error)。
  5. 将 iterated 设置为 ? GetIteratorDirect(obj)。
  6. 令 closure 为不带参数的新 Abstract Closure,它捕获 iterated 和 mapper,并在被调用时执行以下步骤:
    1. 令 counter 为 +0𝔽。
    2. 重复执行,
      1. 令 value 为 ? IteratorStepValue(iterated)。
      2. 如果 value 是 done,则返回 ReturnCompletion(undefined)。
      3. 令 mapped 为 Completion(Call(mapper, undefined, « value, counter »))。
      4. IfAbruptCloseIterator(mapped, iterated)。
      5. 令 completion 为 Completion(Yield(mapped))。
      6. IfAbruptCloseIterator(completion, iterated)。
      7. 注:一旦 counter 达到 253𝔽,以下步骤将不再改变 counter。
      8. 将 counter 设置为 counter + 1𝔽。
  7. 令 result 为 CreateIteratorFromClosure(closure, "Iterator Helper", %IteratorHelperPrototype%, « [[UnderlyingIterators]] »)。
  8. 将 result.[[UnderlyingIterators]] 设置为 « iterated »。
  9. 返回 result。

27.1.3.3.10 Iterator.prototype.reduce ( reducer [ , initialValue ] )

调用时,此方法执行以下步骤:

  1. 令 obj 为 this value。
  2. 如果 obj 不是 Object,则抛出 TypeError 异常。
  3. 令 iterated 为 Iterator Record { [[Iterator]]: obj, [[NextMethod]]: undefined, [[Done]]: false }。
  4. 如果 IsCallable(reducer) 是 false,则
    1. 令 error 为 ThrowCompletion(a newly created TypeError object)。
    2. 返回 ? IteratorClose(iterated, error)。
  5. 将 iterated 设置为 ? GetIteratorDirect(obj)。
  6. 如果不存在 initialValue,则
    1. 令 accumulator 为 ? IteratorStepValue(iterated)。
    2. 如果 accumulator 是 done,则抛出 TypeError 异常。
    3. 令 counter 为 1𝔽。
  7. 否则,
    1. 令 accumulator 为 initialValue。
    2. 令 counter 为 +0𝔽。
  8. 重复执行,
    1. 令 value 为 ? IteratorStepValue(iterated)。
    2. 如果 value 是 done,则返回 accumulator。
    3. 令 result 为 Completion(Call(reducer, undefined, « accumulator, value, counter »))。
    4. IfAbruptCloseIterator(result, iterated)。
    5. 将 accumulator 设置为 result。
    6. 注:一旦 counter 达到 253𝔽,以下步骤将不再改变 counter。
    7. 将 counter 设置为 counter + 1𝔽。

27.1.3.3.11 Iterator.prototype.some ( predicate )

调用时,此方法执行以下步骤:

  1. 令 obj 为 this value。
  2. 如果 obj 不是 Object,则抛出 TypeError 异常。
  3. 令 iterated 为 Iterator Record { [[Iterator]]: obj, [[NextMethod]]: undefined, [[Done]]: false }。
  4. 如果 IsCallable(predicate) 是 false,则
    1. 令 error 为 ThrowCompletion(a newly created TypeError object)。
    2. 返回 ? IteratorClose(iterated, error)。
  5. 将 iterated 设置为 ? GetIteratorDirect(obj)。
  6. 令 counter 为 +0𝔽。
  7. 重复执行,
    1. 令 value 为 ? IteratorStepValue(iterated)。
    2. 如果 value 是 done,则返回 false。
    3. 令 result 为 Completion(Call(predicate, undefined, « value, counter »))。
    4. IfAbruptCloseIterator(result, iterated)。
    5. 如果 ToBoolean(result) 是 true,则返回 ? IteratorClose(iterated, NormalCompletion(true))。
    6. 注:一旦 counter 达到 253𝔽,以下步骤将不再改变 counter。
    7. 将 counter 设置为 counter + 1𝔽。

27.1.3.3.12 Iterator.prototype.take ( limit )

调用时,此方法执行以下步骤:

  1. 令 obj 为 this value。
  2. 如果 obj 不是 Object,则抛出 TypeError 异常。
  3. 令 iterated 为 Iterator Record { [[Iterator]]: obj, [[NextMethod]]: undefined, [[Done]]: false }。
  4. 令 numberLimit 为 Completion(ToNumber(limit))。
  5. IfAbruptCloseIterator(numberLimit, iterated)。
  6. 如果 numberLimit 是 NaN,则
    1. 令 error 为 ThrowCompletion(a newly created RangeError object)。
    2. 返回 ? IteratorClose(iterated, error)。
  7. 如果 numberLimit 是有限值且 numberLimit > 𝔽(253 - 1),则
    1. 令 error 为 ThrowCompletion(a newly created RangeError object)。
    2. 返回 ? IteratorClose(iterated, error)。
  8. 令 intLimit 为 ! ToIntegerOrInfinity(numberLimit)。
  9. 如果 intLimit < 0,则
    1. 令 error 为 ThrowCompletion(a newly created RangeError object)。
    2. 返回 ? IteratorClose(iterated, error)。
  10. 将 iterated 设置为 ? GetIteratorDirect(obj)。
  11. 令 closure 为不带参数的新 Abstract Closure,它捕获 iterated 和 intLimit,并在被调用时执行以下步骤:
    1. 令 remaining 为 𝔽(intLimit)。
    2. 重复执行,
      1. 如果 remaining 是 +0𝔽,则
        1. 返回 ? IteratorClose(iterated, ReturnCompletion(undefined))。
      2. 将 remaining 设置为 remaining - 1𝔽。
      3. 令 value 为 ? IteratorStepValue(iterated)。
      4. 如果 value 是 done,则返回 ReturnCompletion(undefined)。
      5. 令 completion 为 Completion(Yield(value))。
      6. IfAbruptCloseIterator(completion, iterated)。
  12. 令 result 为 CreateIteratorFromClosure(closure, "Iterator Helper", %IteratorHelperPrototype%, « [[UnderlyingIterators]] »)。
  13. 将 result.[[UnderlyingIterators]] 设置为 « iterated »。
  14. 返回 result。

27.1.3.3.13 Iterator.prototype.toArray ( )

调用时,此方法执行以下步骤:

  1. 令 obj 为 this value。
  2. 如果 obj 不是 Object,则抛出 TypeError 异常。
  3. 令 iterated 为 ? GetIteratorDirect(obj)。
  4. 令 items 为新的空 List。
  5. 重复执行,
    1. 令 value 为 ? IteratorStepValue(iterated)。
    2. 如果 value 是 done,则返回 CreateArrayFromList(items)。
    3. 将 value 追加到 items。

27.1.3.3.14 Iterator.prototype [ %Symbol.dispose% ] ( )

调用时,此方法执行以下步骤:

  1. 令 obj 为 this value。
  2. 令 return 为 ? GetMethod(obj, "return")。
  3. 如果 return 不是 undefined,则
    1. 执行 ? Call(return, obj)。
  4. 返回 undefined。

此方法的 "name" 属性的值是 "[Symbol.dispose]"。

27.1.3.3.15 Iterator.prototype [ %Symbol.iterator% ] ( )

调用时,此函数执行以下步骤:

  1. 返回 this value。

此函数的 "name" 属性的值是 "[Symbol.iterator]"。

27.1.3.3.16 Iterator.prototype [ %Symbol.toStringTag% ]

Iterator.prototype[%Symbol.toStringTag%] 是访问器属性,具有特性 { [[Enumerable]]: false, [[Configurable]]: true }。[[Getter]] 和 [[Setter]] 特性定义如下:

27.1.3.3.16.1 get Iterator.prototype [ %Symbol.toStringTag% ]

[[Getter]] 特性的值是一个无需参数的内置函数。调用时,它执行以下步骤:

  1. 返回 "Iterator"。

27.1.3.3.16.2 set Iterator.prototype [ %Symbol.toStringTag% ]

[[Setter]] 特性的值是一个接受参数 v 的内置函数。调用时,它执行以下步骤:

  1. 执行 ? SetterThatIgnoresPrototypeProperties(this value, %Iterator.prototype%, %Symbol.toStringTag%, v)。
  2. 返回 undefined。
注

与大多数内置原型上的 %Symbol.toStringTag% 属性不同,出于 Web 兼容性原因,此属性必须是访问器。

27.1.3.4 Iterator 的抽象操作

27.1.3.4.1 IteratorZip ( iters, mode, padding, finishResults )

抽象操作 IteratorZip,接收参数 iters (列表 (元素:Iterator 记录))、mode (("shortest"、"longest" 或 "strict"))、padding (列表 (元素:ECMAScript 语言值)) 和 finishResults (an Abstract Closure that takes a List of ECMAScript language values and returns an ECMAScript language value);返回值:Generator。 调用时执行以下步骤:

  1. 令 iterCount 为 iters 中的元素数量。
  2. 令 openIters 为 iters 的副本。
  3. 令 closure 为不带参数的新 Abstract Closure,它捕获 iters、iterCount、openIters、mode、padding 和 finishResults,并在被调用时执行以下步骤:
    1. 如果 iterCount = 0,则返回 ReturnCompletion(undefined)。
    2. 重复执行,
      1. 令 results 为新的空 List。
      2. 断言:openIters 非空。
      3. 对满足 0 ≤ i < iterCount 的每个整数 i,按升序执行
        1. 令 iter 为 iters[i]。
        2. 如果 iter 是 null,则
          1. 断言:mode 是 "longest"。
          2. 令 result 为 padding[i]。
        3. 否则,
          1. 令 result 为 Completion(IteratorStepValue(iter))。
          2. 如果 result 是突然完成,则
            1. 从 openIters 中移除 iter。
            2. 返回 ? IteratorCloseAll(openIters, result)。
          3. 将 result 设置为 ! result。
          4. 如果 result 是 done,则
            1. 从 openIters 中移除 iter。
            2. 如果 mode 是 "shortest",则
              1. 返回 ? IteratorCloseAll(openIters, ReturnCompletion(undefined))。
            3. 否则如果 mode 是 "strict",则
              1. 如果 i ≠ 0,则
                1. 返回 ? IteratorCloseAll(openIters, ThrowCompletion(a newly created TypeError object))。
              2. 对满足 1 ≤ k < iterCount 的每个整数 k,按升序执行
                1. 断言:iters[k] 不是 null。
                2. 令 open 为 Completion(IteratorStep(iters[k]))。
                3. 如果 open 是突然完成,则
                  1. 从 openIters 中移除 iters[k]。
                  2. 返回 ? IteratorCloseAll(openIters, open)。
                4. 将 open 设置为 ! open。
                5. 如果 open 是 done,则
                  1. 从 openIters 中移除 iters[k]。
                6. 否则,
                  1. 返回 ? IteratorCloseAll(openIters, ThrowCompletion(a newly created TypeError object))。
              3. 返回 ReturnCompletion(undefined)。
            4. 否则,
              1. 断言:mode 是 "longest"。
              2. 如果 openIters 为空,则返回 ReturnCompletion(undefined)。
              3. 将 iters[i] 设置为 null。
              4. 将 result 设置为 padding[i]。
        4. 将 result 追加到 results。
      4. 将 results 设置为 finishResults(results)。
      5. 令 completion 为 Completion(Yield(results))。
      6. IfAbruptCloseIterators(completion, openIters)。
  4. 令 gen 为 CreateIteratorFromClosure(closure, "Iterator Helper", %IteratorHelperPrototype%, « [[UnderlyingIterators]] »)。
  5. 将 gen.[[UnderlyingIterators]] 设置为 openIters。
  6. 返回 gen。

27.1.4 %AsyncIteratorPrototype% 对象

%AsyncIteratorPrototype% 对象:

注

本规范中定义的所有实现 async iterator 接口的对象也都继承自 %AsyncIteratorPrototype%。ECMAScript 代码也可以定义继承自 %AsyncIteratorPrototype% 的对象。%AsyncIteratorPrototype% 对象提供了一个可以添加适用于所有 async iterator 对象的其他方法的位置。

27.1.4.1 %AsyncIteratorPrototype% [ %Symbol.asyncDispose% ] ( )

调用时,此方法执行以下步骤:

  1. 令 obj 为 this value。
  2. 令 promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  3. 令 return 为 Completion(GetMethod(obj, "return"))。
  4. IfAbruptRejectPromise(return, promiseCapability)。
  5. 如果 return 是 undefined,则
    1. 执行 ! Call(promiseCapability.[[Resolve]], undefined, « undefined »)。
  6. 否则,
    1. 令 result 为 Completion(Call(return, obj, « »))。
    2. IfAbruptRejectPromise(result, promiseCapability)。
    3. 令 resultWrapper 为 Completion(PromiseResolve(%Promise%, result))。
    4. IfAbruptRejectPromise(resultWrapper, promiseCapability)。
    5. 令 unwrap 为不带参数且不捕获任何内容的新 Abstract Closure,它在被调用时执行以下步骤:
      1. 返回 undefined。
    6. 令 onFulfilled 为 CreateBuiltinFunction(unwrap, 1, "", « »)。
    7. 执行 PerformPromiseThen(resultWrapper, onFulfilled, undefined, promiseCapability)。
  7. 返回 promiseCapability.[[Promise]]。

此方法的 "name" 属性的值是 "[Symbol.asyncDispose]"。

27.1.4.2 %AsyncIteratorPrototype% [ %Symbol.asyncIterator% ] ( )

调用时,此函数执行以下步骤:

  1. 返回 this value。

此函数的 "name" 属性的值是 "[Symbol.asyncIterator]"。

27.1.5 Async-from-Sync Iterator 对象

Async-from-Sync Iterator 对象是适配某个特定同步 iterator 的 async iterator。ECMAScript 代码永远无法直接访问 Async-from-Sync Iterator 对象。Async-from-Sync Iterator 对象没有具名构造函数。相反,Async-from-Sync Iterator 对象会根据需要由 CreateAsyncFromSyncIterator 抽象操作创建。

27.1.5.1 CreateAsyncFromSyncIterator ( syncIteratorRecord )

抽象操作 CreateAsyncFromSyncIterator,接收参数 syncIteratorRecord (Iterator 记录);返回值:Iterator 记录。 它用于从同步 Iterator Record 创建 async Iterator Record。 调用时执行以下步骤:

  1. 令 asyncIterator 为 OrdinaryObjectCreate(%AsyncFromSyncIteratorPrototype%, « [[SyncIteratorRecord]] »)。
  2. 将 asyncIterator.[[SyncIteratorRecord]] 设置为 syncIteratorRecord。
  3. 令 nextMethod 为 ! Get(asyncIterator, "next")。
  4. 令 iteratorRecord 为 Iterator Record { [[Iterator]]: asyncIterator, [[NextMethod]]: nextMethod, [[Done]]: false }。
  5. 返回 iteratorRecord。

27.1.5.2 %AsyncFromSyncIteratorPrototype% 对象

%AsyncFromSyncIteratorPrototype% 对象:

27.1.5.2.1 %AsyncFromSyncIteratorPrototype%.next ( [ value ] )

  1. 令 obj 为 this value。
  2. 断言:obj 是具有 [[SyncIteratorRecord]] 内部槽的 Object。
  3. 令 promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  4. 令 syncIteratorRecord 为 obj.[[SyncIteratorRecord]]。
  5. 如果存在 value,则
    1. 令 result 为 Completion(IteratorNext(syncIteratorRecord, value))。
  6. 否则,
    1. 令 result 为 Completion(IteratorNext(syncIteratorRecord))。
  7. IfAbruptRejectPromise(result, promiseCapability)。
  8. 返回 AsyncFromSyncIteratorContinuation(result, promiseCapability, syncIteratorRecord, true)。

27.1.5.2.2 %AsyncFromSyncIteratorPrototype%.return ( [ value ] )

  1. 令 obj 为 this value。
  2. 断言:obj 是具有 [[SyncIteratorRecord]] 内部槽的 Object。
  3. 令 promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  4. 令 syncIteratorRecord 为 obj.[[SyncIteratorRecord]]。
  5. 令 syncIterator 为 syncIteratorRecord.[[Iterator]]。
  6. 令 return 为 Completion(GetMethod(syncIterator, "return"))。
  7. IfAbruptRejectPromise(return, promiseCapability)。
  8. 如果 return 是 undefined,则
    1. 令 iteratorResult 为 CreateIteratorResultObject(value, true)。
    2. 执行 ! Call(promiseCapability.[[Resolve]], undefined, « iteratorResult »)。
    3. 返回 promiseCapability.[[Promise]]。
  9. 如果存在 value,则
    1. 令 result 为 Completion(Call(return, syncIterator, « value »))。
  10. 否则,
    1. 令 result 为 Completion(Call(return, syncIterator))。
  11. IfAbruptRejectPromise(result, promiseCapability)。
  12. 如果 result 不是 Object,则
    1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « a newly created TypeError object »)。
    2. 返回 promiseCapability.[[Promise]]。
  13. 返回 AsyncFromSyncIteratorContinuation(result, promiseCapability, syncIteratorRecord, false)。

27.1.5.2.3 %AsyncFromSyncIteratorPrototype%.throw ( [ value ] )

注
在本规范中,始终会提供 value,但为与 %AsyncFromSyncIteratorPrototype%.return ( [ value ] ) 保持一致,它仍被设为可选。
  1. 令 obj 为 this value。
  2. 断言:obj 是具有 [[SyncIteratorRecord]] 内部槽的 Object。
  3. 令 promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  4. 令 syncIteratorRecord 为 obj.[[SyncIteratorRecord]]。
  5. 令 syncIterator 为 syncIteratorRecord.[[Iterator]]。
  6. 令 throw 为 Completion(GetMethod(syncIterator, "throw"))。
  7. IfAbruptRejectPromise(throw, promiseCapability)。
  8. 如果 throw 是 undefined,则
    1. 注:如果 syncIterator 没有 throw 方法,则关闭它,让它有机会在我们拒绝 capability 之前进行清理。
    2. 令 closeCompletion 为 NormalCompletion(empty)。
    3. 令 result 为 Completion(IteratorClose(syncIteratorRecord, closeCompletion))。
    4. IfAbruptRejectPromise(result, promiseCapability)。
    5. 注:下一步骤抛出 TypeError,以表明发生了协议违规:syncIterator 没有 throw 方法。
    6. 注:如果关闭 syncIterator 没有抛出异常,则忽略该操作的结果,即使它产生一个被拒绝的 promise。
    7. 执行 ! Call(promiseCapability.[[Reject]], undefined, « a newly created TypeError object »)。
    8. 返回 promiseCapability.[[Promise]]。
  9. 如果存在 value,则
    1. 令 result 为 Completion(Call(throw, syncIterator, « value »))。
  10. 否则,
    1. 令 result 为 Completion(Call(throw, syncIterator))。
  11. IfAbruptRejectPromise(result, promiseCapability)。
  12. 如果 result 不是 Object,则
    1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « a newly created TypeError object »)。
    2. 返回 promiseCapability.[[Promise]]。
  13. 返回 AsyncFromSyncIteratorContinuation(result, promiseCapability, syncIteratorRecord, true)。

27.1.5.3 Async-from-Sync Iterator 实例的属性

Async-from-Sync Iterator 实例是从 %AsyncFromSyncIteratorPrototype% 固有对象继承属性的普通对象。Async-from-Sync Iterator 实例最初创建时具有 表 86 中列出的内部槽。

表 86: Async-from-Sync Iterator 实例的内部槽
内部槽 类型 描述
[[SyncIteratorRecord]] an Iterator Record 表示正在被适配的原始同步 iterator。

27.1.5.4 AsyncFromSyncIteratorContinuation ( result, promiseCapability, syncIteratorRecord, closeOnRejection )

抽象操作 AsyncFromSyncIteratorContinuation,接收参数 result (Object)、promiseCapability (a PromiseCapability Record for an intrinsic %Promise%)、syncIteratorRecord (Iterator 记录) 和 closeOnRejection (Boolean);返回值:Promise。 调用时执行以下步骤:

  1. 注:由于 promiseCapability 派生自固有的 %Promise%,因此由下文使用 IfAbruptRejectPromise 所导致的对 promiseCapability.[[Reject]] 的调用保证不会抛出异常。
  2. 令 done 为 Completion(IteratorComplete(result))。
  3. IfAbruptRejectPromise(done, promiseCapability)。
  4. 令 value 为 Completion(IteratorValue(result))。
  5. IfAbruptRejectPromise(value, promiseCapability)。
  6. 令 valueWrapper 为 Completion(PromiseResolve(%Promise%, value))。
  7. 如果 valueWrapper 是突然完成、done 是 false 且 closeOnRejection 是 true,则
    1. 将 valueWrapper 设置为 Completion(IteratorClose(syncIteratorRecord, valueWrapper))。
  8. IfAbruptRejectPromise(valueWrapper, promiseCapability)。
  9. 令 unwrap 为参数为 (value) 的新 Abstract Closure,它捕获 done,并在被调用时执行以下步骤:
    1. 返回 CreateIteratorResultObject(value, done)。
  10. 令 onFulfilled 为 CreateBuiltinFunction(unwrap, 1, "", « »)。
  11. 注:onFulfilled 用于处理 IteratorResult 对象的 "value" 属性,以便在其值是 promise 时等待该值,并将结果重新封装到新的“已解包”IteratorResult 对象中。
  12. 如果 done 是 true 或 closeOnRejection 是 false,则
    1. 令 onRejected 为 undefined。
  13. 否则,
    1. 令 closeIterator 为参数为 (error) 的新 Abstract Closure,它捕获 syncIteratorRecord,并在被调用时执行以下步骤:
      1. 返回 ? IteratorClose(syncIteratorRecord, ThrowCompletion(error))。
    2. 令 onRejected 为 CreateBuiltinFunction(closeIterator, 1, "", « »)。
    3. 注:当其生成的 IteratorResult 对象的 "value" 属性是被拒绝的 promise 时,onRejected 用于关闭 Iterator。
  14. 执行 PerformPromiseThen(valueWrapper, onFulfilled, onRejected, promiseCapability)。
  15. 返回 promiseCapability.[[Promise]]。

27.2 资源管理

27.2.1 通用资源管理接口

27.2.1.1 Disposable 接口

Disposable 接口包含 表 87 中描述的属性:

表 87: Disposable 接口必需属性
属性 值 要求
%Symbol.dispose% a function object

调用此方法会通知 Disposable 对象,调用者不打算继续使用该对象。此方法应执行显式清理资源所需的任何逻辑,包括但不限于文件系统句柄、流、宿主对象等。当此方法抛出异常时,通常意味着无法显式释放资源。

对同一对象多次调用此方法时,应避免对已经处置的资源重复执行清理逻辑,并且即使第一次调用时抛出了异常,也不应抛出异常。不过,此要求不会被强制执行。

将 Disposable 对象与 using 或 await using 声明一起使用时,在直接包含该声明的 Block 或 Module 求值完成时,资源将被自动处置。

27.2.1.2 AsyncDisposable 接口

AsyncDisposable 接口包含 表 88 中描述的属性:

表 88: AsyncDisposable 接口必需属性
属性 值 要求
%Symbol.asyncDispose% a function object that returns a promise

调用此方法会通知 AsyncDisposable 对象,调用者不打算继续使用该对象。此方法应执行显式清理资源所需的任何逻辑,包括但不限于文件系统句柄、流、宿主对象等。当此方法返回的 promise 被拒绝时,通常意味着无法显式释放资源。在结果 Promise 被兑现之前,AsyncDisposable 对象不被视为“已处置”。

对同一对象多次调用此方法时,应避免对已经处置的资源重复执行清理逻辑,并且即使第一次调用时抛出了异常或返回了被拒绝的 promise,也不应抛出异常或返回被拒绝的 promise。不过,此要求不会被强制执行。

将 AsyncDisposable 对象与 await using 声明一起使用时,在直接包含该声明的 Block 或 Module 求值完成时,资源将被自动处置。

27.3 DisposableStack 对象

DisposableStack 是一种可以用于包含一个或多个应当一起处置的资源的对象。

任何 DisposableStack 对象都处于两个互斥状态之一:已处置或待处理。当且仅当既未对 d 调用 d.dispose() 也未调用 d.move() 时,可处置栈 d 才处于待处理状态。

27.3.1 DisposableStack 构造函数

DisposableStack 构造函数:

  • 是 %DisposableStack%。
  • 是全局对象的 "DisposableStack" 属性的初始值。
  • 作为构造函数调用时,创建并初始化新的 DisposableStack。
  • 不旨在作为函数调用,并且以这种方式调用时会抛出异常。
  • 可以用作类定义的 extends 子句中的值。希望继承指定 DisposableStack 行为的子类构造函数必须包含对 DisposableStack 构造函数的 super 调用,以创建并初始化具有支持 DisposableStack.prototype 内置方法所必需内部状态的子类实例。

27.3.1.1 DisposableStack ( )

调用时,此函数执行以下步骤:

  1. 如果 NewTarget 是 undefined,则抛出 TypeError 异常。
  2. 令 disposableStack 为 ? OrdinaryCreateFromConstructor(NewTarget, "%DisposableStack.prototype%", « [[DisposableState]], [[DisposableResourceStack]] »)。
  3. 将 disposableStack.[[DisposableState]] 设置为 pending。
  4. 将 disposableStack.[[DisposableResourceStack]] 设置为新的空 List。
  5. 返回 disposableStack。

27.3.2 DisposableStack 构造函数的属性

DisposableStack 构造函数:

27.3.2.1 DisposableStack.prototype

DisposableStack.prototype 的初始值是 DisposableStack 原型对象。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

27.3.3 DisposableStack 原型对象的属性

DisposableStack 原型对象:

  • 是 %DisposableStack.prototype%。
  • 具有 [[Prototype]] 内部槽,其值是 %Object.prototype%。
  • 是普通对象。
  • 不具有 [[DisposableState]] 内部槽,也不具有 DisposableStack 实例的任何其他内部槽。

27.3.3.1 DisposableStack.prototype.adopt ( value, onDispose )

调用时,此方法执行以下步骤:

  1. 令 disposableStack 为 this value。
  2. 执行 ? RequireInternalSlot(disposableStack, [[DisposableState]])。
  3. 如果 disposableStack.[[DisposableState]] 是 disposed,则抛出 ReferenceError 异常。
  4. 如果 IsCallable(onDispose) 是 false,则抛出 TypeError 异常。
  5. 令 closure 为不带参数的新 Abstract Closure,它捕获 value 和 onDispose,并在被调用时执行以下步骤:
    1. 返回 ? Call(onDispose, undefined, « value »)。
  6. 令 func 为 CreateBuiltinFunction(closure, 0, "", « »)。
  7. 执行 ? AddDisposableResource(disposableStack.[[DisposableResourceStack]], undefined, sync-dispose, func)。
  8. 返回 value。

27.3.3.2 DisposableStack.prototype.constructor

DisposableStack.prototype.constructor 的初始值是 %DisposableStack%。

27.3.3.3 DisposableStack.prototype.defer ( onDispose )

调用时,此方法执行以下步骤:

  1. 令 disposableStack 为 this value。
  2. 执行 ? RequireInternalSlot(disposableStack, [[DisposableState]])。
  3. 如果 disposableStack.[[DisposableState]] 是 disposed,则抛出 ReferenceError 异常。
  4. 如果 IsCallable(onDispose) 是 false,则抛出 TypeError 异常。
  5. 执行 ? AddDisposableResource(disposableStack.[[DisposableResourceStack]], undefined, sync-dispose, onDispose)。
  6. 返回 undefined。

27.3.3.4 DisposableStack.prototype.dispose ( )

调用时,此方法执行以下步骤:

  1. 令 disposableStack 为 this value。
  2. 执行 ? RequireInternalSlot(disposableStack, [[DisposableState]])。
  3. 如果 disposableStack.[[DisposableState]] 是 disposed,则返回 undefined。
  4. 将 disposableStack.[[DisposableState]] 设置为 disposed。
  5. 返回 ? DisposeResources(disposableStack.[[DisposableResourceStack]], NormalCompletion(undefined))。

27.3.3.5 get DisposableStack.prototype.disposed

DisposableStack.prototype.disposed 是访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数在调用时执行以下步骤:

  1. 令 disposableStack 为 this value。
  2. 执行 ? RequireInternalSlot(disposableStack, [[DisposableState]])。
  3. 如果 disposableStack.[[DisposableState]] 是 disposed,则返回 true。
  4. 返回 false。

27.3.3.6 DisposableStack.prototype.move ( )

调用时,此方法执行以下步骤:

  1. 令 disposableStack 为 this value。
  2. 执行 ? RequireInternalSlot(disposableStack, [[DisposableState]])。
  3. 如果 disposableStack.[[DisposableState]] 是 disposed,则抛出 ReferenceError 异常。
  4. 令 newDisposableStack 为 ? OrdinaryCreateFromConstructor(%DisposableStack%, "%DisposableStack.prototype%", « [[DisposableState]], [[DisposableResourceStack]] »)。
  5. 将 newDisposableStack.[[DisposableState]] 设置为 pending。
  6. 将 newDisposableStack.[[DisposableResourceStack]] 设置为 disposableStack.[[DisposableResourceStack]]。
  7. 将 disposableStack.[[DisposableResourceStack]] 设置为新的空 List。
  8. 将 disposableStack.[[DisposableState]] 设置为 disposed。
  9. 返回 newDisposableStack。

27.3.3.7 DisposableStack.prototype.use ( value )

调用时,此方法执行以下步骤:

  1. 令 disposableStack 为 this value。
  2. 执行 ? RequireInternalSlot(disposableStack, [[DisposableState]])。
  3. 如果 disposableStack.[[DisposableState]] 是 disposed,则抛出 ReferenceError 异常。
  4. 执行 ? AddDisposableResource(disposableStack.[[DisposableResourceStack]], value, sync-dispose)。
  5. 返回 value。

27.3.3.8 DisposableStack.prototype [ %Symbol.dispose% ] ( )

%Symbol.dispose% 属性的初始值是 27.3.3.4 中定义的 %DisposableStack.prototype.dispose%。

27.3.3.9 DisposableStack.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "DisposableStack"。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

27.3.4 DisposableStack 实例的属性

DisposableStack 实例是从 DisposableStack 原型对象(固有对象 %DisposableStack.prototype%)继承属性的普通对象。DisposableStack 实例最初创建时具有 表 89 中描述的内部槽。

表 89: DisposableStack 实例的内部槽
内部槽 类型 描述
[[DisposableState]] pending or disposed 控制可处置栈如何响应对其 %Symbol.dispose% 方法的调用。
[[DisposableResourceStack]] a List of DisposableResource Records 可处置栈被处置时要处置的资源。资源按照初始化顺序添加,并按照相反顺序处置。

27.4 AsyncDisposableStack 对象

AsyncDisposableStack 是一种可以用于包含一个或多个应当一起异步处置的资源的对象。

任何 AsyncDisposableStack 对象都处于两个互斥状态之一:已处置或待处理。当且仅当既未对 d 调用 d.disposeAsync() 也未调用 d.move() 时,异步可处置栈 d 才处于待处理状态。

27.4.1 AsyncDisposableStack 构造函数

AsyncDisposableStack 构造函数:

  • 是 %AsyncDisposableStack%。
  • 是全局对象的 "AsyncDisposableStack" 属性的初始值。
  • 作为构造函数调用时,创建并初始化新的 AsyncDisposableStack。
  • 不旨在作为函数调用,并且以这种方式调用时会抛出异常。
  • 可以用作类定义的 extends 子句中的值。希望继承指定 AsyncDisposableStack 行为的子类构造函数必须包含对 AsyncDisposableStack 构造函数的 super 调用,以创建并初始化具有支持 AsyncDisposableStack.prototype 内置方法所必需内部状态的子类实例。

27.4.1.1 AsyncDisposableStack ( )

调用时,此函数执行以下步骤:

  1. 如果 NewTarget 是 undefined,则抛出 TypeError 异常。
  2. 令 asyncDisposableStack 为 ? OrdinaryCreateFromConstructor(NewTarget, "%AsyncDisposableStack.prototype%", « [[AsyncDisposableState]], [[DisposableResourceStack]] »)。
  3. 将 asyncDisposableStack.[[AsyncDisposableState]] 设置为 pending。
  4. 将 asyncDisposableStack.[[DisposableResourceStack]] 设置为新的空 List。
  5. 返回 asyncDisposableStack。

27.4.2 AsyncDisposableStack 构造函数的属性

AsyncDisposableStack 构造函数:

27.4.2.1 AsyncDisposableStack.prototype

AsyncDisposableStack.prototype 的初始值是 AsyncDisposableStack 原型对象。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

27.4.3 AsyncDisposableStack 原型对象的属性

AsyncDisposableStack 原型对象:

  • 是 %AsyncDisposableStack.prototype%。
  • 具有 [[Prototype]] 内部槽,其值是 %Object.prototype%。
  • 是普通对象。
  • 不具有 [[AsyncDisposableState]] 内部槽,也不具有 AsyncDisposableStack 实例的任何其他内部槽。

27.4.3.1 AsyncDisposableStack.prototype.adopt ( value, onDisposeAsync )

调用时,此方法执行以下步骤:

  1. 令 asyncDisposableStack 为 this value。
  2. 执行 ? RequireInternalSlot(asyncDisposableStack, [[AsyncDisposableState]])。
  3. 如果 asyncDisposableStack.[[AsyncDisposableState]] 是 disposed,则抛出 ReferenceError 异常。
  4. 如果 IsCallable(onDisposeAsync) 是 false,则抛出 TypeError 异常。
  5. 令 closure 为不带参数的新 Abstract Closure,它捕获 value 和 onDisposeAsync,并在被调用时执行以下步骤:
    1. 返回 ? Call(onDisposeAsync, undefined, « value »)。
  6. 令 func 为 CreateBuiltinFunction(closure, 0, "", « »)。
  7. 执行 ? AddDisposableResource(asyncDisposableStack.[[DisposableResourceStack]], undefined, async-dispose, func)。
  8. 返回 value。

27.4.3.2 AsyncDisposableStack.prototype.constructor

AsyncDisposableStack.prototype.constructor 的初始值是 %AsyncDisposableStack%。

27.4.3.3 AsyncDisposableStack.prototype.defer ( onDisposeAsync )

调用时,此方法执行以下步骤:

  1. 令 asyncDisposableStack 为 this value。
  2. 执行 ? RequireInternalSlot(asyncDisposableStack, [[AsyncDisposableState]])。
  3. 如果 asyncDisposableStack.[[AsyncDisposableState]] 是 disposed,则抛出 ReferenceError 异常。
  4. 如果 IsCallable(onDisposeAsync) 是 false,则抛出 TypeError 异常。
  5. 执行 ? AddDisposableResource(asyncDisposableStack.[[DisposableResourceStack]], undefined, async-dispose, onDisposeAsync)。
  6. 返回 undefined。

27.4.3.4 AsyncDisposableStack.prototype.disposeAsync ( )

调用时,此异步方法执行以下步骤:

  1. 令 asyncDisposableStack 为 this value。
  2. 执行 ? RequireInternalSlot(asyncDisposableStack, [[AsyncDisposableState]])。
  3. 如果 asyncDisposableStack.[[AsyncDisposableState]] 是 disposed,则返回 undefined。
  4. 将 asyncDisposableStack.[[AsyncDisposableState]] 设置为 disposed。
  5. 返回 ? DisposeResources(asyncDisposableStack.[[DisposableResourceStack]], NormalCompletion(undefined))。

27.4.3.5 get AsyncDisposableStack.prototype.disposed

AsyncDisposableStack.prototype.disposed 是访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数在调用时执行以下步骤:

  1. 令 asyncDisposableStack 为 this value。
  2. 执行 ? RequireInternalSlot(asyncDisposableStack, [[AsyncDisposableState]])。
  3. 如果 asyncDisposableStack.[[AsyncDisposableState]] 是 disposed,则返回 true。
  4. 返回 false。

27.4.3.6 AsyncDisposableStack.prototype.move ( )

调用时,此方法执行以下步骤:

  1. 令 asyncDisposableStack 为 this value。
  2. 执行 ? RequireInternalSlot(asyncDisposableStack, [[AsyncDisposableState]])。
  3. 如果 asyncDisposableStack.[[AsyncDisposableState]] 是 disposed,则抛出 ReferenceError 异常。
  4. 令 newAsyncDisposableStack 为 ? OrdinaryCreateFromConstructor(%AsyncDisposableStack%, "%AsyncDisposableStack.prototype%", « [[AsyncDisposableState]], [[DisposableResourceStack]] »)。
  5. 将 newAsyncDisposableStack.[[AsyncDisposableState]] 设置为 pending。
  6. 将 newAsyncDisposableStack.[[DisposableResourceStack]] 设置为 asyncDisposableStack.[[DisposableResourceStack]]。
  7. 将 asyncDisposableStack.[[DisposableResourceStack]] 设置为新的空 List。
  8. 将 asyncDisposableStack.[[AsyncDisposableState]] 设置为 disposed。
  9. 返回 newAsyncDisposableStack。

27.4.3.7 AsyncDisposableStack.prototype.use ( value )

调用时,此方法执行以下步骤:

  1. 令 asyncDisposableStack 为 this value。
  2. 执行 ? RequireInternalSlot(asyncDisposableStack, [[AsyncDisposableState]])。
  3. 如果 asyncDisposableStack.[[AsyncDisposableState]] 是 disposed,则抛出 ReferenceError 异常。
  4. 执行 ? AddDisposableResource(asyncDisposableStack.[[DisposableResourceStack]], value, async-dispose)。
  5. 返回 value。

27.4.3.8 AsyncDisposableStack.prototype [ %Symbol.asyncDispose% ] ( )

%Symbol.asyncDispose% 属性的初始值是 27.4.3.4 中定义的 %AsyncDisposableStack.prototype.disposeAsync%。

27.4.3.9 AsyncDisposableStack.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "AsyncDisposableStack"。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

27.4.4 AsyncDisposableStack 实例的属性

AsyncDisposableStack 实例是从 AsyncDisposableStack 原型对象(固有对象 %AsyncDisposableStack.prototype%)继承属性的普通对象。AsyncDisposableStack 实例最初创建时具有 表 90 中描述的内部槽。

表 90: AsyncDisposableStack 实例的内部槽
内部槽 类型 描述
[[AsyncDisposableState]] pending or disposed 控制可处置栈如何响应对其 %Symbol.asyncDispose% 方法的调用。
[[DisposableResourceStack]] a List of DisposableResource Records 可处置栈被处置时要处置的资源。资源按照初始化顺序添加,并按照相反顺序处置。

27.5 Promise 对象

Promise 是一种用作延迟(并且可能是异步)计算最终结果占位符的对象。

任何 Promise 都处于三个互斥状态之一:已兑现、已拒绝和待处理:

  • 如果 p.then(f, r) 会立即将一个调用函数 f 的 Job 加入队列,则 promise p 已兑现。
  • 如果 p.then(f, r) 会立即将一个调用函数 r 的 Job 加入队列,则 promise p 已拒绝。
  • 如果 promise 既未兑现也未拒绝,则它处于待处理状态。

如果 promise 不处于待处理状态,即它已兑现或已拒绝,则称该 promise 已敲定。

如果 promise 已敲定,或者已被“锁定”为匹配另一个 promise 的状态,则称该 promise 已解决。尝试解决或拒绝一个已经解决的 promise 不会产生任何效果。如果 promise 尚未解决,则称其未解决。未解决的 promise 始终处于待处理状态。已解决的 promise 可以处于待处理、已兑现或已拒绝状态。

thenable 是一个对象 obj,对其执行 Get(obj, "then") 会返回函数对象。

27.5.1 Promise 抽象操作

27.5.1.1 PromiseCapability Record

PromiseCapability Record 是用于封装 Promise 或类 promise 对象以及能够解决或拒绝该 promise 的函数的 Record。PromiseCapability Record 由 NewPromiseCapability 抽象操作产生。

PromiseCapability Record 具有 表 91 中列出的字段。

表 91: PromiseCapability Record 字段
字段名称 值 含义
[[Promise]] an Object 可作为 promise 使用的对象。
[[Resolve]] a function object 用于解决给定 promise 的函数。
[[Reject]] a function object 用于拒绝给定 promise 的函数。

27.5.1.1.1 IfAbruptRejectPromise ( value, capability )

IfAbruptRejectPromise 是一组使用 PromiseCapability Record 的算法步骤的简写。如下形式的算法步骤:

  1. IfAbruptRejectPromise(value, capability).

与以下内容具有相同含义:

  1. 断言:value 是 Completion Record。
  2. 如果 value 是突然完成,则
    1. 执行 ? Call(capability.[[Reject]], undefined, « value.[[Value]] »)。
    2. 返回 capability.[[Promise]]。
  3. 将 value 设置为 ! value。

27.5.1.2 PromiseReaction Record

PromiseReaction Record 是用于存储有关 promise 在以给定值解决或拒绝时应如何作出反应的信息的 Record。PromiseReaction Record 由 PerformPromiseThen 抽象操作创建,并由 NewPromiseReactionJob 返回的 Abstract Closure 使用。

PromiseReaction Record 具有 表 92 中列出的字段。

表 92: PromiseReaction Record 字段
字段名称 值 含义
[[Capability]] a PromiseCapability Record or undefined 此 Record 为其提供反应处理器的 promise 的 capability。
[[Type]] fulfill or reject 当 [[Handler]] 为 empty 时,[[Type]] 用于允许与敲定类型相关的特定行为。
[[Handler]] a JobCallback Record or empty 应应用于传入值的函数,其返回值将决定派生 promise 随后发生什么。如果 [[Handler]] 是 empty,则改用一个依赖 [[Type]] 值的函数。

27.5.1.3 CreateResolvingFunctions ( toResolve )

抽象操作 CreateResolvingFunctions,接收参数 toResolve (Promise);返回值:记录 (字段:[[Resolve]] (函数对象), [[Reject]] (函数对象))。 调用时执行以下步骤:

  1. 令 promiseOrEmpty 为 Record { [[Value]]: toResolve }。
  2. 令 resolveSteps 为参数为 (resolution) 的新 Abstract Closure,它捕获 promiseOrEmpty,并在被调用时执行以下步骤:
    1. 如果 promiseOrEmpty.[[Value]] 是 empty,则返回 undefined。
    2. 令 promise 为 promiseOrEmpty.[[Value]]。
    3. 将 promiseOrEmpty.[[Value]] 设置为 empty。
    4. 如果 SameValue(resolution, promise) 是 true,则
      1. 令 selfResolutionError 为新创建的 TypeError 对象。
      2. 执行 RejectPromise(promise, selfResolutionError)。
      3. 返回 undefined。
    5. 如果 resolution 不是 Object,则
      1. 执行 FulfillPromise(promise, resolution)。
      2. 返回 undefined。
    6. 令 then 为 Completion(Get(resolution, "then"))。
    7. 如果 then 是突然完成,则
      1. 执行 RejectPromise(promise, then.[[Value]])。
      2. 返回 undefined。
    8. 令 thenAction 为 then.[[Value]]。
    9. 如果 IsCallable(thenAction) 是 false,则
      1. 执行 FulfillPromise(promise, resolution)。
      2. 返回 undefined。
    10. 令 thenJobCallback 为 HostMakeJobCallback(thenAction)。
    11. 令 job 为 NewPromiseResolveThenableJob(promise, resolution, thenJobCallback)。
    12. 执行 HostEnqueuePromiseJob(job.[[Job]], job.[[Realm]])。
    13. 返回 undefined。
  3. 令 resolve 为 CreateBuiltinFunction(resolveSteps, 1, "", « »)。
  4. 令 rejectSteps 为参数为 (reason) 的新 Abstract Closure,它捕获 promiseOrEmpty,并在被调用时执行以下步骤:
    1. 如果 promiseOrEmpty.[[Value]] 是 empty,则返回 undefined。
    2. 令 promise 为 promiseOrEmpty.[[Value]]。
    3. 将 promiseOrEmpty.[[Value]] 设置为 empty。
    4. 执行 RejectPromise(promise, reason)。
    5. 返回 undefined。
  5. 令 reject 为 CreateBuiltinFunction(rejectSteps, 1, "", « »)。
  6. 返回 Record { [[Resolve]]: resolve, [[Reject]]: reject }。

27.5.1.4 FulfillPromise ( promise, value )

抽象操作 FulfillPromise,接收参数 promise (Promise) 和 value (ECMAScript 语言值);返回值:unused。 调用时执行以下步骤:

  1. 断言:promise.[[PromiseState]] 是 pending。
  2. 令 reactions 为 promise.[[PromiseFulfillReactions]]。
  3. 将 promise.[[PromiseResult]] 设置为 value。
  4. 将 promise.[[PromiseFulfillReactions]] 设置为 undefined。
  5. 将 promise.[[PromiseRejectReactions]] 设置为 undefined。
  6. 将 promise.[[PromiseState]] 设置为 fulfilled。
  7. 执行 TriggerPromiseReactions(reactions, value)。
  8. 返回 unused。

27.5.1.5 NewPromiseCapability ( ctor )

抽象操作 NewPromiseCapability,接收参数 ctor (ECMAScript 语言值);返回值:(正常完成 (值:PromiseCapability 记录) 或 抛出完成)。 它尝试以类似内置 Promise 构造函数的方式将 ctor 用作构造函数,以创建 promise 并提取其 resolve 和 reject 函数。该 promise 加上 resolve 和 reject 函数用于初始化新的 PromiseCapability Record。 调用时执行以下步骤:

  1. 如果 IsConstructor(ctor) 是 false,则抛出 TypeError 异常。
  2. 注:假定 ctor 是支持 Promise 构造函数参数约定的构造函数(参见 27.5.3.1)。
  3. 令 resolvingFuncs 为 Record { [[Resolve]]: undefined, [[Reject]]: undefined }。
  4. 令 executorClosure 为参数为 (resolve, reject) 的新 Abstract Closure,它捕获 resolvingFuncs,并在被调用时执行以下步骤:
    1. 如果 resolvingFuncs.[[Resolve]] 不是 undefined,则抛出 TypeError 异常。
    2. 如果 resolvingFuncs.[[Reject]] 不是 undefined,则抛出 TypeError 异常。
    3. 将 resolvingFuncs.[[Resolve]] 设置为 resolve。
    4. 将 resolvingFuncs.[[Reject]] 设置为 reject。
    5. 返回 NormalCompletion(undefined)。
  5. 令 executor 为 CreateBuiltinFunction(executorClosure, 2, "", « »)。
  6. 令 promise 为 ? Construct(ctor, « executor »)。
  7. 如果 IsCallable(resolvingFuncs.[[Resolve]]) 是 false,则抛出 TypeError 异常。
  8. 如果 IsCallable(resolvingFuncs.[[Reject]]) 是 false,则抛出 TypeError 异常。
  9. 返回 PromiseCapability Record { [[Promise]]: promise, [[Resolve]]: resolvingFuncs.[[Resolve]], [[Reject]]: resolvingFuncs.[[Reject]] }。
注

此抽象操作支持 Promise 子类化,因为它可以通用于任何以与 Promise 构造函数相同方式调用传入 executor 函数参数的构造函数。它用于将 Promise 构造函数的静态方法推广到任何子类。

27.5.1.6 IsPromise ( arg )

抽象操作 IsPromise,接收参数 arg (ECMAScript 语言值);返回值:Boolean。 它检查对象是否具有 promise 品牌。 调用时执行以下步骤:

  1. 如果 arg 不是 Object,则返回 false。
  2. 如果 arg 不具有 [[PromiseState]] 内部槽,则返回 false。
  3. 返回 true。

27.5.1.7 RejectPromise ( promise, reason )

抽象操作 RejectPromise,接收参数 promise (Promise) 和 reason (ECMAScript 语言值);返回值:unused。 调用时执行以下步骤:

  1. 断言:promise.[[PromiseState]] 是 pending。
  2. 令 reactions 为 promise.[[PromiseRejectReactions]]。
  3. 将 promise.[[PromiseResult]] 设置为 reason。
  4. 将 promise.[[PromiseFulfillReactions]] 设置为 undefined。
  5. 将 promise.[[PromiseRejectReactions]] 设置为 undefined。
  6. 将 promise.[[PromiseState]] 设置为 rejected。
  7. 如果 promise.[[PromiseIsHandled]] 是 false,则执行 HostPromiseRejectionTracker(promise, "reject")。
  8. 执行 TriggerPromiseReactions(reactions, reason)。
  9. 返回 unused。

27.5.1.8 TriggerPromiseReactions ( reactions, arg )

抽象操作 TriggerPromiseReactions,接收参数 reactions (列表 (元素:PromiseReaction 记录)) 和 arg (ECMAScript 语言值);返回值:unused。 它为 reactions 中的每个 Record 将一个新的 Job 加入队列。每个此类 Job 处理 PromiseReaction Record 的 [[Type]] 和 [[Handler]],如果 [[Handler]] 不是 empty,则调用它并传入给定参数。如果 [[Handler]] 是 empty,则行为由 [[Type]] 决定。 调用时执行以下步骤:

  1. 对 reactions 的每个元素 reaction,执行
    1. 令 job 为 NewPromiseReactionJob(reaction, arg)。
    2. 执行 HostEnqueuePromiseJob(job.[[Job]], job.[[Realm]])。
  2. 返回 unused。

27.5.1.9 HostPromiseRejectionTracker ( promise, operation )

宿主定义的抽象操作 HostPromiseRejectionTracker,接收参数 promise (Promise) 和 operation (("reject" 或 "handle"));返回值:unused。 它允许宿主环境跟踪 promise 拒绝。

HostPromiseRejectionTracker 的默认实现是返回 unused。

注 1

HostPromiseRejectionTracker 会在两种情况下被调用:

  • 当 promise 在没有任何处理器的情况下被拒绝时,会以 operation 参数设置为 "reject" 来调用它。
  • 当第一次向已拒绝的 promise 添加处理器时,会以 operation 参数设置为 "handle" 来调用它。

HostPromiseRejectionTracker 的典型实现可能会尝试向开发者通知未处理的拒绝,同时也会谨慎地在随后附加新处理器而使先前通知失效时通知他们。

注 2

如果 operation 是 "handle",实现不应以会干扰垃圾回收的方式保留对 promise 的引用。如果 operation 是 "reject",实现可以保留对 promise 的引用,因为预期拒绝很少发生,也不会出现在热点代码路径上。

27.5.2 Promise Job

27.5.2.1 NewPromiseReactionJob ( reaction, arg )

抽象操作 NewPromiseReactionJob,接收参数 reaction (PromiseReaction 记录) 和 arg (ECMAScript 语言值);返回值:记录 (字段:[[Job]] (a Job Abstract Closure), [[Realm]] ((Realm 记录 或 null)))。 它返回一个新的 Job Abstract Closure,该闭包将适当的处理器应用于传入值,并使用处理器的返回值来解决或拒绝与该处理器关联的派生 promise。 调用时执行以下步骤:

  1. 令 job 为不带参数的新 Job Abstract Closure,它捕获 reaction 和 arg,并在被调用时执行以下步骤:
    1. 令 promiseCapability 为 reaction.[[Capability]]。
    2. 令 type 为 reaction.[[Type]]。
    3. 令 handler 为 reaction.[[Handler]]。
    4. 如果 handler 是 empty,则
      1. 如果 type 是 fulfill,则
        1. 令 handlerResult 为 NormalCompletion(arg)。
      2. 否则,
        1. 断言:type 是 reject。
        2. 令 handlerResult 为 ThrowCompletion(arg)。
    5. 否则,
      1. 令 handlerResult 为 Completion(HostCallJobCallback(handler, undefined, « arg »))。
    6. 如果 promiseCapability 是 undefined,则
      1. 断言:handlerResult 不是突然完成。
      2. 返回 empty。
    7. 断言:promiseCapability 是 PromiseCapability Record。
    8. 如果 handlerResult 是突然完成,则
      1. 返回 ? Call(promiseCapability.[[Reject]], undefined, « handlerResult.[[Value]] »)。
    9. 返回 ? Call(promiseCapability.[[Resolve]], undefined, « handlerResult.[[Value]] »)。
  2. 令 handlerRealm 为 null。
  3. 如果 reaction.[[Handler]] 不是 empty,则
    1. 令 getHandlerRealmResult 为 Completion(GetFunctionRealm(reaction.[[Handler]].[[Callback]]))。
    2. 如果 getHandlerRealmResult 是正常完成,则将 handlerRealm 设置为 getHandlerRealmResult.[[Value]]。
    3. 否则,将 handlerRealm 设置为当前 Realm Record。
    4. 注:除非处理器是 undefined,否则 handlerRealm 永远不会是 null。当处理器是已撤销的 Proxy 且没有 ECMAScript 代码运行时,handlerRealm 用于创建错误对象。
  4. 返回 Record { [[Job]]: job, [[Realm]]: handlerRealm }。

27.5.2.2 NewPromiseResolveThenableJob ( promiseToResolve, thenable, then )

抽象操作 NewPromiseResolveThenableJob,接收参数 promiseToResolve (Promise)、thenable (Object) 和 then (JobCallback 记录);返回值:记录 (字段:[[Job]] (a Job Abstract Closure), [[Realm]] (Realm 记录))。 调用时执行以下步骤:

  1. 令 job 为不带参数的新 Job Abstract Closure,它捕获 promiseToResolve、thenable 和 then,并在被调用时执行以下步骤:
    1. 令 resolvingFuncs 为 CreateResolvingFunctions(promiseToResolve)。
    2. 令 thenCallResult 为 Completion(HostCallJobCallback(then, thenable, « resolvingFuncs.[[Resolve]], resolvingFuncs.[[Reject]] »))。
    3. 如果 thenCallResult 是突然完成,则
      1. 返回 ? Call(resolvingFuncs.[[Reject]], undefined, « thenCallResult.[[Value]] »)。
    4. 返回 ! thenCallResult。
  2. 令 getThenRealmResult 为 Completion(GetFunctionRealm(then.[[Callback]]))。
  3. 如果 getThenRealmResult 是正常完成,则令 thenRealm 为 getThenRealmResult.[[Value]]。
  4. 否则,令 thenRealm 为当前 Realm Record。
  5. 注:thenRealm 永远不会是 null。当 then.[[Callback]] 是已撤销的 Proxy 且没有代码运行时,thenRealm 用于创建错误对象。
  6. 返回 Record { [[Job]]: job, [[Realm]]: thenRealm }。
注

此 Job 使用提供的 thenable 及其 then 方法来解决给定的 promise。此过程必须作为 Job 执行,以确保 then 方法的求值发生在任何周围代码求值完成之后。

27.5.3 Promise 构造函数

Promise 构造函数:

  • 是 %Promise%。
  • 是全局对象的 "Promise" 属性的初始值。
  • 作为构造函数调用时,创建并初始化新的 Promise。
  • 不旨在作为函数调用,并且以这种方式调用时会抛出异常。
  • 可以用作类定义的 extends 子句中的值。希望继承指定 Promise 行为的子类构造函数必须包含对 Promise 构造函数的 super 调用,以创建并初始化具有支持 Promise 和 Promise.prototype 内置方法所必需内部状态的子类实例。

27.5.3.1 Promise ( executor )

调用时,此函数执行以下步骤:

  1. 如果 NewTarget 是 undefined,则抛出 TypeError 异常。
  2. 如果 IsCallable(executor) 是 false,则抛出 TypeError 异常。
  3. 令 promise 为 ? OrdinaryCreateFromConstructor(NewTarget, "%Promise.prototype%", « [[PromiseState]], [[PromiseResult]], [[PromiseFulfillReactions]], [[PromiseRejectReactions]], [[PromiseIsHandled]] »)。
  4. 将 promise.[[PromiseState]] 设置为 pending。
  5. 将 promise.[[PromiseResult]] 设置为 empty。
  6. 将 promise.[[PromiseFulfillReactions]] 设置为新的空 List。
  7. 将 promise.[[PromiseRejectReactions]] 设置为新的空 List。
  8. 将 promise.[[PromiseIsHandled]] 设置为 false。
  9. 令 resolvingFuncs 为 CreateResolvingFunctions(promise)。
  10. 令 completion 为 Completion(Call(executor, undefined, « resolvingFuncs.[[Resolve]], resolvingFuncs.[[Reject]] »))。
  11. 如果 completion 是突然完成,则
    1. 执行 ? Call(resolvingFuncs.[[Reject]], undefined, « completion.[[Value]] »)。
  12. 返回 promise。
注

executor 参数必须是函数对象。调用它是为了启动并报告此 Promise 所表示的可能延迟操作的完成情况。调用 executor 时传入两个参数:resolve 和 reject。executor 函数可以使用这些函数来报告延迟计算最终完成或失败。从 executor 函数返回并不意味着延迟操作已经完成,而只意味着最终执行该延迟操作的请求已被接受。

传递给 executor 函数的 resolve 函数接受一个参数。executor 代码最终可以调用 resolve 函数,以表明它希望解决关联的 Promise。传递给 resolve 函数的参数表示延迟操作的最终值,可以是实际兑现值,也可以是另一个 promise;如果后者被兑现,它将提供该值。

传递给 executor 函数的 reject 函数接受一个参数。executor 代码最终可以调用 reject 函数,以表明关联的 Promise 被拒绝并且永远不会兑现。传递给 reject 函数的参数用作 promise 的拒绝值。通常它会是 Error 对象。

Promise 构造函数传递给 executor 函数的 resolve 和 reject 函数具有实际解决和拒绝关联 promise 的能力。子类可以具有不同的构造函数行为,为 resolve 和 reject 传入自定义值。

27.5.4 Promise 构造函数的属性

Promise 构造函数:

27.5.4.1 Promise.all ( iterable )

此函数返回一个新的 promise,该 promise 会以传入 promise 的兑现值数组兑现;或者以第一个被拒绝的传入 promise 的原因被拒绝。执行此算法时,它会将传入 iterable 的所有元素都解决为 promise。

  1. 令 ctor 为 this value。
  2. 令 promiseCapability 为 ? NewPromiseCapability(ctor)。
  3. 令 promiseResolve 为 Completion(GetPromiseResolve(ctor))。
  4. IfAbruptRejectPromise(promiseResolve, promiseCapability)。
  5. 令 iteratorRecord 为 Completion(GetIterator(iterable, sync))。
  6. IfAbruptRejectPromise(iteratorRecord, promiseCapability)。
  7. 令 result 为 Completion(PerformPromiseAll(iteratorRecord, ctor, promiseCapability, promiseResolve))。
  8. 如果 result 是突然完成,则
    1. 如果 iteratorRecord.[[Done]] 是 false,则将 result 设置为 Completion(IteratorClose(iteratorRecord, result))。
    2. IfAbruptRejectPromise(result, promiseCapability)。
  9. 返回 ! result。
注

此函数要求其 this value 是支持 Promise 构造函数参数约定的构造函数。

27.5.4.1.1 GetPromiseResolve ( promiseCtor )

抽象操作 GetPromiseResolve,接收参数 promiseCtor (构造函数);返回值:(正常完成 (值:函数对象) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 promiseResolve 为 ? Get(promiseCtor, "resolve")。
  2. 如果 IsCallable(promiseResolve) 是 false,则抛出 TypeError 异常。
  3. 返回 promiseResolve。

27.5.4.1.2 PerformPromiseAll ( iteratorRecord, ctor, resultCapability, promiseResolve )

抽象操作 PerformPromiseAll,接收参数 iteratorRecord (Iterator 记录)、ctor (构造函数)、resultCapability (PromiseCapability 记录) 和 promiseResolve (函数对象);返回值:(正常完成 (值:Object) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 values 为新的空 List。
  2. 注:remainingElementsCount 从 1 而不是 0 开始,以确保即使存在行为异常的 "then" 在输入 iterator 耗尽之前就调用传入的回调,resultCapability.[[Resolve]] 也只会被调用一次。
  3. 令 remainingElementsCount 为 Record { [[Value]]: 1 }。
  4. 令 index 为 0。
  5. 重复执行,
    1. 令 next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 next 是 done,则
      1. 将 remainingElementsCount.[[Value]] 设置为 remainingElementsCount.[[Value]] - 1。
      2. 如果 remainingElementsCount.[[Value]] = 0,则
        1. 令 valuesArray 为 CreateArrayFromList(values)。
        2. 执行 ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »)。
      3. 返回 resultCapability.[[Promise]]。
    3. 将 undefined 追加到 values。
    4. 令 nextPromise 为 ? Call(promiseResolve, ctor, « next »)。
    5. 令 fulfilledSteps 为参数为 (value) 的新 Abstract Closure,它捕获 values、resultCapability 和 remainingElementsCount,并在被调用时执行以下步骤:
      1. 令 activeFunc 为活动函数对象。
      2. 如果 activeFunc.[[AlreadyCalled]] 是 true,则返回 undefined。
      3. 将 activeFunc.[[AlreadyCalled]] 设置为 true。
      4. 令 thisIndex 为 activeFunc.[[Index]]。
      5. 将 values[thisIndex] 设置为 value。
      6. 将 remainingElementsCount.[[Value]] 设置为 remainingElementsCount.[[Value]] - 1。
      7. 如果 remainingElementsCount.[[Value]] = 0,则
        1. 令 valuesArray 为 CreateArrayFromList(values)。
        2. 返回 ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »)。
      8. 返回 undefined。
    6. 令 onFulfilled 为 CreateBuiltinFunction(fulfilledSteps, 1, "", « [[AlreadyCalled]], [[Index]] »)。
    7. 将 onFulfilled.[[AlreadyCalled]] 设置为 false。
    8. 将 onFulfilled.[[Index]] 设置为 index。
    9. 将 index 设置为 index + 1。
    10. 将 remainingElementsCount.[[Value]] 设置为 remainingElementsCount.[[Value]] + 1。
    11. 执行 ? Invoke(nextPromise, "then", « onFulfilled, resultCapability.[[Reject]] »)。

27.5.4.2 Promise.allSettled ( iterable )

此函数返回一个 promise,该 promise 会以 promise 状态快照数组兑现,但只会在所有原始 promise 都已敲定(即变为已兑现或已拒绝)之后兑现。执行此算法时,它会将传入 iterable 的所有元素都解决为 promise。

  1. 令 ctor 为 this value。
  2. 令 promiseCapability 为 ? NewPromiseCapability(ctor)。
  3. 令 promiseResolve 为 Completion(GetPromiseResolve(ctor))。
  4. IfAbruptRejectPromise(promiseResolve, promiseCapability)。
  5. 令 iteratorRecord 为 Completion(GetIterator(iterable, sync))。
  6. IfAbruptRejectPromise(iteratorRecord, promiseCapability)。
  7. 令 result 为 Completion(PerformPromiseAllSettled(iteratorRecord, ctor, promiseCapability, promiseResolve))。
  8. 如果 result 是突然完成,则
    1. 如果 iteratorRecord.[[Done]] 是 false,则将 result 设置为 Completion(IteratorClose(iteratorRecord, result))。
    2. IfAbruptRejectPromise(result, promiseCapability)。
  9. 返回 ! result。
注

此函数要求其 this value 是支持 Promise 构造函数参数约定的构造函数。

27.5.4.2.1 PerformPromiseAllSettled ( iteratorRecord, ctor, resultCapability, promiseResolve )

抽象操作 PerformPromiseAllSettled,接收参数 iteratorRecord (Iterator 记录)、ctor (构造函数)、resultCapability (PromiseCapability 记录) 和 promiseResolve (函数对象);返回值:(正常完成 (值:Object) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 values 为新的空 List。
  2. 注:remainingElementsCount 从 1 而不是 0 开始,以确保即使存在行为异常的 "then" 在输入 iterator 耗尽之前就调用传入的某个回调,resultCapability.[[Resolve]] 也只会被调用一次。
  3. 令 remainingElementsCount 为 Record { [[Value]]: 1 }。
  4. 令 index 为 0。
  5. 重复执行,
    1. 令 next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 next 是 done,则
      1. 将 remainingElementsCount.[[Value]] 设置为 remainingElementsCount.[[Value]] - 1。
      2. 如果 remainingElementsCount.[[Value]] = 0,则
        1. 令 valuesArray 为 CreateArrayFromList(values)。
        2. 执行 ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »)。
      3. 返回 resultCapability.[[Promise]]。
    3. 将 undefined 追加到 values。
    4. 令 nextPromise 为 ? Call(promiseResolve, ctor, « next »)。
    5. 令 alreadyCalled 为 Record { [[Value]]: false }。
    6. 令 fulfilledSteps 为参数为 (value) 的新 Abstract Closure,它捕获 values、resultCapability 和 remainingElementsCount,并在被调用时执行以下步骤:
      1. 令 activeFunc 为活动函数对象。
      2. 如果 activeFunc.[[AlreadyCalled]].[[Value]] 是 true,则返回 undefined。
      3. 将 activeFunc.[[AlreadyCalled]].[[Value]] 设置为 true。
      4. 令 obj 为 OrdinaryObjectCreate(%Object.prototype%)。
      5. 执行 ! CreateDataPropertyOrThrow(obj, "status", "fulfilled")。
      6. 执行 ! CreateDataPropertyOrThrow(obj, "value", value)。
      7. 令 thisIndex 为 activeFunc.[[Index]]。
      8. 将 values[thisIndex] 设置为 obj。
      9. 将 remainingElementsCount.[[Value]] 设置为 remainingElementsCount.[[Value]] - 1。
      10. 如果 remainingElementsCount.[[Value]] = 0,则
        1. 令 valuesArray 为 CreateArrayFromList(values)。
        2. 返回 ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »)。
      11. 返回 undefined。
    7. 令 onFulfilled 为 CreateBuiltinFunction(fulfilledSteps, 1, "", « [[AlreadyCalled]], [[Index]] »)。
    8. 将 onFulfilled.[[AlreadyCalled]] 设置为 alreadyCalled。
    9. 将 onFulfilled.[[Index]] 设置为 index。
    10. 令 rejectedSteps 为参数为 (error) 的新 Abstract Closure,它捕获 values、resultCapability 和 remainingElementsCount,并在被调用时执行以下步骤:
      1. 令 activeFunc 为活动函数对象。
      2. 如果 activeFunc.[[AlreadyCalled]].[[Value]] 是 true,则返回 undefined。
      3. 将 activeFunc.[[AlreadyCalled]].[[Value]] 设置为 true。
      4. 令 obj 为 OrdinaryObjectCreate(%Object.prototype%)。
      5. 执行 ! CreateDataPropertyOrThrow(obj, "status", "rejected")。
      6. 执行 ! CreateDataPropertyOrThrow(obj, "reason", error)。
      7. 令 thisIndex 为 activeFunc.[[Index]]。
      8. 将 values[thisIndex] 设置为 obj。
      9. 将 remainingElementsCount.[[Value]] 设置为 remainingElementsCount.[[Value]] - 1。
      10. 如果 remainingElementsCount.[[Value]] = 0,则
        1. 令 valuesArray 为 CreateArrayFromList(values)。
        2. 返回 ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »)。
      11. 返回 undefined。
    11. 令 onRejected 为 CreateBuiltinFunction(rejectedSteps, 1, "", « [[AlreadyCalled]], [[Index]] »)。
    12. 将 onRejected.[[AlreadyCalled]] 设置为 alreadyCalled。
    13. 将 onRejected.[[Index]] 设置为 index。
    14. 将 index 设置为 index + 1。
    15. 将 remainingElementsCount.[[Value]] 设置为 remainingElementsCount.[[Value]] + 1。
    16. 执行 ? Invoke(nextPromise, "then", « onFulfilled, onRejected »)。

27.5.4.3 Promise.any ( iterable )

此函数返回一个 promise,该 promise 会由第一个兑现的给定 promise 兑现;如果所有给定 promise 都被拒绝,则以包含这些拒绝原因的 AggregateError 被拒绝。执行此算法时,它会将传入 iterable 的所有元素都解决为 promise。

  1. 令 ctor 为 this value。
  2. 令 promiseCapability 为 ? NewPromiseCapability(ctor)。
  3. 令 promiseResolve 为 Completion(GetPromiseResolve(ctor))。
  4. IfAbruptRejectPromise(promiseResolve, promiseCapability)。
  5. 令 iteratorRecord 为 Completion(GetIterator(iterable, sync))。
  6. IfAbruptRejectPromise(iteratorRecord, promiseCapability)。
  7. 令 result 为 Completion(PerformPromiseAny(iteratorRecord, ctor, promiseCapability, promiseResolve))。
  8. 如果 result 是突然完成,则
    1. 如果 iteratorRecord.[[Done]] 是 false,则将 result 设置为 Completion(IteratorClose(iteratorRecord, result))。
    2. IfAbruptRejectPromise(result, promiseCapability)。
  9. 返回 ! result。
注

此函数要求其 this value 是支持 Promise 构造函数参数约定的构造函数。

27.5.4.3.1 PerformPromiseAny ( iteratorRecord, ctor, resultCapability, promiseResolve )

抽象操作 PerformPromiseAny,接收参数 iteratorRecord (Iterator 记录)、ctor (构造函数)、resultCapability (PromiseCapability 记录) 和 promiseResolve (函数对象);返回值:(正常完成 (值:Object) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 errors 为新的空 List。
  2. 注:remainingElementsCount 从 1 而不是 0 开始,以确保即使存在行为异常的 "then" 在输入 iterator 耗尽之前就调用传入的回调,resultCapability.[[Reject]] 也只会被调用一次。
  3. 令 remainingElementsCount 为 Record { [[Value]]: 1 }。
  4. 令 index 为 0。
  5. 重复执行,
    1. 令 next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 next 是 done,则
      1. 将 remainingElementsCount.[[Value]] 设置为 remainingElementsCount.[[Value]] - 1。
      2. 如果 remainingElementsCount.[[Value]] = 0,则
        1. 令 aggregateError 为新创建的 AggregateError 对象。
        2. 执行 ! DefinePropertyOrThrow(aggregateError, "errors", PropertyDescriptor { [[Configurable]]: true, [[Enumerable]]: false, [[Writable]]: true, [[Value]]: CreateArrayFromList(errors) })。
        3. 执行 ? Call(resultCapability.[[Reject]], undefined, « aggregateError »)。
      3. 返回 resultCapability.[[Promise]]。
    3. 将 undefined 追加到 errors。
    4. 令 nextPromise 为 ? Call(promiseResolve, ctor, « next »)。
    5. 令 rejectedSteps 为参数为 (error) 的新 Abstract Closure,它捕获 errors、resultCapability 和 remainingElementsCount,并在被调用时执行以下步骤:
      1. 令 activeFunc 为活动函数对象。
      2. 如果 activeFunc.[[AlreadyCalled]] 是 true,则返回 undefined。
      3. 将 activeFunc.[[AlreadyCalled]] 设置为 true。
      4. 令 thisIndex 为 activeFunc.[[Index]]。
      5. 将 errors[thisIndex] 设置为 error。
      6. 将 remainingElementsCount.[[Value]] 设置为 remainingElementsCount.[[Value]] - 1。
      7. 如果 remainingElementsCount.[[Value]] = 0,则
        1. 令 aggregateError 为新创建的 AggregateError 对象。
        2. 执行 ! DefinePropertyOrThrow(aggregateError, "errors", PropertyDescriptor { [[Configurable]]: true, [[Enumerable]]: false, [[Writable]]: true, [[Value]]: CreateArrayFromList(errors) })。
        3. 返回 ? Call(resultCapability.[[Reject]], undefined, « aggregateError »)。
      8. 返回 undefined。
    6. 令 onRejected 为 CreateBuiltinFunction(rejectedSteps, 1, "", « [[AlreadyCalled]], [[Index]] »)。
    7. 将 onRejected.[[AlreadyCalled]] 设置为 false。
    8. 将 onRejected.[[Index]] 设置为 index。
    9. 将 index 设置为 index + 1。
    10. 将 remainingElementsCount.[[Value]] 设置为 remainingElementsCount.[[Value]] + 1。
    11. 执行 ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], onRejected »)。

27.5.4.4 Promise.prototype

Promise.prototype 的初始值是 Promise 原型对象。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

27.5.4.5 Promise.race ( iterable )

此函数返回一个新的 promise,该 promise 会以与第一个敲定的传入 promise 相同的方式敲定。执行此算法时,它会将传入 iterable 的所有元素都解决为 promise。

  1. 令 ctor 为 this value。
  2. 令 promiseCapability 为 ? NewPromiseCapability(ctor)。
  3. 令 promiseResolve 为 Completion(GetPromiseResolve(ctor))。
  4. IfAbruptRejectPromise(promiseResolve, promiseCapability)。
  5. 令 iteratorRecord 为 Completion(GetIterator(iterable, sync))。
  6. IfAbruptRejectPromise(iteratorRecord, promiseCapability)。
  7. 令 result 为 Completion(PerformPromiseRace(iteratorRecord, ctor, promiseCapability, promiseResolve))。
  8. 如果 result 是突然完成,则
    1. 如果 iteratorRecord.[[Done]] 是 false,则将 result 设置为 Completion(IteratorClose(iteratorRecord, result))。
    2. IfAbruptRejectPromise(result, promiseCapability)。
  9. 返回 ! result。
注 1

如果 iterable 参数不产生任何值,或者 iterable 产生的 promise 都永远不会敲定,那么此方法返回的待处理 promise 将永远不会敲定。

注 2

此函数预期其 this value 是支持 Promise 构造函数参数约定的构造函数。它还预期其 this value 提供 resolve 方法。

27.5.4.5.1 PerformPromiseRace ( iteratorRecord, ctor, resultCapability, promiseResolve )

抽象操作 PerformPromiseRace,接收参数 iteratorRecord (Iterator 记录)、ctor (构造函数)、resultCapability (PromiseCapability 记录) 和 promiseResolve (函数对象);返回值:(正常完成 (值:Object) 或 抛出完成)。 调用时执行以下步骤:

  1. 重复执行,
    1. 令 next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 next 是 done,则
      1. 返回 resultCapability.[[Promise]]。
    3. 令 nextPromise 为 ? Call(promiseResolve, ctor, « next »)。
    4. 执行 ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], resultCapability.[[Reject]] »)。

27.5.4.6 Promise.reject ( reason )

此函数返回一个以传入参数作为拒绝原因的新 promise。

  1. 令 ctor 为 this value。
  2. 令 promiseCapability 为 ? NewPromiseCapability(ctor)。
  3. 执行 ? Call(promiseCapability.[[Reject]], undefined, « reason »)。
  4. 返回 promiseCapability.[[Promise]]。
注

此函数预期其 this value 是支持 Promise 构造函数参数约定的构造函数。

27.5.4.7 Promise.resolve ( resolution )

此函数返回一个以传入参数解决的新 promise;或者,如果该参数是由此构造函数产生的 promise,则返回该参数本身。

  1. 令 ctor 为 this value。
  2. 如果 ctor 不是 Object,则抛出 TypeError 异常。
  3. 返回 ? PromiseResolve(ctor, resolution)。
注

此函数预期其 this value 是支持 Promise 构造函数参数约定的构造函数。

27.5.4.7.1 PromiseResolve ( ctor, resolution )

抽象操作 PromiseResolve,接收参数 ctor (Object) 和 resolution (ECMAScript 语言值);返回值:(正常完成 (值:Object) 或 抛出完成)。 它返回一个以 resolution 解决的新 promise。 调用时执行以下步骤:

  1. 如果 IsPromise(resolution) 是 true,则
    1. 令 resolutionCtor 为 ? Get(resolution, "constructor")。
    2. 如果 SameValue(resolutionCtor, ctor) 是 true,则返回 resolution。
  2. 令 promiseCapability 为 ? NewPromiseCapability(ctor)。
  3. 执行 ? Call(promiseCapability.[[Resolve]], undefined, « resolution »)。
  4. 返回 promiseCapability.[[Promise]]。

27.5.4.8 Promise.try ( callback, ...args )

调用时,此函数执行以下步骤:

  1. 令 ctor 为 this value。
  2. 如果 ctor 不是 Object,则抛出 TypeError 异常。
  3. 令 status 为 Completion(Call(callback, undefined, args))。
  4. 如果 status 是突然完成,则
    1. 令 promiseCapability 为 ? NewPromiseCapability(ctor)。
    2. 执行 ? Call(promiseCapability.[[Reject]], undefined, « status.[[Value]] »)。
    3. 返回 promiseCapability.[[Promise]]。
  5. 否则,
    1. 返回 ? PromiseResolve(ctor, ! status)。
注

此函数预期其 this value 是支持 Promise 构造函数参数约定的构造函数。

27.5.4.9 Promise.withResolvers ( )

此函数返回一个具有三个属性的对象:一个新的 promise,以及与其关联的 resolve 和 reject 函数。

  1. 令 ctor 为 this value。
  2. 令 promiseCapability 为 ? NewPromiseCapability(ctor)。
  3. 令 obj 为 OrdinaryObjectCreate(%Object.prototype%)。
  4. 执行 ! CreateDataPropertyOrThrow(obj, "promise", promiseCapability.[[Promise]])。
  5. 执行 ! CreateDataPropertyOrThrow(obj, "resolve", promiseCapability.[[Resolve]])。
  6. 执行 ! CreateDataPropertyOrThrow(obj, "reject", promiseCapability.[[Reject]])。
  7. 返回 obj。

27.5.4.10 get Promise [ %Symbol.species% ]

Promise[%Symbol.species%] 是访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数在调用时执行以下步骤:

  1. 返回 this value。

此函数的 "name" 属性的值是 "get [Symbol.species]"。

注

Promise 原型方法通常使用其 this value 的构造函数来创建派生对象。不过,子类构造函数可以通过重新定义其 %Symbol.species% 属性覆盖该默认行为。

27.5.5 Promise 原型对象的属性

Promise 原型对象:

  • 是 %Promise.prototype%。
  • 具有 [[Prototype]] 内部槽,其值是 %Object.prototype%。
  • 是普通对象。
  • 不具有 [[PromiseState]] 内部槽,也不具有 Promise 实例的任何其他内部槽。

27.5.5.1 Promise.prototype.catch ( onRejected )

调用时,此方法执行以下步骤:

  1. 令 promise 为 this value。
  2. 返回 ? Invoke(promise, "then", « undefined, onRejected »)。

27.5.5.2 Promise.prototype.constructor

Promise.prototype.constructor 的初始值是 %Promise%。

27.5.5.3 Promise.prototype.finally ( onFinally )

调用时,此方法执行以下步骤:

  1. 令 promise 为 this value。
  2. 如果 promise 不是 Object,则抛出 TypeError 异常。
  3. 令 ctor 为 ? SpeciesConstructor(promise, %Promise%)。
  4. 断言:IsConstructor(ctor) 是 true。
  5. 如果 IsCallable(onFinally) 是 false,则
    1. 令 thenFinally 为 onFinally。
    2. 令 catchFinally 为 onFinally。
  6. 否则,
    1. 令 thenFinallyClosure 为参数为 (value) 的新 Abstract Closure,它捕获 onFinally 和 ctor,并在被调用时执行以下步骤:
      1. 令 result 为 ? Call(onFinally, undefined)。
      2. 令 p 为 ? PromiseResolve(ctor, result)。
      3. 令 returnValue 为不带参数的新 Abstract Closure,它捕获 value,并在被调用时执行以下步骤:
        1. 返回 NormalCompletion(value)。
      4. 令 valueThunk 为 CreateBuiltinFunction(returnValue, 0, "", « »)。
      5. 返回 ? Invoke(p, "then", « valueThunk »)。
    2. 令 thenFinally 为 CreateBuiltinFunction(thenFinallyClosure, 1, "", « »)。
    3. 令 catchFinallyClosure 为参数为 (reason) 的新 Abstract Closure,它捕获 onFinally 和 ctor,并在被调用时执行以下步骤:
      1. 令 result 为 ? Call(onFinally, undefined)。
      2. 令 p 为 ? PromiseResolve(ctor, result)。
      3. 令 throwReason 为不带参数的新 Abstract Closure,它捕获 reason,并在被调用时执行以下步骤:
        1. 抛出 reason。
      4. 令 thrower 为 CreateBuiltinFunction(throwReason, 0, "", « »)。
      5. 返回 ? Invoke(p, "then", « thrower »)。
    4. 令 catchFinally 为 CreateBuiltinFunction(catchFinallyClosure, 1, "", « »)。
  7. 返回 ? Invoke(promise, "then", « thenFinally, catchFinally »)。

27.5.5.4 Promise.prototype.then ( onFulfilled, onRejected )

调用时,此方法执行以下步骤:

  1. 令 promise 为 this value。
  2. 如果 IsPromise(promise) 是 false,则抛出 TypeError 异常。
  3. 令 ctor 为 ? SpeciesConstructor(promise, %Promise%)。
  4. 令 resultCapability 为 ? NewPromiseCapability(ctor)。
  5. 返回 PerformPromiseThen(promise, onFulfilled, onRejected, resultCapability)。

27.5.5.4.1 PerformPromiseThen ( promise, onFulfilled, onRejected [ , resultCapability ] )

抽象操作 PerformPromiseThen,接收参数 promise (Promise)、onFulfilled (ECMAScript 语言值) 和 onRejected (ECMAScript 语言值)和可选参数 resultCapability (PromiseCapability 记录);返回值:(Object 或 undefined)。 它使用 onFulfilled 和 onRejected 作为敲定操作,对 promise 执行“then”操作。如果传入 resultCapability,则通过更新 resultCapability 的 promise 来存储结果。如果未传入,则 PerformPromiseThen 是由规范内部操作调用,其结果并不重要。 调用时执行以下步骤:

  1. 断言:IsPromise(promise) 是 true。
  2. 如果不存在 resultCapability,则
    1. 将 resultCapability 设置为 undefined。
  3. 如果 IsCallable(onFulfilled) 是 false,则
    1. 令 onFulfilledJobCallback 为 empty。
  4. 否则,
    1. 令 onFulfilledJobCallback 为 HostMakeJobCallback(onFulfilled)。
  5. 如果 IsCallable(onRejected) 是 false,则
    1. 令 onRejectedJobCallback 为 empty。
  6. 否则,
    1. 令 onRejectedJobCallback 为 HostMakeJobCallback(onRejected)。
  7. 令 fulfillReaction 为 PromiseReaction Record { [[Capability]]: resultCapability, [[Type]]: fulfill, [[Handler]]: onFulfilledJobCallback }。
  8. 令 rejectReaction 为 PromiseReaction Record { [[Capability]]: resultCapability, [[Type]]: reject, [[Handler]]: onRejectedJobCallback }。
  9. 如果 promise.[[PromiseState]] 是 pending,则
    1. 将 fulfillReaction 追加到 promise.[[PromiseFulfillReactions]]。
    2. 将 rejectReaction 追加到 promise.[[PromiseRejectReactions]]。
  10. 否则如果 promise.[[PromiseState]] 是 fulfilled,则
    1. 令 value 为 promise.[[PromiseResult]]。
    2. 令 fulfillJob 为 NewPromiseReactionJob(fulfillReaction, value)。
    3. 执行 HostEnqueuePromiseJob(fulfillJob.[[Job]], fulfillJob.[[Realm]])。
  11. 否则,
    1. 断言:promise.[[PromiseState]] 是 rejected。
    2. 令 reason 为 promise.[[PromiseResult]]。
    3. 如果 promise.[[PromiseIsHandled]] 是 false,则执行 HostPromiseRejectionTracker(promise, "handle")。
    4. 令 rejectJob 为 NewPromiseReactionJob(rejectReaction, reason)。
    5. 执行 HostEnqueuePromiseJob(rejectJob.[[Job]], rejectJob.[[Realm]])。
  12. 将 promise.[[PromiseIsHandled]] 设置为 true。
  13. 如果 resultCapability 是 undefined,则返回 undefined。
  14. 返回 resultCapability.[[Promise]]。

27.5.5.5 Promise.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "Promise"。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

27.5.6 Promise 实例的属性

Promise 实例是从 Promise 原型对象(固有对象 %Promise.prototype%)继承属性的普通对象。Promise 实例最初创建时具有 表 93 中描述的内部槽。

表 93: Promise 实例的内部槽
内部槽 类型 描述
[[PromiseState]] pending, fulfilled, or rejected 控制 promise 如何响应对其 then 方法的调用。
[[PromiseResult]] an ECMAScript language value or empty promise 已兑现或拒绝所使用的值(如果有)。当且仅当 [[PromiseState]] 是 pending 时为 empty。
[[PromiseFulfillReactions]] a List of PromiseReaction Records 当且如果 promise 从 pending 状态转换为 fulfilled 状态时要处理的 Record。
[[PromiseRejectReactions]] a List of PromiseReaction Records 当且如果 promise 从 pending 状态转换为 rejected 状态时要处理的 Record。
[[PromiseIsHandled]] a Boolean 指示 promise 是否曾经具有兑现或拒绝处理器;用于未处理拒绝跟踪。

27.6 GeneratorFunction 对象

GeneratorFunction 是通常通过对 GeneratorDeclaration、GeneratorExpression 和 GeneratorMethod 求值创建的函数。也可以通过调用 %GeneratorFunction% 固有对象来创建它们。

图 6 (资料性): Generator 对象关系
数量惊人的各种方框和箭头。

27.6.1 GeneratorFunction 构造函数

GeneratorFunction 构造函数:

  • 是 %GeneratorFunction%。
  • 是 Function 的子类。
  • 作为函数而不是构造函数调用时,创建并初始化新的 GeneratorFunction。因此,函数调用 GeneratorFunction (…) 等价于使用相同参数的对象创建表达式 new GeneratorFunction (…)。
  • 可以用作类定义的 extends 子句的值。希望继承指定 GeneratorFunction 行为的子类构造函数必须包含对 GeneratorFunction 构造函数的 super 调用,以创建并初始化具有内置 GeneratorFunction 行为所必需内部槽的子类实例。所有用于定义 generator 函数对象的 ECMAScript 句法形式都会创建 GeneratorFunction 的直接实例。没有句法手段可以创建 GeneratorFunction 子类的实例。

27.6.1.1 GeneratorFunction ( ...paramArgs, bodyArg )

最后一个参数(如果有)指定 generator 函数的主体(可执行代码);任何前面的参数指定形式参数。

调用时,此函数执行以下步骤:

  1. 令 activeFunc 为活动函数对象。
  2. 如果不存在 bodyArg,则将 bodyArg 设置为空 String。
  3. 返回 ? CreateDynamicFunction(activeFunc, NewTarget, generator, paramArgs, bodyArg)。
注

参见 20.2.1.1 的注。

27.6.2 GeneratorFunction 构造函数的属性

GeneratorFunction 构造函数:

  • 是从 Function 构造函数继承的标准内置函数对象。
  • 具有 [[Prototype]] 内部槽,其值是 %Function%。
  • 具有 "length" 属性,其值是 1𝔽。
  • 具有 "name" 属性,其值是 "GeneratorFunction"。
  • 具有以下属性:

27.6.2.1 GeneratorFunction.prototype

GeneratorFunction.prototype 的初始值是 GeneratorFunction 原型对象。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

27.6.3 GeneratorFunction 原型对象的属性

GeneratorFunction 原型对象:

27.6.3.1 GeneratorFunction.prototype.constructor

GeneratorFunction.prototype.constructor 的初始值是 %GeneratorFunction%。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

27.6.3.2 GeneratorFunction.prototype.prototype

GeneratorFunction.prototype.prototype 的初始值是 %GeneratorPrototype%。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

27.6.3.3 GeneratorFunction.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "GeneratorFunction"。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

27.6.4 GeneratorFunction 实例

每个 GeneratorFunction 实例都是 ECMAScript 函数对象,并具有 表 26 中列出的内部槽。所有此类实例的 [[IsClassConstructor]] 内部槽的值都是 false。

每个 GeneratorFunction 实例都具有以下自有属性:

27.6.4.1 length

20.2.4.1 中给出的 Function 实例的 "length" 属性规范同样适用于 GeneratorFunction 实例。

27.6.4.2 name

20.2.4.2 中给出的 Function 实例的 "name" 属性规范同样适用于 GeneratorFunction 实例。

27.6.4.3 prototype

每当创建 GeneratorFunction 实例时,还会创建另一个普通对象,并将其作为 generator 函数 "prototype" 属性的初始值。当使用 [[Call]] 调用 generator 函数对象时,prototype 属性的值用于初始化新创建 Generator 的 [[Prototype]] 内部槽。

此属性具有特性 { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }。

注

与 Function 实例不同,作为 GeneratorFunction 的 "prototype" 属性值的对象没有一个值为该 GeneratorFunction 实例的 "constructor" 属性。

27.7 AsyncGeneratorFunction 对象

AsyncGeneratorFunction 是通常通过对 AsyncGeneratorDeclaration、AsyncGeneratorExpression 和 AsyncGeneratorMethod 句法产生式求值创建的函数。也可以通过调用 %AsyncGeneratorFunction% 固有对象来创建它们。

27.7.1 AsyncGeneratorFunction 构造函数

AsyncGeneratorFunction 构造函数:

  • 是 %AsyncGeneratorFunction%。
  • 是 Function 的子类。
  • 作为函数而不是构造函数调用时,创建并初始化新的 AsyncGeneratorFunction。因此,函数调用 AsyncGeneratorFunction (...) 等价于使用相同参数的对象创建表达式 new AsyncGeneratorFunction (...)。
  • 可以用作类定义的 extends 子句的值。希望继承指定 AsyncGeneratorFunction 行为的子类构造函数必须包含对 AsyncGeneratorFunction 构造函数的 super 调用,以创建并初始化具有内置 AsyncGeneratorFunction 行为所必需内部槽的子类实例。所有用于定义 async generator 函数对象的 ECMAScript 句法形式都会创建 AsyncGeneratorFunction 的直接实例。没有句法手段可以创建 AsyncGeneratorFunction 子类的实例。

27.7.1.1 AsyncGeneratorFunction ( ...paramArgs, bodyArg )

最后一个参数(如果有)指定 async generator 函数的主体(可执行代码);任何前面的参数指定形式参数。

调用时,此函数执行以下步骤:

  1. 令 activeFunc 为活动函数对象。
  2. 如果不存在 bodyArg,则将 bodyArg 设置为空 String。
  3. 返回 ? CreateDynamicFunction(activeFunc, NewTarget, async-generator, paramArgs, bodyArg)。
注

参见 20.2.1.1 的注。

27.7.2 AsyncGeneratorFunction 构造函数的属性

AsyncGeneratorFunction 构造函数:

  • 是从 Function 构造函数继承的标准内置函数对象。
  • 具有 [[Prototype]] 内部槽,其值是 %Function%。
  • 具有 "length" 属性,其值是 1𝔽。
  • 具有 "name" 属性,其值是 "AsyncGeneratorFunction"。
  • 具有以下属性:

27.7.2.1 AsyncGeneratorFunction.prototype

AsyncGeneratorFunction.prototype 的初始值是 AsyncGeneratorFunction 原型对象。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

27.7.3 AsyncGeneratorFunction 原型对象的属性

AsyncGeneratorFunction 原型对象:

27.7.3.1 AsyncGeneratorFunction.prototype.constructor

AsyncGeneratorFunction.prototype.constructor 的初始值是 %AsyncGeneratorFunction%。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

27.7.3.2 AsyncGeneratorFunction.prototype.prototype

AsyncGeneratorFunction.prototype.prototype 的初始值是 %AsyncGeneratorPrototype%。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

27.7.3.3 AsyncGeneratorFunction.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "AsyncGeneratorFunction"。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

27.7.4 AsyncGeneratorFunction 实例

每个 AsyncGeneratorFunction 实例都是 ECMAScript 函数对象,并具有 表 26 中列出的内部槽。所有此类实例的 [[IsClassConstructor]] 内部槽的值都是 false。

每个 AsyncGeneratorFunction 实例都具有以下自有属性:

27.7.4.1 length

"length" 属性的值是整数 Number,表示 AsyncGeneratorFunction 通常预期的参数数量。不过,语言允许使用其他数量的参数调用该函数。当使用与其 "length" 属性指定数量不同的参数数量调用 AsyncGeneratorFunction 时,其行为取决于该函数。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

27.7.4.2 name

20.2.4.2 中给出的 Function 实例的 "name" 属性规范同样适用于 AsyncGeneratorFunction 实例。

27.7.4.3 prototype

每当创建 AsyncGeneratorFunction 实例时,还会创建另一个普通对象,并将其作为 async generator 函数 "prototype" 属性的初始值。当使用 [[Call]] 调用 generator 函数对象时,prototype 属性的值用于初始化新创建 AsyncGenerator 的 [[Prototype]] 内部槽。

此属性具有特性 { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }。

注

与函数实例不同,作为 AsyncGeneratorFunction 的 "prototype" 属性值的对象没有一个值为该 AsyncGeneratorFunction 实例的 "constructor" 属性。

27.8 Generator 对象

Generator 通过调用 generator 函数创建,并且同时符合 iterator 接口和 iterable 接口。

Generator 实例直接从创建该实例的 generator 函数的 "prototype" 属性初始值继承属性。Generator 实例间接从 %GeneratorPrototype% 继承属性。

27.8.1 %GeneratorPrototype% 对象

%GeneratorPrototype% 对象:

  • 是 %GeneratorFunction.prototype.prototype%。
  • 是普通对象。
  • 不是 Generator 实例,并且不具有 [[GeneratorState]] 内部槽。
  • 具有 [[Prototype]] 内部槽,其值是 %Iterator.prototype%。
  • 具有由所有 Generator 实例间接继承的属性。

27.8.1.1 %GeneratorPrototype%.constructor

%GeneratorPrototype%.constructor 的初始值是 %GeneratorFunction.prototype%。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

27.8.1.2 %GeneratorPrototype%.next ( value )

  1. 返回 ? GeneratorResume(this value, value, empty)。

27.8.1.3 %GeneratorPrototype%.return ( value )

调用时,此方法执行以下步骤:

  1. 令 gen 为 this value。
  2. 令 completion 为 ReturnCompletion(value)。
  3. 返回 ? GeneratorResumeAbrupt(gen, completion, empty)。

27.8.1.4 %GeneratorPrototype%.throw ( exception )

调用时,此方法执行以下步骤:

  1. 令 gen 为 this value。
  2. 令 completion 为 ThrowCompletion(exception)。
  3. 返回 ? GeneratorResumeAbrupt(gen, completion, empty)。

27.8.1.5 %GeneratorPrototype% [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "Generator"。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

27.8.2 Generator 实例的属性

Generator 实例最初创建时具有 表 94 中描述的内部槽。

表 94: Generator 实例的内部槽
内部槽 类型 描述
[[GeneratorState]] suspended-start, suspended-yield, executing, or completed generator 的当前执行状态。
[[GeneratorContext]] an execution context 执行此 generator 的代码时使用的执行上下文。
[[GeneratorBrand]] a String or empty 用于区分不同种类 generator 的品牌。由 ECMAScript 源文本声明的 generator 的 [[GeneratorBrand]] 始终是 empty。

27.8.3 Generator 抽象操作

27.8.3.1 GeneratorStart ( gen, genBody )

抽象操作 GeneratorStart,接收参数 gen (Generator) 和 genBody ((a FunctionBody Parse Node 或 无参数的抽象闭包));返回值:unused。 调用时执行以下步骤:

  1. 断言:gen.[[GeneratorState]] 是 suspended-start。
  2. 令 genContext 为正在运行的执行上下文。
  3. 将 genContext 的 Generator 组件设置为 gen。
  4. 令 closure 为不带参数的新 Abstract Closure,它捕获 genBody,并在被调用时执行以下步骤:
    1. 令 acGenContext 为正在运行的执行上下文。
    2. 令 acGen 为 acGenContext 的 Generator 组件。
    3. 如果 genBody 是 Parse Node,则
      1. 令 result 为 Completion(Evaluation of genBody)。
    4. 否则,
      1. 断言:genBody 是不带参数的 Abstract Closure。
      2. 令 result 为 Completion(genBody())。
    5. 断言:如果在此返回,则 generator 要么抛出了异常,要么执行了隐式或显式 return。
    6. 从执行上下文栈中移除 acGenContext,并恢复执行上下文栈顶部的执行上下文作为正在运行的执行上下文。
    7. 将 acGen.[[GeneratorState]] 设置为 completed。
    8. 注:一旦 generator 进入 completed 状态,它就永远不会离开该状态,并且其关联的执行上下文永远不会恢复。此时可以丢弃与 acGen 关联的任何执行状态。
    9. 如果 result 是抛出完成,则
      1. 令 resumption 为 result。
    10. 否则,
      1. 如果 result 是正常完成,则
        1. 令 resultValue 为 undefined。
      2. 否则如果 result 是返回完成,则
        1. 令 resultValue 为 result.[[Value]]。
      3. 令 resumption 为 NormalCompletion(CreateIteratorResultObject(resultValue, true))。
    11. 令 callerContext 为正在运行的执行上下文。
    12. 恢复 callerContext,传入 resumption。
    13. 断言:永远不会到达此步骤。
  5. 设置 genContext 的代码求值状态,使得当该执行上下文恢复求值时,将无参数调用 closure。
  6. 将 gen.[[GeneratorContext]] 设置为 genContext。
  7. 返回 unused。

27.8.3.2 GeneratorValidate ( gen, genBrand )

抽象操作 GeneratorValidate,接收参数 gen (ECMAScript 语言值) 和 genBrand ((String 或 empty));返回值:(正常完成 (值:(suspended-start、suspended-yield 或 completed)) 或 抛出完成)。 调用时执行以下步骤:

  1. 执行 ? RequireInternalSlot(gen, [[GeneratorState]])。
  2. 执行 ? RequireInternalSlot(gen, [[GeneratorBrand]])。
  3. 如果 gen.[[GeneratorBrand]] 不是 genBrand,则抛出 TypeError 异常。
  4. 断言:gen 具有 [[GeneratorContext]] 内部槽。
  5. 令 state 为 gen.[[GeneratorState]]。
  6. 如果 state 是 executing,则抛出 TypeError 异常。
  7. 返回 state。

27.8.3.3 GeneratorResume ( gen, value, genBrand )

抽象操作 GeneratorResume,接收参数 gen (ECMAScript 语言值)、value ((ECMAScript 语言值 或 empty)) 和 genBrand ((String 或 empty));返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 state 为 ? GeneratorValidate(gen, genBrand)。
  2. 如果 state 是 completed,则返回 CreateIteratorResultObject(undefined, true)。
  3. 断言:state 是 suspended-start 或 suspended-yield。
  4. 令 genContext 为 gen.[[GeneratorContext]]。
  5. 将 gen.[[GeneratorState]] 设置为 executing。
  6. 返回 ? RunSuspendedContext(genContext, NormalCompletion(value))。

27.8.3.4 GeneratorResumeAbrupt ( gen, abruptCompletion, genBrand )

抽象操作 GeneratorResumeAbrupt,接收参数 gen (ECMAScript 语言值)、abruptCompletion ((返回完成 或 抛出完成)) 和 genBrand ((String 或 empty));返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 state 为 ? GeneratorValidate(gen, genBrand)。
  2. 如果 state 是 suspended-start,则
    1. 将 gen.[[GeneratorState]] 设置为 completed。
    2. 注:一旦 generator 进入 completed 状态,它就永远不会离开该状态,并且其关联的执行上下文永远不会恢复。此时可以丢弃与 gen 关联的任何执行状态。
    3. 将 state 设置为 completed。
  3. 如果 state 是 completed,则
    1. 如果 abruptCompletion 是返回完成,则
      1. 返回 CreateIteratorResultObject(abruptCompletion.[[Value]], true)。
    2. 返回 ? abruptCompletion。
  4. 断言:state 是 suspended-yield。
  5. 令 genContext 为 gen.[[GeneratorContext]]。
  6. 将 gen.[[GeneratorState]] 设置为 executing。
  7. 返回 ? RunSuspendedContext(genContext, abruptCompletion)。

27.8.3.5 GetGeneratorKind ( )

抽象操作 GetGeneratorKind,接收无参数;返回值:(non-generator、sync 或 async)。 调用时执行以下步骤:

  1. 令 genContext 为正在运行的执行上下文。
  2. 如果 genContext 不具有 Generator 组件,则返回 non-generator。
  3. 令 gen 为 genContext 的 Generator 组件。
  4. 如果 gen 具有 [[AsyncGeneratorState]] 内部槽,则返回 async。
  5. 返回 sync。

27.8.3.6 GeneratorYield ( iteratorResult )

抽象操作 GeneratorYield,接收参数 iteratorResult (an Object that conforms to the IteratorResult interface);返回值:(正常完成 (值:ECMAScript 语言值) 或 突兀完成)。 调用时执行以下步骤:

  1. 令 genContext 为正在运行的执行上下文。
  2. 断言:genContext 是 generator 的执行上下文。
  3. 令 gen 为 genContext 的 Generator 组件的值。
  4. 断言:GetGeneratorKind() 是 sync。
  5. 将 gen.[[GeneratorState]] 设置为 suspended-yield。
  6. 返回 ? RunCallerContext(iteratorResult)。

27.8.3.7 Yield ( arg )

抽象操作 Yield,接收参数 arg (ECMAScript 语言值);返回值:(正常完成 (值:ECMAScript 语言值) 或 突兀完成)。 调用时执行以下步骤:

  1. 令 genKind 为 GetGeneratorKind()。
  2. 如果 genKind 是 async,则返回 ? AsyncGeneratorYield(? Await(arg))。
  3. 返回 ? GeneratorYield(CreateIteratorResultObject(arg, false))。

27.8.3.8 CreateIteratorFromClosure ( closure, genBrand, genProto [ , extraSlots ] )

抽象操作 CreateIteratorFromClosure,接收参数 closure (无参数的抽象闭包)、genBrand ((String 或 empty)) 和 genProto (Object)和可选参数 extraSlots (列表 (元素:内部槽名称));返回值:Generator。 调用时执行以下步骤:

  1. 注:closure 可以包含对 Yield 操作的使用,以生成 IteratorResult 对象。
  2. 如果不存在 extraSlots,则将 extraSlots 设置为新的空 List。
  3. 令 internalSlotsList 为 extraSlots 和 « [[GeneratorState]], [[GeneratorContext]], [[GeneratorBrand]] » 的列表连接。
  4. 令 gen 为 OrdinaryObjectCreate(genProto, internalSlotsList)。
  5. 将 gen.[[GeneratorBrand]] 设置为 genBrand。
  6. 将 gen.[[GeneratorState]] 设置为 suspended-start。
  7. 令 callerContext 为正在运行的执行上下文。
  8. 令 calleeContext 为新的执行上下文。
  9. 将 calleeContext 的 Function 设置为 null。
  10. 将 calleeContext 的 Realm 设置为当前 Realm Record。
  11. 将 calleeContext 的 ScriptOrModule 设置为 callerContext 的 ScriptOrModule。
  12. 如果 callerContext 尚未挂起,则挂起 callerContext。
  13. 将 calleeContext 压入执行上下文栈;calleeContext 现在是正在运行的执行上下文。
  14. 执行 GeneratorStart(gen, closure)。
  15. 从执行上下文栈中移除 calleeContext,并恢复 callerContext 作为正在运行的执行上下文。
  16. 返回 gen。

27.9 AsyncGenerator 对象

AsyncGenerator 通过调用 async generator 函数创建,并且同时符合 async iterator 接口和 async iterable 接口。

AsyncGenerator 实例直接从创建该实例的 async generator 函数的 "prototype" 属性初始值继承属性。AsyncGenerator 实例间接从 %AsyncGeneratorPrototype% 继承属性。

27.9.1 %AsyncGeneratorPrototype% 对象

%AsyncGeneratorPrototype% 对象:

  • 是 %AsyncGeneratorFunction.prototype.prototype%。
  • 是普通对象。
  • 不是 AsyncGenerator 实例,并且不具有 [[AsyncGeneratorState]] 内部槽。
  • 具有 [[Prototype]] 内部槽,其值是 %AsyncIteratorPrototype%。
  • 具有由所有 AsyncGenerator 实例间接继承的属性。

27.9.1.1 %AsyncGeneratorPrototype%.constructor

%AsyncGeneratorPrototype%.constructor 的初始值是 %AsyncGeneratorFunction.prototype%。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

27.9.1.2 %AsyncGeneratorPrototype%.next ( value )

  1. 令 gen 为 this value。
  2. 令 promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  3. 令 result 为 Completion(AsyncGeneratorValidate(gen, empty))。
  4. IfAbruptRejectPromise(result, promiseCapability)。
  5. 令 state 为 gen.[[AsyncGeneratorState]]。
  6. 如果 state 是 completed,则
    1. 令 iteratorResult 为 CreateIteratorResultObject(undefined, true)。
    2. 执行 ! Call(promiseCapability.[[Resolve]], undefined, « iteratorResult »)。
    3. 返回 promiseCapability.[[Promise]]。
  7. 令 completion 为 NormalCompletion(value)。
  8. 执行 AsyncGeneratorEnqueue(gen, completion, promiseCapability)。
  9. 如果 state 是 suspended-start 或 suspended-yield,则
    1. 执行 AsyncGeneratorResume(gen, completion)。
  10. 否则,
    1. 断言:state 是 executing 或 draining-queue。
  11. 返回 promiseCapability.[[Promise]]。

27.9.1.3 %AsyncGeneratorPrototype%.return ( value )

  1. 令 gen 为 this value。
  2. 令 promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  3. 令 result 为 Completion(AsyncGeneratorValidate(gen, empty))。
  4. IfAbruptRejectPromise(result, promiseCapability)。
  5. 令 completion 为 ReturnCompletion(value)。
  6. 执行 AsyncGeneratorEnqueue(gen, completion, promiseCapability)。
  7. 令 state 为 gen.[[AsyncGeneratorState]]。
  8. 如果 state 是 suspended-start 或 completed,则
    1. 将 gen.[[AsyncGeneratorState]] 设置为 draining-queue。
    2. 执行 AsyncGeneratorAwaitReturn(gen)。
  9. 否则如果 state 是 suspended-yield,则
    1. 执行 AsyncGeneratorResume(gen, completion)。
  10. 否则,
    1. 断言:state 是 executing 或 draining-queue。
  11. 返回 promiseCapability.[[Promise]]。

27.9.1.4 %AsyncGeneratorPrototype%.throw ( exception )

  1. 令 gen 为 this value。
  2. 令 promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  3. 令 result 为 Completion(AsyncGeneratorValidate(gen, empty))。
  4. IfAbruptRejectPromise(result, promiseCapability)。
  5. 令 state 为 gen.[[AsyncGeneratorState]]。
  6. 如果 state 是 suspended-start,则
    1. 将 gen.[[AsyncGeneratorState]] 设置为 completed。
    2. 将 state 设置为 completed。
  7. 如果 state 是 completed,则
    1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « exception »)。
    2. 返回 promiseCapability.[[Promise]]。
  8. 令 completion 为 ThrowCompletion(exception)。
  9. 执行 AsyncGeneratorEnqueue(gen, completion, promiseCapability)。
  10. 如果 state 是 suspended-yield,则
    1. 执行 AsyncGeneratorResume(gen, completion)。
  11. 否则,
    1. 断言:state 是 executing 或 draining-queue。
  12. 返回 promiseCapability.[[Promise]]。

27.9.1.5 %AsyncGeneratorPrototype% [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "AsyncGenerator"。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

27.9.2 AsyncGenerator 实例的属性

AsyncGenerator 实例最初创建时具有下述内部槽:

表 95: AsyncGenerator 实例的内部槽
内部槽 类型 描述
[[AsyncGeneratorState]] suspended-start, suspended-yield, executing, draining-queue, or completed async generator 的当前执行状态。
[[AsyncGeneratorContext]] an execution context 执行此 async generator 的代码时使用的执行上下文。
[[AsyncGeneratorQueue]] a List of AsyncGeneratorRequest Records 表示恢复 async generator 请求的 Record。除状态转换期间外,当且仅当 [[AsyncGeneratorState]] 是 executing 或 draining-queue 时,它非空。
[[GeneratorBrand]] a String or empty 用于区分不同种类 async generator 的品牌。由 ECMAScript 源文本声明的 async generator 的 [[GeneratorBrand]] 始终是 empty。

27.9.3 AsyncGenerator 抽象操作

27.9.3.1 AsyncGeneratorRequest Record

AsyncGeneratorRequest 是用于存储有关 async generator 应如何恢复的信息的 Record,并包含用于兑现或拒绝对应 promise 的 capability。

它们具有以下字段:

表 96: AsyncGeneratorRequest Record 字段
字段名称 值 含义
[[Completion]] a Completion Record 应当用于恢复 async generator 的 Completion Record。
[[Capability]] a PromiseCapability Record 与此请求关联的 promise capability。

27.9.3.2 AsyncGeneratorStart ( gen, genBody )

抽象操作 AsyncGeneratorStart,接收参数 gen (AsyncGenerator) 和 genBody ((a FunctionBody Parse Node 或 无参数的抽象闭包));返回值:unused。 调用时执行以下步骤:

  1. 断言:gen.[[AsyncGeneratorState]] 是 suspended-start。
  2. 令 genContext 为正在运行的执行上下文。
  3. 将 genContext 的 Generator 组件设置为 gen。
  4. 令 closure 为不带参数的新 Abstract Closure,它捕获 genBody,并在被调用时执行以下步骤:
    1. 令 acGenContext 为正在运行的执行上下文。
    2. 令 acGen 为 acGenContext 的 Generator 组件。
    3. 如果 genBody 是 Parse Node,则
      1. 令 result 为 Completion(Evaluation of genBody)。
    4. 否则,
      1. 断言:genBody 是不带参数的 Abstract Closure。
      2. 令 result 为 Completion(genBody())。
    5. 断言:如果在此返回,则 async generator 要么抛出了异常,要么执行了隐式或显式 return。
    6. 从执行上下文栈中移除 acGenContext,并恢复执行上下文栈顶部的执行上下文作为正在运行的执行上下文。
    7. 将 acGen.[[AsyncGeneratorState]] 设置为 draining-queue。
    8. 如果 result 是正常完成,则将 result 设置为 NormalCompletion(undefined)。
    9. 如果 result 是返回完成,则将 result 设置为 NormalCompletion(result.[[Value]])。
    10. 执行 AsyncGeneratorCompleteStep(acGen, result, true)。
    11. 执行 AsyncGeneratorDrainQueue(acGen)。
    12. 令 callerContext 为正在运行的执行上下文。
    13. 恢复 callerContext,传入 NormalCompletion(undefined)。
    14. 断言:永远不会到达此步骤。
  5. 设置 genContext 的代码求值状态,使得当该执行上下文恢复求值时,将无参数调用 closure。
  6. 将 gen.[[AsyncGeneratorContext]] 设置为 genContext。
  7. 将 gen.[[AsyncGeneratorQueue]] 设置为新的空 List。
  8. 返回 unused。

27.9.3.3 AsyncGeneratorValidate ( gen, genBrand )

抽象操作 AsyncGeneratorValidate,接收参数 gen (ECMAScript 语言值) 和 genBrand ((String 或 empty));返回值:(正常完成 (值:unused) 或 抛出完成)。 调用时执行以下步骤:

  1. 执行 ? RequireInternalSlot(gen, [[AsyncGeneratorContext]])。
  2. 执行 ? RequireInternalSlot(gen, [[AsyncGeneratorState]])。
  3. 执行 ? RequireInternalSlot(gen, [[AsyncGeneratorQueue]])。
  4. 如果 gen.[[GeneratorBrand]] 不是 genBrand,则抛出 TypeError 异常。
  5. 返回 unused。

27.9.3.4 AsyncGeneratorEnqueue ( gen, completion, promiseCapability )

抽象操作 AsyncGeneratorEnqueue,接收参数 gen (AsyncGenerator)、completion (完成记录) 和 promiseCapability (PromiseCapability 记录);返回值:unused。 调用时执行以下步骤:

  1. 令 request 为 AsyncGeneratorRequest { [[Completion]]: completion, [[Capability]]: promiseCapability }。
  2. 将 request 追加到 gen.[[AsyncGeneratorQueue]]。
  3. 返回 unused。

27.9.3.5 AsyncGeneratorCompleteStep ( gen, completion, done [ , realm ] )

抽象操作 AsyncGeneratorCompleteStep,接收参数 gen (AsyncGenerator)、completion (完成记录) 和 done (Boolean)和可选参数 realm (Realm 记录);返回值:unused。 调用时执行以下步骤:

  1. 断言:gen.[[AsyncGeneratorQueue]] 非空。
  2. 令 next 为 gen.[[AsyncGeneratorQueue]] 的第一个元素。
  3. 从 gen.[[AsyncGeneratorQueue]] 中移除第一个元素。
  4. 令 promiseCapability 为 next.[[Capability]]。
  5. 令 value 为 completion.[[Value]]。
  6. 如果 completion 是抛出完成,则
    1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « value »)。
  7. 否则,
    1. 断言:completion 是正常完成。
    2. 如果存在 realm,则
      1. 令 oldRealm 为正在运行的执行上下文的 Realm。
      2. 将正在运行的执行上下文的 Realm 设置为 realm。
      3. 令 iteratorResult 为 CreateIteratorResultObject(value, done)。
      4. 将正在运行的执行上下文的 Realm 设置为 oldRealm。
    3. 否则,
      1. 令 iteratorResult 为 CreateIteratorResultObject(value, done)。
    4. 执行 ! Call(promiseCapability.[[Resolve]], undefined, « iteratorResult »)。
  8. 返回 unused。

27.9.3.6 AsyncGeneratorResume ( gen, completion )

抽象操作 AsyncGeneratorResume,接收参数 gen (AsyncGenerator) 和 completion (完成记录);返回值:unused。 调用时执行以下步骤:

  1. 断言:gen.[[AsyncGeneratorState]] 是 suspended-start 或 suspended-yield。
  2. 令 genContext 为 gen.[[AsyncGeneratorContext]]。
  3. 将 gen.[[AsyncGeneratorState]] 设置为 executing。
  4. 执行 ! RunSuspendedContext(genContext, completion)。
  5. 返回 unused。

27.9.3.7 AsyncGeneratorUnwrapYieldResumption ( resumptionValue )

抽象操作 AsyncGeneratorUnwrapYieldResumption,接收参数 resumptionValue (完成记录);返回值:(正常完成 (值:ECMAScript 语言值) 或 突兀完成)。 调用时执行以下步骤:

  1. 如果 resumptionValue 不是返回完成,则返回 ? resumptionValue。
  2. 令 awaited 为 Completion(Await(resumptionValue.[[Value]]))。
  3. 如果 awaited 是抛出完成,则返回 ? awaited。
  4. 断言:awaited 是正常完成。
  5. 返回 ReturnCompletion(awaited.[[Value]])。

27.9.3.8 AsyncGeneratorYield ( arg )

抽象操作 AsyncGeneratorYield,接收参数 arg (ECMAScript 语言值);返回值:(正常完成 (值:ECMAScript 语言值) 或 突兀完成)。 调用时执行以下步骤:

  1. 令 genContext 为正在运行的执行上下文。
  2. 断言:genContext 是 generator 的执行上下文。
  3. 令 gen 为 genContext 的 Generator 组件的值。
  4. 断言:GetGeneratorKind() 是 async。
  5. 令 completion 为 NormalCompletion(arg)。
  6. 断言:执行上下文栈至少有两个元素。
  7. 令 previousContext 为执行上下文栈中倒数第二个元素。
  8. 令 previousRealm 为 previousContext 的 Realm。
  9. 执行 AsyncGeneratorCompleteStep(gen, completion, false, previousRealm)。
  10. 令 queue 为 gen.[[AsyncGeneratorQueue]]。
  11. 如果 queue 非空,则
    1. 注:继续执行而不挂起 generator。
    2. 令 toYield 为 queue 的第一个元素。
    3. 令 resumptionValue 为 Completion(toYield.[[Completion]])。
    4. 返回 ? AsyncGeneratorUnwrapYieldResumption(resumptionValue)。
  12. 将 gen.[[AsyncGeneratorState]] 设置为 suspended-yield。
  13. 令 resumptionValue 为 Completion(RunCallerContext(undefined))。
  14. 返回 ? AsyncGeneratorUnwrapYieldResumption(resumptionValue)。

27.9.3.9 AsyncGeneratorAwaitReturn ( gen )

抽象操作 AsyncGeneratorAwaitReturn,接收参数 gen (AsyncGenerator);返回值:unused。 调用时执行以下步骤:

  1. 断言:gen.[[AsyncGeneratorState]] 是 draining-queue。
  2. 令 queue 为 gen.[[AsyncGeneratorQueue]]。
  3. 断言:queue 非空。
  4. 令 next 为 queue 的第一个元素。
  5. 令 completion 为 Completion(next.[[Completion]])。
  6. 断言:completion 是返回完成。
  7. 令 promiseCompletion 为 Completion(PromiseResolve(%Promise%, completion.[[Value]]))。
  8. 如果 promiseCompletion 是突然完成,则
    1. 执行 AsyncGeneratorCompleteStep(gen, promiseCompletion, true)。
    2. 执行 AsyncGeneratorDrainQueue(gen)。
    3. 返回 unused。
  9. 断言:promiseCompletion 是正常完成。
  10. 令 promise 为 promiseCompletion.[[Value]]。
  11. 令 fulfilledClosure 为参数为 (value) 的新 Abstract Closure,它捕获 gen,并在被调用时执行以下步骤:
    1. 断言:gen.[[AsyncGeneratorState]] 是 draining-queue。
    2. 令 result 为 NormalCompletion(value)。
    3. 执行 AsyncGeneratorCompleteStep(gen, result, true)。
    4. 执行 AsyncGeneratorDrainQueue(gen)。
    5. 返回 NormalCompletion(undefined)。
  12. 令 onFulfilled 为 CreateBuiltinFunction(fulfilledClosure, 1, "", « »)。
  13. 令 rejectedClosure 为参数为 (reason) 的新 Abstract Closure,它捕获 gen,并在被调用时执行以下步骤:
    1. 断言:gen.[[AsyncGeneratorState]] 是 draining-queue。
    2. 令 result 为 ThrowCompletion(reason)。
    3. 执行 AsyncGeneratorCompleteStep(gen, result, true)。
    4. 执行 AsyncGeneratorDrainQueue(gen)。
    5. 返回 NormalCompletion(undefined)。
  14. 令 onRejected 为 CreateBuiltinFunction(rejectedClosure, 1, "", « »)。
  15. 执行 PerformPromiseThen(promise, onFulfilled, onRejected)。
  16. 返回 unused。

27.9.3.10 AsyncGeneratorDrainQueue ( gen )

抽象操作 AsyncGeneratorDrainQueue,接收参数 gen (AsyncGenerator);返回值:unused。 它会排空 generator 的 AsyncGeneratorQueue,直到遇到一个持有返回完成的 AsyncGeneratorRequest。 调用时执行以下步骤:

  1. 断言:gen.[[AsyncGeneratorState]] 是 draining-queue。
  2. 令 queue 为 gen.[[AsyncGeneratorQueue]]。
  3. 当 queue 非空时,重复执行,
    1. 令 next 为 queue 的第一个元素。
    2. 令 completion 为 Completion(next.[[Completion]])。
    3. 如果 completion 是返回完成,则
      1. 执行 AsyncGeneratorAwaitReturn(gen)。
      2. 返回 unused。
    4. 如果 completion 是正常完成,则
      1. 将 completion 设置为 NormalCompletion(undefined)。
    5. 执行 AsyncGeneratorCompleteStep(gen, completion, true)。
  4. 将 gen.[[AsyncGeneratorState]] 设置为 completed。
  5. 返回 unused。

27.10 AsyncFunction 对象

AsyncFunction 是通常通过对 AsyncFunctionDeclaration、AsyncFunctionExpression、AsyncMethod 和 AsyncArrowFunction 求值创建的函数。也可以通过调用 %AsyncFunction% 固有对象来创建它们。

27.10.1 AsyncFunction 构造函数

AsyncFunction 构造函数:

  • 是 %AsyncFunction%。
  • 是 Function 的子类。
  • 作为函数而不是构造函数调用时,创建并初始化新的 AsyncFunction。因此,函数调用 AsyncFunction(…) 等价于使用相同参数的对象创建表达式 new AsyncFunction(…)。
  • 可以用作类定义的 extends 子句的值。希望继承指定 AsyncFunction 行为的子类构造函数必须包含对 AsyncFunction 构造函数的 super 调用,以创建并初始化具有内置 async 函数行为所必需内部槽的子类实例。所有用于定义 async 函数对象的 ECMAScript 句法形式都会创建 AsyncFunction 的直接实例。没有句法手段可以创建 AsyncFunction 子类的实例。

27.10.1.1 AsyncFunction ( ...paramArgs, bodyArg )

最后一个参数(如果有)指定 async 函数的主体(可执行代码)。任何前面的参数指定形式参数。

调用时,此函数执行以下步骤:

  1. 令 activeFunc 为活动函数对象。
  2. 如果不存在 bodyArg,则将 bodyArg 设置为空 String。
  3. 返回 ? CreateDynamicFunction(activeFunc, NewTarget, async, paramArgs, bodyArg)。
注
参见 20.2.1.1 的注。

27.10.2 AsyncFunction 构造函数的属性

AsyncFunction 构造函数:

  • 是从 Function 构造函数继承的标准内置函数对象。
  • 具有 [[Prototype]] 内部槽,其值是 %Function%。
  • 具有 "length" 属性,其值是 1𝔽。
  • 具有 "name" 属性,其值是 "AsyncFunction"。
  • 具有以下属性:

27.10.2.1 AsyncFunction.prototype

AsyncFunction.prototype 的初始值是 AsyncFunction 原型对象。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

27.10.3 AsyncFunction 原型对象的属性

AsyncFunction 原型对象:

27.10.3.1 AsyncFunction.prototype.constructor

AsyncFunction.prototype.constructor 的初始值是 %AsyncFunction%。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

27.10.3.2 AsyncFunction.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "AsyncFunction"。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

27.10.4 AsyncFunction 实例

每个 AsyncFunction 实例都是 ECMAScript 函数对象,并具有 表 26 中列出的内部槽。所有此类实例的 [[IsClassConstructor]] 内部槽的值都是 false。AsyncFunction 实例不是构造函数,也不具有 [[Construct]] 内部方法。由于 AsyncFunction 实例不可构造,因此它们没有 prototype 属性。

每个 AsyncFunction 实例都具有以下自有属性:

27.10.4.1 length

20.2.4.1 中给出的 Function 实例的 "length" 属性规范同样适用于 AsyncFunction 实例。

27.10.4.2 name

20.2.4.2 中给出的 Function 实例的 "name" 属性规范同样适用于 AsyncFunction 实例。

27.10.5 Async Function 抽象操作

27.10.5.1 AsyncFunctionStart ( promiseCapability, asyncFuncBody )

抽象操作 AsyncFunctionStart,接收参数 promiseCapability (PromiseCapability 记录) 和 asyncFuncBody ((a FunctionBody Parse Node、an ExpressionBody Parse Node 或 无参数的抽象闭包));返回值:unused。 调用时执行以下步骤:

  1. 令 runningContext 为正在运行的执行上下文。
  2. 令 asyncContext 为 runningContext 的副本。
  3. 注:为了使 AsyncBlockStart 能够恢复其执行,需要复制执行状态。恢复当前正在执行的上下文是没有明确定义的。
  4. 执行 AsyncBlockStart(promiseCapability, asyncFuncBody, asyncContext)。
  5. 返回 unused。

27.10.5.2 AsyncBlockStart ( promiseCapability, asyncBody, asyncContext )

抽象操作 AsyncBlockStart,接收参数 promiseCapability (PromiseCapability 记录)、asyncBody ((解析节点 或 无参数的抽象闭包)) 和 asyncContext (执行上下文);返回值:unused。 调用时执行以下步骤:

  1. 令 closure 为不带参数的新 Abstract Closure,它捕获 promiseCapability 和 asyncBody,并在被调用时执行以下步骤:
    1. 令 acAsyncContext 为正在运行的执行上下文。
    2. 如果 asyncBody 是 Parse Node,则
      1. 令 result 为 Completion(Evaluation of asyncBody)。
    3. 否则,
      1. 断言:asyncBody 是不带参数的 Abstract Closure。
      2. 令 result 为 Completion(asyncBody())。
    4. 断言:如果在此返回,则 async 函数要么抛出了异常,要么执行了隐式或显式 return;所有 await 都已完成。
    5. 从执行上下文栈中移除 acAsyncContext,并恢复执行上下文栈顶部的执行上下文作为正在运行的执行上下文。
    6. 如果 result 是正常完成,则
      1. 执行 ! Call(promiseCapability.[[Resolve]], undefined, « undefined »)。
    7. 否则如果 result 是返回完成,则
      1. 执行 ! Call(promiseCapability.[[Resolve]], undefined, « result.[[Value]] »)。
    8. 否则,
      1. 断言:result 是抛出完成。
      2. 执行 ! Call(promiseCapability.[[Reject]], undefined, « result.[[Value]] »)。
    9. 令 callerContext 为正在运行的执行上下文。
    10. 恢复 callerContext,传入 NormalCompletion(unused)。
    11. 断言:永远不会到达此步骤。
  2. 设置 asyncContext 的代码求值状态,使得当该执行上下文恢复求值时,将无参数调用 closure。
  3. 令 result 为 ! RunSuspendedContext(asyncContext, NormalCompletion(empty))。
  4. 断言:result 是 unused。
  5. 注:result 值的可能来源是 Await,或者如果 async 函数没有 await 任何内容,则是上面的步骤 1.j。
  6. 返回 unused。

27.10.5.3 Await ( arg )

抽象操作 Await,接收参数 arg (ECMAScript 语言值);返回值:(正常完成 (值:(ECMAScript 语言值 或 empty)) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 asyncContext 为正在运行的执行上下文。
  2. 令 promise 为 ? PromiseResolve(%Promise%, arg)。
  3. 令 fulfilledClosure 为参数为 (value) 的新 Abstract Closure,它捕获 asyncContext,并在被调用时执行以下步骤:
    1. 执行 Completion(RunSuspendedContext(asyncContext, NormalCompletion(value)))。
    2. 注:有意忽略 RunSuspendedContext 返回的 Completion Record。
    3. 返回 NormalCompletion(undefined)。
  4. 令 onFulfilled 为 CreateBuiltinFunction(fulfilledClosure, 1, "", « »)。
  5. 令 rejectedClosure 为参数为 (reason) 的新 Abstract Closure,它捕获 asyncContext,并在被调用时执行以下步骤:
    1. 执行 Completion(RunSuspendedContext(asyncContext, ThrowCompletion(reason)))。
    2. 注:有意忽略 RunSuspendedContext 返回的 Completion Record。
    3. 返回 NormalCompletion(undefined)。
  6. 令 onRejected 为 CreateBuiltinFunction(rejectedClosure, 1, "", « »)。
  7. 执行 PerformPromiseThen(promise, onFulfilled, onRejected)。
  8. 返回 ? RunCallerContext(empty)。

28 反射

28.1 Reflect 对象

Reflect 对象:

28.1.1 Reflect.apply ( target, thisArg, args )

调用时,此函数执行以下步骤:

  1. 如果 IsCallable(target) 是 false,则抛出 TypeError 异常。
  2. 令 argList 为 ? CreateListFromArrayLike(args)。
  3. 执行 PrepareForTailCall()。
  4. 返回 ? Call(target, thisArg, argList)。

28.1.2 Reflect.construct ( target, args [ , newTarget ] )

调用时,此函数执行以下步骤:

  1. 如果 IsConstructor(target) 是 false,则抛出 TypeError 异常。
  2. 如果不存在 newTarget,则将 newTarget 设置为 target。
  3. 否则如果 IsConstructor(newTarget) 是 false,则抛出 TypeError 异常。
  4. 令 argList 为 ? CreateListFromArrayLike(args)。
  5. 返回 ? Construct(target, argList, newTarget)。

28.1.3 Reflect.defineProperty ( target, key, attrs )

调用时,此函数执行以下步骤:

  1. 如果 target 不是 Object,则抛出 TypeError 异常。
  2. 令 propertyKey 为 ? ToPropertyKey(key)。
  3. 令 propertyDesc 为 ? ToPropertyDescriptor(attrs)。
  4. 返回 ? target.[[DefineOwnProperty]](propertyKey, propertyDesc)。

28.1.4 Reflect.deleteProperty ( target, key )

调用时,此函数执行以下步骤:

  1. 如果 target 不是 Object,则抛出 TypeError 异常。
  2. 令 propertyKey 为 ? ToPropertyKey(key)。
  3. 返回 ? target.[[Delete]](propertyKey)。

28.1.5 Reflect.get ( target, key [ , receiver ] )

调用时,此函数执行以下步骤:

  1. 如果 target 不是 Object,则抛出 TypeError 异常。
  2. 令 propertyKey 为 ? ToPropertyKey(key)。
  3. 如果不存在 receiver,则
    1. 将 receiver 设置为 target。
  4. 返回 ? target.[[Get]](propertyKey, receiver)。

28.1.6 Reflect.getOwnPropertyDescriptor ( target, key )

调用时,此函数执行以下步骤:

  1. 如果 target 不是 Object,则抛出 TypeError 异常。
  2. 令 propertyKey 为 ? ToPropertyKey(key)。
  3. 令 propertyDesc 为 ? target.[[GetOwnProperty]](propertyKey)。
  4. 返回 FromPropertyDescriptor(propertyDesc)。

28.1.7 Reflect.getPrototypeOf ( target )

调用时,此函数执行以下步骤:

  1. 如果 target 不是 Object,则抛出 TypeError 异常。
  2. 返回 ? target.[[GetPrototypeOf]]()。

28.1.8 Reflect.has ( target, key )

调用时,此函数执行以下步骤:

  1. 如果 target 不是 Object,则抛出 TypeError 异常。
  2. 令 propertyKey 为 ? ToPropertyKey(key)。
  3. 返回 ? target.[[HasProperty]](propertyKey)。

28.1.9 Reflect.isExtensible ( target )

调用时,此函数执行以下步骤:

  1. 如果 target 不是 Object,则抛出 TypeError 异常。
  2. 返回 ? target.[[IsExtensible]]()。

28.1.10 Reflect.ownKeys ( target )

调用时,此函数执行以下步骤:

  1. 如果 target 不是 Object,则抛出 TypeError 异常。
  2. 令 keys 为 ? target.[[OwnPropertyKeys]]()。
  3. 返回 CreateArrayFromList(keys)。

28.1.11 Reflect.preventExtensions ( target )

调用时,此函数执行以下步骤:

  1. 如果 target 不是 Object,则抛出 TypeError 异常。
  2. 返回 ? target.[[PreventExtensions]]()。

28.1.12 Reflect.set ( target, key, value [ , receiver ] )

调用时,此函数执行以下步骤:

  1. 如果 target 不是 Object,则抛出 TypeError 异常。
  2. 令 propertyKey 为 ? ToPropertyKey(key)。
  3. 如果不存在 receiver,则
    1. 将 receiver 设置为 target。
  4. 返回 ? target.[[Set]](propertyKey, value, receiver)。

28.1.13 Reflect.setPrototypeOf ( target, proto )

调用时,此函数执行以下步骤:

  1. 如果 target 不是 Object,则抛出 TypeError 异常。
  2. 如果 proto 不是 Object 且 proto 不是 null,则抛出 TypeError 异常。
  3. 返回 ? target.[[SetPrototypeOf]](proto)。

28.1.14 Reflect [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "Reflect"。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

28.2 Proxy 对象

28.2.1 Proxy 构造函数

Proxy 构造函数:

  • 是 %Proxy%。
  • 是全局对象的 "Proxy" 属性的初始值。
  • 作为构造函数调用时,创建并初始化新的 Proxy 对象。
  • 不旨在作为函数调用,并且以这种方式调用时会抛出异常。

28.2.1.1 Proxy ( target, handler )

调用时,此函数执行以下步骤:

  1. 如果 NewTarget 是 undefined,则抛出 TypeError 异常。
  2. 返回 ? ProxyCreate(target, handler)。

28.2.2 Proxy 构造函数的属性

Proxy 构造函数:

  • 具有 [[Prototype]] 内部槽,其值是 %Function.prototype%。
  • 不具有 "prototype" 属性,因为 Proxy 对象没有需要初始化的 [[Prototype]] 内部槽。
  • 具有以下属性:

28.2.2.1 Proxy.revocable ( target, handler )

此函数创建一个可撤销的 Proxy 对象。

调用时,它执行以下步骤:

  1. 令 proxy 为 ? ProxyCreate(target, handler)。
  2. 令 revokerClosure 为不带参数且不捕获任何内容的新 Abstract Closure,它在被调用时执行以下步骤:
    1. 令 activeFunc 为活动函数对象。
    2. 令 revocableProxy 为 activeFunc.[[RevocableProxy]]。
    3. 如果 revocableProxy 是 null,则返回 NormalCompletion(undefined)。
    4. 将 activeFunc.[[RevocableProxy]] 设置为 null。
    5. 断言:revocableProxy 是 Proxy exotic object。
    6. 将 revocableProxy.[[ProxyTarget]] 设置为 null。
    7. 将 revocableProxy.[[ProxyHandler]] 设置为 null。
    8. 返回 NormalCompletion(undefined)。
  3. 令 revoker 为 CreateBuiltinFunction(revokerClosure, 0, "", « [[RevocableProxy]] »)。
  4. 将 revoker.[[RevocableProxy]] 设置为 proxy。
  5. 令 result 为 OrdinaryObjectCreate(%Object.prototype%)。
  6. 执行 ! CreateDataPropertyOrThrow(result, "proxy", proxy)。
  7. 执行 ! CreateDataPropertyOrThrow(result, "revoke", revoker)。
  8. 返回 result。

28.3 Module Namespace 对象

Module Namespace Object 是一种 module namespace exotic object,它提供基于运行时属性访问模块导出绑定的能力。Module Namespace Object 没有构造函数。相反,对于由包含 NameSpaceImport 的 ImportDeclaration 导入的每个模块,都会创建此类对象。

除了 10.4.6 中规定的属性外,每个 Module Namespace Object 还具有以下自有属性:

28.3.1 %Symbol.toStringTag%

%Symbol.toStringTag% 属性的初始值是 String 值 "Module"。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

29 内存模型

内存一致性模型,或称内存模型,规定了通过访问由 SharedArrayBuffer 支持的 TypedArray 实例以及通过 Atomics 对象上的方法而产生的 Shared Data Block 事件的可能顺序。当程序没有数据竞争(定义见下文)时,事件顺序表现为顺序一致,即各个代理的操作相互交错。当程序存在数据竞争时,共享内存操作可能表现为顺序不一致。例如,程序可能表现出违反因果关系的行为以及其他令人意外的现象。这些现象源自编译器转换和 CPU 的设计(例如乱序执行和推测执行)。内存模型既定义程序表现出顺序一致行为的精确条件,也定义从数据竞争中可能读取到的值。也就是说,不存在未定义行为。

内存模型被定义为对求值期间由 SharedArrayBuffer 上的抽象操作或 Atomics 对象上的方法引入的 Memory 事件施加的关系约束。

注

本节针对由 SharedArrayBuffer 上的抽象操作引入的 Memory 事件提供公理化模型。需要强调的是,与本规范其余部分不同,该模型无法用算法形式表达。抽象操作以非确定性方式引入事件,是 ECMAScript 求值的操作语义与内存模型公理语义之间的接口。这些事件的语义通过考虑一次求值中所有事件组成的图来定义。它们既不是静态语义,也不是运行时语义。这里没有已证明的算法实现,而是一组用于确定某个特定事件图是允许还是不允许的约束。

29.1 内存模型基础

共享内存访问(读取和写入)分为以下定义的两组:原子访问和数据访问。原子访问是顺序一致的,也就是说,代理集群中的所有代理都认同事件存在一个严格全序。非原子访问不存在所有代理都认同的严格全序,也就是说,它们是无序的。

注 1

不支持弱于顺序一致但强于无序的排序方式,例如 release-acquire。

Shared Data Block 事件是 ReadSharedMemory、WriteSharedMemory 或 ReadModifyWriteSharedMemory Record 中的任一种。读取事件是 ReadSharedMemory 或 ReadModifyWriteSharedMemory。写入事件是 WriteSharedMemory 或 ReadModifyWriteSharedMemory。

表 97: ReadSharedMemory 事件字段
字段名称 值 含义
[[Order]] seq-cst or unordered 内存模型为该事件保证的最弱排序。
[[NoTear]] a Boolean 是否允许此事件从与此事件具有相同内存范围的多个写入事件中读取。
[[Block]] a Shared Data Block 事件所操作的数据块。
[[ByteIndex]] a non-negative integer [[Block]] 中读取操作的字节地址。
[[ElementSize]] a non-negative integer 读取操作的大小。
表 98: WriteSharedMemory 事件字段
字段名称 值 含义
[[Order]] seq-cst, unordered, or init 内存模型为该事件保证的最弱排序。
[[NoTear]] a Boolean 是否允许多个与此事件具有相同内存范围的读取事件从该事件中读取。
[[Block]] a Shared Data Block 事件所操作的数据块。
[[ByteIndex]] a non-negative integer [[Block]] 中写入操作的字节地址。
[[ElementSize]] a non-negative integer 写入操作的大小。
[[Payload]] a List of byte values 供其他事件读取的字节值 List。
表 99: ReadModifyWriteSharedMemory 事件字段
字段名称 值 含义
[[Order]] seq-cst 读-修改-写事件始终是顺序一致的。
[[NoTear]] true 读-修改-写事件不能发生撕裂。
[[Block]] a Shared Data Block 事件所操作的数据块。
[[ByteIndex]] a non-negative integer [[Block]] 中读-修改-写操作的字节地址。
[[ElementSize]] a non-negative integer 读-修改-写操作的大小。
[[Payload]] a List of byte values 要传递给 [[ModifyOp]] 的字节值 List。
[[ModifyOp]] a read-modify-write modification function 从读取到的字节值 List 和 [[Payload]] 返回修改后字节值 List 的 Abstract Closure。

Shared Data Block 事件由抽象操作或 Atomics 对象上的方法引入候选执行的 Agent Events Record 中。某些操作还会引入Synchronize 事件,这些事件没有字段,仅用于直接约束其他事件允许的排序。最后,还存在宿主特定事件。Memory 事件是 Shared Data Block 事件、Synchronize 事件或此类宿主特定事件中的任一种。

令 Shared Data Block 事件 e 的内存范围为从 e.[[ByteIndex]](包含)到 e.[[ByteIndex]] + e.[[ElementSize]](不包含)的区间中所有整数构成的 Set。如果两个事件具有相同的 [[Block]]、[[ByteIndex]] 和 [[ElementSize]],则称两个事件的内存范围相等。如果两个事件具有相同的 [[Block]],范围不相等,并且它们的交集非空,则称两个事件的内存范围重叠。如果两个事件不具有相同的 [[Block]],或者它们的范围既不相等也不重叠,则称两个事件的内存范围不相交。

注 2

应当考虑的宿主特定同步事件示例包括:将 SharedArrayBuffer 从一个代理发送到另一个代理(例如浏览器中的 postMessage)、启动和停止代理,以及通过共享内存以外的通道在代理集群内通信。对于特定执行 execution,这些事件由宿主通过 host-synchronizes-with 严格偏序提供。此外,宿主还可以向 execution.[[EventList]] 添加宿主特定的同步事件,使其参与 is-agent-order-before Relation。

候选执行中的事件按照下文定义的关系排序。

29.2 Agent Events Record

Agent Events Record 是具有以下字段的 Record。

表 100: Agent Events Record 字段
字段名称 值 含义
[[AgentSignifier]] an agent signifier 其求值产生此排序的代理。
[[EventList]] a List of Memory events 事件在求值期间追加到该 List。
[[AgentSynchronizesWith]] a List of pairs of Synchronize events 由操作语义引入的 Synchronize 关系。

29.3 Chosen Value Record

Chosen Value Record 是具有以下字段的 Record。

表 101: Chosen Value Record 字段
字段名称 值 含义
[[Event]] a Shared Data Block event 为此选定值引入的 ReadSharedMemory 或 ReadModifyWriteSharedMemory 事件。
[[ChosenValue]] a List of byte values 求值期间非确定性选择的字节。

29.4 候选执行

代理集群求值的候选执行是具有以下字段的 Record。

表 102: 候选执行 Record 字段
字段名称 值 含义
[[EventsRecords]] a List of Agent Events Records 将代理映射到求值期间追加的 Memory 事件 List。
[[ChosenValues]] a List of Chosen Value Records 将 ReadSharedMemory 或 ReadModifyWriteSharedMemory 事件映射到求值期间选择的字节值 List。

空候选执行是字段均为空 List 的候选执行 Record。

29.5 内存模型的抽象操作

29.5.1 EventSet ( execution )

抽象操作 EventSet,接收参数 execution (a candidate execution);返回值:a Set of Memory events。 调用时执行以下步骤:

  1. 令 events 为空 Set。
  2. 对 execution.[[EventsRecords]] 的每个 Agent Events Record eventsRecord,执行
    1. 对 eventsRecord.[[EventList]] 的每个 Memory event event,执行
      1. 将 event 添加到 events。
  3. 返回 events。

29.5.2 SharedDataBlockEventSet ( execution )

抽象操作 SharedDataBlockEventSet,接收参数 execution (a candidate execution);返回值:a Set of Shared Data Block events。 调用时执行以下步骤:

  1. 令 events 为空 Set。
  2. 对 EventSet(execution) 的每个 Memory event event,执行
    1. 如果 event 是 Shared Data Block event,则将 event 添加到 events。
  3. 返回 events。

29.5.3 HostEventSet ( execution )

抽象操作 HostEventSet,接收参数 execution (a candidate execution);返回值:a Set of Memory events。 调用时执行以下步骤:

  1. 返回一个新的 Set,其中包含 EventSet(execution) 中所有不属于 SharedDataBlockEventSet(execution) 的元素。

29.5.4 ComposeWriteEventBytes ( execution, byteIndex, writes )

抽象操作 ComposeWriteEventBytes,接收参数 execution (a candidate execution)、byteIndex (非负整数) 和 writes (列表 (元素:(WriteSharedMemory 或 ReadModifyWriteSharedMemory events)));返回值:列表 (元素:字节值)。 调用时执行以下步骤:

  1. 令 byteLocation 为 byteIndex。
  2. 令 bytesRead 为新的空 List。
  3. 对 writes 的每个元素 writeEvent,执行
    1. 断言:writeEvent 的内存范围包含 byteLocation。
    2. 令 payloadIndex 为 byteLocation - writeEvent.[[ByteIndex]]。
    3. 如果 writeEvent 是 WriteSharedMemory event,则
      1. 令 byte 为 writeEvent.[[Payload]][payloadIndex]。
    4. 否则,
      1. 断言:writeEvent 是 ReadModifyWriteSharedMemory event。
      2. 令 bytes 为 ValueOfReadEvent(execution, writeEvent)。
      3. 令 bytesModified 为 writeEvent.[[ModifyOp]](bytes, writeEvent.[[Payload]])。
      4. 令 byte 为 bytesModified[payloadIndex]。
    5. 将 byte 追加到 bytesRead。
    6. 将 byteLocation 设置为 byteLocation + 1。
  4. 返回 bytesRead。
注 1

读-修改-写修改 [[ModifyOp]] 由 Atomics 对象上会引入 ReadModifyWriteSharedMemory 事件的函数属性给出。

注 2

此抽象操作将写入事件 List 组合成字节值 List。它用于 ReadSharedMemory 和 ReadModifyWriteSharedMemory 事件的事件语义。

29.5.5 ValueOfReadEvent ( execution, readEvent )

抽象操作 ValueOfReadEvent,接收参数 execution (a candidate execution) 和 readEvent ((a ReadSharedMemory 或 ReadModifyWriteSharedMemory event));返回值:列表 (元素:字节值)。 调用时执行以下步骤:

  1. 令 writes 为 reads-bytes-from(readEvent) in execution。
  2. 断言:writes 是 WriteSharedMemory 或 ReadModifyWriteSharedMemory 事件的 List,其长度等于 readEvent.[[ElementSize]]。
  3. 返回 ComposeWriteEventBytes(execution, readEvent.[[ByteIndex]], writes)。

29.6 候选执行的关系

以下关系和数学函数以某个特定候选执行为参数,并对其 Memory 事件进行排序。

29.6.1 is-agent-order-before

对于候选执行 execution,其 is-agent-order-before Relation 是满足以下条件的 Memory 事件上的最小 Relation。

  • 对于事件 eventA 和 eventB,如果 execution.[[EventsRecords]] 中存在某个 Agent Events Record eventsRecord,使得 eventsRecord.[[EventList]] 同时包含 eventA 和 eventB,并且按照 eventsRecord.[[EventList]] 的 List 顺序,eventA 位于 eventB 之前,则 eventA is-agent-order-before eventB in execution。
注

每个代理在求值期间都按每代理严格全序引入事件。这是这些严格全序的并集。

29.6.2 reads-bytes-from

对于候选执行 execution,其 reads-bytes-from 函数是一个数学函数,它将 SharedDataBlockEventSet(execution) 中的 Memory 事件映射到 SharedDataBlockEventSet(execution) 中的事件 List,并满足以下条件。

候选执行始终允许存在 reads-bytes-from 函数。

29.6.3 reads-from

对于候选执行 execution,其 reads-from Relation 是满足以下条件的 Memory 事件上的最小 Relation。

29.6.4 host-synchronizes-with

对于候选执行 execution,其 host-synchronizes-with Relation 是由宿主提供的宿主特定 Memory 事件上的严格偏序,并且至少满足以下条件。

  • 如果 eventA host-synchronizes-with eventB in execution,则 HostEventSet(execution) 包含 eventA 和 eventB。
  • execution 中 host-synchronizes-with 和 is-agent-order-before 的并集中不存在环。
注 1

对于候选执行 execution 中两个宿主特定事件 eventA 和 eventB,eventA host-synchronizes-with eventB in execution 蕴含 eventA happens-before eventB in execution。

注 2

此 Relation 允许宿主提供其他同步机制,例如 HTML worker 之间的 postMessage。

29.6.5 synchronizes-with

对于候选执行 execution,其 synchronizes-with Relation 是满足以下条件的 Memory 事件上的最小 Relation。

  • 对于事件 readEvent 和 writeEvent,如果 readEvent reads-from writeEvent in execution、readEvent.[[Order]] 是 seq-cst、writeEvent.[[Order]] 是 seq-cst,并且 readEvent 和 writeEvent 具有相等的内存范围,则 writeEvent synchronizes-with readEvent in execution。
  • 对于 execution.[[EventsRecords]] 的每个元素 eventsRecord,以下条件成立。
    • 对于事件 eventA 和 eventB,如果 eventsRecord.[[AgentSynchronizesWith]] 包含 (eventA, eventB),则 eventA synchronizes-with eventB in execution。
  • 对于事件 eventA 和 eventB,如果 eventA host-synchronizes-with eventB in execution,则 eventA synchronizes-with eventB in execution。
注 1

按照内存模型文献中的惯例,在候选执行 execution 中,是写入事件 synchronizes-with 读取事件,而不是读取事件 synchronizes-with 写入事件。

注 2

在候选执行 execution 中,init 事件不参与此 Relation,而是由 happens-before 直接约束。

注 3

在候选执行 execution 中,并非所有通过 reads-from 相关联的 seq-cst 事件也通过 synchronizes-with 相关联。只有同时具有相等内存范围的事件才通过 synchronizes-with 相关联。

注 4

对于候选执行 execution 中满足 writeEvent synchronizes-with readEvent 的 Shared Data Block 事件 readEvent 和 writeEvent,readEvent 可能 reads-from writeEvent 之外的其他写入。

29.6.6 happens-before

对于候选执行 execution,其 happens-before Relation 是满足以下条件的 Memory 事件上的最小 Relation。

  • 对于事件 eventA 和 eventB,如果以下任一条件为真,则 eventA happens-before eventB in execution。

注

由于 happens-before 是 agent-order 的超集,因此候选执行与 ECMAScript 的单线程求值语义一致。

29.7 有效执行的属性

29.7.1 有效的选定读取

如果以下算法返回 true,则候选执行 execution 具有有效的选定读取。

  1. 对 SharedDataBlockEventSet(execution) 的每个 ReadSharedMemory 或 ReadModifyWriteSharedMemory event readEvent,执行
    1. 令 chosenValueRecord 为 execution.[[ChosenValues]] 中 [[Event]] 字段为 readEvent 的元素。
    2. 令 chosenValue 为 chosenValueRecord.[[ChosenValue]]。
    3. 令 readValue 为 ValueOfReadEvent(execution, readEvent)。
    4. 令 chosenLength 为 chosenValue 中的元素数量。
    5. 令 readLength 为 readValue 中的元素数量。
    6. 如果 chosenLength ≠ readLength,则
      1. 返回 false。
    7. 如果对于从 0(包含)到 chosenLength(不包含)区间中的某个整数 i,chosenValue[i] ≠ readValue[i],则
      1. 返回 false。
  2. 返回 true。

29.7.2 一致读取

如果以下算法返回 true,则候选执行 execution 具有一致读取。

  1. 对 SharedDataBlockEventSet(execution) 的每个 ReadSharedMemory 或 ReadModifyWriteSharedMemory event readEvent,执行
    1. 令 writes 为 reads-bytes-from(readEvent) in execution。
    2. 令 byteLocation 为 readEvent.[[ByteIndex]]。
    3. 对 writes 的每个元素 writeEvent,执行
      1. 如果 readEvent happens-before writeEvent in execution,则
        1. 返回 false。
      2. 如果存在 WriteSharedMemory 或 ReadModifyWriteSharedMemory event value,其内存范围包含 byteLocation,并且 writeEvent happens-before value in execution 且 value happens-before readEvent in execution,则
        1. 返回 false。
      3. 将 byteLocation 设置为 byteLocation + 1。
  2. 返回 true。

29.7.3 无撕裂读取

如果以下算法返回 true,则候选执行 execution 具有无撕裂读取。

  1. 对 SharedDataBlockEventSet(execution) 的每个 ReadSharedMemory 或 ReadModifyWriteSharedMemory event readEvent,执行
    1. 如果 readEvent.[[NoTear]] 是 true,则
      1. 断言:readEvent.[[ByteIndex]] 除以 readEvent.[[ElementSize]] 的余数为 0。
      2. 对满足 readEvent reads-from writeEvent in execution 且 writeEvent.[[NoTear]] 是 true 的每个 Memory event writeEvent,执行
        1. 如果 readEvent 和 writeEvent 具有相等的内存范围,并且存在 Memory event value,使得 value 和 writeEvent 具有相等的内存范围、value.[[NoTear]] 是 true、writeEvent 与 value 不是同一个 Shared Data Block event,并且 readEvent reads-from value in execution,则
          1. 返回 false。
  2. 返回 true。
注

当 Shared Data Block event 是通过访问整数 TypedArray 引入时,其 [[NoTear]] 字段为 true;当通过访问浮点 TypedArray 或 DataView 引入时,则为 false。

直观地说,此要求意味着,当通过整数 TypedArray 以对齐方式访问某个内存范围时,如果对该范围的一次写入事件与其他具有相同范围的写入事件发生数据竞争,则必须有一个写入事件“胜出”。更准确地说,此要求意味着,对齐读取事件不能读取由多个不同写入事件的字节组合而成的值,而这些写入事件都具有相同范围。不过,对齐读取事件仍可能从多个具有重叠范围的写入事件中读取。

29.7.4 顺序一致的原子操作

对于候选执行 execution,is-memory-order-before 是 EventSet(execution) 中所有 Memory 事件的严格全序,并满足以下条件。

如果候选执行允许存在 is-memory-order-before Relation,则它具有顺序一致的原子操作。

注 3

虽然 is-memory-order-before 包含 EventSet(execution) 中的所有事件,但在 execution 中不受 happens-before 或 synchronizes-with 约束的事件可以出现在该顺序中的任何位置。

29.7.5 有效执行

如果以下所有条件均为真,则候选执行 execution 是有效执行(或简称执行)。

所有程序至少具有一个有效执行。

29.8 竞争

对于执行 execution 以及包含在 SharedDataBlockEventSet(execution) 中的事件 eventA 和 eventB,如果以下算法返回 true,则 eventA 和 eventB 处于竞争中。

  1. 如果 eventA 和 eventB 不是同一个 Shared Data Block event,则
    1. 如果并非 eventA happens-before eventB in execution 和 eventB happens-before eventA in execution 同时成立,则
      1. 如果 eventA 是 WriteSharedMemory 或 ReadModifyWriteSharedMemory event、eventB 是 WriteSharedMemory 或 ReadModifyWriteSharedMemory event,并且 eventA 和 eventB 的内存范围并非不相交,则
        1. 返回 true。
      2. 如果 eventA reads-from eventB in execution 或 eventB reads-from eventA in execution,则
        1. 返回 true。
  2. 返回 false。

29.9 数据竞争

对于执行 execution 以及包含在 SharedDataBlockEventSet(execution) 中的事件 eventA 和 eventB,如果以下算法返回 true,则 eventA 和 eventB 处于数据竞争中。

  1. 如果 eventA 和 eventB 在 execution 中处于竞争中,则
    1. 如果 eventA.[[Order]] 不是 seq-cst 或 eventB.[[Order]] 不是 seq-cst,则
      1. 返回 true。
    2. 如果 eventA 和 eventB 具有重叠的内存范围,则
      1. 返回 true。
  2. 返回 false。

29.10 无数据竞争

如果 SharedDataBlockEventSet(execution) 中不存在两个处于数据竞争中的事件,则执行 execution 是无数据竞争的。

如果程序的所有执行都是无数据竞争的,则该程序是无数据竞争的。

内存模型保证无数据竞争程序中所有事件的顺序一致性。

29.11 共享内存指南

注 1

以下是供使用共享内存的 ECMAScript 程序员参考的指南。

建议使程序保持无数据竞争,也就是说,使同一内存位置上不可能出现并发非原子操作。无数据竞争程序具有交错语义,每个代理求值语义中的每个步骤彼此交错。对于无数据竞争程序,无需理解内存模型的细节。这些细节不太可能帮助建立更好编写 ECMAScript 代码所需的直觉。

更一般地说,即使程序并非无数据竞争,只要原子操作不参与任何数据竞争,并且发生竞争的操作都具有相同的访问大小,其行为仍可能是可预测的。确保原子操作不参与竞争的最简单方式,是让原子操作和非原子操作使用不同的内存单元,并且不要同时使用不同大小的原子访问来访问相同单元。实际上,程序应尽可能将共享内存视为强类型内存。仍然不能依赖发生竞争的非原子访问的顺序和时机,但如果将内存视为强类型,则发生竞争的访问不会“撕裂”(其值的位不会混合)。

注 2

以下是供为使用共享内存的程序编写编译器转换的 ECMAScript 实现者参考的指南。

为了确保多代理程序中每个代理的性能与单代理环境中一样好,希望允许大多数在单代理环境中有效的程序转换在多代理环境中同样有效。这些转换往往很难判断。下面概述一些关于程序转换的规则,这些规则旨在被视为规范性规则(因为它们由内存模型隐含,或强于内存模型所隐含的内容),但很可能并不穷尽。这些规则旨在适用于引入构成 is-agent-order-before Relation 的 Memory 事件之前进行的程序转换。

令agent-order 切片为 is-agent-order-before Relation 中属于单个代理的子集。

令读取事件的可能读取值为该事件在所有有效执行中的所有 ValueOfReadEvent 值的集合。

在没有共享内存时有效的任何 agent-order 切片转换,在存在共享内存时也有效,但以下情况除外。

  • 原子操作不可撼动:程序转换不得导致 [[Order]] 为 seq-cst 的任何 Shared Data Block 事件从 is-agent-order-before Relation 中移除,不得相互重排,也不得在 agent-order 切片内相对于 [[Order]] 为 unordered 的事件重新排序。

    (实际上,对重排的禁止迫使编译器假定每个 seq-cst 操作都是同步操作并包含在最终的 is-memory-order-before Relation 中;在缺少代理间程序分析的情况下,它通常无论如何都必须作出这种假设。它还迫使编译器假定,每个其被调用者对 memory-order 的影响未知的调用都可能包含 seq-cst 操作。)

  • 读取必须稳定:任何给定的共享内存读取在一次执行中都只能观察到一个值。

    (例如,如果程序中语义上是单次读取的操作被执行多次,那么程序随后只能观察读取到的其中一个值。称为重物化的转换可能违反此规则。)

  • 写入必须稳定:对共享内存的所有可观察写入都必须源自一次执行中的程序语义。

    (例如,转换不得引入某些可观察写入,例如通过对更大位置使用读-修改-写操作来写入较小数据、向内存写入程序不可能写入的值,或者在某位置可能在读取后已被另一代理覆盖的情况下,将刚刚读取的值写回其读取位置。)

  • 可能读取值必须非空:程序转换不能导致共享内存读取的可能读取值变为空。

    (反直觉的是,此规则实际上限制了对写入的转换,因为写入在内存模型中的作用在于可被读取事件读取。例如,可以移动和合并写入,有时还可以在两个 seq-cst 操作之间重排写入,但转换不得移除更新某个位置的所有写入;必须保留某个写入。)

仍然有效的转换示例包括:合并对同一位置的多个非原子读取、重排非原子读取、引入推测性非原子读取、合并对同一位置的多个非原子写入、重排对不同位置的非原子写入,以及即使会影响终止性也将非原子读取提升到循环之外。一般而言,需要注意别名 TypedArray 会使证明位置彼此不同变得困难。

注 3

以下是供为共享内存访问生成机器代码的 ECMAScript 实现者参考的指南。

对于内存模型不弱于 ARM 或 Power 的架构,非原子存储和加载可以编译为目标架构上的裸存储和裸加载。原子存储和加载可以编译为保证顺序一致性的指令。如果不存在此类指令,则应使用内存屏障,例如在裸存储或加载的两侧放置屏障。读-修改-写操作可以编译为目标架构上的读-修改-写指令,例如 x86 上带 LOCK 前缀的指令、ARM 上的 load-exclusive/store-exclusive 指令,以及 Power 上的 load-link/store-conditional 指令。

具体来说,内存模型旨在允许按以下方式生成代码。

  • 假定程序中的每个原子操作都是必需的。
  • 原子操作永远不会彼此重排,也不会与非原子操作重排。
  • 始终假定函数会执行原子操作。
  • 原子操作永远不会实现为在更大数据上的读-修改-写操作;如果平台没有适当大小的原子操作,则实现为非无锁原子操作。(我们已经假定每个平台都具有所有相关大小的普通内存访问操作。)

朴素代码生成使用以下模式:

  • 普通加载和存储编译为单个加载和存储指令。
  • 无锁原子加载和存储编译为一个完整(顺序一致)屏障、一次普通加载或存储以及另一个完整屏障。
  • 无锁原子读-修改-写访问编译为一个完整屏障、一段原子读-修改-写指令序列以及另一个完整屏障。
  • 非无锁原子操作编译为获取自旋锁、一个完整屏障、一系列非原子加载和存储指令、一个完整屏障,以及释放自旋锁。

只要某个内存范围上的原子操作不与非原子写入或不同大小的原子操作发生竞争,这种映射就是正确的。不过,这正是我们所需要的:内存模型实际上将参与竞争的原子操作降级为非原子状态。另一方面,朴素映射相当强:它允许将原子操作用作顺序一致的屏障,而内存模型实际上并不保证这一点。

在内存模型约束下,也允许对这些基本模式进行局部改进。例如:

  • 存在明显的依赖平台的优化,可以移除冗余屏障。例如,在 x86 上,无锁原子加载和存储周围的屏障始终可以省略,但存储后的屏障除外;无锁读-修改-写指令不需要屏障,因为这些指令都使用带 LOCK 前缀的指令。许多平台具有多种强度的屏障,可以在特定上下文中使用较弱的屏障而不会破坏顺序一致性。
  • 大多数现代平台对 ECMAScript 原子操作所需的所有数据大小都支持无锁原子操作。如果需要非无锁原子操作,原子操作主体周围的屏障通常可以并入加锁和解锁步骤。对于非无锁原子操作,最简单的解决方案是每个 SharedArrayBuffer 使用一个锁字。
  • 还有一些更复杂、依赖平台的局部改进,需要一定的代码分析。例如,连续的两个屏障通常与单个屏障效果相同,因此如果连续为两个原子操作生成代码,只需一个屏障将它们分开。在 x86 上,即使分隔原子存储的单个屏障也可以省略,因为存储后的屏障只在需要将该存储与后续加载分隔时才有必要。

附录 A (资料性) 文法摘要

A.1 词法文法

SourceCharacter :: any Unicode code point InputElementDiv :: WhiteSpace LineTerminator Comment CommonToken DivPunctuator RightBracePunctuator InputElementRegExp :: WhiteSpace LineTerminator Comment CommonToken RightBracePunctuator RegularExpressionLiteral InputElementRegExpOrTemplateTail :: WhiteSpace LineTerminator Comment CommonToken RegularExpressionLiteral TemplateSubstitutionTail InputElementTemplateTail :: WhiteSpace LineTerminator Comment CommonToken DivPunctuator TemplateSubstitutionTail InputElementHashbangOrRegExp :: WhiteSpace LineTerminator Comment CommonToken HashbangComment RegularExpressionLiteral WhiteSpace :: <TAB> <VT> <FF> <ZWNBSP> <USP> LineTerminator :: <LF> <CR> <LS> <PS> LineTerminatorSequence :: <LF> <CR> [lookahead ≠ <LF>] <LS> <PS> <CR> <LF> Comment :: MultiLineComment SingleLineComment MultiLineComment :: /* MultiLineCommentCharsopt */ MultiLineCommentChars :: MultiLineNotAsteriskChar MultiLineCommentCharsopt * PostAsteriskCommentCharsopt PostAsteriskCommentChars :: MultiLineNotForwardSlashOrAsteriskChar MultiLineCommentCharsopt * PostAsteriskCommentCharsopt MultiLineNotAsteriskChar :: SourceCharacter but not * MultiLineNotForwardSlashOrAsteriskChar :: SourceCharacter but not one of / or * SingleLineComment :: // SingleLineCommentCharsopt SingleLineCommentChars :: SingleLineCommentChar SingleLineCommentCharsopt SingleLineCommentChar :: SourceCharacter but not LineTerminator HashbangComment :: #! SingleLineCommentCharsopt CommonToken :: IdentifierName PrivateIdentifier Punctuator NumericLiteral StringLiteral Template PrivateIdentifier :: # IdentifierName IdentifierName :: IdentifierStart IdentifierName IdentifierPart IdentifierStart :: IdentifierStartChar \ UnicodeEscapeSequence IdentifierPart :: IdentifierPartChar \ UnicodeEscapeSequence IdentifierStartChar :: UnicodeIDStart $ _ IdentifierPartChar :: UnicodeIDContinue $ AsciiLetter :: one of a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z UnicodeIDStart :: any Unicode code point with the Unicode property “ID_Start” UnicodeIDContinue :: any Unicode code point with the Unicode property “ID_Continue” ReservedWord :: one of await break case catch class const continue debugger default delete do else enum export extends false finally for function if import in instanceof new null return super switch this throw true try typeof var void while with yield Punctuator :: OptionalChainingPunctuator OtherPunctuator OptionalChainingPunctuator :: ?. [lookahead ∉ DecimalDigit] OtherPunctuator :: one of { ( ) [ ] . ... ; , < > <= >= == != === !== + - * % ** ++ -- << >> >>> & | ^ ! ~ && || ?? ? : = += -= *= %= **= <<= >>= >>>= &= |= ^= &&= ||= ??= => DivPunctuator :: / /= RightBracePunctuator :: } NullLiteral :: null BooleanLiteral :: true false NumericLiteralSeparator :: _ NumericLiteral :: DecimalLiteral DecimalBigIntegerLiteral NonDecimalIntegerLiteral[+Sep] NonDecimalIntegerLiteral[+Sep] BigIntLiteralSuffix LegacyOctalIntegerLiteral DecimalBigIntegerLiteral :: 0 BigIntLiteralSuffix NonZeroDigit DecimalDigits[+Sep]opt BigIntLiteralSuffix NonZeroDigit NumericLiteralSeparator DecimalDigits[+Sep] BigIntLiteralSuffix NonDecimalIntegerLiteral[Sep] :: BinaryIntegerLiteral[?Sep] OctalIntegerLiteral[?Sep] HexIntegerLiteral[?Sep] BigIntLiteralSuffix :: n DecimalLiteral :: DecimalIntegerLiteral . DecimalDigits[+Sep]opt ExponentPart[+Sep]opt . DecimalDigits[+Sep] ExponentPart[+Sep]opt DecimalIntegerLiteral ExponentPart[+Sep]opt DecimalIntegerLiteral :: DecimalDigit NonZeroDigit NumericLiteralSeparatoropt DecimalDigits[+Sep] NonOctalDecimalIntegerLiteral DecimalDigits[Sep] :: DecimalDigit DecimalDigits[?Sep] DecimalDigit [+Sep] DecimalDigits[+Sep] NumericLiteralSeparator DecimalDigit DecimalDigit :: one of 0 1 2 3 4 5 6 7 8 9 NonZeroDigit :: one of 1 2 3 4 5 6 7 8 9 ExponentPart[Sep] :: ExponentIndicator SignedInteger[?Sep] ExponentIndicator :: one of e E SignedInteger[Sep] :: DecimalDigits[?Sep] + DecimalDigits[?Sep] - DecimalDigits[?Sep] BinaryIntegerLiteral[Sep] :: 0b BinaryDigits[?Sep] 0B BinaryDigits[?Sep] BinaryDigits[Sep] :: BinaryDigit BinaryDigits[?Sep] BinaryDigit [+Sep] BinaryDigits[+Sep] NumericLiteralSeparator BinaryDigit BinaryDigit :: one of 0 1 OctalIntegerLiteral[Sep] :: 0o OctalDigits[?Sep] 0O OctalDigits[?Sep] OctalDigits[Sep] :: OctalDigit OctalDigits[?Sep] OctalDigit [+Sep] OctalDigits[+Sep] NumericLiteralSeparator OctalDigit LegacyOctalIntegerLiteral :: 0 OctalDigit LegacyOctalIntegerLiteral OctalDigit NonOctalDecimalIntegerLiteral :: 0 LegacyOctalLikeDecimalDigitsopt NonOctalDigit NonOctalDecimalIntegerLiteral DecimalDigit LegacyOctalLikeDecimalDigits :: OctalDigit LegacyOctalLikeDecimalDigits OctalDigit OctalDigit :: one of 0 1 2 3 4 5 6 7 NonOctalDigit :: one of 8 9 HexIntegerLiteral[Sep] :: 0x HexDigits[?Sep] 0X HexDigits[?Sep] HexDigits[Sep] :: HexDigit HexDigits[?Sep] HexDigit [+Sep] HexDigits[+Sep] NumericLiteralSeparator HexDigit HexDigit :: one of 0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F StringLiteral :: " DoubleStringCharactersopt " ' SingleStringCharactersopt ' DoubleStringCharacters :: DoubleStringCharacter DoubleStringCharactersopt SingleStringCharacters :: SingleStringCharacter SingleStringCharactersopt DoubleStringCharacter :: SourceCharacter but not one of " or \ or LineTerminator <LS> <PS> \ EscapeSequence LineContinuation SingleStringCharacter :: SourceCharacter but not one of ' or \ or LineTerminator <LS> <PS> \ EscapeSequence LineContinuation LineContinuation :: \ LineTerminatorSequence EscapeSequence :: CharacterEscapeSequence 0 [lookahead ∉ DecimalDigit] LegacyOctalEscapeSequence NonOctalDecimalEscapeSequence HexEscapeSequence UnicodeEscapeSequence CharacterEscapeSequence :: SingleEscapeCharacter NonEscapeCharacter SingleEscapeCharacter :: one of ' " \ b f n r t v NonEscapeCharacter :: SourceCharacter but not one of EscapeCharacter or LineTerminator EscapeCharacter :: SingleEscapeCharacter DecimalDigit x u LegacyOctalEscapeSequence :: 0 [lookahead ∈ { 8, 9 }] NonZeroOctalDigit [lookahead ∉ OctalDigit] ZeroToThree OctalDigit [lookahead ∉ OctalDigit] FourToSeven OctalDigit ZeroToThree OctalDigit OctalDigit NonZeroOctalDigit :: OctalDigit but not 0 ZeroToThree :: one of 0 1 2 3 FourToSeven :: one of 4 5 6 7 NonOctalDecimalEscapeSequence :: one of 8 9 HexEscapeSequence :: x HexDigit HexDigit UnicodeEscapeSequence :: u Hex4Digits u{ CodePoint } Hex4Digits :: HexDigit HexDigit HexDigit HexDigit RegularExpressionLiteral :: / RegularExpressionBody / RegularExpressionFlags RegularExpressionBody :: RegularExpressionFirstChar RegularExpressionChars RegularExpressionChars :: [empty] RegularExpressionChars RegularExpressionChar RegularExpressionFirstChar :: RegularExpressionNonTerminator but not one of * or \ or / or [ RegularExpressionBackslashSequence RegularExpressionClass RegularExpressionChar :: RegularExpressionNonTerminator but not one of \ or / or [ RegularExpressionBackslashSequence RegularExpressionClass RegularExpressionBackslashSequence :: \ RegularExpressionNonTerminator RegularExpressionNonTerminator :: SourceCharacter but not LineTerminator RegularExpressionClass :: [ RegularExpressionClassChars ] RegularExpressionClassChars :: [empty] RegularExpressionClassChars RegularExpressionClassChar RegularExpressionClassChar :: RegularExpressionNonTerminator but not one of ] or \ RegularExpressionBackslashSequence RegularExpressionFlags :: [empty] RegularExpressionFlags IdentifierPartChar Template :: NoSubstitutionTemplate TemplateHead NoSubstitutionTemplate :: ` TemplateCharactersopt ` TemplateHead :: ` TemplateCharactersopt ${ TemplateSubstitutionTail :: TemplateMiddle TemplateTail TemplateMiddle :: } TemplateCharactersopt ${ TemplateTail :: } TemplateCharactersopt ` TemplateCharacters :: TemplateCharacter TemplateCharactersopt TemplateCharacter :: $ [lookahead ≠ {] \ TemplateEscapeSequence \ NotEscapeSequence LineContinuation LineTerminatorSequence SourceCharacter but not one of ` or \ or $ or LineTerminator TemplateEscapeSequence :: CharacterEscapeSequence 0 [lookahead ∉ DecimalDigit] HexEscapeSequence UnicodeEscapeSequence NotEscapeSequence :: 0 DecimalDigit DecimalDigit but not 0 x [lookahead ∉ HexDigit] x HexDigit [lookahead ∉ HexDigit] u [lookahead ∉ HexDigit] [lookahead ≠ {] u HexDigit [lookahead ∉ HexDigit] u HexDigit HexDigit [lookahead ∉ HexDigit] u HexDigit HexDigit HexDigit [lookahead ∉ HexDigit] u { [lookahead ∉ HexDigit] u { NotCodePoint [lookahead ∉ HexDigit] u { CodePoint [lookahead ∉ HexDigit] [lookahead ≠ }] NotCodePoint :: HexDigits[~Sep] but only if the MV of HexDigits > 0x10FFFF CodePoint :: HexDigits[~Sep] but only if the MV of HexDigits ≤ 0x10FFFF

A.2 表达式

IdentifierReference[Yield, Await] : Identifier [~Yield] yield [~Await] await BindingIdentifier[Yield, Await] : Identifier yield await LabelIdentifier[Yield, Await] : Identifier [~Yield] yield [~Await] await Identifier : IdentifierName but not ReservedWord PrimaryExpression[Yield, Await] : this IdentifierReference[?Yield, ?Await] Literal ArrayLiteral[?Yield, ?Await] ObjectLiteral[?Yield, ?Await] FunctionExpression ClassExpression[?Yield, ?Await] GeneratorExpression AsyncFunctionExpression AsyncGeneratorExpression RegularExpressionLiteral TemplateLiteral[?Yield, ?Await, ~Tagged] CoverParenthesizedExpressionAndArrowParameterList[?Yield, ?Await] CoverParenthesizedExpressionAndArrowParameterList[Yield, Await] : ( ) ( Expression[+In, ?Yield, ?Await] ,opt ) ( ... BindingIdentifier[?Yield, ?Await] ) ( ... BindingPattern[?Yield, ?Await] ) ( Expression[+In, ?Yield, ?Await] , ... BindingIdentifier[?Yield, ?Await] ) ( Expression[+In, ?Yield, ?Await] , ... BindingPattern[?Yield, ?Await] )

在处理以下产生式的实例时
PrimaryExpression[Yield, Await] : CoverParenthesizedExpressionAndArrowParameterList[?Yield, ?Await]
使用以下文法进一步解释 CoverParenthesizedExpressionAndArrowParameterList:

ParenthesizedExpression[Yield, Await] : ( Expression[+In, ?Yield, ?Await] )

 

Literal : NullLiteral BooleanLiteral NumericLiteral StringLiteral ArrayLiteral[Yield, Await] : [ Elisionopt ] [ ElementList[?Yield, ?Await] ] [ ElementList[?Yield, ?Await] , Elisionopt ] ElementList[Yield, Await] : Elisionopt AssignmentExpression[+In, ?Yield, ?Await] Elisionopt SpreadElement[?Yield, ?Await] ElementList[?Yield, ?Await] , Elisionopt AssignmentExpression[+In, ?Yield, ?Await] ElementList[?Yield, ?Await] , Elisionopt SpreadElement[?Yield, ?Await] Elision : , Elision , SpreadElement[Yield, Await] : ... AssignmentExpression[+In, ?Yield, ?Await] ObjectLiteral[Yield, Await] : { } { PropertyDefinitionList[?Yield, ?Await] ,opt } PropertyDefinitionList[Yield, Await] : PropertyDefinition[?Yield, ?Await] PropertyDefinitionList[?Yield, ?Await] , PropertyDefinition[?Yield, ?Await] PropertyDefinition[Yield, Await] : IdentifierReference[?Yield, ?Await] CoverInitializedName[?Yield, ?Await] PropertyName[?Yield, ?Await] : AssignmentExpression[+In, ?Yield, ?Await] MethodDefinition[?Yield, ?Await] ... AssignmentExpression[+In, ?Yield, ?Await] PropertyName[Yield, Await] : LiteralPropertyName ComputedPropertyName[?Yield, ?Await] LiteralPropertyName : IdentifierName StringLiteral NumericLiteral ComputedPropertyName[Yield, Await] : [ AssignmentExpression[+In, ?Yield, ?Await] ] CoverInitializedName[Yield, Await] : IdentifierReference[?Yield, ?Await] Initializer[+In, ?Yield, ?Await] Initializer[In, Yield, Await] : = AssignmentExpression[?In, ?Yield, ?Await] TemplateLiteral[Yield, Await, Tagged] : NoSubstitutionTemplate SubstitutionTemplate[?Yield, ?Await] SubstitutionTemplate[Yield, Await] : TemplateHead Expression[+In, ?Yield, ?Await] TemplateSpans[?Yield, ?Await] TemplateSpans[Yield, Await] : TemplateTail TemplateMiddleList[?Yield, ?Await] TemplateTail TemplateMiddleList[Yield, Await] : TemplateMiddle Expression[+In, ?Yield, ?Await] TemplateMiddleList[?Yield, ?Await] TemplateMiddle Expression[+In, ?Yield, ?Await] MemberExpression[Yield, Await] : PrimaryExpression[?Yield, ?Await] MemberExpression[?Yield, ?Await] [ Expression[+In, ?Yield, ?Await] ] MemberExpression[?Yield, ?Await] . IdentifierName MemberExpression[?Yield, ?Await] TemplateLiteral[?Yield, ?Await, +Tagged] SuperProperty[?Yield, ?Await] MetaProperty new MemberExpression[?Yield, ?Await] Arguments[?Yield, ?Await] MemberExpression[?Yield, ?Await] . PrivateIdentifier SuperProperty[Yield, Await] : super [ Expression[+In, ?Yield, ?Await] ] super . IdentifierName MetaProperty : NewTarget ImportMeta NewTarget : new . target ImportMeta : import . meta NewExpression[Yield, Await] : MemberExpression[?Yield, ?Await] new NewExpression[?Yield, ?Await] CallExpression[Yield, Await] : CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await] SuperCall[?Yield, ?Await] ImportCall[?Yield, ?Await] CallExpression[?Yield, ?Await] Arguments[?Yield, ?Await] CallExpression[?Yield, ?Await] [ Expression[+In, ?Yield, ?Await] ] CallExpression[?Yield, ?Await] . IdentifierName CallExpression[?Yield, ?Await] TemplateLiteral[?Yield, ?Await, +Tagged] CallExpression[?Yield, ?Await] . PrivateIdentifier

在处理以下产生式的实例时
CallExpression[Yield, Await] : CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await]
使用以下文法进一步解释 CoverCallExpressionAndAsyncArrowHead:

CallMemberExpression[Yield, Await] : MemberExpression[?Yield, ?Await] Arguments[?Yield, ?Await]

 

SuperCall[Yield, Await] : super Arguments[?Yield, ?Await] ImportCall[Yield, Await] : import ( AssignmentExpression[+In, ?Yield, ?Await] ,opt ) import ( AssignmentExpression[+In, ?Yield, ?Await] , AssignmentExpression[+In, ?Yield, ?Await] ,opt ) Arguments[Yield, Await] : ( ) ( ArgumentList[?Yield, ?Await] ,opt ) ArgumentList[Yield, Await] : AssignmentExpression[+In, ?Yield, ?Await] ... AssignmentExpression[+In, ?Yield, ?Await] ArgumentList[?Yield, ?Await] , AssignmentExpression[+In, ?Yield, ?Await] ArgumentList[?Yield, ?Await] , ... AssignmentExpression[+In, ?Yield, ?Await] OptionalExpression[Yield, Await] : MemberExpression[?Yield, ?Await] OptionalChain[?Yield, ?Await] CallExpression[?Yield, ?Await] OptionalChain[?Yield, ?Await] OptionalExpression[?Yield, ?Await] OptionalChain[?Yield, ?Await] OptionalChain[Yield, Await] : ?. Arguments[?Yield, ?Await] ?. [ Expression[+In, ?Yield, ?Await] ] ?. IdentifierName ?. TemplateLiteral[?Yield, ?Await, +Tagged] ?. PrivateIdentifier OptionalChain[?Yield, ?Await] Arguments[?Yield, ?Await] OptionalChain[?Yield, ?Await] [ Expression[+In, ?Yield, ?Await] ] OptionalChain[?Yield, ?Await] . IdentifierName OptionalChain[?Yield, ?Await] TemplateLiteral[?Yield, ?Await, +Tagged] OptionalChain[?Yield, ?Await] . PrivateIdentifier LeftHandSideExpression[Yield, Await] : NewExpression[?Yield, ?Await] CallExpression[?Yield, ?Await] OptionalExpression[?Yield, ?Await] UpdateExpression[Yield, Await] : LeftHandSideExpression[?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] [no LineTerminator here] ++ LeftHandSideExpression[?Yield, ?Await] [no LineTerminator here] -- ++ UnaryExpression[?Yield, ?Await] -- UnaryExpression[?Yield, ?Await] UnaryExpression[Yield, Await] : UpdateExpression[?Yield, ?Await] delete UnaryExpression[?Yield, ?Await] void UnaryExpression[?Yield, ?Await] typeof UnaryExpression[?Yield, ?Await] + UnaryExpression[?Yield, ?Await] - UnaryExpression[?Yield, ?Await] ~ UnaryExpression[?Yield, ?Await] ! UnaryExpression[?Yield, ?Await] [+Await] CoverAwaitExpressionAndAwaitUsingDeclarationHead[?Yield] CoverAwaitExpressionAndAwaitUsingDeclarationHead[Yield] : await UnaryExpression[?Yield, +Await]

在处理以下产生式的实例时
UnaryExpression[Yield, Await] : [+Await] CoverAwaitExpressionAndAwaitUsingDeclarationHead[?Yield]
使用以下文法进一步解释 CoverAwaitExpressionAndAwaitUsingDeclarationHead:

AwaitExpression[Yield] : await UnaryExpression[?Yield, +Await]

 

ExponentiationExpression[Yield, Await] : UnaryExpression[?Yield, ?Await] UpdateExpression[?Yield, ?Await] ** ExponentiationExpression[?Yield, ?Await] MultiplicativeExpression[Yield, Await] : ExponentiationExpression[?Yield, ?Await] MultiplicativeExpression[?Yield, ?Await] MultiplicativeOperator ExponentiationExpression[?Yield, ?Await] MultiplicativeOperator : one of * / % AdditiveExpression[Yield, Await] : MultiplicativeExpression[?Yield, ?Await] AdditiveExpression[?Yield, ?Await] + MultiplicativeExpression[?Yield, ?Await] AdditiveExpression[?Yield, ?Await] - MultiplicativeExpression[?Yield, ?Await] ShiftExpression[Yield, Await] : AdditiveExpression[?Yield, ?Await] ShiftExpression[?Yield, ?Await] << AdditiveExpression[?Yield, ?Await] ShiftExpression[?Yield, ?Await] >> AdditiveExpression[?Yield, ?Await] ShiftExpression[?Yield, ?Await] >>> AdditiveExpression[?Yield, ?Await] RelationalExpression[In, Yield, Await] : ShiftExpression[?Yield, ?Await] RelationalExpression[?In, ?Yield, ?Await] < ShiftExpression[?Yield, ?Await] RelationalExpression[?In, ?Yield, ?Await] > ShiftExpression[?Yield, ?Await] RelationalExpression[?In, ?Yield, ?Await] <= ShiftExpression[?Yield, ?Await] RelationalExpression[?In, ?Yield, ?Await] >= ShiftExpression[?Yield, ?Await] RelationalExpression[?In, ?Yield, ?Await] instanceof ShiftExpression[?Yield, ?Await] [+In] RelationalExpression[+In, ?Yield, ?Await] in ShiftExpression[?Yield, ?Await] [+In] PrivateIdentifier in ShiftExpression[?Yield, ?Await] EqualityExpression[In, Yield, Await] : RelationalExpression[?In, ?Yield, ?Await] EqualityExpression[?In, ?Yield, ?Await] == RelationalExpression[?In, ?Yield, ?Await] EqualityExpression[?In, ?Yield, ?Await] != RelationalExpression[?In, ?Yield, ?Await] EqualityExpression[?In, ?Yield, ?Await] === RelationalExpression[?In, ?Yield, ?Await] EqualityExpression[?In, ?Yield, ?Await] !== RelationalExpression[?In, ?Yield, ?Await] BitwiseANDExpression[In, Yield, Await] : EqualityExpression[?In, ?Yield, ?Await] BitwiseANDExpression[?In, ?Yield, ?Await] & EqualityExpression[?In, ?Yield, ?Await] BitwiseXORExpression[In, Yield, Await] : BitwiseANDExpression[?In, ?Yield, ?Await] BitwiseXORExpression[?In, ?Yield, ?Await] ^ BitwiseANDExpression[?In, ?Yield, ?Await] BitwiseORExpression[In, Yield, Await] : BitwiseXORExpression[?In, ?Yield, ?Await] BitwiseORExpression[?In, ?Yield, ?Await] | BitwiseXORExpression[?In, ?Yield, ?Await] LogicalANDExpression[In, Yield, Await] : BitwiseORExpression[?In, ?Yield, ?Await] LogicalANDExpression[?In, ?Yield, ?Await] && BitwiseORExpression[?In, ?Yield, ?Await] LogicalORExpression[In, Yield, Await] : LogicalANDExpression[?In, ?Yield, ?Await] LogicalORExpression[?In, ?Yield, ?Await] || LogicalANDExpression[?In, ?Yield, ?Await] CoalesceExpression[In, Yield, Await] : CoalesceExpressionHead[?In, ?Yield, ?Await] ?? BitwiseORExpression[?In, ?Yield, ?Await] CoalesceExpressionHead[In, Yield, Await] : CoalesceExpression[?In, ?Yield, ?Await] BitwiseORExpression[?In, ?Yield, ?Await] ShortCircuitExpression[In, Yield, Await] : LogicalORExpression[?In, ?Yield, ?Await] CoalesceExpression[?In, ?Yield, ?Await] ConditionalExpression[In, Yield, Await] : ShortCircuitExpression[?In, ?Yield, ?Await] ShortCircuitExpression[?In, ?Yield, ?Await] ? AssignmentExpression[+In, ?Yield, ?Await] : AssignmentExpression[?In, ?Yield, ?Await] AssignmentExpression[In, Yield, Await] : ConditionalExpression[?In, ?Yield, ?Await] [+Yield] YieldExpression[?In, ?Await] ArrowFunction[?In, ?Yield, ?Await] AsyncArrowFunction[?In, ?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] = AssignmentExpression[?In, ?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] AssignmentOperator AssignmentExpression[?In, ?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] &&= AssignmentExpression[?In, ?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] ||= AssignmentExpression[?In, ?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] ??= AssignmentExpression[?In, ?Yield, ?Await] AssignmentOperator : one of *= /= %= += -= <<= >>= >>>= &= ^= |= **=

在某些情况下处理以下产生式的实例时
AssignmentExpression[In, Yield, Await] : LeftHandSideExpression[?Yield, ?Await] = AssignmentExpression[?In, ?Yield, ?Await]
使用以下文法进一步解释 LeftHandSideExpression:

AssignmentPattern[Yield, Await] : ObjectAssignmentPattern[?Yield, ?Await] ArrayAssignmentPattern[?Yield, ?Await] ObjectAssignmentPattern[Yield, Await] : { } { AssignmentRestProperty[?Yield, ?Await] } { AssignmentPropertyList[?Yield, ?Await] ,opt } { AssignmentPropertyList[?Yield, ?Await] , AssignmentRestProperty[?Yield, ?Await] } ArrayAssignmentPattern[Yield, Await] : [ Elisionopt AssignmentRestElement[?Yield, ?Await]opt ] [ AssignmentElementList[?Yield, ?Await] ] [ AssignmentElementList[?Yield, ?Await] , Elisionopt AssignmentRestElement[?Yield, ?Await]opt ] AssignmentRestProperty[Yield, Await] : ... DestructuringAssignmentTarget[?Yield, ?Await] AssignmentPropertyList[Yield, Await] : AssignmentProperty[?Yield, ?Await] AssignmentPropertyList[?Yield, ?Await] , AssignmentProperty[?Yield, ?Await] AssignmentElementList[Yield, Await] : AssignmentElisionElement[?Yield, ?Await] AssignmentElementList[?Yield, ?Await] , AssignmentElisionElement[?Yield, ?Await] AssignmentElisionElement[Yield, Await] : Elisionopt AssignmentElement[?Yield, ?Await] AssignmentProperty[Yield, Await] : IdentifierReference[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]opt PropertyName[?Yield, ?Await] : AssignmentElement[?Yield, ?Await] AssignmentElement[Yield, Await] : DestructuringAssignmentTarget[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]opt AssignmentRestElement[Yield, Await] : ... DestructuringAssignmentTarget[?Yield, ?Await] DestructuringAssignmentTarget[Yield, Await] : LeftHandSideExpression[?Yield, ?Await]

 

Expression[In, Yield, Await] : AssignmentExpression[?In, ?Yield, ?Await] Expression[?In, ?Yield, ?Await] , AssignmentExpression[?In, ?Yield, ?Await]

A.3 语句

Statement[Yield, Await, Return] : BlockStatement[?Yield, ?Await, ?Return] VariableStatement[?Yield, ?Await] EmptyStatement ExpressionStatement[?Yield, ?Await] IfStatement[?Yield, ?Await, ?Return] BreakableStatement[?Yield, ?Await, ?Return] ContinueStatement[?Yield, ?Await] BreakStatement[?Yield, ?Await] [+Return] ReturnStatement[?Yield, ?Await] WithStatement[?Yield, ?Await, ?Return] LabelledStatement[?Yield, ?Await, ?Return] ThrowStatement[?Yield, ?Await] TryStatement[?Yield, ?Await, ?Return] DebuggerStatement Declaration[Yield, Await] : HoistableDeclaration[?Yield, ?Await, ~Default] ClassDeclaration[?Yield, ?Await, ~Default] LexicalDeclaration[+In, ?Yield, ?Await] HoistableDeclaration[Yield, Await, Default] : FunctionDeclaration[?Yield, ?Await, ?Default] GeneratorDeclaration[?Yield, ?Await, ?Default] AsyncFunctionDeclaration[?Yield, ?Await, ?Default] AsyncGeneratorDeclaration[?Yield, ?Await, ?Default] BreakableStatement[Yield, Await, Return] : IterationStatement[?Yield, ?Await, ?Return] SwitchStatement[?Yield, ?Await, ?Return] BlockStatement[Yield, Await, Return] : Block[?Yield, ?Await, ?Return] Block[Yield, Await, Return] : { StatementList[?Yield, ?Await, ?Return]opt } StatementList[Yield, Await, Return] : StatementListItem[?Yield, ?Await, ?Return] StatementList[?Yield, ?Await, ?Return] StatementListItem[?Yield, ?Await, ?Return] StatementListItem[Yield, Await, Return] : Statement[?Yield, ?Await, ?Return] Declaration[?Yield, ?Await] LexicalDeclaration[In, Yield, Await] : LetOrConst BindingList[?In, ?Yield, ?Await, +Pattern] ; UsingDeclaration[?In, ?Yield, ?Await] [+Await] AwaitUsingDeclaration[?In, ?Yield] LetOrConst : let const UsingDeclaration[In, Yield, Await] : using [no LineTerminator here] BindingList[?In, ?Yield, ?Await, ~Pattern] ; AwaitUsingDeclaration[In, Yield] : CoverAwaitExpressionAndAwaitUsingDeclarationHead[?Yield] [no LineTerminator here] BindingList[?In, ?Yield, +Await, ~Pattern] ; BindingList[In, Yield, Await, Pattern] : LexicalBinding[?In, ?Yield, ?Await, ?Pattern] BindingList[?In, ?Yield, ?Await, ?Pattern] , LexicalBinding[?In, ?Yield, ?Await, ?Pattern] LexicalBinding[In, Yield, Await, Pattern] : BindingIdentifier[?Yield, ?Await] Initializer[?In, ?Yield, ?Await]opt [+Pattern] BindingPattern[?Yield, ?Await] Initializer[?In, ?Yield, ?Await]

在处理以下产生式的实例时
AwaitUsingDeclaration[In, Yield] : CoverAwaitExpressionAndAwaitUsingDeclarationHead[?Yield] [no LineTerminator here] BindingList[?In, ?Yield, +Await, ~Pattern] ;
使用以下文法进一步解释 CoverAwaitExpressionAndAwaitUsingDeclarationHead:

AwaitUsingDeclarationHead : await [no LineTerminator here] using

 

VariableStatement[Yield, Await] : var VariableDeclarationList[+In, ?Yield, ?Await] ; VariableDeclarationList[In, Yield, Await] : VariableDeclaration[?In, ?Yield, ?Await] VariableDeclarationList[?In, ?Yield, ?Await] , VariableDeclaration[?In, ?Yield, ?Await] VariableDeclaration[In, Yield, Await] : BindingIdentifier[?Yield, ?Await] Initializer[?In, ?Yield, ?Await]opt BindingPattern[?Yield, ?Await] Initializer[?In, ?Yield, ?Await] BindingPattern[Yield, Await] : ObjectBindingPattern[?Yield, ?Await] ArrayBindingPattern[?Yield, ?Await] ObjectBindingPattern[Yield, Await] : { } { BindingRestProperty[?Yield, ?Await] } { BindingPropertyList[?Yield, ?Await] ,opt } { BindingPropertyList[?Yield, ?Await] , BindingRestProperty[?Yield, ?Await] } ArrayBindingPattern[Yield, Await] : [ Elisionopt BindingRestElement[?Yield, ?Await]opt ] [ BindingElementList[?Yield, ?Await] ] [ BindingElementList[?Yield, ?Await] , Elisionopt BindingRestElement[?Yield, ?Await]opt ] BindingRestProperty[Yield, Await] : ... BindingIdentifier[?Yield, ?Await] BindingPropertyList[Yield, Await] : BindingProperty[?Yield, ?Await] BindingPropertyList[?Yield, ?Await] , BindingProperty[?Yield, ?Await] BindingElementList[Yield, Await] : BindingElisionElement[?Yield, ?Await] BindingElementList[?Yield, ?Await] , BindingElisionElement[?Yield, ?Await] BindingElisionElement[Yield, Await] : Elisionopt BindingElement[?Yield, ?Await] BindingProperty[Yield, Await] : SingleNameBinding[?Yield, ?Await] PropertyName[?Yield, ?Await] : BindingElement[?Yield, ?Await] BindingElement[Yield, Await] : SingleNameBinding[?Yield, ?Await] BindingPattern[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]opt SingleNameBinding[Yield, Await] : BindingIdentifier[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]opt BindingRestElement[Yield, Await] : ... BindingIdentifier[?Yield, ?Await] ... BindingPattern[?Yield, ?Await] EmptyStatement : ; ExpressionStatement[Yield, Await] : [lookahead ∉ { {, function, async [no LineTerminator here] function, class, let [ }] Expression[+In, ?Yield, ?Await] ; IfStatement[Yield, Await, Return] : if ( Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] else Statement[?Yield, ?Await, ?Return] if ( Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] [lookahead ≠ else] IterationStatement[Yield, Await, Return] : DoWhileStatement[?Yield, ?Await, ?Return] WhileStatement[?Yield, ?Await, ?Return] ForStatement[?Yield, ?Await, ?Return] ForInOfStatement[?Yield, ?Await, ?Return] DoWhileStatement[Yield, Await, Return] : do Statement[?Yield, ?Await, ?Return] while ( Expression[+In, ?Yield, ?Await] ) ; WhileStatement[Yield, Await, Return] : while ( Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] ForStatement[Yield, Await, Return] : for ( [lookahead ≠ let [] Expression[~In, ?Yield, ?Await]opt ; Expression[+In, ?Yield, ?Await]opt ; Expression[+In, ?Yield, ?Await]opt ) Statement[?Yield, ?Await, ?Return] for ( var VariableDeclarationList[~In, ?Yield, ?Await] ; Expression[+In, ?Yield, ?Await]opt ; Expression[+In, ?Yield, ?Await]opt ) Statement[?Yield, ?Await, ?Return] for ( LexicalDeclaration[~In, ?Yield, ?Await] Expression[+In, ?Yield, ?Await]opt ; Expression[+In, ?Yield, ?Await]opt ) Statement[?Yield, ?Await, ?Return] ForInOfStatement[Yield, Await, Return] : for ( [lookahead ≠ let [] LeftHandSideExpression[?Yield, ?Await] in Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] for ( var ForBinding[?Yield, ?Await, +Pattern] in Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] for ( ForDeclaration[?Yield, ?Await, ~Using] in Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] for ( [lookahead ∉ { let, async of }] LeftHandSideExpression[?Yield, ?Await] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] for ( var ForBinding[?Yield, ?Await, +Pattern] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] for ( [lookahead ≠ using of] ForDeclaration[?Yield, ?Await, +Using] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] [+Await] for await ( [lookahead ≠ let] LeftHandSideExpression[?Yield, ?Await] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] [+Await] for await ( var ForBinding[?Yield, ?Await, +Pattern] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] [+Await] for await ( [lookahead ≠ using of] ForDeclaration[?Yield, ?Await, +Using] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] ForDeclaration[Yield, Await, Using] : LetOrConst ForBinding[?Yield, ?Await, +Pattern] [+Using] using [no LineTerminator here] ForBinding[?Yield, ?Await, ~Pattern] [+Using, +Await] await [no LineTerminator here] using [no LineTerminator here] ForBinding[?Yield, +Await, ~Pattern] ForBinding[Yield, Await, Pattern] : BindingIdentifier[?Yield, ?Await] [+Pattern] BindingPattern[?Yield, ?Await] ContinueStatement[Yield, Await] : continue ; continue [no LineTerminator here] LabelIdentifier[?Yield, ?Await] ; BreakStatement[Yield, Await] : break ; break [no LineTerminator here] LabelIdentifier[?Yield, ?Await] ; ReturnStatement[Yield, Await] : return ; return [no LineTerminator here] Expression[+In, ?Yield, ?Await] ; WithStatement[Yield, Await, Return] : with ( Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] SwitchStatement[Yield, Await, Return] : switch ( Expression[+In, ?Yield, ?Await] ) CaseBlock[?Yield, ?Await, ?Return] CaseBlock[Yield, Await, Return] : { CaseClauses[?Yield, ?Await, ?Return]opt } { CaseClauses[?Yield, ?Await, ?Return]opt DefaultClause[?Yield, ?Await, ?Return] CaseClauses[?Yield, ?Await, ?Return]opt } CaseClauses[Yield, Await, Return] : CaseClause[?Yield, ?Await, ?Return] CaseClauses[?Yield, ?Await, ?Return] CaseClause[?Yield, ?Await, ?Return] CaseClause[Yield, Await, Return] : case Expression[+In, ?Yield, ?Await] : StatementList[?Yield, ?Await, ?Return]opt DefaultClause[Yield, Await, Return] : default : StatementList[?Yield, ?Await, ?Return]opt LabelledStatement[Yield, Await, Return] : LabelIdentifier[?Yield, ?Await] : LabelledItem[?Yield, ?Await, ?Return] LabelledItem[Yield, Await, Return] : Statement[?Yield, ?Await, ?Return] FunctionDeclaration[?Yield, ?Await, ~Default] ThrowStatement[Yield, Await] : throw [no LineTerminator here] Expression[+In, ?Yield, ?Await] ; TryStatement[Yield, Await, Return] : try Block[?Yield, ?Await, ?Return] Catch[?Yield, ?Await, ?Return] try Block[?Yield, ?Await, ?Return] Finally[?Yield, ?Await, ?Return] try Block[?Yield, ?Await, ?Return] Catch[?Yield, ?Await, ?Return] Finally[?Yield, ?Await, ?Return] Catch[Yield, Await, Return] : catch ( CatchParameter[?Yield, ?Await] ) Block[?Yield, ?Await, ?Return] catch Block[?Yield, ?Await, ?Return] Finally[Yield, Await, Return] : finally Block[?Yield, ?Await, ?Return] CatchParameter[Yield, Await] : BindingIdentifier[?Yield, ?Await] BindingPattern[?Yield, ?Await] DebuggerStatement : debugger ;

A.4 函数和类

UniqueFormalParameters[Yield, Await] : FormalParameters[?Yield, ?Await] FormalParameters[Yield, Await] : [empty] FunctionRestParameter[?Yield, ?Await] FormalParameterList[?Yield, ?Await] FormalParameterList[?Yield, ?Await] , FormalParameterList[?Yield, ?Await] , FunctionRestParameter[?Yield, ?Await] FormalParameterList[Yield, Await] : FormalParameter[?Yield, ?Await] FormalParameterList[?Yield, ?Await] , FormalParameter[?Yield, ?Await] FunctionRestParameter[Yield, Await] : BindingRestElement[?Yield, ?Await] FormalParameter[Yield, Await] : BindingElement[?Yield, ?Await] FunctionDeclaration[Yield, Await, Default] : function BindingIdentifier[?Yield, ?Await] ( FormalParameters[~Yield, ~Await] ) { FunctionBody[~Yield, ~Await] } [+Default] function ( FormalParameters[~Yield, ~Await] ) { FunctionBody[~Yield, ~Await] } FunctionExpression : function BindingIdentifier[~Yield, ~Await]opt ( FormalParameters[~Yield, ~Await] ) { FunctionBody[~Yield, ~Await] } FunctionBody[Yield, Await] : FunctionStatementList[?Yield, ?Await] FunctionStatementList[Yield, Await] : StatementList[?Yield, ?Await, +Return]opt ArrowFunction[In, Yield, Await] : ArrowParameters[?Yield, ?Await] [no LineTerminator here] => ConciseBody[?In] ArrowParameters[Yield, Await] : BindingIdentifier[?Yield, ?Await] CoverParenthesizedExpressionAndArrowParameterList[?Yield, ?Await] ConciseBody[In] : [lookahead ≠ {] ExpressionBody[?In, ~Await] { FunctionBody[~Yield, ~Await] } ExpressionBody[In, Await] : AssignmentExpression[?In, ~Yield, ?Await]

在处理以下产生式的实例时
ArrowParameters[Yield, Await] : CoverParenthesizedExpressionAndArrowParameterList[?Yield, ?Await]
使用以下文法进一步解释 CoverParenthesizedExpressionAndArrowParameterList:

ArrowFormalParameters[Yield, Await] : ( UniqueFormalParameters[?Yield, ?Await] )

 

AsyncArrowFunction[In, Yield, Await] : async [no LineTerminator here] AsyncArrowBindingIdentifier[?Yield] [no LineTerminator here] => AsyncConciseBody[?In] CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await] [no LineTerminator here] => AsyncConciseBody[?In] AsyncConciseBody[In] : [lookahead ≠ {] ExpressionBody[?In, +Await] { AsyncFunctionBody } AsyncArrowBindingIdentifier[Yield] : BindingIdentifier[?Yield, +Await] CoverCallExpressionAndAsyncArrowHead[Yield, Await] : MemberExpression[?Yield, ?Await] Arguments[?Yield, ?Await]

在处理以下产生式的实例时
AsyncArrowFunction[In, Yield, Await] : CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await] [no LineTerminator here] => AsyncConciseBody[?In]
使用以下文法进一步解释 CoverCallExpressionAndAsyncArrowHead:

AsyncArrowHead : async [no LineTerminator here] ArrowFormalParameters[~Yield, +Await]

 

MethodDefinition[Yield, Await] : ClassElementName[?Yield, ?Await] ( UniqueFormalParameters[~Yield, ~Await] ) { FunctionBody[~Yield, ~Await] } GeneratorMethod[?Yield, ?Await] AsyncMethod[?Yield, ?Await] AsyncGeneratorMethod[?Yield, ?Await] get ClassElementName[?Yield, ?Await] ( ) { FunctionBody[~Yield, ~Await] } set ClassElementName[?Yield, ?Await] ( PropertySetParameterList ) { FunctionBody[~Yield, ~Await] } PropertySetParameterList : FormalParameter[~Yield, ~Await] GeneratorDeclaration[Yield, Await, Default] : function * BindingIdentifier[?Yield, ?Await] ( FormalParameters[+Yield, ~Await] ) { GeneratorBody } [+Default] function * ( FormalParameters[+Yield, ~Await] ) { GeneratorBody } GeneratorExpression : function * BindingIdentifier[+Yield, ~Await]opt ( FormalParameters[+Yield, ~Await] ) { GeneratorBody } GeneratorMethod[Yield, Await] : * ClassElementName[?Yield, ?Await] ( UniqueFormalParameters[+Yield, ~Await] ) { GeneratorBody } GeneratorBody : FunctionBody[+Yield, ~Await] YieldExpression[In, Await] : yield yield [no LineTerminator here] AssignmentExpression[?In, +Yield, ?Await] yield [no LineTerminator here] * AssignmentExpression[?In, +Yield, ?Await] AsyncGeneratorDeclaration[Yield, Await, Default] : async [no LineTerminator here] function * BindingIdentifier[?Yield, ?Await] ( FormalParameters[+Yield, +Await] ) { AsyncGeneratorBody } [+Default] async [no LineTerminator here] function * ( FormalParameters[+Yield, +Await] ) { AsyncGeneratorBody } AsyncGeneratorExpression : async [no LineTerminator here] function * BindingIdentifier[+Yield, +Await]opt ( FormalParameters[+Yield, +Await] ) { AsyncGeneratorBody } AsyncGeneratorMethod[Yield, Await] : async [no LineTerminator here] * ClassElementName[?Yield, ?Await] ( UniqueFormalParameters[+Yield, +Await] ) { AsyncGeneratorBody } AsyncGeneratorBody : FunctionBody[+Yield, +Await] AsyncFunctionDeclaration[Yield, Await, Default] : async [no LineTerminator here] function BindingIdentifier[?Yield, ?Await] ( FormalParameters[~Yield, +Await] ) { AsyncFunctionBody } [+Default] async [no LineTerminator here] function ( FormalParameters[~Yield, +Await] ) { AsyncFunctionBody } AsyncFunctionExpression : async [no LineTerminator here] function BindingIdentifier[~Yield, +Await]opt ( FormalParameters[~Yield, +Await] ) { AsyncFunctionBody } AsyncMethod[Yield, Await] : async [no LineTerminator here] ClassElementName[?Yield, ?Await] ( UniqueFormalParameters[~Yield, +Await] ) { AsyncFunctionBody } AsyncFunctionBody : FunctionBody[~Yield, +Await] AwaitExpression[Yield] : await UnaryExpression[?Yield, +Await] ClassDeclaration[Yield, Await, Default] : class BindingIdentifier[?Yield, ?Await] ClassTail[?Yield, ?Await] [+Default] class ClassTail[?Yield, ?Await] ClassExpression[Yield, Await] : class BindingIdentifier[?Yield, ?Await]opt ClassTail[?Yield, ?Await] ClassTail[Yield, Await] : ClassHeritage[?Yield, ?Await]opt { ClassBody[?Yield, ?Await]opt } ClassHeritage[Yield, Await] : extends LeftHandSideExpression[?Yield, ?Await] ClassBody[Yield, Await] : ClassElementList[?Yield, ?Await] ClassElementList[Yield, Await] : ClassElement[?Yield, ?Await] ClassElementList[?Yield, ?Await] ClassElement[?Yield, ?Await] ClassElement[Yield, Await] : MethodDefinition[?Yield, ?Await] static MethodDefinition[?Yield, ?Await] FieldDefinition[?Yield, ?Await] ; static FieldDefinition[?Yield, ?Await] ; ClassStaticBlock ; FieldDefinition[Yield, Await] : ClassElementName[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]opt ClassElementName[Yield, Await] : PropertyName[?Yield, ?Await] PrivateIdentifier ClassStaticBlock : static { ClassStaticBlockBody } ClassStaticBlockBody : ClassStaticBlockStatementList ClassStaticBlockStatementList : StatementList[~Yield, +Await, ~Return]opt

A.5 脚本和模块

Script : ScriptBodyopt ScriptBody : StatementList[~Yield, ~Await, ~Return] Module : ModuleBodyopt ModuleBody : ModuleItemList ModuleItemList : ModuleItem ModuleItemList ModuleItem ModuleItem : ImportDeclaration ExportDeclaration StatementListItem[~Yield, +Await, ~Return] ModuleExportName : IdentifierName StringLiteral ImportDeclaration : import ImportClause FromClause WithClauseopt ; import ModuleSpecifier WithClauseopt ; ImportClause : ImportedDefaultBinding NameSpaceImport NamedImports ImportedDefaultBinding , NameSpaceImport ImportedDefaultBinding , NamedImports ImportedDefaultBinding : ImportedBinding NameSpaceImport : * as ImportedBinding NamedImports : { } { ImportsList ,opt } FromClause : from ModuleSpecifier ImportsList : ImportSpecifier ImportsList , ImportSpecifier ImportSpecifier : ImportedBinding ModuleExportName as ImportedBinding ModuleSpecifier : StringLiteral ImportedBinding : BindingIdentifier[~Yield, +Await] WithClause : with { } with { WithEntries ,opt } WithEntries : AttributeKey : StringLiteral AttributeKey : StringLiteral , WithEntries AttributeKey : IdentifierName StringLiteral ExportDeclaration : export ExportFromClause FromClause WithClauseopt ; export NamedExports ; export VariableStatement[~Yield, +Await] export [lookahead ∉ { using, await }] Declaration[~Yield, +Await] export default HoistableDeclaration[~Yield, +Await, +Default] export default ClassDeclaration[~Yield, +Await, +Default] export default [lookahead ∉ { function, async [no LineTerminator here] function, class }] AssignmentExpression[+In, ~Yield, +Await] ; ExportFromClause : * * as ModuleExportName NamedExports NamedExports : { } { ExportsList ,opt } ExportsList : ExportSpecifier ExportsList , ExportSpecifier ExportSpecifier : ModuleExportName ModuleExportName as ModuleExportName

A.6 Number 转换

StringNumericLiteral ::: StrWhiteSpaceopt StrWhiteSpaceopt StrNumericLiteral StrWhiteSpaceopt StrWhiteSpace ::: StrWhiteSpaceChar StrWhiteSpaceopt StrWhiteSpaceChar ::: WhiteSpace LineTerminator StrNumericLiteral ::: StrDecimalLiteral NonDecimalIntegerLiteral[~Sep] StrDecimalLiteral ::: StrUnsignedDecimalLiteral + StrUnsignedDecimalLiteral - StrUnsignedDecimalLiteral StrUnsignedDecimalLiteral ::: Infinity DecimalDigits[~Sep] . DecimalDigits[~Sep]opt ExponentPart[~Sep]opt . DecimalDigits[~Sep] ExponentPart[~Sep]opt DecimalDigits[~Sep] ExponentPart[~Sep]opt

所有未由 StringNumericLiteral 文法显式定义的文法符号,都采用数值字面量的词法文法中使用的定义。

StringIntegerLiteral ::: StrWhiteSpaceopt StrWhiteSpaceopt StrIntegerLiteral StrWhiteSpaceopt StrIntegerLiteral ::: SignedInteger[~Sep] NonDecimalIntegerLiteral[~Sep]

A.7 时区偏移 String 格式

UTCOffset ::: ASCIISign Hour ASCIISign Hour HourSubcomponents[+Extended] ASCIISign Hour HourSubcomponents[~Extended] ASCIISign ::: one of + - Hour ::: 0 DecimalDigit 1 DecimalDigit 20 21 22 23 HourSubcomponents[Extended] ::: TimeSeparator[?Extended] MinuteSecond TimeSeparator[?Extended] MinuteSecond TimeSeparator[?Extended] MinuteSecond TemporalDecimalFractionopt TimeSeparator[Extended] ::: [+Extended] : [~Extended] [empty] MinuteSecond ::: 0 DecimalDigit 1 DecimalDigit 2 DecimalDigit 3 DecimalDigit 4 DecimalDigit 5 DecimalDigit TemporalDecimalFraction ::: TemporalDecimalSeparator DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator ::: one of . ,

A.8 正则表达式

Pattern[UnicodeMode, UnicodeSetsMode, NamedCaptureGroups] :: Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Disjunction[UnicodeMode, UnicodeSetsMode, NamedCaptureGroups] :: Alternative[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Alternative[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] | Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Alternative[UnicodeMode, UnicodeSetsMode, NamedCaptureGroups] :: [empty] Alternative[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Term[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Term[UnicodeMode, UnicodeSetsMode, NamedCaptureGroups] :: Assertion[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Atom[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Atom[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Quantifier Assertion[UnicodeMode, UnicodeSetsMode, NamedCaptureGroups] :: ^ $ \b \B (?= Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) (?! Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) (?<= Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) (?<! Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) Quantifier :: QuantifierPrefix QuantifierPrefix ? QuantifierPrefix :: * + ? { DecimalDigits[~Sep] } { DecimalDigits[~Sep] ,} { DecimalDigits[~Sep] , DecimalDigits[~Sep] } Atom[UnicodeMode, UnicodeSetsMode, NamedCaptureGroups] :: PatternCharacter . \ AtomEscape[?UnicodeMode, ?NamedCaptureGroups] CharacterClass[?UnicodeMode, ?UnicodeSetsMode] ( GroupSpecifier[?UnicodeMode]opt Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) (? RegularExpressionModifiers : Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) (? RegularExpressionModifiers - RegularExpressionModifiers : Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) RegularExpressionModifiers :: [empty] RegularExpressionModifiers RegularExpressionModifier RegularExpressionModifier :: one of i m s SyntaxCharacter :: one of ^ $ \ . * + ? ( ) [ ] { } | PatternCharacter :: SourceCharacter but not SyntaxCharacter AtomEscape[UnicodeMode, NamedCaptureGroups] :: DecimalEscape CharacterClassEscape[?UnicodeMode] CharacterEscape[?UnicodeMode] [+NamedCaptureGroups] k GroupName[?UnicodeMode] CharacterEscape[UnicodeMode] :: ControlEscape c AsciiLetter 0 [lookahead ∉ DecimalDigit] HexEscapeSequence RegExpUnicodeEscapeSequence[?UnicodeMode] IdentityEscape[?UnicodeMode] ControlEscape :: one of f n r t v GroupSpecifier[UnicodeMode] :: ? GroupName[?UnicodeMode] GroupName[UnicodeMode] :: < RegExpIdentifierName[?UnicodeMode] > RegExpIdentifierName[UnicodeMode] :: RegExpIdentifierStart[?UnicodeMode] RegExpIdentifierName[?UnicodeMode] RegExpIdentifierPart[?UnicodeMode] RegExpIdentifierStart[UnicodeMode] :: IdentifierStartChar \ RegExpUnicodeEscapeSequence[+UnicodeMode] [~UnicodeMode] UnicodeLeadSurrogate UnicodeTrailSurrogate RegExpIdentifierPart[UnicodeMode] :: IdentifierPartChar \ RegExpUnicodeEscapeSequence[+UnicodeMode] [~UnicodeMode] UnicodeLeadSurrogate UnicodeTrailSurrogate RegExpUnicodeEscapeSequence[UnicodeMode] :: [+UnicodeMode] u HexLeadSurrogate \u HexTrailSurrogate [+UnicodeMode] u HexLeadSurrogate [+UnicodeMode] u HexTrailSurrogate [+UnicodeMode] u HexNonSurrogate [~UnicodeMode] u Hex4Digits [+UnicodeMode] u{ CodePoint } UnicodeLeadSurrogate :: any Unicode code point in the inclusive interval from U+D800 to U+DBFF UnicodeTrailSurrogate :: any Unicode code point in the inclusive interval from U+DC00 to U+DFFF

对于每个相关联的 u HexLeadSurrogate 选择存在歧义的 \u HexTrailSurrogate,都应将其与最近的、否则不会有对应 \u HexTrailSurrogate 的可能 u HexLeadSurrogate 关联。

 

HexLeadSurrogate :: Hex4Digits but only if the MV of Hex4Digits is in the inclusive interval from 0xD800 to 0xDBFF HexTrailSurrogate :: Hex4Digits but only if the MV of Hex4Digits is in the inclusive interval from 0xDC00 to 0xDFFF HexNonSurrogate :: Hex4Digits but only if the MV of Hex4Digits is not in the inclusive interval from 0xD800 to 0xDFFF IdentityEscape[UnicodeMode] :: [+UnicodeMode] SyntaxCharacter [+UnicodeMode] / [~UnicodeMode] SourceCharacter but not UnicodeIDContinue DecimalEscape :: NonZeroDigit DecimalDigits[~Sep]opt [lookahead ∉ DecimalDigit] CharacterClassEscape[UnicodeMode] :: d D s S w W [+UnicodeMode] p{ UnicodePropertyValueExpression } [+UnicodeMode] P{ UnicodePropertyValueExpression } UnicodePropertyValueExpression :: UnicodePropertyName = UnicodePropertyValue LoneUnicodePropertyNameOrValue UnicodePropertyName :: UnicodePropertyNameCharacters UnicodePropertyNameCharacters :: UnicodePropertyNameCharacter UnicodePropertyNameCharactersopt UnicodePropertyValue :: UnicodePropertyValueCharacters LoneUnicodePropertyNameOrValue :: UnicodePropertyValueCharacters UnicodePropertyValueCharacters :: UnicodePropertyValueCharacter UnicodePropertyValueCharactersopt UnicodePropertyValueCharacter :: UnicodePropertyNameCharacter DecimalDigit UnicodePropertyNameCharacter :: AsciiLetter _ CharacterClass[UnicodeMode, UnicodeSetsMode] :: [ [lookahead ≠ ^] ClassContents[?UnicodeMode, ?UnicodeSetsMode] ] [^ ClassContents[?UnicodeMode, ?UnicodeSetsMode] ] ClassContents[UnicodeMode, UnicodeSetsMode] :: [empty] [~UnicodeSetsMode] NonemptyClassRanges[?UnicodeMode] [+UnicodeSetsMode] ClassSetExpression NonemptyClassRanges[UnicodeMode] :: ClassAtom[?UnicodeMode] ClassAtom[?UnicodeMode] NonemptyClassRangesNoDash[?UnicodeMode] ClassAtom[?UnicodeMode] - ClassAtom[?UnicodeMode] ClassContents[?UnicodeMode, ~UnicodeSetsMode] NonemptyClassRangesNoDash[UnicodeMode] :: ClassAtom[?UnicodeMode] ClassAtomNoDash[?UnicodeMode] NonemptyClassRangesNoDash[?UnicodeMode] ClassAtomNoDash[?UnicodeMode] - ClassAtom[?UnicodeMode] ClassContents[?UnicodeMode, ~UnicodeSetsMode] ClassAtom[UnicodeMode] :: - ClassAtomNoDash[?UnicodeMode] ClassAtomNoDash[UnicodeMode] :: SourceCharacter but not one of \ or ] or - \ ClassEscape[?UnicodeMode] ClassEscape[UnicodeMode] :: b [+UnicodeMode] - CharacterClassEscape[?UnicodeMode] CharacterEscape[?UnicodeMode] ClassSetExpression :: ClassUnion ClassIntersection ClassSubtraction ClassUnion :: ClassSetRange ClassUnionopt ClassSetOperand ClassUnionopt ClassIntersection :: ClassSetOperand && [lookahead ≠ &] ClassSetOperand ClassIntersection && [lookahead ≠ &] ClassSetOperand ClassSubtraction :: ClassSetOperand -- ClassSetOperand ClassSubtraction -- ClassSetOperand ClassSetRange :: ClassSetCharacter - ClassSetCharacter ClassSetOperand :: NestedClass ClassStringDisjunction ClassSetCharacter NestedClass :: [ [lookahead ≠ ^] ClassContents[+UnicodeMode, +UnicodeSetsMode] ] [^ ClassContents[+UnicodeMode, +UnicodeSetsMode] ] \ CharacterClassEscape[+UnicodeMode] ClassStringDisjunction :: \q{ ClassStringDisjunctionContents } ClassStringDisjunctionContents :: ClassString ClassString | ClassStringDisjunctionContents ClassString :: [empty] NonEmptyClassString NonEmptyClassString :: ClassSetCharacter NonEmptyClassStringopt ClassSetCharacter :: [lookahead ∉ ClassSetReservedDoublePunctuator] SourceCharacter but not ClassSetSyntaxCharacter \ CharacterEscape[+UnicodeMode] \ ClassSetReservedPunctuator \b ClassSetReservedDoublePunctuator :: one of && !! ## $$ %% ** ++ ,, .. :: ;; << == >> ?? @@ ^^ `` ~~ ClassSetSyntaxCharacter :: one of ( ) [ ] { } / - \ | ClassSetReservedPunctuator :: one of & - ! # % , : ; < = > @ ` ~

附录 B (规范性) Web 浏览器的附加 ECMAScript 特性

当 ECMAScript 宿主是 Web 浏览器时,必须支持本附录中定义的 ECMAScript 语言语法和语义。如果 ECMAScript 宿主不是 Web 浏览器,则本附录的内容是规范性的,但为可选。

本附录中定义的某些特性在本附录中规定,另一些则在本文档主体中规定。

当某个特性在主体中规定时,其影响本文档的每个位置都会在有色框中标有“Normative Optional”字样。此外,如果该特性涉及算法或提前错误规则中的特定措辞,则会以“宿主支持”相关特性这一条件进行保护。Web 浏览器必须支持所有此类特性。

注

本附录描述 Web 浏览器 ECMAScript 宿主的各种遗留特性和其他特征。本附录规定的所有语言特性和行为都具有一个或多个不良特征,如果不存在遗留使用,本应从本规范中移除。然而,大量现有网页使用这些特性,意味着 Web 浏览器必须继续支持它们。本附录中的规范定义了这些遗留特性实现互操作性所需的要求。

这些特性不被视为核心 ECMAScript 语言的一部分。程序员编写新的 ECMAScript 代码时不应使用或假定这些特性和行为存在。除非实现属于 Web 浏览器的一部分,或需要运行 Web 浏览器所遇到的相同遗留 ECMAScript 代码,否则不鼓励 ECMAScript 实现去实现这些特性。

B.1 附加语法

B.1.1 类 HTML 注释

12.4 的语法和语义扩展如下,但使用目标符号 Module 解析源文本时不允许此扩展:

语法

InputElementHashbangOrRegExp :: WhiteSpace LineTerminator Comment CommonToken HashbangComment RegularExpressionLiteral HTMLCloseComment Comment :: MultiLineComment SingleLineComment SingleLineHTMLOpenComment SingleLineHTMLCloseComment SingleLineDelimitedComment MultiLineComment :: /* FirstCommentLineopt LineTerminator MultiLineCommentCharsopt */ HTMLCloseCommentopt FirstCommentLine :: SingleLineDelimitedCommentChars SingleLineHTMLOpenComment :: <!-- SingleLineCommentCharsopt SingleLineHTMLCloseComment :: LineTerminatorSequence HTMLCloseComment SingleLineDelimitedComment :: /* SingleLineDelimitedCommentCharsopt */ HTMLCloseComment :: WhiteSpaceSequenceopt SingleLineDelimitedCommentSequenceopt --> SingleLineCommentCharsopt SingleLineDelimitedCommentChars :: SingleLineNotAsteriskChar SingleLineDelimitedCommentCharsopt * SingleLinePostAsteriskCommentCharsopt SingleLineNotAsteriskChar :: SourceCharacter but not one of * or LineTerminator SingleLinePostAsteriskCommentChars :: SingleLineNotForwardSlashOrAsteriskChar SingleLineDelimitedCommentCharsopt * SingleLinePostAsteriskCommentCharsopt SingleLineNotForwardSlashOrAsteriskChar :: SourceCharacter but not one of / or * or LineTerminator WhiteSpaceSequence :: WhiteSpace WhiteSpaceSequenceopt SingleLineDelimitedCommentSequence :: SingleLineDelimitedComment WhiteSpaceSequenceopt SingleLineDelimitedCommentSequenceopt

与包含行终止符码点的 MultiLineComment 类似,为句法文法解析之目的,SingleLineHTMLCloseComment 被视为 LineTerminator。

B.1.2 正则表达式模式

22.2.1 的语法修改并扩展如下。这些更改引入了歧义,这些歧义通过文法产生式的顺序和上下文信息消解。使用以下文法解析时,只有在先前的产生式备选项不匹配时,才会考虑每个备选项。

此替代模式文法和语义只改变 BMP 模式的语法和语义。以下文法扩展包括以 [UnicodeMode] 参数参数化的产生式。不过,这些扩展均不会改变使用目标符号上存在的 [UnicodeMode] 参数进行解析时所识别的 Unicode 模式语法。

语法

Term[UnicodeMode, UnicodeSetsMode, NamedCaptureGroups] :: [+UnicodeMode] Assertion[+UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] [+UnicodeMode] Atom[+UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Quantifier [+UnicodeMode] Atom[+UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] [~UnicodeMode] QuantifiableAssertion[?NamedCaptureGroups] Quantifier [~UnicodeMode] Assertion[~UnicodeMode, ~UnicodeSetsMode, ?NamedCaptureGroups] [~UnicodeMode] ExtendedAtom[?NamedCaptureGroups] Quantifier [~UnicodeMode] ExtendedAtom[?NamedCaptureGroups] Assertion[UnicodeMode, UnicodeSetsMode, NamedCaptureGroups] :: ^ $ \b \B [+UnicodeMode] (?= Disjunction[+UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) [+UnicodeMode] (?! Disjunction[+UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) [~UnicodeMode] QuantifiableAssertion[?NamedCaptureGroups] (?<= Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) (?<! Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) QuantifiableAssertion[NamedCaptureGroups] :: (?= Disjunction[~UnicodeMode, ~UnicodeSetsMode, ?NamedCaptureGroups] ) (?! Disjunction[~UnicodeMode, ~UnicodeSetsMode, ?NamedCaptureGroups] ) ExtendedAtom[NamedCaptureGroups] :: . \ AtomEscape[~UnicodeMode, ?NamedCaptureGroups] \ [lookahead = c] CharacterClass[~UnicodeMode, ~UnicodeSetsMode] ( GroupSpecifier[~UnicodeMode]opt Disjunction[~UnicodeMode, ~UnicodeSetsMode, ?NamedCaptureGroups] ) (? RegularExpressionModifiers : Disjunction[~UnicodeMode, ~UnicodeSetsMode, ?NamedCaptureGroups] ) (? RegularExpressionModifiers - RegularExpressionModifiers : Disjunction[~UnicodeMode, ~UnicodeSetsMode, ?NamedCaptureGroups] ) InvalidBracedQuantifier ExtendedPatternCharacter InvalidBracedQuantifier :: { DecimalDigits[~Sep] } { DecimalDigits[~Sep] ,} { DecimalDigits[~Sep] , DecimalDigits[~Sep] } ExtendedPatternCharacter :: SourceCharacter but not one of ^ $ \ . * + ? ( ) [ | AtomEscape[UnicodeMode, NamedCaptureGroups] :: [+UnicodeMode] DecimalEscape [~UnicodeMode] DecimalEscape but only if the CapturingGroupNumber of DecimalEscape is ≤ CountLeftCapturingParensWithin(the Pattern containing DecimalEscape) CharacterClassEscape[?UnicodeMode] CharacterEscape[?UnicodeMode, ?NamedCaptureGroups] [+NamedCaptureGroups] k GroupName[?UnicodeMode] CharacterEscape[UnicodeMode, NamedCaptureGroups] :: ControlEscape c AsciiLetter 0 [lookahead ∉ DecimalDigit] HexEscapeSequence RegExpUnicodeEscapeSequence[?UnicodeMode] [~UnicodeMode] LegacyOctalEscapeSequence IdentityEscape[?UnicodeMode, ?NamedCaptureGroups] IdentityEscape[UnicodeMode, NamedCaptureGroups] :: [+UnicodeMode] SyntaxCharacter [+UnicodeMode] / [~UnicodeMode] SourceCharacterIdentityEscape[?NamedCaptureGroups] SourceCharacterIdentityEscape[NamedCaptureGroups] :: [~NamedCaptureGroups] SourceCharacter but not c [+NamedCaptureGroups] SourceCharacter but not one of c or k ClassAtomNoDash[UnicodeMode, NamedCaptureGroups] :: SourceCharacter but not one of \ or ] or - \ ClassEscape[?UnicodeMode, ?NamedCaptureGroups] \ [lookahead = c] ClassEscape[UnicodeMode, NamedCaptureGroups] :: b [+UnicodeMode] - [~UnicodeMode] c ClassControlLetter CharacterClassEscape[?UnicodeMode] CharacterEscape[?UnicodeMode, ?NamedCaptureGroups] ClassControlLetter :: DecimalDigit _ 注

当相同的左侧同时出现 [+UnicodeMode] 和 [~UnicodeMode] 守卫时,这是为了控制消歧优先级。

B.1.2.1 Static Semantics: 提前错误

22.2.1.1 的语义扩展如下:

ExtendedAtom :: InvalidBracedQuantifier
  • 如果有任何源文本被此产生式匹配,则为 Syntax Error。

此外,以下产生式的规则通过添加突出显示的文本进行修改:

NonemptyClassRanges :: ClassAtom - ClassAtom ClassContents NonemptyClassRangesNoDash :: ClassAtomNoDash - ClassAtom ClassContents

B.1.2.2 Static Semantics: CountLeftCapturingParensWithin 和 CountLeftCapturingParensBefore

在 CountLeftCapturingParensWithin 和 CountLeftCapturingParensBefore 的定义中,对“ Atom :: ( GroupSpecifieropt Disjunction ) ”的引用应解释为“ Atom :: ( GroupSpecifieropt Disjunction ) ”或“ ExtendedAtom :: ( GroupSpecifieropt Disjunction ) ”。

B.1.2.3 Static Semantics: IsCharacterClass

IsCharacterClass 的语义扩展如下:

ClassAtomNoDash :: \ [lookahead = c]
  1. 返回 false。

B.1.2.4 Static Semantics: CharacterValue

CharacterValue 的语义扩展如下:

ClassAtomNoDash :: \ [lookahead = c]
  1. 返回 U+005C (REVERSE SOLIDUS) 的数值。
ClassEscape :: c ClassControlLetter
  1. 令 codePoint 为 ClassControlLetter 匹配的码点。
  2. 令 i 为 codePoint 的数值。
  3. 返回 i 除以 32 的余数。
CharacterEscape :: LegacyOctalEscapeSequence
  1. 返回 the MV of LegacyOctalEscapeSequence(参见 12.9.4.3)。

B.1.2.5 Runtime Semantics: CompileSubpattern

带参数 regexpRecord 和 direction 的 CompileSubpattern 语义扩展如下:

Term :: QuantifiableAssertion Quantifier 的规则与 Term :: Atom Quantifier 相同,但用 QuantifiableAssertion 替换 Atom。

Term :: ExtendedAtom Quantifier 的规则与 Term :: Atom Quantifier 相同,但用 ExtendedAtom 替换 Atom。

Term :: ExtendedAtom 的规则与 Term :: Atom 相同,但用 ExtendedAtom 替换 Atom。

B.1.2.6 Runtime Semantics: CompileAssertion

带参数 regexpRecord 的 CompileAssertion 语义扩展如下:

QuantifiableAssertion :: (?= Disjunction ) 的规则与 Assertion :: (?= Disjunction ) 相同,但用 QuantifiableAssertion 替换 Atom。

QuantifiableAssertion :: (?! Disjunction ) 的规则与 Assertion :: (?! Disjunction ) 相同,但用 QuantifiableAssertion 替换 Atom。

B.1.2.7 Runtime Semantics: CompileAtom

带参数 regexpRecord 和 direction 的 CompileAtom 语义扩展如下:

除 Atom :: PatternCharacter 外,Atom 产生式的规则也用于 ExtendedAtom 产生式,但用 ExtendedAtom 替换 Atom。

还会添加以下规则:

ExtendedAtom :: \ [lookahead = c]
  1. 令 charSet 为包含单个字符 \ U+005C (REVERSE SOLIDUS) 的 CharSet。
  2. 返回 CharacterSetMatcher(regexpRecord, charSet, false, direction)。
ExtendedAtom :: ExtendedPatternCharacter
  1. 令 char 为 ExtendedPatternCharacter 表示的字符。
  2. 令 charSet 为包含字符 char 的单元素 CharSet。
  3. 返回 CharacterSetMatcher(regexpRecord, charSet, false, direction)。

B.1.2.8 Runtime Semantics: CompileToCharSet

带参数 regexpRecord 的 CompileToCharSet 语义扩展如下:

替换以下两个规则:

NonemptyClassRanges :: ClassAtom - ClassAtom ClassContents
  1. 令 charSet 为 CompileToCharSet of the first ClassAtom with argument regexpRecord。
  2. 令 otherSet 为 CompileToCharSet of the second ClassAtom with argument regexpRecord。
  3. 令 remainingSet 为 CompileToCharSet of ClassContents with argument regexpRecord。
  4. 令 rangeSet 为 CharacterRangeOrUnion(regexpRecord, charSet, otherSet)。
  5. 返回 rangeSet 和 remainingSet 的并集。
NonemptyClassRangesNoDash :: ClassAtomNoDash - ClassAtom ClassContents
  1. 令 charSet 为 CompileToCharSet of ClassAtomNoDash with argument regexpRecord。
  2. 令 otherSet 为 CompileToCharSet of ClassAtom with argument regexpRecord。
  3. 令 remainingSet 为 CompileToCharSet of ClassContents with argument regexpRecord。
  4. 令 rangeSet 为 CharacterRangeOrUnion(regexpRecord, charSet, otherSet)。
  5. 返回 rangeSet 和 remainingSet 的并集。

还会添加以下规则:

ClassEscape :: c ClassControlLetter
  1. 令 charValue 为 the CharacterValue of this ClassEscape。
  2. 令 char 为字符值为 charValue 的字符。
  3. 返回包含单个字符 char 的 CharSet。
ClassAtomNoDash :: \ [lookahead = c]
  1. 返回包含单个字符 \ U+005C (REVERSE SOLIDUS) 的 CharSet。
注
此产生式只能从字符类中的序列 \c 到达,并且该序列后面没有可接受的控制字符。

B.1.2.8.1 CharacterRangeOrUnion ( regexpRecord, charSet, otherSet )

抽象操作 CharacterRangeOrUnion,接收参数 regexpRecord (RegExp 记录)、charSet (CharSet) 和 otherSet (CharSet);返回值:CharSet。 调用时执行以下步骤:

  1. 如果 HasEitherUnicodeFlag(regexpRecord) 是 false,则
    1. 如果 charSet 不恰好包含一个字符,或 otherSet 不恰好包含一个字符,则
      1. 令 remainingSet 为包含单个字符 - U+002D (HYPHEN-MINUS) 的 CharSet。
      2. 返回 CharSet charSet、otherSet 和 remainingSet 的并集。
  2. 返回 CharacterRange(charSet, otherSet)。

B.1.2.9 Static Semantics: ParsePattern ( patternText, u, v )

带参数 patternText、u 和 v 的 ParsePattern 语义扩展如下,其中修改内容以突出显示:

  1. 如果 v 是 true 且 u 是 true,则
    1. 令 parseResult 为包含一个或多个 SyntaxError 对象的 List。
  2. 否则如果 v 是 true,则
    1. 令 parseResult 为 ParseText(patternText, Pattern[+UnicodeMode, +UnicodeSetsMode, +NamedCaptureGroups])。
  3. 否则如果 u 是 true,则
    1. 令 parseResult 为 ParseText(patternText, Pattern[+UnicodeMode, ~UnicodeSetsMode, +NamedCaptureGroups])。
  4. 否则,
    1. 令 parseResult 为 ParseText(patternText, Pattern[~UnicodeMode, ~UnicodeSetsMode, ~NamedCaptureGroups])。
    2. 如果 parseResult 是 Parse Node 且 parseResult contains a GroupName,则
      1. 将 parseResult 设置为 ParseText(patternText, Pattern[~UnicodeMode, ~UnicodeSetsMode, +NamedCaptureGroups])。
  5. 返回 parseResult。

B.2 附加内置属性

当 ECMAScript 宿主是 Web 浏览器时,定义标准内置对象的以下附加属性。

B.2.1 全局对象的附加属性

将 表 103 中的条目添加到 表 6。

表 103: 附加知名固有对象
固有名称 全局名称 ECMAScript 语言关联
%escape% "escape" escape 函数(B.2.1.1)
%unescape% "unescape" unescape 函数(B.2.1.2)

B.2.1.1 escape ( string )

此函数是全局对象的属性。它计算 String 值的新版本,其中某些码元被替换为十六进制转义序列。

替换数值小于或等于 0x00FF 的码元时,使用形式为 %xx 的两位转义序列。替换数值严格大于 0x00FF 的码元时,使用形式为 %uxxxx 的四位转义序列。

它是 %escape% 固有对象。

调用时,它执行以下步骤:

  1. 将 string 设置为 ? ToString(string)。
  2. 令 length 为 string 的长度。
  3. 令 result 为空 String。
  4. 令 unescapedSet 为 ASCII word characters 与 "@*+-./" 的字符串连接。
  5. 令 k 为 0。
  6. 当 k < length 时,重复执行,
    1. 令 codeUnit 为 string 中索引 k 处的码元。
    2. 如果 unescapedSet 包含 codeUnit,则
      1. 令 nextPart 为 codeUnit。
    3. 否则,
      1. 令 codeUnitNumber 为 codeUnit 的数值。
      2. 如果 codeUnitNumber < 256,则
        1. 令 hex 为 codeUnitNumber 的 String 表示,格式化为大写十六进制数。
        2. 令 nextPart 为 "%" 和 StringPad(hex, 2, "0", start) 的字符串连接。
      3. 否则,
        1. 令 hex 为 codeUnitNumber 的 String 表示,格式化为大写十六进制数。
        2. 令 nextPart 为 "%u" 和 StringPad(hex, 4, "0", start) 的字符串连接。
    4. 将 result 设置为 result 和 nextPart 的字符串连接。
    5. 将 k 设置为 k + 1。
  7. 返回 result。
注

此编码部分基于 RFC 1738 中描述的编码,但本标准规定的完整编码已在上文描述,与 RFC 1738 的内容无关。此编码不反映 RFC 3986 对 RFC 1738 所作的更改。

B.2.1.2 unescape ( string )

此函数是全局对象的属性。它计算 String 值的新版本,其中每个可能由 escape 函数引入的转义序列都被替换为其所表示的码元。

它是 %unescape% 固有对象。

调用时,它执行以下步骤:

  1. 将 string 设置为 ? ToString(string)。
  2. 令 length 为 string 的长度。
  3. 令 result 为空 String。
  4. 令 k 为 0。
  5. 当 k < length 时,重复执行,
    1. 令 codeUnit 为 string 中索引 k 处的码元。
    2. 如果 codeUnit 是码元 0x0025 (PERCENT SIGN),则
      1. 令 hexDigits 为空 String。
      2. 令 optionalAdvance 为 0。
      3. 如果 k + 5 < length 且 string 中索引 k + 1 处的码元是码元 0x0075 (LATIN SMALL LETTER U),则
        1. 将 hexDigits 设置为 string 从 k + 2 到 k + 6 的子字符串。
        2. 将 optionalAdvance 设置为 5。
      4. 否则如果 k + 3 ≤ length,则
        1. 将 hexDigits 设置为 string 从 k + 1 到 k + 3 的子字符串。
        2. 将 optionalAdvance 设置为 2。
      5. 令 parseResult 为 ParseText(hexDigits, HexDigits[~Sep])。
      6. 如果 parseResult 是 Parse Node,则
        1. 令 codeUnitNumber 为 the MV of parseResult。
        2. 将 codeUnit 设置为数值为 codeUnitNumber 的码元。
        3. 将 k 设置为 k + optionalAdvance。
    3. 将 result 设置为 result 和 codeUnit 的字符串连接。
    4. 将 k 设置为 k + 1。
  6. 返回 result。

B.2.2 String.prototype 对象的附加属性

B.2.2.1 String.prototype.substr ( start, length )

此方法返回将 this value 转换为 String 的结果的一个子字符串,从索引 start 开始并持续 length 个码元(如果 length 是 undefined,则持续到 String 末尾)。如果 start 为负数,则将其视为 sourceLength + start,其中 sourceLength 是 String 的长度。结果是 String 值,而不是 String 对象。

调用时,它执行以下步骤:

  1. 令 obj 为 this value。
  2. 执行 ? RequireObjectCoercible(obj)。
  3. 令 string 为 ? ToString(obj)。
  4. 令 size 为 string 的长度。
  5. 令 intStart 为 ? ToClampedIndex(start, size)。
  6. 如果 length 是 undefined,则令 intLength 为 size;否则令 intLength 为将 ? ToIntegerOrInfinity(length) 限制在 0 和 size 之间的结果。
  7. 令 intEnd 为 min(intStart + intLength, size)。
  8. 返回 string 从 intStart 到 intEnd 的子字符串。
注

此方法有意设计为泛型;它不要求其 this value 是 String 对象。因此,它可以转移到其他种类的对象上用作方法。

B.2.2.2 String.prototype.anchor ( name )

调用时,此方法执行以下步骤:

  1. 令 string 为 this value。
  2. 返回 ? CreateHTML(string, "a", "name", name)。

B.2.2.2.1 CreateHTML ( contents, tag, attr, attrValue )

抽象操作 CreateHTML,接收参数 contents (ECMAScript 语言值)、tag (String)、attr (String) 和 attrValue (ECMAScript 语言值);返回值:(正常完成 (值:String) 或 抛出完成)。 调用时执行以下步骤:

  1. 执行 ? RequireObjectCoercible(contents)。
  2. 令 contentsString 为 ? ToString(contents)。
  3. 令 part1 为 "<" 和 tag 的字符串连接。
  4. 如果 attr 不是空 String,则
    1. 令 attrValueString 为 ? ToString(attrValue)。
    2. 令 escapedAttrValue 为一个 String 值,它与 attrValueString 相同,但 attrValueString 中每次出现的码元 0x0022 (QUOTATION MARK) 都被替换为六个码元组成的序列 "&quot;"。
    3. 将 part1 设置为以下各项的字符串连接:
      • part1
      • 码元 0x0020 (SPACE)
      • attr
      • 码元 0x003D (EQUALS SIGN)
      • 码元 0x0022 (QUOTATION MARK)
      • escapedAttrValue
      • 码元 0x0022 (QUOTATION MARK)
  5. 令 part2 为 part1 和 ">" 的字符串连接。
  6. 令 part3 为 part2 和 contentsString 的字符串连接。
  7. 令 part4 为 part3、"</"、tag 和 ">" 的字符串连接。
  8. 返回 part4。

B.2.2.3 String.prototype.big ( )

调用时,此方法执行以下步骤:

  1. 令 string 为 this value。
  2. 返回 ? CreateHTML(string, "big", "", "")。

B.2.2.4 String.prototype.blink ( )

调用时,此方法执行以下步骤:

  1. 令 string 为 this value。
  2. 返回 ? CreateHTML(string, "blink", "", "")。

B.2.2.5 String.prototype.bold ( )

调用时,此方法执行以下步骤:

  1. 令 string 为 this value。
  2. 返回 ? CreateHTML(string, "b", "", "")。

B.2.2.6 String.prototype.fixed ( )

调用时,此方法执行以下步骤:

  1. 令 string 为 this value。
  2. 返回 ? CreateHTML(string, "tt", "", "")。

B.2.2.7 String.prototype.fontcolor ( colour )

调用时,此方法执行以下步骤:

  1. 令 string 为 this value。
  2. 返回 ? CreateHTML(string, "font", "color", colour)。

B.2.2.8 String.prototype.fontsize ( size )

调用时,此方法执行以下步骤:

  1. 令 string 为 this value。
  2. 返回 ? CreateHTML(string, "font", "size", size)。

B.2.2.9 String.prototype.italics ( )

调用时,此方法执行以下步骤:

  1. 令 string 为 this value。
  2. 返回 ? CreateHTML(string, "i", "", "")。

B.2.2.10 String.prototype.link ( url )

调用时,此方法执行以下步骤:

  1. 令 string 为 this value。
  2. 返回 ? CreateHTML(string, "a", "href", url)。

B.2.2.11 String.prototype.small ( )

调用时,此方法执行以下步骤:

  1. 令 string 为 this value。
  2. 返回 ? CreateHTML(string, "small", "", "")。

B.2.2.12 String.prototype.strike ( )

调用时,此方法执行以下步骤:

  1. 令 string 为 this value。
  2. 返回 ? CreateHTML(string, "strike", "", "")。

B.2.2.13 String.prototype.sub ( )

调用时,此方法执行以下步骤:

  1. 令 string 为 this value。
  2. 返回 ? CreateHTML(string, "sub", "", "")。

B.2.2.14 String.prototype.sup ( )

调用时,此方法执行以下步骤:

  1. 令 string 为 this value。
  2. 返回 ? CreateHTML(string, "sup", "", "")。

B.2.2.15 String.prototype.trimLeft ( )

注

首选 "trimStart" 属性。"trimLeft" 属性主要为了兼容旧代码而提供。建议新的 ECMAScript 代码使用 "trimStart" 属性。

"trimLeft" 属性的初始值是 22.1.3.34 中定义的 %String.prototype.trimStart%。

B.2.2.16 String.prototype.trimRight ( )

注

首选 "trimEnd" 属性。"trimRight" 属性主要为了兼容旧代码而提供。建议新的 ECMAScript 代码使用 "trimEnd" 属性。

"trimRight" 属性的初始值是 22.1.3.33 中定义的 %String.prototype.trimEnd%。

B.2.3 Date.prototype 对象的附加属性

B.2.3.1 Date.prototype.getYear ( )

注

对于几乎所有用途,都首选 getFullYear 方法,因为它避免了“2000 年问题”。

调用时,此方法执行以下步骤:

  1. 令 dateObj 为 this value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. 令 tv 为 dateObj.[[DateValue]]。
  4. 如果 tv 是 NaN,则返回 NaN。
  5. 返回 𝔽(YearFromTime(LocalTime(tv))) - 1900𝔽。

B.2.3.2 Date.prototype.setYear ( year )

注

对于几乎所有用途,都首选 setFullYear 方法,因为它避免了“2000 年问题”。

调用时,此方法执行以下步骤:

  1. 令 dateObj 为 this value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. 令 time 为 dateObj.[[DateValue]]。
  4. 如果 time 是 NaN,则将 time 设置为 +0𝔽;否则将 time 设置为 LocalTime(time)。
  5. 令 fullYear 为 MakeFullYear(? ToNumber(year))。
  6. 令 day 为 MakeDay(fullYear, 𝔽(MonthFromTime(time)), 𝔽(DateFromTime(time)))。
  7. 令 date 为 MakeDate(day, 𝔽(TimeWithinDay(time)))。
  8. 令 utcTimestamp 为 TimeClip(UTC(date))。
  9. 将 dateObj.[[DateValue]] 设置为 utcTimestamp。
  10. 返回 utcTimestamp。

B.2.3.3 Date.prototype.toGMTString ( )

注

首选 toUTCString 方法。此方法主要为了兼容旧代码而提供。

"toGMTString" 属性的初始值是 21.4.4.43 中定义的 %Date.prototype.toUTCString%。

B.2.4 RegExp.prototype 对象的附加属性

B.2.4.1 RegExp.prototype.compile ( pattern, flags )

调用时,此方法执行以下步骤:

  1. 令 obj 为 this value。
  2. 执行 ? RequireInternalSlot(obj, [[RegExpMatcher]])。
  3. 如果 pattern 是 Object 且 pattern 具有 [[RegExpMatcher]] 内部槽,则
    1. 如果 flags 不是 undefined,则抛出 TypeError 异常。
    2. 将 flags 设置为 pattern.[[OriginalFlags]]。
    3. 将 pattern 设置为 pattern.[[OriginalSource]]。
  4. 返回 ? RegExpInitialize(obj, pattern, flags)。
注

此方法使用新的模式和标志完全重新初始化作为 this value 的 RegExp。实现可以将使用此方法解释为一种断言,即生成的 RegExp 对象将被多次使用,因此是进行额外优化的候选对象。

B.3 其他附加特性

B.3.1 带标签的函数声明

在 ECMAScript 2015 之前,LabelledStatement 的规范不允许将语句标签与 FunctionDeclaration 关联。不过,带标签的 FunctionDeclaration 是非严格代码允许的扩展,并且大多数浏览器宿主的 ECMAScript 实现都支持该扩展。在 ECMAScript 2015 及更高版本中,LabelledStatement 的文法产生式允许将 FunctionDeclaration 用作 LabelledItem,但 14.13.1 包含一条提前错误规则,如果发生这种情况会产生 Syntax Error。如果宿主支持此特性,该规则随后会被修改,以便在非严格代码中抑制 Syntax Error。

注

B.3.2 块级函数声明的 Web 遗留兼容性语义

在 ECMAScript 2015 之前,ECMAScript 规范未定义 FunctionDeclaration 作为 Block 语句的 StatementList 元素出现的情况。不过,支持这种形式的 FunctionDeclaration 是允许的扩展,并且大多数浏览器宿主的 ECMAScript 实现都允许它们。不幸的是,这类声明的语义在不同实现之间有所不同。由于这些语义差异,使用 Block 级函数声明的现有 Web ECMAScript 源文本,只有当其使用方式仅依赖所有浏览器实现对此类声明语义的交集时,才能在浏览器实现之间移植。以下用例属于该交集语义:

  1. 函数在单个块内声明,并且仅在该块内被引用。

  2. 函数在单个 Block 内声明并可能在其中使用,但也被不包含在同一 Block 内的内部函数定义引用。

  3. 函数在单个块内声明并可能在其中使用,但也在后续块中被引用。

第一个用例与 ECMAScript 2015 提供的 Block 级函数声明语义具有互操作性。任何使用该用例的既有 ECMAScript 源文本都会使用条款 10、14 和 15 中定义的块级函数声明语义运行。

第二和第三个用例与 ECMAScript 2015 的互操作性需要对条款 10、条款 15、条款 19.2.1 和条款 16.1.7 的语义进行以下扩展。

如果 ECMAScript 实现具有报告诊断警告消息的机制,那么当代码包含应用这些兼容性语义的 FunctionDeclaration 且会引入相对于非兼容性语义可观察到的差异时,应产生警告。例如,如果因为引入 var 绑定会创建提前错误而未引入该绑定,则不应产生警告消息。

此特性在以下位置涉及特殊语义:

B.3.3 IfStatement 语句子句中的 FunctionDeclaration

以下内容扩充 14.6 中的 IfStatement 产生式:

IfStatement[Yield, Await, Return] : if ( Expression[+In, ?Yield, ?Await] ) FunctionDeclaration[?Yield, ?Await, ~Default] else Statement[?Yield, ?Await, ?Return] if ( Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] else FunctionDeclaration[?Yield, ?Await, ~Default] if ( Expression[+In, ?Yield, ?Await] ) FunctionDeclaration[?Yield, ?Await, ~Default] else FunctionDeclaration[?Yield, ?Await, ~Default] if ( Expression[+In, ?Yield, ?Await] ) FunctionDeclaration[?Yield, ?Await, ~Default] [lookahead ≠ else]

此产生式仅在解析非严格代码时适用。与此产生式匹配的源文本按如下方式处理:将每个匹配的 FunctionDeclaration[?Yield, ?Await, ~Default] 出现位置视为一个占据源文本中该位置的 BlockStatement 的唯一 StatementListItem。这种合成 BlockStatement 的语义包括 B.3.2 中规定的 Web 遗留兼容性语义。

B.3.4 Catch 块中的 VariableStatement

在此特性中,Catch 子句的 Block 可以包含 var 声明,该声明绑定一个也由 CatchParameter 绑定的名称。这通过修改 14.15.1 中 Catch : catch ( CatchParameter ) Block 的一条提前错误规则来实现。

注

在运行时,此类绑定会在 VariableDeclarationEnvironment 中实例化。它们不会遮蔽由 CatchParameter 引入的同名绑定,因此此类 var 声明的 Initializer 会赋值给对应的 catch 参数,而不是 var 绑定。

这种修改后的行为也适用于 Catch 子句的 Block 中包含的直接 eval 调用所引入的 var 和 function 声明。此更改通过修改 EvalDeclarationInstantiation 中的步骤 3.d.i.2.a.i 和 13.b.ii.4.a.i.i 来实现。

B.3.5 ForIn 语句头中的初始化器

以下内容扩充 14.7.5 中的 ForInOfStatement 产生式:

ForInOfStatement[Yield, Await, Return] : for ( var BindingIdentifier[?Yield, ?Await] Initializer[~In, ?Yield, ?Await] in Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return]

此产生式仅在解析非严格代码时适用。

带参数 labelSet 的 ContainsDuplicateLabels 静态语义扩充如下:

ForInOfStatement : for ( var BindingIdentifier Initializer in Expression ) Statement
  1. 返回 ContainsDuplicateLabels of Statement with argument labelSet。

带参数 labelSet 的 ContainsUndefinedBreakTarget 静态语义扩充如下:

ForInOfStatement : for ( var BindingIdentifier Initializer in Expression ) Statement
  1. 返回 ContainsUndefinedBreakTarget of Statement with argument labelSet。

带参数 iterationSet 和 labelSet 的 ContainsUndefinedContinueTarget 静态语义扩充如下:

ForInOfStatement : for ( var BindingIdentifier Initializer in Expression ) Statement
  1. 返回 ContainsUndefinedContinueTarget of Statement with arguments iterationSet and « »。

IsDestructuring 静态语义扩充如下:

BindingIdentifier : Identifier yield await
  1. 返回 false。

VarDeclaredNames 静态语义扩充如下:

ForInOfStatement : for ( var BindingIdentifier Initializer in Expression ) Statement
  1. 令 names1 为 the BoundNames of BindingIdentifier。
  2. 令 names2 为 the VarDeclaredNames of Statement。
  3. 返回 names1 和 names2 的列表连接。

VarScopedDeclarations 静态语义扩充如下:

ForInOfStatement : for ( var BindingIdentifier Initializer in Expression ) Statement
  1. 令 decls1 为 « BindingIdentifier »。
  2. 令 decls2 为 the VarScopedDeclarations of Statement。
  3. 返回 decls1 和 decls2 的列表连接。

带参数 labelSet 的 ForInOfLoopEvaluation 运行时语义扩充如下:

ForInOfStatement : for ( var BindingIdentifier Initializer in Expression ) Statement
  1. 令 name 为 the StringValue of BindingIdentifier。
  2. 令 lhs 为 ? ResolveBinding(name)。
  3. 如果 IsAnonymousFunctionDefinition(Initializer) 是 true,则
    1. 令 value 为 ? NamedEvaluation of Initializer with argument name。
  4. 否则,
    1. 令 rhs 为 ? Evaluation of Initializer。
    2. 令 value 为 ? GetValue(rhs)。
  5. 执行 ? PutValue(lhs, value)。
  6. 令 keyResult 为 ? ForIn/OfHeadEvaluation(« », Expression, enumerate)。
  7. 返回 ? ForIn/OfBodyEvaluation(BindingIdentifier, Statement, keyResult, enumerate, var-binding, labelSet)。

B.3.6 [[IsHTMLDDA]] 内部槽

宿主定义对象上可以存在 [[IsHTMLDDA]] 内部槽。具有 [[IsHTMLDDA]] 内部槽的对象在 ToBoolean 和 IsLooselyEqual 抽象操作中,以及作为 typeof 运算符的操作数时,其行为类似于 undefined。

注

本规范从不创建具有 [[IsHTMLDDA]] 内部槽的对象。不过,Web 浏览器中的 document.all 对象是出于 Web 兼容性目的而存在的、具有此槽的宿主定义异质对象。除此之外,没有其他已知的此类对象示例,实现不应创建任何此类对象,document.all 除外。

此特性在以下位置涉及特殊语义:

B.3.7 HostMakeJobCallback 中的非默认行为

HostMakeJobCallback 抽象操作允许属于 Web 浏览器的宿主规定非默认行为。

B.3.8 HostEnsureCanAddPrivateElement 中的非默认行为

HostEnsureCanAddPrivateElement 抽象操作允许属于 Web 浏览器的宿主规定非默认行为。

B.3.9 函数调用赋值目标的运行时错误

当函数调用(13.3.6)在非严格代码中用作赋值目标时,不会产生提前错误,而是在赋值求值期间抛出 ReferenceError 异常。

注

当赋值目标是 AssignmentExpression 的 LeftHandSideExpression 时,赋值运算符必须是 = 或 AssignmentOperator;尤其是,此处的允许不适用于逻辑赋值运算符(??=、&&=、||=)。

参见 AssignmentTargetType 针对 CallExpression : CoverCallExpressionAndAsyncArrowHead 和 CallExpression : CallExpression Arguments 的步骤 1。

附录 C (资料性) ECMAScript 的严格模式

严格模式的限制和例外

附录 D (资料性) 宿主分层点

宿主的定义参见 4.2。

D.1 宿主钩子

HostCallJobCallback(...)

HostEnqueueFinalizationRegistryCleanupJob(...)

HostEnqueueGenericJob(...)

HostEnqueuePromiseJob(...)

HostEnqueueTimeoutJob(...)

HostEnsureCanCompileStrings(...)

HostFinalizeImportMeta(...)

HostGetImportMetaProperties(...)

HostGrowSharedArrayBuffer(...)

HostHasSourceTextAvailable(...)

HostLoadImportedModule(...)

HostGetSupportedImportAttributes(...)

HostMakeJobCallback(...)

HostPromiseRejectionTracker(...)

HostResizeArrayBuffer(...)

InitializeHostDefinedRealm(...)

D.2 宿主定义字段

Realm Record 上的 [[HostDefined]]:参见 表 20。

Script Record 上的 [[HostDefined]]:参见 表 35。

Module Record 上的 [[HostDefined]]:参见 表 39。

JobCallback Record 上的 [[HostDefined]]:参见 表 24。

[[IsHTMLDDA]]:参见 B.3.6。

D.3 宿主定义对象

全局对象:参见条款 19。

D.4 运行 Job

调用 Job Abstract Closure 之前的准备步骤,以及调用之后的清理步骤。参见 9.5。

D.5 异质对象的内部方法

对于本规范未规定的任何异质对象,表 4 中的任何必要内部方法。

D.6 内置对象和方法

本规范中未定义的任何内置对象和方法,但受 17.1 限制的除外。

附录 E (资料性) ECMAScript 2015 中可能影响兼容性的更正和澄清

9.1.1.4.14-9.1.1.4.17 第 5 版和第 5.1 版使用属性存在性测试来确定与新的全局声明对应的全局对象属性是否已经存在。ECMAScript 2015 使用自有属性存在性测试。这与 Web 浏览器最常见的实现方式一致。

10.4.2.1:第 5 版将当前数组长度的捕获移动到数组索引或新长度值的整数转换之前。不过,如果转换过程具有改变数组长度的副作用,则捕获的长度值可能变得无效。ECMAScript 2015 规定,必须在可能发生此类副作用之后捕获当前数组长度。

21.4.1.31:以前的版本允许 TimeClip 抽象操作返回 +0𝔽 或 -0𝔽 作为 0 时间值的表示。ECMAScript 2015 规定始终返回 +0𝔽。这意味着在 ECMAScript 2015 中,Date 的时间值永远不会可观察地为 -0𝔽,并且返回时间值的方法永远不会返回 -0𝔽。

21.4.1.32:如果不存在 UTC 偏移表示,则使用本地时区。第 5.1 版错误地规定,缺失的时区应解释为 "z"。

21.4.4.36:如果年份无法使用 21.4.1.32 中规定的 Date Time String Format 表示,则抛出 RangeError 异常。以前的版本没有规定这种情况的行为。

21.4.4.41:以前的版本没有规定当时间值为 NaN 时 Date.prototype.toString 返回的值。ECMAScript 2015 规定结果为 String 值 "Invalid Date"。

22.2.4.1、22.2.6.13.1:RegExp 实例的 "source" 属性值中的任何 LineTerminator 码点都必须使用转义序列表示。第 5.1 版只要求转义 /。

22.2.6.8、22.2.6.11:在以前的版本中,当 pattern 参数是 global 标志已设置的 RegExp 值时,String.prototype.match 和 String.prototype.replace 的规范存在错误。以前的规范规定,对于每次尝试匹配模式,如果 lastIndex 未改变,则应将其增加 1。正确行为是,仅当模式匹配空 String 时才应将 lastIndex 增加 1。

23.1.3.30:以前的版本没有规定如何解释 comparator 返回的 NaN 值。ECMAScript 2015 规定,此类值按 comparator 返回 +0𝔽 来处理。ECMAScript 2015 还规定对 comparator 返回的结果应用 ToNumber。在以前的版本中,comparator 结果不是 Number 值时的效果是实现定义的。实际中,实现会调用 ToNumber。

附录 F (资料性) 引入与以前版本不兼容性的新增内容和更改

6.2.5:在 ECMAScript 2015 中,不允许 Function 调用返回 Reference Record。

7.1.4.1:在 ECMAScript 2015 中,对 String 值应用 ToNumber 现在会识别并转换 BinaryIntegerLiteral 和 OctalIntegerLiteral 数值字符串。在以前的版本中,此类字符串会被转换为 NaN。

9.3:在 ECMAScript 2018 中,Template 对象基于 Parse Node(源位置)进行规范化,而以前的版本是在 Realm 中该模板字面量或带标签模板的所有出现位置之间进行规范化。

12.2:ECMAScript 2016 强制要求 Unicode 8.0.0 或更高版本,而 ECMAScript 2015 强制要求 Unicode 5.1。尤其是,这导致 U+180E MONGOLIAN VOWEL SEPARATOR 从 Space_Separator(Zs)类别(因此在 ECMAScript 2015 中被视为空白)移动到 Format(Cf)类别(自 Unicode 6.3.0 起)。这会导致对空白敏感的方法产生不同的行为。例如,"\u180E".trim().length 在以前版本中为 0,但在 ECMAScript 2016 及更高版本中为 1。此外,ECMAScript 2017 强制规定始终使用 Unicode 标准的最新版本。

12.7:在 ECMAScript 2015 中,IdentifierName 的有效码点使用 Unicode 属性“ID_Start”和“ID_Continue”来规定。在以前的版本中,有效的 IdentifierName 或 Identifier 码点通过枚举各种 Unicode 码点类别来规定。

12.10.1:在 ECMAScript 2015 中,如果 do-while 语句末尾缺少分号,自动分号插入会在其末尾添加分号。此更改使规范与大多数现有实现的实际行为一致。

13.2.5.1:在 ECMAScript 2015 中,Object Initializer 中存在重复属性名称不再是提前错误。

13.15.1:在 ECMAScript 2015 中,严格模式代码如果包含对不可变绑定(例如 FunctionExpression 的函数名称)的赋值,不会产生提前错误,而是产生运行时错误。

14.2:在 ECMAScript 2015 中,以 token let 开头,后跟输入元素 LineTerminator,再后跟 Identifier 的 StatementList 是 LexicalDeclaration 的开始。在以前的版本中,自动分号插入始终会在 Identifier 输入元素之前插入分号。

14.5:在 ECMAScript 2015 中,以 token let 开头且后跟 token [ 的 StatementListItem 是 LexicalDeclaration 的开始。在以前的版本中,这种序列会是 ExpressionStatement 的开始。

14.6.2:在 ECMAScript 2015 中,IfStatement 的正常结果永远不会是值 empty。如果没有对 Statement 部分求值,或者求值的 Statement 部分产生包含 empty 的正常完成,则 IfStatement 的结果是 undefined。

14.7:在 ECMAScript 2015 中,如果 for 语句的 ( token 后面紧接 token 序列 let [,则该 let 被视为 LexicalDeclaration 的开始。在以前的版本中,这种 token 序列会是 Expression 的开始。

14.7:在 ECMAScript 2015 中,如果 for-in 语句的 ( token 后面紧接 token 序列 let [,则该 let 被视为 ForDeclaration 的开始。在以前的版本中,这种 token 序列会是 LeftHandSideExpression 的开始。

14.7:在 ECMAScript 2015 之前,初始化表达式可以作为位于 in 关键字之前的 VariableDeclaration 的一部分出现。在 ECMAScript 2015 中,相同位置的 ForBinding 不允许出现此类初始化器。在 ECMAScript 2017 中,此类初始化器只允许出现在非严格代码中。

14.7:在 ECMAScript 2015 中,对 IterationStatement 求值的结果永远不会是 [[Value]] 为 empty 的正常完成。如果没有对 IterationStatement 的 Statement 部分求值,或者最后一次对 Statement 部分求值产生 [[Value]] 为 empty 的正常完成,则对 IterationStatement 求值的结果是 [[Value]] 为 undefined 的正常完成。

14.11.2:在 ECMAScript 2015 中,对 WithStatement 求值的结果永远不会是 [[Value]] 为 empty 的正常完成。如果对 WithStatement 的 Statement 部分求值产生 [[Value]] 为 empty 的正常完成,则对 WithStatement 求值的结果是 [[Value]] 为 undefined 的正常完成。

14.12.4:在 ECMAScript 2015 中,对 SwitchStatement 求值的结果永远不会是 [[Value]] 为 empty 的正常完成。如果对 SwitchStatement 的 CaseBlock 部分求值产生 [[Value]] 为 empty 的正常完成,则对 SwitchStatement 求值的结果是 [[Value]] 为 undefined 的正常完成。

14.15:在 ECMAScript 2015 中,如果 Catch 子句包含一个 var 声明,而该声明使用了与 Catch 子句参数相同的 Identifier,则为提前错误。在以前的版本中,此类变量声明会在外层变量环境中实例化,但声明的 Initializer 值会赋给 Catch 参数。

14.15、19.2.1.3:在 ECMAScript 2015 中,如果 Catch 子句对非严格直接 eval 求值,并且其 eval 代码包含绑定与 Catch 子句参数相同 Identifier 的 var 或 FunctionDeclaration 声明,则会抛出运行时 SyntaxError。

14.15.3:在 ECMAScript 2015 中,TryStatement 的结果永远不会是值 empty。如果 TryStatement 的 Block 部分求值为包含 empty 的正常完成,则 TryStatement 的结果是 undefined。如果 TryStatement 的 Block 部分求值为抛出完成,并且其具有求值为包含 empty 的正常完成的 Catch 部分,那么如果不存在 Finally 子句,或者其 Finally 子句求值为 empty 正常完成,则 TryStatement 的结果是 undefined。

15.4.5 在 ECMAScript 2015 中,作为 ObjectLiteral 中访问器属性 [[Getter]] 或 [[Setter]] 特性值创建的函数对象不是构造函数,并且不具有 "prototype" 自有属性。在以前的版本中,它们是构造函数并具有 "prototype" 属性。

20.1.2.6:在 ECMAScript 2015 中,如果 Object.freeze 的参数不是对象,则将其视为没有自有属性的不可扩展普通对象。在以前的版本中,非对象参数始终会导致抛出 TypeError。

20.1.2.8:在 ECMAScript 2015 中,如果 Object.getOwnPropertyDescriptor 的参数不是对象,则尝试使用 ToObject 强制转换该参数。如果转换成功,则使用结果代替原始参数值。在以前的版本中,非对象参数始终会导致抛出 TypeError。

20.1.2.10:在 ECMAScript 2015 中,如果 Object.getOwnPropertyNames 的参数不是对象,则尝试使用 ToObject 强制转换该参数。如果转换成功,则使用结果代替原始参数值。在以前的版本中,非对象参数始终会导致抛出 TypeError。

20.1.2.12:在 ECMAScript 2015 中,如果 Object.getPrototypeOf 的参数不是对象,则尝试使用 ToObject 强制转换该参数。如果转换成功,则使用结果代替原始参数值。在以前的版本中,非对象参数始终会导致抛出 TypeError。

20.1.2.16:在 ECMAScript 2015 中,如果 Object.isExtensible 的参数不是对象,则将其视为没有自有属性的不可扩展普通对象。在以前的版本中,非对象参数始终会导致抛出 TypeError。

20.1.2.17:在 ECMAScript 2015 中,如果 Object.isFrozen 的参数不是对象,则将其视为没有自有属性的不可扩展普通对象。在以前的版本中,非对象参数始终会导致抛出 TypeError。

20.1.2.18:在 ECMAScript 2015 中,如果 Object.isSealed 的参数不是对象,则将其视为没有自有属性的不可扩展普通对象。在以前的版本中,非对象参数始终会导致抛出 TypeError。

20.1.2.19:在 ECMAScript 2015 中,如果 Object.keys 的参数不是对象,则尝试使用 ToObject 强制转换该参数。如果转换成功,则使用结果代替原始参数值。在以前的版本中,非对象参数始终会导致抛出 TypeError。

20.1.2.20:在 ECMAScript 2015 中,如果 Object.preventExtensions 的参数不是对象,则将其视为没有自有属性的不可扩展普通对象。在以前的版本中,非对象参数始终会导致抛出 TypeError。

20.1.2.22:在 ECMAScript 2015 中,如果 Object.seal 的参数不是对象,则将其视为没有自有属性的不可扩展普通对象。在以前的版本中,非对象参数始终会导致抛出 TypeError。

20.2.3.2:在 ECMAScript 2015 中,绑定函数的 [[Prototype]] 内部槽被设置为其目标函数的 [[GetPrototypeOf]] 值。在以前的版本中,[[Prototype]] 始终设置为 %Function.prototype%。

20.2.4.1:在 ECMAScript 2015 中,函数实例的 "length" 属性是可配置的。在以前的版本中它不可配置。

20.5.6.2:在 ECMAScript 2015 中,NativeError 构造函数的 [[Prototype]] 内部槽是 Error 构造函数。在以前的版本中,它是 Function 原型对象。

21.4.4 在 ECMAScript 2015 中,Date 原型对象不是 Date 实例。在以前的版本中,它是 TimeValue 为 NaN 的 Date 实例。

22.1.3.12 在 ECMAScript 2015 中,String.prototype.localeCompare 函数必须将按照 Unicode 标准规范等价的 String 视为相同。在以前的版本中,实现可以忽略规范等价性,并改用按位比较。

22.1.3.28 和 22.1.3.30 在 ECMAScript 2015 中,小写/大写转换处理以码点为单位进行。在以前的版本中,这种转换处理只应用于单个码元。唯一受影响的码点是 Unicode Deseret 区块中的码点。

22.1.3.32 在 ECMAScript 2015 中,String.prototype.trim 方法被定义为识别可能存在于 Unicode BMP 之外的空白码点。不过,截至 Unicode 7 尚未定义此类码点。在以前的版本中,此类码点不会被识别为空白。

22.2.4.1 在 ECMAScript 2015 中,如果 pattern 参数是 RegExp 实例且 flags 参数不是 undefined,则创建一个与 pattern 相同的新 RegExp 实例,但将 pattern 的标志替换为参数 flags。在以前的版本中,当 pattern 是 RegExp 实例且 flags 不是 undefined 时,会抛出 TypeError 异常。

22.2.6 在 ECMAScript 2015 中,RegExp 原型对象不是 RegExp 实例。在以前的版本中,它是模式为空 String 的 RegExp 实例。

22.2.6 在 ECMAScript 2015 中,"source"、"global"、"ignoreCase" 和 "multiline" 是定义在 RegExp 原型对象上的访问器属性。在以前的版本中,它们是定义在 RegExp 实例上的数据属性。

25.4.10:在 ECMAScript 2019 中,Atomics.wake 已重命名为 Atomics.notify,以避免与 Atomics.wait 混淆。

27.1.5.4、27.9.3.6:在 ECMAScript 2019 中,await 入队的 Job 数量减少,这可能会导致 then() 调用与 await 表达式之间的解决顺序出现可观察差异。

参考文献

  1. IEEE 754-2019:IEEE 浮点算术标准。电气与电子工程师协会,纽约(2019) 注

    IEEE 754-2008 与 IEEE 754-2019 之间不存在影响 ECMA-262 规范的规范性更改。

  2. Unicode 标准,可在 <https://unicode.org/versions/latest> 获取
  3. Unicode 技术注释 #5:应用程序中的规范等价性,可在 <https://unicode.org/notes/tn5/> 获取
  4. Unicode 技术标准 #10:Unicode 排序算法,可在 <https://unicode.org/reports/tr10/> 获取
  5. Unicode 标准附录 #15,Unicode 规范化形式,可在 <https://unicode.org/reports/tr15/> 获取
  6. Unicode 标准附录 #18:Unicode 正则表达式,可在 <https://unicode.org/reports/tr18/> 获取
  7. Unicode 标准附录 #24:Unicode Script 属性,可在 <https://unicode.org/reports/tr24/> 获取
  8. Unicode 标准附录 #31,Unicode 标识符和模式语法,可在 <https://unicode.org/reports/tr31/> 获取
  9. Unicode 标准附录 #44:Unicode 字符数据库,可在 <https://unicode.org/reports/tr44/> 获取
  10. Unicode 技术标准 #51:Unicode Emoji,可在 <https://unicode.org/reports/tr51/> 获取
  11. IANA 时区数据库,可在 <https://www.iana.org/time-zones> 获取
  12. ISO 8601-1:2019(E) 日期和时间 — 信息交换表示法 — 第 1 部分:基本规则以及修正案 1:2022。
  13. RFC 1738 “统一资源定位符(URL)”,可在 <https://rfc-editor.org/info/rfc1738> 获取
  14. RFC 2396 “统一资源标识符(URI):通用语法”,可在 <https://rfc-editor.org/info/rfc2396> 获取
  15. RFC 3629 “UTF-8,ISO 10646 的一种转换格式”,可在 <https://rfc-editor.org/info/rfc3629> 获取
  16. RFC 7231 “超文本传输协议(HTTP/1.1):语义和内容”,可在 <https://rfc-editor.org/info/rfc7231> 获取
  17. RFC 9557 “互联网中的日期和时间:带附加信息的时间戳”,可在 <https://rfc-editor.org/info/rfc9557> 获取

编后记

本规范在 GitHub 上使用一种名为 Ecmarkup 的纯文本源格式编写。Ecmarkup 是 HTML 和 Markdown 的一种方言,为以纯文本编写 Ecma 规范并将规范处理成遵循本文档编辑约定的功能完整 HTML 渲染提供框架和工具集。Ecmarkup 构建于并集成了多种其他格式和技术,包括用于定义语法的 Grammarkdown 和用于编写算法步骤的 Ecmarkdown。本规范的 PDF 渲染使用利用 CSS Paged Media 规范的打印样式表生成,并使用 PrinceXML 转换。

本规范以前的版本使用 Word 编写——构成本版本基础的 Ecmarkup 源文本,是使用自动转换工具将 ECMAScript 2015 Word 文档转换为 Ecmarkup 生成的。

版权与软件许可

Ecma International

Rue du Rhone 114

CH-1204 Geneva

Tel: +41 22 849 6000

Fax: +41 22 849 6001

Web: https://ecma-international.org/

软件许可

All Software contained in this document ("Software") is protected by copyright and is being made available under the "BSD License", included below. This Software may be subject to third party rights (rights from parties other than Ecma International), including patent rights, and no licenses under such third party rights are granted under this license even if the third party concerned is a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS AVAILABLE AT https://ecma-international.org/memento/codeofconduct.htm FOR INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO IMPLEMENT ECMA INTERNATIONAL STANDARDS.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  3. Neither the name of the authors nor Ecma International may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ECMA INTERNATIONAL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.