Draft ECMA-262 / June 25, 2026

ECMAScript® 2027 语言规范

关于本规范

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

本文档以单页多页形式提供。

参与本规范

本规范在 GitHub 上借助 ECMAScript 社区的帮助进行开发。有多种方式可以参与本规范的开发:

有关本文档如何创建的更多信息,请参阅附录说明

引言

本 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 第 5th 版发布)将浏览器实现中已变得常见的对语言规范的事实解释规范化,并增加了对自第三版发布以来出现的新特性的支持。这些特性包括访问器属性、对象的反射式创建与检查、对属性属性的程序控制、额外的数组操作函数、对 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 引入了 Async Functions、Shared Memory 和 Atomics,以及较小的语言和库增强、缺陷修复和编辑更新。Async 函数通过为返回 Promise 的函数提供语法,改善了异步编程体验。Shared Memory 和 Atomics 引入了一种新的内存模型,允许多代理程序使用原子操作进行通信,这些原子操作即使在并行 CPU 上也能确保定义明确的执行顺序。它还包含了 Object 上的新静态方法:Object.valuesObject.entriesObject.getOwnPropertyDescriptors

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

ECMAScript 2019 引入了若干新的内置函数:Array.prototype 上用于扁平化数组的 flatflatMap、用于直接将 Object.entries 的返回值转换为新 Object 的 Object.fromEntries,以及 String.prototype 上作为已广泛实现但非标准的 String.prototype.trimLefttrimRight 内置函数更好命名替代项的 trimStarttrimEnd。此外,它还包含了若干语法和语义上的小更新。更新后的语法包括可选的 catch 绑定参数,以及允许字符串字面量中出现 U+2028(LINE SEPARATOR)和 U+2029(PARAGRAPH SEPARATOR),以与 JSON 对齐。其他更新包括要求 Array.prototype.sort 是稳定排序、要求 JSON.stringify 无论输入如何都返回格式良好的 UTF-8,以及通过要求 Function.prototype.toString 要么返回对应的原始源文本,要么返回标准占位符来澄清该方法。

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

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

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

ECMAScript 2023,第 14th 版,引入了 Array.prototypeTypedArray.prototype 上的 toSortedtoReversedwithfindLastfindLastIndex 方法,以及 Array.prototype 上的 toSpliced 方法;增加了对文件开头 #! 注释的支持,以更好地便于可执行 ECMAScript 文件;并允许将大多数 Symbols 用作弱集合中的键。

ECMAScript 2024,第 15th 版,添加了用于调整和转移 ArrayBuffers 与 SharedArrayBuffers 的设施;添加了新的 RegExp /v 标志,用于创建具备更高级特性、可处理字符串集合的 RegExps;并引入了用于构造 Promises 的便捷方法 Promise.withResolvers,用于聚合数据的 Object.groupByMap.groupBy 方法,用于异步等待共享内存变化的 Atomics.waitAsync 方法,以及用于检查并确保字符串只包含格式良好 Unicode 的 String.prototype.isWellFormedString.prototype.toWellFormed 方法。

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

ECMAScript 2026,第 17th 版,添加了 Math.sumPrecise,用于对不同量级的 Numbers 可迭代对象求和,同时最小化精度损失;Iterator.concat,用于串接迭代器;Array.fromAsync,用于从 async iterables 和其他异步源构造 Arrays;Error.isError,用于识别错误对象;向 Map.prototypeWeakMap.prototype 添加了方法,用于在键尚不存在时提供检索期间使用的默认值;向 Uint8Array 添加了方法,用于转换为十六进制和 base64 编码二进制数据的 Strings 以及从这些 Strings 转换回来;向 JSON.parse revivers 添加了一个参数,用于访问匹配的 JSON 源片段;以及 JSON.rawJSON,用于对原始值的 JSON.stringify 输出进行精细控制。

来自许多组织的数十名个人对本版以及之前各版在 Ecma TC39 内的发展作出了非常重要的贡献。此外,一个充满活力的社区已经形成,支持 TC39 的 ECMAScript 工作。该社区审阅了大量草案,提交了数千份缺陷报告,开展了实现实验,贡献了测试套件,并向全球开发者社区普及了 ECMAScript。遗憾的是,要识别并致谢每一位为此作出贡献的个人和组织是不可能的。

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

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

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

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

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

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

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

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

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

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

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 的一致实现可以选择实现或不实现 Normative Optional 子条款,除非另有说明。Web 浏览器通常被要求实现所有规范可选子条款。(参见附录 B。)如果实现了任何 Normative Optional 行为,则必须实现包含该行为的 Normative Optional 条款中的所有行为。Normative Optional 条款在本规范中用彩色框内的文字“Normative Optional”表示,如下所示。

2.1 示例 Normative Optional 条款标题

示例条款内容。

ECMAScript 的一致实现必须实现 Legacy 子条款,除非它们也被标记为 Normative Optional。Legacy 子条款中规定的所有语言特性和行为都具有一个或多个不良特征。然而,它们在现有应用中的持续使用阻止了它们从本规范中移除。这些特性不被视为 ECMAScript 语言核心的一部分。程序员在编写新的 ECMAScript 代码时,不应使用或假定这些特性和行为的存在。

2.2 示例 Legacy 条款标题

示例条款内容。

2.3 示例 Legacy Normative Optional 条款标题

示例条款内容。

3 规范性引用

以下引用文档对于本文档的应用是不可缺少的。对于有日期的引用,仅所引用的版本适用。对于无日期的引用,所引用文档的最新版本(包括任何修订)适用。

IEEE 754-2019IEEE 浮点算术标准

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

ISO/IEC 10646,信息技术 — 通用多八位编码字符集(UCS),加上 Amendment 1:2005、Amendment 2:2006、Amendment 3:2008、Amendment 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 代码任何试图为该属性赋不同值的操作都会失败。属性是容器,可持有其他对象、原始值函数。原始值是以下内置类型之一的成员:UndefinedNullBooleanNumberBigIntStringSymbol; 对象是内置类型 Object 的成员;函数是可调用对象。通过属性与对象关联的函数称为方法

ECMAScript 定义了一组内置对象,用于完善 ECMAScript 实体的定义。这些内置对象包括全局对象;对语言运行时语义至关重要的对象,包括 ObjectFunctionBooleanSymbol 和各种 Error 对象;表示和操纵数值的对象,包括 MathNumberDate;文本处理对象 StringRegExp;作为值的索引集合的对象,包括 Array 和九种不同类型的 Typed Arrays,其元素均具有特定的数值数据表示;键控集合,包括 MapSet 对象;支持结构化数据的对象,包括 JSON 对象、ArrayBufferSharedArrayBufferDataView;支持控制抽象的对象,包括生成器函数和 Promise 对象;以及反射对象,包括 ProxyReflect

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 隐式引用,依此类推;这称为原型链。当引用对象中的某个属性时,该引用指向原型链中第一个包含该名称属性的对象中的该名称属性。换言之,首先检查直接提到的对象是否有这样的属性;如果该对象包含该命名属性,这就是该引用所指的属性;如果该对象不包含该命名属性,则接着检查该对象的原型;依此类推。

Figure 1: Object/Prototype Relationships
An image of lots of boxes and arrows.

在基于类的面向对象语言中,一般来说,状态由实例承载,方法由类承载,而继承只继承结构和行为。在 ECMAScript 中,状态和方法由对象承载,而结构、行为和状态都会被继承。

所有不直接包含其原型所包含的某个特定属性的对象,都共享该属性及其值。图 1 说明了这一点:

CF 是一个构造函数(同时也是一个对象)。使用 new 表达式创建了五个对象:cf1cf2cf3cf4cf5。这些对象各自都包含名为 "q1""q2" 的属性。虚线表示隐式原型关系;因此,例如,cf3 的原型是 CFp构造函数 CF 自身具有两个属性,名为 "P1""P2",它们对 CFpcf1cf2cf3cf4cf5 均不可见。CFp 中名为 "CFP1" 的属性由 cf1cf2cf3cf4cf5 共享(但不由 CF 共享),CFp 的隐式原型链中任何不名为 "q1""q2""CFP1" 的属性也是如此。注意,CFCFp 之间没有隐式原型链接。

不同于大多数基于类的对象语言,可以通过向对象赋值来动态添加属性。也就是说,构造函数不要求命名或赋值给所构造对象的全部或任何属性。在上图中,可以通过为 CFp 中的属性赋新值,为 cf1cf2cf3cf4cf5 添加一个新的共享属性。

虽然 ECMAScript 对象并非内在地基于类,但基于构造函数、原型对象和方法的常见模式来定义类似类的抽象通常很方便。ECMAScript 内置对象本身就遵循这种类似类的模式。从 ECMAScript 2015 开始,ECMAScript 语言包含语法化的类定义,允许程序员简洁地定义符合内置对象所用同一类似类抽象模式的对象。

4.3.2 ECMAScript 的严格变体

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

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

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

4.4 术语和定义

为本文档之目的,适用以下术语和定义。

4.4.1 implementation-approximated

实现近似的设施整体或部分由外部来源定义,但在本规范中具有推荐的理想行为

4.4.2 implementation-defined

实现定义的设施整体或部分由本规范的外部来源定义

4.4.3 host-defined

与 implementation-defined 相同

Note

编辑上,参见条款 4.2

4.4.4 type

如条款 6 中定义的数据值集合

4.4.5 primitive value

如条款 6 中定义的 Undefined、Null、Boolean、Number、BigInt、Symbol 或 String 类型之一的成员

Note

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

4.4.6 object

Object 类型的成员

Note

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

4.4.7 constructor

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

Note

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

4.4.8 prototype

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

Note

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

4.4.9 ordinary object

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

4.4.10 exotic object

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

Note

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

4.4.11 standard object

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

4.4.12 built-in object

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

Note

标准内置对象在本规范中定义。ECMAScript 实现可以指定并提供额外种类的内置对象。

4.4.13 undefined value

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

4.4.14 Undefined type

唯一值为 undefined 值的类型

4.4.15 null value

表示有意缺少任何对象值的原始值

4.4.16 Null type

唯一值为 null 值的类型

4.4.17 Boolean value

Boolean 类型的成员

Note

只有两个 Boolean 值,truefalse

4.4.18 Boolean type

由原始值 truefalse 组成的类型

4.4.19 Boolean object

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

Note

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

4.4.20 String value

作为零个或多个 16 位无符号整数值的有限有序序列的原始值

Note

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

4.4.21 String type

所有可能 String 值的集合

4.4.22 String object

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

Note

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

4.4.23 Number value

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

Note

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

4.4.24 Number type

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

4.4.25 Number object

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

Note

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

4.4.26 Infinity

作为正无穷 Number 值Number 值

4.4.27 NaN

作为 IEEE 754-2019 NaN(“not a number”)值的 Number 值

4.4.28 BigInt value

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

4.4.29 BigInt type

所有可能 BigInt 值的集合

4.4.30 BigInt object

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

4.4.31 Symbol value

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

4.4.32 Symbol type

所有可能 Symbol 值的集合

4.4.33 Symbol object

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

4.4.34 function

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

Note

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

4.4.35 built-in function

作为函数的内置对象

Note

内置函数的示例包括 parseIntMath.exp宿主或实现可以提供本规范中未描述的额外内置函数。

4.4.36 built-in constructor

作为构造函数的内置函数

Note

内置构造函数的示例包括 ObjectFunction宿主或实现可以提供本规范中未描述的额外内置构造函数

4.4.37 property

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

Note

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

4.4.38 method

作为属性值的函数

Note

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

4.4.39 built-in method

作为内置函数的方法

Note

标准内置方法在本规范中定义。宿主或实现可以提供本规范中未描述的额外内置方法。

4.4.40 attribute

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

4.4.41 own property

直接包含在其对象中的属性

4.4.42 inherited property

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

4.5 本规范的组织

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

条款 5 定义本规范通篇使用的记号约定。

条款 610 定义 ECMAScript 程序运行所在的执行环境。

条款 1117 定义实际的 ECMAScript 编程语言,包括其句法编码以及所有语言特性的执行语义。

条款 1828 定义 ECMAScript 标准库。它们包括 ECMAScript 程序执行时可供其使用的所有标准对象的定义。

条款 29 描述对 SharedArrayBuffer 支持的内存的访问以及 Atomics 对象方法的内存一致性模型。

5 记号约定

5.1 句法和词法语法

5.1.1 上下文无关语法

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

链式产生式是指其右手边恰好有一个非终结符符号并伴随零个或多个终结符符号的产生式。

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

5.1.2 词法语法和 RegExp 语法

ECMAScript 的词法语法在条款 12 中给出。该语法以符合 11.1 中定义的 SourceCharacter 规则的 Unicode 码点作为其终结符符号。它定义了一组产生式,从目标符号 InputElementDivInputElementTemplateTailInputElementRegExpInputElementRegExpOrTemplateTailInputElementHashbangOrRegExp 开始,描述此类码点序列如何被翻译为输入元素序列。

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

ECMAScript 的 RegExp 语法22.2.1 中给出。该语法也以由 SourceCharacter 定义的码点作为其终结符符号。它定义了一组产生式,从目标符号 Pattern 开始,描述码点序列如何被翻译为正则表达式模式。

词法语法和 RegExp 语法的产生式以两个冒号“::”作为分隔标点来区分。词法语法和 RegExp 语法共享一些产生式。

5.1.3 数值字符串语法

数值字符串语法出现在 7.1.4.1 中。它以 SourceCharacter 作为其终结符符号,并用于从目标符号 StringNumericLiteral 开始将 Strings 翻译为数值(该语法类似于但不同于数值字面量的词法语法)。

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

5.1.4 句法语法

ECMAScript 的句法语法在条款 1316 中给出。该语法以词法语法定义的 ECMAScript token 作为其终结符符号(5.1.2)。它定义了一组产生式,从两个可选目标符号 ScriptModule 开始,描述 token 序列如何构成句法正确的 ECMAScript 程序独立组件。

当码点流将被解析为 ECMAScript ScriptModule 时,它首先通过重复应用词法语法转换为输入元素流;然后该输入元素流通过一次应用句法语法来解析。如果输入元素流中的 token 不能被解析为目标非终结符(ScriptModule)的单个实例且没有剩余 token,则输入流在句法上有错误。

解析成功时,会构造一棵解析树,即一种根树结构,其中每个节点都是一个 Parse Node。每个 Parse Node 都是语法中某个符号的实例;它表示可从该符号派生出的源文本跨度。解析树的根节点表示整个源文本,是该解析目标符号的实例。当 Parse Node 是非终结符的实例时,它也是某个以该非终结符为左手边的产生式的实例。此外,它有零个或多个子节点,产生式右手边的每个符号对应一个子节点:每个子节点都是对应符号的实例的 Parse Node。

每次调用解析器都会实例化新的 Parse Nodes,并且即使源文本相同,也绝不会在不同解析之间复用 Parse Nodes。当且仅当 Parse Nodes 表示相同的源文本跨度、是相同语法符号的实例,并且来自同一次解析器调用时,才认为它们是同一 Parse Node

Note 1

多次解析同一个 String 会导致不同的 Parse Nodes。例如,考虑:

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

每次对 eval 的调用都会将 str 的值转换为 ECMAScript 源文本,并执行一次独立解析,创建其自身独立的 Parse Nodes 树。即使每次解析都作用于由同一个 String 值派生出的源文本,这些树也是不同的。

Note 2
Parse Nodes 是规范制品,实现不要求使用类似的数据结构。

句法语法的产生式以仅一个冒号“:”作为标点来区分。

条款 1316 中呈现的句法语法,并不完整说明哪些 token 序列会被接受为正确的 ECMAScript ScriptModule。某些额外的 token 序列也会被接受,即如果只在序列的某些位置(例如行终止符字符之前)添加分号就会由语法描述的那些 token 序列。此外,如果行终止符字符出现在某些“尴尬”的位置,某些由语法描述的 token 序列也不被认为是可接受的。

在某些情况下,为避免歧义,句法语法使用广义产生式,这些产生式允许并不构成有效 ECMAScript ScriptModule 的 token 序列。例如,这种技术用于对象字面量和对象解构模式。在这类情况下,会提供更具限制性的补充语法,以进一步限制可接受的 token 序列。通常,早期错误规则随后会说明,在某些上下文中,“p must cover an n”,其中 p 是 Parse Node(广义产生式的一个实例),而 n 是补充语法中的非终结符。这意味着:

  1. 最初由 p 匹配的 token 序列会以 n 作为目标符号重新解析。如果 n 具有语法参数,则这些参数会被设置为 p 最初解析时使用的相同值。
  2. 如果该 token 序列能够被解析为 n 的单个实例且没有剩余 token,则:
    1. 我们将该 n 的实例(一个 Parse Node,对给定的 p 唯一)称为“由 p 覆盖的 n”。
    2. n 及其派生产生式的所有 Early Error 规则也适用于由 p 覆盖的 n
  3. 否则(如果解析失败),它是一个早期 Syntax Error。

5.1.5 语法记号

5.1.5.1 终结符符号

在 ECMAScript 语法中,一些终结符符号以 fixed-width 字体显示。它们应完全按所写形式出现在源文本中。以这种方式指定的所有终结符符号码点,都应被理解为来自 Basic Latin 块的相应 Unicode 码点,而不是来自其他 Unicode 范围的任何外观相似码点。终结符符号中的码点不能用 \ UnicodeEscapeSequence 表示。

在终结符符号为单个 Unicode 码点的语法中(即词法、RegExp 和数值字符串语法),产生式中出现的多个连续定宽码点是一种简单简写,表示同样的码点序列,但写作独立的终结符符号。

例如,产生式:

HexIntegerLiteral :: 0x HexDigits

是以下形式的简写:

HexIntegerLiteral :: 0 x HexDigits

相比之下,在句法语法中,连续的一串定宽码点是单个终结符符号。

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

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

5.1.5.2 非终结符符号和产生式

非终结符符号以斜体显示。非终结符的定义(也称为“产生式”)由被定义的非终结符名称引入,后跟一个或多个冒号。(冒号数量表示该产生式属于哪种语法。)随后的一行或多行给出该非终结符的一个或多个可选右手边。例如,句法定义:

WhileStatement : while ( Expression ) Statement

说明非终结符 WhileStatement 表示 token while,后跟左圆括号 token,后跟 Expression,后跟右圆括号 token,后跟 StatementExpressionStatement 的出现本身是非终结符。再举一个例子,句法定义:

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 的词法语法包含产生式:

NonZeroDigit :: one of 1 2 3 4 5 6 7 8 9

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

NonZeroDigit :: 1 2 3 4 5 6 7 8 9

5.1.5.6 [empty]

如果短语“[empty]”出现在产生式右手边,则表示该产生式的右手边不包含终结符或非终结符。

5.1.5.7 向前看限制

如果短语“[lookahead = seq]”出现在产生式右手边,则表示只有在 token 序列 seq 是紧接其后的输入 token 序列的前缀时,该产生式才可使用。类似地,“[lookahead ∈ set]”,其中 set 是 token 序列的有限非空集合,表示只有在 set 的某个元素是紧接其后的 token 序列的前缀时,该产生式才可使用。为方便起见,该集合也可以写作非终结符,此时它表示该非终结符可展开得到的所有 token 序列的集合。如果该非终结符可以展开为无限多个不同 token 序列,则认为这是编辑错误。

这些条件可以被否定。“[lookahead ≠ seq]”表示只有在 seq 不是紧接其后的输入 token 序列的前缀时,包含该条件的产生式才可使用;而“[lookahead ∉ set]”表示只有在 set没有元素是紧接其后的 token 序列的前缀时,该产生式才可使用。

作为示例,给定定义:

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 后跟一个或多个十进制数字且第一个数字为偶数,或者匹配一个后面不跟另一个十进制数字的十进制数字。

注意,当这些短语在句法语法中使用时,可能无法无歧义地识别紧接其后的 token 序列,因为确定后续 token 需要知道在后续位置使用哪个词法目标符号。因此,当这些短语在句法语法中使用时,如果 token 序列 seq 出现在向前看限制中(包括作为序列集合的一部分),而词法目标符号的选择可能改变 seq 是否会成为所得 token 序列的前缀,则认为这是编辑错误。

5.1.5.8 [no LineTerminator here]

如果短语“[no LineTerminator here]”出现在句法语法产生式的右手边,则表示该产生式是受限产生式:如果 LineTerminator 出现在输入流中所示位置,则不能使用该产生式。例如,产生式:

ThrowStatement : throw [no LineTerminator here] Expression ;

表示如果脚本中 throw token 与 Expression 之间出现 LineTerminator,则不能使用该产生式。

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

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 ]),并且在算法步骤中与必需参数没有区别。rest 参数可以出现在参数列表末尾,以前导省略号表示(, ...name)。rest 参数将必需参数和可选参数之后提供的所有实参捕获到一个 List 中。如果没有这样的额外实参,该 List 为空。

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

  1. 顶层步骤
    1. 子步骤。
    2. 子步骤。
      1. 子子步骤。
        1. 子子子步骤
          1. 子子子子步骤
            1. 子子子子子步骤

步骤或子步骤可以写作一个“if”谓词,用其条件控制其子步骤。在这种情况下,只有在该谓词为真时才应用这些子步骤。如果步骤或子步骤以词语“else”开头,则它是同一层级前一个“if”谓词步骤的否定谓词。

步骤可以以“For each”或“Repeat”开头,以指定其子步骤的迭代应用。

以“Assert:”开头的步骤断言其算法的不变条件。这些断言用于明确本来会隐含的算法不变式。类似地,以“NOTE:”开头的步骤为附近步骤提供相关上下文。断言步骤和注记步骤严格而言是信息性的;它们不添加额外的语义要求,因此实现无需检查它们。

算法步骤可以使用形式“Let x be someValue”为任意值声明命名别名。这些别名类似引用,因为 xsomeValue 都引用相同的底层数据,对任一者的修改对二者均可见。希望避免这种类引用行为的算法步骤应显式复制右手边:“Let x be a copy of someValue” 创建 someValue 的浅拷贝。

别名一经声明,就可以在任何后续步骤中引用,并且不得在声明之前的步骤中引用。别名可以使用形式“Set x to someOtherValue”进行修改。

5.2.1 求值顺序

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

  1. Return A(B(), C.[[D]]) + E(F()).

等价于

  1. Let tmp1 be B().
  2. Let tmp2 be C.[[D]].
  3. Let tmp3 be A(tmp1, tmp2).
  4. Let tmp4 be F().
  5. Let tmp5 be E(tmp4).
  6. Let tmp6 be tmp3 + tmp5.
  7. Return tmp6.

其中各种 tmpN 别名是临时的,并且只在这些步骤中可见。

5.2.2 抽象操作

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

5.2.3 语法制导操作

语法制导操作是一个命名操作,其定义由算法组成,每个算法与某个 ECMAScript 语法中的一个或多个产生式关联。具有多个可选定义的产生式,通常会为每个替代项具有不同的算法。当算法与语法产生式关联时,它可以像引用算法参数一样引用该产生式替代项的终结符和非终结符符号。以这种方式使用时,非终结符符号指的是解析源文本时匹配到的实际替代定义。由某个语法产生式或由它派生出的 Parse Node 匹配的源文本,是从参与匹配的第一个终结符开始处到参与匹配的最后一个终结符结束处之间的那部分源文本。

当算法与产生式替代项关联时,该替代项通常显示时不带任何“[ ]”语法注解。此类注解只应影响对替代项的句法识别,而不影响该替代项的相关语义。

语法制导操作使用以下算法中步骤 134 上的约定,以 parse node 以及可选的其他参数来调用:

  1. Let status be SyntaxDirectedOperation of SomeNonTerminal.
  2. Let someParseNode be the parse of some source text.
  3. Perform SyntaxDirectedOperation of someParseNode.
  4. Perform SyntaxDirectedOperation of someParseNode with argument "value".

除非另有明确规定,否则所有链式产生式对可能应用于该产生式左手边非终结符的每个操作,都有一个隐式定义。该隐式定义只是用相同参数(若有)将同一操作重新应用于该链式产生式唯一的右手边非终结符,然后返回结果。例如,假设某算法具有形如“Return Evaluation of Block”的步骤,并且有一个产生式:

Block : { StatementList }

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

Runtime Semantics: Evaluation

Block : { StatementList }
  1. Return Evaluation of StatementList.

5.2.4 运行时语义

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

5.2.4.1 Completion ( completionRecord )

The abstract operation Completion takes argument completionRecord (a Completion Record) and returns a Completion Record. 它用于强调正在返回 Completion Record。 It performs the following steps when called:

  1. Assert: completionRecord is a Completion Record.
  2. Return completionRecord.

5.2.4.2 Throw

在算法步骤中,词语“throw”是返回调用 ThrowCompletion 的结果的简写。例如,

  1. If result.[[Error]] is not none, throw result.[[Error]].

等价于

  1. If result.[[Error]] is not none, return ThrowCompletion(result.[[Error]]).

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

  1. Throw a TypeError exception.

等价于

  1. Return ThrowCompletion(a newly created TypeError object).

5.2.4.3 解包 Completion Records 的简写

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

  1. Let result be ? record.

等价于

  1. Assert: record is a Completion Record.
  2. If record is an abrupt completion, return record.
  3. Let result be record.[[Value]].

同样,步骤

  1. Let result be ! record.

等价于

  1. Assert: record is a normal completion.
  2. Let result be record.[[Value]].

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

  1. Perform AO(? Other()).

可以重写为

  1. Let tmp1 be Other().
  2. Let tmp2 be ? tmp1.
  3. Perform AO(tmp2).

它又展开为

  1. Let tmp1 be Other().
  2. Assert: tmp1 is a Completion Record.
  3. If tmp1 is an abrupt completion, return tmp1.
  4. Let tmp2 be tmp1.[[Value]].
  5. Perform AO(tmp2).

5.2.4.4 隐式正常完成

在声明为返回 Completion Record抽象操作内的算法中,以及在所有内置函数内,返回值会首先传递给 NormalCompletion,并使用所得结果。本规则不适用于 Completion 算法内部,也不适用于该步骤中返回值已被清楚标记为 Completion Record 的情况;这些情况是:

如果从这类抽象操作中以任何其他方式返回 Completion Record,则这是编辑错误。例如,在这些抽象操作中,

  1. Return true.

与以下任一形式含义相同

  1. Return NormalCompletion(true).

  1. Let completion be NormalCompletion(true).
  2. Return Completion(completion).

  1. Return Completion Record { [[Type]]: normal, [[Value]]: true, [[Target]]: empty }.

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

  1. Return ? completion.

以下示例会是编辑错误,因为正在返回 Completion Record 而该步骤中未进行注解。

  1. Let completion be NormalCompletion(true).
  2. Return completion.

5.2.5 静态语义

上下文无关语法不足以表达所有规则,这些规则定义输入元素流是否形成可被求值的有效 ECMAScript ScriptModule。在某些情况下,需要使用 ECMAScript 算法约定或散文式要求来表达的额外规则。这类规则总是与语法产生式关联,并称为该产生式的静态语义

Static Semantic Rules 具有名称,并且通常使用算法定义。命名的 Static Semantic Rules 与语法产生式关联,而具有多个可选定义的产生式通常会为每个适用的命名静态语义规则的每个替代项具有不同算法。

一种特殊的静态语义规则是 Early Error Rule。Early error 规则定义与特定语法产生式关联的 early error 条件(参见条款 17)。大多数 early error 规则的求值不会在本规范的算法中显式调用。一致实现必须在首次求值 ScriptModule 之前,验证用于解析该 ScriptModule 的产生式的所有 early error 规则。如果违反任何 early error 规则,则该 ScriptModule 无效且不能被求值。

5.2.6 数学操作

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

  • 数学值:任意实数,用作默认数值类型。
  • 扩展数学值数学值加上 +∞ 和 -∞。
  • NumbersIEEE 754-2019 binary64(双精度浮点)值。
  • BigInts:与任意整数一一对应的 ECMAScript 语言值

在本规范语言中,数值使用下标后缀来区分不同的数值种类。下标 𝔽 指 Numbers,下标 指 BigInts。不带下标后缀的数值指数学值。本规范以 10 进制表示大多数数值;也使用形如 0x 后跟数字 0-9 或 A-F 的数值作为 16 进制值。

一般而言,当本规范引用一个数值时,例如在短语“the length of y”或“the integer represented by the four hexadecimal digits ...”中,如果未显式指定数值种类,该短语指数学值。引用 Number 或 BigInt 值的短语会显式标注;例如,“the Number value for the number of code points in …”或“the BigInt value for …”。

当术语 integer 在本规范中使用时,除非另有说明,它指的是属于整数集合的数学值。当术语 integral Number 在本规范中使用时,它指的是其数学值属于整数集合的有限 Number 值

数值运算符如 +、×、= 和 ≥ 指由操作数类型决定的那些操作。当应用于数学值时,运算符指通常的数学操作。当应用于扩展数学值时,运算符指扩展实数上的通常数学操作;不定式未定义,其在本规范中的使用应被视为编辑错误。当应用于 Numbers 时,运算符指 IEEE 754-2019 中的相关操作。当应用于 BigInts 时,运算符指应用于该 BigInt 数学值的通常数学操作。应用于混合类型操作数(例如 Number 和数学值)的数值运算符未定义,并且在本规范中应被视为编辑错误。

数学值与 Numbers 或 BigInts 之间的转换在本文档中始终是显式的。从数学值扩展数学值 x 到 Number 的转换表示为“the Number value for x”或 𝔽(x),并在 6.1.6.1 中定义。从整数 x 到 BigInt 的转换表示为“the BigInt value for x”或 ℤ(x)。从 Number 或 BigInt x数学值的转换表示为“the mathematical value of x”,或 ℝ(x)+0𝔽-0𝔽数学值数学值 0。非有限值的数学值未定义。xextended mathematical value of有限值时 x数学值,而对 +∞𝔽-∞𝔽 分别为 +∞ 和 -∞;对 NaN 未定义。

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

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

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

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

短语“the result of clamping x between lower and upper”(其中 x扩展数学值lowerupper 是满足 lowerupper数学值)在 x < lower 时产生 lower,在 x > upper 时产生 upper,否则产生 x

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

Note

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

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

数学函数 minmaxabsfloortruncate 对 Numbers 和 BigInts 未定义,任何使用这些方法且带有非数学值实参的情况,在本规范中都会是编辑错误。

从下界 a 到上界 b区间,是一个可能无限、可能为空的同一数值类型的数值集合。每个边界会被描述为包含或排除其边界值,但不会同时如此。区间有以下四种:

  • a包含)到 b包含)的区间,也称为从 ab闭区间包含同一数值类型中满足 axb 的所有值 x,且不包含其他值。
  • a包含)到 b(排除)的区间包含同一数值类型中满足 ax < b 的所有值 x,且不包含其他值。
  • a(排除)到 b包含)的区间包含同一数值类型中满足 a < xb 的所有值 x,且不包含其他值。
  • a(排除)到 b(排除)的区间包含同一数值类型中满足 a < x < b 的所有值 x,且不包含其他值。

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

5.2.7 值记号

在本规范中,ECMAScript 语言值bold 显示。示例包括 nulltrue"hello"。这些值与 ECMAScript 源文本相区分,例如 Function.prototype.applylet n = 42;

5.2.8 同一性

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

从本规范的视角看,词语“is”用于比较两个值是否相等,如“If bool is true, then ...”;词语“contains”用于通过相等比较在列表中搜索某个值,如“If list contains a Record r such that r.[[Foo]] is true, then ...”。值的规范同一性决定这些比较的结果,并且在本规范中是公理性的。

从 ECMAScript 语言的视角看,语言值使用 SameValue 抽象操作及其传递调用的抽象操作进行相等比较。这些比较抽象操作的算法决定 ECMAScript 语言值语言同一性

对于规范值,无规范同一性的值示例包括但不限于:数学值扩展数学值;ECMAScript 源文本、代理对Directive Prologues 等;UTF-16 代码单元;Unicode 码点;枚举;抽象操作,包括语法制导操作宿主钩子等;以及有序对。有规范同一性的规范值示例包括但不限于:任何种类的 Records,包括 Property DescriptorsPrivateElements 等;Parse NodesListsSetsRelationsAbstract ClosuresData BlocksPrivate Names;执行上下文和执行上下文栈;agent signifiers;以及 WaiterList Records

除由 Symbol.for 产生的 Symbol 值外,所有 ECMAScript 语言值的规范同一性与语言同一性一致。无规范同一性且无语言同一性的 ECMAScript 语言值undefinednullBooleansStringsNumbersBigInts。有规范同一性和语言同一性的 ECMAScript 语言值是并非由 Symbol.for 产生的 Symbols 以及 Objects。由 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 类型表示具有两个值的逻辑实体,这两个值称为 truefalse

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 值,但其他操作不会隐式规范化它们所操作的字符串。除非另有说明,操作结果不受语言和/或区域设置影响。

Note

此设计背后的理由是,使 Strings 的实现尽可能简单且高性能。如果 ECMAScript 源文本采用 Normalized Form C,则只要字符串字面量不包含任何 Unicode 转义序列,就保证它们也被规范化。

在本规范中,短语“AB、... 的字符串连接”(其中每个实参都是 String 值、码元或码元序列)表示一个 String 值,其码元序列是每个实参的码元(按顺序)的连接(按顺序)。

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

短语“ASCII 单词字符”表示以下 String 值,该值仅由 Unicode Basic Latin 块中的每个字母和数字以及 U+005F(LOW LINE)组成:
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_"
出于历史原因,它对各种算法具有意义。

6.1.4.1 StringIndexOf ( string, searchValue, fromIndex )

The abstract operation StringIndexOf takes arguments string (a String), searchValue (a String), and fromIndex (a non-negative integer) and returns a non-negative integer or not-found. It performs the following steps when called:

  1. lengthstring 的长度。
  2. 如果 searchValue 为空 String 且 fromIndexlength,则返回 fromIndex
  3. searchLengthsearchValue 的长度。
  4. 对于满足 fromIndexilength - searchLength 的每个整数 i,按升序执行:
    1. candidatestringii + searchLength子字符串
    2. 如果 candidatesearchValue,则返回 i
  5. 返回 not-found
Note 1

如果 searchValue 为空 String 且 fromIndexstring 的长度,则该算法返回 fromIndex。空 String 实际上会在字符串内的每个位置被找到,包括最后一个码元之后。

Note 2

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

6.1.4.2 StringLastIndexOf ( string, searchValue, fromIndex )

The abstract operation StringLastIndexOf takes arguments string (a String), searchValue (a String), and fromIndex (a non-negative integer) and returns a non-negative integer or not-found. It performs the following steps when called:

  1. lengthstring 的长度。
  2. searchLengthsearchValue 的长度。
  3. 断言:fromIndex + searchLengthlength
  4. 对于满足 0 ≤ ifromIndex 的每个整数 i,按降序执行:
    1. candidatestringii + searchLength子字符串
    2. 如果 candidatesearchValue,则返回 i
  5. 返回 not-found
Note

如果 searchValue 为空 String,则该算法返回 fromIndex。空 String 实际上会在字符串内的每个位置被找到,包括最后一个码元之后。

6.1.5 Symbol 类型

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

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

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

6.1.5.1 众所周知的 Symbols

众所周知的 symbols 是由本规范的算法显式引用的内置 Symbol 值。它们通常用作属性的键,而这些属性的值充当规范算法的扩展点。除非另有规定,众所周知的 symbol 值由所有 realms 共享(9.3)。

在本规范中,使用标准内在记号引用众所周知的 symbol,其中该内在是 Table 1 中列出的值之一。

Note
本规范的早期版本使用形如 @@name 的记号,而当前版本会使用 %Symbol.name%。特别地,曾使用以下名称:@@asyncIterator、@@hasInstance、@@isConcatSpreadable、@@iterator、@@match、@@matchAll、@@replace、@@search、@@species、@@split、@@toPrimitive、@@toStringTag 和 @@unscopables。
Table 1: 众所周知的 Symbol
规范名称 [[描述]] 值和用途
%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" 一个 function 值属性,它是用于创建派生对象的构造函数
%Symbol.split% "Symbol.split" 一个正则表达式方法,用于在与正则表达式匹配的索引处拆分字符串。由 String.prototype.split 方法调用。
%Symbol.toPrimitive% "Symbol.toPrimitive" 一个方法,用于将对象转换为对应的原始值。由 ToPrimitive 抽象操作调用。
%Symbol.toStringTag% "Symbol.toStringTag" 一个 String 值属性,用于创建对象的默认字符串描述。由内置方法 Object.prototype.toString 访问。
%Symbol.unscopables% "Symbol.unscopables" 一个 object 值属性,其自身和继承的属性名,是要从关联对象的 with 环境绑定中排除的属性名

6.1.6 数值类型

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

Table 2: Numeric Type Operations
操作 示例源代码 由……的 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) 对象内部方法, 经由 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 语言不在这些类型之间提供隐式转换。调用需要另一种类型的函数时,程序员必须显式调用 NumberBigInt 函数以在类型之间转换。

Note

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

6.1.6.1 Number 类型

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

Note

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

还有另外两个特殊值,称为 positive Infinitynegative Infinity。为简洁起见,出于说明目的,这些值也分别用符号 +∞𝔽-∞𝔽 指代。(注意,这两个无穷 Number 值由程序表达式 +Infinity(或简单地 Infinity)和 -Infinity 产生。)

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

注意,存在 positive zeronegative zero。为简洁起见,出于说明目的,这些值也分别用符号 +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𝔽

如果有限数非零,且用于以上两种形式之一表示它的整数 m 为奇数,则它具有奇数有效数。否则,它具有偶数有效数

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

+∞ 的 Number 值+∞𝔽,-∞ 的 Number 值-∞𝔽

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

6.1.6.1.1 Number::unaryMinus ( number )

The abstract operation Number::unaryMinus takes argument number (a Number) and returns a Number. It performs the following steps when called:

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

6.1.6.1.2 Number::bitwiseNOT ( number )

The abstract operation Number::bitwiseNOT takes argument number (a Number) and returns an integral Number. It performs the following steps when called:

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

6.1.6.1.3 Number::exponentiate ( base, exponent )

The abstract operation Number::exponentiate takes arguments base (a Number) and exponent (a Number) and returns a Number. 它返回一个实现近似值,表示 baseexponent 次幂结果。 It performs the following steps when called:

  1. 如果 exponentNaN,则返回 NaN
  2. 如果 exponent+0𝔽-0𝔽,则返回 1𝔽
  3. 如果 baseNaN,则返回 NaN
  4. 如果 base+∞𝔽,则
    1. 如果 exponent > +0𝔽,则返回 +∞𝔽
    2. 返回 +0𝔽
  5. 如果 base-∞𝔽,则
    1. 如果 exponent > +0𝔽,则
      1. 如果 exponent 是奇数 integral Number,则返回 -∞𝔽
      2. 返回 +∞𝔽
    2. 如果 exponent 是奇数 integral Number,则返回 -0𝔽
    3. 返回 +0𝔽
  6. 如果 base+0𝔽,则
    1. 如果 exponent > +0𝔽,则返回 +0𝔽
    2. 返回 +∞𝔽
  7. 如果 base-0𝔽,则
    1. 如果 exponent > +0𝔽,则
      1. 如果 exponent 是奇数 integral Number,则返回 -0𝔽
      2. 返回 +0𝔽
    2. 如果 exponent 是奇数 integral Number,则返回 -∞𝔽
    3. 返回 +∞𝔽
  8. 断言:base有限的,且既不是 +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有限的,且既不是 +0𝔽 也不是 -0𝔽
  12. 如果 base < -0𝔽exponent 不是 integral Number,则返回 NaN
  13. 返回一个实现近似的 Number 值,表示将 (base) 提升到 (exponent) 次幂的结果。
Note

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

6.1.6.1.4 Number::multiply ( x, y )

The abstract operation Number::multiply takes arguments x (a Number) and y (a Number) and returns a Number. 它按照 IEEE 754-2019 二进制双精度算术规则执行乘法,产生 xy 的乘积。 It performs the following steps when called:

  1. 如果 xNaNyNaN,则返回 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))。
Note

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

6.1.6.1.5 Number::divide ( x, y )

The abstract operation Number::divide takes arguments x (a Number) and y (a Number) and returns a Number. 它按照 IEEE 754-2019 二进制双精度算术规则执行除法,产生 xy 的商,其中 x 是被除数,y 是除数。 It performs the following steps when called:

  1. 如果 xNaNyNaN,则返回 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 )

The abstract operation Number::remainder takes arguments numerator (a Number) and denominator (a Number) and returns a Number. 它产生由其操作数的隐含除法得到的余数,其中 numerator 是被除数,denominator 是除数。 It performs the following steps when called:

  1. 如果 numeratorNaNdenominatorNaN,则返回 NaN
  2. 如果 numerator+∞𝔽-∞𝔽,则返回 NaN
  3. 如果 denominator+∞𝔽-∞𝔽,则返回 numerator
  4. 如果 denominator+0𝔽-0𝔽,则返回 NaN
  5. 如果 numerator+0𝔽-0𝔽,则返回 numerator
  6. 断言:numeratordenominator有限且非零的。
  7. quotient(numerator) / (denominator)。
  8. truncatedQuotienttruncate(quotient)。
  9. remainder(numerator) - ((denominator) × truncatedQuotient)。
  10. 如果 remainder = 0 且 numerator < -0𝔽,则返回 -0𝔽
  11. 返回 𝔽(remainder)。
Note 1

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

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

6.1.6.1.7 Number::add ( x, y )

The abstract operation Number::add takes arguments x (a Number) and y (a Number) and returns a Number. 它按照 IEEE 754-2019 二进制双精度算术规则执行加法,产生其实参之和。 It performs the following steps when called:

  1. 如果 xNaNyNaN,则返回 NaN
  2. 如果 x+∞𝔽y-∞𝔽,则返回 NaN
  3. 如果 x-∞𝔽y+∞𝔽,则返回 NaN
  4. 如果 x+∞𝔽-∞𝔽,则返回 x
  5. 如果 y+∞𝔽-∞𝔽,则返回 y
  6. 断言:xy 都是有限的。
  7. 如果 x-0𝔽y-0𝔽,则返回 -0𝔽
  8. 返回 𝔽((x) + (y))。
Note

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

6.1.6.1.8 Number::subtract ( x, y )

The abstract operation Number::subtract takes arguments x (a Number) and y (a Number) and returns a Number. 它执行减法,产生其操作数之差;x 是被减数,y 是减数。 It performs the following steps when called:

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

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

6.1.6.1.9 Number::leftShift ( x, y )

The abstract operation Number::leftShift takes arguments x (a Number) and y (a Number) and returns an integral Number. It performs the following steps when called:

  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 )

The abstract operation Number::signedRightShift takes arguments x (a Number) and y (a Number) and returns an integral Number. It performs the following steps when called:

  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 )

The abstract operation Number::unsignedRightShift takes arguments x (a Number) and y (a Number) and returns an integral Number. It performs the following steps when called:

  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 )

The abstract operation Number::lessThan takes arguments x (a Number) and y (a Number) and returns a Boolean or undefined. It performs the following steps when called:

  1. 如果 xNaN,则返回 undefined
  2. 如果 yNaN,则返回 undefined
  3. 如果 xy,则返回 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. 断言:xy有限的。
  11. 如果 (x) < (y),则返回 true
  12. 返回 false

6.1.6.1.13 Number::equal ( x, y )

The abstract operation Number::equal takes arguments x (a Number) and y (a Number) and returns a Boolean. It performs the following steps when called:

  1. 如果 xNaN,则返回 false
  2. 如果 yNaN,则返回 false
  3. 如果 xy,则返回 true
  4. 如果 x+0𝔽y-0𝔽,则返回 true
  5. 如果 x-0𝔽y+0𝔽,则返回 true
  6. 返回 false

6.1.6.1.14 Number::sameValue ( x, y )

The abstract operation Number::sameValue takes arguments x (a Number) and y (a Number) and returns a Boolean. It performs the following steps when called:

  1. 如果 xNaNyNaN,则返回 true
  2. 如果 x+0𝔽y-0𝔽,则返回 false
  3. 如果 x-0𝔽y+0𝔽,则返回 false
  4. 如果 xy,则返回 true
  5. 返回 false

6.1.6.1.15 Number::sameValueZero ( x, y )

The abstract operation Number::sameValueZero takes arguments x (a Number) and y (a Number) and returns a Boolean. It performs the following steps when called:

  1. 如果 xNaNyNaN,则返回 true
  2. 如果 x+0𝔽y-0𝔽,则返回 true
  3. 如果 x-0𝔽y+0𝔽,则返回 true
  4. 如果 xy,则返回 true
  5. 返回 false

6.1.6.1.16 NumberBitwiseOp ( op, x, y )

The abstract operation NumberBitwiseOp takes arguments op (&, ^, or |), x (a Number), and y (a Number) and returns an integral Number. It performs the following steps when called:

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

6.1.6.1.17 Number::bitwiseAND ( x, y )

The abstract operation Number::bitwiseAND takes arguments x (a Number) and y (a Number) and returns an integral Number. It performs the following steps when called:

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

6.1.6.1.18 Number::bitwiseXOR ( x, y )

The abstract operation Number::bitwiseXOR takes arguments x (a Number) and y (a Number) and returns an integral Number. It performs the following steps when called:

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

6.1.6.1.19 Number::bitwiseOR ( x, y )

The abstract operation Number::bitwiseOR takes arguments x (a Number) and y (a Number) and returns an integral Number. It performs the following steps when called:

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

6.1.6.1.20 Number::toString ( x, radix )

The abstract operation Number::toString takes arguments x (a Number) and radix (an integer in the inclusive interval from 2 to 36) and returns a String. 它使用基数为 radix 的位置计数系统,将 x 表示为 String。使用基数 r 表示数时所用的数字,按顺序取自 "0123456789abcdefghijklmnopqrstuvwxyz" 的前 r 个码元。大小大于或等于 1𝔽 的数的表示从不包含前导零。 It performs the following steps when called:

  1. 如果 xNaN,则返回 "NaN"
  2. 如果 x+0𝔽-0𝔽,则返回 "0"
  3. 如果 x < -0𝔽,则返回 "-"Number::toString(-x, radix) 的字符串连接
  4. 如果 x+∞𝔽,则返回 "Infinity"
  5. nks 为整数,使得 k ≥ 1,radixk - 1s < radixk𝔽(s × radixn - k) 是 x,并且 k 尽可能小。注意,k 是使用基数 radix 表示 s 时的位数,s 不能被 radix 整除,并且 s 的最低有效位不一定由这些条件唯一确定。
  6. 如果 radix ≠ 10 或 n 位于从 -5 到 21 的闭区间内,则
    1. 如果 nk,则
      1. 返回以下项的字符串连接
        • 使用基数 radix 表示 sk 个数字的码元
        • 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 表示 sk 个数字的码元
  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) 的十进制表示的码元
Note 1

以下观察对实现可作为指南而有用,但不是本标准规范性要求的一部分:

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

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

  1. nks 为整数,使得 k ≥ 1,radixk - 1s < radixk𝔽(s × radixn - k) 是 x,并且 k 尽可能小。如果 s 有多种可能,则选择使 s × radixn - k 最接近 (x) 的 s。如果存在两个这样的 s 的可能值,则选择偶数者。注意,k 是使用基数 radix 表示 s 时的位数,并且 s 不能被 radix 整除。
Note 3

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

Gay, David M. Correctly Rounded Binary-Decimal and Decimal-Binary Conversions. Numerical Analysis, Manuscript 90-10. AT&T Bell Laboratories (Murray Hill, New Jersey). 30 November 1990. 可获取为
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 类型表示整数值。该值可以是任意大小,且不限于特定位宽。通常,除非另有说明,操作被设计为返回基于精确数学的答案。对于二元操作,BigInts 表现为二进制补码二进制字符串,负数被视为在左侧无限设置位。

6.1.6.2.1 BigInt::unaryMinus ( bigint )

The abstract operation BigInt::unaryMinus takes argument bigint (a BigInt) and returns a BigInt. It performs the following steps when called:

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

6.1.6.2.2 BigInt::bitwiseNOT ( bigint )

The abstract operation BigInt::bitwiseNOT takes argument bigint (a BigInt) and returns a BigInt. 它返回 bigint 的一补数。 It performs the following steps when called:

  1. 返回 -bigint - 1

6.1.6.2.3 BigInt::exponentiate ( base, exponent )

The abstract operation BigInt::exponentiate takes arguments base (a BigInt) and exponent (a BigInt) and returns either a normal completion containing a BigInt or a throw completion. It performs the following steps when called:

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

6.1.6.2.4 BigInt::multiply ( x, y )

The abstract operation BigInt::multiply takes arguments x (a BigInt) and y (a BigInt) and returns a BigInt. It performs the following steps when called:

  1. 返回 x × y
Note
即使结果具有比输入大得多的位宽,也会给出精确的数学答案。

6.1.6.2.5 BigInt::divide ( x, y )

The abstract operation BigInt::divide takes arguments x (a BigInt) and y (a BigInt) and returns either a normal completion containing a BigInt or a throw completion. It performs the following steps when called:

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

6.1.6.2.6 BigInt::remainder ( numerator, denominator )

The abstract operation BigInt::remainder takes arguments numerator (a BigInt) and denominator (a BigInt) and returns either a normal completion containing a BigInt or a throw completion. It performs the following steps when called:

  1. 如果 denominator = 0,则抛出 RangeError 异常。
  2. 如果 numerator = 0,则返回 0
  3. quotient(numerator) / (denominator)。
  4. truncatedQuotient(truncate(quotient))。
  5. 返回 numerator - (denominator × truncatedQuotient)。
Note
结果的符号是被除数的符号。

6.1.6.2.7 BigInt::add ( x, y )

The abstract operation BigInt::add takes arguments x (a BigInt) and y (a BigInt) and returns a BigInt. It performs the following steps when called:

  1. 返回 x + y

6.1.6.2.8 BigInt::subtract ( x, y )

The abstract operation BigInt::subtract takes arguments x (a BigInt) and y (a BigInt) and returns a BigInt. It performs the following steps when called:

  1. 返回 x - y

6.1.6.2.9 BigInt::leftShift ( x, y )

The abstract operation BigInt::leftShift takes arguments x (a BigInt) and y (a BigInt) and returns a BigInt. It performs the following steps when called:

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

6.1.6.2.10 BigInt::signedRightShift ( x, y )

The abstract operation BigInt::signedRightShift takes arguments x (a BigInt) and y (a BigInt) and returns a BigInt. It performs the following steps when called:

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

6.1.6.2.11 BigInt::unsignedRightShift ( x, y )

The abstract operation BigInt::unsignedRightShift takes arguments x (a BigInt) and y (a BigInt) and returns a throw completion. It performs the following steps when called:

  1. 抛出 TypeError 异常。

6.1.6.2.12 BigInt::lessThan ( x, y )

The abstract operation BigInt::lessThan takes arguments x (a BigInt) and y (a BigInt) and returns a Boolean. It performs the following steps when called:

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

6.1.6.2.13 BigInt::equal ( x, y )

The abstract operation BigInt::equal takes arguments x (a BigInt) and y (a BigInt) and returns a Boolean. It performs the following steps when called:

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

6.1.6.2.14 BinaryAnd ( x, y )

The abstract operation BinaryAnd takes arguments x (0 or 1) and y (0 or 1) and returns 0 or 1. It performs the following steps when called:

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

6.1.6.2.15 BinaryOr ( x, y )

The abstract operation BinaryOr takes arguments x (0 or 1) and y (0 or 1) and returns 0 or 1. It performs the following steps when called:

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

6.1.6.2.16 BinaryXor ( x, y )

The abstract operation BinaryXor takes arguments x (0 or 1) and y (0 or 1) and returns 0 or 1. It performs the following steps when called:

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

6.1.6.2.17 BigIntBitwiseOp ( op, x, y )

The abstract operation BigIntBitwiseOp takes arguments op (&, ^, or |), x (a BigInt), and y (a BigInt) and returns a BigInt. It performs the following steps when called:

  1. x 设置为 (x)。
  2. y 设置为 (y)。
  3. result 为 0。
  4. shift 为 0。
  5. 重复,直到 (x = 0 或 x = -1) 且 (y = 0 或 y = -1):
    1. xDigitx modulo 2。
    2. yDigity 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. signBitBinaryAnd(x modulo 2, y modulo 2)。
  7. 否则如果 op|,则
    1. signBitBinaryOr(x modulo 2, y modulo 2)。
  8. 否则,
    1. 断言:op^
    2. signBitBinaryXor(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 )

The abstract operation BigInt::bitwiseAND takes arguments x (a BigInt) and y (a BigInt) and returns a BigInt. It performs the following steps when called:

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

6.1.6.2.19 BigInt::bitwiseXOR ( x, y )

The abstract operation BigInt::bitwiseXOR takes arguments x (a BigInt) and y (a BigInt) and returns a BigInt. It performs the following steps when called:

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

6.1.6.2.20 BigInt::bitwiseOR ( x, y )

The abstract operation BigInt::bitwiseOR takes arguments x (a BigInt) and y (a BigInt) and returns a BigInt. It performs the following steps when called:

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

6.1.6.2.21 BigInt::toString ( x, radix )

The abstract operation BigInt::toString takes arguments x (a BigInt) and radix (an integer in the inclusive interval from 2 to 36) and returns a String. 它使用基数为 radix 的位置计数系统,将 x 表示为 String。使用基数 r 表示 BigInt 时所用的数字,按顺序取自 "0123456789abcdefghijklmnopqrstuvwxyz" 的前 r 个码元。除 0 之外的 BigInts 的表示从不包含前导零。 It performs the following steps when called:

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

6.1.7 Object 类型

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

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

对象的属性使用属性键唯一标识。属性键要么是 String,要么是 Symbol。所有 Strings 和 Symbols,包括空 String,都可作为有效的属性键属性名是作为 String 的属性键

整数索引是一个属性名 n,使得 CanonicalNumericIndexString(n) 返回从 +0𝔽𝔽(253 - 1) 的闭区间内的 integral Number数组索引是一个整数索引 n,使得 CanonicalNumericIndexString(n) 返回从 +0𝔽𝔽(232 - 2) 的闭区间内的 integral Number

Note

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

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

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

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

6.1.7.1 属性特性

本规范使用特性来定义和解释 Object 属性的状态,如 Table 3 所述。除非显式指定,否则每个特性的初始值都是其默认值。

Table 3: Object 属性的特性
特性名称 它出现于哪类属性 值域 默认值 描述
[[Value]] 数据属性 一个 ECMAScript 语言值 undefined 对该属性执行 get 访问时取回的值。
[[Writable]] 数据属性 一个 Boolean false 如果为 false,ECMAScript 代码尝试使用 [[Set]] 改变该属性的 [[Value]] 特性将不会成功。
[[Get]] 访问器属性 一个 Object 或 undefined undefined 如果该值是 Object,则它必须是函数对象。每次对该属性执行 get 访问以取回属性值时,都会以空实参列表调用该函数的 [[Call]] 内部方法(Table 5)。
[[Set]] 访问器属性 一个 Object 或 undefined undefined 如果该值是 Object,则它必须是函数对象。每次对该属性执行 set 访问时,都会以包含被赋值作为唯一实参的实参列表调用该函数的 [[Call]] 内部方法(Table 5)。属性的 [[Set]] 内部方法的效果可以、但并不要求,对该属性后续 [[Get]] 内部方法调用返回的值产生影响。
[[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 异常。

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

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

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

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

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

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

异质对象是不是普通对象的对象。

本规范通过这些对象的内部方法识别不同种类的异质对象。行为上等价于某种特定异质对象(例如 Array 异质对象绑定函数异质对象)的对象,如果没有为该种类指定的相同内部方法集合,则不会被识别为该种异质对象

Table 4 以及其他类似表格中的“Signature”列描述每个内部方法的调用模式。调用模式总是包含一个带括号的描述性形参名列表。如果形参名与 ECMAScript 类型名相同,则该名称描述形参值所需的类型。如果内部方法显式返回一个值,则其形参列表后跟符号“→”和返回值的类型名。签名中使用的类型名指代条款 6 中定义的类型,并由以下附加名称扩充。“any”表示该值可以是任何 ECMAScript 语言类型

除形参之外,内部方法始终能够访问作为方法调用目标的对象。

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

Table 4: 基本内部方法
内部方法 签名 描述
[[GetPrototypeOf]] ( ) Object | Null 确定为此对象提供继承属性的对象。null 值表示没有继承属性。
[[SetPrototypeOf]] (Object | Null) Boolean 将此对象与另一个提供继承属性的对象相关联。传入 null 表示没有继承属性。返回 true 表示操作成功完成,或返回 false 表示操作未成功。
[[IsExtensible]] ( ) Boolean 确定是否允许向此对象添加额外属性。
[[PreventExtensions]] ( ) Boolean 控制是否可以向此对象添加新属性。如果操作成功则返回 true,如果操作不成功则返回 false
[[GetOwnProperty]] (propertyKey) Undefined | Property Descriptor 返回此对象中键为 propertyKey 的自有属性的 Property Descriptor;如果不存在这样的属性,则返回 undefined
[[DefineOwnProperty]] (propertyKey, propertyDesc) Boolean 创建或变更键为 propertyKey 的自有属性,使其具有 propertyDesc 描述的状态。如果该属性被成功创建/更新,则返回 true;如果该属性无法被创建或更新,则返回 false
[[HasProperty]] (propertyKey) Boolean 返回一个 Boolean 值,指示此对象是否已经具有键为 propertyKey 的自有属性或继承属性。
[[Get]] (propertyKey, receiver) any 从此对象返回键为 propertyKey 的属性的值。如果必须执行任何 ECMAScript 代码以取回该属性值,则在求值该代码时使用 receiver 作为 this 值。
[[Set]] (propertyKey, value, receiver) Boolean 将键为 propertyKey 的属性的值设置为 value。如果必须执行任何 ECMAScript 代码以设置该属性值,则在求值该代码时使用 receiver 作为 this 值。如果属性值被设置则返回 true,如果无法设置则返回 false
[[Delete]] (propertyKey) Boolean 从此对象移除键为 propertyKey 的自有属性。如果该属性未被删除且仍然存在,则返回 false。如果该属性已被删除或不存在,则返回 true
[[OwnPropertyKeys]] ( ) List of property keys 返回一个 List,其元素是该对象的所有自有属性键

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

Table 5: 函数对象的附加基本内部方法
内部方法 签名 描述
[[Call]] (any, a List of any) any 执行与此对象相关联的代码。通过函数调用表达式调用。该内部方法的实参是一个 this 值和一个 List,其元素是调用表达式传给函数的实参。实现此内部方法的对象是可调用的
[[Construct]] (a List of any, Object) Object 创建一个对象。通过 new 运算符或 super 调用来调用。该内部方法的第一个实参是一个 List,其元素是构造函数调用或 super 调用的实参。第二个实参是 new 运算符最初应用到的对象。实现此内部方法的对象称为构造函数函数对象不一定是构造函数,这类非构造函数函数对象没有 [[Construct]] 内部方法。

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

6.1.7.3 基本内部方法的不变式

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

任何实现提供的异质对象也必须为这些对象维护这些不变式。违反这些不变式可能导致 ECMAScript 代码具有不可预测行为并产生安全问题。然而,违反这些不变式绝不能危及实现的内存安全。

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

定义:

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

返回值:

任何内部方法返回的值必须是一个 Completion Record,具有以下二者之一:

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

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

[[GetPrototypeOf]] ( )

  • 正常返回类型要么是 Object,要么是 Null。
  • 如果 target 是不可扩展的,并且 [[GetPrototypeOf]] 返回值 proto,则对 [[GetPrototypeOf]] 的任何未来调用都应返回与 proto SameValue 的值。
Note 2

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

[[SetPrototypeOf]] ( proto )

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

[[IsExtensible]] ( )

  • 正常返回类型是 Boolean。
  • 如果 [[IsExtensible]] 返回 false,则该 target 上未来对 [[IsExtensible]] 的所有调用都必须返回 false

[[PreventExtensions]] ( )

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

[[GetOwnProperty]] ( propertyKey )

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

作为第三个不变式的结果,如果某属性被描述为数据属性,并且它可能随时间返回不同的值,则即使没有通过其他基本内部方法暴露改变该值的机制,[[Writable]][[Configurable]] 特性之一或二者也必须为 true

[[DefineOwnProperty]] ( propertyKey, propertyDesc )

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

[[HasProperty]] ( propertyKey )

  • 正常返回类型是 Boolean。
  • 如果 propertyKey 先前已被观察为 target 的不可配置自有数据属性访问器属性,则 [[HasProperty]] 必须返回 true

[[Get]] ( propertyKey, receiver )

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

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

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

[[Delete]] ( propertyKey )

  • 正常返回类型是 Boolean。
  • 如果 propertyKey 先前已被观察为 target 的不可配置自有数据属性访问器属性,则 [[Delete]] 必须返回 false

[[OwnPropertyKeys]] ( )

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

[[Call]] ( )

[[Construct]] ( )

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

6.1.7.4 众所周知的内在对象

众所周知的内在是由本规范的算法显式引用的内置对象,并且它们通常具有 realm 特有的身份。除非另有规定,每个内在对象实际上对应于一组相似的对象,每个 realm 一个。

在本规范中,诸如 %name% 的引用表示与当前 realm 相关联、对应于该名称的内在对象。诸如 %name.a.b% 的引用表示,好像在任何 ECMAScript 代码被求值之前,访问了内在对象 %name% 的 "a" 属性值的 "b" 属性。当前 realm 及其内在的确定在 9.4 中描述。众所周知的内在列于 Table 6

Table 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% async function 对象的 构造函数27.10.1
%AsyncGeneratorFunction% async generator function 对象的 构造函数27.7.1
%AsyncGeneratorPrototype% async generator 对象的原型(27.9
%AsyncIteratorPrototype% 所有标准内置 async iterator 对象都间接继承自的对象
%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% generator function 对象的 构造函数27.6.1
%GeneratorPrototype% generator 对象的原型(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% 所有 typed 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 返回的 wrapped iterator 对象的原型(27.1.3.2.2.1
Note

Table 103 中还有附加条目。

6.2 ECMAScript 规范类型

规范类型对应于在算法中用于描述 ECMAScript 语言构造和 ECMAScript 语言类型语义的元值。规范类型包括 Reference RecordListCompletion RecordProperty DescriptorEnvironment RecordAbstract ClosureData Block。规范类型值是规范工件,不一定对应于 ECMAScript 实现中的任何特定实体。规范类型值可用于描述 ECMAScript 表达式求值的中间结果,但这类值不能作为对象属性或 ECMAScript 语言变量的值存储。

6.2.1 Enum 规范类型

Enums 是规范内部的值,不能从 ECMAScript 代码中直接观察到。Enums 使用 sans-serif 字体以 upper kebab case 表示。例如,Completion Record[[Type]] 字段会取 normalreturnthrow 之类的值。Enums 除名称之外没有任何特性。enum 的名称除了将其与其他 enums 区分开之外没有其他目的,并且不暗示其在上下文中的用法或含义。

6.2.2 List 和 Record 规范类型

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

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

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

在本规范中,短语“AB、... 的列表连接”(其中每个实参都是可能为空的 List)表示一个新的 List 值,其元素是每个实参的元素(按顺序)的连接(按顺序)。

当应用于 Strings 的 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 类型的值是简单的元素集合,其中没有元素出现超过一次。可以向 Sets 添加元素,也可以从 Sets 中移除元素。Sets 可以彼此求并集、交集或差集。

Relation 类型用于解释 Sets 上的约束。Relation 类型的值是其值域中值的有序对的 Sets。例如,Memory 事件上的 Relation 是 Memory 事件的有序对集合。对于 Relation R 以及 R 的值域中的两个值 aba R b 是“有序对 (a, b) 是 R 的成员”的简写。当某个 Relation 是满足某些条件的最小 Relation 时,它就是相对于这些条件的最小 Relation

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

  • 对于 R 的域中的所有 abc

    • 并非 a R a,并且
    • 如果 a R bb R c,则 a R c
Note 1

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

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

  • 对于 R 的域中的所有 abc

    • ab,或 a R b,或 b R a,并且
    • 并非 a R a,并且
    • 如果 a R bb R c,则 a R c
Note 2

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

6.2.4 Completion Record 规范类型

Completion Record 规范类型用于解释值和控制流的运行时传播,例如执行非局部控制转移的语句(breakcontinuereturnthrow)的行为。

Completion Records 具有 Table 7 中定义的字段。

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

以下简写术语有时用于指代 Completion Records。

  • 正常完成指任何 [[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 )

The abstract operation NormalCompletion takes argument value (any value except a Completion Record) and returns a normal completion. It performs the following steps when called:

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

6.2.4.2 ThrowCompletion ( value )

The abstract operation ThrowCompletion takes argument value (an ECMAScript language value) and returns a throw completion. It performs the following steps when called:

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

6.2.4.3 ReturnCompletion ( value )

The abstract operation ReturnCompletion takes argument value (an ECMAScript language value) and returns a return completion. It performs the following steps when called:

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

6.2.4.4 UpdateEmpty ( completionRecord, value )

The abstract operation UpdateEmpty takes arguments completionRecord (a Completion Record) and value (any value except a Completion Record) and returns a Completion Record. It performs the following steps when called:

  1. 断言:如果 completionRecordreturn 完成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 类型用于解释 deletetypeof、赋值运算符、super 关键字以及其他语言特性的行为。例如,赋值的左侧操作数预期会产生 Reference Record。

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

Table 8: Reference Record 字段
字段名 含义
[[Base]] ECMAScript 语言值Environment Recordunresolvable 保存绑定的值或 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 Records:

6.2.5.1 IsPropertyReference ( refRecord )

The abstract operation IsPropertyReference takes argument refRecord (a Reference Record) and returns a Boolean. It performs the following steps when called:

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

6.2.5.2 IsUnresolvableReference ( refRecord )

The abstract operation IsUnresolvableReference takes argument refRecord (a Reference Record) and returns a Boolean. It performs the following steps when called:

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

6.2.5.3 IsSuperReference ( refRecord )

The abstract operation IsSuperReference takes argument refRecord (a Reference Record) and returns a Boolean. It performs the following steps when called:

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

6.2.5.4 IsPrivateReference ( refRecord )

The abstract operation IsPrivateReference takes argument refRecord (a Reference Record) and returns a Boolean. It performs the following steps when called:

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

6.2.5.5 GetValue ( refRecord )

The abstract operation GetValue takes argument refRecord (a Reference Record or an ECMAScript language value) and returns either a normal completion containing an ECMAScript language value or an abrupt completion. It performs the following steps when called:

  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. baserefRecord.[[Base]]
  5. 断言:baseEnvironment Record
  6. 返回 ? base.GetBindingValue(refRecord.[[ReferencedName]], refRecord.[[Strict]])(参见 9.1)。
Note

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

6.2.5.6 PutValue ( refRecord, value )

The abstract operation PutValue takes arguments refRecord (a Reference Record or an ECMAScript language value) and value (an ECMAScript language value) and returns either a normal completion containing unused or an abrupt completion. It performs the following steps when called:

  1. 如果 refRecord 不是 Reference Record,则抛出 ReferenceError 异常。
  2. 如果 IsUnresolvableReference(refRecord) 是 true,则
    1. 如果 refRecord.[[Strict]]true,则抛出 ReferenceError 异常。
    2. globalObjGetGlobalObject()。
    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. 如果 succeededfalserefRecord.[[Strict]]true,则抛出 TypeError 异常。
    6. 返回 unused
  4. baserefRecord.[[Base]]
  5. 断言:baseEnvironment Record
  6. 返回 ? base.SetMutableBinding(refRecord.[[ReferencedName]], value, refRecord.[[Strict]])(参见 9.1)。
Note

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

6.2.5.7 GetThisValue ( refRecord )

The abstract operation GetThisValue takes argument refRecord (a Reference Record) and returns an ECMAScript language value. It performs the following steps when called:

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

6.2.5.8 InitializeReferencedBinding ( refRecord, value )

The abstract operation InitializeReferencedBinding takes arguments refRecord (a Reference Record) and value (an ECMAScript language value) and returns either a normal completion containing unused or an abrupt completion. It performs the following steps when called:

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

6.2.5.9 MakePrivateReference ( baseValue, privateIdentifier )

The abstract operation MakePrivateReference takes arguments baseValue (an ECMAScript language value) and privateIdentifier (a String) and returns a Reference Record. It performs the following steps when called:

  1. privateEnv 为运行中执行上下文的 PrivateEnvironment。
  2. 断言:privateEnv 不是 null
  3. privateNameResolvePrivateIdentifier(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 records 字面量描述的模式名称是“PropertyDescriptor”。

Property Descriptor 值可以根据某些字段的存在或使用进一步分类为数据 Property Descriptors 和访问器 Property Descriptors。数据 Property Descriptor 是包含名为 [[Value]][[Writable]] 的任一字段的描述符。访问器 Property Descriptor 是包含名为 [[Get]][[Set]] 的任一字段的描述符。任何 Property Descriptor 都可以具有名为 [[Enumerable]][[Configurable]] 的字段。Property Descriptor 值不能既是数据 Property Descriptor 又是访问器 Property Descriptor;但是,它可以二者都不是(在这种情况下它是通用 Property Descriptor)。完整填充的 Property Descriptor是访问器 Property Descriptor 或数据 Property Descriptor,并且具有 Table 3 中定义的所有对应字段。

以下抽象操作在本规范中用于操作 Property Descriptor 值:

6.2.6.1 IsAccessorDescriptor ( propertyDesc )

The abstract operation IsAccessorDescriptor takes argument propertyDesc (a Property Descriptor) and returns a Boolean. It performs the following steps when called:

  1. 如果 propertyDesc 具有 [[Get]] 字段,则返回 true
  2. 如果 propertyDesc 具有 [[Set]] 字段,则返回 true
  3. 返回 false

6.2.6.2 IsDataDescriptor ( propertyDesc )

The abstract operation IsDataDescriptor takes argument propertyDesc (a Property Descriptor) and returns a Boolean. It performs the following steps when called:

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

6.2.6.3 IsGenericDescriptor ( propertyDesc )

The abstract operation IsGenericDescriptor takes argument propertyDesc (a Property Descriptor) and returns a Boolean. It performs the following steps when called:

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

6.2.6.4 FromPropertyDescriptor ( propertyDesc )

The abstract operation FromPropertyDescriptor takes argument propertyDesc (a Property Descriptor or undefined) and returns an Object or undefined. It performs the following steps when called:

  1. 如果 propertyDescundefined,则返回 undefined
  2. objOrdinaryObjectCreate(%Object.prototype%)。
  3. 断言:obj 是一个可扩展的普通对象,且没有自有属性。
  4. 如果 propertyDesc 具有 [[Value]] 字段,则
    1. 执行 ! CreateDataPropertyOrThrow(obj, "value", propertyDesc.[[Value]])。
  5. 如果 propertyDesc 具有 [[Writable]] 字段,则
    1. 执行 ! CreateDataPropertyOrThrow(obj, "writable", propertyDesc.[[Writable]])。
  6. 如果 propertyDesc 具有 [[Get]] 字段,则
    1. 执行 ! CreateDataPropertyOrThrow(obj, "get", propertyDesc.[[Get]])。
  7. 如果 propertyDesc 具有 [[Set]] 字段,则
    1. 执行 ! CreateDataPropertyOrThrow(obj, "set", propertyDesc.[[Set]])。
  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 )

The abstract operation ToPropertyDescriptor takes argument obj (an ECMAScript language value) and returns either a normal completion containing a Property Descriptor or a throw completion. It performs the following steps when called:

  1. 如果 obj 不是 Object,则抛出 TypeError 异常。
  2. propertyDesc 为一个新的 Property Descriptor,其最初没有字段。
  3. hasEnumerable 为 ? HasProperty(obj, "enumerable")。
  4. 如果 hasEnumerabletrue,则
    1. enumerableToBoolean(? Get(obj, "enumerable")).
    2. propertyDesc.[[Enumerable]] 设置为 enumerable
  5. hasConfigurable 为 ? HasProperty(obj, "configurable")。
  6. 如果 hasConfigurabletrue,则
    1. configurableToBoolean(? Get(obj, "configurable")).
    2. propertyDesc.[[Configurable]] 设置为 configurable
  7. hasValue 为 ? HasProperty(obj, "value")。
  8. 如果 hasValuetrue,则
    1. value 为 ? Get(obj, "value")。
    2. propertyDesc.[[Value]] 设置为 value
  9. hasWritable 为 ? HasProperty(obj, "writable")。
  10. 如果 hasWritabletrue,则
    1. writableToBoolean(? Get(obj, "writable")).
    2. propertyDesc.[[Writable]] 设置为 writable
  11. hasGet 为 ? HasProperty(obj, "get")。
  12. 如果 hasGettrue,则
    1. getter 为 ? Get(obj, "get")。
    2. 如果 IsCallable(getter) 是 falsegetter 不是 undefined,则抛出 TypeError 异常。
    3. propertyDesc.[[Get]] 设置为 getter
  13. hasSet 为 ? HasProperty(obj, "set")。
  14. 如果 hasSettrue,则
    1. setter 为 ? Get(obj, "set")。
    2. 如果 IsCallable(setter) 是 falsesetter 不是 undefined,则抛出 TypeError 异常。
    3. propertyDesc.[[Set]] 设置为 setter
  15. 如果 propertyDesc 具有 [[Get]] 字段或 propertyDesc 具有 [[Set]] 字段,则
    1. 如果 propertyDesc 具有 [[Value]] 字段或 propertyDesc 具有 [[Writable]] 字段,则抛出 TypeError 异常。
  16. 返回 propertyDesc

6.2.6.6 CompletePropertyDescriptor ( propertyDesc )

The abstract operation CompletePropertyDescriptor takes argument propertyDesc (a Property Descriptor) and returns unused. It performs the following steps when called:

  1. likeRecord { [[Value]]: undefined, [[Writable]]: false, [[Get]]: undefined, [[Set]]: undefined, [[Enumerable]]: false, [[Configurable]]: false }。
  2. 如果 IsGenericDescriptor(propertyDesc) 是 trueIsDataDescriptor(propertyDesc) 是 true,则
    1. 如果 propertyDesc 不具有 [[Value]] 字段,则将 propertyDesc.[[Value]] 设置为 like.[[Value]]
    2. 如果 propertyDesc 不具有 [[Writable]] 字段,则将 propertyDesc.[[Writable]] 设置为 like.[[Writable]]
  3. 否则,
    1. 如果 propertyDesc 不具有 [[Get]] 字段,则将 propertyDesc.[[Get]] 设置为 like.[[Get]]
    2. 如果 propertyDesc 不具有 [[Set]] 字段,则将 propertyDesc.[[Set]] 设置为 like.[[Set]]
  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 Closures 是元值,并使用函数应用样式调用,例如 closure(arg1, arg2)。与抽象操作一样,调用会执行 Abstract Closure 所描述的算法步骤。

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

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

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

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

6.2.9 Data Blocks

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

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

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

Shared Data Blocks 的语义由内存模型使用 Shared Data Block 事件定义。下面的抽象操作引入 Shared Data Block 事件,并作为求值语义与内存模型事件语义之间的接口。事件形成一个候选执行,内存模型将其作为过滤器作用于该候选执行。完整语义请参阅内存模型

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

以下抽象操作在本规范中用于操作 Data Block 值:

6.2.9.1 CreateByteDataBlock ( size )

The abstract operation CreateByteDataBlock takes argument size (a non-negative integer) and returns either a normal completion containing a Data Block or a throw completion. It performs the following steps when called:

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

6.2.9.2 CreateSharedByteDataBlock ( size )

The abstract operation CreateSharedByteDataBlock takes argument size (a non-negative integer) and returns either a normal completion containing a Shared Data Block or a throw completion. It performs the following steps when called:

  1. dataBlock 为一个由 size 个字节组成的新 Shared Data Block 值。如果无法创建这样的 Shared Data Block,则抛出 RangeError 异常。
  2. agentRecord周围 agentAgent Record
  3. executionagentRecord.[[CandidateExecution]]
  4. eventsRecordexecution.[[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 )

The abstract operation CopyDataBlockBytes takes arguments toBlock (a Data Block or a Shared Data Block), toIndex (a non-negative integer), fromBlock (a Data Block or a Shared Data Block), fromIndex (a non-negative integer), and count (a non-negative integer) and returns unused. It performs the following steps when called:

  1. 断言:fromBlocktoBlock 是不同的值。
  2. fromSizefromBlock 中的字节数。
  3. 断言:fromIndex + countfromSize
  4. toSizetoBlock 中的字节数。
  5. 断言:toIndex + counttoSize
  6. 重复,当 count > 0 时:
    1. 如果 fromBlockShared Data Block,则
      1. agentRecord周围 agentAgent Record
      2. executionagentRecord.[[CandidateExecution]]
      3. eventsRecordexecution.[[EventsRecords]][[AgentSignifier]]AgentSignifier() 的 Agent Events Record
      4. bytes 为一个 List,其唯一元素是一个非确定性选择的字节值
      5. 注记:在实现中,bytes 是底层硬件上非原子读指令的结果。该非确定性是内存模型的语义规定,用于描述弱一致性硬件的可观察行为。
      6. readEventReadSharedMemory { [[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. 如果 toBlockShared 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 Descriptors 不用于私有元素,私有字段的行为类似于不可配置、不可枚举、可写的数据属性,私有方法的行为类似于不可配置、不可枚举、不可写的数据属性,而私有访问器的行为类似于不可配置、不可枚举的访问器属性

PrivateElement 类型的值是 Record 值,其字段由 Table 9 定义。这类值称为 PrivateElements

Table 9: PrivateElement 字段
字段名 其存在所对应的 [[Kind]] 字段值 含义
[[Key]] 全部 Private Name 字段、方法或访问器的名称。
[[Kind]] 全部 field, method, or accessor 元素的种类。
[[Value]] fieldmethod ECMAScript 语言值 字段的值。
[[Get]] accessor 函数对象undefined 私有访问器的 getter。
[[Set]] accessor 函数对象undefined 私有访问器的 setter。

6.2.11 ClassFieldDefinition Record 规范类型

ClassFieldDefinition 类型是用于类字段规范的 Record

ClassFieldDefinition 类型的值是 Record 值,其字段由 Table 10 定义。这类值称为 ClassFieldDefinition Records

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

6.2.12 Private Names

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

6.2.13 ClassStaticBlockDefinition Record 规范类型

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

ClassStaticBlockDefinition Records 具有 Table 11 中列出的字段。

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

7 抽象操作

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

7.1 类型转换

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

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

7.1.1 ToPrimitive ( input [ , preferredType ] )

The abstract operation ToPrimitive takes argument input (an ECMAScript language value) and optional argument preferredType (string or number) and returns either a normal completion containing an ECMAScript language value or a throw completion. 它将其 input 实参转换为非 Object 类型。如果对象能够转换为不止一种原始类型,它可以使用可选提示 preferredType 来偏向该类型。 It performs the following steps when called:

  1. 如果 input 是 Object,则
    1. exoticToPrimitive 为 ? GetMethod(input, %Symbol.toPrimitive%)。
    2. 如果 exoticToPrimitive 不是 undefined,则
      1. 如果 preferredType 不存在,则
        1. hint"default"
      2. 否则如果 preferredTypestring,则
        1. hint"string"
      3. 否则,
        1. 断言:preferredTypenumber
        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
Note

当调用 ToPrimitive 时没有提示,它通常表现得好像提示为 number。然而,对象可以通过定义 %Symbol.toPrimitive% 方法来覆盖此行为。在本规范中定义的对象中,只有 Dates(参见 21.4.4.45)和 Symbol 对象(参见 20.4.3.5)会覆盖默认的 ToPrimitive 行为。Dates 将不存在提示视为提示为 string

7.1.1.1 OrdinaryToPrimitive ( obj, hint )

The abstract operation OrdinaryToPrimitive takes arguments obj (an Object) and hint (string or number) and returns either a normal completion containing an ECMAScript language value or a throw completion. It performs the following steps when called:

  1. 如果 hintstring,则
    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 )

The abstract operation ToBoolean takes argument arg (an ECMAScript language value) and returns a Boolean. 它将 arg 转换为 Boolean 类型的值。 It performs the following steps when called:

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

7.1.3 ToNumeric ( arg )

The abstract operation ToNumeric takes argument arg (an ECMAScript language value) and returns either a normal completion containing either a Number or a BigInt, or a throw completion. 它返回转换为 Number 或 BigInt 的 arg。 It performs the following steps when called:

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

7.1.4 ToNumber ( arg )

The abstract operation ToNumber takes argument arg (an ECMAScript language value) and returns either a normal completion containing a Number or a throw completion. 它将 arg 转换为 Number 类型的值。 It performs the following steps when called:

  1. 如果 arg 是 Number,则返回 arg
  2. 如果 arg 是 Symbol 或 BigInt,则抛出 TypeError 异常。
  3. 如果 argundefined,则返回 NaN
  4. 如果 argnullfalse,则返回 +0𝔽
  5. 如果 argtrue,则返回 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)中所用的定义

Note

应注意 StringNumericLiteralNumericLiteral 的语法之间存在一些差异:

7.1.4.1.1 StringToNumber ( string )

The abstract operation StringToNumber takes argument string (a String) and returns a Number. It performs the following steps when called:

  1. literalParseText(string, StringNumericLiteral)。
  2. 如果 literal 是错误的 List,则返回 NaN
  3. 返回 literalStringNumericValue

7.1.4.1.2 Runtime Semantics: StringNumericValue

The syntax-directed operation StringNumericValue takes no arguments and returns a Number.

Note

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

It is defined piecewise over the following productions:

StringNumericLiteral ::: StrWhiteSpaceopt
  1. 返回 +0𝔽
StringNumericLiteral ::: StrWhiteSpaceopt StrNumericLiteral StrWhiteSpaceopt
  1. 返回 StrNumericLiteralStringNumericValue
StrNumericLiteral ::: NonDecimalIntegerLiteral
  1. 返回 𝔽(NonDecimalIntegerLiteral 的 MV)。
StrDecimalLiteral ::: - StrUnsignedDecimalLiteral
  1. aStrUnsignedDecimalLiteralStringNumericValue
  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 存在,则令 eExponentPart 的 MV;否则令 e 为 0。
  5. 返回 RoundMVResult((a + (b × 10-n)) × 10e)。
StrUnsignedDecimalLiteral ::: . DecimalDigits ExponentPartopt
  1. bDecimalDigits 的 MV。
  2. 如果 ExponentPart 存在,则令 eExponentPart 的 MV;否则令 e 为 0。
  3. nDecimalDigits 中码点的数量。
  4. 返回 RoundMVResult(b × 10e - n)。
StrUnsignedDecimalLiteral ::: DecimalDigits ExponentPartopt
  1. aDecimalDigits 的 MV。
  2. 如果 ExponentPart 存在,则令 eExponentPart 的 MV;否则令 e 为 0。
  3. 返回 RoundMVResult(a × 10e)。

7.1.4.1.3 RoundMVResult ( n )

The abstract operation RoundMVResult takes argument n (a mathematical value) and returns a Number. 它以实现定义的方式将 n 转换为 Number。就此抽象操作而言,如果一个数字不是零,或者其左侧存在非零数字且其右侧存在非零数字,则该数字是有效的。就此抽象操作而言,一个数学值表示的“所表示的数学值”是一个数学值“的十进制表示”的逆。 It performs the following steps when called:

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

7.1.5 ToIntegerOrInfinity ( arg )

The abstract operation ToIntegerOrInfinity takes argument arg (an ECMAScript language value) and returns either a normal completion containing either an integer, +∞, or -∞, or a throw completion. 它将 arg 转换为表示其 Number 值并截断小数部分的整数;或者当该 Number 值为无穷时,转换为 +∞ 或 -∞。 It performs the following steps when called:

  1. number 为 ? ToNumber(arg)。
  2. 如果 numberNaN+0𝔽-0𝔽 之一,则返回 0。
  3. 如果 number+∞𝔽,则返回 +∞。
  4. 如果 number-∞𝔽,则返回 -∞。
  5. 返回 truncate((number))。
Note
对任意值 x𝔽(ToIntegerOrInfinity(x)) 永远不会返回 -0𝔽。小数部分的截断是在将 x 转换为数学值之后执行的。

7.1.6 ToFixedSizeInteger ( int, signed, bitWidth )

The abstract operation ToFixedSizeInteger takes arguments int (an integer, +∞, or -∞), signed (unsigned or signed), and bitWidth (a positive integer) and returns an integer. 它将 int 映射到 2bitWidth 个整数之一:如果 signedunsigned,则在从 0 到 2bitWidth - 1 的闭区间内;如果 signedsigned,则在从 -2bitWidth - 1 到 2bitWidth - 1 - 1 的闭区间内。 It performs the following steps when called:

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

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.7 ToInt32 ( arg )

The abstract operation ToInt32 takes argument arg (an ECMAScript language value) and returns either a normal completion containing an integral Number or a throw completion. 它将 arg 转换为 232integral Number 值之一,这些值位于从 𝔽(-231) 到 𝔽(231 - 1) 的闭区间内,不包括 -0𝔽。 It performs the following steps when called:

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

7.1.8 ToUint32 ( arg )

The abstract operation ToUint32 takes argument arg (an ECMAScript language value) and returns either a normal completion containing an integral Number or a throw completion. 它将 arg 转换为 232integral Number 值之一,这些值位于从 +0𝔽𝔽(232 - 1) 的闭区间内。 It performs the following steps when called:

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

7.1.9 ToInt16 ( arg )

The abstract operation ToInt16 takes argument arg (an ECMAScript language value) and returns either a normal completion containing an integral Number or a throw completion. 它将 arg 转换为 216integral Number 值之一,这些值位于从 𝔽(-215) 到 𝔽(215 - 1) 的闭区间内,不包括 -0𝔽。 It performs the following steps when called:

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

7.1.10 ToUint16 ( arg )

The abstract operation ToUint16 takes argument arg (an ECMAScript language value) and returns either a normal completion containing an integral Number or a throw completion. 它将 arg 转换为 216integral Number 值之一,这些值位于从 +0𝔽𝔽(216 - 1) 的闭区间内。 It performs the following steps when called:

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

7.1.11 ToInt8 ( arg )

The abstract operation ToInt8 takes argument arg (an ECMAScript language value) and returns either a normal completion containing an integral Number or a throw completion. 它将 arg 转换为 28integral Number 值之一,这些值位于从 -128𝔽127𝔽闭区间内,不包括 -0𝔽。 It performs the following steps when called:

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

7.1.12 ToUint8 ( arg )

The abstract operation ToUint8 takes argument arg (an ECMAScript language value) and returns either a normal completion containing an integral Number or a throw completion. 它将 arg 转换为 28integral Number 值之一,这些值位于从 +0𝔽255𝔽闭区间内。 It performs the following steps when called:

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

7.1.13 ToUint8Clamp ( arg )

The abstract operation ToUint8Clamp takes argument arg (an ECMAScript language value) and returns either a normal completion containing an integral Number or a throw completion. 它将 arg 钳制并舍入为 28integral Number 值之一,这些值位于从 +0𝔽255𝔽闭区间内。 It performs the following steps when called:

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

不同于大多数其他 ECMAScript 整数转换操作,ToUint8Clamp 会对非整数值进行舍入而不是截断。它还使用“舍入到最接近偶数”的平局决策方式,这不同于 Math.round 的“四舍五入”平局决策方式。

7.1.14 ToBigInt ( arg )

The abstract operation ToBigInt takes argument arg (an ECMAScript language value) and returns either a normal completion containing a BigInt or a throw completion. 它将 arg 转换为 BigInt 值;如果需要从 Number 进行隐式转换,则抛出。 It performs the following steps when called:

  1. primitive 为 ? ToPrimitive(arg, number)。
  2. 返回 primitiveTable 12 中对应的值。
Table 12: BigInt 转换
实参类型 结果
Undefined 抛出 TypeError 异常。
Null 抛出 TypeError 异常。
Boolean 如果 primitivetrue,则返回 1n;如果 primitivefalse,则返回 0n
BigInt 返回 primitive
Number 抛出 TypeError 异常。
String
  1. nStringToBigInt(primitive)。
  2. 如果 nundefined,则抛出 SyntaxError 异常。
  3. 返回 n
Symbol 抛出 TypeError 异常。

7.1.15 StringToBigInt ( string )

The abstract operation StringToBigInt takes argument string (a String) and returns a BigInt or undefined. It performs the following steps when called:

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

7.1.15.1 StringIntegerLiteral 文法

StringToBigInt 使用以下文法。

语法

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

7.1.15.2 Runtime Semantics: MV

7.1.16 ToBigInt64 ( arg )

The abstract operation ToBigInt64 takes argument arg (an ECMAScript language value) and returns either a normal completion containing a BigInt or a throw completion. 它将 arg 转换为 264 个 BigInt 值之一,这些值位于从 (-263) 到 (263 - 1) 的闭区间内。 It performs the following steps when called:

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

7.1.17 ToBigUint64 ( arg )

The abstract operation ToBigUint64 takes argument arg (an ECMAScript language value) and returns either a normal completion containing a BigInt or a throw completion. 它将 arg 转换为 264 个 BigInt 值之一,这些值位于从 0(264 - 1) 的闭区间内。 It performs the following steps when called:

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

7.1.18 ToString ( arg )

The abstract operation ToString takes argument arg (an ECMAScript language value) and returns either a normal completion containing a String or a throw completion. 它将 arg 转换为 String 类型的值。 It performs the following steps when called:

  1. 如果 arg 是 String,则返回 arg
  2. 如果 arg 是 Symbol,则抛出 TypeError 异常。
  3. 如果 argundefined,则返回 "undefined"
  4. 如果 argnull,则返回 "null"
  5. 如果 argtrue,则返回 "true"
  6. 如果 argfalse,则返回 "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.19 ToObject ( arg )

The abstract operation ToObject takes argument arg (an ECMAScript language value) and returns either a normal completion containing an Object or a throw completion. 它将 arg 转换为 Object 类型的值。 It performs the following steps when called:

  1. 如果 argundefinednull,则抛出 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.20 ToPropertyKey ( arg )

The abstract operation ToPropertyKey takes argument arg (an ECMAScript language value) and returns either a normal completion containing a property key or a throw completion. 它将 arg 转换为可用作属性键的值。 It performs the following steps when called:

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

7.1.21 ToLength ( arg )

The abstract operation ToLength takes argument arg (an ECMAScript language value) and returns either a normal completion containing a non-negative integral Number or a throw completion. 它将 arg 钳制并截断为适合用作类数组对象长度的非负 integral Number。 It performs the following steps when called:

  1. length 为 ? ToIntegerOrInfinity(arg)。
  2. 如果 length ≤ 0,则返回 +0𝔽
  3. 返回 𝔽(min(length, 253 - 1))。

7.1.22 CanonicalNumericIndexString ( arg )

The abstract operation CanonicalNumericIndexString takes argument arg (a String) and returns a Number or undefined. 如果 arg"-0",或与某个 Number 值 nToString(n) 完全匹配,则它返回相应的 Number 值。否则,它返回 undefined。 It performs the following steps when called:

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

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

7.1.23 ToIndex ( arg )

The abstract operation ToIndex takes argument arg (an ECMAScript language value) and returns either a normal completion containing a non-negative integer or a throw completion. 它将 arg 转换为整数,并在该整数为非负且对应于整数索引时返回该整数。否则,它抛出异常。 It performs the following steps when called:

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

7.2 测试和比较操作

7.2.1 RequireObjectCoercible ( arg )

The abstract operation RequireObjectCoercible takes argument arg (an ECMAScript language value) and returns either a normal completion containing unused or a throw completion. 如果 arg 是无法使用 ToObject 转换为 Object 的值,则它抛出错误。 It performs the following steps when called:

  1. 如果 argundefinednull,则抛出 TypeError 异常。
  2. 返回 unused

7.2.2 IsArray ( arg )

The abstract operation IsArray takes argument arg (an ECMAScript language value) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

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

7.2.3 IsCallable ( arg )

The abstract operation IsCallable takes argument arg (an ECMAScript language value) and returns a Boolean. 它确定 arg 是否是具有 [[Call]] 内部方法的可调用函数。 It performs the following steps when called:

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

7.2.4 IsConstructor ( arg )

The abstract operation IsConstructor takes argument arg (an ECMAScript language value) and returns a Boolean. 它确定 arg 是否是具有 [[Construct]] 内部方法的函数对象。 It performs the following steps when called:

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

7.2.5 IsExtensible ( obj )

The abstract operation IsExtensible takes argument obj (an Object) and returns either a normal completion containing a Boolean or a throw completion. 它用于确定是否可以向 obj 添加额外属性。 It performs the following steps when called:

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

7.2.6 IsRegExp ( arg )

The abstract operation IsRegExp takes argument arg (an ECMAScript language value) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

  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 )

The abstract operation IsStringWellFormedUnicode takes argument string (a String) and returns a Boolean. 它按照 6.1.4 中所述,将 string 解释为 UTF-16 编码码点序列,并确定它是否是格式良好的 UTF-16 序列。 It performs the following steps when called:

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

7.2.8 SameType ( x, y )

The abstract operation SameType takes arguments x (an ECMAScript language value) and y (an ECMAScript language value) and returns a Boolean. 它确定两个实参是否属于同一类型。 It performs the following steps when called:

  1. 如果 xundefinedyundefined,则返回 true
  2. 如果 xnullynull,则返回 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 )

The abstract operation SameValue takes arguments x (an ECMAScript language value) and y (an ECMAScript language value) and returns a Boolean. 它确定两个实参是否为同一值。 It performs the following steps when called:

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

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

7.2.10 SameValueZero ( x, y )

The abstract operation SameValueZero takes arguments x (an ECMAScript language value) and y (an ECMAScript language value) and returns a Boolean. 它确定两个实参是否为同一值(忽略 +0𝔽-0𝔽 之间的差异)。 It performs the following steps when called:

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

SameValueZero 与 SameValue 的不同仅在于,它将 +0𝔽-0𝔽 视为等价。

7.2.11 SameValueNonNumber ( x, y )

The abstract operation SameValueNonNumber takes arguments x (an ECMAScript language value, but not a Number) and y (an ECMAScript language value, but not a Number) and returns a Boolean. It performs the following steps when called:

  1. 断言:SameType(x, y) 是 true
  2. 如果 xundefinednull,则返回 true
  3. 如果 x 是 BigInt,则
    1. 返回 BigInt::equal(x, y)。
  4. 如果 x 是 String,则
    1. 如果 xy 具有相同长度并且相同位置具有相同码元,则返回 true
    2. 返回 false
  5. 如果 x 是 Boolean,则
    1. 如果 xtrueytrue,则返回 true
    2. 如果 xfalseyfalse,则返回 true
    3. 返回 false
  6. 注记:所有其他 ECMAScript 语言值均按身份进行比较。
  7. 如果 xy,则返回 true
  8. 返回 false
Note 1
出于说明目的,此算法中单独处理了一些情况,即使这样做并非必要。
Note 2
xy”具体意味着什么,详见 5.2.8

7.2.12 IsLessThan ( x, y, leftFirst )

The abstract operation IsLessThan takes arguments x (an ECMAScript language value), y (an ECMAScript language value), and leftFirst (a Boolean) and returns either a normal completion containing either a Boolean or undefined, or a throw completion. 它提供比较 x < y 的语义,返回 truefalseundefined(表示操作数无法被强制转换为同一数值类型的可比较值)。leftFirst 标志用于控制对 xy 执行可能具有可见副作用的操作的顺序。它是必要的,因为 ECMAScript 指定表达式按从左到右的顺序求值。如果 leftFirsttrue,则 x 形参对应于出现在 y 形参对应表达式左侧的表达式。如果 leftFirstfalse,则情况相反,必须先对 y 执行操作,再对 x 执行操作。 It performs the following steps when called:

  1. 如果 leftFirsttrue,则
    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. lxpx 的长度。
    2. lypy 的长度。
    3. 对每个满足 0 ≤ i < min(lx, ly) 的整数 i,按升序执行:
      1. cxpx 内索引 i 处码元的数值。
      2. cypy 内索引 i 处码元的数值。
      3. 如果 cx < cy,则返回 true
      4. 如果 cx > cy,则返回 false
    4. 如果 lx < ly,则返回 true
    5. 返回 false
  4. 如果 px 是 BigInt 且 py 是 String,则
    1. nyStringToBigInt(py)。
    2. 如果 nyundefined,则返回 undefined
    3. 返回 BigInt::lessThan(px, ny)。
  5. 如果 px 是 String 且 py 是 BigInt,则
    1. nxStringToBigInt(px)。
    2. 如果 nxundefined,则返回 undefined
    3. 返回 BigInt::lessThan(nx, py)。
  6. 注记:因为 pxpy 是原始值,求值顺序并不重要。
  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. 如果 nxNaNnyNaN,则返回 undefined
  12. 如果 nx-∞𝔽ny+∞𝔽,则返回 true
  13. 如果 nx+∞𝔽ny-∞𝔽,则返回 false
  14. 如果 (nx) < (ny),则返回 true
  15. 返回 false
Note 1

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

Note 2

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

7.2.13 IsLooselyEqual ( x, y )

The abstract operation IsLooselyEqual takes arguments x (an ECMAScript language value) and y (an ECMAScript language value) and returns either a normal completion containing a Boolean or a throw completion. 它提供 == 运算符的语义。 It performs the following steps when called:

  1. 如果 SameType(x, y) 是 true,则
    1. 返回 IsStrictlyEqual(x, y)。
  2. 如果 xnullyundefined,则返回 true
  3. 如果 xundefinedynull,则返回 true
  4. 如果宿主是 Web 浏览器,或以其他方式支持 [[IsHTMLDDA]] 内部槽,则
    1. 如果 x 是 Object,x 具有 [[IsHTMLDDA]] 内部槽,且 yundefinednull,则返回 true
    2. 如果 xundefinednully 是 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. nStringToBigInt(y)。
    2. 如果 nundefined,则返回 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 不是有限的,则返回 false
    2. 如果 (x) = (y),则返回 true
    3. 返回 false
  14. 返回 false

7.2.14 IsStrictlyEqual ( x, y )

The abstract operation IsStrictlyEqual takes arguments x (an ECMAScript language value) and y (an ECMAScript language value) and returns a Boolean. 它提供 === 运算符的语义。 It performs the following steps when called:

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

此算法与 SameValue 算法的不同之处在于其对有符号零和 NaNs 的处理。

7.3 对象上的操作

7.3.1 MakeBasicObject ( internalSlotsList )

The abstract operation MakeBasicObject takes argument internalSlotsList (a List of internal slot names) and returns an Object. 它是所有通过算法创建的 ECMAScript 对象的来源,包括普通对象异质对象。它抽取了创建所有对象时使用的公共步骤,并集中化对象创建。 It performs the following steps when called:

  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
Note

在本规范中,异质对象在诸如 ArrayCreateBoundFunctionCreate 这样的抽象操作中创建,方法是先调用 MakeBasicObject 以获得一个基本的、基础性的对象,然后重写该对象的一些或全部内部方法。为了封装异质对象的创建,对象的基本内部方法绝不会在这些操作之外被修改。

7.3.2 Get ( obj, propertyKey )

The abstract operation Get takes arguments obj (an Object) and propertyKey (a property key) and returns either a normal completion containing an ECMAScript language value or a throw completion. 它用于取回对象的特定属性的值。 It performs the following steps when called:

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

7.3.3 GetV ( value, propertyKey )

The abstract operation GetV takes arguments value (an ECMAScript language value) and propertyKey (a property key) and returns either a normal completion containing an ECMAScript language value or a throw completion. 它用于取回 ECMAScript 语言值的特定属性的值。如果该值不是对象,则使用适合该值类型的包装对象执行属性查找。 It performs the following steps when called:

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

7.3.4 Set ( obj, propertyKey, value, throw )

The abstract operation Set takes arguments obj (an Object), propertyKey (a property key), value (an ECMAScript language value), and throw (a Boolean) and returns either a normal completion containing unused or a throw completion. 它用于设置对象的特定属性的值。value 是该属性的新值。 It performs the following steps when called:

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

7.3.5 CreateDataProperty ( obj, propertyKey, value )

The abstract operation CreateDataProperty takes arguments obj (an Object), propertyKey (a property key), and value (an ECMAScript language value) and returns either a normal completion containing a Boolean or a throw completion. 它用于创建对象的一个新自有属性。 It performs the following steps when called:

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

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

7.3.6 CreateDataPropertyOrThrow ( obj, propertyKey, value )

The abstract operation CreateDataPropertyOrThrow takes arguments obj (an Object), propertyKey (a property key), and value (an ECMAScript language value) and returns either a normal completion containing unused or a throw completion. 它用于创建对象的一个新自有属性。如果所请求的属性更新不能执行,则抛出 TypeError 异常。 It performs the following steps when called:

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

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

7.3.7 CreateNonEnumerableDataPropertyOrThrow ( obj, propertyKey, value )

The abstract operation CreateNonEnumerableDataPropertyOrThrow takes arguments obj (an Object), propertyKey (a property key), and value (an ECMAScript language value) and returns unused. 它用于创建普通对象的一个新的不可枚举自有属性。 It performs the following steps when called:

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

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

7.3.8 DefinePropertyOrThrow ( obj, propertyKey, propertyDesc )

The abstract operation DefinePropertyOrThrow takes arguments obj (an Object), propertyKey (a property key), and propertyDesc (a Property Descriptor) and returns either a normal completion containing unused or a throw completion. 它用于调用对象的 [[DefineOwnProperty]] 内部方法,调用方式为:如果所请求的属性更新不能执行,则会抛出 TypeError 异常。 It performs the following steps when called:

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

7.3.9 DeletePropertyOrThrow ( obj, propertyKey )

The abstract operation DeletePropertyOrThrow takes arguments obj (an Object) and propertyKey (a property key) and returns either a normal completion containing unused or a throw completion. 它用于移除对象的特定自有属性。如果该属性不可配置,则抛出异常。 It performs the following steps when called:

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

7.3.10 GetMethod ( value, propertyKey )

The abstract operation GetMethod takes arguments value (an ECMAScript language value) and propertyKey (a property key) and returns either a normal completion containing either a function object or undefined, or a throw completion. 当预期某个 ECMAScript 语言值的特定属性的值是函数时,它用于获取该属性的值。 It performs the following steps when called:

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

7.3.11 HasProperty ( obj, propertyKey )

The abstract operation HasProperty takes arguments obj (an Object) and propertyKey (a property key) and returns either a normal completion containing a Boolean or a throw completion. 它用于确定对象是否具有指定属性键的属性。该属性可以是自有属性或继承属性。 It performs the following steps when called:

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

7.3.12 HasOwnProperty ( obj, propertyKey )

The abstract operation HasOwnProperty takes arguments obj (an Object) and propertyKey (a property key) and returns either a normal completion containing a Boolean or a throw completion. 它用于确定对象是否具有指定属性键的自有属性。 It performs the following steps when called:

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

7.3.13 Call ( func, thisValue [ , argList ] )

The abstract operation Call takes arguments func (an ECMAScript language value) and thisValue (an ECMAScript language value) and optional argument argList (a List of ECMAScript language values) and returns either a normal completion containing an ECMAScript language value or a throw completion. 它用于调用函数对象[[Call]] 内部方法。func函数对象thisValue 是作为 [[Call]]this 值的 ECMAScript 语言值argList 是传递给该内部方法对应实参的值。如果 argList 不存在,则使用新的空 List 作为其值。 It performs the following steps when called:

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

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

The abstract operation Construct takes argument ctor (a constructor) and optional arguments argList (a List of ECMAScript language values) and newTarget (a constructor) and returns either a normal completion containing an Object or a throw completion. 它用于调用函数对象[[Construct]] 内部方法。argListnewTarget 是要作为该内部方法对应实参传递的值。如果 argList 不存在,则使用新的空 List 作为其值。如果 newTarget 不存在,则使用 ctor 作为其值。 It performs the following steps when called:

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

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

7.3.15 SetIntegrityLevel ( obj, level )

The abstract operation SetIntegrityLevel takes arguments obj (an Object) and level (sealed or frozen) and returns either a normal completion containing a Boolean or a throw completion. 它用于固定对象的自有属性集合。 It performs the following steps when called:

  1. status 为 ? obj.[[PreventExtensions]]()。
  2. 如果 statusfalse,则返回 false
  3. keys 为 ? obj.[[OwnPropertyKeys]]()。
  4. 如果 levelsealed,则
    1. keys 的每个元素 key,执行:
      1. 执行 ? DefinePropertyOrThrow(obj, key, PropertyDescriptor { [[Configurable]]: false })。
  5. 否则,
    1. 断言:levelfrozen
    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 )

The abstract operation TestIntegrityLevel takes arguments obj (an Object) and level (sealed or frozen) and returns either a normal completion containing a Boolean or a throw completion. 它用于确定对象的自有属性集合是否已固定。 It performs the following steps when called:

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

7.3.17 CreateArrayFromList ( elements )

The abstract operation CreateArrayFromList takes argument elements (a List of ECMAScript language values) and returns an Array. 它用于创建一个 Array,其元素由 elements 提供。 It performs the following steps when called:

  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 )

The abstract operation LengthOfArrayLike takes argument obj (an Object) and returns either a normal completion containing a non-negative integer or a throw completion. 它返回类数组对象的 "length" 属性的值。 It performs the following steps when called:

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

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

Note 1
通常,类数组对象还会具有一些以整数索引为名称的属性。然而,这并不是此定义的要求。
Note 2
Arrays 和 String 对象是类数组对象的例子。

7.3.19 CreateListFromArrayLike ( obj [ , validElementTypes ] )

The abstract operation CreateListFromArrayLike takes argument obj (an ECMAScript language value) and optional argument validElementTypes (all or property-key) and returns either a normal completion containing a List of ECMAScript language values or a throw completion. 它用于创建一个 List 值,其元素由 obj 的索引属性提供。validElementTypes 指示允许作为元素的值的类型。 It performs the following steps when called:

  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. 如果 validElementTypesproperty-keynext 不是属性键,则抛出 TypeError 异常。
    4. next 追加到 list
    5. index 设置为 index + 1。
  7. 返回 list

7.3.20 Invoke ( value, propertyKey [ , argList ] )

The abstract operation Invoke takes arguments value (an ECMAScript language value) and propertyKey (a property key) and optional argument argList (a List of ECMAScript language values) and returns either a normal completion containing an ECMAScript language value or a throw completion. 它用于调用 ECMAScript 语言值的方法属性。value 同时作为属性的查找点和该调用的 this 值。argList 是传递给该方法的实参值列表。如果 argList 不存在,则使用新的空 List 作为其值。 It performs the following steps when called:

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

7.3.21 OrdinaryHasInstance ( ctor, instance )

The abstract operation OrdinaryHasInstance takes arguments ctor (an ECMAScript language value) and instance (an ECMAScript language value) and returns either a normal completion containing a Boolean or a throw completion. 它实现默认算法,用于确定 instance 是否继承自 ctor 提供的实例对象继承路径。 It performs the following steps when called:

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

7.3.22 SpeciesConstructor ( obj, defaultCtor )

The abstract operation SpeciesConstructor takes arguments obj (an Object) and defaultCtor (a constructor) and returns either a normal completion containing a constructor or a throw completion. 它用于取回应当用来创建派生自 obj 的新对象的构造函数defaultCtor 是在从 obj 开始无法找到构造函数%Symbol.species% 属性时要使用的构造函数。 It performs the following steps when called:

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

7.3.23 EnumerableOwnProperties ( obj, kind )

The abstract operation EnumerableOwnProperties takes arguments obj (an Object) and kind (key, value, or key+value) and returns either a normal completion containing a List of ECMAScript language values or a throw completion. It performs the following steps when called:

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

7.3.24 GetFunctionRealm ( func )

The abstract operation GetFunctionRealm takes argument func (a function object) and returns either a normal completion containing a Realm Record or a throw completion. It performs the following steps when called:

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

只有当 func 是一个非标准函数异质对象且没有 [[Realm]] 内部槽时,才会到达步骤 4

7.3.25 CopyDataProperties ( target, source, excludedItems )

The abstract operation CopyDataProperties takes arguments target (an Object), source (an ECMAScript language value), and excludedItems (a List of property keys) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

  1. 如果 sourceundefinednull,则返回 unused
  2. from 为 ! ToObject(source)。
  3. keys 为 ? from.[[OwnPropertyKeys]]()
  4. keys 的每个元素 nextKey,执行:
    1. excludedfalse
    2. excludedItems 的每个元素 element,执行:
      1. 如果 SameValue(element, nextKey) 是 true,则
        1. excluded 设置为 true
    3. 如果 excludedfalse,则
      1. propertyDesc 为 ? from.[[GetOwnProperty]](nextKey)
      2. 如果 propertyDesc 不是 undefinedpropertyDesc.[[Enumerable]]true,则
        1. propertyValue 为 ? Get(from, nextKey)。
        2. 执行 ! CreateDataPropertyOrThrow(target, nextKey, propertyValue)。
  5. 返回 unused
Note

这里传入的 target 始终是新创建的对象,在抛出错误的情况下无法直接访问。

7.3.26 PrivateElementFind ( obj, privateName )

The abstract operation PrivateElementFind takes arguments obj (an Object) and privateName (a Private Name) and returns a PrivateElement or empty. It performs the following steps when called:

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

7.3.27 PrivateFieldAdd ( obj, privateName, value )

The abstract operation PrivateFieldAdd takes arguments obj (an Object), privateName (a Private Name), and value (an ECMAScript language value) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

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

7.3.28 PrivateMethodOrAccessorAdd ( obj, method )

The abstract operation PrivateMethodOrAccessorAdd takes arguments obj (an Object) and method (a PrivateElement) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

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

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

7.3.29 HostEnsureCanAddPrivateElement ( obj )

The host-defined abstract operation HostEnsureCanAddPrivateElement takes argument obj (an Object) and returns either a normal completion containing unused or a throw completion. 它允许宿主环境阻止向特定宿主定义的异质对象添加私有元素。

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

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

抽象操作只由作为 Web 浏览器的 ECMAScript 宿主调用。

7.3.30 PrivateGet ( obj, privateName )

The abstract operation PrivateGet takes arguments obj (an Object) and privateName (a Private Name) and returns either a normal completion containing an ECMAScript language value or a throw completion. It performs the following steps when called:

  1. entryPrivateElementFind(obj, privateName)。
  2. 如果 entryempty,则抛出 TypeError 异常。
  3. 如果 entry.[[Kind]]fieldmethod,则
    1. 返回 entry.[[Value]]
  4. 断言:entry.[[Kind]]accessor
  5. 如果 entry.[[Get]]undefined,则抛出 TypeError 异常。
  6. getterentry.[[Get]]
  7. 返回 ? Call(getter, obj)。

7.3.31 PrivateSet ( obj, privateName, value )

The abstract operation PrivateSet takes arguments obj (an Object), privateName (a Private Name), and value (an ECMAScript language value) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

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

7.3.32 DefineField ( receiver, fieldRecord )

The abstract operation DefineField takes arguments receiver (an Object) and fieldRecord (a ClassFieldDefinition Record) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

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

7.3.33 InitializeInstanceElements ( obj, ctor )

The abstract operation InitializeInstanceElements takes arguments obj (an Object) and ctor (an ECMAScript function object or a built-in function object) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

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

7.3.34 AddValueToKeyedGroup ( groups, key, value )

The abstract operation AddValueToKeyedGroup takes arguments groups (a List of Records with fields [[Key]] (an ECMAScript language value) and [[Elements]] (a List of ECMAScript language values)), key (an ECMAScript language value), and value (an ECMAScript language value) and returns unused. It performs the following steps when called:

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

7.3.35 GroupBy ( items, callback, keyCoercion )

The abstract operation GroupBy takes arguments items (an ECMAScript language value), callback (an ECMAScript language value), and keyCoercion (property or collection) and returns either a normal completion containing a List of Records with fields [[Key]] (an ECMAScript language value) and [[Elements]] (a List of ECMAScript language values), or a throw completion. It performs the following steps when called:

  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. errorThrowCompletion(一个新创建的 TypeError 对象)。
      2. 返回 ? IteratorClose(iteratorRecord, error)。
    2. next 为 ? IteratorStepValue(iteratorRecord)。
    3. 如果 nextdone,则
      1. 返回 groups
    4. valuenext
    5. keyCompletion(Call(callback, undefined, « value, 𝔽(k) »))。
    6. IfAbruptCloseIterator(key, iteratorRecord)。
    7. 如果 keyCoercionproperty,则
      1. key 设置为 Completion(ToPropertyKey(key))。
      2. IfAbruptCloseIterator(key, iteratorRecord)。
    8. 否则,
      1. 断言:keyCoercioncollection
      2. key 设置为 CanonicalizeKeyedCollectionKey(key)。
    9. 执行 AddValueToKeyedGroup(groups, key, value)。
    10. k 设置为 k + 1。

7.3.36 GetOptionsObject ( options )

The abstract operation GetOptionsObject takes argument options (an ECMAScript language value) and returns either a normal completion containing an Object or a throw completion. It performs the following steps when called:

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

7.3.37 SetterThatIgnoresPrototypeProperties ( thisValue, home, propertyKey, value )

The abstract operation SetterThatIgnoresPrototypeProperties takes arguments thisValue (an ECMAScript language value), home (an Object), propertyKey (a property key), and value (an ECMAScript language value) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

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

7.4 迭代器对象上的操作

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

7.4.1 Iterator Records

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

Iterator Records 具有 Table 13 中列出的字段。

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

7.4.2 GetIteratorDirect ( obj )

The abstract operation GetIteratorDirect takes argument obj (an Object) and returns either a normal completion containing an Iterator Record or a throw completion. It performs the following steps when called:

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

7.4.3 GetIteratorFromMethod ( obj, method )

The abstract operation GetIteratorFromMethod takes arguments obj (an ECMAScript language value) and method (a function object) and returns either a normal completion containing an Iterator Record or a throw completion. It performs the following steps when called:

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

7.4.4 GetIterator ( obj, kind )

The abstract operation GetIterator takes arguments obj (an ECMAScript language value) and kind (sync or async) and returns either a normal completion containing an Iterator Record or a throw completion. It performs the following steps when called:

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

7.4.5 GetIteratorFlattenable ( obj, primitiveHandling )

The abstract operation GetIteratorFlattenable takes arguments obj (an ECMAScript language value) and primitiveHandling (iterate-string-primitives or reject-primitives) and returns either a normal completion containing an Iterator Record or a throw completion. It performs the following steps when called:

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

7.4.6 IteratorNext ( iteratorRecord [ , value ] )

The abstract operation IteratorNext takes argument iteratorRecord (an Iterator Record) and optional argument value (an ECMAScript language value) and returns either a normal completion containing an Object or a throw completion. It performs the following steps when called:

  1. 如果 value 不存在,则
    1. resultCompletion(Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]]))。
  2. 否则,
    1. resultCompletion(Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]], « value »))。
  3. 如果 resultthrow 完成,则
    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 )

The abstract operation IteratorComplete takes argument iteratorResult (an Object) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

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

7.4.8 IteratorValue ( iteratorResult )

The abstract operation IteratorValue takes argument iteratorResult (an Object) and returns either a normal completion containing an ECMAScript language value or a throw completion. It performs the following steps when called:

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

7.4.9 IteratorStep ( iteratorRecord )

The abstract operation IteratorStep takes argument iteratorRecord (an Iterator Record) and returns either a normal completion containing either an Object or done, or a throw completion. 它通过调用 iteratorRecord.[[NextMethod]]iteratorRecord.[[Iterator]] 请求下一个值,并返回 done 或 IteratorResult 对象;done 表示该迭代器已到达其末尾,IteratorResult 对象表示下一个值可用。 It performs the following steps when called:

  1. result 为 ? IteratorNext(iteratorRecord)。
  2. doneCompletion(IteratorComplete(result))。
  3. 如果 donethrow 完成,则
    1. iteratorRecord.[[Done]] 设置为 true
    2. 返回 ? done
  4. done 设置为 ! done
  5. 如果 donetrue,则
    1. iteratorRecord.[[Done]] 设置为 true
    2. 返回 done
  6. 返回 result

7.4.10 IteratorStepValue ( iteratorRecord )

The abstract operation IteratorStepValue takes argument iteratorRecord (an Iterator Record) and returns either a normal completion containing either an ECMAScript language value or done, or a throw completion. 它通过调用 iteratorRecord.[[NextMethod]]iteratorRecord.[[Iterator]] 请求下一个值,并返回 done 或 IteratorResult 对象中的值;done 表示该迭代器已到达其末尾,值表示下一个值可用。 It performs the following steps when called:

  1. result 为 ? IteratorStep(iteratorRecord)。
  2. 如果 resultdone,则
    1. 返回 done
  3. valueCompletion(IteratorValue(result))。
  4. 如果 valuethrow 完成,则
    1. iteratorRecord.[[Done]] 设置为 true
  5. 返回 ? value

7.4.11 IteratorClose ( iteratorRecord, completion )

The abstract operation IteratorClose takes arguments iteratorRecord (an Iterator Record) and completion (a Completion Record) and returns a Completion Record. 它用于通知迭代器应执行其在到达完成状态时通常会执行的任何动作。 It performs the following steps when called:

  1. 断言:iteratorRecord.[[Iterator]] 是 Object。
  2. iteratoriteratorRecord.[[Iterator]]
  3. innerResultCompletion(GetMethod(iterator, "return")).
  4. 如果 innerResult 是 normal 完成,则
    1. returninnerResult.[[Value]]
    2. 如果 returnundefined,则返回 ? completion
    3. innerResult 设置为 Completion(Call(return, iterator))。
  5. 如果 completionthrow 完成,则返回 ? completion
  6. 如果 innerResultthrow 完成,则返回 ? innerResult
  7. 如果 innerResult.[[Value]] 不是 Object,则抛出 TypeError 异常。
  8. 返回 ? completion

7.4.12 IteratorCloseAll ( iterators, completion )

The abstract operation IteratorCloseAll takes arguments iterators (a List of Iterator Records) and completion (a Completion Record) and returns a Completion Record. It performs the following steps when called:

  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. 断言:valueCompletion Record
  2. 如果 value 是 abrupt 完成,则返回 ? IteratorClose(iteratorRecord, value)。
  3. value 设置为 ! value

7.4.14 IfAbruptCloseIterators ( value, iteratorRecords )

IfAbruptCloseIterators 是一系列使用 Iterator Records 列表的算法步骤的简写。形如以下形式的算法步骤:

  1. IfAbruptCloseIterators(value, iteratorRecords).

与以下内容含义相同:

  1. 断言:valueCompletion Record
  2. 如果 value 是 abrupt 完成,则返回 ? IteratorCloseAll(iteratorRecords, value)。
  3. value 设置为 ! value

7.4.15 AsyncIteratorClose ( iteratorRecord, completion )

The abstract operation AsyncIteratorClose takes arguments iteratorRecord (an Iterator Record) and completion (a Completion Record) and returns a Completion Record. 它用于通知异步迭代器应执行其在到达完成状态时通常会执行的任何动作。 It performs the following steps when called:

  1. 断言:iteratorRecord.[[Iterator]] 是 Object。
  2. iteratoriteratorRecord.[[Iterator]]
  3. innerResultCompletion(GetMethod(iterator, "return")).
  4. 如果 innerResult 是 normal 完成,则
    1. returninnerResult.[[Value]]
    2. 如果 returnundefined,则返回 ? completion
    3. innerResult 设置为 Completion(Call(return, iterator))。
    4. 如果 innerResult 是 normal 完成,则将 innerResult 设置为 Completion(Await(innerResult.[[Value]]))。
  5. 如果 completionthrow 完成,则返回 ? completion
  6. 如果 innerResultthrow 完成,则返回 ? innerResult
  7. 如果 innerResult.[[Value]] 不是 Object,则抛出 TypeError 异常。
  8. 返回 ? completion

7.4.16 IfAbruptCloseAsyncIterator ( value, iteratorRecord )

IfAbruptCloseAsyncIterator 是一系列使用 Iterator Record 的算法步骤的简写。形如以下形式的算法步骤:

  1. IfAbruptCloseAsyncIterator(value, iteratorRecord).

与以下内容含义相同:

  1. 断言:valueCompletion Record
  2. 如果 value 是 abrupt 完成,则返回 ? AsyncIteratorClose(iteratorRecord, value)。
  3. value 设置为 ! value

7.4.17 CreateIteratorResultObject ( value, done )

The abstract operation CreateIteratorResultObject takes arguments value (an ECMAScript language value) and done (a Boolean) and returns an Object that conforms to the IteratorResult interface. 它创建一个符合 IteratorResult 接口的对象。 It performs the following steps when called:

  1. objOrdinaryObjectCreate(%Object.prototype%)。
  2. 执行 ! CreateDataPropertyOrThrow(obj, "value", value)。
  3. 执行 ! CreateDataPropertyOrThrow(obj, "done", done)。
  4. 返回 obj

7.4.18 CreateListIteratorRecord ( list )

The abstract operation CreateListIteratorRecord takes argument list (a List of ECMAScript language values) and returns an Iterator Record. 它创建一个 Iterator Record,其 [[NextMethod]] 返回 list 的连续元素。 It performs the following steps when called:

  1. closure 为一个不带形参的新 Abstract Closure,它捕获 list,并在被调用时执行以下步骤:
    1. list 的每个元素 value,执行:
      1. 执行 ? GeneratorYield(CreateIteratorResultObject(value, false))。
    2. 返回 NormalCompletion(undefined)。
  2. iteratorCreateIteratorFromClosure(closure, empty, %Iterator.prototype%)。
  3. 返回 Iterator Record { [[Iterator]]: iterator, [[NextMethod]]: %GeneratorPrototype.next%, [[Done]]: false }。
Note

list 迭代器对象永远不会被 ECMAScript 代码直接访问。

7.4.19 IteratorToList ( iteratorRecord )

The abstract operation IteratorToList takes argument iteratorRecord (an Iterator Record) and returns either a normal completion containing a List of ECMAScript language values or a throw completion. It performs the following steps when called:

  1. values 为新的空 List
  2. 重复:
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 nextdone,则
      1. 返回 values
    3. next 追加到 values

7.5 对可处置对象的操作

参见通用资源管理接口(27.2.1)。

7.5.1 DisposableResource 记录

DisposableResource 记录是一个记录值,用于封装一个可处置对象以及用于处置该对象的方法。DisposableResource 记录由 CreateDisposableResource 抽象操作产生。

DisposableResource 记录具有 Table 14 中列出的字段:

Table 14: DisposableResource 记录字段
字段名 含义
[[ResourceValue]] 一个对象或 undefined 要被处置的值。
[[Kind]] sync-disposeasync-dispose 指示资源是由 using 声明或 DisposableStack 对象添加的(sync-dispose),还是由 await using 声明或 AsyncDisposableStack 对象添加的(async-dispose)。
[[DisposeMethod]] 一个函数对象undefined 当资源被处置时,将以 [[ResourceValue]] 作为其 this 值调用的函数对象

7.5.2 AddDisposableResource ( disposableResourceStack, value, kind [ , method ] )

The abstract operation AddDisposableResource takes arguments disposableResourceStack (DisposableResource 记录的列表,), value (ECMAScript 语言值,), and kind (sync-disposeasync-dispose,) and optional argument method (函数对象,) and returns 含有 unused正常完成,或抛出完成. It performs the following steps when called:

  1. 如果存在 method,则
    1. 断言:valueundefined
    2. resource 为 ? CreateDisposableResource(undefined, kind, method)。
  2. 否则,
    1. 如果 valuenullundefined,且 kindsync-dispose,则返回 unused
    2. 注:当 valuenullundefined,且 kindasync-dispose 时,我们会记录该资源已被求值,以确保稍后处置资源时仍将执行 Await
    3. resource 为 ? CreateDisposableResource(value, kind)。
  3. resource 追加到 disposableResourceStack
  4. 返回 unused

7.5.3 CreateDisposableResource ( value, kind [ , method ] )

The abstract operation CreateDisposableResource takes arguments value (ECMAScript 语言值,) and kind (sync-disposeasync-dispose,) and optional argument method (函数对象,) and returns 含有 DisposableResource 记录正常完成,或抛出完成. It performs the following steps when called:

  1. 如果不存在 method,则
    1. 如果 valuenullundefined,则
      1. value 设置为 undefined
      2. method 设置为 undefined
    2. 否则,
      1. method 设置为 ? GetDisposeMethod(value, kind)。
      2. 如果 methodundefined,则抛出 TypeError 异常。
  2. 返回 DisposableResource 记录 { [[ResourceValue]]: value, [[Kind]]: kind, [[DisposeMethod]]: method }。

7.5.4 GetDisposeMethod ( value, kind )

The abstract operation GetDisposeMethod takes arguments value (ECMAScript 语言值,) and kind (sync-disposeasync-dispose,) and returns 含有函数对象undefined正常完成,或抛出完成. It performs the following steps when called:

  1. 如果 value 不是对象,则抛出 TypeError 异常。
  2. 如果 kindsync-dispose,则返回 ? GetMethod(value, %Symbol.dispose%)。
  3. 断言:kindasync-dispose
  4. asyncMethod 为 ? GetMethod(value, %Symbol.asyncDispose%)。
  5. 如果 asyncMethod 不是 undefined,则返回 asyncMethod
  6. syncMethod 为 ? GetMethod(value, %Symbol.dispose%)。
  7. 如果 syncMethodundefined,则返回 undefined
  8. closure 为一个新的抽象闭包,该闭包没有参数,捕获 syncMethod,并在被调用时执行以下步骤:
    1. objthis 值。
    2. promiseCapability 为 ! NewPromiseCapability(%Promise%)。
    3. resultCompletion(Call(syncMethod, obj))。
    4. IfAbruptRejectPromise(result, promiseCapability)。
    5. 执行 ! Call(promiseCapability.[[Resolve]], undefined, « undefined »)。
    6. 返回 promiseCapability.[[Promise]]
  9. 注:此函数对用户代码不可观察。它用于确保从同步 %Symbol.dispose% 方法返回的 Promise 不会被 awaited,并且同步异常会被转换为被拒绝的 Promise。
  10. 返回 CreateBuiltinFunction(closure, 0, "", « »)。

7.5.5 DisposeResources ( disposableResourceStack, completion )

The abstract operation DisposeResources takes arguments disposableResourceStack (DisposableResource 记录的列表,) and completion (含有 ECMAScript 语言值empty正常完成,或突兀完成,) and returns 含有 ECMAScript 语言值empty正常完成,或突兀完成. It performs the following steps when called:

  1. needsAwaitfalse
  2. hasAwaitedfalse
  3. outputCompletioncompletion
  4. disposableResourceStack 的每个元素 resource,按列表逆序执行
    1. valueresource.[[ResourceValue]]
    2. kindresource.[[Kind]]
    3. methodresource.[[DisposeMethod]]
    4. 如果 kindsync-disposeneedsAwaittrue,并且 hasAwaitedfalse,则
      1. 执行 ! Await(undefined)。
      2. needsAwait 设置为 false
    5. 如果 method 不是 undefined,则
      1. resultCompletion(Call(method, value))。
      2. 如果 result正常完成kindasync-dispose,则
        1. result 设置为 Completion(Await(result.[[Value]]))。
        2. hasAwaited 设置为 true
      3. 如果 result 是抛出完成,则
        1. 如果 outputCompletion 是抛出完成,则
          1. result 设置为 result.[[Value]]
          2. suppressedoutputCompletion.[[Value]]
          3. error 为新创建的 SuppressedError 对象。
          4. 执行 CreateNonEnumerableDataPropertyOrThrow(error, "error", result)。
          5. 执行 CreateNonEnumerableDataPropertyOrThrow(error, "suppressed", suppressed)。
          6. outputCompletion 设置为 ThrowCompletion(error)。
        2. 否则,
          1. outputCompletion 设置为 result
    6. 否则,
      1. 断言:kindasync-dispose
      2. needsAwait 设置为 true
      3. 注:这只能表示 await using 声明的初始化值为 nullundefined 的情况。
  5. 如果 needsAwaittruehasAwaitedfalse,则
    1. 执行 ! Await(undefined)。
  6. 注:此时 disposableResourceStack 将永远不会再被使用。在实现中可以丢弃 disposableResourceStack 的内容,例如通过垃圾回收。
  7. 返回 ? outputCompletion

8 语法制导操作

除本节中定义的操作外,本规范各处还定义了专门的语法制导操作

8.1 Runtime Semantics: Evaluation

The syntax-directed operation Evaluation takes no arguments and returns a Completion Record.

Note
此操作的定义分布在本规范的“ECMAScript 语言”各节中。每个定义都出现在相关产生式的定义性出现之后。

8.2 作用域分析

8.2.1 Static Semantics: BoundNames

The syntax-directed operation BoundNames takes no arguments and returns a List of Strings.

Note

"*default*" 在本规范中用作模块默认导出的合成名称,当该默认导出没有其他名称时使用。模块的 [[Environment]] 中会用该名称创建一个条目并保存对应的值,并且通过为该模块调用 ResolveExport ( exportName [ , resolveSet ] ) 来解析名为 "default" 的导出,将返回一个 [[BindingName]]"*default*"ResolvedBinding Record,随后它会在模块的 [[Environment]] 中解析为上述值。这样做只是为了方便规范表述,使匿名默认导出可以像任何其他导出一样被解析。这个 "*default*" 字符串永远不能被 ECMAScript 代码或模块链接算法访问。

It is defined piecewise over the following productions:

BindingIdentifier : Identifier
  1. 返回一个 List,其唯一元素是 IdentifierStringValue
BindingIdentifier : yield
  1. 返回 « "yield" »。
BindingIdentifier : await
  1. 返回 « "await" »。
LexicalDeclaration : LetOrConst BindingList ;
  1. 返回 BindingListBoundNames
UsingDeclaration : using BindingList ; AwaitUsingDeclaration : CoverAwaitExpressionAndAwaitUsingDeclarationHead BindingList ;
  1. 返回 BindingListBoundNames
BindingList : BindingList , LexicalBinding
  1. names1BindingListBoundNames
  2. names2LexicalBindingBoundNames
  3. 返回 names1names2列表连接
LexicalBinding : BindingIdentifier Initializeropt
  1. 返回 BindingIdentifierBoundNames
LexicalBinding : BindingPattern Initializer
  1. 返回 BindingPatternBoundNames
VariableDeclarationList : VariableDeclarationList , VariableDeclaration
  1. names1VariableDeclarationListBoundNames
  2. names2VariableDeclarationBoundNames
  3. 返回 names1names2列表连接
VariableDeclaration : BindingIdentifier Initializeropt
  1. 返回 BindingIdentifierBoundNames
VariableDeclaration : BindingPattern Initializer
  1. 返回 BindingPatternBoundNames
ObjectBindingPattern : { }
  1. 返回一个新的空 List
ObjectBindingPattern : { BindingPropertyList , BindingRestProperty }
  1. names1BindingPropertyListBoundNames
  2. names2BindingRestPropertyBoundNames
  3. 返回 names1names2列表连接
ArrayBindingPattern : [ Elisionopt ]
  1. 返回一个新的空 List
ArrayBindingPattern : [ Elisionopt BindingRestElement ]
  1. 返回 BindingRestElementBoundNames
ArrayBindingPattern : [ BindingElementList , Elisionopt ]
  1. 返回 BindingElementListBoundNames
ArrayBindingPattern : [ BindingElementList , Elisionopt BindingRestElement ]
  1. names1BindingElementListBoundNames
  2. names2BindingRestElementBoundNames
  3. 返回 names1names2列表连接
BindingPropertyList : BindingPropertyList , BindingProperty
  1. names1BindingPropertyListBoundNames
  2. names2BindingPropertyBoundNames
  3. 返回 names1names2列表连接
BindingElementList : BindingElementList , BindingElisionElement
  1. names1BindingElementListBoundNames
  2. names2BindingElisionElementBoundNames
  3. 返回 names1names2列表连接
BindingElisionElement : Elisionopt BindingElement
  1. 返回 BindingElementBoundNames
BindingProperty : PropertyName : BindingElement
  1. 返回 BindingElementBoundNames
SingleNameBinding : BindingIdentifier Initializeropt
  1. 返回 BindingIdentifierBoundNames
BindingElement : BindingPattern Initializeropt
  1. 返回 BindingPatternBoundNames
ForDeclaration : LetOrConst ForBinding
  1. 返回 ForBindingBoundNames
FunctionDeclaration : function BindingIdentifier ( FormalParameters ) { FunctionBody }
  1. 返回 BindingIdentifierBoundNames
FunctionDeclaration : function ( FormalParameters ) { FunctionBody }
  1. 返回 « "*default*" »。
FormalParameters : [empty]
  1. 返回一个新的空 List
FormalParameters : FormalParameterList , FunctionRestParameter
  1. names1FormalParameterListBoundNames
  2. names2FunctionRestParameterBoundNames
  3. 返回 names1names2列表连接
FormalParameterList : FormalParameterList , FormalParameter
  1. names1FormalParameterListBoundNames
  2. names2FormalParameterBoundNames
  3. 返回 names1names2列表连接
ArrowParameters : CoverParenthesizedExpressionAndArrowParameterList
  1. formalsCoverParenthesizedExpressionAndArrowParameterList覆盖的 ArrowFormalParameters
  2. 返回 formalsBoundNames
GeneratorDeclaration : function * BindingIdentifier ( FormalParameters ) { GeneratorBody }
  1. 返回 BindingIdentifierBoundNames
GeneratorDeclaration : function * ( FormalParameters ) { GeneratorBody }
  1. 返回 « "*default*" »。
AsyncGeneratorDeclaration : async function * BindingIdentifier ( FormalParameters ) { AsyncGeneratorBody }
  1. 返回 BindingIdentifierBoundNames
AsyncGeneratorDeclaration : async function * ( FormalParameters ) { AsyncGeneratorBody }
  1. 返回 « "*default*" »。
ClassDeclaration : class BindingIdentifier ClassTail
  1. 返回 BindingIdentifierBoundNames
ClassDeclaration : class ClassTail
  1. 返回 « "*default*" »。
AsyncFunctionDeclaration : async function BindingIdentifier ( FormalParameters ) { AsyncFunctionBody }
  1. 返回 BindingIdentifierBoundNames
AsyncFunctionDeclaration : async function ( FormalParameters ) { AsyncFunctionBody }
  1. 返回 « "*default*" »。
CoverCallExpressionAndAsyncArrowHead : MemberExpression Arguments
  1. headCoverCallExpressionAndAsyncArrowHead覆盖的 AsyncArrowHead
  2. 返回 headBoundNames
ImportDeclaration : import ImportClause FromClause WithClauseopt ;
  1. 返回 ImportClauseBoundNames
ImportDeclaration : import ModuleSpecifier WithClauseopt ;
  1. 返回一个新的空 List
ImportClause : ImportedDefaultBinding , NameSpaceImport
  1. names1ImportedDefaultBindingBoundNames
  2. names2NameSpaceImportBoundNames
  3. 返回 names1names2列表连接
ImportClause : ImportedDefaultBinding , NamedImports
  1. names1ImportedDefaultBindingBoundNames
  2. names2NamedImportsBoundNames
  3. 返回 names1names2列表连接
NamedImports : { }
  1. 返回一个新的空 List
ImportsList : ImportsList , ImportSpecifier
  1. names1ImportsListBoundNames
  2. names2ImportSpecifierBoundNames
  3. 返回 names1names2列表连接
ImportSpecifier : ModuleExportName as ImportedBinding
  1. 返回 ImportedBindingBoundNames
ExportDeclaration : export ExportFromClause FromClause WithClauseopt ; export NamedExports ;
  1. 返回一个新的空 List
ExportDeclaration : export VariableStatement
  1. 返回 VariableStatementBoundNames
ExportDeclaration : export Declaration
  1. 返回 DeclarationBoundNames
ExportDeclaration : export default HoistableDeclaration
  1. declNamesHoistableDeclarationBoundNames
  2. 如果 declNames包含元素 "*default*",则将 "*default*" 追加到 declNames
  3. 返回 declNames
ExportDeclaration : export default ClassDeclaration
  1. declNamesClassDeclarationBoundNames
  2. 如果 declNames包含元素 "*default*",则将 "*default*" 追加到 declNames
  3. 返回 declNames
ExportDeclaration : export default AssignmentExpression ;
  1. 返回 « "*default*" »。

8.2.2 Static Semantics: DeclarationPart

The syntax-directed operation DeclarationPart takes no arguments and returns a Parse Node. It is defined piecewise over the following productions:

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

The syntax-directed operation IsConstantDeclaration takes no arguments and returns a Boolean. It is defined piecewise over the following productions:

LexicalDeclaration : LetOrConst BindingList ;
  1. 返回 LetOrConstIsConstantDeclaration
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
Note

无需将 export default AssignmentExpression 视为常量声明,因为没有语法允许对用于引用模块默认对象的内部绑定名称进行赋值。

8.2.4 Static Semantics: IsUsingDeclaration

The syntax-directed operation IsUsingDeclaration takes no arguments and returns Boolean. It is defined piecewise over the following productions:

LexicalDeclaration : LetOrConst BindingList ;
  1. 返回 false
UsingDeclaration : using BindingList ; AwaitUsingDeclaration : CoverAwaitExpressionAndAwaitUsingDeclarationHead BindingList ;
  1. 返回 true
ForDeclaration : LetOrConst ForBinding
  1. 返回 false
ForDeclaration : using ForBinding 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.5 Static Semantics: IsAwaitUsingDeclaration

The syntax-directed operation IsAwaitUsingDeclaration takes no arguments and returns Boolean. It is defined piecewise over the following productions:

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

The syntax-directed operation LexicallyDeclaredNames takes no arguments and returns a List of Strings. It is defined piecewise over the following productions:

Block : { }
  1. 返回一个新的空 List
StatementList : StatementList StatementListItem
  1. names1StatementListLexicallyDeclaredNames
  2. names2StatementListItemLexicallyDeclaredNames
  3. 返回 names1names2列表连接
StatementListItem : Statement
  1. 如果 Statement Statement : LabelledStatement ,则返回 LabelledStatementLexicallyDeclaredNames
  2. 返回一个新的空 List
StatementListItem : Declaration
  1. 返回 DeclarationBoundNames
CaseBlock : { }
  1. 返回一个新的空 List
CaseBlock : { CaseClausesopt DefaultClause CaseClausesopt }
  1. 如果第一个 CaseClauses 存在,则令 names1 为第一个 CaseClausesLexicallyDeclaredNames
  2. 否则,令 names1 为一个新的空 List
  3. names2DefaultClauseLexicallyDeclaredNames
  4. 如果第二个 CaseClauses 存在,则令 names3 为第二个 CaseClausesLexicallyDeclaredNames
  5. 否则,令 names3 为一个新的空 List
  6. 返回 names1names2names3列表连接
CaseClauses : CaseClauses CaseClause
  1. names1CaseClausesLexicallyDeclaredNames
  2. names2CaseClauseLexicallyDeclaredNames
  3. 返回 names1names2列表连接
CaseClause : case Expression : StatementListopt
  1. 如果 StatementList 存在,则返回 StatementListLexicallyDeclaredNames
  2. 返回一个新的空 List
DefaultClause : default : StatementListopt
  1. 如果 StatementList 存在,则返回 StatementListLexicallyDeclaredNames
  2. 返回一个新的空 List
LabelledStatement : LabelIdentifier : LabelledItem
  1. 返回 LabelledItemLexicallyDeclaredNames
LabelledItem : Statement
  1. 返回一个新的空 List
LabelledItem : FunctionDeclaration
  1. 返回 FunctionDeclarationBoundNames
FunctionStatementList : [empty]
  1. 返回一个新的空 List
FunctionStatementList : StatementList
  1. 返回 StatementListTopLevelLexicallyDeclaredNames
ClassStaticBlockStatementList : [empty]
  1. 返回一个新的空 List
ClassStaticBlockStatementList : StatementList
  1. 返回 StatementListTopLevelLexicallyDeclaredNames
ConciseBody : ExpressionBody
  1. 返回一个新的空 List
AsyncConciseBody : ExpressionBody
  1. 返回一个新的空 List
Script : [empty]
  1. 返回一个新的空 List
ScriptBody : StatementList
  1. 返回 StatementListTopLevelLexicallyDeclaredNames
Note 1

Script 的顶层,函数声明会被像 var 声明一样处理,而不是像词法声明一样处理。

Note 2

Module 的 LexicallyDeclaredNames 包括其所有导入绑定的名称。

ModuleItemList : ModuleItemList ModuleItem
  1. names1ModuleItemListLexicallyDeclaredNames
  2. names2ModuleItemLexicallyDeclaredNames
  3. 返回 names1names2列表连接
ModuleItem : ImportDeclaration
  1. 返回 ImportDeclarationBoundNames
ModuleItem : ExportDeclaration
  1. 如果 ExportDeclarationexport VariableStatement,则返回一个新的空 List
  2. 返回 ExportDeclarationBoundNames
ModuleItem : StatementListItem
  1. 返回 StatementListItemLexicallyDeclaredNames
Note 3

Module 的顶层,函数声明会被像词法声明一样处理,而不是像 var 声明一样处理。

8.2.7 Static Semantics: LexicallyScopedDeclarations

The syntax-directed operation LexicallyScopedDeclarations takes no arguments and returns a List of Parse Nodes. It is defined piecewise over the following productions:

StatementList : StatementList StatementListItem
  1. decls1StatementListLexicallyScopedDeclarations
  2. decls2StatementListItemLexicallyScopedDeclarations
  3. 返回 decls1decls2列表连接
StatementListItem : Statement
  1. 如果 Statement Statement : LabelledStatement ,则返回 LabelledStatementLexicallyScopedDeclarations
  2. 返回一个新的空 List
StatementListItem : Declaration
  1. 返回一个 List,其唯一元素是 DeclarationDeclarationPart
CaseBlock : { }
  1. 返回一个新的空 List
CaseBlock : { CaseClausesopt DefaultClause CaseClausesopt }
  1. 如果第一个 CaseClauses 存在,则令 decls1 为第一个 CaseClausesLexicallyScopedDeclarations
  2. 否则,令 decls1 为一个新的空 List
  3. decls2DefaultClauseLexicallyScopedDeclarations
  4. 如果第二个 CaseClauses 存在,则令 decls3 为第二个 CaseClausesLexicallyScopedDeclarations
  5. 否则,令 decls3 为一个新的空 List
  6. 返回 decls1decls2decls3列表连接
CaseClauses : CaseClauses CaseClause
  1. decls1CaseClausesLexicallyScopedDeclarations
  2. decls2CaseClauseLexicallyScopedDeclarations
  3. 返回 decls1decls2列表连接
CaseClause : case Expression : StatementListopt
  1. 如果 StatementList 存在,则返回 StatementListLexicallyScopedDeclarations
  2. 返回一个新的空 List
DefaultClause : default : StatementListopt
  1. 如果 StatementList 存在,则返回 StatementListLexicallyScopedDeclarations
  2. 返回一个新的空 List
LabelledStatement : LabelIdentifier : LabelledItem
  1. 返回 LabelledItemLexicallyScopedDeclarations
LabelledItem : Statement
  1. 返回一个新的空 List
LabelledItem : FunctionDeclaration
  1. 返回 « FunctionDeclaration »。
FunctionStatementList : [empty]
  1. 返回一个新的空 List
FunctionStatementList : StatementList
  1. 返回 StatementListTopLevelLexicallyScopedDeclarations
ClassStaticBlockStatementList : [empty]
  1. 返回一个新的空 List
ClassStaticBlockStatementList : StatementList
  1. 返回 StatementListTopLevelLexicallyScopedDeclarations
ConciseBody : ExpressionBody
  1. 返回一个新的空 List
AsyncConciseBody : ExpressionBody
  1. 返回一个新的空 List
Script : [empty]
  1. 返回一个新的空 List
ScriptBody : StatementList
  1. 返回 StatementListTopLevelLexicallyScopedDeclarations
Module : [empty]
  1. 返回一个新的空 List
ModuleItemList : ModuleItemList ModuleItem
  1. decls1ModuleItemListLexicallyScopedDeclarations
  2. decls2ModuleItemLexicallyScopedDeclarations
  3. 返回 decls1decls2列表连接
ModuleItem : ImportDeclaration
  1. 返回一个新的空 List
ExportDeclaration : export ExportFromClause FromClause WithClauseopt ; export NamedExports ; export VariableStatement
  1. 返回一个新的空 List
ExportDeclaration : export Declaration
  1. 返回一个 List,其唯一元素是 DeclarationDeclarationPart
ExportDeclaration : export default HoistableDeclaration
  1. 返回一个 List,其唯一元素是 HoistableDeclarationDeclarationPart
ExportDeclaration : export default ClassDeclaration
  1. 返回一个 List,其唯一元素是 ClassDeclaration
ExportDeclaration : export default AssignmentExpression ;
  1. 返回一个 List,其唯一元素是此 ExportDeclaration

8.2.8 Static Semantics: VarDeclaredNames

The syntax-directed operation VarDeclaredNames takes no arguments and returns a List of Strings. It is defined piecewise over the following productions:

Statement : EmptyStatement ExpressionStatement ContinueStatement BreakStatement ReturnStatement ThrowStatement DebuggerStatement
  1. 返回一个新的空 List
Block : { }
  1. 返回一个新的空 List
StatementList : StatementList StatementListItem
  1. names1StatementListVarDeclaredNames
  2. names2StatementListItemVarDeclaredNames
  3. 返回 names1names2列表连接
StatementListItem : Declaration
  1. 返回一个新的空 List
VariableStatement : var VariableDeclarationList ;
  1. 返回 VariableDeclarationListBoundNames
IfStatement : if ( Expression ) Statement else Statement
  1. names1 为第一个 StatementVarDeclaredNames
  2. names2 为第二个 StatementVarDeclaredNames
  3. 返回 names1names2列表连接
IfStatement : if ( Expression ) Statement
  1. 返回 StatementVarDeclaredNames
DoWhileStatement : do Statement while ( Expression ) ;
  1. 返回 StatementVarDeclaredNames
WhileStatement : while ( Expression ) Statement
  1. 返回 StatementVarDeclaredNames
ForStatement : for ( Expressionopt ; Expressionopt ; Expressionopt ) Statement
  1. 返回 StatementVarDeclaredNames
ForStatement : for ( var VariableDeclarationList ; Expressionopt ; Expressionopt ) Statement
  1. names1VariableDeclarationListBoundNames
  2. names2StatementVarDeclaredNames
  3. 返回 names1names2列表连接
ForStatement : for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement
  1. 返回 StatementVarDeclaredNames
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. 返回 StatementVarDeclaredNames
ForInOfStatement : for ( var ForBinding in Expression ) Statement for ( var ForBinding of AssignmentExpression ) Statement for await ( var ForBinding of AssignmentExpression ) Statement
  1. names1ForBindingBoundNames
  2. names2StatementVarDeclaredNames
  3. 返回 names1names2列表连接
Note

本节由附录 B.3.5 扩展。

WithStatement : with ( Expression ) Statement
  1. 返回 StatementVarDeclaredNames
SwitchStatement : switch ( Expression ) CaseBlock
  1. 返回 CaseBlockVarDeclaredNames
CaseBlock : { }
  1. 返回一个新的空 List
CaseBlock : { CaseClausesopt DefaultClause CaseClausesopt }
  1. 如果第一个 CaseClauses 存在,则令 names1 为第一个 CaseClausesVarDeclaredNames
  2. 否则,令 names1 为一个新的空 List
  3. names2DefaultClauseVarDeclaredNames
  4. 如果第二个 CaseClauses 存在,则令 names3 为第二个 CaseClausesVarDeclaredNames
  5. 否则,令 names3 为一个新的空 List
  6. 返回 names1names2names3列表连接
CaseClauses : CaseClauses CaseClause
  1. names1CaseClausesVarDeclaredNames
  2. names2CaseClauseVarDeclaredNames
  3. 返回 names1names2列表连接
CaseClause : case Expression : StatementListopt
  1. 如果 StatementList 存在,则返回 StatementListVarDeclaredNames
  2. 返回一个新的空 List
DefaultClause : default : StatementListopt
  1. 如果 StatementList 存在,则返回 StatementListVarDeclaredNames
  2. 返回一个新的空 List
LabelledStatement : LabelIdentifier : LabelledItem
  1. 返回 LabelledItemVarDeclaredNames
LabelledItem : FunctionDeclaration
  1. 返回一个新的空 List
TryStatement : try Block Catch
  1. names1BlockVarDeclaredNames
  2. names2CatchVarDeclaredNames
  3. 返回 names1names2列表连接
TryStatement : try Block Finally
  1. names1BlockVarDeclaredNames
  2. names2FinallyVarDeclaredNames
  3. 返回 names1names2列表连接
TryStatement : try Block Catch Finally
  1. names1BlockVarDeclaredNames
  2. names2CatchVarDeclaredNames
  3. names3FinallyVarDeclaredNames
  4. 返回 names1names2names3列表连接
Catch : catch ( CatchParameter ) Block
  1. 返回 BlockVarDeclaredNames
FunctionStatementList : [empty]
  1. 返回一个新的空 List
FunctionStatementList : StatementList
  1. 返回 StatementListTopLevelVarDeclaredNames
ClassStaticBlockStatementList : [empty]
  1. 返回一个新的空 List
ClassStaticBlockStatementList : StatementList
  1. 返回 StatementListTopLevelVarDeclaredNames
ConciseBody : ExpressionBody
  1. 返回一个新的空 List
AsyncConciseBody : ExpressionBody
  1. 返回一个新的空 List
Script : [empty]
  1. 返回一个新的空 List
ScriptBody : StatementList
  1. 返回 StatementListTopLevelVarDeclaredNames
ModuleItemList : ModuleItemList ModuleItem
  1. names1ModuleItemListVarDeclaredNames
  2. names2ModuleItemVarDeclaredNames
  3. 返回 names1names2列表连接
ModuleItem : ImportDeclaration
  1. 返回一个新的空 List
ModuleItem : ExportDeclaration
  1. 如果 ExportDeclarationexport VariableStatement,则返回 ExportDeclarationBoundNames
  2. 返回一个新的空 List

8.2.9 Static Semantics: VarScopedDeclarations

The syntax-directed operation VarScopedDeclarations takes no arguments and returns a List of Parse Nodes. It is defined piecewise over the following productions:

Statement : EmptyStatement ExpressionStatement ContinueStatement BreakStatement ReturnStatement ThrowStatement DebuggerStatement
  1. 返回一个新的空 List
Block : { }
  1. 返回一个新的空 List
StatementList : StatementList StatementListItem
  1. decls1StatementListVarScopedDeclarations
  2. decls2StatementListItemVarScopedDeclarations
  3. 返回 decls1decls2列表连接
StatementListItem : Declaration
  1. 返回一个新的空 List
VariableDeclarationList : VariableDeclaration
  1. 返回 « VariableDeclaration »。
VariableDeclarationList : VariableDeclarationList , VariableDeclaration
  1. decls1VariableDeclarationListVarScopedDeclarations
  2. 返回 decls1 与 « VariableDeclaration » 的列表连接
IfStatement : if ( Expression ) Statement else Statement
  1. decls1 为第一个 StatementVarScopedDeclarations
  2. decls2 为第二个 StatementVarScopedDeclarations
  3. 返回 decls1decls2列表连接
IfStatement : if ( Expression ) Statement
  1. 返回 StatementVarScopedDeclarations
DoWhileStatement : do Statement while ( Expression ) ;
  1. 返回 StatementVarScopedDeclarations
WhileStatement : while ( Expression ) Statement
  1. 返回 StatementVarScopedDeclarations
ForStatement : for ( Expressionopt ; Expressionopt ; Expressionopt ) Statement
  1. 返回 StatementVarScopedDeclarations
ForStatement : for ( var VariableDeclarationList ; Expressionopt ; Expressionopt ) Statement
  1. decls1VariableDeclarationListVarScopedDeclarations
  2. decls2StatementVarScopedDeclarations
  3. 返回 decls1decls2列表连接
ForStatement : for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement
  1. 返回 StatementVarScopedDeclarations
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. 返回 StatementVarScopedDeclarations
ForInOfStatement : for ( var ForBinding in Expression ) Statement for ( var ForBinding of AssignmentExpression ) Statement for await ( var ForBinding of AssignmentExpression ) Statement
  1. decls1 为 « ForBinding »。
  2. decls2StatementVarScopedDeclarations
  3. 返回 decls1decls2列表连接
Note

本节由附录 B.3.5 扩展。

WithStatement : with ( Expression ) Statement
  1. 返回 StatementVarScopedDeclarations
SwitchStatement : switch ( Expression ) CaseBlock
  1. 返回 CaseBlockVarScopedDeclarations
CaseBlock : { }
  1. 返回一个新的空 List
CaseBlock : { CaseClausesopt DefaultClause CaseClausesopt }
  1. 如果第一个 CaseClauses 存在,则令 decls1 为第一个 CaseClausesVarScopedDeclarations
  2. 否则,令 decls1 为一个新的空 List
  3. decls2DefaultClauseVarScopedDeclarations
  4. 如果第二个 CaseClauses 存在,则令 decls3 为第二个 CaseClausesVarScopedDeclarations
  5. 否则,令 decls3 为一个新的空 List
  6. 返回 decls1decls2decls3列表连接
CaseClauses : CaseClauses CaseClause
  1. decls1CaseClausesVarScopedDeclarations
  2. decls2CaseClauseVarScopedDeclarations
  3. 返回 decls1decls2列表连接
CaseClause : case Expression : StatementListopt
  1. 如果 StatementList 存在,则返回 StatementListVarScopedDeclarations
  2. 返回一个新的空 List
DefaultClause : default : StatementListopt
  1. 如果 StatementList 存在,则返回 StatementListVarScopedDeclarations
  2. 返回一个新的空 List
LabelledStatement : LabelIdentifier : LabelledItem
  1. 返回 LabelledItemVarScopedDeclarations
LabelledItem : FunctionDeclaration
  1. 返回一个新的空 List
TryStatement : try Block Catch
  1. decls1BlockVarScopedDeclarations
  2. decls2CatchVarScopedDeclarations
  3. 返回 decls1decls2列表连接
TryStatement : try Block Finally
  1. decls1BlockVarScopedDeclarations
  2. decls2FinallyVarScopedDeclarations
  3. 返回 decls1decls2列表连接
TryStatement : try Block Catch Finally
  1. decls1BlockVarScopedDeclarations
  2. decls2CatchVarScopedDeclarations
  3. decls3FinallyVarScopedDeclarations
  4. 返回 decls1decls2decls3列表连接
Catch : catch ( CatchParameter ) Block
  1. 返回 BlockVarScopedDeclarations
FunctionStatementList : [empty]
  1. 返回一个新的空 List
FunctionStatementList : StatementList
  1. 返回 StatementListTopLevelVarScopedDeclarations
ClassStaticBlockStatementList : [empty]
  1. 返回一个新的空 List
ClassStaticBlockStatementList : StatementList
  1. 返回 StatementListTopLevelVarScopedDeclarations
ConciseBody : ExpressionBody
  1. 返回一个新的空 List
AsyncConciseBody : ExpressionBody
  1. 返回一个新的空 List
Script : [empty]
  1. 返回一个新的空 List
ScriptBody : StatementList
  1. 返回 StatementListTopLevelVarScopedDeclarations
Module : [empty]
  1. 返回一个新的空 List
ModuleItemList : ModuleItemList ModuleItem
  1. decls1ModuleItemListVarScopedDeclarations
  2. decls2ModuleItemVarScopedDeclarations
  3. 返回 decls1decls2列表连接
ModuleItem : ImportDeclaration
  1. 返回一个新的空 List
ModuleItem : ExportDeclaration
  1. 如果 ExportDeclarationexport VariableStatement,则返回 VariableStatementVarScopedDeclarations
  2. 返回一个新的空 List

8.2.10 Static Semantics: TopLevelLexicallyDeclaredNames

The syntax-directed operation TopLevelLexicallyDeclaredNames takes no arguments and returns a List of Strings. It is defined piecewise over the following productions:

StatementList : StatementList StatementListItem
  1. names1StatementListTopLevelLexicallyDeclaredNames
  2. names2StatementListItemTopLevelLexicallyDeclaredNames
  3. 返回 names1names2列表连接
StatementListItem : Statement
  1. 返回一个新的空 List
StatementListItem : Declaration
  1. 如果 Declaration Declaration : HoistableDeclaration ,则
    1. 返回一个新的空 List
  2. 返回 DeclarationBoundNames
Note

在函数或脚本的顶层,函数声明会被像 var 声明一样处理,而不是像词法声明一样处理。

8.2.11 Static Semantics: TopLevelLexicallyScopedDeclarations

The syntax-directed operation TopLevelLexicallyScopedDeclarations takes no arguments and returns a List of Parse Nodes. It is defined piecewise over the following productions:

StatementList : StatementList StatementListItem
  1. decls1StatementListTopLevelLexicallyScopedDeclarations
  2. decls2StatementListItemTopLevelLexicallyScopedDeclarations
  3. 返回 decls1decls2列表连接
StatementListItem : Statement
  1. 返回一个新的空 List
StatementListItem : Declaration
  1. 如果 Declaration Declaration : HoistableDeclaration ,则
    1. 返回一个新的空 List
  2. 返回 « Declaration »。

8.2.12 Static Semantics: TopLevelVarDeclaredNames

The syntax-directed operation TopLevelVarDeclaredNames takes no arguments and returns a List of Strings. It is defined piecewise over the following productions:

StatementList : StatementList StatementListItem
  1. names1StatementListTopLevelVarDeclaredNames
  2. names2StatementListItemTopLevelVarDeclaredNames
  3. 返回 names1names2列表连接
StatementListItem : Declaration
  1. 如果 Declaration Declaration : HoistableDeclaration ,则
    1. 返回 HoistableDeclarationBoundNames
  2. 返回一个新的空 List
StatementListItem : Statement
  1. 如果 Statement Statement : LabelledStatement ,则返回 StatementTopLevelVarDeclaredNames
  2. 返回 StatementVarDeclaredNames
Note

在函数或脚本的顶层,内部函数声明会被像 var 声明一样处理。

LabelledStatement : LabelIdentifier : LabelledItem
  1. 返回 LabelledItemTopLevelVarDeclaredNames
LabelledItem : Statement
  1. 如果 Statement Statement : LabelledStatement ,则返回 StatementTopLevelVarDeclaredNames
  2. 返回 StatementVarDeclaredNames
LabelledItem : FunctionDeclaration
  1. 返回 FunctionDeclarationBoundNames

8.2.13 Static Semantics: TopLevelVarScopedDeclarations

The syntax-directed operation TopLevelVarScopedDeclarations takes no arguments and returns a List of Parse Nodes. It is defined piecewise over the following productions:

StatementList : StatementList StatementListItem
  1. decls1StatementListTopLevelVarScopedDeclarations
  2. decls2StatementListItemTopLevelVarScopedDeclarations
  3. 返回 decls1decls2列表连接
StatementListItem : Statement
  1. 如果 Statement Statement : LabelledStatement ,则返回 StatementTopLevelVarScopedDeclarations
  2. 返回 StatementVarScopedDeclarations
StatementListItem : Declaration
  1. 如果 Declaration Declaration : HoistableDeclaration ,则
    1. declHoistableDeclarationDeclarationPart
    2. 返回 « decl »。
  2. 返回一个新的空 List
LabelledStatement : LabelIdentifier : LabelledItem
  1. 返回 LabelledItemTopLevelVarScopedDeclarations
LabelledItem : Statement
  1. 如果 Statement Statement : LabelledStatement ,则返回 StatementTopLevelVarScopedDeclarations
  2. 返回 StatementVarScopedDeclarations
LabelledItem : FunctionDeclaration
  1. 返回 « FunctionDeclaration »。

8.3 标签

8.3.1 Static Semantics: ContainsDuplicateLabels

The syntax-directed operation ContainsDuplicateLabels takes argument labelSet (a List of Strings) and returns a Boolean. It is defined piecewise over the following productions:

Statement : VariableStatement EmptyStatement ExpressionStatement ContinueStatement BreakStatement ReturnStatement ThrowStatement DebuggerStatement Block : { } StatementListItem : Declaration
  1. 返回 false
StatementList : StatementList StatementListItem
  1. hasDuplicatesStatementList 带实参 labelSetContainsDuplicateLabels
  2. 如果 hasDuplicatestrue,则返回 true
  3. 返回 StatementListItem 带实参 labelSetContainsDuplicateLabels
IfStatement : if ( Expression ) Statement else Statement
  1. hasDuplicate 为第一个 Statement 带实参 labelSetContainsDuplicateLabels
  2. 如果 hasDuplicatetrue,则返回 true
  3. 返回第二个 Statement 带实参 labelSetContainsDuplicateLabels
IfStatement : if ( Expression ) Statement
  1. 返回 Statement 带实参 labelSetContainsDuplicateLabels
DoWhileStatement : do Statement while ( Expression ) ;
  1. 返回 Statement 带实参 labelSetContainsDuplicateLabels
WhileStatement : while ( Expression ) Statement
  1. 返回 Statement 带实参 labelSetContainsDuplicateLabels
ForStatement : for ( Expressionopt ; Expressionopt ; Expressionopt ) Statement for ( var VariableDeclarationList ; Expressionopt ; Expressionopt ) Statement for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement
  1. 返回 Statement 带实参 labelSetContainsDuplicateLabels
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. 返回 Statement 带实参 labelSetContainsDuplicateLabels
Note

本节由附录 B.3.5 扩展。

WithStatement : with ( Expression ) Statement
  1. 返回 Statement 带实参 labelSetContainsDuplicateLabels
SwitchStatement : switch ( Expression ) CaseBlock
  1. 返回 CaseBlock 带实参 labelSetContainsDuplicateLabels
CaseBlock : { }
  1. 返回 false
CaseBlock : { CaseClausesopt DefaultClause CaseClausesopt }
  1. 如果第一个 CaseClauses 存在,则
    1. 如果第一个 CaseClauses 带实参 labelSetContainsDuplicateLabelstrue,则返回 true
  2. 如果 DefaultClause 带实参 labelSetContainsDuplicateLabelstrue,则返回 true
  3. 如果第二个 CaseClauses 不存在,则返回 false
  4. 返回第二个 CaseClauses 带实参 labelSetContainsDuplicateLabels
CaseClauses : CaseClauses CaseClause
  1. hasDuplicatesCaseClauses 带实参 labelSetContainsDuplicateLabels
  2. 如果 hasDuplicatestrue,则返回 true
  3. 返回 CaseClause 带实参 labelSetContainsDuplicateLabels
CaseClause : case Expression : StatementListopt
  1. 如果 StatementList 存在,则返回 StatementList 带实参 labelSetContainsDuplicateLabels
  2. 返回 false
DefaultClause : default : StatementListopt
  1. 如果 StatementList 存在,则返回 StatementList 带实参 labelSetContainsDuplicateLabels
  2. 返回 false
LabelledStatement : LabelIdentifier : LabelledItem
  1. labelLabelIdentifierStringValue
  2. 如果 labelSet 包含 label,则返回 true
  3. newLabelSetlabelSet 与 « label » 的列表连接
  4. 返回 LabelledItem 带实参 newLabelSetContainsDuplicateLabels
LabelledItem : FunctionDeclaration
  1. 返回 false
TryStatement : try Block Catch
  1. hasDuplicatesBlock 带实参 labelSetContainsDuplicateLabels
  2. 如果 hasDuplicatestrue,则返回 true
  3. 返回 Catch 带实参 labelSetContainsDuplicateLabels
TryStatement : try Block Finally
  1. hasDuplicatesBlock 带实参 labelSetContainsDuplicateLabels
  2. 如果 hasDuplicatestrue,则返回 true
  3. 返回 Finally 带实参 labelSetContainsDuplicateLabels
TryStatement : try Block Catch Finally
  1. 如果 Block 带实参 labelSetContainsDuplicateLabelstrue,则返回 true
  2. 如果 Catch 带实参 labelSetContainsDuplicateLabelstrue,则返回 true
  3. 返回 Finally 带实参 labelSetContainsDuplicateLabels
Catch : catch ( CatchParameter ) Block
  1. 返回 Block 带实参 labelSetContainsDuplicateLabels
FunctionStatementList : [empty]
  1. 返回 false
ClassStaticBlockStatementList : [empty]
  1. 返回 false
ModuleItemList : ModuleItemList ModuleItem
  1. hasDuplicatesModuleItemList 带实参 labelSetContainsDuplicateLabels
  2. 如果 hasDuplicatestrue,则返回 true
  3. 返回 ModuleItem 带实参 labelSetContainsDuplicateLabels
ModuleItem : ImportDeclaration ExportDeclaration
  1. 返回 false

8.3.2 Static Semantics: ContainsUndefinedBreakTarget

The syntax-directed operation ContainsUndefinedBreakTarget takes argument labelSet (a List of Strings) and returns a Boolean. It is defined piecewise over the following productions:

Statement : VariableStatement EmptyStatement ExpressionStatement ContinueStatement ReturnStatement ThrowStatement DebuggerStatement Block : { } StatementListItem : Declaration
  1. 返回 false
StatementList : StatementList StatementListItem
  1. hasUndefinedLabelsStatementList 带实参 labelSetContainsUndefinedBreakTarget
  2. 如果 hasUndefinedLabelstrue,则返回 true
  3. 返回 StatementListItem 带实参 labelSetContainsUndefinedBreakTarget
IfStatement : if ( Expression ) Statement else Statement
  1. hasUndefinedLabels 为第一个 Statement 带实参 labelSetContainsUndefinedBreakTarget
  2. 如果 hasUndefinedLabelstrue,则返回 true
  3. 返回第二个 Statement 带实参 labelSetContainsUndefinedBreakTarget
IfStatement : if ( Expression ) Statement
  1. 返回 Statement 带实参 labelSetContainsUndefinedBreakTarget
DoWhileStatement : do Statement while ( Expression ) ;
  1. 返回 Statement 带实参 labelSetContainsUndefinedBreakTarget
WhileStatement : while ( Expression ) Statement
  1. 返回 Statement 带实参 labelSetContainsUndefinedBreakTarget
ForStatement : for ( Expressionopt ; Expressionopt ; Expressionopt ) Statement for ( var VariableDeclarationList ; Expressionopt ; Expressionopt ) Statement for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement
  1. 返回 Statement 带实参 labelSetContainsUndefinedBreakTarget
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. 返回 Statement 带实参 labelSetContainsUndefinedBreakTarget
Note

本节由附录 B.3.5 扩展。

BreakStatement : break ;
  1. 返回 false
BreakStatement : break LabelIdentifier ;
  1. 如果 labelSet 包含 LabelIdentifierStringValue,则返回 false
  2. 返回 true
WithStatement : with ( Expression ) Statement
  1. 返回 Statement 带实参 labelSetContainsUndefinedBreakTarget
SwitchStatement : switch ( Expression ) CaseBlock
  1. 返回 CaseBlock 带实参 labelSetContainsUndefinedBreakTarget
CaseBlock : { }
  1. 返回 false
CaseBlock : { CaseClausesopt DefaultClause CaseClausesopt }
  1. 如果第一个 CaseClauses 存在,则
    1. 如果第一个 CaseClauses 带实参 labelSetContainsUndefinedBreakTargettrue,则返回 true
  2. 如果 DefaultClause 带实参 labelSetContainsUndefinedBreakTargettrue,则返回 true
  3. 如果第二个 CaseClauses 不存在,则返回 false
  4. 返回第二个 CaseClauses 带实参 labelSetContainsUndefinedBreakTarget
CaseClauses : CaseClauses CaseClause
  1. hasUndefinedLabelsCaseClauses 带实参 labelSetContainsUndefinedBreakTarget
  2. 如果 hasUndefinedLabelstrue,则返回 true
  3. 返回 CaseClause 带实参 labelSetContainsUndefinedBreakTarget
CaseClause : case Expression : StatementListopt
  1. 如果 StatementList 存在,则返回 StatementList 带实参 labelSetContainsUndefinedBreakTarget
  2. 返回 false
DefaultClause : default : StatementListopt
  1. 如果 StatementList 存在,则返回 StatementList 带实参 labelSetContainsUndefinedBreakTarget
  2. 返回 false
LabelledStatement : LabelIdentifier : LabelledItem
  1. labelLabelIdentifierStringValue
  2. newLabelSetlabelSet 与 « label » 的列表连接
  3. 返回 LabelledItem 带实参 newLabelSetContainsUndefinedBreakTarget
LabelledItem : FunctionDeclaration
  1. 返回 false
TryStatement : try Block Catch
  1. hasUndefinedLabelsBlock 带实参 labelSetContainsUndefinedBreakTarget
  2. 如果 hasUndefinedLabelstrue,则返回 true
  3. 返回 Catch 带实参 labelSetContainsUndefinedBreakTarget
TryStatement : try Block Finally
  1. hasUndefinedLabelsBlock 带实参 labelSetContainsUndefinedBreakTarget
  2. 如果 hasUndefinedLabelstrue,则返回 true
  3. 返回 Finally 带实参 labelSetContainsUndefinedBreakTarget
TryStatement : try Block Catch Finally
  1. 如果 Block 带实参 labelSetContainsUndefinedBreakTargettrue,则返回 true
  2. 如果 Catch 带实参 labelSetContainsUndefinedBreakTargettrue,则返回 true
  3. 返回 Finally 带实参 labelSetContainsUndefinedBreakTarget
Catch : catch ( CatchParameter ) Block
  1. 返回 Block 带实参 labelSetContainsUndefinedBreakTarget
FunctionStatementList : [empty]
  1. 返回 false
ClassStaticBlockStatementList : [empty]
  1. 返回 false
ModuleItemList : ModuleItemList ModuleItem
  1. hasUndefinedLabelsModuleItemList 带实参 labelSetContainsUndefinedBreakTarget
  2. 如果 hasUndefinedLabelstrue,则返回 true
  3. 返回 ModuleItem 带实参 labelSetContainsUndefinedBreakTarget
ModuleItem : ImportDeclaration ExportDeclaration
  1. 返回 false

8.3.3 Static Semantics: ContainsUndefinedContinueTarget

The syntax-directed operation ContainsUndefinedContinueTarget takes arguments iterationSet (a List of Strings) and labelSet (a List of Strings) and returns a Boolean. It is defined piecewise over the following productions:

Statement : VariableStatement EmptyStatement ExpressionStatement BreakStatement ReturnStatement ThrowStatement DebuggerStatement Block : { } StatementListItem : Declaration
  1. 返回 false
Statement : BlockStatement
  1. 返回 BlockStatement 带实参 iterationSet 和 « » 的 ContainsUndefinedContinueTarget
BreakableStatement : IterationStatement
  1. newIterationSetiterationSetlabelSet列表连接
  2. 返回 IterationStatement 带实参 newIterationSet 和 « » 的 ContainsUndefinedContinueTarget
StatementList : StatementList StatementListItem
  1. hasUndefinedLabelsStatementList 带实参 iterationSet 和 « » 的 ContainsUndefinedContinueTarget
  2. 如果 hasUndefinedLabelstrue,则返回 true
  3. 返回 StatementListItem 带实参 iterationSet 和 « » 的 ContainsUndefinedContinueTarget
IfStatement : if ( Expression ) Statement else Statement
  1. hasUndefinedLabels 为第一个 Statement 带实参 iterationSet 和 « » 的 ContainsUndefinedContinueTarget
  2. 如果 hasUndefinedLabelstrue,则返回 true
  3. 返回第二个 Statement 带实参 iterationSet 和 « » 的 ContainsUndefinedContinueTarget
IfStatement : if ( Expression ) Statement
  1. 返回 Statement 带实参 iterationSet 和 « » 的 ContainsUndefinedContinueTarget
DoWhileStatement : do Statement while ( Expression ) ;
  1. 返回 Statement 带实参 iterationSet 和 « » 的 ContainsUndefinedContinueTarget
WhileStatement : while ( Expression ) Statement
  1. 返回 Statement 带实参 iterationSet 和 « » 的 ContainsUndefinedContinueTarget
ForStatement : for ( Expressionopt ; Expressionopt ; Expressionopt ) Statement for ( var VariableDeclarationList ; Expressionopt ; Expressionopt ) Statement for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement
  1. 返回 Statement 带实参 iterationSet 和 « » 的 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. 返回 Statement 带实参 iterationSet 和 « » 的 ContainsUndefinedContinueTarget
Note

本节由附录 B.3.5 扩展。

ContinueStatement : continue ;
  1. 返回 false
ContinueStatement : continue LabelIdentifier ;
  1. 如果 iterationSet 包含 LabelIdentifierStringValue,则返回 false
  2. 返回 true
WithStatement : with ( Expression ) Statement
  1. 返回 Statement 带实参 iterationSet 和 « » 的 ContainsUndefinedContinueTarget
SwitchStatement : switch ( Expression ) CaseBlock
  1. 返回 CaseBlock 带实参 iterationSet 和 « » 的 ContainsUndefinedContinueTarget
CaseBlock : { }
  1. 返回 false
CaseBlock : { CaseClausesopt DefaultClause CaseClausesopt }
  1. 如果第一个 CaseClauses 存在,则
    1. 如果第一个 CaseClauses 带实参 iterationSet 和 « » 的 ContainsUndefinedContinueTargettrue,则返回 true
  2. 如果 DefaultClause 带实参 iterationSet 和 « » 的 ContainsUndefinedContinueTargettrue,则返回 true
  3. 如果第二个 CaseClauses 不存在,则返回 false
  4. 返回第二个 CaseClauses 带实参 iterationSet 和 « » 的 ContainsUndefinedContinueTarget
CaseClauses : CaseClauses CaseClause
  1. hasUndefinedLabelsCaseClauses 带实参 iterationSet 和 « » 的 ContainsUndefinedContinueTarget
  2. 如果 hasUndefinedLabelstrue,则返回 true
  3. 返回 CaseClause 带实参 iterationSet 和 « » 的 ContainsUndefinedContinueTarget
CaseClause : case Expression : StatementListopt
  1. 如果 StatementList 存在,则返回 StatementList 带实参 iterationSet 和 « » 的 ContainsUndefinedContinueTarget
  2. 返回 false
DefaultClause : default : StatementListopt
  1. 如果 StatementList 存在,则返回 StatementList 带实参 iterationSet 和 « » 的 ContainsUndefinedContinueTarget
  2. 返回 false
LabelledStatement : LabelIdentifier : LabelledItem
  1. labelLabelIdentifierStringValue
  2. newLabelSetlabelSet 与 « label » 的列表连接
  3. 返回 LabelledItem 带实参 iterationSetnewLabelSetContainsUndefinedContinueTarget
LabelledItem : FunctionDeclaration
  1. 返回 false
TryStatement : try Block Catch
  1. hasUndefinedLabelsBlock 带实参 iterationSet 和 « » 的 ContainsUndefinedContinueTarget
  2. 如果 hasUndefinedLabelstrue,则返回 true
  3. 返回 Catch 带实参 iterationSet 和 « » 的 ContainsUndefinedContinueTarget
TryStatement : try Block Finally
  1. hasUndefinedLabelsBlock 带实参 iterationSet 和 « » 的 ContainsUndefinedContinueTarget
  2. 如果 hasUndefinedLabelstrue,则返回 true
  3. 返回 Finally 带实参 iterationSet 和 « » 的 ContainsUndefinedContinueTarget
TryStatement : try Block Catch Finally
  1. 如果 Block 带实参 iterationSet 和 « » 的 ContainsUndefinedContinueTargettrue,则返回 true
  2. 如果 Catch 带实参 iterationSet 和 « » 的 ContainsUndefinedContinueTargettrue,则返回 true
  3. 返回 Finally 带实参 iterationSet 和 « » 的 ContainsUndefinedContinueTarget
Catch : catch ( CatchParameter ) Block
  1. 返回 Block 带实参 iterationSet 和 « » 的 ContainsUndefinedContinueTarget
FunctionStatementList : [empty]
  1. 返回 false
ClassStaticBlockStatementList : [empty]
  1. 返回 false
ModuleItemList : ModuleItemList ModuleItem
  1. hasUndefinedLabelsModuleItemList 带实参 iterationSet 和 « » 的 ContainsUndefinedContinueTarget
  2. 如果 hasUndefinedLabelstrue,则返回 true
  3. 返回 ModuleItem 带实参 iterationSet 和 « » 的 ContainsUndefinedContinueTarget
ModuleItem : ImportDeclaration ExportDeclaration
  1. 返回 false

8.4 函数名称推断

8.4.1 Static Semantics: HasName

The syntax-directed operation HasName takes no arguments and returns a Boolean. It is defined piecewise over the following productions:

PrimaryExpression : CoverParenthesizedExpressionAndArrowParameterList
  1. exprCoverParenthesizedExpressionAndArrowParameterList覆盖的 ParenthesizedExpression
  2. 如果 exprIsFunctionDefinitionfalse,则返回 false
  3. 返回 exprHasName
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

The syntax-directed operation IsFunctionDefinition takes no arguments and returns a Boolean. It is defined piecewise over the following productions:

PrimaryExpression : CoverParenthesizedExpressionAndArrowParameterList
  1. exprCoverParenthesizedExpressionAndArrowParameterList覆盖的 ParenthesizedExpression
  2. 返回 exprIsFunctionDefinition
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 )

The abstract operation IsAnonymousFunctionDefinition takes argument expr (an AssignmentExpression Parse Node, an Initializer Parse Node, or an Expression Parse Node) and returns a Boolean. 它确定其实参是否为不绑定名称的函数定义。 It performs the following steps when called:

  1. 如果 exprIsFunctionDefinitionfalse,则返回 false
  2. hasNameexprHasName
  3. 如果 hasNametrue,则返回 false
  4. 返回 true

8.4.4 Static Semantics: IsIdentifierRef

The syntax-directed operation IsIdentifierRef takes no arguments and returns a Boolean. It is defined piecewise over the following productions:

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

The syntax-directed operation NamedEvaluation takes argument name (a property key or a Private Name) and returns either a normal completion containing a function object or an abrupt completion. It is defined piecewise over the following productions:

PrimaryExpression : CoverParenthesizedExpressionAndArrowParameterList
  1. exprCoverParenthesizedExpressionAndArrowParameterList覆盖的 ParenthesizedExpression
  2. 返回 ? expr 带实参 nameNamedEvaluation
ParenthesizedExpression : ( Expression )
  1. 断言:IsAnonymousFunctionDefinition(Expression) 是 true
  2. 返回 ? Expression 带实参 nameNamedEvaluation
FunctionExpression : function ( FormalParameters ) { FunctionBody }
  1. 返回 FunctionExpression 带实参 nameInstantiateOrdinaryFunctionExpression
GeneratorExpression : function * ( FormalParameters ) { GeneratorBody }
  1. 返回 GeneratorExpression 带实参 nameInstantiateGeneratorFunctionExpression
AsyncGeneratorExpression : async function * ( FormalParameters ) { AsyncGeneratorBody }
  1. 返回 AsyncGeneratorExpression 带实参 nameInstantiateAsyncGeneratorFunctionExpression
AsyncFunctionExpression : async function ( FormalParameters ) { AsyncFunctionBody }
  1. 返回 AsyncFunctionExpression 带实参 nameInstantiateAsyncFunctionExpression
ArrowFunction : ArrowParameters => ConciseBody
  1. 返回 ArrowFunction 带实参 nameInstantiateArrowFunctionExpression
AsyncArrowFunction : async AsyncArrowBindingIdentifier => AsyncConciseBody CoverCallExpressionAndAsyncArrowHead => AsyncConciseBody
  1. 返回 AsyncArrowFunction 带实参 nameInstantiateAsyncArrowFunctionExpression
ClassExpression : class ClassTail
  1. sourceTextClassExpression匹配的源文本
  2. 返回 ? ClassTail 带实参 undefinednamesourceTextClassDefinitionEvaluation

8.5 Contains

8.5.1 Static Semantics: Contains

The syntax-directed operation Contains takes argument symbol (a grammar symbol) and returns a Boolean.

本规范中未在下方列出的每个文法产生式替代项,都隐式具有以下 Contains 的默认定义:

  1. 对此 Parse Node 的每个子节点 child,执行:
    1. 如果 childsymbol 的实例,则返回 true
    2. 如果 child 是非终结符的实例,则
      1. containedchild Contains symbol 的结果。
      2. 如果 containedtrue,则返回 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
Note 1

依赖子结构的静态语义规则通常不会查看函数定义内部。

ClassTail : ClassHeritageopt { ClassBody }
  1. 如果 symbolClassBody,则返回 true
  2. 如果 symbolClassHeritage,则
    1. 如果 ClassHeritage 存在,则返回 true
    2. 返回 false
  3. 如果 ClassHeritage 存在,则
    1. 如果 ClassHeritage Contains symboltrue,则返回 true
  4. 返回 ClassBody 带实参 symbolComputedPropertyContains 的结果。
Note 2

依赖子结构的静态语义规则通常不会查看类体内部,除 PropertyName 外。

ClassStaticBlock : static { ClassStaticBlockBody }
  1. 返回 false
Note 3

依赖子结构的静态语义规则通常不会查看 static 初始化块内部。

ArrowFunction : ArrowParameters => ConciseBody
  1. 如果 symbol 不是 NewTargetSuperPropertySuperCallsuperthis 之一,则返回 false
  2. 如果 ArrowParameters Contains symboltrue,则返回 true
  3. 返回 ConciseBody Contains symbol
ArrowParameters : CoverParenthesizedExpressionAndArrowParameterList
  1. formalsCoverParenthesizedExpressionAndArrowParameterList覆盖的 ArrowFormalParameters
  2. 返回 formals Contains symbol
AsyncArrowFunction : async AsyncArrowBindingIdentifier => AsyncConciseBody
  1. 如果 symbol 不是 NewTargetSuperPropertySuperCallsuperthis 之一,则返回 false
  2. 返回 AsyncConciseBody Contains symbol
AsyncArrowFunction : CoverCallExpressionAndAsyncArrowHead => AsyncConciseBody
  1. 如果 symbol 不是 NewTargetSuperPropertySuperCallsuperthis 之一,则返回 false
  2. headCoverCallExpressionAndAsyncArrowHead覆盖的 AsyncArrowHead
  3. 如果 head Contains symboltrue,则返回 true
  4. 返回 AsyncConciseBody Contains symbol
Note 4

Contains 用于检测 ArrowFunctionAsyncArrowFunction 中的 new.targetthissuper 用法。

PropertyDefinition : MethodDefinition
  1. 如果 symbolMethodDefinition,则返回 true
  2. 返回 MethodDefinition 带实参 symbolComputedPropertyContains 的结果。
LiteralPropertyName : IdentifierName
  1. 返回 false
MemberExpression : MemberExpression . IdentifierName
  1. 如果 MemberExpression Contains symboltrue,则返回 true
  2. 返回 false
SuperProperty : super . IdentifierName
  1. 如果 symbolReservedWord super,则返回 true
  2. 返回 false
CallExpression : CallExpression . IdentifierName
  1. 如果 CallExpression Contains symboltrue,则返回 true
  2. 返回 false
OptionalChain : ?. IdentifierName
  1. 返回 false
OptionalChain : OptionalChain . IdentifierName
  1. 如果 OptionalChain Contains symboltrue,则返回 true
  2. 返回 false

8.5.2 Static Semantics: ComputedPropertyContains

The syntax-directed operation ComputedPropertyContains takes argument symbol (a grammar symbol) and returns a Boolean. It is defined piecewise over the following productions:

ClassElementName : PrivateIdentifier PropertyName : LiteralPropertyName
  1. 返回 false
PropertyName : ComputedPropertyName
  1. 返回 ComputedPropertyName Contains symbol 的结果。
MethodDefinition : ClassElementName ( UniqueFormalParameters ) { FunctionBody } get ClassElementName ( ) { FunctionBody } set ClassElementName ( PropertySetParameterList ) { FunctionBody }
  1. 返回 ClassElementName 带实参 symbolComputedPropertyContains 的结果。
GeneratorMethod : * ClassElementName ( UniqueFormalParameters ) { GeneratorBody }
  1. 返回 ClassElementName 带实参 symbolComputedPropertyContains 的结果。
AsyncGeneratorMethod : async * ClassElementName ( UniqueFormalParameters ) { AsyncGeneratorBody }
  1. 返回 ClassElementName 带实参 symbolComputedPropertyContains 的结果。
ClassElementList : ClassElementList ClassElement
  1. inListClassElementList 带实参 symbolComputedPropertyContains
  2. 如果 inListtrue,则返回 true
  3. 返回 ClassElement 带实参 symbolComputedPropertyContains 的结果。
ClassElement : ClassStaticBlock
  1. 返回 false
ClassElement : ;
  1. 返回 false
AsyncMethod : async ClassElementName ( UniqueFormalParameters ) { AsyncFunctionBody }
  1. 返回 ClassElementName 带实参 symbolComputedPropertyContains 的结果。
FieldDefinition : ClassElementName Initializeropt
  1. 返回 ClassElementName 带实参 symbolComputedPropertyContains 的结果。

8.6 杂项

这些操作在整个规范的多个地方使用。

8.6.1 Runtime Semantics: InstantiateFunctionObject

The syntax-directed operation InstantiateFunctionObject takes arguments envRecord (an Environment Record) and privateEnv (a PrivateEnvironment Record or null) and returns an ECMAScript function object. It is defined piecewise over the following productions:

FunctionDeclaration : function BindingIdentifier ( FormalParameters ) { FunctionBody } function ( FormalParameters ) { FunctionBody }
  1. 返回 FunctionDeclaration 带实参 envRecordprivateEnvInstantiateOrdinaryFunctionObject
GeneratorDeclaration : function * BindingIdentifier ( FormalParameters ) { GeneratorBody } function * ( FormalParameters ) { GeneratorBody }
  1. 返回 GeneratorDeclaration 带实参 envRecordprivateEnvInstantiateGeneratorFunctionObject
AsyncGeneratorDeclaration : async function * BindingIdentifier ( FormalParameters ) { AsyncGeneratorBody } async function * ( FormalParameters ) { AsyncGeneratorBody }
  1. 返回 AsyncGeneratorDeclaration 带实参 envRecordprivateEnvInstantiateAsyncGeneratorFunctionObject
AsyncFunctionDeclaration : async function BindingIdentifier ( FormalParameters ) { AsyncFunctionBody } async function ( FormalParameters ) { AsyncFunctionBody }
  1. 返回 AsyncFunctionDeclaration 带实参 envRecordprivateEnvInstantiateAsyncFunctionObject

8.6.2 Runtime Semantics: BindingInitialization

The syntax-directed operation BindingInitialization takes arguments value (an ECMAScript language value) and envRecord (an Environment Record or undefined) and returns either a normal completion containing unused or an abrupt completion.

Note

envRecord 传递 undefined 表示应使用 PutValue 操作来赋予初始化值。这适用于 var 语句和某些非严格函数的形式参数列表(参见 10.2.11)。在这些情况下,词法绑定会在其初始化器求值之前被提升并预初始化。

It is defined piecewise over the following productions:

BindingIdentifier : Identifier
  1. nameIdentifierStringValue
  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. 返回 ? ObjectBindingPattern 带实参 valueenvRecordBindingInitialization
BindingPattern : ArrayBindingPattern
  1. iteratorRecord 为 ? GetIterator(value, sync)。
  2. resultCompletion(ArrayBindingPattern 带实参 iteratorRecordenvRecordIteratorBindingInitialization)。
  3. 如果 iteratorRecord.[[Done]]false,则返回 ? IteratorClose(iteratorRecord, result)。
  4. 返回 ? result
ObjectBindingPattern : { }
  1. 返回 unused
ObjectBindingPattern : { BindingPropertyList } { BindingPropertyList , }
  1. 执行 ? BindingPropertyList 带实参 valueenvRecordPropertyBindingInitialization
  2. 返回 unused
ObjectBindingPattern : { BindingRestProperty }
  1. excludedNames 为新的空 List
  2. 返回 ? BindingRestProperty 带实参 valueenvRecordexcludedNamesRestBindingInitialization
ObjectBindingPattern : { BindingPropertyList , BindingRestProperty }
  1. excludedNames 为 ? BindingPropertyList 带实参 valueenvRecordPropertyBindingInitialization
  2. 返回 ? BindingRestProperty 带实参 valueenvRecordexcludedNamesRestBindingInitialization

8.6.2.1 InitializeBoundName ( name, value, envRecord )

The abstract operation InitializeBoundName takes arguments name (a String), value (an ECMAScript language value), and envRecord (an Environment Record or undefined) and returns either a normal completion containing unused or an abrupt completion. It performs the following steps when called:

  1. 如果 envRecord 不是 undefined,则
    1. 执行 ! envRecord.InitializeBinding(name, value)。
    2. 返回 unused
  2. lhs 为 ? ResolveBinding(name)。
  3. 返回 ? PutValue(lhs, value)。

8.6.3 Runtime Semantics: IteratorBindingInitialization

The syntax-directed operation IteratorBindingInitialization takes arguments iteratorRecord (an Iterator Record) and envRecord (an Environment Record or undefined) and returns either a normal completion containing unused or an abrupt completion.

Note

当为 envRecord 传递 undefined 时,表示应使用 PutValue 操作来赋予初始化值。这适用于非严格函数的形式参数列表。在这种情况下,为了处理可能存在多个同名参数的情形,形式参数绑定会被预初始化。

It is defined piecewise over the following productions:

ArrayBindingPattern : [ ]
  1. 返回 unused
ArrayBindingPattern : [ Elision ]
  1. 返回 ? Elision 带实参 iteratorRecordIteratorDestructuringAssignmentEvaluation
ArrayBindingPattern : [ Elisionopt BindingRestElement ]
  1. 如果 Elision 存在,则
    1. 执行 ? Elision 带实参 iteratorRecordIteratorDestructuringAssignmentEvaluation
  2. 返回 ? BindingRestElement 带实参 iteratorRecordenvRecordIteratorBindingInitialization
ArrayBindingPattern : [ BindingElementList , Elision ]
  1. 执行 ? BindingElementList 带实参 iteratorRecordenvRecordIteratorBindingInitialization
  2. 返回 ? Elision 带实参 iteratorRecordIteratorDestructuringAssignmentEvaluation
ArrayBindingPattern : [ BindingElementList , Elisionopt BindingRestElement ]
  1. 执行 ? BindingElementList 带实参 iteratorRecordenvRecordIteratorBindingInitialization
  2. 如果 Elision 存在,则
    1. 执行 ? Elision 带实参 iteratorRecordIteratorDestructuringAssignmentEvaluation
  3. 返回 ? BindingRestElement 带实参 iteratorRecordenvRecordIteratorBindingInitialization
BindingElementList : BindingElementList , BindingElisionElement
  1. 执行 ? BindingElementList 带实参 iteratorRecordenvRecordIteratorBindingInitialization
  2. 返回 ? BindingElisionElement 带实参 iteratorRecordenvRecordIteratorBindingInitialization
BindingElisionElement : Elision BindingElement
  1. 执行 ? Elision 带实参 iteratorRecordIteratorDestructuringAssignmentEvaluation
  2. 返回 ? BindingElement 带实参 iteratorRecordenvRecordIteratorBindingInitialization
SingleNameBinding : BindingIdentifier Initializeropt
  1. bindingIdBindingIdentifierStringValue
  2. lhs 为 ? ResolveBinding(bindingId, envRecord)。
  3. vundefined
  4. 如果 iteratorRecord.[[Done]]false,则
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 next 不是 done,则
      1. v 设置为 next
  5. 如果 Initializer 存在且 vundefined,则
    1. 如果 IsAnonymousFunctionDefinition(Initializer) 是 true,则
      1. v 设置为 ? Initializer 带实参 bindingIdNamedEvaluation
    2. 否则,
      1. defaultValue 为 ? InitializerEvaluation
      2. v 设置为 ? GetValue(defaultValue)。
  6. 如果 envRecordundefined,则返回 ? PutValue(lhs, v)。
  7. 返回 ? InitializeReferencedBinding(lhs, v)。
BindingElement : BindingPattern Initializeropt
  1. vundefined
  2. 如果 iteratorRecord.[[Done]]false,则
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 next 不是 done,则
      1. v 设置为 next
  3. 如果 Initializer 存在且 vundefined,则
    1. defaultValue 为 ? InitializerEvaluation
    2. v 设置为 ? GetValue(defaultValue)。
  4. 返回 ? BindingPattern 带实参 venvRecordBindingInitialization
BindingRestElement : ... BindingIdentifier
  1. lhs 为 ? ResolveBinding(BindingIdentifierStringValue, envRecord)。
  2. array 为 ! ArrayCreate(0)。
  3. n 为 0。
  4. 重复,
    1. nextdone
    2. 如果 iteratorRecord.[[Done]]false,则
      1. next 设置为 ? IteratorStepValue(iteratorRecord)。
    3. 如果 nextdone,则
      1. 如果 envRecordundefined,则返回 ? 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. nextdone
    2. 如果 iteratorRecord.[[Done]]false,则
      1. next 设置为 ? IteratorStepValue(iteratorRecord)。
    3. 如果 nextdone,则
      1. 返回 ? BindingPattern 带实参 arrayenvRecordBindingInitialization
    4. 执行 ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(n)), next)。
    5. n 设置为 n + 1。
FormalParameters : [empty]
  1. 返回 unused
FormalParameters : FormalParameterList , FunctionRestParameter
  1. 执行 ? FormalParameterList 带实参 iteratorRecordenvRecordIteratorBindingInitialization
  2. 返回 ? FunctionRestParameter 带实参 iteratorRecordenvRecordIteratorBindingInitialization
FormalParameterList : FormalParameterList , FormalParameter
  1. 执行 ? FormalParameterList 带实参 iteratorRecordenvRecordIteratorBindingInitialization
  2. 返回 ? FormalParameter 带实参 iteratorRecordenvRecordIteratorBindingInitialization
ArrowParameters : BindingIdentifier
  1. vundefined
  2. 断言:iteratorRecord.[[Done]]false
  3. next 为 ? IteratorStepValue(iteratorRecord)。
  4. 如果 next 不是 done,则
    1. v 设置为 next
  5. 返回 ? BindingIdentifier 带实参 venvRecordBindingInitialization
ArrowParameters : CoverParenthesizedExpressionAndArrowParameterList
  1. formalsCoverParenthesizedExpressionAndArrowParameterList覆盖的 ArrowFormalParameters
  2. 返回 ? formals 带实参 iteratorRecordenvRecordIteratorBindingInitialization
AsyncArrowBindingIdentifier : BindingIdentifier
  1. vundefined
  2. 断言:iteratorRecord.[[Done]]false
  3. next 为 ? IteratorStepValue(iteratorRecord)。
  4. 如果 next 不是 done,则
    1. v 设置为 next
  5. 返回 ? BindingIdentifier 带实参 venvRecordBindingInitialization

8.6.4 Static Semantics: AssignmentTargetType

The syntax-directed operation AssignmentTargetType takes no arguments and returns simple, web-compat, or invalid. It is defined piecewise over the following productions:

IdentifierReference : Identifier
  1. 如果 IsStrict(this IdentifierReference) 是 trueIdentifierStringValue"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. exprCoverParenthesizedExpressionAndArrowParameterList覆盖的 ParenthesizedExpression
  2. 返回 exprAssignmentTargetType
CallExpression : CoverCallExpressionAndAsyncArrowHead CallExpression Arguments
  1. 如果宿主是 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

The syntax-directed operation PropName takes no arguments and returns a String or empty. It is defined piecewise over the following productions:

PropertyDefinition : IdentifierReference
  1. 返回 IdentifierReferenceStringValue
PropertyDefinition : ... AssignmentExpression
  1. 返回 empty
PropertyDefinition : PropertyName : AssignmentExpression
  1. 返回 PropertyNamePropName
LiteralPropertyName : IdentifierName AttributeKey : IdentifierName
  1. 返回 IdentifierNameStringValue
LiteralPropertyName : StringLiteral AttributeKey : StringLiteral
  1. 返回 StringLiteralSV
LiteralPropertyName : NumericLiteral
  1. numberNumericLiteralNumericValue
  2. 返回 ! ToString(number)。
ComputedPropertyName : [ AssignmentExpression ]
  1. 返回 empty
MethodDefinition : ClassElementName ( UniqueFormalParameters ) { FunctionBody } get ClassElementName ( ) { FunctionBody } set ClassElementName ( PropertySetParameterList ) { FunctionBody }
  1. 返回 ClassElementNamePropName
GeneratorMethod : * ClassElementName ( UniqueFormalParameters ) { GeneratorBody }
  1. 返回 ClassElementNamePropName
AsyncGeneratorMethod : async * ClassElementName ( UniqueFormalParameters ) { AsyncGeneratorBody }
  1. 返回 ClassElementNamePropName
ClassElement : ClassStaticBlock
  1. 返回 empty
ClassElement : ;
  1. 返回 empty
AsyncMethod : async ClassElementName ( UniqueFormalParameters ) { AsyncFunctionBody }
  1. 返回 ClassElementNamePropName
FieldDefinition : ClassElementName Initializeropt
  1. 返回 ClassElementNamePropName
ClassElementName : PrivateIdentifier
  1. 返回 empty

8.6.6 Static Semantics: ContainsUsing

The syntax-directed operation ContainsUsing takes no arguments and returns Boolean. It is defined piecewise over the following productions:

StatementList : StatementList StatementListItem
  1. 如果派生的 StatementListContainsUsingtrue,则返回 true
  2. 如果 StatementListItemContainsUsingtrue,则返回 true
  3. 返回 false
StatementListItem : Statement
  1. 返回 false
StatementListItem : Declaration
  1. 如果 DeclarationIsUsingDeclarationtrue,则返回 true
  2. 如果 DeclarationIsAwaitUsingDeclarationtrue,则返回 true
  3. 返回 false

9 可执行代码与执行上下文

9.1 环境记录

Environment Record 是一种规范类型,用于基于 ECMAScript 代码的词法嵌套结构,定义 Identifier 与特定变量和函数之间的关联。通常,一个 Environment Record 与 ECMAScript 代码的某个特定句法结构相关联,例如 FunctionDeclarationBlockStatementTryStatementCatch 子句。每当这类代码被求值时,都会创建一个新的 Environment Record,用于记录由该代码创建的标识符绑定。

每个 Environment Record 都有一个 [[OuterEnv]] 字段,它要么是 null,要么是对外层 Environment Record 的引用。这用于建模 Environment Record 值的逻辑嵌套。某个(内层)Environment Record 的外层引用,是对在逻辑上包围该内层 Environment Record 的 Environment Record 的引用。当然,一个外层 Environment Record 可以有自己的外层 Environment Record。一个 Environment Record 可以作为多个内层 Environment Records 的外层环境。例如,如果一个 FunctionDeclaration 包含两个嵌套的 FunctionDeclaration,则每个嵌套函数的 Environment Record 都会将包围函数当前求值的 Environment Record 作为其外层 Environment Record。

Environment Records 纯粹是规范机制,并不需要对应于 ECMAScript 实现中的任何特定工件。ECMAScript 程序不可能直接访问或操纵这类值。

9.1.1 Environment Record 类型层级结构

Environment Records 可以被看作存在于一个简单的面向对象层级结构中,其中 Environment Record 是一个抽象类,具有三个具体子类:Declarative Environment RecordObject Environment RecordGlobal Environment RecordFunction Environment RecordsModule Environment RecordsDeclarative Environment Record 的子类。

Environment Record 抽象类包含 Table 15 中定义的抽象规范方法。这些抽象方法对于每个具体子类都有不同的具体算法。

Table 15: Abstract Methods of Environment Records
方法 目的 定义
HasBinding ( name )

The abstract method HasBinding takes argument name (a String) and returns either a normal completion containing a Boolean or a throw completion.

它确定 Environment Record 是否具有 name 的绑定。
它在以下类型中有具体定义:
CreateMutableBinding ( name, deletable )

The abstract method CreateMutableBinding takes arguments name (a String) and deletable (a Boolean) and returns either a normal completion containing unused or a throw completion.

它在 Environment Record 中创建一个新的、但未初始化的可变绑定。name 是被绑定名称的文本。如果 deletabletrue,则该绑定随后可以被删除。
它在以下类型中有具体定义:
CreateImmutableBinding ( name, strict )

The abstract method CreateImmutableBinding takes arguments name (a String) and strict (a Boolean) and returns either a normal completion containing unused or a throw completion.

它在 Environment Record 中创建一个新的、但未初始化的不可变绑定。name 是被绑定名称的文本。如果 stricttrue,则在它已被初始化之后尝试设置它时,总是会抛出异常,而不管引用该绑定的操作的严格模式设置如何。
它在以下类型中有具体定义:
InitializeBinding ( name, value )

The abstract method InitializeBinding takes arguments name (a String) and value (an ECMAScript language value) and returns either a normal completion containing unused or a throw completion.

它设置 Environment Record 中一个已存在但未初始化绑定的值。name 是被绑定名称的文本。value 是该绑定的值。
它在以下类型中有具体定义:
SetMutableBinding ( name, value, strict )

The abstract method SetMutableBinding takes arguments name (a String), value (an ECMAScript language value), and strict (a Boolean) and returns either a normal completion containing unused or a throw completion.

它设置 Environment Record 中一个已存在的可变绑定的值。name 是被绑定名称的文本。value 是该绑定的值。如果 stricttrue 且该绑定不能被设置,则会抛出 TypeError 异常。
它在以下类型中有具体定义:
GetBindingValue ( name, strict )

The abstract method GetBindingValue takes arguments name (a String) and strict (a Boolean) and returns either a normal completion containing an ECMAScript language value or a throw completion.

它从 Environment Record 返回一个已存在绑定的值。name 是被绑定名称的文本。strict 用于识别源自严格模式代码或以其他方式要求严格模式引用语义的引用。如果 stricttrue 且该绑定不存在,则会抛出 ReferenceError 异常。如果该绑定存在但未初始化,则会抛出 ReferenceError,而不管 strict 的值如何。
它在以下类型中有具体定义:
DeleteBinding ( name )

The abstract method DeleteBinding takes argument name (a String) and returns either a normal completion containing a Boolean or a throw completion.

它从 Environment Record 删除一个绑定。name 是被绑定名称的文本。如果 name 的绑定存在,则移除该绑定并返回 true。如果该绑定存在但不能被移除,则返回 false。如果该绑定不存在,则返回 true
它在以下类型中有具体定义:
HasThisBinding ( )

The abstract method HasThisBinding takes no arguments and returns a Boolean.

它确定 Environment Record 是否建立 this 绑定。如果它建立了则返回 true,否则返回 false
它在以下类型中有具体定义:
GetThisBinding ( )

The abstract method GetThisBinding takes no arguments and returns either a normal completion containing an ECMAScript language value or a throw completion.

它返回此 Environment Recordthis 绑定的值。如果 this 绑定尚未初始化,则抛出 ReferenceError
它在以下类型中有具体定义:
HasSuperBinding ( )

The abstract method HasSuperBinding takes no arguments and returns a Boolean.

它确定 Environment Record 是否建立 super 方法绑定。如果它建立了则返回 true,否则返回 false。如果它返回 true,则意味着该 Environment RecordFunction Environment Record,尽管反向蕴含并不成立。
它在以下类型中有具体定义:
WithBaseObject ( )

The abstract method WithBaseObject takes no arguments and returns an Object or undefined.

如果此 Environment Recordwith 语句相关联,则返回 with 对象。否则,返回 undefined
它在以下类型中有具体定义:

9.1.1.1 声明式环境记录

每个 Declarative Environment Record 都与一个 ECMAScript 程序作用域相关联,该作用域包含变量、常量、let、class、module、import 和/或 function 声明。Declarative Environment Record 绑定其作用域内包含的声明所定义的一组标识符。

每个声明式环境记录也都有一个 [[DisposableResourceStack]] 字段,其中包含一个 DisposableResource 记录的列表。此列表中的元素由 using 声明和 await using 声明跟踪,并且必须在构造该环境记录的求值步骤完成时被处置。

9.1.1.1.1 HasBinding ( name )

The HasBinding concrete method of a Declarative Environment Record envRecord takes argument name (a String) and returns a normal completion containing a Boolean. 它确定实参标识符是否为该记录所绑定的标识符之一。 It performs the following steps when called:

  1. 如果 envRecord 具有 name 的绑定,则返回 true
  2. 返回 false

9.1.1.1.2 CreateMutableBinding ( name, deletable )

The CreateMutableBinding concrete method of a Declarative Environment Record envRecord takes arguments name (a String) and deletable (a Boolean) and returns a normal completion containing unused. 它为名称 name 创建一个新的、未初始化的可变绑定。此 Environment Record 中必须尚不存在 name 的绑定。如果 deletabletrue,则新绑定会被标记为可被删除。 It performs the following steps when called:

  1. 断言:envRecord 尚不具有 name 的绑定。
  2. envRecord 中为 name 创建一个可变绑定,并记录它未被初始化。如果 deletabletrue,则记录新创建的绑定可以由后续的 DeleteBinding 调用删除。
  3. 返回 unused

9.1.1.1.3 CreateImmutableBinding ( name, strict )

The CreateImmutableBinding concrete method of a Declarative Environment Record envRecord takes arguments name (a String) and strict (a Boolean) and returns a normal completion containing unused. 它为名称 name 创建一个新的、未初始化的不可变绑定。此 Environment Record 中必须尚不存在 name 的绑定。如果 stricttrue,则新绑定会被标记为严格绑定。 It performs the following steps when called:

  1. 断言:envRecord 尚不具有 name 的绑定。
  2. envRecord 中为 name 创建一个不可变绑定,并记录它未被初始化。如果 stricttrue,则记录新创建的绑定是严格绑定。
  3. 返回 unused

9.1.1.1.4 InitializeBinding ( name, value )

The InitializeBinding concrete method of a Declarative Environment Record envRecord takes arguments name (a String) and value (an ECMAScript language value) and returns a normal completion containing unused. 它用于将名称为 name 的标识符的当前绑定的绑定值设置为值 valuename 的未初始化绑定必须已经存在。 It performs the following steps when called:

  1. 断言:envRecord 必须具有 name 的未初始化绑定。
  2. envRecordname 的绑定值设置为 value
  3. 记录 envRecordname 的绑定已经被初始化。
  4. 返回 unused

9.1.1.1.5 SetMutableBinding ( name, value, strict )

The SetMutableBinding concrete method of a Declarative Environment Record envRecord takes arguments name (a String), value (an ECMAScript language value), and strict (a Boolean) and returns either a normal completion containing unused or a throw completion. 它尝试将名称为 name 的标识符的当前绑定的绑定值更改为值 valuename 的绑定通常已经存在,但在少数情况下可能不存在。如果该绑定是不可变绑定,且 stricttrue,则会抛出 TypeError。 It performs the following steps when called:

  1. 如果 envRecord 不具有 name 的绑定,则
    1. 如果 stricttrue,则抛出 ReferenceError 异常。
    2. 执行 ! envRecord.CreateMutableBinding(name, true)。
    3. 执行 ! envRecord.InitializeBinding(name, value)。
    4. 返回 unused
  2. 如果 envRecordname 的绑定是严格绑定,则将 strict 设置为 true
  3. 如果 envRecordname 的绑定尚未被初始化,则
    1. 抛出 ReferenceError 异常。
  4. 否则如果 envRecordname 的绑定是可变绑定,则
    1. 将其绑定值更改为 value
  5. 否则,
    1. 断言:这是一次尝试更改不可变绑定的值。
    2. 如果 stricttrue,则抛出 TypeError 异常。
  6. 返回 unused
Note

导致在步骤 1 出现缺失绑定的 ECMAScript 代码示例为:

function f() { eval("var x; x = (delete x, 0);"); }

9.1.1.1.6 GetBindingValue ( name, strict )

The GetBindingValue concrete method of a Declarative Environment Record envRecord takes arguments name (a String) and strict (a Boolean) and returns either a normal completion containing an ECMAScript language value or a throw completion. 它返回其名称为 name 的已绑定标识符的值。如果该绑定存在但未初始化,则会抛出 ReferenceError,而不管 strict 的值如何。 It performs the following steps when called:

  1. 断言:envRecord 具有 name 的绑定。
  2. 如果 envRecordname 的绑定是未初始化绑定,则抛出 ReferenceError 异常。
  3. 返回 envRecord 中当前绑定到 name 的值。

9.1.1.1.7 DeleteBinding ( name )

The DeleteBinding concrete method of a Declarative Environment Record envRecord takes argument name (a String) and returns a normal completion containing a Boolean. 它只能删除那些已被显式指定为可被删除的绑定。 It performs the following steps when called:

  1. 断言:envRecord 具有 name 的绑定。
  2. 如果 envRecordname 的绑定不能被删除,则返回 false
  3. envRecord 中移除 name 的绑定。
  4. 返回 true

9.1.1.1.8 HasThisBinding ( )

The HasThisBinding concrete method of a Declarative Environment Record envRecord takes no arguments and returns false. It performs the following steps when called:

  1. 返回 false
Note

常规的 Declarative Environment Record(即既不是 Function Environment Record,也不是 Module Environment Record 的记录)不提供 this 绑定。

9.1.1.1.9 GetThisBinding ( )

Declarative Environment RecordGetThisBinding 具体方法在本规范中从未被使用。

9.1.1.1.10 HasSuperBinding ( )

The HasSuperBinding concrete method of a Declarative Environment Record envRecord takes no arguments and returns false. It performs the following steps when called:

  1. 返回 false
Note

常规的 Declarative Environment Record(即既不是 Function Environment Record,也不是 Module Environment Record 的记录)不提供 super 绑定。

9.1.1.1.11 WithBaseObject ( )

The WithBaseObject concrete method of a Declarative Environment Record envRecord takes no arguments and returns undefined. It performs the following steps when called:

  1. 返回 undefined

9.1.1.2 对象环境记录

每个 Object Environment Record 都与一个称为其绑定对象的对象相关联。Object Environment Record 绑定一组字符串标识符名称,这些名称直接对应于其绑定对象的属性名称。不是 IdentifierName 形式字符串的属性键包含在被绑定标识符集合中。自有属性和继承属性都包含在该集合中,而不管其 [[Enumerable]] 特性的设置如何。由于属性可以动态地添加到对象并从对象中删除,因此 Object Environment Record 所绑定的标识符集合可能会作为添加或删除属性的任何操作的副作用而发生改变。作为这类副作用结果创建的任何绑定都被认为是可变绑定,即使对应属性的 Writable 特性是 false。Object Environment Records 不存在不可变绑定。

with 语句(14.11)创建的 Object Environment Records 可以提供其绑定对象,作为在函数调用中使用的隐式 this 值。该能力由 Boolean [[IsWithEnvironment]] 字段控制。

Object Environment Records 具有 Table 16 中列出的附加状态字段。

Table 16: Object Environment Records 的附加字段
字段名 含义
[[BindingObject]] an Object Environment Record 的绑定对象。
[[IsWithEnvironment]] a Boolean 指示此 Environment Record 是否为 with 语句创建。

9.1.1.2.1 HasBinding ( name )

The HasBinding concrete method of an Object Environment Record envRecord takes argument name (a String) and returns either a normal completion containing a Boolean or a throw completion. 它确定其关联的绑定对象是否具有名称为 name 的属性。 It performs the following steps when called:

  1. bindingObjenvRecord.[[BindingObject]]
  2. foundBinding 为 ? HasProperty(bindingObj, name)。
  3. 如果 foundBindingfalse,则返回 false
  4. 如果 envRecord.[[IsWithEnvironment]]false,则返回 true
  5. unscopables 为 ? Get(bindingObj, %Symbol.unscopables%)。
  6. 如果 unscopables 是 Object,则
    1. blockedToBoolean(? Get(unscopables, name))。
    2. 如果 blockedtrue,则返回 false
  7. 返回 true

9.1.1.2.2 CreateMutableBinding ( name, deletable )

The CreateMutableBinding concrete method of an Object Environment Record envRecord takes arguments name (a String) and deletable (a Boolean) and returns either a normal completion containing unused or a throw completion. 它在 Environment Record 的关联绑定对象中创建一个名称为 name 的属性,并将其初始化为值 undefined。如果 deletabletrue,则新属性的 [[Configurable]] 特性被设置为 true;否则被设置为 false。 It performs the following steps when called:

  1. bindingObjenvRecord.[[BindingObject]]
  2. 执行 ? DefinePropertyOrThrow(bindingObj, name, PropertyDescriptor { [[Value]]: undefined, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: deletable })。
  3. 返回 unused
Note

通常 envRecord 不会具有 name 的绑定,但如果它确实具有,则 DefinePropertyOrThrow 的语义可能导致现有绑定被替换或遮蔽,或导致返回一个 abrupt completion。

9.1.1.2.3 CreateImmutableBinding ( name, strict )

Object Environment RecordCreateImmutableBinding 具体方法在本规范中从未被使用。

9.1.1.2.4 InitializeBinding ( name, value )

The InitializeBinding concrete method of an Object Environment Record envRecord takes arguments name (a String) and value (an ECMAScript language value) and returns either a normal completion containing unused or a throw completion. 它用于将名称为 name 的标识符的当前绑定的绑定值设置为值 value。 It performs the following steps when called:

  1. 执行 ? envRecord.SetMutableBinding(name, value, false)
  2. 返回 unused
Note

在本规范中,Object Environment RecordsCreateMutableBinding 的所有使用后面都会立即跟随对相同名称调用 InitializeBinding。因此,本规范不会显式跟踪 Object Environment Records 中绑定的初始化状态。

9.1.1.2.5 SetMutableBinding ( name, value, strict )

The SetMutableBinding concrete method of an Object Environment Record envRecord takes arguments name (a String), value (an ECMAScript language value), and strict (a Boolean) and returns either a normal completion containing unused or a throw completion. 它尝试将该 Environment Record 的关联绑定对象中名称为 name 的属性的值设置为值 value。名为 name 的属性通常已经存在,但如果它不存在或当前不可写,则错误处理由 strict 决定。 It performs the following steps when called:

  1. bindingObjenvRecord.[[BindingObject]]
  2. stillExists 为 ? HasProperty(bindingObj, name)。
  3. 如果 stillExistsfalsestricttrue,则抛出 ReferenceError 异常。
  4. 执行 ? Set(bindingObj, name, value, strict)。
  5. 返回 unused

9.1.1.2.6 GetBindingValue ( name, strict )

The GetBindingValue concrete method of an Object Environment Record envRecord takes arguments name (a String) and strict (a Boolean) and returns either a normal completion containing an ECMAScript language value or a throw completion. 它返回其关联绑定对象中名称为 name 的属性的值。该属性应当已经存在,但如果它不存在,结果取决于 strict。 It performs the following steps when called:

  1. bindingObjenvRecord.[[BindingObject]]
  2. value 为 ? HasProperty(bindingObj, name)。
  3. 如果 valuefalse,则
    1. 如果 strictfalse,则返回 undefined
    2. 抛出 ReferenceError 异常。
  4. 返回 ? Get(bindingObj, name)。

9.1.1.2.7 DeleteBinding ( name )

The DeleteBinding concrete method of an Object Environment Record envRecord takes argument name (a String) and returns either a normal completion containing a Boolean or a throw completion. 它只能删除对应于环境对象属性且其 [[Configurable]] 特性值为 true 的绑定。 It performs the following steps when called:

  1. bindingObjenvRecord.[[BindingObject]]
  2. 返回 ? bindingObj.[[Delete]](name)

9.1.1.2.8 HasThisBinding ( )

The HasThisBinding concrete method of an Object Environment Record envRecord takes no arguments and returns false. It performs the following steps when called:

  1. 返回 false
Note

Object Environment Records 不提供 this 绑定。

9.1.1.2.9 GetThisBinding ( )

Object Environment RecordGetThisBinding 具体方法在本规范中从未被使用。

9.1.1.2.10 HasSuperBinding ( )

The HasSuperBinding concrete method of an Object Environment Record envRecord takes no arguments and returns false. It performs the following steps when called:

  1. 返回 false
Note

Object Environment Records 不提供 super 绑定。

9.1.1.2.11 WithBaseObject ( )

The WithBaseObject concrete method of an Object Environment Record envRecord takes no arguments and returns an Object or undefined. It performs the following steps when called:

  1. 如果 envRecord.[[IsWithEnvironment]]true,则返回 envRecord.[[BindingObject]]
  2. 返回 undefined

9.1.1.3 函数环境记录

Function Environment Record 是一种 Declarative Environment Record,用于表示函数的顶层作用域,并且如果该函数不是 ArrowFunction 函数或 AsyncArrowFunction 函数,则提供 this 绑定。如果一个函数不是 ArrowFunction 函数或 AsyncArrowFunction 函数并且引用 super,则它的 Function Environment Record 还包含用于从函数内部执行 super 方法调用的状态。

Function Environment Records 具有 Table 17 中列出的附加状态字段。

Table 17: Function Environment Records 的附加字段
字段名 含义
[[ThisValue]] an ECMAScript language value 这是此函数调用所使用的 this 值。
[[ThisBindingStatus]] lexical, initialized, or uninitialized 如果值是 lexical,则这是一个 ArrowFunctionAsyncArrowFunction,并且没有本地 this 值。
[[FunctionObject]] an ECMAScript function object 其调用导致此 Environment Record 被创建的函数对象
[[NewTarget]] a constructor or undefined 如果此 Environment Record[[Construct]] 内部方法创建,则 [[NewTarget]][[Construct]]newTarget 形参的值。否则,其值为 undefined

Function Environment Records 支持 Table 15 中列出的所有 Declarative Environment Record 方法,并且除 HasThisBindingGetThisBindingHasSuperBinding 之外,所有这些方法都共享相同的规范。

9.1.1.3.1 BindThisValue ( envRecord, value )

The abstract operation BindThisValue takes arguments envRecord (a Function Environment Record) and value (an ECMAScript language value) and returns either a normal completion containing unused or a throw completion. 它设置 envRecord.[[ThisValue]],并记录其已被初始化。 It performs the following steps when called:

  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 ( )

The HasThisBinding concrete method of a Function Environment Record envRecord takes no arguments and returns a Boolean. It performs the following steps when called:

  1. 如果 envRecord.[[ThisBindingStatus]]lexical,则返回 false
  2. 返回 true

9.1.1.3.3 GetThisBinding ( )

The GetThisBinding concrete method of a Function Environment Record envRecord takes no arguments and returns either a normal completion containing an ECMAScript language value or a throw completion. It performs the following steps when called:

  1. 断言:envRecord.[[ThisBindingStatus]] 不是 lexical
  2. 如果 envRecord.[[ThisBindingStatus]]uninitialized,则抛出 ReferenceError 异常。
  3. 返回 envRecord.[[ThisValue]]

9.1.1.3.4 HasSuperBinding ( )

The HasSuperBinding concrete method of a Function Environment Record envRecord takes no arguments and returns a Boolean. It performs the following steps when called:

  1. 如果 envRecord.[[ThisBindingStatus]]lexical,则返回 false
  2. 如果 envRecord.[[FunctionObject]].[[HomeObject]]undefined,则返回 false
  3. 返回 true

9.1.1.3.5 GetSuperBase ( envRecord )

The abstract operation GetSuperBase takes argument envRecord (a Function Environment Record) and returns an Object, null, or undefined. 它返回在 envRecord 中绑定的 super 属性访问的基对象。值 undefined 表示这类访问会产生运行时错误。 It performs the following steps when called:

  1. homeenvRecord.[[FunctionObject]].[[HomeObject]]
  2. 如果 homeundefined,则返回 undefined
  3. 断言:home普通对象
  4. 返回 ! home.[[GetPrototypeOf]]()。

9.1.1.4 全局环境记录

Global Environment Record 用于表示由在共同 realm 中处理的所有 ECMAScript Script 元素共享的最外层作用域。Global Environment Record 提供内置全局(条款 19)、全局对象属性,以及在 Script 内出现的所有顶层声明(8.2.118.2.13)的绑定。

Global Environment Record 在逻辑上是一个单一记录,但在规范中被指定为封装 Object Environment RecordDeclarative Environment Record 的复合体。Object Environment Record 以关联 Realm Record全局对象作为其基础对象。此全局对象是 Global Environment Record 的 GetThisBinding 具体方法返回的值。Global Environment Record 的 Object Environment Record 组成部分包含所有内置全局(条款 19)的绑定,以及全局代码中包含FunctionDeclarationGeneratorDeclarationAsyncFunctionDeclarationAsyncGeneratorDeclarationVariableStatement 引入的所有绑定。全局代码中所有其他 ECMAScript 声明的绑定都包含在 Global Environment Record 的 Declarative Environment Record 组成部分中。

属性可以直接在全局对象上创建。因此,Global Environment Record 的 Object Environment Record 组成部分可以同时包含FunctionDeclarationGeneratorDeclarationAsyncFunctionDeclarationAsyncGeneratorDeclarationVariableDeclaration 声明显式创建的绑定,以及作为全局对象属性隐式创建的绑定。

Global Environment Records 具有 Table 18 中列出的附加字段。

Table 18: Global Environment Records 的附加字段
字段名 含义
[[ObjectRecord]] an Object Environment Record 绑定对象是全局对象。它包含内置全局绑定,以及关联 realm 的全局代码中的 FunctionDeclarationGeneratorDeclarationAsyncFunctionDeclarationAsyncGeneratorDeclarationVariableDeclaration 绑定。
[[GlobalThisValue]] an Object 在全局作用域中由 this 返回的值。宿主可以提供任何 ECMAScript Object 值。
[[DeclarativeRecord]] a Declarative Environment Record 包含关联 realm 代码的全局代码中所有声明的绑定,但 FunctionDeclarationGeneratorDeclarationAsyncFunctionDeclarationAsyncGeneratorDeclarationVariableDeclaration 绑定除外。

9.1.1.4.1 HasBinding ( name )

The HasBinding concrete method of a Global Environment Record envRecord takes argument name (a String) and returns either a normal completion containing a Boolean or a throw completion. 它确定实参标识符是否为该记录所绑定的标识符之一。 It performs the following steps when called:

  1. declRecordenvRecord.[[DeclarativeRecord]]
  2. 如果 ! declRecord.HasBinding(name) 是 true,则返回 true
  3. objRecordenvRecord.[[ObjectRecord]]
  4. 返回 ? objRecord.HasBinding(name)

9.1.1.4.2 CreateMutableBinding ( name, deletable )

The CreateMutableBinding concrete method of a Global Environment Record envRecord takes arguments name (a String) and deletable (a Boolean) and returns either a normal completion containing unused or a throw completion. 它为名称 name 创建一个新的、未初始化的可变绑定。该绑定创建于关联的 DeclarativeRecord 中。DeclarativeRecord 中必须尚不存在 name 的绑定。如果 deletabletrue,则新绑定会被标记为可被删除。 It performs the following steps when called:

  1. declRecordenvRecord.[[DeclarativeRecord]]
  2. 如果 ! declRecord.HasBinding(name) 是 true,则抛出 TypeError 异常。
  3. 返回 ! declRecord.CreateMutableBinding(name, deletable)。

9.1.1.4.3 CreateImmutableBinding ( name, strict )

The CreateImmutableBinding concrete method of a Global Environment Record envRecord takes arguments name (a String) and strict (a Boolean) and returns either a normal completion containing unused or a throw completion. 它为名称 name 创建一个新的、未初始化的不可变绑定。此 Environment Record 中必须尚不存在 name 的绑定。如果 stricttrue,则新绑定会被标记为严格绑定。 It performs the following steps when called:

  1. declRecordenvRecord.[[DeclarativeRecord]]
  2. 如果 ! declRecord.HasBinding(name) 是 true,则抛出 TypeError 异常。
  3. 返回 ! declRecord.CreateImmutableBinding(name, strict)。

9.1.1.4.4 InitializeBinding ( name, value )

The InitializeBinding concrete method of a Global Environment Record envRecord takes arguments name (a String) and value (an ECMAScript language value) and returns either a normal completion containing unused or a throw completion. 它用于将名称为 name 的标识符的当前绑定的绑定值设置为值 valuename 的未初始化绑定必须已经存在。 It performs the following steps when called:

  1. declRecordenvRecord.[[DeclarativeRecord]]
  2. 如果 ! declRecord.HasBinding(name) 是 true,则
    1. 返回 ! declRecord.InitializeBinding(name, value)。
  3. 断言:如果绑定存在,它必须在 Object Environment Record 中。
  4. objRecordenvRecord.[[ObjectRecord]]
  5. 返回 ? objRecord.InitializeBinding(name, value)

9.1.1.4.5 SetMutableBinding ( name, value, strict )

The SetMutableBinding concrete method of a Global Environment Record envRecord takes arguments name (a String), value (an ECMAScript language value), and strict (a Boolean) and returns either a normal completion containing unused or a throw completion. 它尝试将名称为 name 的标识符的当前绑定的绑定值更改为值 value。如果该绑定是不可变绑定且 stricttrue,则会抛出 TypeError。名为 name 的绑定通常已经存在,但如果它不存在或当前不可写,则错误处理由 strict 决定。 It performs the following steps when called:

  1. declRecordenvRecord.[[DeclarativeRecord]]
  2. 如果 ! declRecord.HasBinding(name) 是 true,则
    1. 返回 ? declRecord.SetMutableBinding(name, value, strict)。
  3. objRecordenvRecord.[[ObjectRecord]]
  4. 返回 ? objRecord.SetMutableBinding(name, value, strict)

9.1.1.4.6 GetBindingValue ( name, strict )

The GetBindingValue concrete method of a Global Environment Record envRecord takes arguments name (a String) and strict (a Boolean) and returns either a normal completion containing an ECMAScript language value or a throw completion. 它返回其名称为 name 的已绑定标识符的值。如果该绑定是未初始化绑定,则会抛出 ReferenceError 异常。名为 name 的绑定通常已经存在,但如果它不存在或当前不可写,则错误处理由 strict 决定。 It performs the following steps when called:

  1. declRecordenvRecord.[[DeclarativeRecord]]
  2. 如果 ! declRecord.HasBinding(name) 是 true,则
    1. 返回 ? declRecord.GetBindingValue(name, strict)。
  3. objRecordenvRecord.[[ObjectRecord]]
  4. 返回 ? objRecord.GetBindingValue(name, strict)

9.1.1.4.7 DeleteBinding ( name )

The DeleteBinding concrete method of a Global Environment Record envRecord takes argument name (a String) and returns either a normal completion containing a Boolean or a throw completion. 它只能删除那些已被显式指定为可被删除的绑定。 It performs the following steps when called:

  1. declRecordenvRecord.[[DeclarativeRecord]]
  2. 如果 ! declRecord.HasBinding(name) 是 true,则
    1. 返回 ! declRecord.DeleteBinding(name)。
  3. objRecordenvRecord.[[ObjectRecord]]
  4. globalObjobjRecord.[[BindingObject]]
  5. existingProperty 为 ? HasOwnProperty(globalObj, name)。
  6. 如果 existingPropertytrue,则
    1. 返回 ? objRecord.DeleteBinding(name)
  7. 返回 true

9.1.1.4.8 HasThisBinding ( )

The HasThisBinding concrete method of a Global Environment Record envRecord takes no arguments and returns true. It performs the following steps when called:

  1. 返回 true
Note

Global Environment Records 总是提供 this 绑定。

9.1.1.4.9 GetThisBinding ( )

The GetThisBinding concrete method of a Global Environment Record envRecord takes no arguments and returns a normal completion containing an Object. It performs the following steps when called:

  1. 返回 envRecord.[[GlobalThisValue]]

9.1.1.4.10 HasSuperBinding ( )

The HasSuperBinding concrete method of a Global Environment Record envRecord takes no arguments and returns false. It performs the following steps when called:

  1. 返回 false
Note

Global Environment Records 不提供 super 绑定。

9.1.1.4.11 WithBaseObject ( )

The WithBaseObject concrete method of a Global Environment Record envRecord takes no arguments and returns undefined. It performs the following steps when called:

  1. 返回 undefined

9.1.1.4.12 HasLexicalDeclaration ( envRecord, name )

The abstract operation HasLexicalDeclaration takes arguments envRecord (a Global Environment Record) and name (a String) and returns a Boolean. 它确定实参标识符是否在 envRecord 中具有通过词法声明(例如 LexicalDeclarationClassDeclaration)创建的绑定。 It performs the following steps when called:

  1. declRecordenvRecord.[[DeclarativeRecord]]
  2. 返回 ! declRecord.HasBinding(name)。

9.1.1.4.13 HasRestrictedGlobalProperty ( envRecord, name )

The abstract operation HasRestrictedGlobalProperty takes arguments envRecord (a Global Environment Record) and name (a String) and returns either a normal completion containing a Boolean or a throw completion. 它确定实参标识符是否为全局对象的某个属性的名称,而该属性不得被全局词法绑定遮蔽。 It performs the following steps when called:

  1. objRecordenvRecord.[[ObjectRecord]]
  2. globalObjobjRecord.[[BindingObject]]
  3. existingProperty 为 ? globalObj.[[GetOwnProperty]](name)
  4. 如果 existingPropertyundefined,则返回 false
  5. 如果 existingProperty.[[Configurable]]true,则返回 false
  6. 返回 true
Note

全局对象上可能存在直接创建而不是使用 var 或 function 声明声明的属性。不得创建与全局对象的不可配置属性具有相同名称的全局词法绑定。全局属性 "undefined" 是这类属性的一个例子。

9.1.1.4.14 CanDeclareGlobalVar ( envRecord, name )

The abstract operation CanDeclareGlobalVar takes arguments envRecord (a Global Environment Record) and name (a String) and returns either a normal completion containing a Boolean or a throw completion. 它确定如果使用相同实参 name 调用对应的 CreateGlobalVarBinding 调用是否会成功。允许冗余的 var 声明和针对预先存在的全局对象属性的 var 声明。 It performs the following steps when called:

  1. objRecordenvRecord.[[ObjectRecord]]
  2. globalObjobjRecord.[[BindingObject]]
  3. hasProperty 为 ? HasOwnProperty(globalObj, name)。
  4. 如果 hasPropertytrue,则返回 true
  5. 返回 ? IsExtensible(globalObj)。

9.1.1.4.15 CanDeclareGlobalFunction ( envRecord, name )

The abstract operation CanDeclareGlobalFunction takes arguments envRecord (a Global Environment Record) and name (a String) and returns either a normal completion containing a Boolean or a throw completion. 它确定如果使用相同实参 name 调用对应的 CreateGlobalFunctionBinding 调用是否会成功。 It performs the following steps when called:

  1. objRecordenvRecord.[[ObjectRecord]]
  2. globalObjobjRecord.[[BindingObject]]
  3. existingProperty 为 ? globalObj.[[GetOwnProperty]](name)
  4. 如果 existingPropertyundefined,则返回 ? IsExtensible(globalObj)。
  5. 如果 existingProperty.[[Configurable]]true,则返回 true
  6. 如果 IsDataDescriptor(existingProperty) 是 trueexistingProperty 具有特性值 { [[Writable]]: true, [[Enumerable]]: true },则返回 true
  7. 返回 false

9.1.1.4.16 CreateGlobalVarBinding ( envRecord, name, deletable )

The abstract operation CreateGlobalVarBinding takes arguments envRecord (a Global Environment Record), name (a String), and deletable (a Boolean) and returns either a normal completion containing unused or a throw completion. 它在关联的 Object Environment Record 中创建并初始化一个可变绑定。如果绑定已经存在,则重用它,并假定它已被初始化。 It performs the following steps when called:

  1. objRecordenvRecord.[[ObjectRecord]]
  2. globalObjobjRecord.[[BindingObject]]
  3. hasProperty 为 ? HasOwnProperty(globalObj, name)。
  4. extensible 为 ? IsExtensible(globalObj)。
  5. 如果 hasPropertyfalseextensibletrue,则
    1. 执行 ? objRecord.CreateMutableBinding(name, deletable)
    2. 执行 ? objRecord.InitializeBinding(name, undefined)
  6. 返回 unused

9.1.1.4.17 CreateGlobalFunctionBinding ( envRecord, name, value, deletable )

The abstract operation CreateGlobalFunctionBinding takes arguments envRecord (a Global Environment Record), name (a String), value (an ECMAScript function object), and deletable (a Boolean) and returns either a normal completion containing unused or a throw completion. 它在关联的 Object Environment Record 中创建并初始化一个可变绑定。如果绑定已经存在,则替换它。 It performs the following steps when called:

  1. objRecordenvRecord.[[ObjectRecord]]
  2. globalObjobjRecord.[[BindingObject]]
  3. existingProperty 为 ? globalObj.[[GetOwnProperty]](name)
  4. 如果 existingPropertyundefinedexistingProperty.[[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
Note

全局函数声明总是表示为全局对象的自有属性。如果可能,现有自有属性会被重新配置为具有一组标准特性值。步骤 7 等价于调用 InitializeBinding 具体方法所做的事情,并且如果 globalObj 是 Proxy,将产生相同的 Proxy 陷阱调用序列。

9.1.1.5 模块环境记录

Module Environment Record 是一种 Declarative Environment Record,用于表示 ECMAScript Module 的外层作用域。除了正常的可变绑定和不可变绑定之外,Module Environment Records 还提供不可变导入绑定,即提供对存在于另一个 Environment Record 中的目标绑定的间接访问的绑定。

Module Environment Records 支持 Table 15 中列出的所有 Declarative Environment Record 方法,并且除 GetBindingValueDeleteBindingHasThisBindingGetThisBinding 之外,所有这些方法都共享相同的规范。

9.1.1.5.1 GetBindingValue ( name, strict )

The GetBindingValue concrete method of a Module Environment Record envRecord takes arguments name (a String) and strict (a Boolean) and returns either a normal completion containing an ECMAScript language value or a throw completion. 它返回其名称为 name 的已绑定标识符的值。不过,如果该绑定是间接绑定,则返回目标绑定的值。如果该绑定存在但未初始化,则会抛出 ReferenceError。 It performs the following steps when called:

  1. 断言:stricttrue
  2. 断言:envRecord 具有 name 的绑定。
  3. 如果 name 的绑定是间接绑定,则
    1. moduletargetName 为创建 name 的此绑定时提供的间接值。
    2. targetEnvmodule.[[Environment]]
    3. 如果 targetEnvempty,则抛出 ReferenceError 异常。
    4. 返回 ? targetEnv.GetBindingValue(targetName, true)
  4. 如果 envRecordname 的绑定是未初始化绑定,则抛出 ReferenceError 异常。
  5. 返回 envRecord 中当前绑定到 name 的值。
Note

strict 将始终是 true,因为 Module 始终是严格模式代码。

9.1.1.5.2 DeleteBinding ( name )

Module Environment RecordDeleteBinding 具体方法在本规范中从未被使用。

Note

Module Environment Records 仅在严格代码中使用,并且早期错误规则会阻止在严格代码中将 delete 运算符应用于会解析到 Module Environment Record 绑定的 Reference Record。参见 13.5.1.1

9.1.1.5.3 HasThisBinding ( )

The HasThisBinding concrete method of a Module Environment Record envRecord takes no arguments and returns true. It performs the following steps when called:

  1. 返回 true
Note

Module Environment Records 总是提供 this 绑定。

9.1.1.5.4 GetThisBinding ( )

The GetThisBinding concrete method of a Module Environment Record envRecord takes no arguments and returns a normal completion containing undefined. It performs the following steps when called:

  1. 返回 undefined

9.1.1.5.5 CreateImportBinding ( envRecord, name, targetModule, targetName )

The abstract operation CreateImportBinding takes arguments envRecord (a Module Environment Record), name (a String), targetModule (a Module Record), and targetName (a String) and returns unused. 它为名称 name 创建一个新的、已初始化的不可变间接绑定。envRecord 中必须尚不存在 name 的绑定。targetName 是存在于 targetModuleModule Environment Record 中的绑定名称。对新绑定值的访问将间接访问目标绑定的绑定值。 It performs the following steps when called:

  1. 断言:envRecord 尚不具有 name 的绑定。
  2. 断言:当 targetModule.[[Environment]] 被实例化时,它将具有 targetName 的直接绑定。
  3. envRecord 中为 name 创建一个不可变间接绑定,该绑定引用 targetModuletargetName 作为其目标绑定,并记录该绑定已被初始化。
  4. 返回 unused

9.1.2 Environment Record 操作

以下抽象操作在本规范中用于对 Environment Records 进行操作:

9.1.2.1 GetIdentifierReference ( envRecord, name, strict )

The abstract operation GetIdentifierReference takes arguments envRecord (an Environment Record or null), name (a String), and strict (a Boolean) and returns either a normal completion containing a Reference Record or a throw completion. It performs the following steps when called:

  1. 如果 envRecordnull,则
    1. 返回 Reference Record { [[Base]]: unresolvable, [[ReferencedName]]: name, [[Strict]]: strict, [[ThisValue]]: empty }。
  2. exists 为 ? envRecord.HasBinding(name)
  3. 如果 existstrue,则
    1. 返回 Reference Record { [[Base]]: envRecord, [[ReferencedName]]: name, [[Strict]]: strict, [[ThisValue]]: empty }。
  4. outerenvRecord.[[OuterEnv]]
  5. 返回 ? GetIdentifierReference(outer, name, strict)。

9.1.2.2 NewDeclarativeEnvironment ( outerEnv )

The abstract operation NewDeclarativeEnvironment takes argument outerEnv (an Environment Record or null) and returns a Declarative Environment Record. It performs the following steps when called:

  1. envRecord 为一个不包含任何绑定的新声明式环境记录。
  2. envRecord.[[OuterEnv]] 设置为 outerEnv
  3. envRecord.[[DisposableResourceStack]] 设置为一个新的空列表。
  4. 返回 envRecord

9.1.2.3 NewObjectEnvironment ( obj, isWithEnv, outerEnv )

The abstract operation NewObjectEnvironment takes arguments obj (an Object), isWithEnv (a Boolean), and outerEnv (an Environment Record or null) and returns an Object Environment Record. It performs the following steps when called:

  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 )

The abstract operation NewFunctionEnvironment takes arguments func (an ECMAScript function object) and newTarget (an Object or undefined) and returns a Function Environment Record. It performs the following steps when called:

  1. envRecord 为一个不包含任何绑定的新函数环境记录。
  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]] 设置为一个新的空列表。
  8. 返回 envRecord

9.1.2.5 NewGlobalEnvironment ( obj, thisValue )

The abstract operation NewGlobalEnvironment takes arguments obj (an Object) and thisValue (an Object) and returns a Global Environment Record. It performs the following steps when called:

  1. objRecordNewObjectEnvironment(obj, false, null)。
  2. declRecordNewDeclarativeEnvironment(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 )

The abstract operation NewModuleEnvironment takes argument outerEnv (a Global Environment Record) and returns a Module Environment Record. It performs the following steps when called:

  1. envRecord 为一个不包含任何绑定的新模块环境记录。
  2. envRecord.[[OuterEnv]] 设置为 outerEnv
  3. envRecord.[[DisposableResourceStack]] 设置为一个新的空列表。
  4. 返回 envRecord

9.2 PrivateEnvironment Records

PrivateEnvironment Record 是一种规范机制,用于基于 ECMAScript 代码中 ClassDeclarationClassExpression 的词法嵌套结构来跟踪 Private Names。它们类似于 Environment Records,但又与其不同。每个 PrivateEnvironment Record 都与一个 ClassDeclarationClassExpression 相关联。每当这样的类被求值时,都会创建一个新的 PrivateEnvironment Record,用于记录由该类声明的 Private Names

每个 PrivateEnvironment Record 都具有 Table 19 中定义的字段。

Table 19: PrivateEnvironment Record 字段
字段名 值类型 含义
[[OuterPrivateEnvironment]] a PrivateEnvironment Record or null 最近的包含类的 PrivateEnvironment Record。如果与此 PrivateEnvironment Record 关联的类不包含在任何其他类中,则为 null
[[Names]] a List of Private Names 此类声明的 Private Names

9.2.1 PrivateEnvironment Record 操作

以下抽象操作在本规范中用于对 PrivateEnvironment Records 进行操作:

9.2.1.1 NewPrivateEnvironment ( outerPrivateEnv )

The abstract operation NewPrivateEnvironment takes argument outerPrivateEnv (a PrivateEnvironment Record or null) and returns a PrivateEnvironment Record. It performs the following steps when called:

  1. names 为一个新的空 List
  2. 返回 PrivateEnvironment Record { [[OuterPrivateEnvironment]]: outerPrivateEnv, [[Names]]: names }。

9.2.1.2 ResolvePrivateIdentifier ( privateEnv, identifier )

The abstract operation ResolvePrivateIdentifier takes arguments privateEnv (a PrivateEnvironment Record) and identifier (a String) and returns a Private Name. It performs the following steps when called:

  1. namesprivateEnv.[[Names]]
  2. names 的每个 Private Name privateName,执行:
    1. 如果 privateName.[[Description]]identifier,则
      1. 返回 privateName
  3. outerPrivateEnvprivateEnv.[[OuterPrivateEnvironment]]
  4. 断言:outerPrivateEnv 不是 null
  5. 返回 ResolvePrivateIdentifier(outerPrivateEnv, identifier)。

9.3 Realms

所有 ECMAScript 代码在被求值之前都必须与一个 realm 相关联。从概念上讲,一个 realm 由一组固有对象、一个 ECMAScript 全局环境、加载到该全局环境作用域内的所有 ECMAScript 代码,以及其他关联状态和资源组成。

在本规范中,realm 表示为一个 Realm Record,其字段在 Table 20 中指定:

Table 20: Realm Record 字段
字段名 含义
[[AgentSignifier]] an agent signifier 拥有此 realmagent
[[Intrinsics]] a Record whose field names are intrinsic keys and whose values are objects 与此 realm 关联的代码所使用的固有值
[[GlobalObject]] an Object realm全局对象
[[GlobalEnv]] a Global Environment Record realm 的全局环境
[[TemplateMap]] a List of Records with fields [[Site]] (a TemplateLiteral Parse Node) and [[Array]] (an Array)

模板对象会使用其 Realm Record[[TemplateMap]],为每个 realm 分别进行规范化。每个 [[Site]] 值都是一个 TemplateLiteral Parse Node。关联的 [[Array]] 值是传递给 tag 函数的对应模板对象。

Note 1
一旦某个 Parse Node 变得不可达,对应的 [[Array]] 也不可达,并且如果实现从 [[TemplateMap]] 列表中移除这一对,将是不可观察的。
[[LoadedModules]] a List of LoadedModuleRequest Records

从此 realm 导入的说明符字符串到已解析 Module Record 的映射。该列表不包含两个不同的 Records r1r2,使得 ModuleRequestsEqual(r1, r2) 是 true

Note 2
HostLoadImportedModule16.2.1.10 Note 1)中所述,Realm Records 中的 [[LoadedModules]] 仅在没有活动脚本或模块的上下文中运行 import() 表达式时使用。
[[HostDefined]] anything (default value is undefined) 保留给需要将额外信息与 Realm Record 关联的宿主使用的字段。

9.3.1 InitializeHostDefinedRealm ( )

The abstract operation InitializeHostDefinedRealm takes no arguments and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

  1. realm 为一个新的 Realm Record
  2. 执行 CreateIntrinsics(realm)。
  3. realm.[[AgentSignifier]] 设置为 AgentSignifier()。
  4. realm.[[TemplateMap]] 设置为一个新的空 List
  5. newContext 为一个新的执行上下文。
  6. newContext 的 Function 设置为 null
  7. newContextRealm 设置为 realm
  8. newContext 的 ScriptOrModule 设置为 null
  9. newContext 压入执行上下文栈;newContext 现在是运行中执行上下文。
  10. 如果宿主要求使用特定对象作为 realm全局对象,则
    1. global 为以宿主定义方式创建的这种对象。
  11. 否则,
    1. globalOrdinaryObjectCreate(realm.[[Intrinsics]].[[%Object.prototype%]])。
  12. 如果宿主要求 realm 的全局作用域中的 this 绑定返回全局对象以外的对象,则
    1. thisValue 为以宿主定义方式创建的这种对象。
  13. 否则,
    1. thisValueglobal
  14. realm.[[GlobalObject]] 设置为 global
  15. realm.[[GlobalEnv]] 设置为 NewGlobalEnvironment(global, thisValue)。
  16. 执行 ? SetDefaultGlobalBindings(realm)。
  17. global 上创建任何宿主定义的全局对象属性。
  18. 返回 unused

9.3.2 CreateIntrinsics ( realmRecord )

The abstract operation CreateIntrinsics takes argument realmRecord (a Realm Record) and returns unused. It performs the following steps when called:

  1. realmRecord.[[Intrinsics]] 设置为一个新的 Record
  2. 使用 Table 6 中列出的值设置 realmRecord.[[Intrinsics]] 的字段。字段名是该表“Intrinsic Name”列中列出的名称。每个字段的值都是一个新的对象值,并按照 1928 各条款中每个对象的规范所定义的属性值完全且递归地填充。所有对象属性值都是新创建的对象值。所有作为内置函数对象的值都通过执行 CreateBuiltinFunction(steps, length, name, slots, realmRecord, proto, async) 创建,其中 steps 是本规范提供的该函数的定义,name 是该函数 "name" 属性的初始值,length 是该函数 "length" 属性的初始值,slots 是该函数指定内部槽的名称列表(如果有),proto 是该函数 [[Prototype]] 内部槽的指定值,且如果该函数被描述为“async”则 asynctrue,否则为 false。固有对象及其属性的创建必须进行排序,以避免依赖尚未创建的对象。
  3. 执行 AddRestrictedFunctionProperties(realmRecord.[[Intrinsics]].[[%Function.prototype%]], realmRecord)。
  4. 返回 unused

9.3.3 SetDefaultGlobalBindings ( realmRecord )

The abstract operation SetDefaultGlobalBindings takes argument realmRecord (a Realm Record) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

  1. globalrealmRecord.[[GlobalObject]]
  2. 对条款 19 中指定的 Global Object 的每个属性,执行:
    1. name 为该属性名的 String 值。
    2. propertyDesc 为该属性的完全填充的数据 Property Descriptor,其中包含该属性的指定特性。对于 19.219.319.4 中列出的属性,[[Value]] 特性的值是来自 realmRecord 的对应固有对象。
    3. 执行 ? DefinePropertyOrThrow(global, name, propertyDesc)。
  3. 返回 unused

9.4 执行上下文

execution context 是一种规范装置,ECMAScript 实现使用它跟踪代码的运行时求值。在任意时刻,每个 agent 至多有一个实际正在执行代码的执行上下文。这被称为该 agentrunning execution context。本规范中对运行中执行上下文的所有引用,都指周围 agent 的运行中执行上下文。

execution context stack 用于跟踪执行上下文。运行中执行上下文始终是此栈的顶层元素。每当控制从与当前运行中执行上下文关联的可执行代码转移到不与该执行上下文关联的可执行代码时,就会创建一个新的执行上下文。新创建的执行上下文被压入栈中,并成为运行中执行上下文。

执行上下文包含跟踪其关联代码执行进度所需的任何实现特定状态。每个执行上下文至少具有 Table 21 中列出的状态组件。

Table 21: 所有执行上下文的状态组件
组件 目的
code evaluation state 执行、暂停和恢复与此执行上下文关联的代码求值所需的任何状态。
Function 如果此执行上下文正在求值一个函数对象的代码,则此组件的值就是该函数对象。如果该上下文正在求值 ScriptModule 的代码,则该值为 null
Realm 关联代码访问 ECMAScript 资源所来自的 Realm Record
ScriptOrModule 关联代码所源自的 Module RecordScript Record。如果没有起源脚本或模块,例如在 InitializeHostDefinedRealm 中创建的原始执行上下文的情形,则该值为 null

运行中执行上下文对代码的求值,可以在本规范中定义的各个点被暂停。一旦运行中执行上下文被暂停,另一个不同的执行上下文就可以成为运行中执行上下文并开始求值其代码。在之后的某个时间,被暂停的执行上下文可以再次成为运行中执行上下文,并在它此前被暂停的位置继续求值其代码。运行中执行上下文状态在执行上下文之间的转移通常以类似栈的后进先出方式发生。然而,某些 ECMAScript 特性需要运行中执行上下文的非 LIFO 转移。

运行中执行上下文的 Realm 组件的值也称为 当前 Realm Record。运行中执行上下文的 Function 组件的值也称为 活动函数对象

ECMAScript 代码执行上下文具有 Table 22 中列出的附加状态组件。

Table 22: ECMAScript 代码执行上下文的附加状态组件
组件 目的
LexicalEnvironment 标识用于解析此执行上下文内代码所产生的标识符引用的 Environment Record
VariableEnvironment 标识保存此执行上下文内由 VariableStatement 创建的绑定的 Environment Record
PrivateEnvironment 标识保存最近包含类中的 ClassElement 创建的 Private NamesPrivateEnvironment Record。如果没有包含类,则为 null

执行上下文的 LexicalEnvironment 和 VariableEnvironment 组件始终是 Environment Records

表示 Generators 求值的执行上下文具有 Table 23 中列出的附加状态组件。

Table 23: Generator 执行上下文的附加状态组件
组件 目的
Generator 此执行上下文正在求值的 Generator。

在大多数情况下,本规范中的算法只直接操纵运行中执行上下文(执行上下文栈的顶端)。因此,当术语 “LexicalEnvironment” 和 “VariableEnvironment” 未加限定地使用时,它们指的是运行中执行上下文的这些组件。

执行上下文纯粹是一种规范机制,并不需要对应于 ECMAScript 实现中的任何特定工件。ECMAScript 代码不可能直接访问或观察执行上下文。

9.4.1 GetActiveScriptOrModule ( )

The abstract operation GetActiveScriptOrModule takes no arguments and returns a Script Record, a Module Record, or null. 它用于基于运行中执行上下文来确定运行中的脚本或模块。 It performs the following steps when called:

  1. 如果执行上下文栈为空,则返回 null
  2. executionContext 为执行上下文栈中 ScriptOrModule 组件不是 null 的最顶层执行上下文。
  3. 如果不存在这样的执行上下文,则返回 null
  4. 返回 executionContext 的 ScriptOrModule。

9.4.2 ResolveBinding ( name [ , envRecord ] )

The abstract operation ResolveBinding takes argument name (a String) and optional argument envRecord (an Environment Record or undefined) and returns either a normal completion containing a Reference Record or a throw completion. 它用于确定 name 的绑定。envRecord 可用于显式提供要搜索该绑定的 Environment Record。 It performs the following steps when called:

  1. 如果 envRecord 不存在或 envRecordundefined,则
    1. envRecord 设置为运行中执行上下文的 LexicalEnvironment。
  2. 断言:envRecordEnvironment Record
  3. strictIsStrict(正在求值的句法产生式)。
  4. 返回 ? GetIdentifierReference(envRecord, name, strict)。
Note

ResolveBinding 的结果始终是 [[ReferencedName]] 字段为 nameReference Record

9.4.3 GetThisEnvironment ( )

The abstract operation GetThisEnvironment takes no arguments and returns an Environment Record. 它查找当前提供关键字 this 绑定的 Environment Record。 It performs the following steps when called:

  1. envRecord 为运行中执行上下文的 LexicalEnvironment。
  2. 重复,
    1. existsenvRecord.HasThisBinding()。
    2. 如果 existstrue,则返回 envRecord
    3. outerenvRecord.[[OuterEnv]]
    4. 断言:outer 不是 null
    5. envRecord 设置为 outer
Note

步骤 2 中的循环总会终止,因为环境列表总是以具有 this 绑定的全局环境结束。

9.4.4 ResolveThisBinding ( )

The abstract operation ResolveThisBinding takes no arguments and returns either a normal completion containing an ECMAScript language value or a throw completion. 它使用运行中执行上下文的 LexicalEnvironment 确定关键字 this 的绑定。 It performs the following steps when called:

  1. envRecordGetThisEnvironment()。
  2. 返回 ? envRecord.GetThisBinding()。

9.4.5 GetNewTarget ( )

The abstract operation GetNewTarget takes no arguments and returns an Object or undefined. 它使用运行中执行上下文的 LexicalEnvironment 确定 NewTarget 值。 It performs the following steps when called:

  1. envRecordGetThisEnvironment()。
  2. 断言:envRecord 具有 [[NewTarget]] 字段。
  3. 返回 envRecord.[[NewTarget]]

9.4.6 GetGlobalObject ( )

The abstract operation GetGlobalObject takes no arguments and returns an Object. 它返回当前运行中执行上下文使用的全局对象。 It performs the following steps when called:

  1. currentRealm当前 Realm Record
  2. 返回 currentRealm.[[GlobalObject]]

9.4.7 RunSuspendedContext ( context, completionRecord )

The abstract operation RunSuspendedContext takes arguments context (an execution context) and completionRecord (a Completion Record) and returns either a normal completion containing either an ECMAScript language value or unused, or an abrupt completion. 它恢复 context(将 completionRecord 作为恢复值发送给它),并等待结果。 It performs the following steps when called:

  1. callerContext 为运行中执行上下文。
  2. 暂停 callerContext
  3. context 压入执行上下文栈;context 现在是运行中执行上下文。
  4. 使用 completionRecord 作为导致其暂停的操作的结果,恢复 context 的暂停求值。令 result 为恢复的计算返回的 Completion Record
  5. 断言:当我们到达此步骤时,context 已经从执行上下文栈中移除,并且 callerContext 再次成为运行中执行上下文。
  6. 返回 Completion(result)。

9.4.8 RunCallerContext ( value )

The abstract operation RunCallerContext takes argument value (一个 ECMAScript 语言值empty) and returns 一个完成记录. 它恢复调用方上下文(将 value 作为恢复值发送给它),并等待结果(如果有)。 It performs the following steps when called:

  1. genContext 为运行中的执行上下文。
  2. 从执行上下文栈中移除 genContext,并将位于执行上下文栈顶部的执行上下文恢复为运行中的执行上下文。
  3. callerContext 为运行中的执行上下文。
  4. 恢复 callerContext,传入 NormalCompletion(value)。
  5. 注:上述步骤将控制转移给 callerContext 并暂停。使其解除暂停并让控制继续到此算法后续步骤的唯一方式,是再次恢复 genContext,而这可能永远不会发生。
  6. 断言:genContext 是运行中的执行上下文。
  7. resultgenContext 刚刚被恢复时所用的完成记录。
  8. 返回 Completion(result)。

9.5 作业和用于将作业入队的宿主操作

Job 是一个不带形参的 Abstract Closure,它在当前没有其他 ECMAScript 计算正在进行时发起一个 ECMAScript 计算。

Jobs 由 ECMAScript 宿主环境在特定 agent 中调度执行。本规范描述了宿主钩子 HostEnqueueGenericJobHostEnqueueFinalizationRegistryCleanupJobHostEnqueuePromiseJobHostEnqueueTimeoutJob,用于调度 jobs。本规范中的宿主钩子按对 jobs 调度施加的附加约束组织。宿主可以定义调度 jobs 的附加抽象操作。这样的操作接受一个 Job Abstract Closure 和一个 realmRealm Recordnull)作为形参。如果提供了 Realm Record,这些操作会调度该 job 在提供的 realm 中、在拥有该 realmagent 中,于将来的某个时间执行。如果改为为 realm 提供 null,则该 job 不会求值 ECMAScript 代码。它们的实现必须符合以下要求:

  • 在将来的某个时间点,当为该 job 调度的 agent 中没有运行中上下文且该 agent 的执行上下文栈为空时,实现必须:
    1. 执行任何宿主定义的准备步骤。
    2. 调用Job Abstract Closure
    3. 执行任何宿主定义的清理步骤,之后执行上下文栈必须为空。
  • 在任意时间点,一个 agent 中只能有一个 Job 正在主动经历求值。
  • 一旦某个 Job 的求值开始,它必须运行至完成,然后一个 agent 中的任何其他 Job 才能开始求值。
  • Abstract Closure 必须返回 normal completion,并实现其自身的错误处理。
Note 1
宿主环境不要求在调度方面统一对待 Jobs。例如,Web 浏览器和 Node.js 将处理 Promise 的 Jobs 视为比其他工作具有更高优先级;未来特性可能添加不按如此高优先级处理的 Jobs

在任意特定时间,如果以下所有条件均为真,则 scriptOrModuleScript RecordModule Recordnull)是活动脚本或模块

  • GetActiveScriptOrModule() 是 scriptOrModule
  • 如果 scriptOrModuleScript RecordModule Record,则令 executionContext 为执行上下文栈中 ScriptOrModule 组件为 scriptOrModule 的最顶层执行上下文。executionContextRealm 组件是 scriptOrModule.[[Realm]]

在任意特定时间,如果以下所有条件均为真,则某次执行已准备好求值 ECMAScript 代码

  • 执行上下文栈不为空。
  • 执行上下文栈最顶层执行上下文的 Realm 组件是 Realm Record
Note 2

宿主环境可以通过将执行上下文压入执行上下文栈来准备一次执行以求值代码。具体步骤是实现定义的

Realm 的具体选择取决于宿主环境。此初始执行上下文和 Realm 仅在调用任何回调函数之前使用。当调用与 Job 相关的回调函数(例如 Promise handler)时,该调用会压入其自己的执行上下文和 Realm

特定种类的 Jobs 具有附加的一致性要求。

9.5.1 JobCallback Records

JobCallback Record 是一个 Record 值,用于存储一个函数对象和一个宿主定义值。通过宿主入队的 Job 调用的函数对象可能具有额外的宿主定义上下文。为传播该状态,Job Abstract Closures 不应直接捕获并调用函数对象。相反,应使用 HostMakeJobCallbackHostCallJobCallback

Note

例如,WHATWG HTML 规范(https://html.spec.whatwg.org/)使用宿主定义值来为 Promise 回调传播 incumbent settings object。

JobCallback Records 具有 Table 24 中列出的字段。

Table 24: JobCallback Record 字段
字段名 含义
[[Callback]] a function object Job 被调用时要调用的函数。
[[HostDefined]] anything (default value is empty) 保留给宿主使用的字段。

9.5.2 HostMakeJobCallback ( callback )

The host-defined abstract operation HostMakeJobCallback takes argument callback (a function object) and returns a JobCallback Record.

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

HostMakeJobCallback 的默认实现在被调用时执行以下步骤:

  1. 返回 JobCallback Record { [[Callback]]: callback, [[HostDefined]]: empty }。

不是 Web 浏览器的 ECMAScript 宿主必须使用 HostMakeJobCallback 的默认实现。

Note

这在回调被传给负责最终调度并运行它的函数时调用。例如,promise.then(thenAction) 在调用 Promise.prototype.then 时对 thenAction 调用 MakeJobCallback,而不是在调度 reaction Job 时调用。

9.5.3 HostCallJobCallback ( jobCallback, thisValue, argList )

The host-defined abstract operation HostCallJobCallback takes arguments jobCallback (a JobCallback Record), thisValue (an ECMAScript language value), and argList (a List of ECMAScript language values) and returns either a normal completion containing an ECMAScript language value or a throw completion.

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

  • 它必须执行并返回 Call(jobCallback.[[Callback]], thisValue, argList) 的结果。
Note

此要求意味着宿主不能改变本规范中定义的函数对象[[Call]] 行为。

HostCallJobCallback 的默认实现在被调用时执行以下步骤:

  1. 断言:IsCallable(jobCallback.[[Callback]]) 是 true
  2. 返回 ? Call(jobCallback.[[Callback]], thisValue, argList)。

不是 Web 浏览器的 ECMAScript 宿主必须使用 HostCallJobCallback 的默认实现。

9.5.4 HostEnqueueGenericJob ( job, realm )

The host-defined abstract operation HostEnqueueGenericJob takes arguments job (a Job Abstract Closure) and realm (a Realm Record) and returns unused. 它在 realm realm 中、在由 realm.[[AgentSignifier]] 表示的 agent 中,调度 job 在将来某个时间执行。与此算法一起使用的 Abstract Closures 旨在无附加约束(例如优先级和顺序)地被调度。

HostEnqueueGenericJob 的实现必须符合 9.5 中的要求。

9.5.5 HostEnqueuePromiseJob ( job, realm )

The host-defined abstract operation HostEnqueuePromiseJob takes arguments job (a Job Abstract Closure) and realm (a Realm Record or null) and returns unused. 它调度 job 在将来某个时间执行。与此算法一起使用的 Abstract Closures 旨在与 Promises 的处理有关,或者以其他方式按与 Promise 处理操作相同的优先级调度。

HostEnqueuePromiseJob 的实现必须符合 9.5 中的要求,以及以下要求:

Note

NewPromiseResolveThenableJob 返回的 Jobsrealm 通常是对 then 函数对象调用 GetFunctionRealm 的结果。NewPromiseReactionJob 返回的 Jobsrealm 通常是在 handler 不是 undefined 时对该 handler 调用 GetFunctionRealm 的结果。如果 handler 是 undefined,则 realmnull。对于这两种 Jobs,当 GetFunctionRealm 异常完成(即在已撤销 Proxy 上调用)时,realmGetFunctionRealm 调用时的当前 Realm Record。当 realmnull 时,不会求值用户 ECMAScript 代码,也不会创建新的 ECMAScript 对象(例如 Error 对象)。例如,WHATWG HTML 规范(https://html.spec.whatwg.org/)使用 realm 来检查运行脚本的能力以及 entry 概念。

9.5.6 HostEnqueueTimeoutJob ( timeoutJob, realm, milliseconds )

The host-defined abstract operation HostEnqueueTimeoutJob takes arguments timeoutJob (a Job Abstract Closure), realm (a Realm Record), and milliseconds (a non-negative finite Number) and returns unused. 它在 realm realm 中、在由 realm.[[AgentSignifier]] 表示的 agent 中,调度 timeoutJob 至少在 milliseconds 毫秒之后执行。

HostEnqueueTimeoutJob 的实现必须符合 9.5 中的要求。

9.6 Agents

agent 包含一组 ECMAScript 执行上下文、一个执行上下文栈、一个运行中执行上下文、一个 Agent Record,以及一个 执行线程。除执行线程外,agent 的组成部分专属于该 agent

agent执行线程在该 agent 的执行上下文上执行算法步骤,并独立于其他 agents;但一个执行线程可以被多个 agents 用作执行线程,前提是共享该线程的 agents 中没有任何 agent 具有 [[CanBlock]] 字段为 trueAgent Record

Note 1

例如,某些 Web 浏览器会在一个浏览器窗口的多个不相关标签页之间共享单个执行线程

agent执行线程正在执行算法步骤时,该 agent 是这些步骤的周围 agent。这些步骤使用周围 agent 访问该 agent 内持有的规范级执行对象:运行中执行上下文、执行上下文栈,以及 Agent Record 的字段。

agent signifier 是一个全局唯一的不透明值,用于标识 Agent

Table 25: 代理记录字段
字段名称 含义
[[LittleEndian]] 一个布尔值 当算法 GetValueFromBufferSetValueInBuffer 需要 isLittleEndian 参数时,为该参数计算出的默认值。该选择由实现定义,并且应当是对该实现而言最高效的选项。
[[CanBlock]] 一个布尔值 确定该代理是否可以阻塞。
[[Signifier]] 一个代理标识符 在其代理集群中唯一标识该代理。
[[IsLockFree1]] 一个布尔值 如果对一字节值的原子操作是无锁的,则为 true;否则为 false
[[IsLockFree2]] 一个布尔值 如果对两字节值的原子操作是无锁的,则为 true;否则为 false
[[IsLockFree8]] 一个布尔值 如果对八字节值的原子操作是无锁的,则为 true;否则为 false
[[CandidateExecution]] 一个候选执行记录 内存模型
[[KeptAlive]] 一个由对象或 Symbol 组成的列表 最初是一个新的空列表,表示要保持活动直到当前 Job 结束的对象和/或 Symbol 的列表
[[ModuleAsyncEvaluationCount]] 一个整数 最初为 0,用于为异步模块或具有异步依赖项的模块的 [[AsyncEvaluationOrder]] 字段分配唯一的递增值。
[[GlobalSymbolRegistry]] 一个 GlobalSymbolRegistry 记录列表 最初是一个新的空列表,表示由 Symbol.for 产生的 Symbol 值的列表。

[[LittleEndian]][[Signifier]][[IsLockFree1]][[IsLockFree2]][[IsLockFree8]] 的值不能改变。

[[GlobalSymbolRegistry]] 列表只能追加,且绝不会被重新赋值。

Note 2

[[IsLockFree1]][[IsLockFree2]][[IsLockFree8]] 的值不一定由硬件决定,也可以反映会随时间以及 ECMAScript 实现而变化的实现选择。

没有 [[IsLockFree4]] 字段:4 字节原子操作始终是免锁的。

在实践中,如果某个原子操作使用任何类型的锁来实现,则该操作不是免锁的。免锁并不意味着无等待:完成一个免锁原子操作可能需要多少机器步骤没有上界。

大小为 n 的原子访问是免锁的,并不意味着大小为 n 的非原子访问的(感知)原子性有任何保证;具体而言,非原子访问仍可能作为若干独立内存访问的序列执行。详情参见 ReadSharedMemoryWriteSharedMemory

Note 3

agent 是一种规范机制,并不需要对应于 ECMAScript 实现中的任何特定工件。

9.6.1 AgentSignifier ( )

The abstract operation AgentSignifier takes no arguments and returns an agent signifier. It performs the following steps when called:

  1. agentRecord周围 agentAgent Record
  2. 返回 agentRecord.[[Signifier]]

9.6.2 AgentCanSuspend ( )

The abstract operation AgentCanSuspend takes no arguments and returns a Boolean. It performs the following steps when called:

  1. agentRecord周围 agentAgent Record
  2. 返回 agentRecord.[[CanBlock]]
Note

在某些环境中,允许给定 agent 暂停可能并不合理。例如,在 Web 浏览器环境中,禁止挂起 document 的主事件处理线程可能是合理的,同时仍允许 workers 的事件处理线程暂停。

9.6.3 IncrementModuleAsyncEvaluationCount ( )

The abstract operation IncrementModuleAsyncEvaluationCount takes no arguments and returns a non-negative integer. It performs the following steps when called:

  1. agentRecord周围 agentAgent Record
  2. countagentRecord.[[ModuleAsyncEvaluationCount]]
  3. agentRecord.[[ModuleAsyncEvaluationCount]] 设置为 count + 1。
  4. 返回 count
Note

此值仅用于跟踪待处理模块之间的相对求值顺序。只要没有待处理模块,实现就可以不可观察地将 [[ModuleAsyncEvaluationCount]] 重置为 0。

9.7 Agent Clusters

agent cluster 是可以通过对共享内存进行操作来通信的最大 agent 集合。

Note 1

不同 agents 中的程序可以通过未指定的方式共享内存。至少,SharedArrayBuffers 的后备内存可以在 cluster 中的 agents 之间共享。

可能存在可以通过消息传递通信但不能共享内存的 agents;它们永远不会位于同一个 agent cluster 中。

每个 agent 都恰好属于一个 agent cluster。

Note 2

cluster 中的 agents 不需要在某个特定时间点全部存活。如果 agent A 创建另一个 agent B,之后 A 终止并且 B 创建 agent C,只要 A 能够与 B 共享某些内存,且 B 能够与 C 共享某些内存,则这三个 agents 位于同一个 cluster 中。

cluster 内的所有 agents 在各自 Agent Records 中的 [[LittleEndian]] 字段必须具有相同的值。

Note 3

如果一个 agent cluster 内不同 agents[[LittleEndian]] 值不同,则难以将共享内存用于多字节数据。

cluster 内的所有 agents 在各自 Agent Records 中的 [[IsLockFree1]] 字段必须具有相同值;[[IsLockFree2]][[IsLockFree8]] 字段同理。

cluster 内的所有 agents 在各自 Agent Records 中的 [[Signifier]] 字段必须具有不同值。

嵌入环境可以在 agent 不知情或不配合的情况下停用(停止前向进展)或激活(恢复前向进展)该 agent。如果嵌入环境这样做,则不得让 cluster 中某些 agents 保持活动,而让同一 cluster 中其他 agents 被无限期停用。

Note 4

前述限制的目的,是避免 agent 因另一个 agent 被停用而死锁或饥饿的情况。例如,如果允许一个生命周期独立于任何窗口中文档的 HTML shared worker 与这样一个独立文档的 dedicated worker 共享内存,而该文档及其 dedicated worker 在该 dedicated worker 持有锁时被停用(例如,该文档被推入其窗口的历史记录中),随后 shared worker 试图获取该锁,则 shared worker 将被阻塞,直到 dedicated worker 再次被激活,如果它还有机会被激活的话。与此同时,其他窗口中试图访问该 shared worker 的其他 workers 将会饥饿。

该限制的含义是,在嵌入环境中,不属于同一暂停/唤醒集体的 agents 之间将无法共享内存。

嵌入环境可以在 agent cluster 的其他 agents 事先不知情或不配合的情况下终止某个 agent。如果某个 agent 的终止不是由其自身或 cluster 中另一个 agent 的程序性动作导致,而是由 cluster 外部力量导致,则嵌入环境必须选择两种策略之一:要么终止 cluster 中的所有 agents,要么提供可靠的 API,使 cluster 中的 agents 能够协调,从而让 cluster 中至少一个剩余成员能够检测到该终止,并且终止数据中包含足够信息来标识被终止的 agent

Note 5

这类终止的例子包括:操作系统或用户终止运行在独立进程中的 agents;当按 agent 资源核算表明某个 agent 失控时,嵌入环境自身终止与其他 agents 运行在进程内的该 agent

以下每个规范值,以及从它们传递可达的值,都恰好属于一个 agent cluster。

在一个 cluster 中任何 agent 对任何 ECMAScript 代码进行任何求值之前,cluster 中所有 agentsAgent Record[[CandidateExecution]] 字段都被设置为初始 candidate execution。初始 candidate execution 是一个空 candidate execution,其 [[EventsRecords]] 字段是一个 List,其中对每个 agent 包含一个 Agent Events Record,该记录的 [[AgentSignifier]] 字段为该 agentagent signifier,且其 [[EventList]][[AgentSynchronizesWith]] 字段为空 Lists

Note 6

一个 agent cluster 中的所有 agents 在其 Agent Record[[CandidateExecution]] 字段中共享同一个 candidate executioncandidate execution内存模型使用的一种规范机制。

Note 7

agent cluster 是一种规范机制,并不需要对应于 ECMAScript 实现中的任何特定工件。

9.8 前向进展

一个 agent 取得前向进展,是指它按照本规范执行一个求值步骤。

agent 的运行中执行上下文同步且无限期地等待外部事件时,该 agent 变为阻塞。只有 Agent Record[[CanBlock]] 字段为 trueagents 才能以这种意义变为阻塞。未阻塞agent 是指未被阻塞的 agent

实现必须确保:

  • 每个具有专用执行线程的未阻塞 agent 最终取得前向进展
  • 在共享执行线程的一组 agents 中,某个 agent 最终取得前向进展
  • 一个 agent 不会导致另一个 agent 变为阻塞,除非通过提供阻塞的显式 API。
Note

这与内存模型中的活性保证一起,确保所有 seq-cst 写入最终都变得对所有 agents 可观察。

9.9 WeakRef 和 FinalizationRegistry 目标的处理模型

9.9.1 目标

本规范不保证任何对象或符号会被垃圾回收。不存活的对象或符号可能在很长时间之后被释放,或者永远不会被释放。因此,本规范在描述由垃圾回收触发的行为时使用术语“may”。

WeakRefsFinalizationRegistrys 的语义基于两个发生在特定时间点的操作:

这两个动作(ClearKeptObjectsCleanupFinalizationRegistry)都不得中断同步 ECMAScript 执行。由于宿主可能组装更长的同步 ECMAScript 执行运行,本规范将 ClearKeptObjectsCleanupFinalizationRegistry 的调度推迟给宿主环境

某些 ECMAScript 实现包含在后台运行的垃圾回收器实现,包括在 ECMAScript 空闲时运行。允许宿主环境调度 CleanupFinalizationRegistry,使其可以恢复 ECMAScript 执行来运行 finalizer 工作,这可能释放 held values,从而减少总体内存使用。

9.9.2 活性

对于某组对象和/或符号 objSet,相对于 objSet 的一次假想的 WeakRef-oblivious 执行,是这样一种执行:WeakRef抽象操作 WeakRefDeref 在该 WeakRef 的所指对象是 objSet 的元素时始终返回 undefined

Note 1
WeakRef-obliviousness 与 liveness 一起捕获两个概念。其一,WeakRef 本身不会保持其所指对象存活。其二,liveness 中的循环并不意味着某个值是存活的。具体而言,如果确定 v 的 liveness 依赖于确定某个 WeakRef 所指对象 r 的 liveness,则 r 的 liveness 不能假定 v 的 liveness,因为这将构成循环推理。
Note 2
WeakRef-obliviousness 定义在对象或符号集合上,而不是单个值上,以说明循环。如果它定义在单个值上,则循环中的 WeakRef 所指对象即使其身份仅通过该循环中的其他 WeakRef 所指对象被观察到,也会被认为是存活的。
Note 3
通俗地说,如果包含某个个体对象或符号的每个集合都是 live,我们就说该个体对象或符号是 live。

在求值期间的任何时刻,如果满足以下任一条件,则一组对象和/或符号 objSet 被认为是 live

  • objSet 中的任何元素包含在任何 agent[[KeptAlive]] List 中。
  • 存在一次相对于 objSet 的有效未来假想 WeakRef-oblivious 执行,该执行观察到 objSet 中任何值的身份。
Note 4
上述第二个条件旨在捕获这样的直觉:如果某个值的身份可通过非 WeakRef 手段观察到,则该值是 live。值的身份可以通过观察严格相等比较,或观察该值被用作 Map 中的键来观察。
Note 5

对象或符号出现在某个字段、内部槽或属性中,并不意味着该值是 live。例如,如果所讨论的值永远不会被传回程序,则它不能被观察到。

WeakMap 中的键、WeakSet 的成员,以及 FinalizationRegistry Cell record 的 [[WeakRefTarget]][[UnregisterToken]] 字段,都属于这种情况。

上述定义意味着,如果 WeakMap 中的某个键不是 live,则其对应值也不一定是 live。

Note 6
Liveness 是保证引擎不得清空哪些 WeakRefs 的下界。这里定义的 liveness 是不可判定的。在实践中,引擎使用诸如可达性之类的保守近似。预计会有显著的实现余地。

9.9.3 执行

在任意时间,如果一组对象和/或符号 objSet 不是 live,则 ECMAScript 实现可以原子地执行以下步骤:

  1. objSet 的每个元素 value,执行:
    1. 对每个 WeakRef ref,如果 ref.[[WeakRefTarget]]value,则执行:
      1. ref.[[WeakRefTarget]] 设置为 empty
    2. 对每个 FinalizationRegistry finalizationRegistry,如果 finalizationRegistry.[[Cells]] 包含一个 Record cell,使得 cell.[[WeakRefTarget]]value,则执行:
      1. cell.[[WeakRefTarget]] 设置为 empty
      2. enqueueCleanup 为一个实现定义的选择,其值为 truefalse
      3. 如果 enqueueCleanuptrue,则执行 HostEnqueueFinalizationRegistryCleanupJob(finalizationRegistry)。
    3. 对每个 WeakMap map,如果 map.[[WeakMapData]] 包含一个 Record entry,使得 entry.[[Key]]value,则执行:
      1. entry.[[Key]] 设置为 empty
      2. entry.[[Value]] 设置为 empty
    4. 对每个 WeakSet set,如果 set.[[WeakSetData]] 包含 value,则执行:
      1. set.[[WeakSetData]] 中值为 value 的元素替换为一个值为 empty 的元素。
Note 1

本条款与 liveness 的定义一起,规定了实现可以对 WeakRefs 应用的优化。

可以访问对象而不观察其身份。允许对身份未被观察的非逃逸对象的属性进行诸如死变量消除和标量替换之类的优化。因此,这些优化被允许以可观察方式清空指向这类对象的 WeakRefs

另一方面,如果某个对象的身份是可观察的,并且该对象位于 WeakRef[[WeakRefTarget]] 内部槽中,则禁止诸如 rematerialization 之类会以可观察方式清空 WeakRef 的优化。

由于调用 HostEnqueueFinalizationRegistryCleanupJob 是可选的,FinalizationRegistry 中已注册的对象不一定使该 FinalizationRegistry 保持 live。实现可以出于任何原因省略 FinalizationRegistry 回调,例如,如果 FinalizationRegistry 本身变为 dead,或者应用程序正在关闭。

Note 2

实现没有义务为最大非 live 对象或符号集合清空 WeakRefs

如果实现选择一个非 live 集合 objSet 来清空 WeakRefs,则此定义要求它同时清空 objSet 中所有值的 WeakRefs。换言之,实现如果清空指向值 vWeakRef,而不清空其他 WeakRefs(若不清空则可能导致一次观察到 v 值的执行),则不符合规范。

9.9.4 宿主钩子

9.9.4.1 HostEnqueueFinalizationRegistryCleanupJob ( finalizationRegistry )

The host-defined abstract operation HostEnqueueFinalizationRegistryCleanupJob takes argument finalizationRegistry (a FinalizationRegistry) and returns unused.

cleanupJob 为一个不带形参的新 Job Abstract Closure,它捕获 finalizationRegistry 并在被调用时执行以下步骤:

  1. cleanupResultCompletion(CleanupFinalizationRegistry(finalizationRegistry))。
  2. 如果 cleanupResult 是 abrupt completion,则执行任何宿主定义的步骤来报告错误。
  3. 返回 unused

HostEnqueueFinalizationRegistryCleanupJob 的实现会调度 cleanupJob 在将来某个时间执行,如果可能的话。它还必须符合 9.5 中的要求。

9.10 ClearKeptObjects ( )

The abstract operation ClearKeptObjects takes no arguments and returns unused. ECMAScript 实现应当在一段同步 ECMAScript 执行序列完成时调用 ClearKeptObjects。 It performs the following steps when called:

  1. agentRecord周围 agentAgent Record
  2. agentRecord.[[KeptAlive]] 设置为一个新的空 List
  3. 返回 unused

9.11 AddToKeptObjects ( value )

The abstract operation AddToKeptObjects takes argument value (an Object or a Symbol) and returns unused. It performs the following steps when called:

  1. agentRecord周围 agentAgent Record
  2. value 追加到 agentRecord.[[KeptAlive]]
  3. 返回 unused
Note
抽象操作 AddToKeptObjects 以目标对象或符号调用时,它会将该目标添加到一个列表中,该列表会强引用该目标,直到调用 ClearKeptObjects

9.12 CleanupFinalizationRegistry ( finalizationRegistry )

The abstract operation CleanupFinalizationRegistry takes argument finalizationRegistry (a FinalizationRegistry) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

  1. 断言:finalizationRegistry 具有 [[Cells]][[CleanupCallback]] 内部槽。
  2. callbackfinalizationRegistry.[[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 )

The abstract operation CanBeHeldWeakly takes argument arg (an ECMAScript language value) and returns a Boolean. 当且仅当 arg 适合用作弱引用时,它返回 true。只有适合用作弱引用的值,才可以作为 WeakMap 的键、WeakSet 的元素、WeakRef 的目标,或 FinalizationRegistry 的目标之一。 It performs the following steps when called:

  1. 如果 arg 是 Object,则返回 true
  2. 如果 arg 是 Symbol 且 KeyForSymbol(arg) 是 undefined,则返回 true
  3. 返回 false
Note

没有语言身份的语言值可以在没有先前引用的情况下显现,因此不适合用作弱引用。由 Symbol.for 产生的 Symbol 值不同于其他 Symbol 值,它没有语言身份,因此不适合用作弱引用。众所周知符号可能永远不会被回收,但仍被视为适合用作弱引用,因为它们数量有限,因此可由各种实现方法管理。然而,在 live WeakMap 中与众所周知符号关联的任何值都不太可能被回收,并可能在实现中“泄漏”内存资源。

10 普通对象与异质对象行为

10.1 普通对象内部方法与内部槽

所有普通对象都有一个称为 [[Prototype]] 的内部槽。此内部槽的值要么是 null,要么是一个对象,并用于实现继承。假设名为 propertyKey 的属性在普通对象 obj 中缺失,但存在于其 [[Prototype]] 对象上。如果 propertyKey 引用的是 [[Prototype]] 对象上的数据属性,则 obj 会为 get 访问继承它,使其表现得仿佛 propertyKeyobj 的属性。如果 propertyKey 引用的是 [[Prototype]] 对象上的可写数据属性,则对 objpropertyKey 的 set 访问会在 obj 上创建一个名为 propertyKey 的新数据属性。如果 propertyKey 引用的是 [[Prototype]] 对象上的不可写数据属性,则对 objpropertyKey 的 set 访问会失败。如果 propertyKey 引用的是 [[Prototype]] 对象上的访问器属性,则该访问器会被 obj 继承,用于 get 访问和 set 访问。

每个普通对象都有一个 Boolean 值的 [[Extensible]] 内部槽,用于满足 6.1.7.3 中指定的与可扩展性相关的内部方法不变量。也就是说,一旦对象的 [[Extensible]] 内部槽的值被设置为 false,就不再可能向该对象添加属性、修改该对象的 [[Prototype]] 内部槽的值,或随后将 [[Extensible]] 的值改回 true

在以下算法描述中,假设 obj普通对象propertyKey属性键值,value 是任意 ECMAScript 语言值,且 propertyDesc 是一个 Property Descriptor Record

每个普通对象内部方法都会委托给一个名称类似的抽象操作。如果这样的抽象操作依赖另一个内部方法,则会在 obj 上调用该内部方法,而不是直接调用名称类似的抽象操作。这些语义确保当普通对象内部方法应用于异质对象时,会调用这些异质对象被覆写的内部方法。

10.1.1 [[GetPrototypeOf]] ( )

The [[GetPrototypeOf]] internal method of 一个普通对象 obj takes no arguments and returns a normal completion containing either an Object or null. It performs the following steps when called:

  1. 返回 OrdinaryGetPrototypeOf(obj)。

10.1.1.1 OrdinaryGetPrototypeOf ( obj )

The abstract operation OrdinaryGetPrototypeOf takes argument obj (an Object) and returns an Object or null. It performs the following steps when called:

  1. 返回 obj.[[Prototype]]

10.1.2 [[SetPrototypeOf]] ( proto )

The [[SetPrototypeOf]] internal method of 一个普通对象 obj takes argument proto (an Object or null) and returns a normal completion containing a Boolean. It performs the following steps when called:

  1. 返回 OrdinarySetPrototypeOf(obj, proto)。

10.1.2.1 OrdinarySetPrototypeOf ( obj, proto )

The abstract operation OrdinarySetPrototypeOf takes arguments obj (an Object) and proto (an Object or null) and returns a Boolean. It performs the following steps when called:

  1. currentobj.[[Prototype]]
  2. 如果 SameValue(proto, current) 是 true,则返回 true
  3. extensibleobj.[[Extensible]]
  4. 如果 extensiblefalse,则返回 false
  5. cursorproto
  6. donefalse
  7. 重复,当 donefalse 时,
    1. 如果 cursornull,则
      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
Note

步骤 7 中的循环保证,在任何只包含使用 [[GetPrototypeOf]][[SetPrototypeOf]] 普通对象定义的对象的原型链中,不会存在循环。

10.1.3 [[IsExtensible]] ( )

The [[IsExtensible]] internal method of 一个普通对象 obj takes no arguments and returns a normal completion containing a Boolean. It performs the following steps when called:

  1. 返回 OrdinaryIsExtensible(obj)。

10.1.3.1 OrdinaryIsExtensible ( obj )

The abstract operation OrdinaryIsExtensible takes argument obj (an Object) and returns a Boolean. It performs the following steps when called:

  1. 返回 obj.[[Extensible]]

10.1.4 [[PreventExtensions]] ( )

The [[PreventExtensions]] internal method of 一个普通对象 obj takes no arguments and returns a normal completion containing true. It performs the following steps when called:

  1. 返回 OrdinaryPreventExtensions(obj)。

10.1.4.1 OrdinaryPreventExtensions ( obj )

The abstract operation OrdinaryPreventExtensions takes argument obj (an Object) and returns true. It performs the following steps when called:

  1. obj.[[Extensible]] 设置为 false
  2. 返回 true

10.1.5 [[GetOwnProperty]] ( propertyKey )

The [[GetOwnProperty]] internal method of 一个普通对象 obj takes argument propertyKey (a property key) and returns a normal completion containing either a Property Descriptor or undefined. It performs the following steps when called:

  1. 返回 OrdinaryGetOwnProperty(obj, propertyKey)。

10.1.5.1 OrdinaryGetOwnProperty ( obj, propertyKey )

The abstract operation OrdinaryGetOwnProperty takes arguments obj (an Object) and propertyKey (a property key) and returns a Property Descriptor or undefined. It performs the following steps when called:

  1. 如果 obj 没有键为 propertyKey 的自有属性,则返回 undefined
  2. propertyDesc 为一个新创建且不含字段的 Property Descriptor
  3. ownPropertyobj 中键为 propertyKey 的自有属性。
  4. 如果 ownProperty数据属性,则
    1. propertyDesc.[[Value]] 设置为 ownProperty[[Value]] 特性的值。
    2. propertyDesc.[[Writable]] 设置为 ownProperty[[Writable]] 特性的值。
  5. 否则,
    1. 断言:ownProperty访问器属性
    2. propertyDesc.[[Get]] 设置为 ownProperty[[Get]] 特性的值。
    3. propertyDesc.[[Set]] 设置为 ownProperty[[Set]] 特性的值。
  6. propertyDesc.[[Enumerable]] 设置为 ownProperty[[Enumerable]] 特性的值。
  7. propertyDesc.[[Configurable]] 设置为 ownProperty[[Configurable]] 特性的值。
  8. 返回 propertyDesc

10.1.6 [[DefineOwnProperty]] ( propertyKey, propertyDesc )

The [[DefineOwnProperty]] internal method of 一个普通对象 obj takes arguments propertyKey (a property key) and propertyDesc (a Property Descriptor) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

  1. 返回 ? OrdinaryDefineOwnProperty(obj, propertyKey, propertyDesc)。

10.1.6.1 OrdinaryDefineOwnProperty ( obj, propertyKey, propertyDesc )

The abstract operation OrdinaryDefineOwnProperty takes arguments obj (an Object), propertyKey (a property key), and propertyDesc (a Property Descriptor) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

  1. current 为 ? obj.[[GetOwnProperty]](propertyKey)
  2. extensible 为 ? IsExtensible(obj)。
  3. 返回 ValidateAndApplyPropertyDescriptor(obj, propertyKey, extensible, propertyDesc, current)。

10.1.6.2 IsCompatiblePropertyDescriptor ( extensible, propertyDesc, current )

The abstract operation IsCompatiblePropertyDescriptor takes arguments extensible (a Boolean), propertyDesc (a Property Descriptor), and current (a Property Descriptor or undefined) and returns a Boolean. It performs the following steps when called:

  1. 返回 ValidateAndApplyPropertyDescriptor(undefined, "", extensible, propertyDesc, current)。

10.1.6.3 ValidateAndApplyPropertyDescriptor ( obj, propertyKey, extensible, propertyDesc, current )

The abstract operation ValidateAndApplyPropertyDescriptor takes arguments obj (an Object or undefined), propertyKey (a property key), extensible (a Boolean), propertyDesc (a Property Descriptor), and current (a Property Descriptor or undefined) and returns a Boolean. 当且仅当 propertyDesc 可在维护不变量的同时,作为具有指定 extensibility 和当前属性 current 的对象的属性被应用时,它返回 true。当这种应用是可能的且 obj 不是 undefined 时,会对名为 propertyKey 的属性执行该应用(必要时创建该属性)。 It performs the following steps when called:

  1. 断言:propertyKey属性键
  2. 如果 currentundefined,则
    1. 如果 extensiblefalse,则返回 false
    2. 如果 objundefined,则返回 true
    3. 如果 IsAccessorDescriptor(propertyDesc) 是 true,则
      1. 创建对象 obj 的一个名为 propertyKey 的自有访问器属性,其 [[Get]][[Set]][[Enumerable]][[Configurable]] 特性被设置为 propertyDesc 中对应字段的值(如果 propertyDesc 具有该字段),否则设置为该特性的默认值
    4. 否则,
      1. 创建对象 obj 的一个名为 propertyKey 的自有数据属性,其 [[Value]][[Writable]][[Enumerable]][[Configurable]] 特性被设置为 propertyDesc 中对应字段的值(如果 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) 是 falseIsAccessorDescriptor(propertyDesc) 不是 IsAccessorDescriptor(current),则返回 false
    4. 如果 IsAccessorDescriptor(current) 是 true,则
      1. 如果 propertyDesc 具有 [[Get]] 字段且 SameValue(propertyDesc.[[Get]], current.[[Get]]) 是 false,则返回 false
      2. 如果 propertyDesc 具有 [[Set]] 字段且 SameValue(propertyDesc.[[Set]], current.[[Set]]) 是 false,则返回 false
    5. 否则如果 current.[[Writable]]false,则
      1. 如果 propertyDesc 具有 [[Writable]] 字段且 propertyDesc.[[Writable]]true,则返回 false
      2. 注:SameValueNaN 值返回 true,而这些值可能通过其他方式区分。在这里返回可确保 obj 的任何现有属性保持未修改。
      3. 如果 propertyDesc 具有 [[Value]] 字段,则返回 SameValue(propertyDesc.[[Value]], current.[[Value]])。
  6. 如果 obj 不是 undefined,则
    1. 如果 IsDataDescriptor(current) 是 trueIsAccessorDescriptor(propertyDesc) 是 true,则
      1. 如果 propertyDesc 具有 [[Configurable]] 字段,则令 configurablepropertyDesc.[[Configurable]];否则令 configurablecurrent.[[Configurable]]
      2. 如果 propertyDesc 具有 [[Enumerable]] 字段,则令 enumerablepropertyDesc.[[Enumerable]];否则令 enumerablecurrent.[[Enumerable]]
      3. 将对象 obj 的名为 propertyKey 的属性替换为一个访问器属性,其 [[Configurable]][[Enumerable]] 特性分别被设置为 configurableenumerable,且其 [[Get]][[Set]] 特性被设置为 propertyDesc 中对应字段的值(如果 propertyDesc 具有该字段),否则设置为该特性的默认值
    2. 否则如果 IsAccessorDescriptor(current) 是 trueIsDataDescriptor(propertyDesc) 是 true,则
      1. 如果 propertyDesc 具有 [[Configurable]] 字段,则令 configurablepropertyDesc.[[Configurable]];否则令 configurablecurrent.[[Configurable]]
      2. 如果 propertyDesc 具有 [[Enumerable]] 字段,则令 enumerablepropertyDesc.[[Enumerable]];否则令 enumerablecurrent.[[Enumerable]]
      3. 将对象 obj 的名为 propertyKey 的属性替换为一个数据属性,其 [[Configurable]][[Enumerable]] 特性分别被设置为 configurableenumerable,且其 [[Value]][[Writable]] 特性被设置为 propertyDesc 中对应字段的值(如果 propertyDesc 具有该字段),否则设置为该特性的默认值
    3. 否则,
      1. propertyDesc 的每个字段名 fieldName,将对象 obj 的名为 propertyKey 的属性中名为 fieldName 的特性设置为 propertyDescfieldName 字段的值。
  7. 返回 true

10.1.7 [[HasProperty]] ( propertyKey )

The [[HasProperty]] internal method of 一个普通对象 obj takes argument propertyKey (a property key) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

  1. 返回 ? OrdinaryHasProperty(obj, propertyKey)。

10.1.7.1 OrdinaryHasProperty ( obj, propertyKey )

The abstract operation OrdinaryHasProperty takes arguments obj (an Object) and propertyKey (a property key) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

  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 )

The [[Get]] internal method of 一个普通对象 obj takes arguments propertyKey (a property key) and receiver (an ECMAScript language value) and returns either a normal completion containing an ECMAScript language value or a throw completion. It performs the following steps when called:

  1. 返回 ? OrdinaryGet(obj, propertyKey, receiver)。

10.1.8.1 OrdinaryGet ( obj, propertyKey, receiver )

The abstract operation OrdinaryGet takes arguments obj (an Object), propertyKey (a property key), and receiver (an ECMAScript language value) and returns either a normal completion containing an ECMAScript language value or a throw completion. It performs the following steps when called:

  1. propertyDesc 为 ? obj.[[GetOwnProperty]](propertyKey)
  2. 如果 propertyDescundefined,则
    1. parent 为 ? obj.[[GetPrototypeOf]]()
    2. 如果 parentnull,则返回 undefined
    3. 返回 ? parent.[[Get]](propertyKey, receiver)
  3. 如果 IsDataDescriptor(propertyDesc) 是 true,则返回 propertyDesc.[[Value]]
  4. 断言:IsAccessorDescriptor(propertyDesc) 是 true
  5. getterpropertyDesc.[[Get]]
  6. 如果 getterundefined,则返回 undefined
  7. 返回 ? Call(getter, receiver)。

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

The [[Set]] internal method of 一个普通对象 obj takes arguments propertyKey (a property key), value (an ECMAScript language value), and receiver (an ECMAScript language value) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

  1. 返回 ? OrdinarySet(obj, propertyKey, value, receiver)。

10.1.9.1 OrdinarySet ( obj, propertyKey, value, receiver )

The abstract operation OrdinarySet takes arguments obj (an Object), propertyKey (a property key), value (an ECMAScript language value), and receiver (an ECMAScript language value) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

  1. ownDesc 为 ? obj.[[GetOwnProperty]](propertyKey)
  2. 返回 ? OrdinarySetWithOwnDescriptor(obj, propertyKey, value, receiver, ownDesc)。

10.1.9.2 OrdinarySetWithOwnDescriptor ( obj, propertyKey, value, receiver, ownDesc )

The abstract operation OrdinarySetWithOwnDescriptor takes arguments obj (an Object), propertyKey (a property key), value (an ECMAScript language value), receiver (an ECMAScript language value), and ownDesc (a Property Descriptor or undefined) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

  1. 如果 ownDescundefined,则
    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. 如果 existingDescundefined,则
      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. setterownDesc.[[Set]]
  5. 如果 setterundefined,则返回 false
  6. 执行 ? Call(setter, receiver, « value »)。
  7. 返回 true

10.1.10 [[Delete]] ( propertyKey )

The [[Delete]] internal method of 一个普通对象 obj takes argument propertyKey (a property key) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

  1. 返回 ? OrdinaryDelete(obj, propertyKey)。

10.1.10.1 OrdinaryDelete ( obj, propertyKey )

The abstract operation OrdinaryDelete takes arguments obj (an Object) and propertyKey (a property key) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

  1. propertyDesc 为 ? obj.[[GetOwnProperty]](propertyKey)
  2. 如果 propertyDescundefined,则返回 true
  3. 如果 propertyDesc.[[Configurable]]true,则
    1. obj 中移除名称为 propertyKey 的自有属性。
    2. 返回 true
  4. 返回 false

10.1.11 [[OwnPropertyKeys]] ( )

The [[OwnPropertyKeys]] internal method of 一个普通对象 obj takes no arguments and returns a normal completion containing a List of property keys. It performs the following steps when called:

  1. 返回 OrdinaryOwnPropertyKeys(obj)。

10.1.11.1 OrdinaryOwnPropertyKeys ( obj )

The abstract operation OrdinaryOwnPropertyKeys takes argument obj (an Object) and returns a List of property keys. It performs the following steps when called:

  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 ] )

The abstract operation OrdinaryObjectCreate takes argument proto (an Object or null) and optional argument additionalInternalSlotsList (a List of names of internal slots) and returns an Object. 它用于指定新普通对象的运行时创建。additionalInternalSlotsList 包含[[Prototype]][[Extensible]] 之外,必须作为对象一部分定义的附加内部槽名称。如果未提供 additionalInternalSlotsList,则使用一个新的空 List。 It performs the following steps when called:

  1. internalSlotsList 为 « [[Prototype]], [[Extensible]] »。
  2. 如果 additionalInternalSlotsList 存在,则将 internalSlotsList 设置为 internalSlotsListadditionalInternalSlotsList列表连接
  3. objMakeBasicObject(internalSlotsList)。
  4. obj.[[Prototype]] 设置为 proto
  5. 返回 obj
Note

尽管 OrdinaryObjectCreate 几乎只是调用 MakeBasicObject,但它的使用传达了创建普通对象而非异质对象的意图。因此,在本规范中,任何随后会以使结果变为非普通对象的方式修改对象内部方法的算法,都不会调用它。创建异质对象的操作会直接调用 MakeBasicObject

10.1.13 OrdinaryCreateFromConstructor ( ctor, intrinsicDefaultProto [ , internalSlotsList ] )

The abstract operation OrdinaryCreateFromConstructor takes arguments ctor (a function object) and intrinsicDefaultProto (a String) and optional argument internalSlotsList (a List of names of internal slots) and returns either a normal completion containing an Object or a throw completion. 它创建一个普通对象,其 [[Prototype]] 值从构造函数"prototype" 属性取得(如果存在)。否则,使用由 intrinsicDefaultProto 命名的固有对象作为 [[Prototype]]internalSlotsList 包含必须作为对象一部分定义的附加内部槽名称。如果未提供 internalSlotsList,则使用一个新的空 List。 It performs the following steps when called:

  1. 断言:intrinsicDefaultProto 是本规范中某个固有对象的名称。对应对象必须是预期用作对象 [[Prototype]] 值的固有对象。
  2. proto 为 ? GetPrototypeFromConstructor(ctor, intrinsicDefaultProto)。
  3. 如果 internalSlotsList 存在,则令 slotsinternalSlotsList
  4. 否则,令 slots 为一个新的空 List
  5. 返回 OrdinaryObjectCreate(proto, slots)。

10.1.14 GetPrototypeFromConstructor ( ctor, intrinsicDefaultProto )

The abstract operation GetPrototypeFromConstructor takes arguments ctor (a function object) and intrinsicDefaultProto (a String) and returns either a normal completion containing an Object or a throw completion. 它确定应当用于创建与特定构造函数对应的对象的 [[Prototype]] 值。该值从构造函数"prototype" 属性取得(如果存在)。否则,使用由 intrinsicDefaultProto 命名的固有对象作为 [[Prototype]]。 It performs the following steps when called:

  1. 断言:intrinsicDefaultProto 是本规范中某个固有对象的名称。对应对象必须是预期用作对象 [[Prototype]] 值的固有对象。
  2. proto 为 ? Get(ctor, "prototype")。
  3. 如果 proto 不是 Object,则
    1. realm 为 ? GetFunctionRealm(ctor)。
    2. proto 设置为 realm 中名为 intrinsicDefaultProto 的固有对象。
  4. 返回 proto
Note

如果 ctor 不提供 [[Prototype]] 值,则所使用的默认值从 ctor 函数的 realm 中取得,而不是从运行中执行上下文取得。

10.1.15 RequireInternalSlot ( obj, internalSlot )

The abstract operation RequireInternalSlot takes arguments obj (an ECMAScript language value) and internalSlot (an internal slot name) and returns either a normal completion containing unused or a throw completion. 除非 obj 是 Object 且具有给定内部槽,否则它会抛出异常。 It performs the following steps when called:

  1. 如果 obj 不是 Object,则抛出 TypeError 异常。
  2. 如果 obj 没有 internalSlot 内部槽,则抛出 TypeError 异常。
  3. 返回 unused

10.2 ECMAScript 函数对象

ECMAScript 函数对象封装了闭合于词法环境的带参数 ECMAScript 代码,并支持该代码的动态求值。ECMAScript 函数对象普通对象,并且具有与其他普通对象相同的内部槽和相同的内部方法。ECMAScript 函数对象的代码可以是严格模式代码(11.2.2),也可以是非严格代码。其代码是严格模式代码的 ECMAScript 函数对象称为严格函数。其代码不是严格模式代码的函数对象称为非严格函数

除了 [[Extensible]][[Prototype]] 之外,ECMAScript 函数对象还具有 Table 26 中列出的内部槽。

Table 26: ECMAScript 函数对象的内部槽
内部槽 类型 描述
[[Environment]] an Environment Record 函数闭合于其上的 Environment Record。在求值函数代码时用作外层环境。
[[PrivateEnvironment]] a PrivateEnvironment Record or null 函数闭合于其上的、用于 Private NamesPrivateEnvironment Record。如果此函数在句法上不包含在类内,则为 null。在求值函数代码时,用作内部类的外层 PrivateEnvironment。
[[FormalParameters]] a Parse Node 定义该函数形式参数列表的源文本的根解析节点。
[[ECMAScriptCode]] a Parse Node 定义该函数体的源文本的根解析节点。
[[ConstructorKind]] base or derived 该函数是否为派生类构造函数
[[Realm]] a Realm Record 函数被创建所在的 realm,并提供在求值函数时访问的任何固有对象。
[[ScriptOrModule]] a Script Record or a Module Record 函数被创建所在的脚本或模块。
[[ThisMode]] lexical, strict, or global 定义如何解释该函数的形式参数和代码体内的 this 引用。lexical 表示 this 引用词法包围函数的 this 值。strict 表示精确使用函数调用所提供的 this 值。global 表示 undefinednullthis 值会被解释为对全局对象的引用,而任何其他 this 值都会先传递给 ToObject
[[Strict]] a Boolean 如果这是严格函数,则为 true;如果这是非严格函数,则为 false
[[HomeObject]] an Object or undefined 如果该函数使用 super,则这是一个对象,其 [[GetPrototypeOf]] 提供 super 属性查找开始所在的对象。
[[SourceText]] a sequence of Unicode code points 定义该函数的源文本
[[Fields]] a List of ClassFieldDefinition Records 如果该函数是一个类,则这是表示该类的非静态字段及对应初始化器的 Records 列表。
[[PrivateMethods]] a List of PrivateElements 如果该函数是一个类,则这是表示该类的非静态私有方法和访问器的列表。
[[ClassFieldInitializerName]] a String, a Symbol, a Private Name, or empty 如果该函数作为类字段的初始化器创建,则为该字段的 NamedEvaluation 使用的名称;否则为 empty
[[IsClassConstructor]] a Boolean 指示该函数是否为类构造函数。(如果为 true,调用该函数的 [[Call]] 会立即抛出 TypeError 异常。)

所有 ECMAScript 函数对象都具有此处定义的 [[Call]] 内部方法。除了是函数之外还是构造函数的 ECMAScript 函数还具有 [[Construct]] 内部方法。

10.2.1 [[Call]] ( thisArg, argList )

The [[Call]] internal method of an ECMAScript function object func takes arguments thisArg (an ECMAScript language value) and argList (a List of ECMAScript language values) and returns either a normal completion containing an ECMAScript language value or a throw completion. It performs the following steps when called:

  1. callerContext 为运行中执行上下文。
  2. calleeContextPrepareForOrdinaryCall(func, undefined)。
  3. 断言:calleeContext 现在是运行中执行上下文。
  4. 如果 func.[[IsClassConstructor]]true,则
    1. error 为新创建的 TypeError 对象。
    2. 注:errorcalleeContext 中、使用 func 的关联 Realm Record 创建。
    3. 从执行上下文栈中移除 calleeContext,并将 callerContext 恢复为运行中执行上下文。
    4. 抛出 error
  5. 执行 OrdinaryCallBindThis(func, calleeContext, thisArg)。
  6. resultCompletion(OrdinaryCallEvaluateBody(func, argList))。
  7. 从执行上下文栈中移除 calleeContext,并将 callerContext 恢复为运行中执行上下文。
  8. 如果 result 是 return completion,则返回 result.[[Value]]
  9. 断言:result 是 throw completion。
  10. 返回 ? result
Note

calleeContext 在步骤 7 中从执行上下文栈中移除时,如果它已暂停并被可访问的 Generator 保留以供稍后恢复,则不得销毁它。

10.2.1.1 PrepareForOrdinaryCall ( func, newTarget )

The abstract operation PrepareForOrdinaryCall takes arguments func (an ECMAScript function object) and newTarget (an Object or undefined) and returns an execution context. It performs the following steps when called:

  1. callerContext 为运行中执行上下文。
  2. calleeContext 为新的 ECMAScript 代码执行上下文
  3. calleeContext 的 Function 设置为 func
  4. calleeRealmfunc.[[Realm]]
  5. calleeContextRealm 设置为 calleeRealm
  6. calleeContext 的 ScriptOrModule 设置为 func.[[ScriptOrModule]]
  7. localEnvNewFunctionEnvironment(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 )

The abstract operation OrdinaryCallBindThis takes arguments func (an ECMAScript function object), calleeContext (an execution context), and thisArg (an ECMAScript language value) and returns unused. It performs the following steps when called:

  1. thisModefunc.[[ThisMode]]
  2. 如果 thisModelexical,则返回 unused
  3. calleeRealmfunc.[[Realm]]
  4. localEnvcalleeContext 的 LexicalEnvironment。
  5. 如果 thisModestrict,则
    1. thisValuethisArg
  6. 否则,
    1. 如果 thisArgundefinednull,则
      1. globalEnvcalleeRealm.[[GlobalEnv]]
      2. 断言:globalEnvGlobal Environment Record
      3. thisValueglobalEnv.[[GlobalThisValue]]
    2. 否则,
      1. thisValue 为 ! ToObject(thisArg)。
      2. 注:ToObject 使用 calleeRealm 产生包装器对象。
  7. 断言:localEnvFunction Environment Record
  8. 断言:下一步绝不会返回 abrupt completion,因为 localEnv.[[ThisBindingStatus]] 不是 initialized
  9. 执行 ! BindThisValue(localEnv, thisValue)。
  10. 返回 unused

10.2.1.3 Runtime Semantics: EvaluateBody

The syntax-directed operation EvaluateBody takes arguments func (an ECMAScript function object) and argList (a List of ECMAScript language values) and returns a return completion or a throw completion. It is defined piecewise over the following productions:

FunctionBody : FunctionStatementList
  1. 返回 ? FunctionBody 带实参 funcargListEvaluateFunctionBody
ConciseBody : ExpressionBody
  1. 返回 ? ConciseBody 带实参 funcargListEvaluateConciseBody
GeneratorBody : FunctionBody
  1. 返回 ? GeneratorBody 带实参 funcargListEvaluateGeneratorBody
AsyncGeneratorBody : FunctionBody
  1. 返回 ? AsyncGeneratorBody 带实参 funcargListEvaluateAsyncGeneratorBody
AsyncFunctionBody : FunctionBody
  1. 返回 ? AsyncFunctionBody 带实参 funcargListEvaluateAsyncFunctionBody
AsyncConciseBody : ExpressionBody
  1. 返回 ? AsyncConciseBody 带实参 funcargListEvaluateAsyncConciseBody
Initializer : = AssignmentExpression
  1. 断言:argList 为空。
  2. 断言:func.[[ClassFieldInitializerName]] 不是 empty
  3. 如果 IsAnonymousFunctionDefinition(AssignmentExpression) 是 true,则
    1. value 为 ? Initializer 带实参 func.[[ClassFieldInitializerName]]NamedEvaluation
  4. 否则,
    1. rhs 为 ? AssignmentExpressionEvaluation
    2. value 为 ? GetValue(rhs)。
  5. 返回 ReturnCompletion(value)。
Note

即使字段初始化器构成函数边界,调用 FunctionDeclarationInstantiation 也没有任何可观察效果,因此被省略。

ClassStaticBlockBody : ClassStaticBlockStatementList
  1. 断言:argList 为空。
  2. 返回 ? ClassStaticBlockBody 带实参 funcEvaluateClassStaticBlockBody

10.2.1.4 OrdinaryCallEvaluateBody ( func, argList )

The abstract operation OrdinaryCallEvaluateBody takes arguments func (an ECMAScript function object) and argList (a List of ECMAScript language values) and returns a return completion or a throw completion. It performs the following steps when called:

  1. 返回 ? func.[[ECMAScriptCode]] 带实参 funcargListEvaluateBody

10.2.2 [[Construct]] ( argList, newTarget )

The [[Construct]] internal method of an ECMAScript function object func takes arguments argList (a List of ECMAScript language values) and newTarget (a constructor) and returns either a normal completion containing an Object or a throw completion. It performs the following steps when called:

  1. callerContext 为运行中执行上下文。
  2. kindfunc.[[ConstructorKind]]
  3. 如果 kindbase,则
    1. thisArg 为 ? OrdinaryCreateFromConstructor(newTarget, "%Object.prototype%")。
  4. calleeContextPrepareForOrdinaryCall(func, newTarget)。
  5. 断言:calleeContext 现在是运行中执行上下文。
  6. 如果 kindbase,则
    1. 执行 OrdinaryCallBindThis(func, calleeContext, thisArg)。
    2. initializeResultCompletion(InitializeInstanceElements(thisArg, func))。
    3. 如果 initializeResult 是 abrupt completion,则
      1. 从执行上下文栈中移除 calleeContext,并将 callerContext 恢复为运行中执行上下文。
      2. 返回 ? initializeResult
  7. ctorEnvcalleeContext 的 LexicalEnvironment。
  8. resultCompletion(OrdinaryCallEvaluateBody(func, argList))。
  9. 从执行上下文栈中移除 calleeContext,并将 callerContext 恢复为运行中执行上下文。
  10. 如果 result 是 throw completion,则
    1. 返回 ? result
  11. 断言:result 是 return completion。
  12. 如果 result.[[Value]] 是 Object,则返回 result.[[Value]]
  13. 如果 kindbase,则返回 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 )

The abstract operation OrdinaryFunctionCreate takes arguments proto (an Object), sourceText (a sequence of Unicode code points), paramList (a Parse Node), body (a Parse Node), thisMode (lexical-this or non-lexical-this), envRecord (an Environment Record), and privateEnv (a PrivateEnvironment Record or null) and returns an ECMAScript function object. 它用于指定具有默认 [[Call]] 内部方法且不具有 [[Construct]] 内部方法的新函数的运行时创建(尽管随后可以由诸如 MakeConstructor 的操作添加一个)。sourceText 是要创建函数的句法定义的源文本。 It performs the following steps when called:

  1. internalSlotsListTable 26 中列出的内部槽。
  2. funcOrdinaryObjectCreate(proto, internalSlotsList)。
  3. func.[[Call]] 设置为 10.2.1 中指定的定义。
  4. func.[[SourceText]] 设置为 sourceText
  5. func.[[FormalParameters]] 设置为 paramList
  6. func.[[ECMAScriptCode]] 设置为 body
  7. strictIsStrict(body)。
  8. func.[[Strict]] 设置为 strict
  9. 如果 thisModelexical-this,则将 func.[[ThisMode]] 设置为 lexical
  10. 否则如果 stricttrue,则将 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. lengthparamListExpectedArgumentCount
  22. 执行 SetFunctionLength(func, length)。
  23. 返回 func

10.2.4 AddRestrictedFunctionProperties ( func, realm )

The abstract operation AddRestrictedFunctionProperties takes arguments func (a function object) and realm (a Realm Record) and returns unused. It performs the following steps when called:

  1. 断言:realm.[[Intrinsics]].[[%ThrowTypeError%]] 存在且已被初始化。
  2. throwerrealm.[[Intrinsics]].[[%ThrowTypeError%]]。
  3. 执行 ! DefinePropertyOrThrow(func, "caller", PropertyDescriptor { [[Get]]: thrower, [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: true })。
  4. 执行 ! DefinePropertyOrThrow(func, "arguments", PropertyDescriptor { [[Get]]: thrower, [[Set]]: 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 ] ] )

The abstract operation MakeConstructor takes argument func (an ECMAScript function object or a built-in function object) and optional arguments writableProto (a Boolean) and proto (an Object) and returns unused. 它将 func 转换为构造函数。 It performs the following steps when called:

  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 )

The abstract operation MakeClassConstructor takes argument func (an ECMAScript function object) and returns unused. It performs the following steps when called:

  1. 断言:func.[[IsClassConstructor]]false
  2. func.[[IsClassConstructor]] 设置为 true
  3. 返回 unused

10.2.7 MakeMethod ( func, homeObj )

The abstract operation MakeMethod takes arguments func (an ECMAScript function object) and homeObj (an Object) and returns unused. 它将 func 配置为方法。 It performs the following steps when called:

  1. 断言:homeObj普通对象
  2. func.[[HomeObject]] 设置为 homeObj
  3. 返回 unused

10.2.8 DefineMethodProperty ( homeObj, name, closure, enumerable )

The abstract operation DefineMethodProperty takes arguments homeObj (an Object), name (a property key or Private Name), closure (a function object), and enumerable (a Boolean) and returns either a normal completion containing either a PrivateElement or unused, or an abrupt completion. It performs the following steps when called:

  1. 断言:homeObj 是普通的、可扩展的对象。
  2. 如果 namePrivate 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" 的类静态方法时返回 abrupt completion。
  6. 返回 unused

10.2.9 SetFunctionName ( func, name [ , prefix ] )

The abstract operation SetFunctionName takes arguments func (a function object) and name (a property key or Private Name) and optional argument prefix (a String) and returns unused. 它向 func 添加一个 "name" 属性。 It performs the following steps when called:

  1. 断言:func 是可扩展对象,且没有 "name" 自有属性。
  2. 如果 name 是 Symbol,则
    1. descriptionname.[[Description]]
    2. 如果 descriptionundefined,则将 name 设置为空 String。
    3. 否则,将 name 设置为 "["description"]"字符串连接
  3. 否则如果 namePrivate Name,则
    1. name 设置为 name.[[Description]]
  4. 如果 func 具有 [[InitialName]] 内部槽,则
    1. func.[[InitialName]] 设置为 name
  5. 如果 prefix 存在,则
    1. prefixedNameprefix、代码单元 0x0020 (SPACE) 和 name字符串连接
    2. 如果 func 具有 [[InitialName]] 内部槽,则
      1. 注:以下步骤中的选择在每次调用此抽象操作时独立作出。
      2. func.[[InitialName]] 设置为 nameprefixedName 之一的实现定义选择。
    3. name 设置为 prefixedName
  6. 执行 ! DefinePropertyOrThrow(func, "name", PropertyDescriptor { [[Value]]: name, [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true })。
  7. 返回 unused

10.2.10 SetFunctionLength ( func, length )

The abstract operation SetFunctionLength takes arguments func (a function object) and length (a non-negative integer or +∞) and returns unused. 它向 func 添加一个 "length" 属性。 It performs the following steps when called:

  1. 断言:func 是可扩展对象,且没有 "length" 自有属性。
  2. 执行 ! DefinePropertyOrThrow(func, "length", PropertyDescriptor { [[Value]]: 𝔽(length), [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true })。
  3. 返回 unused

10.2.11 FunctionDeclarationInstantiation ( func, argList )

The abstract operation FunctionDeclarationInstantiation takes arguments func (an ECMAScript function object) and argList (a List of ECMAScript language values) and returns either a normal completion containing unused or a throw completion. func 是正在为其建立执行上下文的函数对象

Note

当为求值 ECMAScript 函数建立执行上下文时,会创建新的 Function Environment Record,并在该 Environment Record 中实例化每个形式参数的绑定。函数体中的每个声明也会被实例化。如果函数的形式参数不包含任何默认值初始化器,则函数体声明会在与参数相同的 Environment Record 中实例化。如果存在默认值参数初始化器,则会为函数体声明创建第二个 Environment Record。形式参数和函数会作为 FunctionDeclarationInstantiation 的一部分被初始化。所有其他绑定会在函数体求值期间初始化。

它在被调用时执行以下步骤:

  1. calleeContext 为正在运行的执行上下文。
  2. codefunc.[[ECMAScriptCode]]
  3. strictfunc.[[Strict]]
  4. formalsfunc.[[FormalParameters]]
  5. paramNamesformalsBoundNames
  6. 如果 paramNames 有任何重复条目,令 hasDuplicatestrue;否则令 hasDuplicatesfalse
  7. simpleParamListformalsIsSimpleParameterList
  8. hasParamExprsformalsContainsExpression
  9. variableNamescodeVarDeclaredNames
  10. variableDeclscodeVarScopedDeclarations
  11. lexicalNamescodeLexicallyDeclaredNames
  12. funcNames 为一个新的空 List
  13. funcsToInitialize 为一个新的空 List
  14. variableDecls 的每个元素 variableDecl,按 List 的逆序执行:
    1. 如果 variableDecl 既不是 VariableDeclaration、也不是 ForBinding、也不是 BindingIdentifier,则
      1. 断言:variableDeclFunctionDeclarationGeneratorDeclarationAsyncFunctionDeclarationAsyncGeneratorDeclaration
      2. funcNamevariableDeclBoundNames 的唯一元素。
      3. 如果 funcNames包含 funcName,则
        1. funcName 作为 funcNames 的第一个元素插入。
        2. 注:如果同一名称有多个函数声明,则使用最后一个声明。
        3. variableDecl 作为 funcsToInitialize 的第一个元素插入。
  15. argumentsObjNeededtrue
  16. 如果 func.[[ThisMode]]lexical,则
    1. 注:箭头函数永远没有 arguments 对象。
    2. argumentsObjNeeded 设为 false
  17. 否则,如果 paramNames 包含 "arguments",则
    1. argumentsObjNeeded 设为 false
  18. 否则,如果 hasParamExprsfalse,则
    1. 如果 funcNames 包含 "arguments"lexicalNames 包含 "arguments",则
      1. argumentsObjNeeded 设为 false
  19. 如果 stricttruehasParamExprsfalse,则
    1. 注:参数只需要一个 Environment Record,因为严格模式代码中对 eval 的调用不能创建在 eval 外部可见的新绑定。
    2. envRecordcalleeContext 的 LexicalEnvironment。
  20. 否则,
    1. 注:需要一个单独的 Environment Record,以确保在形式参数列表中的直接 eval 调用所创建的绑定位于声明参数的环境之外。
    2. calleeEnvcalleeContext 的 LexicalEnvironment。
    3. envRecordNewDeclarativeEnvironment(calleeEnv)。
    4. 断言:calleeContext 的 VariableEnvironment 与 calleeEnv 是同一个 Environment Record
    5. calleeContext 的 LexicalEnvironment 设为 envRecord
  21. paramNames 的每个 String paramName,执行:
    1. alreadyDeclared 为 ! envRecord.HasBinding(paramName)。
    2. 注:早期错误确保重复的参数名称只能出现在没有参数默认值或剩余参数的非严格函数中。
    3. 如果 alreadyDeclaredfalse,则
      1. 执行 ! envRecord.CreateMutableBinding(paramName, false)。
      2. 如果 hasDuplicatestrue,则
        1. 执行 ! envRecord.InitializeBinding(paramName, undefined)。
  22. 如果 argumentsObjNeededtrue,则
    1. 如果 stricttruesimpleParamListfalse,则
      1. argumentsObjCreateUnmappedArgumentsObject(argList)。
    2. 否则,
      1. 注:映射 arguments 对象只为没有 rest 参数、任何参数默认值初始化器或任何解构参数的非严格函数提供。
      2. argumentsObjCreateMappedArgumentsObject(func, formals, argList, envRecord)。
    3. 如果 stricttrue,则
      1. 执行 ! envRecord.CreateImmutableBinding("arguments", false)。
      2. 注:在严格模式代码中,早期错误会阻止尝试向此绑定赋值,因此其可变性不可观察。
    4. 否则,
      1. 执行 ! envRecord.CreateMutableBinding("arguments", false)。
    5. 执行 ! envRecord.InitializeBinding("arguments", argumentsObj)。
    6. paramBindingsparamNames 与 « "arguments" » 的列表连接
  23. 否则,
    1. paramBindingsparamNames
  24. iteratorRecordCreateListIteratorRecord(argList)。
  25. 如果 hasDuplicatestrue,则
    1. usedEnvundefined
  26. 否则,
    1. usedEnvenvRecord
  27. 注:以下步骤不能返回 ReturnCompletion,因为这种完成在表达式位置出现的唯一方式是使用 YieldExpression,而早期错误规则在 15.5.115.6.1 中禁止其出现在参数列表中。
  28. 使用参数 iteratorRecordusedEnv 执行 ? formalsIteratorBindingInitialization
  29. 如果 hasParamExprsfalse,则
    1. 注:参数和顶层 vars 只需要一个 Environment Record
    2. instantiatedVariableNamesList paramBindings 的副本。
    3. variableNames 的每个元素 name,执行:
      1. 如果 instantiatedVariableNames包含 name,则
        1. name 追加到 instantiatedVariableNames
        2. 执行 ! envRecord.CreateMutableBinding(name, false)。
        3. 执行 ! envRecord.InitializeBinding(name, undefined)。
    4. variableEnvenvRecord
  30. 否则,
    1. 注:需要一个单独的 Environment Record,以确保由形式参数列表中的表达式创建的闭包看不到函数体中的声明。
    2. variableEnvNewDeclarativeEnvironment(envRecord)。
    3. calleeContext 的 VariableEnvironment 设为 variableEnv
    4. instantiatedVariableNames 为一个新的空 List
    5. variableNames 的每个元素 name,执行:
      1. 如果 instantiatedVariableNames包含 name,则
        1. name 追加到 instantiatedVariableNames
        2. 执行 ! variableEnv.CreateMutableBinding(name, false)。
        3. 如果 paramBindings包含 namefuncNames 包含 name,则
          1. initialValueundefined
        4. 否则,
          1. initialValue 为 ! envRecord.GetBindingValue(name, false)。
        5. 执行 ! variableEnv.InitializeBinding(name, initialValue)。
        6. 注:与形式参数同名的 var 最初具有与相应已初始化参数相同的值。
  31. 如果 stricttrue,则
    1. lexicalEnvvariableEnv
  32. 否则,
    1. 如果宿主是 Web 浏览器,或以其他方式支持 块级函数声明的 Web 遗留兼容性语义,则
      1. 对每个 FunctionDeclaration funcDecl,其直接包含在任何 BlockCaseClauseDefaultClause xStatementList 中,且 code Contains xtrue,执行:
        1. funcNamefuncDeclBindingIdentifierStringValue
        2. 如果将 FunctionDeclaration funcDecl 替换为以 funcName 作为 BindingIdentifierVariableStatement 不会为 func 产生任何早期错误,并且 paramNames包含 funcName,则
          1. 注:只有当 funcName 既不是 VarDeclaredName、形式参数名称,也不是另一个 FunctionDeclaration 的名称时,才在此处实例化 funcName 的 var 绑定。
          2. 如果 instantiatedVariableNames包含 funcNamefuncName 不是 "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. lexicalEnvNewDeclarativeEnvironment(variableEnv)。
    3. 注:非严格函数为顶层词法声明使用单独的 Environment Record,使得直接 eval 可以确定 eval 代码引入的任何 var 作用域声明是否与既有的顶层词法作用域声明冲突。严格函数不需要这样做,因为严格的直接 eval 总是将所有声明放入新的 Environment Record
  33. calleeContext 的 LexicalEnvironment 设为 lexicalEnv
  34. lexicalDeclscodeLexicallyScopedDeclarations
  35. lexicalDecls 的每个元素 lexicalDecl,执行:
    1. 注:词法声明的名称不能与函数/生成器声明、形式参数或 var 名称相同。词法声明的名称仅在此处实例化,但不初始化。
    2. lexicalDeclBoundNames 的每个元素 name,执行:
      1. 如果 lexicalDeclIsConstantDeclarationtrue,则
        1. 执行 ! lexicalEnv.CreateImmutableBinding(name, true)。
      2. 否则,
        1. 执行 ! lexicalEnv.CreateMutableBinding(name, false)。
  36. privateEnvcalleeContext 的 PrivateEnvironment。
  37. funcsToInitialize 的每个 Parse Node funcDecl,执行:
    1. funcNamefuncDeclBoundNames 的唯一元素。
    2. funcObj 为使用参数 lexicalEnvprivateEnvfuncDecl 执行 InstantiateFunctionObject 的结果。
    3. 执行 ! variableEnv.SetMutableBinding(funcName, funcObj, false)。
  38. 返回 unused

10.3 内置函数对象

内置函数对象普通对象;它必须满足 10.1 中列出的普通对象要求。

除了每个普通对象都要求的内部槽(参见 10.1)之外,内置函数对象还必须具有以下内部槽:

  • [[Realm]],一个 Realm Record,表示该函数被创建所在的 realm
  • [[InitialName]],一个 String,是该函数的初始名称。它由 20.2.3.5 使用。
  • [[Async]],一个 Boolean,指示该函数在 BuiltinCallOrConstruct 中是否具有 async 函数调用和构造行为。

除非另有指定,内置函数对象[[Prototype]] 内部槽的初始值为 %Function.prototype%

内置函数对象必须具有符合 10.3.1 中定义的 [[Call]] 内部方法。

当且仅当内置函数对象被描述为“constructor”,或本规范中的某个算法显式设置了它的 [[Construct]] 内部方法时,它才具有 [[Construct]] 内部方法。这种 [[Construct]] 内部方法必须符合 10.3.2 中的定义。

实现可以提供本规范未定义的附加内置函数对象

10.3.1 [[Call]] ( thisArg, argList )

The [[Call]] internal method of a built-in function object func takes arguments thisArg (an ECMAScript language value) and argList (a List of ECMAScript language values) and returns either a normal completion containing an ECMAScript language value or a throw completion. It performs the following steps when called:

  1. 返回 ? BuiltinCallOrConstruct(func, thisArg, argList, undefined)。

10.3.2 [[Construct]] ( argList, newTarget )

The [[Construct]] internal method of a built-in function object func(当该方法存在时) takes arguments argList (a List of ECMAScript language values) and newTarget (a constructor) and returns either a normal completion containing an Object or a throw completion. It performs the following steps when called:

  1. result 为 ? BuiltinCallOrConstruct(func, uninitialized, argList, newTarget)。
  2. 断言:result 是 Object。
  3. 返回 result

10.3.3 BuiltinCallOrConstruct ( func, thisArg, argList, newTarget )

The abstract operation BuiltinCallOrConstruct takes arguments func (a built-in function object), thisArg (an ECMAScript language value or uninitialized), argList (a List of ECMAScript language values), and newTarget (a constructor or undefined) and returns either a normal completion containing an ECMAScript language value or a throw completion. It performs the following steps when called:

  1. callerContext 为运行中执行上下文。
  2. 如果 callerContext 尚未暂停,则暂停 callerContext
  3. calleeContext 为一个新的执行上下文。
  4. calleeContext 的 Function 设置为 func
  5. calleeRealmfunc.[[Realm]]
  6. calleeContextRealm 设置为 calleeRealm
  7. calleeContext 的 ScriptOrModule 设置为 null
  8. 执行 calleeContext 的任何必要的实现定义初始化。
  9. calleeContext 压入执行上下文栈;calleeContext 现在是运行中执行上下文。
  10. 如果 func.[[Async]]true,则
    1. promiseCapability 为 ! NewPromiseCapability(%Promise%)。
    2. resultsClosure 为一个不带形参的新 Abstract Closure,它捕获 functhisArgargListnewTarget,并在被调用时执行以下步骤:
      1. resultCompletion Record,其是以符合 func 规范的方式求值 func 的结果。如果 thisArguninitialized,则 this 值未初始化;否则 thisArg 提供 this 值。argList 提供命名形参。newTarget 提供 NewTarget 值。
      2. 注:如果 func 在本文档中定义,则“func 的规范”是通过算法步骤或其他方式为其指定的行为。
      3. 返回 Completion(result)。
    3. 执行 AsyncFunctionStart(promiseCapability, resultsClosure)。
    4. 从执行上下文栈中移除 calleeContext,并将 callerContext 恢复为运行中执行上下文。
    5. 返回 promiseCapability.[[Promise]]
  11. resultCompletion Record,其是以符合 func 规范的方式求值 func 的结果。如果 thisArguninitialized,则 this 值未初始化;否则 thisArg 提供 this 值。argList 提供命名形参。newTarget 提供 NewTarget 值。
  12. 注:如果 func 在本文档中定义,则“func 的规范”是通过算法步骤或其他方式为其指定的行为。
  13. 从执行上下文栈中移除 calleeContext,并将 callerContext 恢复为运行中执行上下文。
  14. 返回 ? result
Note

calleeContext 从执行上下文栈中移除时,如果它已暂停并被可访问的 Generator 保留以供稍后恢复,则不得销毁它。

10.3.4 CreateBuiltinFunction ( behaviour, length, name, additionalInternalSlotsList [ , realm [ , proto [ , prefix [ , async ] ] ] ] )

The abstract operation CreateBuiltinFunction takes arguments behaviour (an Abstract Closure, a set of algorithm steps, or some other definition of a function's behaviour provided in this specification), length (a non-negative integer or +∞), name (a property key or a Private Name), and additionalInternalSlotsList (a List of names of internal slots) and optional arguments realm (a Realm Record), proto (an Object or null), prefix (a String), and async (a Boolean) and returns a built-in function object. additionalInternalSlotsList 包含必须作为对象一部分定义的附加内部槽的名称。此操作会创建一个内置函数对象。 It performs the following steps when called:

  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 安装。

绑定函数异质对象不具有 Table 26 中列出的 ECMAScript 函数对象内部槽。相反,除了 [[Prototype]][[Extensible]] 之外,它们还具有 Table 27 中列出的内部槽。

Table 27: 绑定函数异质对象的内部槽
内部槽 类型 描述
[[BoundTargetFunction]] a callable Object 被包装的函数对象
[[BoundThis]] an ECMAScript language value 调用被包装函数时始终作为 this 值传递的值。
[[BoundArguments]] a List of ECMAScript language values 一个值列表,其元素用作对被包装函数的任何调用的最前面的实参。

10.4.1.1 [[Call]] ( thisArg, argList )

The [[Call]] internal method of a bound function exotic object func takes arguments thisArg (an ECMAScript language value) and argList (a List of ECMAScript language values) and returns either a normal completion containing an ECMAScript language value or a throw completion. It performs the following steps when called:

  1. targetfunc.[[BoundTargetFunction]]
  2. boundThisfunc.[[BoundThis]]
  3. boundArgsfunc.[[BoundArguments]]
  4. argsboundArgsargList列表连接
  5. 返回 ? Call(target, boundThis, args)。

10.4.1.2 [[Construct]] ( argList, newTarget )

The [[Construct]] internal method of a bound function exotic object func takes arguments argList (a List of ECMAScript language values) and newTarget (a constructor) and returns either a normal completion containing an Object or a throw completion. It performs the following steps when called:

  1. targetfunc.[[BoundTargetFunction]]
  2. 断言:IsConstructor(target) 是 true
  3. boundArgsfunc.[[BoundArguments]]
  4. argsboundArgsargList列表连接
  5. 如果 SameValue(func, newTarget) 是 true,则将 newTarget 设置为 target
  6. 返回 ? Construct(target, args, newTarget)。

10.4.1.3 BoundFunctionCreate ( targetFunc, boundThis, boundArgs )

The abstract operation BoundFunctionCreate takes arguments targetFunc (a function object), boundThis (an ECMAScript language value), and boundArgs (a List of ECMAScript language values) and returns either a normal completion containing a function object or a throw completion. 它用于指定新的绑定函数异质对象的创建。 It performs the following steps when called:

  1. proto 为 ? targetFunc.[[GetPrototypeOf]]()
  2. internalSlotsList 为 « [[Prototype]], [[Extensible]] » 和 Table 27 中列出的内部槽的列表连接
  3. objMakeBasicObject(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 是一种对数组索引属性键(参见 6.1.7)进行特殊处理的异质对象属性名数组索引的属性也称为元素。每个 Array 都有一个不可配置的 "length" 属性,其值始终是一个非负整数 Number,其数学值严格小于 232"length" 属性的值在数值上大于每个名称为数组索引的自有属性的名称;每当 Array 的自有属性被创建或更改时,其他属性会按需要调整以维持此不变量。具体而言,每当添加一个名称为数组索引的自有属性时,"length" 属性的值会在必要时被改为比该数组索引的数值大一;并且每当 "length" 属性的值改变时,所有名称为数组索引且其值不小于新长度的自有属性都会被删除。此约束仅适用于 Array 的自有属性,并且不受可能从其原型继承的 "length"数组索引属性影响。

如果一个对象的 [[DefineOwnProperty]] 内部方法使用以下实现,且其其他基本内部方法使用 10.1 中的定义,则该对象是 Array 异质对象(或简称为 Array)。这些方法由 ArrayCreate 安装。

10.4.2.1 [[DefineOwnProperty]] ( propertyKey, propertyDesc )

The [[DefineOwnProperty]] internal method of an Array exotic object array takes arguments propertyKey (a property key) and propertyDesc (a Property Descriptor) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

  1. 如果 propertyKey"length",则返回 ? ArraySetLength(array, propertyDesc)。
  2. 如果 propertyKey数组索引,则
    1. lengthDescOrdinaryGetOwnProperty(array, "length")。
    2. 断言:lengthDesc 不是 undefined
    3. 断言:IsDataDescriptor(lengthDesc) 是 true
    4. 断言:lengthDesc.[[Configurable]]false
    5. lengthlengthDesc.[[Value]]
    6. 断言:length 是非负整数 Number。
    7. index 为 ! ToUint32(propertyKey)。
    8. 如果 indexlengthlengthDesc.[[Writable]]false,则返回 false
    9. succeeded 为 ! OrdinaryDefineOwnProperty(array, propertyKey, propertyDesc)。
    10. 如果 succeededfalse,则返回 false
    11. 如果 indexlength,则
      1. lengthDesc.[[Value]] 设置为 index + 1𝔽
      2. succeeded 设置为 ! OrdinaryDefineOwnProperty(array, "length", lengthDesc)。
      3. 断言:succeededtrue
    12. 返回 true
  3. 返回 ? OrdinaryDefineOwnProperty(array, propertyKey, propertyDesc)。

10.4.2.2 ArrayCreate ( length [ , proto ] )

The abstract operation ArrayCreate takes argument length (a non-negative integer) and optional argument proto (an Object) and returns either a normal completion containing an Array exotic object or a throw completion. 它用于指定新 Arrays 的创建。 It performs the following steps when called:

  1. 如果 length > 232 - 1,则抛出 RangeError 异常。
  2. 如果 proto 不存在,则将 proto 设置为 %Array.prototype%
  3. arrayMakeBasicObject[[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 )

The abstract operation ArraySpeciesCreate takes arguments originalArray (an Object) and length (a non-negative integer) and returns either a normal completion containing an Object or a throw completion. 它用于指定使用从 originalArray 派生的构造函数来创建新的 Array 或类似对象。它不强制要求该构造函数返回 Array。 It performs the following steps when called:

  1. isArray 为 ? IsArray(originalArray)。
  2. 如果 isArrayfalse,则返回 ? ArrayCreate(length)。
  3. ctor 为 ? Get(originalArray, "constructor")。
  4. 如果 IsConstructor(ctor) 是 true,则
    1. thisRealm当前 Realm Record
    2. ctorRealm 为 ? GetFunctionRealm(ctor)。
    3. 如果 thisRealmctorRealm 不是同一个 Realm Record,则
      1. 如果 SameValue(ctor, ctorRealm.[[Intrinsics]].[[%Array%]]) 是 true,则将 ctor 设置为 undefined
  5. 如果 ctor 是 Object,则
    1. ctor 设置为 ? Get(ctor, %Symbol.species%)。
    2. 如果 ctornull,则将 ctor 设置为 undefined
  6. 如果 ctorundefined,则返回 ? ArrayCreate(length)。
  7. 如果 IsConstructor(ctor) 是 false,则抛出 TypeError 异常。
  8. 返回 ? Construct(ctor, « 𝔽(length) »)。
Note

如果 originalArray 是使用一个不同于运行中执行上下文 realmrealm 的标准内置 Array 构造函数创建的,则使用运行中执行上下文的 realm 创建新的 Array。这保持了与 Web 浏览器的兼容性,Web 浏览器历史上对现在使用 ArraySpeciesCreate 定义的 Array.prototype 方法具有这种行为。

10.4.2.4 ArraySetLength ( array, propertyDesc )

The abstract operation ArraySetLength takes arguments array (an Array) and propertyDesc (a Property Descriptor) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

  1. 如果 propertyDesc 不具有 [[Value]] 字段,则
    1. 返回 ! OrdinaryDefineOwnProperty(array, "length", propertyDesc)。
  2. newLengthDescpropertyDesc 的副本。
  3. newLength 为 ? ToUint32(propertyDesc.[[Value]])。
  4. numberLength 为 ? ToNumber(propertyDesc.[[Value]])。
  5. 如果 SameValueZero(newLength, numberLength) 是 false,则抛出 RangeError 异常。
  6. newLengthDesc.[[Value]] 设置为 newLength
  7. oldLengthDescOrdinaryGetOwnProperty(array, "length")。
  8. 断言:oldLengthDesc 不是 undefined
  9. 断言:IsDataDescriptor(oldLengthDesc) 是 true
  10. 断言:oldLengthDesc.[[Configurable]]false
  11. oldLengtholdLengthDesc.[[Value]]
  12. 如果 newLengtholdLength,则
    1. 返回 ! OrdinaryDefineOwnProperty(array, "length", newLengthDesc)。
  13. 如果 oldLengthDesc.[[Writable]]false,则返回 false
  14. 如果 newLengthDesc 不具有 [[Writable]] 字段,或 newLengthDesc.[[Writable]]true,则
    1. newWritabletrue
  15. 否则,
    1. 注:将 [[Writable]] 特性设置为 false 会被推迟,以防某些元素无法删除。
    2. newWritablefalse
    3. newLengthDesc.[[Writable]] 设置为 true
  16. succeeded 为 ! OrdinaryDefineOwnProperty(array, "length", newLengthDesc)。
  17. 如果 succeededfalse,则返回 false
  18. array 的每个自有属性键 propertyKey,如果 propertyKey数组索引且 ! ToUint32(propertyKey) ≥ newLength,则按降序数值索引顺序,执行:
    1. deleteSucceeded 为 ! array.[[Delete]](propertyKey)。
    2. 如果 deleteSucceededfalse,则
      1. newLengthDesc.[[Value]] 设置为 ! ToUint32(propertyKey) + 1𝔽
      2. 如果 newWritablefalse,则将 newLengthDesc.[[Writable]] 设置为 false
      3. 执行 ! OrdinaryDefineOwnProperty(array, "length", newLengthDesc)。
      4. 返回 false
  19. 如果 newWritablefalse,则
    1. succeeded 设置为 ! OrdinaryDefineOwnProperty(array, "length", PropertyDescriptor { [[Writable]]: false })。
    2. 断言:succeededtrue
  20. 返回 true
Note

在步骤 34 中,如果 propertyDesc.[[Value]] 是对象,则其 valueOf 方法会被调用两次。这是一种遗留行为,自本规范第 2nd 版起就以这种效果指定。

10.4.3 字符串异质对象

String 对象是一种异质对象,它封装一个 String 值,并暴露与该 String 值的各个代码单元元素对应的虚拟整数索引数据属性String 异质对象始终具有名为 "length"数据属性,其值是所封装 String 值的长度。代码单元数据属性"length" 属性都不可写且不可配置。

如果一个对象的 [[GetOwnProperty]][[DefineOwnProperty]][[OwnPropertyKeys]] 内部方法使用以下实现,且其其他基本内部方法使用 10.1 中的定义,则该对象是 String 异质对象(或简称为 String 对象)。这些方法由 StringCreate 安装。

String 异质对象具有与普通对象相同的内部槽。它们还具有一个 [[StringData]] 内部槽。

10.4.3.1 [[GetOwnProperty]] ( propertyKey )

The [[GetOwnProperty]] internal method of a String exotic object string takes argument propertyKey (a property key) and returns a normal completion containing either a Property Descriptor or undefined. It performs the following steps when called:

  1. propertyDescOrdinaryGetOwnProperty(string, propertyKey)。
  2. 如果 propertyDesc 不是 undefined,则返回 propertyDesc
  3. 返回 StringGetOwnProperty(string, propertyKey)。

10.4.3.2 [[DefineOwnProperty]] ( propertyKey, propertyDesc )

The [[DefineOwnProperty]] internal method of a String exotic object string takes arguments propertyKey (a property key) and propertyDesc (a Property Descriptor) and returns a normal completion containing a Boolean. It performs the following steps when called:

  1. stringDescStringGetOwnProperty(string, propertyKey)。
  2. 如果 stringDesc 不是 undefined,则
    1. extensiblestring.[[Extensible]]
    2. 返回 IsCompatiblePropertyDescriptor(extensible, propertyDesc, stringDesc)。
  3. 返回 ! OrdinaryDefineOwnProperty(string, propertyKey, propertyDesc)。

10.4.3.3 [[OwnPropertyKeys]] ( )

The [[OwnPropertyKeys]] internal method of a String exotic object obj takes no arguments and returns a normal completion containing a List of property keys. It performs the following steps when called:

  1. keys 为新的空 List
  2. stringobj.[[StringData]]
  3. 断言:string 是 String。
  4. lengthstring 的长度。
  5. 对每个整数 i,使得 0 ≤ i < length,按升序,执行:
    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 )

The abstract operation StringCreate takes arguments value (a String) and proto (an Object) and returns a String exotic object. 它用于指定新 String 异质对象的创建。 It performs the following steps when called:

  1. stringMakeBasicObject[[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. lengthvalue 的长度。
  8. 执行 ! DefinePropertyOrThrow(string, "length", PropertyDescriptor { [[Value]]: 𝔽(length), [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false })。
  9. 返回 string

10.4.3.5 StringGetOwnProperty ( string, propertyKey )

The abstract operation StringGetOwnProperty takes arguments string (an Object that has a [[StringData]] internal slot) and propertyKey (a property key) and returns a Property Descriptor or undefined. It performs the following steps when called:

  1. 如果 propertyKey 不是 String,则返回 undefined
  2. numericIndexCanonicalNumericIndexString(propertyKey)。
  3. 如果 numericIndex 不是整数 Number,则返回 undefined
  4. 如果 numericIndex-0𝔽numericIndex < -0𝔽,则返回 undefined
  5. stringDatastring.[[StringData]]
  6. 断言:stringData 是 String。
  7. lengthstringData 的长度。
  8. 如果 (numericIndex) ≥ length,则返回 undefined
  9. resultStringstringData 中从 (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 安装。

Note 1

虽然 CreateUnmappedArgumentsObject 被归入本条款,但它创建的是普通对象,而不是 arguments 异质对象

arguments 异质对象具有与普通对象相同的内部槽。它们还具有一个 [[ParameterMap]] 内部槽。普通 arguments 对象也具有一个 [[ParameterMap]] 内部槽,其值始终为 undefined。对于普通 arguments 对象,[[ParameterMap]] 内部槽仅由 Object.prototype.toString20.1.3.6)用于将其识别为这类对象。

Note 2

arguments 异质对象中数值名称值小于相应函数对象的形式参数数量的整数索引数据属性,初始时与函数执行上下文中的相应实参绑定共享其值。这意味着更改该属性会更改相应实参绑定的值,反之亦然。如果这样的属性被删除然后重新定义,或者该属性被更改为访问器属性,则这种对应关系会被打破。如果 arguments 对象是普通对象,则其属性值只是传给函数的实参的副本,属性值与形式参数值之间没有动态链接。

Note 3

ParameterMap 对象及其属性值用作指定 arguments 对象与实参绑定对应关系的装置。ParameterMap 对象以及作为其属性值的对象不能从 ECMAScript 代码直接观察到。ECMAScript 实现不需要实际创建或使用这些对象来实现指定语义。

Note 4

普通 arguments 对象定义了一个名为 "callee" 的不可配置访问器属性,访问它时会抛出 TypeError 异常。"callee" 属性对于 arguments 异质对象具有更具体的含义,后者只为某些非严格函数类别创建。此属性在普通变体中的定义,是为了确保符合规范的 ECMAScript 实现不会以任何其他方式定义它。

Note 5

ECMAScript 的 arguments 异质对象实现历史上曾包含一个名为 "caller"访问器属性。在 ECMAScript 2017 之前,本规范包含了在普通 arguments 对象上定义抛出型 "caller" 属性的要求。由于实现不再包含此扩展,ECMAScript 2017 删除了对抛出型 "caller" 访问器的要求。

10.4.4.1 [[GetOwnProperty]] ( propertyKey )

The [[GetOwnProperty]] internal method of an arguments exotic object args takes argument propertyKey (a property key) and returns a normal completion containing either a Property Descriptor or undefined. It performs the following steps when called:

  1. propertyDescOrdinaryGetOwnProperty(args, propertyKey)。
  2. 如果 propertyDescundefined,则返回 undefined
  3. mapargs.[[ParameterMap]]
  4. isMapped 为 ! HasOwnProperty(map, propertyKey)。
  5. 如果 isMappedtrue,则
    1. propertyDesc.[[Value]] 设置为 ! Get(map, propertyKey)。
  6. 返回 propertyDesc

10.4.4.2 [[DefineOwnProperty]] ( propertyKey, propertyDesc )

The [[DefineOwnProperty]] internal method of an arguments exotic object args takes arguments propertyKey (a property key) and propertyDesc (a Property Descriptor) and returns a normal completion containing a Boolean. It performs the following steps when called:

  1. mapargs.[[ParameterMap]]
  2. isMapped 为 ! HasOwnProperty(map, propertyKey)。
  3. newArgDescpropertyDesc
  4. 如果 isMappedtrueIsDataDescriptor(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. 如果 allowedfalse,则返回 false
  7. 如果 isMappedtrue,则
    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 )

The [[Get]] internal method of an arguments exotic object args takes arguments propertyKey (a property key) and receiver (an ECMAScript language value) and returns either a normal completion containing an ECMAScript language value or a throw completion. It performs the following steps when called:

  1. mapargs.[[ParameterMap]]
  2. isMapped 为 ! HasOwnProperty(map, propertyKey)。
  3. 如果 isMappedfalse,则返回 ? OrdinaryGet(args, propertyKey, receiver)。
  4. 断言:map 包含 propertyKey 的形式参数映射。
  5. 返回 ! Get(map, propertyKey)。

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

The [[Set]] internal method of an arguments exotic object args takes arguments propertyKey (a property key), value (an ECMAScript language value), and receiver (an ECMAScript language value) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

  1. 如果 SameValue(args, receiver) 是 false,则
    1. isMappedfalse
  2. 否则,
    1. mapargs.[[ParameterMap]]
    2. isMapped 为 ! HasOwnProperty(map, propertyKey)。
  3. 如果 isMappedtrue,则
    1. 断言:以下 Set 会成功,因为由 arguments 对象映射的形式参数始终可写。
    2. 执行 ! Set(map, propertyKey, value, false)。
  4. 返回 ? OrdinarySet(args, propertyKey, value, receiver)。

10.4.4.5 [[Delete]] ( propertyKey )

The [[Delete]] internal method of an arguments exotic object args takes argument propertyKey (a property key) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

  1. mapargs.[[ParameterMap]]
  2. isMapped 为 ! HasOwnProperty(map, propertyKey)。
  3. result 为 ? OrdinaryDelete(args, propertyKey)。
  4. 如果 resulttrueisMappedtrue,则
    1. 执行 ! map.[[Delete]](propertyKey)。
  5. 返回 result

10.4.4.6 CreateUnmappedArgumentsObject ( argList )

The abstract operation CreateUnmappedArgumentsObject takes argument argList (a List of ECMAScript language values) and returns an ordinary object. It performs the following steps when called:

  1. lengthargList 中元素的数量。
  2. objOrdinaryObjectCreate(%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. valueargList[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 { [[Get]]: %ThrowTypeError%, [[Set]]: %ThrowTypeError%, [[Enumerable]]: false, [[Configurable]]: false })。
  9. 返回 obj

10.4.4.7 CreateMappedArgumentsObject ( func, formals, argList, envRecord )

The abstract operation CreateMappedArgumentsObject takes arguments func (an ECMAScript function object), formals (a Parse Node), argList (a List of ECMAScript language values), and envRecord (an Environment Record) and returns an arguments exotic object. It performs the following steps when called:

  1. 断言:formals包含 rest 参数、任何绑定模式或任何初始化器。它可以包含重复标识符。
  2. lengthargList 中元素的数量。
  3. objMakeBasicObject[[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. mapOrdinaryObjectCreate(null)。
  11. obj.[[ParameterMap]] 设置为 map
  12. paramNamesformalsBoundNames
  13. paramCountparamNames 中元素的数量。
  14. index 为 0。
  15. 重复,当 index < length 时,
    1. valueargList[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. nameparamNames[index]。
    2. 如果 mappedNames包含 name,则
      1. name 追加到 mappedNames
      2. 如果 index < length,则
        1. getterMakeArgGetter(name, envRecord)。
        2. setterMakeArgSetter(name, envRecord)。
        3. 执行 ! map.[[DefineOwnProperty]](! ToString(𝔽(index)), PropertyDescriptor { [[Set]]: setter, [[Get]]: 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 )

The abstract operation MakeArgGetter takes arguments name (a String) and envRecord (an Environment Record) and returns a function object. 它创建一个内置函数对象,该对象在执行时返回 envRecord 中为 name 绑定的值。 It performs the following steps when called:

  1. getterClosure 为一个不带形参的新 Abstract Closure,它捕获 nameenvRecord,并在被调用时执行以下步骤:
    1. 返回 NormalCompletion(! envRecord.GetBindingValue(name, false))。
  2. getterCreateBuiltinFunction(getterClosure, 0, "", « »)。
  3. 注:getter 永远不能被 ECMAScript 代码直接访问。
  4. 返回 getter

10.4.4.7.2 MakeArgSetter ( name, envRecord )

The abstract operation MakeArgSetter takes arguments name (a String) and envRecord (an Environment Record) and returns a function object. 它创建一个内置函数对象,该对象在执行时设置 envRecord 中为 name 绑定的值。 It performs the following steps when called:

  1. setterClosure 为一个具有形参 (value) 的新 Abstract Closure,它捕获 nameenvRecord,并在被调用时执行以下步骤:
    1. 返回 NormalCompletion(! envRecord.SetMutableBinding(name, value, false))。
  2. setterCreateBuiltinFunction(setterClosure, 1, "", « »)。
  3. 注:setter 永远不能被 ECMAScript 代码直接访问。
  4. 返回 setter

10.4.5 TypedArray 异质对象

TypedArray 是一种异质对象,它对作为规范数值字符串属性键进行特殊处理,使用其中处于边界内的整数索引子集来索引统一类型的元素,并强制执行这样的不变量:其余属性不存在且不会引发原型链遍历。

Note

因为对于任何 Number nToString(n) 都是一个规范数值字符串,所以实现可以将 Numbers 视为 TypedArrays属性键,而无需实际执行字符串转换。

TypedArrays 具有与普通对象相同的内部槽,并且还具有 [[ViewedArrayBuffer]][[TypedArrayName]][[ContentType]][[ByteLength]][[ByteOffset]][[ArrayLength]] 内部槽。

如果一个对象的 [[PreventExtensions]][[GetOwnProperty]][[HasProperty]][[DefineOwnProperty]][[Get]][[Set]][[Delete]][[OwnPropertyKeys]] 内部方法使用本节中的定义,且其其他基本内部方法使用 10.1 中的定义,则该对象是 TypedArray。这些方法由 TypedArrayCreate 安装。

10.4.5.1 [[PreventExtensions]] ( )

The [[PreventExtensions]] internal method of a TypedArray obj takes no arguments and returns a normal completion containing a Boolean. It performs the following steps when called:

  1. 注:6.1.7.3 中指定的与可扩展性相关的不变量,不允许此方法在 obj 可以获得(或失去后重新获得)属性时返回 true;当其底层 buffer 被调整大小时,具有整数索引名称的属性可能发生这种情况。
  2. 如果 IsTypedArrayFixedLength(obj) 是 false,则返回 false
  3. 返回 OrdinaryPreventExtensions(obj)。

10.4.5.2 [[GetOwnProperty]] ( propertyKey )

The [[GetOwnProperty]] internal method of a TypedArray obj takes argument propertyKey (a property key) and returns a normal completion containing either a Property Descriptor or undefined. It performs the following steps when called:

  1. 如果 propertyKey 是 String,则
    1. numericIndexCanonicalNumericIndexString(propertyKey)。
    2. 如果 numericIndex 不是 undefined,则
      1. valueTypedArrayGetElement(obj, numericIndex)。
      2. 如果 valueundefined,则返回 undefined
      3. 返回 PropertyDescriptor { [[Value]]: value, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true }。
  2. 返回 OrdinaryGetOwnProperty(obj, propertyKey)。

10.4.5.3 [[HasProperty]] ( propertyKey )

The [[HasProperty]] internal method of a TypedArray obj takes argument propertyKey (a property key) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

  1. 如果 propertyKey 是 String,则
    1. numericIndexCanonicalNumericIndexString(propertyKey)。
    2. 如果 numericIndex 不是 undefined,则返回 IsValidIntegerIndex(obj, numericIndex)。
  2. 返回 ? OrdinaryHasProperty(obj, propertyKey)。

10.4.5.4 [[DefineOwnProperty]] ( propertyKey, propertyDesc )

The [[DefineOwnProperty]] internal method of a TypedArray obj takes arguments propertyKey (a property key) and propertyDesc (a Property Descriptor) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

  1. 如果 propertyKey 是 String,则
    1. numericIndexCanonicalNumericIndexString(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 )

The [[Get]] internal method of a TypedArray obj takes arguments propertyKey (a property key) and receiver (an ECMAScript language value) and returns either a normal completion containing an ECMAScript language value or a throw completion. It performs the following steps when called:

  1. 如果 propertyKey 是 String,则
    1. numericIndexCanonicalNumericIndexString(propertyKey)。
    2. 如果 numericIndex 不是 undefined,则
      1. 返回 TypedArrayGetElement(obj, numericIndex)。
  2. 返回 ? OrdinaryGet(obj, propertyKey, receiver)。

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

The [[Set]] internal method of a TypedArray obj takes arguments propertyKey (a property key), value (an ECMAScript language value), and receiver (an ECMAScript language value) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

  1. 如果 propertyKey 是 String,则
    1. numericIndexCanonicalNumericIndexString(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 )

The [[Delete]] internal method of a TypedArray obj takes argument propertyKey (a property key) and returns a normal completion containing a Boolean. It performs the following steps when called:

  1. 如果 propertyKey 是 String,则
    1. numericIndexCanonicalNumericIndexString(propertyKey)。
    2. 如果 numericIndex 不是 undefined,则
      1. 如果 IsValidIntegerIndex(obj, numericIndex) 是 false,则返回 true
      2. 返回 false
  2. 返回 ! OrdinaryDelete(obj, propertyKey)。

10.4.5.8 [[OwnPropertyKeys]] ( )

The [[OwnPropertyKeys]] internal method of a TypedArray obj takes no arguments and returns a normal completion containing a List of property keys. It performs the following steps when called:

  1. taRecordMakeTypedArrayWithBufferWitnessRecord(obj, seq-cst)。
  2. keys 为新的空 List
  3. 如果 IsTypedArrayOutOfBounds(taRecord) 是 false,则
    1. lengthTypedArrayLength(taRecord)。
    2. 对每个整数 i,使得 0 ≤ i < length,按升序,执行:
      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 Records

TypedArray With Buffer Witness Record 是一个 Record 值,用于封装 TypedArray 以及被查看 buffer 的缓存字节长度。它用于帮助确保当被查看 buffer 是可增长 SharedArrayBuffer 时,字节长度数据块只有单个 ReadSharedMemory 事件。

TypedArray With Buffer Witness Records 具有 Table 28 中列出的字段。

Table 28: TypedArray With Buffer Witness Record 字段
字段名 含义
[[Object]] a TypedArray 其 buffer 的字节长度被加载的 TypedArray
[[CachedBufferByteLength]] a non-negative integer or detached 创建该 Record 时对象的 [[ViewedArrayBuffer]] 的字节长度。

10.4.5.10 MakeTypedArrayWithBufferWitnessRecord ( obj, order )

The abstract operation MakeTypedArrayWithBufferWitnessRecord takes arguments obj (a TypedArray) and order (seq-cst or unordered) and returns a TypedArray With Buffer Witness Record. It performs the following steps when called:

  1. bufferobj.[[ViewedArrayBuffer]]
  2. 如果 IsDetachedBuffer(buffer) 是 true,则
    1. byteLengthdetached
  3. 否则,
    1. byteLengthArrayBufferByteLength(buffer, order)。
  4. 返回 TypedArray With Buffer Witness Record { [[Object]]: obj, [[CachedBufferByteLength]]: byteLength }。

10.4.5.11 TypedArrayCreate ( proto )

The abstract operation TypedArrayCreate takes argument proto (an Object) and returns a TypedArray. 它用于指定新 TypedArrays 的创建。 It performs the following steps when called:

  1. internalSlotsList 为 « [[Prototype]], [[Extensible]], [[ViewedArrayBuffer]], [[TypedArrayName]], [[ContentType]], [[ByteLength]], [[ByteOffset]], [[ArrayLength]] »。
  2. taMakeBasicObject(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 )

The abstract operation TypedArrayByteLength takes argument taRecord (a TypedArray With Buffer Witness Record) and returns a non-negative integer. It performs the following steps when called:

  1. 断言:IsTypedArrayOutOfBounds(taRecord) 是 false
  2. objtaRecord.[[Object]]
  3. 如果 obj.[[ByteLength]] 不是 auto,则返回 obj.[[ByteLength]]
  4. lengthTypedArrayLength(taRecord)。
  5. elementSizeTypedArrayElementSize(obj)。
  6. 注:返回的字节长度始终是 elementSize 的整数倍,即使底层 buffer 已被调整为非整数倍。
  7. 返回 length × elementSize

10.4.5.13 TypedArrayLength ( taRecord )

The abstract operation TypedArrayLength takes argument taRecord (a TypedArray With Buffer Witness Record) and returns a non-negative integer. It performs the following steps when called:

  1. 断言:IsTypedArrayOutOfBounds(taRecord) 是 false
  2. objtaRecord.[[Object]]
  3. 如果 obj.[[ArrayLength]] 不是 auto,则返回 obj.[[ArrayLength]]
  4. 断言:IsFixedLengthArrayBuffer(obj.[[ViewedArrayBuffer]]) 是 false
  5. byteOffsetobj.[[ByteOffset]]
  6. elementSizeTypedArrayElementSize(obj)。
  7. byteLengthtaRecord.[[CachedBufferByteLength]]
  8. 断言:byteLength 不是 detached
  9. 返回 floor((byteLength - byteOffset) / elementSize)。

10.4.5.14 IsTypedArrayOutOfBounds ( taRecord )

The abstract operation IsTypedArrayOutOfBounds takes argument taRecord (a TypedArray With Buffer Witness Record) and returns a Boolean. 它检查该对象的任何数值属性是否引用了不包含在底层 buffer 边界内的索引处的值。 It performs the following steps when called:

  1. objtaRecord.[[Object]]
  2. bufferByteLengthtaRecord.[[CachedBufferByteLength]]
  3. 如果 IsDetachedBuffer(obj.[[ViewedArrayBuffer]]) 是 true,则
    1. 断言:bufferByteLengthdetached
    2. 返回 true
  4. 断言:bufferByteLength 是非负整数。
  5. byteOffsetStartobj.[[ByteOffset]]
  6. 如果 obj.[[ArrayLength]]auto,则
    1. byteOffsetEndbufferByteLength
  7. 否则,
    1. elementSizeTypedArrayElementSize(obj)。
    2. arrayByteLengthobj.[[ArrayLength]] × elementSize
    3. byteOffsetEndbyteOffsetStart + arrayByteLength
  8. 注:[[ByteOffset]]bufferByteLength 的 0 长度 TypedArray 不被视为越界。
  9. 如果 byteOffsetStart > bufferByteLengthbyteOffsetEnd > bufferByteLength,则返回 true
  10. 返回 false

10.4.5.15 IsTypedArrayFixedLength ( obj )

The abstract operation IsTypedArrayFixedLength takes argument obj (a TypedArray) and returns a Boolean. It performs the following steps when called:

  1. 如果 obj.[[ArrayLength]]auto,则返回 false
  2. bufferobj.[[ViewedArrayBuffer]]
  3. 如果 IsFixedLengthArrayBuffer(buffer) 是 falseIsSharedArrayBuffer(buffer) 是 false,则返回 false
  4. 返回 true

10.4.5.16 IsValidIntegerIndex ( obj, index )

The abstract operation IsValidIntegerIndex takes arguments obj (a TypedArray) and index (a Number) and returns a Boolean. It performs the following steps when called:

  1. 如果 IsDetachedBuffer(obj.[[ViewedArrayBuffer]]) 是 true,则返回 false
  2. 如果 index 不是整数 Number,则返回 false
  3. 如果 index-0𝔽index < -0𝔽,则返回 false
  4. taRecordMakeTypedArrayWithBufferWitnessRecord(obj, unordered)。
  5. 注:当 obj 的后备 buffer 是可增长 SharedArrayBuffer 时,边界检查不是同步操作。
  6. 如果 IsTypedArrayOutOfBounds(taRecord) 是 true,则返回 false
  7. lengthTypedArrayLength(taRecord)。
  8. 如果 (index) ≥ length,则返回 false
  9. 返回 true

10.4.5.17 TypedArrayGetElement ( obj, index )

The abstract operation TypedArrayGetElement takes arguments obj (a TypedArray) and index (a Number) and returns a Number, a BigInt, or undefined. It performs the following steps when called:

  1. 如果 IsValidIntegerIndex(obj, index) 是 false,则返回 undefined
  2. offsetobj.[[ByteOffset]]
  3. elementSizeTypedArrayElementSize(obj)。
  4. byteIndexInBuffer 为 ((index) × elementSize) + offset
  5. elementTypeTypedArrayElementType(obj)。
  6. 返回 GetValueFromBuffer(obj.[[ViewedArrayBuffer]], byteIndexInBuffer, elementType, true, unordered)。

10.4.5.18 TypedArraySetElement ( obj, index, value )

The abstract operation TypedArraySetElement takes arguments obj (a TypedArray), index (a Number), and value (an ECMAScript language value) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

  1. 如果 obj.[[ContentType]]bigint,则令 number 为 ? ToBigInt(value)。
  2. 否则,令 number 为 ? ToNumber(value)。
  3. 如果 IsValidIntegerIndex(obj, index) 是 true,则
    1. offsetobj.[[ByteOffset]]
    2. elementSizeTypedArrayElementSize(obj)。
    3. byteIndexInBuffer 为 ((index) × elementSize) + offset
    4. elementTypeTypedArrayElementType(obj)。
    5. 执行 SetValueInBuffer(obj.[[ViewedArrayBuffer]], byteIndexInBuffer, elementType, number, true, unordered)。
  4. 返回 unused
Note

此操作总是表现为成功,但当尝试写入超过 TypedArray 末尾的位置,或写入由 detached ArrayBuffer 支撑的 TypedArray 时,它没有效果。

10.4.5.19 IsArrayBufferViewOutOfBounds ( obj )

The abstract operation IsArrayBufferViewOutOfBounds takes argument obj (a TypedArray or a DataView) and returns a Boolean. 它检查 TypedArray 的任何数值属性或 DataView 对象的方法是否可以引用不包含在底层数据块边界内的索引处的值。此抽象操作作为上游规范的便利而存在。 It performs the following steps when called:

  1. 如果 obj 具有 [[DataView]] 内部槽,则
    1. viewRecordMakeDataViewWithBufferWitnessRecord(obj, seq-cst)。
    2. 返回 IsViewOutOfBounds(viewRecord)。
  2. taRecordMakeTypedArrayWithBufferWitnessRecord(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 安装。

模块命名空间异质对象具有 Table 29 中定义的内部槽。

Table 29: 模块命名空间异质对象的内部槽
内部槽 类型 描述
[[Module]] a Module Record 此命名空间所暴露导出的 Module Record
[[Exports]] a List of Strings 一个 List,其元素是作为此对象自有属性暴露的导出名称的 String 值。该列表按照词典序代码单元顺序排序。

10.4.6.1 [[GetPrototypeOf]] ( )

The [[GetPrototypeOf]] internal method of a module namespace exotic object takes no arguments and returns a normal completion containing null. It performs the following steps when called:

  1. 返回 null

10.4.6.2 [[SetPrototypeOf]] ( proto )

The [[SetPrototypeOf]] internal method of a module namespace exotic object obj takes argument proto (an Object or null) and returns a normal completion containing a Boolean. It performs the following steps when called:

  1. 返回 ! SetImmutablePrototype(obj, proto)。

10.4.6.3 [[IsExtensible]] ( )

The [[IsExtensible]] internal method of a module namespace exotic object takes no arguments and returns a normal completion containing false. It performs the following steps when called:

  1. 返回 false

10.4.6.4 [[PreventExtensions]] ( )

The [[PreventExtensions]] internal method of a module namespace exotic object takes no arguments and returns a normal completion containing true. It performs the following steps when called:

  1. 返回 true

10.4.6.5 [[GetOwnProperty]] ( propertyKey )

The [[GetOwnProperty]] internal method of a module namespace exotic object obj takes argument propertyKey (a property key) and returns either a normal completion containing either a Property Descriptor or undefined, or a throw completion. It performs the following steps when called:

  1. 如果 propertyKey 是 Symbol,则返回 OrdinaryGetOwnProperty(obj, propertyKey)。
  2. exportsobj.[[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 )

The [[DefineOwnProperty]] internal method of a module namespace exotic object obj takes arguments propertyKey (a property key) and propertyDesc (a Property Descriptor) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

  1. 如果 propertyKey 是 Symbol,则返回 ! OrdinaryDefineOwnProperty(obj, propertyKey, propertyDesc)。
  2. current 为 ? obj.[[GetOwnProperty]](propertyKey)。
  3. 如果 currentundefined,则返回 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 )

The [[HasProperty]] internal method of a module namespace exotic object obj takes argument propertyKey (a property key) and returns a normal completion containing a Boolean. It performs the following steps when called:

  1. 如果 propertyKey 是 Symbol,则返回 ! OrdinaryHasProperty(obj, propertyKey)。
  2. exportsobj.[[Exports]]
  3. 如果 exports 包含 propertyKey,则返回 true
  4. 返回 false

10.4.6.8 [[Get]] ( propertyKey, receiver )

The [[Get]] internal method of a module namespace exotic object obj takes arguments propertyKey (a property key) and receiver (an ECMAScript language value) and returns either a normal completion containing an ECMAScript language value or a throw completion. It performs the following steps when called:

  1. 如果 propertyKey 是 Symbol,则
    1. 返回 ! OrdinaryGet(obj, propertyKey, receiver)。
  2. exportsobj.[[Exports]]
  3. 如果 exports包含 propertyKey,则返回 undefined
  4. moduleobj.[[Module]]
  5. bindingmodule.ResolveExport(propertyKey)。
  6. 断言:bindingResolvedBinding Record
  7. targetModulebinding.[[Module]]
  8. 断言:targetModule 不是 undefined
  9. 如果 binding.[[BindingName]]namespace,则
    1. 返回 GetModuleNamespace(targetModule)。
  10. targetEnvtargetModule.[[Environment]]
  11. 如果 targetEnvempty,则抛出 ReferenceError 异常。
  12. 返回 ? targetEnv.GetBindingValue(binding.[[BindingName]], true)。
Note

ResolveExport 无副作用。每次此操作以特定 exportNameresolveSet 对作为实参调用时,它必须返回相同结果。实现可以选择为每个模块命名空间异质对象[[Exports]] 预先计算或缓存 ResolveExport 结果。

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

The [[Set]] internal method of a module namespace exotic object takes arguments propertyKey (a property key), value (an ECMAScript language value), and receiver (an ECMAScript language value) and returns a normal completion containing false. It performs the following steps when called:

  1. 返回 false

10.4.6.10 [[Delete]] ( propertyKey )

The [[Delete]] internal method of a module namespace exotic object obj takes argument propertyKey (a property key) and returns a normal completion containing a Boolean. It performs the following steps when called:

  1. 如果 propertyKey 是 Symbol,则
    1. 返回 ! OrdinaryDelete(obj, propertyKey)。
  2. exportsobj.[[Exports]]
  3. 如果 exports 包含 propertyKey,则返回 false
  4. 返回 true

10.4.6.11 [[OwnPropertyKeys]] ( )

The [[OwnPropertyKeys]] internal method of a module namespace exotic object obj takes no arguments and returns a normal completion containing a List of property keys. It performs the following steps when called:

  1. exportsobj.[[Exports]]
  2. symbolKeysOrdinaryOwnPropertyKeys(obj)。
  3. 返回 exportssymbolKeys列表连接

10.4.6.12 ModuleNamespaceCreate ( module, exports )

The abstract operation ModuleNamespaceCreate takes arguments module (a Module Record) and exports (a List of Strings) and returns a module namespace exotic object. 它用于指定新模块命名空间异质对象的创建。 It performs the following steps when called:

  1. 断言:module.[[Namespace]]empty
  2. internalSlotsListTable 29 中列出的内部槽。
  3. namespaceMakeBasicObject(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]] 内部方法使用以下实现,则该对象是不可变原型异质对象。(其其他基本内部方法可以使用任何实现,取决于所讨论的具体不可变原型异质对象。)

Note

与其他异质对象不同,没有为不可变原型异质对象提供专门的创建抽象操作。这是因为它们仅由 %Object.prototype%宿主环境使用,并且在宿主环境中,相关对象可能在其他方面也是异质的,因此需要其自身专门的创建操作。

10.4.7.1 [[SetPrototypeOf]] ( proto )

The [[SetPrototypeOf]] internal method of an immutable prototype exotic object obj takes argument proto (an Object or null) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

  1. 返回 ? SetImmutablePrototype(obj, proto)。

10.4.7.2 SetImmutablePrototype ( obj, proto )

The abstract operation SetImmutablePrototype takes arguments obj (an Object) and proto (an Object or null) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

  1. current 为 ? obj.[[GetPrototypeOf]]()
  2. 如果 SameValue(proto, current) 是 true,则返回 true
  3. 返回 false

10.5 Proxy 对象内部方法与内部槽

Proxy 对象是一种异质对象,其基本内部方法部分使用 ECMAScript 代码实现。每个 Proxy 对象都有一个称为 [[ProxyHandler]] 的内部槽。[[ProxyHandler]] 的值是一个对象,称为该 proxy 的handler 对象,或为 null。handler 对象的方法(参见 Table 30)可用于增强 Proxy 对象一个或多个内部方法的实现。每个 Proxy 对象还有一个称为 [[ProxyTarget]] 的内部槽,其值要么是一个对象,要么是 null。此对象称为该 proxy 的target 对象

如果一个对象的基本内部方法(包括 [[Call]][[Construct]],如果适用)使用本节中的定义,则该对象是 Proxy 异质对象。这些内部方法由 ProxyCreate 安装。

Table 30: Proxy Handler 方法
内部方法 Handler 方法
[[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

当调用 handler 方法以提供 Proxy 对象内部方法的实现时,会将该 proxy 的 target 对象作为形参传递给 handler 方法。proxy 的 handler 对象不一定具有与每个基本内部方法对应的方法。如果 handler 对象没有与内部陷阱对应的方法,则在 proxy 上调用内部方法会导致在该 proxy 的 target 对象上调用对应的内部方法。

Proxy 对象的 [[ProxyHandler]][[ProxyTarget]] 内部槽总是在对象创建时初始化,并且通常不能被修改。有些 Proxy 对象以允许它们随后被撤销的方式创建。当 proxy 被撤销时,其 [[ProxyHandler]][[ProxyTarget]] 内部槽被设置为 null,导致随后在该 Proxy 对象上调用内部方法时抛出 TypeError 异常。

由于 Proxy 对象允许由任意 ECMAScript 代码提供内部方法的实现,因此可以定义其 handler 方法违反 6.1.7.3 中定义的不变量的 Proxy 对象。6.1.7.3 中定义的某些内部方法不变量是基本完整性不变量。这些不变量由本节中指定的 Proxy 对象内部方法显式强制执行。ECMAScript 实现必须能稳健地应对所有可能的不变量违反。

在以下算法描述中,假设 obj 是 ECMAScript Proxy 对象,propertyKey属性键值,value 是任意 ECMAScript 语言值,且 propertyDescProperty Descriptor Record

10.5.1 [[GetPrototypeOf]] ( )

The [[GetPrototypeOf]] internal method of a Proxy exotic object obj takes no arguments and returns either a normal completion containing either an Object or null, or a throw completion. It performs the following steps when called:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. targetobj.[[ProxyTarget]]
  3. handlerobj.[[ProxyHandler]]
  4. 断言:handler 是 Object。
  5. trap 为 ? GetMethod(handler, "getPrototypeOf")。
  6. 如果 trapundefined,则
    1. 返回 ? target.[[GetPrototypeOf]]()
  7. handlerProto 为 ? Call(trap, handler, « target »)。
  8. 如果 handlerProto 不是 Object 且 handlerProto 不是 null,则抛出 TypeError 异常。
  9. extensibleTarget 为 ? IsExtensible(target)。
  10. 如果 extensibleTargettrue,则返回 handlerProto
  11. targetProto 为 ? target.[[GetPrototypeOf]]()
  12. 如果 SameValue(handlerProto, targetProto) 是 false,则抛出 TypeError 异常。
  13. 返回 handlerProto
Note

Proxy 对象的 [[GetPrototypeOf]] 会强制执行以下不变量:

  • [[GetPrototypeOf]] 的结果必须是 Object 或 null
  • 如果 target 对象不可扩展,则应用于 Proxy 对象的 [[GetPrototypeOf]] 必须返回与应用于该 Proxy 对象的 target 对象的 [[GetPrototypeOf]] 相同的值。

10.5.2 [[SetPrototypeOf]] ( proto )

The [[SetPrototypeOf]] internal method of a Proxy exotic object obj takes argument proto (an Object or null) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. targetobj.[[ProxyTarget]]
  3. handlerobj.[[ProxyHandler]]
  4. 断言:handler 是 Object。
  5. trap 为 ? GetMethod(handler, "setPrototypeOf")。
  6. 如果 trapundefined,则
    1. 返回 ? target.[[SetPrototypeOf]](proto)
  7. boolTrapResultToBoolean(? Call(trap, handler, « target, proto »))。
  8. 如果 boolTrapResultfalse,则返回 false
  9. extensibleTarget 为 ? IsExtensible(target)。
  10. 如果 extensibleTargettrue,则返回 true
  11. targetProto 为 ? target.[[GetPrototypeOf]]()
  12. 如果 SameValue(proto, targetProto) 是 false,则抛出 TypeError 异常。
  13. 返回 true
Note

Proxy 对象的 [[SetPrototypeOf]] 会强制执行以下不变量:

  • [[SetPrototypeOf]] 的结果是 Boolean 值。
  • 如果 target 对象不可扩展,则实参值必须与应用于 target 对象的 [[GetPrototypeOf]] 的结果相同。

10.5.3 [[IsExtensible]] ( )

The [[IsExtensible]] internal method of a Proxy exotic object obj takes no arguments and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. targetobj.[[ProxyTarget]]
  3. handlerobj.[[ProxyHandler]]
  4. 断言:handler 是 Object。
  5. trap 为 ? GetMethod(handler, "isExtensible")。
  6. 如果 trapundefined,则
    1. 返回 ? IsExtensible(target)。
  7. boolTrapResultToBoolean(? Call(trap, handler, « target »))。
  8. targetResult 为 ? IsExtensible(target)。
  9. 如果 boolTrapResult 不是 targetResult,则抛出 TypeError 异常。
  10. 返回 boolTrapResult
Note

Proxy 对象的 [[IsExtensible]] 会强制执行以下不变量:

  • [[IsExtensible]] 的结果是 Boolean 值。
  • 应用于 Proxy 对象的 [[IsExtensible]] 必须返回与以相同实参应用于该 Proxy 对象的 target 对象的 [[IsExtensible]] 相同的值。

10.5.4 [[PreventExtensions]] ( )

The [[PreventExtensions]] internal method of a Proxy exotic object obj takes no arguments and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. targetobj.[[ProxyTarget]]
  3. handlerobj.[[ProxyHandler]]
  4. 断言:handler 是 Object。
  5. trap 为 ? GetMethod(handler, "preventExtensions")。
  6. 如果 trapundefined,则
    1. 返回 ? target.[[PreventExtensions]]()
  7. boolTrapResultToBoolean(? Call(trap, handler, « target »))。
  8. 如果 boolTrapResulttrue,则
    1. extensibleTarget 为 ? IsExtensible(target)。
    2. 如果 extensibleTargettrue,则抛出 TypeError 异常。
  9. 返回 boolTrapResult
Note

Proxy 对象的 [[PreventExtensions]] 会强制执行以下不变量:

  • [[PreventExtensions]] 的结果是 Boolean 值。
  • 应用于 Proxy 对象的 [[PreventExtensions]] 只有在应用于该 Proxy 对象的 target 对象的 [[IsExtensible]]false 时才会返回 true

10.5.5 [[GetOwnProperty]] ( propertyKey )

The [[GetOwnProperty]] internal method of a Proxy exotic object obj takes argument propertyKey (a property key) and returns either a normal completion containing either a Property Descriptor or undefined, or a throw completion. It performs the following steps when called:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. targetobj.[[ProxyTarget]]
  3. handlerobj.[[ProxyHandler]]
  4. 断言:handler 是 Object。
  5. trap 为 ? GetMethod(handler, "getOwnPropertyDescriptor")。
  6. 如果 trapundefined,则
    1. 返回 ? target.[[GetOwnProperty]](propertyKey)
  7. trapResultObj 为 ? Call(trap, handler, « target, propertyKey »)。
  8. 如果 trapResultObj 不是 Object 且 trapResultObj 不是 undefined,则抛出 TypeError 异常。
  9. targetDesc 为 ? target.[[GetOwnProperty]](propertyKey)
  10. 如果 trapResultObjundefined,则
    1. 如果 targetDescundefined,则返回 undefined
    2. 如果 targetDesc.[[Configurable]]false,则抛出 TypeError 异常。
    3. extensibleTarget 为 ? IsExtensible(target)。
    4. 如果 extensibleTargetfalse,则抛出 TypeError 异常。
    5. 返回 undefined
  11. extensibleTarget 为 ? IsExtensible(target)。
  12. resultDesc 为 ? ToPropertyDescriptor(trapResultObj)。
  13. 执行 CompletePropertyDescriptor(resultDesc)。
  14. validIsCompatiblePropertyDescriptor(extensibleTarget, resultDesc, targetDesc)。
  15. 如果 validfalse,则抛出 TypeError 异常。
  16. 如果 resultDesc.[[Configurable]]false,则
    1. 如果 targetDescundefinedtargetDesc.[[Configurable]]true,则
      1. 抛出 TypeError 异常。
    2. 如果 resultDesc 具有 [[Writable]] 字段且 resultDesc.[[Writable]]false,则
      1. 断言:targetDesc 具有 [[Writable]] 字段。
      2. 如果 targetDesc.[[Writable]]true,则抛出 TypeError 异常。
  17. 返回 resultDesc
Note

Proxy 对象的 [[GetOwnProperty]] 会强制执行以下不变量:

  • [[GetOwnProperty]] 的结果必须是 Property Descriptorundefined
  • 如果属性作为 target 对象的不可配置自有属性存在,则不能将该属性报告为不存在。
  • 如果属性作为不可扩展 target 对象的自有属性存在,则不能将该属性报告为不存在。
  • 如果属性不是 target 对象的自有属性且 target 对象不可扩展,则不能将该属性报告为存在。
  • 除非属性作为 target 对象的不可配置自有属性存在,否则不能将该属性报告为不可配置。
  • 除非属性作为 target 对象的不可配置、不可写自有属性存在,否则不能将该属性同时报告为不可配置且不可写。

10.5.6 [[DefineOwnProperty]] ( propertyKey, propertyDesc )

The [[DefineOwnProperty]] internal method of a Proxy exotic object obj takes arguments propertyKey (a property key) and propertyDesc (a Property Descriptor) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. targetobj.[[ProxyTarget]]
  3. handlerobj.[[ProxyHandler]]
  4. 断言:handler 是 Object。
  5. trap 为 ? GetMethod(handler, "defineProperty")。
  6. 如果 trapundefined,则
    1. 返回 ? target.[[DefineOwnProperty]](propertyKey, propertyDesc)
  7. propertyDescObjFromPropertyDescriptor(propertyDesc)。
  8. boolTrapResultToBoolean(? Call(trap, handler, « target, propertyKey, propertyDescObj »))。
  9. 如果 boolTrapResultfalse,则返回 false
  10. targetDesc 为 ? target.[[GetOwnProperty]](propertyKey)
  11. extensibleTarget 为 ? IsExtensible(target)。
  12. 如果 propertyDesc 具有 [[Configurable]] 字段且 propertyDesc.[[Configurable]]false,则
    1. settingConfigFalsetrue
  13. 否则,
    1. settingConfigFalsefalse
  14. 如果 targetDescundefined,则
    1. 如果 extensibleTargetfalse,则抛出 TypeError 异常。
    2. 如果 settingConfigFalsetrue,则抛出 TypeError 异常。
  15. 否则,
    1. 如果 IsCompatiblePropertyDescriptor(extensibleTarget, propertyDesc, targetDesc) 是 false,则抛出 TypeError 异常。
    2. 如果 settingConfigFalsetruetargetDesc.[[Configurable]]true,则抛出 TypeError 异常。
    3. 如果 IsDataDescriptor(targetDesc) 是 truetargetDesc.[[Configurable]]false,且 targetDesc.[[Writable]]true,则
      1. 如果 propertyDesc 具有 [[Writable]] 字段且 propertyDesc.[[Writable]]false,则抛出 TypeError 异常。
  16. 返回 true
Note

Proxy 对象的 [[DefineOwnProperty]] 会强制执行以下不变量:

  • [[DefineOwnProperty]] 的结果是 Boolean 值。
  • 如果 target 对象不可扩展,则不能添加属性。
  • 除非 target 对象存在对应的不可配置自有属性,否则属性不能是不可配置的。
  • 除非 target 对象存在对应的不可配置、不可写自有属性,否则不可配置属性不能是不可写的。
  • 如果属性有对应的 target 对象属性,则使用 [[DefineOwnProperty]] 将该属性的 Property Descriptor 应用于 target 对象不会抛出异常。

10.5.7 [[HasProperty]] ( propertyKey )

The [[HasProperty]] internal method of a Proxy exotic object obj takes argument propertyKey (a property key) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. targetobj.[[ProxyTarget]]
  3. handlerobj.[[ProxyHandler]]
  4. 断言:handler 是 Object。
  5. trap 为 ? GetMethod(handler, "has")。
  6. 如果 trapundefined,则
    1. 返回 ? target.[[HasProperty]](propertyKey)
  7. boolTrapResultToBoolean(? Call(trap, handler, « target, propertyKey »))。
  8. 如果 boolTrapResultfalse,则
    1. targetDesc 为 ? target.[[GetOwnProperty]](propertyKey)
    2. 如果 targetDesc 不是 undefined,则
      1. 如果 targetDesc.[[Configurable]]false,则抛出 TypeError 异常。
      2. extensibleTarget 为 ? IsExtensible(target)。
      3. 如果 extensibleTargetfalse,则抛出 TypeError 异常。
  9. 返回 boolTrapResult
Note

Proxy 对象的 [[HasProperty]] 会强制执行以下不变量:

  • [[HasProperty]] 的结果是 Boolean 值。
  • 如果属性作为 target 对象的不可配置自有属性存在,则不能将该属性报告为不存在。
  • 如果属性作为 target 对象的自有属性存在且 target 对象不可扩展,则不能将该属性报告为不存在。

10.5.8 [[Get]] ( propertyKey, receiver )

The [[Get]] internal method of a Proxy exotic object obj takes arguments propertyKey (a property key) and receiver (an ECMAScript language value) and returns either a normal completion containing an ECMAScript language value or a throw completion. It performs the following steps when called:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. targetobj.[[ProxyTarget]]
  3. handlerobj.[[ProxyHandler]]
  4. 断言:handler 是 Object。
  5. trap 为 ? GetMethod(handler, "get")。
  6. 如果 trapundefined,则
    1. 返回 ? target.[[Get]](propertyKey, receiver)
  7. trapResult 为 ? Call(trap, handler, « target, propertyKey, receiver »)。
  8. targetDesc 为 ? target.[[GetOwnProperty]](propertyKey)
  9. 如果 targetDesc 不是 undefinedtargetDesc.[[Configurable]]false,则
    1. 如果 IsDataDescriptor(targetDesc) 是 truetargetDesc.[[Writable]]false,则
      1. 如果 SameValue(trapResult, targetDesc.[[Value]]) 是 false,则抛出 TypeError 异常。
    2. 如果 IsAccessorDescriptor(targetDesc) 是 truetargetDesc.[[Get]]undefined,则
      1. 如果 trapResult 不是 undefined,则抛出 TypeError 异常。
  10. 返回 trapResult
Note

Proxy 对象的 [[Get]] 会强制执行以下不变量:

  • 如果 target 对象属性是不可写、不可配置的自有数据属性,则为某属性报告的值必须与对应 target 对象属性的值相同。
  • 如果对应的 target 对象属性是不可配置的自有访问器属性,且其 [[Get]] 特性为 undefined,则为某属性报告的值必须是 undefined

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

The [[Set]] internal method of a Proxy exotic object obj takes arguments propertyKey (a property key), value (an ECMAScript language value), and receiver (an ECMAScript language value) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. targetobj.[[ProxyTarget]]
  3. handlerobj.[[ProxyHandler]]
  4. 断言:handler 是 Object。
  5. trap 为 ? GetMethod(handler, "set")。
  6. 如果 trapundefined,则
    1. 返回 ? target.[[Set]](propertyKey, value, receiver)
  7. boolTrapResultToBoolean(? Call(trap, handler, « target, propertyKey, value, receiver »))。
  8. 如果 boolTrapResultfalse,则返回 false
  9. targetDesc 为 ? target.[[GetOwnProperty]](propertyKey)
  10. 如果 targetDesc 不是 undefinedtargetDesc.[[Configurable]]false,则
    1. 如果 IsDataDescriptor(targetDesc) 是 truetargetDesc.[[Writable]]false,则
      1. 如果 SameValue(value, targetDesc.[[Value]]) 是 false,则抛出 TypeError 异常。
    2. 如果 IsAccessorDescriptor(targetDesc) 是 true,则
      1. 如果 targetDesc.[[Set]]undefined,则抛出 TypeError 异常。
  11. 返回 true
Note

Proxy 对象的 [[Set]] 会强制执行以下不变量:

  • [[Set]] 的结果是 Boolean 值。
  • 如果对应的 target 对象属性是不可写、不可配置的自有数据属性,则不能将属性值更改为不同于对应 target 对象属性值的值。
  • 如果对应的 target 对象属性是不可配置的自有访问器属性,且其 [[Set]] 特性为 undefined,则不能设置该属性的值。

10.5.10 [[Delete]] ( propertyKey )

The [[Delete]] internal method of a Proxy exotic object obj takes argument propertyKey (a property key) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. targetobj.[[ProxyTarget]]
  3. handlerobj.[[ProxyHandler]]
  4. 断言:handler 是 Object。
  5. trap 为 ? GetMethod(handler, "deleteProperty")。
  6. 如果 trapundefined,则
    1. 返回 ? target.[[Delete]](propertyKey)
  7. boolTrapResultToBoolean(? Call(trap, handler, « target, propertyKey »))。
  8. 如果 boolTrapResultfalse,则返回 false
  9. targetDesc 为 ? target.[[GetOwnProperty]](propertyKey)
  10. 如果 targetDescundefined,则返回 true
  11. 如果 targetDesc.[[Configurable]]false,则抛出 TypeError 异常。
  12. extensibleTarget 为 ? IsExtensible(target)。
  13. 如果 extensibleTargetfalse,则抛出 TypeError 异常。
  14. 返回 true
Note

Proxy 对象的 [[Delete]] 会强制执行以下不变量:

  • [[Delete]] 的结果是 Boolean 值。
  • 如果属性作为 target 对象的不可配置自有属性存在,则不能将该属性报告为已删除。
  • 如果属性作为 target 对象的自有属性存在且 target 对象不可扩展,则不能将该属性报告为已删除。

10.5.11 [[OwnPropertyKeys]] ( )

The [[OwnPropertyKeys]] internal method of a Proxy exotic object obj takes no arguments and returns either a normal completion containing a List of property keys or a throw completion. It performs the following steps when called:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. targetobj.[[ProxyTarget]]
  3. handlerobj.[[ProxyHandler]]
  4. 断言:handler 是 Object。
  5. trap 为 ? GetMethod(handler, "ownKeys")。
  6. 如果 trapundefined,则
    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 不是 undefinedpropertyDesc.[[Configurable]]false,则
      1. key 追加到 targetNonconfigurableKeys
    3. 否则,
      1. key 追加到 targetConfigurableKeys
  17. 如果 extensibleTargettruetargetNonconfigurableKeys 为空,则
    1. 返回 trapResult
  18. uncheckedResultKeys 为一个 List,其元素是 trapResult 的元素。
  19. targetNonconfigurableKeys 的每个元素 key,执行:
    1. 如果 uncheckedResultKeys包含 key,则抛出 TypeError 异常。
    2. uncheckedResultKeys 中移除 key
  20. 如果 extensibleTargettrue,则返回 trapResult
  21. targetConfigurableKeys 的每个元素 key,执行:
    1. 如果 uncheckedResultKeys包含 key,则抛出 TypeError 异常。
    2. uncheckedResultKeys 中移除 key
  22. 如果 uncheckedResultKeys 不为空,则抛出 TypeError 异常。
  23. 返回 trapResult
Note

Proxy 对象的 [[OwnPropertyKeys]] 会强制执行以下不变量:

  • [[OwnPropertyKeys]] 的结果是 List
  • 返回的 List包含重复项。
  • 返回的 List 的每个元素都是属性键
  • 结果 List 必须包含 target 对象所有不可配置自有属性的键。
  • 如果 target 对象不可扩展,则结果 List 必须包含 target 对象自有属性的所有键,且不包含其他值。

10.5.12 [[Call]] ( thisArg, argList )

The [[Call]] internal method of a Proxy exotic object obj takes arguments thisArg (an ECMAScript language value) and argList (a List of ECMAScript language values) and returns either a normal completion containing an ECMAScript language value or a throw completion. It performs the following steps when called:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. targetobj.[[ProxyTarget]]
  3. handlerobj.[[ProxyHandler]]
  4. 断言:handler 是 Object。
  5. trap 为 ? GetMethod(handler, "apply")。
  6. 如果 trapundefined,则
    1. 返回 ? Call(target, thisArg, argList)。
  7. argArrayCreateArrayFromList(argList)。
  8. 返回 ? Call(trap, handler, « target, thisArg, argArray »)。
Note

只有当 Proxy 异质对象[[ProxyTarget]] 内部槽的初始值是具有 [[Call]] 内部方法的对象时,该 Proxy 异质对象才具有 [[Call]] 内部方法。

10.5.13 [[Construct]] ( argList, newTarget )

The [[Construct]] internal method of a Proxy exotic object obj takes arguments argList (a List of ECMAScript language values) and newTarget (a constructor) and returns either a normal completion containing an Object or a throw completion. It performs the following steps when called:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. targetobj.[[ProxyTarget]]
  3. 断言:IsConstructor(target) 是 true
  4. handlerobj.[[ProxyHandler]]
  5. 断言:handler 是 Object。
  6. trap 为 ? GetMethod(handler, "construct")。
  7. 如果 trapundefined,则
    1. 返回 ? Construct(target, argList, newTarget)。
  8. argArrayCreateArrayFromList(argList)。
  9. newObj 为 ? Call(trap, handler, « target, argArray, newTarget »)。
  10. 如果 newObj 不是 Object,则抛出 TypeError 异常。
  11. 返回 newObj
Note 1

只有当 Proxy 异质对象[[ProxyTarget]] 内部槽的初始值是具有 [[Construct]] 内部方法的对象时,该 Proxy 异质对象才具有 [[Construct]] 内部方法。

Note 2

Proxy 对象的 [[Construct]] 会强制执行以下不变量:

  • [[Construct]] 的结果必须是 Object。

10.5.14 ValidateNonRevokedProxy ( proxy )

The abstract operation ValidateNonRevokedProxy takes argument proxy (a Proxy exotic object) and returns either a normal completion containing unused or a throw completion. 如果 proxy 已被撤销,它会抛出 TypeError 异常。 It performs the following steps when called:

  1. 如果 proxy.[[ProxyTarget]]null,则抛出 TypeError 异常。
  2. 断言:proxy.[[ProxyHandler]] 不是 null
  3. 返回 unused

10.5.15 ProxyCreate ( target, handler )

The abstract operation ProxyCreate takes arguments target (an ECMAScript language value) and handler (an ECMAScript language value) and returns either a normal completion containing a Proxy exotic object or a throw completion. 它用于指定新 Proxy 对象的创建。 It performs the following steps when called:

  1. 如果 target 不是 Object,则抛出 TypeError 异常。
  2. 如果 handler 不是 Object,则抛出 TypeError 异常。
  3. proxyMakeBasicObject[[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 source text 是一系列 Unicode 码点。从 U+0000 到 U+10FFFF 的所有 Unicode 码点值,包括代理码点,都可以在 ECMAScript 语法允许的位置出现在 ECMAScript 源文本中。用于存储和交换 ECMAScript 源文本的实际编码与本规范无关。无论外部源文本编码如何,符合规范的 ECMAScript 实现都会像处理等价的 SourceCharacter 值序列一样处理源文本,其中每个 SourceCharacter 都是一个 Unicode 码点。符合规范的 ECMAScript 实现不要求对源文本执行任何规范化,也不要求表现得仿佛正在执行源文本规范化。

组合字符序列的组成部分会被当作单独的 Unicode 码点处理,即使用户可能认为整个序列是单个字符。

Note

在字符串字面量、正则表达式字面量、模板字面量和标识符中,任何 Unicode 码点也可以使用显式表示码点数值的 Unicode 转义序列表达。在注释内,这种转义序列实际上会作为注释的一部分被忽略。

ECMAScript 在 Unicode 转义序列的行为上不同于 Java 编程语言。例如,在 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 )

The abstract operation UTF16EncodeCodePoint takes argument codePoint (a Unicode code point) and returns a String. It performs the following steps when called:

  1. 断言:0 ≤ codePoint ≤ 0x10FFFF。
  2. 如果 codePoint ≤ 0xFFFF,则返回由数值为 codePoint 的代码单元组成的 String 值。
  3. cu1 为数值为 floor((codePoint - 0x10000) / 0x400) + 0xD800 的代码单元。
  4. cu2 为数值为 ((codePoint - 0x10000) modulo 0x400) + 0xDC00 的代码单元。
  5. 返回 cu1cu2字符串连接

11.1.2 Static Semantics: CodePointsToString ( text )

The abstract operation CodePointsToString takes argument text (a sequence of Unicode code points) and returns a String. 它将 text 转换为 String 值,如 6.1.4 中所述。 It performs the following steps when called:

  1. result 为空 String。
  2. text 的每个码点 codePoint,执行:
    1. result 设置为 resultUTF16EncodeCodePoint(codePoint) 的字符串连接
  3. 返回 result

11.1.3 Static Semantics: UTF16SurrogatePairToCodePoint ( lead, trail )

The abstract operation UTF16SurrogatePairToCodePoint takes arguments lead (a code unit) and trail (a code unit) and returns a code point. 将形成 UTF-16 代理对的两个代码单元转换为一个码点。 It performs the following steps when called:

  1. 断言:lead 是前导代理,且 trail 是后尾代理。
  2. codePoint 为 (lead - 0xD800) × 0x400 + (trail - 0xDC00) + 0x10000。
  3. 返回码点 codePoint

11.1.4 Static Semantics: CodePointAt ( string, position )

The abstract operation CodePointAt takes arguments string (a String) and position (a non-negative integer) and returns a Record with fields [[CodePoint]] (a code point), [[CodeUnitCount]] (a positive integer), and [[IsUnpairedSurrogate]] (a Boolean). 它将 string 解释为 UTF-16 编码码点序列,如 6.1.4 中所述,并从索引 position 处的代码单元开始读取一个码点。 It performs the following steps when called:

  1. sizestring 的长度。
  2. 断言:position ≥ 0 且 position < size
  3. firststring 内索引 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. secondstring 内索引 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 )

The abstract operation StringToCodePoints takes argument string (a String) and returns a List of code points. 它返回将 string6.1.4 中所述解释为 UTF-16 编码 Unicode 文本所得的 Unicode 码点序列。 It performs the following steps when called:

  1. codePoints 为新的空 List
  2. sizestring 的长度。
  3. position 为 0。
  4. 重复,当 position < size 时,
    1. codePointCodePointAt(string, position)。
    2. codePoint.[[CodePoint]] 追加到 codePoints
    3. position 设置为 position + codePoint.[[CodeUnitCount]]
  5. 返回 codePoints

11.1.6 Static Semantics: ParseText ( sourceText, goalSymbol )

The abstract operation ParseText takes arguments sourceText (a String or a sequence of Unicode code points) and goalSymbol (a nonterminal in one of the ECMAScript grammars) and returns a Parse Node or a non-empty List of SyntaxError objects. It performs the following steps when called:

  1. 如果 sourceText 是 String,则将 sourceText 设置为 StringToCodePoints(sourceText)。
  2. 尝试使用 goalSymbol 作为目标符号解析 sourceText,并分析解析结果以查找任何早期错误条件。解析和早期错误检测可以以实现定义的方式交错进行。
  3. 如果解析成功且未发现早期错误,则返回由解析产生的解析树根部的 Parse NodegoalSymbol 的实例)。
  4. 返回一个包含一个或多个 SyntaxError 对象的 List,这些对象表示解析错误和/或早期错误。如果存在多个解析错误或早期错误,则列表中错误对象的数量和顺序是实现定义的,但至少必须存在一个。
Note 1

考虑一段文本,它在某个特定位置有早期错误,并且在稍后位置也有语法错误。先执行解析遍历再执行早期错误遍历的实现,可能会报告语法错误而不继续进行早期错误遍历。将这两项活动交错进行的实现,可能会报告早期错误而不继续查找语法错误。第三种实现可能会报告两个错误。所有这些行为都符合规范。

Note 2

另请参见条款 17

11.2 源代码的类型

ECMAScript 代码有四种类型:

Note 1

Function code 通常作为函数定义(15.2)、箭头函数定义(15.3)、方法定义(15.4)、生成器函数定义(15.5)、异步函数定义(15.8)、异步生成器函数定义(15.6)以及异步箭头函数(15.9)的函数体提供。Function code 也从 Function 构造函数20.2.1.1)、GeneratorFunction 构造函数27.6.1.1)、AsyncFunction 构造函数27.10.1.1)以及 AsyncGeneratorFunction 构造函数27.7.1.1)的实参派生而来。

Note 2

BindingIdentifier 包含在 function code 中的实际效果是:严格模式代码的 Early Errors 会应用于一个 BindingIdentifier,该 BindingIdentifier 是函数体包含 Use Strict Directive 的函数的名称,即使周围代码不是严格模式代码。

11.2.1 指令序言和 Use Strict 指令

Directive Prologue 是出现在 FunctionBodyScriptBodyModuleBody 的初始 StatementListItemModuleItem 位置上的最长 ExpressionStatement 序列,并且该序列中的每个 ExpressionStatement 都完全由一个 StringLiteral token 后跟分号组成。分号可以显式出现,也可以由自动分号插入(12.10)插入。Directive Prologue 可以是空序列。

Use Strict DirectiveDirective Prologue 中的一个 ExpressionStatement,其 StringLiteral 恰好是码点序列 "use strict"'use strict'Use Strict Directive 不得包含 EscapeSequenceLineContinuation

Directive Prologue 可以包含多个 Use Strict Directive。不过,如果发生这种情况,实现可以发出警告。

Note

Directive PrologueExpressionStatement 会在对包含它的产生式求值期间正常求值。实现可以为不是 Use Strict Directive 且出现在 Directive Prologue 中的 ExpressionStatement 定义实现特定含义。如果存在适当的通知机制,则当实现遇到 Directive Prologue 中不是 Use Strict Directive 且没有由实现定义含义的 ExpressionStatement 时,应当发出警告。

11.2.2 严格模式代码

ECMAScript 句法单元可以使用不受限模式或严格模式语法和语义(4.3.2)处理。在以下情形中,代码会被解释为 strict mode code

不是 strict mode code 的 ECMAScript 代码称为 non-strict code

11.2.2.1 Static Semantics: IsStrict ( parseNode )

The abstract operation IsStrict takes argument parseNode (a Parse Node) and returns a Boolean. It performs the following steps when called:

  1. 如果 parseNode 匹配的源文本strict mode code,则返回 true
  2. 返回 false

11.2.3 非 ECMAScript 函数

ECMAScript 实现可以支持对函数异质对象的求值,这些对象的求值行为以某种宿主定义的、非 ECMAScript 源文本的可执行代码形式表示。一个函数对象是在 ECMAScript 代码中定义的,还是内置函数,从调用或被这种函数对象调用的 ECMAScript 代码角度来看是不可观察的。

12 ECMAScript 语言:词法语法

ECMAScript ScriptModule 的源文本首先会被转换为一系列输入元素,这些输入元素是 token、行终止符、注释或空白。源文本会从左到右扫描,反复取尽可能长的码点序列作为下一个输入元素。

在若干情况下,词法输入元素的识别会对消费这些输入元素的句法语法上下文敏感。这要求词法语法具有多个目标符号InputElementHashbangOrRegExp 目标用于 ScriptModule 的开头。InputElementRegExpOrTemplateTail 目标用于允许 RegularExpressionLiteralTemplateMiddleTemplateTail 的句法语法上下文。InputElementRegExp 目标符号用于所有允许 RegularExpressionLiteral,但既不允许 TemplateMiddle 也不允许 TemplateTail 的句法语法上下文。InputElementTemplateTail 目标用于所有允许 TemplateMiddleTemplateTail,但不允许 RegularExpressionLiteral 的句法语法上下文。在所有其他上下文中,InputElementDiv 用作词法目标符号

Note

使用多个词法目标可确保不存在会影响自动分号插入的词法歧义。例如,不存在同时允许前导除法或除法赋值,以及前导 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 空白

空白码点用于提高源文本可读性,并将 token(不可分割的词法单元)彼此分隔开,但除此之外并不重要。空白码点可以出现在任意两个 token 之间,也可以出现在输入的开头或结尾。空白码点可以出现在 StringLiteralRegularExpressionLiteralTemplateTemplateSubstitutionTail 内部,在那里它们被视为构成字面量值一部分的重要码点。它们也可以出现在 Comment 内部,但不能出现在任何其他类型的 token 内部。

ECMAScript 空白码点列于 Table 31

Table 31: 空白码点
码点 名称 缩写
U+0009 CHARACTER TABULATION <TAB>
U+000B LINE TABULATION <VT>
U+000C FORM FEED (FF) <FF>
U+FEFF ZERO WIDTH NO-BREAK SPACE <ZWNBSP>
一般类别 “Space_Separator” 中的任何码点 <USP>
Note 1

U+0020 (SPACE) 和 U+00A0 (NO-BREAK SPACE) 码点是 <USP> 的一部分。

Note 2

除了 Table 31 中列出的码点之外,ECMAScript WhiteSpace 有意排除所有具有 Unicode “White_Space” 属性但未被归类到一般类别 “Space_Separator”(“Zs”)中的码点。

语法

WhiteSpace :: <TAB> <VT> <FF> <ZWNBSP> <USP>

12.3 行终止符

与空白码点类似,行终止符码点用于提高源文本可读性,并将 token(不可分割的词法单元)彼此分隔开。不过,与空白码点不同,行终止符会对句法语法的行为产生一些影响。一般而言,行终止符可以出现在任意两个 token 之间,但句法语法在少数位置禁止它们出现。行终止符还会影响自动分号插入过程(12.10)。除 StringLiteralTemplateTemplateSubstitutionTail 之外,行终止符不能出现在任何 token 内部。<LF> 和 <CR> 行终止符不能出现在 StringLiteral token 内部,除非作为 LineContinuation 的一部分。

行终止符可以出现在 MultiLineComment 内部,但不能出现在 SingleLineComment 内部。

行终止符包含在正则表达式中由 \s 类匹配的空白码点集合内。

ECMAScript 行终止符码点列于 Table 32

Table 32: 行终止符码点
码点 Unicode 名称 缩写
U+000A LINE FEED (LF) <LF>
U+000D CARRIAGE RETURN (CR) <CR>
U+2028 LINE SEPARATOR <LS>
U+2029 PARAGRAPH SEPARATOR <PS>

只有 Table 32 中的 Unicode 码点会被当作行终止符处理。其他换行或断行 Unicode 码点不会被当作行终止符处理,但如果它们满足 Table 31 中列出的要求,则会被当作空白处理。序列 <CR><LF> 通常用作行终止符。为报告行号之目的,应将其视为单个 SourceCharacter

语法

LineTerminator :: <LF> <CR> <LS> <PS> LineTerminatorSequence :: <LF> <CR> [lookahead ≠ <LF>] <LS> <PS> <CR> <LF>

12.4 注释

注释可以是单行或多行。多行注释不能嵌套。

因为单行注释可以包含LineTerminator 码点之外的任何 Unicode 码点,又因为一般规则是 token 总是尽可能长,所以单行注释总是由从 // 标记到行尾的所有码点组成。不过,行尾的 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 Tokens

语法

CommonToken :: IdentifierName PrivateIdentifier Punctuator NumericLiteral StringLiteral Template Note

DivPunctuatorRegularExpressionLiteralRightBracePunctuatorTemplateSubstitutionTail 产生式派生出未包含CommonToken 产生式中的附加 token。

12.7 名称和关键字

IdentifierNameReservedWord 是根据 Unicode 标准附录 #31《Identifier and Pattern Syntax》中给出的默认标识符语法解释的 token,并带有一些小的修改。ReservedWordIdentifierName 的枚举子集。句法语法将 Identifier 定义为不是 ReservedWordIdentifierName。Unicode 标识符语法基于 Unicode 标准指定的字符属性。Unicode 标准最新版本中指定类别内的 Unicode 码点,必须被所有符合规范的 ECMAScript 实现视为属于这些类别。ECMAScript 实现可以识别在 Unicode 标准后续版本中定义的标识符码点。

Note 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 中给出。

Note 2

非终结符 IdentifierPart 通过 UnicodeIDContinue 派生 _

Note 3

具有 Unicode 属性 “ID_Start” 和 “ID_Continue” 的码点集合分别包括具有 Unicode 属性 “Other_ID_Start” 和 “Other_ID_Continue” 的码点。

12.7.1 标识符名称

Unicode 转义序列允许出现在 IdentifierName 中,在那里它们贡献一个等于 UnicodeEscapeSequenceIdentifierCodePoint 的单个 Unicode 码点。UnicodeEscapeSequence 前面的 \ 不贡献任何码点。UnicodeEscapeSequence 不能用于向 IdentifierName 贡献一个本来无效的码点。换言之,如果一个 \ UnicodeEscapeSequence 序列被替换为它所贡献的 SourceCharacter,结果仍必须是有效的 IdentifierName,且其 SourceCharacter 元素序列必须与原始 IdentifierName 完全相同。本规范内对 IdentifierName 的所有解释都基于其实际码点,而不论是否使用了转义序列来贡献某个特定码点。

根据 Unicode 标准规范等价的两个 IdentifierName,除非在替换每个 UnicodeEscapeSequence 后由完全相同的码点序列表示,否则并不相等。

12.7.1.1 Static Semantics: 早期错误

IdentifierStart :: \ UnicodeEscapeSequence IdentifierPart :: \ UnicodeEscapeSequence

12.7.1.2 Static Semantics: IdentifierCodePoints

The syntax-directed operation IdentifierCodePoints takes no arguments and returns a List of code points. It is defined piecewise over the following productions:

IdentifierName :: IdentifierStart
  1. codePointIdentifierStartIdentifierCodePoint
  2. 返回 « codePoint »。
IdentifierName :: IdentifierName IdentifierPart
  1. codePoints 为派生的 IdentifierNameIdentifierCodePoints
  2. codePointIdentifierPartIdentifierCodePoint
  3. 返回 codePoints 和 « codePoint » 的列表连接

12.7.1.3 Static Semantics: IdentifierCodePoint

The syntax-directed operation IdentifierCodePoint takes no arguments and returns a code point. It is defined piecewise over the following productions:

IdentifierStart :: IdentifierStartChar
  1. 返回由 IdentifierStartChar 匹配的码点。
IdentifierPart :: IdentifierPartChar
  1. 返回由 IdentifierPartChar 匹配的码点。
UnicodeEscapeSequence :: u Hex4Digits
  1. 返回其数值为 Hex4Digits 的 MV 的码点。
UnicodeEscapeSequence :: u{ CodePoint }
  1. 返回其数值为 CodePoint 的 MV 的码点。

12.7.2 关键字和保留字

关键字是一个匹配 IdentifierName 但也具有句法用途的 token;也就是说,它以 fixed width 字体字面出现在某个句法产生式中。ECMAScript 的关键字包括 ifwhileasyncawait 以及许多其他关键字。

保留字是不能用作标识符的 IdentifierName。许多关键字是保留字,但有些不是,有些只在特定上下文中保留。ifwhile 是保留字。await 只在 async 函数和模块内部保留。async 不是保留字;它可以不受限制地用作变量名或语句标签。

本规范使用语法产生式和早期错误规则的组合来指定哪些名称是有效标识符,哪些是保留字。下方 ReservedWord 列表中的所有 token,除 awaityield 外,都无条件保留。awaityield 的例外在 13.1 中使用参数化句法产生式指定。最后,若干早期错误规则会限制有效标识符集合。参见 13.1.114.3.1.114.7.5.115.7.1。总之,标识符名称分为五类:

  • 始终允许作为标识符且不是关键字的名称,例如 MathwindowtoString_

  • 永远不允许作为标识符的名称,即下方列出的 ReservedWord,但不包括 awaityield

  • 上下文允许作为标识符的名称,即 awaityield

  • 在严格模式代码中,上下文禁止作为标识符的名称:letstaticimplementsinterfacepackageprivateprotectedpublic

  • 始终允许作为标识符,但也在某些句法产生式中、在不允许 Identifier 的位置作为关键字出现的名称:asasyncfromgetmetaofsettarget

术语 条件关键字上下文关键字 有时用于指代落入后三类的关键字,因此它们在某些上下文中可用作标识符,而在其他上下文中可用作关键字。

语法

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 Note 1

根据 5.1.5,语法中的关键字匹配特定 SourceCharacter 元素的字面序列。关键字中的码点不能由 \ UnicodeEscapeSequence 表达。

IdentifierName 可以包含 \ UnicodeEscapeSequence,但不能通过拼写为 els\u{65} 来声明一个名为 “else” 的变量。13.1.1 中的早期错误规则排除了与保留字具有相同 StringValue 的标识符。

Note 2

enum 目前在本规范中未用作关键字。它是未来保留字,预留用于未来语言扩展中的关键字。

类似地,implementsinterfacepackageprivateprotectedpublic 是严格模式代码中的未来保留字。

Note 3

名称 argumentseval 不是关键字,但它们在严格模式代码中受一些限制。参见 13.1.18.6.415.2.115.5.115.6.115.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 :: 0 NonZeroDigit 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 NonOctalDigit LegacyOctalLikeDecimalIntegerLiteral NonOctalDigit NonOctalDecimalIntegerLiteral DecimalDigit LegacyOctalLikeDecimalIntegerLiteral :: 0 OctalDigit LegacyOctalLikeDecimalIntegerLiteral 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 不得是 IdentifierStartDecimalDigit

Note

例如:3in 是错误,而不是两个输入元素 3in

12.9.3.1 Static Semantics: 早期错误

NumericLiteral :: LegacyOctalIntegerLiteral DecimalIntegerLiteral :: NonOctalDecimalIntegerLiteral
  • 如果 IsStrict(this production) 是 true,则为语法错误。
Note
在非严格代码中,此语法是 Legacy

12.9.3.2 Static Semantics: MV

数值字面量表示 Number 类型BigInt 类型的值。

12.9.3.3 Static Semantics: NumericValue

The syntax-directed operation NumericValue takes no arguments and returns a Number or a BigInt. It is defined piecewise over the following productions:

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. nDecimalDigits 中码点的数量,不包括所有 NumericLiteralSeparator 的出现。
  2. mv 为(NonZeroDigit 的 MV × 10n)加上 DecimalDigits 的 MV。
  3. 返回 (mv)。

12.9.4 字符串字面量

Note 1

字符串字面量是 0 个或多个包含在单引号或双引号中的 Unicode 码点。Unicode 码点也可以由转义序列表示。除闭合引号码点、U+005C (REVERSE SOLIDUS)、U+000D (CARRIAGE RETURN) 和 U+000A (LINE FEED) 外,所有码点都可以按字面出现在字符串字面量中。任何码点都可以以转义序列的形式出现。字符串字面量求值为 ECMAScript String 值。生成这些 String 值时,Unicode 码点会按 11.1.1 中定义的方式进行 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 中。

Note 2

<LF> 和 <CR> 不能出现在字符串字面量中,除非作为 LineContinuation 的一部分以产生空码点序列。将任意一个包含到字符串字面量的 String 值中的正确方式,是使用诸如 \n\u000A 这样的转义序列。

12.9.4.1 Static Semantics: 早期错误

EscapeSequence :: LegacyOctalEscapeSequence NonOctalDecimalEscapeSequence
  • 如果 IsStrict(this production) 是 true,则为语法错误。
Note 1
在非严格代码中,此语法是 Legacy
Note 2

字符串字面量可能出现在使包围代码进入严格模式Use Strict Directive 之前,并且实现必须注意对这类字面量强制执行上述规则。例如,以下源文本包含语法错误:

function invalid() { "\7"; "use strict"; }

12.9.4.2 Static Semantics: SV

The syntax-directed operation SV takes no arguments and returns a String.

字符串字面量表示 String 类型的值。SV 通过对字符串字面量各个部分递归应用,产生字符串字面量的 String 值。作为此过程的一部分,字符串字面量内的某些 Unicode 码点会被解释为具有数学值,如下所述,或如 12.9.3 中所述。

Table 33: String 单字符转义序列
转义序列 代码单元值 Unicode 字符名称 符号
\b 0x0008 BACKSPACE <BS>
\t 0x0009 CHARACTER TABULATION <HT>
\n 0x000A LINE FEED (LF) <LF>
\v 0x000B LINE TABULATION <VT>
\f 0x000C FORM FEED (FF) <FF>
\r 0x000D CARRIAGE RETURN (CR) <CR>
\" 0x0022 QUOTATION MARK "
\' 0x0027 APOSTROPHE '
\\ 0x005C REVERSE SOLIDUS \

12.9.4.3 Static Semantics: MV

12.9.5 正则表达式字面量

Note 1

正则表达式字面量是一个输入元素,每次对该字面量求值时,它都会被转换为 RegExp 对象(参见 22.2)。程序中的两个正则表达式字面量会求值为永远不会通过 === 相互比较为相等的正则表达式对象,即使这两个字面量的内容相同。RegExp 对象也可以在运行时通过 new RegExp 或将 RegExp 构造函数作为函数调用来创建(参见 22.2.4)。

下面的产生式描述正则表达式字面量的语法,并由输入元素扫描器用于查找正则表达式字面量的结束位置。随后,构成 RegularExpressionBodyRegularExpressionFlags 的源文本会再次使用更严格的 ECMAScript 正则表达式语法(22.2.1)进行解析。

实现可以扩展 22.2.1 中定义的 ECMAScript 正则表达式语法,但不得扩展下面定义的 RegularExpressionBodyRegularExpressionFlags 产生式,也不得扩展这些产生式所使用的产生式。

语法

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 Note 2

正则表达式字面量不得为空;代码单元序列 // 会开始单行注释,而不是表示空正则表达式字面量。要指定空正则表达式,请使用:/(?:)/

12.9.5.1 Static Semantics: BodyText

The syntax-directed operation BodyText takes no arguments and returns source text. It is defined piecewise over the following productions:

RegularExpressionLiteral :: / RegularExpressionBody / RegularExpressionFlags
  1. 返回被识别为 RegularExpressionBody 的源文本。

12.9.5.2 Static Semantics: FlagText

The syntax-directed operation FlagText takes no arguments and returns source text. It is defined piecewise over the following productions:

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 Note

TemplateSubstitutionTailInputElementTemplateTail 替代词法目标使用。

12.9.6.1 Static Semantics: TV

The syntax-directed operation TV takes no arguments and returns a String or undefined. 模板字面量组件由 TV 解释为 String 类型的值。TV 用于构造模板对象的索引组件(通俗地说,即模板值)。在 TV 中,转义序列会被替换为该转义序列所表示的 Unicode 码点的 UTF-16 代码单元。

12.9.6.2 Static Semantics: TRV

The syntax-directed operation TRV takes no arguments and returns a String. 模板字面量组件由 TRV 解释为 String 类型的值。TRV 用于构造模板对象的 raw 组件(通俗地说,即模板 raw 值)。TRV 类似于 TV,不同之处在于,在 TRV 中,转义序列会按其在字面量中出现的样子解释。

Note

TV 排除 LineContinuation 的代码单元,而 TRV 包含它们。对于 TV 和 TRV,<CR><LF> 与 <CR> LineTerminatorSequence 都会被规范化为 <LF>。要包含 <CR> 或 <CR><LF> 序列,需要显式的 TemplateEscapeSequence

12.10 自动分号插入

大多数 ECMAScript 语句和声明必须以分号终止。这类分号始终可以显式出现在源文本中。不过,为了方便,在某些情况下,这类分号可以从源文本中省略。对这些情况的描述方式是:在这些情况下,分号会被自动插入到源代码 token 流中。

12.10.1 自动分号插入规则

在以下规则中,“token” 指的是使用当前词法目标符号确定的实际识别出的词法 token,如条款 12 中所述。

分号插入有三条基本规则:

  1. 当源文本从左到右解析时,遇到一个不被语法任何产生式允许的 token(称为违规 token)时,如果以下一个或多个条件为真,则会在该违规 token 之前自动插入一个分号:

    • 违规 token 与前一个 token 之间至少由一个 LineTerminator 分隔。
    • 违规 token 是 }
    • 前一个 token 是 ),且插入的分号随后会被解析为 do-while 语句(14.7.2)的终止分号。
  2. 当源文本从左到右解析时,如果遇到 token 输入流的结尾,且解析器无法将输入 token 流解析为目标非终结符的单个实例,则会在输入流末尾自动插入一个分号。
  3. 当源文本从左到右解析时,如果遇到一个被语法某个产生式允许的 token,但该产生式是受限产生式,且该 token 会成为受限产生式中标注 “[no LineTerminator here]” 后紧跟的终结符或非终结符的第一个 token(因此这样的 token 称为受限 token),并且该受限 token 与前一个 token 之间至少由一个 LineTerminator 分隔,则会在该受限 token 之前自动插入一个分号。

不过,前述规则还有一个额外的覆盖条件:如果插入的分号随后会被解析为空语句,或者该分号会成为 for 语句头部中的两个分号之一(参见 14.7.4),则绝不会自动插入分号。

Note

以下是语法中仅有的受限产生式:

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 标记之后自动插入分号。
  • 当遇到 continuebreakreturnthrowyield 标记,并且在下一个标记之前遇到 LineTerminator 时,会在 continuebreakreturnthrowyield 标记之后自动插入分号。
  • 当箭头函数形参后面在 => 标记之前跟着 LineTerminator 时,会自动插入分号,并且该标点符会导致语法错误。
  • async 标记后面在 functionIdentifierName( 标记之前跟着 LineTerminator 时,会自动插入分号,并且 async 标记不会被视为与后续标记属于同一个表达式或类元素。
  • async 标记后面在 * 标记之前跟着 LineTerminator 时,会自动插入分号,并且该标点符会导致语法错误。

由此给 ECMAScript 程序员得出的实际建议是:

  • 后缀 ++-- 运算符应与其操作数位于同一行。
  • using 声明中的 BindingList 应与 using 标记在同一行开始。
  • returnthrow 语句中的 Expression,或者 yield 表达式中的 AssignmentExpression,应与 returnthrowyield 标记在同一行开始。
  • breakcontinue 语句中的 LabelIdentifier 应与 breakcontinue 标记位于同一行。
  • 箭头函数形参的末尾及其 => 应位于同一行。
  • 异步函数或方法之前的 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;
Note 1

表达式 a + b 不会被当作 return 语句要返回的值,因为 LineTerminator 将它与 token return 分隔开。

源文本

a = b
++c

会通过自动分号插入转换为以下内容:

a = b;
++c;
Note 2

token ++ 不会被当作应用于变量 b 的后缀运算符,因为 b++ 之间出现了 LineTerminator

源文本

if (a > b)
else c = d

不是有效的 ECMAScript 句子,并且不会在 else token 之前通过自动分号插入改变,即使在该点没有语法产生式适用,因为自动插入的分号随后会被解析为空语句。

源文本

a = b + c
(d + e).print()

不会通过自动分号插入转换,因为第二行开头的带括号表达式可以被解释为函数调用的实参列表:

a = b + c(d + e).print()

在赋值语句必须以左括号开头的情况下,程序员最好在前一个语句末尾提供显式分号,而不是依赖自动分号插入。

12.10.3 自动分号插入的有趣情形

本节为非规范性内容。

ECMAScript 程序可以通过依赖自动分号插入,以很少分号的风格编写。如上所述,分号并不会在每个换行处插入,而且自动分号插入可能依赖跨越行终止符的多个 token。

随着新的句法特性加入 ECMAScript,可能会添加额外的语法产生式,使依赖自动分号插入且位于这些产生式之前的行在解析时改变语法产生式。

就本节而言,如果某个自动分号插入情形是一个可能插入也可能不插入分号的位置,取决于它之前的源文本,则该情形被认为是有趣的。本节其余部分描述此 ECMAScript 版本中若干自动分号插入的有趣情形。

12.10.3.1 语句列表中自动分号插入的有趣情形

StatementList 中,许多 StatementListItem 以分号结尾,而这些分号可以使用自动分号插入省略。作为上述规则的结果,在结束表达式的行末,如果下一行以下列任一内容开头,则需要分号:

  • 左括号((。没有分号时,两行会一起被当作 CallExpression 处理。
  • 左方括号([。没有分号时,两行会一起被当作属性访问,而不是 ArrayLiteralArrayAssignmentPattern
  • 模板字面量(`。没有分号时,两行会一起被解释为带标签 Template(13.3.11),其中前一个表达式作为 MemberExpression
  • 一元 +-。没有分号时,两行会一起被解释为对应二元运算符的使用。
  • RegExp 字面量。没有分号时,两行可能会改为被解析为 / MultiplicativeOperator,例如当该 RegExp 有 flags 时。

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 Note

语法中允许 yieldawait 作为 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] 参数,且 IdentifierStringValue"yield",则为语法错误。
  • 如果此产生式具有 [Await] 参数,且 IdentifierStringValue"await",则为语法错误。
Identifier : IdentifierName but not ReservedWord Note

IdentifierNameStringValue 会规范化 IdentifierName 中的任何 Unicode 转义序列,因此这种转义不能用于写出码点序列与 ReservedWord 相同的 Identifier

13.1.2 Static Semantics: StringValue

The syntax-directed operation StringValue takes no arguments and returns a String. It is defined piecewise over the following productions:

IdentifierName :: IdentifierStart IdentifierName IdentifierPart
  1. idTextUnescapedIdentifierNameIdentifierCodePoints
  2. 返回 CodePointsToString(idTextUnescaped)。
IdentifierReference : yield BindingIdentifier : yield LabelIdentifier : yield
  1. 返回 "yield"
IdentifierReference : await BindingIdentifier : await LabelIdentifier : await
  1. 返回 "await"
Identifier : IdentifierName but not ReservedWord
  1. 返回 IdentifierNameStringValue
PrivateIdentifier :: # IdentifierName
  1. 返回 0x0023 (NUMBER SIGN) 和 IdentifierNameStringValue字符串连接
ModuleExportName : StringLiteral
  1. 返回 StringLiteralSV

13.1.3 Runtime Semantics: Evaluation

IdentifierReference : Identifier
  1. 返回 ? ResolveBinding(IdentifierStringValue)。
IdentifierReference : yield
  1. 返回 ? ResolveBinding("yield")。
IdentifierReference : await
  1. 返回 ? ResolveBinding("await")。
Note 1

求值 IdentifierReference 的结果始终是 Reference 类型的值。

Note 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] ) ( Expression[+In, ?Yield, ?Await] , ) ( ) ( ... 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 是 token false,则返回 false
  2. 如果 BooleanLiteral 是 token true,则返回 true
Literal : NumericLiteral
  1. 返回 12.9.3 中定义的 NumericLiteralNumericValue
Literal : StringLiteral
  1. 返回 12.9.4.2 中定义的 StringLiteralSV

13.2.4 数组初始化器

Note

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

The syntax-directed operation ArrayAccumulation takes arguments array (an Array) and nextIndex (an integer) and returns either a normal completion containing an integer or an abrupt completion. It is defined piecewise over the following productions:

Elision : ,
  1. lengthnextIndex + 1。
  2. 执行 ? Set(array, "length", 𝔽(length), true)。
  3. 注:如果 length 超过 232 - 1,则上一步会抛出异常。
  4. 返回 length
Elision : Elision ,
  1. 返回以 array 和 (nextIndex + 1) 为实参执行 ElisionArrayAccumulation 的结果。
ElementList : Elisionopt AssignmentExpression
  1. 如果存在 Elision,则
    1. nextIndex 设置为以 arraynextIndex 为实参执行 ElisionArrayAccumulation 的结果。
  2. initResult 为 ? AssignmentExpressionEvaluation
  3. initValue 为 ? GetValue(initResult)。
  4. 执行 ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(nextIndex)), initValue)。
  5. 返回 nextIndex + 1。
ElementList : Elisionopt SpreadElement
  1. 如果存在 Elision,则
    1. nextIndex 设置为以 arraynextIndex 为实参执行 ElisionArrayAccumulation 的结果。
  2. 返回以 arraynextIndex 为实参执行 SpreadElementArrayAccumulation 的结果。
ElementList : ElementList , Elisionopt AssignmentExpression
  1. nextIndex 设置为以 arraynextIndex 为实参执行派生的 ElementListArrayAccumulation 的结果。
  2. 如果存在 Elision,则
    1. nextIndex 设置为以 arraynextIndex 为实参执行 ElisionArrayAccumulation 的结果。
  3. initResult 为 ? AssignmentExpressionEvaluation
  4. initValue 为 ? GetValue(initResult)。
  5. 执行 ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(nextIndex)), initValue)。
  6. 返回 nextIndex + 1。
ElementList : ElementList , Elisionopt SpreadElement
  1. nextIndex 设置为以 arraynextIndex 为实参执行派生的 ElementListArrayAccumulation 的结果。
  2. 如果存在 Elision,则
    1. nextIndex 设置为以 arraynextIndex 为实参执行 ElisionArrayAccumulation 的结果。
  3. 返回以 arraynextIndex 为实参执行 SpreadElementArrayAccumulation 的结果。
SpreadElement : ... AssignmentExpression
  1. spreadRef 为 ? AssignmentExpressionEvaluation
  2. spreadObj 为 ? GetValue(spreadRef)。
  3. iteratorRecord 为 ? GetIterator(spreadObj, sync)。
  4. 重复:
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 nextdone,则返回 nextIndex
    3. 执行 ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(nextIndex)), next)。
    4. nextIndex 设置为 nextIndex + 1。
Note

使用 CreateDataPropertyOrThrow 是为了确保即使标准内置 Array prototype 对象已被以某种会妨碍使用 [[Set]] 创建新自有属性的方式修改,也会为该数组定义自有属性。

13.2.4.2 Runtime Semantics: Evaluation

ArrayLiteral : [ Elisionopt ]
  1. array 为 ! ArrayCreate(0)。
  2. 如果存在 Elision,则
    1. 执行 ? 以 array 和 0 为实参执行 ElisionArrayAccumulation
  3. 返回 array
ArrayLiteral : [ ElementList ]
  1. array 为 ! ArrayCreate(0)。
  2. 执行 ? 以 array 和 0 为实参执行 ElementListArrayAccumulation
  3. 返回 array
ArrayLiteral : [ ElementList , Elisionopt ]
  1. array 为 ! ArrayCreate(0)。
  2. nextIndex 为 ? 以 array 和 0 为实参执行 ElementListArrayAccumulation
  3. 如果存在 Elision,则
    1. 执行 ? 以 arraynextIndex 为实参执行 ElisionArrayAccumulation
  4. 返回 array

13.2.5 对象初始化器

Note 1

对象初始化器是描述 Object 初始化的表达式,它以类似字面量的形式编写。它是由花括号包围的、零个或多个属性键及其关联值的配对列表。这些值不必是字面量;每次求值对象初始化器时都会求值它们。

语法

ObjectLiteral[Yield, Await] : { } { PropertyDefinitionList[?Yield, ?Await] } { PropertyDefinitionList[?Yield, ?Await] , } 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] Note 2

MethodDefinition15.4 中定义。

Note 3

在某些上下文中,ObjectLiteral 被用作更受限的次级语法的覆盖语法。CoverInitializedName 产生式是完整覆盖这些次级语法所必需的。不过,在期望实际 ObjectLiteral 的正常上下文中,使用此产生式会导致早期语法错误。

13.2.5.1 Static Semantics: 早期错误

PropertyDefinition : MethodDefinition

除了描述实际对象初始化器之外,ObjectLiteral 产生式还被用作 ObjectAssignmentPattern 的覆盖语法,并且可能作为 CoverParenthesizedExpressionAndArrowParameterList 的一部分被识别。当 ObjectLiteral 出现在需要 ObjectAssignmentPattern 的上下文中时,不会应用以下早期错误规则。此外,在初始解析 CoverParenthesizedExpressionAndArrowParameterListCoverCallExpressionAndAsyncArrowHead 时,也不会应用这些规则。

PropertyDefinition : CoverInitializedName
  • 如果此产生式匹配到任何源文本,则为语法错误。
Note 1

此产生式存在是为了让 ObjectLiteral 可作为 ObjectAssignmentPattern 的覆盖语法。它不能出现在实际的对象初始化器中。

ObjectLiteral : { PropertyDefinitionList } { PropertyDefinitionList , } Note 2

PropertyNameList 返回的 List包含使用 ComputedPropertyName 定义的属性名

13.2.5.2 Static Semantics: IsComputedPropertyKey

The syntax-directed operation IsComputedPropertyKey takes no arguments and returns a Boolean. It is defined piecewise over the following productions:

PropertyName : LiteralPropertyName
  1. 返回 false
PropertyName : ComputedPropertyName
  1. 返回 true

13.2.5.3 Static Semantics: PropertyDefinitionNodes

The syntax-directed operation PropertyDefinitionNodes takes no arguments and returns a List of Parse Nodes. It is defined piecewise over the following productions:

ObjectLiteral : { }
  1. 返回一个新的空 List
PropertyDefinitionList : PropertyDefinition
  1. 返回 « PropertyDefinition »。
PropertyDefinitionList : PropertyDefinitionList , PropertyDefinition
  1. head 为派生的 PropertyDefinitionListPropertyDefinitionNodes
  2. 返回 head 和 « PropertyDefinition » 的列表连接

13.2.5.4 Static Semantics: PropertyNameList

The syntax-directed operation PropertyNameList takes no arguments and returns a List of Strings. It is defined piecewise over the following productions:

PropertyDefinitionList : PropertyDefinition
  1. propertyNamePropertyDefinitionPropName
  2. 如果 propertyNameempty,则返回一个新的空 List
  3. 返回 « propertyName »。
PropertyDefinitionList : PropertyDefinitionList , PropertyDefinition
  1. listPropertyDefinitionListPropertyNameList
  2. propertyNamePropertyDefinitionPropName
  3. 如果 propertyNameempty,则返回 list
  4. 返回 list 和 « propertyName » 的列表连接

13.2.5.5 Runtime Semantics: Evaluation

ObjectLiteral : { }
  1. 返回 OrdinaryObjectCreate(%Object.prototype%)。
ObjectLiteral : { PropertyDefinitionList } { PropertyDefinitionList , }
  1. objOrdinaryObjectCreate(%Object.prototype%)。
  2. 执行 ? 以 obj 为实参执行 PropertyDefinitionListPropertyDefinitionEvaluation
  3. 返回 obj
LiteralPropertyName : IdentifierName
  1. 返回 IdentifierNameStringValue
LiteralPropertyName : StringLiteral
  1. 返回 StringLiteralSV
LiteralPropertyName : NumericLiteral
  1. numberNumericLiteralNumericValue
  2. 返回 ! ToString(number)。
ComputedPropertyName : [ AssignmentExpression ]
  1. exprValue 为 ? AssignmentExpressionEvaluation
  2. propertyName 为 ? GetValue(exprValue)。
  3. 返回 ? ToPropertyKey(propertyName)。

13.2.5.6 Runtime Semantics: PropertyDefinitionEvaluation

The syntax-directed operation PropertyDefinitionEvaluation takes argument obj (an Object) and returns either a normal completion containing unused or an abrupt completion. It is defined piecewise over the following productions:

PropertyDefinitionList : PropertyDefinitionList , PropertyDefinition
  1. 执行 ? 以 obj 为实参执行 PropertyDefinitionListPropertyDefinitionEvaluation
  2. 执行 ? 以 obj 为实参执行 PropertyDefinitionPropertyDefinitionEvaluation
  3. 返回 unused
PropertyDefinition : ... AssignmentExpression
  1. exprValue 为 ? AssignmentExpressionEvaluation
  2. fromValue 为 ? GetValue(exprValue)。
  3. excludedNames 为新的空 List
  4. 执行 ? CopyDataProperties(obj, fromValue, excludedNames)。
  5. 返回 unused
PropertyDefinition : IdentifierReference
  1. propertyNameIdentifierReferenceStringValue
  2. exprValue 为 ? IdentifierReferenceEvaluation
  3. propertyValue 为 ? GetValue(exprValue)。
  4. 断言:obj 是一个普通的、可扩展的对象,且没有不可配置属性。
  5. 执行 ! CreateDataPropertyOrThrow(obj, propertyName, propertyValue)。
  6. 返回 unused
PropertyDefinition : PropertyName : AssignmentExpression
  1. propertyKey 为 ? PropertyNameEvaluation
  2. 如果此 PropertyDefinition 包含在正为 ParseJSON 求值的 Script 内(参见 ParseJSON 的步骤 6),则
    1. isProtoSetterfalse
  3. 否则,如果 propertyKey"__proto__"PropertyNameIsComputedPropertyKeyfalse,则
    1. isProtoSettertrue
  4. 否则,
    1. isProtoSetterfalse
  5. 如果 IsAnonymousFunctionDefinition(AssignmentExpression) 是 trueisProtoSetterfalse,则
    1. propertyValue 为 ? 以 propertyKey 为实参执行 AssignmentExpressionNamedEvaluation
  6. 否则,
    1. exprValueRef 为 ? AssignmentExpressionEvaluation
    2. propertyValue 为 ? GetValue(exprValueRef)。
  7. 如果 isProtoSettertrue,则
    1. 如果 propertyValue 是 Object 或 propertyValuenull,则
      1. 执行 ! obj.[[SetPrototypeOf]](propertyValue)
    2. 返回 unused
  8. 断言:obj 是一个普通的、可扩展的对象,且没有不可配置属性。
  9. 执行 ! CreateDataPropertyOrThrow(obj, propertyKey, propertyValue)。
  10. 返回 unused
PropertyDefinition : MethodDefinition
  1. 执行 ? 以 objtrue 为实参执行 MethodDefinitionMethodDefinitionEvaluation
  2. 返回 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 )

The abstract operation IsValidRegularExpressionLiteral takes argument literal (a RegularExpressionLiteral Parse Node) and returns a Boolean. 它确定其实参是否是有效的正则表达式字面量。 It performs the following steps when called:

  1. flagsliteralFlagText
  2. 如果 flags 包含dgimsuvy 之外的任何码点,则返回 false
  3. 如果 flags 包含任何出现次数超过一次的码点,则返回 false
  4. 如果 flags 包含 u,则令 utrue;否则令 ufalse
  5. 如果 flags 包含 v,则令 vtrue;否则令 vfalse
  6. patternTextliteralBodyText
  7. 如果 ufalsevfalse,则
    1. stringValueCodePointsToString(patternText)。
    2. patternText 设置为将 stringValue 的每个 16 位元素解释为 Unicode BMP 码点所得的码点序列。不会对这些元素应用 UTF-16 解码。
  8. parseResultParsePattern(patternText, u, v)。
  9. 如果 parseResultParse Node,则返回 true
  10. 返回 false

13.2.7.3 Runtime Semantics: Evaluation

PrimaryExpression : RegularExpressionLiteral
  1. patternCodePointsToString(RegularExpressionLiteralBodyText)。
  2. flagsCodePointsToString(RegularExpressionLiteralFlagText)。
  3. 返回 ! RegExpCreate(pattern, flags)。

13.2.8 模板字面量

语法

TemplateLiteral[Yield, Await, Tagged] : NoSubstitutionTemplate SubstitutionTemplate[?Yield, ?Await, ?Tagged] SubstitutionTemplate[Yield, Await, Tagged] : TemplateHead Expression[+In, ?Yield, ?Await] TemplateSpans[?Yield, ?Await, ?Tagged] TemplateSpans[Yield, Await, Tagged] : TemplateTail TemplateMiddleList[?Yield, ?Await, ?Tagged] TemplateTail TemplateMiddleList[Yield, Await, Tagged] : TemplateMiddle Expression[+In, ?Yield, ?Await] TemplateMiddleList[?Yield, ?Await, ?Tagged] TemplateMiddle Expression[+In, ?Yield, ?Await]

13.2.8.1 Static Semantics: 早期错误

TemplateLiteral[Yield, Await, Tagged] : NoSubstitutionTemplate TemplateLiteral[Yield, Await, Tagged] : SubstitutionTemplate[?Yield, ?Await, ?Tagged] SubstitutionTemplate[Yield, Await, Tagged] : TemplateHead Expression[+In, ?Yield, ?Await] TemplateSpans[?Yield, ?Await, ?Tagged] TemplateSpans[Yield, Await, Tagged] : TemplateTail TemplateMiddleList[Yield, Await, Tagged] : TemplateMiddle Expression[+In, ?Yield, ?Await] TemplateMiddleList[?Yield, ?Await, ?Tagged] TemplateMiddle Expression[+In, ?Yield, ?Await]

13.2.8.2 Static Semantics: TemplateStrings

The syntax-directed operation TemplateStrings takes argument raw (a Boolean) and returns a List of either Strings or undefined. It is defined piecewise over the following productions:

TemplateLiteral : NoSubstitutionTemplate
  1. 返回 « TemplateString(NoSubstitutionTemplate, raw) »。
SubstitutionTemplate : TemplateHead Expression TemplateSpans
  1. head 为 « TemplateString(TemplateHead, raw) »。
  2. tail 为以 raw 为实参的 TemplateSpansTemplateStrings
  3. 返回 headtail列表连接
TemplateSpans : TemplateTail
  1. 返回 « TemplateString(TemplateTail, raw) »。
TemplateSpans : TemplateMiddleList TemplateTail
  1. middle 为以 raw 为实参的 TemplateMiddleListTemplateStrings
  2. tail 为 « TemplateString(TemplateTail, raw) »。
  3. 返回 middletail列表连接
TemplateMiddleList : TemplateMiddle Expression
  1. 返回 « TemplateString(TemplateMiddle, raw) »。
TemplateMiddleList : TemplateMiddleList TemplateMiddle Expression
  1. front 为以 raw 为实参的 TemplateMiddleListTemplateStrings
  2. last 为 « TemplateString(TemplateMiddle, raw) »。
  3. 返回 frontlast列表连接

13.2.8.3 Static Semantics: TemplateString ( templateToken, raw )

The abstract operation TemplateString takes arguments templateToken (a NoSubstitutionTemplate Parse Node, a TemplateHead Parse Node, a TemplateMiddle Parse Node, or a TemplateTail Parse Node) and raw (a Boolean) and returns a String or undefined. It performs the following steps when called:

  1. 如果 rawtrue,则
    1. stringtemplateTokenTRV
  2. 否则,
    1. stringtemplateTokenTV
  3. 返回 string
Note

如果 rawfalsetemplateToken 包含 NotEscapeSequence,则此操作返回 undefined。在所有其他情况下,它返回 String。

13.2.8.4 GetTemplateObject ( templateLiteral )

The abstract operation GetTemplateObject takes argument templateLiteral (a Parse Node) and returns an Array. It performs the following steps when called:

  1. realm当前 Realm Record
  2. templateRegistryrealm.[[TemplateMap]]
  3. templateRegistry 的每个元素 element,执行:
    1. 如果 element.[[Site]]templateLiteral 是同一个 Parse Node,则
      1. 返回 element.[[Array]]
  4. rawStrings 为以 true 为实参的 templateLiteralTemplateStrings
  5. 断言:rawStrings 是 Strings 的 List
  6. cookedStrings 为以 false 为实参的 templateLiteralTemplateStrings
  7. countList cookedStrings 中元素的数量。
  8. 断言:count ≤ 232 - 1。
  9. template 为 ! ArrayCreate(count)。
  10. rawObj 为 ! ArrayCreate(count)。
  11. index 为 0。
  12. 重复,当 index < count 时,
    1. propertyKey 为 ! ToString(𝔽(index))。
    2. cookedValuecookedStrings[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
Note 1

创建模板对象不会导致 abrupt completion。

Note 2

realm 的程序代码中的每个 TemplateLiteral 都与一个唯一的模板对象关联,该模板对象用于带标签 Template 的求值(13.2.8.6)。模板对象被冻结,并且每次求值特定带标签 Template 时都使用同一个模板对象。模板对象是在首次求值 TemplateLiteral 时惰性创建,还是在首次求值之前急切创建,是实现选择,对 ECMAScript 代码不可观察。

Note 3

本规范的未来版本可能会定义模板对象的附加不可枚举属性。

13.2.8.5 Runtime Semantics: SubstitutionEvaluation

The syntax-directed operation SubstitutionEvaluation takes no arguments and returns either a normal completion containing a List of ECMAScript language values or an abrupt completion. It is defined piecewise over the following productions:

TemplateSpans : TemplateTail
  1. 返回一个新的空 List
TemplateSpans : TemplateMiddleList TemplateTail
  1. 返回 ? TemplateMiddleListSubstitutionEvaluation
TemplateMiddleList : TemplateMiddle Expression
  1. subRef 为 ? ExpressionEvaluation
  2. sub 为 ? GetValue(subRef)。
  3. 返回 « sub »。
TemplateMiddleList : TemplateMiddleList TemplateMiddle Expression
  1. preceding 为 ? TemplateMiddleListSubstitutionEvaluation
  2. nextRef 为 ? ExpressionEvaluation
  3. next 为 ? GetValue(nextRef)。
  4. 返回 preceding 和 « next » 的列表连接

13.2.8.6 Runtime Semantics: Evaluation

TemplateLiteral : NoSubstitutionTemplate
  1. 返回 12.9.6 中定义的 NoSubstitutionTemplateTV
SubstitutionTemplate : TemplateHead Expression TemplateSpans
  1. head12.9.6 中定义的 TemplateHeadTV
  2. subRef 为 ? ExpressionEvaluation
  3. sub 为 ? GetValue(subRef)。
  4. middle 为 ? ToString(sub)。
  5. tail 为 ? TemplateSpansEvaluation
  6. 返回 headmiddletail字符串连接
Note 1

应用于 Expression 值的字符串转换语义类似于 String.prototype.concat,而不是 + 运算符。

TemplateSpans : TemplateTail
  1. 返回 12.9.6 中定义的 TemplateTailTV
TemplateSpans : TemplateMiddleList TemplateTail
  1. head 为 ? TemplateMiddleListEvaluation
  2. tail12.9.6 中定义的 TemplateTailTV
  3. 返回 headtail字符串连接
TemplateMiddleList : TemplateMiddle Expression
  1. head12.9.6 中定义的 TemplateMiddleTV
  2. subRef 为 ? ExpressionEvaluation
  3. sub 为 ? GetValue(subRef)。
  4. middle 为 ? ToString(sub)。
  5. 返回 headmiddle字符串连接
Note 2

应用于 Expression 值的字符串转换语义类似于 String.prototype.concat,而不是 + 运算符。

TemplateMiddleList : TemplateMiddleList TemplateMiddle Expression
  1. rest 为 ? TemplateMiddleListEvaluation
  2. middle12.9.6 中定义的 TemplateMiddleTV
  3. subRef 为 ? ExpressionEvaluation
  4. sub 为 ? GetValue(subRef)。
  5. last 为 ? ToString(sub)。
  6. 返回 restmiddlelast字符串连接
Note 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. 返回 ? exprEvaluation
ParenthesizedExpression : ( Expression )
  1. 返回 ? ExpressionEvaluation。这可能是 Reference 类型。
Note

此算法不会对 ExpressionEvaluation 应用 GetValue。其主要动机是让 deletetypeof 等运算符可以应用于带括号表达式。

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] ) ( ArgumentList[?Yield, ?Await] , ) 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
  • 如果此产生式匹配到任何源文本,则为语法错误。
Note

此产生式存在是为了防止自动分号插入规则(12.10)应用于以下代码:

a?.b
`c`

从而避免其被解释为两个有效语句。其目的是保持与没有可选链的类似代码一致:

a.b
`c`

这是一个有效语句,且不会应用自动分号插入。

ImportMeta : import . meta

13.3.2 属性访问器

Note

属性通过名称访问,使用点号记法:

或方括号记法:

点号记法由以下句法转换解释:

在行为上等同于

MemberExpression [ <identifier-name-string> ]

并且类似地

在行为上等同于

CallExpression [ <identifier-name-string> ]

其中 <identifier-name-string> 是 IdentifierNameStringValue

13.3.2.1 Runtime Semantics: Evaluation

MemberExpression : MemberExpression [ Expression ]
  1. baseRef 为 ? MemberExpressionEvaluation
  2. baseValue 为 ? GetValue(baseRef)。
  3. strictIsStrict(this MemberExpression)。
  4. 返回 ? EvaluatePropertyAccessWithExpressionKey(baseValue, Expression, strict)。
MemberExpression : MemberExpression . IdentifierName
  1. baseRef 为 ? MemberExpressionEvaluation
  2. baseValue 为 ? GetValue(baseRef)。
  3. strictIsStrict(this MemberExpression)。
  4. 返回 EvaluatePropertyAccessWithIdentifierKey(baseValue, IdentifierName, strict)。
MemberExpression : MemberExpression . PrivateIdentifier
  1. baseRef 为 ? MemberExpressionEvaluation
  2. baseValue 为 ? GetValue(baseRef)。
  3. fieldNameStringPrivateIdentifierStringValue
  4. 返回 MakePrivateReference(baseValue, fieldNameString)。
CallExpression : CallExpression [ Expression ]
  1. baseRef 为 ? CallExpressionEvaluation
  2. baseValue 为 ? GetValue(baseRef)。
  3. strictIsStrict(this CallExpression)。
  4. 返回 ? EvaluatePropertyAccessWithExpressionKey(baseValue, Expression, strict)。
CallExpression : CallExpression . IdentifierName
  1. baseRef 为 ? CallExpressionEvaluation
  2. baseValue 为 ? GetValue(baseRef)。
  3. strictIsStrict(this CallExpression)。
  4. 返回 EvaluatePropertyAccessWithIdentifierKey(baseValue, IdentifierName, strict)。
CallExpression : CallExpression . PrivateIdentifier
  1. baseRef 为 ? CallExpressionEvaluation
  2. baseValue 为 ? GetValue(baseRef)。
  3. fieldNameStringPrivateIdentifierStringValue
  4. 返回 MakePrivateReference(baseValue, fieldNameString)。

13.3.3 EvaluatePropertyAccessWithExpressionKey ( baseValue, expr, strict )

The abstract operation EvaluatePropertyAccessWithExpressionKey takes arguments baseValue (an ECMAScript language value), expr (an Expression Parse Node), and strict (a Boolean) and returns either a normal completion containing a Reference Record or an abrupt completion. It performs the following steps when called:

  1. propertyNameRef 为 ? exprEvaluation
  2. propertyNameValue 为 ? GetValue(propertyNameRef)。
  3. 注:在大多数情况下,ToPropertyKey 会在此步骤之后立即对 propertyNameValue 执行。不过,在 a[b] = c 的情况下,它要到 c 求值之后才会执行。
  4. 返回 Reference Record { [[Base]]: baseValue, [[ReferencedName]]: propertyNameValue, [[Strict]]: strict, [[ThisValue]]: empty }。

13.3.4 EvaluatePropertyAccessWithIdentifierKey ( baseValue, identifierName, strict )

The abstract operation EvaluatePropertyAccessWithIdentifierKey takes arguments baseValue (an ECMAScript language value), identifierName (an IdentifierName Parse Node), and strict (a Boolean) and returns a Reference Record. It performs the following steps when called:

  1. propertyNameStringidentifierNameStringValue
  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 )

The abstract operation EvaluateNew takes arguments constructExpr (a NewExpression Parse Node or a MemberExpression Parse Node) and argumentsNode (empty or an Arguments Parse Node) and returns either a normal completion containing an Object or an abrupt completion. It performs the following steps when called:

  1. ref 为 ? constructExprEvaluation
  2. ctor 为 ? GetValue(ref)。
  3. 如果 argumentsNodeempty,则
    1. argList 为一个新的空 List
  4. 否则,
    1. argList 为 ? argumentsNodeArgumentListEvaluation
  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. memberExprexprMemberExpression
  3. argsexprArguments
  4. ref 为 ? memberExprEvaluation
  5. func 为 ? GetValue(ref)。
  6. 如果 refReference RecordIsPropertyReference(ref) 是 false,且 ref.[[ReferencedName]]"eval",则
    1. 如果 SameValue(func, %eval%) 是 true,则
      1. argList 为 ? argsArgumentListEvaluation
      2. 如果 argList 没有元素,则返回 undefined
      3. evalArgargList 的第一个元素。
      4. 如果 IsStrict(this CallExpression) 是 true,则令 strictCallertrue;否则令 strictCallerfalse
      5. 返回 ? PerformEval(evalArg, strictCaller, true)。
  7. thisCall 为此 CallExpression
  8. tailCallIsInTailPosition(thisCall)。
  9. 返回 ? EvaluateCall(func, ref, args, tailCall)。

执行步骤 6.a.vCallExpression 求值是 direct eval

CallExpression : CallExpression Arguments
  1. ref 为 ? CallExpressionEvaluation
  2. func 为 ? GetValue(ref)。
  3. thisCall 为此 CallExpression
  4. tailCallIsInTailPosition(thisCall)。
  5. 返回 ? EvaluateCall(func, ref, Arguments, tailCall)。

13.3.6.2 EvaluateCall ( func, thisValueRef, argumentListNode, tailPosition )

The abstract operation EvaluateCall takes arguments func (an ECMAScript language value), thisValueRef (an ECMAScript language value or a Reference Record), argumentListNode (a Parse Node), and tailPosition (a Boolean) and returns either a normal completion containing an ECMAScript language value or an abrupt completion. It performs the following steps when called:

  1. 如果 thisValueRefReference Record,则
    1. 如果 IsPropertyReference(thisValueRef) 是 true,则
      1. thisValueGetThisValue(thisValueRef)。
    2. 否则,
      1. refEnvthisValueRef.[[Base]]
      2. 断言:refEnvEnvironment Record
      3. thisValuerefEnv.WithBaseObject()。
  2. 否则,
    1. thisValueundefined
  3. argList 为 ? argumentListNodeArgumentListEvaluation
  4. 如果 func 不是 Object,则抛出 TypeError 异常。
  5. 如果 IsCallable(func) 是 false,则抛出 TypeError 异常。
  6. 如果 tailPositiontrue,则执行 PrepareForTailCall()。
  7. 返回 ? Call(func, thisValue, argList)。

13.3.7 super 关键字

13.3.7.1 Runtime Semantics: Evaluation

SuperProperty : super [ Expression ]
  1. envRecordGetThisEnvironment()。
  2. actualThis 为 ? envRecord.GetThisBinding()。
  3. propertyNameRef 为 ? ExpressionEvaluation
  4. propertyNameValue 为 ? GetValue(propertyNameRef)。
  5. strictIsStrict(this SuperProperty)。
  6. 注:在大多数情况下,ToPropertyKey 会在此步骤之后立即对 propertyNameValue 执行。不过,在 super[b] = c 的情况下,它要到 c 求值之后才会执行。
  7. 返回 MakeSuperPropertyReference(actualThis, propertyNameValue, strict)。
SuperProperty : super . IdentifierName
  1. envRecordGetThisEnvironment()。
  2. actualThis 为 ? envRecord.GetThisBinding()。
  3. propertyKeyIdentifierNameStringValue
  4. strictIsStrict(this SuperProperty)。
  5. 返回 MakeSuperPropertyReference(actualThis, propertyKey, strict)。
SuperCall : super Arguments
  1. newTargetGetNewTarget()。
  2. 断言:newTarget 是 constructor。
  3. superCtorGetSuperConstructor()。
  4. argList 为 ? ArgumentsArgumentListEvaluation
  5. 如果 IsConstructor(superCtor) 是 false,则抛出 TypeError 异常。
  6. result 为 ? Construct(superCtor, argList, newTarget)。
  7. thisERGetThisEnvironment()。
  8. 断言:thisERFunction Environment Record
  9. 执行 ? BindThisValue(thisER, result)。
  10. funcObjthisER.[[FunctionObject]]
  11. 断言:funcObj 是 ECMAScript 函数对象
  12. 执行 ? InitializeInstanceElements(result, funcObj)。
  13. 返回 result

13.3.7.2 GetSuperConstructor ( )

The abstract operation GetSuperConstructor takes no arguments and returns an Object or null. It performs the following steps when called:

  1. envRecordGetThisEnvironment()。
  2. 断言:envRecordFunction Environment Record
  3. activeFuncenvRecord.[[FunctionObject]]
  4. 断言:activeFunc 是 ECMAScript 函数对象
  5. superCtor 为 ! activeFunc.[[GetPrototypeOf]]()。
  6. 返回 superCtor

13.3.7.3 MakeSuperPropertyReference ( actualThis, propertyKey, strict )

The abstract operation MakeSuperPropertyReference takes arguments actualThis (an ECMAScript language value), propertyKey (an ECMAScript language value), and strict (a Boolean) and returns a Super Reference Record. It performs the following steps when called:

  1. envRecordGetThisEnvironment()。
  2. 断言:envRecord.HasSuperBinding() 是 true
  3. 断言:envRecordFunction Environment Record
  4. baseValueGetSuperBase(envRecord)。
  5. 返回 Reference Record { [[Base]]: baseValue, [[ReferencedName]]: propertyKey, [[Strict]]: strict, [[ThisValue]]: actualThis }。

13.3.8 实参列表

Note

求值实参列表会产生一个值的 List

13.3.8.1 Runtime Semantics: ArgumentListEvaluation

The syntax-directed operation ArgumentListEvaluation takes no arguments and returns either a normal completion containing a List of ECMAScript language values or an abrupt completion. It is defined piecewise over the following productions:

Arguments : ( )
  1. 返回一个新的空 List
ArgumentList : AssignmentExpression
  1. ref 为 ? AssignmentExpressionEvaluation
  2. arg 为 ? GetValue(ref)。
  3. 返回 « arg »。
ArgumentList : ... AssignmentExpression
  1. list 为一个新的空 List
  2. spreadRef 为 ? AssignmentExpressionEvaluation
  3. spreadObj 为 ? GetValue(spreadRef)。
  4. iteratorRecord 为 ? GetIterator(spreadObj, sync)。
  5. 重复:
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 nextdone,则返回 list
    3. next 追加到 list
ArgumentList : ArgumentList , AssignmentExpression
  1. precedingArgs 为 ? ArgumentListArgumentListEvaluation
  2. ref 为 ? AssignmentExpressionEvaluation
  3. arg 为 ? GetValue(ref)。
  4. 返回 precedingArgs 和 « arg » 的列表连接
ArgumentList : ArgumentList , ... AssignmentExpression
  1. precedingArgs 为 ? ArgumentListArgumentListEvaluation
  2. spreadRef 为 ? AssignmentExpressionEvaluation
  3. iteratorRecord 为 ? GetIterator(? GetValue(spreadRef), sync)。
  4. 重复:
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 nextdone,则返回 precedingArgs
    3. next 追加到 precedingArgs
TemplateLiteral : NoSubstitutionTemplate
  1. templateLiteral 为此 TemplateLiteral
  2. siteObjGetTemplateObject(templateLiteral)。
  3. 返回 « siteObj »。
TemplateLiteral : SubstitutionTemplate
  1. templateLiteral 为此 TemplateLiteral
  2. siteObjGetTemplateObject(templateLiteral)。
  3. remaining 为 ? SubstitutionTemplateArgumentListEvaluation
  4. 返回 « siteObj » 和 remaining列表连接
SubstitutionTemplate : TemplateHead Expression TemplateSpans
  1. firstSubRef 为 ? ExpressionEvaluation
  2. firstSub 为 ? GetValue(firstSubRef)。
  3. restSub 为 ? TemplateSpansSubstitutionEvaluation
  4. 断言:restSub 是一个可能为空的 List
  5. 返回 « firstSub » 和 restSub列表连接

13.3.9 可选链

Note
可选链是一个由一个或多个属性访问和函数调用组成的链,其中第一个以 token ?. 开头。

13.3.9.1 Runtime Semantics: Evaluation

OptionalExpression : MemberExpression OptionalChain
  1. baseRef 为 ? MemberExpressionEvaluation
  2. baseValue 为 ? GetValue(baseRef)。
  3. 如果 baseValueundefinednull,则
    1. 返回 undefined
  4. 返回 ? 以 baseValuebaseRef 为实参执行 OptionalChainChainEvaluation
OptionalExpression : CallExpression OptionalChain
  1. baseRef 为 ? CallExpressionEvaluation
  2. baseValue 为 ? GetValue(baseRef)。
  3. 如果 baseValueundefinednull,则
    1. 返回 undefined
  4. 返回 ? 以 baseValuebaseRef 为实参执行 OptionalChainChainEvaluation
OptionalExpression : OptionalExpression OptionalChain
  1. baseRef 为 ? OptionalExpressionEvaluation
  2. baseValue 为 ? GetValue(baseRef)。
  3. 如果 baseValueundefinednull,则
    1. 返回 undefined
  4. 返回 ? 以 baseValuebaseRef 为实参执行 OptionalChainChainEvaluation

13.3.9.2 Runtime Semantics: ChainEvaluation

The syntax-directed operation ChainEvaluation takes arguments baseValue (an ECMAScript language value) and baseRef (an ECMAScript language value or a Reference Record) and returns either a normal completion containing either an ECMAScript language value or a Reference Record, or an abrupt completion. It is defined piecewise over the following productions:

OptionalChain : ?. Arguments
  1. thisChain 为此 OptionalChain
  2. tailCallIsInTailPosition(thisChain)。
  3. 返回 ? EvaluateCall(baseValue, baseRef, Arguments, tailCall)。
OptionalChain : ?. [ Expression ]
  1. strictIsStrict(this OptionalChain)。
  2. 返回 ? EvaluatePropertyAccessWithExpressionKey(baseValue, Expression, strict)。
OptionalChain : ?. IdentifierName
  1. strictIsStrict(this OptionalChain)。
  2. 返回 EvaluatePropertyAccessWithIdentifierKey(baseValue, IdentifierName, strict)。
OptionalChain : ?. PrivateIdentifier
  1. fieldNameStringPrivateIdentifierStringValue
  2. 返回 MakePrivateReference(baseValue, fieldNameString)。
OptionalChain : OptionalChain Arguments
  1. optionalChainOptionalChain
  2. newRef 为 ? 以 baseValuebaseRef 为实参执行 optionalChainChainEvaluation
  3. newValue 为 ? GetValue(newRef)。
  4. thisChain 为此 OptionalChain
  5. tailCallIsInTailPosition(thisChain)。
  6. 返回 ? EvaluateCall(newValue, newRef, Arguments, tailCall)。
OptionalChain : OptionalChain [ Expression ]
  1. optionalChainOptionalChain
  2. newRef 为 ? 以 baseValuebaseRef 为实参执行 optionalChainChainEvaluation
  3. newValue 为 ? GetValue(newRef)。
  4. strictIsStrict(this OptionalChain)。
  5. 返回 ? EvaluatePropertyAccessWithExpressionKey(newValue, Expression, strict)。
OptionalChain : OptionalChain . IdentifierName
  1. optionalChainOptionalChain
  2. newRef 为 ? 以 baseValuebaseRef 为实参执行 optionalChainChainEvaluation
  3. newValue 为 ? GetValue(newRef)。
  4. strictIsStrict(this OptionalChain)。
  5. 返回 EvaluatePropertyAccessWithIdentifierKey(newValue, IdentifierName, strict)。
OptionalChain : OptionalChain . PrivateIdentifier
  1. optionalChainOptionalChain
  2. newRef 为 ? 以 baseValuebaseRef 为实参执行 optionalChainChainEvaluation
  3. newValue 为 ? GetValue(newRef)。
  4. fieldNameStringPrivateIdentifierStringValue
  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 ] )

The abstract operation EvaluateImportCall takes argument specifierExpr (a Parse Node) and optional argument optionsExpr (a Parse Node) and returns either a normal completion containing a Promise or an abrupt completion. It performs the following steps when called:

  1. referrerGetActiveScriptOrModule()。
  2. 如果 referrernull,则将 referrer 设置为当前 Realm Record
  3. specifierRef 为 ? specifierExprEvaluation
  4. specifier 为 ? GetValue(specifierRef)。
  5. 如果 optionsExpr 存在,则
    1. optionsRef 为 ? optionsExprEvaluation
    2. options 为 ? GetValue(optionsRef)。
  6. 否则,
    1. optionsundefined
  7. promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  8. specifierStringCompletion(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. attrsObjCompletion(Get(options, "with")))。
    3. IfAbruptRejectPromise(attrsObj, promiseCapability)。
    4. 如果 attrsObj 不是 undefined,则
      1. 如果 attrsObj 不是 Object,则
        1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « 一个新创建的 TypeError 对象 »)。
        2. 返回 promiseCapability.[[Promise]]
      2. entriesCompletion(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. 按照 attrs[[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 )

The abstract operation ContinueDynamicImport takes arguments promiseCapability (a PromiseCapability Record) and moduleCompletion (either a normal completion containing a Module Record or a throw completion) and returns unused. 它完成最初由 import() 调用启动的动态 import 过程,并根据情况 resolve 或 reject 该调用返回的 promise。 It performs the following steps when called:

  1. 如果 moduleCompletion 是 abrupt completion,则
    1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « moduleCompletion.[[Value]] »)。
    2. 返回 unused
  2. modulemoduleCompletion.[[Value]]
  3. loadPromisemodule.LoadRequestedModules()。
  4. rejectedClosure 为一个具有形参 (reason) 的新 Abstract Closure,它捕获 promiseCapability,并在被调用时执行以下步骤:
    1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « reason »)。
    2. 返回 NormalCompletion(undefined)。
  5. onRejectedCreateBuiltinFunction(rejectedClosure, 1, "", « »)。
  6. linkAndEvaluateClosure 为一个不带形参的新 Abstract Closure,它捕获 modulepromiseCapabilityonRejected,并在被调用时执行以下步骤:
    1. linkCompletion(module.Link())。
    2. 如果 link 是 abrupt completion,则
      1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « link.[[Value]] »)。
      2. 返回 NormalCompletion(undefined)。
    3. evaluatePromisemodule.Evaluate()。
    4. fulfilledClosure 为一个不带形参的新 Abstract Closure,它捕获 modulepromiseCapability,并在被调用时执行以下步骤:
      1. namespaceGetModuleNamespace(module)。
      2. 执行 ! Call(promiseCapability.[[Resolve]], undefined, « namespace »)。
      3. 返回 NormalCompletion(undefined)。
    5. onFulfilledCreateBuiltinFunction(fulfilledClosure, 0, "", « »)。
    6. 执行 PerformPromiseThen(evaluatePromise, onFulfilled, onRejected)。
    7. 返回 unused
  7. linkAndEvaluateCreateBuiltinFunction(linkAndEvaluateClosure, 0, "", « »)。
  8. 执行 PerformPromiseThen(loadPromise, linkAndEvaluate, onRejected)。
  9. 返回 unused

13.3.11 带标签模板

Note

带标签模板是一种函数调用,其中该调用的实参派生自 TemplateLiteral13.2.8)。实际实参包括一个模板对象(13.2.8.4)以及通过求值嵌入在 TemplateLiteral 内部的表达式所产生的值。

13.3.11.1 Runtime Semantics: Evaluation

MemberExpression : MemberExpression TemplateLiteral
  1. tagRef 为 ? MemberExpressionEvaluation
  2. tagFunc 为 ? GetValue(tagRef)。
  3. thisCall 为此 MemberExpression
  4. tailCallIsInTailPosition(thisCall)。
  5. 返回 ? EvaluateCall(tagFunc, tagRef, TemplateLiteral, tailCall)。
CallExpression : CallExpression TemplateLiteral
  1. tagRef 为 ? CallExpressionEvaluation
  2. tagFunc 为 ? GetValue(tagRef)。
  3. thisCall 为此 CallExpression
  4. tailCallIsInTailPosition(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. moduleGetActiveScriptOrModule()。
  2. 断言:moduleSource Text Module Record
  3. importMetamodule.[[ImportMeta]]
  4. 如果 importMetaempty,则
    1. importMeta 设置为 OrdinaryObjectCreate(null)。
    2. importMetaValuesHostGetImportMetaProperties(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 )

The host-defined abstract operation HostGetImportMetaProperties takes argument moduleRecord (a Module Record) and returns a List of Records with fields [[Key]] (a property key) and [[Value]] (an ECMAScript language value). 它允许宿主import.meta 返回的对象提供属性键和值。

HostGetImportMetaProperties 的默认实现是返回一个新的空 List

13.3.12.1.2 HostFinalizeImportMeta ( importMeta, moduleRecord )

The host-defined abstract operation HostFinalizeImportMeta takes arguments importMeta (an Object) and moduleRecord (a Module Record) and returns 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 为 ? LeftHandSideExpressionEvaluation
  2. 如果 LeftHandSideExpressionAssignmentTargetTypeweb-compat,则抛出 ReferenceError 异常。
  3. oldValue 为 ? ToNumeric(? GetValue(lhs))。
  4. 如果 oldValue 是 Number,则
    1. newValueNumber::add(oldValue, 1𝔽)。
  5. 否则,
    1. 断言:oldValue 是 BigInt。
    2. newValueBigInt::add(oldValue, 1)。
  6. 执行 ? PutValue(lhs, newValue)。
  7. 返回 oldValue

13.4.3 后缀递减运算符

13.4.3.1 Runtime Semantics: Evaluation

UpdateExpression : LeftHandSideExpression --
  1. lhs 为 ? LeftHandSideExpressionEvaluation
  2. 如果 LeftHandSideExpressionAssignmentTargetTypeweb-compat,则抛出 ReferenceError 异常。
  3. oldValue 为 ? ToNumeric(? GetValue(lhs))。
  4. 如果 oldValue 是 Number,则
    1. newValueNumber::subtract(oldValue, 1𝔽)。
  5. 否则,
    1. 断言:oldValue 是 BigInt。
    2. newValueBigInt::subtract(oldValue, 1)。
  6. 执行 ? PutValue(lhs, newValue)。
  7. 返回 oldValue

13.4.4 前缀递增运算符

13.4.4.1 Runtime Semantics: Evaluation

UpdateExpression : ++ UnaryExpression
  1. expr 为 ? UnaryExpressionEvaluation
  2. 如果 UnaryExpressionAssignmentTargetTypeweb-compat,则抛出 ReferenceError 异常。
  3. oldValue 为 ? ToNumeric(? GetValue(expr))。
  4. 如果 oldValue 是 Number,则
    1. newValueNumber::add(oldValue, 1𝔽)。
  5. 否则,
    1. 断言:oldValue 是 BigInt。
    2. newValueBigInt::add(oldValue, 1)。
  6. 执行 ? PutValue(expr, newValue)。
  7. 返回 newValue

13.4.5 前缀递减运算符

13.4.5.1 Runtime Semantics: Evaluation

UpdateExpression : -- UnaryExpression
  1. expr 为 ? UnaryExpressionEvaluation
  2. 如果 UnaryExpressionAssignmentTargetTypeweb-compat,则抛出 ReferenceError 异常。
  3. oldValue 为 ? ToNumeric(? GetValue(expr))。
  4. 如果 oldValue 是 Number,则
    1. newValueNumber::subtract(oldValue, 1𝔽)。
  5. 否则,
    1. 断言:oldValue 是 BigInt。
    2. newValueBigInt::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 Note

最后一条规则意味着,像 delete (((foo))) 这样的表达式会因为第一条规则的递归应用而产生早期错误

13.5.1.2 Runtime Semantics: Evaluation

UnaryExpression : delete UnaryExpression
  1. ref 为 ? UnaryExpressionEvaluation
  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. 如果 deleteStatusfalseref.[[Strict]]true,则抛出 TypeError 异常。
    7. 返回 deleteStatus
  5. baseref.[[Base]]
  6. 断言:baseEnvironment Record
  7. 返回 ? base.DeleteBinding(ref.[[ReferencedName]])
Note 1

delete 运算符出现在严格模式代码中时,如果其 UnaryExpression 是对变量、函数实参或函数名的直接引用,则会抛出 SyntaxError 异常。此外,如果 delete 运算符出现在严格模式代码中,且要删除的属性具有 { [[Configurable]]: false } 特性(或以其他方式无法删除),则会抛出 TypeError 异常。

Note 2

在步骤 4.c 中可能创建的对象,在上述抽象操作普通对象 [[Delete]] 内部方法之外不可访问。实现可以选择避免实际创建该对象。

13.5.2 void 运算符

13.5.2.1 Runtime Semantics: Evaluation

UnaryExpression : void UnaryExpression
  1. expr 为 ? UnaryExpressionEvaluation
  2. 执行 ? GetValue(expr)。
  3. 返回 undefined
Note

即使其值未被使用,也必须调用 GetValue,因为它可能具有可观察的副作用。

13.5.3 typeof 运算符

13.5.3.1 Runtime Semantics: Evaluation

UnaryExpression : typeof UnaryExpression
  1. value 为 ? UnaryExpressionEvaluation
  2. 如果 valueReference Record,则
    1. 如果 IsUnresolvableReference(value) 是 true,则返回 "undefined"
  3. value 设置为 ? GetValue(value)。
  4. 如果 valueundefined,则返回 "undefined"
  5. 如果 valuenull,则返回 "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. 如果宿主是 Web 浏览器,或以其他方式支持 [[IsHTMLDDA]] 内部槽,则
    1. 如果 value 具有 [[IsHTMLDDA]] 内部槽,则返回 "undefined"
  13. 如果 value 具有 [[Call]] 内部方法,则返回 "function"
  14. 返回 "object"

13.5.4 一元 + 运算符

Note

一元 + 运算符将其操作数转换为 Number 类型

13.5.4.1 Runtime Semantics: Evaluation

UnaryExpression : + UnaryExpression
  1. expr 为 ? UnaryExpressionEvaluation
  2. 返回 ? ToNumber(? GetValue(expr))。

13.5.5 一元 - 运算符

Note

一元 - 运算符将其操作数转换为数值,然后对其取负。对 +0𝔽 取负会产生 -0𝔽,对 -0𝔽 取负会产生 +0𝔽

13.5.5.1 Runtime Semantics: Evaluation

UnaryExpression : - UnaryExpression
  1. expr 为 ? UnaryExpressionEvaluation
  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 为 ? UnaryExpressionEvaluation
  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 为 ? UnaryExpressionEvaluation
  2. oldValueToBoolean(? GetValue(expr))。
  3. 如果 oldValuetrue,则返回 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 * / % Note
  • * 运算符执行乘法,产生其操作数的乘积。
  • / 运算符执行除法,产生其操作数的商。
  • % 运算符从隐含的除法中产生其操作数的余数。

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 加法运算符(+

Note

加法运算符执行字符串连接或数值加法。

13.8.1.1 Runtime Semantics: Evaluation

AdditiveExpression : AdditiveExpression + MultiplicativeExpression
  1. 返回 ? EvaluateStringOrNumericBinaryExpression(AdditiveExpression, +, MultiplicativeExpression)。

13.8.2 减法运算符(-

Note

- 运算符执行减法,产生其操作数的差。

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 左移运算符(<<

Note

按右操作数指定的数量,对左操作数执行按位左移操作。

13.9.1.1 Runtime Semantics: Evaluation

ShiftExpression : ShiftExpression << AdditiveExpression
  1. 返回 ? EvaluateStringOrNumericBinaryExpression(ShiftExpression, <<, AdditiveExpression)。

13.9.2 带符号右移运算符(>>

Note

按右操作数指定的数量,对左操作数执行符号填充的按位右移操作。

13.9.2.1 Runtime Semantics: Evaluation

ShiftExpression : ShiftExpression >> AdditiveExpression
  1. 返回 ? EvaluateStringOrNumericBinaryExpression(ShiftExpression, >>, AdditiveExpression)。

13.9.3 无符号右移运算符(>>>

Note

按右操作数指定的数量,对左操作数执行零填充的按位右移操作。

13.9.3.1 Runtime Semantics: Evaluation

ShiftExpression : ShiftExpression >>> AdditiveExpression
  1. 返回 ? EvaluateStringOrNumericBinaryExpression(ShiftExpression, >>>, AdditiveExpression)。

13.10 关系运算符

Note 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] Note 2

需要 [In] 语法参数,以避免将关系表达式中的 in 运算符与 for 语句中的 in 运算符混淆。

13.10.1 Runtime Semantics: Evaluation

RelationalExpression : RelationalExpression < ShiftExpression
  1. leftRef 为 ? RelationalExpressionEvaluation
  2. leftValue 为 ? GetValue(leftRef)。
  3. rightRef 为 ? ShiftExpressionEvaluation
  4. rightValue 为 ? GetValue(rightRef)。
  5. result 为 ? IsLessThan(leftValue, rightValue, true)。
  6. 如果 resultundefined,则返回 false
  7. 返回 result
RelationalExpression : RelationalExpression > ShiftExpression
  1. leftRef 为 ? RelationalExpressionEvaluation
  2. leftValue 为 ? GetValue(leftRef)。
  3. rightRef 为 ? ShiftExpressionEvaluation
  4. rightValue 为 ? GetValue(rightRef)。
  5. result 为 ? IsLessThan(rightValue, leftValue, false)。
  6. 如果 resultundefined,则返回 false
  7. 返回 result
RelationalExpression : RelationalExpression <= ShiftExpression
  1. leftRef 为 ? RelationalExpressionEvaluation
  2. leftValue 为 ? GetValue(leftRef)。
  3. rightRef 为 ? ShiftExpressionEvaluation
  4. rightValue 为 ? GetValue(rightRef)。
  5. result 为 ? IsLessThan(rightValue, leftValue, false)。
  6. 如果 resulttrueundefined,则返回 false
  7. 返回 true
RelationalExpression : RelationalExpression >= ShiftExpression
  1. leftRef 为 ? RelationalExpressionEvaluation
  2. leftValue 为 ? GetValue(leftRef)。
  3. rightRef 为 ? ShiftExpressionEvaluation
  4. rightValue 为 ? GetValue(rightRef)。
  5. result 为 ? IsLessThan(leftValue, rightValue, true)。
  6. 如果 resulttrueundefined,则返回 false
  7. 返回 true
RelationalExpression : RelationalExpression instanceof ShiftExpression
  1. leftRef 为 ? RelationalExpressionEvaluation
  2. leftValue 为 ? GetValue(leftRef)。
  3. rightRef 为 ? ShiftExpressionEvaluation
  4. rightValue 为 ? GetValue(rightRef)。
  5. 返回 ? InstanceofOperator(leftValue, rightValue)。
RelationalExpression : RelationalExpression in ShiftExpression
  1. leftRef 为 ? RelationalExpressionEvaluation
  2. leftValue 为 ? GetValue(leftRef)。
  3. rightRef 为 ? ShiftExpressionEvaluation
  4. rightValue 为 ? GetValue(rightRef)。
  5. 如果 rightValue 不是 Object,则抛出 TypeError 异常。
  6. 返回 ? HasProperty(rightValue, ? ToPropertyKey(leftValue))。
RelationalExpression : PrivateIdentifier in ShiftExpression
  1. privateIdentifierPrivateIdentifierStringValue
  2. rightRef 为 ? ShiftExpressionEvaluation
  3. rightValue 为 ? GetValue(rightRef)。
  4. 如果 rightValue 不是 Object,则抛出 TypeError 异常。
  5. privateEnv 为运行中的执行上下文的 PrivateEnvironment。
  6. 断言:privateEnv 不是 null
  7. privateNameResolvePrivateIdentifier(privateEnv, privateIdentifier)。
  8. 如果 PrivateElementFind(rightValue, privateName) 是 empty,则返回 false
  9. 返回 true

13.10.2 InstanceofOperator ( value, target )

The abstract operation InstanceofOperator takes arguments value (an ECMAScript language value) and target (an ECMAScript language value) and returns either a normal completion containing a Boolean or a throw completion. 它实现用于确定 value 是否为 target 实例的通用算法:要么咨询 target%Symbol.hasInstance% 方法;如果不存在,则确定 target"prototype" 属性值是否存在于 value 的原型链中。 It performs the following steps when called:

  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)。
Note

步骤 45 提供与 ECMAScript 早期版本的兼容性,早期版本没有使用 %Symbol.hasInstance% 方法来定义 instanceof 运算符语义。如果对象没有定义或继承 %Symbol.hasInstance%,则使用默认的 instanceof 语义。

13.11 相等运算符

Note

求值相等运算符的结果始终是 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 为 ? EqualityExpressionEvaluation
  2. leftValue 为 ? GetValue(leftRef)。
  3. rightRef 为 ? RelationalExpressionEvaluation
  4. rightValue 为 ? GetValue(rightRef)。
  5. 返回 ? IsLooselyEqual(rightValue, leftValue)。
EqualityExpression : EqualityExpression != RelationalExpression
  1. leftRef 为 ? EqualityExpressionEvaluation
  2. leftValue 为 ? GetValue(leftRef)。
  3. rightRef 为 ? RelationalExpressionEvaluation
  4. rightValue 为 ? GetValue(rightRef)。
  5. result 为 ? IsLooselyEqual(rightValue, leftValue)。
  6. 如果 resulttrue,则返回 false
  7. 返回 true
EqualityExpression : EqualityExpression === RelationalExpression
  1. leftRef 为 ? EqualityExpressionEvaluation
  2. leftValue 为 ? GetValue(leftRef)。
  3. rightRef 为 ? RelationalExpressionEvaluation
  4. rightValue 为 ? GetValue(rightRef)。
  5. 返回 IsStrictlyEqual(rightValue, leftValue)。
EqualityExpression : EqualityExpression !== RelationalExpression
  1. leftRef 为 ? EqualityExpressionEvaluation
  2. leftValue 为 ? GetValue(leftRef)。
  3. rightRef 为 ? RelationalExpressionEvaluation
  4. rightValue 为 ? GetValue(rightRef)。
  5. resultIsStrictlyEqual(rightValue, leftValue)。
  6. 如果 resulttrue,则返回 false
  7. 返回 true
Note 1

相等运算符维持以下不变量:

  • A != B 等价于 !(A == B)
  • A == B 等价于 B == A,但 AB 的求值顺序除外。
Note 2

相等运算符并不总是具有传递性。例如,可能有两个不同的 String 对象,每个都表示相同的 String 值;每个 String 对象都会被 == 运算符认为等于该 String 值,但这两个 String 对象彼此并不相等。例如:

  • new String("a") == "a""a" == new String("a") 都是 true
  • new String("a") == new String("a")false
Note 3

String 的比较使用对代码单元值序列的简单相等性测试。不会尝试使用 Unicode 规范中定义的更复杂、面向语义的字符或字符串相等性和排序顺序定义。因此,按照 Unicode 标准规范等价的 Strings 值可能会测试为不相等。实际上,此算法假定两个 Strings 都已经处于规范化形式。

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] Note

&&|| 运算符产生的值不一定是 Boolean 类型。产生的值始终是两个操作数表达式之一的值。

13.13.1 Runtime Semantics: Evaluation

LogicalANDExpression : LogicalANDExpression && BitwiseORExpression
  1. leftRef 为 ? LogicalANDExpressionEvaluation
  2. leftValue 为 ? GetValue(leftRef)。
  3. 如果 ToBoolean(leftValue) 是 false,则返回 leftValue
  4. rightRef 为 ? BitwiseORExpressionEvaluation
  5. 返回 ? GetValue(rightRef)。
LogicalORExpression : LogicalORExpression || LogicalANDExpression
  1. leftRef 为 ? LogicalORExpressionEvaluation
  2. leftValue 为 ? GetValue(leftRef)。
  3. 如果 ToBoolean(leftValue) 是 true,则返回 leftValue
  4. rightRef 为 ? LogicalANDExpressionEvaluation
  5. 返回 ? GetValue(rightRef)。
CoalesceExpression : CoalesceExpressionHead ?? BitwiseORExpression
  1. leftRef 为 ? CoalesceExpressionHeadEvaluation
  2. leftValue 为 ? GetValue(leftRef)。
  3. 如果 leftValue 既不是 undefined 也不是 null,则返回 leftValue
  4. rightRef 为 ? BitwiseORExpressionEvaluation
  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] Note

ECMAScript 中 ConditionalExpression 的语法与 C 和 Java 中的略有不同,后两者都允许第二个子表达式为 Expression,但限制第三个表达式为 ConditionalExpression。ECMAScript 中这种差异的动机是允许赋值表达式受条件表达式任一分支控制,并消除逗号表达式作为中间表达式时令人困惑且相当无用的情况。

13.14.1 Runtime Semantics: Evaluation

ConditionalExpression : ShortCircuitExpression ? AssignmentExpression : AssignmentExpression
  1. leftRef 为 ? ShortCircuitExpressionEvaluation
  2. leftValueToBoolean(? GetValue(leftRef))。
  3. 如果 leftValuetrue,则
    1. trueRef 为 ? 第一个 AssignmentExpressionEvaluation
    2. 返回 ? GetValue(trueRef)。
  4. falseRef 为 ? 第二个 AssignmentExpressionEvaluation
  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 为 ? LeftHandSideExpressionEvaluation
    2. 如果 LeftHandSideExpressionAssignmentTargetTypeweb-compat,则抛出 ReferenceError 异常。
    3. 如果 IsAnonymousFunctionDefinition(AssignmentExpression) 是 trueLeftHandSideExpressionIsIdentifierReftrue,则
      1. lhsLeftHandSideExpressionStringValue
      2. rightValue 为 ? 以 lhs 为实参执行 AssignmentExpressionNamedEvaluation
    4. 否则,
      1. rightRef 为 ? AssignmentExpressionEvaluation
      2. rightValue 为 ? GetValue(rightRef)。
    5. 执行 ? PutValue(leftRef, rightValue)。
    6. 返回 rightValue
  2. assignmentPattern 为由 LeftHandSideExpression 覆盖的 AssignmentPattern
  3. rightRef 为 ? AssignmentExpressionEvaluation
  4. rightValue 为 ? GetValue(rightRef)。
  5. 执行 ? 以 rightValue 为实参执行 assignmentPatternDestructuringAssignmentEvaluation
  6. 返回 rightValue
AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression
  1. leftRef 为 ? LeftHandSideExpressionEvaluation
  2. 如果 LeftHandSideExpressionAssignmentTargetTypeweb-compat,则抛出 ReferenceError 异常。
  3. leftValue 为 ? GetValue(leftRef)。
  4. rightRef 为 ? AssignmentExpressionEvaluation
  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 为 ? LeftHandSideExpressionEvaluation
  2. leftValue 为 ? GetValue(leftRef)。
  3. 如果 ToBoolean(leftValue) 是 false,则返回 leftValue
  4. 如果 IsAnonymousFunctionDefinition(AssignmentExpression) 是 trueLeftHandSideExpressionIsIdentifierReftrue,则
    1. lhsLeftHandSideExpressionStringValue
    2. rightValue 为 ? 以 lhs 为实参执行 AssignmentExpressionNamedEvaluation
  5. 否则,
    1. rightRef 为 ? AssignmentExpressionEvaluation
    2. rightValue 为 ? GetValue(rightRef)。
  6. 执行 ? PutValue(leftRef, rightValue)。
  7. 返回 rightValue
AssignmentExpression : LeftHandSideExpression ||= AssignmentExpression
  1. leftRef 为 ? LeftHandSideExpressionEvaluation
  2. leftValue 为 ? GetValue(leftRef)。
  3. 如果 ToBoolean(leftValue) 是 true,则返回 leftValue
  4. 如果 IsAnonymousFunctionDefinition(AssignmentExpression) 是 trueLeftHandSideExpressionIsIdentifierReftrue,则
    1. lhsLeftHandSideExpressionStringValue
    2. rightValue 为 ? 以 lhs 为实参执行 AssignmentExpressionNamedEvaluation
  5. 否则,
    1. rightRef 为 ? AssignmentExpressionEvaluation
    2. rightValue 为 ? GetValue(rightRef)。
  6. 执行 ? PutValue(leftRef, rightValue)。
  7. 返回 rightValue
AssignmentExpression : LeftHandSideExpression ??= AssignmentExpression
  1. leftRef 为 ? LeftHandSideExpressionEvaluation
  2. leftValue 为 ? GetValue(leftRef)。
  3. 如果 leftValue 既不是 undefined 也不是 null,则返回 leftValue
  4. 如果 IsAnonymousFunctionDefinition(AssignmentExpression) 是 trueLeftHandSideExpressionIsIdentifierReftrue,则
    1. lhsLeftHandSideExpressionStringValue
    2. rightValue 为 ? 以 lhs 为实参执行 AssignmentExpressionNamedEvaluation
  5. 否则,
    1. rightRef 为 ? AssignmentExpressionEvaluation
    2. rightValue 为 ? GetValue(rightRef)。
  6. 执行 ? PutValue(leftRef, rightValue)。
  7. 返回 rightValue
Note

当此表达式出现在严格模式代码中时,如果步骤 1.e3222 中的 leftRef 是无法解析的引用,则为运行时错误。如果是这种情况,则会抛出 ReferenceError 异常。此外,如果步骤 9666 中的 leftRef 是对特性值为 { [[Writable]]: false } 的数据属性、特性值为 { [[Set]]: undefined } 的访问器属性,或对 IsExtensible 谓词返回值为 false 的对象的不存在属性的引用,则为运行时错误。在这些情况下会抛出 TypeError 异常。

13.15.3 ApplyStringOrNumericBinaryOperator ( leftValue, opText, rightValue )

The abstract operation ApplyStringOrNumericBinaryOperator takes arguments leftValue (an ECMAScript language value), opText (**, *, /, %, +, -, <<, >>, >>>, &, ^, or |), and rightValue (an ECMAScript language value) and returns either a normal completion containing either a String, a BigInt, or a Number, or a throw completion. It performs the following steps when called:

  1. 如果 opText+,则
    1. leftPrimitive 为 ? ToPrimitive(leftValue)。
    2. rightPrimitive 为 ? ToPrimitive(rightValue)。
    3. 如果 leftPrimitive 是 String 或 rightPrimitive 是 String,则
      1. leftString 为 ? ToString(leftPrimitive)。
      2. rightString 为 ? ToString(rightPrimitive)。
      3. 返回 leftStringrightString字符串连接
    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)。
Note 1

在步骤 1.a1.b 中调用 ToPrimitive 时不提供 hint。除 Dates 外的所有标准对象都会像给出了 number 一样处理没有 hint 的情况;Dates 会像给出了 string 一样处理没有 hint 的情况。异质对象可以以其他某种方式处理没有 hint 的情况。

Note 2

步骤 1.cIsLessThan 算法的步骤 3 不同,因为它使用逻辑或操作,而不是逻辑与操作。

13.15.4 EvaluateStringOrNumericBinaryExpression ( leftOperand, opText, rightOperand )

The abstract operation EvaluateStringOrNumericBinaryExpression takes arguments leftOperand (a Parse Node), opText (**, *, /, %, +, -, <<, >>, >>>, &, ^, or |), and rightOperand (a Parse Node) and returns either a normal completion containing either a String, a BigInt, or a Number, or an abrupt completion. It performs the following steps when called:

  1. leftRef 为 ? leftOperandEvaluation
  2. leftValue 为 ? GetValue(leftRef)。
  3. rightRef 为 ? rightOperandEvaluation
  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] } { AssignmentPropertyList[?Yield, ?Await] , AssignmentRestProperty[?Yield, ?Await]opt } 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

The syntax-directed operation DestructuringAssignmentEvaluation takes argument value (an ECMAScript language value) and returns either a normal completion containing unused or an abrupt completion. It is defined piecewise over the following productions:

ObjectAssignmentPattern : { }
  1. 执行 ? RequireObjectCoercible(value)。
  2. 返回 unused
ObjectAssignmentPattern : { AssignmentPropertyList } { AssignmentPropertyList , }
  1. 执行 ? RequireObjectCoercible(value)。
  2. 执行 ? 以 value 为实参执行 AssignmentPropertyListPropertyDestructuringAssignmentEvaluation
  3. 返回 unused
ObjectAssignmentPattern : { AssignmentRestProperty }
  1. 执行 ? RequireObjectCoercible(value)。
  2. excludedNames 为新的空 List
  3. 返回 ? 以 valueexcludedNames 为实参执行 AssignmentRestPropertyRestDestructuringAssignmentEvaluation
ObjectAssignmentPattern : { AssignmentPropertyList , AssignmentRestProperty }
  1. 执行 ? RequireObjectCoercible(value)。
  2. excludedNames 为 ? 以 value 为实参执行 AssignmentPropertyListPropertyDestructuringAssignmentEvaluation
  3. 返回 ? 以 valueexcludedNames 为实参执行 AssignmentRestPropertyRestDestructuringAssignmentEvaluation
ArrayAssignmentPattern : [ ]
  1. iteratorRecord 为 ? GetIterator(value, sync)。
  2. 返回 ? IteratorClose(iteratorRecord, NormalCompletion(unused))。
ArrayAssignmentPattern : [ Elision ]
  1. iteratorRecord 为 ? GetIterator(value, sync)。
  2. resultCompletion(以 iteratorRecord 为实参执行 ElisionIteratorDestructuringAssignmentEvaluation)。
  3. 如果 iteratorRecord.[[Done]]false,则返回 ? IteratorClose(iteratorRecord, result)。
  4. 返回 result
ArrayAssignmentPattern : [ Elisionopt AssignmentRestElement ]
  1. iteratorRecord 为 ? GetIterator(value, sync)。
  2. 如果存在 Elision,则
    1. statusCompletion(以 iteratorRecord 为实参执行 ElisionIteratorDestructuringAssignmentEvaluation)。
    2. 如果 status 是 abrupt completion,则
      1. 断言:iteratorRecord.[[Done]]true
      2. 返回 ? status
  3. resultCompletion(以 iteratorRecord 为实参执行 AssignmentRestElementIteratorDestructuringAssignmentEvaluation)。
  4. 如果 iteratorRecord.[[Done]]false,则返回 ? IteratorClose(iteratorRecord, result)。
  5. 返回 result
ArrayAssignmentPattern : [ AssignmentElementList ]
  1. iteratorRecord 为 ? GetIterator(value, sync)。
  2. resultCompletion(以 iteratorRecord 为实参执行 AssignmentElementListIteratorDestructuringAssignmentEvaluation)。
  3. 如果 iteratorRecord.[[Done]]false,则返回 ? IteratorClose(iteratorRecord, result)。
  4. 返回 result
ArrayAssignmentPattern : [ AssignmentElementList , Elisionopt AssignmentRestElementopt ]
  1. iteratorRecord 为 ? GetIterator(value, sync)。
  2. statusCompletion(以 iteratorRecord 为实参执行 AssignmentElementListIteratorDestructuringAssignmentEvaluation)。
  3. 如果 status 是 abrupt completion,则
    1. 如果 iteratorRecord.[[Done]]false,则返回 ? IteratorClose(iteratorRecord, status)。
    2. 返回 ? status
  4. 如果存在 Elision,则
    1. status 设置为 Completion(以 iteratorRecord 为实参执行 ElisionIteratorDestructuringAssignmentEvaluation)。
    2. 如果 status 是 abrupt completion,则
      1. 断言:iteratorRecord.[[Done]]true
      2. 返回 ? status
  5. 如果存在 AssignmentRestElement,则
    1. status 设置为 Completion(以 iteratorRecord 为实参执行 AssignmentRestElementIteratorDestructuringAssignmentEvaluation)。
  6. 如果 iteratorRecord.[[Done]]false,则返回 ? IteratorClose(iteratorRecord, status)。
  7. 返回 ? status

13.15.5.3 Runtime Semantics: PropertyDestructuringAssignmentEvaluation

The syntax-directed operation PropertyDestructuringAssignmentEvaluation takes argument value (an ECMAScript language value) and returns either a normal completion containing a List of property keys or an abrupt completion. 它收集所有被解构属性键的列表。 It is defined piecewise over the following productions:

AssignmentPropertyList : AssignmentPropertyList , AssignmentProperty
  1. propertyNames 为 ? 以 value 为实参执行 AssignmentPropertyListPropertyDestructuringAssignmentEvaluation
  2. nextNames 为 ? 以 value 为实参执行 AssignmentPropertyPropertyDestructuringAssignmentEvaluation
  3. 返回 propertyNamesnextNames列表连接
AssignmentProperty : IdentifierReference Initializeropt
  1. propertyNameIdentifierReferenceStringValue
  2. leftRef 为 ? ResolveBinding(propertyName)。
  3. value 设置为 ? GetV(value, propertyName)。
  4. 如果存在 Initializervalueundefined,则
    1. 如果 IsAnonymousFunctionDefinition(Initializer) 是 true,则
      1. value 设置为 ? 以 propertyName 为实参执行 InitializerNamedEvaluation
    2. 否则,
      1. defaultValue 为 ? InitializerEvaluation
      2. value 设置为 ? GetValue(defaultValue)。
  5. 执行 ? PutValue(leftRef, value)。
  6. 返回 « propertyName »。
AssignmentProperty : PropertyName : AssignmentElement
  1. name 为 ? PropertyNameEvaluation
  2. 执行 ? 以 valuename 为实参执行 AssignmentElementKeyedDestructuringAssignmentEvaluation
  3. 返回 « name »。

13.15.5.4 Runtime Semantics: RestDestructuringAssignmentEvaluation

The syntax-directed operation RestDestructuringAssignmentEvaluation takes arguments value (an ECMAScript language value) and excludedNames (a List of property keys) and returns either a normal completion containing unused or an abrupt completion. It is defined piecewise over the following productions:

AssignmentRestProperty : ... DestructuringAssignmentTarget
  1. leftRef 为 ? DestructuringAssignmentTargetEvaluation
  2. restObjOrdinaryObjectCreate(%Object.prototype%)。
  3. 执行 ? CopyDataProperties(restObj, value, excludedNames)。
  4. 返回 ? PutValue(leftRef, restObj)。

13.15.5.5 Runtime Semantics: IteratorDestructuringAssignmentEvaluation

The syntax-directed operation IteratorDestructuringAssignmentEvaluation takes argument iteratorRecord (an Iterator Record) and returns either a normal completion containing unused or an abrupt completion. It is defined piecewise over the following productions:

AssignmentElementList : AssignmentElisionElement
  1. 返回 ? 以 iteratorRecord 为实参执行 AssignmentElisionElementIteratorDestructuringAssignmentEvaluation
AssignmentElementList : AssignmentElementList , AssignmentElisionElement
  1. 执行 ? 以 iteratorRecord 为实参执行 AssignmentElementListIteratorDestructuringAssignmentEvaluation
  2. 返回 ? 以 iteratorRecord 为实参执行 AssignmentElisionElementIteratorDestructuringAssignmentEvaluation
AssignmentElisionElement : AssignmentElement
  1. 返回 ? 以 iteratorRecord 为实参执行 AssignmentElementIteratorDestructuringAssignmentEvaluation
AssignmentElisionElement : Elision AssignmentElement
  1. 执行 ? 以 iteratorRecord 为实参执行 ElisionIteratorDestructuringAssignmentEvaluation
  2. 返回 ? 以 iteratorRecord 为实参执行 AssignmentElementIteratorDestructuringAssignmentEvaluation
Elision : ,
  1. 如果 iteratorRecord.[[Done]]false,则
    1. 执行 ? IteratorStep(iteratorRecord)。
  2. 返回 unused
Elision : Elision ,
  1. 执行 ? 以 iteratorRecord 为实参执行 ElisionIteratorDestructuringAssignmentEvaluation
  2. 如果 iteratorRecord.[[Done]]false,则
    1. 执行 ? IteratorStep(iteratorRecord)。
  3. 返回 unused
AssignmentElement : DestructuringAssignmentTarget Initializeropt
  1. 如果 DestructuringAssignmentTarget 既不是 ObjectLiteral 也不是 ArrayLiteral,则
    1. leftRef 为 ? DestructuringAssignmentTargetEvaluation
  2. valueundefined
  3. 如果 iteratorRecord.[[Done]]false,则
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 next 不是 done,则
      1. value 设置为 next
  4. 如果存在 Initializervalueundefined,则
    1. 如果 IsAnonymousFunctionDefinition(Initializer) 是 trueDestructuringAssignmentTargetIsIdentifierReftrue,则
      1. targetDestructuringAssignmentTargetStringValue
      2. v 为 ? 以 target 为实参执行 InitializerNamedEvaluation
    2. 否则,
      1. defaultValue 为 ? InitializerEvaluation
      2. v 为 ? GetValue(defaultValue)。
  5. 否则,
    1. vvalue
  6. 如果 DestructuringAssignmentTargetObjectLiteralArrayLiteral,则
    1. nestedAssignmentPattern 为由 DestructuringAssignmentTarget 覆盖的 AssignmentPattern
    2. 返回 ? 以 v 为实参执行 nestedAssignmentPatternDestructuringAssignmentEvaluation
  7. 返回 ? PutValue(leftRef, v)。
Note

通过在访问迭代器或求值 Initializer 之前求值不是解构模式的 DestructuringAssignmentTarget,来维持从左到右的求值顺序。

AssignmentRestElement : ... DestructuringAssignmentTarget
  1. 如果 DestructuringAssignmentTarget 既不是 ObjectLiteral 也不是 ArrayLiteral,则
    1. leftRef 为 ? DestructuringAssignmentTargetEvaluation
  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 为实参执行 nestedAssignmentPatternDestructuringAssignmentEvaluation

13.15.5.6 Runtime Semantics: KeyedDestructuringAssignmentEvaluation

The syntax-directed operation KeyedDestructuringAssignmentEvaluation takes arguments value (an ECMAScript language value) and propertyName (a property key) and returns either a normal completion containing unused or an abrupt completion. It is defined piecewise over the following productions:

AssignmentElement : DestructuringAssignmentTarget Initializeropt
  1. 如果 DestructuringAssignmentTarget 既不是 ObjectLiteral 也不是 ArrayLiteral,则
    1. leftRef 为 ? DestructuringAssignmentTargetEvaluation
  2. value 设置为 ? GetV(value, propertyName)。
  3. 如果存在 Initializervalueundefined,则
    1. 如果 IsAnonymousFunctionDefinition(Initializer) 是 trueDestructuringAssignmentTargetIsIdentifierReftrue,则
      1. targetDestructuringAssignmentTargetStringValue
      2. rhsValue 为 ? 以 target 为实参执行 InitializerNamedEvaluation
    2. 否则,
      1. defaultValue 为 ? InitializerEvaluation
      2. rhsValue 为 ? GetValue(defaultValue)。
  4. 否则,
    1. rhsValuevalue
  5. 如果 DestructuringAssignmentTargetObjectLiteralArrayLiteral,则
    1. assignmentPattern 为由 DestructuringAssignmentTarget 覆盖的 AssignmentPattern
    2. 返回 ? 以 rhsValue 为实参执行 assignmentPatternDestructuringAssignmentEvaluation
  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 为 ? ExpressionEvaluation
  2. 执行 ? GetValue(leftRef)。
  3. rightRef 为 ? AssignmentExpressionEvaluation
  4. 返回 ? GetValue(rightRef)。
Note

即使其值未被使用,也必须调用 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. 返回 ? FunctionDeclarationEvaluation
BreakableStatement : IterationStatement SwitchStatement
  1. newLabelSet 为新的空 List
  2. 返回 ? 以 newLabelSet 为实参执行此 BreakableStatementLabelledEvaluation

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. blockEnvNewDeclarativeEnvironment(oldEnv)。
  3. 执行 BlockDeclarationInstantiation(StatementList, blockEnv)。
  4. 将运行中执行上下文的 LexicalEnvironment 设置为 blockEnv
  5. blockValueCompletion(StatementList 的求值)。
  6. blockValue 设置为 Completion(DisposeResources(blockEnv.[[DisposableResourceStack]], blockValue))。
  7. 将运行中执行上下文的 LexicalEnvironment 设置为 oldEnv
  8. 返回 ? blockValue
Note 1

无论控制如何离开 Block,LexicalEnvironment 总会恢复到其先前状态。

StatementList : StatementList StatementListItem
  1. sl 为 ? StatementListEvaluation
  2. sCompletion(StatementListItemEvaluation)。
  3. 返回 ? UpdateEmpty(s, sl)。
Note 2

StatementList 的值是 StatementList 中最后一个会产生值的项目的值。例如,以下对 eval 函数的调用都会返回值 1:

eval("1;;;;;")
eval("1;{}")
eval("1;var a;")

14.2.3 BlockDeclarationInstantiation ( code, envRecord )

The abstract operation BlockDeclarationInstantiation takes arguments code (a Parse Node) and envRecord (a Declarative Environment Record) and returns unused. code 是对应于块体的 Parse NodeenvRecord 是要在其中创建绑定的 Environment Record

Note

当求值 BlockCaseBlock 时,会创建一个新的 Declarative Environment Record,并且块中声明的每个块作用域变量、常量、函数或类的绑定都会在该 Environment Record 中实例化。

它在被调用时执行以下步骤:

  1. declscodeLexicallyScopedDeclarations
  2. privateEnv 为正在运行的执行上下文的 PrivateEnvironment。
  3. decls 的每个元素 decl,执行:
    1. declBoundNames 的每个元素 name,执行:
      1. 如果 declIsConstantDeclarationtrue,则
        1. 执行 ! envRecord.CreateImmutableBinding(name, true)。
      2. 否则,
        1. 如果宿主是 Web 浏览器,或以其他方式支持 块级函数声明的 Web 遗留兼容性语义,则
          1. 如果 ! envRecord.HasBinding(name) 为 false,则
            1. 执行 ! envRecord.CreateMutableBinding(name, false)。
        2. 否则,
          1. 执行 ! envRecord.CreateMutableBinding(name, false)。
    2. 如果 declFunctionDeclarationGeneratorDeclarationAsyncFunctionDeclarationAsyncGeneratorDeclaration,则
      1. funcNamedeclBoundNames 的唯一元素。
      2. funcObj 为使用参数 envRecordprivateEnvdecl 执行 InstantiateFunctionObject 的结果。
      3. 如果宿主是 Web 浏览器,或以其他方式支持 块级函数声明的 Web 遗留兼容性语义,则
        1. 如果 envRecordfuncName 的绑定是未初始化绑定,则
          1. 执行 ! envRecord.InitializeBinding(funcName, funcObj)。
        2. 否则,
          1. 断言:declFunctionDeclaration
          2. 执行 ! envRecord.SetMutableBinding(funcName, funcObj, false)。
      4. 否则,
        1. 执行 ! envRecord.InitializeBinding(funcName, funcObj)。
  4. 返回 unused

14.3 声明和变量语句

14.3.1 Let、Const、Using 和 Await Using 声明

Note

letconstusingawait using 声明定义的变量,其作用域为运行中执行上下文的 LexicalEnvironment。这些变量会在其包含的环境记录实例化时创建,但在变量的 LexicalBinding 被求值之前,不得以任何方式访问。由带有 InitializerLexicalBinding 定义的变量,会在 LexicalBinding 被求值时被赋予其 InitializerAssignmentExpression 的值,而不是在变量创建时赋值。如果 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: 求值

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

The syntax-directed operation BindingEvaluation takes argument kind (normalsync-disposeasync-dispose,) and returns 含有 unused正常完成,或突兀完成. It is defined piecewise over the following productions:

BindingList : BindingList , LexicalBinding
  1. 执行以 kind 为参数的派生 BindingList 的 ? BindingEvaluation
  2. 返回以 kind 为参数的 LexicalBinding 的 ? BindingEvaluation
LexicalBinding : BindingIdentifier
  1. 断言:kindnormal
  2. lhs 为 ! ResolveBinding(BindingIdentifierStringValue)。
  3. 执行 ! InitializeReferencedBinding(lhs, undefined)。
  4. 返回 unused
Note

一条静态语义规则确保这种形式的 LexicalBinding 永远不会出现在 constusingawait using 声明中。

LexicalBinding : BindingIdentifier Initializer
  1. bindingIdBindingIdentifierStringValue
  2. lhs 为 ! ResolveBinding(bindingId)。
  3. 如果 IsAnonymousFunctionDefinition(Initializer) 是 true,则
    1. value 为以 bindingId 为参数的 Initializer 的 ? NamedEvaluation
  4. 否则,
    1. rhsInitializer 的 ? Evaluation
    2. value 为 ? GetValue(rhs)。
  5. 如果 kind 不是 normal,则
    1. 断言:IsUnresolvableReference(lhs) 是 false
    2. baselhs.[[Base]]
    3. 断言:base 是声明式环境记录。
    4. 执行 ? AddDisposableResource(base.[[DisposableResourceStack]], value, kind)。
  6. 执行 ? InitializeReferencedBinding(lhs, value)。
  7. 返回 unused
LexicalBinding : BindingPattern Initializer
  1. 断言:kindnormal
  2. rhsInitializer 的 ? Evaluation
  3. value 为 ? GetValue(rhs)。
  4. envRecord 为运行中执行上下文的 LexicalEnvironment。
  5. 返回以 valueenvRecord 为参数的 BindingPattern 的 ? BindingInitialization

14.3.2 变量语句

Note

var 语句声明的变量,其作用域限定在运行中的执行上下文的 VariableEnvironment 内。var 变量会在其所在 Environment Record 被实例化时创建,并在创建时初始化为 undefined。在任何 VariableEnvironment 的作用域内,一个普通的 BindingIdentifier 可以出现在多个 VariableDeclaration 中,但这些声明合起来只定义一个变量。由带有 InitializerVariableDeclaration 定义的变量,会在执行 VariableDeclaration 时被赋予其 InitializerAssignmentExpression 的值,而不是在变量被创建时。

语法

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. 执行 ? VariableDeclarationListEvaluation
  2. 返回 empty
VariableDeclarationList : VariableDeclarationList , VariableDeclaration
  1. 执行 ? VariableDeclarationListEvaluation
  2. 返回 ? VariableDeclarationEvaluation
VariableDeclaration : BindingIdentifier
  1. 返回 empty
VariableDeclaration : BindingIdentifier Initializer
  1. bindingIdBindingIdentifierStringValue
  2. lhs 为 ? ResolveBinding(bindingId)。
  3. 如果 IsAnonymousFunctionDefinition(Initializer) 是 true,则
    1. value 为 ? 以 bindingId 为实参执行 InitializerNamedEvaluation
  4. 否则,
    1. rhs 为 ? InitializerEvaluation
    2. value 为 ? GetValue(rhs)。
  5. 执行 ? PutValue(lhs, value)。
  6. 返回 empty
Note

如果 VariableDeclaration 嵌套在 with 语句内,且 VariableDeclaration 中的 BindingIdentifier 与该 with 语句的 Object Environment Record 的绑定对象的某个属性名相同,则步骤 5 会将 value 赋给该属性,而不是赋给 Identifier 的 VariableEnvironment 绑定。

VariableDeclaration : BindingPattern Initializer
  1. rhs 为 ? InitializerEvaluation
  2. rightValue 为 ? GetValue(rhs)。
  3. 返回 ? 以 rightValueundefined 为实参执行 BindingPatternBindingInitialization

14.3.3 解构绑定模式

语法

BindingPattern[Yield, Await] : ObjectBindingPattern[?Yield, ?Await] ArrayBindingPattern[?Yield, ?Await] ObjectBindingPattern[Yield, Await] : { } { BindingRestProperty[?Yield, ?Await] } { BindingPropertyList[?Yield, ?Await] } { BindingPropertyList[?Yield, ?Await] , BindingRestProperty[?Yield, ?Await]opt } 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

The syntax-directed operation PropertyBindingInitialization takes arguments value (an ECMAScript language value) and envRecord (an Environment Record or undefined) and returns either a normal completion containing a List of property keys or an abrupt completion. 它收集所有被绑定属性名的列表。 It is defined piecewise over the following productions:

BindingPropertyList : BindingPropertyList , BindingProperty
  1. boundNames 为 ? 以 valueenvRecord 为实参执行 BindingPropertyListPropertyBindingInitialization
  2. nextNames 为 ? 以 valueenvRecord 为实参执行 BindingPropertyPropertyBindingInitialization
  3. 返回 boundNamesnextNames列表连接
BindingProperty : SingleNameBinding
  1. nameSingleNameBindingBoundNames 的唯一元素。
  2. 执行 ? 以 valueenvRecordname 为实参执行 SingleNameBindingKeyedBindingInitialization
  3. 返回 « name »。
BindingProperty : PropertyName : BindingElement
  1. propertyKey 为 ? PropertyNameEvaluation
  2. 执行 ? 以 valueenvRecordpropertyKey 为实参执行 BindingElementKeyedBindingInitialization
  3. 返回 « propertyKey »。

14.3.3.2 Runtime Semantics: RestBindingInitialization

The syntax-directed operation RestBindingInitialization takes arguments value (an ECMAScript language value), envRecord (an Environment Record or undefined), and excludedNames (a List of property keys) and returns either a normal completion containing unused or an abrupt completion. It is defined piecewise over the following productions:

BindingRestProperty : ... BindingIdentifier
  1. lhs 为 ? ResolveBinding(BindingIdentifierStringValue, envRecord)。
  2. restObjOrdinaryObjectCreate(%Object.prototype%)。
  3. 执行 ? CopyDataProperties(restObj, value, excludedNames)。
  4. 如果 envRecordundefined,则返回 ? PutValue(lhs, restObj)。
  5. 返回 ? InitializeReferencedBinding(lhs, restObj)。

14.3.3.3 Runtime Semantics: KeyedBindingInitialization

The syntax-directed operation KeyedBindingInitialization takes arguments value (an ECMAScript language value), envRecord (an Environment Record or undefined), and propertyName (a property key) and returns either a normal completion containing unused or an abrupt completion.

Note

当为 envRecord 传入 undefined 时,表示应使用 PutValue 操作来赋予初始化值。这适用于非严格函数的形参列表。在这种情况下,形参绑定会预先初始化,以处理多个形参可能具有相同名称的情况。

It is defined piecewise over the following productions:

BindingElement : BindingPattern Initializeropt
  1. value 设置为 ? GetV(value, propertyName)。
  2. 如果存在 Initializervalueundefined,则
    1. defaultValue 为 ? InitializerEvaluation
    2. value 设置为 ? GetValue(defaultValue)。
  3. 返回 ? 以 valueenvRecord 为实参执行 BindingPatternBindingInitialization
SingleNameBinding : BindingIdentifier Initializeropt
  1. bindingIdBindingIdentifierStringValue
  2. lhs 为 ? ResolveBinding(bindingId, envRecord)。
  3. value 设置为 ? GetV(value, propertyName)。
  4. 如果存在 Initializervalueundefined,则
    1. 如果 IsAnonymousFunctionDefinition(Initializer) 是 true,则
      1. value 设置为 ? 以 bindingId 为实参执行 InitializerNamedEvaluation
    2. 否则,
      1. defaultValue 为 ? InitializerEvaluation
      2. value 设置为 ? GetValue(defaultValue)。
  5. 如果 envRecordundefined,则返回 ? 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] ; Note

ExpressionStatement 不能以 U+007B (LEFT CURLY BRACKET) 开始,因为这可能使它与 Block 产生歧义。ExpressionStatement 不能以 functionclass 关键字开始,因为这会使它与 FunctionDeclarationGeneratorDeclarationClassDeclaration 产生歧义。ExpressionStatement 不能以 async function 开始,因为这会使它与 AsyncFunctionDeclarationAsyncGeneratorDeclaration 产生歧义。ExpressionStatement 不能以两个 token 序列 let [ 开始,因为这会使它与首个 LexicalBindingArrayBindingPatternlet LexicalDeclaration 产生歧义。

14.5.1 Runtime Semantics: Evaluation

ExpressionStatement : Expression ;
  1. exprRef 为 ? ExpressionEvaluation
  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] Note
前瞻限制 [lookahead ≠ else] 以通常方式解决经典的“悬挂 else”问题。也就是说,当关联哪个 if 的选择除此之外存在歧义时,else 会与候选 if 中最近的(最内层的)那个关联

14.6.1 Static Semantics: 早期错误

IfStatement : if ( Expression ) Statement else Statement IfStatement : if ( Expression ) Statement Note

只有在实现了 B.3.1 中指定的扩展时,才需要应用此规则。

14.6.2 Runtime Semantics: Evaluation

IfStatement : if ( Expression ) Statement else Statement
  1. exprRef 为 ? ExpressionEvaluation
  2. exprValueToBoolean(? GetValue(exprRef))。
  3. 如果 exprValuetrue,则
    1. stmtCompletionCompletion(第一个 StatementEvaluation)。
  4. 否则,
    1. stmtCompletionCompletion(第二个 StatementEvaluation)。
  5. 返回 ? UpdateEmpty(stmtCompletion, undefined)。
IfStatement : if ( Expression ) Statement
  1. exprRef 为 ? ExpressionEvaluation
  2. exprValueToBoolean(? GetValue(exprRef))。
  3. 如果 exprValuefalse,则返回 undefined
  4. stmtCompletionCompletion(StatementEvaluation)。
  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 )

The abstract operation LoopContinues takes arguments completion (a Completion Record) and labelSet (a List of Strings) and returns a Boolean. It performs the following steps when called:

  1. 如果 completion 是 normal completion,则返回 true
  2. 如果 completion 不是 continue completion,则返回 false
  3. 如果 completion.[[Target]]empty,则返回 true
  4. 如果 labelSet 包含 completion.[[Target]],则返回 true
  5. 返回 false
Note

IterationStatementStatement 部分内,可以使用 ContinueStatement 来开始一次新的迭代。

14.7.1.2 Runtime Semantics: LoopEvaluation

The syntax-directed operation LoopEvaluation takes argument labelSet (a List of Strings) and returns either a normal completion containing an ECMAScript language value or an abrupt completion. It is defined piecewise over the following productions:

IterationStatement : DoWhileStatement
  1. 返回 ? 以 labelSet 为实参执行 DoWhileStatementDoWhileLoopEvaluation
IterationStatement : WhileStatement
  1. 返回 ? 以 labelSet 为实参执行 WhileStatementWhileLoopEvaluation
IterationStatement : ForStatement
  1. 返回 ? 以 labelSet 为实参执行 ForStatementForLoopEvaluation
IterationStatement : ForInOfStatement
  1. 返回 ? 以 labelSet 为实参执行 ForInOfStatementForInOfLoopEvaluation

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 ) ; Note

只有在实现了 B.3.1 中指定的扩展时,才需要应用此规则。

14.7.2.2 Runtime Semantics: DoWhileLoopEvaluation

The syntax-directed operation DoWhileLoopEvaluation takes argument labelSet (a List of Strings) and returns either a normal completion containing an ECMAScript language value or an abrupt completion. It is defined piecewise over the following productions:

DoWhileStatement : do Statement while ( Expression ) ;
  1. iterationResultundefined
  2. 重复:
    1. stmtResultCompletion(StatementEvaluation)。
    2. 如果 LoopContinues(stmtResult, labelSet) 是 false,则返回 ? UpdateEmpty(stmtResult, iterationResult)。
    3. 如果 stmtResult.[[Value]] 不是 empty,则将 iterationResult 设置为 stmtResult.[[Value]]
    4. exprRef 为 ? ExpressionEvaluation
    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 Note

只有在实现了 B.3.1 中指定的扩展时,才需要应用此规则。

14.7.3.2 Runtime Semantics: WhileLoopEvaluation

The syntax-directed operation WhileLoopEvaluation takes argument labelSet (a List of Strings) and returns either a normal completion containing an ECMAScript language value or an abrupt completion. It is defined piecewise over the following productions:

WhileStatement : while ( Expression ) Statement
  1. iterationResultundefined
  2. 重复:
    1. exprRef 为 ? ExpressionEvaluation
    2. exprValue 为 ? GetValue(exprRef)。
    3. 如果 ToBoolean(exprValue) 是 false,则返回 iterationResult
    4. stmtResultCompletion(StatementEvaluation)。
    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 Note

只有在实现了 B.3.1 中指定的扩展时,才需要应用此规则。

ForStatement : for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement

14.7.4.2 Runtime Semantics: ForLoopEvaluation

The syntax-directed operation ForLoopEvaluation takes argument labelSet (a List of Strings) and returns either a normal completion containing an ECMAScript language value or an abrupt completion. It is defined piecewise over the following productions:

ForStatement : for ( Expressionopt ; Expressionopt ; Expressionopt ) Statement
  1. 如果存在第一个 Expression,则
    1. exprRef 为 ? 第一个 ExpressionEvaluation
    2. 执行 ? GetValue(exprRef)。
  2. 如果存在第二个 Expression,则令 test 为第二个 Expression;否则令 testempty
  3. 如果存在第三个 Expression,则令 increment 为第三个 Expression;否则令 incrementempty
  4. 返回 ? ForBodyEvaluation(test, increment, Statement, « », labelSet)。
ForStatement : for ( var VariableDeclarationList ; Expressionopt ; Expressionopt ) Statement
  1. 执行 ? VariableDeclarationListEvaluation
  2. 如果存在第一个 Expression,则令 test 为第一个 Expression;否则令 testempty
  3. 如果存在第二个 Expression,则令 increment 为第二个 Expression;否则令 incrementempty
  4. 返回 ? ForBodyEvaluation(test, increment, Statement, « », labelSet)。
ForStatement : for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement
  1. oldEnv 为运行中执行上下文的 LexicalEnvironment。
  2. loopEnvNewDeclarativeEnvironment(oldEnv)。
  3. isConstLexicalDeclarationIsConstantDeclaration
  4. boundNamesLexicalDeclarationBoundNames
  5. boundNames 的每个元素 name,执行
    1. 如果 isConsttrue,则
      1. 执行 ! loopEnv.CreateImmutableBinding(name, true)。
    2. 否则,
      1. 执行 ! loopEnv.CreateMutableBinding(name, false)。
  6. 将运行中执行上下文的 LexicalEnvironment 设置为 loopEnv
  7. forDeclCompletion(LexicalDeclaration 的求值)。
  8. 如果 forDecl 是突兀完成,则
    1. forDecl 设置为 Completion(DisposeResources(loopEnv.[[DisposableResourceStack]], forDecl))。
    2. 断言:forDecl 是突兀完成。
    3. 将运行中执行上下文的 LexicalEnvironment 设置为 oldEnv
    4. 返回 ? forDecl
  9. 如果 isConstfalse,则令 perIterationLetsboundNames;否则令 perIterationLets 为一个新的空列表。
  10. 如果第一个 Expression 存在,则令 test 为第一个 Expression;否则令 testempty
  11. 如果第二个 Expression 存在,则令 increment 为第二个 Expression;否则令 incrementempty
  12. bodyResultCompletion(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 )

The abstract operation ForBodyEvaluation takes arguments test (an Expression Parse Node or empty), increment (an Expression Parse Node or empty), stmt (a Statement Parse Node), perIterationBindings (a List of Strings), and labelSet (a List of Strings) and returns either a normal completion containing an ECMAScript language value or an abrupt completion. It performs the following steps when called:

  1. iterationResultundefined
  2. 执行 ? CreatePerIterationEnvironment(perIterationBindings)。
  3. 重复:
    1. 如果 test 不是 empty,则
      1. testRef 为 ? testEvaluation
      2. testValue 为 ? GetValue(testRef)。
      3. 如果 ToBoolean(testValue) 是 false,则返回 iterationResult
    2. resultCompletion(stmtEvaluation)。
    3. 如果 LoopContinues(result, labelSet) 是 false,则返回 ? UpdateEmpty(result, iterationResult)。
    4. 如果 result.[[Value]] 不是 empty,则将 iterationResult 设置为 result.[[Value]]
    5. 执行 ? CreatePerIterationEnvironment(perIterationBindings)。
    6. 如果 increment 不是 empty,则
      1. incRef 为 ? incrementEvaluation
      2. 执行 ? GetValue(incRef)。

14.7.4.4 CreatePerIterationEnvironment ( perIterationBindings )

The abstract operation CreatePerIterationEnvironment takes argument perIterationBindings (a List of Strings) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

  1. 如果 perIterationBindings 有任何元素,则
    1. lastIterationEnv 为正在运行的执行上下文的 LexicalEnvironment。
    2. outerlastIterationEnv.[[OuterEnv]]
    3. 断言:outer 不是 null
    4. thisIterationEnvNewDeclarativeEnvironment(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-infor-offor-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] Note

本节由附录 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 Note

只有在实现了 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

The syntax-directed operation IsDestructuring takes no arguments and returns a Boolean. It is defined piecewise over the following productions:

MemberExpression : PrimaryExpression
  1. 如果 PrimaryExpressionObjectLiteralArrayLiteral,则返回 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. 返回 ForBindingIsDestructuring
ForBinding : BindingIdentifier
  1. 返回 false
ForBinding : BindingPattern
  1. 返回 true
Note

本节由附录 B.3.5 扩展。

14.7.5.3 Runtime Semantics: ForDeclarationBindingInitialization

The syntax-directed operation ForDeclarationBindingInitialization takes arguments value (an ECMAScript language value) and envRecord (an Environment Record) and returns either a normal completion containing unused or an abrupt completion. It is defined piecewise over the following productions:

ForDeclaration : LetOrConst ForBinding
  1. 返回 ? 以 valueenvRecord 为实参执行 ForBindingBindingInitialization
ForDeclaration : using ForBinding await using ForBinding
  1. 抛出 SyntaxError 异常。

14.7.5.4 Runtime Semantics: ForDeclarationBindingInstantiation

The syntax-directed operation ForDeclarationBindingInstantiation takes argument envRecord (a Declarative Environment Record) and returns unused. It is defined piecewise over the following productions:

ForDeclaration : LetOrConst ForBinding
  1. ForBindingBoundNames 的每个元素 name,执行:
    1. 如果 LetOrConstIsConstantDeclarationtrue,则
      1. 执行 ! envRecord.CreateImmutableBinding(name, true)。
    2. 否则,
      1. 执行 ! envRecord.CreateMutableBinding(name, false)。
  2. 返回 unused
ForDeclaration : using ForBinding await using ForBinding
  1. ForBindingBoundNames 的每个元素 name,执行
    1. 执行 ! envRecord.CreateImmutableBinding(name, true)。
  2. 返回 unused

14.7.5.5 Runtime Semantics: ForInOfLoopEvaluation

The syntax-directed operation ForInOfLoopEvaluation takes argument labelSet (a List of Strings) and returns either a normal completion containing an ECMAScript language value or an abrupt completion. It is defined piecewise over the following productions:

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(ForDeclarationBoundNames, 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(ForDeclarationBoundNames, 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(ForDeclarationBoundNames, AssignmentExpression, async-iterate)。
  2. 返回 ? ForIn/OfBodyEvaluation(ForDeclaration, Statement, keyResult, iterate, lexical-binding, labelSet, async)。
Note

本节由附录 B.3.5 扩展。

14.7.5.6 ForIn/OfHeadEvaluation ( uninitializedBoundNames, expr, iterationKind )

The abstract operation ForIn/OfHeadEvaluation takes arguments uninitializedBoundNames (a List of Strings), expr (an Expression Parse Node or an AssignmentExpression Parse Node), and iterationKind (enumerate, iterate, or async-iterate) and returns either a normal completion containing an Iterator Record or an abrupt completion. It performs the following steps when called:

  1. oldEnv 为运行中的执行上下文的 LexicalEnvironment。
  2. 如果 uninitializedBoundNames 不是空的,则
    1. 断言:uninitializedBoundNames 没有重复项。
    2. newEnvNewDeclarativeEnvironment(oldEnv)。
    3. uninitializedBoundNames 的每个 String name,执行:
      1. 执行 ! newEnv.CreateMutableBinding(name, false)。
    4. 将运行中的执行上下文的 LexicalEnvironment 设置为 newEnv
  3. exprRefCompletion(exprEvaluation)。
  4. 将运行中的执行上下文的 LexicalEnvironment 设置为 oldEnv
  5. exprValue 为 ? GetValue(? exprRef)。
  6. 如果 iterationKindenumerate,则
    1. 如果 exprValueundefinednull,则
      1. 返回 Completion Record { [[Type]]: break, [[Value]]: empty, [[Target]]: empty }。
    2. obj 为 ! ToObject(exprValue)。
    3. iteratorEnumerateObjectProperties(obj)。
    4. nextMethod 为 ! GetV(iterator, "next")。
    5. 返回 Iterator Record { [[Iterator]]: iterator, [[NextMethod]]: nextMethod, [[Done]]: false }。
  7. 断言:iterationKinditerateasync-iterate
  8. 如果 iterationKindasync-iterate,则令 iteratorKindasync
  9. 否则,令 iteratorKindsync
  10. 返回 ? GetIterator(exprValue, iteratorKind)。

14.7.5.7 ForIn/OfBodyEvaluation ( lhs, stmt, iteratorRecord, iterationKind, lhsKind, labelSet [ , iteratorKind ] )

The abstract operation ForIn/OfBodyEvaluation takes arguments lhs (a Parse Node), stmt (a Statement Parse Node), iteratorRecord (an Iterator Record), iterationKind (enumerate or iterate), lhsKind (assignment, var-binding, or lexical-binding), and labelSet (a List of Strings) and optional argument iteratorKind (sync or async) and returns either a normal completion containing an ECMAScript language value or an abrupt completion. It performs the following steps when called:

  1. 如果 iteratorKind 不存在,则将 iteratorKind 设置为 sync
  2. oldEnv 为运行中执行上下文的 LexicalEnvironment。
  3. iterationResultundefined
  4. 如果 lhsKindlexical-binding,则
    1. 断言:lhs 是一个 ForDeclaration
    2. 如果 lhsIsAwaitUsingDeclarationtrue,则
      1. declarationKindasync-dispose
    3. 否则如果 lhsIsUsingDeclarationtrue,则
      1. declarationKindsync-dispose
    4. 否则,
      1. declarationKindnormal
  5. 否则,
    1. declarationKindnormal
  6. destructuringlhsIsDestructuring
  7. 如果 destructuringtruelhsKindassignment,则
    1. 断言:lhs 是一个 LeftHandSideExpression
    2. assignmentPatternlhs覆盖的 AssignmentPattern
  8. 重复,
    1. nextResult 为 ? Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]])。
    2. 如果 iteratorKindasync,则将 nextResult 设置为 ? Await(nextResult)。
    3. 如果 nextResult 不是对象,则抛出 TypeError 异常。
    4. done 为 ? IteratorComplete(nextResult)。
    5. 如果 donetrue,则返回 iterationResult
    6. nextValue 为 ? IteratorValue(nextResult)。
    7. 如果 lhsKindassignmentvar-binding,则
      1. 如果 destructuringtrue,则
        1. 如果 lhsKindassignment,则
          1. status 为以 nextValue 为参数的 assignmentPatternDestructuringAssignmentEvaluationCompletion
        2. 否则,
          1. 断言:lhsKindvar-binding
          2. 断言:lhs 是一个 ForBinding
          3. status 为以 nextValueundefined 为参数的 lhsBindingInitializationCompletion
      2. 否则,
        1. lhsReflhs 的求值的 Completion。(它可能会被重复求值。)
        2. 如果 lhsKindassignmentlhsAssignmentTargetTypeweb-compat,则抛出 ReferenceError 异常。
        3. 如果 lhsRef 是突兀完成,则
          1. statuslhsRef
        4. 否则,
          1. statusCompletion(PutValue(lhsRef.[[Value]], nextValue))。
      3. iterationEnvundefined
    8. 否则,
      1. 断言:lhsKindlexical-binding
      2. 断言:lhs 是一个 ForDeclaration
      3. iterationEnvNewDeclarativeEnvironment(oldEnv)。
      4. 执行以 iterationEnv 为参数的 lhsForDeclarationBindingInstantiation
      5. 将运行中执行上下文的 LexicalEnvironment 设置为 iterationEnv
      6. 如果 destructuringtrue,则
        1. status 为以 nextValueiterationEnv 为参数的 lhsForDeclarationBindingInitializationCompletion
      7. 否则,
        1. 断言:lhs 绑定单个名称。
        2. lhsNamelhsBoundNames 的唯一元素。
        3. lhsRef 为 ! ResolveBinding(lhsName)。
        4. 如果 declarationKind 不是 normal,则
          1. 断言:IsUnresolvableReference(lhsRef) 是 false
          2. baselhsRef.[[Base]]
          3. 断言:base 是声明式环境记录。
          4. statusCompletion(AddDisposableResource(base.[[DisposableResourceStack]], nextValue, declarationKind))。
        5. 否则,
          1. statusNormalCompletion(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. 如果 iterationKindenumerate,则返回 ? status
      4. 断言:iterationKinditerate
      5. 如果 iteratorKindasync,则返回 ? AsyncIteratorClose(iteratorRecord, status)。
      6. 返回 ? IteratorClose(iteratorRecord, status)。
    10. resultstmt 的求值的 Completion
    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. 如果 iterationKindenumerate,则返回 ? status
      3. 断言:iterationKinditerate
      4. 如果 iteratorKindasync,则返回 ? 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. bindingIdBindingIdentifierStringValue
  2. 返回 ? ResolveBinding(bindingId)。

14.7.5.9 EnumerateObjectProperties ( obj )

The abstract operation EnumerateObjectProperties takes argument obj (an Object) and returns an iterator object. It performs the following steps when called:

  1. 返回一个迭代器对象,其 next 方法会遍历 obj 的可枚举属性中所有 String 值键。该迭代器对象永远不能被 ECMAScript 代码直接访问。枚举属性的机制和顺序未指定,但必须符合下面指定的规则。

该迭代器的 throwreturn 方法是 null,且永远不会被调用。该迭代器的 next 方法会处理对象属性,以确定是否应将属性键作为迭代器值返回。返回的属性键不包括 Symbol 键。目标对象的属性可以在枚举期间被删除。在迭代器的 next 方法处理某个属性之前被删除的属性会被忽略。如果在枚举期间向目标对象添加新属性,则不保证新添加的属性会在活动枚举中被处理。在任意枚举中,一个属性名最多只会由迭代器的 next 方法返回一次。

枚举目标对象的属性包括递归地枚举其原型、原型的原型,依此类推;但如果某个原型的属性与迭代器的 next 方法已经处理过的属性同名,则不会处理该原型属性。在确定原型对象的某个属性是否已经被处理过时,不考虑 [[Enumerable]] 特性的值。原型对象的可枚举属性名必须通过以该原型对象作为实参调用 EnumerateObjectProperties 来获得。EnumerateObjectProperties 必须通过调用目标对象的 [[OwnPropertyKeys]] 内部方法来获得其自有属性键。目标对象的属性特性必须通过调用其 [[GetOwnProperty]] 内部方法来获得。

此外,如果 obj 及其原型链中的任何对象都不是 Proxy 异质对象TypedArray模块命名空间异质对象或由实现提供的异质对象,则在发生以下任一情况之前,该迭代器必须表现得像由 CreateForInIterator(obj) 给出的迭代器一样:

  • obj 或其原型链中某个对象的 [[Prototype]] 内部槽的值发生变化,
  • obj 或其原型链中的某个对象移除了属性,
  • obj 的原型链中的某个对象添加了属性,或
  • obj 或其原型链中某个对象的某个属性的 [[Enumerable]] 特性值发生变化。
Note 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;
  }
}
Note 2
选择这些异质对象作为实现不要求匹配 CreateForInIterator 的对象列表,是因为实现历史上在这些情况中的行为有所不同,而在所有其他情况中行为一致。

14.7.5.10 For-In 迭代器对象

For-In Iterator 是一个表示对某个特定对象进行某次特定迭代的对象。For-In Iterator 对象永远不能被 ECMAScript 代码直接访问;它们的存在只是为了说明 EnumerateObjectProperties 的行为。

14.7.5.10.1 CreateForInIterator ( obj )

The abstract operation CreateForInIterator takes argument obj (an Object) and returns a For-In Iterator. 它用于创建一个 For-In Iterator 对象,该对象以特定顺序迭代 obj 的自有和继承的可枚举字符串属性。 It performs the following steps when called:

  1. iteratorOrdinaryObjectCreate(%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. iteratorthis 值。
  2. 断言:iterator 是 Object。
  3. 断言:iterator 具有 For-In Iterator 实例的所有内部槽(14.7.5.10.3)。
  4. objiterator.[[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. keyiterator.[[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. 如果 objnull,则返回 CreateIteratorResultObject(undefined, true)。

14.7.5.10.3 For-In Iterator 实例的属性

For-In Iterator 实例是从 %ForInIteratorPrototype% 内在对象继承属性的普通对象For-In Iterator 实例最初使用 Table 34 中列出的内部槽创建。

Table 34: For-In Iterator 实例的内部槽
内部槽 类型 描述
[[Object]] Object 其属性正被迭代的 Object 值。
[[ObjectWasVisited]] Boolean 如果迭代器已在 [[Object]] 上调用 [[OwnPropertyKeys]],则为 true;否则为 false
[[VisitedKeys]] Strings 的 List 此迭代器到目前为止已经发出的值。
[[RemainingKeys]] Strings 的 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. labelLabelIdentifierStringValue
  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. labelLabelIdentifierStringValue
  2. 返回 Completion Record { [[Type]]: break, [[Value]]: empty, [[Target]]: label }。

14.10 return 语句

语法

ReturnStatement[Yield, Await] : return ; return [no LineTerminator here] Expression[+In, ?Yield, ?Await] ; Note

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 为 ? ExpressionEvaluation
  2. exprValue 为 ? GetValue(exprRef)。
  3. 如果 GetGeneratorKind() 是 async,则将 exprValue 设置为 ? Await(exprValue)。
  4. 返回 ReturnCompletion(exprValue)。

14.11 with 语句

Note 1

不鼓励在新的 ECMAScript 代码中使用 Legacy with 语句。请考虑在严格模式代码和非严格代码中都允许的替代方案,例如 解构赋值

语法

WithStatement[Yield, Await, Return] : with ( Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] Note 2

with 语句会把一个计算所得对象的 Object Environment Record 添加到运行中的执行上下文的词法环境中。然后它使用这个扩充后的词法环境执行一条语句。最后,它恢复原始词法环境。

14.11.1 Static Semantics: 早期错误

WithStatement : with ( Expression ) Statement Note

只有在实现了 B.3.1 中指定的扩展时,才需要应用第二条规则。

14.11.2 Runtime Semantics: Evaluation

WithStatement : with ( Expression ) Statement
  1. value 为 ? ExpressionEvaluation
  2. obj 为 ? ToObject(? GetValue(value))。
  3. oldEnv 为运行中的执行上下文的 LexicalEnvironment。
  4. newEnvNewObjectEnvironment(obj, true, oldEnv)。
  5. 将运行中的执行上下文的 LexicalEnvironment 设置为 newEnv
  6. stmtCompletionCompletion(StatementEvaluation)。
  7. 将运行中的执行上下文的 LexicalEnvironment 设置为 oldEnv
  8. 返回 ? UpdateEmpty(stmtCompletion, undefined)。
Note

无论控制如何离开嵌入的 Statement,不管是正常离开、某种形式的 abrupt completion,还是异常,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

The syntax-directed operation CaseBlockEvaluation takes argument input (an ECMAScript language value) and returns either a normal completion containing an ECMAScript language value or an abrupt completion. It is defined piecewise over the following productions:

CaseBlock : { }
  1. 返回 undefined
CaseBlock : { CaseClauses }
  1. resultValueundefined
  2. caseClausesCaseClauses 中按源文本顺序排列的 CaseClause 项的 List
  3. foundfalse
  4. caseClauses 的每个 CaseClause clause,执行:
    1. 如果 foundfalse,则
      1. found 设置为 ? CaseClauseIsSelected(clause, input)。
    2. 如果 foundtrue,则
      1. completionCompletion(clauseEvaluation)。
      2. 如果 completion.[[Value]] 不是 empty,则将 resultValue 设置为 completion.[[Value]]
      3. 如果 completion 是 abrupt completion,则返回 ? UpdateEmpty(completion, resultValue)。
  5. 返回 resultValue
CaseBlock : { CaseClausesopt DefaultClause CaseClausesopt }
  1. resultValueundefined
  2. 如果存在第一个 CaseClauses,则
    1. caseClauses 为第一个 CaseClauses 中按源文本顺序排列的 CaseClause 项的 List
  3. 否则,
    1. caseClauses 为新的空 List
  4. foundfalse
  5. caseClauses 的每个 CaseClause clause,执行:
    1. 如果 foundfalse,则
      1. found 设置为 ? CaseClauseIsSelected(clause, input)。
    2. 如果 foundtrue,则
      1. completionCompletion(clauseEvaluation)。
      2. 如果 completion.[[Value]] 不是 empty,则将 resultValue 设置为 completion.[[Value]]
      3. 如果 completion 是 abrupt completion,则返回 ? UpdateEmpty(completion, resultValue)。
  6. foundInBfalse
  7. 如果存在第二个 CaseClauses,则
    1. secondCaseClauses 为第二个 CaseClauses 中按源文本顺序排列的 CaseClause 项的 List
  8. 否则,
    1. secondCaseClauses 为新的空 List
  9. 如果 foundfalse,则
    1. secondCaseClauses 的每个 CaseClause clause,执行:
      1. 如果 foundInBfalse,则
        1. foundInB 设置为 ? CaseClauseIsSelected(clause, input)。
      2. 如果 foundInBtrue,则
        1. completionCompletion(CaseClause clauseEvaluation)。
        2. 如果 completion.[[Value]] 不是 empty,则将 resultValue 设置为 completion.[[Value]]
        3. 如果 completion 是 abrupt completion,则返回 ? UpdateEmpty(completion, resultValue)。
  10. 如果 foundInBtrue,则返回 resultValue
  11. defaultRCompletion(DefaultClauseEvaluation)。
  12. 如果 defaultR.[[Value]] 不是 empty,则将 resultValue 设置为 defaultR.[[Value]]
  13. 如果 defaultR 是 abrupt completion,则返回 ? UpdateEmpty(defaultR, resultValue)。
  14. 注:以下是对第二个 CaseClauses 的另一次完整迭代。
  15. secondCaseClauses 的每个 CaseClause clause,执行:
    1. completionCompletion(CaseClause clauseEvaluation)。
    2. 如果 completion.[[Value]] 不是 empty,则将 resultValue 设置为 completion.[[Value]]
    3. 如果 completion 是 abrupt completion,则返回 ? UpdateEmpty(completion, resultValue)。
  16. 返回 resultValue

14.12.3 CaseClauseIsSelected ( caseClauseNode, input )

The abstract operation CaseClauseIsSelected takes arguments caseClauseNode (a CaseClause Parse Node) and input (an ECMAScript language value) and returns either a normal completion containing a Boolean or an abrupt completion. 它确定 caseClauseNode 是否匹配 input。 It performs the following steps when called:

  1. 断言:caseClauseNode 是产生式 CaseClause : case Expression : StatementListopt 的实例。
  2. exprRef 为 ? caseClauseNodeExpressionEvaluation
  3. clauseSelector 为 ? GetValue(exprRef)。
  4. 返回 IsStrictlyEqual(input, clauseSelector)。
Note

此操作不会执行 caseClauseNodeStatementList(如果有)。CaseBlock 算法使用其返回值来确定从哪个 StatementList 开始执行。

14.12.4 Runtime Semantics: Evaluation

SwitchStatement : switch ( Expression ) CaseBlock
  1. exprRefExpression 的 ? Evaluation
  2. switchValue 为 ? GetValue(exprRef)。
  3. oldEnv 为运行中执行上下文的 LexicalEnvironment。
  4. blockEnvNewDeclarativeEnvironment(oldEnv)。
  5. 执行 BlockDeclarationInstantiation(CaseBlock, blockEnv)。
  6. 将运行中执行上下文的 LexicalEnvironment 设置为 blockEnv
  7. blockResult 为以 switchValue 为参数的 CaseBlockCaseBlockEvaluationCompletion
  8. 断言:blockEnv.[[DisposableResourceStack]] 是一个空列表。
  9. 将运行中执行上下文的 LexicalEnvironment 设置为 oldEnv
  10. 返回 blockResult
Note

无论控制如何离开 SwitchStatement,LexicalEnvironment 总会恢复到其先前状态。

CaseClause : case Expression :
  1. 返回 empty
CaseClause : case Expression : StatementList
  1. 返回 ? StatementListEvaluation
DefaultClause : default :
  1. 返回 empty
DefaultClause : default : StatementList
  1. 返回 ? StatementListEvaluation

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] Note

Statement 可以带有前缀标签。带标签语句只与带标签的 breakcontinue 语句结合使用。ECMAScript 没有 goto 语句。一个 Statement 可以是 LabelledStatement 的一部分,而该 LabelledStatement 本身又可以是另一个 LabelledStatement 的一部分,依此类推。以这种方式引入的标签,在描述各个语句的语义时统称为“当前标签集”。

14.13.1 Static Semantics: 早期错误

LabelledItem : FunctionDeclaration
  • 如果此产生式匹配到任何源文本,则为语法错误,除非该源文本是非严格代码,且宿主是 Web 浏览器或以其他方式支持 带标签的函数声明

14.13.2 Static Semantics: IsLabelledFunction ( stmt )

The abstract operation IsLabelledFunction takes argument stmt (a Statement Parse Node) and returns a Boolean. It performs the following steps when called:

  1. 如果 stmt 不是 LabelledStatement,则返回 false
  2. itemstmtLabelledItem
  3. 如果 item LabelledItem : FunctionDeclaration ,则返回 true
  4. subStmtitemStatement
  5. 返回 IsLabelledFunction(subStmt)。

14.13.3 Runtime Semantics: Evaluation

LabelledStatement : LabelIdentifier : LabelledItem
  1. 返回 ? 以 « » 为实参执行此 LabelledStatementLabelledEvaluation

14.13.4 Runtime Semantics: LabelledEvaluation

The syntax-directed operation LabelledEvaluation takes argument labelSet (a List of Strings) and returns either a normal completion containing either an ECMAScript language value or empty, or an abrupt completion. It is defined piecewise over the following productions:

BreakableStatement : IterationStatement
  1. stmtResultCompletion(以 labelSet 为实参执行 IterationStatementLoopEvaluation)。
  2. 如果 stmtResult 是 break completion,则
    1. 如果 stmtResult.[[Target]]empty,则
      1. 如果 stmtResult.[[Value]]empty,则将 stmtResult 设置为 NormalCompletion(undefined)。
      2. 否则,将 stmtResult 设置为 NormalCompletion(stmtResult.[[Value]])。
  3. 返回 ? stmtResult
BreakableStatement : SwitchStatement
  1. stmtResultCompletion(SwitchStatementEvaluation)。
  2. 如果 stmtResult 是 break completion,则
    1. 如果 stmtResult.[[Target]]empty,则
      1. 如果 stmtResult.[[Value]]empty,则将 stmtResult 设置为 NormalCompletion(undefined)。
      2. 否则,将 stmtResult 设置为 NormalCompletion(stmtResult.[[Value]])。
  3. 返回 ? stmtResult
Note 1

BreakableStatement 是可以通过无标签 BreakStatement 退出的语句。

LabelledStatement : LabelIdentifier : LabelledItem
  1. labelLabelIdentifierStringValue
  2. newLabelSetlabelSet 和 « label » 的列表连接
  3. stmtResultCompletion(以 newLabelSet 为实参执行 LabelledItemLabelledEvaluation)。
  4. 如果 stmtResult 是 break completion 且 stmtResult.[[Target]]label,则
    1. stmtResult 设置为 NormalCompletion(stmtResult.[[Value]])。
  5. 返回 ? stmtResult
LabelledItem : FunctionDeclaration
  1. 返回 ? FunctionDeclarationEvaluation
Statement : BlockStatement VariableStatement EmptyStatement ExpressionStatement IfStatement ContinueStatement BreakStatement ReturnStatement WithStatement ThrowStatement TryStatement DebuggerStatement
  1. 返回 ? StatementEvaluation
Note 2

Statement 中仅有两个产生式对 LabelledEvaluation 具有特殊语义:BreakableStatementLabelledStatement

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 为 ? ExpressionEvaluation
  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] Note

try 语句包围一段代码块,其中可能发生异常条件,例如运行时错误或 throw 语句。catch 子句提供异常处理代码。当 catch 子句捕获异常时,其 CatchParameter 会被绑定到该异常。

14.15.1 Static Semantics: 早期错误

Catch : catch ( CatchParameter ) Block

14.15.2 Runtime Semantics: CatchClauseEvaluation

The syntax-directed operation CatchClauseEvaluation takes argument thrownValue (an ECMAScript language value) and returns either a normal completion containing either an ECMAScript language value or empty, or an abrupt completion. It is defined piecewise over the following productions:

Catch : catch ( CatchParameter ) Block
  1. oldEnv 为运行中的执行上下文的 LexicalEnvironment。
  2. catchEnvNewDeclarativeEnvironment(oldEnv)。
  3. CatchParameterBoundNames 的每个元素 argName,执行:
    1. 执行 ! catchEnv.CreateMutableBinding(argName, false)。
  4. 将运行中的执行上下文的 LexicalEnvironment 设置为 catchEnv
  5. statusCompletion(以 thrownValuecatchEnv 为实参执行 CatchParameterBindingInitialization)。
  6. 如果 status 是 abrupt completion,则
    1. 将运行中的执行上下文的 LexicalEnvironment 设置为 oldEnv
    2. 返回 ? status
  7. blockCompletionCompletion(BlockEvaluation)。
  8. 将运行中的执行上下文的 LexicalEnvironment 设置为 oldEnv
  9. 返回 ? blockCompletion
Catch : catch Block
  1. 返回 ? BlockEvaluation
Note

无论控制如何离开 Block,LexicalEnvironment 总会恢复到其先前状态。

14.15.3 Runtime Semantics: Evaluation

TryStatement : try Block Catch
  1. blockResultCompletion(BlockEvaluation)。
  2. 如果 blockResult 是 throw completion,则令 catchResultCompletion(以 blockResult.[[Value]] 为实参执行 CatchCatchClauseEvaluation)。
  3. 否则,令 catchResultblockResult
  4. 返回 ? UpdateEmpty(catchResult, undefined)。
TryStatement : try Block Finally
  1. blockResultCompletion(BlockEvaluation)。
  2. finallyResultCompletion(FinallyEvaluation)。
  3. 如果 finallyResult 是 normal completion,则将 finallyResult 设置为 blockResult
  4. 返回 ? UpdateEmpty(finallyResult, undefined)。
TryStatement : try Block Catch Finally
  1. blockResultCompletion(BlockEvaluation)。
  2. 如果 blockResult 是 throw completion,则令 catchResultCompletion(以 blockResult.[[Value]] 为实参执行 CatchCatchClauseEvaluation)。
  3. 否则,令 catchResultblockResult
  4. finallyResultCompletion(FinallyEvaluation)。
  5. 如果 finallyResult 是 normal completion,则将 finallyResult 设置为 catchResult
  6. 返回 ? UpdateEmpty(finallyResult, undefined)。

14.16 debugger 语句

语法

DebuggerStatement : debugger ;

14.16.1 Runtime Semantics: Evaluation

Note

求值 DebuggerStatement 时,在调试器下运行的实现可以因此产生一个断点。如果不存在调试器或调试器未激活,此语句没有可观察效果。

DebuggerStatement : debugger ;
  1. 如果实现定义的调试设施可用且已启用,则
    1. 执行一个实现定义的调试动作。
    2. 返回一个新的实现定义 Completion Record
  2. 返回 empty

15 ECMAScript 语言:函数和类

Note

各种 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 Note

同一个 BindingIdentifierFormalParameterList 中多次出现,只允许用于具有简单参数列表且不是在严格模式代码中定义的函数。

15.1.2 Static Semantics: ContainsExpression

The syntax-directed operation ContainsExpression takes no arguments and returns a Boolean. It is defined piecewise over the following productions:

ObjectBindingPattern : { } { BindingRestProperty }
  1. 返回 false
ObjectBindingPattern : { BindingPropertyList , BindingRestProperty }
  1. 返回 BindingPropertyListContainsExpression
ArrayBindingPattern : [ Elisionopt ]
  1. 返回 false
ArrayBindingPattern : [ Elisionopt BindingRestElement ]
  1. 返回 BindingRestElementContainsExpression
ArrayBindingPattern : [ BindingElementList , Elisionopt ]
  1. 返回 BindingElementListContainsExpression
ArrayBindingPattern : [ BindingElementList , Elisionopt BindingRestElement ]
  1. hasBindingElementListContainsExpression
  2. 如果 hastrue,则返回 true
  3. 返回 BindingRestElementContainsExpression
BindingPropertyList : BindingPropertyList , BindingProperty
  1. hasBindingPropertyListContainsExpression
  2. 如果 hastrue,则返回 true
  3. 返回 BindingPropertyContainsExpression
BindingElementList : BindingElementList , BindingElisionElement
  1. hasBindingElementListContainsExpression
  2. 如果 hastrue,则返回 true
  3. 返回 BindingElisionElementContainsExpression
BindingElisionElement : Elisionopt BindingElement
  1. 返回 BindingElementContainsExpression
BindingProperty : PropertyName : BindingElement
  1. hasPropertyNameIsComputedPropertyKey
  2. 如果 hastrue,则返回 true
  3. 返回 BindingElementContainsExpression
BindingElement : BindingPattern Initializer
  1. 返回 true
SingleNameBinding : BindingIdentifier
  1. 返回 false
SingleNameBinding : BindingIdentifier Initializer
  1. 返回 true
BindingRestElement : ... BindingIdentifier
  1. 返回 false
BindingRestElement : ... BindingPattern
  1. 返回 BindingPatternContainsExpression
FormalParameters : [empty]
  1. 返回 false
FormalParameters : FormalParameterList , FunctionRestParameter
  1. 如果 FormalParameterListContainsExpressiontrue,则返回 true
  2. 返回 FunctionRestParameterContainsExpression
FormalParameterList : FormalParameterList , FormalParameter
  1. 如果 FormalParameterListContainsExpressiontrue,则返回 true
  2. 返回 FormalParameterContainsExpression
ArrowParameters : BindingIdentifier
  1. 返回 false
ArrowParameters : CoverParenthesizedExpressionAndArrowParameterList
  1. formals 为由 CoverParenthesizedExpressionAndArrowParameterList 覆盖的 ArrowFormalParameters
  2. 返回 formalsContainsExpression
AsyncArrowBindingIdentifier : BindingIdentifier
  1. 返回 false

15.1.3 Static Semantics: IsSimpleParameterList

The syntax-directed operation IsSimpleParameterList takes no arguments and returns a Boolean. It is defined piecewise over the following productions:

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. 如果 FormalParameterListIsSimpleParameterListfalse,则返回 false
  2. 返回 FormalParameterIsSimpleParameterList
FormalParameter : BindingElement
  1. 返回 BindingElementIsSimpleParameterList
ArrowParameters : BindingIdentifier
  1. 返回 true
ArrowParameters : CoverParenthesizedExpressionAndArrowParameterList
  1. formals 为由 CoverParenthesizedExpressionAndArrowParameterList 覆盖的 ArrowFormalParameters
  2. 返回 formalsIsSimpleParameterList
AsyncArrowBindingIdentifier : BindingIdentifier
  1. 返回 true
CoverCallExpressionAndAsyncArrowHead : MemberExpression Arguments
  1. head 为由 CoverCallExpressionAndAsyncArrowHead 覆盖的 AsyncArrowHead
  2. 返回 headIsSimpleParameterList

15.1.4 Static Semantics: HasInitializer

The syntax-directed operation HasInitializer takes no arguments and returns a Boolean. It is defined piecewise over the following productions:

BindingElement : BindingPattern
  1. 返回 false
BindingElement : BindingPattern Initializer
  1. 返回 true
SingleNameBinding : BindingIdentifier
  1. 返回 false
SingleNameBinding : BindingIdentifier Initializer
  1. 返回 true
FormalParameterList : FormalParameterList , FormalParameter
  1. 如果 FormalParameterListHasInitializertrue,则返回 true
  2. 返回 FormalParameterHasInitializer

15.1.5 Static Semantics: ExpectedArgumentCount

The syntax-directed operation ExpectedArgumentCount takes no arguments and returns a non-negative integer. It is defined piecewise over the following productions:

FormalParameters : [empty] FunctionRestParameter
  1. 返回 0。
FormalParameters : FormalParameterList , FunctionRestParameter
  1. 返回 FormalParameterListExpectedArgumentCount
Note

FormalParameterList 的 ExpectedArgumentCount,是位于 rest 参数或第一个带有 Initializer 的 FormalParameter 左侧的 FormalParameters 的数量。第一个带有 initializer 的形参之后允许出现没有 initializer 的 FormalParameter,但这类形参会被视为以 undefined 作为默认值的可选形参。

FormalParameterList : FormalParameter
  1. 如果 FormalParameterHasInitializertrue,则返回 0。
  2. 返回 1。
FormalParameterList : FormalParameterList , FormalParameter
  1. countFormalParameterListExpectedArgumentCount
  2. 如果 FormalParameterListHasInitializertrue,或 FormalParameterHasInitializertrue,则返回 count
  3. 返回 count + 1。
ArrowParameters : BindingIdentifier
  1. 返回 1。
ArrowParameters : CoverParenthesizedExpressionAndArrowParameterList
  1. formals 为由 CoverParenthesizedExpressionAndArrowParameterList 覆盖的 ArrowFormalParameters
  2. 返回 formalsExpectedArgumentCount
PropertySetParameterList : FormalParameter
  1. 如果 FormalParameterHasInitializertrue,则返回 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 } Note

FunctionBodyLexicallyDeclaredNames 不包括使用 var 或函数声明绑定的标识符。

FunctionBody : FunctionStatementList

15.2.2 Static Semantics: FunctionBodyContainsUseStrict

The syntax-directed operation FunctionBodyContainsUseStrict takes no arguments and returns a Boolean. It is defined piecewise over the following productions:

FunctionBody : FunctionStatementList
  1. 如果 FunctionBodyDirective Prologue 包含 Use Strict Directive,则返回 true
  2. 返回 false

15.2.3 Runtime Semantics: EvaluateFunctionBody

The syntax-directed operation EvaluateFunctionBody takes arguments funcObj (an ECMAScript function object) and argList (a List of ECMAScript language values) and returns a return completion or a throw completion. It is defined piecewise over the following productions:

FunctionBody : FunctionStatementList
  1. 执行 ? FunctionDeclarationInstantiation(funcObj, argList)。
  2. 执行 ? FunctionStatementListEvaluation
  3. 注:如果前一步产生了 normal completion,则求值是通过越过 FunctionStatementList 末尾而完成的。
  4. 返回 ReturnCompletion(undefined)。

15.2.4 Runtime Semantics: InstantiateOrdinaryFunctionObject

The syntax-directed operation InstantiateOrdinaryFunctionObject takes arguments envRecord (an Environment Record) and privateEnv (a PrivateEnvironment Record or null) and returns an ECMAScript function object. It is defined piecewise over the following productions:

FunctionDeclaration : function BindingIdentifier ( FormalParameters ) { FunctionBody }
  1. nameBindingIdentifierStringValue
  2. sourceText 为由 FunctionDeclaration 匹配的源文本
  3. closureOrdinaryFunctionCreate(%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. closureOrdinaryFunctionCreate(%Function.prototype%, sourceText, FormalParameters, FunctionBody, non-lexical-this, envRecord, privateEnv)。
  3. 执行 SetFunctionName(closure, "default")。
  4. 执行 MakeConstructor(closure)。
  5. 返回 closure
Note

匿名 FunctionDeclaration 只能作为 export default 声明的一部分出现,因此其函数代码始终是严格模式代码。

15.2.5 Runtime Semantics: InstantiateOrdinaryFunctionExpression

The syntax-directed operation InstantiateOrdinaryFunctionExpression takes optional argument name (a property key or a Private Name) and returns an ECMAScript function object. It is defined piecewise over the following productions:

FunctionExpression : function ( FormalParameters ) { FunctionBody }
  1. 如果 name 不存在,则将 name 设置为空 String。
  2. envRecord 为运行中的执行上下文的 LexicalEnvironment。
  3. privateEnv 为运行中的执行上下文的 PrivateEnvironment。
  4. sourceText 为由 FunctionExpression 匹配的源文本
  5. closureOrdinaryFunctionCreate(%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 设置为 BindingIdentifierStringValue
  3. outerEnv 为运行中的执行上下文的 LexicalEnvironment。
  4. funcEnvNewDeclarativeEnvironment(outerEnv)。
  5. 执行 ! funcEnv.CreateImmutableBinding(name, false)。
  6. privateEnv 为运行中的执行上下文的 PrivateEnvironment。
  7. sourceText 为由 FunctionExpression 匹配的源文本
  8. closureOrdinaryFunctionCreate(%Function.prototype%, sourceText, FormalParameters, FunctionBody, non-lexical-this, funcEnv, privateEnv)。
  9. 执行 SetFunctionName(closure, name)。
  10. 执行 MakeConstructor(closure)。
  11. 执行 ! funcEnv.InitializeBinding(name, closure)。
  12. 返回 closure
Note

FunctionExpression 中的 BindingIdentifier 可以从该 FunctionExpressionFunctionBody 内部引用,以允许函数递归调用自身。不过,不同于 FunctionDeclarationFunctionExpression 中的 BindingIdentifier 不能从包围该 FunctionExpression 的作用域中引用,也不会影响该作用域。

15.2.6 Runtime Semantics: Evaluation

FunctionDeclaration : function BindingIdentifier ( FormalParameters ) { FunctionBody }
  1. 返回 empty
Note 1 FunctionDeclaration : function ( FormalParameters ) { FunctionBody }
  1. 返回 empty
FunctionExpression : function BindingIdentifieropt ( FormalParameters ) { FunctionBody }
  1. 返回 FunctionExpressionInstantiateOrdinaryFunctionExpression
Note 2

对于使用 FunctionDeclarationFunctionExpression 定义的每个函数,都会自动创建一个 "prototype" 属性,以允许该函数可能被用作构造器。

FunctionStatementList : [empty]
  1. 返回 undefined
FunctionStatementList : StatementList
  1. resultStatementList 的求值的 Completion
  2. env 为运行中执行上下文的 LexicalEnvironment。
  3. 断言:env 是声明式环境记录。
  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

The syntax-directed operation ConciseBodyContainsUseStrict takes no arguments and returns a Boolean. It is defined piecewise over the following productions:

ConciseBody : ExpressionBody
  1. 返回 false
ConciseBody : { FunctionBody }
  1. 返回 FunctionBodyFunctionBodyContainsUseStrict

15.3.3 Runtime Semantics: EvaluateConciseBody

The syntax-directed operation EvaluateConciseBody takes arguments funcObj (an ECMAScript function object) and argList (a List of ECMAScript language values) and returns a return completion or a throw completion. It is defined piecewise over the following productions:

ConciseBody : ExpressionBody
  1. 执行 ? FunctionDeclarationInstantiation(funcObj, argList)。
  2. 返回 ? ExpressionBodyEvaluation

15.3.4 Runtime Semantics: InstantiateArrowFunctionExpression

The syntax-directed operation InstantiateArrowFunctionExpression takes optional argument name (a property key or a Private Name) and returns an ECMAScript function object. It is defined piecewise over the following productions:

ArrowFunction : ArrowParameters => ConciseBody
  1. 如果 name 不存在,则将 name 设置为空 String。
  2. envRecord 为运行中的执行上下文的 LexicalEnvironment。
  3. privateEnv 为运行中的执行上下文的 PrivateEnvironment。
  4. sourceText 为由 ArrowFunction 匹配的源文本
  5. closureOrdinaryFunctionCreate(%Function.prototype%, sourceText, ArrowParameters, ConciseBody, lexical-this, envRecord, privateEnv)。
  6. 执行 SetFunctionName(closure, name)。
  7. 返回 closure
Note

ArrowFunction 不会为 argumentssuperthisnew.target 定义局部绑定。ArrowFunction 内部对 argumentssuperthisnew.target 的任何引用,都必须解析到词法外层环境中的绑定。通常,这会是紧邻外层函数的 Function Environment。即使 ArrowFunction 可以包含super 的引用,步骤 5 中创建的函数对象也不会通过执行 MakeMethod 而成为方法。引用 superArrowFunction 始终包含在非 ArrowFunction 内部,并且实现 super 所必需的状态可通过 ArrowFunction函数对象所捕获的 envRecord 访问。

15.3.5 Runtime Semantics: Evaluation

ArrowFunction : ArrowParameters => ConciseBody
  1. 返回 ArrowFunctionInstantiateArrowFunctionExpression
ExpressionBody : AssignmentExpression
  1. exprRef 为 ? AssignmentExpressionEvaluation
  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

The syntax-directed operation HasDirectSuper takes no arguments and returns a Boolean. It is defined piecewise over the following productions:

MethodDefinition : ClassElementName ( UniqueFormalParameters ) { FunctionBody }
  1. 如果 UniqueFormalParameters Contains SuperCalltrue,则返回 true
  2. 返回 FunctionBody Contains SuperCall
MethodDefinition : get ClassElementName ( ) { FunctionBody }
  1. 返回 FunctionBody Contains SuperCall
MethodDefinition : set ClassElementName ( PropertySetParameterList ) { FunctionBody }
  1. 如果 PropertySetParameterList Contains SuperCalltrue,则返回 true
  2. 返回 FunctionBody Contains SuperCall
GeneratorMethod : * ClassElementName ( UniqueFormalParameters ) { GeneratorBody }
  1. 如果 UniqueFormalParameters Contains SuperCalltrue,则返回 true
  2. 返回 GeneratorBody Contains SuperCall
AsyncGeneratorMethod : async * ClassElementName ( UniqueFormalParameters ) { AsyncGeneratorBody }
  1. 如果 UniqueFormalParameters Contains SuperCalltrue,则返回 true
  2. 返回 AsyncGeneratorBody Contains SuperCall
AsyncMethod : async ClassElementName ( UniqueFormalParameters ) { AsyncFunctionBody }
  1. 如果 UniqueFormalParameters Contains SuperCalltrue,则返回 true
  2. 返回 AsyncFunctionBody Contains SuperCall

15.4.3 Static Semantics: SpecialMethod

The syntax-directed operation SpecialMethod takes no arguments and returns a Boolean. It is defined piecewise over the following productions:

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

The syntax-directed operation DefineMethod takes argument obj (an Object) and optional argument proto (an Object) and returns either a normal completion containing a Record with fields [[Key]] (a property key) and [[Closure]] (an ECMAScript function object) or an abrupt completion. It is defined piecewise over the following productions:

MethodDefinition : ClassElementName ( UniqueFormalParameters ) { FunctionBody }
  1. propertyKey 为 ? ClassElementNameEvaluation
  2. envRecord 为运行中的执行上下文的 LexicalEnvironment。
  3. privateEnv 为运行中的执行上下文的 PrivateEnvironment。
  4. 如果 proto 不存在,则将 proto 设置为 %Function.prototype%
  5. sourceText 为由 MethodDefinition 匹配的源文本
  6. closureOrdinaryFunctionCreate(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

The syntax-directed operation MethodDefinitionEvaluation takes arguments obj (an Object) and enumerable (a Boolean) and returns either a normal completion containing either a PrivateElement or unused, or an abrupt completion. It is defined piecewise over the following productions:

MethodDefinition : ClassElementName ( UniqueFormalParameters ) { FunctionBody }
  1. methodDef 为 ? 以 obj 为实参执行 MethodDefinitionDefineMethod
  2. 执行 SetFunctionName(methodDef.[[Closure]], methodDef.[[Key]])。
  3. 返回 ? DefineMethodProperty(obj, methodDef.[[Key]], methodDef.[[Closure]], enumerable)。
MethodDefinition : get ClassElementName ( ) { FunctionBody }
  1. propertyKey 为 ? ClassElementNameEvaluation
  2. envRecord 为运行中的执行上下文的 LexicalEnvironment。
  3. privateEnv 为运行中的执行上下文的 PrivateEnvironment。
  4. sourceText 为由 MethodDefinition 匹配的源文本
  5. formalParamList 为产生式 FormalParameters : [empty] 的实例。
  6. closureOrdinaryFunctionCreate(%Function.prototype%, sourceText, formalParamList, FunctionBody, non-lexical-this, envRecord, privateEnv)。
  7. 执行 MakeMethod(closure, obj)。
  8. 执行 SetFunctionName(closure, propertyKey, "get")。
  9. 如果 propertyKeyPrivate Name,则
    1. 返回 PrivateElement { [[Key]]: propertyKey, [[Kind]]: accessor, [[Get]]: closure, [[Set]]: undefined }。
  10. propertyDesc 为 PropertyDescriptor { [[Get]]: closure, [[Enumerable]]: enumerable, [[Configurable]]: true }。
  11. 执行 ? DefinePropertyOrThrow(obj, propertyKey, propertyDesc)。
  12. 返回 unused
MethodDefinition : set ClassElementName ( PropertySetParameterList ) { FunctionBody }
  1. propertyKey 为 ? ClassElementNameEvaluation
  2. envRecord 为运行中的执行上下文的 LexicalEnvironment。
  3. privateEnv 为运行中的执行上下文的 PrivateEnvironment。
  4. sourceText 为由 MethodDefinition 匹配的源文本
  5. closureOrdinaryFunctionCreate(%Function.prototype%, sourceText, PropertySetParameterList, FunctionBody, non-lexical-this, envRecord, privateEnv)。
  6. 执行 MakeMethod(closure, obj)。
  7. 执行 SetFunctionName(closure, propertyKey, "set")。
  8. 如果 propertyKeyPrivate Name,则
    1. 返回 PrivateElement { [[Key]]: propertyKey, [[Kind]]: accessor, [[Get]]: undefined, [[Set]]: closure }。
  9. propertyDesc 为 PropertyDescriptor { [[Set]]: closure, [[Enumerable]]: enumerable, [[Configurable]]: true }。
  10. 执行 ? DefinePropertyOrThrow(obj, propertyKey, propertyDesc)。
  11. 返回 unused
GeneratorMethod : * ClassElementName ( UniqueFormalParameters ) { GeneratorBody }
  1. propertyKey 为 ? ClassElementNameEvaluation
  2. envRecord 为运行中的执行上下文的 LexicalEnvironment。
  3. privateEnv 为运行中的执行上下文的 PrivateEnvironment。
  4. sourceText 为由 GeneratorMethod 匹配的源文本
  5. closureOrdinaryFunctionCreate(%GeneratorFunction.prototype%, sourceText, UniqueFormalParameters, GeneratorBody, non-lexical-this, envRecord, privateEnv)。
  6. 执行 MakeMethod(closure, obj)。
  7. 执行 SetFunctionName(closure, propertyKey)。
  8. protoOrdinaryObjectCreate(%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 为 ? ClassElementNameEvaluation
  2. envRecord 为运行中的执行上下文的 LexicalEnvironment。
  3. privateEnv 为运行中的执行上下文的 PrivateEnvironment。
  4. sourceText 为由 AsyncGeneratorMethod 匹配的源文本
  5. closureOrdinaryFunctionCreate(%AsyncGeneratorFunction.prototype%, sourceText, UniqueFormalParameters, AsyncGeneratorBody, non-lexical-this, envRecord, privateEnv)。
  6. 执行 MakeMethod(closure, obj)。
  7. 执行 SetFunctionName(closure, propertyKey)。
  8. protoOrdinaryObjectCreate(%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 为 ? ClassElementNameEvaluation
  2. envRecord 为运行中的执行上下文的 LexicalEnvironment。
  3. privateEnv 为运行中的执行上下文的 PrivateEnvironment。
  4. sourceText 为由 AsyncMethod 匹配的源文本
  5. closureOrdinaryFunctionCreate(%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] Note 1

紧跟在 yield 之后的句法上下文需要使用 InputElementRegExpOrTemplateTail 词法目标。

Note 2

YieldExpression 不能在生成器函数的 FormalParameters 中使用,因为作为 FormalParameters 一部分的任何表达式都会在所得 Generator 处于可恢复状态之前被求值。

Note 3

与 Generators 相关的抽象操作定义在 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

The syntax-directed operation EvaluateGeneratorBody takes arguments funcObj (an ECMAScript function object) and argList (a List of ECMAScript language values) and returns a throw completion or a return completion. It is defined piecewise over the following productions:

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

The syntax-directed operation InstantiateGeneratorFunctionObject takes arguments envRecord (an Environment Record) and privateEnv (a PrivateEnvironment Record or null) and returns an ECMAScript function object. It is defined piecewise over the following productions:

GeneratorDeclaration : function * BindingIdentifier ( FormalParameters ) { GeneratorBody }
  1. nameBindingIdentifierStringValue
  2. sourceText 为由 GeneratorDeclaration 匹配的源文本
  3. closureOrdinaryFunctionCreate(%GeneratorFunction.prototype%, sourceText, FormalParameters, GeneratorBody, non-lexical-this, envRecord, privateEnv)。
  4. 执行 SetFunctionName(closure, name)。
  5. protoOrdinaryObjectCreate(%GeneratorPrototype%)。
  6. 执行 ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: proto, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  7. 返回 closure
GeneratorDeclaration : function * ( FormalParameters ) { GeneratorBody }
  1. sourceText 为由 GeneratorDeclaration 匹配的源文本
  2. closureOrdinaryFunctionCreate(%GeneratorFunction.prototype%, sourceText, FormalParameters, GeneratorBody, non-lexical-this, envRecord, privateEnv)。
  3. 执行 SetFunctionName(closure, "default")。
  4. protoOrdinaryObjectCreate(%GeneratorPrototype%)。
  5. 执行 ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: proto, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  6. 返回 closure
Note

匿名 GeneratorDeclaration 只能作为 export default 声明的一部分出现,因此其函数代码始终是严格模式代码。

15.5.4 Runtime Semantics: InstantiateGeneratorFunctionExpression

The syntax-directed operation InstantiateGeneratorFunctionExpression takes optional argument name (a property key or a Private Name) and returns an ECMAScript function object. It is defined piecewise over the following productions:

GeneratorExpression : function * ( FormalParameters ) { GeneratorBody }
  1. 如果 name 不存在,则将 name 设置为空 String。
  2. envRecord 为运行中的执行上下文的 LexicalEnvironment。
  3. privateEnv 为运行中的执行上下文的 PrivateEnvironment。
  4. sourceText 为由 GeneratorExpression 匹配的源文本
  5. closureOrdinaryFunctionCreate(%GeneratorFunction.prototype%, sourceText, FormalParameters, GeneratorBody, non-lexical-this, envRecord, privateEnv)。
  6. 执行 SetFunctionName(closure, name)。
  7. protoOrdinaryObjectCreate(%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 设置为 BindingIdentifierStringValue
  3. outerEnv 为运行中的执行上下文的 LexicalEnvironment。
  4. funcEnvNewDeclarativeEnvironment(outerEnv)。
  5. 执行 ! funcEnv.CreateImmutableBinding(name, false)。
  6. privateEnv 为运行中的执行上下文的 PrivateEnvironment。
  7. sourceText 为由 GeneratorExpression 匹配的源文本
  8. closureOrdinaryFunctionCreate(%GeneratorFunction.prototype%, sourceText, FormalParameters, GeneratorBody, non-lexical-this, funcEnv, privateEnv)。
  9. 执行 SetFunctionName(closure, name)。
  10. protoOrdinaryObjectCreate(%GeneratorPrototype%)。
  11. 执行 ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: proto, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  12. 执行 ! funcEnv.InitializeBinding(name, closure)。
  13. 返回 closure
Note

GeneratorExpression 中的 BindingIdentifier 可以从该 GeneratorExpressionFunctionBody 内部引用,以允许生成器代码递归调用自身。不过,不同于 GeneratorDeclarationGeneratorExpression 中的 BindingIdentifier 不能从包围该 GeneratorExpression 的作用域中引用,也不会影响该作用域。

15.5.5 Runtime Semantics: Evaluation

GeneratorExpression : function * BindingIdentifieropt ( FormalParameters ) { GeneratorBody }
  1. 返回 GeneratorExpressionInstantiateGeneratorFunctionExpression
YieldExpression : yield
  1. 返回 ? Yield(undefined)。
YieldExpression : yield AssignmentExpression
  1. exprRef 为 ? AssignmentExpressionEvaluation
  2. value 为 ? GetValue(exprRef)。
  3. 返回 ? Yield(value)。
YieldExpression : yield * AssignmentExpression
  1. genKindGetGeneratorKind()。
  2. 断言:genKindsyncasync
  3. exprRef 为 ? AssignmentExpressionEvaluation
  4. value 为 ? GetValue(exprRef)。
  5. iteratorRecord 为 ? GetIterator(value, genKind)。
  6. iteratoriteratorRecord.[[Iterator]]
  7. receivedNormalCompletion(undefined)。
  8. 重复:
    1. 如果 received 是 normal completion,则
      1. innerResult 为 ? Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]], « received.[[Value]] »)。
      2. 如果 genKindasync,则将 innerResult 设置为 ? Await(innerResult)。
      3. 如果 innerResult 不是 Object,则抛出 TypeError 异常。
      4. done 为 ? IteratorComplete(innerResult)。
      5. 如果 donetrue,则
        1. 返回 ? IteratorValue(innerResult)。
      6. 如果 genKindasync,则将 received 设置为 Completion(AsyncGeneratorYield(? IteratorValue(innerResult)))。
      7. 否则,将 received 设置为 Completion(GeneratorYield(innerResult))。
    2. 否则如果 received 是 throw completion,则
      1. throw 为 ? GetMethod(iterator, "throw")。
      2. 如果 throw 不是 undefined,则
        1. innerResult 为 ? Call(throw, iterator, « received.[[Value]] »)。
        2. 如果 genKindasync,则将 innerResult 设置为 ? Await(innerResult)。
        3. 注:来自内部迭代器 throw 方法的异常会被传播。来自内部 throw 方法的 normal completion 会以类似于内部 next 的方式处理。
        4. 如果 innerResult 不是 Object,则抛出 TypeError 异常。
        5. done 为 ? IteratorComplete(innerResult)。
        6. 如果 donetrue,则
          1. 返回 ? IteratorValue(innerResult)。
        7. 如果 genKindasync,则将 received 设置为 Completion(AsyncGeneratorYield(? IteratorValue(innerResult)))。
        8. 否则,将 received 设置为 Completion(GeneratorYield(innerResult))。
      3. 否则,
        1. 注:如果 iterator 没有 throw 方法,这个 throw 将会终止 yield* 循环。但首先我们需要给 iterator 一个清理的机会。
        2. closeCompletionNormalCompletion(empty)。
        3. 如果 genKindasync,则执行 ? AsyncIteratorClose(iteratorRecord, closeCompletion)。
        4. 否则,执行 ? IteratorClose(iteratorRecord, closeCompletion)。
        5. 注:下一步会抛出 TypeError,以表明存在 yield* 协议违规:iterator 没有 throw 方法。
        6. 抛出 TypeError 异常。
    3. 否则,
      1. 断言:received 是 return completion。
      2. return 为 ? GetMethod(iterator, "return")。
      3. 如果 returnundefined,则
        1. receivedValuereceived.[[Value]]
        2. 如果 genKindasync,则
          1. receivedValue 设置为 ? Await(receivedValue)。
        3. 返回 ReturnCompletion(receivedValue)。
      4. innerReturnResult 为 ? Call(return, iterator, « received.[[Value]] »)。
      5. 如果 genKindasync,则将 innerReturnResult 设置为 ? Await(innerReturnResult)。
      6. 如果 innerReturnResult 不是 Object,则抛出 TypeError 异常。
      7. done 为 ? IteratorComplete(innerReturnResult)。
      8. 如果 donetrue,则
        1. returnedValue 为 ? IteratorValue(innerReturnResult)。
        2. 返回 ReturnCompletion(returnedValue)。
      9. 如果 genKindasync,则将 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] Note 1

YieldExpressionAwaitExpression 不能在异步生成器函数的 FormalParameters 中使用,因为作为 FormalParameters 一部分的任何表达式都会在所得 AsyncGenerator 处于可恢复状态之前被求值。

Note 2

与 AsyncGenerators 相关的抽象操作定义在 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

The syntax-directed operation EvaluateAsyncGeneratorBody takes arguments funcObj (an ECMAScript function object) and argList (a List of ECMAScript language values) and returns a throw completion or a return completion. It is defined piecewise over the following productions:

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

The syntax-directed operation InstantiateAsyncGeneratorFunctionObject takes arguments envRecord (an Environment Record) and privateEnv (a PrivateEnvironment Record or null) and returns an ECMAScript function object. It is defined piecewise over the following productions:

AsyncGeneratorDeclaration : async function * BindingIdentifier ( FormalParameters ) { AsyncGeneratorBody }
  1. nameBindingIdentifierStringValue
  2. sourceText 为由 AsyncGeneratorDeclaration 匹配的源文本
  3. closureOrdinaryFunctionCreate(%AsyncGeneratorFunction.prototype%, sourceText, FormalParameters, AsyncGeneratorBody, non-lexical-this, envRecord, privateEnv)。
  4. 执行 SetFunctionName(closure, name)。
  5. protoOrdinaryObjectCreate(%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. closureOrdinaryFunctionCreate(%AsyncGeneratorFunction.prototype%, sourceText, FormalParameters, AsyncGeneratorBody, non-lexical-this, envRecord, privateEnv)。
  3. 执行 SetFunctionName(closure, "default")。
  4. protoOrdinaryObjectCreate(%AsyncGeneratorPrototype%)。
  5. 执行 ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: proto, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  6. 返回 closure
Note

匿名 AsyncGeneratorDeclaration 只能作为 export default 声明的一部分出现。

15.6.4 Runtime Semantics: InstantiateAsyncGeneratorFunctionExpression

The syntax-directed operation InstantiateAsyncGeneratorFunctionExpression takes optional argument name (a property key or a Private Name) and returns an ECMAScript function object. It is defined piecewise over the following productions:

AsyncGeneratorExpression : async function * ( FormalParameters ) { AsyncGeneratorBody }
  1. 如果 name 不存在,则将 name 设置为空 String。
  2. envRecord 为运行中的执行上下文的 LexicalEnvironment。
  3. privateEnv 为运行中的执行上下文的 PrivateEnvironment。
  4. sourceText 为由 AsyncGeneratorExpression 匹配的源文本
  5. closureOrdinaryFunctionCreate(%AsyncGeneratorFunction.prototype%, sourceText, FormalParameters, AsyncGeneratorBody, non-lexical-this, envRecord, privateEnv)。
  6. 执行 SetFunctionName(closure, name)。
  7. protoOrdinaryObjectCreate(%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 设置为 BindingIdentifierStringValue
  3. outerEnv 为运行中的执行上下文的 LexicalEnvironment。
  4. funcEnvNewDeclarativeEnvironment(outerEnv)。
  5. 执行 ! funcEnv.CreateImmutableBinding(name, false)。
  6. privateEnv 为运行中的执行上下文的 PrivateEnvironment。
  7. sourceText 为由 AsyncGeneratorExpression 匹配的源文本
  8. closureOrdinaryFunctionCreate(%AsyncGeneratorFunction.prototype%, sourceText, FormalParameters, AsyncGeneratorBody, non-lexical-this, funcEnv, privateEnv)。
  9. 执行 SetFunctionName(closure, name)。
  10. protoOrdinaryObjectCreate(%AsyncGeneratorPrototype%)。
  11. 执行 ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: proto, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  12. 执行 ! funcEnv.InitializeBinding(name, closure)。
  13. 返回 closure
Note

AsyncGeneratorExpression 中的 BindingIdentifier 可以从该 AsyncGeneratorExpressionAsyncGeneratorBody 内部引用,以允许生成器代码递归调用自身。不过,不同于 AsyncGeneratorDeclarationAsyncGeneratorExpression 中的 BindingIdentifier 不能从包围该 AsyncGeneratorExpression 的作用域中引用,也不会影响该作用域。

15.6.5 Runtime Semantics: Evaluation

AsyncGeneratorExpression : async function * BindingIdentifieropt ( FormalParameters ) { AsyncGeneratorBody }
  1. 返回 AsyncGeneratorExpressionInstantiateAsyncGeneratorFunctionExpression

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 Note

类定义始终是严格模式代码。

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

The syntax-directed operation ClassElementKind takes no arguments and returns constructor-method, non-constructor-method, or empty. It is defined piecewise over the following productions:

ClassElement : MethodDefinition
  1. 如果 MethodDefinitionPropName"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

The syntax-directed operation ConstructorMethod takes no arguments and returns a ClassElement Parse Node or empty. It is defined piecewise over the following productions:

ClassElementList : ClassElement
  1. 如果 ClassElementClassElementKindconstructor-method,则返回 ClassElement
  2. 返回 empty
ClassElementList : ClassElementList ClassElement
  1. headClassElementListConstructorMethod
  2. 如果 head 不是 empty,则返回 head
  3. 如果 ClassElementClassElementKindconstructor-method,则返回 ClassElement
  4. 返回 empty
Note

早期错误规则确保只存在一个名为 "constructor" 的方法定义,并且它不是访问器属性或生成器定义。

15.7.4 Static Semantics: IsStatic

The syntax-directed operation IsStatic takes no arguments and returns a Boolean. It is defined piecewise over the following productions:

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

The syntax-directed operation NonConstructorElements takes no arguments and returns a List of ClassElement Parse Nodes. It is defined piecewise over the following productions:

ClassElementList : ClassElement
  1. 如果 ClassElementClassElementKindnon-constructor-method,则
    1. 返回 « ClassElement »。
  2. 返回新的空 List
ClassElementList : ClassElementList ClassElement
  1. listClassElementListNonConstructorElements
  2. 如果 ClassElementClassElementKindnon-constructor-method,则
    1. ClassElement 追加到 list
  3. 返回 list

15.7.6 Static Semantics: PrototypePropertyNameList

The syntax-directed operation PrototypePropertyNameList takes no arguments and returns a List of property keys. It is defined piecewise over the following productions:

ClassElementList : ClassElement
  1. propertyNameClassElementPropName
  2. 如果 propertyNameempty,则返回新的空 List
  3. 如果 ClassElementIsStatictrue,则返回新的空 List
  4. 返回 « propertyName »。
ClassElementList : ClassElementList ClassElement
  1. listClassElementListPrototypePropertyNameList
  2. propertyNameClassElementPropName
  3. 如果 propertyNameempty,则返回 list
  4. 如果 ClassElementIsStatictrue,则返回 list
  5. 返回 list 和 « propertyName » 的列表连接

15.7.7 Static Semantics: AllPrivateIdentifiersValid

The syntax-directed operation AllPrivateIdentifiersValid takes argument names (a List of Strings) and returns a Boolean.

本规范中未在下面列出的每个语法产生式替代项,都隐式具有以下 AllPrivateIdentifiersValid 的默认定义:

  1. 对此 Parse Node 的每个子节点 child,执行:
    1. 如果 child 是一个非终结符的实例,则
      1. 如果以 names 为实参执行 childAllPrivateIdentifiersValidfalse,则返回 false
  2. 返回 true
MemberExpression : MemberExpression . PrivateIdentifier
  1. 如果 names 包含 PrivateIdentifierStringValue,则
    1. 返回以 names 为实参执行 MemberExpressionAllPrivateIdentifiersValid
  2. 返回 false
CallExpression : CallExpression . PrivateIdentifier
  1. 如果 names 包含 PrivateIdentifierStringValue,则
    1. 返回以 names 为实参执行 CallExpressionAllPrivateIdentifiersValid
  2. 返回 false
OptionalChain : ?. PrivateIdentifier
  1. 如果 names 包含 PrivateIdentifierStringValue,则返回 true
  2. 返回 false
OptionalChain : OptionalChain . PrivateIdentifier
  1. 如果 names 包含 PrivateIdentifierStringValue,则
    1. 返回以 names 为实参执行 OptionalChainAllPrivateIdentifiersValid
  2. 返回 false
ClassBody : ClassElementList
  1. newNamesnamesClassBodyPrivateBoundIdentifiers列表连接
  2. 返回以 newNames 为实参执行 ClassElementListAllPrivateIdentifiersValid
RelationalExpression : PrivateIdentifier in ShiftExpression
  1. 如果 names 包含 PrivateIdentifierStringValue,则
    1. 返回以 names 为实参执行 ShiftExpressionAllPrivateIdentifiersValid
  2. 返回 false

15.7.8 Static Semantics: PrivateBoundIdentifiers

The syntax-directed operation PrivateBoundIdentifiers takes no arguments and returns a List of Strings. It is defined piecewise over the following productions:

FieldDefinition : ClassElementName Initializeropt
  1. 返回 ClassElementNamePrivateBoundIdentifiers
ClassElementName : PrivateIdentifier
  1. 返回一个 List,其唯一元素为 PrivateIdentifierStringValue
ClassElementName : PropertyName ClassElement : ClassStaticBlock ;
  1. 返回新的空 List
ClassElementList : ClassElementList ClassElement
  1. names1ClassElementListPrivateBoundIdentifiers
  2. names2ClassElementPrivateBoundIdentifiers
  3. 返回 names1names2列表连接
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. 返回 ClassElementNamePrivateBoundIdentifiers

15.7.9 Static Semantics: ContainsArguments

The syntax-directed operation ContainsArguments takes no arguments and returns a Boolean.

本规范中未在下面列出的每个语法产生式替代项,都隐式具有以下 ContainsArguments 的默认定义:

  1. 对此 Parse Node 的每个子节点 child,执行:
    1. 如果 child 是一个非终结符的实例,则
      1. 如果 childContainsArgumentstrue,则返回 true
  2. 返回 false
IdentifierReference : Identifier
  1. 如果 IdentifierStringValue"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. 返回 ClassElementNameContainsArguments

15.7.10 Runtime Semantics: ClassFieldDefinitionEvaluation

The syntax-directed operation ClassFieldDefinitionEvaluation takes argument homeObj (an Object) and returns either a normal completion containing a ClassFieldDefinition Record or an abrupt completion. It is defined piecewise over the following productions:

FieldDefinition : ClassElementName Initializeropt
  1. name 为 ? ClassElementNameEvaluation
  2. 如果存在 Initializer,则
    1. formalParamList 为产生式 FormalParameters : [empty] 的实例。
    2. envRecord 为运行中的执行上下文的 LexicalEnvironment。
    3. privateEnv 为运行中的执行上下文的 PrivateEnvironment。
    4. sourceText 为空的 Unicode 码点序列。
    5. initializerOrdinaryFunctionCreate(%Function.prototype%, sourceText, formalParamList, Initializer, non-lexical-this, envRecord, privateEnv)。
    6. 执行 MakeMethod(initializer, homeObj)。
    7. initializer.[[ClassFieldInitializerName]] 设置为 name
  3. 否则,
    1. initializerempty
  4. 返回 ClassFieldDefinition Record { [[Name]]: name, [[Initializer]]: initializer }。
Note
initializer 创建的函数永远不能被 ECMAScript 代码直接访问。

15.7.11 Runtime Semantics: ClassStaticBlockDefinitionEvaluation

The syntax-directed operation ClassStaticBlockDefinitionEvaluation takes argument homeObj (an Object) and returns a ClassStaticBlockDefinition Record. It is defined piecewise over the following productions:

ClassStaticBlock : static { ClassStaticBlockBody }
  1. lexicalEnv 为正在运行的执行上下文的 LexicalEnvironment。
  2. privateEnv 为正在运行的执行上下文的 PrivateEnvironment。
  3. sourceText 为空的 Unicode 码点序列。
  4. formalParams 为产生式 FormalParameters : [empty] 的一个实例。
  5. bodyFuncOrdinaryFunctionCreate(%Function.prototype%, sourceText, formalParams, ClassStaticBlockBody, non-lexical-this, lexicalEnv, privateEnv)。
  6. 执行 MakeMethod(bodyFunc, homeObj)。
  7. 返回 ClassStaticBlockDefinition Record { [[BodyFunction]]: bodyFunc }。
Note
函数 bodyFunc 永远不能被 ECMAScript 代码直接访问。

15.7.12 Runtime Semantics: EvaluateClassStaticBlockBody

The syntax-directed operation EvaluateClassStaticBlockBody takes argument funcObj (an ECMAScript function object) and returns a return completion or a throw completion. It is defined piecewise over the following productions:

ClassStaticBlockBody : ClassStaticBlockStatementList
  1. 断言:funcObj 是由 ClassStaticBlockDefinitionEvaluation 步骤 5 创建的合成函数。
  2. 执行 ! FunctionDeclarationInstantiation(funcObj, « »)。
  3. resultClassStaticBlockStatementList 的求值的 Completion
  4. envRecord 为运行中执行上下文的 LexicalEnvironment。
  5. 断言:envRecord 是声明式环境记录。
  6. 执行 ? DisposeResources(envRecord.[[DisposableResourceStack]], result)。
  7. 返回 ReturnCompletion(undefined)。

15.7.13 Runtime Semantics: ClassElementEvaluation

The syntax-directed operation ClassElementEvaluation takes argument obj (an Object) and returns either a normal completion containing either a ClassFieldDefinition Record, a ClassStaticBlockDefinition Record, a PrivateElement, or unused, or an abrupt completion. It is defined piecewise over the following productions:

ClassElement : FieldDefinition ; static FieldDefinition ;
  1. 返回 ? 以 obj 为实参执行 FieldDefinitionClassFieldDefinitionEvaluation
ClassElement : MethodDefinition static MethodDefinition
  1. 返回 ? 以 objfalse 为实参执行 MethodDefinitionMethodDefinitionEvaluation
ClassElement : ClassStaticBlock
  1. 返回以 obj 为实参执行 ClassStaticBlockClassStaticBlockDefinitionEvaluation
ClassElement : ;
  1. 返回 unused

15.7.14 Runtime Semantics: ClassDefinitionEvaluation

The syntax-directed operation ClassDefinitionEvaluation takes arguments classBinding (a String or undefined), className (a property key or a Private Name), and sourceText (ECMAScript source text) and returns either a normal completion containing a function object or an abrupt completion.

Note

为了便于规范表述,私有方法和访问器与私有字段一起包含在类实例的 [[PrivateElements]] 槽中。不过,任何给定对象要么拥有由给定类定义的所有私有方法和访问器,要么一个都没有。此特性的设计使实现可以选择使用一种不需要单独跟踪每个方法或访问器的策略来实现私有方法和访问器。

例如,实现可以将实例私有方法直接与其对应的 Private Name 关联,并对每个对象跟踪哪些类构造器曾以该对象作为其 this 值运行。然后,在对象上查找实例私有方法就包括检查定义该方法的类构造器是否已用于初始化该对象,然后返回与该 Private Name 关联的方法。

这不同于私有字段:由于字段初始化器可能在类实例化期间抛出异常,所以单个对象可能只具有给定类的私有字段的某个真子集,因此私有字段通常必须被单独跟踪。

It is defined piecewise over the following productions:

ClassTail : ClassHeritageopt { ClassBodyopt }
  1. envRecord 为正在运行的执行上下文的 LexicalEnvironment。
  2. classEnvNewDeclarativeEnvironment(envRecord)。
  3. 如果 classBinding 不是 undefined,则
    1. 执行 ! classEnv.CreateImmutableBinding(classBinding, true)。
  4. outerPrivateEnv 为正在运行的执行上下文的 PrivateEnvironment。
  5. classPrivateEnvNewPrivateEnvironment(outerPrivateEnv)。
  6. 如果 ClassBody 存在,则
    1. ClassBodyPrivateBoundIdentifiers 的每个 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. superclassRefClassHeritageCompletion(Evaluation)。
    4. 将正在运行的执行上下文的 LexicalEnvironment 设为 envRecord
    5. superclass 为 ? GetValue(? superclassRef)。
    6. 如果 superclassnull,则
      1. protoParentnull
      2. ctorParent%Function.prototype%
    7. 否则,如果 IsConstructor(superclass) 为 false,则
      1. 抛出一个 TypeError 异常。
    8. 否则,
      1. protoParent 为 ? Get(superclass, "prototype")。
      2. 如果 protoParent 不是 Object 且 protoParent 不是 null,则抛出一个 TypeError 异常。
      3. ctorParentsuperclass
  9. protoOrdinaryObjectCreate(protoParent)。
  10. 如果 ClassBody 不存在,则令 ctorempty
  11. 否则,令 ctorClassBodyConstructorMethod
  12. 将正在运行的执行上下文的 LexicalEnvironment 设为 classEnv
  13. 将正在运行的执行上下文的 PrivateEnvironment 设为 classPrivateEnv
  14. 如果 ctorempty,则
    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. ctorFuncCreateBuiltinFunction(defaultCtor, 0, className, « [[ConstructorKind]], [[SourceText]], [[PrivateMethods]], [[Fields]] », 当前 Realm Record, ctorParent)。
  15. 否则,
    1. ctorInfo 为以 protoctorParent 为参数对 ctor 执行 ! DefineMethod 的结果。
    2. ctorFuncctorInfo.[[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. 否则,令 classElementsClassBodyNonConstructorElements
  22. instancePrivateMethods 为一个新的空 List
  23. staticPrivateMethods 为一个新的空 List
  24. instanceFields 为一个新的空 List
  25. staticElements 为一个新的空 List
  26. classElements 的每个 ClassElement classElement,执行:
    1. 如果 classElementIsStaticfalse,则
      1. element 为以 proto 为参数对 classElement 执行 ClassElementEvaluationCompletion
    2. 否则,
      1. element 为以 ctorFunc 为参数对 classElement 执行 ClassElementEvaluationCompletion
    3. 如果 element 是一个突然完成,则
      1. 将正在运行的执行上下文的 LexicalEnvironment 设为 envRecord
      2. 将正在运行的执行上下文的 PrivateEnvironment 设为 outerPrivateEnv
      3. 返回 ? element
    4. element 设为 ! element
    5. 如果 elementPrivateElement,则
      1. 断言:element.[[Kind]]methodaccessor
      2. 如果 classElementIsStaticfalse,则令 containerinstancePrivateMethods
      3. 否则,令 containerstaticPrivateMethods
      4. 如果 container 包含一个 PrivateElement existingElement,使得 existingElement.[[Key]]element.[[Key]],则
        1. 断言:element.[[Kind]]existingElement.[[Kind]] 都为 accessor
        2. 如果 element.[[Get]]undefined,则
          1. combinedPrivateElement { [[Key]]: element.[[Key]], [[Kind]]: accessor, [[Get]]: existingElement.[[Get]], [[Set]]: element.[[Set]] }。
        3. 否则,
          1. combinedPrivateElement { [[Key]]: element.[[Key]], [[Kind]]: accessor, [[Get]]: element.[[Get]], [[Set]]: existingElement.[[Set]] }。
        4. combined 替换 container 中的 existingElement
      5. 否则,
        1. element 追加到 container
    6. 否则,如果 elementClassFieldDefinition Record,则
      1. 如果 classElementIsStaticfalse,则将 element 追加到 instanceFields
      2. 否则,将 element 追加到 staticElements
    7. 否则,如果 elementClassStaticBlockDefinition Record,则
      1. element 追加到 staticElements
  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. 如果 elementRecordClassFieldDefinition Record,则
      1. resultCompletion(DefineField(ctorFunc, elementRecord))。
    2. 否则,
      1. 断言:elementRecordClassStaticBlockDefinition Record
      2. resultCompletion(Call(elementRecord.[[BodyFunction]], ctorFunc))。
    3. 如果 result 是一个突然完成,则
      1. 将正在运行的执行上下文的 PrivateEnvironment 设为 outerPrivateEnv
      2. 返回 ? result
  33. 将正在运行的执行上下文的 PrivateEnvironment 设为 outerPrivateEnv
  34. 返回 ctorFunc

15.7.15 Runtime Semantics: BindingClassDeclarationEvaluation

The syntax-directed operation BindingClassDeclarationEvaluation takes no arguments and returns either a normal completion containing a function object or an abrupt completion. It is defined piecewise over the following productions:

ClassDeclaration : class BindingIdentifier ClassTail
  1. classNameBindingIdentifierStringValue
  2. sourceText 为由 ClassDeclaration 匹配的源文本
  3. value 为 ? 以 classNameclassNamesourceText 为实参执行 ClassTailClassDefinitionEvaluation
  4. envRecord 为运行中的执行上下文的 LexicalEnvironment。
  5. 执行 ? InitializeBoundName(className, value, envRecord)。
  6. 返回 value
ClassDeclaration : class ClassTail
  1. sourceText 为由 ClassDeclaration 匹配的源文本
  2. 返回 ? 以 undefined"default"sourceText 为实参执行 ClassTailClassDefinitionEvaluation
Note

ClassDeclaration : class ClassTail 只作为 ExportDeclaration 的一部分出现,并且建立其绑定作为该产生式求值动作的一部分处理。见 16.2.3.7

15.7.16 Runtime Semantics: Evaluation

ClassDeclaration : class BindingIdentifier ClassTail
  1. 执行 ? 此 ClassDeclarationBindingClassDeclarationEvaluation
  2. 返回 empty
Note

ClassDeclaration : class ClassTail 只作为 ExportDeclaration 的一部分出现,并且永远不会被直接求值。

ClassExpression : class ClassTail
  1. sourceText 为由 ClassExpression 匹配的源文本
  2. 返回 ? 以 undefined、空 String 和 sourceText 为实参执行 ClassTailClassDefinitionEvaluation
ClassExpression : class BindingIdentifier ClassTail
  1. classNameBindingIdentifierStringValue
  2. sourceText 为由 ClassExpression 匹配的源文本
  3. 返回 ? 以 classNameclassNamesourceText 为实参执行 ClassTailClassDefinitionEvaluation
ClassElementName : PrivateIdentifier
  1. privateIdentifierPrivateIdentifierStringValue
  2. privateEnvRecord 为运行中的执行上下文的 PrivateEnvironment。
  3. namesprivateEnvRecord.[[Names]]
  4. 断言:names 中恰有一个元素是其 [[Description]]privateIdentifierPrivate Name
  5. privateNamenames 中其 [[Description]]privateIdentifierPrivate 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] Note 1

[Await] 参数存在时,await 会被解析为 AwaitExpression关键字[Await] 参数存在于以下上下文的顶层,尽管取决于非终结符(例如 FunctionBody),该参数在某些上下文中可能不存在:

Script 是句法目标符号时,如果 [Await] 参数不存在,await 可以被解析为标识符。这包括以下上下文:

Note 2

不同于 YieldExpression,省略 AwaitExpression 的操作数是语法错误。你必须 await 某些东西。

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

The syntax-directed operation InstantiateAsyncFunctionObject takes arguments envRecord (an Environment Record) and privateEnv (a PrivateEnvironment Record or null) and returns an ECMAScript function object. It is defined piecewise over the following productions:

AsyncFunctionDeclaration : async function BindingIdentifier ( FormalParameters ) { AsyncFunctionBody }
  1. nameBindingIdentifierStringValue
  2. sourceText 为由 AsyncFunctionDeclaration 匹配的源文本
  3. closureOrdinaryFunctionCreate(%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. closureOrdinaryFunctionCreate(%AsyncFunction.prototype%, sourceText, FormalParameters, AsyncFunctionBody, non-lexical-this, envRecord, privateEnv)。
  3. 执行 SetFunctionName(closure, "default")。
  4. 返回 closure

15.8.3 Runtime Semantics: InstantiateAsyncFunctionExpression

The syntax-directed operation InstantiateAsyncFunctionExpression takes optional argument name (a property key or a Private Name) and returns an ECMAScript function object. It is defined piecewise over the following productions:

AsyncFunctionExpression : async function ( FormalParameters ) { AsyncFunctionBody }
  1. 如果 name 不存在,则将 name 设置为空 String。
  2. envRecord 为运行中的执行上下文的 LexicalEnvironment。
  3. privateEnv 为运行中的执行上下文的 PrivateEnvironment。
  4. sourceText 为由 AsyncFunctionExpression 匹配的源文本
  5. closureOrdinaryFunctionCreate(%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 设置为 BindingIdentifierStringValue
  3. outerEnv 为运行中的执行上下文的 LexicalEnvironment。
  4. funcEnvNewDeclarativeEnvironment(outerEnv)。
  5. 执行 ! funcEnv.CreateImmutableBinding(name, false)。
  6. privateEnv 为运行中的执行上下文的 PrivateEnvironment。
  7. sourceText 为由 AsyncFunctionExpression 匹配的源文本
  8. closureOrdinaryFunctionCreate(%AsyncFunction.prototype%, sourceText, FormalParameters, AsyncFunctionBody, non-lexical-this, funcEnv, privateEnv)。
  9. 执行 SetFunctionName(closure, name)。
  10. 执行 ! funcEnv.InitializeBinding(name, closure)。
  11. 返回 closure
Note

AsyncFunctionExpression 中的 BindingIdentifier 可以从该 AsyncFunctionExpressionAsyncFunctionBody 内部引用,以允许函数递归调用自身。不过,不同于 FunctionDeclarationAsyncFunctionExpression 中的 BindingIdentifier 不能从包围该 AsyncFunctionExpression 的作用域中引用,也不会影响该作用域。

15.8.4 Runtime Semantics: EvaluateAsyncFunctionBody

The syntax-directed operation EvaluateAsyncFunctionBody takes arguments funcObj (an ECMAScript function object) and argList (a List of ECMAScript language values) and returns a return completion. It is defined piecewise over the following productions:

AsyncFunctionBody : FunctionBody
  1. promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  2. completionCompletion(FunctionDeclarationInstantiation(funcObj, argList))。
  3. 如果 completion 是 abrupt 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. 返回 AsyncFunctionExpressionInstantiateAsyncFunctionExpression
UnaryExpression : CoverAwaitExpressionAndAwaitUsingDeclarationHead
  1. exprCoverAwaitExpressionAndAwaitUsingDeclarationHead覆盖的 AwaitExpression
  2. 返回 expr 的 ? Evaluation
AwaitExpression : await UnaryExpression
  1. exprRef 为 ? UnaryExpressionEvaluation
  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

The syntax-directed operation AsyncConciseBodyContainsUseStrict takes no arguments and returns a Boolean. It is defined piecewise over the following productions:

AsyncConciseBody : ExpressionBody
  1. 返回 false
AsyncConciseBody : { AsyncFunctionBody }
  1. 返回 AsyncFunctionBodyFunctionBodyContainsUseStrict

15.9.3 Runtime Semantics: EvaluateAsyncConciseBody

The syntax-directed operation EvaluateAsyncConciseBody takes arguments funcObj (an ECMAScript function object) and argList (a List of ECMAScript language values) and returns a return completion. It is defined piecewise over the following productions:

AsyncConciseBody : ExpressionBody
  1. promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  2. completionCompletion(FunctionDeclarationInstantiation(funcObj, argList))。
  3. 如果 completion 是 abrupt completion,则
    1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « completion.[[Value]] »)。
  4. 否则,
    1. 执行 AsyncFunctionStart(promiseCapability, ExpressionBody)。
  5. 返回 ReturnCompletion(promiseCapability.[[Promise]])。

15.9.4 Runtime Semantics: InstantiateAsyncArrowFunctionExpression

The syntax-directed operation InstantiateAsyncArrowFunctionExpression takes optional argument name (a property key or a Private Name) and returns an ECMAScript function object. It is defined piecewise over the following productions:

AsyncArrowFunction : async AsyncArrowBindingIdentifier => AsyncConciseBody
  1. 如果 name 不存在,则将 name 设置为空 String。
  2. envRecord 为运行中的执行上下文的 LexicalEnvironment。
  3. privateEnv 为运行中的执行上下文的 PrivateEnvironment。
  4. sourceText 为由 AsyncArrowFunction 匹配的源文本
  5. paramsAsyncArrowBindingIdentifier
  6. closureOrdinaryFunctionCreate(%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. paramsheadArrowFormalParameters
  7. closureOrdinaryFunctionCreate(%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. 返回 AsyncArrowFunctionInstantiateAsyncArrowFunctionExpression

15.10 尾位置调用

15.10.1 Static Semantics: IsInTailPosition ( call )

The abstract operation IsInTailPosition takes argument call (a CallExpression Parse Node, a MemberExpression Parse Node, or an OptionalChain Parse Node) and returns a Boolean. It performs the following steps when called:

  1. 如果 IsStrict(call) 是 false,则返回 false
  2. 如果 call包含FunctionBodyConciseBodyAsyncConciseBody 中,则返回 false
  3. body 为最紧密包含 callFunctionBodyConciseBodyAsyncConciseBody
  4. 如果 bodyGeneratorBodyFunctionBody,则返回 false
  5. 如果 bodyAsyncFunctionBodyFunctionBody,则返回 false
  6. 如果 bodyAsyncGeneratorBodyFunctionBody,则返回 false
  7. 如果 bodyAsyncConciseBody,则返回 false
  8. 返回以 call 为实参执行 bodyHasCallInTailPosition 的结果。
Note

尾位置调用只在严格模式代码中定义,这是因为一种常见的非标准语言扩展(见 10.2.4)允许观察调用者上下文链。

15.10.2 Static Semantics: HasCallInTailPosition

The syntax-directed operation HasCallInTailPosition takes argument call (a CallExpression Parse Node, a MemberExpression Parse Node, or an OptionalChain Parse Node) and returns a Boolean.

Note 1

call 是一个解析节点,表示源文本的一个特定范围。当以下算法将 call 与另一个解析节点进行比较时,这是在测试它们是否表示同一段源文本。

Note 2

紧跟着返回调用结果的 GetValue 的潜在尾位置调用,也是一个可能的尾位置调用。函数调用不能返回 Reference Record,因此这样的 GetValue 操作总是会返回与实际函数调用结果相同的值。

Note 3

在同一个 BlockForStatementForInOfStatementFunctionBodyGeneratorBodyAsyncGeneratorBodyAsyncFunctionBodyClassStaticBlockBody 中,位于某个调用之前的 using 声明或 await using 声明会阻止该调用成为可能的尾位置调用。

It is defined piecewise over the following productions:

StatementList : StatementList StatementListItem
  1. has 为以 call 为参数的派生 StatementListHasCallInTailPosition
  2. 如果 hastrue,则返回 true
  3. 如果派生 StatementListContainsUsingtrue,则返回 false
  4. 返回以 call 为参数的 StatementListItemHasCallInTailPosition
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 为实参执行第一个 StatementHasCallInTailPosition
  2. 如果 hastrue,则返回 true
  3. 返回以 call 为实参执行第二个 StatementHasCallInTailPosition
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 为实参执行 StatementHasCallInTailPosition
LabelledStatement : LabelIdentifier : LabelledItem
  1. 返回以 call 为实参执行 LabelledItemHasCallInTailPosition
ReturnStatement : return Expression ;
  1. 返回以 call 为实参执行 ExpressionHasCallInTailPosition
SwitchStatement : switch ( Expression ) CaseBlock
  1. 返回以 call 为实参执行 CaseBlockHasCallInTailPosition
CaseBlock : { CaseClausesopt DefaultClause CaseClausesopt }
  1. hasfalse
  2. 如果存在第一个 CaseClauses,则将 has 设置为以 call 为实参执行第一个 CaseClausesHasCallInTailPosition
  3. 如果 hastrue,则返回 true
  4. has 设置为以 call 为实参执行 DefaultClauseHasCallInTailPosition
  5. 如果 hastrue,则返回 true
  6. 如果存在第二个 CaseClauses,则将 has 设置为以 call 为实参执行第二个 CaseClausesHasCallInTailPosition
  7. 返回 has
CaseClauses : CaseClauses CaseClause
  1. has 为以 call 为实参执行 CaseClausesHasCallInTailPosition
  2. 如果 hastrue,则返回 true
  3. 返回以 call 为实参执行 CaseClauseHasCallInTailPosition
CaseClause : case Expression : StatementListopt DefaultClause : default : StatementListopt
  1. 如果存在 StatementList,则返回以 call 为实参执行 StatementListHasCallInTailPosition
  2. 返回 false
TryStatement : try Block Catch
  1. 返回以 call 为实参执行 CatchHasCallInTailPosition
TryStatement : try Block Finally try Block Catch Finally
  1. 返回以 call 为实参执行 FinallyHasCallInTailPosition
Catch : catch ( CatchParameter ) Block
  1. 返回以 call 为实参执行 BlockHasCallInTailPosition
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 为实参执行 AssignmentExpressionHasCallInTailPosition
ConditionalExpression : ShortCircuitExpression ? AssignmentExpression : AssignmentExpression
  1. has 为以 call 为实参执行第一个 AssignmentExpressionHasCallInTailPosition
  2. 如果 hastrue,则返回 true
  3. 返回以 call 为实参执行第二个 AssignmentExpressionHasCallInTailPosition
LogicalANDExpression : LogicalANDExpression && BitwiseORExpression
  1. 返回以 call 为实参执行 BitwiseORExpressionHasCallInTailPosition
LogicalORExpression : LogicalORExpression || LogicalANDExpression
  1. 返回以 call 为实参执行 LogicalANDExpressionHasCallInTailPosition
CoalesceExpression : CoalesceExpressionHead ?? BitwiseORExpression
  1. 返回以 call 为实参执行 BitwiseORExpressionHasCallInTailPosition
CallExpression : CoverCallExpressionAndAsyncArrowHead CallExpression Arguments CallExpression TemplateLiteral
  1. 如果此 CallExpressioncall,则返回 true
  2. 返回 false
OptionalExpression : MemberExpression OptionalChain CallExpression OptionalChain OptionalExpression OptionalChain
  1. 返回以 call 为实参执行 OptionalChainHasCallInTailPosition
OptionalChain : ?. [ Expression ] ?. IdentifierName ?. PrivateIdentifier OptionalChain [ Expression ] OptionalChain . IdentifierName OptionalChain . PrivateIdentifier
  1. 返回 false
OptionalChain : ?. Arguments OptionalChain Arguments
  1. 如果此 OptionalChaincall,则返回 true
  2. 返回 false
MemberExpression : MemberExpression TemplateLiteral
  1. 如果此 MemberExpressioncall,则返回 true
  2. 返回 false
PrimaryExpression : CoverParenthesizedExpressionAndArrowParameterList
  1. expr 为由 CoverParenthesizedExpressionAndArrowParameterList 覆盖的 ParenthesizedExpression
  2. 返回以 call 为实参执行 exprHasCallInTailPosition
ParenthesizedExpression : ( Expression )
  1. 返回以 call 为实参执行 ExpressionHasCallInTailPosition

15.10.3 PrepareForTailCall ( )

The abstract operation PrepareForTailCall takes no arguments and returns unused. It performs the following steps when called:

  1. 断言:当前执行上下文随后不会再用于求值任何 ECMAScript 代码或内置函数。在调用此抽象操作之后对 Call 的调用,会在执行任何此类求值之前创建并压入一个新的执行上下文。
  2. 丢弃与当前执行上下文关联的所有资源。
  3. 返回 unused

尾位置调用必须在调用目标函数之前释放与当前正在执行的函数执行上下文关联的任何临时内部资源,或者重用这些资源以支持目标函数。

Note

例如,尾位置调用使实现的激活记录栈增长的量,应仅为目标函数激活记录大小超出调用函数激活记录大小的部分。如果目标函数的激活记录更小,则栈的总大小应减少。

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

The syntax-directed operation ScriptIsStrict takes no arguments and returns a Boolean. It is defined piecewise over the following productions:

Script : ScriptBodyopt
  1. 如果存在 ScriptBodyScriptBodyDirective Prologue 包含 Use Strict Directive,则返回 true
  2. 返回 false

16.1.3 Runtime Semantics: Evaluation

Script : [empty]
  1. 返回 undefined

16.1.4 Script Record

Script Record 封装关于正在求值的脚本的信息。每个 script record 都包含 Table 35 中列出的字段。

Table 35: Script Record 字段
字段名 值类型 含义
[[Realm]] a Realm Record 创建此脚本所在的 realm
[[ECMAScriptCode]] a Script Parse Node 解析此脚本源文本的结果。
[[LoadedModules]] a List of LoadedModuleRequest Records 从此脚本导入的说明符字符串到已解析 Module Record 的映射。该列表不包含两个不同的 Record r1r2,使得 ModuleRequestsEqual(r1, r2) 是 true
[[HostDefined]] anything(默认值为 empty 为需要把附加信息与脚本关联起来的宿主环境保留的字段。

16.1.5 ParseScript ( sourceText, realm, hostDefined )

The abstract operation ParseScript takes arguments sourceText (a String or a sequence of Unicode code points), realm (a Realm Record), and hostDefined (anything) and returns a Script Record or a non-empty List of SyntaxError objects. 它基于把 sourceText 解析为 Script 的结果创建一个 Script Record。 It performs the following steps when called:

  1. scriptParseText(sourceText, Script)。
  2. 如果 script 是错误列表,则返回 script
  3. 返回 Script Record { [[Realm]]: realm, [[ECMAScriptCode]]: script, [[LoadedModules]]: « », [[HostDefined]]: hostDefined }。
Note

实现可以在对脚本源文本求值 ParseScript 之前解析脚本源文本并分析其早期错误条件。不过,任何错误的报告都必须推迟到本规范实际对该源文本执行 ParseScript 的时刻。

16.1.6 ScriptEvaluation ( scriptRecord )

The abstract operation ScriptEvaluation takes argument scriptRecord (a Script Record) and returns either a normal completion containing an ECMAScript language value or an abrupt completion. It performs the following steps when called:

  1. globalEnvscriptRecord.[[Realm]].[[GlobalEnv]]
  2. scriptContext 为一个新的 ECMAScript 代码执行上下文
  3. scriptContext 的 Function 设置为 null
  4. scriptContextRealm 设置为 scriptRecord.[[Realm]]
  5. scriptContext 的 ScriptOrModule 设置为 scriptRecord
  6. scriptContext 的 VariableEnvironment 设置为 globalEnv
  7. scriptContext 的 LexicalEnvironment 设置为 globalEnv
  8. scriptContext 的 PrivateEnvironment 设置为 null
  9. 挂起运行中的执行上下文。
  10. scriptContext 压入执行上下文栈;scriptContext 现在是运行中的执行上下文。
  11. scriptNodescriptRecord.[[ECMAScriptCode]]
  12. resultCompletion(GlobalDeclarationInstantiation(scriptNode, globalEnv))。
  13. 如果 result 是 normal completion,则
    1. result 设置为 Completion(scriptNodeEvaluation)。
    2. 如果 result 是 normal completion 且 result.[[Value]]empty,则
      1. result 设置为 NormalCompletion(undefined)。
  14. 挂起 scriptContext 并将其从执行上下文栈中移除。
  15. 断言:执行上下文栈不是空的。
  16. 恢复当前位于执行上下文栈顶部的上下文作为运行中的执行上下文。
  17. 返回 ? result

16.1.7 GlobalDeclarationInstantiation ( script, envRecord )

The abstract operation GlobalDeclarationInstantiation takes arguments script (a Script Parse Node) and envRecord (a Global Environment Record) and returns either a normal completion containing unused or a throw completion. script 是正在为其建立执行上下文的 ScriptenvRecord 是要在其中创建绑定的全局环境。

Note 1

当为求值脚本而建立执行上下文时,声明会在当前全局环境中实例化。代码中声明的每个全局绑定都会被实例化。

它在被调用时执行以下步骤:

  1. lexicalNamesscriptLexicallyDeclaredNames
  2. variableNamesscriptVarDeclaredNames
  3. lexicalNames 的每个元素 name,执行:
    1. 如果 HasLexicalDeclaration(envRecord, name) 为 true,则抛出一个 SyntaxError 异常。
    2. hasRestrictedGlobal 为 ? HasRestrictedGlobalProperty(envRecord, name)。
    3. 注:全局 varfunction 绑定(由非严格直接 eval 引入的那些绑定除外)是不可配置的,因此是受限制的全局属性。
    4. 如果 hasRestrictedGlobaltrue,则抛出一个 SyntaxError 异常。
  4. variableNames 的每个元素 name,执行:
    1. 如果 HasLexicalDeclaration(envRecord, name) 为 true,则抛出一个 SyntaxError 异常。
  5. variableDeclsscriptVarScopedDeclarations
  6. funcsToInitialize 为一个新的空 List
  7. declaredFuncNames 为一个新的空 List
  8. variableDecls 的每个元素 variableDecl,按 List 的逆序执行:
    1. 如果 variableDecl 不是 VariableDeclarationForBindingBindingIdentifier 中的任一者,则
      1. 断言:variableDeclFunctionDeclarationGeneratorDeclarationAsyncFunctionDeclarationAsyncGeneratorDeclaration
      2. 注:如果同一名称有多个函数声明,则使用最后一个声明。
      3. funcNamevariableDeclBoundNames 的唯一元素。
      4. 如果 declaredFuncNames包含 funcName,则
        1. funcDefinable 为 ? CanDeclareGlobalFunction(envRecord, funcName)。
        2. 如果 funcDefinablefalse,则抛出一个 TypeError 异常。
        3. funcName 追加到 declaredFuncNames
        4. variableDecl 作为 funcsToInitialize 的第一个元素插入。
  9. declaredVariableNames 为一个新的空 List
  10. variableDecls 的每个元素 variableDecl,执行:
    1. 如果 variableDeclVariableDeclarationForBindingBindingIdentifier 中的任一者,则
      1. variableDeclBoundNames 的每个 String name,执行:
        1. 如果 declaredFuncNames包含 name,则
          1. variableDefinable 为 ? CanDeclareGlobalVar(envRecord, name)。
          2. 如果 variableDefinablefalse,则抛出一个 TypeError 异常。
          3. 如果 declaredVariableNames包含 name,则
            1. name 追加到 declaredVariableNames
  11. 注:如果全局对象普通对象,则在此算法步骤之后不会发生异常终止。但是,如果全局对象Proxy 异质对象,它可能表现出会导致以下某些步骤中发生异常终止的行为。
  12. 如果宿主是 Web 浏览器,或以其他方式支持 块级函数声明的 Web 遗留兼容性语义,则
    1. strictscriptScriptIsStrict
    2. 如果 strictfalse,则
      1. declaredFuncOrVariableNamesdeclaredFuncNamesdeclaredVariableNames列表连接
      2. 对每个 FunctionDeclaration funcDecl,其直接包含在任何 BlockCaseClauseDefaultClause xStatementList 中,且 script Contains xtrue,执行:
        1. funcNamefuncDeclBindingIdentifierStringValue
        2. 如果将 FunctionDeclaration funcDecl 替换为以 funcName 作为 BindingIdentifierVariableStatement 不会为 script 产生任何早期错误,则
          1. 如果 HasLexicalDeclaration(envRecord, funcName) 为 false,则
            1. funcDefinable 为 ? CanDeclareGlobalVar(envRecord, funcName)。
            2. 如果 funcDefinabletrue,则
              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. lexicalDeclsscriptLexicallyScopedDeclarations
  14. privateEnvnull
  15. lexicalDecls 的每个元素 lexicalDecl,执行:
    1. 注:词法声明的名称仅在此处实例化,但不初始化。
    2. lexicalDeclBoundNames 的每个元素 name,执行:
      1. 如果 lexicalDeclIsConstantDeclarationtrue,则
        1. 执行 ? envRecord.CreateImmutableBinding(name, true)
      2. 否则,
        1. 执行 ? envRecord.CreateMutableBinding(name, false)
  16. funcsToInitialize 的每个 Parse Node funcDecl,执行:
    1. funcNamefuncDeclBoundNames 的唯一元素。
    2. funcObj 为使用参数 envRecordprivateEnvfuncDecl 执行 InstantiateFunctionObject 的结果。
    3. 执行 ? CreateGlobalFunctionBinding(envRecord, funcName, funcObj, false)。
  17. declaredVariableNames 的每个 String variableName,执行:
    1. 执行 ? CreateGlobalVarBinding(envRecord, variableName, false)。
  18. 返回 unused
Note 2

16.1.1 中指定的早期错误会防止单个 Script包含的声明在 function/var 声明与 let/const/class 声明之间发生名称冲突,以及防止重新声明 let/const/class 绑定。不过,跨越多个 Script 的此类冲突和重新声明会在 GlobalDeclarationInstantiation 期间作为运行时错误被检测到。如果检测到任何此类错误,则不会为该脚本实例化任何绑定。不过,如果全局对象是使用 Proxy 异质对象定义的,则用于检测冲突声明的运行时测试可能不可靠,从而导致 abrupt completion,并且某些全局声明未被实例化。如果发生这种情况,则不会求值该 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 Note

重复 ExportedNames 规则意味着,在一个 ModuleBody包含多个 export default ExportDeclaration 项是语法错误。与冲突或重复声明相关的其他错误条件,会在求值 Module 之前的模块链接期间检查。如果检测到任何此类错误,则不会求值该 Module

ModuleExportName : StringLiteral

16.2.1.2 Static Semantics: ImportedLocalNames ( importEntries )

The abstract operation ImportedLocalNames takes argument importEntries (a List of ImportEntry Records) and returns a List of Strings. 它创建由 importEntries 定义的所有本地名称绑定的 List。 It performs the following steps when called:

  1. localNames 为一个新的空 List
  2. importEntries 的每个 ImportEntry Record importEntry,执行:
    1. importEntry.[[LocalName]] 追加到 localNames
  3. 返回 localNames

16.2.1.3 ModuleRequest Record

ModuleRequest Record 表示带有给定导入属性的导入模块请求。它由以下字段组成:

Table 36: ModuleRequest Record 字段
字段名 值类型 含义
[[Specifier]] a String 模块说明符
[[Attributes]] a List of ImportAttribute Records 导入属性

LoadedModuleRequest Record 表示导入模块的请求以及所得的 Module Record。它由表 Table 36 中定义的相同字段组成,并额外带有 [[Module]]

Table 37: LoadedModuleRequest Record 字段
字段名 值类型 含义
[[Specifier]] a String 模块说明符
[[Attributes]] a List of ImportAttribute Records 导入属性
[[Module]] a Module Record 与此模块请求对应的已加载模块

ImportAttribute Record 由以下字段组成:

Table 38: ImportAttribute Record 字段
字段名 值类型 含义
[[Key]] a String 属性键
[[Value]] a String 属性值

16.2.1.3.1 ModuleRequestsEqual ( x, y )

The abstract operation ModuleRequestsEqual takes arguments x (a ModuleRequest Record or a LoadedModuleRequest Record) and y (a ModuleRequest Record or a LoadedModuleRequest Record) and returns a Boolean. It performs the following steps when called:

  1. 如果 x.[[Specifier]] 不是 y.[[Specifier]],则返回 false
  2. xAttrsx.[[Attributes]]
  3. yAttrsy.[[Attributes]]
  4. xAttrsCountxAttrs 中元素的数量。
  5. yAttrsCountyAttrs 中元素的数量。
  6. 如果 xAttrsCountyAttrsCount,则返回 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

The syntax-directed operation ModuleRequests takes no arguments and returns a List of ModuleRequest Records. It is defined piecewise over the following productions:

Module : [empty]
  1. 返回新的空 List
ModuleItemList : ModuleItem
  1. 返回 ModuleItemModuleRequests
ModuleItemList : ModuleItemList ModuleItem
  1. requestsModuleItemListModuleRequests
  2. additionalRequestsModuleItemModuleRequests
  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. specifierFromClauseSV
  2. 返回一个 List,其唯一元素为 ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: « » }。
ImportDeclaration : import ImportClause FromClause WithClause ;
  1. specifierFromClauseSV
  2. attrsWithClauseWithClauseToAttributes
  3. 返回一个 List,其唯一元素为 ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: attrs }。
ImportDeclaration : import ModuleSpecifier ;
  1. specifierModuleSpecifierSV
  2. 返回一个 List,其唯一元素为 ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: « » }。
ImportDeclaration : import ModuleSpecifier WithClause ;
  1. specifierModuleSpecifierSV
  2. attrsWithClauseWithClauseToAttributes
  3. 返回一个 List,其唯一元素为 ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: attrs }。
ExportDeclaration : export ExportFromClause FromClause ;
  1. specifierFromClauseSV
  2. 返回一个 List,其唯一元素为 ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: « » }。
ExportDeclaration : export ExportFromClause FromClause WithClause ;
  1. specifierFromClauseSV
  2. attrsWithClauseWithClauseToAttributes
  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 Record

Module Record 封装关于单个模块的导入和导出的结构信息。此信息用于链接一组相互连接模块的导入和导出。Module Record 包含四个只在求值模块时使用的字段。

出于规范目的,Module Record 值是 Record 规范类型的值,可以被认为存在于一个简单的面向对象层级中,其中 Module Record 是一个抽象类,具有抽象子类和具体子类。本规范定义名为 Cyclic Module Record 的抽象子类,以及名为 Source Text Module Record 的具体子类。其他规范和实现可以定义附加的 Module Record 子类,对应于它们所定义的替代模块定义设施。

Module Record 定义 Table 39 中列出的字段。所有 Module Definition 子类至少都包含这些字段。Module Record 还定义 Table 40 中的抽象方法列表。所有 Module definition 子类都必须提供这些抽象方法的具体实现。

Table 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(默认值为 undefined 为需要把附加信息与模块关联起来的宿主环境保留的字段。
Table 40: Abstract Methods of Module Records
方法 目的 定义
LoadRequestedModules ( [ hostDefined ] )

The abstract method LoadRequestedModules takes optional argument hostDefined (anything) and returns a Promise.

它通过递归加载所有依赖项,为模块链接做准备。

在本规范内,它在以下类型中有定义;宿主可以提供带有自身定义的附加类型:
GetExportedNames ( [ exportStarSet ] )

The abstract method GetExportedNames takes optional argument exportStarSet (a List of Source Text Module Records) and returns a List of Strings.

它返回从此模块直接或间接导出的所有名称的列表。

在调用此方法之前,LoadRequestedModules 必须已经成功完成。

在本规范内,它在以下类型中有定义;宿主可以提供带有自身定义的附加类型:
ResolveExport ( exportName [ , resolveSet ] )

The abstract method ResolveExport takes argument exportName (a String) and optional argument resolveSet (a List of Records with fields [[Module]] (a Module Record) and [[ExportName]] (a String)) and returns a ResolvedBinding Record, null, or ambiguous.

它返回此模块导出名称的绑定。绑定由 ResolvedBinding Record 表示,其形式为 { [[Module]]: Module Record, [[BindingName]]: String | namespace }。如果导出是不带任何模块中直接绑定的 Module Namespace Object,则 [[BindingName]] 会被设置为 namespace。如果无法解析名称,则返回 null;如果找到多个绑定,则返回 ambiguous

每次以特定的 exportNameresolveSet 参数对调用此操作时,都必须返回相同的结果。

在调用此方法之前,LoadRequestedModules 必须已经成功完成。

在本规范内,它在以下类型中有定义;宿主可以提供带有自身定义的附加类型:
Evaluate ( )

The abstract method Evaluate takes no arguments and returns a Promise.

它返回一个用于此模块及其依赖项求值的 promise,该 promise 会在成功求值时或已经成功求值过时兑现,并在求值错误或已经求值失败过时拒绝。如果 promise 被拒绝,期望宿主处理该 promise 拒绝并重新抛出求值错误。除非此模块是 Cyclic Module Record,否则返回的 promise 必须已经 settled。

在调用此方法之前,Link 必须已经成功完成。

在本规范内,它在以下类型中有定义;宿主可以提供带有自身定义的附加类型:

16.2.1.5.1 EvaluateModuleSync ( module )

The abstract operation EvaluateModuleSync takes argument module (a Module Record) and returns either a normal completion containing unused or a throw completion. 它同步求值 module,前提是调用者保证 module 的求值会返回一个已经 settled 的 promise。 It performs the following steps when called:

  1. 断言:module 不是 Cyclic Module Record
  2. promisemodule.Evaluate()。
  3. 断言:promise.[[PromiseState]]fulfilledrejected
  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 Record

Cyclic Module Record 用于表示关于某个模块的信息,该模块可以与作为 Cyclic Module Record 类型子类的其他模块一起参与依赖循环。不是 Cyclic Module Record 类型子类的 Module Record 不得与 Source Text Module Record 一起参与依赖循环。

除了 Table 39 中定义的字段之外,Cyclic Module Record 还具有 Table 41 中列出的附加字段

Table 41: Cyclic Module Record 的附加字段
字段名 值类型 含义
[[Status]] new, unlinked, linking, linked, evaluating, evaluating-async, or evaluated 初始为 new。随着模块在其生命周期中前进,依次转换为 unlinkedlinkinglinkedevaluating、可能为 evaluating-asyncevaluatedevaluating-async 表示此模块已排队等待其异步依赖项完成后执行,或者它是一个 [[HasTLA]] 字段为 true、已被执行且正在等待顶层完成的模块。
[[EvaluationError]] a throw completion or empty 表示求值期间发生的异常的 throw completion。如果没有发生异常,或 [[Status]] 不是 evaluated,则为 empty
[[DFSAncestorIndex]] an integer or empty 仅在 LinkEvaluate 期间使用的辅助字段。如果 [[Status]]linkingevaluating,则它要么是模块的深度优先遍历索引,要么是同一强连通分量中“更早”模块的深度优先遍历索引。
[[RequestedModules]] a List of ModuleRequest Records 与此模块中导入关联的 ModuleRequest RecordList。该 List 按导入在源文本中的出现顺序排列。
[[LoadedModules]] a List of LoadedModuleRequest Records 从由此 Record 表示的模块用于请求导入具有相对导入属性的模块的说明符字符串,到已解析 Module Record 的映射。该列表不包含两个不同的 Record r1r2,使得 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。它用于使从 Evaluate() 抽象方法返回的 Promise 对象 settled。对于该模块的任何依赖项,此字段将为 empty,除非已经为这些依赖项中的某些依赖项启动了顶层 Evaluate()。
[[AsyncParentModules]] a List of Cyclic Module Records 如果此模块或某个依赖项具有 [[HasTLA]] true,且执行正在进行中,则此字段为顶层执行作业跟踪此模块的父级导入者。这些父级模块不会在此模块成功完成执行之前开始执行。
[[PendingAsyncDependencies]] an integer or empty 如果此模块有任何异步依赖项,则此字段跟踪此模块剩余要执行的异步依赖模块数量。具有异步依赖项的模块会在此字段达到 0 且没有执行错误时执行。

除了 Table 40 中定义的方法之外,Cyclic Module Record 还具有 Table 42 中列出的附加方法:

Table 42: Cyclic Module Record 的附加抽象方法
方法 目的 定义
InitializeEnvironment ( )

The abstract method InitializeEnvironment takes no arguments and returns either a normal completion containing unused or a throw completion.

它初始化模块的 Environment Record,包括解析所有导入绑定,并创建模块的执行上下文。
在本规范内,它在以下类型中有定义;宿主可以提供带有自身定义的附加类型:
ExecuteModule ( [ capability ] )

The abstract method ExecuteModule takes optional argument capability (a PromiseCapability Record) and returns either a normal completion containing unused or a throw completion.

它在模块的执行上下文内求值该模块的代码。如果此模块在 [[HasTLA]] 中具有 true,则 PromiseCapability Record 会作为实参传入,并且期望该方法 resolve 或 reject 给定 capability。在这种情况下,该方法不得抛出异常,而应在必要时 reject 该 PromiseCapability Record
在本规范内,它在以下类型中有定义;宿主可以提供带有自身定义的附加类型:

GraphLoadingState Record 是一个包含模块图加载过程相关信息的 Record。它用于在调用 HostLoadImportedModule 后继续加载。每个 GraphLoadingState Record 都具有 Table 43 中定义的字段:

Table 43: GraphLoadingState Record 字段
字段名 值类型 含义
[[PromiseCapability]] a PromiseCapability Record 加载过程结束时要 resolve 的 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 的具体方法,它们实现 Table 40 中定义的相应 Module Record 抽象方法。

16.2.1.6.1.1 LoadRequestedModules ( [ hostDefined ] )

The LoadRequestedModules concrete method of a Cyclic Module Record module takes optional argument hostDefined (anything) and returns a Promise. 它填充 module 的依赖图中所有 Module Record[[LoadedModules]](大部分工作由辅助函数 InnerModuleLoading 完成)。它接受一个可选的 hostDefined 参数,并将其传递给 HostLoadImportedModule hook。 It performs the following steps when called:

  1. 如果 hostDefined 不存在,则将 hostDefined 设置为 empty
  2. promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  3. stateGraphLoadingState Record { [[IsLoading]]: true, [[PendingModulesCount]]: 1, [[Visited]]: « », [[PromiseCapability]]: promiseCapability, [[HostDefined]]: hostDefined }。
  4. 执行 InnerModuleLoading(state, module)。
  5. 返回 promiseCapability.[[Promise]]
Note
hostDefined 参数可用于传递获取导入模块所需的附加信息。例如,HTML 会使用它为 <link rel="preload" as="..."> 标签设置正确的 fetch destination。 import() 表达式永远不会设置 hostDefined 参数。

16.2.1.6.1.1.1 InnerModuleLoading ( state, module )

The abstract operation InnerModuleLoading takes arguments state (a GraphLoadingState Record) and module (a Module Record) and returns unused. LoadRequestedModules 使用它来为 module 的依赖图递归执行实际加载过程。 It performs the following steps when called:

  1. 断言:state.[[IsLoading]]true
  2. 如果 moduleCyclic Module Recordmodule.[[Status]]new,并且 state.[[Visited]]包含 module,则
    1. module 追加到 state.[[Visited]]
    2. requestedModulesCountmodule.[[RequestedModules]] 中元素的数量。
    3. state.[[PendingModulesCount]] 设置为 state.[[PendingModulesCount]] + requestedModulesCount
    4. module.[[RequestedModules]] 的每个 ModuleRequest Record request,执行:
      1. 如果 AllImportAttributesSupported(request.[[Attributes]]) 是 false,则
        1. errorThrowCompletion(一个新创建的 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 )

The abstract operation ContinueModuleLoading takes arguments state (a GraphLoadingState Record) and moduleCompletion (either a normal completion containing a Module Record or a throw completion) and returns unused. 它用于在调用 HostLoadImportedModule 后重新进入加载过程。 It performs the following steps when called:

  1. 如果 state.[[IsLoading]]false,则返回 unused
  2. 如果 moduleCompletion 是 normal completion,则
    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 ( )

The Link concrete method of a Cyclic Module Record module takes no arguments and returns either a normal completion containing unused or a throw completion. 成功时,Link 会将此模块的 [[Status]]unlinked 转换为 linked。失败时,会抛出异常,并且此模块的 [[Status]] 保持 unlinked。(大部分工作由辅助函数 InnerModuleLinking 完成。) It performs the following steps when called:

  1. 断言:module.[[Status]]unlinkedlinkedevaluating-asyncevaluated 之一。
  2. stack 为一个新的空 List
  3. resultCompletion(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]]linkedevaluating-asyncevaluated 之一。
  6. 断言:stack 为空。
  7. 返回 unused

16.2.1.6.1.2.1 InnerModuleLinking ( module, stack, index )

The abstract operation InnerModuleLinking takes arguments module (a Module Record), stack (a List of Cyclic Module Records), and index (a non-negative integer) and returns either a normal completion containing a non-negative integer or a throw completion. Link 使用它来为 module 执行实际链接过程,并递归地对依赖图中的所有其他模块执行实际链接过程。stackindex 参数,以及模块的 [[DFSAncestorIndex]] 字段,用于跟踪深度优先搜索(DFS)遍历。特别地,[[DFSAncestorIndex]] 用于发现强连通分量(SCC),使得一个 SCC 中的所有模块一起转换为 linked。 It performs the following steps when called:

  1. 如果 module 不是 Cyclic Module Record,则
    1. 执行 ? module.Link()。
    2. 返回 index
  2. 如果 module.[[Status]]linkinglinkedevaluating-asyncevaluated 之一,则
    1. 返回 index
  3. 断言:module.[[Status]]unlinked
  4. module.[[Status]] 设置为 linking
  5. moduleIndexindex
  6. module.[[DFSAncestorIndex]] 设置为 index
  7. index 设置为 index + 1。
  8. module 追加到 stack
  9. module.[[RequestedModules]] 的每个 ModuleRequest Record request,执行:
    1. requiredModuleGetImportedModule(module, request)。
    2. index 设置为 ? InnerModuleLinking(requiredModule, stack, index)。
    3. 如果 requiredModuleCyclic Module Record,则
      1. 断言:requiredModule.[[Status]]linkinglinkedevaluating-asyncevaluated 之一。
      2. 断言:当且仅当 stack 包含 requiredModule 时,requiredModule.[[Status]]linking
      3. 如果 requiredModule.[[Status]]linking,则
        1. module.[[DFSAncestorIndex]] 设置为 min(module.[[DFSAncestorIndex]], requiredModule.[[DFSAncestorIndex]])。
  10. 执行 ? module.InitializeEnvironment()。
  11. 断言:modulestack 中恰好出现一次。
  12. 断言:module.[[DFSAncestorIndex]]moduleIndex
  13. 如果 module.[[DFSAncestorIndex]] = moduleIndex,则
    1. donefalse
    2. 重复,只要 donefalse
      1. requiredModulestack 的最后一个元素。
      2. 移除 stack 的最后一个元素。
      3. 断言:requiredModuleCyclic Module Record
      4. requiredModule.[[Status]] 设置为 linked
      5. 如果 requiredModulemodule 是同一个 Module Record,则将 done 设置为 true
  14. 返回 index

16.2.1.6.1.3 Evaluate ( )

The Evaluate concrete method of a Cyclic Module Record module takes no arguments and returns a Promise. Evaluate 会将此模块的 [[Status]]linked 转换为 evaluating-asyncevaluated。第一次对给定强连通分量中的某个模块调用它时,Evaluate 会创建并返回一个 Promise,该 Promise 会在模块完成求值时 resolve。此 Promise 存储在该分量的 [[CycleRoot]][[TopLevelCapability]] 字段中。之后对该分量中任何模块调用 Evaluate,都会返回同一个 Promise。(大部分工作由辅助函数 InnerModuleEvaluation 完成。) It performs the following steps when called:

  1. 断言:对 Evaluate 的此调用不会与周围 agent 内对 Evaluate 的另一个调用同时发生。
  2. 断言:module.[[Status]]linkedevaluating-asyncevaluated 之一。
  3. 如果 module.[[Status]]evaluating-asyncevaluated,则
    1. 如果 module.[[CycleRoot]] 不是 empty,则
      1. module 设为 module.[[CycleRoot]]
    2. 否则,
      1. 断言:module.[[Status]]evaluated,且 module.[[EvaluationError]] 是一个 throw completion。
  4. 如果 module.[[TopLevelCapability]] 不是 empty,则
    1. 返回 module.[[TopLevelCapability]].[[Promise]]
  5. stack 为一个新的空 List
  6. promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  7. module.[[TopLevelCapability]] 设为 promiseCapability
  8. resultCompletion(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-asyncevaluated
    2. 断言:module.[[EvaluationError]]empty
    3. 如果 module.[[Status]]evaluated,则
      1. 断言:module.[[AsyncEvaluationOrder]]unsetdone
      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 )

The abstract operation InnerModuleEvaluation takes arguments module (a Module Record), stack (a List of Cyclic Module Records), and index (a non-negative integer) and returns either a normal completion containing a non-negative integer or a throw completion. Evaluate 使用它来为 module 执行实际求值过程,并递归地对依赖图中的所有其他模块执行实际求值过程。stackindex 参数,以及 module[[DFSAncestorIndex]] 字段,其用法与 InnerModuleLinking 中相同。 It performs the following steps when called:

  1. 如果 module 不是 Cyclic Module Record,则
    1. 执行 ? EvaluateModuleSync(module)。
    2. 返回 index
  2. 如果 module.[[Status]]evaluating-asyncevaluated,则
    1. 如果 module.[[EvaluationError]]empty,则返回 index
    2. 返回 ? module.[[EvaluationError]]
  3. 如果 module.[[Status]]evaluating,则返回 index
  4. 断言:module.[[Status]]linked
  5. module.[[Status]] 设置为 evaluating
  6. moduleIndexindex
  7. module.[[DFSAncestorIndex]] 设置为 index
  8. module.[[PendingAsyncDependencies]] 设置为 0。
  9. index 设置为 index + 1。
  10. module 追加到 stack
  11. module.[[RequestedModules]] 的每个 ModuleRequest Record request,执行:
    1. requiredModuleGetImportedModule(module, request)。
    2. index 设置为 ? InnerModuleEvaluation(requiredModule, stack, index)。
    3. 如果 requiredModuleCyclic Module Record,则
      1. 断言:requiredModule.[[Status]]evaluatingevaluating-asyncevaluated 之一。
      2. 断言:当且仅当 stack 包含 requiredModule 时,requiredModule.[[Status]]evaluating
      3. 如果 requiredModule.[[Status]]evaluating,则
        1. module.[[DFSAncestorIndex]] 设置为 min(module.[[DFSAncestorIndex]], requiredModule.[[DFSAncestorIndex]])。
      4. 否则,
        1. requiredModule 设置为 requiredModule.[[CycleRoot]]
        2. 断言:requiredModule.[[Status]]evaluating-asyncevaluated
        3. 如果 requiredModule.[[EvaluationError]] 不是 empty,则返回 ? requiredModule.[[EvaluationError]]
      5. 如果 requiredModule.[[AsyncEvaluationOrder]] 是整数,则
        1. module.[[PendingAsyncDependencies]] 设置为 module.[[PendingAsyncDependencies]] + 1。
        2. module 追加到 requiredModule.[[AsyncParentModules]]
  12. 如果 module.[[PendingAsyncDependencies]] > 0 或 module.[[HasTLA]]true,则
    1. 断言:module.[[AsyncEvaluationOrder]]unset
    2. module.[[AsyncEvaluationOrder]] 设置为 IncrementModuleAsyncEvaluationCount()。
    3. 如果 module.[[PendingAsyncDependencies]] = 0,则执行 ExecuteAsyncModule(module)。
  13. 否则,
    1. 执行 ? module.ExecuteModule()
  14. 断言:modulestack 中恰好出现一次。
  15. 断言:module.[[DFSAncestorIndex]]moduleIndex
  16. 如果 module.[[DFSAncestorIndex]] = moduleIndex,则
    1. donefalse
    2. 重复,只要 donefalse
      1. requiredModulestack 的最后一个元素。
      2. 移除 stack 的最后一个元素。
      3. 断言:requiredModuleCyclic Module Record
      4. 断言:requiredModule.[[AsyncEvaluationOrder]] 是整数或 unset
      5. 如果 requiredModule.[[AsyncEvaluationOrder]]unset,则将 requiredModule.[[Status]] 设置为 evaluated
      6. 否则,将 requiredModule.[[Status]] 设置为 evaluating-async
      7. 如果 requiredModulemodule 是同一个 Module Record,则将 done 设置为 true
      8. requiredModule.[[CycleRoot]] 设置为 module
  17. 返回 index
Note 1

模块在被 InnerModuleEvaluation 遍历期间是 evaluating。模块在执行完成时是 evaluated;如果其 [[HasTLA]] 字段是 true 或具有异步依赖项,则在执行期间是 evaluating-async

Note 2

当异步循环不处于 evaluating 状态时,任何依赖该异步循环中某个模块的模块,将改为通过 [[CycleRoot]] 依赖该循环根的执行。这确保循环状态可以通过其根模块状态被视为一个单一的强连通分量。

16.2.1.6.1.3.2 ExecuteAsyncModule ( module )

The abstract operation ExecuteAsyncModule takes argument module (a Cyclic Module Record) and returns unused. It performs the following steps when called:

  1. 断言:module.[[Status]]evaluatingevaluating-async
  2. 断言:module.[[HasTLA]]true
  3. promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  4. fulfilledClosure 为一个新的 Abstract Closure,它没有参数、捕获 module,并在被调用时执行以下步骤:
    1. 执行 AsyncModuleExecutionFulfilled(module)。
    2. 返回 NormalCompletion(undefined)。
  5. onFulfilledCreateBuiltinFunction(fulfilledClosure, 0, "", « »)。
  6. rejectedClosure 为一个新的 Abstract Closure,它具有参数 (error)、捕获 module,并在被调用时执行以下步骤:
    1. 执行 AsyncModuleExecutionRejected(module, error)。
    2. 返回 NormalCompletion(undefined)。
  7. onRejectedCreateBuiltinFunction(rejectedClosure, 0, "", « »)。
  8. 执行 PerformPromiseThen(promiseCapability.[[Promise]], onFulfilled, onRejected)。
  9. 执行 ! module.ExecuteModule(promiseCapability)
  10. 返回 unused

16.2.1.6.1.3.3 GatherAvailableAncestors ( module, execList )

The abstract operation GatherAvailableAncestors takes arguments module (a Cyclic Module Record) and execList (a List of Cyclic Module Records) and returns unused. It performs the following steps when called:

  1. module.[[AsyncParentModules]] 的每个 Cyclic Module Record ancestorModule,执行:
    1. 如果 execList包含 ancestorModuleancestorModule.[[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
Note

当根 module 的异步执行被 fulfilled 时,此函数会确定能够在此完成时一起同步执行的模块列表,并将其填充到 execList 中。

16.2.1.6.1.3.4 AsyncModuleExecutionFulfilled ( module )

The abstract operation AsyncModuleExecutionFulfilled takes argument module (a Cyclic Module Record) and returns unused. It performs the following steps when called:

  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. resultCompletion(ancestorModule.ExecuteModule())。
      2. 如果 result 是 abrupt completion,则
        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 )

The abstract operation AsyncModuleExecutionRejected takes arguments module (a Cyclic Module Record) and error (an ECMAScript language value) and returns unused. It performs the following steps when called:

  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 图示例

本非规范性小节给出一些常见模块图的链接和求值的一系列示例,并特别关注错误如何发生。

首先考虑以下简单模块图:

Figure 2: 一个简单模块图
一个模块图,其中模块 A 依赖模块 B,模块 B 依赖模块 C

我们先假设没有错误条件。当宿主首次调用 A.LoadRequestedModules() 时,根据假设,这将成功完成,并递归加载 BC 的依赖项(分别为 C 和无),然后设置 A.[[Status]] = B.[[Status]] = C.[[Status]] = unlinked。然后,当宿主调用 A.Link() 时,它将成功完成(同样根据假设),使得 A.[[Status]] = B.[[Status]] = C.[[Status]] = linked。这些准备步骤可以在任何时候执行。稍后,当宿主准备承受模块可能产生的任何副作用时,它可以调用 A.Evaluate(),这将成功完成,返回一个 resolving to undefined 的 Promise(同样根据假设),并递归地先求值 C,再求值 B。此时每个模块的 [[Status]] 都将是 evaluated

接下来考虑在成功调用 A.LoadRequestedModules() 之后发生链接错误的情况。如果 CInnerModuleLinking 成功,但之后 BInnerModuleLinking 失败,例如因为它导入了 C 未提供的某个内容,那么原始 A.Link() 将失败,并且 AB[[Status]] 都保持 unlinked。不过,C[[Status]] 已经变为 linked

最后,考虑在成功调用 Link() 之后发生求值错误的情况。如果 CInnerModuleEvaluation 成功,但之后 BInnerModuleEvaluation 失败,例如因为 B 包含会抛出异常的代码,那么原始 A.Evaluate() 将失败,返回一个 rejected Promise。所得异常将记录在 AB[[EvaluationError]] 字段中,并且它们的 [[Status]] 将变为 evaluatedC 也会变为 evaluated,但与 AB 不同,由于它成功完成了求值,它将保持没有 [[EvaluationError]]。存储异常确保宿主任何时候尝试通过调用 Evaluate() 方法重用 AB 时,都会遇到相同的异常。(宿主不需要重用 Cyclic Module Record;类似地,宿主不需要暴露由这些方法抛出的异常对象。不过,本规范允许这种用途。)

现在考虑另一种类型的错误条件:

Figure 3: 带有无法解析模块的模块图
一个模块图,其中模块 A 依赖一个缺失(无法解析)的模块,用 ??? 表示

在此场景中,模块 A 声明了对某个其他模块的依赖,但不存在该模块的 Module Record,即当请求它时,HostLoadImportedModule 会用异常调用 FinishLoadingImportedModule。这可能由于各种原因发生,例如对应资源不存在,或资源存在但 ParseModule 在尝试解析所得源文本时返回一些错误。宿主可以选择通过传给 FinishLoadingImportedModule 的 completion 暴露失败原因。无论如何,此异常都会导致加载失败,从而使 A[[Status]] 保持 new

这里加载、链接和求值错误之间的差异,是由于以下特性:

  • 求值必须只执行一次,因为它可能产生副作用;因此,记住求值是否已经执行非常重要,即使执行失败也如此。(在错误情况下,同时记住异常也是有意义的,因为否则后续 Evaluate() 调用将不得不合成一个新的异常。)
  • 另一方面,链接没有副作用,因此即使失败,也可以在以后重试而没有问题。
  • 加载与宿主紧密交互,并且对某些宿主来说,允许用户重试失败的加载可能是可取的(例如,如果失败是由临时网络状况不佳引起的)。

现在,考虑一个带有循环的模块图:

Figure 4: 一个循环模块图
一个模块图,其中模块 A 依赖模块 B 和 C,但模块 B 也依赖模块 A

这里我们假设入口点是模块 A,因此宿主首先调用 A.LoadRequestedModules(),它会在 A 上执行 InnerModuleLoading。这又会在 BC 上调用 InnerModuleLoading。由于存在循环,这又会触发在 A 上调用 InnerModuleLoading,但此时它是 no-op,因为在此次 LoadRequestedModules 过程中 A 的依赖项加载已经被触发。当图中的所有模块都已成功加载时,它们的 [[Status]] 同时从 new 转换为 unlinked

然后宿主继续调用 A.Link(),它会在 A 上执行 InnerModuleLinking。这又会在 B 上调用 InnerModuleLinking。由于存在循环,这又会触发在 A 上调用 InnerModuleLinking,但此时它是 no-op,因为 A.[[Status]] 已经是 linking。当控制回到 A 并在 C 上触发 InnerModuleLinking 时,B.[[Status]] 自身仍保持 linking。在这返回且 C.[[Status]]linked 后,AB 一起从 linking 转换为 linked;这是有意设计的,因为它们形成一个强连通分量。能够同时转换同一 SCC 中模块的状态,是因为在此阶段模块图通过深度优先搜索遍历。

在循环模块图求值阶段的成功情况下,也会发生类似的过程。

现在考虑 A 有链接错误的情况;例如,它尝试从 C 导入一个不存在的绑定。在这种情况下,上述步骤仍会发生,包括第二次在 A 上调用 InnerModuleLinking 时的提前返回。不过,一旦我们回退到 A 上原始的 InnerModuleLinking,它会在 InitializeEnvironment 期间失败,也就是在 C.ResolveExport() 之后立即失败。抛出的 SyntaxError 异常会传播到 A.Link,后者会重置当前位于其 stack 上的所有模块(这些始终恰好是仍处于 linking 的模块)。因此 AB 都变为 unlinked。注意,C 会保留为 linked

或者,考虑 A 有求值错误的情况;例如,其源代码抛出异常。在这种情况下,上述步骤的求值时类比仍会发生,包括第二次在 A 上调用 InnerModuleEvaluation 时的提前返回。不过,一旦我们回退到 A 上原始的 InnerModuleEvaluation,根据假设它会失败。抛出的异常会传播到 A.Evaluate(),后者会把错误记录到当前位于其 stack 上的所有模块(即仍处于 evaluating 的模块),并且也通过 [[AsyncParentModules]] 记录,该字段会为包含顶层 await 或依赖顶层 await 的模块,通过 AsyncModuleExecutionRejected 算法在整个依赖图中形成一条链。因此 AB 都变为 evaluated,并且异常会记录在 AB[[EvaluationError]] 字段中,而 C 会保留为 evaluated 且没有 [[EvaluationError]]

最后,考虑一个带有循环且所有模块都异步完成的模块图:

Figure 5: 一个异步循环模块图
一个模块图,其中模块 A 依赖模块 B 和 C,模块 B 依赖模块 D,模块 C 依赖模块 D 和 E,并且模块 D 依赖模块 A

加载和链接按之前一样发生,并且所有模块最终的 [[Status]] 都设置为 linked

调用 A.Evaluate() 会在 ABD 上调用 InnerModuleEvaluation,它们都会转换为 evaluating。然后再次在 A 上调用 InnerModuleEvaluation,这是一项 no-op,因为它已经是 evaluating。此时,D.[[PendingAsyncDependencies]] 是 0,因此调用 ExecuteAsyncModule(D),并且我们以一个跟踪 D 异步执行的新 PromiseCapability 调用 D.ExecuteModule。我们回退到 B 上的 InnerModuleEvaluation,将 B.[[PendingAsyncDependencies]] 设置为 1,并将 B.[[AsyncEvaluationOrder]] 设置为 1。我们再回退到 A 上原始的 InnerModuleEvaluation,将 A.[[PendingAsyncDependencies]] 设置为 1。在遍历 A 依赖项的下一次循环迭代中,我们在 C 上调用 InnerModuleEvaluation,并由此在 D(再次 no-op)和 E 上调用它。由于 E 没有依赖项且不是循环的一部分,我们以与 D 相同的方式调用 ExecuteAsyncModule(E),并且 E 会立即从栈中移除。我们再次回退到 C 上的 InnerModuleEvaluation,将 C.[[AsyncEvaluationOrder]] 设置为 3。现在我们完成对 A 依赖项的循环,将 A.[[AsyncEvaluationOrder]] 设置为 4,并从栈中移除整个强连通分量,使所有模块一次性转换为 evaluating-async。此时,模块字段如 Table 44 所示。

Table 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(BC 1(D 2(DE 0 0

让我们假设 E 最先完成执行。当这发生时,会调用 AsyncModuleExecutionFulfilledE.[[Status]] 会被设置为 evaluated,并且 C.[[PendingAsyncDependencies]] 会递减为 1。更新后的模块字段如 Table 45 所示。

Table 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 并行)。更新后的模块字段如 Table 46 所示。

Table 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 接下来完成执行。当这发生时,会再次调用 AsyncModuleExecutionFulfilledC.[[Status]] 会被设置为 evaluated,并且 A.[[PendingAsyncDependencies]] 会递减为 1。更新后的模块字段如 Table 47 所示。

Table 47: 模块 C 完成执行之后的模块字段
字段
模块
A C
[[DFSAncestorIndex]] 0 0
[[Status]] evaluating-async evaluated
[[AsyncEvaluationOrder]] 4 done
[[AsyncParentModules]] « » « A »
[[PendingAsyncDependencies]] 1(B 0

然后,B 完成执行。当这发生时,会再次调用 AsyncModuleExecutionFulfilled,并且 B.[[Status]] 会被设置为 evaluatedA.[[PendingAsyncDependencies]] 会递减为 0,因此调用 ExecuteAsyncModule 并且它开始执行。更新后的模块字段如 Table 48 所示。

Table 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() 返回的)会被 resolve,并且这结束了对此模块图的处理。更新后的模块字段如 Table 49 所示。

Table 49: 模块 A 完成执行之后的模块字段
字段
模块
A
[[DFSAncestorIndex]] 0
[[Status]] evaluated
[[AsyncEvaluationOrder]] done
[[AsyncParentModules]] « »
[[PendingAsyncDependencies]] 0

或者,考虑一个失败情况,其中 C 执行失败,并在 B 完成执行之前返回错误。当这发生时,会调用 AsyncModuleExecutionRejected,它会将 C.[[Status]] 设置为 evaluated,并将 C.[[EvaluationError]] 设置为该错误。然后它通过对每个 AsyncParentModules 执行 AsyncModuleExecutionRejected,把此错误传播到所有 AsyncParentModules。更新后的模块字段如 Table 50 所示。

Table 50: 模块 C 以错误完成之后的模块字段
字段
模块
A C
[[DFSAncestorIndex]] 0 0
[[Status]] evaluated evaluated
[[AsyncEvaluationOrder]] done done
[[AsyncParentModules]] « » « A »
[[PendingAsyncDependencies]] 1(B 0
[[EvaluationError]] empty C 的求值错误

由于 C 会以 C 的错误在 A 上调用 AsyncModuleExecutionRejected,因此 A 将以与 C 相同的错误被 rejected。A.[[Status]] 被设置为 evaluated。此时,A.[[TopLevelCapability]] 中的 Promise(它是从 A.Evaluate() 返回的)会被 rejected。更新后的模块字段如 Table 51 所示。

Table 51: 模块 A 被 rejected 之后的模块字段
字段
模块
A
[[DFSAncestorIndex]] 0
[[Status]] evaluated
[[AsyncEvaluationOrder]] done
[[AsyncParentModules]] « »
[[PendingAsyncDependencies]] 0
[[EvaluationError]] CEvaluation Error

然后,B 完成执行且没有错误。当这发生时,会再次调用 AsyncModuleExecutionFulfilled,并且 B.[[Status]] 会被设置为 evaluated。会在 B 上调用 GatherAvailableAncestors。不过,A.[[CycleRoot]]A,且它有求值错误,因此它不会被添加到返回的 sortedExecList,并且 AsyncModuleExecutionFulfilled 将返回而不做进一步处理。B 的任何未来导入者都会从循环根 A 上设置的来自 C 的求值错误中,解析 B.[[CycleRoot]].[[EvaluationError]] 的拒绝。更新后的模块字段如 Table 52 所示。

Table 52: 错误图中模块 B 完成执行之后的模块字段
字段
模块
A B
[[DFSAncestorIndex]] 0 0
[[Status]] evaluated evaluated
[[AsyncEvaluationOrder]] 4 1
[[AsyncParentModules]] « » « A »
[[PendingAsyncDependencies]] 0 0
[[EvaluationError]] CEvaluation Error empty

16.2.1.7 Source Text Module Record

Source Text Module Record 用于表示关于从 ECMAScript 源文本(11)定义的模块的信息,该源文本使用目标符号 Module 解析。其字段包含关于该模块导入和导出名称的摘要信息,其具体方法使用这些摘要来链接和求值该模块。

Source Text Module Record 可以与抽象 Module Record 类型的其他子类一起存在于模块图中,并且可以与 Cyclic Module Record 类型的其他子类一起参与循环。

除了 Table 41 中定义的字段之外,Source Text Module Record 还具有 Table 53 中列出的附加字段。这些字段中的每一个最初都在 ParseModule 中设置。

Table 53: Source Text Module Record 的附加字段
字段名 值类型 含义
[[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 RecordList
[[LocalExportEntries]] a List of ExportEntry Records 从此模块代码派生出的 ExportEntry RecordList,对应于模块内出现的声明。
[[IndirectExportEntries]] a List of ExportEntry Records 从此模块代码派生出的 ExportEntry RecordList,对应于模块内出现的重导出导入,或来自 export * as namespace 声明的导出。
[[StarExportEntries]] a List of ExportEntry Records 从此模块代码派生出的 ExportEntry RecordList,对应于模块内出现的 export * 声明,但不包括 export * as namespace 声明。

ImportEntry Record 是摘要化关于单个声明式导入的信息的 Record。每个 ImportEntry Record 都具有 Table 54 中定义的字段:

Table 54: ImportEntry Record 字段
字段名 值类型 含义
[[ModuleRequest]] a ModuleRequest Record 表示 ImportDeclarationModuleSpecifier 和导入属性的 ModuleRequest Record
[[ImportName]] a String or namespace 所需绑定由 [[ModuleRequest]] 标识的模块导出时使用的名称。值 namespace 表示导入请求针对目标模块的命名空间对象。
[[LocalName]] a String 在导入模块内部本地访问导入值时使用的名称。
Note 1

Table 55 给出了用于表示句法导入形式的 ImportEntry record 字段示例:

Table 55 (Informative): 导入形式到 ImportEntry Record 的映射
Import 语句形式 [[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 都具有 Table 56 中定义的字段:

Table 56: ExportEntry Record 字段
字段名 值类型 含义
[[ExportName]] a String or null 此绑定被此模块导出时使用的名称。
[[ModuleRequest]] a ModuleRequest Record or null 表示 ExportDeclarationModuleSpecifier 和导入属性的 ModuleRequest Record。如果 ExportDeclaration 没有 ModuleSpecifier,则为 null
[[ImportName]] a String, null, namespace, or all-but-default 所需绑定由 [[ModuleRequest]] 标识的模块导出时使用的名称。如果 ExportDeclaration 没有 ModuleSpecifier,则为 nullnamespace 用于 export * as ns from "mod" 声明。all-but-default 用于 export * from "mod" 声明。
[[LocalName]] a String or null 在导入模块内部本地访问被导出值时使用的名称。如果被导出的值不能从模块内部本地访问,则为 null
Note 2

Table 57 给出了用于表示句法导出形式的 ExportEntry record 字段示例:

Table 57 (Informative): 导出形式到 ExportEntry Record 的映射
Export 语句形式 [[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 )

The abstract operation ParseModule takes arguments sourceText (a String or a sequence of Unicode code points), realm (a Realm Record), and hostDefined (anything) and returns a Source Text Module Record or a non-empty List of SyntaxError objects. 它基于把 sourceText 解析为 Module 的结果创建一个 Source Text Module Record。 It performs the following steps when called:

  1. bodyParseText(sourceText, Module)。
  2. 如果 body 是错误 List,则返回 body
  3. requestedModulesbodyModuleRequests
  4. importEntriesbodyImportEntries
  5. importedBoundNamesImportedLocalNames(importEntries)。
  6. indirectExportEntries 为一个新的空 List
  7. localExportEntries 为一个新的空 List
  8. starExportEntries 为一个新的空 List
  9. exportEntriesbodyExportEntries
  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. importEntryimportEntries[[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. asyncbody 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 }。
Note

实现可以在对模块源文本求值 ParseModule 之前解析模块源文本并分析其早期错误条件。不过,任何错误的报告都必须推迟到本规范实际对该源文本执行 ParseModule 的时刻。

16.2.1.7.2 Module Record 抽象方法的实现

以下是 Source Text Module Record 的具体方法,它们实现 Table 40 中定义的相应 Module Record 抽象方法。

16.2.1.7.2.1 GetExportedNames ( [ exportStarSet ] )

The GetExportedNames concrete method of a Source Text Module Record module takes optional argument exportStarSet (a List of Source Text Module Records) and returns a List of Strings. It performs the following steps when called:

  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. requestedModuleGetImportedModule(module, exportEntry.[[ModuleRequest]])。
    3. starNamesrequestedModule.GetExportedNames(exportStarSet)。
    4. starNames 的每个元素 name,执行:
      1. 如果 name 不是 "default",则
        1. 如果 exportedNames包含 name,则
          1. name 追加到 exportedNames
  9. 返回 exportedNames
Note

GetExportedNames 不会过滤掉具有 ambiguous 星号导出绑定的名称,也不会对此抛出异常。

16.2.1.7.2.2 ResolveExport ( exportName [ , resolveSet ] )

The ResolveExport concrete method of a Source Text Module Record module takes argument exportName (a String) and optional argument resolveSet (a List of Records with fields [[Module]] (a Module Record) and [[ExportName]] (a String)) and returns a ResolvedBinding Record, null, or ambiguous.

ResolveExport 尝试将导入绑定解析为实际定义该绑定的模块和本地绑定名称。定义模块可以是调用此方法的 Module Record 所表示的模块,也可以是由该模块导入的某个其他模块。参数 resolveSet 用于检测未解析的循环导入/导出路径。如果到达一个由特定 Module RecordexportName 组成、且已经在 resolveSet 中的 pair,就遇到了导入循环性。在递归调用 ResolveExport 之前,会把由 moduleexportName 组成的 pair 添加到 resolveSet

如果找到定义模块,则返回 ResolvedBinding Record { [[Module]], [[BindingName]] }。此 record 标识最初请求的导出的已解析绑定,除非这是没有本地绑定的命名空间导出。在这种情况下,[[BindingName]] 会被设置为 namespace。如果未找到定义或发现请求是循环的,则返回 null。如果发现请求是 ambiguous,则返回 ambiguous

It performs the following steps when called:

  1. 断言:module.[[Status]] 不是 new
  2. 如果 resolveSet 不存在,则将 resolveSet 设为一个新的空 List
  3. resolveSet 的每个 Record { [[Module]], [[ExportName]] } record,执行:
    1. 如果 modulerecord.[[Module]] 是同一个 Module Record,且 exportNamerecord.[[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. importedModuleGetImportedModule(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. starResolutionnull
  9. module.[[StarExportEntries]] 的每个 ExportEntry Record exportEntry,执行:
    1. 断言:exportEntry.[[ModuleRequest]] 不是 null
    2. importedModuleGetImportedModule(module, exportEntry.[[ModuleRequest]])。
    3. resolutionimportedModule.ResolveExport(exportName, resolveSet)。
    4. 如果 resolutionambiguous,则返回 ambiguous
    5. 如果 resolution 不是 null,则
      1. 断言:resolution 是一个 ResolvedBinding Record
      2. 如果 starResolutionnull,则
        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 的具体方法,它们实现 Table 42 中定义的相应 Cyclic Module Record 抽象方法。

16.2.1.7.3.1 InitializeEnvironment ( )

The InitializeEnvironment concrete method of a Source Text Module Record module takes no arguments and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

  1. module.[[IndirectExportEntries]] 的每个 ExportEntry Record exportEntry,执行:
    1. 断言:exportEntry.[[ExportName]] 不是 null
    2. resolutionmodule.ResolveExport(exportEntry.[[ExportName]])。
    3. 如果 resolutionnullambiguous,则抛出一个 SyntaxError 异常。
    4. 断言:resolution 是一个 ResolvedBinding Record
  2. 断言:来自 module 的所有具名导出都是可解析的。
  3. realmmodule.[[Realm]]
  4. 断言:realm 不是 undefined
  5. envRecordNewModuleEnvironment(realm.[[GlobalEnv]])。
  6. module.[[Environment]] 设为 envRecord
  7. module.[[ImportEntries]] 的每个 ImportEntry Record importEntry,执行:
    1. importedModuleGetImportedModule(module, importEntry.[[ModuleRequest]])。
    2. 如果 importEntry.[[ImportName]]namespace,则
      1. namespaceGetModuleNamespace(importedModule)。
      2. 执行 ! envRecord.CreateImmutableBinding(importEntry.[[LocalName]], true)。
      3. 执行 ! envRecord.InitializeBinding(importEntry.[[LocalName]], namespace)。
    3. 否则,
      1. 断言:importEntry.[[ImportName]] 是一个 String。
      2. resolutionimportedModule.ResolveExport(importEntry.[[ImportName]])。
      3. 如果 resolutionnullambiguous,则抛出一个 SyntaxError 异常。
      4. 如果 resolution.[[BindingName]]namespace,则
        1. namespaceGetModuleNamespace(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. moduleContextRealm 设为 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. codemodule.[[ECMAScriptCode]]
  19. variableDeclscodeVarScopedDeclarations
  20. declaredVariableNames 为一个新的空 List
  21. variableDecls 的每个元素 variableDecl,执行:
    1. variableDeclBoundNames 的每个元素 name,执行:
      1. 如果 declaredVariableNames包含 name,则
        1. 执行 ! envRecord.CreateMutableBinding(name, false)。
        2. 执行 ! envRecord.InitializeBinding(name, undefined)。
        3. name 追加到 declaredVariableNames
  22. lexicalDeclscodeLexicallyScopedDeclarations
  23. privateEnvnull
  24. lexicalDecls 的每个元素 lexicalDecl,执行:
    1. lexicalDeclBoundNames 的每个元素 name,执行:
      1. 如果 lexicalDeclIsConstantDeclarationtrue,则
        1. 执行 ! envRecord.CreateImmutableBinding(name, true)。
      2. 否则,
        1. 执行 ! envRecord.CreateMutableBinding(name, false)。
      3. 如果 lexicalDeclFunctionDeclarationGeneratorDeclarationAsyncFunctionDeclarationAsyncGeneratorDeclaration,则
        1. funcObj 为使用参数 envRecordprivateEnvlexicalDecl 执行 InstantiateFunctionObject 的结果。
        2. 执行 ! envRecord.InitializeBinding(name, funcObj)。
  25. 从执行上下文栈中移除 moduleContext
  26. 返回 unused

16.2.1.7.3.2 ExecuteModule ( [ capability ] )

The ExecuteModule concrete method of a Source Text Module Record module takes optional argument capability (a PromiseCapability Record) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

  1. 断言:module 已被链接,并且其模块环境中的声明已被实例化。
  2. moduleContextmodule.[[Context]]
  3. 如果 module.[[HasTLA]]false,则
    1. 断言:capability 不存在。
    2. envmodule.[[Environment]]
    3. 挂起运行中执行上下文。
    4. moduleContext 推入执行上下文栈;moduleContext 现在是运行中执行上下文。
    5. resultmodule.[[ECMAScriptCode]] 的求值的 Completion
    6. result 设置为 Completion(DisposeResources(env.[[DisposableResourceStack]], result))。
    7. 挂起 moduleContext,并将其从执行上下文栈中移除。
    8. 恢复当前位于执行上下文栈顶部的上下文作为运行中执行上下文。
    9. 如果 result 是突兀完成,则
      1. 返回 ? result
  4. 否则,
    1. 断言:capability 是 PromiseCapability 记录。
    2. 执行 AsyncBlockStart(capability, module.[[ECMAScriptCode]], moduleContext)。
  5. 返回 unused

16.2.1.8 Synthetic Module Record

Synthetic Module Record 用于表示由规范定义的模块相关信息。其导出名称在创建时静态定义,而其对应值可以随时间通过 SetSyntheticModuleExport 改变。它没有导入或依赖项。

Note
Synthetic Module Record 可用于定义各种模块类型:例如 JSON 模块或 CSS 模块。

除了 Table 39 中定义的字段之外,Synthetic Module Record 还具有 Table 58 中列出的附加字段。

Table 58: Synthetic Module Record 的附加字段
字段名 值类型 含义
[[ExportNames]] a List of Strings 模块的导出名称。此列表不包含重复项。
[[EvaluationSteps]] an Abstract Closure 在求值模块时要执行的初始化逻辑,以 Synthetic Module Record 作为其唯一实参。它不得修改 [[ExportNames]]。它可以返回 abrupt completion。

16.2.1.8.1 CreateDefaultExportSyntheticModule ( defaultExport )

The abstract operation CreateDefaultExportSyntheticModule takes argument defaultExport (an ECMAScript language value) and returns a Synthetic Module Record. 它创建一个默认导出为 defaultExportSynthetic Module Record。 It performs the following steps when called:

  1. realm当前 Realm Record
  2. setDefaultExport 为一个新的 Abstract Closure,它具有参数 (module)、捕获 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 )

The abstract operation ParseJSONModule takes argument source (a String) and returns either a normal completion containing a Synthetic Module Record, or a throw completion. It performs the following steps when called:

  1. parseResult 为 ? ParseJSON(source)。
  2. 返回 CreateDefaultExportSyntheticModule(parseResult.[[Value]])。

16.2.1.8.3 SetSyntheticModuleExport ( module, exportName, exportValue )

The abstract operation SetSyntheticModuleExport takes arguments module (a Synthetic Module Record), exportName (a String), and exportValue (an ECMAScript language value) and returns unused. 它可用于为 Synthetic Module Record 的现有导出设置或更改导出值。 It performs the following steps when called:

  1. 断言:module.[[ExportNames]] 包含 exportName
  2. envRecordmodule.[[Environment]]
  3. 断言:envRecord 不是 empty
  4. 执行 ! envRecord.SetMutableBinding(exportName, exportValue, true)。
  5. 返回 unused

16.2.1.8.4 Module Record 抽象方法的实现

以下是 Synthetic Module Record 的具体方法,它们实现 Table 40 中定义的相应 Module Record 抽象方法。

16.2.1.8.4.1 LoadRequestedModules ( [ hostDefined ] )

The LoadRequestedModules concrete method of a Synthetic Module Record module takes optional argument hostDefined (anything) and returns a Promise. It performs the following steps when called:

  1. 注:此 LoadRequestedModules 的实现不使用 hostDefined
  2. 返回 ! PromiseResolve(%Promise%, undefined)。
Note
Synthetic Module Record 没有依赖项。

16.2.1.8.4.2 GetExportedNames ( [ exportStarSet ] )

The GetExportedNames concrete method of a Synthetic Module Record module takes optional argument exportStarSet (a List of Source Text Module Records) and returns a List of Strings. It performs the following steps when called:

  1. 注:此 GetExportedNames 的实现不使用 exportStarSet
  2. 返回 module.[[ExportNames]]

16.2.1.8.4.3 ResolveExport ( exportName [ , resolveSet ] )

The ResolveExport concrete method of a Synthetic Module Record module takes argument exportName (a String) and optional argument resolveSet (a List of Records with fields [[Module]] (a Module Record) and [[ExportName]] (a String)) and returns a ResolvedBinding Record, null, or ambiguous. It performs the following steps when called:

  1. 注:此 ResolveExport 的实现不使用 resolveSet
  2. 如果 module.[[ExportNames]]包含 exportName,则返回 null
  3. 返回 ResolvedBinding Record { [[Module]]: module, [[BindingName]]: exportName }。

16.2.1.8.4.4 Link ( )

The Link concrete method of a Synthetic Module Record module takes no arguments and returns a normal completion containing unused. It performs the following steps when called:

  1. realmmodule.[[Realm]]
  2. envRecordNewModuleEnvironment(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 ( )

The Evaluate concrete method of a Synthetic Module Record module takes no arguments and returns a Promise. It performs the following steps when called:

  1. moduleContext 为新的 ECMAScript 代码执行上下文
  2. moduleContext 的 Function 设置为 null
  3. moduleContextRealm 设置为 module.[[Realm]]
  4. moduleContext 的 ScriptOrModule 设置为 module
  5. moduleContext 的 VariableEnvironment 设置为 module.[[Environment]]
  6. moduleContext 的 LexicalEnvironment 设置为 module.[[Environment]]
  7. 挂起运行中的执行上下文。
  8. moduleContext 压入执行上下文栈;moduleContext 现在是运行中的执行上下文。
  9. stepsmodule.[[EvaluationSteps]]
  10. resultCompletion(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 )

The abstract operation GetImportedModule takes arguments referrer (a Cyclic Module Record) and request (a ModuleRequest Record) and returns a Module Record. It performs the following steps when called:

  1. records 为一个 List,它由 referrer.[[LoadedModules]] 的每个 LoadedModuleRequest Record r 组成,且 ModuleRequestsEqual(r, request) 是 true
  2. 断言:records 恰好有一个元素,因为在调用此抽象操作之前,LoadRequestedModules 已经在 referrer 上成功完成。
  3. recordrecords 的唯一元素。
  4. 返回 record.[[Module]]

16.2.1.10 HostLoadImportedModule ( referrer, moduleRequest, hostDefined, payload )

The host-defined abstract operation HostLoadImportedModule takes arguments referrer (a Script Record, a Cyclic Module Record, or a Realm Record), moduleRequest (a ModuleRequest Record), hostDefined (anything), and payload (a GraphLoadingState Record or a PromiseCapability Record) and returns unused.

Note 1

referrer 可以是 Realm Record 的一个示例是在 Web 浏览器宿主中。在那里,如果用户点击由以下内容给出的控件

<button type="button" onclick="import('./foo.mjs')">Click me</button>

则在 import() 表达式运行时,将没有活动脚本或模块。更一般地说,这可能发生在宿主把 ScriptOrModule 组件为 null 的执行上下文压入执行上下文栈的任何情况下。

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

实际执行的过程由宿主定义,但通常包括执行加载相应 Module Record 所需的任何 I/O 操作。多个不同的 (referrer, moduleRequest.[[Specifier]], moduleRequest.[[Attributes]]) 三元组可以映射到同一个 Module Record 实例。实际映射语义由宿主定义,但通常会把规范化过程作为映射过程的一部分应用于 specifier。典型的规范化过程会包括展开相对路径和缩略路径说明符等动作。

Note 2

上述文本要求宿主在用 type: "json" 导入 JSON 模块时支持 JSON 模块(并且 HostLoadImportedModule 正常完成),但它不禁止宿主在未用 type: "json" 导入时支持 JSON 模块。

16.2.1.11 FinishLoadingImportedModule ( referrer, moduleRequest, payload, result )

The abstract operation FinishLoadingImportedModule takes arguments referrer (a Script Record, a Cyclic Module Record, or a Realm Record), moduleRequest (a ModuleRequest Record), payload (a GraphLoadingState Record or a PromiseCapability Record), and result (either a normal completion containing a Module Record or a throw completion) and returns unused. It performs the following steps when called:

  1. 如果 result 是 normal completion,则
    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. 如果 payloadGraphLoadingState Record,则
    1. 执行 ContinueModuleLoading(payload, result)。
  3. 否则,
    1. 执行 ContinueDynamicImport(payload, result)。
  4. 返回 unused

16.2.1.12 AllImportAttributesSupported ( attrs )

The abstract operation AllImportAttributesSupported takes argument attrs (a List of ImportAttribute Records) and returns a Boolean. It performs the following steps when called:

  1. supportedHostGetSupportedImportAttributes()。
  2. attrs 的每个 ImportAttribute Record attr,执行:
    1. 如果 supported包含 attr.[[Key]],则返回 false
  3. 返回 true

16.2.1.12.1 HostGetSupportedImportAttributes ( )

The host-defined abstract operation HostGetSupportedImportAttributes takes no arguments and returns a List of Strings. 它允许宿主环境指定它们支持哪些导入属性。只有带有受支持键的属性才会提供给宿主

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

  • 它必须返回一个 Strings 的 List,每个 String 表示一个受支持属性。
  • 每次调用此操作时,它都必须返回具有相同内容和相同顺序的同一个 List

HostGetSupportedImportAttributes 的默认实现是返回新的空 List

Note
要求宿主指定其支持的导入属性,而不是把所有属性传给宿主然后让宿主选择想处理哪些属性,其目的是确保在不同宿主中以一致方式处理不受支持的属性。

16.2.1.13 GetModuleNamespace ( module )

The abstract operation GetModuleNamespace takes argument module (an instance of a concrete subclass of Module Record) and returns a Module Namespace Object. 它取得表示 module 导出的 Module Namespace Object,在首次请求时惰性创建它,并将其存储在 module.[[Namespace]] 中以供将来取得。 It performs the following steps when called:

  1. 断言:如果 moduleCyclic Module Record,则 module.[[Status]] 不是 newunlinked
  2. namespacemodule.[[Namespace]]
  3. 如果 namespaceempty,则
    1. exportedNamesmodule.GetExportedNames()。
    2. unambiguousNames 为新的空 List
    3. exportedNames 的每个元素 name,执行:
      1. resolutionmodule.ResolveExport(name)。
      2. 如果 resolutionResolvedBinding Record,则将 name 追加到 unambiguousNames
    4. namespace 设置为 ModuleNamespaceCreate(module, unambiguousNames)。
  4. 返回 namespace
Note

GetModuleNamespace 永远不会抛出。相反,无法解析的名称只是在此时从 namespace 中排除。它们稍后会导致真正的链接错误,除非它们全都是未在任何地方被显式请求的 ambiguous 星号导出。

16.2.1.14 Runtime Semantics: Evaluation

Module : [empty]
  1. 返回 undefined
ModuleBody : ModuleItemList
  1. resultCompletion(ModuleItemListEvaluation)。
  2. 如果 result 是 normal completion 且 result.[[Value]]empty,则
    1. 返回 undefined
  3. 返回 ? result
ModuleItemList : ModuleItemList ModuleItem
  1. sl 为 ? ModuleItemListEvaluation
  2. sCompletion(ModuleItemEvaluation)。
  3. 返回 ? UpdateEmpty(s, sl)。
Note

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 } { ImportsList , } 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

The syntax-directed operation ImportEntries takes no arguments and returns a List of ImportEntry Records. It is defined piecewise over the following productions:

Module : [empty]
  1. 返回新的空 List
ModuleItemList : ModuleItemList ModuleItem
  1. entries1ModuleItemListImportEntries
  2. entries2ModuleItemImportEntries
  3. 返回 entries1entries2列表连接
ModuleItem : ExportDeclaration StatementListItem
  1. 返回新的空 List
ImportDeclaration : import ImportClause FromClause WithClauseopt ;
  1. moduleImportDeclarationModuleRequests 的唯一元素。
  2. 返回以 module 为实参执行 ImportClauseImportEntriesForModule
ImportDeclaration : import ModuleSpecifier WithClauseopt ;
  1. 返回新的空 List

16.2.2.3 Static Semantics: ImportEntriesForModule

The syntax-directed operation ImportEntriesForModule takes argument module (a ModuleRequest Record) and returns a List of ImportEntry Records. It is defined piecewise over the following productions:

ImportClause : ImportedDefaultBinding , NameSpaceImport
  1. entries1 为以 module 为实参执行 ImportedDefaultBindingImportEntriesForModule
  2. entries2 为以 module 为实参执行 NameSpaceImportImportEntriesForModule
  3. 返回 entries1entries2列表连接
ImportClause : ImportedDefaultBinding , NamedImports
  1. entries1 为以 module 为实参执行 ImportedDefaultBindingImportEntriesForModule
  2. entries2 为以 module 为实参执行 NamedImportsImportEntriesForModule
  3. 返回 entries1entries2列表连接
ImportedDefaultBinding : ImportedBinding
  1. localNameImportedBindingBoundNames 的唯一元素。
  2. defaultEntryImportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: "default", [[LocalName]]: localName }。
  3. 返回 « defaultEntry »。
NameSpaceImport : * as ImportedBinding
  1. localNameImportedBindingStringValue
  2. entryImportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: namespace, [[LocalName]]: localName }。
  3. 返回 « entry »。
NamedImports : { }
  1. 返回新的空 List
ImportsList : ImportsList , ImportSpecifier
  1. specs1 为以 module 为实参执行 ImportsListImportEntriesForModule
  2. specs2 为以 module 为实参执行 ImportSpecifierImportEntriesForModule
  3. 返回 specs1specs2列表连接
ImportSpecifier : ImportedBinding
  1. localNameImportedBindingBoundNames 的唯一元素。
  2. entryImportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: localName, [[LocalName]]: localName }。
  3. 返回 « entry »。
ImportSpecifier : ModuleExportName as ImportedBinding
  1. importNameModuleExportNameStringValue
  2. localNameImportedBindingStringValue
  3. entryImportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: importName, [[LocalName]]: localName }。
  4. 返回 « entry »。

16.2.2.4 Static Semantics: WithClauseToAttributes

The syntax-directed operation WithClauseToAttributes takes no arguments and returns a List of ImportAttribute Records. It is defined piecewise over the following productions:

WithClause : with { }
  1. 返回新的空 List
WithClause : with { WithEntries ,opt }
  1. attrsWithEntriesWithClauseToAttributes
  2. 根据 attrs[[Key]] 字段的字典序对 attrs 排序,把每个此类字段的值视为 UTF-16 码元值序列。注:此排序唯一可观察之处在于,宿主被禁止基于枚举属性的顺序来改变行为。
  3. 返回 attrs
WithEntries : AttributeKey : StringLiteral
  1. keyAttributeKeyPropName
  2. entryImportAttribute Record { [[Key]]: key, [[Value]]: StringLiteralSV }。
  3. 返回 « entry »。
WithEntries : AttributeKey : StringLiteral , WithEntries
  1. keyAttributeKeyPropName
  2. entryImportAttribute Record { [[Key]]: key, [[Value]]: StringLiteralSV }。
  3. restWithEntriesWithClauseToAttributes
  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 } { ExportsList , } ExportsList : ExportSpecifier ExportsList , ExportSpecifier ExportSpecifier : ModuleExportName ModuleExportName as ModuleExportName

16.2.3.1 Static Semantics: 早期错误

ExportDeclaration : export NamedExports ; Note

上述规则意味着 NamedExports 的每个 ReferencedBindings 都会被视为 IdentifierReference

16.2.3.2 Static Semantics: ExportedBindings

The syntax-directed operation ExportedBindings takes no arguments and returns a List of Strings.

Note

ExportedBindings 是与 ModuleExportedNames 显式关联的本地绑定名称。

It is defined piecewise over the following productions:

ModuleItemList : ModuleItemList ModuleItem
  1. names1ModuleItemListExportedBindings
  2. names2ModuleItemExportedBindings
  3. 返回 names1names2列表连接
ModuleItem : ImportDeclaration StatementListItem
  1. 返回新的空 List
ExportDeclaration : export ExportFromClause FromClause WithClauseopt ;
  1. 返回新的空 List
ExportDeclaration : export NamedExports ;
  1. 返回 NamedExportsExportedBindings
ExportDeclaration : export VariableStatement
  1. 返回 VariableStatementBoundNames
ExportDeclaration : export Declaration
  1. 返回 DeclarationBoundNames
ExportDeclaration : export default HoistableDeclaration export default ClassDeclaration export default AssignmentExpression ;
  1. 返回此 ExportDeclarationBoundNames
NamedExports : { }
  1. 返回新的空 List
ExportsList : ExportsList , ExportSpecifier
  1. names1ExportsListExportedBindings
  2. names2ExportSpecifierExportedBindings
  3. 返回 names1names2列表连接
ExportSpecifier : ModuleExportName
  1. 返回一个 List,其唯一元素为 ModuleExportNameStringValue
ExportSpecifier : ModuleExportName as ModuleExportName
  1. 返回一个 List,其唯一元素为第一个 ModuleExportNameStringValue

16.2.3.3 Static Semantics: ExportedNames

The syntax-directed operation ExportedNames takes no arguments and returns a List of Strings.

Note

ExportedNames 是外部可见名称,Module 会显式地将其映射到自己的某个本地名称绑定。

It is defined piecewise over the following productions:

ModuleItemList : ModuleItemList ModuleItem
  1. names1ModuleItemListExportedNames
  2. names2ModuleItemExportedNames
  3. 返回 names1names2列表连接
ModuleItem : ExportDeclaration
  1. 返回 ExportDeclarationExportedNames
ModuleItem : ImportDeclaration StatementListItem
  1. 返回新的空 List
ExportDeclaration : export ExportFromClause FromClause WithClauseopt ;
  1. 返回 ExportFromClauseExportedNames
ExportFromClause : *
  1. 返回新的空 List
ExportFromClause : * as ModuleExportName
  1. 返回一个 List,其唯一元素为 ModuleExportNameStringValue
ExportFromClause : NamedExports
  1. 返回 NamedExportsExportedNames
ExportDeclaration : export VariableStatement
  1. 返回 VariableStatementBoundNames
ExportDeclaration : export Declaration
  1. 返回 DeclarationBoundNames
ExportDeclaration : export default HoistableDeclaration export default ClassDeclaration export default AssignmentExpression ;
  1. 返回 « "default" »。
NamedExports : { }
  1. 返回新的空 List
ExportsList : ExportsList , ExportSpecifier
  1. names1ExportsListExportedNames
  2. names2ExportSpecifierExportedNames
  3. 返回 names1names2列表连接
ExportSpecifier : ModuleExportName
  1. 返回一个 List,其唯一元素为 ModuleExportNameStringValue
ExportSpecifier : ModuleExportName as ModuleExportName
  1. 返回一个 List,其唯一元素为第二个 ModuleExportNameStringValue

16.2.3.4 Static Semantics: ExportEntries

The syntax-directed operation ExportEntries takes no arguments and returns a List of ExportEntry Records. It is defined piecewise over the following productions:

Module : [empty]
  1. 返回新的空 List
ModuleItemList : ModuleItemList ModuleItem
  1. entries1ModuleItemListExportEntries
  2. entries2ModuleItemExportEntries
  3. 返回 entries1entries2列表连接
ModuleItem : ImportDeclaration StatementListItem
  1. 返回新的空 List
ExportDeclaration : export ExportFromClause FromClause WithClauseopt ;
  1. moduleExportDeclarationModuleRequests 的唯一元素。
  2. 返回以 module 为实参执行 ExportFromClauseExportEntriesForModule
ExportDeclaration : export NamedExports ;
  1. 返回以 null 为实参执行 NamedExportsExportEntriesForModule
ExportDeclaration : export VariableStatement
  1. entries 为新的空 List
  2. namesVariableStatementBoundNames
  3. names 的每个元素 name,执行:
    1. ExportEntry Record { [[ModuleRequest]]: null, [[ImportName]]: null, [[LocalName]]: name, [[ExportName]]: name } 追加到 entries
  4. 返回 entries
ExportDeclaration : export Declaration
  1. entries 为新的空 List
  2. namesDeclarationBoundNames
  3. names 的每个元素 name,执行:
    1. ExportEntry Record { [[ModuleRequest]]: null, [[ImportName]]: null, [[LocalName]]: name, [[ExportName]]: name } 追加到 entries
  4. 返回 entries
ExportDeclaration : export default HoistableDeclaration
  1. namesHoistableDeclarationBoundNames
  2. localNamenames 的唯一元素。
  3. 返回一个 List,其唯一元素为新的 ExportEntry Record { [[ModuleRequest]]: null, [[ImportName]]: null, [[LocalName]]: localName, [[ExportName]]: "default" }。
ExportDeclaration : export default ClassDeclaration
  1. namesClassDeclarationBoundNames
  2. localNamenames 的唯一元素。
  3. 返回一个 List,其唯一元素为新的 ExportEntry Record { [[ModuleRequest]]: null, [[ImportName]]: null, [[LocalName]]: localName, [[ExportName]]: "default" }。
ExportDeclaration : export default AssignmentExpression ;
  1. entryExportEntry Record { [[ModuleRequest]]: null, [[ImportName]]: null, [[LocalName]]: "*default*", [[ExportName]]: "default" }。
  2. 返回 « entry »。
Note

"*default*" 在本规范内用作匿名默认导出值的合成名称。更多细节见此注

16.2.3.5 Static Semantics: ExportEntriesForModule

The syntax-directed operation ExportEntriesForModule takes argument module (a ModuleRequest Record or null) and returns a List of ExportEntry Records. It is defined piecewise over the following productions:

ExportFromClause : *
  1. entryExportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: all-but-default, [[LocalName]]: null, [[ExportName]]: null }。
  2. 返回 « entry »。
ExportFromClause : * as ModuleExportName
  1. exportNameModuleExportNameStringValue
  2. entryExportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: namespace, [[LocalName]]: null, [[ExportName]]: exportName }。
  3. 返回 « entry »。
NamedExports : { }
  1. 返回新的空 List
ExportsList : ExportsList , ExportSpecifier
  1. specs1 为以 module 为实参执行 ExportsListExportEntriesForModule
  2. specs2 为以 module 为实参执行 ExportSpecifierExportEntriesForModule
  3. 返回 specs1specs2列表连接
ExportSpecifier : ModuleExportName
  1. sourceNameModuleExportNameStringValue
  2. 如果 modulenull,则
    1. localNamesourceName
    2. importNamenull
  3. 否则,
    1. localNamenull
    2. importNamesourceName
  4. 返回一个 List,其唯一元素为新的 ExportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: importName, [[LocalName]]: localName, [[ExportName]]: sourceName }。
ExportSpecifier : ModuleExportName as ModuleExportName
  1. sourceName 为第一个 ModuleExportNameStringValue
  2. exportName 为第二个 ModuleExportNameStringValue
  3. 如果 modulenull,则
    1. localNamesourceName
    2. importNamenull
  4. 否则,
    1. localNamenull
    2. importNamesourceName
  5. 返回一个 List,其唯一元素为新的 ExportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: importName, [[LocalName]]: localName, [[ExportName]]: exportName }。

16.2.3.6 Static Semantics: ReferencedBindings

The syntax-directed operation ReferencedBindings takes no arguments and returns a List of Parse Nodes. It is defined piecewise over the following productions:

NamedExports : { }
  1. 返回新的空 List
ExportsList : ExportsList , ExportSpecifier
  1. names1ExportsListReferencedBindings
  2. names2ExportSpecifierReferencedBindings
  3. 返回 names1names2列表连接
ExportSpecifier : ModuleExportName as ModuleExportName
  1. 返回第一个 ModuleExportNameReferencedBindings
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. 返回 ? VariableStatementEvaluation
ExportDeclaration : export Declaration
  1. 返回 ? DeclarationEvaluation
ExportDeclaration : export default HoistableDeclaration
  1. 返回 ? HoistableDeclarationEvaluation
ExportDeclaration : export default ClassDeclaration
  1. value 为 ? ClassDeclarationBindingClassDeclarationEvaluation
  2. classNameClassDeclarationBoundNames 的唯一元素。
  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 为 ? AssignmentExpressionEvaluation
    2. value 为 ? GetValue(rhs)。
  3. envRecord 为运行中执行上下文的 LexicalEnvironment。
  4. 执行 ? InitializeBoundName("*default*", value, envRecord)。
  5. 返回 empty

17 错误处理和语言扩展

实现必须在相关 ECMAScript 语言构造被求值时报告大多数错误。早期错误是可以在包含该错误的 Script 中任何构造求值之前被检测并报告的错误。存在早期错误会阻止该构造的求值。实现必须在 ParseScript 中解析该 Script 时,作为解析该 Script 的一部分报告 Script 中的早期错误Module 中的早期错误会在该 Module 将被求值的时刻报告,并且该 Module 永远不会被初始化。eval 代码中的早期错误会在调用 eval 时报告,并阻止该 eval 代码求值。所有不是早期错误的错误都是运行时错误。

实现必须把本规范“Static Semantics: 早期错误”子条款中列出的条件的任何出现报告为早期错误

即使编译器能够证明某个构造在任何情况下都无法不出错地执行,实现也不得把其他种类的错误当作早期错误处理。在这种情况下,实现可以发出早期警告,但在相关构造实际执行之前,不应报告该错误。

实现应按规定报告所有错误,但以下情况除外:

17.1 禁止的扩展

实现不得以下列方式扩展本规范:

18 ECMAScript 标准内置对象

每当 ECMAScript ScriptModule 开始执行时,都有某些内置对象可用。其中一个是全局对象,它是执行程序的全局环境的一部分。其他对象可作为全局对象的初始属性访问,或间接作为可访问内置对象的属性访问。

除非另有规定,可作为函数调用的内置对象是具有 10.3 中所述特性的内置函数对象。除非另有规定,内置对象的 [[Extensible]] 内部槽最初具有值 true。每个内置函数对象都有一个 [[Realm]] 内部槽,其值为该对象最初被创建时所在 realmRealm Record

许多内置对象是函数:它们可以用实参调用。其中一些还同时是构造器:它们是旨在与 new 运算符一起使用的函数。对于每个内置函数,本规范描述该函数所需的实参以及该函数对象的属性。对于每个内置构造器,本规范还描述该构造器的原型对象的属性,以及调用该构造器的 new 表达式所返回的特定对象实例的属性。

除非特定函数的描述中另有规定,如果内置函数或构造器给定的实参数少于规定该函数所需的实参数,则该函数或构造器应表现得完全像已给定足够的附加实参一样,每个此类实参都是 undefined 值。此类缺失实参被认为是“not present”,并且可以在规范算法中以这种方式识别。在特定函数的描述中,术语“this value”和“NewTarget”具有 10.3 中给出的含义。

除非特定函数的描述中另有规定,如果所描述的内置函数或构造器给定的实参数多于规定该函数所允许的实参数,则额外实参会由调用求值,然后被该函数忽略。但是,只要该行为不是仅仅以存在额外实参为前提而抛出 TypeError 异常,实现就可以定义与此类实参相关的实现特定行为。

Note 1

鼓励向内置函数集合添加附加能力的实现通过添加新函数,而不是向现有函数添加新参数来做到这一点。

除非另有规定,每个内置函数和每个内置构造器都具有 Function 原型对象,即表达式 Function.prototype 的初始值(20.2.3),作为其 [[Prototype]] 内部槽的值。

除非另有规定,每个内置原型对象都具有 Object 原型对象,即表达式 Object.prototype 的初始值(20.1.3),作为其 [[Prototype]] 内部槽的值,但 Object 原型对象自身除外。

如果本规范通过算法步骤定义内置构造器的行为,则这就是其在 [[Call]][[Construct]] 两种情况下的行为。如果此类算法需要区分这两种情况,它会检查 NewTarget 是否为 undefined,这表示一次 [[Call]] 调用。

未被识别为构造器的内置函数对象不实现 [[Construct]] 内部方法,除非特定函数的描述中另有规定。

不是构造器的内置函数对象没有 "prototype" 属性,除非特定函数的描述中另有规定。

本规范中定义的每个内置函数都是通过调用 CreateBuiltinFunction 抽象操作10.3.4)创建的。lengthname 参数的值是如下所讨论的 "length""name" 属性的初始值。prefix 参数的值也在下文类似讨论。

每个内置函数对象,包括构造器,都有一个 "length" 属性,其值为非负整数 Number。除非另有规定,此值是函数描述的子条款标题中显示的必需参数数量。可选参数和剩余参数不计入参数计数。

Note 2

例如,作为 Array 原型对象"map" 属性初始值的函数对象,在子条款标题 «Array.prototype.map (callback [ , thisArg])» 下描述,该标题显示两个命名实参 callback 和 thisArg,其中后者是可选的;因此该函数对象"length" 属性值是 1𝔽

除非另有规定,内置函数对象"length" 属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

每个内置函数对象,包括构造器,都有一个 "name" 属性,其值为 String。除非另有规定,此值是在本规范中给出的该函数名称。被识别为匿名函数的函数使用空 String 作为 "name" 属性的值。对于被规定为对象属性的函数,name 值是用于访问该函数的属性名字符串。被规定为内置属性的 get 或 set 访问器函数的函数,在调用 CreateBuiltinFunction 时会分别把 "get""set" 传给 prefix 参数。

对于属性键是 Symbol 值的每个内置函数,其 "name" 属性的值都被显式规定。如果此类显式规定的值以 "get ""set " 前缀开头,且为其规定该值的函数是某个内置属性的 get 或 set 访问器函数,则去掉前缀后的值会传给 name 参数,并且在调用 CreateBuiltinFunction 时,值 "get""set"(分别)会传给 prefix 参数。

除非另有规定,内置函数对象"name" 属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

条款 1928 以及附录 B.2 中描述的每个其他数据属性,都具有特性 { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true },除非另有规定。

条款 1928 以及附录 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 )

The abstract operation PerformEval takes arguments source (an ECMAScript language value), strictCaller (a Boolean), and direct (a Boolean) and returns either a normal completion containing an ECMAScript language value or a throw completion. It performs the following steps when called:

  1. 断言:如果 directfalse,则 strictCaller 也是 false
  2. 如果 source 不是 String,则返回 source
  3. evalRealm当前 Realm Record
  4. 注:在直接 eval 的情况下,evalRealmeval 调用者以及 eval 函数自身的 realm
  5. 执行 ? HostEnsureCanCompileStrings(evalRealm, « », source, direct)。
  6. inFuncfalse
  7. inMethodfalse
  8. inDerivedCtorfalse
  9. inClassFieldInitializerfalse
  10. 如果 directtrue,则
    1. thisEnvRecordGetThisEnvironment()。
    2. 如果 thisEnvRecordFunction Environment Record,则
      1. functhisEnvRecord.[[FunctionObject]]
      2. inFunc 设置为 true
      3. inMethod 设置为 thisEnvRecord.HasSuperBinding()。
      4. 如果 func.[[ConstructorKind]]derived,则将 inDerivedCtor 设置为 true
      5. classFieldInitializerNamefunc.[[ClassFieldInitializerName]]
      6. 如果 classFieldInitializerName 不是 empty,则将 inClassFieldInitializer 设置为 true
  11. 实现定义的顺序执行以下子步骤,可能会交错执行解析和错误检测:
    1. scriptParseText(source, Script)。
    2. 如果 script 是错误列表,则抛出 SyntaxError 异常。
    3. 如果 script Contains ScriptBodyfalse,则返回 undefined
    4. bodyscriptScriptBody
    5. 如果 inFuncfalsebody Contains NewTarget,则抛出 SyntaxError 异常。
    6. 如果 inMethodfalsebody Contains SuperProperty,则抛出 SyntaxError 异常。
    7. 如果 inDerivedCtorfalsebody Contains SuperCall,则抛出 SyntaxError 异常。
    8. 如果 inClassFieldInitializertruebodyContainsArgumentstrue,则抛出 SyntaxError 异常。
  12. 如果 strictCallertrue,则令 strictEvaltrue
  13. 否则,令 strictEvalscriptScriptIsStrict
  14. runningContext 为运行中的执行上下文。
  15. 注:如果 directtrue,则 runningContext 将是执行直接 eval 的执行上下文。如果 directfalse,则 runningContext 将是 eval 函数调用的执行上下文。
  16. 如果 directtrue,则
    1. lexicalEnvNewDeclarativeEnvironment(runningContext 的 LexicalEnvironment)。
    2. variableEnvrunningContext 的 VariableEnvironment。
    3. privateEnvrunningContext 的 PrivateEnvironment。
  17. 否则,
    1. lexicalEnvNewDeclarativeEnvironment(evalRealm.[[GlobalEnv]])。
    2. variableEnvevalRealm.[[GlobalEnv]]
    3. privateEnvnull
  18. 如果 strictEvaltrue,则将 variableEnv 设置为 lexicalEnv
  19. 如果 runningContext 尚未挂起,则挂起 runningContext
  20. evalContext 为新的 ECMAScript 代码执行上下文
  21. evalContext 的 Function 设置为 null
  22. evalContextRealm 设置为 evalRealm
  23. evalContext 的 ScriptOrModule 设置为 runningContext 的 ScriptOrModule。
  24. evalContext 的 VariableEnvironment 设置为 variableEnv
  25. evalContext 的 LexicalEnvironment 设置为 lexicalEnv
  26. evalContext 的 PrivateEnvironment 设置为 privateEnv
  27. evalContext 压入执行上下文栈;evalContext 现在是运行中的执行上下文。
  28. resultCompletion(EvalDeclarationInstantiation(body, variableEnv, lexicalEnv, privateEnv, strictEval))。
  29. 如果 result 是 normal completion,则
    1. result 设置为 Completion(bodyEvaluation)。
  30. 如果 result 是 normal completion 且 result.[[Value]]empty,则
    1. result 设置为 NormalCompletion(undefined)。
  31. 挂起 evalContext 并将其从执行上下文栈中移除。
  32. 恢复当前位于执行上下文栈顶部的上下文作为运行中的执行上下文。
  33. 返回 ? result
Note

如果调用 eval 的调用上下文代码或 eval 代码任一者是严格模式代码,则 eval 代码不能在调用上下文的变量环境中实例化变量或函数绑定。相反,此类绑定会在一个仅对 eval 代码可访问的新 VariableEnvironment 中实例化。由 letconstclass 声明引入的绑定总是在新的 LexicalEnvironment 中实例化。

19.2.1.2 HostEnsureCanCompileStrings ( calleeRealm, paramStrings, bodyString, direct )

The host-defined abstract operation HostEnsureCanCompileStrings takes arguments calleeRealm (a Realm Record), paramStrings (a List of Strings), bodyString (a String), and direct (a Boolean) and returns either a normal completion containing unused or a throw completion. 它允许宿主环境阻止某些允许开发者把字符串解释并求值为 ECMAScript 代码的 ECMAScript 函数。

paramStrings 表示在使用某个函数构造器时,会被连接在一起以构建参数列表的字符串。bodyString 表示函数体,或传给 eval 调用的字符串。 direct 表示该求值是否为直接 eval。

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

19.2.1.3 EvalDeclarationInstantiation ( body, variableEnv, lexicalEnv, privateEnv, strict )

The abstract operation EvalDeclarationInstantiation takes arguments body (a ScriptBody Parse Node), variableEnv (an Environment Record), lexicalEnv (a Declarative Environment Record), privateEnv (a PrivateEnvironment Record or null), and strict (a Boolean) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

  1. variableNamesbodyVarDeclaredNames
  2. variableDeclsbodyVarScopedDeclarations
  3. 如果 strictfalse,则
    1. 如果 variableEnv 是一个 Global Environment Record,则
      1. variableNames 的每个元素 name,执行:
        1. 如果 HasLexicalDeclaration(variableEnv, name) 为 true,则抛出一个 SyntaxError 异常。
        2. 注:eval 不会创建会被全局词法声明遮蔽的全局 var 声明。
    2. thisEnvlexicalEnv
    3. 断言:以下循环将会终止。
    4. 重复,直到 thisEnvvariableEnv 是同一个 Environment Record
      1. 如果 thisEnv 不是 Object Environment Record,则
        1. 注:with 语句的环境不能包含任何词法声明,因此不需要检查 var/let 提升冲突。
        2. variableNames 的每个元素 name,执行:
          1. 如果 ! thisEnv.HasBinding(name) 为 true,则
            1. 如果宿主是 Web 浏览器,或以其他方式支持 Catch 块中的 VariableStatement,则
              1. 如果 thisEnv 不是 Catch 子句的 Environment Record,则抛出一个 SyntaxError 异常。
            2. 否则,
              1. 抛出一个 SyntaxError 异常。
          2. 注:直接 eval 不会把 var 声明提升到同名词法声明之上。
      2. thisEnv 设为 thisEnv.[[OuterEnv]]
  4. privateIdentifiers 为一个新的空 List
  5. pointerprivateEnv
  6. 重复,直到 pointernull
    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. variableDecls 的每个元素 variableDecl,按 List 的逆序执行:
    1. 如果 variableDecl 不是 VariableDeclarationForBindingBindingIdentifier 中的任一者,则
      1. 断言:variableDeclFunctionDeclarationGeneratorDeclarationAsyncFunctionDeclarationAsyncGeneratorDeclaration
      2. 注:如果同一名称有多个函数声明,则使用最后一个声明。
      3. funcNamevariableDeclBoundNames 的唯一元素。
      4. 如果 declaredFuncNames包含 funcName,则
        1. 如果 variableEnv 是一个 Global Environment Record,则
          1. funcDefinable 为 ? CanDeclareGlobalFunction(variableEnv, funcName)。
          2. 如果 funcDefinablefalse,则抛出一个 TypeError 异常。
        2. funcName 追加到 declaredFuncNames
        3. variableDecl 作为 funcsToInitialize 的第一个元素插入。
  11. declaredVariableNames 为一个新的空 List
  12. variableDecls 的每个元素 variableDecl,执行:
    1. 如果 variableDeclVariableDeclarationForBindingBindingIdentifier 中的任一者,则
      1. variableDeclBoundNames 的每个 String name,执行:
        1. 如果 declaredFuncNames包含 name,则
          1. 如果 variableEnv 是一个 Global Environment Record,则
            1. variableDefinable 为 ? CanDeclareGlobalVar(variableEnv, name)。
            2. 如果 variableDefinablefalse,则抛出一个 TypeError 异常。
          2. 如果 declaredVariableNames包含 name,则
            1. name 追加到 declaredVariableNames
  13. 如果 strictfalse,且宿主是 Web 浏览器,或以其他方式支持 块级函数声明的 Web 遗留兼容性语义,则
    1. declaredFuncOrVariableNamesdeclaredFuncNamesdeclaredVariableNames列表连接
    2. 对每个 FunctionDeclaration funcDecl,其直接包含在任何 BlockCaseClauseDefaultClause xStatementList 中,且 body Contains xtrue,执行:
      1. funcNamefuncDeclBindingIdentifierStringValue
      2. 如果将 FunctionDeclaration funcDecl 替换为以 funcName 作为 BindingIdentifierVariableStatement 不会为 body 产生任何早期错误,则
        1. bindingExistsfalse
        2. thisEnv 设为 lexicalEnv
        3. 断言:以下循环将会终止。
        4. 重复,直到 thisEnvvariableEnv
          1. 如果 thisEnv 不是 Object Environment Record,则
            1. 如果 ! thisEnv.HasBinding(funcName) 为 true,则
              1. 如果宿主是 Web 浏览器,或以其他方式支持 Catch 块中的 VariableStatement,则
                1. 如果 thisEnv 不是 Catch 子句的 Environment Record,则将 bindingExists 设为 true
              2. 否则,
                1. bindingExists 设为 true
          2. thisEnv 设为 thisEnv.[[OuterEnv]]
        5. 如果 bindingExistsfalsevariableEnv 是一个 Global Environment Record,则
          1. 如果 HasLexicalDeclaration(variableEnv, funcName) 为 false,则
            1. funcDefinable 为 ? CanDeclareGlobalVar(variableEnv, funcName)。
          2. 否则,
            1. funcDefinablefalse
        6. 否则,
          1. funcDefinabletrue
        7. 如果 bindingExistsfalsefuncDefinabletrue,则
          1. 如果 declaredFuncOrVariableNames包含 funcName,则
            1. 如果 variableEnv 是一个 Global Environment Record,则
              1. 执行 ? CreateGlobalVarBinding(variableEnv, funcName, true)。
            2. 否则,
              1. bindingExists 设为 ! variableEnv.HasBinding(funcName)。
              2. 如果 bindingExistsfalse,则
                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. 注:除非 variableEnvGlobal Environment Record全局对象Proxy 异质对象,否则在此算法步骤之后不会发生异常终止。
  15. lexicalDeclsbodyLexicallyScopedDeclarations
  16. lexicalDecls 的每个元素 lexicalDecl,执行:
    1. 注:词法声明的名称仅在此处实例化,但不初始化。
    2. lexicalDeclBoundNames 的每个元素 name,执行:
      1. 如果 lexicalDeclIsConstantDeclarationtrue,则
        1. 执行 ? lexicalEnv.CreateImmutableBinding(name, true)。
      2. 否则,
        1. 执行 ? lexicalEnv.CreateMutableBinding(name, false)。
  17. funcsToInitialize 的每个 Parse Node funcDecl,执行:
    1. funcNamefuncDeclBoundNames 的唯一元素。
    2. funcObj 为使用参数 lexicalEnvprivateEnvfuncDecl 执行 InstantiateFunctionObject 的结果。
    3. 如果 variableEnv 是一个 Global Environment Record,则
      1. 执行 ? CreateGlobalFunctionBinding(variableEnv, funcName, funcObj, true)。
    4. 否则,
      1. bindingExists 为 ! variableEnv.HasBinding(funcName)。
      2. 如果 bindingExistsfalse,则
        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. 如果 bindingExistsfalse,则
        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有限的,则返回 true
  3. 返回 false

19.2.3 isNaN ( value )

此函数是 %isNaN% 内在对象。

它在被调用时执行以下步骤:

  1. number 为 ? ToNumber(value)。
  2. 如果 numberNaN,则返回 true
  3. 返回 false
Note

ECMAScript 代码测试值 X 是否为 NaN 的一种可靠方式,是形如 X !== X 的表达式。当且仅当 XNaN 时,其结果才会是 true

19.2.4 parseFloat ( string )

此函数通过把 string 实参的内容解释为十进制字面量来产生一个 Number 值

它是 %parseFloat% 内在对象。

它在被调用时执行以下步骤:

  1. inputString 为 ? ToString(string)。
  2. trimmedString 为 ! TrimString(inputString, start)。
  3. trimmedStringToCodePoints(trimmedString)。
  4. trimmedPrefixtrimmed 中满足 StrDecimalLiteral 语法的最长前缀,它可以是 trimmed 自身。如果不存在这样的前缀,则返回 NaN
  5. parsedNumberParseText(trimmedPrefix, StrDecimalLiteral)。
  6. 断言:parsedNumberParse Node
  7. 返回 parsedNumberStringNumericValue
Note

此函数可能只把 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. trimmedString 为 ! TrimString(inputString, start)。
  3. sign 为 1。
  4. 如果 trimmedString 不为空且 trimmedString 的第一个码元是码元 0x002D(HYPHEN-MINUS),则将 sign 设置为 -1。
  5. 如果 trimmedString 不为空且 trimmedString 的第一个码元是码元 0x002B(PLUS SIGN)或码元 0x002D(HYPHEN-MINUS),则将 trimmedString 设置为 trimmedString 从索引 1 开始的子字符串
  6. radixMV(? ToInt32(radix))。
  7. stripPrefixtrue
  8. 如果 radixMV ≠ 0,则
    1. 如果 radixMV < 2 或 radixMV > 36,则返回 NaN
    2. 如果 radixMV ≠ 16,则将 stripPrefix 设置为 false
  9. 否则,
    1. radixMV 设置为 10。
  10. 如果 stripPrefixtrue,则
    1. 如果 trimmedString 的长度 ≥ 2 且 trimmedString 的前两个码元是 "0x""0X",则
      1. trimmedString 设置为 trimmedString 从索引 2 开始的子字符串
      2. radixMV 设置为 16。
  11. 如果 trimmedString 包含不是 radix-radixMV 数字的码元,则令 endtrimmedString 中第一个此类码元的索引;否则令 endtrimmedString 的长度。
  12. numberStringtrimmedString 从 0 到 end子字符串
  13. 如果 numberString 为空,则返回 NaN
  14. mathIntnumberString 以 radix-radixMV 记号表示的整数值,使用字母 AZ 以及 az 表示值为 10 到 35 的数字。(但是,如果 radixMV = 10 且 numberString 包含超过 20 个有效数字,则实现可以选择把第 20 个之后的每个有效数字替换为 0 数字;并且如果 radixMV 不是 2、4、8、10、16 或 32 之一,则 mathInt 可以是表示 numberString 以 radix-radixMV 记号所表示整数值的实现近似整数。)
  15. 如果 mathInt = 0,则
    1. 如果 sign = -1,则返回 -0𝔽
    2. 返回 +0𝔽
  16. 返回 𝔽(sign × mathInt)。
Note

此函数可能只把 string 的前导部分解释为整数值;它会忽略任何不能解释为整数记号一部分的码元,并且不会给出任何此类码元已被忽略的指示。

19.2.6 URI 处理函数

统一资源标识符(Uniform Resource Identifiers,URI)是标识资源(例如网页或文件)以及在 Internet 上访问这些资源所用传输协议(例如 HTTP 或 FTP)的 String。除了本节所述用于编码和解码 URI 的函数外,ECMAScript 语言自身不提供任何使用 URI 的支持。encodeURIdecodeURI 旨在处理完整 URI;它们假定任何保留字符都意图具有特殊含义(例如作为分隔符),因此不会编码它们。encodeURIComponentdecodeURIComponent 旨在处理 URI 的各个组成部分;它们假定任何保留字符都表示文本,并且当该组成部分作为完整 URI 的一部分时,为避免特殊含义必须对其编码。

Note 1

保留字符集合基于 RFC 2396,并不反映较新的 RFC 3986 引入的变更。

Note 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 )

The abstract operation Encode takes arguments string (a String) and extraUnescaped (a String) and returns either a normal completion containing a String or a throw completion. 它执行 URI 编码和转义,将 string 解释为 6.1.4 中所述的 UTF-16 编码码点序列。如果某个字符在 RFC 2396 中被标识为非保留字符,或出现在 extraUnescaped 中,则不会被转义。 It performs the following steps when called:

  1. lengthstring 的长度。
  2. result 为空 String。
  3. alwaysUnescapedASCII 单词字符"-.!~*'()"字符串连接
  4. unescapedSetalwaysUnescapedextraUnescaped字符串连接
  5. k 为 0。
  6. 重复,只要 k < length
    1. codeUnitstring 中索引 k 处的码元。
    2. 如果 unescapedSet 包含 codeUnit,则
      1. k 设置为 k + 1。
      2. result 设置为 resultcodeUnit字符串连接
    3. 否则,
      1. codePointCodePointAt(string, k)。
      2. 如果 codePoint.[[IsUnpairedSurrogate]]true,则抛出 URIError 异常。
      3. k 设置为 k + codePoint.[[CodeUnitCount]]
      4. octets 为对 codePoint.[[CodePoint]] 应用 UTF-8 转换所得的八位字节 List
      5. octets 的每个元素 octet,执行:
        1. hexoctet 的 String 表示,格式化为大写十六进制数。
        2. result 设置为 result"%"StringPad(hex, 2, "0", start) 的字符串连接
  7. 返回 result
Note

由于百分号编码用于表示单个八位字节,一个码点可以表示为多个连续转义序列(其 8 位 UTF-8 码元各一个)。

19.2.6.6 Decode ( string, preserveEscapeSet )

The abstract operation Decode takes arguments string (a String) and preserveEscapeSet (a String) and returns either a normal completion containing a String or a throw completion. 它执行 URI 反转义和解码,并保留与 preserveEscapeSet 中的基本拉丁字符对应的任何转义序列。 It performs the following steps when called:

  1. lengthstring 的长度。
  2. result 为空 String。
  3. k 为 0。
  4. 重复,只要 k < length
    1. codeUnitstring 中索引 k 处的码元。
    2. segmentcodeUnit
    3. 如果 codeUnit 是码元 0x0025(PERCENT SIGN),则
      1. 如果 k + 3 > length,则抛出 URIError 异常。
      2. escapestringkk + 3 的子字符串
      3. firstOctetParseHexOctet(string, k + 1)。
      4. 如果 firstOctet 不是整数,则抛出 URIError 异常。
      5. k 设置为 k + 2。
      6. nfirstOctet 中前导 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. continuationByteParseHexOctet(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 设置为 resultsegment字符串连接
    5. k 设置为 k + 1。
  5. 返回 result
Note

RFC 3629 禁止解码无效的 UTF-8 八位字节序列。例如,无效序列 0xC0 0x80 不得解码为码元 0x0000。Decode 算法的实现遇到此类无效序列时必须抛出 URIError

19.2.6.7 ParseHexOctet ( string, position )

The abstract operation ParseHexOctet takes arguments string (a String) and position (a non-negative integer) and returns either a non-negative integer or a non-empty List of SyntaxError objects. 它把 string 中指定 position 处的两个十六进制字符序列解析为无符号 8 位整数。 It performs the following steps when called:

  1. lengthstring 的长度。
  2. 断言:position + 2 ≤ length
  3. hexDigitsstringpositionposition + 2 的子字符串
  4. parseResultParseText(hexDigits, HexDigits[~Sep])。
  5. 如果 parseResult 不是 Parse Node,则返回 parseResult
  6. nparseResult 的 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 构造器:

  • %Object%
  • 全局对象"Object" 属性的初始值。
  • 在作为构造器调用时创建一个新的普通对象
  • 在作为函数而非构造器调用时执行类型转换。
  • 可以用作类定义的 extends 子句的值。

20.1.1.1 Object ( value )

此函数在被调用时执行以下步骤:

  1. 如果 NewTarget 既不是 undefined,也不是活动函数对象,则
    1. 返回 ? OrdinaryCreateFromConstructor(NewTarget, "%Object.prototype%")。
  2. 如果 valueundefinednull,则返回 OrdinaryObjectCreate(%Object.prototype%)。
  3. 返回 ! ToObject(value)。

20.1.2 Object 构造器的属性

Object 构造器:

  • 具有一个 [[Prototype]] 内部槽,其值为 %Function.prototype%
  • 具有以下附加属性:

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 不是 undefinedpropertyDesc.[[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. objOrdinaryObjectCreate(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 )

The abstract operation ObjectDefineProperties takes arguments obj (an Object) and properties (an ECMAScript language value) and returns either a normal completion containing an Object or a throw completion. It performs the following steps when called:

  1. properties 设置为 ? ToObject(properties)。
  2. keys 为 ? properties.[[OwnPropertyKeys]]()
  3. propertyDescs 为新的空 List
  4. keys 的每个元素 nextKey,执行:
    1. currentPropertyDesc 为 ? properties.[[GetOwnProperty]](nextKey)
    2. 如果 currentPropertyDesc 不是 undefinedcurrentPropertyDesc.[[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. 如果 statusfalse,则抛出 TypeError 异常。
  4. 返回 obj

20.1.2.7 Object.fromEntries ( iterable )

此函数在被调用时执行以下步骤:

  1. 执行 ? RequireObjectCoercible(iterable)。
  2. objOrdinaryObjectCreate(%Object.prototype%)。
  3. 断言:obj 是一个可扩展、没有自身属性的普通对象
  4. closure 为一个新的 Abstract Closure,它具有参数 (key, value)、捕获 obj,并在被调用时执行以下步骤:
    1. propertyKey 为 ? ToPropertyKey(key)。
    2. 执行 ! CreateDataPropertyOrThrow(obj, propertyKey, value)。
    3. 返回 NormalCompletion(undefined)。
  5. adderCreateBuiltinFunction(closure, 2, "", « »)。
  6. 返回 ? AddEntriesFromIterable(obj, iterable, adder)。
Note
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. descsOrdinaryObjectCreate(%Object.prototype%)。
  4. ownKeys 的每个元素 key,执行:
    1. propertyDesc 为 ? coerced.[[GetOwnProperty]](key)
    2. propertyDescObjFromPropertyDescriptor(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 )

The abstract operation GetOwnPropertyKeys takes arguments value (an ECMAScript language value) and type (string or symbol) and returns either a normal completion containing a List of property keys or a throw completion. It performs the following steps when called:

  1. obj 为 ? ToObject(value)。
  2. keys 为 ? obj.[[OwnPropertyKeys]]()
  3. nameList 为新的空 List
  4. keys 的每个元素 nextKey,执行:
    1. 如果 nextKey 是 Symbol 且 typesymbol,或如果 nextKey 是 String 且 typestring,则
      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 )

Note

callback 应该是一个接受两个实参的函数。groupBy 会按升序对 items 中的每个元素调用一次 callback,并构造一个新对象。callback 返回的每个值都会被强制转换为属性键。对于每个这样的属性键,结果对象都有一个属性,其键为该属性键,其值为一个数组,包含 callback 返回值强制转换为该键的所有元素。

callback 会带两个实参调用:元素的值和元素的索引。

groupBy 的返回值是一个不继承自 %Object.prototype% 的对象。

此函数在被调用时执行以下步骤:

  1. groups 为 ? GroupBy(items, callback, property)。
  2. objOrdinaryObjectCreate(null)。
  3. groups 的每个 Record { [[Key]], [[Elements]] } group,执行:
    1. elementsCreateArrayFromList(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. 如果 statusfalse,则抛出 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. 如果 statusfalse,则抛出 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. 如果 statusfalse,则抛出 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)。
Note

步骤 12 的顺序被选择为确保,即使 this value 是 undefinednull,本规范先前版本中本应由步骤 1 抛出的任何异常也会继续被抛出。

20.1.3.3 Object.prototype.isPrototypeOf ( value )

此方法在被调用时执行以下步骤:

  1. 如果 value 不是 Object,则返回 false
  2. obj 为 ? ToObject(this value)。
  3. 重复,
    1. value 设置为 ? value.[[GetPrototypeOf]]()
    2. 如果 valuenull,则返回 false
    3. 如果 SameValue(obj, value) 是 true,则返回 true
Note

步骤 12 的顺序,保留了本规范先前版本为 value 不是对象且 this value 是 undefinednull 的情况所规定的行为。

20.1.3.4 Object.prototype.propertyIsEnumerable ( value )

此方法在被调用时执行以下步骤:

  1. propertyKey 为 ? ToPropertyKey(value)。
  2. obj 为 ? ToObject(this value)。
  3. propertyDesc 为 ? obj.[[GetOwnProperty]](propertyKey)
  4. 如果 propertyDescundefined,则返回 false
  5. 返回 propertyDesc.[[Enumerable]]
Note 1

此方法不考虑原型链中的对象。

Note 2

步骤 12 的顺序被选择为确保,即使 this value 是 undefinednull,本规范先前版本中本应由步骤 1 抛出的任何异常也会继续被抛出。

20.1.3.5 Object.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] )

此方法在被调用时执行以下步骤:

  1. thisValuethis value。
  2. 返回 ? Invoke(thisValue, "toString")。

此方法的可选参数未被使用,但旨在对应于 ECMA-402 toLocaleString 方法所使用的参数模式。不包含 ECMA-402 支持的实现不得把这些参数位置用于其他目的。

Note 1

此方法为没有区域设置敏感 toString 行为的对象提供一个通用 toLocaleString 实现。ArrayNumberDate%TypedArray% 提供它们自己的区域设置敏感 toLocaleString 方法。

Note 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. 如果 isArraytrue,则令 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"]"字符串连接
Note

从历史上看,此方法偶尔用于访问 [[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 }。[[Get]][[Set]] 特性定义如下:

20.1.3.8.1 get Object.prototype.__proto__

[[Get]] 特性的值是一个不需要实参的内置函数。它在被调用时执行以下步骤:

  1. obj 为 ? ToObject(this value)。
  2. 返回 ? obj.[[GetPrototypeOf]]()

20.1.3.8.2 set Object.prototype.__proto__

[[Set]] 特性的值是一个接受实参 proto 的内置函数。它在被调用时执行以下步骤:

  1. thisValuethis value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. 如果 proto 不是 Object 且 proto 不是 null,则返回 undefined
  4. 如果 thisValue 不是 Object,则返回 undefined
  5. status 为 ? thisValue.[[SetPrototypeOf]](proto)
  6. 如果 statusfalse,则抛出 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 { [[Get]]: 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 { [[Set]]: 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.[[Get]]
      2. 返回 undefined
    3. obj 设置为 ? obj.[[GetPrototypeOf]]()
    4. 如果 objnull,则返回 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.[[Set]]
      2. 返回 undefined
    3. obj 设置为 ? obj.[[GetPrototypeOf]]()
    4. 如果 objnull,则返回 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)。
Note

可以但不必为要指定的每个形式参数提供一个实参。例如,以下三个表达式都会产生相同结果:

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 )

The abstract operation CreateDynamicFunction takes arguments ctor (a constructor), newTarget (a constructor or undefined), kind (normal, generator, async, or async-generator), paramArgs (a List of ECMAScript language values), and bodyArg (an ECMAScript language value) and returns either a normal completion containing an ECMAScript function object or a throw completion. ctor 是执行此动作的构造器函数。newTarget 是最初应用 new 的构造器。paramArgsbodyArg 反映传给 ctor 的实参值。 It performs the following steps when called:

  1. 如果 newTargetundefined,则将 newTarget 设置为 ctor
  2. 如果 kindnormal,则
    1. prefix"function"
    2. exprGrammar 为文法符号 FunctionExpression
    3. bodyGrammar 为文法符号 FunctionBody[~Yield, ~Await]
    4. paramGrammar 为文法符号 FormalParameters[~Yield, ~Await]
    5. fallbackProto"%Function.prototype%"
  3. 否则,如果 kindgenerator,则
    1. prefix"function*"
    2. exprGrammar 为文法符号 GeneratorExpression
    3. bodyGrammar 为文法符号 GeneratorBody
    4. paramGrammar 为文法符号 FormalParameters[+Yield, ~Await]
    5. fallbackProto"%GeneratorFunction.prototype%"
  4. 否则,如果 kindasync,则
    1. prefix"async function"
    2. exprGrammar 为文法符号 AsyncFunctionExpression
    3. bodyGrammar 为文法符号 AsyncFunctionBody
    4. paramGrammar 为文法符号 FormalParameters[~Yield, +Await]
    5. fallbackProto"%AsyncFunction.prototype%"
  5. 否则,
    1. 断言:kindasync-generator
    2. prefix"async function*"
    3. exprGrammar 为文法符号 AsyncGeneratorExpression
    4. bodyGrammar 为文法符号 AsyncGeneratorBody
    5. paramGrammar 为文法符号 FormalParameters[+Yield, +Await]
    6. fallbackProto"%AsyncGeneratorFunction.prototype%"
  6. argCountparamArgs 中元素的数量。
  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. nextArgStringparamStrings[k]。
      2. paramString 设置为 paramString","(逗号)和 nextArgString字符串连接
      3. k 设置为 k + 1。
  14. bodyParseString 为 0x000A(LINE FEED)、bodyString 和 0x000A(LINE FEED)的字符串连接
  15. sourceStringprefix" anonymous("paramString、0x000A(LINE FEED)、") {"bodyParseString"}"字符串连接
  16. sourceTextStringToCodePoints(sourceString)。
  17. paramsParseText(paramString, paramGrammar)。
  18. 如果 params 是错误列表,则抛出 SyntaxError 异常。
  19. bodyParseText(bodyParseString, bodyGrammar)。
  20. 如果 body 是错误列表,则抛出 SyntaxError 异常。
  21. 注:参数和主体会分别解析,以确保它们各自单独有效。例如,new Function("/*", "*/ ) {") 不会求值为一个函数。
  22. 注:如果到达此步骤,则 sourceText 必须具有 exprGrammar 的语法(尽管其逆命题不成立)。接下来两个步骤的目的是强制执行任何直接适用于 exprGrammar早期错误规则。
  23. exprParseText(sourceText, exprGrammar)。
  24. 如果 expr 是错误列表,则抛出 SyntaxError 异常。
  25. funcProto 为 ? GetPrototypeFromConstructor(newTarget, fallbackProto)。
  26. envRecordcurrentRealm.[[GlobalEnv]]
  27. privateEnvnull
  28. funcOrdinaryFunctionCreate(funcProto, sourceText, params, body, non-lexical-this, envRecord, privateEnv)。
  29. 执行 SetFunctionName(func, "anonymous")。
  30. 如果 kindgenerator,则
    1. protoProtoOrdinaryObjectCreate(%GeneratorPrototype%)。
    2. 执行 ! DefinePropertyOrThrow(func, "prototype", PropertyDescriptor { [[Value]]: protoProto, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  31. 否则,如果 kindasync-generator,则
    1. protoProtoOrdinaryObjectCreate(%AsyncGeneratorPrototype%)。
    2. 执行 ! DefinePropertyOrThrow(func, "prototype", PropertyDescriptor { [[Value]]: protoProto, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  32. 否则,如果 kindnormal,则
    1. 执行 MakeConstructor(func)。
  33. 注:kindasync 的函数不可构造,并且没有 [[Construct]] 内部方法或 "prototype" 属性。
  34. 返回 func
Note

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。
Note

Function 原型对象被规定为函数对象,是为了确保与 ECMAScript 2015 规范之前创建的 ECMAScript 代码兼容。

20.2.3.1 Function.prototype.apply ( thisArg, argArray )

此方法在被调用时执行以下步骤:

  1. functhis value。
  2. 如果 IsCallable(func) 是 false,则抛出 TypeError 异常。
  3. 如果 argArrayundefinednull,则
    1. 执行 PrepareForTailCall()。
    2. 返回 ? Call(func, thisArg)。
  4. argList 为 ? CreateListFromArrayLike(argArray)。
  5. 执行 PrepareForTailCall()。
  6. 返回 ? Call(func, thisArg, argList)。
Note 1

thisArg 值会不经修改地作为 this value 传入。这是相对于第 3 版的一个变化,在第 3 版中,undefinednullthisArg 会被替换为全局对象,且 ToObject 会应用于所有其他值,并将该结果作为 this value 传入。即使 thisArg 会不经修改地传入,非严格函数在进入函数时仍会执行这些转换。

Note 2

如果 func 是箭头函数或绑定函数奇异对象,则 thisArg 会在步骤 6 的函数 [[Call]] 中被忽略。

20.2.3.2 Function.prototype.bind ( thisArg, ...args )

此方法在被调用时执行以下步骤:

  1. targetthis value。
  2. 如果 IsCallable(target) 是 false,则抛出 TypeError 异常。
  3. boundFunc 为 ? BoundFunctionCreate(target, thisArg, args)。
  4. length 为 0。
  5. targetHasLength 为 ? HasOwnProperty(target, "length")。
  6. 如果 targetHasLengthtrue,则
    1. targetLength 为 ? Get(target, "length")。
    2. 如果 targetLength 是 Number,则
      1. 如果 targetLength+∞𝔽,则
        1. length 设置为 +∞。
      2. 否则,如果 targetLength-∞𝔽,则
        1. length 设置为 0。
      3. 否则,
        1. targetLengthAsInt 为 ! ToIntegerOrInfinity(targetLength)。
        2. 断言:targetLengthAsInt有限的。
        3. argCountargs 中元素的数量。
        4. 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
Note 1

使用 Function.prototype.bind 创建的 Function 对象是奇异对象。它们也没有 "prototype" 属性。

Note 2

如果 target 是箭头函数或绑定函数奇异对象,则传给此方法的 thisArg 不会被后续对 func 的调用使用。

20.2.3.3 Function.prototype.call ( thisArg, ...args )

此方法在被调用时执行以下步骤:

  1. functhis value。
  2. 如果 IsCallable(func) 是 false,则抛出 TypeError 异常。
  3. 执行 PrepareForTailCall()。
  4. 返回 ? Call(func, thisArg, args)。
Note 1

thisArg 值会不经修改地作为 this value 传入。这是相对于第 3 版的一个变化,在第 3 版中,undefinednullthisArg 会被替换为全局对象,且 ToObject 会应用于所有其他值,并将该结果作为 this value 传入。即使 thisArg 会不经修改地传入,非严格函数在进入函数时仍会执行这些转换。

Note 2

如果 func 是箭头函数或绑定函数奇异对象,则 thisArg 会在步骤 4 的函数 [[Call]] 中被忽略。

20.2.3.4 Function.prototype.constructor

Function.prototype.constructor 的初始值是 %Function%

20.2.3.5 Function.prototype.toString ( )

此方法在被调用时执行以下步骤:

  1. functhis 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. thisValuethis value。
  2. 返回 ? OrdinaryHasInstance(thisValue, value)。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

Note

这是大多数函数继承的 %Symbol.hasInstance% 默认实现。instanceof 运算符会调用 %Symbol.hasInstance% 来确定某个值是否为特定构造器的实例。诸如

v instanceof F

的表达式会求值为

F[%Symbol.hasInstance%](v)

构造器函数可以通过在该函数上暴露不同的 %Symbol.hasInstance% 方法,来控制哪些对象会被 instanceof 识别为其实例。

此属性不可写且不可配置,以防止可能被用于全局暴露绑定函数目标函数的篡改。

此方法的 "name" 属性的值是 "[Symbol.hasInstance]"

20.2.4 Function 实例

每个 Function 实例都是 ECMAScript 函数对象,并具有 Table 26 中列出的内部槽。使用 Function.prototype.bind 方法(20.2.3.2)创建的 Function 对象具有 Table 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 }。

Note

使用 Function.prototype.bind 创建的 Function 对象,或通过求值 MethodDefinition(不是 GeneratorMethodAsyncGeneratorMethod)或 ArrowFunction 创建的 Function 对象,没有 "prototype" 属性。

20.2.5 HostHasSourceTextAvailable ( func )

The host-defined abstract operation HostHasSourceTextAvailable takes argument func (a function object) and returns a 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. boolToBoolean(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. 如果 booltrue,则返回 "true"
  3. 返回 "false"

20.3.3.3 Boolean.prototype.valueOf ( )

此方法在被调用时执行以下步骤:

  1. 返回 ? ThisBooleanValue(this value)。

20.3.3.3.1 ThisBooleanValue ( arg )

The abstract operation ThisBooleanValue takes argument arg (an ECMAScript language value) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

  1. 如果 arg 是 Boolean,则返回 arg
  2. 如果 arg 是 Object 且 arg 具有 [[BooleanData]] 内部槽,则
    1. boolarg.[[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. 如果 descriptionundefined,则令 descStringundefined
  3. 否则,令 descString 为 ? ToString(description)。
  4. 返回一个新的 Symbol,其 [[Description]]descString

20.4.2 Symbol 构造器的属性

Symbol 构造器:

20.4.2.1 Symbol.asyncIterator

Symbol.asyncIterator 的初始值是知名 symbol %Symbol.asyncIterator%Table 1)。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.2 Symbol.for ( key )

此函数在被调用时执行以下步骤:

  1. stringKey 为 ? ToString(key)。
  2. agentRecord 为周围代理的代理记录。
  3. globalSymbolRegistryagentRecord.[[GlobalSymbolRegistry]]
  4. globalSymbolRegistry 的每个元素 element,执行
    1. 如果 element.[[Key]]stringKey,则返回 element.[[Symbol]]
  5. 断言:globalSymbolRegistry 当前不包含 stringKey 的条目。
  6. newSymbol 为一个新的 Symbol,其 [[Description]]stringKey
  7. GlobalSymbolRegistry 记录 { [[Key]]: stringKey, [[Symbol]]: newSymbol } 追加到 globalSymbolRegistry
  8. 返回 newSymbol

20.4.2.3 Symbol.hasInstance

Symbol.hasInstance 的初始值是知名 symbol %Symbol.hasInstance%Table 1)。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.4 Symbol.isConcatSpreadable

Symbol.isConcatSpreadable 的初始值是知名 symbol %Symbol.isConcatSpreadable%Table 1)。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.5 Symbol.iterator

Symbol.iterator 的初始值是知名 symbol %Symbol.iterator%Table 1)。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.6 Symbol.keyFor ( symbol )

此函数在被调用时执行以下步骤:

  1. 如果 symbol 不是 Symbol,则抛出 TypeError 异常。
  2. 返回 KeyForSymbol(symbol)。

20.4.2.7 Symbol.match

Symbol.match 的初始值是知名 symbol %Symbol.match%Table 1)。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.8 Symbol.matchAll

Symbol.matchAll 的初始值是知名 symbol %Symbol.matchAll%Table 1)。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.9 Symbol.prototype

Symbol.prototype 的初始值是 Symbol 原型对象

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.10 Symbol.replace

Symbol.replace 的初始值是知名 symbol %Symbol.replace%Table 1)。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.11 Symbol.search

Symbol.search 的初始值是知名 symbol %Symbol.search%Table 1)。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.12 Symbol.species

Symbol.species 的初始值是知名 symbol %Symbol.species%Table 1)。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.13 Symbol.split

Symbol.split 的初始值是知名 symbol %Symbol.split%Table 1)。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.14 Symbol.toPrimitive

Symbol.toPrimitive 的初始值是知名 symbol %Symbol.toPrimitive%Table 1)。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.15 Symbol.toStringTag

Symbol.toStringTag 的初始值是知名 symbol %Symbol.toStringTag%Table 1)。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.16 Symbol.unscopables

Symbol.unscopables 的初始值是知名 symbol %Symbol.unscopables%Table 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 )

The abstract operation SymbolDescriptiveString takes argument symbol (a Symbol) and returns a String. It performs the following steps when called:

  1. descriptionsymbol.[[Description]]
  2. 如果 descriptionundefined,则将 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 )

The abstract operation ThisSymbolValue takes argument arg (an ECMAScript language value) and returns either a normal completion containing a Symbol or a throw completion. It performs the following steps when called:

  1. 如果 arg 是 Symbol,则返回 arg
  2. 如果 arg 是 Object 且 arg 具有 [[SymbolData]] 内部槽,则
    1. symbolarg.[[SymbolData]]
    2. 断言:symbol 是 Symbol。
    3. 返回 symbol
  3. 抛出 TypeError 异常。

20.4.3.5 Symbol.prototype [ %Symbol.toPrimitive% ] ( hint )

此方法由 ECMAScript 语言运算符调用,用于把 Symbol 对象转换为原始值。

它在被调用时执行以下步骤:

  1. 返回 ? ThisSymbolValue(this value)。
Note

该实参会被忽略。

此属性具有特性 { [[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 记录

GlobalSymbolRegistry 记录是一个记录值,用于将一个字符串键与通过 Symbol.for 注册的 Symbol 值相关联。

GlobalSymbolRegistry 记录具有 Table 59 中列出的字段。

Table 59: GlobalSymbolRegistry 记录字段
字段名称 用法
[[Key]] 一个字符串 一个用于全局标识 Symbol 的字符串键。
[[Symbol]] 一个 Symbol 一个可从任何 realm 中检索到的 symbol。

20.4.5.2 KeyForSymbol ( symbol )

The abstract operation KeyForSymbol takes argument symbol (a Symbol) and returns a String or undefined. 如果 symbol 位于周围代理的 [[GlobalSymbolRegistry]] 列表中,则返回用于注册 symbol 的字符串。 It performs the following steps when called:

  1. agentRecord 为周围代理的代理记录。
  2. globalSymbolRegistryagentRecord.[[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. objthis value。
  2. 如果 obj 不是 Object,则抛出 TypeError 异常。
  3. name 为 ? Get(obj, "name")。
  4. 如果 nameundefined,则将 name 设置为 "Error";否则将 name 设置为 ? ToString(name)。
  5. message 为 ? Get(obj, "message")。
  6. 如果 messageundefined,则将 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 原型对象继承属性,并具有一个值为 undefined[[ErrorData]] 内部槽。[[ErrorData]] 唯一规定的用途,是在 Object.prototype.toStringError.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 原型对象继承属性,并具有一个值为 undefined[[ErrorData]] 内部槽。[[ErrorData]] 唯一规定的用途,是由 Object.prototype.toString20.1.3.6)和 Error.isError20.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 原型对象继承属性,并具有一个值为 undefined[[ErrorData]] 内部槽。[[ErrorData]] 唯一规定的用途,是由 Object.prototype.toString20.1.3.6)和 Error.isError20.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 构造函数

  • 具有一个值为 %Error%[[Prototype]] 内部槽。
  • 具有以下属性:

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]] 内部槽。
  • 具有一个值为 %Error.prototype%[[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 原型对象继承属性,并具有一个值为 undefined[[ErrorData]] 内部槽。[[ErrorData]] 唯一规定的用途,是在 Object.prototype.toStringError.isError 中将 Error、AggregateError、SuppressedError 和 NativeError 实例识别为 Error 对象。

20.5.9 Error 对象的抽象操作

20.5.9.1 InstallErrorCause ( obj, options )

The abstract operation InstallErrorCause takes arguments obj (an Object) and options (an ECMAScript language value) and returns either a normal completion containing unused or a throw completion. 当 options 上存在 "cause" 属性时,它用于在 obj 上创建 "cause" 属性。 It performs the following steps when called:

  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. 否则,令 nprimitive
  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,则返回 false
  2. 如果 number 不是有限的,则返回 false
  3. 返回 true

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. 如果 numberNaN,则返回 true
  3. 返回 false
Note

此函数不同于全局 isNaN 函数(19.2.3),因为它在确定其实参是否为 NaN 之前,不会把该实参转换为 Number。

21.1.2.5 Number.isSafeInteger ( number )

Note

当且仅当整数 nNumber 值不是任何其他整数的 Number 值时,整数 n 是一个“安全整数”。

此函数在被调用时执行以下步骤:

  1. 如果 number 是整数 Number,则
    1. 如果 abs((number)) ≤ 253 - 1,则返回 true
  2. 返回 false

21.1.2.6 Number.MAX_SAFE_INTEGER

Note

由于 IEEE 754-2019 精度限制所必需的舍入行为,每个大于 Number.MAX_SAFE_INTEGER 的整数的 Number 值都至少与另一个整数共享。因此,这类大数量级整数不是安全的,并且不能保证可以被精确表示为 Number 值,甚至不能保证彼此可区分。例如,90071992547409929007199254740993 都会求值为 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

Note

由于 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 对象;它具有一个 [[NumberData]] 内部槽,其值为 +0𝔽
  • 具有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%

除非另有明确说明,下文定义的 Number 原型对象的方法不是泛型的,传给它们的 this 值必须是 Number 值,或是一个具有已初始化为 Number 值[[NumberData]] 内部槽的对象。

在某个方法的规范中,短语“this Number value”指以该方法调用的 this 值作为实参调用抽象操作 ThisNumberValue 所返回的结果。

21.1.3.1 Number.prototype.constructor

Number.prototype.constructor 的初始值是 %Number%

21.1.3.2 Number.prototype.toExponential ( fractionDigits )

此方法返回一个 String,其中包含以十进制指数记号表示的 this Number value,尾数的小数点前有一位数字,小数点后有 fractionDigits 位数字。如果 fractionDigitsundefined,它会包含唯一指定该 Number 所需的尽可能多的尾数数字(类似 ToString,只是这种情况下 Number 总是以指数记号输出)。

它在被调用时执行以下步骤:

  1. number 为 ? ThisNumberValue(this value)。
  2. fractionCount 为 ? ToIntegerOrInfinity(fractionDigits)。
  3. 断言:如果 fractionDigitsundefined,则 fractionCount 是 0。
  4. 如果 number 不是有限的,则返回 Number::toString(number, 10)。
  5. 如果 fractionCount < 0 或 fractionCount > 100,则抛出 RangeError 异常。
  6. number 设置为 (number)。
  7. sign 为空 String。
  8. 如果 number < 0,则
    1. sign 设置为 "-"
    2. number 设置为 -number
  9. 如果 number = 0,则
    1. significand 为由 fractionCount + 1 个码元 0x0030(DIGIT ZERO)组成的 String 值。
    2. exponent 为 0。
  10. 否则,
    1. 如果 fractionDigits 不是 undefined,则
      1. exponentintSignificand 为这样的整数:10fractionCountintSignificand < 10fractionCount + 1,并且 intSignificand × 10exponent - fractionCount - number 尽可能接近零。如果存在两组这样的 exponentintSignificand,则选择使 intSignificand × 10exponent - fractionCount 较大的那组 exponentintSignificand
    2. 否则,
      1. exponentintSignificandff 为这样的整数:ff ≥ 0,10ffintSignificand < 10ff + 1𝔽(intSignificand × 10exponent - ff) 是 𝔽(number),并且 ff 尽可能小。注意,intSignificand 的十进制表示具有 ff + 1 位数字,intSignificand 不能被 10 整除,且 intSignificand 的最低有效数字不一定由这些准则唯一确定。
      2. fractionCount 设置为 ff
    3. significand 为由 intSignificand 的十进制表示的数字组成的 String 值(按顺序,且没有前导零)。
  11. 如果 fractionCount ≠ 0,则
    1. intPartsignificand 的第一个码元。
    2. fractionalPartsignificand 的其他 fractionCount 个码元。
    3. significand 设置为 intPart"."fractionalPart字符串连接
  12. 如果 exponent = 0,则
    1. exponentSign"+"
    2. exponentDigits"0"
  13. 否则,
    1. 如果 exponent > 0,则
      1. exponentSign"+"
    2. 否则,
      1. 断言:exponent < 0。
      2. exponentSign"-"
      3. exponent 设置为 -exponent
    3. exponentDigits 为由 exponent 的十进制表示的数字组成的 String 值(按顺序,且没有前导零)。
  14. significand 设置为 significand"e"exponentSignexponentDigits字符串连接
  15. 返回 signsignificand字符串连接
Note

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

  1. exponentintSignificandff 为这样的整数:ff ≥ 0,10ffintSignificand < 10ff + 1𝔽(intSignificand × 10exponent - ff) 是 𝔽(number),并且 ff 尽可能小。如果 intSignificand 有多种可能,则选择这样的 intSignificand:使 𝔽(intSignificand × 10exponent - ff) 最接近 𝔽(number)。如果存在两个这样的 intSignificand 可能值,则选择偶数的那个。

21.1.3.3 Number.prototype.toFixed ( fractionDigits )

Note 1

此方法返回一个 String,其中包含以十进制定点记号表示的 this Number value,小数点后有 fractionDigits 位数字。如果 fractionDigitsundefined,则假定为 0。

它在被调用时执行以下步骤:

  1. number 为 ? ThisNumberValue(this value)。
  2. fractionCount 为 ? ToIntegerOrInfinity(fractionDigits)。
  3. 断言:如果 fractionDigitsundefined,则 fractionCount 是 0。
  4. 如果 fractionCount 不是有限的,则抛出 RangeError 异常。
  5. 如果 fractionCount < 0 或 fractionCount > 100,则抛出 RangeError 异常。
  6. 如果 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. digitCountdigitString 的长度。
      2. 如果 digitCountfractionCount,则
        1. zeroPad 为由 fractionCount + 1 - digitCount 个码元 0x0030(DIGIT ZERO)组成的 String 值。
        2. digitString 设置为 zeroPaddigitString字符串连接
        3. digitCount 设置为 fractionCount + 1。
      3. intPartdigitString 的前 digitCount - fractionCount 个码元。
      4. fractionalPartdigitString 的其他 fractionCount 个码元。
      5. digitString 设置为 intPart"."fractionalPart字符串连接
  12. 返回 signdigitString字符串连接
Note 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 规范中的规定实现此方法。如果 ECMAScript 实现不包含 ECMA-402 API,则使用此方法的以下规范:

此方法产生一个 String 值,表示根据宿主环境当前区域设置的约定格式化的 this Number value。此方法由实现定义,并且允许但不鼓励它返回与 toString 相同的结果。

此方法可选参数的含义在 ECMA-402 规范中定义;不包含 ECMA-402 支持的实现不得把这些参数位置用于任何其他用途。

21.1.3.5 Number.prototype.toPrecision ( precision )

此方法返回一个 String,其中包含以十进制指数记号表示的 this Number value(尾数的小数点前有一位数字,小数点后有 precision - 1 位数字),或以具有 precision 位有效数字的十进制定点记号表示的 this Number value。如果 precisionundefined,它会改为调用 ToString

它在被调用时执行以下步骤:

  1. number 为 ? ThisNumberValue(this value)。
  2. 如果 precisionundefined,则返回 ! ToString(number)。
  3. precisionCount 为 ? ToIntegerOrInfinity(precision)。
  4. 如果 number 不是有限的,则返回 Number::toString(number, 10)。
  5. 如果 precisionCount < 1 或 precisionCount > 100,则抛出 RangeError 异常。
  6. number 设置为 (number)。
  7. sign 为空 String。
  8. 如果 number < 0,则
    1. sign 设置为码元 0x002D(HYPHEN-MINUS)。
    2. number 设置为 -number
  9. 如果 number = 0,则
    1. significand 为由 precisionCount 个码元 0x0030(DIGIT ZERO)组成的 String 值。
    2. exponent 为 0。
  10. 否则,
    1. exponentintSignificand 为这样的整数:10precisionCount - 1intSignificand < 10precisionCount,并且 intSignificand × 10exponent - precisionCount + 1 - number 尽可能接近零。如果存在两组这样的 exponentintSignificand,则选择使 intSignificand × 10exponent - precisionCount + 1 较大的那组 exponentintSignificand
    2. significand 为由 intSignificand 的十进制表示的数字组成的 String 值(按顺序,且没有前导零)。
    3. 如果 exponent < -6 或 exponentprecisionCount,则
      1. 断言:exponent ≠ 0。
      2. 如果 precisionCount ≠ 1,则
        1. intPartsignificand 的第一个码元。
        2. fractionalPartsignificand 的其他 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. 返回 signsignificand、码元 0x0065(LATIN SMALL LETTER E)、exponentSignexponentDigits字符串连接
  11. 如果 exponent = precisionCount - 1,则返回 signsignificand字符串连接
  12. 如果 exponent ≥ 0,则
    1. significand 设置为 significand 的前 exponent + 1 个码元、码元 0x002E(FULL STOP)和 significand 的剩余 precisionCount - (exponent + 1) 个码元的字符串连接
  13. 否则,
    1. significand 设置为码元 0x0030(DIGIT ZERO)、码元 0x002E(FULL STOP)、-(exponent + 1) 个码元 0x0030(DIGIT ZERO)和 String significand字符串连接
  14. 返回 signsignificand字符串连接

21.1.3.6 Number.prototype.toString ( [ radix ] )

Note

可选的 radix 应为包含区间 2𝔽36𝔽 内的整数 Number 值。如果 radixundefined,则使用 10𝔽 作为 radix 的值。

此方法在被调用时执行以下步骤:

  1. x 为 ? ThisNumberValue(this value)。
  2. 如果 radixundefined,则令 radixMV 为 10。
  3. 否则,令 radixMV 为 ? ToIntegerOrInfinity(radix)。
  4. 如果 radixMV 不在从 2 到 36 的闭区间内,则抛出 RangeError 异常。
  5. 返回 Number::toString(x, radixMV)。

此方法不是泛型的;如果其 this value 不是 Number 或 Number 对象,它会抛出 TypeError 异常。因此,它不能被转移到其他种类的对象上作为方法使用。

此方法的 "length" 属性是 1𝔽

21.1.3.7 Number.prototype.valueOf ( )

  1. 返回 ? ThisNumberValue(this value)。

21.1.3.7.1 ThisNumberValue ( arg )

The abstract operation ThisNumberValue takes argument arg (an ECMAScript language value) and returns either a normal completion containing a Number or a throw completion. It performs the following steps when called:

  1. 如果 arg 是 Number,则返回 arg
  2. 如果 arg 是 Object 且 arg 具有 [[NumberData]] 内部槽,则
    1. numberarg.[[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 )

The abstract operation NumberToBigInt takes argument number (a Number) and returns either a normal completion containing a BigInt or a throw completion. It performs the following steps when called:

  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) 模 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) 对 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]] 内部槽。
  • 具有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%

在某个方法的规范中,短语“this BigInt value”指以该方法调用的 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 规范中的规定实现此方法。如果 ECMAScript 实现不包含 ECMA-402 API,则使用此方法的以下规范:

此方法产生一个 String 值,表示根据宿主环境当前区域设置的约定格式化的 this BigInt value。此方法由实现定义,并且允许但不鼓励它返回与 toString 相同的结果。

此方法可选参数的含义在 ECMA-402 规范中定义;不包含 ECMA-402 支持的实现不得把这些参数位置用于任何其他用途。

21.2.3.3 BigInt.prototype.toString ( [ radix ] )

Note

可选的 radix 应为包含区间 2𝔽36𝔽 内的整数 Number 值。如果 radixundefined,则使用 10𝔽 作为 radix 的值。

此方法在被调用时执行以下步骤:

  1. x 为 ? ThisBigIntValue(this value)。
  2. 如果 radixundefined,则令 radixMV 为 10。
  3. 否则,令 radixMV 为 ? ToIntegerOrInfinity(radix)。
  4. 如果 radixMV 不在从 2 到 36 的闭区间内,则抛出 RangeError 异常。
  5. 返回 BigInt::toString(x, radixMV)。

此方法不是泛型的;如果其 this value 不是 BigInt 或 BigInt 对象,它会抛出 TypeError 异常。因此,它不能被转移到其他种类的对象上作为方法使用。

21.2.3.4 BigInt.prototype.valueOf ( )

  1. 返回 ? ThisBigIntValue(this value)。

21.2.3.4.1 ThisBigIntValue ( arg )

The abstract operation ThisBigIntValue takes argument arg (an ECMAScript language value) and returns either a normal completion containing a BigInt or a throw completion. It performs the following steps when called:

  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 对象:

  • %Math%
  • 全局对象"Math" 属性的初始值。
  • 普通对象
  • 具有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%
  • 不是函数对象
  • 没有 [[Construct]] 内部方法;它不能作为构造器与 new 运算符一起使用。
  • 没有 [[Call]] 内部方法;它不能作为函数调用。
Note

在本规范中,短语“the Number value for x”具有 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 }。

Note

Math.LOG10E 的值约为 Math.LN10 值的倒数。

21.3.1.5 Math.LOG2E

e(自然对数的底)的以 2 为底的对数的 Number 值;此值约为 1.4426950408889634。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

Note

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 }。

Note

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 对象的函数属性

Note

函数 acosacoshasinasinhatanatanhatan2cbrtcoscoshexpexpm1hypotloglog1plog2log10powrandomsinsinhtantanh 的行为在这里没有精确规定,除了要求对于某些表示相关边界情况的实参值给出特定结果。对于其他实参值,这些函数旨在计算熟悉数学函数结果的近似值,但在近似算法的选择上允许一定的自由度。总体意图是,实现者应能够在给定硬件平台上为 ECMAScript 使用与该平台上 C 程序员可用的相同数学库。

尽管算法的选择留给实现,但建议(而非本标准规定)实现使用 fdlibm包含IEEE 754-2019 算术近似算法,fdlibm 是 Sun Microsystems 的可自由分发数学库(http://www.netlib.org/fdlibm)。

21.3.2.1 Math.abs ( x )

此函数返回 x 的绝对值;结果具有与 x 相同的大小,但符号为正。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN,则返回 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. 如果 nNaNn > 1𝔽,或 n < -1𝔽,则返回 NaN
  3. 如果 n1𝔽,则返回 +0𝔽
  4. 返回表示 (n) 的反余弦的实现近似 Number 值

21.3.2.3 Math.acosh ( x )

此函数返回 x 的反双曲余弦。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+∞𝔽,则返回 n
  3. 如果 n1𝔽,则返回 +0𝔽
  4. 如果 n < 1𝔽,则返回 NaN
  5. 返回表示 (n) 的反双曲余弦的实现近似 Number 值

21.3.2.4 Math.asin ( x )

此函数返回 x 的反正弦。结果以弧度表示,并位于从 𝔽(-π / 2) 到 𝔽(π / 2) 的闭区间内。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+0𝔽-0𝔽 之一,则返回 n
  3. 如果 n > 1𝔽n < -1𝔽,则返回 NaN
  4. 返回表示 (n) 的反正弦的实现近似 Number 值

21.3.2.5 Math.asinh ( x )

此函数返回 x 的反双曲正弦。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 n 不是有限的,或 n+0𝔽-0𝔽,则返回 n
  3. 返回表示 (n) 的反双曲正弦的实现近似 Number 值

21.3.2.6 Math.atan ( x )

此函数返回 x 的反正切。结果以弧度表示,并位于从 𝔽(-π / 2) 到 𝔽(π / 2) 的闭区间内。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+0𝔽-0𝔽 之一,则返回 n
  3. 如果 n+∞𝔽,则返回表示 π / 2 的实现近似 Number 值
  4. 如果 n-∞𝔽,则返回表示 -π / 2 的实现近似 Number 值
  5. 返回表示 (n) 的反正切的实现近似 Number 值

21.3.2.7 Math.atanh ( x )

此函数返回 x 的反双曲正切。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+0𝔽-0𝔽 之一,则返回 n
  3. 如果 n > 1𝔽n < -1𝔽,则返回 NaN
  4. 如果 n1𝔽,则返回 +∞𝔽
  5. 如果 n-1𝔽,则返回 -∞𝔽
  6. 返回表示 (n) 的反双曲正切的实现近似 Number 值

21.3.2.8 Math.atan2 ( y, x )

此函数返回实参 yx 的商 y / x 的反正切,其中 yx 的符号用于确定结果所在的象限。注意,对于双实参反正切函数,名为 y 的实参在前而名为 x 的实参在后,这是有意且传统的。结果以弧度表示,并位于从 -π 到 +π 的闭区间内。

它在被调用时执行以下步骤:

  1. ny 为 ? ToNumber(y)。
  2. nx 为 ? ToNumber(x)。
  3. 如果 nyNaNnxNaN,则返回 NaN
  4. 如果 ny+∞𝔽,则
    1. 如果 nx+∞𝔽,则返回表示 π / 4 的实现近似 Number 值
    2. 如果 nx-∞𝔽,则返回表示 3π / 4 的实现近似 Number 值
    3. 返回表示 π / 2 的实现近似 Number 值
  5. 如果 ny-∞𝔽,则
    1. 如果 nx+∞𝔽,则返回表示 -π / 4 的实现近似 Number 值
    2. 如果 nx-∞𝔽,则返回表示 -3π / 4 的实现近似 Number 值
    3. 返回表示 -π / 2 的实现近似 Number 值
  6. 如果 ny+0𝔽,则
    1. 如果 nx > +0𝔽nx+0𝔽,则返回 +0𝔽
    2. 返回表示 π 的实现近似 Number 值
  7. 如果 ny-0𝔽,则
    1. 如果 nx > +0𝔽nx+0𝔽,则返回 -0𝔽
    2. 返回表示 -π 的实现近似 Number 值
  8. 断言:ny有限的,并且既不是 +0𝔽 也不是 -0𝔽
  9. 如果 ny > +0𝔽,则
    1. 如果 nx+∞𝔽,则返回 +0𝔽
    2. 如果 nx-∞𝔽,则返回表示 π 的实现近似 Number 值
    3. 如果 nx+0𝔽-0𝔽,则返回表示 π / 2 的实现近似 Number 值
  10. 如果 ny < -0𝔽,则
    1. 如果 nx+∞𝔽,则返回 -0𝔽
    2. 如果 nx-∞𝔽,则返回表示 -π 的实现近似 Number 值
    3. 如果 nx+0𝔽-0𝔽,则返回表示 -π / 2 的实现近似 Number 值
  11. 断言:nx有限的,并且既不是 +0𝔽 也不是 -0𝔽
  12. resultabs((ny) / (nx)) 的反正切。
  13. 如果 nx < -0𝔽,则
    1. 如果 ny > +0𝔽,则将 result 设置为 π - result
    2. 否则,将 result 设置为 -π + result
  14. 否则,
    1. 如果 ny < -0𝔽,则将 result 设置为 -result
  15. 返回表示 result 的实现近似 Number 值

21.3.2.9 Math.cbrt ( x )

此函数返回 x 的立方根。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 n 不是有限的,或 n+0𝔽-0𝔽,则返回 n
  3. 返回表示 (n) 的立方根的实现近似 Number 值

21.3.2.10 Math.ceil ( x )

此函数返回不小于 x 的最小(最接近 -∞ 的)整数 Number 值。如果 x 已经是整数 Number,则结果为 x

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 n 不是有限的,或 n+0𝔽-0𝔽,则返回 n
  3. 如果 n < -0𝔽n > -1𝔽,则返回 -0𝔽
  4. 如果 n 是整数 Number,则返回 n
  5. 返回不小于 n 的最小(最接近 -∞ 的)整数 Number 值
Note

Math.ceil(x) 的值与 -Math.floor(-x) 的值相同。

21.3.2.11 Math.clz32 ( x )

此函数在被调用时执行以下步骤:

  1. n 为 ? ToUint32(x)。
  2. pn 的无符号 32 位二进制表示中的前导零位数。
  3. 返回 𝔽(p)。
Note

如果 n+0𝔽-0𝔽,此方法返回 32𝔽。如果 n 的 32 位二进制编码的最高有效位是 1,此方法返回 +0𝔽

21.3.2.12 Math.cos ( x )

此函数返回 x 的余弦。实参以弧度表示。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 n 不是有限的,则返回 NaN
  3. 如果 n+0𝔽-0𝔽,则返回 1𝔽
  4. 返回表示 (n) 的余弦的实现近似 Number 值

21.3.2.13 Math.cosh ( x )

此函数返回 x 的双曲余弦。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN,则返回 NaN
  3. 如果 n+∞𝔽-∞𝔽,则返回 +∞𝔽
  4. 如果 n+0𝔽-0𝔽,则返回 1𝔽
  5. 返回表示 (n) 的双曲余弦的实现近似 Number 值
Note

Math.cosh(x) 的值与 (Math.exp(x) + Math.exp(-x)) / 2 的值相同。

21.3.2.14 Math.exp ( x )

此函数返回 x 的指数函数(ex 次幂,其中 e 是自然对数的底)。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+∞𝔽,则返回 n
  3. 如果 n+0𝔽-0𝔽,则返回 1𝔽
  4. 如果 n-∞𝔽,则返回 +0𝔽
  5. 返回表示 (n) 的指数函数的实现近似 Number 值

21.3.2.15 Math.expm1 ( x )

此函数返回从 x 的指数函数(ex 次幂,其中 e 是自然对数的底)中减去 1 的结果。即使 x 的值接近 0,也会以准确的方式计算该结果。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+0𝔽-0𝔽+∞𝔽 之一,则返回 n
  3. 如果 n-∞𝔽,则返回 -1𝔽
  4. exp(n) 的指数函数。
  5. 返回表示 exp - 1 的实现近似 Number 值

21.3.2.16 Math.floor ( x )

此函数返回不大于 x 的最大(最接近 +∞ 的)整数 Number 值。如果 x 已经是整数 Number,则结果为 x

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 n 不是有限的,或 n+0𝔽-0𝔽,则返回 n
  3. 如果 n < 1𝔽n > +0𝔽,则返回 +0𝔽
  4. 如果 n 是整数 Number,则返回 n
  5. 返回不大于 n 的最大(最接近 +∞ 的)整数 Number 值
Note

Math.floor(x) 的值与 -Math.ceil(-x) 的值相同。

21.3.2.17 Math.fround ( x )

此函数在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN,则返回 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. 如果 nNaN,则返回 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 值
Note

此操作不同于先转换为 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. onlyZerotrue
  5. coerced 的每个元素 number,执行:
    1. 如果 numberNaN,则返回 NaN
    2. 如果 number 既不是 +0𝔽 也不是 -0𝔽,则将 onlyZero 设置为 false
  6. 如果 onlyZerotrue,则返回 +0𝔽
  7. 返回表示 coerced 中各元素数学值平方和的平方根的实现近似 Number 值

此函数的 "length" 属性是 2𝔽

Note

当此函数以两个或更多实参调用时,实现应注意避免朴素实现中容易发生的上溢和下溢所导致的精度损失。

21.3.2.20 Math.imul ( x, y )

此函数在被调用时执行以下步骤:

  1. a(? ToUint32(x))。
  2. b(? ToUint32(y))。
  3. product 为 (a × b) 对 232 取模。
  4. 如果 product ≥ 231,则返回 𝔽(product - 232)。
  5. 返回 𝔽(product)。

21.3.2.21 Math.log ( x )

此函数返回 x 的自然对数。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+∞𝔽,则返回 n
  3. 如果 n1𝔽,则返回 +0𝔽
  4. 如果 n+0𝔽-0𝔽,则返回 -∞𝔽
  5. 如果 n < -0𝔽,则返回 NaN
  6. 返回表示 ln((n)) 的实现近似 Number 值

21.3.2.22 Math.log1p ( x )

此函数返回 1 + x 的自然对数。即使 x 的值接近零,也会以准确的方式计算该结果。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+0𝔽-0𝔽+∞𝔽 之一,则返回 n
  3. 如果 n-1𝔽,则返回 -∞𝔽
  4. 如果 n < -1𝔽,则返回 NaN
  5. 返回表示 ln(1 + (n)) 的实现近似 Number 值

21.3.2.23 Math.log10 ( x )

此函数返回 x 的以 10 为底的对数。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+∞𝔽,则返回 n
  3. 如果 n1𝔽,则返回 +0𝔽
  4. 如果 n+0𝔽-0𝔽,则返回 -∞𝔽
  5. 如果 n < -0𝔽,则返回 NaN
  6. 返回表示 log10((n)) 的实现近似 Number 值

21.3.2.24 Math.log2 ( x )

此函数返回 x 的以 2 为底的对数。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+∞𝔽,则返回 n
  3. 如果 n1𝔽,则返回 +0𝔽
  4. 如果 n+0𝔽-0𝔽,则返回 -∞𝔽
  5. 如果 n < -0𝔽,则返回 NaN
  6. 返回表示 log2((n)) 的实现近似 Number 值

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. 如果 numberNaN,则返回 NaN
    2. 如果 number+0𝔽highest-0𝔽,则将 highest 设置为 +0𝔽
    3. 如果 number > highest,则将 highest 设置为 number
  5. 返回 highest
Note

用于确定最大值的值比较使用 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. 如果 numberNaN,则返回 NaN
    2. 如果 number-0𝔽lowest+0𝔽,则将 lowest 设置为 -0𝔽
    3. 如果 number < lowest,则将 lowest 设置为 number
  5. 返回 lowest
Note

用于确定最小值的值比较使用 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 ( )

此函数返回一个符号为正、大于或等于 +0𝔽 但严格小于 1𝔽Number 值,该值使用实现定义的算法或策略,以在该范围内近似均匀分布的方式随机或伪随机选择。

为不同 realm 创建的每个 Math.random 函数,必须从连续调用中产生不同的值序列。

21.3.2.29 Math.round ( x )

此函数返回最接近 x 且为整数的 Number 值。如果两个整数 Number 与 x 等距,则结果是更接近 +∞ 的 Number 值。如果 x 已经是整数,则结果为 x

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 n 不是有限的或 n 是整数 Number,则返回 n
  3. 如果 n < 0.5𝔽n > +0𝔽,则返回 +0𝔽
  4. 如果 n < -0𝔽n-0.5𝔽,则返回 -0𝔽
  5. 返回最接近 n 的整数 Number,平局时偏向更接近 +∞ 的 Number。
Note 1

Math.round(3.5) 返回 4,但 Math.round(-3.5) 返回 -3。

Note 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. 如果 nNaN+0𝔽-0𝔽 之一,则返回 n
  3. 如果 n < -0𝔽,则返回 -1𝔽
  4. 返回 1𝔽

21.3.2.31 Math.sin ( x )

此函数返回 x 的正弦。实参以弧度表示。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+0𝔽-0𝔽 之一,则返回 n
  3. 如果 n+∞𝔽-∞𝔽,则返回 NaN
  4. 返回表示 (n) 的正弦的实现近似 Number 值

21.3.2.32 Math.sinh ( x )

此函数返回 x 的双曲正弦。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 n 不是有限的,或 n+0𝔽-0𝔽,则返回 n
  3. 返回表示 (n) 的双曲正弦的实现近似 Number 值
Note

Math.sinh(x) 的值与 (Math.exp(x) - Math.exp(-x)) / 2 的值相同。

21.3.2.33 Math.sqrt ( x )

此函数返回 x 的平方根。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+0𝔽-0𝔽+∞𝔽 之一,则返回 n
  3. 如果 n < -0𝔽,则返回 NaN
  4. 返回 𝔽((n) 的平方根)。

21.3.2.34 Math.sumPrecise ( items )

给定一个 Numbers 的可迭代对象,此函数对可迭代对象中的每个值求和,并返回其和。如果任何值不是 Number,则抛出 TypeError 异常。

它在被调用时执行以下步骤:

  1. 执行 ? RequireObjectCoercible(items)。
  2. iteratorRecord 为 ? GetIterator(items, sync)。
  3. stateminus-zero
  4. sum 为 0。
  5. count 为 0。
  6. nextnot-started
  7. 重复,只要 next 不是 done
    1. next 设置为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 next 不是 done,则
      1. 如果 count ≥ 253 - 1,则
        1. 注:在实践中不预计会达到此步骤,包含它只是为了使实现可以依赖输入为“合理大小”而不违反本规范。
        2. errorThrowCompletion(一个新创建的 RangeError 对象)。
        3. 返回 ? IteratorClose(iteratorRecord, error)。
      2. 如果 next 不是 Number,则
        1. errorThrowCompletion(一个新创建的 TypeError 对象)。
        2. 返回 ? IteratorClose(iteratorRecord, error)。
      3. nnext
      4. 如果 state 不是 not-a-number,则
        1. 如果 nNaN,则
          1. state 设置为 not-a-number
        2. 否则,如果 n+∞𝔽,则
          1. 如果 stateminus-infinity,则将 state 设置为 not-a-number
          2. 否则,将 state 设置为 plus-infinity
        3. 否则,如果 n-∞𝔽,则
          1. 如果 stateplus-infinity,则将 state 设置为 not-a-number
          2. 否则,将 state 设置为 minus-infinity
        4. 否则,如果 n 不是 -0𝔽stateminus-zerofinite,则
          1. state 设置为 finite
          2. sum 设置为 sum + (n)。
      5. count 设置为 count + 1。
  8. 如果 statenot-a-number,则返回 NaN
  9. 如果 stateplus-infinity,则返回 +∞𝔽
  10. 如果 stateminus-infinity,则返回 -∞𝔽
  11. 如果 stateminus-zero,则返回 -0𝔽
  12. 返回 𝔽(sum)。
Note

sum 的值可以通过多种算法在不使用任意精度算术的情况下计算。其中一种是 Jonathan Richard Shewchuk 在 Adaptive Precision Floating-Point Arithmetic and Fast Robust Geometric Predicates 中给出的“Grow-Expansion”算法。一个更新的算法见“Fast exact summation using small and large superaccumulators”,其代码可在 https://gitlab.com/radfordneal/xsum 获得。

21.3.2.35 Math.tan ( x )

此函数返回 x 的正切。实参以弧度表示。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+0𝔽-0𝔽 之一,则返回 n
  3. 如果 n+∞𝔽-∞𝔽,则返回 NaN
  4. 返回表示 (n) 的正切的实现近似 Number 值

21.3.2.36 Math.tanh ( x )

此函数返回 x 的双曲正切。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+0𝔽-0𝔽 之一,则返回 n
  3. 如果 n+∞𝔽,则返回 1𝔽
  4. 如果 n-∞𝔽,则返回 -1𝔽
  5. 返回表示 (n) 的双曲正切的实现近似 Number 值
Note

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 不是有限的,或 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 中的时间度量,特别是共享以预推格里高利历、UTC 1970 年 1 月 1 日开始时的午夜作为 epoch,并且把每一天都计为正好 86,400 秒(每秒长度为 1000 毫秒)的定义。

ECMAScript 时间值是 Number,要么是表示毫秒精度的时间瞬间的有限整数 Number,要么是表示没有特定瞬间的 NaN。作为 24 × 60 × 60 × 1000 = 86,400,000 的倍数的时间值(即,对于某个整数 d,是 86,400,000 × d)表示从 epoch 起经过 d 个完整 UTC 日后的 UTC 日开始处的瞬间(负 d 表示早于 epoch)。其他每个有限时间值 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.821.1.2.6)。时间值支持略小的范围,即 -8,640,000,000,000,000 到 8,640,000,000,000,000 毫秒。这产生的受支持时间值范围,相对于 UTC 1970 年 1 月 1 日开始时的午夜,正好是 -100,000,000 天到 100,000,000 天。

UTC 1970 年 1 月 1 日开始时午夜的精确时刻由时间值 +0𝔽 表示。

Note

在预推格里高利历中,闰年正是那些可被 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
msPerSecond = 1000𝔽
msPerMinute = 60000𝔽 = msPerSecond × 𝔽(SecondsPerMinute)
msPerHour = 3600000𝔽 = msPerMinute × 𝔽(MinutesPerHour)
msPerDay = 86400000𝔽 = msPerHour × 𝔽(HoursPerDay)

21.4.1.3 Day ( tv )

The abstract operation Day takes argument tv (a finite time value) and returns an integral Number. 它返回 tv 所落入日期的日编号。 It performs the following steps when called:

  1. 返回 𝔽(floor((tv / msPerDay)))。

21.4.1.4 TimeWithinDay ( tv )

The abstract operation TimeWithinDay takes argument tv (a finite time value) and returns an integral Number in the interval from +0𝔽 (inclusive) to msPerDay (exclusive). 它返回自 tv 所落入日期开始以来的毫秒数。 It performs the following steps when called:

  1. 返回 𝔽((tv) modulo (msPerDay))。

21.4.1.5 DaysInYear ( y )

The abstract operation DaysInYear takes argument y (an integral Number) and returns 365𝔽 or 366𝔽. 它返回年份 y 中的天数。闰年有 366 天;所有其他年份有 365 天。 It performs the following steps when called:

  1. ry(y)。
  2. 如果 (ry modulo 400) = 0,则返回 366𝔽
  3. 如果 (ry modulo 100) = 0,则返回 365𝔽
  4. 如果 (ry modulo 4) = 0,则返回 366𝔽
  5. 返回 365𝔽

21.4.1.6 DayFromYear ( y )

The abstract operation DayFromYear takes argument y (an integral Number) and returns an integral Number. 它返回年份 y 第一天的日编号。 It performs the following steps when called:

  1. ry(y)。
  2. 注:在以下步骤中,numberYears1numberYears4numberYears100numberYears400 分别表示在 epoch 与年份 y 开始之间出现的、可被 1、4、100 和 400 整除的年份数。如果 y 早于 epoch,则该数为负。
  3. numberYears1 为 (ry - 1970)。
  4. numberYears4floor((ry - 1969) / 4)。
  5. numberYears100floor((ry - 1901) / 100)。
  6. numberYears400floor((ry - 1601) / 400)。
  7. 返回 𝔽(365 × numberYears1 + numberYears4 - numberYears100 + numberYears400)。

21.4.1.7 TimeFromYear ( y )

The abstract operation TimeFromYear takes argument y (an integral Number) and returns a time value. 它返回年份 y 开始处的时间值。 It performs the following steps when called:

  1. 返回 msPerDay × DayFromYear(y)。

21.4.1.8 YearFromTime ( tv )

The abstract operation YearFromTime takes argument tv (a finite time value) and returns an integral Number. 它返回 tv 所落入的年份。 It performs the following steps when called:

  1. 返回最大的整数 Number y(最接近 +∞),使得 TimeFromYear(y) ≤ tv

21.4.1.9 DayWithinYear ( tv )

The abstract operation DayWithinYear takes argument tv (a finite time value) and returns an integral Number in the inclusive interval from +0𝔽 to 365𝔽. It performs the following steps when called:

  1. 返回 Day(tv) - DayFromYear(YearFromTime(tv))。

21.4.1.10 InLeapYear ( tv )

The abstract operation InLeapYear takes argument tv (a finite time value) and returns +0𝔽 or 1𝔽. 如果 tv 位于闰年内,则返回 1𝔽;否则返回 +0𝔽。 It performs the following steps when called:

  1. 如果 DaysInYear(YearFromTime(tv)) 是 366𝔽,则返回 1𝔽
  2. 返回 +0𝔽

21.4.1.11 MonthFromTime ( tv )

The abstract operation MonthFromTime takes argument tv (a finite time value) and returns an integral Number in the inclusive interval from +0𝔽 to 11𝔽. 它返回一个 Number,用于标识 tv 所落入的月份。月份值 +0𝔽 指定一月;1𝔽 指定二月;2𝔽 指定三月;3𝔽 指定四月;4𝔽 指定五月;5𝔽 指定六月;6𝔽 指定七月;7𝔽 指定八月;8𝔽 指定九月;9𝔽 指定十月;10𝔽 指定十一月;11𝔽 指定十二月。注意,MonthFromTime(+0𝔽) = +0𝔽,对应于 1970 年 1 月 1 日星期四。 It performs the following steps when called:

  1. inLeapYearInLeapYear(tv)。
  2. dayWithinYearDayWithinYear(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.12 DateFromTime ( tv )

The abstract operation DateFromTime takes argument tv (a finite time value) and returns an integral Number in the inclusive interval from 1𝔽 to 31𝔽. 它返回 tv 所落入月份中的日期。 It performs the following steps when called:

  1. inLeapYearInLeapYear(tv)。
  2. dayWithinYearDayWithinYear(tv)。
  3. monthMonthFromTime(tv)。
  4. 如果 month+0𝔽,则返回 dayWithinYear + 1𝔽
  5. 如果 month1𝔽,则返回 dayWithinYear - 30𝔽
  6. 如果 month2𝔽,则返回 dayWithinYear - 58𝔽 - inLeapYear
  7. 如果 month3𝔽,则返回 dayWithinYear - 89𝔽 - inLeapYear
  8. 如果 month4𝔽,则返回 dayWithinYear - 119𝔽 - inLeapYear
  9. 如果 month5𝔽,则返回 dayWithinYear - 150𝔽 - inLeapYear
  10. 如果 month6𝔽,则返回 dayWithinYear - 180𝔽 - inLeapYear
  11. 如果 month7𝔽,则返回 dayWithinYear - 211𝔽 - inLeapYear
  12. 如果 month8𝔽,则返回 dayWithinYear - 242𝔽 - inLeapYear
  13. 如果 month9𝔽,则返回 dayWithinYear - 272𝔽 - inLeapYear
  14. 如果 month10𝔽,则返回 dayWithinYear - 303𝔽 - inLeapYear
  15. 断言:month11𝔽
  16. 返回 dayWithinYear - 333𝔽 - inLeapYear

21.4.1.13 WeekDay ( tv )

The abstract operation WeekDay takes argument tv (a finite time value) and returns an integral Number in the inclusive interval from +0𝔽 to 6𝔽. 它返回一个 Number,用于标识 tv 所落入的星期几。星期值 +0𝔽 指定星期日;1𝔽 指定星期一;2𝔽 指定星期二;3𝔽 指定星期三;4𝔽 指定星期四;5𝔽 指定星期五;6𝔽 指定星期六。注意,WeekDay(+0𝔽) = 4𝔽,对应于 1970 年 1 月 1 日星期四。 It performs the following steps when called:

  1. 返回 𝔽((Day(tv) + 4𝔽) modulo 7)。

21.4.1.14 HourFromTime ( tv )

The abstract operation HourFromTime takes argument tv (a finite time value) and returns an integral Number in the inclusive interval from +0𝔽 to 23𝔽. 它返回 tv 所落入日期中的小时。 It performs the following steps when called:

  1. 返回 𝔽(floor((tv / msPerHour)) modulo HoursPerDay)。

21.4.1.15 MinFromTime ( tv )

The abstract operation MinFromTime takes argument tv (a finite time value) and returns an integral Number in the inclusive interval from +0𝔽 to 59𝔽. 它返回 tv 所落入小时中的分钟。 It performs the following steps when called:

  1. 返回 𝔽(floor((tv / msPerMinute)) modulo MinutesPerHour)。

21.4.1.16 SecFromTime ( tv )

The abstract operation SecFromTime takes argument tv (a finite time value) and returns an integral Number in the inclusive interval from +0𝔽 to 59𝔽. 它返回 tv 所落入分钟中的秒。 It performs the following steps when called:

  1. 返回 𝔽(floor((tv / msPerSecond)) modulo SecondsPerMinute)。

21.4.1.17 msFromTime ( tv )

The abstract operation msFromTime takes argument tv (a finite time value) and returns an integral Number in the inclusive interval from +0𝔽 to 999𝔽. 它返回 tv 所落入秒中的毫秒。 It performs the following steps when called:

  1. 返回 𝔽((tv) modulo (msPerSecond))。

21.4.1.18 GetUTCEpochNanoseconds ( year, month, day, hour, minute, second, millisecond, microsecond, nanosecond )

The abstract operation GetUTCEpochNanoseconds takes arguments year (an integer), 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), and nanosecond (an integer in the inclusive interval from 0 to 999) and returns a BigInt. 返回值表示自 epoch 以来的纳秒数,该值对应于给定的 ISO 8601 日历日期和 UTC 挂钟时间。 It performs the following steps when called:

  1. dateMakeDay(𝔽(year), 𝔽(month - 1), 𝔽(day))。
  2. timeMakeTime(𝔽(hour), 𝔽(minute), 𝔽(second), 𝔽(millisecond))。
  3. msMakeDate(date, time)。
  4. 断言:ms 是整数 Number。
  5. 返回 ((ms) × 106 + microsecond × 103 + nanosecond)。

21.4.1.19 时区标识符

ECMAScript 中的时区由时区标识符表示,它们是完全由从 0x0000 到 0x007F 闭区间内的码元组成的 String。 ECMAScript 实现支持的时区可以是可用命名时区,由 AvailableNamedTimeZoneIdentifiers 返回的 Time Zone Identifier Records[[Identifier]] 字段表示;也可以是偏移时区,由 IsTimeZoneOffsetString 返回 true 的 String 表示。

主时区标识符是某个可用命名时区的首选标识符。 非主时区标识符是某个可用命名时区的标识符,且不是主时区标识符。 可用命名时区标识符要么是主时区标识符,要么是非主时区标识符。 每个可用命名时区标识符都恰好关联到一个可用命名时区。 每个可用命名时区都恰好关联到一个主时区标识符,并关联到零个或更多非主时区标识符。

ECMAScript 实现必须支持标识符为 "UTC" 的可用命名时区,该标识符必须是 UTC 时区的主时区标识符。 此外,实现可以支持任意数量的其他可用命名时区。

遵循 ECMA-402 国际化 API 规范中所述时区要求的实现称为时区感知。 时区感知实现必须支持与 IANA Time Zone Database 的 Zone 和 Link 名称对应的可用命名时区,并且只能支持这样的名称。 在时区感知实现中,主时区标识符分别是 IANA Time Zone Database 中的 Zone 名称,非主时区标识符是 Link 名称,但 ECMA-402 规范中规定的 AvailableNamedTimeZoneIdentifiers 特别覆盖的情况除外。 仍建议不支持完整 IANA Time Zone Database 的实现使用 IANA Time Zone Database 名称作为表示时区的标识符。

21.4.1.20 GetNamedTimeZoneEpochNanoseconds ( timeZoneIdentifier, year, month, day, hour, minute, second, millisecond, microsecond, nanosecond )

The implementation-defined abstract operation GetNamedTimeZoneEpochNanoseconds takes arguments timeZoneIdentifier (a String), year (an integer), 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), and nanosecond (an integer in the inclusive interval from 0 to 999) and returns a List of BigInts. 返回的 List 中的每个值都表示自 epoch 以来的纳秒数,该值对应于由 timeZoneIdentifier 标识的命名时区中的给定 ISO 8601 日历日期和挂钟时间。

当输入表示的本地时间因负时区转换而出现多次(例如夏令时结束时,或因时区规则变更而时区偏移减少时),返回的 List 将有多个元素,并按数值升序排序。 当输入表示的本地时间因正时区转换而被跳过(例如夏令时开始时,或因时区规则变更而时区偏移增加时),返回的 List 将为空。 否则,返回的 List 将有一个元素。

GetNamedTimeZoneEpochNanoseconds 的默认实现(用于不包含任何时区本地政治规则的 ECMAScript 实现)在被调用时执行以下步骤:

  1. 断言:timeZoneIdentifier"UTC"
  2. epochNanosecondsGetUTCEpochNanoseconds(year, month, day, hour, minute, second, millisecond, microsecond, nanosecond)。
  3. 返回 « epochNanoseconds »。
Note

要求时区感知实现(并建议所有其他实现)使用 IANA Time Zone Database 的时区信息 https://www.iana.org/time-zones/

America/New_York 中 2017 年 11 月 5 日凌晨 1:30 会重复两次,因此 GetNamedTimeZoneEpochNanoseconds("America/New_York", 2017, 11, 5, 1, 30, 0, 0, 0, 0) 会返回一个长度为 2 的 List,其中第一个元素表示 05:30 UTC(对应 UTC 偏移 -04:00 的美国东部夏令时 01:30),第二个元素表示 06:30 UTC(对应 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 )

The implementation-defined abstract operation GetNamedTimeZoneOffsetNanoseconds takes arguments timeZoneIdentifier (a String) and epochNanoseconds (a BigInt) and returns an integer.

返回的整数表示由 timeZoneIdentifier 标识的命名时区,在相对于 epochepochNanoseconds 对应的瞬间相对于 UTC 的偏移,两者都以纳秒为单位。

GetNamedTimeZoneOffsetNanoseconds 的默认实现(用于不包含任何时区本地政治规则的 ECMAScript 实现)在被调用时执行以下步骤:

  1. 断言:timeZoneIdentifier"UTC"
  2. 返回 0。
Note

时区偏移值可以为正,也可以为负。

21.4.1.22 Time Zone Identifier Record

Time Zone Identifier Record 是一种 Record,用于描述可用命名时区标识符及其对应的主时区标识符

Time Zone Identifier Record 具有 Table 60 中列出的字段。

Table 60: Time Zone Identifier Record 字段
字段名 含义
[[Identifier]] a String 实现支持的可用命名时区标识符
[[PrimaryIdentifier]] a String [[Identifier]] 解析到的主时区标识符
Note

如果 [[Identifier]]主时区标识符,则 [[Identifier]] 就是 [[PrimaryIdentifier]]

21.4.1.23 AvailableNamedTimeZoneIdentifiers ( )

The implementation-defined abstract operation AvailableNamedTimeZoneIdentifiers takes no arguments and returns a List of Time Zone Identifier Records. 其结果描述此实现中的所有可用命名时区标识符,以及每个可用命名时区标识符对应的主时区标识符。 该 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. primaryidentifier
    2. 如果 identifier 是此实现中的非主时区标识符,且 identifier 不是 "UTC",则
      1. primary 设置为与 identifier 关联的主时区标识符
      2. 注:实现可能需要迭代解析 identifier,以获得主时区标识符
    3. recordTime 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 ( )

The implementation-defined abstract operation SystemTimeZoneIdentifier takes no arguments and returns a String. 它返回一个表示宿主环境当前时区的 String,该 String 要么是表示 UTC 偏移且使 IsTimeZoneOffsetString 返回 true 的 String,要么是主时区标识符。 It performs the following steps when called:

  1. 如果实现只支持 UTC 时区,则返回 "UTC"
  2. systemTimeZoneString 为表示宿主环境当前时区的 String,它要么是主时区标识符,要么是偏移时区标识符。
  3. 返回 systemTimeZoneString
Note

为确保实现通常在 Date 对象方法中提供的功能水平,建议 SystemTimeZoneIdentifier 返回与宿主环境时区设置对应的 IANA 时区名称,如果存在这样的名称。 如果该时区存在标准时和夏令时的本地政治规则,则 GetNamedTimeZoneEpochNanosecondsGetNamedTimeZoneOffsetNanoseconds 必须反映这些规则。

例如,如果宿主环境是在用户已选择美国东部时间作为其时区的系统上的浏览器,则 SystemTimeZoneIdentifier 返回 "America/New_York"

21.4.1.25 LocalTime ( tv )

The abstract operation LocalTime takes argument tv (a finite time value) and returns an integral Number. 它将 tv 从 UTC 转换为本地时间。 应使用 tv 处生效的标准时和夏令时本地政治规则,按本节规定的方式确定结果。 It performs the following steps when called:

  1. systemTimeZoneIdentifierSystemTimeZoneIdentifier()。
  2. 如果 IsTimeZoneOffsetString(systemTimeZoneIdentifier) 是 true,则
    1. offsetNsParseTimeZoneOffsetString(systemTimeZoneIdentifier)。
  3. 否则,
    1. offsetNsGetNamedTimeZoneOffsetNanoseconds(systemTimeZoneIdentifier, ((tv) × 106))。
  4. offsetMstruncate(offsetNs / 106)。
  5. 返回 tv + 𝔽(offsetMs)。
Note 1

如果实现内没有本地时间 tv 的政治规则,则结果为 tv,因为 SystemTimeZoneIdentifier 返回 "UTC"GetNamedTimeZoneOffsetNanoseconds 返回 0。

Note 2

要求时区感知实现(并建议所有其他实现)使用 IANA Time Zone Database 的时区信息 https://www.iana.org/time-zones/

Note 3

两个不同的输入时间值 tvUTC 会在负时区转换处存在重复时间时(例如夏令时结束或时区调整减少时)转换为相同本地时间 tlocal

LocalTime(UTC(tvlocal)) 不一定总是等于 tvlocal。相应地,UTC(LocalTime(tvUTC)) 也不一定总是等于 tvUTC

21.4.1.26 UTC ( t )

The abstract operation UTC takes argument t (a Number) and returns a time value. 它将 t 从本地时间转换为 UTC 时间值。 应使用 t 处生效的标准时和夏令时本地政治规则,按本节规定的方式确定结果。 It performs the following steps when called:

  1. 如果 t 不是有限的,则返回 NaN
  2. systemTimeZoneIdentifierSystemTimeZoneIdentifier()。
  3. 如果 IsTimeZoneOffsetString(systemTimeZoneIdentifier) 是 true,则
    1. offsetNsParseTimeZoneOffsetString(systemTimeZoneIdentifier)。
  4. 否则,
    1. possibleInstantsGetNamedTimeZoneEpochNanoseconds(systemTimeZoneIdentifier, (YearFromTime(t)), (MonthFromTime(t)) + 1, (DateFromTime(t)), (HourFromTime(t)), (MinFromTime(t)), (SecFromTime(t)), (msFromTime(t)), 0, 0)。
    2. 注:以下步骤确保当 t 表示在负时区转换处重复多次的本地时间(例如夏令时结束时,或因时区规则变更而时区偏移减少时)或在正时区转换处被跳过的本地时间(例如夏令时开始时,或因时区规则变更而时区偏移增加时)时,t 会使用转换之前的时区偏移来解释。
    3. 如果 possibleInstants 非空,则
      1. disambiguatedInstantpossibleInstants[0]。
    4. 否则,
      1. 注:t 表示在正时区转换处被跳过的本地时间(例如由于夏令时开始或时区规则变更增加 UTC 偏移)。
      2. possibleInstantsBeforeGetNamedTimeZoneEpochNanoseconds(systemTimeZoneIdentifier, (YearFromTime(tBefore)), (MonthFromTime(tBefore)) + 1, (DateFromTime(tBefore)), (HourFromTime(tBefore)), (MinFromTime(tBefore)), (SecFromTime(tBefore)), (msFromTime(tBefore)), 0, 0),其中 tBefore 是小于 t 且使 possibleInstantsBefore 非空的最大整数 Number(即,tBefore 表示转换前的最后一个本地时间)。
      3. disambiguatedInstantpossibleInstantsBefore 的最后一个元素。
    5. offsetNsGetNamedTimeZoneOffsetNanoseconds(systemTimeZoneIdentifier, disambiguatedInstant)。
  5. offsetMstruncate(offsetNs / 106)。
  6. 返回 t - 𝔽(offsetMs)。

输入 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。

Note 1

要求时区感知实现(并建议所有其他实现)使用 IANA Time Zone Database 的时区信息 https://www.iana.org/time-zones/

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)))) 中,offsetMs 的值是 -4 × msPerHour

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)))) 中,offsetMs 的值是 -5 × msPerHour

Note 2

UTC(LocalTime(tUTC)) 不一定总是等于 tUTC。相应地,LocalTime(UTC(tlocal)) 也不一定总是等于 tlocal

21.4.1.27 MakeTime ( hour, min, sec, ms )

The abstract operation MakeTime takes arguments hour (a Number), min (a Number), sec (a Number), and ms (a Number) and returns a Number. 它计算毫秒数。 It performs the following steps when called:

  1. 如果 hour 不是有限的、min 不是有限的、sec 不是有限的,或 ms 不是有限的,则返回 NaN
  2. h𝔽(! ToIntegerOrInfinity(hour))。
  3. m𝔽(! ToIntegerOrInfinity(min))。
  4. s𝔽(! ToIntegerOrInfinity(sec))。
  5. milli𝔽(! ToIntegerOrInfinity(ms))。
  6. 返回 ((h × msPerHour + m × msPerMinute) + s × msPerSecond) + milli
Note

MakeTime 中的算术是浮点算术,不满足结合律,因此操作必须按正确顺序执行。

21.4.1.28 MakeDay ( year, month, date )

The abstract operation MakeDay takes arguments year (a Number), month (a Number), and date (a Number) and returns a finite Number or NaN. 它计算天数。 It performs the following steps when called:

  1. 如果 year 不是有限的、month 不是有限的,或 date 不是有限的,则返回 NaN
  2. y𝔽(! ToIntegerOrInfinity(year))。
  3. m𝔽(! ToIntegerOrInfinity(month))。
  4. dt𝔽(! ToIntegerOrInfinity(date))。
  5. ymy + 𝔽(floor((m) / 12))。
  6. 如果 ym 不是有限的,则返回 NaN
  7. mn𝔽((m) modulo 12)。
  8. 找到一个有限时间值 tv,使得 YearFromTime(tv) 是 ymMonthFromTime(tv) 是 mn,并且 DateFromTime(tv) 是 1𝔽;但如果这不可能(因为某个实参超出范围),则返回 NaN
  9. 返回 Day(tv) + dt - 1𝔽

21.4.1.29 MakeDate ( day, time )

The abstract operation MakeDate takes arguments day (a Number) and time (a Number) and returns a finite Number or NaN. 它计算毫秒数。 It performs the following steps when called:

  1. 如果 day 不是有限的或 time 不是有限的,则返回 NaN
  2. tvday × msPerDay + time
  3. 如果 tv 不是有限的,则返回 NaN
  4. 返回 tv

21.4.1.30 MakeFullYear ( year )

The abstract operation MakeFullYear takes argument year (a Number) and returns an integral Number or NaN. 它返回与 year 的整数部分关联的完整年份,将从 0 到 99 的闭区间内的任何值解释为自 1900 年开始以来的年数。为与预推格里高利历对齐,“完整年份”定义为自年份 0(公元前 1 年)开始以来的完整年数的带符号计数。 It performs the following steps when called:

  1. 如果 yearNaN+∞𝔽-∞𝔽 之一,则返回 NaN
  2. truncated 为 ! ToIntegerOrInfinity(year)。
  3. 如果 truncated 在从 0 到 99 的闭区间内,则返回 1900𝔽 + 𝔽(truncated)。
  4. 返回 𝔽(truncated)。

21.4.1.31 TimeClip ( time )

The abstract operation TimeClip takes argument time (a Number) and returns a time value. 它计算毫秒数。 It performs the following steps when called:

  1. 如果 time 不是有限的,则返回 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
        

包含越界元素或不符合格式元素的字符串,不是此格式的有效实例。

Note 1

由于每天都以午夜开始并以午夜结束,记法 00:0024:00 可用于区分可与一个日期关联的两个午夜。这意味着以下两个记法指代完全相同的时间点:1995-02-04T24:001995-02-05T00:00。后一种形式作为“日历日结束”的这种解释与 ISO 8601 一致,尽管该规范将其保留用于描述时间区间,并且不允许在单个时间点的表示中使用它。

Note 2

不存在指定 CET、EST 等民用时区缩写的国际标准,并且有时同一个缩写甚至会用于两个非常不同的时区。因此,ISO 8601 和此格式都指定时区偏移的数字表示。

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,且不会回退到实现特定行为或启发式规则。

Note

带扩展年份的 date-time values 示例:

-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 )

The abstract operation IsTimeZoneOffsetString takes argument offsetString (a String) and returns a Boolean. 返回值指示 offsetString 是否符合 UTCOffset 给出的文法。 It performs the following steps when called:

  1. parseResultParseText(offsetString, UTCOffset)。
  2. 如果 parseResult 是错误列表,则返回 false
  3. 返回 true

21.4.1.33.2 ParseTimeZoneOffsetString ( offsetString )

The abstract operation ParseTimeZoneOffsetString takes argument offsetString (a String) and returns an integer. 返回值是与 String offsetString 对应的 UTC 偏移,表示为纳秒数。 It performs the following steps when called:

  1. parseResultParseText(offsetString, UTCOffset)。
  2. 断言:parseResult 不是错误列表。
  3. 断言:parseResult 包含一个 ASCIISign Parse Node
  4. parsedSignparseResult包含ASCIISign Parse Node匹配的源文本
  5. 如果 parsedSign 是单个码点 U+002D(HYPHEN-MINUS),则
    1. sign 为 -1。
  6. 否则,
    1. sign 为 1。
  7. 注:下面 StringToNumber 的应用不会损失精度,因为每个被解析的值都保证是足够短的十进制数字字符串。
  8. 断言:parseResult 包含一个 Hour Parse Node
  9. parsedHoursparseResult包含Hour Parse Node匹配的源文本
  10. hours(StringToNumber(CodePointsToString(parsedHours)))。
  11. 如果 parseResult包含 MinuteSecond Parse Node,则
    1. minutes 为 0。
  12. 否则,
    1. parsedMinutesparseResult包含的第一个 MinuteSecond Parse Node匹配的源文本
    2. minutes(StringToNumber(CodePointsToString(parsedMinutes)))。
  13. 如果 parseResult包含两个 MinuteSecond Parse Node,则
    1. seconds 为 0。
  14. 否则,
    1. parsedSecondsparseResult包含的第二个 MinuteSecond Parse Node匹配的源文本
    2. seconds(StringToNumber(CodePointsToString(parsedSeconds)))。
  15. 如果 parseResult包含 TemporalDecimalFraction Parse Node,则
    1. nanoseconds 为 0。
  16. 否则,
    1. parsedFractionparseResult包含TemporalDecimalFraction Parse Node匹配的源文本
    2. fractionCodePointsToString(parsedFraction) 和 "000000000"字符串连接
    3. nanosecondsStringfraction 从 1 到 10 的子字符串
    4. nanoseconds(StringToNumber(nanosecondsString))。
  17. 返回 sign × (((hours × 60 + minutes) × 60 + seconds) × 109 + 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. numberOfArgsvalues 中元素的数量。
  3. 如果 numberOfArgs = 0,则
    1. dv 为标识当前时间的时间值(UTC)。
  4. 否则,如果 numberOfArgs = 1,则
    1. valuevalues[0]。
    2. 如果 value 是 Object 且 value 具有 [[DateValue]] 内部槽,则
      1. tvvalue.[[DateValue]]
    3. 否则,
      1. v 为 ? ToPrimitive(value)。
      2. 如果 v 是 String,则
        1. 断言:下一步永远不会返回 abrupt completion,因为 v 是 String。
        2. tv 为把 v 解析为日期的结果,其方式与 parse 方法(21.4.3.2)完全相同。
      3. 否则,
        1. tv 为 ? ToNumber(v)。
    4. dvTimeClip(tv)。
  5. 否则,
    1. 断言:numberOfArgs ≥ 2。
    2. y 为 ? ToNumber(values[0])。
    3. m 为 ? ToNumber(values[1])。
    4. 如果 numberOfArgs > 2,则令 dt 为 ? ToNumber(values[2]);否则令 dt1𝔽
    5. 如果 numberOfArgs > 3,则令 h 为 ? ToNumber(values[3]);否则令 h+0𝔽
    6. 如果 numberOfArgs > 4,则令 min 为 ? ToNumber(values[4]);否则令 min+0𝔽
    7. 如果 numberOfArgs > 5,则令 s 为 ? ToNumber(values[5]);否则令 s+0𝔽
    8. 如果 numberOfArgs > 6,则令 milli 为 ? ToNumber(values[6]);否则令 milli+0𝔽
    9. yrMakeFullYear(y)。
    10. finalDateMakeDate(MakeDay(yr, m, dt), MakeTime(h, min, s, milli))。
    11. dvTimeClip(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 产生 abrupt completion,则立即返回该 Completion Record。否则,此函数把所得 String 解释为日期和时间;它返回一个 Number,即与该日期和时间对应的 UTC 时间值。取决于 String 的内容,该 String 可以被解释为本地时间、UTC 时间,或某个其他时区中的时间。此函数首先尝试按照日期时间字符串格式(21.4.1.32)中描述的格式解析该 String,包括扩展年份。如果该 String 不符合该格式,则函数可以回退到任何实现特定的启发式规则或实现特定日期格式。不可识别或包含越界格式元素值的 String 应导致此函数返回 NaN

如果该 String 符合日期时间字符串格式,则替代值会替代缺失的格式元素。当 MMDD 元素缺失时,使用 "01"。当 HHmmss 元素缺失时,使用 "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)且无法由该实现中的 toStringtoUTCString 方法产生的 String 值时,此函数产生的值是由实现定义的

21.4.3.3 Date.prototype

Date.prototype 的初始值是 Date 原型对象

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.4.3.4 Date.UTC ( year [ , month [ , date [ , hours [ , minutes [ , seconds [ , ms ] ] ] ] ] ] )

此函数在被调用时执行以下步骤:

  1. y 为 ? ToNumber(year)。
  2. 如果 month 存在,则令 m 为 ? ToNumber(month);否则令 m+0𝔽
  3. 如果 date 存在,则令 dt 为 ? ToNumber(date);否则令 dt1𝔽
  4. 如果 hours 存在,则令 h 为 ? ToNumber(hours);否则令 h+0𝔽
  5. 如果 minutes 存在,则令 min 为 ? ToNumber(minutes);否则令 min+0𝔽
  6. 如果 seconds 存在,则令 s 为 ? ToNumber(seconds);否则令 s+0𝔽
  7. 如果 ms 存在,则令 milli 为 ? ToNumber(ms);否则令 milli+0𝔽
  8. yrMakeFullYear(y)。
  9. 返回 TimeClip(MakeDate(MakeDay(yr, m, dt), MakeTime(h, min, s, milli)))。

此函数的 "length" 属性是 7𝔽

Note

此函数与 Date 构造器有两点不同:它返回一个作为 Number 的时间值,而不是创建 Date;并且它把实参解释为 UTC,而不是本地时间。

21.4.4 Date 原型对象的属性

Date 原型对象

  • %Date.prototype%
  • 自身是普通对象
  • 不是 Date 实例,并且没有 [[DateValue]] 内部槽。
  • 具有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%

除非另有明确定义,下文定义的 Date 原型对象方法不是泛型的,并且传给它们的 this 值必须是一个对象,该对象具有已初始化为时间值[[DateValue]] 内部槽。

21.4.4.1 Date.prototype.constructor

Date.prototype.constructor 的初始值是 %Date%

21.4.4.2 Date.prototype.getDate ( )

此方法在被调用时执行以下步骤:

  1. dateObjthis value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. tvdateObj.[[DateValue]]
  4. 如果 tvNaN,则返回 NaN
  5. 返回 DateFromTime(LocalTime(tv))。

21.4.4.3 Date.prototype.getDay ( )

此方法在被调用时执行以下步骤:

  1. dateObjthis value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. tvdateObj.[[DateValue]]
  4. 如果 tvNaN,则返回 NaN
  5. 返回 WeekDay(LocalTime(tv))。

21.4.4.4 Date.prototype.getFullYear ( )

此方法在被调用时执行以下步骤:

  1. dateObjthis value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. tvdateObj.[[DateValue]]
  4. 如果 tvNaN,则返回 NaN
  5. 返回 YearFromTime(LocalTime(tv))。

21.4.4.5 Date.prototype.getHours ( )

此方法在被调用时执行以下步骤:

  1. dateObjthis value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. tvdateObj.[[DateValue]]
  4. 如果 tvNaN,则返回 NaN
  5. 返回 HourFromTime(LocalTime(tv))。

21.4.4.6 Date.prototype.getMilliseconds ( )

此方法在被调用时执行以下步骤:

  1. dateObjthis value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. tvdateObj.[[DateValue]]
  4. 如果 tvNaN,则返回 NaN
  5. 返回 msFromTime(LocalTime(tv))。

21.4.4.7 Date.prototype.getMinutes ( )

此方法在被调用时执行以下步骤:

  1. dateObjthis value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. tvdateObj.[[DateValue]]
  4. 如果 tvNaN,则返回 NaN
  5. 返回 MinFromTime(LocalTime(tv))。

21.4.4.8 Date.prototype.getMonth ( )

此方法在被调用时执行以下步骤:

  1. dateObjthis value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. tvdateObj.[[DateValue]]
  4. 如果 tvNaN,则返回 NaN
  5. 返回 MonthFromTime(LocalTime(tv))。

21.4.4.9 Date.prototype.getSeconds ( )

此方法在被调用时执行以下步骤:

  1. dateObjthis value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. tvdateObj.[[DateValue]]
  4. 如果 tvNaN,则返回 NaN
  5. 返回 SecFromTime(LocalTime(tv))。

21.4.4.10 Date.prototype.getTime ( )

此方法在被调用时执行以下步骤:

  1. dateObjthis value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. 返回 dateObj.[[DateValue]]

21.4.4.11 Date.prototype.getTimezoneOffset ( )

此方法在被调用时执行以下步骤:

  1. dateObjthis value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. tvdateObj.[[DateValue]]
  4. 如果 tvNaN,则返回 NaN
  5. 返回 (tv - LocalTime(tv)) / msPerMinute

21.4.4.12 Date.prototype.getUTCDate ( )

此方法在被调用时执行以下步骤:

  1. dateObjthis value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. tvdateObj.[[DateValue]]
  4. 如果 tvNaN,则返回 NaN
  5. 返回 DateFromTime(tv)。

21.4.4.13 Date.prototype.getUTCDay ( )

此方法在被调用时执行以下步骤:

  1. dateObjthis value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. tvdateObj.[[DateValue]]
  4. 如果 tvNaN,则返回 NaN
  5. 返回 WeekDay(tv)。

21.4.4.14 Date.prototype.getUTCFullYear ( )

此方法在被调用时执行以下步骤:

  1. dateObjthis value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. tvdateObj.[[DateValue]]
  4. 如果 tvNaN,则返回 NaN
  5. 返回 YearFromTime(tv)。

21.4.4.15 Date.prototype.getUTCHours ( )

此方法在被调用时执行以下步骤:

  1. dateObjthis value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. tvdateObj.[[DateValue]]
  4. 如果 tvNaN,则返回 NaN
  5. 返回 HourFromTime(tv)。

21.4.4.16 Date.prototype.getUTCMilliseconds ( )

此方法在被调用时执行以下步骤:

  1. dateObjthis value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. tvdateObj.[[DateValue]]
  4. 如果 tvNaN,则返回 NaN
  5. 返回 msFromTime(tv)。

21.4.4.17 Date.prototype.getUTCMinutes ( )

此方法在被调用时执行以下步骤:

  1. dateObjthis value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. tvdateObj.[[DateValue]]
  4. 如果 tvNaN,则返回 NaN
  5. 返回 MinFromTime(tv)。

21.4.4.18 Date.prototype.getUTCMonth ( )

此方法在被调用时执行以下步骤:

  1. dateObjthis value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. tvdateObj.[[DateValue]]
  4. 如果 tvNaN,则返回 NaN
  5. 返回 MonthFromTime(tv)。

21.4.4.19 Date.prototype.getUTCSeconds ( )

此方法在被调用时执行以下步骤:

  1. dateObjthis value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. tvdateObj.[[DateValue]]
  4. 如果 tvNaN,则返回 NaN
  5. 返回 SecFromTime(tv)。

21.4.4.20 Date.prototype.setDate ( date )

此方法在被调用时执行以下步骤:

  1. dateObjthis value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. tvdateObj.[[DateValue]]
  4. dt 为 ? ToNumber(date)。
  5. 如果 tvNaN,则返回 NaN
  6. tv 设置为 LocalTime(tv)。
  7. newDateMakeDate(MakeDay(YearFromTime(tv), MonthFromTime(tv), dt), TimeWithinDay(tv))。
  8. uTimeClip(UTC(newDate))。
  9. dateObj.[[DateValue]] 设置为 u
  10. 返回 u

21.4.4.21 Date.prototype.setFullYear ( year [ , month [ , date ] ] )

此方法在被调用时执行以下步骤:

  1. dateObjthis value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. tvdateObj.[[DateValue]]
  4. y 为 ? ToNumber(year)。
  5. 如果 tvNaN,则将 tv 设置为 +0𝔽;否则将 tv 设置为 LocalTime(tv)。
  6. 如果 month 存在,则令 m 为 ? ToNumber(month);否则令 mMonthFromTime(tv)。
  7. 如果 date 存在,则令 dt 为 ? ToNumber(date);否则令 dtDateFromTime(tv)。
  8. newDateMakeDate(MakeDay(y, m, dt), TimeWithinDay(tv))。
  9. uTimeClip(UTC(newDate))。
  10. dateObj.[[DateValue]] 设置为 u
  11. 返回 u

此方法的 "length" 属性是 3𝔽

Note

如果 month 不存在,此方法表现得仿佛 month 存在且其值为 getMonth()。如果 date 不存在,它表现得仿佛 date 存在且其值为 getDate()

21.4.4.22 Date.prototype.setHours ( hour [ , min [ , sec [ , ms ] ] ] )

此方法在被调用时执行以下步骤:

  1. dateObjthis value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. tvdateObj.[[DateValue]]
  4. h 为 ? ToNumber(hour)。
  5. 如果 min 存在,则令 m 为 ? ToNumber(min)。
  6. 如果 sec 存在,则令 s 为 ? ToNumber(sec)。
  7. 如果 ms 存在,则令 milli 为 ? ToNumber(ms)。
  8. 如果 tvNaN,则返回 NaN
  9. tv 设置为 LocalTime(tv)。
  10. 如果 min 不存在,则令 mMinFromTime(tv)。
  11. 如果 sec 不存在,则令 sSecFromTime(tv)。
  12. 如果 ms 不存在,则令 millimsFromTime(tv)。
  13. dateMakeDate(Day(tv), MakeTime(h, m, s, milli))。
  14. uTimeClip(UTC(date))。
  15. dateObj.[[DateValue]] 设置为 u
  16. 返回 u

此方法的 "length" 属性是 4𝔽

Note

如果 min 不存在,此方法表现得仿佛 min 存在且其值为 getMinutes()。如果 sec 不存在,它表现得仿佛 sec 存在且其值为 getSeconds()。如果 ms 不存在,它表现得仿佛 ms 存在且其值为 getMilliseconds()

21.4.4.23 Date.prototype.setMilliseconds ( ms )

此方法在被调用时执行以下步骤:

  1. dateObjthis value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. tvdateObj.[[DateValue]]
  4. ms 设置为 ? ToNumber(ms)。
  5. 如果 tvNaN,则返回 NaN
  6. tv 设置为 LocalTime(tv)。
  7. timeMakeTime(HourFromTime(tv), MinFromTime(tv), SecFromTime(tv), ms)。
  8. uTimeClip(UTC(MakeDate(Day(tv), time)))。
  9. dateObj.[[DateValue]] 设置为 u
  10. 返回 u

21.4.4.24 Date.prototype.setMinutes ( min [ , sec [ , ms ] ] )

此方法在被调用时执行以下步骤:

  1. dateObjthis value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. tvdateObj.[[DateValue]]
  4. m 为 ? ToNumber(min)。
  5. 如果 sec 存在,则令 s 为 ? ToNumber(sec)。
  6. 如果 ms 存在,则令 milli 为 ? ToNumber(ms)。
  7. 如果 tvNaN,则返回 NaN
  8. tv 设置为 LocalTime(tv)。
  9. 如果 sec 不存在,则令 sSecFromTime(tv)。
  10. 如果 ms 不存在,则令 millimsFromTime(tv)。
  11. dateMakeDate(Day(tv), MakeTime(HourFromTime(tv), m, s, milli))。
  12. uTimeClip(UTC(date))。
  13. dateObj.[[DateValue]] 设置为 u
  14. 返回 u

此方法的 "length" 属性是 3𝔽

Note

如果 sec 不存在,此方法表现得仿佛 sec 存在且其值为 getSeconds()。如果 ms 不存在,它表现得仿佛 ms 存在且其值为 getMilliseconds()

21.4.4.25 Date.prototype.setMonth ( month [ , date ] )

此方法在被调用时执行以下步骤:

  1. dateObjthis value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. tvdateObj.[[DateValue]]
  4. m 为 ? ToNumber(month)。
  5. 如果 date 存在,则令 dt 为 ? ToNumber(date)。
  6. 如果 tvNaN,则返回 NaN
  7. tv 设置为 LocalTime(tv)。
  8. 如果 date 不存在,则令 dtDateFromTime(tv)。
  9. newDateMakeDate(MakeDay(YearFromTime(tv), m, dt), TimeWithinDay(tv))。
  10. uTimeClip(UTC(newDate))。
  11. dateObj.[[DateValue]] 设置为 u
  12. 返回 u

此方法的 "length" 属性是 2𝔽

Note

如果 date 不存在,此方法表现得仿佛 date 存在且其值为 getDate()

21.4.4.26 Date.prototype.setSeconds ( sec [ , ms ] )

此方法在被调用时执行以下步骤:

  1. dateObjthis value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. tvdateObj.[[DateValue]]
  4. s 为 ? ToNumber(sec)。
  5. 如果 ms 存在,则令 milli 为 ? ToNumber(ms)。
  6. 如果 tvNaN,则返回 NaN
  7. tv 设置为 LocalTime(tv)。
  8. 如果 ms 不存在,则令 millimsFromTime(tv)。
  9. dateMakeDate(Day(tv), MakeTime(HourFromTime(tv), MinFromTime(tv), s, milli))。
  10. uTimeClip(UTC(date))。
  11. dateObj.[[DateValue]] 设置为 u
  12. 返回 u

此方法的 "length" 属性是 2𝔽

Note

如果 ms 不存在,此方法表现得仿佛 ms 存在且其值为 getMilliseconds()

21.4.4.27 Date.prototype.setTime ( time )

此方法在被调用时执行以下步骤:

  1. dateObjthis value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. t 为 ? ToNumber(time)。
  4. vTimeClip(t)。
  5. dateObj.[[DateValue]] 设置为 v
  6. 返回 v

21.4.4.28 Date.prototype.setUTCDate ( date )

此方法在被调用时执行以下步骤:

  1. dateObjthis value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. tvdateObj.[[DateValue]]
  4. dt 为 ? ToNumber(date)。
  5. 如果 tvNaN,则返回 NaN
  6. newDateMakeDate(MakeDay(YearFromTime(tv), MonthFromTime(tv), dt), TimeWithinDay(tv))。
  7. vTimeClip(newDate)。
  8. dateObj.[[DateValue]] 设置为 v
  9. 返回 v

21.4.4.29 Date.prototype.setUTCFullYear ( year [ , month [ , date ] ] )

此方法在被调用时执行以下步骤:

  1. dateObjthis value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. tvdateObj.[[DateValue]]
  4. 如果 tvNaN,则将 tv 设置为 +0𝔽
  5. y 为 ? ToNumber(year)。
  6. 如果 month 存在,则令 m 为 ? ToNumber(month);否则令 mMonthFromTime(tv)。
  7. 如果 date 存在,则令 dt 为 ? ToNumber(date);否则令 dtDateFromTime(tv)。
  8. newDateMakeDate(MakeDay(y, m, dt), TimeWithinDay(tv))。
  9. vTimeClip(newDate)。
  10. dateObj.[[DateValue]] 设置为 v
  11. 返回 v

此方法的 "length" 属性是 3𝔽

Note

如果 month 不存在,此方法表现得仿佛 month 存在且其值为 getUTCMonth()。如果 date 不存在,它表现得仿佛 date 存在且其值为 getUTCDate()

21.4.4.30 Date.prototype.setUTCHours ( hour [ , min [ , sec [ , ms ] ] ] )

此方法在被调用时执行以下步骤:

  1. dateObjthis value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. tvdateObj.[[DateValue]]
  4. h 为 ? ToNumber(hour)。
  5. 如果 min 存在,则令 m 为 ? ToNumber(min)。
  6. 如果 sec 存在,则令 s 为 ? ToNumber(sec)。
  7. 如果 ms 存在,则令 milli 为 ? ToNumber(ms)。
  8. 如果 tvNaN,则返回 NaN
  9. 如果 min 不存在,则令 mMinFromTime(tv)。
  10. 如果 sec 不存在,则令 sSecFromTime(tv)。
  11. 如果 ms 不存在,则令 millimsFromTime(tv)。
  12. dateMakeDate(Day(tv), MakeTime(h, m, s, milli))。
  13. vTimeClip(date)。
  14. dateObj.[[DateValue]] 设置为 v
  15. 返回 v

此方法的 "length" 属性是 4𝔽

Note

如果 min 不存在,此方法表现得仿佛 min 存在且其值为 getUTCMinutes()。如果 sec 不存在,它表现得仿佛 sec 存在且其值为 getUTCSeconds()。如果 ms 不存在,它表现得仿佛 ms 存在且其值为 getUTCMilliseconds()

21.4.4.31 Date.prototype.setUTCMilliseconds ( ms )

此方法在被调用时执行以下步骤:

  1. dateObjthis value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. tvdateObj.[[DateValue]]
  4. ms 设置为 ? ToNumber(ms)。
  5. 如果 tvNaN,则返回 NaN
  6. timeMakeTime(HourFromTime(tv), MinFromTime(tv), SecFromTime(tv), ms)。
  7. vTimeClip(MakeDate(Day(tv), time))。
  8. dateObj.[[DateValue]] 设置为 v
  9. 返回 v

21.4.4.32 Date.prototype.setUTCMinutes ( min [ , sec [ , ms ] ] )

此方法在被调用时执行以下步骤:

  1. dateObjthis value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. tvdateObj.[[DateValue]]
  4. m 为 ? ToNumber(min)。
  5. 如果 sec 存在,则令 s 为 ? ToNumber(sec)。
  6. 如果 ms 存在,则令 milli 为 ? ToNumber(ms)。
  7. 如果 tvNaN,则返回 NaN
  8. 如果 sec 不存在,则令 sSecFromTime(tv)。
  9. 如果 ms 不存在,则令 millimsFromTime(tv)。
  10. dateMakeDate(Day(tv), MakeTime(HourFromTime(tv), m, s, milli))。
  11. vTimeClip(date)。
  12. dateObj.[[DateValue]] 设置为 v
  13. 返回 v

此方法的 "length" 属性是 3𝔽

Note

如果 sec 不存在,此方法表现得仿佛 sec 存在且其值为 getUTCSeconds()。如果 ms 不存在,它表现得仿佛 ms 存在且其值为 getUTCMilliseconds() 返回的值。

21.4.4.33 Date.prototype.setUTCMonth ( month [ , date ] )

此方法在被调用时执行以下步骤:

  1. dateObjthis value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. tvdateObj.[[DateValue]]
  4. m 为 ? ToNumber(month)。
  5. 如果 date 存在,则令 dt 为 ? ToNumber(date)。
  6. 如果 tvNaN,则返回 NaN
  7. 如果 date 不存在,则令 dtDateFromTime(tv)。
  8. newDateMakeDate(MakeDay(YearFromTime(tv), m, dt), TimeWithinDay(tv))。
  9. vTimeClip(newDate)。
  10. dateObj.[[DateValue]] 设置为 v
  11. 返回 v

此方法的 "length" 属性是 2𝔽

Note

如果 date 不存在,此方法表现得仿佛 date 存在且其值为 getUTCDate()

21.4.4.34 Date.prototype.setUTCSeconds ( sec [ , ms ] )

此方法在被调用时执行以下步骤:

  1. dateObjthis value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. tvdateObj.[[DateValue]]
  4. s 为 ? ToNumber(sec)。
  5. 如果 ms 存在,则令 milli 为 ? ToNumber(ms)。
  6. 如果 tvNaN,则返回 NaN
  7. 如果 ms 不存在,则令 millimsFromTime(tv)。
  8. dateMakeDate(Day(tv), MakeTime(HourFromTime(tv), MinFromTime(tv), s, milli))。
  9. vTimeClip(date)。
  10. dateObj.[[DateValue]] 设置为 v
  11. 返回 v

此方法的 "length" 属性是 2𝔽

Note

如果 ms 不存在,此方法表现得仿佛 ms 存在且其值为 getUTCMilliseconds()

21.4.4.35 Date.prototype.toDateString ( )

此方法在被调用时执行以下步骤:

  1. dateObjthis value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. tvdateObj.[[DateValue]]
  4. 如果 tvNaN,则返回 "Invalid Date"
  5. tLocalTime(tv)。
  6. 返回 DateString(t)。

21.4.4.36 Date.prototype.toISOString ( )

此方法在被调用时执行以下步骤:

  1. dateObjthis value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. tvdateObj.[[DateValue]]
  4. 如果 tvNaN,则抛出 RangeError 异常。
  5. 断言:tv 是整数 Number。
  6. 如果 tv 对应于不能在日期时间字符串格式中表示的年份,则抛出 RangeError 异常。
  7. 返回 tv 在 UTC 时间尺度上的日期时间字符串格式中的 String 表示,包括所有格式元素和 UTC 偏移表示 "Z"

21.4.4.37 Date.prototype.toJSON ( key )

此方法提供 Date 的 String 表示,以供 JSON.stringify25.5.4)使用。

它在被调用时执行以下步骤:

  1. obj 为 ? ToObject(this value)。
  2. tv 为 ? ToPrimitive(obj, number)。
  3. 如果 tv 是 Number 且 tv 不是有限的,则返回 null
  4. 返回 ? Invoke(obj, "toISOString")。
Note 1

该实参会被忽略。

Note 2

此方法有意设计为泛型的;它不要求其 this 值是 Date。因此,它可以被转移到其他种类的对象上作为方法使用。不过,它要求任何这样的对象都具有 toISOString 方法。

21.4.4.38 Date.prototype.toLocaleDateString ( [ reserved1 [ , reserved2 ] ] )

包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按 ECMA-402 规范中的规定实现此方法。如果 ECMAScript 实现不包含 ECMA-402 API,则使用此方法的以下规范:

此方法返回一个 String 值。该 String 的内容由实现定义,但旨在以方便且人类可读的形式表示当前时区中 Date 的“日期”部分,并对应于宿主环境当前区域设置的约定。

此方法可选参数的含义在 ECMA-402 规范中定义;不包含 ECMA-402 支持的实现不得把这些参数位置用于任何其他用途。

21.4.4.39 Date.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] )

包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按 ECMA-402 规范中的规定实现此方法。如果 ECMAScript 实现不包含 ECMA-402 API,则使用此方法的以下规范:

此方法返回一个 String 值。该 String 的内容由实现定义,但旨在以方便且人类可读的形式表示当前时区中的 Date,并对应于宿主环境当前区域设置的约定。

此方法可选参数的含义在 ECMA-402 规范中定义;不包含 ECMA-402 支持的实现不得把这些参数位置用于任何其他用途。

21.4.4.40 Date.prototype.toLocaleTimeString ( [ reserved1 [ , reserved2 ] ] )

包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按 ECMA-402 规范中的规定实现此方法。如果 ECMAScript 实现不包含 ECMA-402 API,则使用此方法的以下规范:

此方法返回一个 String 值。该 String 的内容由实现定义,但旨在以方便且人类可读的形式表示当前时区中 Date 的“时间”部分,并对应于宿主环境当前区域设置的约定。

此方法可选参数的含义在 ECMA-402 规范中定义;不包含 ECMA-402 支持的实现不得把这些参数位置用于任何其他用途。

21.4.4.41 Date.prototype.toString ( )

此方法在被调用时执行以下步骤:

  1. dateObjthis value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. tvdateObj.[[DateValue]]
  4. 返回 ToDateString(tv)。
Note 1

对于任何 Date d,如果 d.[[DateValue]] 可被 1000 整除,则 Date.parse(d.toString()) 的结果 = d.valueOf()。见 21.4.3.2

Note 2

此方法不是泛型的;如果其 this 值不是 Date,它会抛出 TypeError 异常。因此,它不能被转移到其他种类的对象上作为方法使用。

21.4.4.41.1 TimeString ( tv )

The abstract operation TimeString takes argument tv (a Number, but not NaN) and returns a String. It performs the following steps when called:

  1. hourToZeroPaddedDecimalString((HourFromTime(tv)), 2)。
  2. minuteToZeroPaddedDecimalString((MinFromTime(tv)), 2)。
  3. secondToZeroPaddedDecimalString((SecFromTime(tv)), 2)。
  4. 返回 hour":"minute":"second、码元 0x0020(SPACE)和 "GMT"字符串连接

21.4.4.41.2 DateString ( tv )

The abstract operation DateString takes argument tv (a Number, but not NaN) and returns a String. It performs the following steps when called:

  1. weekdayTable 61 中 Number 为 WeekDay(tv) 的条目的 Name。
  2. monthTable 62 中 Number 为 MonthFromTime(tv) 的条目的 Name。
  3. dayToZeroPaddedDecimalString((DateFromTime(tv)), 2)。
  4. yvYearFromTime(tv)。
  5. 如果 yv+0𝔽yv > +0𝔽,则令 yearSign 为空 String;否则令 yearSign"-"
  6. paddedYearToZeroPaddedDecimalString(abs((yv)), 4)。
  7. 返回 weekday、码元 0x0020(SPACE)、month、码元 0x0020(SPACE)、day、码元 0x0020(SPACE)、yearSignpaddedYear字符串连接
Table 61: 星期中各天的名称
Number Name
+0𝔽 "Sun"
1𝔽 "Mon"
2𝔽 "Tue"
3𝔽 "Wed"
4𝔽 "Thu"
5𝔽 "Fri"
6𝔽 "Sat"
Table 62: 一年中各月份的名称
Number Name
+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 )

The abstract operation TimeZoneString takes argument tv (an integral Number) and returns a String. It performs the following steps when called:

  1. systemTimeZoneIdentifierSystemTimeZoneIdentifier()。
  2. 如果 IsTimeZoneOffsetString(systemTimeZoneIdentifier) 是 true,则
    1. offsetNsParseTimeZoneOffsetString(systemTimeZoneIdentifier)。
  3. 否则,
    1. offsetNsGetNamedTimeZoneOffsetNanoseconds(systemTimeZoneIdentifier, ((tv) × 106))。
  4. offset𝔽(truncate(offsetNs / 106))。
  5. 如果 offset+0𝔽offset > +0𝔽,则
    1. offsetSign"+"
    2. absOffsetoffset
  6. 否则,
    1. offsetSign"-"
    2. absOffset 为 -offset
  7. offsetMinToZeroPaddedDecimalString((MinFromTime(absOffset)), 2)。
  8. offsetHourToZeroPaddedDecimalString((HourFromTime(absOffset)), 2)。
  9. tzName 为一个由实现定义的字符串,它要么是空 String,要么是码元 0x0020(SPACE)、码元 0x0028(LEFT PARENTHESIS)、一个由实现定义的时区名称和码元 0x0029(RIGHT PARENTHESIS)的字符串连接
  10. 返回 offsetSignoffsetHouroffsetMintzName字符串连接

21.4.4.41.4 ToDateString ( tv )

The abstract operation ToDateString takes argument tv (an integral Number or NaN) and returns a String. It performs the following steps when called:

  1. 如果 tvNaN,则返回 "Invalid Date"
  2. localTimeLocalTime(tv)。
  3. 返回 DateString(localTime)、码元 0x0020(SPACE)、TimeString(localTime) 和 TimeZoneString(tv) 的字符串连接

21.4.4.42 Date.prototype.toTimeString ( )

此方法在被调用时执行以下步骤:

  1. dateObjthis value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. tvdateObj.[[DateValue]]
  4. 如果 tvNaN,则返回 "Invalid Date"
  5. localTimeLocalTime(tv)。
  6. 返回 TimeString(localTime) 和 TimeZoneString(tv) 的字符串连接

21.4.4.43 Date.prototype.toUTCString ( )

此方法返回一个 String 值,表示与 this 值对应的时间瞬间。该 String 的格式基于 RFC 7231 中的 HTTP-date,并泛化为支持 ECMAScript Date 所支持的完整时间范围。

它在被调用时执行以下步骤:

  1. dateObjthis value。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. tvdateObj.[[DateValue]]
  4. 如果 tvNaN,则返回 "Invalid Date"
  5. weekdayTable 61 中 Number 为 WeekDay(tv) 的条目的 Name。
  6. monthTable 62 中 Number 为 MonthFromTime(tv) 的条目的 Name。
  7. dayToZeroPaddedDecimalString((DateFromTime(tv)), 2)。
  8. yvYearFromTime(tv)。
  9. 如果 yv+0𝔽yv > +0𝔽,则令 yearSign 为空 String;否则令 yearSign"-"
  10. paddedYearToZeroPaddedDecimalString(abs((yv)), 4)。
  11. 返回 weekday","、码元 0x0020(SPACE)、day、码元 0x0020(SPACE)、month、码元 0x0020(SPACE)、yearSignpaddedYear、码元 0x0020(SPACE)和 TimeString(tv) 的字符串连接

21.4.4.44 Date.prototype.valueOf ( )

此方法在被调用时执行以下步骤:

  1. dateObjthis 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. objthis value。
  2. 如果 obj 不是 Object,则抛出 TypeError 异常。
  3. 如果 hint"string""default",则
    1. tryFirststring
  4. 否则,如果 hint"number",则
    1. tryFirstnumber
  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 是 undefinedvalue 是 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 )

此函数可以用任意数量的实参调用,这些实参构成 rest 参数 codeUnits

它在被调用时执行以下步骤:

  1. result 为空 String。
  2. codeUnits 的每个元素 next,执行:
    1. nextCU 为数值为 (? ToUint16(next)) 的码元。
    2. result 设置为 resultnextCU字符串连接
  3. 返回 result

此函数的 "length" 属性是 1𝔽

22.1.2.2 String.fromCodePoint ( ...codePoints )

此函数可以用任意数量的实参调用,这些实参构成 rest 参数 codePoints

它在被调用时执行以下步骤:

  1. result 为空 String。
  2. codePoints 的每个元素 next,执行:
    1. nextCP 为 ? ToNumber(next)。
    2. 如果 nextCP 不是整数 Number,则抛出 RangeError 异常。
    3. 如果 (nextCP) < 0 或 (nextCP) > 0x10FFFF,则抛出 RangeError 异常。
    4. result 设置为 resultUTF16EncodeCodePoint((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. substitutionCountsubstitutions 中元素的数量。
  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 设置为 resultnextLiteral字符串连接
    4. 如果 nextIndex + 1 = literalCount,则返回 result
    5. 如果 nextIndex < substitutionCount,则
      1. nextSubValuesubstitutions[nextIndex]。
      2. nextSub 为 ? ToString(nextSubValue)。
      3. result 设置为 resultnextSub字符串连接
    6. nextIndex 设置为 nextIndex + 1。
Note

此函数旨在用作 Tagged Template(13.3.11)的标签函数。当以这种方式调用时,第一个实参将是一个格式良好的模板对象,rest 参数将包含替换值。

22.1.3 String 原型对象的属性

String 原型对象

  • %String.prototype%
  • 是 String 奇异对象,并具有为这类对象指定的内部方法。
  • 具有一个 [[StringData]] 内部槽,其值为空 String。
  • 具有一个 "length" 属性,其初始值为 +0𝔽,并且其特性为 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。
  • 具有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%

除非另有明确说明,下文定义的 String 原型对象的方法不是泛型的,并且传给它们的 this 值必须是 String 值,或是一个具有已初始化为 String 值的 [[StringData]] 内部槽的对象。

22.1.3.1 String.prototype.at ( index )

  1. thisValuethis value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. string 为 ? ToString(thisValue)。
  4. lengthstring 的长度。
  5. relativeIndex 为 ? ToIntegerOrInfinity(index)。
  6. 如果 relativeIndex ≥ 0,则
    1. krelativeIndex
  7. 否则,
    1. klength + relativeIndex
  8. 如果 k < 0 或 klength,则返回 undefined
  9. 返回 stringkk + 1 的子字符串

22.1.3.2 String.prototype.charAt ( position )

Note 1

此方法返回一个单元素 String,包含将此对象转换为 String 后所得 String 值中索引 position 处的码元。如果该索引处没有元素,则结果为空 String。结果是 String 值,而不是 String 对象。

如果 pos 是整数 Number,则 x.charAt(pos) 的结果等价于 x.substring(pos, pos + 1) 的结果。

此方法在被调用时执行以下步骤:

  1. thisValuethis value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. string 为 ? ToString(thisValue)。
  4. position 设置为 ? ToIntegerOrInfinity(position)。
  5. sizestring 的长度。
  6. 如果 position < 0 或 positionsize,则返回空 String。
  7. 返回 stringpositionposition + 1 的子字符串
Note 2

此方法有意设计为泛型的;它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

22.1.3.3 String.prototype.charCodeAt ( position )

Note 1

此方法返回一个 Number(一个小于 216 的非负整数 Number),它是将此对象转换为 String 后所得 String 中索引 position 处码元的数值。如果该索引处没有元素,则结果为 NaN

此方法在被调用时执行以下步骤:

  1. thisValuethis value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. string 为 ? ToString(thisValue)。
  4. position 设置为 ? ToIntegerOrInfinity(position)。
  5. sizestring 的长度。
  6. 如果 position < 0 或 positionsize,则返回 NaN
  7. 返回 String string 中索引 position 处码元的数值对应的 Number 值
Note 2

此方法有意设计为泛型的;它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

22.1.3.4 String.prototype.codePointAt ( position )

Note 1

此方法返回一个小于或等于 0x10FFFF𝔽 的非负整数 Number,它是将此对象转换为 String 后所得 String 中索引 position 处的字符串元素开始的 UTF-16 编码码点(6.1.4)的数值。如果该索引处没有元素,则结果为 undefined。如果有效 UTF-16 代理对不是从 position 开始,则结果为 position 处的码元。

此方法在被调用时执行以下步骤:

  1. thisValuethis value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. string 为 ? ToString(thisValue)。
  4. position 设置为 ? ToIntegerOrInfinity(position)。
  5. sizestring 的长度。
  6. 如果 position < 0 或 positionsize,则返回 undefined
  7. codePointCodePointAt(string, position)。
  8. 返回 𝔽(codePoint.[[CodePoint]])。
Note 2

此方法有意设计为泛型的;它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

22.1.3.5 String.prototype.concat ( ...args )

Note 1

调用此方法时,它返回一个 String 值,该值由 this 值(转换为 String)的码元,后跟每个实参转换为 String 后的码元组成。结果是 String 值,而不是 String 对象。

此方法在被调用时执行以下步骤:

  1. thisValuethis value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. string 为 ? ToString(thisValue)。
  4. resultstring
  5. args 的每个元素 next,执行:
    1. nextString 为 ? ToString(next)。
    2. result 设置为 resultnextString字符串连接
  6. 返回 result

此方法的 "length" 属性是 1𝔽

Note 2

此方法有意设计为泛型的;它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

22.1.3.6 String.prototype.constructor

String.prototype.constructor 的初始值是 %String%

22.1.3.7 String.prototype.endsWith ( searchString [ , endPosition ] )

此方法在被调用时执行以下步骤:

  1. thisValuethis value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. string 为 ? ToString(thisValue)。
  4. isRegexp 为 ? IsRegExp(searchString)。
  5. 如果 isRegexptrue,则抛出 TypeError 异常。
  6. searchString 设置为 ? ToString(searchString)。
  7. lengthstring 的长度。
  8. 如果 endPositionundefined,则令 positionlength;否则令 position 为 ? ToIntegerOrInfinity(endPosition)。
  9. end 为将 position 夹在 0 与 length 之间的结果。
  10. searchLengthsearchString 的长度。
  11. 如果 searchLength = 0,则返回 true
  12. startend - searchLength
  13. 如果 start < 0,则返回 false
  14. substringstringstartend子字符串
  15. 如果 substringsearchString,则返回 true
  16. 返回 false
Note 1

指定当第一个实参是 RegExp 时抛出异常,是为了允许未来版本定义允许这类实参值的扩展。

Note 2

此方法有意设计为泛型的;它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

22.1.3.8 String.prototype.includes ( searchString [ , position ] )

此方法在被调用时执行以下步骤:

  1. thisValuethis value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. string 为 ? ToString(thisValue)。
  4. isRegexp 为 ? IsRegExp(searchString)。
  5. 如果 isRegexptrue,则抛出 TypeError 异常。
  6. searchString 设置为 ? ToString(searchString)。
  7. positionInt 为 ? ToIntegerOrInfinity(position)。
  8. 断言:如果 positionundefined,则 positionInt 是 0。
  9. lengthstring 的长度。
  10. start 为将 positionInt 夹在 0 与 length 之间的结果。
  11. indexStringIndexOf(string, searchString, start)。
  12. 如果 indexnot-found,则返回 false
  13. 返回 true
Note 1

如果 searchString 作为将此对象转换为 String 的结果的子字符串出现在一个或多个大于或等于 position 的索引处,则此函数返回 true;否则返回 false。如果 positionundefined,则假定为 0,以搜索整个 String。

Note 2

指定当第一个实参是 RegExp 时抛出异常,是为了允许未来版本定义允许这类实参值的扩展。

Note 3

此方法有意设计为泛型的;它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

22.1.3.9 String.prototype.indexOf ( searchString [ , position ] )

Note 1

如果 searchString 作为将此对象转换为 String 的结果的子字符串出现在一个或多个大于或等于 position 的索引处,则返回这样的最小索引;否则返回 -1𝔽。如果 positionundefined,则假定为 +0𝔽,以搜索整个 String。

此方法在被调用时执行以下步骤:

  1. thisValuethis value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. string 为 ? ToString(thisValue)。
  4. searchString 设置为 ? ToString(searchString)。
  5. positionInt 为 ? ToIntegerOrInfinity(position)。
  6. 断言:如果 positionundefined,则 positionInt 是 0。
  7. lengthstring 的长度。
  8. start 为将 positionInt 夹在 0 与 length 之间的结果。
  9. resultStringIndexOf(string, searchString, start)。
  10. 如果 resultnot-found,则返回 -1𝔽
  11. 返回 𝔽(result)。
Note 2

此方法有意设计为泛型的;它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

22.1.3.10 String.prototype.isWellFormed ( )

此方法在被调用时执行以下步骤:

  1. thisValuethis value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. string 为 ? ToString(thisValue)。
  4. 返回 IsStringWellFormedUnicode(string)。

22.1.3.11 String.prototype.lastIndexOf ( searchString [ , position ] )

Note 1

如果 searchString 作为将此对象转换为 String 的结果的子字符串出现在一个或多个小于或等于 position 的索引处,则返回这样的最大索引;否则返回 -1𝔽。如果 positionundefined,则假定为 String 值的长度,以搜索整个 String。

此方法在被调用时执行以下步骤:

  1. thisValuethis value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. string 为 ? ToString(thisValue)。
  4. searchString 设置为 ? ToString(searchString)。
  5. numberPosition 为 ? ToNumber(position)。
  6. 断言:如果 positionundefined,则 numberPositionNaN
  7. 如果 numberPositionNaN,则将 position 设置为 +∞;否则将 position 设置为 ! ToIntegerOrInfinity(numberPosition)。
  8. lengthstring 的长度。
  9. searchLengthsearchString 的长度。
  10. 如果 length < searchLength,则返回 -1𝔽
  11. start 为将 position 夹在 0 与 length - searchLength 之间的结果。
  12. resultStringLastIndexOf(string, searchString, start)。
  13. 如果 resultnot-found,则返回 -1𝔽
  14. 返回 𝔽(result)。
Note 2

此方法有意设计为泛型的;它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

22.1.3.12 String.prototype.localeCompare ( that [ , reserved1 [ , reserved2 ] ] )

包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按 ECMA-402 规范中的规定实现此方法。如果 ECMAScript 实现不包含 ECMA-402 API,则使用此方法的以下规范:

此方法返回一个非 NaN 的 Number,表示对 this 值(转换为 String string)与 that(转换为 String thatValue)执行的实现定义的区域设置敏感 String 比较的结果。该结果旨在对应于根据宿主环境当前区域设置的约定对 String 值排序的顺序;当 string 排在 thatValue 之前时为负,当 string 排在 thatValue 之后时为正,在所有其他情况下为零(表示 stringthatValue 之间没有相对顺序)。

在执行比较之前,此方法执行以下步骤以准备 Strings:

  1. thisValuethis value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. string 为 ? ToString(thisValue)。
  4. thatValue 为 ? ToString(that)。

此方法的可选第二和第三参数的含义在 ECMA-402 规范中定义;不包含 ECMA-402 支持的实现不得为这些参数位置指定任何其他解释。

实际返回值由实现定义,以允许在其中编码额外信息,但当此方法被视为两个实参的方法时,它必须是一个一致的比较器,定义所有 Strings 集合上的全序。此方法还必须识别并遵守 Unicode Standard 中的规范等价,包括在比较可区分但规范等价的 Strings 时返回 +0𝔽

Note 1

此方法本身不适合直接作为 Array.prototype.sort 的实参,因为后者要求一个二元函数。

Note 2

此方法可以依赖 ECMAScript 环境从宿主环境可获得的任何语言和/或区域设置敏感比较功能,并旨在根据宿主环境当前区域设置的约定进行比较。不过,无论比较能力如何,此方法都必须识别并遵守 Unicode Standard 中的规范等价——例如,以下比较必须全部返回 +0𝔽

// Å ANGSTROM SIGN vs.
// Å LATIN CAPITAL LETTER A + COMBINING RING ABOVE
"\u212B".localeCompare("A\u030A")

// Ω OHM SIGN vs.
// Ω GREEK CAPITAL LETTER OMEGA
"\u2126".localeCompare("\u03A9")

// ṩ LATIN SMALL LETTER S WITH DOT BELOW AND DOT ABOVE vs.
// ṩ 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 vs.
// ḍ̇ LATIN SMALL LETTER D WITH DOT BELOW + COMBINING DOT ABOVE
"\u1E0B\u0323".localeCompare("\u1E0D\u0307")

// 가 HANGUL CHOSEONG KIYEOK + HANGUL JUNGSEONG A vs.
// 가 HANGUL SYLLABLE GA
"\u1100\u1161".localeCompare("\uAC00")

关于规范等价的定义和讨论,见 Unicode Standard 第 2 章和第 3 章,以及 Unicode Standard Annex #15, Unicode Normalization FormsUnicode Technical Note #5, Canonical Equivalence in Applications。另见 Unicode Technical Standard #10, Unicode Collation Algorithm

建议此方法不应遵守 Unicode Standard 第 3 章第 3.7 节中定义的 Unicode 兼容等价或兼容分解。

Note 3

此方法有意设计为泛型的;它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

22.1.3.13 String.prototype.match ( regexpOrPattern )

此方法在被调用时执行以下步骤:

  1. thisValuethis 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 »)。
Note

此方法有意设计为泛型的;它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

22.1.3.14 String.prototype.matchAll ( regexpOrPattern )

此方法对表示 this 值的 String 与 regexpOrPattern 执行正则表达式匹配,并返回一个产生匹配结果的迭代器。每个匹配结果都是一个 Array,其中第一个元素是 String 中被匹配的部分,随后是任何捕获组匹配到的部分。如果正则表达式从未匹配,则返回的迭代器不会产生任何匹配结果。

它在被调用时执行以下步骤:

  1. thisValuethis value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. 如果 regexpOrPattern 是 Object,则
    1. isRegexp 为 ? IsRegExp(regexpOrPattern)。
    2. 如果 isRegexptrue,则
      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 »)。
Note 1
此方法有意设计为泛型的;它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。
Note 2
类似于 String.prototype.splitString.prototype.matchAll 被设计为通常不改变其输入。

22.1.3.15 String.prototype.normalize ( [ form ] )

此方法在被调用时执行以下步骤:

  1. thisValuethis value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. string 为 ? ToString(thisValue)。
  4. 如果 formundefined,则将 form 设置为 "NFC"
  5. 否则,将 form 设置为 ? ToString(form)。
  6. 如果 form 不是 "NFC""NFD""NFKC""NFKD" 之一,则抛出 RangeError 异常。
  7. normal 为 String 值,它是按照 最新 Unicode Standard, Normalization Forms 中指定的方式,把 string 规范化为由 form 命名的规范化形式所得的结果。
  8. 返回 normal
Note

此方法有意设计为泛型的;它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

22.1.3.16 String.prototype.padEnd ( maxLength [ , fillString ] )

此方法在被调用时执行以下步骤:

  1. thisValuethis value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. 返回 ? StringPaddingBuiltinsImpl(thisValue, maxLength, fillString, end)。

22.1.3.17 String.prototype.padStart ( maxLength [ , fillString ] )

此方法在被调用时执行以下步骤:

  1. thisValuethis value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. 返回 ? StringPaddingBuiltinsImpl(thisValue, maxLength, fillString, start)。

22.1.3.17.1 StringPaddingBuiltinsImpl ( thisValue, maxLength, fillString, placement )

The abstract operation StringPaddingBuiltinsImpl takes arguments thisValue (an ECMAScript language value), maxLength (an ECMAScript language value), fillString (an ECMAScript language value), and placement (start or end) and returns either a normal completion containing a String or a throw completion. It performs the following steps when called:

  1. string 为 ? ToString(thisValue)。
  2. intMaxLength(? ToLength(maxLength))。
  3. stringLengthstring 的长度。
  4. 如果 intMaxLengthstringLength,则返回 string
  5. 如果 fillStringundefined,则将 fillString 设置为仅由码元 0x0020(SPACE)组成的 String 值。
  6. 否则,将 fillString 设置为 ? ToString(fillString)。
  7. 返回 StringPad(string, intMaxLength, fillString, placement)。

22.1.3.17.2 StringPad ( string, maxLength, fillString, placement )

The abstract operation StringPad takes arguments string (a String), maxLength (a non-negative integer), fillString (a String), and placement (start or end) and returns a String. It performs the following steps when called:

  1. stringLengthstring 的长度。
  2. 如果 maxLengthstringLength,则返回 string
  3. 如果 fillString 是空 String,则返回 string
  4. fillLengthmaxLength - stringLength
  5. truncatedStringFiller 为由 fillString 的重复连接组成并截断到长度 fillLength 的 String 值。
  6. 如果 placementstart,则返回 truncatedStringFillerstring字符串连接
  7. 返回 stringtruncatedStringFiller字符串连接
Note 1

实参 maxLength 会被夹住,使其不能小于 string 的长度。

Note 2

实参 fillString 默认为 " "(由码元 0x0020 SPACE 组成的 String 值)。

22.1.3.17.3 ToZeroPaddedDecimalString ( n, minLength )

The abstract operation ToZeroPaddedDecimalString takes arguments n (a non-negative integer) and minLength (a non-negative integer) and returns a String. It performs the following steps when called:

  1. stringn 的 String 表示,格式化为十进制数。
  2. 返回 StringPad(string, minLength, "0", start)。

22.1.3.18 String.prototype.repeat ( count )

此方法在被调用时执行以下步骤:

  1. thisValuethis value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. string 为 ? ToString(thisValue)。
  4. n 为 ? ToIntegerOrInfinity(count)。
  5. 如果 n < 0 或 n = +∞,则抛出 RangeError 异常。
  6. 如果 n = 0,则返回空 String。
  7. 返回由 stringn 个副本连接在一起构成的 String 值。
Note 1

此方法创建由 this 值(转换为 String)的码元重复 count 次组成的 String 值。

Note 2

此方法有意设计为泛型的;它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

22.1.3.19 String.prototype.replace ( searchValue, replaceValue )

此方法在被调用时执行以下步骤:

  1. thisValuethis 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. functionalReplaceIsCallable(replaceValue)。
  7. 如果 functionalReplacefalse,则
    1. replaceValue 设置为 ? ToString(replaceValue)。
  8. searchLengthsearchString 的长度。
  9. positionStringIndexOf(string, searchString, 0)。
  10. 如果 positionnot-found,则返回 string
  11. precedingstring 从 0 到 position子字符串
  12. followingstringposition + searchLength 起的子字符串
  13. 如果 functionalReplacetrue,则
    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. 返回 precedingreplacementfollowing字符串连接
Note

此方法有意设计为泛型的;它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

22.1.3.19.1 GetSubstitution ( matched, string, position, captures, namedCaptures, replacementTemplate )

The abstract operation GetSubstitution takes arguments matched (a String), string (a String), position (a non-negative integer), captures (a List of either Strings or undefined), namedCaptures (an Object or undefined), and replacementTemplate (a String) and returns either a normal completion containing a String or a throw completion. 对于此抽象操作而言,十进制数字是从 0x0030(DIGIT ZERO)到 0x0039(DIGIT NINE)闭区间内的码元。 It performs the following steps when called:

  1. stringLengthstring 的长度。
  2. 断言:positionstringLength
  3. result 为空 String。
  4. templateRemainderreplacementTemplate
  5. 重复,只要 templateRemainder 不是空 String,
    1. 注:以下步骤分离 reftemplateRemainder 的前缀),确定 refReplacement(其替换),然后把该替换追加到 result
    2. 如果 templateRemainder"$$" 开头,则
      1. ref"$$"
      2. refReplacement"$"
    3. 否则,如果 templateRemainder"$`" 开头,则
      1. ref"$`"
      2. refReplacementstring 从 0 到 position子字符串
    4. 否则,如果 templateRemainder"$&" 开头,则
      1. ref"$&"
      2. refReplacementmatched
    5. 否则,如果 templateRemainder"$'"(0x0024(DOLLAR SIGN)后跟 0x0027(APOSTROPHE))开头,则
      1. ref"$'"
      2. matchLengthmatched 的长度。
      3. tailPositionposition + matchLength
      4. refReplacementstringmin(tailPosition, stringLength) 起的子字符串
      5. 注:只有当此抽象操作%RegExp.prototype% 的固有 %Symbol.replace% 方法在其 "exec" 属性不是固有 %RegExp.prototype.exec% 的对象上调用时,tailPosition 才可能超过 stringLength
    6. 否则,如果 templateRemainder"$" 后跟 1 个或更多十进制数字开头,则
      1. 如果 templateRemainder"$" 后跟 2 个或更多十进制数字开头,则令 digitCount 为 2;否则令 digitCount 为 1。
      2. digitstemplateRemainder 从 1 到 1 + digitCount子字符串
      3. index(StringToNumber(digits))。
      4. 断言:0 ≤ index ≤ 99。
      5. captureLengthcaptures 中元素的数量。
      6. 如果 index > captureLengthdigitCount = 2,则
        1. 注:当两位替换模式指定了超出捕获组数量的索引时,它会被视为一位替换模式,后跟一个字面数字。
        2. digitCount 设置为 1。
        3. digits 设置为 digits 从 0 到 1 的子字符串
        4. index 设置为 (StringToNumber(digits))。
      7. reftemplateRemainder 从 0 到 1 + digitCount子字符串
      8. 如果 1 ≤ indexcaptureLength,则
        1. capturecaptures[index - 1]。
        2. 如果 captureundefined,则
          1. refReplacement 为空 String。
        3. 否则,
          1. refReplacementcapture
      9. 否则,
        1. refReplacementref
    7. 否则,如果 templateRemainder"$<" 开头,则
      1. gtPositionStringIndexOf(templateRemainder, ">", 0)。
      2. 如果 gtPositionnot-foundnamedCapturesundefined,则
        1. ref"$<"
        2. refReplacementref
      3. 否则,
        1. reftemplateRemainder 从 0 到 gtPosition + 1 的子字符串
        2. groupNametemplateRemainder 从 2 到 gtPosition子字符串
        3. 断言:namedCaptures 是 Object。
        4. capture 为 ? Get(namedCaptures, groupName)。
        5. 如果 captureundefined,则
          1. refReplacement 为空 String。
        6. 否则,
          1. refReplacement 为 ? ToString(capture)。
    8. 否则,
      1. reftemplateRemainder 从 0 到 1 的子字符串
      2. refReplacementref
    9. refLengthref 的长度。
    10. templateRemainder 设置为 templateRemainderrefLength 起的子字符串
    11. result 设置为 resultrefReplacement字符串连接
  6. 返回 result

22.1.3.20 String.prototype.replaceAll ( searchValue, replaceValue )

此方法在被调用时执行以下步骤:

  1. thisValuethis value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. 如果 searchValue 是 Object,则
    1. isRegexp 为 ? IsRegExp(searchValue)。
    2. 如果 isRegexptrue,则
      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. functionalReplaceIsCallable(replaceValue)。
  7. 如果 functionalReplacefalse,则
    1. replaceValue 设置为 ? ToString(replaceValue)。
  8. searchLengthsearchString 的长度。
  9. advanceBymax(1, searchLength)。
  10. matchPositions 为新的空 List
  11. positionStringIndexOf(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. preservedstringendOfLastMatchmatchPosition子字符串
    2. 如果 functionalReplacetrue,则
      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 设置为 resultpreservedreplacement字符串连接
    5. endOfLastMatch 设置为 matchPosition + searchLength
  16. 如果 endOfLastMatch < string 的长度,则
    1. result 设置为 resultstringendOfLastMatch 起的子字符串字符串连接
  17. 返回 result

22.1.3.21 String.prototype.search ( regexpOrPattern )

此方法在被调用时执行以下步骤:

  1. thisValuethis 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 »)。
Note

此方法有意设计为泛型的;它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

22.1.3.22 String.prototype.slice ( start, end )

此方法返回将此对象转换为 String 后所得结果的一个子字符串,从索引 start 开始,并持续到但不包括索引 end(如果 endundefined,则持续到 String 末尾)。如果 start 为负,则将其视为 sourceLength + start,其中 sourceLength 是 String 的长度。如果 end 为负,则将其视为 sourceLength + end,其中 sourceLength 是 String 的长度。结果是 String 值,而不是 String 对象。

它在被调用时执行以下步骤:

  1. thisValuethis value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. string 为 ? ToString(thisValue)。
  4. lengthstring 的长度。
  5. intStart 为 ? ToIntegerOrInfinity(start)。
  6. 如果 intStart = -∞,则令 from 为 0。
  7. 否则,如果 intStart < 0,则令 frommax(length + intStart, 0)。
  8. 否则,令 frommin(intStart, length)。
  9. 如果 endundefined,则令 intEndlength;否则令 intEnd 为 ? ToIntegerOrInfinity(end)。
  10. 如果 intEnd = -∞,则令 to 为 0。
  11. 否则,如果 intEnd < 0,则令 tomax(length + intEnd, 0)。
  12. 否则,令 tomin(intEnd, length)。
  13. 如果 fromto,则返回空 String。
  14. 返回 stringfromto子字符串
Note

此方法有意设计为泛型的;它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

22.1.3.23 String.prototype.split ( separator, limit )

此方法返回一个 Array,其中存储了将此对象转换为 String 后所得结果的各个子字符串。这些子字符串通过从左到右搜索 separator 的出现位置来确定;这些出现位置不是返回数组中任何 String 的一部分,而是用来分割该 String 值。separator 的值可以是任意长度的 String,也可以是具有 %Symbol.split% 方法的对象,例如 RegExp。

它在被调用时执行以下步骤:

  1. thisValuethis 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. 如果 limitundefined,则令 lim 为 232 - 1;否则令 lim(? ToUint32(limit))。
  6. separatorString 为 ? ToString(separator)。
  7. 如果 lim = 0,则
    1. 返回 CreateArrayFromList(« »)。
  8. 如果 separatorundefined,则
    1. 返回 CreateArrayFromListstring »)。
  9. separatorLengthseparatorString 的长度。
  10. 如果 separatorLength = 0,则
    1. stringLengthstring 的长度。
    2. outLength 为将 lim 夹在 0 与 stringLength 之间的结果。
    3. headstring 从 0 到 outLength子字符串
    4. codeUnits 为由 head 的各元素码元序列组成的 List
    5. 返回 CreateArrayFromList(codeUnits)。
  11. 如果 string 是空 String,则返回 CreateArrayFromListstring »)。
  12. substrings 为新的空 List
  13. searchStart 为 0。
  14. matchIndexStringIndexOf(string, separatorString, 0)。
  15. 重复,只要 matchIndex 不是 not-found
    1. substringstringsearchStartmatchIndex子字符串
    2. substring 追加到 substrings
    3. 如果 substrings 中元素的数量是 lim,则返回 CreateArrayFromList(substrings)。
    4. searchStart 设置为 matchIndex + separatorLength
    5. matchIndex 设置为 StringIndexOf(string, separatorString, searchStart)。
  16. substringstringsearchStart 起的子字符串
  17. substring 追加到 substrings
  18. 返回 CreateArrayFromList(substrings)。
Note 1

separator 的值可以是空 String。在这种情况下,separator 不匹配输入 String 开头或结尾处的空子字符串,也不匹配上一个分隔符匹配末尾处的空子字符串。如果 separator 是空 String,则 String 会被拆分为单个码元元素;结果数组的长度等于 String 的长度,并且每个子字符串包含一个码元。

如果 this 值是(或转换为)空 String,则结果取决于 separator 是否能匹配空 String。如果可以,则结果数组不包含元素。否则,结果数组包含一个元素,即空 String。

如果 separatorundefined,则结果数组只包含一个 String,即 this 值(转换为 String)。如果 limit 不是 undefined,则输出数组会被截断,使其包含不超过 limit 个元素。

Note 2

此方法有意设计为泛型的;它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

22.1.3.24 String.prototype.startsWith ( searchString [ , position ] )

此方法在被调用时执行以下步骤:

  1. thisValuethis value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. string 为 ? ToString(thisValue)。
  4. isRegexp 为 ? IsRegExp(searchString)。
  5. 如果 isRegexptrue,则抛出 TypeError 异常。
  6. searchString 设置为 ? ToString(searchString)。
  7. lengthstring 的长度。
  8. 如果 positionundefined,则将 position 设置为 0;否则将 position 设置为 ? ToIntegerOrInfinity(position)。
  9. start 为将 position 夹在 0 与 length 之间的结果。
  10. searchLengthsearchString 的长度。
  11. 如果 searchLength = 0,则返回 true
  12. endstart + searchLength
  13. 如果 end > length,则返回 false
  14. substringstringstartend子字符串
  15. 如果 substringsearchString,则返回 true
  16. 返回 false
Note 1

指定当第一个实参是 RegExp 时抛出异常,是为了允许未来版本定义允许这类实参值的扩展。

Note 2

此方法有意设计为泛型的;它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

22.1.3.25 String.prototype.substring ( start, end )

此方法返回将此对象转换为 String 后所得结果的一个子字符串,从索引 start 开始,并持续到但不包括 String 的索引 end(如果 endundefined,则持续到 String 末尾)。结果是 String 值,而不是 String 对象。

如果任一实参是 NaN 或负数,则将其替换为零;如果任一实参严格大于 String 的长度,则将其替换为 String 的长度。

如果 start 严格大于 end,则交换二者。

它在被调用时执行以下步骤:

  1. thisValuethis value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. string 为 ? ToString(thisValue)。
  4. lengthstring 的长度。
  5. intStart 为 ? ToIntegerOrInfinity(start)。
  6. 如果 endundefined,则令 intEndlength;否则令 intEnd 为 ? ToIntegerOrInfinity(end)。
  7. finalStart 为将 intStart 夹在 0 与 length 之间的结果。
  8. finalEnd 为将 intEnd 夹在 0 与 length 之间的结果。
  9. frommin(finalStart, finalEnd)。
  10. tomax(finalStart, finalEnd)。
  11. 返回 stringfromto子字符串
Note

此方法有意设计为泛型的;它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

22.1.3.26 String.prototype.toLocaleLowerCase ( [ reserved1 [ , reserved2 ] ] )

包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按 ECMA-402 规范中的规定实现此方法。如果 ECMAScript 实现不包含 ECMA-402 API,则使用此方法的以下规范:

此方法将 String 值解释为 UTF-16 编码码点序列,如 6.1.4 中所述。

它的工作方式与 toLowerCase 完全相同,只是它旨在产生与宿主环境当前区域设置的约定相对应的区域设置敏感结果。只有在少数情况(例如土耳其语)中,该语言的规则与常规 Unicode 大小写映射冲突时,才会存在差异。

此方法可选参数的含义在 ECMA-402 规范中定义;不包含 ECMA-402 支持的实现不得把这些参数位置用于任何其他用途。

Note

此方法有意设计为泛型的;它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

22.1.3.27 String.prototype.toLocaleUpperCase ( [ reserved1 [ , reserved2 ] ] )

包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按 ECMA-402 规范中的规定实现此方法。如果 ECMAScript 实现不包含 ECMA-402 API,则使用此方法的以下规范:

此方法将 String 值解释为 UTF-16 编码码点序列,如 6.1.4 中所述。

它的工作方式与 toUpperCase 完全相同,只是它旨在产生与宿主环境当前区域设置的约定相对应的区域设置敏感结果。只有在少数情况(例如土耳其语)中,该语言的规则与常规 Unicode 大小写映射冲突时,才会存在差异。

此方法可选参数的含义在 ECMA-402 规范中定义;不包含 ECMA-402 支持的实现不得把这些参数位置用于任何其他用途。

Note

此方法有意设计为泛型的;它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

22.1.3.28 String.prototype.toLowerCase ( )

此方法将 String 值解释为 UTF-16 编码码点序列,如 6.1.4 中所述。

它在被调用时执行以下步骤:

  1. thisValuethis value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. string 为 ? ToString(thisValue)。
  4. sTextStringToCodePoints(string)。
  5. lowerText 为按照 Unicode Default Case Conversion 算法对 sText 执行 toLowercase 的结果。
  6. lowercaseStringCodePointsToString(lowerText)。
  7. 返回 lowercaseString

结果必须根据 Unicode Character Database 中的区域设置无关大小写映射派生(这明确不仅包括文件 UnicodeData.txt,还包括随附文件 SpecialCasing.txt 中所有区域设置无关的映射)。

Note 1

某些码点的大小写映射可能产生多个码点。在这种情况下,结果 String 的长度可能与源 String 不同。由于 toUpperCasetoLowerCase 都具有上下文敏感行为,这两个方法并不对称。换句话说,s.toUpperCase().toLowerCase() 不一定等于 s.toLowerCase()

Note 2

此方法有意设计为泛型的;它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

22.1.3.29 String.prototype.toString ( )

此方法在被调用时执行以下步骤:

  1. 返回 ? ThisStringValue(this value)。
Note

对于 String 对象,此方法恰好返回与 valueOf 方法相同的内容。

22.1.3.30 String.prototype.toUpperCase ( )

此方法将 String 值解释为 UTF-16 编码码点序列,如 6.1.4 中所述。

它的行为与 String.prototype.toLowerCase 完全相同,只是 String 使用 Unicode Default Case Conversion 的 toUppercase 算法进行映射。

Note

此方法有意设计为泛型的;它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

22.1.3.31 String.prototype.toWellFormed ( )

此方法返回此对象的 String 表示,其中所有不属于代理对的前导代理和尾随代理都会被替换为 U+FFFD(REPLACEMENT CHARACTER)。

它在被调用时执行以下步骤:

  1. thisValuethis value。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. string 为 ? ToString(thisValue)。
  4. stringLengthstring 的长度。
  5. k 为 0。
  6. result 为空 String。
  7. 重复,只要 k < stringLength
    1. codePointCodePointAt(string, k)。
    2. 如果 codePoint.[[IsUnpairedSurrogate]]true,则
      1. result 设置为 result 和 0xFFFD(REPLACEMENT CHARACTER)的字符串连接
    3. 否则,
      1. result 设置为 resultUTF16EncodeCodePoint(codePoint.[[CodePoint]]) 的字符串连接
    4. k 设置为 k + codePoint.[[CodeUnitCount]]
  8. 返回 result

22.1.3.32 String.prototype.trim ( )

此方法将 String 值解释为 UTF-16 编码码点序列,如 6.1.4 中所述。

它在被调用时执行以下步骤:

  1. thisValuethis value。
  2. 返回 ? TrimString(thisValue, start+end)。
Note

此方法有意设计为泛型的;它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

22.1.3.32.1 TrimString ( arg, where )

The abstract operation TrimString takes arguments arg (an ECMAScript language value) and where (start, end, or start+end) and returns either a normal completion containing a String or a throw completion. 它将 arg 解释为 UTF-16 编码码点序列,如 6.1.4 中所述。 It performs the following steps when called:

  1. 执行 ? RequireObjectCoercible(arg)。
  2. string 为 ? ToString(arg)。
  3. 如果 wherestart,则
    1. trimmedStringstring 的副本并移除其前导空白。
  4. 否则,如果 whereend,则
    1. trimmedStringstring 的副本并移除其尾随空白。
  5. 否则,
    1. 断言:wherestart+end
    2. trimmedStringstring 的副本并移除其前导和尾随空白。
  6. 返回 trimmedString

空白的定义是 WhiteSpaceLineTerminator 的并集。在确定 Unicode 码点是否属于 Unicode 通用类别 “Space_Separator”(“Zs”)时,码元序列会按 6.1.4 中指定的方式解释为 UTF-16 编码码点序列。

22.1.3.33 String.prototype.trimEnd ( )

此方法将 String 值解释为 UTF-16 编码码点序列,如 6.1.4 中所述。

它在被调用时执行以下步骤:

  1. stringthis value。
  2. 返回 ? TrimString(string, end)。
Note

此方法有意设计为泛型的;它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

22.1.3.34 String.prototype.trimStart ( )

此方法将 String 值解释为 UTF-16 编码码点序列,如 6.1.4 中所述。

它在被调用时执行以下步骤:

  1. stringthis value。
  2. 返回 ? TrimString(string, start)。
Note

此方法有意设计为泛型的;它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

22.1.3.35 String.prototype.valueOf ( )

此方法在被调用时执行以下步骤:

  1. 返回 ? ThisStringValue(this value)。

22.1.3.35.1 ThisStringValue ( arg )

The abstract operation ThisStringValue takes argument arg (an ECMAScript language value) and returns either a normal completion containing a String or a throw completion. It performs the following steps when called:

  1. 如果 arg 是 String,则返回 arg
  2. 如果 arg 是 Object 且 arg 具有 [[StringData]] 内部槽,则
    1. stringarg.[[StringData]]
    2. 断言:string 是 String。
    3. 返回 string
  3. 抛出 TypeError 异常。

22.1.3.36 String.prototype [ %Symbol.iterator% ] ( )

此方法返回一个迭代器对象,该对象迭代 String 值的码点,并将每个码点作为 String 值返回。

它在被调用时执行以下步骤:

  1. stringthis value。
  2. 执行 ? RequireObjectCoercible(string)。
  3. string 设置为 ? ToString(string)。
  4. closure 为一个新的无参数 Abstract Closure,它捕获 string,并在被调用时执行以下步骤:
    1. lengthstring 的长度。
    2. position 为 0。
    3. 重复,只要 position < length
      1. codePointCodePointAt(string, position)。
      2. nextIndexposition + codePoint.[[CodeUnitCount]]
      3. resultStringstringpositionnextIndex子字符串
      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 Iterator 对象

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 对象包含一个正则表达式以及相关联的标志。

Note

正则表达式的形式和功能以 Perl 5 编程语言中的正则表达式设施为模型。

22.2.1 模式

RegExp 构造器会把以下文法应用于输入的 pattern 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 HexLeadSurrogate,且该 u HexLeadSurrogate 否则就没有对应的 \u HexTrailSurrogate

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] Note 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 & - ! # % , : ; < = > @ ` ~ Note 2

本节中的若干产生式在 B.1.2 一节中给出了替代定义。

22.2.1.1 Static Semantics: 早期错误

Note

本节在 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 )

The abstract operation CountLeftCapturingParensWithin takes argument parseNode (a Parse Node) and returns a non-negative integer. 它返回 parseNode 中左捕获括号的数量。左捕获括号是被 Atom :: ( GroupSpecifieropt Disjunction ) 产生式的 ( 终结符匹配的任意 ( 模式字符。

Note

本节在 B.1.2.2 中被修订。

It performs the following steps when called:

  1. 断言:parseNodeRegExp Pattern 文法中某个产生式的实例。
  2. 返回 parseNode包含 Atom :: ( GroupSpecifieropt Disjunction ) Parse Node 的数量。

22.2.1.3 Static Semantics: CountLeftCapturingParensBefore ( parseNode )

The abstract operation CountLeftCapturingParensBefore takes argument parseNode (a Parse Node) and returns a non-negative integer. 它返回外围 pattern 中位于 parseNode 左侧的左捕获括号数量。

Note

本节在 B.1.2.2 中被修订。

It performs the following steps when called:

  1. 断言:parseNodeRegExp Pattern 文法中某个产生式的实例。
  2. pattern包含 parseNodePattern
  3. 返回 pattern包含的、出现在 parseNode 之前或包含 parseNode Atom :: ( GroupSpecifieropt Disjunction ) Parse Node 的数量。

22.2.1.4 Static Semantics: MightBothParticipate ( x, y )

The abstract operation MightBothParticipate takes arguments x (a Parse Node) and y (a Parse Node) and returns a Boolean. It performs the following steps when called:

  1. 断言:xy 具有相同的外围 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

The syntax-directed operation CapturingGroupNumber takes no arguments and returns a positive integer.

Note

本节在 B.1.2.1 中被修订。

It is defined piecewise over the following productions:

DecimalEscape :: NonZeroDigit
  1. 返回 NonZeroDigit 的 MV。
DecimalEscape :: NonZeroDigit DecimalDigits
  1. nDecimalDigits 中码点的数量。
  2. 返回(NonZeroDigit 的 MV × 10n 加上 DecimalDigits 的 MV)。

NonZeroDigit 的 MV”和“DecimalDigits 的 MV”的定义见 12.9.3

22.2.1.6 Static Semantics: IsCharacterClass

The syntax-directed operation IsCharacterClass takes no arguments and returns a Boolean.

Note

本节在 B.1.2.3 中被修订。

It is defined piecewise over the following productions:

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

The syntax-directed operation CharacterValue takes no arguments and returns a non-negative integer.

Note 1

本节在 B.1.2.4 中被修订。

It is defined piecewise over the following productions:

ClassAtom :: -
  1. 返回 U+002D(HYPHEN-MINUS)的数值。
ClassAtomNoDash :: SourceCharacter but not one of \ or ] or -
  1. codePointSourceCharacter 匹配的码点。
  2. 返回 codePoint 的数值。
ClassEscape :: b
  1. 返回 U+0008(BACKSPACE)的数值。
ClassEscape :: -
  1. 返回 U+002D(HYPHEN-MINUS)的数值。
CharacterEscape :: ControlEscape
  1. 返回依据 Table 63 得到的数值。
Table 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. codePointAsciiLetter 匹配的码点。
  2. icodePoint 的数值。
  3. 返回 i 除以 32 的余数。
CharacterEscape :: 0 [lookahead ∉ DecimalDigit]
  1. 返回 U+0000(NULL)的数值。
Note 2

\0 表示 <NUL> 字符,并且其后不能跟十进制数字。

CharacterEscape :: HexEscapeSequence
  1. 返回 HexEscapeSequence 的 MV。
RegExpUnicodeEscapeSequence :: u HexLeadSurrogate \u HexTrailSurrogate
  1. leadHexLeadSurrogateCharacterValue
  2. trailHexTrailSurrogateCharacterValue
  3. codePointUTF16SurrogatePairToCodePoint(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. codePointIdentityEscape 匹配的码点。
  2. 返回 codePoint 的数值。
ClassSetCharacter :: SourceCharacter but not ClassSetSyntaxCharacter
  1. codePointSourceCharacter 匹配的码点。
  2. 返回 codePoint 的数值。
ClassSetCharacter :: \ ClassSetReservedPunctuator
  1. codePointClassSetReservedPunctuator 匹配的码点。
  2. 返回 codePoint 的数值。
ClassSetCharacter :: \b
  1. 返回 U+0008(BACKSPACE)的数值。

22.2.1.8 Static Semantics: MayContainStrings

The syntax-directed operation MayContainStrings takes no arguments and returns a Boolean. It is defined piecewise over the following productions:

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 匹配的源文本Table 67 的 “Property name” 列中列出的字符串二元属性,则返回 true
  2. 返回 false
ClassUnion :: ClassSetRange ClassUnionopt
  1. 如果 ClassUnion 存在,则返回 ClassUnionMayContainStrings
  2. 返回 false
ClassUnion :: ClassSetOperand ClassUnionopt
  1. 如果 ClassSetOperandMayContainStringstrue,则返回 true
  2. 如果 ClassUnion 存在,则返回 ClassUnionMayContainStrings
  3. 返回 false
ClassIntersection :: ClassSetOperand && ClassSetOperand
  1. 如果第一个 ClassSetOperandMayContainStringsfalse,则返回 false
  2. 如果第二个 ClassSetOperandMayContainStringsfalse,则返回 false
  3. 返回 true
ClassIntersection :: ClassIntersection && ClassSetOperand
  1. 如果 ClassIntersectionMayContainStringsfalse,则返回 false
  2. 如果 ClassSetOperandMayContainStringsfalse,则返回 false
  3. 返回 true
ClassSubtraction :: ClassSetOperand -- ClassSetOperand
  1. 返回第一个 ClassSetOperandMayContainStrings
ClassSubtraction :: ClassSubtraction -- ClassSetOperand
  1. 返回 ClassSubtractionMayContainStrings
ClassStringDisjunctionContents :: ClassString | ClassStringDisjunctionContents
  1. 如果 ClassStringMayContainStringstrue,则返回 true
  2. 返回 ClassStringDisjunctionContentsMayContainStrings
ClassString :: [empty]
  1. 返回 true
ClassString :: NonEmptyClassString
  1. 返回 NonEmptyClassStringMayContainStrings
NonEmptyClassString :: ClassSetCharacter NonEmptyClassStringopt
  1. 如果 NonEmptyClassString 存在,则返回 true
  2. 返回 false

22.2.1.9 Static Semantics: GroupSpecifiersThatMatch ( thisGroupName )

The abstract operation GroupSpecifiersThatMatch takes argument thisGroupName (a GroupName Parse Node) and returns a List of GroupSpecifier Parse Nodes. It performs the following steps when called:

  1. namethisGroupNameCapturingGroupName
  2. pattern包含 thisGroupNamePattern
  3. result 为新的空 List
  4. pattern 包含的每个 GroupSpecifier groupSpecifier,执行:
    1. 如果 groupSpecifierCapturingGroupNamename,则
      1. groupSpecifier 追加到 result
  5. 返回 result

22.2.1.10 Static Semantics: CapturingGroupName

The syntax-directed operation CapturingGroupName takes no arguments and returns a String. It is defined piecewise over the following productions:

GroupName :: < RegExpIdentifierName >
  1. idTextUnescapedRegExpIdentifierNameRegExpIdentifierCodePoints
  2. 返回 CodePointsToString(idTextUnescaped)。

22.2.1.11 Static Semantics: RegExpIdentifierCodePoints

The syntax-directed operation RegExpIdentifierCodePoints takes no arguments and returns a List of code points. It is defined piecewise over the following productions:

RegExpIdentifierName :: RegExpIdentifierStart
  1. codePointRegExpIdentifierStartRegExpIdentifierCodePoint
  2. 返回 « codePoint »。
RegExpIdentifierName :: RegExpIdentifierName RegExpIdentifierPart
  1. codePoints 为派生的 RegExpIdentifierNameRegExpIdentifierCodePoints
  2. codePointRegExpIdentifierPartRegExpIdentifierCodePoint
  3. 返回 codePoints 和 « codePoint » 的列表连接

22.2.1.12 Static Semantics: RegExpIdentifierCodePoint

The syntax-directed operation RegExpIdentifierCodePoint takes no arguments and returns a code point. It is defined piecewise over the following productions:

RegExpIdentifierStart :: IdentifierStartChar
  1. 返回 IdentifierStartChar 匹配的码点。
RegExpIdentifierPart :: IdentifierPartChar
  1. 返回 IdentifierPartChar 匹配的码点。
RegExpIdentifierStart :: \ RegExpUnicodeEscapeSequence RegExpIdentifierPart :: \ RegExpUnicodeEscapeSequence
  1. 返回其数值为 RegExpUnicodeEscapeSequenceCharacterValue 的码点。
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 模式会匹配被解释为由 16 位值序列组成的 String,这些 16 位值是 Basic Multilingual Plane 范围内的 Unicode 码点。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 的元素。

Note

例如,考虑一个在源文本中表示为单个非 BMP 字符 U+1D11E(MUSICAL SYMBOL G CLEF)的模式。如果解释为 Unicode 模式,它将是一个由单个码点 U+1D11E 组成的单元素(字符)List。然而,如果解释为 BMP 模式,它会先被 UTF-16 编码,产生一个由码元 0xD834 和 0xDD1E 组成的双元素 List

模式作为 ECMAScript String 值传给 RegExp 构造器,其中非 BMP 字符以 UTF-16 编码。例如,单个字符 MUSICAL SYMBOL G CLEF 模式,表示为 String 值时,是一个长度为 2 的 String,其元素是码元 0xD834 和 0xDD1E。因此,将其处理为由两个模式字符组成的 BMP 模式时,不需要进一步转换该字符串。然而,将其处理为 Unicode 模式时,必须使用 UTF16SurrogatePairToCodePoint 来产生一个 List,该 List 的唯一元素是单个模式字符,即码点 U+1D11E。

实现实际上可以不执行这种到 UTF-16 或从 UTF-16 的转换,但本规范的语义要求模式匹配的结果必须如同执行了这种转换一样。

22.2.2.1 记法

下列描述使用以下内部数据结构:

  • CharSetElement 是以下两个实体之一:
    • 如果 regexpRecord.[[UnicodeSets]]false,则 CharSetElement 是上述 Pattern Semantics 意义上的一个字符。
    • 如果 regexpRecord.[[UnicodeSets]]true,则 CharSetElement 是一个序列,其元素是上述 Pattern Semantics 意义上的字符。这包括空序列、一个字符的序列以及多于一个字符的序列。为方便起见,在处理这种 CharSetElement 时,单个字符可与一个字符的序列互换对待。
  • CharSet 是 CharSetElement 的数学集合。
  • CaptureRangeRecord { [[StartIndex]], [[EndIndex]] },表示 capture 中包含的字符范围,其中 [[StartIndex]] 是表示该范围在 input 中开始索引(包含)的整数,[[EndIndex]] 是表示该范围在 input 中结束索引(不包含)的整数。对于任何 CaptureRange,这些索引都必须满足不变量 [[StartIndex]][[EndIndex]]
  • MatchStateRecord { [[Input]], [[EndIndex]], [[Captures]] },其中 [[Input]] 是表示被匹配 String 的字符 List[[EndIndex]] 是整数,[[Captures]] 是值的 List,对应模式中每个左捕获括号各一个。MatchState 用于在正则表达式匹配算法中表示部分匹配状态。[[EndIndex]] 是目前为止由模式匹配到的最后一个输入字符索引加一,而 [[Captures]] 保存捕获括号的结果。[[Captures]] 的第 nth 个元素要么是表示第 nth 组捕获括号所捕获字符范围的 CaptureRange,要么是 undefined,如果第 nth 组捕获括号尚未到达。由于回溯,在匹配过程中任意时刻都可能使用许多 MatchState
  • MatcherContinuation 是一个 Abstract Closure,它接受一个 MatchState 实参,并返回 MatchStatefailureMatcherContinuation 会尝试从其 MatchState 实参给定的中间状态开始,把模式剩余部分(由该 closure 的捕获值指定)与 input 进行匹配。如果匹配成功,MatcherContinuation 返回其到达的最终 MatchState;如果匹配失败,MatcherContinuation 返回 failure
  • Matcher 是一个 Abstract Closure,它接受两个实参——一个 MatchState 和一个 MatcherContinuation——并返回 MatchStatefailureMatcher 会尝试从其 MatchState 实参给定的中间状态开始,把模式的中间子模式(由该 closure 的捕获值指定)与 MatchState[[Input]] 进行匹配。MatcherContinuation 实参应是匹配模式其余部分的 closure。在匹配模式的子模式以获得新的 MatchState 后,Matcher 随后会在该新的 MatchState 上调用 MatcherContinuation,以测试模式的其余部分是否也能匹配。如果可以,Matcher 返回 MatcherContinuation 返回的 MatchState;如果不可以,Matcher 可以在其选择点尝试不同选择,反复调用 MatcherContinuation,直到成功或所有可能性都已耗尽。

22.2.2.1.1 RegExp Record

RegExp Record 是一种 Record 值,用于存储编译期间以及可能在匹配期间需要的 RegExp 相关信息。

它具有以下字段:

Table 64: RegExp Record 字段
字段名 含义
[[IgnoreCase]] a Boolean 指示 RegExp 的 flags 中是否出现 "i"
[[Multiline]] a Boolean 指示 RegExp 的 flags 中是否出现 "m"
[[DotAll]] a Boolean 指示 RegExp 的 flags 中是否出现 "s"
[[Unicode]] a Boolean 指示 RegExp 的 flags 中是否出现 "u"
[[UnicodeSets]] a Boolean 指示 RegExp 的 flags 中是否出现 "v"
[[CapturingGroupsCount]] a non-negative integer RegExp 模式中的左捕获括号数量

22.2.2.2 Runtime Semantics: CompilePattern

The syntax-directed operation CompilePattern takes argument regexpRecord (a RegExp Record) and returns an Abstract Closure that takes a List of characters and a non-negative integer and returns either a MatchState or failure. It is defined piecewise over the following productions:

Pattern :: Disjunction
  1. m 为以 regexpRecordforward 为实参执行 DisjunctionCompileSubpattern
  2. 返回一个新的 Abstract Closure,其参数为 (input, index),捕获 regexpRecordm,并在被调用时执行以下步骤:
    1. 断言:input 是字符 List
    2. 断言:0 ≤ indexinput 中的元素数量。
    3. c 为新的 MatcherContinuation,其参数为 (y),不捕获任何内容,并在被调用时执行以下步骤:
      1. 断言:yMatchState
      2. 返回 y
    4. capability 为由 regexpRecord.[[CapturingGroupsCount]]undefined 值组成的 List,索引从 1 到 regexpRecord.[[CapturingGroupsCount]]
    5. xMatchState { [[Input]]: input, [[EndIndex]]: index, [[Captures]]: capability }。
    6. 返回 m(x, c)。
Note

Pattern 会编译为 Abstract Closure 值。随后 RegExpBuiltinExec 可以把此过程应用于字符 List 以及该 List 中的偏移,以确定模式是否会从该 List 中的确切偏移开始匹配;如果确实匹配,则确定捕获括号的值是什么。22.2.2 中的算法设计为使编译模式可能抛出 SyntaxError 异常;另一方面,一旦模式成功编译,把所得 Abstract Closure 应用于在字符 List 中寻找匹配就不能抛出异常(除了可能在任何地方发生的任何由实现定义的异常,例如内存不足)。

22.2.2.3 Runtime Semantics: CompileSubpattern

The syntax-directed operation CompileSubpattern takes arguments regexpRecord (a RegExp Record) and direction (forward or backward) and returns a Matcher.

Note 1

本节在 B.1.2.5 中被修订。

It is defined piecewise over the following productions:

Disjunction :: Alternative | Disjunction
  1. m1 为以 regexpRecorddirection 为实参执行 AlternativeCompileSubpattern
  2. m2 为以 regexpRecorddirection 为实参执行 DisjunctionCompileSubpattern
  3. 返回 MatchTwoAlternatives(m1, m2)。
Note 2

| 正则表达式运算符分隔两个 alternatives。模式首先尝试匹配左侧 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]

尝试两个 alternatives 的顺序与 direction 的值无关。

Alternative :: [empty]
  1. 返回 EmptyMatcher()。
Alternative :: Alternative Term
  1. m1 为以 regexpRecorddirection 为实参执行 AlternativeCompileSubpattern
  2. m2 为以 regexpRecorddirection 为实参执行 TermCompileSubpattern
  3. 返回 MatchSequence(m1, m2, direction)。
Note 3

连续的 Term 会尝试同时匹配 input 的连续部分。当 directionforward 时,如果左侧 Alternative、右侧 Term 和正则表达式的后续部分全都有选择点,则先尝试后续部分中的所有选择,然后再转到右侧 Term 中的下一个选择;并且先尝试右侧 Term 中的所有选择,然后再转到左侧 Alternative 中的下一个选择。当 directionbackward 时,AlternativeTerm 的求值顺序会被反转。

Term :: Assertion
  1. 返回以 regexpRecord 为实参执行 AssertionCompileAssertion
Note 4

所得 Matcherdirection 无关。

Term :: Atom
  1. 返回以 regexpRecorddirection 为实参执行 AtomCompileAtom
Term :: Atom Quantifier
  1. m 为以 regexpRecorddirection 为实参执行 AtomCompileAtom
  2. qQuantifierCompileQuantifier
  3. 断言:q.[[Min]]q.[[Max]]
  4. parenIndexCountLeftCapturingParensBefore(Term)。
  5. parenCountCountLeftCapturingParensWithin(Atom)。
  6. 返回一个新的 Matcher,其参数为 (x, c),捕获 mqparenIndexparenCount,并在被调用时执行以下步骤:
    1. 断言:xMatchState
    2. 断言:cMatcherContinuation
    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 )

The abstract operation RepeatMatcher takes arguments m (a Matcher), min (a non-negative integer), max (a non-negative integer or +∞), greedy (a Boolean), matchState (a MatchState), continue (a MatcherContinuation), parenIndex (a non-negative integer), and parenCount (a non-negative integer) and returns either a MatchState or failure. It performs the following steps when called:

  1. 如果 max = 0,则返回 continue(matchState)。
  2. d 为新的 MatcherContinuation,其参数为 (y),捕获 mminmaxgreedymatchStatecontinueparenIndexparenCount,并在被调用时执行以下步骤:
    1. 断言:yMatchState
    2. 如果 min = 0 且 y.[[EndIndex]] = matchState.[[EndIndex]],则返回 failure
    3. 如果 min = 0,则令 min2 为 0;否则令 min2min - 1。
    4. 如果 max = +∞,则令 max2 为 +∞;否则令 max2max - 1。
    5. 返回 RepeatMatcher(m, min2, max2, greedy, y, continue, parenIndex, parenCount)。
  3. capabilitymatchState.[[Captures]] 的副本。
  4. 对从 parenIndex + 1 到 parenIndex + parenCount闭区间内的每个整数 k,将 capability[k] 设置为 undefined
  5. inputmatchState.[[Input]]
  6. ematchState.[[EndIndex]]
  7. xrMatchState { [[Input]]: input, [[EndIndex]]: e, [[Captures]]: capability }。
  8. 如果 min ≠ 0,则返回 m(xr, d)。
  9. 如果 greedyfalse,则
    1. zcontinue(matchState)。
    2. 如果 z 不是 failure,则返回 z
    3. 返回 m(xr, d)。
  10. zm(xr, d)。
  11. 如果 z 不是 failure,则返回 z
  12. 返回 continue(matchState)。
Note 1

后跟 QuantifierAtom 会重复 Quantifier 指定的次数。Quantifier 可以是非贪婪的,在这种情况下 Atom 模式会以仍能匹配后续部分的最少次数重复;也可以是贪婪的,在这种情况下 Atom 模式会以仍能匹配后续部分的最多次数重复。被重复的是 Atom 模式,而不是它匹配到的输入字符序列,因此 Atom 的不同重复可以匹配不同的输入子字符串

Note 2

如果 Atom 和正则表达式的后续部分全都有选择点,则 Atom 首先会尽可能多次(或如果是非贪婪,则尽可能少次)匹配。先尝试后续部分中的所有选择,然后再转到 Atom 最后一次重复中的下一个选择。先尝试 Atom 最后一次(第 nth 次)重复中的所有选择,然后再转到 Atom 倒数第二次(第 n - 1st 次)重复中的下一个选择;此时可能会发现 Atom 现在可以进行更多或更少次重复;这些选择会被耗尽(同样,从尽可能少或尽可能多开始),然后再转到 Atom 第 (n - 1)st 次重复中的下一个选择,如此类推。

比较

/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 的 gcd:

"aaaaaaaaaa,aaaaaaaaaaaaaaa".replace(/^(a+)\1*,\1+$/, "$1")

其返回一元记法的 gcd "aaaaa"

Note 3

RepeatMatcher 的步骤 4 会在每次重复 Atom 时清除 Atom 的 captures。我们可以在正则表达式

/(z)((a+)?(b+)?(c))*/.exec("zaacbbbcac")

中看到它的行为,其返回数组

["zaacbbbcac", "z", "ac", "a", undefined, "c"]

而不是

["zaacbbbcac", "z", "ac", "a", "bbb", "c"]

因为最外层 * 的每次迭代都会清除被量化 Atom包含的所有捕获 Strings,在此情况下包括编号为 2、3、4 和 5 的捕获 Strings。

Note 4

RepeatMatcher 的步骤 2.b 规定,一旦已满足最小重复次数,就不再考虑对匹配空字符序列的 Atom 进行更多展开以进行进一步重复。这可以防止正则表达式引擎在如下模式上陷入无限循环:

/(a*)*/.exec("b")

或稍微更复杂的:

/(a*)b\1+/.exec("baaaac")

其返回数组

["b", ""]

22.2.2.3.2 EmptyMatcher ( )

The abstract operation EmptyMatcher takes no arguments and returns a Matcher. It performs the following steps when called:

  1. 返回一个新的 Matcher,其参数为 (matchState, continue),不捕获任何内容,并在被调用时执行以下步骤:
    1. 断言:matchStateMatchState
    2. 断言:continueMatcherContinuation
    3. 返回 continue(matchState)。

22.2.2.3.3 MatchTwoAlternatives ( m1, m2 )

The abstract operation MatchTwoAlternatives takes arguments m1 (a Matcher) and m2 (a Matcher) and returns a Matcher. It performs the following steps when called:

  1. 返回一个新的 Matcher,其参数为 (matchState, continue),捕获 m1m2,并在被调用时执行以下步骤:
    1. 断言:matchStateMatchState
    2. 断言:continueMatcherContinuation
    3. resultm1(matchState, continue)。
    4. 如果 result 不是 failure,则返回 result
    5. 返回 m2(matchState, continue)。

22.2.2.3.4 MatchSequence ( m1, m2, direction )

The abstract operation MatchSequence takes arguments m1 (a Matcher), m2 (a Matcher), and direction (forward or backward) and returns a Matcher. It performs the following steps when called:

  1. 如果 directionforward,则
    1. 返回一个新的 Matcher,其参数为 (matchState, continue),捕获 m1m2,并在被调用时执行以下步骤:
      1. 断言:matchStateMatchState
      2. 断言:continueMatcherContinuation
      3. d 为新的 MatcherContinuation,其参数为 (y),捕获 continuem2,并在被调用时执行以下步骤:
        1. 断言:yMatchState
        2. 返回 m2(y, continue)。
      4. 返回 m1(matchState, d)。
  2. 断言:directionbackward
  3. 返回一个新的 Matcher,其参数为 (matchState, continue),捕获 m1m2,并在被调用时执行以下步骤:
    1. 断言:matchStateMatchState
    2. 断言:continueMatcherContinuation
    3. d 为新的 MatcherContinuation,其参数为 (y),捕获 continuem1,并在被调用时执行以下步骤:
      1. 断言:yMatchState
      2. 返回 m1(y, continue)。
    4. 返回 m2(matchState, d)。

22.2.2.4 Runtime Semantics: CompileAssertion

The syntax-directed operation CompileAssertion takes argument regexpRecord (a RegExp Record) and returns a Matcher.

Note 1

本节在 B.1.2.6 中被修订。

It is defined piecewise over the following productions:

Assertion :: ^
  1. 返回一个新的 Matcher,其参数为 (matchState, continue),捕获 regexpRecord,并在被调用时执行以下步骤:
    1. 断言:matchStateMatchState
    2. 断言:continueMatcherContinuation
    3. inputmatchState.[[Input]]
    4. ematchState.[[EndIndex]]
    5. 如果 e = 0,或者如果 regexpRecord.[[Multiline]]true 且字符 input[e - 1] 被 LineTerminator 匹配,则
      1. 返回 continue(matchState)。
    6. 返回 failure
Note 2

即使 y 标志与模式一起使用,^ 也始终只匹配 input 开头,或(如果 regexpRecord.[[Multiline]]true)行开头。

Assertion :: $
  1. 返回一个新的 Matcher,其参数为 (matchState, continue),捕获 regexpRecord,并在被调用时执行以下步骤:
    1. 断言:matchStateMatchState
    2. 断言:continueMatcherContinuation
    3. inputmatchState.[[Input]]
    4. ematchState.[[EndIndex]]
    5. inputLengthinput 中的元素数量。
    6. 如果 e = inputLength,或者如果 regexpRecord.[[Multiline]]true 且字符 input[e] 被 LineTerminator 匹配,则
      1. 返回 continue(matchState)。
    7. 返回 failure
Assertion :: \b
  1. 返回一个新的 Matcher,其参数为 (matchState, continue),捕获 regexpRecord,并在被调用时执行以下步骤:
    1. 断言:matchStateMatchState
    2. 断言:continueMatcherContinuation
    3. inputmatchState.[[Input]]
    4. ematchState.[[EndIndex]]
    5. aIsWordChar(regexpRecord, input, e - 1)。
    6. bIsWordChar(regexpRecord, input, e)。
    7. 如果 atruebfalse,或者如果 afalsebtrue,则返回 continue(matchState)。
    8. 返回 failure
Assertion :: \B
  1. 返回一个新的 Matcher,其参数为 (matchState, continue),捕获 regexpRecord,并在被调用时执行以下步骤:
    1. 断言:matchStateMatchState
    2. 断言:continueMatcherContinuation
    3. inputmatchState.[[Input]]
    4. ematchState.[[EndIndex]]
    5. aIsWordChar(regexpRecord, input, e - 1)。
    6. bIsWordChar(regexpRecord, input, e)。
    7. 如果 atruebtrue,或者如果 afalsebfalse,则返回 continue(matchState)。
    8. 返回 failure
Assertion :: (?= Disjunction )
  1. m 为以 regexpRecordforward 为实参执行 DisjunctionCompileSubpattern
  2. 返回一个新的 Matcher,其参数为 (matchState, continue),捕获 m,并在被调用时执行以下步骤:
    1. 断言:matchStateMatchState
    2. 断言:continueMatcherContinuation
    3. d 为新的 MatcherContinuation,其参数为 (y),不捕获任何内容,并在被调用时执行以下步骤:
      1. 断言:yMatchState
      2. 返回 y
    4. resultm(matchState, d)。
    5. 如果 resultfailure,则返回 failure
    6. 断言:resultMatchState
    7. capabilityresult.[[Captures]]
    8. inputmatchState.[[Input]]
    9. xematchState.[[EndIndex]]
    10. zMatchState { [[Input]]: input, [[EndIndex]]: xe, [[Captures]]: capability }。
    11. 返回 continue(z)。
Note 3

形式 (?= Disjunction ) 指定零宽正向先行断言。为了使其成功,Disjunction 内的模式必须在当前位置匹配,但在匹配后续部分之前当前位置不会前进。如果 Disjunction 可以在当前位置以多种方式匹配,则只尝试第一种方式。与其他正则表达式运算符不同,不会回溯进入 (?= 形式(这种不寻常行为继承自 Perl)。只有当 Disjunction 包含捕获括号,并且模式的后续部分包含对这些 captures 的反向引用时,这一点才重要。

例如,

/(?=(a+))/.exec("baaabac")

匹配第一个 b 后紧接的空 String,因此返回数组:

["", "aaa"]

为说明不会回溯进入先行断言,请考虑:

/(?=(a+))a*b\1/.exec("baaabac")

此表达式返回

["aba", "a"]

而不是:

["aaaba", "a"]
Assertion :: (?! Disjunction )
  1. m 为以 regexpRecordforward 为实参执行 DisjunctionCompileSubpattern
  2. 返回一个新的 Matcher,其参数为 (matchState, continue),捕获 m,并在被调用时执行以下步骤:
    1. 断言:matchStateMatchState
    2. 断言:continueMatcherContinuation
    3. d 为新的 MatcherContinuation,其参数为 (y),不捕获任何内容,并在被调用时执行以下步骤:
      1. 断言:yMatchState
      2. 返回 y
    4. resultm(matchState, d)。
    5. 如果 result 不是 failure,则返回 failure
    6. 返回 continue(matchState)。
Note 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 为以 regexpRecordbackward 为实参执行 DisjunctionCompileSubpattern
  2. 返回一个新的 Matcher,其参数为 (matchState, continue),捕获 m,并在被调用时执行以下步骤:
    1. 断言:matchStateMatchState
    2. 断言:continueMatcherContinuation
    3. d 为新的 MatcherContinuation,其参数为 (y),不捕获任何内容,并在被调用时执行以下步骤:
      1. 断言:yMatchState
      2. 返回 y
    4. resultm(matchState, d)。
    5. 如果 resultfailure,则返回 failure
    6. 断言:resultMatchState
    7. capabilityresult.[[Captures]]
    8. inputmatchState.[[Input]]
    9. xematchState.[[EndIndex]]
    10. zMatchState { [[Input]]: input, [[EndIndex]]: xe, [[Captures]]: capability }。
    11. 返回 continue(z)。
Assertion :: (?<! Disjunction )
  1. m 为以 regexpRecordbackward 为实参执行 DisjunctionCompileSubpattern
  2. 返回一个新的 Matcher,其参数为 (matchState, continue),捕获 m,并在被调用时执行以下步骤:
    1. 断言:matchStateMatchState
    2. 断言:continueMatcherContinuation
    3. d 为新的 MatcherContinuation,其参数为 (y),不捕获任何内容,并在被调用时执行以下步骤:
      1. 断言:yMatchState
      2. 返回 y
    4. resultm(matchState, d)。
    5. 如果 result 不是 failure,则返回 failure
    6. 返回 continue(matchState)。

22.2.2.4.1 IsWordChar ( regexpRecord, input, e )

The abstract operation IsWordChar takes arguments regexpRecord (a RegExp Record), input (a List of characters), and e (an integer) and returns a Boolean. It performs the following steps when called:

  1. inputLengthinput 中的元素数量。
  2. 如果 e = -1 或 e = inputLength,则返回 false
  3. char 为字符 input[e]。
  4. 如果 WordCharacters(regexpRecord) 包含 char,则返回 true
  5. 返回 false

22.2.2.5 Runtime Semantics: CompileQuantifier

The syntax-directed operation CompileQuantifier takes no arguments and returns a Record with fields [[Min]] (a non-negative integer), [[Max]] (a non-negative integer or +∞), and [[Greedy]] (a Boolean). It is defined piecewise over the following productions:

Quantifier :: QuantifierPrefix
  1. qpQuantifierPrefixCompileQuantifierPrefix
  2. 返回 Record { [[Min]]: qp.[[Min]], [[Max]]: qp.[[Max]], [[Greedy]]: true }。
Quantifier :: QuantifierPrefix ?
  1. qpQuantifierPrefixCompileQuantifierPrefix
  2. 返回 Record { [[Min]]: qp.[[Min]], [[Max]]: qp.[[Max]], [[Greedy]]: false }。

22.2.2.6 Runtime Semantics: CompileQuantifierPrefix

The syntax-directed operation CompileQuantifierPrefix takes no arguments and returns a Record with fields [[Min]] (a non-negative integer) and [[Max]] (a non-negative integer or +∞). It is defined piecewise over the following productions:

QuantifierPrefix :: *
  1. 返回 Record { [[Min]]: 0, [[Max]]: +∞ }。
QuantifierPrefix :: +
  1. 返回 Record { [[Min]]: 1, [[Max]]: +∞ }。
QuantifierPrefix :: ?
  1. 返回 Record { [[Min]]: 0, [[Max]]: 1 }。
QuantifierPrefix :: { DecimalDigits }
  1. iDecimalDigits 的 MV(见 12.9.3)。
  2. 返回 Record { [[Min]]: i, [[Max]]: i }。
QuantifierPrefix :: { DecimalDigits ,}
  1. iDecimalDigits 的 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

The syntax-directed operation CompileAtom takes arguments regexpRecord (a RegExp Record) and direction (forward or backward) and returns a Matcher.

Note 1

本节在 B.1.2.7 中被修订。

It is defined piecewise over the following productions:

Atom :: PatternCharacter
  1. charPatternCharacter 匹配的字符。
  2. charSet包含字符 char 的单元素 CharSet
  3. 返回 CharacterSetMatcher(regexpRecord, charSet, false, direction)。
Atom :: .
  1. charSetAllCharacters(regexpRecord)。
  2. 如果 regexpRecord.[[DotAll]] 不是 true,则
    1. charSet 中移除所有与 LineTerminator 产生式右侧码点对应的字符。
  3. 返回 CharacterSetMatcher(regexpRecord, charSet, false, direction)。
Atom :: CharacterClass
  1. cc 为以 regexpRecord 为实参执行 CharacterClassCompileCharacterClass
  2. cscc.[[CharSet]]
  3. 如果 regexpRecord.[[UnicodeSets]]false,或 cs 的每个 CharSetElement 都由单个字符组成(包括 cs 为空的情况),则返回 CharacterSetMatcher(regexpRecord, cs, cc.[[Invert]], direction)。
  4. 断言:cc.[[Invert]]false
  5. listOfMatchers 为空 Matcher List
  6. cs包含多于 1 个字符的每个 CharSetElement s,按长度降序迭代,执行:
    1. cs2包含 s 最后一个码点的单元素 CharSet
    2. m2CharacterSetMatcher(regexpRecord, cs2, false, direction)。
    3. s 中每个码点 c1,从其倒数第二个码点开始向后迭代,执行:
      1. cs1包含 c1 的单元素 CharSet
      2. m1CharacterSetMatcher(regexpRecord, cs1, false, direction)。
      3. m2 设置为 MatchSequence(m1, m2, direction)。
    4. m2 追加到 listOfMatchers
  7. singles包含 cs 中所有由单个字符组成的 CharSetElementCharSet
  8. CharacterSetMatcher(regexpRecord, singles, false, direction) 追加到 listOfMatchers
  9. 如果 cs 包含空字符序列,则将 EmptyMatcher() 追加到 listOfMatchers
  10. m2listOfMatchers 中最后一个 Matcher
  11. listOfMatchers 的每个 Matcher m1,从倒数第二个元素开始向后迭代,执行:
    1. m2 设置为 MatchTwoAlternatives(m1, m2)。
  12. 返回 m2
Atom :: ( GroupSpecifieropt Disjunction )
  1. m 为以 regexpRecorddirection 为实参执行 DisjunctionCompileSubpattern
  2. parenIndexCountLeftCapturingParensBefore(Atom)。
  3. 返回一个新的 Matcher,其参数为 (x, c),捕获 directionmparenIndex,并在被调用时执行以下步骤:
    1. 断言:xMatchState
    2. 断言:cMatcherContinuation
    3. d 为新的 MatcherContinuation,其参数为 (y),捕获 xcdirectionparenIndex,并在被调用时执行以下步骤:
      1. 断言:yMatchState
      2. capabilityy.[[Captures]] 的副本。
      3. inputx.[[Input]]
      4. xex.[[EndIndex]]
      5. yey.[[EndIndex]]
      6. 如果 directionforward,则
        1. 断言:xeye
        2. rCaptureRange { [[StartIndex]]: xe, [[EndIndex]]: ye }。
      7. 否则,
        1. 断言:directionbackward
        2. 断言:yexe
        3. rCaptureRange { [[StartIndex]]: ye, [[EndIndex]]: xe }。
      8. capability[parenIndex + 1] 设置为 r
      9. zMatchState { [[Input]]: input, [[EndIndex]]: ye, [[Captures]]: capability }。
      10. 返回 c(z)。
    4. 返回 m(x, d)。
Note 2

形式为 ( Disjunction ) 的括号既用于把 Disjunction 模式的组成部分组合在一起,也用于保存匹配结果。该结果可以用于反向引用(\ 后跟非零十进制数)、在替换 String 中被引用,或作为从正则表达式匹配 Abstract Closure 返回的数组的一部分。要抑制括号的捕获行为,请改用形式 (?: Disjunction )

Atom :: (? RegularExpressionModifiers : Disjunction )
  1. addModifiersRegularExpressionModifiers 匹配的源文本
  2. removeModifiers 为空 String。
  3. modifiedRerUpdateModifiers(regexpRecord, CodePointsToString(addModifiers), removeModifiers)。
  4. 返回以 modifiedRerdirection 为实参执行 DisjunctionCompileSubpattern
Atom :: (? RegularExpressionModifiers - RegularExpressionModifiers : Disjunction )
  1. addModifiers 为第一个 RegularExpressionModifiers 匹配的源文本
  2. removeModifiers 为第二个 RegularExpressionModifiers 匹配的源文本
  3. modifiedRerUpdateModifiers(regexpRecord, CodePointsToString(addModifiers), CodePointsToString(removeModifiers))。
  4. 返回以 modifiedRerdirection 为实参执行 DisjunctionCompileSubpattern
AtomEscape :: DecimalEscape
  1. nDecimalEscapeCapturingGroupNumber
  2. 断言:nregexpRecord.[[CapturingGroupsCount]]
  3. 返回 BackreferenceMatcher(regexpRecord, « n », direction)。
Note 3

形式为 \ 后跟非零十进制数 n 的转义序列,会匹配第 nth 组捕获括号的结果(22.2.2.1)。如果正则表达式的捕获括号少于 n 个,则为错误。如果正则表达式有 n 个或更多捕获括号,但第 nth 个由于尚未捕获任何内容而为 undefined,则该反向引用始终成功。

AtomEscape :: CharacterEscape
  1. charValueCharacterEscapeCharacterValue
  2. char 为其字符值为 charValue 的字符。
  3. charSet包含字符 char 的单元素 CharSet
  4. 返回 CharacterSetMatcher(regexpRecord, charSet, false, direction)。
AtomEscape :: CharacterClassEscape
  1. cs 为以 regexpRecord 为实参执行 CharacterClassEscapeCompileToCharSet
  2. 如果 regexpRecord.[[UnicodeSets]]false,或 cs 的每个 CharSetElement 都由单个字符组成(包括 cs 为空的情况),则返回 CharacterSetMatcher(regexpRecord, cs, false, direction)。
  3. listOfMatchers 为空 Matcher List
  4. cs包含多于 1 个字符的每个 CharSetElement s,按长度降序迭代,执行:
    1. cs2包含 s 最后一个码点的单元素 CharSet
    2. m2CharacterSetMatcher(regexpRecord, cs2, false, direction)。
    3. s 中每个码点 c1,从其倒数第二个码点开始向后迭代,执行:
      1. cs1包含 c1 的单元素 CharSet
      2. m1CharacterSetMatcher(regexpRecord, cs1, false, direction)。
      3. m2 设置为 MatchSequence(m1, m2, direction)。
    4. m2 追加到 listOfMatchers
  5. singles包含 cs 中所有由单个字符组成的 CharSetElementCharSet
  6. CharacterSetMatcher(regexpRecord, singles, false, direction) 追加到 listOfMatchers
  7. 如果 cs 包含空字符序列,则将 EmptyMatcher() 追加到 listOfMatchers
  8. m2listOfMatchers 中最后一个 Matcher
  9. listOfMatchers 的每个 Matcher m1,从倒数第二个元素开始向后迭代,执行:
    1. m2 设置为 MatchTwoAlternatives(m1, m2)。
  10. 返回 m2
AtomEscape :: k GroupName
  1. matchingGroupSpecifiersGroupSpecifiersThatMatch(GroupName)。
  2. parenIndices 为新的空 List
  3. matchingGroupSpecifiers 的每个 GroupSpecifier groupSpecifier,执行:
    1. parenIndexCountLeftCapturingParensBefore(groupSpecifier)。
    2. parenIndex 追加到 parenIndices
  4. 返回 BackreferenceMatcher(regexpRecord, parenIndices, direction)。

22.2.2.7.1 CharacterSetMatcher ( regexpRecord, charSet, invert, direction )

The abstract operation CharacterSetMatcher takes arguments regexpRecord (a RegExp Record), charSet (a CharSet), invert (a Boolean), and direction (forward or backward) and returns a Matcher. It performs the following steps when called:

  1. 如果 regexpRecord.[[UnicodeSets]]true,则
    1. 断言:invertfalse
    2. 断言:charSet 的每个 CharSetElement 都由单个字符组成。
  2. 返回一个新的 Matcher,其参数为 (x, c),捕获 regexpRecordcharSetinvertdirection,并在被调用时执行以下步骤:
    1. 断言:xMatchState
    2. 断言:cMatcherContinuation
    3. inputx.[[Input]]
    4. endIndexx.[[EndIndex]]
    5. 如果 directionforward,则令 fendIndex + 1。
    6. 否则,令 fendIndex - 1。
    7. inputLengthinput 中的元素数量。
    8. 如果 f < 0 或 f > inputLength,则返回 failure
    9. indexmin(endIndex, f)。
    10. char 为字符 input[index]。
    11. ccCanonicalize(regexpRecord, char)。
    12. 如果 charSet 中存在一个 CharSetElement,它恰好包含一个字符 a,并且 Canonicalize(regexpRecord, a) 是 cc,则令 foundtrue;否则令 foundfalse
    13. 如果 invertfalsefoundfalse,则返回 failure
    14. 如果 inverttruefoundtrue,则返回 failure
    15. capabilityx.[[Captures]]
    16. yMatchState { [[Input]]: input, [[EndIndex]]: f, [[Captures]]: capability }。
    17. 返回 c(y)。

22.2.2.7.2 BackreferenceMatcher ( regexpRecord, ns, direction )

The abstract operation BackreferenceMatcher takes arguments regexpRecord (a RegExp Record), ns (a List of positive integers), and direction (forward or backward) and returns a Matcher. It performs the following steps when called:

  1. 返回一个新的 Matcher,其参数为 (x, c),捕获 regexpRecordnsdirection,并在被调用时执行以下步骤:
    1. 断言:xMatchState
    2. 断言:cMatcherContinuation
    3. inputx.[[Input]]
    4. capabilityx.[[Captures]]
    5. rundefined
    6. ns 的每个整数 n,执行:
      1. 如果 capability[n] 不是 undefined,则
        1. 断言:rundefined
        2. r 设置为 capability[n]。
    7. 如果 rundefined,则返回 c(x)。
    8. endIndexx.[[EndIndex]]
    9. rsr.[[StartIndex]]
    10. rer.[[EndIndex]]
    11. lengthre - rs
    12. 如果 directionforward,则令 fendIndex + length
    13. 否则,令 fendIndex - length
    14. inputLengthinput 中的元素数量。
    15. 如果 f < 0 或 f > inputLength,则返回 failure
    16. gmin(endIndex, f)。
    17. 如果存在从 0(包含)到 length(不包含区间内的整数 i,使得 Canonicalize(regexpRecord, input[rs + i]) 不是 Canonicalize(regexpRecord, input[g + i]),则返回 failure
    18. yMatchState { [[Input]]: input, [[EndIndex]]: f, [[Captures]]: capability }。
    19. 返回 c(y)。

22.2.2.7.3 Canonicalize ( regexpRecord, char )

The abstract operation Canonicalize takes arguments regexpRecord (a RegExp Record) and char (a character) and returns a character. It performs the following steps when called:

  1. 如果 HasEitherUnicodeFlag(regexpRecord) 是 trueregexpRecord.[[IgnoreCase]]true,则
    1. 如果 Unicode Character Database 的文件 CaseFolding.txtchar 提供 simple 或 common case folding 映射,则返回把该映射应用于 char 的结果。
    2. 返回 char
  2. 如果 regexpRecord.[[IgnoreCase]]false,则返回 char
  3. 断言:char 是 UTF-16 码元。
  4. codePoint 为其数值为 char 的数值的码点。
  5. u 为依据 Unicode Default Case Conversion 算法的 toUppercase(« codePoint »)。
  6. uStringCodePointsToString(u)。
  7. 如果 uString 的长度 ≠ 1,则返回 char
  8. codeUnituString 的单个码元元素。
  9. 如果 char 的数值 ≥ 128 且 codeUnit 的数值 < 128,则返回 char
  10. 返回 codeUnit
Note

HasEitherUnicodeFlag(regexpRecord) 是 true 的大小写无关匹配中,所有字符在比较之前都会隐式使用 Unicode Standard 提供的 simple 映射进行 case-fold。simple 映射始终映射到单个码点,因此它不会例如把 ß(U+00DF LATIN SMALL LETTER SHARP S)映射为 ssSS。不过,它可能把 Basic Latin 块之外的码点映射到其中的码点——例如,ſ(U+017F LATIN SMALL LETTER LONG S)会 case-fold 为 s(U+0073 LATIN SMALL LETTER S),而 (U+212A KELVIN SIGN)会 case-fold 为 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+03C9 GREEK SMALL LETTER OMEGA),同时 Ω(U+03A9 GREEK CAPITAL 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 )

The abstract operation UpdateModifiers takes arguments regexpRecord (a RegExp Record), add (a String), and remove (a String) and returns a RegExp Record. It performs the following steps when called:

  1. 断言:addremove 没有共同元素。
  2. ignoreCaseregexpRecord.[[IgnoreCase]]
  3. multilineregexpRecord.[[Multiline]]
  4. dotAllregexpRecord.[[DotAll]]
  5. unicoderegexpRecord.[[Unicode]]
  6. unicodeSetsregexpRecord.[[UnicodeSets]]
  7. capturingGroupsCountregexpRecord.[[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

The syntax-directed operation CompileCharacterClass takes argument regexpRecord (a RegExp Record) and returns a Record with fields [[CharSet]] (a CharSet) and [[Invert]] (a Boolean). It is defined piecewise over the following productions:

CharacterClass :: [ ClassContents ]
  1. charSet 为以 regexpRecord 为实参执行 ClassContentsCompileToCharSet
  2. 返回 Record { [[CharSet]]: charSet, [[Invert]]: false }。
CharacterClass :: [^ ClassContents ]
  1. charSet 为以 regexpRecord 为实参执行 ClassContentsCompileToCharSet
  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

The syntax-directed operation CompileToCharSet takes argument regexpRecord (a RegExp Record) and returns a CharSet.

Note 1

本节在 B.1.2.8 中被修订。

It is defined piecewise over the following productions:

ClassContents :: [empty]
  1. 返回空 CharSet
NonemptyClassRanges :: ClassAtom NonemptyClassRangesNoDash
  1. charSet 为以 regexpRecord 为实参执行 ClassAtomCompileToCharSet
  2. otherSet 为以 regexpRecord 为实参执行 NonemptyClassRangesNoDashCompileToCharSet
  3. 返回 CharSet charSetotherSet 的并集。
NonemptyClassRanges :: ClassAtom - ClassAtom ClassContents
  1. charSet 为以 regexpRecord 为实参执行第一个 ClassAtomCompileToCharSet
  2. otherSet 为以 regexpRecord 为实参执行第二个 ClassAtomCompileToCharSet
  3. remainingSet 为以 regexpRecord 为实参执行 ClassContentsCompileToCharSet
  4. rangeSetCharacterRange(charSet, otherSet)。
  5. 返回 rangeSetremainingSet 的并集。
NonemptyClassRangesNoDash :: ClassAtomNoDash NonemptyClassRangesNoDash
  1. charSet 为以 regexpRecord 为实参执行 ClassAtomNoDashCompileToCharSet
  2. otherSet 为以 regexpRecord 为实参执行 NonemptyClassRangesNoDashCompileToCharSet
  3. 返回 CharSet charSetotherSet 的并集。
NonemptyClassRangesNoDash :: ClassAtomNoDash - ClassAtom ClassContents
  1. charSet 为以 regexpRecord 为实参执行 ClassAtomNoDashCompileToCharSet
  2. otherSet 为以 regexpRecord 为实参执行 ClassAtomCompileToCharSet
  3. remainingSet 为以 regexpRecord 为实参执行 ClassContentsCompileToCharSet
  4. rangeSetCharacterRange(charSet, otherSet)。
  5. 返回 rangeSetremainingSet 的并集。
Note 2

ClassContents 可以展开为单个 ClassAtom,和/或由短横线分隔的两个 ClassAtom 的范围。在后一种情况下,ClassContents 包括第一个 ClassAtom 与第二个 ClassAtom 之间的所有字符,包含两端;如果任一 ClassAtom 不表示单个字符(例如,如果其中一个是 \w),或者如果第一个 ClassAtom 的字符值严格大于第二个 ClassAtom 的字符值,则会发生错误。

Note 3

即使模式忽略大小写,范围两端的大小写对于确定哪些字符属于该范围也是重要的。因此,例如,模式 /[E-F]/i 只匹配字母 EFef,而模式 /[E-f]/i 会匹配 Unicode Basic Latin 块中的所有大写和小写字母,以及符号 [, \, ], ^, _`

Note 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 为此 ClassEscapeCharacterValue
  2. char 为其字符值为 charValue 的字符。
  3. 返回包含单个字符 charCharSet
Note 5

ClassAtom 可以使用正则表达式其余部分中允许的任意转义序列,但 \b\B 和反向引用除外。在 CharacterClass 内部,\b 表示退格字符,而 \B 和反向引用会引发错误。在 ClassAtom 内使用反向引用会导致错误。

CharacterClassEscape :: d
  1. 返回包含字符 0123456789 的十元素 CharSet
CharacterClassEscape :: D
  1. charSet CharacterClassEscape :: d 返回的 CharSet
  2. 返回 CharacterComplement(regexpRecord, charSet)。
CharacterClassEscape :: s
  1. 返回包含WhiteSpaceLineTerminator 产生式右侧码点对应的所有字符的 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. 返回以 regexpRecord 为实参执行 UnicodePropertyValueExpressionCompileToCharSet
CharacterClassEscape :: P{ UnicodePropertyValueExpression }
  1. charSet 为以 regexpRecord 为实参执行 UnicodePropertyValueExpressionCompileToCharSet
  2. 断言:charSet包含单个码点。
  3. 返回 CharacterComplement(regexpRecord, charSet)。
UnicodePropertyValueExpression :: UnicodePropertyName = UnicodePropertyValue
  1. psUnicodePropertyName 匹配的源文本
  2. pUnicodeMatchProperty(regexpRecord, ps)。
  3. 断言:pTable 65 的 “Property name and aliases” 列中列出的 Unicode 属性名或属性别名。
  4. vsUnicodePropertyValue 匹配的源文本
  5. vUnicodeMatchPropertyValue(p, vs)。
  6. charSet包含所有 Unicode 码点的 CharSet,这些码点的字符数据库定义包含值为 v 的属性 p
  7. 返回 MaybeSimpleCaseFolding(regexpRecord, charSet)。
UnicodePropertyValueExpression :: LoneUnicodePropertyNameOrValue
  1. sLoneUnicodePropertyNameOrValue 匹配的源文本
  2. 如果 UnicodeMatchPropertyValue(General_Category, s) 是 PropertyValueAliases.txt 中列出的 General_Category (gc) 属性的 Unicode 属性值或属性值别名,则
    1. 返回包含所有 Unicode 码点的 CharSet,这些码点的字符数据库定义包含值为 s 的属性 “General_Category”。
  3. pUnicodeMatchProperty(regexpRecord, s)。
  4. 断言:pTable 66 的 “Property name and aliases” 列中列出的二元 Unicode 属性或二元属性别名,或是 Table 67 的 “Property name” 列中列出的字符串二元 Unicode 属性。
  5. charSet包含所有 CharSetElementCharSet,这些元素的字符数据库定义包含值为 “True” 的属性 p
  6. 返回 MaybeSimpleCaseFolding(regexpRecord, charSet)。
ClassUnion :: ClassSetRange ClassUnionopt
  1. charSet 为以 regexpRecord 为实参执行 ClassSetRangeCompileToCharSet
  2. 如果 ClassUnion 存在,则
    1. otherSet 为以 regexpRecord 为实参执行 ClassUnionCompileToCharSet
    2. 返回 CharSet charSetotherSet 的并集。
  3. 返回 charSet
ClassUnion :: ClassSetOperand ClassUnionopt
  1. charSet 为以 regexpRecord 为实参执行 ClassSetOperandCompileToCharSet
  2. 如果 ClassUnion 存在,则
    1. otherSet 为以 regexpRecord 为实参执行 ClassUnionCompileToCharSet
    2. 返回 CharSet charSetotherSet 的并集。
  3. 返回 charSet
ClassIntersection :: ClassSetOperand && ClassSetOperand
  1. charSet 为以 regexpRecord 为实参执行第一个 ClassSetOperandCompileToCharSet
  2. otherSet 为以 regexpRecord 为实参执行第二个 ClassSetOperandCompileToCharSet
  3. 返回 CharSet charSetotherSet 的交集。
ClassIntersection :: ClassIntersection && ClassSetOperand
  1. charSet 为以 regexpRecord 为实参执行 ClassIntersectionCompileToCharSet
  2. otherSet 为以 regexpRecord 为实参执行 ClassSetOperandCompileToCharSet
  3. 返回 CharSet charSetotherSet 的交集。
ClassSubtraction :: ClassSetOperand -- ClassSetOperand
  1. charSet 为以 regexpRecord 为实参执行第一个 ClassSetOperandCompileToCharSet
  2. otherSet 为以 regexpRecord 为实参执行第二个 ClassSetOperandCompileToCharSet
  3. 返回包含 charSet 中不是 otherSetCharSetElement 的那些 CharSetElementCharSet
ClassSubtraction :: ClassSubtraction -- ClassSetOperand
  1. charSet 为以 regexpRecord 为实参执行 ClassSubtractionCompileToCharSet
  2. otherSet 为以 regexpRecord 为实参执行 ClassSetOperandCompileToCharSet
  3. 返回包含 charSet 中不是 otherSetCharSetElement 的那些 CharSetElementCharSet
ClassSetRange :: ClassSetCharacter - ClassSetCharacter
  1. charSet 为以 regexpRecord 为实参执行第一个 ClassSetCharacterCompileToCharSet
  2. otherSet 为以 regexpRecord 为实参执行第二个 ClassSetCharacterCompileToCharSet
  3. 返回 MaybeSimpleCaseFolding(regexpRecord, CharacterRange(charSet, otherSet))。
Note 6

结果通常会由两个或更多范围组成。当 UnicodeSets 是 true 且 IgnoreCase 是 true 时,MaybeSimpleCaseFolding(regexpRecord, [Ā-č]) 将只包含该范围内奇数编号的码点。

ClassSetOperand :: ClassSetCharacter
  1. charSet 为以 regexpRecord 为实参执行 ClassSetCharacterCompileToCharSet
  2. 返回 MaybeSimpleCaseFolding(regexpRecord, charSet)。
ClassSetOperand :: ClassStringDisjunction
  1. charSet 为以 regexpRecord 为实参执行 ClassStringDisjunctionCompileToCharSet
  2. 返回 MaybeSimpleCaseFolding(regexpRecord, charSet)。
ClassSetOperand :: NestedClass
  1. 返回以 regexpRecord 为实参执行 NestedClassCompileToCharSet
NestedClass :: [ ClassContents ]
  1. 返回以 regexpRecord 为实参执行 ClassContentsCompileToCharSet
NestedClass :: [^ ClassContents ]
  1. charSet 为以 regexpRecord 为实参执行 ClassContentsCompileToCharSet
  2. 返回 CharacterComplement(regexpRecord, charSet)。
NestedClass :: \ CharacterClassEscape
  1. 返回以 regexpRecord 为实参执行 CharacterClassEscapeCompileToCharSet
ClassStringDisjunction :: \q{ ClassStringDisjunctionContents }
  1. 返回以 regexpRecord 为实参执行 ClassStringDisjunctionContentsCompileToCharSet
ClassStringDisjunctionContents :: ClassString
  1. s 为以 regexpRecord 为实参执行 ClassStringCompileClassSetString
  2. 返回包含一个字符串 sCharSet
ClassStringDisjunctionContents :: ClassString | ClassStringDisjunctionContents
  1. s 为以 regexpRecord 为实参执行 ClassStringCompileClassSetString
  2. charSet包含一个字符串 sCharSet
  3. otherSet 为以 regexpRecord 为实参执行 ClassStringDisjunctionContentsCompileToCharSet
  4. 返回 CharSet charSetotherSet 的并集。
ClassSetCharacter :: SourceCharacter but not ClassSetSyntaxCharacter \ CharacterEscape \ ClassSetReservedPunctuator
  1. charValue 为此 ClassSetCharacterCharacterValue
  2. char 为其字符值为 charValue 的字符。
  3. 返回包含单个字符 charCharSet
ClassSetCharacter :: \b
  1. 返回包含单个字符 U+0008(BACKSPACE)的 CharSet

22.2.2.9.1 CharacterRange ( charSet, otherSet )

The abstract operation CharacterRange takes arguments charSet (a CharSet) and otherSet (a CharSet) and returns a CharSet. It performs the following steps when called:

  1. 断言:charSetotherSet 都恰好包含一个字符。
  2. aCharSet charSet 中的一个字符。
  3. bCharSet otherSet 中的一个字符。
  4. i 为字符 a 的字符值。
  5. j 为字符 b 的字符值。
  6. 断言:ij
  7. 返回包含所有字符的 CharSet,这些字符的字符值位于从 ij闭区间内。

22.2.2.9.2 HasEitherUnicodeFlag ( regexpRecord )

The abstract operation HasEitherUnicodeFlag takes argument regexpRecord (a RegExp Record) and returns a Boolean. It performs the following steps when called:

  1. 如果 regexpRecord.[[Unicode]]trueregexpRecord.[[UnicodeSets]]true,则返回 true
  2. 返回 false

22.2.2.9.3 WordCharacters ( regexpRecord )

The abstract operation WordCharacters takes argument regexpRecord (a RegExp Record) and returns a CharSet. 返回一个 CharSet,其中包含\b\B\w\W 的目的而被视为“word characters”的字符。 It performs the following steps when called:

  1. basicWordChars包含 ASCII word characters 中每个字符的 CharSet
  2. extraWordChars包含所有字符 cCharSet,使得 c 不在 basicWordChars 中但 Canonicalize(regexpRecord, c) 在 basicWordChars 中。
  3. 断言:除非 HasEitherUnicodeFlag(regexpRecord) 是 trueregexpRecord.[[IgnoreCase]]true,否则 extraWordChars 为空。
  4. 返回 basicWordCharsextraWordChars 的并集。

22.2.2.9.4 AllCharacters ( regexpRecord )

The abstract operation AllCharacters takes argument regexpRecord (a RegExp Record) and returns a CharSet. 根据正则表达式标志返回“所有字符”的集合。 It performs the following steps when called:

  1. 如果 regexpRecord.[[UnicodeSets]]trueregexpRecord.[[IgnoreCase]]true,则
    1. 返回包含所有没有 Simple Case Folding 映射(即 scf(c)=c)的 Unicode 码点 cCharSet
  2. 如果 HasEitherUnicodeFlag(regexpRecord) 是 true,则
    1. 返回包含所有码点值的 CharSet
  3. 返回包含所有码元值的 CharSet

22.2.2.9.5 MaybeSimpleCaseFolding ( regexpRecord, charSet )

The abstract operation MaybeSimpleCaseFolding takes arguments regexpRecord (a RegExp Record) and charSet (a CharSet) and returns a CharSet. 如果 regexpRecord.[[UnicodeSets]]falseregexpRecord.[[IgnoreCase]]false,则返回 charSet。否则,它使用 Unicode Character Database 文件 CaseFolding.txt 中的 Simple Case Foldingscf(codePoint))定义(每个定义都会把单个码点映射到另一个单个码点),逐字符地把 charSet 的每个 CharSetElement 映射到规范形式,并返回所得 CharSet。 It performs the following steps when called:

  1. 如果 regexpRecord.[[UnicodeSets]]falseregexpRecord.[[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 )

The abstract operation CharacterComplement takes arguments regexpRecord (a RegExp Record) and complement (a CharSet) and returns a CharSet. It performs the following steps when called:

  1. charSetAllCharacters(regexpRecord)。
  2. 返回包含 charSet 中不是 complementCharSetElement 的那些 CharSetElementCharSet

22.2.2.9.7 UnicodeMatchProperty ( regexpRecord, p )

The abstract operation UnicodeMatchProperty takes arguments regexpRecord (a RegExp Record) and p (ECMAScript source text) and returns a Unicode property name. It performs the following steps when called:

  1. 如果 regexpRecord.[[UnicodeSets]]truepTable 67 的 “Property name” 列中列出的 Unicode 属性名,则
    1. 返回 Unicode 码点 List p
  2. 断言:pTable 65Table 66 的 “Property name and aliases” 列中列出的 Unicode 属性名或属性别名。
  3. c 为对应行的 “Canonical property name” 列中给出的 p 的规范 property name
  4. 返回 Unicode 码点 List c

实现必须支持 Table 65Table 66Table 67 中列出的 Unicode property names 和别名。为确保互操作性,实现不得支持任何其他 property names 或别名。

Note 1

例如,Script_Extensionsproperty name)和 scx(属性别名)是有效的,但 script_extensionsScx 不是。

Note 2

所列属性形成了 UTS18 RL1.2 所要求内容的超集。

Note 3

这些表中条目的拼写(包括大小写)与 Unicode Character Database 文件 PropertyAliases.txt 中使用的拼写一致。该文件中的精确拼写保证稳定

Table 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
Table 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
Table 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 )

The abstract operation UnicodeMatchPropertyValue takes arguments p (ECMAScript source text) and v (ECMAScript source text) and returns a Unicode property value. It performs the following steps when called:

  1. 断言:pTable 65 的 “Canonical property name” 列中列出的规范、非别名 Unicode property name
  2. 断言:vPropertyValueAliases.txt 中列出的 Unicode 属性 p 的属性值或属性值别名。
  3. value 为对应行的 “Canonical property value” 列中给出的 v 的规范属性值。
  4. 返回 Unicode 码点 List value

实现必须支持 PropertyValueAliases.txt 中针对 Table 65 所列属性列出的 Unicode 属性值和属性值别名。为确保互操作性,实现不得支持任何其他属性值或属性值别名。

Note 1

例如,XpeoOld_Persian 是有效的 Script_Extensions 值,但 xpeoOld Persian 不是。

Note 2

此算法不同于 UAX44 中列出的符号值匹配规则:大小写、空白、U+002D(HYPHEN-MINUS)和 U+005F(LOW LINE)不会被忽略,并且不支持 Is 前缀。

22.2.2.10 Runtime Semantics: CompileClassSetString

The syntax-directed operation CompileClassSetString takes argument regexpRecord (a RegExp Record) and returns a sequence of characters. It is defined piecewise over the following productions:

ClassString :: [empty]
  1. 返回空字符序列。
ClassString :: NonEmptyClassString
  1. 返回以 regexpRecord 为实参执行 NonEmptyClassStringCompileClassSetString
NonEmptyClassString :: ClassSetCharacter NonEmptyClassStringopt
  1. cs 为以 regexpRecord 为实参执行 ClassSetCharacterCompileToCharSet
  2. s1 为字符序列,它是 cs 中的单个 CharSetElement
  3. 如果 NonEmptyClassString 存在,则
    1. s2 为以 regexpRecord 为实参执行 NonEmptyClassStringCompileClassSetString
    2. 返回 s1s2 的连接。
  4. 返回 s1

22.2.3 RegExp 创建的抽象操作

22.2.3.1 RegExpCreate ( pattern, flags )

The abstract operation RegExpCreate takes arguments pattern (an ECMAScript language value) and flags (a String or undefined) and returns either a normal completion containing an Object or a throw completion. It performs the following steps when called:

  1. obj 为 ! RegExpAlloc(%RegExp%)。
  2. 返回 ? RegExpInitialize(obj, pattern, flags)。

22.2.3.2 RegExpAlloc ( newTarget )

The abstract operation RegExpAlloc takes argument newTarget (a constructor) and returns either a normal completion containing an Object or a throw completion. It performs the following steps when called:

  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 )

The abstract operation RegExpInitialize takes arguments obj (an Object), pattern (an ECMAScript language value), and flags (an ECMAScript language value) and returns either a normal completion containing an Object or a throw completion. It performs the following steps when called:

  1. 如果 patternundefined,则将 pattern 设置为空 String。
  2. 否则,将 pattern 设置为 ? ToString(pattern)。
  3. 如果 flagsundefined,则将 flags 设置为空 String。
  4. 否则,将 flags 设置为 ? ToString(flags)。
  5. 如果 flags 包含"d""g""i""m""s""u""v""y" 之外的任何码元,则抛出 SyntaxError 异常。
  6. 如果 flags 包含任何码元超过一次,则抛出 SyntaxError 异常。
  7. 如果 flags 包含 "i",则令 itrue;否则令 ifalse
  8. 如果 flags 包含 "m",则令 mtrue;否则令 mfalse
  9. 如果 flags 包含 "s",则令 strue;否则令 sfalse
  10. 如果 flags 包含 "u",则令 utrue;否则令 ufalse
  11. 如果 flags 包含 "v",则令 vtrue;否则令 vfalse
  12. 如果 utruevtrue,则
    1. patternTextStringToCodePoints(pattern)。
  13. 否则,
    1. patternText 为将 pattern 的每个 16 位元素解释为 Unicode BMP 码点的结果。不会对这些元素应用 UTF-16 解码。
  14. parseResultParsePattern(patternText, u, v)。
  15. 如果 parseResult 是非空的 SyntaxError 对象 List,则抛出 SyntaxError 异常。
  16. 断言:parseResultPattern Parse Node
  17. obj.[[OriginalSource]] 设置为 pattern
  18. obj.[[OriginalFlags]] 设置为 flags
  19. capturingGroupsCountCountLeftCapturingParensWithin(parseResult)。
  20. regexpRecordRegExp Record { [[IgnoreCase]]: i, [[Multiline]]: m, [[DotAll]]: s, [[Unicode]]: u, [[UnicodeSets]]: v, [[CapturingGroupsCount]]: capturingGroupsCount }。
  21. obj.[[RegExpRecord]] 设置为 regexpRecord
  22. obj.[[RegExpMatcher]] 设置为以 regexpRecord 为实参执行 parseResultCompilePattern
  23. 执行 ? Set(obj, "lastIndex", +0𝔽, true)。
  24. 返回 obj

22.2.3.4 Static Semantics: ParsePattern ( patternText, u, v )

The abstract operation ParsePattern takes arguments patternText (a sequence of Unicode code points), u (a Boolean), and v (a Boolean) and returns a Parse Node or a non-empty List of SyntaxError objects.

Note

本节在 B.1.2.9 中被修订。

It performs the following steps when called:

  1. 如果 vtrueutrue,则
    1. parseResult包含一个或多个 SyntaxError 对象的 List
  2. 否则,如果 vtrue,则
    1. parseResultParseText(patternText, Pattern[+UnicodeMode, +UnicodeSetsMode, +NamedCaptureGroups])。
  3. 否则,如果 utrue,则
    1. parseResultParseText(patternText, Pattern[+UnicodeMode, ~UnicodeSetsMode, +NamedCaptureGroups])。
  4. 否则,
    1. parseResultParseText(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. 如果 patternIsRegExptrueflagsundefined,则
      1. patternCtor 为 ? Get(patternOrRegexp, "constructor")。
      2. 如果 SameValue(newTarget, patternCtor) 是 true,则返回 patternOrRegexp
  3. 否则,
    1. newTarget 为 NewTarget。
  4. 如果 patternOrRegexp 是 Object 且 patternOrRegexp 具有 [[RegExpMatcher]] 内部槽,则
    1. patternSourcepatternOrRegexp.[[OriginalSource]]
    2. 如果 flagsundefined,则将 flags 设置为 patternOrRegexp.[[OriginalFlags]]
  5. 否则,如果 patternIsRegExptrue,则
    1. patternSource 为 ? Get(patternOrRegexp, "source")。
    2. 如果 flagsundefined,则
      1. flags 设置为 ? Get(patternOrRegexp, "flags")。
  6. 否则,
    1. patternSourcepatternOrRegexp
  7. obj 为 ? RegExpAlloc(newTarget)。
  8. 返回 ? RegExpInitialize(obj, patternSource, flags)。
Note

如果 pattern 使用 StringLiteral 提供,则通常的转义序列替换会在该 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. codePointListStringToCodePoints(string)。
  4. codePointList 的每个码点 codePoint,执行:
    1. 如果 escaped 为空 String 且 codePointDecimalDigitAsciiLetter 匹配,则
      1. 注:转义开头的数字可确保输出对应于可在 \0 字符转义或诸如 \1DecimalEscape 之后使用的模式文本,并且仍匹配 string,而不是被解释为前一个转义序列的扩展。转义开头的 ASCII 字母对 \c 之后的上下文也有同样作用。
      2. numericValuecodePoint 的数值。
      3. hexNumber::toString(𝔽(numericValue), 16)。
      4. 断言:hex 的长度为 2。
      5. escaped 设置为码元 0x005C(REVERSE SOLIDUS)、"x"hex字符串连接
    2. 否则,
      1. escaped 设置为 escapedEncodeForRegExpEscape(codePoint) 的字符串连接
  5. 返回 escaped
Note

尽管名称相似,EscapeRegExpPatternRegExp.escape 并不执行相似的操作。前者转义模式以便表示为字符串,而此函数转义字符串以便表示在模式内部。

22.2.5.1.1 EncodeForRegExpEscape ( codePoint )

The abstract operation EncodeForRegExpEscape takes argument codePoint (a code point) and returns a String. 它返回一个表示 Pattern 的 String,用于匹配 codePoint。如果 codePoint 是空白或 ASCII 标点符号,则返回值是转义序列。否则,返回值是 codePoint 自身的 String 表示。 It performs the following steps when called:

  1. 如果 codePointSyntaxCharacter 匹配,或 codePoint 是 U+002F(SOLIDUS),则
    1. 返回 0x005C(REVERSE SOLIDUS)和 UTF16EncodeCodePoint(codePoint) 的字符串连接
  2. 如果 codePointTable 63 的 “Code Point” 列中列出的码点,则
    1. 返回 0x005C(REVERSE SOLIDUS)和其 “Code Point” 列包含 codePoint 的行的 “ControlEscape” 列中的字符串的字符串连接
  3. otherPunctuators",-=<>#&!%:;@~'`" 和码元 0x0022(QUOTATION MARK)的字符串连接
  4. toEscapeStringToCodePoints(otherPunctuators)。
  5. 如果 toEscape 包含 codePointcodePointWhiteSpaceLineTerminator 匹配,或 codePoint 与前导代理或尾随代理具有相同数值,则
    1. codePointNumbercodePoint 的数值。
    2. 如果 codePointNumber ≤ 0xFF,则
      1. hexNumber::toString(𝔽(codePointNumber), 16)。
      2. 返回码元 0x005C(REVERSE SOLIDUS)、"x"StringPad(hex, 2, "0", start) 的字符串连接
    3. escaped 为空 String。
    4. codeUnitsUTF16EncodeCodePoint(codePoint)。
    5. codeUnits 的每个码元 codeUnit,执行:
      1. escaped 设置为 escapedUnicodeEscape(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 值。

此函数的 "name" 属性的值是 "get [Symbol.species]"

Note

RegExp 原型方法通常使用其 this 值的构造器来创建派生对象。然而,子类构造器可以通过重新定义其 %Symbol.species% 属性来覆盖这种默认行为。

22.2.6 RegExp 原型对象的属性

RegExp 原型对象

  • %RegExp.prototype%
  • 普通对象
  • 不是 RegExp 实例,并且没有 [[RegExpMatcher]] 内部槽,也没有 RegExp 实例对象的任何其他内部槽。
  • 具有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%
Note

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. regexpthis 值。
  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. regexpthis 值。
  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. regexpthis 值。
  2. 如果 regexp 不是 Object,则抛出 TypeError 异常。
  3. codeUnits 为新的空 List
  4. hasIndicesToBoolean(? Get(regexp, "hasIndices")).
  5. 如果 hasIndicestrue,则将码元 0x0064(LATIN SMALL LETTER D)追加到 codeUnits
  6. globalToBoolean(? Get(regexp, "global")).
  7. 如果 globaltrue,则将码元 0x0067(LATIN SMALL LETTER G)追加到 codeUnits
  8. ignoreCaseToBoolean(? Get(regexp, "ignoreCase")).
  9. 如果 ignoreCasetrue,则将码元 0x0069(LATIN SMALL LETTER I)追加到 codeUnits
  10. multilineToBoolean(? Get(regexp, "multiline")).
  11. 如果 multilinetrue,则将码元 0x006D(LATIN SMALL LETTER M)追加到 codeUnits
  12. dotAllToBoolean(? Get(regexp, "dotAll")).
  13. 如果 dotAlltrue,则将码元 0x0073(LATIN SMALL LETTER S)追加到 codeUnits
  14. unicodeToBoolean(? Get(regexp, "unicode")).
  15. 如果 unicodetrue,则将码元 0x0075(LATIN SMALL LETTER U)追加到 codeUnits
  16. unicodeSetsToBoolean(? Get(regexp, "unicodeSets")).
  17. 如果 unicodeSetstrue,则将码元 0x0076(LATIN SMALL LETTER V)追加到 codeUnits
  18. stickyToBoolean(? Get(regexp, "sticky")).
  19. 如果 stickytrue,则将码元 0x0079(LATIN SMALL LETTER Y)追加到 codeUnits
  20. 返回一个 String 值,其码元是 List codeUnits 的元素。如果 codeUnits 没有元素,则返回空 String。

22.2.6.4.1 RegExpHasFlag ( regexp, codeUnit )

The abstract operation RegExpHasFlag takes arguments regexp (an ECMAScript language value) and codeUnit (a code unit) and returns either a normal completion containing either a Boolean or undefined, or a throw completion. It performs the following steps when called:

  1. 如果 regexp 不是 Object,则抛出 TypeError 异常。
  2. 如果 regexp 没有 [[OriginalFlags]] 内部槽,则
    1. 如果 SameValue(regexp, %RegExp.prototype%) 是 true,则返回 undefined
    2. 抛出 TypeError 异常。
  3. flagsregexp.[[OriginalFlags]]
  4. 如果 flags 包含 codeUnit,则返回 true
  5. 返回 false

22.2.6.5 get RegExp.prototype.global

RegExp.prototype.global访问器属性,其 set 访问器函数是 undefined。其 get 访问器函数在被调用时执行以下步骤:

  1. regexpthis 值。
  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. regexpthis 值。
  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. regexpthis 值。
  2. codeUnit 为码元 0x0069(LATIN SMALL LETTER I)。
  3. 返回 ? RegExpHasFlag(regexp, codeUnit)。

22.2.6.8 RegExp.prototype [ %Symbol.match% ] ( string )

此方法在被调用时执行以下步骤:

  1. regexpthis 值。
  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",则令 fullUnicodetrue;否则令 fullUnicodefalse
  7. 执行 ? Set(regexp, "lastIndex", +0𝔽, true)。
  8. array 为 ! ArrayCreate(0)。
  9. matchCount 为 0。
  10. 重复,
    1. result 为 ? RegExpExec(regexp, string)。
    2. 如果 resultnull,则
      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. nextIndexAdvanceStringIndex(string, thisIndex, fullUnicode)。
      3. 执行 ? Set(regexp, "lastIndex", 𝔽(nextIndex), true)。
    6. matchCount 设置为 matchCount + 1。

此方法的 "name" 属性的值是 "[Symbol.match]"

Note

%Symbol.match% 属性由 IsRegExp 抽象操作用来标识具有正则表达式基本行为的对象。缺少 %Symbol.match% 属性,或存在这样的属性但其值经 Boolean 强制转换后不是 true,表示该对象并不意图作为正则表达式对象使用。

22.2.6.9 RegExp.prototype [ %Symbol.matchAll% ] ( string )

此方法在被调用时执行以下步骤:

  1. regexpthis 值。
  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",则令 globaltrue
  10. 否则,令 globalfalse
  11. 如果 flags 包含 "u"flags 包含 "v",则令 fullUnicodetrue
  12. 否则,令 fullUnicodefalse
  13. 返回 CreateRegExpStringIterator(matcher, string, global, fullUnicode)。

此方法的 "name" 属性的值是 "[Symbol.matchAll]"

22.2.6.10 get RegExp.prototype.multiline

RegExp.prototype.multiline访问器属性,其 set 访问器函数是 undefined。其 get 访问器函数在被调用时执行以下步骤:

  1. regexpthis 值。
  2. codeUnit 为码元 0x006D(LATIN SMALL LETTER M)。
  3. 返回 ? RegExpHasFlag(regexp, codeUnit)。

22.2.6.11 RegExp.prototype [ %Symbol.replace% ] ( string, replaceValue )

此方法在被调用时执行以下步骤:

  1. regexpthis 值。
  2. 如果 regexp 不是 Object,则抛出 TypeError 异常。
  3. string 设置为 ? ToString(string)。
  4. stringLengthstring 的长度。
  5. functionalReplaceIsCallable(replaceValue)。
  6. 如果 functionalReplacefalse,则
    1. replaceValue 设置为 ? ToString(replaceValue)。
  7. flags 为 ? ToString(? Get(regexp, "flags"))。
  8. 如果 flags 包含 "g",则令 globaltrue;否则令 globalfalse
  9. 如果 globaltrue,则
    1. 执行 ? Set(regexp, "lastIndex", +0𝔽, true)。
  10. results 为新的空 List
  11. donefalse
  12. 重复,只要 donefalse
    1. result 为 ? RegExpExec(regexp, string)。
    2. 如果 resultnull,则
      1. done 设置为 true
    3. 否则,
      1. result 追加到 results
      2. 如果 globalfalse,则
        1. done 设置为 true
      3. 否则,
        1. matchString 为 ? ToString(? Get(result, "0"))。
        2. 如果 matchString 为空 String,则
          1. thisIndex(? ToLength(? Get(regexp, "lastIndex"))).
          2. 如果 flags 包含 "u"flags 包含 "v",则令 fullUnicodetrue;否则令 fullUnicodefalse
          3. nextIndexAdvanceStringIndex(string, thisIndex, fullUnicode)。
          4. 执行 ? Set(regexp, "lastIndex", 𝔽(nextIndex), true)。
  13. accumulatedResult 为空 String。
  14. nextSourcePosition 为 0。
  15. results 的每个元素 result,执行:
    1. resultLength 为 ? LengthOfArrayLike(result)。
    2. capturesCountmax(resultLength - 1, 0)。
    3. matched 为 ? ToString(? Get(result, "0"))。
    4. matchLengthmatched 的长度。
    5. position 为 ? ToIntegerOrInfinity(? Get(result, "index"))。
    6. position 设置为将 position 夹在 0 与 stringLength 之间的结果。
    7. captures 为新的空 List
    8. captureNumber 为 1。
    9. 重复,只要 captureNumbercapturesCount
      1. capture 为 ? Get(result, ! ToString(𝔽(captureNumber)))。
      2. 如果 capture 不是 undefined,则
        1. capture 设置为 ? ToString(capture)。
      3. capture 追加到 captures
      4. 注:当 captureNumber = 1 时,前一步把第一个元素放入 captures(索引为 0)。更一般地,第 captureNumberth 个 capture(第 captureNumberth 组捕获括号捕获的字符)位于 captures[captureNumber - 1]。
      5. captureNumber 设置为 captureNumber + 1。
    10. namedCaptures 为 ? Get(result, "groups")。
    11. 如果 functionalReplacetrue,则
      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. 如果 positionnextSourcePosition,则
      1. 注:position 通常不应向后移动。如果它向后移动,则表明 RegExp 子类行为不良,或使用访问触发的副作用改变了 regexp 的 global 标志或其他特征。在这些情况下,对应的替换会被忽略。
      2. accumulatedResult 设置为 accumulatedResultstringnextSourcePositionposition子字符串,以及 replacementString字符串连接
      3. nextSourcePosition 设置为 position + matchLength
  16. 如果 nextSourcePositionstringLength,则返回 accumulatedResult
  17. 返回 accumulatedResultstringnextSourcePosition 起的子字符串字符串连接

此方法的 "name" 属性的值是 "[Symbol.replace]"

22.2.6.12 RegExp.prototype [ %Symbol.search% ] ( string )

此方法在被调用时执行以下步骤:

  1. regexpthis 值。
  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. 如果 resultnull,则返回 -1𝔽
  10. 返回 ? Get(result, "index")。

此方法的 "name" 属性的值是 "[Symbol.search]"

Note

执行搜索时会忽略此 RegExp 对象的 "lastIndex""global" 属性。"lastIndex" 属性保持不变。

22.2.6.13 get RegExp.prototype.source

RegExp.prototype.source访问器属性,其 set 访问器函数是 undefined。其 get 访问器函数在被调用时执行以下步骤:

  1. regexpthis 值。
  2. 如果 regexp 不是 Object,则抛出 TypeError 异常。
  3. 如果 regexp 没有 [[OriginalSource]] 内部槽,则
    1. 如果 SameValue(regexp, %RegExp.prototype%) 是 true,则返回 "(?:)"
    2. 抛出 TypeError 异常。
  4. 断言:regexp 具有 [[OriginalFlags]] 内部槽。
  5. sourceregexp.[[OriginalSource]]
  6. flagsregexp.[[OriginalFlags]]
  7. 返回 EscapeRegExpPattern(source, flags)。

22.2.6.13.1 EscapeRegExpPattern ( pattern, flags )

The abstract operation EscapeRegExpPattern takes arguments pattern (a String) and flags (a String) and returns a String. It performs the following steps when called:

  1. 如果 flags 包含 "v",则
    1. patternSymbolPattern[+UnicodeMode, +UnicodeSetsMode]
  2. 否则,如果 flags 包含 "u",则
    1. patternSymbolPattern[+UnicodeMode, ~UnicodeSetsMode]
  3. 否则,
    1. patternSymbolPattern[~UnicodeMode, ~UnicodeSetsMode]
  4. escapedPattern 为一个 String,其形式为等价于 patternpatternSymbolpattern 被解释为 UTF-16 编码的 Unicode 码点(6.1.4),其中某些码点按下文描述进行转义。escapedPattern 可以与 pattern 不同,也可以不不同;然而,把 escapedPattern 作为 patternSymbol 求值所产生的 Abstract Closure 必须与构造对象的 [[RegExpMatcher]] 内部槽给出的 Abstract Closure 行为相同。使用相同的 patternflags 值多次调用此抽象操作,必须产生相同结果。
  5. 模式中出现的码点 / 或任何 LineTerminator 应根据需要在 escapedPattern 中被转义,以确保 "/"escapedPattern"/"flags字符串连接可以(在适当的词法上下文中)被解析为与构造的正则表达式行为相同的 RegularExpressionLiteral。例如,如果 pattern"/",则 escapedPattern 可以是 "\/""\u002F" 等,但不能是 "/",因为后跟 flags/// 会被解析为 SingleLineComment,而不是 RegularExpressionLiteral。如果 pattern 是空 String,则可通过令 escapedPattern"(?:)" 来满足本规范。
  6. 返回 escapedPattern
Note

尽管名称相似,RegExp.escape 和 EscapeRegExpPattern 并不执行相似的操作。前者转义字符串以便表示在模式内部,而此函数转义模式以便表示为字符串。

22.2.6.14 RegExp.prototype [ %Symbol.split% ] ( string, limit )

Note 1

此方法返回一个 Array,其中存储了将 string 转换为 String 后所得结果的各个子字符串。这些子字符串通过从左到右搜索 this 值正则表达式的匹配来确定;这些出现位置不是返回数组中任何 String 的一部分,而是用来分割该 String 值。

this 值可以是空正则表达式,或可以匹配空 String 的正则表达式。在这种情况下,该正则表达式不会匹配输入 String 开头或结尾处的空子字符串,也不会匹配上一个分隔符匹配末尾处的空子字符串。(例如,如果该正则表达式匹配空 String,则该 String 会被拆分为单个码元元素;结果数组的长度等于该 String 的长度,并且每个子字符串包含一个码元。)只考虑该 String 给定索引处的第一个匹配,即使回溯可能在该索引产生非空子字符串匹配。(例如,/a*?/[Symbol.split]("ab") 求值为数组 ["a", "b"],而 /a*/[Symbol.split]("ab") 求值为数组 ["","b"]。)

如果 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. regexpthis 值。
  2. 如果 regexp 不是 Object,则抛出 TypeError 异常。
  3. string 设置为 ? ToString(string)。
  4. speciesCtor 为 ? SpeciesConstructor(regexp, %RegExp%)。
  5. flags 为 ? ToString(? Get(regexp, "flags"))。
  6. 如果 flags 包含 "u"flags 包含 "v",则令 unicodeMatchingtrue
  7. 否则,令 unicodeMatchingfalse
  8. 如果 flags 包含 "y",则令 newFlagsflags
  9. 否则,令 newFlagsflags"y"字符串连接
  10. splitter 为 ? Construct(speciesCtor, « regexp, newFlags »)。
  11. array 为 ! ArrayCreate(0)。
  12. lengthA 为 0。
  13. 如果 limitundefined,则令 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. sizestring 的长度。
  17. lastMatchEnd 为 0。
  18. searchIndexlastMatchEnd
  19. 重复,只要 searchIndex < size
    1. 执行 ? Set(splitter, "lastIndex", 𝔽(searchIndex), true)。
    2. matchResult 为 ? RegExpExec(splitter, string)。
    3. 如果 matchResultnull,则
      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. substringstringlastMatchEndsearchIndex子字符串
        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. 重复,只要 captureIndexnumberOfCaptures
          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. substringstringlastMatchEndsize子字符串
  21. 执行 ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(lengthA)), substring)。
  22. 返回 array

此方法的 "name" 属性的值是 "[Symbol.split]"

Note 2

此方法会忽略此 RegExp 对象的 "global""sticky" 属性的值。

22.2.6.15 get RegExp.prototype.sticky

RegExp.prototype.sticky访问器属性,其 set 访问器函数是 undefined。其 get 访问器函数在被调用时执行以下步骤:

  1. regexpthis 值。
  2. codeUnit 为码元 0x0079(LATIN SMALL LETTER Y)。
  3. 返回 ? RegExpHasFlag(regexp, codeUnit)。

22.2.6.16 RegExp.prototype.test ( string )

此方法在被调用时执行以下步骤:

  1. regexpthis 值。
  2. 如果 regexp 不是 Object,则抛出 TypeError 异常。
  3. string 设置为 ? ToString(string)。
  4. match 为 ? RegExpExec(regexp, string)。
  5. 如果 matchnull,则返回 false
  6. 返回 true

22.2.6.17 RegExp.prototype.toString ( )

  1. regexpthis 值。
  2. 如果 regexp 不是 Object,则抛出 TypeError 异常。
  3. pattern 为 ? ToString(? Get(regexp, "source"))。
  4. flags 为 ? ToString(? Get(regexp, "flags"))。
  5. result"/"pattern"/"flags字符串连接
  6. 返回 result
Note

返回的 String 具有 RegularExpressionLiteral 的形式,求值后会得到另一个与此对象具有相同行为的 RegExp 对象。

22.2.6.18 get RegExp.prototype.unicode

RegExp.prototype.unicode访问器属性,其 set 访问器函数是 undefined。其 get 访问器函数在被调用时执行以下步骤:

  1. regexpthis 值。
  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. regexpthis 值。
  2. codeUnit 为码元 0x0076(LATIN SMALL LETTER V)。
  3. 返回 ? RegExpHasFlag(regexp, codeUnit)。

22.2.7 RegExp 匹配的抽象操作

22.2.7.1 RegExpExec ( regexp, string )

The abstract operation RegExpExec takes arguments regexp (an Object) and string (a String) and returns either a normal completion containing either an Object or null, or a throw completion. It performs the following steps when called:

  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)。
Note

如果未找到可调用的 "exec" 属性,此算法会回退为尝试使用内置 RegExp 匹配算法。这为针对旧版本编写的代码提供了兼容行为;在那些版本中,大多数使用正则表达式的内置算法不会对 "exec" 执行动态属性查找。

22.2.7.2 RegExpBuiltinExec ( regexp, string )

The abstract operation RegExpBuiltinExec takes arguments regexp (an initialized RegExp instance) and string (a String) and returns either a normal completion containing either an Array exotic object or null, or a throw completion. It performs the following steps when called:

  1. lengthstring 的长度。
  2. lastIndex(? ToLength(! Get(regexp, "lastIndex")))。
  3. flagsregexp.[[OriginalFlags]]
  4. 如果 flags 包含 "g",则令 globaltrue;否则令 globalfalse
  5. 如果 flags 包含 "y",则令 stickytrue;否则令 stickyfalse
  6. 如果 flags 包含 "d",则令 hasIndicestrue;否则令 hasIndicesfalse
  7. 如果 globalfalsestickyfalse,则将 lastIndex 设置为 0。
  8. matcherregexp.[[RegExpMatcher]]
  9. 如果 flags 包含 "u"flags 包含 "v",则令 fullUnicodetrue;否则令 fullUnicodefalse
  10. matchSucceededfalse
  11. 如果 fullUnicodetrue,则令 inputStringToCodePoints(string);否则令 input 为一个 List,其元素是 string 的元素所对应的码元。
  12. 注:input 的每个元素都被视为一个字符。
  13. 重复,只要 matchSucceededfalse
    1. 如果 lastIndex > length,则
      1. 如果 globaltruestickytrue,则
        1. 执行 ? Set(regexp, "lastIndex", +0𝔽, true)。
      2. 返回 null
    2. inputIndexinput 中的索引,该索引对应从 string 的元素 lastIndex 获得的字符。
    3. resultmatcher(input, inputIndex)。
    4. 如果 resultfailure,则
      1. 如果 stickytrue,则
        1. 执行 ? Set(regexp, "lastIndex", +0𝔽, true)。
        2. 返回 null
      2. lastIndex 设置为 AdvanceStringIndex(string, lastIndex, fullUnicode)。
    5. 否则,
      1. 断言:resultMatchState
      2. matchSucceeded 设置为 true
  14. endIndexresult.[[EndIndex]]
  15. 如果 fullUnicodetrue,则将 endIndex 设置为 GetStringIndex(string, endIndex)。
  16. 如果 globaltruestickytrue,则
    1. 执行 ? Set(regexp, "lastIndex", 𝔽(endIndex), true)。
  17. capturingGroupsCountresult.[[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. matchMatch Record { [[StartIndex]]: lastIndex, [[EndIndex]]: endIndex }。
  25. indices 为新的空 List
  26. groupNames 为新的空 List
  27. match 追加到 indices
  28. matchedSubstringGetMatchString(string, match)。
  29. 执行 ! CreateDataPropertyOrThrow(array, "0", matchedSubstring)。
  30. 如果 regexp 包含任何 GroupName,则
    1. groupsOrdinaryObjectCreate(null)。
    2. hasGroupstrue
  31. 否则,
    1. groupsundefined
    2. hasGroupsfalse
  32. 执行 ! CreateDataPropertyOrThrow(array, "groups", groups)。
  33. matchedGroupNames 为新的空 List
  34. 对每个满足 1 ≤ icapturingGroupsCount 的整数 i,按升序执行:
    1. captureresult.[[Captures]] 的第 ith 个元素。
    2. 如果 captureundefined,则
      1. capturedValueundefined
      2. undefined 追加到 indices
    3. 否则,
      1. captureStartcapture.[[StartIndex]]
      2. captureEndcapture.[[EndIndex]]
      3. 如果 fullUnicodetrue,则
        1. captureStart 设置为 GetStringIndex(string, captureStart)。
        2. captureEnd 设置为 GetStringIndex(string, captureEnd)。
      4. captureRecordMatch Record { [[StartIndex]]: captureStart, [[EndIndex]]: captureEnd }。
      5. capturedValueGetMatchString(string, captureRecord)。
      6. captureRecord 追加到 indices
    4. 执行 ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(i)), capturedValue)。
    5. 如果 regexp 的第 ith 个 capture 使用 GroupName 定义,则
      1. groupName 为该 GroupNameCapturingGroupName
      2. 如果 matchedGroupNames 包含 groupName,则
        1. 断言:capturedValueundefined
        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. 如果 hasIndicestrue,则
    1. indicesArrayMakeMatchIndicesIndexPairArray(string, indices, groupNames, hasGroups)。
    2. 执行 ! CreateDataPropertyOrThrow(array, "indices", indicesArray)。
  36. 返回 array

22.2.7.3 AdvanceStringIndex ( string, index, unicode )

The abstract operation AdvanceStringIndex takes arguments string (a String), index (a non-negative integer), and unicode (a Boolean) and returns a non-negative integer. It performs the following steps when called:

  1. 断言:index ≤ 253 - 1。
  2. 如果 unicodefalse,则返回 index + 1。
  3. lengthstring 的长度。
  4. 如果 index + 1 ≥ length,则返回 index + 1。
  5. codePointCodePointAt(string, index)。
  6. 返回 index + codePoint.[[CodeUnitCount]]

22.2.7.4 GetStringIndex ( string, codePointIndex )

The abstract operation GetStringIndex takes arguments string (a String) and codePointIndex (a non-negative integer) and returns a non-negative integer. 它将 string 解释为 UTF-16 编码码点序列,如 6.1.4 中所述,并在对应于码点索引 codePointIndex 的码元索引存在时返回该码元索引。否则,返回 string 的长度。 It performs the following steps when called:

  1. 如果 string 为空 String,则返回 0。
  2. lengthstring 的长度。
  3. codeUnitCount 为 0。
  4. codePointCount 为 0。
  5. 重复,只要 codeUnitCount < length
    1. 如果 codePointCount = codePointIndex,则返回 codeUnitCount
    2. codePointCodePointAt(string, codeUnitCount)。
    3. codeUnitCount 设置为 codeUnitCount + codePoint.[[CodeUnitCount]]
    4. codePointCount 设置为 codePointCount + 1。
  6. 返回 length

22.2.7.5 Match Record

Match Record 是一种 Record 值,用于封装正则表达式匹配或捕获的开始和结束索引。

Match Record 具有 Table 68 中列出的字段。

Table 68: Match Record 字段
字段名 含义
[[StartIndex]] a non-negative integer 从字符串开头起计数,匹配开始处(包含)的码元数量。
[[EndIndex]] an integer[[StartIndex]] 从字符串开头起计数,匹配结束处(不包含)的码元数量。

22.2.7.6 GetMatchString ( string, match )

The abstract operation GetMatchString takes arguments string (a String) and match (a Match Record) and returns a String. It performs the following steps when called:

  1. 断言:match.[[StartIndex]]match.[[EndIndex]]string 的长度。
  2. 返回 stringmatch.[[StartIndex]]match.[[EndIndex]]子字符串

22.2.7.7 GetMatchIndexPair ( string, match )

The abstract operation GetMatchIndexPair takes arguments string (a String) and match (a Match Record) and returns an Array. It performs the following steps when called:

  1. 断言:match.[[StartIndex]]match.[[EndIndex]]string 的长度。
  2. 返回 CreateArrayFromList𝔽(match.[[StartIndex]]), 𝔽(match.[[EndIndex]]) »)。

22.2.7.8 MakeMatchIndicesIndexPairArray ( string, indices, groupNames, hasGroups )

The abstract operation MakeMatchIndicesIndexPairArray takes arguments string (a String), indices (a List of either Match Records or undefined), groupNames (a List of either Strings or undefined), and hasGroups (a Boolean) and returns an Array. It performs the following steps when called:

  1. nindices 中元素的数量。
  2. 断言:n < 232 - 1。
  3. 断言:groupNamesn - 1 个元素。
  4. 注:groupNames List 包含indices List 中从 indices[1] 开始对齐的元素。
  5. array 为 ! ArrayCreate(n)。
  6. 如果 hasGroupstrue,则
    1. groupsOrdinaryObjectCreate(null)。
  7. 否则,
    1. groupsundefined
  8. 执行 ! CreateDataPropertyOrThrow(array, "groups", groups)。
  9. 对每个满足 0 ≤ i < n 的整数 i,按升序执行:
    1. matchIndicesindices[i]。
    2. 如果 matchIndices 不是 undefined,则
      1. matchIndexPairGetMatchIndexPair(string, matchIndices)。
    3. 否则,
      1. matchIndexPairundefined
    4. 执行 ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(i)), matchIndexPair)。
    5. 如果 i > 0,则
      1. namegroupNames[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 对象的 PatternAbstract Closure 表示。

Note

在 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 Iterator 对象

RegExp String Iterator 是表示对某个特定 String 实例对象进行特定迭代,并与某个特定 RegExp 实例对象匹配的对象。RegExp String Iterator 对象没有具名构造器。相反,RegExp String Iterator 对象通过调用 RegExp 实例对象的某些方法创建。

22.2.9.1 CreateRegExpStringIterator ( regexp, string, global, fullUnicode )

The abstract operation CreateRegExpStringIterator takes arguments regexp (an Object), string (a String), global (a Boolean), and fullUnicode (a Boolean) and returns an Object. It performs the following steps when called:

  1. iteratorOrdinaryObjectCreate(%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. iteratorObjthis 值。
  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. regexpiteratorObj.[[IteratingRegExp]]
  6. stringiteratorObj.[[IteratedString]]
  7. globaliteratorObj.[[Global]]
  8. fullUnicodeiteratorObj.[[Unicode]]
  9. match 为 ? RegExpExec(regexp, string)。
  10. 如果 matchnull,则
    1. iteratorObj.[[Done]] 设置为 true
    2. 返回 CreateIteratorResultObject(undefined, true)。
  11. 如果 globalfalse,则
    1. iteratorObj.[[Done]] 设置为 true
    2. 返回 CreateIteratorResultObject(match, false)。
  12. matchString 为 ? ToString(? Get(match, "0"))。
  13. 如果 matchString 为空 String,则
    1. thisIndex(? ToLength(? Get(regexp, "lastIndex"))).
    2. nextIndexAdvanceStringIndex(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 实例最初以 Table 69 中列出的内部槽创建。

Table 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 值是 Array 奇异对象。

23.1.1.1 Array ( ...values )

此函数在被调用时执行以下步骤:

  1. 如果 NewTarget 是 undefined,则令 newTarget活动函数对象;否则令 newTarget 为 NewTarget。
  2. proto 为 ? GetPrototypeFromConstructor(newTarget, "%Array.prototype%")。
  3. numberOfArgsvalues 中元素的数量。
  4. 如果 numberOfArgs = 0,则返回 ! ArrayCreate(0, proto)。
  5. 如果 numberOfArgs = 1,则
    1. lengthvalues[0]。
    2. array 为 ! ArrayCreate(0, proto)。
    3. 如果 length 不是 Number,则
      1. 执行 ! CreateDataPropertyOrThrow(array, "0", length)。
      2. intLength1𝔽
    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. itemKvalues[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. ctorthis 值。
  2. 如果 mapperundefined,则
    1. mappingfalse
  3. 否则,
    1. 如果 IsCallable(mapper) 是 false,则抛出 TypeError 异常。
    2. mappingtrue
  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. errorThrowCompletion(一个新创建的 TypeError 对象)。
        2. 返回 ? IteratorClose(iteratorRecord, error)。
      2. propertyKey 为 ! ToString(𝔽(k))。
      3. next 为 ? IteratorStepValue(iteratorRecord)。
      4. 如果 nextdone,则
        1. 执行 ? Set(array, "length", 𝔽(k), true)。
        2. 返回 array
      5. 如果 mappingtrue,则
        1. mappedValueCompletion(Call(mapper, thisArg, « next, 𝔽(k) »))。
        2. IfAbruptCloseIterator(mappedValue, iteratorRecord)。
      6. 否则,
        1. mappedValuenext
      7. defineStatusCompletion(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. 如果 mappingtrue,则
      1. mappedValue 为 ? Call(mapper, thisArg, « kValue, 𝔽(k) »)。
    4. 否则,
      1. mappedValuekValue
    5. 执行 ? CreateDataPropertyOrThrow(array, propertyKey, mappedValue)。
    6. k 设置为 k + 1。
  13. 执行 ? Set(array, "length", 𝔽(length), true)。
  14. 返回 array
Note

此方法是有意设计为泛型的工厂方法;它不要求其 this 值是 Array 构造器。因此,它可以被转移到或被其他任何可用单个数值实参调用的构造器继承。

23.1.2.2 Array.fromAsync ( items [ , mapper [ , thisArg ] ] )

此 async 函数在被调用时执行以下步骤:

  1. ctorthis 值。
  2. mappingfalse
  3. 如果 mapper 不是 undefined,则
    1. 如果 IsCallable(mapper) 是 false,则抛出 TypeError 异常。
    2. mapping 设置为 true
  4. iteratorRecordundefined
  5. usingAsyncIterator 为 ? GetMethod(items, %Symbol.asyncIterator%)。
  6. 如果 usingAsyncIteratorundefined,则
    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. errorThrowCompletion(一个新创建的 TypeError 对象)。
        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. 如果 donetrue,则
        1. 执行 ? Set(array, "length", 𝔽(k), true)。
        2. 返回 array
      8. nextValue 为 ? IteratorValue(nextResult)。
      9. 如果 mappingtrue,则
        1. mappedValueCompletion(Call(mapper, thisArg, « nextValue, 𝔽(k) »))。
        2. IfAbruptCloseAsyncIterator(mappedValue, iteratorRecord)。
        3. mappedValue 设置为 Completion(Await(mappedValue))。
        4. IfAbruptCloseAsyncIterator(mappedValue, iteratorRecord)。
      10. 否则,
        1. mappedValuenextValue
      11. defineStatusCompletion(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. 如果 mappingtrue,则
        1. mappedValue 为 ? Call(mapper, thisArg, « kValue, 𝔽(k) »)。
        2. mappedValue 设置为 ? Await(mappedValue)。
      5. 否则,
        1. mappedValuekValue
      6. 执行 ? CreateDataPropertyOrThrow(array, propertyKey, mappedValue)。
      7. k 设置为 k + 1。
    8. 执行 ? Set(array, "length", 𝔽(length), true)。
    9. 返回 array
Note

此方法是有意设计为泛型的工厂方法;它不要求其 this 值是 Array 构造器。因此,它可以被转移到或被其他任何可用单个数值实参调用的构造器继承。

23.1.2.3 Array.isArray ( arg )

此函数在被调用时执行以下步骤:

  1. 返回 ? IsArray(arg)。

23.1.2.4 Array.of ( ...items )

此方法在被调用时执行以下步骤:

  1. lengthitems 中元素的数量。
  2. lengthNumber𝔽(length)。
  3. ctorthis 值。
  4. 如果 IsConstructor(ctor) 是 true,则
    1. array 为 ? Construct(ctor, « lengthNumber »)。
  5. 否则,
    1. array 为 ? ArrayCreate(length)。
  6. k 为 0。
  7. 重复,只要 k < length
    1. kValueitems[k]。
    2. propertyKey 为 ! ToString(𝔽(k))。
    3. 执行 ? CreateDataPropertyOrThrow(array, propertyKey, kValue)。
    4. k 设置为 k + 1。
  8. 执行 ? Set(array, "length", lengthNumber, true)。
  9. 返回 array
Note

此方法是有意设计为泛型的工厂方法;它不要求其 this 值是 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 值。

此函数的 "name" 属性的值是 "get [Symbol.species]"

Note

Array 原型方法通常使用其 this 值的构造器来创建派生对象。不过,子类构造器可以通过重新定义其 %Symbol.species% 属性来覆盖这种默认行为。

23.1.3 Array 原型对象的属性

Array 原型对象

  • %Array.prototype%
  • 是 Array 奇异对象,并具有为这类对象指定的内部方法。
  • 具有一个 "length" 属性,其初始值为 +0𝔽,并且其特性为 { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }。
  • 具有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%
Note

Array 原型对象被指定为 Array 奇异对象,是为了确保与 ECMAScript 2015 规范之前创建的 ECMAScript 代码兼容。

23.1.3.1 Array.prototype.at ( index )

  1. obj 为 ? ToObject(this value)。
  2. length 为 ? LengthOfArrayLike(obj)。
  3. relativeIndex 为 ? ToIntegerOrInfinity(index)。
  4. 如果 relativeIndex ≥ 0,则
    1. krelativeIndex
  5. 否则,
    1. klength + relativeIndex
  6. 如果 k < 0 或 klength,则返回 undefined
  7. 返回 ? 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. 如果 spreadabletrue,则
      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. 如果 existstrue,则
          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𝔽

Note 1

步骤 6 中显式设置 "length" 属性,是为了确保当 items 的最后一个非空元素带有尾随空洞,或 array 不是内置 Array 时,长度仍然正确。

Note 2

此方法有意设计为泛型的;它不要求其 this 值是 Array。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.2.1 IsConcatSpreadable ( obj )

The abstract operation IsConcatSpreadable takes argument obj (an ECMAScript language value) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

  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 ] )

Note 1

end 实参是可选的。如果未提供,则使用 this 值的长度。

Note 2

如果 target 为负,则将其视为 length + target,其中 length 是数组的长度。如果 start 为负,则将其视为 length + start。如果 end 为负,则将其视为 length + end

此方法在被调用时执行以下步骤:

  1. obj 为 ? ToObject(this value)。
  2. length 为 ? LengthOfArrayLike(obj)。
  3. relativeTarget 为 ? ToIntegerOrInfinity(target)。
  4. 如果 relativeTarget = -∞,则令 to 为 0。
  5. 否则,如果 relativeTarget < 0,则令 tomax(length + relativeTarget, 0)。
  6. 否则,令 tomin(relativeTarget, length)。
  7. relativeStart 为 ? ToIntegerOrInfinity(start)。
  8. 如果 relativeStart = -∞,则令 from 为 0。
  9. 否则,如果 relativeStart < 0,则令 frommax(length + relativeStart, 0)。
  10. 否则,令 frommin(relativeStart, length)。
  11. 如果 endundefined,则令 relativeEndlength;否则令 relativeEnd 为 ? ToIntegerOrInfinity(end)。
  12. 如果 relativeEnd = -∞,则令 final 为 0。
  13. 否则,如果 relativeEnd < 0,则令 finalmax(length + relativeEnd, 0)。
  14. 否则,令 finalmin(relativeEnd, length)。
  15. countmin(final - from, length - to)。
  16. 如果 from < toto < from + count,则
    1. direction 为 -1。
    2. from 设置为 from + count - 1。
    3. to 设置为 to + count - 1。
  17. 否则,
    1. direction 为 1。
  18. 重复,只要 count > 0,
    1. fromKey 为 ! ToString(𝔽(from))。
    2. toKey 为 ! ToString(𝔽(to))。
    3. fromPresent 为 ? HasProperty(obj, fromKey)。
    4. 如果 fromPresenttrue,则
      1. fromValue 为 ? Get(obj, fromKey)。
      2. 执行 ? Set(obj, toKey, fromValue, true)。
    5. 否则,
      1. 断言:fromPresentfalse
      2. 执行 ? DeletePropertyOrThrow(obj, toKey)。
    6. from 设置为 from + direction
    7. to 设置为 to + direction
    8. count 设置为 count - 1。
  19. 返回 obj
Note 3

此方法有意设计为泛型的;它不要求其 this 值是 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 ] )

Note 1

callback 应当是一个接受三个实参并返回可强制转换为 Boolean 值的值的函数。every 会按升序为数组中每个存在的元素调用一次 callback,直到找到一个 callback 返回 false 的元素。如果找到这样的元素,every 立即返回 false。否则,every 返回 truecallback 只会对数组中实际存在的元素调用;不会对数组中缺失的元素调用。

如果提供了 thisArg 参数,则它会被用作每次调用 callback 时的 this 值。如果未提供,则改用 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. 如果 kPresenttrue,则
      1. kValue 为 ? Get(obj, propertyKey)。
      2. testResultToBoolean(? Call(callback, thisArg, « kValue, 𝔽(k), obj »))。
      3. 如果 testResultfalse,则返回 false
    4. k 设置为 k + 1。
  6. 返回 true
Note 2

此方法有意设计为泛型的;它不要求其 this 值是 Array。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.7 Array.prototype.fill ( value [ , start [ , end ] ] )

Note 1

start 实参是可选的。如果未提供,则使用 +0𝔽

end 实参是可选的。如果未提供,则使用 this 值的长度。

Note 2

如果 start 为负,则将其视为 length + start,其中 length 是数组的长度。如果 end 为负,则将其视为 length + end

此方法在被调用时执行以下步骤:

  1. obj 为 ? ToObject(this value)。
  2. length 为 ? LengthOfArrayLike(obj)。
  3. relativeStart 为 ? ToIntegerOrInfinity(start)。
  4. 如果 relativeStart = -∞,则令 k 为 0。
  5. 否则,如果 relativeStart < 0,则令 kmax(length + relativeStart, 0)。
  6. 否则,令 kmin(relativeStart, length)。
  7. 如果 endundefined,则令 relativeEndlength;否则令 relativeEnd 为 ? ToIntegerOrInfinity(end)。
  8. 如果 relativeEnd = -∞,则令 final 为 0。
  9. 否则,如果 relativeEnd < 0,则令 finalmax(length + relativeEnd, 0)。
  10. 否则,令 finalmin(relativeEnd, length)。
  11. 重复,只要 k < final
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. 执行 ? Set(obj, propertyKey, value, true)。
    3. k 设置为 k + 1。
  12. 返回 obj
Note 3

此方法有意设计为泛型的;它不要求其 this 值是 Array。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.8 Array.prototype.filter ( callback [ , thisArg ] )

Note 1

callback 应当是一个接受三个实参并返回可强制转换为 Boolean 值的值的函数。filter 会按升序为数组中每个元素调用一次 callback,并构造一个包含所有 callback 返回 true 的值的新数组。callback 只会对数组中实际存在的元素调用;不会对数组中缺失的元素调用。

如果提供了 thisArg 参数,则它会被用作每次调用 callback 时的 this 值。如果未提供,则改用 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. 如果 kPresenttrue,则
      1. kValue 为 ? Get(obj, propertyKey)。
      2. selectedToBoolean(? Call(callback, thisArg, « kValue, 𝔽(k), obj »))。
      3. 如果 selectedtrue,则
        1. 执行 ? CreateDataPropertyOrThrow(array, ! ToString(𝔽(to)), kValue)。
        2. to 设置为 to + 1。
    4. k 设置为 k + 1。
  8. 返回 array
Note 2

此方法有意设计为泛型的;它不要求其 this 值是 Array。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.9 Array.prototype.find ( predicate [ , thisArg ] )

Note 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]]
Note 2

此方法有意设计为泛型的;它不要求其 this 值是 Array。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.10 Array.prototype.findIndex ( predicate [ , thisArg ] )

Note 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]]
Note 2

此方法有意设计为泛型的;它不要求其 this 值是 Array。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.11 Array.prototype.findLast ( predicate [ , thisArg ] )

Note 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]]
Note 2

此方法有意设计为泛型的;它不要求其 this 值是 Array 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.12 Array.prototype.findLastIndex ( predicate [ , thisArg ] )

Note 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]]
Note 2

此方法有意设计为泛型的;它不要求其 this 值是 Array 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.12.1 FindViaPredicate ( obj, length, direction, predicate, thisArg )

The abstract operation FindViaPredicate takes arguments obj (an Object), length (a non-negative integer), direction (ascending or descending), predicate (an ECMAScript language value), and thisArg (an ECMAScript language value) and returns either a normal completion containing a Record with fields [[Index]] (an integral Number) and [[Value]] (an ECMAScript language value) or a throw completion.

obj 应当是类数组对象TypedArray。此操作会按升序索引顺序或降序索引顺序(由 direction 指示)为 obj 的每个元素调用一次 predicate,直到找到一个 predicate 返回会被强制转换为 true 的值的元素。此时,此操作返回一个 Record,其中给出找到元素的索引和值。如果未找到这样的元素,此操作返回一个 Record,其索引指定为 -1𝔽,值指定为 undefined

predicate 应当是一个函数。为数组的某个元素调用时,会传入三个实参:元素的值、元素的索引,以及正在遍历的对象。其返回值会被强制转换为 Boolean 值。

thisArg 会被用作每次调用 predicate 时的 this 值。

此操作不会直接改变调用它的对象,但该对象可能会被对 predicate 的调用改变。

处理的元素范围会在第一次调用 predicate 之前、即遍历开始前确定。在此之后追加到数组中的元素不会被 predicate 访问。如果数组中已有元素被改变,传给 predicate 的值将是此操作访问它们时的值。在遍历开始之后且被访问之前被删除的元素仍会被访问,并且要么从原型查找,要么为 undefined

It performs the following steps when called:

  1. 如果 IsCallable(predicate) 是 false,则抛出 TypeError 异常。
  2. 如果 directionascending,则
    1. indices 为从 0(包含)到 length(不包含区间内的整数 List,按升序排列。
  3. 否则,
    1. indices 为从 0(包含)到 length(不包含区间内的整数 List,按降序排列。
  4. indices 的每个整数 k,执行:
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. 注:如果 objTypedArray,则以下 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 ] ] )

The abstract operation FlattenIntoArray takes arguments target (an Object), source (an Object), sourceLength (a non-negative integer), start (a non-negative integer), and depth (a non-negative integer or +∞) and optional arguments mapperFunc (a function object) and thisArg (an ECMAScript language value) and returns either a normal completion containing a non-negative integer or a throw completion. It performs the following steps when called:

  1. 断言:如果 mapperFunc 存在,则 IsCallable(mapperFunc) 是 truethisArg 存在,且 depth 是 1。
  2. targetIndexstart
  3. sourceIndex+0𝔽
  4. 重复,只要 (sourceIndex) < sourceLength
    1. propertyKey 为 ! ToString(sourceIndex)。
    2. exists 为 ? HasProperty(source, propertyKey)。
    3. 如果 existstrue,则
      1. element 为 ? Get(source, propertyKey)。
      2. 如果 mapperFunc 存在,则
        1. element 设置为 ? Call(mapperFunc, thisArg, « element, sourceIndex, source »)。
      3. shouldFlattenfalse
      4. 如果 depth > 0,则
        1. shouldFlatten 设置为 ? IsArray(element)。
      5. 如果 shouldFlattentrue,则
        1. 如果 depth = +∞,则令 newDepth 为 +∞。
        2. 否则,令 newDepthdepth - 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 ] )

Note 1

callback 应当是一个接受三个实参的函数。forEach 会按升序为数组中每个存在的元素调用一次 callbackcallback 只会对数组中实际存在的元素调用;不会对数组中缺失的元素调用。

如果提供了 thisArg 参数,则它会被用作每次调用 callback 时的 this 值。如果未提供,则改用 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. 如果 kPresenttrue,则
      1. kValue 为 ? Get(obj, propertyKey)。
      2. 执行 ? Call(callback, thisArg, « kValue, 𝔽(k), obj »)。
    4. k 设置为 k + 1。
  6. 返回 undefined
Note 2

此方法有意设计为泛型的;它不要求其 this 值是 Array。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.16 Array.prototype.includes ( searchElement [ , fromIndex ] )

Note 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. startIndex 为 ? ToIntegerOrInfinity(fromIndex)。
  5. 断言:如果 fromIndexundefined,则 startIndex 是 0。
  6. 如果 startIndex = +∞,则返回 false
  7. 如果 startIndex = -∞,则将 startIndex 设置为 0。
  8. 如果 startIndex ≥ 0,则
    1. kstartIndex
  9. 否则,
    1. klength + startIndex
    2. 如果 k < 0,则将 k 设置为 0。
  10. 重复,只要 k < length
    1. elementK 为 ? Get(obj, ! ToString(𝔽(k)))。
    2. 如果 SameValueZero(searchElement, elementK) 是 true,则返回 true
    3. k 设置为 k + 1。
  11. 返回 false
Note 2

此方法有意设计为泛型的;它不要求其 this 值是 Array。因此,它可以被转移到其他种类的对象上作为方法使用。

Note 3

此方法有意在两个方面不同于类似的 indexOf 方法。首先,它使用 SameValueZero 算法而非 IsStrictlyEqual,从而允许检测 NaN 数组元素。其次,它不会跳过缺失的数组元素,而是将它们视为 undefined

23.1.3.17 Array.prototype.indexOf ( searchElement [ , fromIndex ] )

此方法使用 IsStrictlyEqual 算法按升序把 searchElement 与数组的各元素比较;如果在一个或多个索引处找到,则返回这样的最小索引;否则返回 -1𝔽

Note 1

可选第二实参 fromIndex 默认为 +0𝔽(即搜索整个数组)。如果它大于或等于数组长度,则返回 -1𝔽,即不会搜索数组。如果它小于 -0𝔽,则将其用于计算从数组末尾起的偏移。如果计算得到的索引小于或等于 +0𝔽,则会搜索整个数组。

此方法在被调用时执行以下步骤:

  1. obj 为 ? ToObject(this value)。
  2. length 为 ? LengthOfArrayLike(obj)。
  3. 如果 length = 0,则返回 -1𝔽
  4. startIndex 为 ? ToIntegerOrInfinity(fromIndex)。
  5. 断言:如果 fromIndexundefined,则 startIndex 是 0。
  6. 如果 startIndex = +∞,则返回 -1𝔽
  7. 如果 startIndex = -∞,则将 startIndex 设置为 0。
  8. 如果 startIndex ≥ 0,则
    1. kstartIndex
  9. 否则,
    1. klength + startIndex
    2. 如果 k < 0,则将 k 设置为 0。
  10. 重复,只要 k < length
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. kPresent 为 ? HasProperty(obj, propertyKey)。
    3. 如果 kPresenttrue,则
      1. elementK 为 ? Get(obj, propertyKey)。
      2. 如果 IsStrictlyEqual(searchElement, elementK) 是 true,则返回 𝔽(k)。
    4. k 设置为 k + 1。
  11. 返回 -1𝔽
Note 2

此方法有意设计为泛型的;它不要求其 this 值是 Array。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.18 Array.prototype.join ( separator )

此方法将数组的元素转换为 String,然后将这些 String 连接起来,并由 separator 的出现分隔。如果未提供 separator,则使用单个逗号作为 separator。

它在被调用时执行以下步骤:

  1. obj 为 ? ToObject(this value)。
  2. length 为 ? LengthOfArrayLike(obj)。
  3. 如果 separatorundefined,则令 sep","
  4. 否则,令 sep 为 ? ToString(separator)。
  5. result 为空 String。
  6. k 为 0。
  7. 重复,只要 k < length
    1. 如果 k > 0,则将 result 设置为 resultsep字符串连接
    2. element 为 ? Get(obj, ! ToString(𝔽(k)))。
    3. 如果 element 既不是 undefined 也不是 null,则
      1. elementString 为 ? ToString(element)。
      2. result 设置为 resultelementString字符串连接
    4. k 设置为 k + 1。
  8. 返回 result
Note

此方法有意设计为泛型的;它不要求其 this 值是 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 ] )

Note 1

此方法使用 IsStrictlyEqual 算法按降序把 searchElement 与数组的各元素比较;如果在一个或多个索引处找到,则返回这样的最大索引;否则返回 -1𝔽

可选第二实参 fromIndex 默认为数组长度减一(即搜索整个数组)。如果它大于或等于数组长度,则会搜索整个数组。如果它小于 -0𝔽,则将其用于计算从数组末尾起的偏移。如果计算得到的索引小于 -0𝔽,则返回 -1𝔽

此方法在被调用时执行以下步骤:

  1. obj 为 ? ToObject(this value)。
  2. length 为 ? LengthOfArrayLike(obj)。
  3. 如果 length = 0,则返回 -1𝔽
  4. 如果 fromIndex 存在,则令 startIndex 为 ? ToIntegerOrInfinity(fromIndex);否则令 startIndexlength - 1。
  5. 如果 startIndex = -∞,则返回 -1𝔽
  6. 如果 startIndex ≥ 0,则
    1. kmin(startIndex, length - 1)。
  7. 否则,
    1. klength + startIndex
  8. 重复,只要 k ≥ 0,
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. kPresent 为 ? HasProperty(obj, propertyKey)。
    3. 如果 kPresenttrue,则
      1. elementK 为 ? Get(obj, propertyKey)。
      2. 如果 IsStrictlyEqual(searchElement, elementK) 是 true,则返回 𝔽(k)。
    4. k 设置为 k - 1。
  9. 返回 -1𝔽
Note 2

此方法有意设计为泛型的;它不要求其 this 值是 Array。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.21 Array.prototype.map ( callback [ , thisArg ] )

Note 1

callback 应当是一个接受三个实参的函数。map 会按升序为数组中每个元素调用一次 callback,并根据结果构造一个新的 Array。callback 只会对数组中实际存在的元素调用;不会对数组中缺失的元素调用。

如果提供了 thisArg 参数,则它会被用作每次调用 callback 时的 this 值。如果未提供,则改用 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. 如果 kPresenttrue,则
      1. kValue 为 ? Get(obj, propertyKey)。
      2. mappedValue 为 ? Call(callback, thisArg, « kValue, 𝔽(k), obj »)。
      3. 执行 ? CreateDataPropertyOrThrow(array, propertyKey, mappedValue)。
    4. k 设置为 k + 1。
  7. 返回 array
Note 2

此方法有意设计为泛型的;它不要求其 this 值是 Array。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.22 Array.prototype.pop ( )

Note 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
Note 2

此方法有意设计为泛型的;它不要求其 this 值是 Array。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.23 Array.prototype.push ( ...items )

Note 1

此方法按实参出现的顺序将它们追加到数组末尾。它返回数组的新长度。

此方法在被调用时执行以下步骤:

  1. obj 为 ? ToObject(this value)。
  2. length 为 ? LengthOfArrayLike(obj)。
  3. argCountitems 中元素的数量。
  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𝔽

Note 2

此方法有意设计为泛型的;它不要求其 this 值是 Array。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.24 Array.prototype.reduce ( callback [ , initialValue ] )

Note 1

callback 应当是一个接受四个实参的函数。reduce 会按升序为数组中每个存在的元素调用一次 callback,除非提供了 initialValue,否则会跳过第一个元素。

callback 会以四个实参调用:previousValue(前一次调用 callback 所得的值)、currentValue(当前元素的值)、currentIndex,以及正在遍历的对象。首次调用 callback 时,previousValuecurrentValue 可以是两组值之一。如果调用 reduce 时提供了 initialValue,则 previousValue 将是 initialValuecurrentValue 将是数组中的第一个值。如果未提供 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. accumulatorundefined
  7. 如果 initialValue 存在,则
    1. accumulator 设置为 initialValue
  8. 否则,
    1. kPresentfalse
    2. 重复,只要 kPresentfalsek < length
      1. propertyKey 为 ! ToString(𝔽(k))。
      2. kPresent 设置为 ? HasProperty(obj, propertyKey)。
      3. 如果 kPresenttrue,则
        1. accumulator 设置为 ? Get(obj, propertyKey)。
      4. k 设置为 k + 1。
    3. 如果 kPresentfalse,则抛出 TypeError 异常。
  9. 重复,只要 k < length
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. kPresent 为 ? HasProperty(obj, propertyKey)。
    3. 如果 kPresenttrue,则
      1. kValue 为 ? Get(obj, propertyKey)。
      2. accumulator 设置为 ? Call(callback, undefined, « accumulator, kValue, 𝔽(k), obj »)。
    4. k 设置为 k + 1。
  10. 返回 accumulator
Note 2

此方法有意设计为泛型的;它不要求其 this 值是 Array。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.25 Array.prototype.reduceRight ( callback [ , initialValue ] )

Note 1

callback 应当是一个接受四个实参的函数。reduceRight 会按降序为数组中每个存在的元素调用一次 callback,除非提供了 initialValue,否则会跳过第一次调用。

callback 会以四个实参调用:previousValue(前一次调用 callback 所得的值)、currentValue(当前元素的值)、currentIndex,以及正在遍历的对象。首次调用该函数时,previousValuecurrentValue 可以是两组值之一。如果调用 reduceRight 时提供了 initialValue,则 previousValue 将是 initialValuecurrentValue 将是数组中的最后一个值。如果未提供 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. klength - 1。
  6. accumulatorundefined
  7. 如果 initialValue 存在,则
    1. accumulator 设置为 initialValue
  8. 否则,
    1. kPresentfalse
    2. 重复,只要 kPresentfalsek ≥ 0,
      1. propertyKey 为 ! ToString(𝔽(k))。
      2. kPresent 设置为 ? HasProperty(obj, propertyKey)。
      3. 如果 kPresenttrue,则
        1. accumulator 设置为 ? Get(obj, propertyKey)。
      4. k 设置为 k - 1。
    3. 如果 kPresentfalse,则抛出 TypeError 异常。
  9. 重复,只要 k ≥ 0,
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. kPresent 为 ? HasProperty(obj, propertyKey)。
    3. 如果 kPresenttrue,则
      1. kValue 为 ? Get(obj, propertyKey)。
      2. accumulator 设置为 ? Call(callback, undefined, « accumulator, kValue, 𝔽(k), obj »)。
    4. k 设置为 k - 1。
  10. 返回 accumulator
Note 2

此方法有意设计为泛型的;它不要求其 this 值是 Array。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.26 Array.prototype.reverse ( )

Note 1

此方法重新排列数组元素,以反转它们的顺序。它返回反转后的数组。

此方法在被调用时执行以下步骤:

  1. obj 为 ? ToObject(this value)。
  2. length 为 ? LengthOfArrayLike(obj)。
  3. middlefloor(length / 2)。
  4. lower 为 0。
  5. 重复,只要 lowermiddle
    1. upperlength - lower - 1。
    2. upperP 为 ! ToString(𝔽(upper))。
    3. lowerP 为 ! ToString(𝔽(lower))。
    4. lowerExists 为 ? HasProperty(obj, lowerP)。
    5. 如果 lowerExiststrue,则
      1. lowerValue 为 ? Get(obj, lowerP)。
    6. upperExists 为 ? HasProperty(obj, upperP)。
    7. 如果 upperExiststrue,则
      1. upperValue 为 ? Get(obj, upperP)。
    8. 如果 lowerExiststrueupperExiststrue,则
      1. 执行 ? Set(obj, lowerP, upperValue, true)。
      2. 执行 ? Set(obj, upperP, lowerValue, true)。
    9. 否则,如果 lowerExistsfalseupperExiststrue,则
      1. 执行 ? Set(obj, lowerP, upperValue, true)。
      2. 执行 ? DeletePropertyOrThrow(obj, upperP)。
    10. 否则,如果 lowerExiststrueupperExistsfalse,则
      1. 执行 ? DeletePropertyOrThrow(obj, lowerP)。
      2. 执行 ? Set(obj, upperP, lowerValue, true)。
    11. 否则,
      1. 断言:lowerExistsupperExists 都是 false
      2. 注:不需要任何操作。
    12. lower 设置为 lower + 1。
  6. 返回 obj
Note 2

此方法有意设计为泛型的;它不要求其 this 值是 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. 如果 fromPresenttrue,则
      1. fromValue 为 ? Get(obj, from)。
      2. 执行 ? Set(obj, to, fromValue, true)。
    5. 否则,
      1. 断言:fromPresentfalse
      2. 执行 ? DeletePropertyOrThrow(obj, to)。
    6. k 设置为 k + 1。
  7. 执行 ? DeletePropertyOrThrow(obj, ! ToString(𝔽(length - 1)))。
  8. 执行 ? Set(obj, "length", 𝔽(length - 1), true)。
  9. 返回 first
Note

此方法有意设计为泛型的;它不要求其 this 值是 Array。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.28 Array.prototype.slice ( start, end )

此方法返回一个数组,其中包含该数组从元素 start 起,到元素 end(不包含)之前的元素(如果 endundefined,则直到数组末尾)。如果 start 为负,则将其视为 length + start,其中 length 是数组的长度。如果 end 为负,则将其视为 length + end,其中 length 是数组的长度。

它在被调用时执行以下步骤:

  1. obj 为 ? ToObject(this value)。
  2. length 为 ? LengthOfArrayLike(obj)。
  3. relativeStart 为 ? ToIntegerOrInfinity(start)。
  4. 如果 relativeStart = -∞,则令 k 为 0。
  5. 否则,如果 relativeStart < 0,则令 kmax(length + relativeStart, 0)。
  6. 否则,令 kmin(relativeStart, length)。
  7. 如果 endundefined,则令 relativeEndlength;否则令 relativeEnd 为 ? ToIntegerOrInfinity(end)。
  8. 如果 relativeEnd = -∞,则令 final 为 0。
  9. 否则,如果 relativeEnd < 0,则令 finalmax(length + relativeEnd, 0)。
  10. 否则,令 finalmin(relativeEnd, length)。
  11. countmax(final - k, 0)。
  12. array 为 ? ArraySpeciesCreate(obj, count)。
  13. resultIndex 为 0。
  14. 重复,只要 k < final
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. kPresent 为 ? HasProperty(obj, propertyKey)。
    3. 如果 kPresenttrue,则
      1. kValue 为 ? Get(obj, propertyKey)。
      2. 执行 ? CreateDataPropertyOrThrow(array, ! ToString(𝔽(resultIndex)), kValue)。
    4. k 设置为 k + 1。
    5. resultIndex 设置为 resultIndex + 1。
  15. 执行 ? Set(array, "length", 𝔽(resultIndex), true)。
  16. 返回 array
Note 1

步骤 15 中显式设置 "length" 属性,是为了确保即使 array 不是内置 Array,长度也正确。

Note 2

此方法有意设计为泛型的;它不要求其 this 值是 Array。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.29 Array.prototype.some ( callback [ , thisArg ] )

Note 1

callback 应当是一个接受三个实参并返回可强制转换为 Boolean 值的值的函数。some 会按升序为数组中每个存在的元素调用一次 callback,直到找到一个 callback 返回 true 的元素。如果找到这样的元素,some 立即返回 true。否则,some 返回 falsecallback 只会对数组中实际存在的元素调用;不会对数组中缺失的元素调用。

如果提供了 thisArg 参数,则它会被用作每次调用 callback 时的 this 值。如果未提供,则改用 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. 如果 kPresenttrue,则
      1. kValue 为 ? Get(obj, propertyKey)。
      2. testResultToBoolean(? Call(callback, thisArg, « kValue, 𝔽(k), obj »))。
      3. 如果 testResulttrue,则返回 true
    4. k 设置为 k + 1。
  6. 返回 false
Note 2

此方法有意设计为泛型的;它不要求其 this 值是 Array。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.30 Array.prototype.sort ( comparator )

此方法对该数组的元素排序。如果 comparator 不是 undefined,则它应当是一个接受两个实参 xy 的函数,并在 x < y 时返回负 Number,在 x > y 时返回正 Number,否则返回零。

它在被调用时执行以下步骤:

  1. 如果 comparator 不是 undefinedIsCallable(comparator) 是 false,则抛出 TypeError 异常。
  2. obj 为 ? ToObject(this value)。
  3. length 为 ? LengthOfArrayLike(obj)。
  4. sortCompare 为一个新的 Abstract Closure,其参数为 (x, y),捕获 comparator,并在被调用时执行以下步骤:
    1. 返回 ? CompareArrayElements(x, y, comparator)。
  5. sortedList 为 ? SortIndexedProperties(obj, length, sortCompare, skip-holes)。
  6. itemCountsortedList 中元素的数量。
  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
Note 1

由于不存在的属性值总是比较为大于 undefined 属性值,而 undefined 总是比较为大于任何其他值(见 CompareArrayElements),因此 undefined 属性值总是排序到结果末尾,随后是不存在的属性值。

Note 2

步骤 56 中由 ToString 抽象操作执行的方法调用,可能导致 sortCompare 不表现为一致比较器

Note 3

此方法有意设计为泛型的;它不要求其 this 值是 Array。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.30.1 SortIndexedProperties ( obj, length, sortCompare, holes )

The abstract operation SortIndexedProperties takes arguments obj (an Object), length (a non-negative integer), sortCompare (an Abstract Closure with two parameters), and holes (skip-holes or read-through-holes) and returns either a normal completion containing a List of ECMAScript language values or a throw completion. It performs the following steps when called:

  1. items 为新的空 List
  2. k 为 0。
  3. 重复,只要 k < length
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. 如果 holesskip-holes,则
      1. kRead 为 ? HasProperty(obj, propertyKey)。
    3. 否则,
      1. 断言:holesread-through-holes
      2. kReadtrue
    4. 如果 kReadtrue,则
      1. kValue 为 ? Get(obj, propertyKey)。
      2. kValue 追加到 items
    5. k 设置为 k + 1。
  4. 使用实现定义的sortCompare 的调用序列对 items 排序。如果任何这样的调用返回突然完成,则在执行任何进一步的 sortCompare 调用之前停止,并返回该 Completion Record
  5. 返回 items

排序顺序是上述算法的步骤 4 完成后 items 的顺序。如果 sortCompareitems 的元素不是一致比较器,则排序顺序实现定义的。当 SortIndexedProperties 由 Array.prototype.sortArray.prototype.toSorted 调用时,如果 comparatorundefined,并且对传给 sortCompare 的任一特定值应用 ToString 不都产生相同结果,则排序顺序也是实现定义的

除非排序顺序被指定为实现定义,否则它必须满足以下所有条件:

  • 必须存在某个小于 itemCount 的非负整数的数学排列 π,使得对每个小于 itemCount 的非负整数 j,元素 old[j]new[π(j)] 完全相同。
  • 然后,对所有小于 itemCount 的非负整数 jk,如果 (sortCompare(old[j], old[k])) < 0,则 π(j) < π(k)
  • 并且,对所有满足 j < k < itemCount 的非负整数 jk,如果 (sortCompare(old[j], old[k])) = 0,则 π(j) < π(k);即,排序是稳定的。

这里,记法 old[j] 用于指代步骤 4 执行之前的 items[j],记法 new[j] 用于指代步骤 4 执行之后的 items[j]

如果对集合 values 中所有值 abc(可以是同一个值)都满足以下要求,则 Abstract Closure 或函数 comparator 是集合 values一致比较器:记法 a <C b 表示 (comparator(a, b)) < 0a =C b 表示 (comparator(a, b)) = 0;而 a >C b 表示 (comparator(a, b)) > 0

  • 给定特定的一对值 ab 作为两个实参时,调用 comparator(a, b) 总是返回相同的值 v。此外,v 是 Number,且 v 不是 NaN。注意,这意味着对于给定的一对 aba <C ba =C ba >C b 中恰好有一个为 true。
  • 调用 comparator(a, b) 不会修改 objobj 原型链上的任何对象。
  • a =C a(自反性)
  • 如果 a =C b,则 b =C a(对称性)
  • 如果 a =C bb =C c,则 a =C c(=C 的传递性)
  • 如果 a <C bb <C c,则 a <C c(<C 的传递性)
  • 如果 a >C bb >C c,则 a >C c(>C 的传递性)
Note

上述条件是确保 comparator 将集合 values 划分为等价类,且这些等价类被全序排列的充要条件。

23.1.3.30.2 CompareArrayElements ( x, y, comparator )

The abstract operation CompareArrayElements takes arguments x (an ECMAScript language value), y (an ECMAScript language value), and comparator (a function object or undefined) and returns either a normal completion containing a Number or an abrupt completion. It performs the following steps when called:

  1. 如果 xundefinedyundefined,则返回 +0𝔽
  2. 如果 xundefined,则返回 1𝔽
  3. 如果 yundefined,则返回 -1𝔽
  4. 如果 comparator 不是 undefined,则
    1. result 为 ? ToNumber(? Call(comparator, undefined, « x, y »))。
    2. 如果 resultNaN,则返回 +0𝔽
    3. 返回 result
  5. xString 为 ? ToString(x)。
  6. yString 为 ? ToString(y)。
  7. xSmaller 为 ! IsLessThan(xString, yString, true)。
  8. 如果 xSmallertrue,则返回 -1𝔽
  9. ySmaller 为 ! IsLessThan(yString, xString, true)。
  10. 如果 ySmallertrue,则返回 1𝔽
  11. 返回 +0𝔽

23.1.3.31 Array.prototype.splice ( start, deleteCount, ...items )

Note 1

此方法删除从整数索引 start 开始的数组中 deleteCount 个元素,并用 items 的元素替换它们。它返回包含被删除元素(如果有)的 Array。

此方法在被调用时执行以下步骤:

  1. obj 为 ? ToObject(this value)。
  2. length 为 ? LengthOfArrayLike(obj)。
  3. relativeStart 为 ? ToIntegerOrInfinity(start)。
  4. 如果 relativeStart = -∞,则令 actualStart 为 0。
  5. 否则,如果 relativeStart < 0,则令 actualStartmax(length + relativeStart, 0)。
  6. 否则,令 actualStartmin(relativeStart, length)。
  7. itemCountitems 中元素的数量。
  8. 如果 start 不存在,则
    1. actualDeleteCount 为 0。
  9. 否则,如果 deleteCount 不存在,则
    1. actualDeleteCountlength - actualStart
  10. 否则,
    1. dc 为 ? ToIntegerOrInfinity(deleteCount)。
    2. actualDeleteCount 为将 dc 夹在 0 与 length - actualStart 之间的结果。
  11. 如果 length + itemCount - actualDeleteCount > 253 - 1,则抛出 TypeError 异常。
  12. deletedArray 为 ? ArraySpeciesCreate(obj, actualDeleteCount)。
  13. k 为 0。
  14. 重复,只要 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。
  15. 执行 ? Set(deletedArray, "length", 𝔽(actualDeleteCount), true)。
  16. 如果 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。
  17. 否则,如果 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。
  18. k 设置为 actualStart
  19. items 的每个元素 item,执行:
    1. 执行 ? Set(obj, ! ToString(𝔽(k)), item, true)。
    2. k 设置为 k + 1。
  20. 执行 ? Set(obj, "length", 𝔽(length - actualDeleteCount + itemCount), true)。
  21. 返回 deletedArray
Note 2

步骤 1520 中显式设置 "length" 属性,是为了确保即使这些对象不是内置 Array,长度也正确。

Note 3

此方法有意设计为泛型的;它不要求其 this 值是 Array。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.32 Array.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] )

包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按 ECMA-402 规范中的规定实现此方法。如果 ECMAScript 实现不包含 ECMA-402 API,则使用此方法的以下规范。

Note 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 设置为 resultseparator字符串连接
    2. element 为 ? Get(array, ! ToString(𝔽(k)))。
    3. 如果 element 既不是 undefined 也不是 null,则
      1. elementString 为 ? ToString(? Invoke(element, "toLocaleString")).
      2. result 设置为 resultelementString字符串连接
    4. k 设置为 k + 1。
  7. 返回 result
Note 2

此方法使用数组元素的 toLocaleString 方法将它们转换为 String,然后将这些 String 连接起来,并由实现定义的区域设置敏感分隔符 String 的出现分隔。此方法类似于 toString,不同之处在于它旨在产生与宿主环境当前区域设置的约定相对应的区域设置敏感结果。

Note 3

此方法有意设计为泛型的;它不要求其 this 值是 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 不是 undefinedIsCallable(comparator) 是 false,则抛出 TypeError 异常。
  2. obj 为 ? ToObject(this value)。
  3. length 为 ? LengthOfArrayLike(obj)。
  4. array 为 ? ArrayCreate(length)。
  5. sortCompare 为一个新的 Abstract Closure,其参数为 (x, y),捕获 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. relativeStart 为 ? ToIntegerOrInfinity(start)。
  4. 如果 relativeStart = -∞,则令 actualStart 为 0。
  5. 否则,如果 relativeStart < 0,则令 actualStartmax(length + relativeStart, 0)。
  6. 否则,令 actualStartmin(relativeStart, length)。
  7. insertCountitems 中元素的数量。
  8. 如果 start 不存在,则
    1. actualSkipCount 为 0。
  9. 否则,如果 skipCount 不存在,则
    1. actualSkipCountlength - actualStart
  10. 否则,
    1. sc 为 ? ToIntegerOrInfinity(skipCount)。
    2. actualSkipCount 为将 sc 夹在 0 与 length - actualStart 之间的结果。
  11. newLengthlength + insertCount - actualSkipCount
  12. 如果 newLength > 253 - 1,则抛出 TypeError 异常。
  13. newArray 为 ? ArrayCreate(newLength)。
  14. writeIndex 为 0。
  15. readIndexactualStart + actualSkipCount
  16. 重复,只要 writeIndex < actualStart
    1. propertyKey 为 ! ToString(𝔽(writeIndex))。
    2. iValue 为 ? Get(obj, propertyKey)。
    3. 执行 ! CreateDataPropertyOrThrow(newArray, propertyKey, iValue)。
    4. writeIndex 设置为 writeIndex + 1。
  17. items 的每个元素 item,执行:
    1. propertyKey 为 ! ToString(𝔽(writeIndex))。
    2. 执行 ! CreateDataPropertyOrThrow(newArray, propertyKey, item)。
    3. writeIndex 设置为 writeIndex + 1。
  18. 重复,只要 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。
  19. 返回 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)。
Note

此方法有意设计为泛型的;它不要求其 this 值是 Array。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.37 Array.prototype.unshift ( ...items )

此方法把实参前置到数组开头,使它们在数组中的顺序与它们在实参列表中出现的顺序相同。

它在被调用时执行以下步骤:

  1. obj 为 ? ToObject(this value)。
  2. length 为 ? LengthOfArrayLike(obj)。
  3. argCountitems 中元素的数量。
  4. 如果 argCount > 0,则
    1. 如果 length + argCount > 253 - 1,则抛出 TypeError 异常。
    2. klength
    3. 重复,只要 k > 0,
      1. from 为 ! ToString(𝔽(k - 1))。
      2. to 为 ! ToString(𝔽(k + argCount - 1))。
      3. fromPresent 为 ? HasProperty(obj, from)。
      4. 如果 fromPresenttrue,则
        1. fromValue 为 ? Get(obj, from)。
        2. 执行 ? Set(obj, to, fromValue, true)。
      5. 否则,
        1. 断言:fromPresentfalse
        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𝔽

Note

此方法有意设计为泛型的;它不要求其 this 值是 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. relativeIndex 为 ? ToIntegerOrInfinity(index)。
  4. 如果 relativeIndex ≥ 0,则令 actualIndexrelativeIndex
  5. 否则,令 actualIndexlength + relativeIndex
  6. 如果 actualIndexlengthactualIndex < 0,则抛出 RangeError 异常。
  7. array 为 ? ArrayCreate(length)。
  8. k 为 0。
  9. 重复,只要 k < length
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. 如果 k = actualIndex,则令 fromValuevalue
    3. 否则,令 fromValue 为 ? Get(obj, propertyKey)。
    4. 执行 ! CreateDataPropertyOrThrow(array, propertyKey, fromValue)。
    5. k 设置为 k + 1。
  10. 返回 array

23.1.3.40 Array.prototype [ %Symbol.iterator% ] ( )

%Symbol.iterator% 属性的初始值是 %Array.prototype.values%,定义见 23.1.3.38

23.1.3.41 Array.prototype [ %Symbol.unscopables% ]

%Symbol.unscopables% 数据属性的初始值是按以下步骤创建的对象:

  1. unscopableListOrdinaryObjectCreate(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 }。

Note

此对象的自身属性名是在 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 }。

Note

减小 "length" 属性的值具有删除自身数组元素的副作用,这些元素的数组索引位于旧长度值与新长度值之间。不过,不可配置属性不能被删除。尝试将 Array 的 "length" 属性设置为一个数值上小于或等于该数组现有不可配置数组索引属性的最大数值自身属性名的值,会导致 length 被设置为比该不可配置数值自身属性名大一的数值。见 10.4.2.1

23.1.5 Array Iterator 对象

Array Iterator 是表示对某个特定 Array 实例对象进行特定迭代的对象。Array Iterator 对象没有具名构造器。相反,Array Iterator 对象通过调用 Array 实例对象的某些方法创建。

23.1.5.1 CreateArrayIterator ( array, kind )

The abstract operation CreateArrayIterator takes arguments array (an Object) and kind (key+value, key, or value) and returns an Object. 它用于为返回此类迭代器的 Array 方法创建迭代器对象。 It performs the following steps when called:

  1. iteratorOrdinaryObjectCreate(%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. iteratorObjthis 值。
  2. 如果 iteratorObj 不是 Object,则抛出 TypeError 异常。
  3. 如果 iteratorObj 不具有 Array Iterator Instance(23.1.5.3)的所有内部槽,则抛出 TypeError 异常。
  4. arrayiteratorObj.[[IteratedArrayLike]]
  5. 如果 arrayundefined,则返回 CreateIteratorResultObject(undefined, true)。
  6. indexiteratorObj.[[ArrayLikeNextIndex]]
  7. kinditeratorObj.[[ArrayLikeIterationKind]]
  8. 如果 array 具有 [[TypedArrayName]] 内部槽,则
    1. taRecordMakeTypedArrayWithBufferWitnessRecord(array, seq-cst)。
    2. 如果 IsTypedArrayOutOfBounds(taRecord) 是 true,则抛出 TypeError 异常。
    3. lengthTypedArrayLength(taRecord)。
  9. 否则,
    1. length 为 ? LengthOfArrayLike(array)。
  10. 如果 indexlength,则
    1. iteratorObj.[[IteratedArrayLike]] 设置为 undefined
    2. 返回 CreateIteratorResultObject(undefined, true)。
  11. iteratorObj.[[ArrayLikeNextIndex]] 设置为 index + 1。
  12. indexNumber𝔽(index)。
  13. 如果 kindkey,则
    1. resultindexNumber
  14. 否则,
    1. elementKey 为 ! ToString(indexNumber)。
    2. elementValue 为 ? Get(array, elementKey)。
    3. 如果 kindvalue,则
      1. resultelementValue
    4. 否则,
      1. 断言:kindkey+value
      2. resultCreateArrayFromListindexNumber, 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 实例最初以 Table 70 中列出的内部槽创建。

Table 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 构造器,列于 Table 71 中。Table 71 中的每个构造器都有一个对应的不同原型对象。

Table 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. ctorthis 值。
  2. 如果 IsConstructor(ctor) 是 false,则抛出 TypeError 异常。
  3. 如果 mapperundefined,则
    1. mappingfalse
  4. 否则,
    1. 如果 IsCallable(mapper) 是 false,则抛出 TypeError 异常。
    2. mappingtrue
  5. usingIterator 为 ? GetMethod(source, %Symbol.iterator%)。
  6. 如果 usingIterator 不是 undefined,则
    1. values 为 ? IteratorToList(? GetIteratorFromMethod(source, usingIterator))。
    2. lengthvalues 中元素的数量。
    3. targetObj 为 ? TypedArrayCreateFromConstructor(ctor, « 𝔽(length) »)。
    4. k 为 0。
    5. 重复,只要 k < length
      1. propertyKey 为 ! ToString(𝔽(k))。
      2. kValuevalues 的第一个元素。
      3. values 中移除第一个元素。
      4. 如果 mappingtrue,则
        1. mappedValue 为 ? Call(mapper, thisArg, « kValue, 𝔽(k) »)。
      5. 否则,
        1. mappedValuekValue
      6. 执行 ? Set(targetObj, propertyKey, mappedValue, true)。
      7. k 设置为 k + 1。
    6. 断言:values 现在是空 List
    7. 返回 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. 如果 mappingtrue,则
      1. mappedValue 为 ? Call(mapper, thisArg, « kValue, 𝔽(k) »)。
    4. 否则,
      1. mappedValuekValue
    5. 执行 ? Set(targetObj, propertyKey, mappedValue, true)。
    6. k 设置为 k + 1。
  13. 返回 targetObj

23.2.2.2 %TypedArray%.of ( ...items )

此方法在被调用时执行以下步骤:

  1. lengthitems 中元素的数量。
  2. ctorthis 值。
  3. 如果 IsConstructor(ctor) 是 false,则抛出 TypeError 异常。
  4. newObj 为 ? TypedArrayCreateFromConstructor(ctor, « 𝔽(length) »)。
  5. k 为 0。
  6. 重复,只要 k < length
    1. kValueitems[k]。
    2. propertyKey 为 ! ToString(𝔽(k))。
    3. 执行 ? Set(newObj, propertyKey, kValue, true)。
    4. 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 值。

此函数的 "name" 属性的值是 "get [Symbol.species]"

Note

%TypedArray.prototype% 方法通常使用其 this 值的构造器来创建派生对象。不过,子类构造器可以通过重新定义其 %Symbol.species% 属性来覆盖这种默认行为。

23.2.3 %TypedArray% 原型对象的属性

%TypedArray% 原型对象

  • 具有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%
  • %TypedArray.prototype%
  • 普通对象
  • 没有 [[ViewedArrayBuffer]],也没有任何其他 TypedArray 实例对象专有的内部槽。

23.2.3.1 %TypedArray%.prototype.at ( index )

  1. objthis 值。
  2. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. lengthTypedArrayLength(taRecord)。
  4. relativeIndex 为 ? ToIntegerOrInfinity(index)。
  5. 如果 relativeIndex ≥ 0,则
    1. krelativeIndex
  6. 否则,
    1. klength + relativeIndex
  7. 如果 k < 0 或 klength,则返回 undefined
  8. 返回 ! Get(obj, ! ToString(𝔽(k)))。

23.2.3.2 get %TypedArray%.prototype.buffer

%TypedArray%.prototype.buffer访问器属性,其 set 访问器函数是 undefined。其 get 访问器函数在被调用时执行以下步骤:

  1. objthis 值。
  2. 执行 ? RequireInternalSlot(obj, [[TypedArrayName]])。
  3. 断言:obj 具有 [[ViewedArrayBuffer]] 内部槽。
  4. bufferobj.[[ViewedArrayBuffer]]
  5. 返回 buffer

23.2.3.3 get %TypedArray%.prototype.byteLength

%TypedArray%.prototype.byteLength访问器属性,其 set 访问器函数是 undefined。其 get 访问器函数在被调用时执行以下步骤:

  1. objthis 值。
  2. 执行 ? RequireInternalSlot(obj, [[TypedArrayName]])。
  3. 断言:obj 具有 [[ViewedArrayBuffer]] 内部槽。
  4. taRecordMakeTypedArrayWithBufferWitnessRecord(obj, seq-cst)。
  5. 如果 IsTypedArrayOutOfBounds(taRecord) 是 true,则返回 +0𝔽
  6. sizeTypedArrayByteLength(taRecord)。
  7. 返回 𝔽(size)。

23.2.3.4 get %TypedArray%.prototype.byteOffset

%TypedArray%.prototype.byteOffset访问器属性,其 set 访问器函数是 undefined。其 get 访问器函数在被调用时执行以下步骤:

  1. objthis 值。
  2. 执行 ? RequireInternalSlot(obj, [[TypedArrayName]])。
  3. 断言:obj 具有 [[ViewedArrayBuffer]] 内部槽。
  4. taRecordMakeTypedArrayWithBufferWitnessRecord(obj, seq-cst)。
  5. 如果 IsTypedArrayOutOfBounds(taRecord) 是 true,则返回 +0𝔽
  6. offsetobj.[[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. objthis 值。
  2. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. lengthTypedArrayLength(taRecord)。
  4. relativeTarget 为 ? ToIntegerOrInfinity(target)。
  5. 如果 relativeTarget = -∞,则令 targetIndex 为 0。
  6. 否则,如果 relativeTarget < 0,则令 targetIndexmax(length + relativeTarget, 0)。
  7. 否则,令 targetIndexmin(relativeTarget, length)。
  8. relativeStart 为 ? ToIntegerOrInfinity(start)。
  9. 如果 relativeStart = -∞,则令 startIndex 为 0。
  10. 否则,如果 relativeStart < 0,则令 startIndexmax(length + relativeStart, 0)。
  11. 否则,令 startIndexmin(relativeStart, length)。
  12. 如果 endundefined,则令 relativeEndlength;否则令 relativeEnd 为 ? ToIntegerOrInfinity(end)。
  13. 如果 relativeEnd = -∞,则令 endIndex 为 0。
  14. 否则,如果 relativeEnd < 0,则令 endIndexmax(length + relativeEnd, 0)。
  15. 否则,令 endIndexmin(relativeEnd, length)。
  16. countmin(endIndex - startIndex, length - targetIndex)。
  17. 如果 count > 0,则
    1. 注:复制必须以保留源数据的位级编码的方式执行。
    2. bufferobj.[[ViewedArrayBuffer]]
    3. taRecord 设置为 MakeTypedArrayWithBufferWitnessRecord(obj, seq-cst)。
    4. 如果 IsTypedArrayOutOfBounds(taRecord) 是 true,则抛出 TypeError 异常。
    5. length 设置为 TypedArrayLength(taRecord)。
    6. 注:上述步骤的副作用可能已经减小 obj 的大小;在这种情况下,复制应继续处理仍适用的最长前缀。
    7. count 设置为 min(count, length - startIndex, length - targetIndex)。
    8. elementSizeTypedArrayElementSize(obj)。
    9. byteOffsetobj.[[ByteOffset]]
    10. toByteIndex 为 (targetIndex × elementSize) + byteOffset
    11. fromByteIndex 为 (startIndex × elementSize) + byteOffset
    12. countBytescount × elementSize
    13. 如果 fromByteIndex < toByteIndextoByteIndex < fromByteIndex + countBytes,则
      1. direction 为 -1。
      2. fromByteIndex 设置为 fromByteIndex + countBytes - 1。
      3. toByteIndex 设置为 toByteIndex + countBytes - 1。
    14. 否则,
      1. direction 为 1。
    15. 重复,只要 countBytes > 0,
      1. valueGetValueFromBuffer(buffer, fromByteIndex, uint8, true, unordered)。
      2. 执行 SetValueInBuffer(buffer, toByteIndex, uint8, value, true, unordered)。
      3. fromByteIndex 设置为 fromByteIndex + direction
      4. toByteIndex 设置为 toByteIndex + direction
      5. countBytes 设置为 countBytes - 1。
  18. 返回 obj

23.2.3.7 %TypedArray%.prototype.entries ( )

此方法在被调用时执行以下步骤:

  1. objthis 值。
  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. objthis 值。
  2. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. lengthTypedArrayLength(taRecord)。
  4. 如果 IsCallable(callback) 是 false,则抛出 TypeError 异常。
  5. k 为 0。
  6. 重复,只要 k < length
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. kValue 为 ! Get(obj, propertyKey)。
    3. testResultToBoolean(? Call(callback, thisArg, « kValue, 𝔽(k), obj »))。
    4. 如果 testResultfalse,则返回 false
    5. k 设置为 k + 1。
  7. 返回 true

此方法不是泛型的。this 值必须是具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.9 %TypedArray%.prototype.fill ( value [ , start [ , end ] ] )

此方法的实参解释和使用方式与 23.1.3.7 中定义的 Array.prototype.fill 相同。

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. lengthTypedArrayLength(taRecord)。
  4. 如果 obj.[[ContentType]]bigint,则将 value 设置为 ? ToBigInt(value)。
  5. 否则,将 value 设置为 ? ToNumber(value)。
  6. relativeStart 为 ? ToIntegerOrInfinity(start)。
  7. 如果 relativeStart = -∞,则令 startIndex 为 0。
  8. 否则,如果 relativeStart < 0,则令 startIndexmax(length + relativeStart, 0)。
  9. 否则,令 startIndexmin(relativeStart, length)。
  10. 如果 endundefined,则令 relativeEndlength;否则令 relativeEnd 为 ? ToIntegerOrInfinity(end)。
  11. 如果 relativeEnd = -∞,则令 endIndex 为 0。
  12. 否则,如果 relativeEnd < 0,则令 endIndexmax(length + relativeEnd, 0)。
  13. 否则,令 endIndexmin(relativeEnd, length)。
  14. taRecord 设置为 MakeTypedArrayWithBufferWitnessRecord(obj, seq-cst)。
  15. 如果 IsTypedArrayOutOfBounds(taRecord) 是 true,则抛出 TypeError 异常。
  16. length 设置为 TypedArrayLength(taRecord)。
  17. endIndex 设置为 min(endIndex, length)。
  18. kstartIndex
  19. 重复,只要 k < endIndex
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. 执行 ! Set(obj, propertyKey, value, true)。
    3. k 设置为 k + 1。
  20. 返回 obj

23.2.3.10 %TypedArray%.prototype.filter ( callback [ , thisArg ] )

此方法的实参解释和使用方式与 23.1.3.8 中定义的 Array.prototype.filter 相同。

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. lengthTypedArrayLength(taRecord)。
  4. 如果 IsCallable(callback) 是 false,则抛出 TypeError 异常。
  5. kept 为新的空 List
  6. captured 为 0。
  7. k 为 0。
  8. 重复,只要 k < length
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. kValue 为 ! Get(obj, propertyKey)。
    3. selectedToBoolean(? Call(callback, thisArg, « kValue, 𝔽(k), obj »))。
    4. 如果 selectedtrue,则
      1. kValue 追加到 kept
      2. captured 设置为 captured + 1。
    5. k 设置为 k + 1。
  9. result 为 ? TypedArraySpeciesCreate(obj, « 𝔽(captured) »)。
  10. n 为 0。
  11. kept 的每个元素 element,执行:
    1. 执行 ! Set(result, ! ToString(𝔽(n)), element, true)。
    2. n 设置为 n + 1。
  12. 返回 result

此方法不是泛型的。this 值必须是具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.11 %TypedArray%.prototype.find ( predicate [ , thisArg ] )

此方法的实参解释和使用方式与 23.1.3.9 中定义的 Array.prototype.find 相同。

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. lengthTypedArrayLength(taRecord)。
  4. findRecord 为 ? FindViaPredicate(obj, length, ascending, predicate, thisArg)。
  5. 返回 findRecord.[[Value]]

此方法不是泛型的。this 值必须是具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.12 %TypedArray%.prototype.findIndex ( predicate [ , thisArg ] )

此方法的实参解释和使用方式与 23.1.3.10 中定义的 Array.prototype.findIndex 相同。

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. lengthTypedArrayLength(taRecord)。
  4. findRecord 为 ? FindViaPredicate(obj, length, ascending, predicate, thisArg)。
  5. 返回 findRecord.[[Index]]

此方法不是泛型的。this 值必须是具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.13 %TypedArray%.prototype.findLast ( predicate [ , thisArg ] )

此方法的实参解释和使用方式与 23.1.3.11 中定义的 Array.prototype.findLast 相同。

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. lengthTypedArrayLength(taRecord)。
  4. findRecord 为 ? FindViaPredicate(obj, length, descending, predicate, thisArg)。
  5. 返回 findRecord.[[Value]]

此方法不是泛型的。this 值必须是具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.14 %TypedArray%.prototype.findLastIndex ( predicate [ , thisArg ] )

此方法的实参解释和使用方式与 23.1.3.12 中定义的 Array.prototype.findLastIndex 相同。

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. lengthTypedArrayLength(taRecord)。
  4. findRecord 为 ? FindViaPredicate(obj, length, descending, predicate, thisArg)。
  5. 返回 findRecord.[[Index]]

此方法不是泛型的。this 值必须是具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.15 %TypedArray%.prototype.forEach ( callback [ , thisArg ] )

此方法的实参解释和使用方式与 23.1.3.15 中定义的 Array.prototype.forEach 相同。

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. lengthTypedArrayLength(taRecord)。
  4. 如果 IsCallable(callback) 是 false,则抛出 TypeError 异常。
  5. k 为 0。
  6. 重复,只要 k < length
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. kValue 为 ! Get(obj, propertyKey)。
    3. 执行 ? Call(callback, thisArg, « kValue, 𝔽(k), obj »)。
    4. k 设置为 k + 1。
  7. 返回 undefined

此方法不是泛型的。this 值必须是具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.16 %TypedArray%.prototype.includes ( searchElement [ , fromIndex ] )

此方法的实参解释和使用方式与 23.1.3.16 中定义的 Array.prototype.includes 相同。

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. lengthTypedArrayLength(taRecord)。
  4. 如果 length = 0,则返回 false
  5. n 为 ? ToIntegerOrInfinity(fromIndex)。
  6. 断言:如果 fromIndexundefined,则 n 是 0。
  7. 如果 n = +∞,则返回 false
  8. 如果 n = -∞,则将 n 设置为 0。
  9. 如果 n ≥ 0,则
    1. kn
  10. 否则,
    1. klength + n
    2. 如果 k < 0,则将 k 设置为 0。
  11. 重复,只要 k < length
    1. elementK 为 ! Get(obj, ! ToString(𝔽(k)))。
    2. 如果 SameValueZero(searchElement, elementK) 是 true,则返回 true
    3. k 设置为 k + 1。
  12. 返回 false

此方法不是泛型的。this 值必须是具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.17 %TypedArray%.prototype.indexOf ( searchElement [ , fromIndex ] )

此方法的实参解释和使用方式与 23.1.3.17 中定义的 Array.prototype.indexOf 相同。

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. lengthTypedArrayLength(taRecord)。
  4. 如果 length = 0,则返回 -1𝔽
  5. n 为 ? ToIntegerOrInfinity(fromIndex)。
  6. 断言:如果 fromIndexundefined,则 n 是 0。
  7. 如果 n = +∞,则返回 -1𝔽
  8. 如果 n = -∞,则将 n 设置为 0。
  9. 如果 n ≥ 0,则
    1. kn
  10. 否则,
    1. klength + n
    2. 如果 k < 0,则将 k 设置为 0。
  11. 重复,只要 k < length
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. kPresent 为 ! HasProperty(obj, propertyKey)。
    3. 如果 kPresenttrue,则
      1. elementK 为 ! Get(obj, propertyKey)。
      2. 如果 IsStrictlyEqual(searchElement, elementK) 是 true,则返回 𝔽(k)。
    4. k 设置为 k + 1。
  12. 返回 -1𝔽

此方法不是泛型的。this 值必须是具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.18 %TypedArray%.prototype.join ( separator )

此方法的实参解释和使用方式与 23.1.3.18 中定义的 Array.prototype.join 相同。

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. lengthTypedArrayLength(taRecord)。
  4. 如果 separatorundefined,则令 sep","
  5. 否则,令 sep 为 ? ToString(separator)。
  6. result 为空 String。
  7. k 为 0。
  8. 重复,只要 k < length
    1. 如果 k > 0,则将 result 设置为 resultsep字符串连接
    2. element 为 ! Get(obj, ! ToString(𝔽(k)))。
    3. 如果 element 不是 undefined,则
      1. elementString 为 ! ToString(element)。
      2. result 设置为 resultelementString字符串连接
    4. k 设置为 k + 1。
  9. 返回 result

此方法不是泛型的。this 值必须是具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.19 %TypedArray%.prototype.keys ( )

此方法在被调用时执行以下步骤:

  1. objthis 值。
  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. objthis 值。
  2. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. lengthTypedArrayLength(taRecord)。
  4. 如果 length = 0,则返回 -1𝔽
  5. 如果 fromIndex 存在,则令 n 为 ? ToIntegerOrInfinity(fromIndex);否则令 nlength - 1。
  6. 如果 n = -∞,则返回 -1𝔽
  7. 如果 n ≥ 0,则
    1. kmin(n, length - 1)。
  8. 否则,
    1. klength + n
  9. 重复,只要 k ≥ 0,
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. kPresent 为 ! HasProperty(obj, propertyKey)。
    3. 如果 kPresenttrue,则
      1. elementK 为 ! Get(obj, propertyKey)。
      2. 如果 IsStrictlyEqual(searchElement, elementK) 是 true,则返回 𝔽(k)。
    4. k 设置为 k - 1。
  10. 返回 -1𝔽

此方法不是泛型的。this 值必须是具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.21 get %TypedArray%.prototype.length

%TypedArray%.prototype.length访问器属性,其 set 访问器函数是 undefined。其 get 访问器函数在被调用时执行以下步骤:

  1. objthis 值。
  2. 执行 ? RequireInternalSlot(obj, [[TypedArrayName]])。
  3. 断言:obj 具有 [[ViewedArrayBuffer]][[ArrayLength]] 内部槽。
  4. taRecordMakeTypedArrayWithBufferWitnessRecord(obj, seq-cst)。
  5. 如果 IsTypedArrayOutOfBounds(taRecord) 是 true,则返回 +0𝔽
  6. lengthTypedArrayLength(taRecord)。
  7. 返回 𝔽(length)。

此函数不是泛型的。this 值必须是具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.22 %TypedArray%.prototype.map ( callback [ , thisArg ] )

此方法的实参解释和使用方式与 23.1.3.21 中定义的 Array.prototype.map 相同。

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. lengthTypedArrayLength(taRecord)。
  4. 如果 IsCallable(callback) 是 false,则抛出 TypeError 异常。
  5. result 为 ? TypedArraySpeciesCreate(obj, « 𝔽(length) »)。
  6. k 为 0。
  7. 重复,只要 k < length
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. kValue 为 ! Get(obj, propertyKey)。
    3. mappedValue 为 ? Call(callback, thisArg, « kValue, 𝔽(k), obj »)。
    4. 执行 ? Set(result, propertyKey, mappedValue, true)。
    5. k 设置为 k + 1。
  8. 返回 result

此方法不是泛型的。this 值必须是具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.23 %TypedArray%.prototype.reduce ( callback [ , initialValue ] )

此方法的实参解释和使用方式与 23.1.3.24 中定义的 Array.prototype.reduce 相同。

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. lengthTypedArrayLength(taRecord)。
  4. 如果 IsCallable(callback) 是 false,则抛出 TypeError 异常。
  5. 如果 length = 0 且 initialValue 不存在,则抛出 TypeError 异常。
  6. k 为 0。
  7. accumulatorundefined
  8. 如果 initialValue 存在,则
    1. accumulator 设置为 initialValue
  9. 否则,
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. accumulator 设置为 ! Get(obj, propertyKey)。
    3. k 设置为 k + 1。
  10. 重复,只要 k < length
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. kValue 为 ! Get(obj, propertyKey)。
    3. accumulator 设置为 ? Call(callback, undefined, « accumulator, kValue, 𝔽(k), obj »)。
    4. k 设置为 k + 1。
  11. 返回 accumulator

此方法不是泛型的。this 值必须是具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.24 %TypedArray%.prototype.reduceRight ( callback [ , initialValue ] )

此方法的实参解释和使用方式与 23.1.3.25 中定义的 Array.prototype.reduceRight 相同。

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. lengthTypedArrayLength(taRecord)。
  4. 如果 IsCallable(callback) 是 false,则抛出 TypeError 异常。
  5. 如果 length = 0 且 initialValue 不存在,则抛出 TypeError 异常。
  6. klength - 1。
  7. accumulatorundefined
  8. 如果 initialValue 存在,则
    1. accumulator 设置为 initialValue
  9. 否则,
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. accumulator 设置为 ! Get(obj, propertyKey)。
    3. k 设置为 k - 1。
  10. 重复,只要 k ≥ 0,
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. kValue 为 ! Get(obj, propertyKey)。
    3. accumulator 设置为 ? Call(callback, undefined, « accumulator, kValue, 𝔽(k), obj »)。
    4. k 设置为 k - 1。
  11. 返回 accumulator

此方法不是泛型的。this 值必须是具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.25 %TypedArray%.prototype.reverse ( )

此方法的实参解释和使用方式与 23.1.3.26 中定义的 Array.prototype.reverse 相同。

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. lengthTypedArrayLength(taRecord)。
  4. middlefloor(length / 2)。
  5. lower 为 0。
  6. 重复,只要 lowermiddle
    1. upperlength - lower - 1。
    2. upperP 为 ! ToString(𝔽(upper))。
    3. lowerP 为 ! ToString(𝔽(lower))。
    4. lowerValue 为 ! Get(obj, lowerP)。
    5. upperValue 为 ! Get(obj, upperP)。
    6. 执行 ! Set(obj, lowerP, upperValue, true)。
    7. 执行 ! Set(obj, upperP, lowerValue, true)。
    8. lower 设置为 lower + 1。
  7. 返回 obj

此方法不是泛型的。this 值必须是具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.26 %TypedArray%.prototype.set ( source [ , offset ] )

此方法会在此 TypedArray 中设置多个值,并从 source 读取这些值。细节会根据 source 的类型而不同。可选的 offset 值指示在此 TypedArray 中写入值的第一个元素索引。如果省略,则假定为 0。

它在被调用时执行以下步骤:

  1. targetthis 值。
  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 值必须是具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.26.1 SetTypedArrayFromArrayLike ( target, targetOffset, source )

The abstract operation SetTypedArrayFromArrayLike takes arguments target (a TypedArray), targetOffset (a non-negative integer or +∞), and source (an ECMAScript language value, but not a TypedArray) and returns either a normal completion containing unused or a throw completion. 它从 source 读取值,并从索引 targetOffset 开始在 target 中设置多个值。 It performs the following steps when called:

  1. targetRecordMakeTypedArrayWithBufferWitnessRecord(target, seq-cst)。
  2. 如果 IsTypedArrayOutOfBounds(targetRecord) 是 true,则抛出 TypeError 异常。
  3. targetLengthTypedArrayLength(targetRecord)。
  4. source 设置为 ? ToObject(source)。
  5. sourceLength 为 ? LengthOfArrayLike(source)。
  6. 如果 targetOffset = +∞,则抛出 RangeError 异常。
  7. 如果 sourceLength + targetOffset > targetLength,则抛出 RangeError 异常。
  8. k 为 0。
  9. 重复,只要 k < sourceLength
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. value 为 ? Get(source, propertyKey)。
    3. targetIndex𝔽(targetOffset + k)。
    4. 执行 ? TypedArraySetElement(target, targetIndex, value)。
    5. k 设置为 k + 1。
  10. 返回 unused

23.2.3.26.2 SetTypedArrayFromTypedArray ( target, targetOffset, source )

The abstract operation SetTypedArrayFromTypedArray takes arguments target (a TypedArray), targetOffset (a non-negative integer or +∞), and source (a TypedArray) and returns either a normal completion containing unused or a throw completion. 它从 source 读取值,并从索引 targetOffset 开始在 target 中设置多个值。 It performs the following steps when called:

  1. targetBuffertarget.[[ViewedArrayBuffer]]
  2. targetRecordMakeTypedArrayWithBufferWitnessRecord(target, seq-cst)。
  3. 如果 IsTypedArrayOutOfBounds(targetRecord) 是 true,则抛出 TypeError 异常。
  4. targetLengthTypedArrayLength(targetRecord)。
  5. sourceBuffersource.[[ViewedArrayBuffer]]
  6. sourceRecordMakeTypedArrayWithBufferWitnessRecord(source, seq-cst)。
  7. 如果 IsTypedArrayOutOfBounds(sourceRecord) 是 true,则抛出 TypeError 异常。
  8. sourceLengthTypedArrayLength(sourceRecord)。
  9. targetTypeTypedArrayElementType(target)。
  10. targetElementSizeTypedArrayElementSize(target)。
  11. targetByteOffsettarget.[[ByteOffset]]
  12. sourceTypeTypedArrayElementType(source)。
  13. sourceElementSizeTypedArrayElementSize(source)。
  14. sourceByteOffsetsource.[[ByteOffset]]
  15. 如果 targetOffset = +∞,则抛出 RangeError 异常。
  16. 如果 sourceLength + targetOffset > targetLength,则抛出 RangeError 异常。
  17. 如果 target.[[ContentType]] 不是 source.[[ContentType]],则抛出 TypeError 异常。
  18. 如果 IsSharedArrayBuffer(sourceBuffer) 是 trueIsSharedArrayBuffer(targetBuffer) 是 true,且 sourceBuffer.[[ArrayBufferData]]targetBuffer.[[ArrayBufferData]],则令 sameSharedArrayBuffertrue;否则令 sameSharedArrayBufferfalse
  19. 如果 SameValue(sourceBuffer, targetBuffer) 是 truesameSharedArrayBuffertrue,则
    1. sourceByteLengthTypedArrayByteLength(sourceRecord)。
    2. sourceBuffer 设置为 ? CloneArrayBuffer(sourceBuffer, sourceByteOffset, sourceByteLength)。
    3. sourceByteIndex 为 0。
  20. 否则,
    1. sourceByteIndexsourceByteOffset
  21. targetByteIndex 为 (targetOffset × targetElementSize) + targetByteOffset
  22. limittargetByteIndex + (targetElementSize × sourceLength)。
  23. 如果 sourceTypetargetType,则
    1. 注:传输必须以保留源数据的位级编码的方式执行。
    2. 重复,只要 targetByteIndex < limit
      1. valueGetValueFromBuffer(sourceBuffer, sourceByteIndex, uint8, true, unordered)。
      2. 执行 SetValueInBuffer(targetBuffer, targetByteIndex, uint8, value, true, unordered)。
      3. sourceByteIndex 设置为 sourceByteIndex + 1。
      4. targetByteIndex 设置为 targetByteIndex + 1。
  24. 否则,
    1. 重复,只要 targetByteIndex < limit
      1. valueGetValueFromBuffer(sourceBuffer, sourceByteIndex, sourceType, true, unordered)。
      2. 执行 SetValueInBuffer(targetBuffer, targetByteIndex, targetType, value, true, unordered)。
      3. sourceByteIndex 设置为 sourceByteIndex + sourceElementSize
      4. targetByteIndex 设置为 targetByteIndex + targetElementSize
  25. 返回 unused

23.2.3.27 %TypedArray%.prototype.slice ( start, end )

此方法的实参解释和使用方式与 23.1.3.28 中定义的 Array.prototype.slice 相同。

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. sourceArrayLengthTypedArrayLength(taRecord)。
  4. relativeStart 为 ? ToIntegerOrInfinity(start)。
  5. 如果 relativeStart = -∞,则令 startIndex 为 0。
  6. 否则,如果 relativeStart < 0,则令 startIndexmax(sourceArrayLength + relativeStart, 0)。
  7. 否则,令 startIndexmin(relativeStart, sourceArrayLength)。
  8. 如果 endundefined,则令 relativeEndsourceArrayLength;否则令 relativeEnd 为 ? ToIntegerOrInfinity(end)。
  9. 如果 relativeEnd = -∞,则令 endIndex 为 0。
  10. 否则,如果 relativeEnd < 0,则令 endIndexmax(sourceArrayLength + relativeEnd, 0)。
  11. 否则,令 endIndexmin(relativeEnd, sourceArrayLength)。
  12. countBytesmax(endIndex - startIndex, 0)。
  13. resultArray 为 ? TypedArraySpeciesCreate(obj, « 𝔽(countBytes) »)。
  14. 如果 countBytes > 0,则
    1. taRecord 设置为 MakeTypedArrayWithBufferWitnessRecord(obj, seq-cst)。
    2. 如果 IsTypedArrayOutOfBounds(taRecord) 是 true,则抛出 TypeError 异常。
    3. endIndex 设置为 min(endIndex, TypedArrayLength(taRecord))。
    4. countBytes 设置为 max(endIndex - startIndex, 0)。
    5. sourceTypeTypedArrayElementType(obj)。
    6. targetTypeTypedArrayElementType(resultArray)。
    7. 如果 sourceTypetargetType,则
      1. 注:传输必须以保留源数据的位级编码的方式执行。
      2. sourceBufferobj.[[ViewedArrayBuffer]]
      3. targetBufferresultArray.[[ViewedArrayBuffer]]
      4. elementSizeTypedArrayElementSize(obj)。
      5. sourceByteOffsetobj.[[ByteOffset]]
      6. sourceByteIndex 为 (startIndex × elementSize) + sourceByteOffset
      7. targetByteIndexresultArray.[[ByteOffset]]
      8. endByteIndextargetByteIndex + (countBytes × elementSize)。
      9. 重复,只要 targetByteIndex < endByteIndex
        1. valueGetValueFromBuffer(sourceBuffer, sourceByteIndex, uint8, true, unordered)。
        2. 执行 SetValueInBuffer(targetBuffer, targetByteIndex, uint8, value, true, unordered)。
        3. sourceByteIndex 设置为 sourceByteIndex + 1。
        4. targetByteIndex 设置为 targetByteIndex + 1。
    8. 否则,
      1. n 为 0。
      2. kstartIndex
      3. 重复,只要 k < endIndex
        1. propertyKey 为 ! ToString(𝔽(k))。
        2. kValue 为 ! Get(obj, propertyKey)。
        3. 执行 ! Set(resultArray, ! ToString(𝔽(n)), kValue, true)。
        4. k 设置为 k + 1。
        5. n 设置为 n + 1。
  15. 返回 resultArray

此方法不是泛型的。this 值必须是具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.28 %TypedArray%.prototype.some ( callback [ , thisArg ] )

此方法的实参解释和使用方式与 23.1.3.29 中定义的 Array.prototype.some 相同。

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. lengthTypedArrayLength(taRecord)。
  4. 如果 IsCallable(callback) 是 false,则抛出 TypeError 异常。
  5. k 为 0。
  6. 重复,只要 k < length
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. kValue 为 ! Get(obj, propertyKey)。
    3. testResultToBoolean(? Call(callback, thisArg, « kValue, 𝔽(k), obj »))。
    4. 如果 testResulttrue,则返回 true
    5. k 设置为 k + 1。
  7. 返回 false

此方法不是泛型的。this 值必须是具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.29 %TypedArray%.prototype.sort ( comparator )

这是一个不同的方法;除下文所述外,它实现与 23.1.3.30 中定义的 Array.prototype.sort 相同的要求。此方法的实现可以利用这样的知识进行优化:this 值是具有固定长度且其整数索引属性不稀疏的对象。

此方法不是泛型的。this 值必须是具有 [[TypedArrayName]] 内部槽的对象。

它在被调用时执行以下步骤:

  1. 如果 comparator 不是 undefinedIsCallable(comparator) 是 false,则抛出 TypeError 异常。
  2. objthis 值。
  3. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  4. lengthTypedArrayLength(taRecord)。
  5. 注:以下闭包执行数值比较,而不是 23.1.3.30 中使用的字符串比较。
  6. sortCompare 为一个新的 Abstract Closure,其参数为 (x, y),捕获 comparator,并在被调用时执行以下步骤:
    1. 返回 ? CompareTypedArrayElements(x, y, comparator)。
  7. sortedList 为 ? SortIndexedProperties(obj, length, sortCompare, read-through-holes)。
  8. j 为 0。
  9. 重复,只要 j < length
    1. 执行 ! Set(obj, ! ToString(𝔽(j)), sortedList[j], true)。
    2. j 设置为 j + 1。
  10. 返回 obj
Note

由于 NaN 总是比较为大于任何其他值(见 CompareTypedArrayElements),因此当未提供 comparator 时,NaN 属性值总是排序到结果末尾。

23.2.3.30 %TypedArray%.prototype.subarray ( start, end )

此方法返回一个新的 TypedArray,其元素类型是此 TypedArray 的元素类型,其 ArrayBuffer 是此 TypedArray 的 ArrayBuffer,并引用从 start包含)到 end(不包含区间内的元素。如果 startend 为负,则它引用从数组末尾起的索引,而不是从开头起的索引。

它在被调用时执行以下步骤:

  1. objthis 值。
  2. 执行 ? RequireInternalSlot(obj, [[TypedArrayName]])。
  3. 断言:obj 具有 [[ViewedArrayBuffer]] 内部槽。
  4. bufferobj.[[ViewedArrayBuffer]]
  5. sourceRecordMakeTypedArrayWithBufferWitnessRecord(obj, seq-cst)。
  6. 如果 IsTypedArrayOutOfBounds(sourceRecord) 是 true,则
    1. sourceLength 为 0。
  7. 否则,
    1. sourceLengthTypedArrayLength(sourceRecord)。
  8. relativeStart 为 ? ToIntegerOrInfinity(start)。
  9. 如果 relativeStart = -∞,则令 startIndex 为 0。
  10. 否则,如果 relativeStart < 0,则令 startIndexmax(sourceLength + relativeStart, 0)。
  11. 否则,令 startIndexmin(relativeStart, sourceLength)。
  12. elementSizeTypedArrayElementSize(obj)。
  13. sourceByteOffsetobj.[[ByteOffset]]
  14. beginByteOffsetsourceByteOffset + (startIndex × elementSize)。
  15. 如果 obj.[[ArrayLength]]autoendundefined,则
    1. argList 为 « buffer, 𝔽(beginByteOffset) »。
  16. 否则,
    1. 如果 endundefined,则令 relativeEndsourceLength;否则令 relativeEnd 为 ? ToIntegerOrInfinity(end)。
    2. 如果 relativeEnd = -∞,则令 endIndex 为 0。
    3. 否则,如果 relativeEnd < 0,则令 endIndexmax(sourceLength + relativeEnd, 0)。
    4. 否则,令 endIndexmin(relativeEnd, sourceLength)。
    5. newLengthmax(endIndex - startIndex, 0)。
    6. argList 为 « buffer, 𝔽(beginByteOffset), 𝔽(newLength) »。
  17. 返回 ? TypedArraySpeciesCreate(obj, argList)。

此方法不是泛型的。this 值必须是具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.31 %TypedArray%.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] )

这是一个不同的方法,它实现与 23.1.3.32 中定义的 Array.prototype.toLocaleString 相同的算法,不同之处在于调用 TypedArrayLength 来代替对 "length" 执行 [[Get]]。当底层缓冲区不可调整大小时,可以利用 this 值具有固定长度且其整数索引属性不稀疏这一知识来优化算法的实现。不过,这种优化不得在算法的指定行为中引入任何可观察变化。

此方法不是泛型的。在对算法求值之前,以 this 值和 seq-cst 为实参调用 ValidateTypedArray。如果其结果是突然完成,则抛出该异常,而不是对算法求值。

Note

如果 ECMAScript 实现包含 ECMA-402 国际化 API,则此方法基于 ECMA-402 规范中的 Array.prototype.toLocaleString 算法。

23.2.3.32 %TypedArray%.prototype.toReversed ( )

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. lengthTypedArrayLength(taRecord)。
  4. resultArray 为 ? TypedArrayCreateSameType(obj, length)。
  5. k 为 0。
  6. 重复,只要 k < length
    1. from 为 ! ToString(𝔽(length - k - 1))。
    2. propertyKey 为 ! ToString(𝔽(k))。
    3. fromValue 为 ! Get(obj, from)。
    4. 执行 ! Set(resultArray, propertyKey, fromValue, true)。
    5. k 设置为 k + 1。
  7. 返回 resultArray

23.2.3.33 %TypedArray%.prototype.toSorted ( comparator )

此方法在被调用时执行以下步骤:

  1. 如果 comparator 不是 undefinedIsCallable(comparator) 是 false,则抛出 TypeError 异常。
  2. objthis 值。
  3. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  4. lengthTypedArrayLength(taRecord)。
  5. resultArray 为 ? TypedArrayCreateSameType(obj, length)。
  6. 注:以下闭包执行数值比较,而不是 23.1.3.34 中使用的字符串比较。
  7. sortCompare 为一个新的 Abstract Closure,其参数为 (x, y),捕获 comparator,并在被调用时执行以下步骤:
    1. 返回 ? CompareTypedArrayElements(x, y, comparator)。
  8. sortedList 为 ? SortIndexedProperties(obj, length, sortCompare, read-through-holes)。
  9. j 为 0。
  10. 重复,只要 j < length
    1. 执行 ! Set(resultArray, ! ToString(𝔽(j)), sortedList[j], true)。
    2. j 设置为 j + 1。
  11. 返回 resultArray

23.2.3.34 %TypedArray%.prototype.toString ( )

"toString" 属性的初始值是 %Array.prototype.toString%,定义见 23.1.3.36

23.2.3.35 %TypedArray%.prototype.values ( )

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. 执行 ? ValidateTypedArray(obj, seq-cst)。
  3. 返回 CreateArrayIterator(obj, value)。

23.2.3.36 %TypedArray%.prototype.with ( index, value )

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. lengthTypedArrayLength(taRecord)。
  4. relativeIndex 为 ? ToIntegerOrInfinity(index)。
  5. 如果 relativeIndex ≥ 0,则令 actualIndexrelativeIndex
  6. 否则,令 actualIndexlength + relativeIndex
  7. 如果 obj.[[ContentType]]bigint,则令 numericValue 为 ? ToBigInt(value)。
  8. 否则,令 numericValue 为 ? ToNumber(value)。
  9. 如果 IsValidIntegerIndex(obj, 𝔽(actualIndex)) 是 false,则抛出 RangeError 异常。
  10. resultArray 为 ? TypedArrayCreateSameType(obj, length)。
  11. k 为 0。
  12. 重复,只要 k < length
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. 如果 k = actualIndex,则令 fromValuenumericValue
    3. 否则,令 fromValue 为 ! Get(obj, propertyKey)。
    4. 执行 ! Set(resultArray, propertyKey, fromValue, true)。
    5. k 设置为 k + 1。
  13. 返回 resultArray

23.2.3.37 %TypedArray%.prototype [ %Symbol.iterator% ] ( )

%Symbol.iterator% 属性的初始值是 %TypedArray.prototype.values%,定义见 23.2.3.35

23.2.3.38 get %TypedArray%.prototype [ %Symbol.toStringTag% ]

%TypedArray%.prototype[%Symbol.toStringTag%]访问器属性,其 set 访问器函数是 undefined。其 get 访问器函数在被调用时执行以下步骤:

  1. objthis 值。
  2. 如果 obj 不是 Object,则返回 undefined
  3. 如果 obj 不具有 [[TypedArrayName]] 内部槽,则返回 undefined
  4. nameobj.[[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 )

The abstract operation TypedArrayCreateFromConstructor takes arguments ctor (a constructor) and argList (a List of ECMAScript language values) and returns either a normal completion containing a TypedArray or a throw completion. 它用于指定使用构造器函数创建新的 TypedArray。 It performs the following steps when called:

  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. lengthTypedArrayLength(taRecord)。
    3. 如果 length < (argList[0]),则抛出 TypeError 异常。
  5. 返回 ta

23.2.4.2 TypedArrayCreateSameType ( exemplar, length )

The abstract operation TypedArrayCreateSameType takes arguments exemplar (a TypedArray) and length (a non-negative integer) and returns either a normal completion containing a TypedArray or a throw completion. 它用于指定使用从 exemplar 派生的构造器函数创建新的 TypedArray。不同于可以通过使用 %Symbol.species% 构造自定义 TypedArray 子类的 TypedArraySpeciesCreate,此操作总是使用内置 TypedArray 构造器之一。 It performs the following steps when called:

  1. ctorTable 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 )

The abstract operation TypedArraySpeciesCreate takes arguments exemplar (a TypedArray) and argList (a List of ECMAScript language values) and returns either a normal completion containing a TypedArray or a throw completion. 它用于指定使用从 exemplar 派生的构造器函数创建新的 TypedArray。不同于可以通过使用 %Symbol.species% 创建非 Array 对象的 ArraySpeciesCreate,此操作强制要求构造器函数创建实际的 TypedArray。 It performs the following steps when called:

  1. defaultCtorTable 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 )

The abstract operation ValidateTypedArray takes arguments obj (an ECMAScript language value) and order (seq-cst or unordered) and returns either a normal completion containing a TypedArray With Buffer Witness Record or a throw completion. It performs the following steps when called:

  1. 执行 ? RequireInternalSlot(obj, [[TypedArrayName]])。
  2. 断言:obj 具有 [[ViewedArrayBuffer]] 内部槽。
  3. taRecordMakeTypedArrayWithBufferWitnessRecord(obj, order)。
  4. 如果 IsTypedArrayOutOfBounds(taRecord) 是 true,则抛出 TypeError 异常。
  5. 返回 taRecord

23.2.4.5 TypedArrayElementSize ( obj )

The abstract operation TypedArrayElementSize takes argument obj (a TypedArray) and returns a non-negative integer. It performs the following steps when called:

  1. 返回 Table 71 中为 obj.[[TypedArrayName]] 指定的 Element Size 值。

23.2.4.6 TypedArrayElementType ( obj )

The abstract operation TypedArrayElementType takes argument obj (a TypedArray) and returns a TypedArray element type. It performs the following steps when called:

  1. 返回 Table 71 中为 obj.[[TypedArrayName]] 指定的 Element Type 值。

23.2.4.7 CompareTypedArrayElements ( x, y, comparator )

The abstract operation CompareTypedArrayElements takes arguments x (a Number or a BigInt), y (a Number or a BigInt), and comparator (a function object or undefined) and returns either a normal completion containing a Number or an abrupt completion. It performs the following steps when called:

  1. 断言:x 是 Number 且 y 是 Number,或 x 是 BigInt 且 y 是 BigInt。
  2. 如果 comparator 不是 undefined,则
    1. result 为 ? ToNumber(? Call(comparator, undefined, « x, y »))。
    2. 如果 resultNaN,则返回 +0𝔽
    3. 返回 result
  3. 如果 xNaNyNaN,则返回 +0𝔽
  4. 如果 xNaN,则返回 1𝔽
  5. 如果 yNaN,则返回 -1𝔽
  6. 如果 x < y,则返回 -1𝔽
  7. 如果 x > y,则返回 1𝔽
  8. 如果 x-0𝔽y+0𝔽,则返回 -1𝔽
  9. 如果 x+0𝔽y-0𝔽,则返回 1𝔽
  10. 返回 +0𝔽
Note
这执行数值比较,而不是 23.1.3.30.2 中使用的字符串比较。

23.2.5 TypedArray 构造器

每个 TypedArray 构造器:

  • 是具有下述结构的固有对象,除非另有说明,否则只是在 Table 71 中使用的构造器名称不同,而不是使用 TypedArray
  • 是一个其行为会根据实参数量和类型而不同的函数。调用 TypedArray 的实际行为取决于传给它的实参的数量和种类。
  • 不意图作为函数调用,并且在以这种方式调用时会抛出异常。
  • 可以用作类定义的 extends 子句的值。打算继承指定 TypedArray 行为的子类构造函数,必须包含一次对 TypedArray 构造函数super 调用,以创建并初始化子类实例,使其具备支持 %TypedArray%.prototype 的内置方法所必需的内部状态。

23.2.5.1 TypedArray ( ...args )

每个 TypedArray 构造器在被调用时执行以下步骤:

  1. 如果 NewTarget 是 undefined,则抛出 TypeError 异常。
  2. ctorNameTable 71 中为此 TypedArray 构造器指定的 Constructor Name 值的 String 值。
  3. proto"%TypedArray.prototype%"
  4. numberOfArgsargs 中元素的数量。
  5. 如果 numberOfArgs = 0,则返回 ? AllocateTypedArray(ctorName, NewTarget, proto, 0)。
  6. firstArgargs[0]。
  7. 如果 firstArg 是 Object,则
    1. obj 为 ? AllocateTypedArray(ctorName, NewTarget, proto)。
    2. 如果 firstArg 具有 [[TypedArrayName]] 内部槽,则
      1. 执行 ? InitializeTypedArrayFromTypedArray(obj, firstArg)。
    3. 否则,如果 firstArg 具有 [[ArrayBufferData]] 内部槽,则
      1. 如果 numberOfArgs > 1,则令 byteOffsetargs[1];否则令 byteOffsetundefined
      2. 如果 numberOfArgs > 2,则令 lengthargs[2];否则令 lengthundefined
      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 ] )

The abstract operation AllocateTypedArray takes arguments ctorName (a String which is the name of a TypedArray constructor in Table 71), newTarget (a constructor), and defaultProto (a String) and optional argument length (a non-negative integer) and returns either a normal completion containing a TypedArray or a throw completion. 它用于验证并创建 TypedArray 构造器的实例。如果传入了 length 实参,还会分配该长度的 ArrayBuffer,并将其与新的 TypedArray 实例关联。AllocateTypedArray 提供由 TypedArray 使用的公共语义。 It performs the following steps when called:

  1. proto 为 ? GetPrototypeFromConstructor(newTarget, defaultProto)。
  2. objTypedArrayCreate(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 )

The abstract operation InitializeTypedArrayFromTypedArray takes arguments obj (a TypedArray) and sourceArray (a TypedArray) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

  1. sourceDatasourceArray.[[ViewedArrayBuffer]]
  2. elementTypeTypedArrayElementType(obj)。
  3. elementSizeTypedArrayElementSize(obj)。
  4. sourceTypeTypedArrayElementType(sourceArray)。
  5. sourceElementSizeTypedArrayElementSize(sourceArray)。
  6. sourceByteOffsetsourceArray.[[ByteOffset]]
  7. sourceRecordMakeTypedArrayWithBufferWitnessRecord(sourceArray, seq-cst)。
  8. 如果 IsTypedArrayOutOfBounds(sourceRecord) 是 true,则抛出 TypeError 异常。
  9. elementLengthTypedArrayLength(sourceRecord)。
  10. byteLengthelementSize × elementLength
  11. 如果 elementTypesourceType,则
    1. data 为 ? CloneArrayBuffer(sourceData, sourceByteOffset, byteLength)。
  12. 否则,
    1. data 为 ? AllocateArrayBuffer(%ArrayBuffer%, byteLength)。
    2. 如果 sourceArray.[[ContentType]] 不是 obj.[[ContentType]],则抛出 TypeError 异常。
    3. sourceByteIndexsourceByteOffset
    4. targetByteIndex 为 0。
    5. countelementLength
    6. 重复,只要 count > 0,
      1. valueGetValueFromBuffer(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。
  13. obj.[[ViewedArrayBuffer]] 设置为 data
  14. obj.[[ByteLength]] 设置为 byteLength
  15. obj.[[ByteOffset]] 设置为 0。
  16. obj.[[ArrayLength]] 设置为 elementLength
  17. 返回 unused

23.2.5.1.3 InitializeTypedArrayFromArrayBuffer ( obj, buffer, byteOffset, length )

The abstract operation InitializeTypedArrayFromArrayBuffer takes arguments obj (a TypedArray), buffer (an ArrayBuffer or a SharedArrayBuffer), byteOffset (an ECMAScript language value), and length (an ECMAScript language value) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

  1. elementSizeTypedArrayElementSize(obj)。
  2. offset 为 ? ToIndex(byteOffset)。
  3. 如果 offsetelementSize ≠ 0,则抛出 RangeError 异常。
  4. bufferIsFixedLengthIsFixedLengthArrayBuffer(buffer)。
  5. 如果 length 不是 undefined,则
    1. newLength 为 ? ToIndex(length)。
  6. 如果 IsDetachedBuffer(buffer) 是 true,则抛出 TypeError 异常。
  7. bufferByteLengthArrayBufferByteLength(buffer, seq-cst)。
  8. 如果 lengthundefinedbufferIsFixedLengthfalse,则
    1. 如果 offset > bufferByteLength,则抛出 RangeError 异常。
    2. obj.[[ByteLength]] 设置为 auto
    3. obj.[[ArrayLength]] 设置为 auto
  9. 否则,
    1. 如果 lengthundefined,则
      1. 如果 bufferByteLengthelementSize ≠ 0,则抛出 RangeError 异常。
      2. newByteLengthbufferByteLength - offset
      3. 如果 newByteLength < 0,则抛出 RangeError 异常。
    2. 否则,
      1. newByteLengthnewLength × 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 )

The abstract operation InitializeTypedArrayFromList takes arguments obj (a TypedArray) and values (a List of ECMAScript language values) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

  1. lengthvalues 中元素的数量。
  2. 执行 ? AllocateTypedArrayBuffer(obj, length)。
  3. k 为 0。
  4. 重复,只要 k < length
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. kValuevalues 的第一个元素。
    3. values 中移除第一个元素。
    4. 执行 ? Set(obj, propertyKey, kValue, true)。
    5. k 设置为 k + 1。
  5. 断言:values 现在是空 List
  6. 返回 unused

23.2.5.1.5 InitializeTypedArrayFromArrayLike ( obj, arrayLike )

The abstract operation InitializeTypedArrayFromArrayLike takes arguments obj (a TypedArray) and arrayLike (an Object, but not a TypedArray or an ArrayBuffer) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

  1. length 为 ? LengthOfArrayLike(arrayLike)。
  2. 执行 ? AllocateTypedArrayBuffer(obj, length)。
  3. k 为 0。
  4. 重复,只要 k < length
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. kValue 为 ? Get(arrayLike, propertyKey)。
    3. 执行 ? Set(obj, propertyKey, kValue, true)。
    4. k 设置为 k + 1。
  5. 返回 unused

23.2.5.1.6 AllocateTypedArrayBuffer ( obj, length )

The abstract operation AllocateTypedArrayBuffer takes arguments obj (a TypedArray) and length (a non-negative integer) and returns either a normal completion containing unused or a throw completion. 它分配一个 ArrayBuffer,并将其与 obj 关联。 It performs the following steps when called:

  1. 断言:obj.[[ViewedArrayBuffer]]undefined
  2. elementSizeTypedArrayElementSize(obj)。
  3. byteLengthelementSize × 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" 属性,其值是在 Table 71 中为其指定的构造器名称的 String 值。
  • 具有以下属性:

23.2.6.1 TypedArray.BYTES_PER_ELEMENT

TypedArray.BYTES_PER_ELEMENT 的值是 Table 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 的值是 Table 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. opts 为 ? GetOptionsObject(options)。
  3. alphabet 为 ? Get(opts, "alphabet")。
  4. 如果 alphabetundefined,则将 alphabet 设置为 "base64"
  5. 如果 alphabet 既不是 "base64" 也不是 "base64url",则抛出 TypeError 异常。
  6. lastChunkHandling 为 ? Get(opts, "lastChunkHandling")。
  7. 如果 lastChunkHandlingundefined,则将 lastChunkHandling 设置为 "loose"
  8. 如果 lastChunkHandling 不是 "loose""strict""stop-before-partial" 之一,则抛出 TypeError 异常。
  9. resultFromBase64(string, alphabet, lastChunkHandling)。
  10. 如果 result.[[Error]] 不是 none,则
    1. 抛出 result.[[Error]]
  11. resultLengthresult.[[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. resultFromHex(string)。
  3. 如果 result.[[Error]] 不是 none,则
    1. 抛出 result.[[Error]]
  4. resultLengthresult.[[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. intothis 值。
  2. 执行 ? ValidateUint8Array(into)。
  3. 如果 string 不是 String,则抛出 TypeError 异常。
  4. opts 为 ? GetOptionsObject(options)。
  5. alphabet 为 ? Get(opts, "alphabet")。
  6. 如果 alphabetundefined,则将 alphabet 设置为 "base64"
  7. 如果 alphabet 既不是 "base64" 也不是 "base64url",则抛出 TypeError 异常。
  8. lastChunkHandling 为 ? Get(opts, "lastChunkHandling")。
  9. 如果 lastChunkHandlingundefined,则将 lastChunkHandling 设置为 "loose"
  10. 如果 lastChunkHandling 不是 "loose""strict""stop-before-partial" 之一,则抛出 TypeError 异常。
  11. taRecordMakeTypedArrayWithBufferWitnessRecord(into, seq-cst)。
  12. 如果 IsTypedArrayOutOfBounds(taRecord) 是 true,则抛出 TypeError 异常。
  13. byteLengthTypedArrayLength(taRecord)。
  14. resultFromBase64(string, alphabet, lastChunkHandling, byteLength)。
  15. bytesresult.[[Bytes]]
  16. writtenbytes 中元素的数量。
  17. 注:FromBase64 不调用任何用户代码,因此支撑 into 的 ArrayBuffer 不可能已被分离或缩小。
  18. 断言:writtenbyteLength
  19. 执行 SetUint8ArrayBytes(into, bytes)。
  20. 如果 result.[[Error]] 不是 none,则
    1. 抛出 result.[[Error]]
  21. resultObjOrdinaryObjectCreate(%Object.prototype%)。
  22. 执行 ! CreateDataPropertyOrThrow(resultObj, "read", 𝔽(result.[[Read]]))。
  23. 执行 ! CreateDataPropertyOrThrow(resultObj, "written", 𝔽(written))。
  24. 返回 resultObj

23.3.2.2 Uint8Array.prototype.setFromHex ( string )

  1. intothis 值。
  2. 执行 ? ValidateUint8Array(into)。
  3. 如果 string 不是 String,则抛出 TypeError 异常。
  4. taRecordMakeTypedArrayWithBufferWitnessRecord(into, seq-cst)。
  5. 如果 IsTypedArrayOutOfBounds(taRecord) 是 true,则抛出 TypeError 异常。
  6. byteLengthTypedArrayLength(taRecord)。
  7. resultFromHex(string, byteLength)。
  8. bytesresult.[[Bytes]]
  9. writtenbytes 中元素的数量。
  10. 注:FromHex 不调用任何用户代码,因此支撑 into 的 ArrayBuffer 不可能已被分离或缩小。
  11. 断言:writtenbyteLength
  12. 执行 SetUint8ArrayBytes(into, bytes)。
  13. 如果 result.[[Error]] 不是 none,则
    1. 抛出 result.[[Error]]
  14. resultObjOrdinaryObjectCreate(%Object.prototype%)。
  15. 执行 ! CreateDataPropertyOrThrow(resultObj, "read", 𝔽(result.[[Read]]))。
  16. 执行 ! CreateDataPropertyOrThrow(resultObj, "written", 𝔽(written))。
  17. 返回 resultObj

23.3.2.3 Uint8Array.prototype.toBase64 ( [ options ] )

  1. objthis 值。
  2. 执行 ? ValidateUint8Array(obj)。
  3. opts 为 ? GetOptionsObject(options)。
  4. alphabet 为 ? Get(opts, "alphabet")。
  5. 如果 alphabetundefined,则将 alphabet 设置为 "base64"
  6. 如果 alphabet 既不是 "base64" 也不是 "base64url",则抛出 TypeError 异常。
  7. omitPaddingToBoolean(? Get(opts, "omitPadding"))。
  8. toEncode 为 ? GetUint8ArrayBytes(obj)。
  9. 如果 alphabet"base64",则
    1. outAscii 为根据 RFC 4648 第 4 节指定的 base64 编码对 toEncode 进行编码所得的码点序列。当且仅当 omitPaddingfalse包含填充。
  10. 否则,
    1. 断言:alphabet"base64url"
    2. outAscii 为根据 RFC 4648 第 5 节指定的 base64url 编码对 toEncode 进行编码所得的码点序列。当且仅当 omitPaddingfalse包含填充。
  11. 返回 CodePointsToString(outAscii)。

23.3.2.4 Uint8Array.prototype.toHex ( )

  1. objthis 值。
  2. 执行 ? ValidateUint8Array(obj)。
  3. toEncode 为 ? GetUint8ArrayBytes(obj)。
  4. out 为空 String。
  5. toEncode 的每个字节 byte,执行:
    1. hexNumber::toString(𝔽(byte), 16)。
    2. hex 设置为 StringPad(hex, 2, "0", start)。
    3. out 设置为 outhex字符串连接
  6. 返回 out

23.3.3 Uint8Array 对象的抽象操作

23.3.3.1 ValidateUint8Array ( ta )

The abstract operation ValidateUint8Array takes argument ta (an ECMAScript language value) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

  1. 执行 ? RequireInternalSlot(ta, [[TypedArrayName]])。
  2. 如果 ta.[[TypedArrayName]] 不是 "Uint8Array",则抛出 TypeError 异常。
  3. 返回 unused

23.3.3.2 GetUint8ArrayBytes ( ta )

The abstract operation GetUint8ArrayBytes takes argument ta (a Uint8Array) and returns either a normal completion containing a List of byte values or a throw completion. It performs the following steps when called:

  1. bufferta.[[ViewedArrayBuffer]]
  2. taRecordMakeTypedArrayWithBufferWitnessRecord(ta, seq-cst)。
  3. 如果 IsTypedArrayOutOfBounds(taRecord) 是 true,则抛出 TypeError 异常。
  4. lengthTypedArrayLength(taRecord)。
  5. byteOffsetta.[[ByteOffset]]
  6. bytes 为新的空 List
  7. index 为 0。
  8. 重复,只要 index < length
    1. byteIndexbyteOffset + index
    2. byte(GetValueFromBuffer(buffer, byteIndex, uint8, true, unordered))。
    3. byte 追加到 bytes
    4. index 设置为 index + 1。
  9. 返回 bytes

23.3.3.3 SetUint8ArrayBytes ( into, bytes )

The abstract operation SetUint8ArrayBytes takes arguments into (a Uint8Array) and bytes (a List of byte values) and returns unused. It performs the following steps when called:

  1. offsetinto.[[ByteOffset]]
  2. lengthbytes 中元素的数量。
  3. index 为 0。
  4. 重复,只要 index < length
    1. bytebytes[index]。
    2. byteIndexInBufferindex + offset
    3. 执行 SetValueInBuffer(into.[[ViewedArrayBuffer]], byteIndexInBuffer, uint8, 𝔽(byte), true, unordered)。
    4. index 设置为 index + 1。
  5. 返回 unused

23.3.3.4 SkipAsciiWhitespace ( string, index )

The abstract operation SkipAsciiWhitespace takes arguments string (a String) and index (a non-negative integer) and returns a non-negative integer. It performs the following steps when called:

  1. lengthstring 的长度。
  2. 重复,只要 index < length
    1. charstring 中索引 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 )

The abstract operation DecodeFinalBase64Chunk takes arguments chunk (a String of length 2 or 3) and throwOnExtraBits (a Boolean) and returns either a normal completion containing a List of byte values, or a throw completion. It performs the following steps when called:

  1. chunkLengthchunk 的长度。
  2. 如果 chunkLength = 2,则
    1. chunk 设置为 chunk"AA"字符串连接
  3. 否则,
    1. 断言:chunkLength 是 3。
    2. chunk 设置为 chunk"A"字符串连接
  4. bytesDecodeFullLengthBase64Chunk(chunk)。
  5. 如果 chunkLength = 2,则
    1. 如果 throwOnExtraBitstruebytes[1] ≠ 0,则抛出 SyntaxError 异常。
    2. 返回 « bytes[0] »。
  6. 如果 throwOnExtraBitstruebytes[2] ≠ 0,则抛出 SyntaxError 异常。
  7. 返回 « bytes[0], bytes[1] »。

23.3.3.6 DecodeFullLengthBase64Chunk ( chunk )

The abstract operation DecodeFullLengthBase64Chunk takes argument chunk (a String of length 4) and returns a List of byte values of length 3.

标准 base64 字母表"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",即由 Unicode Basic Latin 块中每个字母和数字对应的码元,以及 "+""/" 组成的 String。

  1. byteSequence 为将 chunk 作为 base64 解码所得的唯一 3 字节序列(即,对 byteSequence 应用 RFC 4648 第 4 节指定的 base64 编码会产生 chunk 的序列)。
  2. 返回一个 List,其元素按顺序为 byteSequence 的元素。

23.3.3.7 FromBase64 ( string, alphabet, lastChunkHandling [ , maxLength ] )

The abstract operation FromBase64 takes arguments string (a String), alphabet ("base64" or "base64url"), and lastChunkHandling ("loose", "strict", or "stop-before-partial") and optional argument maxLength (a non-negative integer) and returns a Record with fields [[Read]] (an integer), [[Bytes]] (a List of byte values), and [[Error]] (a SyntaxError object or none). It performs the following steps when called:

  1. 如果 maxLength 不存在,则
    1. maxLength 设置为 253 - 1。
    2. 注:因为输入是 String,String 的长度被限制为 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. lengthstring 的长度。
  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. charstringindexindex + 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 设置为 stringindexindex + 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",则令 throwOnExtraBitstrue;否则令 throwOnExtraBitsfalse
      6. decodeResultCompletion(DecodeFinalBase64Chunk(chunk, throwOnExtraBits))。
      7. 如果 decodeResult突然完成,则
        1. errordecodeResult.[[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. remainingmaxLength - bytes 中元素的数量。
    10. 如果 remaining = 1 且 chunkLength = 2,或如果 remaining = 2 且 chunkLength = 3,则
      1. 返回 Record { [[Read]]: read, [[Bytes]]: bytes, [[Error]]: none }。
    11. chunk 设置为 chunkchar字符串连接
    12. chunkLength 设置为 chunk 的长度。
    13. 如果 chunkLength = 4,则
      1. bytes 设置为 bytesDecodeFullLengthBase64Chunk(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 ] )

The abstract operation FromHex takes argument string (a String) and optional argument maxLength (a non-negative integer) and returns a Record with fields [[Read]] (an integer), [[Bytes]] (a List of byte values), and [[Error]] (a SyntaxError object or none). It performs the following steps when called:

  1. 如果 maxLength 不存在,则将 maxLength 设置为 253 - 1。
  2. lengthstring 的长度。
  3. bytes 为新的空 List
  4. read 为 0。
  5. 如果 length 模 2 ≠ 0,则
    1. error 为新创建的 SyntaxError 对象。
    2. 返回 Record { [[Read]]: read, [[Bytes]]: bytes, [[Error]]: error }。
  6. 重复,只要 read < lengthbytes 中元素的数量 < maxLength
    1. hexitsstringreadread + 2 的子字符串
    2. 如果 hexits 包含任何不在 "0123456789abcdefABCDEF" 中的码元,则
      1. error 为新创建的 SyntaxError 对象。
      2. 返回 Record { [[Read]]: read, [[Bytes]]: bytes, [[Error]]: error }。
    3. read 设置为 read + 2。
    4. bytehexits 以 16 进制记法所表示的整数值,使用字母 AFaf 表示值为 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. 如果 iterableundefinednull,则返回 map
  5. adder 为 ? Get(map, "set")。
  6. 如果 IsCallable(adder) 是 false,则抛出 TypeError 异常。
  7. 返回 ? AddEntriesFromIterable(map, iterable, adder)。
Note

如果存在参数 iterable,则它预期为实现了 %Symbol.iterator% 方法的对象,该方法返回一个迭代器对象,该迭代器对象产生一个双元素的类数组对象,其第一个元素是将用作 Map 键的值,第二个元素是要与该键关联的值。

24.1.1.2 AddEntriesFromIterable ( target, iterable, adder )

The abstract operation AddEntriesFromIterable takes arguments target (an Object), iterable (an ECMAScript language value, but not undefined or null), and adder (a function object) and returns either a normal completion containing an Object or a throw completion. adder 将以 target 作为接收者来调用。 It performs the following steps when called:

  1. iteratorRecord 为 ? GetIterator(iterable, sync)。
  2. 重复,
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 nextdone,则返回 target
    3. 如果 next 不是 Object,则
      1. errorThrowCompletion(一个新创建的 TypeError 对象)。
      2. 返回 ? IteratorClose(iteratorRecord, error)。
    4. keyCompletion(Get(next, "0"))。
    5. IfAbruptCloseIterator(key, iteratorRecord)。
    6. valueCompletion(Get(next, "1"))。
    7. IfAbruptCloseIterator(value, iteratorRecord)。
    8. statusCompletion(Call(adder, target, « key, value »))。
    9. IfAbruptCloseIterator(status, iteratorRecord)。
Note

参数 iterable 预期为实现了 %Symbol.iterator% 方法的对象,该方法返回一个迭代器对象,该迭代器对象产生一个双元素的类数组对象,其第一个元素是将用作 Map 键的值,第二个元素是要与该键关联的值。

24.1.2 Map 构造器的属性

Map 构造器:

24.1.2.1 Map.groupBy ( items, callback )

Note

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. elementsCreateArrayFromList(group.[[Elements]])。
    2. entryRecord { [[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 值。

此函数的 "name" 属性的值是 "get [Symbol.species]"

Note

创建派生集合对象的方法应调用 %Symbol.species%,以确定用于创建派生对象的构造器。子类构造器可以重写 %Symbol.species%,以改变默认构造器分配。

24.1.3 Map 原型对象的属性

Map 原型对象

24.1.3.1 Map.prototype.clear ( )

此方法在被调用时执行以下步骤:

  1. mapthis 值。
  2. 执行 ? RequireInternalSlot(map, [[MapData]])。
  3. map.[[MapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行:
    1. entry.[[Key]] 设置为 empty
    2. entry.[[Value]] 设置为 empty
  4. 返回 undefined
Note

现有的 [[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. mapthis 值。
  2. 执行 ? RequireInternalSlot(map, [[MapData]])。
  3. key 设置为 CanonicalizeKeyedCollectionKey(key)。
  4. map.[[MapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行:
    1. 如果 entry.[[Key]] 不是 emptySameValue(entry.[[Key]], key) 是 true,则
      1. entry.[[Key]] 设置为 empty
      2. entry.[[Value]] 设置为 empty
      3. 返回 true
  5. 返回 false
Note

empty 用作规范装置,用来表示某个条目已被删除。实际实现可以采取其他操作,例如从内部数据结构中物理移除该条目。

24.1.3.4 Map.prototype.entries ( )

此方法在被调用时执行以下步骤:

  1. mapthis 值。
  2. 返回 ? CreateMapIterator(map, key+value)。

24.1.3.5 Map.prototype.forEach ( callback [ , thisArg ] )

此方法在被调用时执行以下步骤:

  1. mapthis 值。
  2. 执行 ? RequireInternalSlot(map, [[MapData]])。
  3. 如果 IsCallable(callback) 是 false,则抛出 TypeError 异常。
  4. entriesmap.[[MapData]]
  5. entriesCountentries 中元素的数量。
  6. index 为 0。
  7. 重复,只要 index < entriesCount
    1. entryentries[index]。
    2. index 设置为 index + 1。
    3. 如果 entry.[[Key]] 不是 empty,则
      1. 执行 ? Call(callback, thisArg, « entry.[[Value]], entry.[[Key]], map »)。
      2. 注:entries 中元素的数量可能已在 callback 执行期间增加。
      3. entriesCount 设置为 entries 中元素的数量。
  8. 返回 undefined
Note

callback 应当是一个接受三个实参的函数。forEach 会按键插入顺序,为 Map 中存在的每个键/值对调用一次 callbackcallback 只会为 Map 中实际存在的键调用;不会为已经从 Map 中删除的键调用。

如果提供了 thisArg 参数,则它会被用作每次调用 callback 时的 this 值。如果未提供,则改用 undefined

callback 会以三个实参调用:项的值、项的键,以及正在遍历的 Map。

forEach 不会直接改变调用它的对象,但该对象可能会被对 callback 的调用改变。Map 的 [[MapData]] 的每个条目只会被访问一次。在对 forEach 的调用开始之后添加的新键会被访问。如果某个键在被访问后被删除,然后又在 forEach 调用完成前重新添加,则该键会再次被访问。在对 forEach 的调用开始之后且被访问之前删除的键不会被访问,除非该键在 forEach 调用完成前再次被添加。

24.1.3.6 Map.prototype.get ( key )

此方法在被调用时执行以下步骤:

  1. mapthis 值。
  2. 执行 ? RequireInternalSlot(map, [[MapData]])。
  3. key 设置为 CanonicalizeKeyedCollectionKey(key)。
  4. map.[[MapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行:
    1. 如果 entry.[[Key]] 不是 emptySameValue(entry.[[Key]], key) 是 true,则返回 entry.[[Value]]
  5. 返回 undefined

24.1.3.7 Map.prototype.getOrInsert ( key, value )

此方法在被调用时执行以下步骤:

  1. mapthis 值。
  2. 执行 ? RequireInternalSlot(map, [[MapData]])。
  3. key 设置为 CanonicalizeKeyedCollectionKey(key)。
  4. map.[[MapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行:
    1. 如果 entry.[[Key]] 不是 emptySameValue(entry.[[Key]], key) 是 true,则返回 entry.[[Value]]
  5. entryRecord { [[Key]]: key, [[Value]]: value }。
  6. entry 追加到 map.[[MapData]]
  7. 返回 value

24.1.3.8 Map.prototype.getOrInsertComputed ( key, callback )

此方法在被调用时执行以下步骤:

  1. mapthis 值。
  2. 执行 ? RequireInternalSlot(map, [[MapData]])。
  3. 如果 IsCallable(callback) 是 false,则抛出 TypeError 异常。
  4. key 设置为 CanonicalizeKeyedCollectionKey(key)。
  5. map.[[MapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行:
    1. 如果 entry.[[Key]] 不是 emptySameValue(entry.[[Key]], key) 是 true,则返回 entry.[[Value]]
  6. value 为 ? Call(callback, undefined, « key »)。
  7. 注:Map 可能已在 callback 执行期间被修改。
  8. map.[[MapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行:
    1. 如果 entry.[[Key]] 不是 emptySameValue(entry.[[Key]], key) 是 true,则
      1. entry.[[Value]] 设置为 value
      2. 返回 value
  9. entryRecord { [[Key]]: key, [[Value]]: value }。
  10. entry 追加到 map.[[MapData]]
  11. 返回 value

24.1.3.9 Map.prototype.has ( key )

此方法在被调用时执行以下步骤:

  1. mapthis 值。
  2. 执行 ? RequireInternalSlot(map, [[MapData]])。
  3. key 设置为 CanonicalizeKeyedCollectionKey(key)。
  4. map.[[MapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行:
    1. 如果 entry.[[Key]] 不是 emptySameValue(entry.[[Key]], key) 是 true,则返回 true
  5. 返回 false

24.1.3.10 Map.prototype.keys ( )

此方法在被调用时执行以下步骤:

  1. mapthis 值。
  2. 返回 ? CreateMapIterator(map, key)。

24.1.3.11 Map.prototype.set ( key, value )

此方法在被调用时执行以下步骤:

  1. mapthis 值。
  2. 执行 ? RequireInternalSlot(map, [[MapData]])。
  3. key 设置为 CanonicalizeKeyedCollectionKey(key)。
  4. map.[[MapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行:
    1. 如果 entry.[[Key]] 不是 emptySameValue(entry.[[Key]], key) 是 true,则
      1. entry.[[Value]] 设置为 value
      2. 返回 map
  5. entryRecord { [[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. mapthis 值。
  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. mapthis 值。
  2. 返回 ? CreateMapIterator(map, value)。

24.1.3.14 Map.prototype [ %Symbol.iterator% ] ( )

%Symbol.iterator% 属性的初始值是 %Map.prototype.entries%,定义见 24.1.3.4

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 Iterator 对象

Map Iterator 是表示对某个特定 Map 实例对象进行特定迭代的对象。Map Iterator 对象没有具名构造器。相反,Map Iterator 对象通过调用 Map 实例对象的某些方法创建。

24.1.5.1 CreateMapIterator ( map, kind )

The abstract operation CreateMapIterator takes arguments map (an ECMAScript language value) and kind (key+value, key, or value) and returns either a normal completion containing a Generator or a throw completion. 它用于为返回此类迭代器的 Map 方法创建迭代器对象。 It performs the following steps when called:

  1. 执行 ? RequireInternalSlot(map, [[MapData]])。
  2. closure 为一个新的无参数 Abstract Closure,它捕获 mapkind,并在被调用时执行以下步骤:
    1. entriesmap.[[MapData]]
    2. index 为 0。
    3. entriesCountentries 中元素的数量。
    4. 重复,只要 index < entriesCount
      1. entryentries[index]。
      2. index 设置为 index + 1。
      3. 如果 entry.[[Key]] 不是 empty,则
        1. 如果 kindkey,则
          1. resultentry.[[Key]]
        2. 否则,如果 kindvalue,则
          1. resultentry.[[Value]]
        3. 否则,
          1. 断言:kindkey+value
          2. resultCreateArrayFromListentry.[[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 是一种 Record 值,用于封装 Set 或类似对象的接口。

Set Record 具有 Table 72 中列出的字段。

Table 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 )

The abstract operation GetSetRecord takes argument obj (an ECMAScript language value) and returns either a normal completion containing a Set Record or a throw completion. It performs the following steps when called:

  1. 如果 obj 不是 Object,则抛出 TypeError 异常。
  2. rawSize 为 ? Get(obj, "size")。
  3. numberSize 为 ? ToNumber(rawSize)。
  4. 注:如果 rawSizeundefined,则 numberSize 将是 NaN
  5. 如果 numberSizeNaN,则抛出 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 )

The abstract operation SetDataHas takes arguments setData (a List of either ECMAScript language values or empty) and value (an ECMAScript language value) and returns a Boolean. It performs the following steps when called:

  1. 如果 SetDataIndex(setData, value) 是 not-found,则返回 false
  2. 返回 true

24.2.1.4 SetDataIndex ( setData, value )

The abstract operation SetDataIndex takes arguments setData (a List of either ECMAScript language values or empty) and value (an ECMAScript language value) and returns a non-negative integer or not-found. It performs the following steps when called:

  1. value 设置为 CanonicalizeKeyedCollectionKey(value)。
  2. sizesetData 中元素的数量。
  3. index 为 0。
  4. 重复,只要 index < size
    1. elementsetData[index]。
    2. 如果 element 不是 emptyelementvalue,则
      1. 返回 index
    3. index 设置为 index + 1。
  5. 返回 not-found

24.2.1.5 SetDataSize ( setData )

The abstract operation SetDataSize takes argument setData (a List of either ECMAScript language values or empty) and returns a non-negative integer. It performs the following steps when called:

  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. 如果 iterableundefinednull,则返回 set
  5. adder 为 ? Get(set, "add")。
  6. 如果 IsCallable(adder) 是 false,则抛出 TypeError 异常。
  7. iteratorRecord 为 ? GetIterator(iterable, sync)。
  8. 重复,
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 nextdone,则返回 set
    3. statusCompletion(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 值。

此函数的 "name" 属性的值是 "get [Symbol.species]"

Note

创建派生集合对象的方法应调用 %Symbol.species%,以确定用于创建派生对象的构造器。子类构造器可以重写 %Symbol.species%,以改变默认构造器分配。

24.2.4 Set 原型对象的属性

Set 原型对象

24.2.4.1 Set.prototype.add ( value )

此方法在被调用时执行以下步骤:

  1. setthis 值。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. value 设置为 CanonicalizeKeyedCollectionKey(value)。
  4. set.[[SetData]] 的每个元素 entry,执行:
    1. 如果 entry 不是 emptySameValue(entry, value) 是 true,则
      1. 返回 set
  5. value 追加到 set.[[SetData]]
  6. 返回 set

24.2.4.2 Set.prototype.clear ( )

此方法在被调用时执行以下步骤:

  1. setthis 值。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. set.[[SetData]] 的每个元素 entry,执行:
    1. set.[[SetData]] 中值为 entry 的元素替换为值为 empty 的元素。
  4. 返回 undefined
Note

现有的 [[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. setthis 值。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. value 设置为 CanonicalizeKeyedCollectionKey(value)。
  4. set.[[SetData]] 的每个元素 entry,执行:
    1. 如果 entry 不是 emptySameValue(entry, value) 是 true,则
      1. set.[[SetData]] 中值为 entry 的元素替换为值为 empty 的元素。
      2. 返回 true
  5. 返回 false
Note

empty 用作规范装置,用来表示某个条目已被删除。实际实现可以采取其他操作,例如从内部数据结构中物理移除该条目。

24.2.4.5 Set.prototype.difference ( other )

此方法在被调用时执行以下步骤:

  1. setthis 值。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. otherRecord 为 ? GetSetRecord(other)。
  4. resultSetDataset.[[SetData]] 的一个副本。
  5. 如果 SetDataSize(set.[[SetData]]) ≤ otherRecord.[[Size]],则
    1. thisSizeset.[[SetData]] 中元素的数量。
    2. index 为 0。
    3. 重复,只要 index < thisSize
      1. entryresultSetData[index]。
      2. 如果 entry 不是 empty,则
        1. inOtherToBoolean(? Call(otherRecord.[[Has]], otherRecord.[[SetObject]], « entry »))。
        2. 如果 inOthertrue,则
          1. resultSetData[index] 设置为 empty
      3. index 设置为 index + 1。
  6. 否则,
    1. keysIterator 为 ? GetIteratorFromMethod(otherRecord.[[SetObject]], otherRecord.[[Keys]])。
    2. nextnot-started
    3. 重复,只要 next 不是 done
      1. next 设置为 ? IteratorStepValue(keysIterator)。
      2. 如果 next 不是 done,则
        1. next 设置为 CanonicalizeKeyedCollectionKey(next)。
        2. valueIndexSetDataIndex(resultSetData, next)。
        3. 如果 valueIndex 不是 not-found,则
          1. resultSetData[valueIndex] 设置为 empty
  7. resultOrdinaryObjectCreate(%Set.prototype%, « [[SetData]] »)。
  8. result.[[SetData]] 设置为 resultSetData
  9. 返回 result

24.2.4.6 Set.prototype.entries ( )

此方法在被调用时执行以下步骤:

  1. setthis 值。
  2. 返回 ? CreateSetIterator(set, key+value)。
Note

出于迭代目的,Set 看起来类似于每个条目的键和值相同的 Map。

24.2.4.7 Set.prototype.forEach ( callback [ , thisArg ] )

此方法在被调用时执行以下步骤:

  1. setthis 值。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. 如果 IsCallable(callback) 是 false,则抛出 TypeError 异常。
  4. entriesset.[[SetData]]
  5. entriesCountentries 中元素的数量。
  6. index 为 0。
  7. 重复,只要 index < entriesCount
    1. entryentries[index]。
    2. index 设置为 index + 1。
    3. 如果 entry 不是 empty,则
      1. 执行 ? Call(callback, thisArg, « entry, entry, set »)。
      2. 注:entries 中元素的数量可能已在 callback 执行期间增加。
      3. entriesCount 设置为 entries 中元素的数量。
  8. 返回 undefined
Note

callback 应当是一个接受三个实参的函数。forEach 会按值插入顺序,为 Set 对象中存在的每个值调用一次 callbackcallback 只会为 Set 中实际存在的值调用;不会为已经从 set 中删除的键调用。

如果提供了 thisArg 参数,则它会被用作每次调用 callback 时的 this 值。如果未提供,则改用 undefined

callback 会以三个实参调用:前两个实参是 Set 中包含的一个值。相同的值会作为这两个实参传入。正在遍历的 Set 对象作为第三个实参传入。

callback 会以三个实参调用,是为了与 Map 和 Array 的 forEach 方法所使用的回调函数保持一致。对于 Set,每个项值都被视为键和值。

forEach 不会直接改变调用它的对象,但该对象可能会被对 callback 的调用改变。

每个值通常只会被访问一次。但是,如果某个值在被访问后被删除,然后又在 forEach 调用完成前重新添加,则该值会再次被访问。在对 forEach 的调用开始之后且被访问之前删除的值不会被访问,除非该值在 forEach 调用完成前再次被添加。在对 forEach 的调用开始之后添加的新值会被访问。

24.2.4.8 Set.prototype.has ( value )

此方法在被调用时执行以下步骤:

  1. setthis 值。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. value 设置为 CanonicalizeKeyedCollectionKey(value)。
  4. set.[[SetData]] 的每个元素 entry,执行:
    1. 如果 entry 不是 emptySameValue(entry, value) 是 true,则返回 true
  5. 返回 false

24.2.4.9 Set.prototype.intersection ( other )

此方法在被调用时执行以下步骤:

  1. setthis 值。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. otherRecord 为 ? GetSetRecord(other)。
  4. resultSetData 为新的空 List
  5. 如果 SetDataSize(set.[[SetData]]) ≤ otherRecord.[[Size]],则
    1. thisSizeset.[[SetData]] 中元素的数量。
    2. index 为 0。
    3. 重复,只要 index < thisSize
      1. entryset.[[SetData]][index]。
      2. index 设置为 index + 1。
      3. 如果 entry 不是 empty,则
        1. inOtherToBoolean(? Call(otherRecord.[[Has]], otherRecord.[[SetObject]], « entry »))。
        2. 如果 inOthertrue,则
          1. 注:先前对 otherRecord.[[Has]] 的调用可能会移除并重新添加 set.[[SetData]] 的一个元素,这可能导致同一个元素在此次迭代期间被访问两次。
          2. 如果 SetDataHas(resultSetData, entry) 是 false,则
            1. entry 追加到 resultSetData
        3. 注:set.[[SetData]] 中元素的数量可能已在 otherRecord.[[Has]] 执行期间增加。
        4. thisSize 设置为 set.[[SetData]] 中元素的数量。
  6. 否则,
    1. keysIterator 为 ? GetIteratorFromMethod(otherRecord.[[SetObject]], otherRecord.[[Keys]])。
    2. nextnot-started
    3. 重复,只要 next 不是 done
      1. next 设置为 ? IteratorStepValue(keysIterator)。
      2. 如果 next 不是 done,则
        1. next 设置为 CanonicalizeKeyedCollectionKey(next)。
        2. inThisSetDataHas(set.[[SetData]], next)。
        3. 如果 inThistrue,则
          1. 注:因为 other 是任意对象,它的 "keys" 迭代器可能会多次产生相同的值。
          2. 如果 SetDataHas(resultSetData, next) 是 false,则
            1. next 追加到 resultSetData
  7. resultOrdinaryObjectCreate(%Set.prototype%, « [[SetData]] »)。
  8. result.[[SetData]] 设置为 resultSetData
  9. 返回 result

24.2.4.10 Set.prototype.isDisjointFrom ( other )

此方法在被调用时执行以下步骤:

  1. setthis 值。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. otherRecord 为 ? GetSetRecord(other)。
  4. 如果 SetDataSize(set.[[SetData]]) ≤ otherRecord.[[Size]],则
    1. thisSizeset.[[SetData]] 中元素的数量。
    2. index 为 0。
    3. 重复,只要 index < thisSize
      1. entryset.[[SetData]][index]。
      2. index 设置为 index + 1。
      3. 如果 entry 不是 empty,则
        1. inOtherToBoolean(? Call(otherRecord.[[Has]], otherRecord.[[SetObject]], « entry »))。
        2. 如果 inOthertrue,则返回 false
        3. 注:set.[[SetData]] 中元素的数量可能已在 otherRecord.[[Has]] 执行期间增加。
        4. thisSize 设置为 set.[[SetData]] 中元素的数量。
  5. 否则,
    1. keysIterator 为 ? GetIteratorFromMethod(otherRecord.[[SetObject]], otherRecord.[[Keys]])。
    2. nextnot-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. setthis 值。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. otherRecord 为 ? GetSetRecord(other)。
  4. 如果 SetDataSize(set.[[SetData]]) > otherRecord.[[Size]],则返回 false
  5. thisSizeset.[[SetData]] 中元素的数量。
  6. index 为 0。
  7. 重复,只要 index < thisSize
    1. entryset.[[SetData]][index]。
    2. index 设置为 index + 1。
    3. 如果 entry 不是 empty,则
      1. inOtherToBoolean(? Call(otherRecord.[[Has]], otherRecord.[[SetObject]], « entry »))。
      2. 如果 inOtherfalse,则返回 false
      3. 注:set.[[SetData]] 中元素的数量可能已在 otherRecord.[[Has]] 执行期间增加。
      4. thisSize 设置为 set.[[SetData]] 中元素的数量。
  8. 返回 true

24.2.4.12 Set.prototype.isSupersetOf ( other )

此方法在被调用时执行以下步骤:

  1. setthis 值。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. otherRecord 为 ? GetSetRecord(other)。
  4. 如果 SetDataSize(set.[[SetData]]) < otherRecord.[[Size]],则返回 false
  5. keysIterator 为 ? GetIteratorFromMethod(otherRecord.[[SetObject]], otherRecord.[[Keys]])。
  6. nextnot-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" 属性的初始值是 %Set.prototype.values%,定义见 24.2.4.17

Note

出于迭代目的,Set 看起来类似于每个条目的键和值相同的 Map。

24.2.4.14 get Set.prototype.size

Set.prototype.size访问器属性,其 set 访问器函数是 undefined。其 get 访问器函数在被调用时执行以下步骤:

  1. setthis 值。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. sizeSetDataSize(set.[[SetData]])。
  4. 返回 𝔽(size)。

24.2.4.15 Set.prototype.symmetricDifference ( other )

此方法在被调用时执行以下步骤:

  1. setthis 值。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. otherRecord 为 ? GetSetRecord(other)。
  4. keysIterator 为 ? GetIteratorFromMethod(otherRecord.[[SetObject]], otherRecord.[[Keys]])。
  5. resultSetDataset.[[SetData]] 的一个副本。
  6. nextnot-started
  7. 重复,只要 next 不是 done
    1. next 设置为 ? IteratorStepValue(keysIterator)。
    2. 如果 next 不是 done,则
      1. next 设置为 CanonicalizeKeyedCollectionKey(next)。
      2. resultIndexSetDataIndex(resultSetData, next)。
      3. 如果 resultIndexnot-found,则令 alreadyInResultfalse;否则令 alreadyInResulttrue
      4. 如果 SetDataHas(set.[[SetData]], next) 是 true,则
        1. 如果 alreadyInResulttrue,则将 resultSetData[resultIndex] 设置为 empty
      5. 否则,
        1. 如果 alreadyInResultfalse,则将 next 追加到 resultSetData
  8. resultOrdinaryObjectCreate(%Set.prototype%, « [[SetData]] »)。
  9. result.[[SetData]] 设置为 resultSetData
  10. 返回 result

24.2.4.16 Set.prototype.union ( other )

此方法在被调用时执行以下步骤:

  1. setthis 值。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. otherRecord 为 ? GetSetRecord(other)。
  4. keysIterator 为 ? GetIteratorFromMethod(otherRecord.[[SetObject]], otherRecord.[[Keys]])。
  5. resultSetDataset.[[SetData]] 的一个副本。
  6. nextnot-started
  7. 重复,只要 next 不是 done
    1. next 设置为 ? IteratorStepValue(keysIterator)。
    2. 如果 next 不是 done,则
      1. next 设置为 CanonicalizeKeyedCollectionKey(next)。
      2. 如果 SetDataHas(resultSetData, next) 是 false,则
        1. next 追加到 resultSetData
  8. resultOrdinaryObjectCreate(%Set.prototype%, « [[SetData]] »)。
  9. result.[[SetData]] 设置为 resultSetData
  10. 返回 result

24.2.4.17 Set.prototype.values ( )

此方法在被调用时执行以下步骤:

  1. setthis 值。
  2. 返回 ? CreateSetIterator(set, value)。

24.2.4.18 Set.prototype [ %Symbol.iterator% ] ( )

%Symbol.iterator% 属性的初始值是 %Set.prototype.values%,定义见 24.2.4.17

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 Iterator 对象

Set Iterator 是具有下文所定义结构的普通对象,表示对某个特定 Set 实例对象进行特定迭代。Set Iterator 对象没有具名构造器。相反,Set Iterator 对象通过调用 Set 实例对象的某些方法创建。

24.2.6.1 CreateSetIterator ( set, kind )

The abstract operation CreateSetIterator takes arguments set (an ECMAScript language value) and kind (key+value or value) and returns either a normal completion containing a Generator or a throw completion. 它用于为返回此类迭代器的 Set 方法创建迭代器对象。 It performs the following steps when called:

  1. 执行 ? RequireInternalSlot(set, [[SetData]])。
  2. closure 为一个新的无参数 Abstract Closure,它捕获 setkind,并在被调用时执行以下步骤:
    1. index 为 0。
    2. entriesset.[[SetData]]
    3. entriesCountentries 中元素的数量。
    4. 重复,只要 index < entriesCount
      1. entryentries[index]。
      2. index 设置为 index + 1。
      3. 如果 entry 不是 empty,则
        1. 如果 kindkey+value,则
          1. resultCreateArrayFromListentry, entry »)。
          2. 执行 ? GeneratorYield(CreateIteratorResultObject(result, false))。
        2. 否则,
          1. 断言:kindvalue
          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 是键/值对的集合,其中键是对象和/或 symbol,值可以是任意 ECMAScript 语言值。可以查询 WeakMap,以查看它是否包含具有特定键的键/值对,但没有提供枚举它作为键所持有的值的机制。在某些条件下,非活动的值会作为 WeakMap 键被移除,如 9.9.3 中所述。

实现可以在 WeakMap 的某个键/值对变得不可访问的时间与该键/值对从 WeakMap 中移除的时间之间施加任意确定的延迟。如果这种延迟对 ECMAScript 程序可观察,它将成为可能影响程序执行的不确定性来源。因此,ECMAScript 实现不得提供任何手段来观察 WeakMap 的某个键,除非观察者需要提供被观察的键。

WeakMap 必须使用哈希表或其他机制来实现,这些机制平均而言提供的访问时间相对于集合中键/值对数量是次线性的。本规范中使用的数据结构仅用于描述 WeakMap 所要求的可观察语义。它并不旨在作为可行的实现模型。

Note

WeakMap 和 WeakSet 旨在提供一种机制,用于以不会“泄漏”内存资源的方式,将状态动态关联到对象或 symbol;也就是说,如果没有 WeakMap 或 WeakSet 实例,该对象或 symbol 原本会变得不可访问,并受到实现的垃圾回收机制进行资源回收。可以通过使用 WeakMap 或 WeakSet 实例到键的反向每对象/symbol 映射来实现这一特性。或者,每个 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. 如果 iterableundefinednull,则返回 map
  5. adder 为 ? Get(map, "set")。
  6. 如果 IsCallable(adder) 是 false,则抛出 TypeError 异常。
  7. 返回 ? AddEntriesFromIterable(map, iterable, adder)。
Note

如果存在参数 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. weakMapthis 值。
  2. 执行 ? RequireInternalSlot(weakMap, [[WeakMapData]])。
  3. 如果 CanBeHeldWeakly(key) 是 false,则返回 false
  4. weakMap.[[WeakMapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行:
    1. 如果 entry.[[Key]] 不是 emptySameValue(entry.[[Key]], key) 是 true,则
      1. entry.[[Key]] 设置为 empty
      2. entry.[[Value]] 设置为 empty
      3. 返回 true
  5. 返回 false
Note

empty 用作规范装置,用来表示某个条目已被删除。实际实现可以采取其他操作,例如从内部数据结构中物理移除该条目。

24.3.3.3 WeakMap.prototype.get ( key )

此方法在被调用时执行以下步骤:

  1. weakMapthis 值。
  2. 执行 ? RequireInternalSlot(weakMap, [[WeakMapData]])。
  3. 如果 CanBeHeldWeakly(key) 是 false,则返回 undefined
  4. weakMap.[[WeakMapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行:
    1. 如果 entry.[[Key]] 不是 emptySameValue(entry.[[Key]], key) 是 true,则返回 entry.[[Value]]
  5. 返回 undefined

24.3.3.4 WeakMap.prototype.getOrInsert ( key, value )

此方法在被调用时执行以下步骤:

  1. weakMapthis 值。
  2. 执行 ? RequireInternalSlot(weakMap, [[WeakMapData]])。
  3. 如果 CanBeHeldWeakly(key) 是 false,则抛出 TypeError 异常。
  4. weakMap.[[WeakMapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行:
    1. 如果 entry.[[Key]] 不是 emptySameValue(entry.[[Key]], key) 是 true,则返回 entry.[[Value]]
  5. entryRecord { [[Key]]: key, [[Value]]: value }。
  6. entry 追加到 weakMap.[[WeakMapData]]
  7. 返回 value

24.3.3.5 WeakMap.prototype.getOrInsertComputed ( key, callback )

此方法在被调用时执行以下步骤:

  1. weakMapthis 值。
  2. 执行 ? RequireInternalSlot(weakMap, [[WeakMapData]])。
  3. 如果 CanBeHeldWeakly(key) 是 false,则抛出 TypeError 异常。
  4. 如果 IsCallable(callback) 是 false,则抛出 TypeError 异常。
  5. weakMap.[[WeakMapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行:
    1. 如果 entry.[[Key]] 不是 emptySameValue(entry.[[Key]], key) 是 true,则返回 entry.[[Value]]
  6. value 为 ? Call(callback, undefined, « key »)。
  7. 注:WeakMap 可能已在 callback 执行期间被修改。
  8. weakMap.[[WeakMapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行:
    1. 如果 entry.[[Key]] 不是 emptySameValue(entry.[[Key]], key) 是 true,则
      1. entry.[[Value]] 设置为 value
      2. 返回 value
  9. entryRecord { [[Key]]: key, [[Value]]: value }。
  10. entry 追加到 weakMap.[[WeakMapData]]
  11. 返回 value

24.3.3.6 WeakMap.prototype.has ( key )

此方法在被调用时执行以下步骤:

  1. weakMapthis 值。
  2. 执行 ? RequireInternalSlot(weakMap, [[WeakMapData]])。
  3. 如果 CanBeHeldWeakly(key) 是 false,则返回 false
  4. weakMap.[[WeakMapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行:
    1. 如果 entry.[[Key]] 不是 emptySameValue(entry.[[Key]], key) 是 true,则返回 true
  5. 返回 false

24.3.3.7 WeakMap.prototype.set ( key, value )

此方法在被调用时执行以下步骤:

  1. weakMapthis 值。
  2. 执行 ? RequireInternalSlot(weakMap, [[WeakMapData]])。
  3. 如果 CanBeHeldWeakly(key) 是 false,则抛出 TypeError 异常。
  4. weakMap.[[WeakMapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行:
    1. 如果 entry.[[Key]] 不是 emptySameValue(entry.[[Key]], key) 是 true,则
      1. entry.[[Value]] 设置为 value
      2. 返回 weakMap
  5. entryRecord { [[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 是对象和/或 symbol 的集合。一个不同的对象或 symbol 在 WeakSet 的集合中只能作为元素出现一次。可以查询 WeakSet,以查看它是否包含某个特定值,但没有提供枚举它所持有的值的机制。在某些条件下,非活动的值会作为 WeakSet 元素被移除,如 9.9.3 中所述。

实现可以在 WeakSet 中包含的某个值变得不可访问的时间与该值从 WeakSet 中移除的时间之间施加任意确定的延迟。如果这种延迟对 ECMAScript 程序可观察,它将成为可能影响程序执行的不确定性来源。因此,ECMAScript 实现不得提供任何手段来确定 WeakSet 是否包含某个特定值,除非观察者需要提供被观察的值。

WeakSet 必须使用哈希表或其他机制来实现,这些机制平均而言提供的访问时间相对于集合中元素数量是次线性的。本规范中使用的数据结构仅用于描述 WeakSet 所要求的可观察语义。它并不旨在作为可行的实现模型。

Note

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. 如果 iterableundefinednull,则返回 set
  5. adder 为 ? Get(set, "add")。
  6. 如果 IsCallable(adder) 是 false,则抛出 TypeError 异常。
  7. iteratorRecord 为 ? GetIterator(iterable, sync)。
  8. 重复,
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 nextdone,则返回 set
    3. statusCompletion(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. weakSetthis 值。
  2. 执行 ? RequireInternalSlot(weakSet, [[WeakSetData]])。
  3. 如果 CanBeHeldWeakly(value) 是 false,则抛出 TypeError 异常。
  4. weakSet.[[WeakSetData]] 的每个元素 entry,执行:
    1. 如果 entry 不是 emptySameValue(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. weakSetthis 值。
  2. 执行 ? RequireInternalSlot(weakSet, [[WeakSetData]])。
  3. 如果 CanBeHeldWeakly(value) 是 false,则返回 false
  4. weakSet.[[WeakSetData]] 的每个元素 entry,执行:
    1. 如果 entry 不是 emptySameValue(entry, value) 是 true,则
      1. weakSet.[[WeakSetData]] 中值为 entry 的元素替换为值为 empty 的元素。
      2. 返回 true
  5. 返回 false
Note

empty 用作规范装置,用来表示某个条目已被删除。实际实现可以采取其他操作,例如从内部数据结构中物理移除该条目。

24.4.3.4 WeakSet.prototype.has ( value )

此方法在被调用时执行以下步骤:

  1. weakSetthis 值。
  2. 执行 ? RequireInternalSlot(weakSet, [[WeakSetData]])。
  3. 如果 CanBeHeldWeakly(value) 是 false,则返回 false
  4. weakSet.[[WeakSetData]] 的每个元素 entry,执行:
    1. 如果 entry 不是 emptySameValue(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 )

The abstract operation CanonicalizeKeyedCollectionKey takes argument key (an ECMAScript language value) and returns an ECMAScript language value. It performs the following steps when called:

  1. 如果 key-0𝔽,则返回 +0𝔽
  2. 返回 key

25 结构化数据

25.1 ArrayBuffer 对象

25.1.1 表示法

本节、25.429 中的以下描述使用读-改-写修改函数内部数据结构。

读-改-写修改函数是一个数学函数,表示为一个 Abstract Closure,它接受两个字节值 List 作为实参并返回一个字节值 List。这些 Abstract Closure 满足以下所有属性:

  • 它们以原子方式执行其所有算法步骤。
  • 它们的各个算法步骤不可观察。
Note

为帮助验证读-改-写修改函数的算法步骤构成纯粹的数学函数,推荐采用以下编辑约定:

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 ] )

The abstract operation AllocateArrayBuffer takes arguments ctor (a constructor) and byteLength (a non-negative integer) and optional argument maxByteLength (a non-negative integer or empty) and returns either a normal completion containing an ArrayBuffer or a throw completion. 它用于创建 ArrayBuffer。 It performs the following steps when called:

  1. slots 为 « [[ArrayBufferData]], [[ArrayBufferByteLength]], [[ArrayBufferDetachKey]] »。
  2. 如果存在 maxByteLengthmaxByteLength 不是 empty,则令 allocatingResizableBuffertrue;否则令 allocatingResizableBufferfalse
  3. 如果 allocatingResizableBuffertrue,则
    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. 如果 allocatingResizableBuffertrue,则
    1. 如果无法创建由 maxByteLength 个字节组成的 Data Block block,则抛出 RangeError 异常。
    2. 注:可调整大小的 ArrayBuffer 被设计为可用原地增长实现。例如,如果虚拟内存无法预先保留,实现可以抛出异常。
    3. obj.[[ArrayBufferMaxByteLength]] 设置为 maxByteLength
  9. 返回 obj

25.1.3.2 ArrayBufferByteLength ( arrayBuffer, order )

The abstract operation ArrayBufferByteLength takes arguments arrayBuffer (an ArrayBuffer or SharedArrayBuffer) and order (seq-cst or unordered) and returns a non-negative integer. It performs the following steps when called:

  1. 如果 IsGrowableSharedArrayBuffer(arrayBuffer) 是 true,则
    1. bufferByteLengthBlockarrayBuffer.[[ArrayBufferByteLengthData]]
    2. rawLengthGetRawBytesFromSharedBlock(bufferByteLengthBlock, 0, biguint64, true, order)。
    3. agentRecord 为 surrounding agentAgent Record
    4. isLittleEndianagentRecord.[[LittleEndian]]
    5. 返回 (RawBytesToNumeric(biguint64, rawLength, isLittleEndian))。
  2. 断言:IsDetachedBuffer(arrayBuffer) 是 false
  3. 返回 arrayBuffer.[[ArrayBufferByteLength]]

25.1.3.3 ArrayBufferCopyAndDetach ( arrayBuffer, newLength, preserveResizability )

The abstract operation ArrayBufferCopyAndDetach takes arguments arrayBuffer (an ECMAScript language value), newLength (an ECMAScript language value), and preserveResizability (preserve-resizability or fixed-length) and returns either a normal completion containing an ArrayBuffer or a throw completion. It performs the following steps when called:

  1. 执行 ? RequireInternalSlot(arrayBuffer, [[ArrayBufferData]])。
  2. 如果 IsSharedArrayBuffer(arrayBuffer) 是 true,则抛出 TypeError 异常。
  3. 如果 newLengthundefined,则
    1. newByteLengtharrayBuffer.[[ArrayBufferByteLength]]
  4. 否则,
    1. newByteLength 为 ? ToIndex(newLength)。
  5. 如果 IsDetachedBuffer(arrayBuffer) 是 true,则抛出 TypeError 异常。
  6. 如果 preserveResizabilitypreserve-resizabilityIsFixedLengthArrayBuffer(arrayBuffer) 是 false,则
    1. newMaxByteLengtharrayBuffer.[[ArrayBufferMaxByteLength]]
  7. 否则,
    1. newMaxByteLengthempty
  8. 如果 arrayBuffer.[[ArrayBufferDetachKey]] 不是 undefined,则抛出 TypeError 异常。
  9. newBuffer 为 ? AllocateArrayBuffer(%ArrayBuffer%, newByteLength, newMaxByteLength)。
  10. copyLengthmin(newByteLength, arrayBuffer.[[ArrayBufferByteLength]])。
  11. fromBlockarrayBuffer.[[ArrayBufferData]]
  12. toBlocknewBuffer.[[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 )

The abstract operation IsDetachedBuffer takes argument arrayBuffer (an ArrayBuffer or a SharedArrayBuffer) and returns a Boolean. It performs the following steps when called:

  1. 如果 arrayBuffer.[[ArrayBufferData]]null,则返回 true
  2. 返回 false

25.1.3.5 DetachArrayBuffer ( arrayBuffer [ , key ] )

The abstract operation DetachArrayBuffer takes argument arrayBuffer (an ArrayBuffer) and optional argument key (anything) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

  1. 断言:IsSharedArrayBuffer(arrayBuffer) 是 false
  2. 如果 key 不存在,则将 key 设置为 undefined
  3. 如果 arrayBuffer.[[ArrayBufferDetachKey]] 不是 key,则抛出 TypeError 异常。
  4. arrayBuffer.[[ArrayBufferData]] 设置为 null
  5. arrayBuffer.[[ArrayBufferByteLength]] 设置为 0。
  6. 返回 unused
Note

分离 ArrayBuffer 实例会解除用作其后备存储的 Data Block 与该实例的关联,并将缓冲区的字节长度设置为 0。

25.1.3.6 CloneArrayBuffer ( sourceBuffer, sourceByteOffset, sourceLength )

The abstract operation CloneArrayBuffer takes arguments sourceBuffer (an ArrayBuffer or a SharedArrayBuffer), sourceByteOffset (a non-negative integer), and sourceLength (a non-negative integer) and returns either a normal completion containing an ArrayBuffer or a throw completion. 它创建一个新的 ArrayBuffer,其数据是 sourceBuffersourceByteOffset 开始并持续 sourceLength 字节范围内数据的副本。 It performs the following steps when called:

  1. 断言:IsDetachedBuffer(sourceBuffer) 是 false
  2. targetBuffer 为 ? AllocateArrayBuffer(%ArrayBuffer%, sourceLength)。
  3. sourceBlocksourceBuffer.[[ArrayBufferData]]
  4. targetBlocktargetBuffer.[[ArrayBufferData]]
  5. 执行 CopyDataBlockBytes(targetBlock, 0, sourceBlock, sourceByteOffset, sourceLength)。
  6. 返回 targetBuffer

25.1.3.7 GetArrayBufferMaxByteLengthOption ( options )

The abstract operation GetArrayBufferMaxByteLengthOption takes argument options (an ECMAScript language value) and returns either a normal completion containing either a non-negative integer or empty, or a throw completion. It performs the following steps when called:

  1. 如果 options 不是 Object,则返回 empty
  2. maxByteLength 为 ? Get(options, "maxByteLength")。
  3. 如果 maxByteLengthundefined,则返回 empty
  4. 返回 ? ToIndex(maxByteLength)。

25.1.3.8 HostResizeArrayBuffer ( buffer, newByteLength )

The host-defined abstract operation HostResizeArrayBuffer takes arguments buffer (an ArrayBuffer) and newByteLength (a non-negative integer) and returns either a normal completion containing either handled or unhandled, or a throw completion. 它给宿主一个机会,对 buffer 执行实现定义的调整大小操作。如果宿主选择不处理 buffer 的调整大小,则可以返回 unhandled 以采用默认行为。

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

HostResizeArrayBuffer 的默认实现是返回 NormalCompletion(unhandled)。

25.1.3.9 IsFixedLengthArrayBuffer ( arrayBuffer )

The abstract operation IsFixedLengthArrayBuffer takes argument arrayBuffer (an ArrayBuffer or a SharedArrayBuffer) and returns a Boolean. It performs the following steps when called:

  1. 如果 arrayBuffer 具有 [[ArrayBufferMaxByteLength]] 内部槽,则返回 false
  2. 返回 true

25.1.3.10 IsUnsignedElementType ( type )

The abstract operation IsUnsignedElementType takes argument type (a TypedArray element type) and returns a Boolean. 它验证实参 type 是否为无符号 TypedArray 元素类型。 It performs the following steps when called:

  1. 如果 typeuint8uint8clampeduint16uint32biguint64 之一,则返回 true
  2. 返回 false

25.1.3.11 IsUnclampedIntegerElementType ( type )

The abstract operation IsUnclampedIntegerElementType takes argument type (a TypedArray element type) and returns a Boolean. 它验证实参 type 是否为不包含 uint8clampedInteger TypedArray 元素类型。 It performs the following steps when called:

  1. 如果 typeint8uint8int16uint16int32uint32 之一,则返回 true
  2. 返回 false

25.1.3.12 IsBigIntElementType ( type )

The abstract operation IsBigIntElementType takes argument type (a TypedArray element type) and returns a Boolean. 它验证实参 type 是否为 BigInt TypedArray 元素类型。 It performs the following steps when called:

  1. 如果 typebiguint64bigint64,则返回 true
  2. 返回 false

25.1.3.13 IsNoTearConfiguration ( type, order )

The abstract operation IsNoTearConfiguration takes arguments type (a TypedArray element type) and order (seq-cst, unordered, or init) and returns a Boolean. It performs the following steps when called:

  1. 如果 IsUnclampedIntegerElementType(type) 是 true,则返回 true
  2. 如果 IsBigIntElementType(type) 是 trueorder 既不是 init 也不是 unordered,则返回 true
  3. 返回 false

25.1.3.14 RawBytesToNumeric ( type, rawBytes, isLittleEndian )

The abstract operation RawBytesToNumeric takes arguments type (a TypedArray element type), rawBytes (a List of byte values), and isLittleEndian (a Boolean) and returns a Number or a BigInt. It performs the following steps when called:

  1. elementSizeTable 71 中为 Element Type type 指定的 Element Size 值。
  2. 如果 isLittleEndianfalse,则反转 rawBytes 的元素顺序。
  3. 如果 typefloat16,则
    1. valuerawBytes 的字节元素连接后并解释为 IEEE 754-2019 binary16 值的小端位串编码。
    2. 如果 value 是 NaN,则返回 NaN
    3. 返回与 value 对应的 Number 值
  4. 如果 typefloat32,则
    1. valuerawBytes 的字节元素连接后并解释为 IEEE 754-2019 binary32 值的小端位串编码。
    2. 如果 value 是 NaN,则返回 NaN
    3. 返回与 value 对应的 Number 值
  5. 如果 typefloat64,则
    1. valuerawBytes 的字节元素连接后并解释为 IEEE 754-2019 binary64 值的小端位串编码。
    2. 如果 value 是 NaN,则返回 NaN
    3. 返回与 value 对应的 Number 值
  6. 如果 IsUnsignedElementType(type) 是 true,则
    1. intValuerawBytes 的字节元素连接后并解释为无符号小端二进制数的位串编码。
  7. 否则,
    1. intValuerawBytes 的字节元素连接后并解释为位长为 elementSize × 8 的二进制小端二进制补码数的位串编码。
  8. 如果 IsBigIntElementType(type) 是 true,则返回与 intValue 对应的 BigInt 值。
  9. 返回与 intValue 对应的 Number 值

25.1.3.15 GetRawBytesFromSharedBlock ( block, byteIndex, type, isTypedArray, order )

The abstract operation GetRawBytesFromSharedBlock takes arguments block (a Shared Data Block), byteIndex (a non-negative integer), type (a TypedArray element type), isTypedArray (a Boolean), and order (seq-cst or unordered) and returns a List of byte values. It performs the following steps when called:

  1. elementSizeTable 71 中为 Element Type type 指定的 Element Size 值。
  2. agentRecord 为 surrounding agentAgent Record
  3. executionagentRecord.[[CandidateExecution]]
  4. eventsRecordexecution.[[EventsRecords]][[AgentSignifier]]AgentSignifier() 的 Agent Events Record
  5. 如果 isTypedArraytrueIsNoTearConfiguration(type, order) 是 true,则令 noTeartrue;否则令 noTearfalse
  6. rawValue 为长度为 elementSizeList,其元素为非确定性选择的字节值
  7. 注:在实现中,rawValue 是底层硬件上的非原子或原子读取指令的结果。非确定性是内存模型的一项语义规定,用于描述弱一致性硬件的可观察行为。
  8. readEventReadSharedMemory { [[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 ] )

The abstract operation GetValueFromBuffer takes arguments arrayBuffer (an ArrayBuffer or SharedArrayBuffer), byteIndex (a non-negative integer), type (a TypedArray element type), isTypedArray (a Boolean), and order (seq-cst or unordered) and optional argument isLittleEndian (a Boolean) and returns a Number or a BigInt. It performs the following steps when called:

  1. 断言:IsDetachedBuffer(arrayBuffer) 是 false
  2. 断言:arrayBuffer 中从 byteIndex 开始有足够的字节来表示 type 的值。
  3. blockarrayBuffer.[[ArrayBufferData]]
  4. elementSizeTable 71 中为 Element Type type 指定的 Element Size 值。
  5. 如果 IsSharedArrayBuffer(arrayBuffer) 是 true,则
    1. 断言:blockShared Data Block
    2. rawValueGetRawBytesFromSharedBlock(block, byteIndex, type, isTypedArray, order)。
  6. 否则,
    1. rawValue 为一个 List,其元素是 block 中索引在从 byteIndex包含)到 byteIndex + elementSize(不包含)的区间内的字节。
  7. 断言:rawValue 中元素的数量是 elementSize
  8. 如果 isLittleEndian 不存在,则
    1. agentRecord 为 surrounding agentAgent Record
    2. isLittleEndian 设置为 agentRecord.[[LittleEndian]]
  9. 返回 RawBytesToNumeric(type, rawValue, isLittleEndian)。

25.1.3.17 NumericToRawBytes ( type, value, isLittleEndian )

The abstract operation NumericToRawBytes takes arguments type (a TypedArray element type), value (a Number or a BigInt), and isLittleEndian (a Boolean) and returns a List of byte values. It performs the following steps when called:

  1. 如果 typefloat16,则
    1. rawBytes 为一个 List,其元素是使用 roundTiesToEven 模式将 value 转换为 IEEE 754-2019 binary16 格式所得的 2 个字节。这些字节按小端顺序排列。如果 valueNaN,则 rawBytes 可以设置为任意实现所选择的 IEEE 754-2019 binary16 格式 NaN 编码。实现必须始终为每个实现可区分的 NaN 值选择相同的编码。
  2. 否则,如果 typefloat32,则
    1. rawBytes 为一个 List,其元素是使用 roundTiesToEven 模式将 value 转换为 IEEE 754-2019 binary32 格式所得的 4 个字节。这些字节按小端顺序排列。如果 valueNaN,则 rawBytes 可以设置为任意实现所选择的 IEEE 754-2019 binary32 格式 NaN 编码。实现必须始终为每个实现可区分的 NaN 值选择相同的编码。
  3. 否则,如果 typefloat64,则
    1. rawBytes 为一个 List,其元素是 valueIEEE 754-2019 binary64 格式编码的 8 个字节。这些字节按小端顺序排列。如果 valueNaN,则 rawBytes 可以设置为任意实现所选择的 IEEE 754-2019 binary64 格式 NaN 编码。实现必须始终为每个实现可区分的 NaN 值选择相同的编码。
  4. 否则,
    1. nTable 71 中为 Element Type type 指定的 Element Size 值。
    2. conversionOperationTable 71 中 Element Type type 的 “Conversion Operation” 列所命名的抽象操作
    3. intValue(! conversionOperation(value))。
    4. 如果 intValue ≥ 0,则
      1. rawBytes 为一个 List,其元素是 intValuen 字节二进制编码。这些字节按小端顺序排列。
    5. 否则,
      1. rawBytes 为一个 List,其元素是 intValuen 字节二进制补码编码。这些字节按小端顺序排列。
  5. 如果 isLittleEndianfalse,则反转 rawBytes 的元素顺序。
  6. 返回 rawBytes

25.1.3.18 SetValueInBuffer ( arrayBuffer, byteIndex, type, value, isTypedArray, order [ , isLittleEndian ] )

The abstract operation SetValueInBuffer takes arguments arrayBuffer (an ArrayBuffer or SharedArrayBuffer), byteIndex (a non-negative integer), type (a TypedArray element type), value (a Number or a BigInt), isTypedArray (a Boolean), and order (seq-cst, unordered, or init) and optional argument isLittleEndian (a Boolean) and returns unused. It performs the following steps when called:

  1. 断言:IsDetachedBuffer(arrayBuffer) 是 false
  2. 断言:arrayBuffer 中从 byteIndex 开始有足够的字节来表示 type 的值。
  3. 断言:如果 IsBigIntElementType(type) 是 true,则 value 是 BigInt;否则,value 是 Number。
  4. blockarrayBuffer.[[ArrayBufferData]]
  5. elementSizeTable 71 中为 Element Type type 指定的 Element Size 值。
  6. agentRecord 为 surrounding agentAgent Record
  7. 如果 isLittleEndian 不存在,则
    1. isLittleEndian 设置为 agentRecord.[[LittleEndian]]
  8. rawBytesNumericToRawBytes(type, value, isLittleEndian)。
  9. 如果 IsSharedArrayBuffer(arrayBuffer) 是 true,则
    1. executionagentRecord.[[CandidateExecution]]
    2. eventsRecordexecution.[[EventsRecords]][[AgentSignifier]]AgentSignifier() 的 Agent Events Record
    3. 如果 isTypedArraytrueIsNoTearConfiguration(type, order) 是 true,则令 noTeartrue;否则令 noTearfalse
    4. WriteSharedMemory { [[Order]]: order, [[NoTear]]: noTear, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes } 追加到 eventsRecord.[[EventList]]
  10. 否则,
    1. rawBytes 的各个字节存储到 block 中,从 block[byteIndex] 开始。
  11. 返回 unused

25.1.3.19 GetModifySetValueInBuffer ( arrayBuffer, byteIndex, type, value, op )

The abstract operation GetModifySetValueInBuffer takes arguments arrayBuffer (an ArrayBuffer or a SharedArrayBuffer), byteIndex (a non-negative integer), type (a TypedArray element type), value (a Number or a BigInt), and op (a read-modify-write modification function) and returns a Number or a BigInt. It performs the following steps when called:

  1. 断言:IsDetachedBuffer(arrayBuffer) 是 false
  2. 断言:arrayBuffer 中从 byteIndex 开始有足够的字节来表示 type 的值。
  3. 断言:如果 IsBigIntElementType(type) 是 true,则 value 是 BigInt;否则,value 是 Number。
  4. blockarrayBuffer.[[ArrayBufferData]]
  5. elementSizeTable 71 中为 Element Type type 指定的 Element Size 值。
  6. agentRecord 为 surrounding agentAgent Record
  7. isLittleEndianagentRecord.[[LittleEndian]]
  8. rawBytesNumericToRawBytes(type, value, isLittleEndian)。
  9. 如果 IsSharedArrayBuffer(arrayBuffer) 是 true,则
    1. executionagentRecord.[[CandidateExecution]]
    2. eventsRecordexecution.[[EventsRecords]][[AgentSignifier]]AgentSignifier() 的 Agent Events Record
    3. rawBytesRead 为长度为 elementSizeList,其元素为非确定性选择的字节值
    4. 注:在实现中,rawBytesRead 是底层硬件上的 load-link、load-exclusive,或读-改-写指令的一个操作数的结果。非确定性是内存模型的一项语义规定,用于描述弱一致性硬件的可观察行为。
    5. rmwEventReadModifyWriteSharedMemory { [[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 为长度为 elementSizeList,其元素是从 block[byteIndex] 开始的 elementSize 个字节序列。
    2. rawBytesModifiedop(rawBytesRead, rawBytes)。
    3. rawBytesModified 的各个字节存储到 block 中,从 block[byteIndex] 开始。
  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 值。

此函数的 "name" 属性的值是 "get [Symbol.species]"

Note

ArrayBuffer.prototype.slice ( start, end ) 通常使用其 this 值的构造器来创建派生对象。不过,子类构造器可以通过重新定义其 %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. objthis 值。
  2. 执行 ? RequireInternalSlot(obj, [[ArrayBufferData]])。
  3. 如果 IsSharedArrayBuffer(obj) 是 true,则抛出 TypeError 异常。
  4. 如果 IsDetachedBuffer(obj) 是 true,则返回 +0𝔽
  5. lengthobj.[[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. objthis 值。
  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. objthis 值。
  2. 执行 ? RequireInternalSlot(obj, [[ArrayBufferData]])。
  3. 如果 IsSharedArrayBuffer(obj) 是 true,则抛出 TypeError 异常。
  4. 如果 IsDetachedBuffer(obj) 是 true,则返回 +0𝔽
  5. 如果 IsFixedLengthArrayBuffer(obj) 是 true,则
    1. lengthobj.[[ArrayBufferByteLength]]
  6. 否则,
    1. lengthobj.[[ArrayBufferMaxByteLength]]
  7. 返回 𝔽(length)。

25.1.6.5 get ArrayBuffer.prototype.resizable

ArrayBuffer.prototype.resizable访问器属性,其 set 访问器函数是 undefined。其 get 访问器函数在被调用时执行以下步骤:

  1. objthis 值。
  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. objthis 值。
  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. 如果 hostHandledhandled,则返回 undefined
  9. oldBlockobj.[[ArrayBufferData]]
  10. newBlock 为 ? CreateByteDataBlock(newByteLength)。
  11. copyLengthmin(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. objthis 值。
  2. 执行 ? RequireInternalSlot(obj, [[ArrayBufferData]])。
  3. 如果 IsSharedArrayBuffer(obj) 是 true,则抛出 TypeError 异常。
  4. 如果 IsDetachedBuffer(obj) 是 true,则抛出 TypeError 异常。
  5. lengthobj.[[ArrayBufferByteLength]]
  6. relativeStart 为 ? ToIntegerOrInfinity(start)。
  7. 如果 relativeStart = -∞,则令 first 为 0。
  8. 否则,如果 relativeStart < 0,则令 firstmax(length + relativeStart, 0)。
  9. 否则,令 firstmin(relativeStart, length)。
  10. 如果 endundefined,则令 relativeEndlength;否则令 relativeEnd 为 ? ToIntegerOrInfinity(end)。
  11. 如果 relativeEnd = -∞,则令 final 为 0。
  12. 否则,如果 relativeEnd < 0,则令 finalmax(length + relativeEnd, 0)。
  13. 否则,令 finalmin(relativeEnd, length)。
  14. newLengthmax(final - first, 0)。
  15. ctor 为 ? SpeciesConstructor(obj, %ArrayBuffer%)。
  16. new 为 ? Construct(ctor, « 𝔽(newLength) »)。
  17. 执行 ? RequireInternalSlot(new, [[ArrayBufferData]])。
  18. 如果 IsSharedArrayBuffer(new) 是 true,则抛出 TypeError 异常。
  19. 如果 IsDetachedBuffer(new) 是 true,则抛出 TypeError 异常。
  20. 如果 SameValue(new, obj) 是 true,则抛出 TypeError 异常。
  21. 如果 new.[[ArrayBufferByteLength]] < newLength,则抛出 TypeError 异常。
  22. 注:上述步骤的副作用可能已分离或调整 obj 的大小。
  23. 如果 IsDetachedBuffer(obj) 是 true,则抛出 TypeError 异常。
  24. fromBufobj.[[ArrayBufferData]]
  25. toBufnew.[[ArrayBufferData]]
  26. currentLengthobj.[[ArrayBufferByteLength]]
  27. 如果 first < currentLength,则
    1. countmin(newLength, currentLength - first)。
    2. 执行 CopyDataBlockBytes(toBuf, 0, fromBuf, first, count)。
  28. 返回 new

25.1.6.8 ArrayBuffer.prototype.transfer ( [ newLength ] )

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. 返回 ? ArrayBufferCopyAndDetach(obj, newLength, preserve-resizability)。

25.1.6.9 ArrayBuffer.prototype.transferToFixedLength ( [ newLength ] )

此方法在被调用时执行以下步骤:

  1. objthis 值。
  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 调用都将相同的“detach key”作为实参传入,否则将导致 TypeError。此内部槽只会由某些嵌入环境设置,而不会由本规范中的算法设置。

25.1.8 可调整大小 ArrayBuffer 指南

Note 1

以下是面向使用可调整大小 ArrayBuffer 的 ECMAScript 程序员的指南。

我们建议尽可能在程序的部署环境中进行测试。不同硬件设备之间可用物理内存的数量差异很大。同样,虚拟内存子系统在不同硬件设备以及操作系统之间也差异很大。一个在 64 位桌面 Web 浏览器上运行而没有内存不足错误的应用,在 32 位移动 Web 浏览器上可能会耗尽内存。

在为可调整大小 ArrayBuffer 选择 "maxByteLength" 选项的值时,我们建议选择应用所需的尽可能小的大小。我们建议 "maxByteLength" 不超过 1,073,741,824(230 字节或 1GiB)。

请注意,成功构造具有特定最大大小的可调整大小 ArrayBuffer,并不保证未来调整大小会成功。

Note 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 ] )

The abstract operation AllocateSharedArrayBuffer takes arguments ctor (a constructor) and byteLength (a non-negative integer) and optional argument maxByteLength (a non-negative integer or empty) and returns either a normal completion containing a SharedArrayBuffer or a throw completion. 它用于创建 SharedArrayBuffer。 It performs the following steps when called:

  1. slots 为 « [[ArrayBufferData]] »。
  2. 如果存在 maxByteLengthmaxByteLength 不是 empty,则令 allocatingGrowableBuffertrue;否则令 allocatingGrowableBufferfalse
  3. 如果 allocatingGrowableBuffertrue,则
    1. 如果 byteLength > maxByteLength,则抛出 RangeError 异常。
    2. [[ArrayBufferByteLengthData]][[ArrayBufferMaxByteLength]] 追加到 slots
  4. 否则,
    1. [[ArrayBufferByteLength]] 追加到 slots
  5. obj 为 ? OrdinaryCreateFromConstructor(ctor, "%SharedArrayBuffer.prototype%", slots)。
  6. 如果 allocatingGrowableBuffertrue,则令 allocLengthmaxByteLength;否则令 allocLengthbyteLength
  7. block 为 ? CreateSharedByteDataBlock(allocLength)。
  8. obj.[[ArrayBufferData]] 设置为 block
  9. 如果 allocatingGrowableBuffertrue,则
    1. 断言:byteLengthmaxByteLength
    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 )

The abstract operation IsSharedArrayBuffer takes argument obj (an ArrayBuffer or a SharedArrayBuffer) and returns a Boolean. 它测试一个对象是否为 SharedArrayBuffer。 It performs the following steps when called:

  1. 如果 obj.[[ArrayBufferData]]Shared Data Block,则返回 true
  2. 返回 false

25.2.2.3 IsGrowableSharedArrayBuffer ( obj )

The abstract operation IsGrowableSharedArrayBuffer takes argument obj (an ArrayBuffer or a SharedArrayBuffer) and returns a Boolean. 它测试一个对象是否为可增长的 SharedArrayBuffer。 It performs the following steps when called:

  1. 如果 IsSharedArrayBuffer(obj) 是 trueobj 具有 [[ArrayBufferByteLengthData]] 内部槽,则返回 true
  2. 返回 false

25.2.2.4 HostGrowSharedArrayBuffer ( buffer, newByteLength )

The host-defined abstract operation HostGrowSharedArrayBuffer takes arguments buffer (a SharedArrayBuffer) and newByteLength (a non-negative integer) and returns either a normal completion containing either handled or unhandled, or a throw completion. 它给宿主一个机会,对 buffer 执行实现定义的增长操作。如果宿主选择不处理 buffer 的增长,则可以返回 unhandled 以采用默认行为。

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

Note

上面的第二项要求有意对如何或何时读取 buffer 的当前字节长度保持模糊。由于字节长度必须通过底层硬件上的原子读-改-写操作来更新,使用 load-link/store-conditional 或 load-exclusive/store-exclusive 指令对的架构可能希望让成对指令在指令流中保持接近。因此,SharedArrayBuffer.prototype.grow ( newLength ) 本身不会在调用 HostGrowSharedArrayBuffer 之前对 newByteLength 执行边界检查,也不要求何时读取当前字节长度。

这与 HostResizeArrayBuffer 形成对比,后者保证 0 ≤ newByteLengthbuffer.[[ArrayBufferMaxByteLength]]

HostGrowSharedArrayBuffer 的默认实现是返回 NormalCompletion(unhandled)。

25.2.3 SharedArrayBuffer 构造器

SharedArrayBuffer 构造器:

  • %SharedArrayBuffer%
  • 全局对象"SharedArrayBuffer" 属性的初始值,如果该属性存在(见下文)。
  • 在作为构造器调用时创建并初始化一个新的 SharedArrayBuffer。
  • 不意图作为函数调用,并且以这种方式调用时会抛出异常。
  • 可以用作类定义的 extends 子句的值。打算继承指定 SharedArrayBuffer 行为的子类构造函数,必须包含一次对 SharedArrayBuffer 构造函数super 调用,以创建并初始化子类实例,使其具备支持 SharedArrayBuffer.prototype 的内置方法所必需的内部状态。

每当宿主不提供对 SharedArrayBuffer 的并发访问时,它可以省略全局对象"SharedArrayBuffer" 属性。

Note

不同于 ArrayBufferSharedArrayBuffer 不能被分离,其内部 [[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 值。

此函数的 "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. objthis 值。
  2. 执行 ? RequireInternalSlot(obj, [[ArrayBufferData]])。
  3. 如果 IsSharedArrayBuffer(obj) 是 false,则抛出 TypeError 异常。
  4. lengthArrayBufferByteLength(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. objthis 值。
  2. 执行 ? RequireInternalSlot(obj, [[ArrayBufferMaxByteLength]])。
  3. 如果 IsSharedArrayBuffer(obj) 是 false,则抛出 TypeError 异常。
  4. newByteLength 为 ? ToIndex(newLength)。
  5. hostHandled 为 ? HostGrowSharedArrayBuffer(obj, newByteLength)。
  6. 如果 hostHandledhandled,则返回 undefined
  7. agentRecord 为 surrounding agentAgent Record
  8. isLittleEndianagentRecord.[[LittleEndian]]
  9. byteLengthBlockobj.[[ArrayBufferByteLengthData]]
  10. currentByteLengthRawBytesGetRawBytesFromSharedBlock(byteLengthBlock, 0, biguint64, true, seq-cst)。
  11. newByteLengthRawBytesNumericToRawBytes(biguint64, (newByteLength), isLittleEndian)。
  12. 重复,
    1. 注:这是一个 compare-and-exchange 循环,用于确保同一缓冲区的并行竞态增长被完全排序,不会丢失,也不会悄然什么都不做。如果它能够尝试无争用地增长,则循环退出。
    2. currentByteLength(RawBytesToNumeric(biguint64, currentByteLengthRawBytes, isLittleEndian))。
    3. 如果 newByteLength = currentByteLength,则返回 undefined
    4. 如果 newByteLength < currentByteLengthnewByteLength > obj.[[ArrayBufferMaxByteLength]],则抛出 RangeError 异常。
    5. byteLengthDeltanewByteLength - currentByteLength
    6. 如果无法创建由 byteLengthDelta 个字节组成的新 Shared Data Block 值,则抛出 RangeError 异常。
    7. 注:这里不会构造并使用新的 Shared Data Block可增长 SharedArrayBuffer 的可观察行为通过在构造时分配最大大小的 Shared Data Block 来指定,此步骤捕获了运行内存不足的实现必须抛出 RangeError 的要求。
    8. readByteLengthRawBytesAtomicCompareExchangeInSharedBlock(byteLengthBlock, 0, 8, currentByteLengthRawBytes, newByteLengthRawBytes)。
    9. 如果 ByteListEqual(readByteLengthRawBytes, currentByteLengthRawBytes) 是 true,则返回 undefined
    10. currentByteLengthRawBytes 设置为 readByteLengthRawBytes
Note

禁止 compare-exchange 更新长度时出现伪失败。如果新长度的边界检查通过且实现未内存不足,则总会向 candidate execution 添加一个 ReadModifyWriteSharedMemory 事件(即一次成功的 compare-exchange)。

对 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. objthis 值。
  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. objthis 值。
  2. 执行 ? RequireInternalSlot(obj, [[ArrayBufferData]])。
  3. 如果 IsSharedArrayBuffer(obj) 是 false,则抛出 TypeError 异常。
  4. 如果 IsFixedLengthArrayBuffer(obj) 是 true,则
    1. lengthobj.[[ArrayBufferByteLength]]
  5. 否则,
    1. lengthobj.[[ArrayBufferMaxByteLength]]
  6. 返回 𝔽(length)。

25.2.5.6 SharedArrayBuffer.prototype.slice ( start, end )

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. 执行 ? RequireInternalSlot(obj, [[ArrayBufferData]])。
  3. 如果 IsSharedArrayBuffer(obj) 是 false,则抛出 TypeError 异常。
  4. lengthArrayBufferByteLength(obj, seq-cst)。
  5. relativeStart 为 ? ToIntegerOrInfinity(start)。
  6. 如果 relativeStart = -∞,则令 first 为 0。
  7. 否则,如果 relativeStart < 0,则令 firstmax(length + relativeStart, 0)。
  8. 否则,令 firstmin(relativeStart, length)。
  9. 如果 endundefined,则令 relativeEndlength;否则令 relativeEnd 为 ? ToIntegerOrInfinity(end)。
  10. 如果 relativeEnd = -∞,则令 final 为 0。
  11. 否则,如果 relativeEnd < 0,则令 finalmax(length + relativeEnd, 0)。
  12. 否则,令 finalmin(relativeEnd, length)。
  13. newLengthmax(final - first, 0)。
  14. ctor 为 ? SpeciesConstructor(obj, %SharedArrayBuffer%)。
  15. new 为 ? Construct(ctor, « 𝔽(newLength) »)。
  16. 执行 ? RequireInternalSlot(new, [[ArrayBufferData]])。
  17. 如果 IsSharedArrayBuffer(new) 是 false,则抛出 TypeError 异常。
  18. 如果 new.[[ArrayBufferData]]obj.[[ArrayBufferData]],则抛出 TypeError 异常。
  19. 如果 ArrayBufferByteLength(new, seq-cst) < newLength,则抛出 TypeError 异常。
  20. fromBufobj.[[ArrayBufferData]]
  21. toBufnew.[[ArrayBufferData]]
  22. 执行 CopyDataBlockBytes(toBuf, 0, fromBuf, first, newLength)。
  23. 返回 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]] 内部槽。

Note

SharedArrayBuffer 实例不同于 ArrayBuffer 实例,它们永远不会被分离。

25.2.7 可增长 SharedArrayBuffer 指南

Note 1

以下是面向使用可增长 SharedArrayBuffer 的 ECMAScript 程序员的指南。

我们建议尽可能在程序的部署环境中进行测试。不同硬件设备之间可用物理内存的数量差异很大。同样,虚拟内存子系统在不同硬件设备以及操作系统之间也差异很大。一个在 64 位桌面 Web 浏览器上运行而没有内存不足错误的应用,在 32 位移动 Web 浏览器上可能会耗尽内存。

在为可增长 SharedArrayBuffer 选择 "maxByteLength" 选项的值时,我们建议选择应用所需的尽可能小的大小。我们建议 "maxByteLength" 不超过 1073741824,即 1GiB。

请注意,成功构造具有特定最大大小的可增长 SharedArrayBuffer,并不保证未来增长会成功。

并非所有对可增长 SharedArrayBuffer 长度的加载都是同步性的 seq-cst 加载。用于整数索引属性访问(例如 u8[idx])边界检查的长度加载不是同步性的。通常,在没有显式同步的情况下,一个属性访问在边界内并不意味着同一 agent 中后续属性访问也在边界内。相比之下,通过 SharedArrayBuffer、%TypedArray%.prototype 和 DataView.prototype 上的 lengthbyteLength getter 对长度进行的显式加载是同步性的。由内置方法为检查 TypedArray 是否整体越界而执行的长度加载也是同步性的。

Note 2

以下是面向实现可增长 SharedArrayBuffer 的 ECMAScript 实现者的指南。

我们建议将可增长 SharedArrayBuffer 实现为通过预先保留虚拟内存进行原地增长。

由于增长操作可以与可增长 SharedArrayBuffer 上的内存访问并行发生,内存模型的约束要求即使无序访问也不会“撕裂”(其值的位不会混合)。实践中,这意味着可增长 SharedArrayBuffer 的底层数据块不能通过复制来增长,除非停止整个世界。我们不建议将停止整个世界作为实现策略,因为它会引入一个序列化点并且很慢。

增长后的内存必须从其创建的那一刻起表现为零填充,包括对于并行的任何竞态访问也是如此。这可以通过按需零填充的虚拟内存页实现,或者在手动清零内存时通过谨慎同步来实现。

可增长 SharedArrayBufferTypedArray 视图进行整数索引属性访问,意图可类似于对不可增长 SharedArrayBufferTypedArray 视图的访问一样进行优化,因为整数索引属性加载并不同步底层缓冲区的长度(见上面的程序员指南)。例如,属性访问的边界检查仍然可以被提升到循环之外。

实践中,在没有虚拟内存的宿主(例如运行在没有 MMU 的嵌入式设备)上,很难通过复制实现可增长 SharedArrayBuffer。这类宿主可增长 SharedArrayBuffer 的内存使用行为可能与具有虚拟内存的宿主有显著差异。这类宿主应向用户清楚传达内存使用预期。

25.3 DataView 对象

25.3.1 DataView 对象的抽象操作

25.3.1.1 DataView With Buffer Witness Record

DataView With Buffer Witness Record 是一种 Record 值,用于封装 DataView 以及被查看缓冲区的缓存字节长度。当被查看缓冲区是可增长 SharedArrayBuffer 时,它用于帮助确保字节长度数据块只有单个 ReadSharedMemory 事件。

DataView With Buffer Witness Record 具有 Table 73 中列出的字段。

Table 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 )

The abstract operation MakeDataViewWithBufferWitnessRecord takes arguments obj (a DataView) and order (seq-cst or unordered) and returns a DataView With Buffer Witness Record. It performs the following steps when called:

  1. bufferobj.[[ViewedArrayBuffer]]
  2. 如果 IsDetachedBuffer(buffer) 是 true,则
    1. byteLengthdetached
  3. 否则,
    1. byteLengthArrayBufferByteLength(buffer, order)。
  4. 返回 DataView With Buffer Witness Record { [[Object]]: obj, [[CachedBufferByteLength]]: byteLength }。

25.3.1.3 GetViewByteLength ( viewRecord )

The abstract operation GetViewByteLength takes argument viewRecord (a DataView With Buffer Witness Record) and returns a non-negative integer. It performs the following steps when called:

  1. 断言:IsViewOutOfBounds(viewRecord) 是 false
  2. viewviewRecord.[[Object]]
  3. 如果 view.[[ByteLength]] 不是 auto,则返回 view.[[ByteLength]]
  4. 断言:IsFixedLengthArrayBuffer(view.[[ViewedArrayBuffer]]) 是 false
  5. byteOffsetview.[[ByteOffset]]
  6. byteLengthviewRecord.[[CachedBufferByteLength]]
  7. 断言:byteLength 不是 detached
  8. 返回 byteLength - byteOffset

25.3.1.4 IsViewOutOfBounds ( viewRecord )

The abstract operation IsViewOutOfBounds takes argument viewRecord (a DataView With Buffer Witness Record) and returns a Boolean. It performs the following steps when called:

  1. viewviewRecord.[[Object]]
  2. bufferByteLengthviewRecord.[[CachedBufferByteLength]]
  3. 如果 IsDetachedBuffer(view.[[ViewedArrayBuffer]]) 是 true,则
    1. 断言:bufferByteLengthdetached
    2. 返回 true
  4. 断言:bufferByteLength 是非负整数。
  5. byteOffsetStartview.[[ByteOffset]]
  6. 如果 view.[[ByteLength]]auto,则
    1. byteOffsetEndbufferByteLength
  7. 否则,
    1. byteOffsetEndbyteOffsetStart + view.[[ByteLength]]
  8. 注:[[ByteOffset]]bufferByteLength 的 0 长度 DataView 不被视为越界。
  9. 如果 byteOffsetStart > bufferByteLengthbyteOffsetEnd > bufferByteLength,则返回 true
  10. 返回 false

25.3.1.5 GetViewValue ( view, requestIndex, isLittleEndian, type )

The abstract operation GetViewValue takes arguments view (an ECMAScript language value), requestIndex (an ECMAScript language value), isLittleEndian (an ECMAScript language value), and type (a TypedArray element type) and returns either a normal completion containing either a Number or a BigInt, or a throw completion. 它由 DataView 实例上的函数用于从视图的缓冲区中检索值。 It performs the following steps when called:

  1. 执行 ? RequireInternalSlot(view, [[DataView]])。
  2. 断言:view 具有 [[ViewedArrayBuffer]] 内部槽。
  3. getIndex 为 ? ToIndex(requestIndex)。
  4. isLittleEndian 设置为 ToBoolean(isLittleEndian)。
  5. viewOffsetview.[[ByteOffset]]
  6. viewRecordMakeDataViewWithBufferWitnessRecord(view, unordered)。
  7. 注:当 view 的后备缓冲区是可增长 SharedArrayBuffer 时,边界检查不是同步操作。
  8. 如果 IsViewOutOfBounds(viewRecord) 是 true,则抛出 TypeError 异常。
  9. viewSizeGetViewByteLength(viewRecord)。
  10. elementSizeTable 71 中为 Element Type type 指定的 Element Size 值。
  11. 如果 getIndex + elementSize > viewSize,则抛出 RangeError 异常。
  12. bufferIndexgetIndex + viewOffset
  13. 返回 GetValueFromBuffer(view.[[ViewedArrayBuffer]], bufferIndex, type, false, unordered, isLittleEndian)。

25.3.1.6 SetViewValue ( view, requestIndex, isLittleEndian, type, value )

The abstract operation SetViewValue takes arguments view (an ECMAScript language value), requestIndex (an ECMAScript language value), isLittleEndian (an ECMAScript language value), type (a TypedArray element type), and value (an ECMAScript language value) and returns either a normal completion containing undefined or a throw completion. 它由 DataView 实例上的函数用于将值存储到视图的缓冲区中。 It performs the following steps when called:

  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. viewOffsetview.[[ByteOffset]]
  8. viewRecordMakeDataViewWithBufferWitnessRecord(view, unordered)。
  9. 注:当 view 的后备缓冲区是可增长 SharedArrayBuffer 时,边界检查不是同步操作。
  10. 如果 IsViewOutOfBounds(viewRecord) 是 true,则抛出 TypeError 异常。
  11. viewSizeGetViewByteLength(viewRecord)。
  12. elementSizeTable 71 中为 Element Type type 指定的 Element Size 值。
  13. 如果 getIndex + elementSize > viewSize,则抛出 RangeError 异常。
  14. bufferIndexgetIndex + viewOffset
  15. 执行 SetValueInBuffer(view.[[ViewedArrayBuffer]], bufferIndex, type, number, false, unordered, isLittleEndian)。
  16. 返回 undefined

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. bufferByteLengthArrayBufferByteLength(buffer, seq-cst)。
  6. 如果 offset > bufferByteLength,则抛出 RangeError 异常。
  7. bufferIsFixedLengthIsFixedLengthArrayBuffer(buffer)。
  8. 如果 byteLengthundefined,则
    1. 如果 bufferIsFixedLengthtrue,则
      1. viewByteLengthbufferByteLength - offset
    2. 否则,
      1. viewByteLengthauto
  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. objthis 值。
  2. 执行 ? RequireInternalSlot(obj, [[DataView]])。
  3. 断言:obj 具有 [[ViewedArrayBuffer]] 内部槽。
  4. bufferobj.[[ViewedArrayBuffer]]
  5. 返回 buffer

25.3.4.2 get DataView.prototype.byteLength

DataView.prototype.byteLength访问器属性,其 set 访问器函数是 undefined。其 get 访问器函数在被调用时执行以下步骤:

  1. objthis 值。
  2. 执行 ? RequireInternalSlot(obj, [[DataView]])。
  3. 断言:obj 具有 [[ViewedArrayBuffer]] 内部槽。
  4. viewRecordMakeDataViewWithBufferWitnessRecord(obj, seq-cst)。
  5. 如果 IsViewOutOfBounds(viewRecord) 是 true,则抛出 TypeError 异常。
  6. sizeGetViewByteLength(viewRecord)。
  7. 返回 𝔽(size)。

25.3.4.3 get DataView.prototype.byteOffset

DataView.prototype.byteOffset访问器属性,其 set 访问器函数是 undefined。其 get 访问器函数在被调用时执行以下步骤:

  1. objthis 值。
  2. 执行 ? RequireInternalSlot(obj, [[DataView]])。
  3. 断言:obj 具有 [[ViewedArrayBuffer]] 内部槽。
  4. viewRecordMakeDataViewWithBufferWitnessRecord(obj, seq-cst)。
  5. 如果 IsViewOutOfBounds(viewRecord) 是 true,则抛出 TypeError 异常。
  6. offsetobj.[[ByteOffset]]
  7. 返回 𝔽(offset)。

25.3.4.4 DataView.prototype.constructor

DataView.prototype.constructor 的初始值是 %DataView%

25.3.4.5 DataView.prototype.getBigInt64 ( byteOffset [ , littleEndian ] )

此方法在被调用时执行以下步骤:

  1. viewthis 值。
  2. 返回 ? GetViewValue(view, byteOffset, littleEndian, bigint64)。

25.3.4.6 DataView.prototype.getBigUint64 ( byteOffset [ , littleEndian ] )

此方法在被调用时执行以下步骤:

  1. viewthis 值。
  2. 返回 ? GetViewValue(view, byteOffset, littleEndian, biguint64)。

25.3.4.7 DataView.prototype.getFloat16 ( byteOffset [ , littleEndian ] )

此方法在被调用时执行以下步骤:

  1. viewthis 值。
  2. 如果 littleEndian 不存在,则将 littleEndian 设置为 false
  3. 返回 ? GetViewValue(view, byteOffset, littleEndian, float16)。

25.3.4.8 DataView.prototype.getFloat32 ( byteOffset [ , littleEndian ] )

此方法在被调用时执行以下步骤:

  1. viewthis 值。
  2. 如果 littleEndian 不存在,则将 littleEndian 设置为 false
  3. 返回 ? GetViewValue(view, byteOffset, littleEndian, float32)。

25.3.4.9 DataView.prototype.getFloat64 ( byteOffset [ , littleEndian ] )

此方法在被调用时执行以下步骤:

  1. viewthis 值。
  2. 如果 littleEndian 不存在,则将 littleEndian 设置为 false
  3. 返回 ? GetViewValue(view, byteOffset, littleEndian, float64)。

25.3.4.10 DataView.prototype.getInt8 ( byteOffset )

此方法在被调用时执行以下步骤:

  1. viewthis 值。
  2. 返回 ? GetViewValue(view, byteOffset, true, int8)。

25.3.4.11 DataView.prototype.getInt16 ( byteOffset [ , littleEndian ] )

此方法在被调用时执行以下步骤:

  1. viewthis 值。
  2. 如果 littleEndian 不存在,则将 littleEndian 设置为 false
  3. 返回 ? GetViewValue(view, byteOffset, littleEndian, int16)。

25.3.4.12 DataView.prototype.getInt32 ( byteOffset [ , littleEndian ] )

此方法在被调用时执行以下步骤:

  1. viewthis 值。
  2. 如果 littleEndian 不存在,则将 littleEndian 设置为 false
  3. 返回 ? GetViewValue(view, byteOffset, littleEndian, int32)。

25.3.4.13 DataView.prototype.getUint8 ( byteOffset )

此方法在被调用时执行以下步骤:

  1. viewthis 值。
  2. 返回 ? GetViewValue(view, byteOffset, true, uint8)。

25.3.4.14 DataView.prototype.getUint16 ( byteOffset [ , littleEndian ] )

此方法在被调用时执行以下步骤:

  1. viewthis 值。
  2. 如果 littleEndian 不存在,则将 littleEndian 设置为 false
  3. 返回 ? GetViewValue(view, byteOffset, littleEndian, uint16)。

25.3.4.15 DataView.prototype.getUint32 ( byteOffset [ , littleEndian ] )

此方法在被调用时执行以下步骤:

  1. viewthis 值。
  2. 如果 littleEndian 不存在,则将 littleEndian 设置为 false
  3. 返回 ? GetViewValue(view, byteOffset, littleEndian, uint32)。

25.3.4.16 DataView.prototype.setBigInt64 ( byteOffset, value [ , littleEndian ] )

此方法在被调用时执行以下步骤:

  1. viewthis 值。
  2. 返回 ? SetViewValue(view, byteOffset, littleEndian, bigint64, value)。

25.3.4.17 DataView.prototype.setBigUint64 ( byteOffset, value [ , littleEndian ] )

此方法在被调用时执行以下步骤:

  1. viewthis 值。
  2. 返回 ? SetViewValue(view, byteOffset, littleEndian, biguint64, value)。

25.3.4.18 DataView.prototype.setFloat16 ( byteOffset, value [ , littleEndian ] )

此方法在被调用时执行以下步骤:

  1. viewthis 值。
  2. 如果 littleEndian 不存在,则将 littleEndian 设置为 false
  3. 返回 ? SetViewValue(view, byteOffset, littleEndian, float16, value)。

25.3.4.19 DataView.prototype.setFloat32 ( byteOffset, value [ , littleEndian ] )

此方法在被调用时执行以下步骤:

  1. viewthis 值。
  2. 如果 littleEndian 不存在,则将 littleEndian 设置为 false
  3. 返回 ? SetViewValue(view, byteOffset, littleEndian, float32, value)。

25.3.4.20 DataView.prototype.setFloat64 ( byteOffset, value [ , littleEndian ] )

此方法在被调用时执行以下步骤:

  1. viewthis 值。
  2. 如果 littleEndian 不存在,则将 littleEndian 设置为 false
  3. 返回 ? SetViewValue(view, byteOffset, littleEndian, float64, value)。

25.3.4.21 DataView.prototype.setInt8 ( byteOffset, value )

此方法在被调用时执行以下步骤:

  1. viewthis 值。
  2. 返回 ? SetViewValue(view, byteOffset, true, int8, value)。

25.3.4.22 DataView.prototype.setInt16 ( byteOffset, value [ , littleEndian ] )

此方法在被调用时执行以下步骤:

  1. viewthis 值。
  2. 如果 littleEndian 不存在,则将 littleEndian 设置为 false
  3. 返回 ? SetViewValue(view, byteOffset, littleEndian, int16, value)。

25.3.4.23 DataView.prototype.setInt32 ( byteOffset, value [ , littleEndian ] )

此方法在被调用时执行以下步骤:

  1. viewthis 值。
  2. 如果 littleEndian 不存在,则将 littleEndian 设置为 false
  3. 返回 ? SetViewValue(view, byteOffset, littleEndian, int32, value)。

25.3.4.24 DataView.prototype.setUint8 ( byteOffset, value )

此方法在被调用时执行以下步骤:

  1. viewthis 值。
  2. 返回 ? SetViewValue(view, byteOffset, true, uint8, value)。

25.3.4.25 DataView.prototype.setUint16 ( byteOffset, value [ , littleEndian ] )

此方法在被调用时执行以下步骤:

  1. viewthis 值。
  2. 如果 littleEndian 不存在,则将 littleEndian 设置为 false
  3. 返回 ? SetViewValue(view, byteOffset, littleEndian, uint16, value)。

25.3.4.26 DataView.prototype.setUint32 ( byteOffset, value [ , littleEndian ] )

此方法在被调用时执行以下步骤:

  1. viewthis 值。
  2. 如果 littleEndian 不存在,则将 littleEndian 设置为 false
  3. 返回 ? SetViewValue(view, byteOffset, littleEndian, uint32, value)。

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]] 内部槽。

Note

[[DataView]] 内部槽的值在本规范中不被使用。该内部槽的单纯存在用于在规范中识别使用 DataView 构造器创建的对象。

25.4 Atomics 对象

Atomics 对象:

  • %Atomics%
  • 全局对象"Atomics" 属性的初始值。
  • 普通对象
  • 具有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%
  • 没有 [[Construct]] 内部方法;它不能作为构造器与 new 操作符一起使用。
  • 没有 [[Call]] 内部方法;它不能作为函数调用。

Atomics 对象提供在共享内存数组单元上不可分割地(原子地)操作的函数,以及让 agent 等待并派发原始事件的函数。当以有纪律的方式使用时,Atomics 函数允许通过共享内存通信的多 agent 程序,即使在并行 CPU 上也能以良好理解的顺序执行。管理共享内存通信的规则由下文定义的内存模型提供。

Note

有关在 ECMAScript 中编程和实现共享内存的信息性指南,请参阅内存模型章节末尾的注。

25.4.1 Waiter Record

Waiter Record 是一种 Record 值,用于表示对 Atomics.waitAtomics.waitAsync 的某次特定调用。

Waiter Record 具有 Table 74 中列出的字段。

Table 74: Waiter Record 字段
字段名 含义
[[AgentSignifier]] an agent signifier 调用了 Atomics.waitAtomics.waitAsyncagent
[[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.waitAtomics.waitAsyncAtomics.notifyagent 的等待和通知。

WaiterList Record 具有 Table 75 中列出的字段。

Table 75: WaiterList Record 字段
字段名 含义
[[Waiters]] a List of Waiter Records 在与此 WaiterList 关联的位置上等待的 Atomics.waitAtomics.waitAsync 调用。
[[MostRecentLeaveEvent]] a Synchronize event or empty 最近一次离开其临界区的事件,或者如果其临界区从未进入过,则为 empty

WaiterList 中可以有多个具有相同 agent signifierWaiter Record

agent cluster 具有一个 WaiterList Record 存储;该存储由 (block, i) 索引,其中 blockShared Data Blockiblock 内存中的字节偏移量。WaiterList Record 与 agent 无关:在 agent cluster 中的任何 agent 内,用 (block, i) 在 WaiterList Record 存储中查找,都会得到同一个 WaiterList Record。

每个 WaiterList Record 都有一个临界区,用于在求值期间控制对该 WaiterList Record 的独占访问。同一时间只能有一个 agent 进入 WaiterList Record 的临界区。进入和离开 WaiterList Record 的临界区由抽象操作 EnterCriticalSectionLeaveCriticalSection 控制。对 WaiterList Record 的操作——添加和移除等待中的 agent、遍历 agent 列表、挂起和通知列表上的 agent、设置和检索 Synchronize 事件——只能由已进入该 WaiterList Record 临界区的 agent 执行。

25.4.3 Atomics 的抽象操作

25.4.3.1 ValidateIntegerTypedArray ( ta, waitable )

The abstract operation ValidateIntegerTypedArray takes arguments ta (an ECMAScript language value) and waitable (a Boolean) and returns either a normal completion containing a TypedArray With Buffer Witness Record, or a throw completion. It performs the following steps when called:

  1. taRecord 为 ? ValidateTypedArray(ta, unordered)。
  2. 注:当 ta 的后备缓冲区是可增长 SharedArrayBuffer 时,边界检查不是同步操作。
  3. 如果 waitabletrue,则
    1. 如果 ta.[[TypedArrayName]] 既不是 "Int32Array" 也不是 "BigInt64Array",则抛出 TypeError 异常。
  4. 否则,
    1. typeTypedArrayElementType(ta)。
    2. 如果 IsUnclampedIntegerElementType(type) 是 falseIsBigIntElementType(type) 是 false,则抛出 TypeError 异常。
  5. 返回 taRecord

25.4.3.2 ValidateAtomicAccess ( taRecord, requestIndex )

The abstract operation ValidateAtomicAccess takes arguments taRecord (a TypedArray With Buffer Witness Record) and requestIndex (an ECMAScript language value) and returns either a normal completion containing a non-negative integer or a throw completion. It performs the following steps when called:

  1. lengthTypedArrayLength(taRecord)。
  2. accessIndex 为 ? ToIndex(requestIndex)。
  3. 断言:accessIndex ≥ 0。
  4. 如果 accessIndexlength,则抛出 RangeError 异常。
  5. tataRecord.[[Object]]
  6. elementSizeTypedArrayElementSize(ta)。
  7. offsetta.[[ByteOffset]]
  8. 返回 (accessIndex × elementSize) + offset

25.4.3.3 ValidateAtomicAccessOnIntegerTypedArray ( ta, requestIndex )

The abstract operation ValidateAtomicAccessOnIntegerTypedArray takes arguments ta (an ECMAScript language value) and requestIndex (an ECMAScript language value) and returns either a normal completion containing a non-negative integer or a throw completion. It performs the following steps when called:

  1. taRecord 为 ? ValidateIntegerTypedArray(ta, false)。
  2. 返回 ? ValidateAtomicAccess(taRecord, requestIndex)。

25.4.3.4 RevalidateAtomicAccess ( ta, byteIndexInBuffer )

The abstract operation RevalidateAtomicAccess takes arguments ta (a TypedArray) and byteIndexInBuffer (a non-negative integer) and returns either a normal completion containing unused or a throw completion. 此操作在 Atomics 方法中所有实参强制转换执行之后,重新验证原子操作在后备缓冲区中的索引,因为实参强制转换可能具有任意副作用,可能导致缓冲区越界。当 ta 的后备缓冲区是 SharedArrayBuffer 时,此操作不会抛出异常。 It performs the following steps when called:

  1. taRecordMakeTypedArrayWithBufferWitnessRecord(ta, unordered)。
  2. 注:当 ta 的后备缓冲区是可增长 SharedArrayBuffer 时,边界检查不是同步操作。
  3. 如果 IsTypedArrayOutOfBounds(taRecord) 是 true,则抛出 TypeError 异常。
  4. 断言:byteIndexInBufferta.[[ByteOffset]]
  5. 如果 byteIndexInBuffertaRecord.[[CachedBufferByteLength]],则抛出 RangeError 异常。
  6. 返回 unused

25.4.3.5 GetWaiterList ( block, i )

The abstract operation GetWaiterList takes arguments block (a Shared Data Block) and i (a non-negative integer that is evenly divisible by 4) and returns a WaiterList Record. It performs the following steps when called:

  1. 断言:ii + 3 是 block 内存内的有效字节偏移量。
  2. 返回由对 (block, i) 引用的 WaiterList Record

25.4.3.6 EnterCriticalSection ( waiterList )

The abstract operation EnterCriticalSection takes argument waiterList (a WaiterList Record) and returns unused. It performs the following steps when called:

  1. 断言:surrounding agent 不在任何 WaiterList Record临界区中。
  2. 等待直到没有 agent 位于 waiterList临界区中,然后进入 waiterList临界区(不允许任何其他 agent 进入)。
  3. 如果 waiterList.[[MostRecentLeaveEvent]] 不是 empty,则
    1. 注:至少进入过一次临界区waiterList 具有由 LeaveCriticalSection 设置的 Synchronize 事件。
    2. agentRecord 为 surrounding agentAgent Record
    3. executionagentRecord.[[CandidateExecution]]
    4. eventsRecordexecution.[[EventsRecords]][[AgentSignifier]]AgentSignifier() 的 Agent Events Record
    5. enterEvent 为新的 Synchronize 事件。
    6. enterEvent 追加到 eventsRecord.[[EventList]]
    7. 将 (waiterList.[[MostRecentLeaveEvent]], enterEvent) 追加到 eventsRecord.[[AgentSynchronizesWith]]
  4. 返回 unused

当试图进入临界区agent 必须等待另一个 agent 离开时,EnterCriticalSection 存在争用。当没有争用时,EnterCriticalSection 调用的 FIFO 顺序是可观察的。当存在争用时,实现可以选择任意顺序,但不得导致某个 agent 无限期等待。

25.4.3.7 LeaveCriticalSection ( waiterList )

The abstract operation LeaveCriticalSection takes argument waiterList (a WaiterList Record) and returns unused. It performs the following steps when called:

  1. 断言:surrounding agent 位于 waiterList临界区中。
  2. agentRecord 为 surrounding agentAgent Record
  3. executionagentRecord.[[CandidateExecution]]
  4. eventsRecordexecution.[[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 )

The abstract operation AddWaiter takes arguments waiterList (a WaiterList Record) and waiterRecord (a Waiter Record) and returns unused. It performs the following steps when called:

  1. 断言:surrounding agent 位于 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 )

The abstract operation RemoveWaiter takes arguments waiterList (a WaiterList Record) and waiterRecord (a Waiter Record) and returns unused. It performs the following steps when called:

  1. 断言:surrounding agent 位于 waiterList临界区中。
  2. 断言:waiterList.[[Waiters]] 包含 waiterRecord
  3. waiterList.[[Waiters]] 中移除 waiterRecord
  4. 返回 unused

25.4.3.10 RemoveWaiters ( waiterList, count )

The abstract operation RemoveWaiters takes arguments waiterList (a WaiterList Record) and count (a non-negative integer or +∞) and returns a List of Waiter Records. It performs the following steps when called:

  1. 断言:surrounding agent 位于 waiterList临界区中。
  2. lengthwaiterList.[[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 )

The abstract operation SuspendThisAgent takes arguments waiterList (a WaiterList Record) and waiterRecord (a Waiter Record) and returns unused. It performs the following steps when called:

  1. 断言:surrounding agent 位于 waiterList临界区中。
  2. 断言:waiterList.[[Waiters]] 包含 waiterRecord
  3. thisAgentAgentSignifier()。
  4. 断言:waiterRecord.[[AgentSignifier]]thisAgent
  5. 断言:waiterRecord.[[PromiseCapability]]blocking
  6. 断言:AgentCanSuspend() 是 true
  7. 执行 LeaveCriticalSection(waiterList) 并挂起 surrounding agent,直到时间为 waiterRecord.[[TimeoutTime]],以一种组合操作的方式执行,使得在退出临界区之后但在挂起生效之前到达的通知不会丢失。surrounding agent 只能因超时或因另一个 agentwaiterListthisAgent 为实参调用 NotifyWaiter(即通过调用 Atomics.notify)而从挂起中唤醒。
  8. 执行 EnterCriticalSection(waiterList)。
  9. 返回 unused

25.4.3.12 NotifyWaiter ( waiterList, waiterRecord )

The abstract operation NotifyWaiter takes arguments waiterList (a WaiterList Record) and waiterRecord (a Waiter Record) and returns unused. It performs the following steps when called:

  1. 断言:surrounding agent 位于 waiterList临界区中。
  2. 如果 waiterRecord.[[PromiseCapability]]blocking,则
    1. 将 signifier 为 waiterRecord.[[AgentSignifier]]agent 从挂起中唤醒。
    2. 注:这会使 agentSuspendThisAgent 中恢复执行。
  3. 否则,如果 AgentSignifier() 是 waiterRecord.[[AgentSignifier]],则
    1. promiseCapabilitywaiterRecord.[[PromiseCapability]]
    2. 执行 ! Call(promiseCapability.[[Resolve]], undefined, « waiterRecord.[[Result]] »)。
  4. 否则,
    1. 执行 EnqueueResolveInAgentJob(waiterRecord.[[AgentSignifier]], waiterRecord.[[PromiseCapability]], waiterRecord.[[Result]])。
  5. 返回 unused
Note

agent 不得以任何能力访问另一个 agent 的 promise capability,除非是将其传递给宿主

25.4.3.13 EnqueueResolveInAgentJob ( agentSignifier, promiseCapability, resolution )

The abstract operation EnqueueResolveInAgentJob takes arguments agentSignifier (an agent signifier), promiseCapability (a PromiseCapability Record), and resolution ("ok" or "timed-out") and returns unused. It performs the following steps when called:

  1. resolveJob 为一个新的无参数 Job Abstract Closure,它捕获 agentSignifierpromiseCapabilityresolution,并在被调用时执行以下步骤:
    1. 断言:AgentSignifier() 是 agentSignifier
    2. 执行 ! Call(promiseCapability.[[Resolve]], undefined, « resolution »)。
    3. 返回 unused
  2. realmInTargetAgent 为 ! GetFunctionRealm(promiseCapability.[[Resolve]])。
  3. 断言:agentSignifierrealmInTargetAgent.[[AgentSignifier]]
  4. 执行 HostEnqueueGenericJob(resolveJob, realmInTargetAgent)。
  5. 返回 unused

25.4.3.14 DoWait ( mode, ta, index, value, timeout )

The abstract operation DoWait takes arguments mode (sync or async), ta (an ECMAScript language value), index (an ECMAScript language value), value (an ECMAScript language value), and timeout (an ECMAScript language value) and returns either a normal completion containing either an Object, "not-equal", "timed-out", or "ok", or a throw completion. It performs the following steps when called:

  1. taRecord 为 ? ValidateIntegerTypedArray(ta, true)。
  2. buffertaRecord.[[Object]].[[ViewedArrayBuffer]]
  3. 如果 IsSharedArrayBuffer(buffer) 是 false,则抛出 TypeError 异常。
  4. byteIndexInBuffer 为 ? ValidateAtomicAccess(taRecord, index)。
  5. arrayTypeNameta.[[TypedArrayName]]
  6. 如果 arrayTypeName"BigInt64Array",则令 expected 为 ? ToBigInt64(value)。
  7. 否则,令 expected 为 ? ToInt32(value)。
  8. timeoutNumber 为 ? ToNumber(timeout)。
  9. 如果 timeoutNumberNaN+∞𝔽,则令 realTimeout 为 +∞。
  10. 否则,如果 timeoutNumber-∞𝔽,则令 realTimeout 为 0。
  11. 否则,令 realTimeoutmax((timeoutNumber), 0)。
  12. 如果 modesyncAgentCanSuspend() 是 false,则抛出 TypeError 异常。
  13. blockbuffer.[[ArrayBufferData]]
  14. waiterListGetWaiterList(block, byteIndexInBuffer)。
  15. 如果 modesync,则
    1. promiseCapabilityblocking
    2. resultObjundefined
  16. 否则,
    1. promiseCapability 为 ! NewPromiseCapability(%Promise%)。
    2. resultObjOrdinaryObjectCreate(%Object.prototype%)。
  17. 执行 EnterCriticalSection(waiterList)。
  18. elementTypeTypedArrayElementType(ta)。
  19. witnessGetValueFromBuffer(buffer, byteIndexInBuffer, elementType, true, seq-cst)。
  20. 如果 expectedwitness,则
    1. 执行 LeaveCriticalSection(waiterList)。
    2. 如果 modesync,则返回 "not-equal"
    3. 执行 ! CreateDataPropertyOrThrow(resultObj, "async", false)。
    4. 执行 ! CreateDataPropertyOrThrow(resultObj, "value", "not-equal")。
    5. 返回 resultObj
  21. 如果 realTimeout = 0 且 modeasync,则
    1. 注:同步的立即超时没有特殊处理。异步的立即超时具有特殊处理,以便快速失败并避免不必要的 Promise job。
    2. 执行 LeaveCriticalSection(waiterList)。
    3. 执行 ! CreateDataPropertyOrThrow(resultObj, "async", false)。
    4. 执行 ! CreateDataPropertyOrThrow(resultObj, "value", "timed-out")。
    5. 返回 resultObj
  22. thisAgentAgentSignifier()。
  23. now 为标识当前时间的时间值(UTC)。
  24. additionalTimeout实现定义的非负数学值
  25. timeoutTime(now) + realTimeout + additionalTimeout
  26. 注:当 realTimeout 是 +∞ 时,timeoutTime 也是 +∞。
  27. waiterRecord 为新的 Waiter Record { [[AgentSignifier]]: thisAgent, [[PromiseCapability]]: promiseCapability, [[TimeoutTime]]: timeoutTime, [[Result]]: "ok" }。
  28. 执行 AddWaiter(waiterList, waiterRecord)。
  29. 如果 modesync,则
    1. 执行 SuspendThisAgent(waiterList, waiterRecord)。
  30. 否则,如果 timeoutTime有限的,则
    1. 执行 EnqueueAtomicsWaitAsyncTimeoutJob(waiterList, waiterRecord)。
  31. 执行 LeaveCriticalSection(waiterList)。
  32. 如果 modesync,则返回 waiterRecord.[[Result]]
  33. 执行 ! CreateDataPropertyOrThrow(resultObj, "async", true)。
  34. 执行 ! CreateDataPropertyOrThrow(resultObj, "value", promiseCapability.[[Promise]])。
  35. 返回 resultObj
Note

additionalTimeout 允许实现根据需要填充超时,例如为了降低功耗或粗化计时器分辨率以缓解定时攻击。此值在不同 DoWait 调用之间可以不同。

25.4.3.15 EnqueueAtomicsWaitAsyncTimeoutJob ( waiterList, waiterRecord )

The abstract operation EnqueueAtomicsWaitAsyncTimeoutJob takes arguments waiterList (a WaiterList Record) and waiterRecord (a Waiter Record) and returns unused. It performs the following steps when called:

  1. timeoutJob 为一个新的无参数 Job Abstract Closure,它捕获 waiterListwaiterRecord,并在被调用时执行以下步骤:
    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 )

The abstract operation AtomicCompareExchangeInSharedBlock takes arguments block (a Shared Data Block), byteIndexInBuffer (an integer), elementSize (a non-negative integer), expectedBytes (a List of byte values), and replacementBytes (a List of byte values) and returns a List of byte values. It performs the following steps when called:

  1. agentRecord 为 surrounding agentAgent Record
  2. executionagentRecord.[[CandidateExecution]]
  3. eventsRecordexecution.[[EventsRecords]][[AgentSignifier]]AgentSignifier() 的 Agent Events Record
  4. rawBytesRead 为长度为 elementSizeList,其元素为非确定性选择的字节值
  5. 注:在实现中,rawBytesRead 是底层硬件上的 load-link、load-exclusive,或读-改-写指令的一个操作数的结果。非确定性是内存模型的一项语义规定,用于描述弱一致性硬件的可观察行为。
  6. 注:期望值与读取值的比较在读-改-写修改函数之外执行,以避免在期望值不等于读取值时产生不必要的强同步。
  7. 如果 ByteListEqual(rawBytesRead, expectedBytes) 是 true,则
    1. second 为一个新的读-改-写修改函数,其参数为 (oldBytes, newBytes),不捕获任何内容,并在被调用时以原子方式执行以下步骤:
      1. 返回 newBytes
    2. eventReadModifyWriteSharedMemory { [[Order]]: seq-cst, [[NoTear]]: true, [[Block]]: block, [[ByteIndex]]: byteIndexInBuffer, [[ElementSize]]: elementSize, [[Payload]]: replacementBytes, [[ModifyOp]]: second }。
  8. 否则,
    1. eventReadSharedMemory { [[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 )

The abstract operation AtomicReadModifyWrite takes arguments ta (an ECMAScript language value), index (an ECMAScript language value), value (an ECMAScript language value), and op (a read-modify-write modification function) and returns either a normal completion containing either a Number or a BigInt, or a throw completion. op 接受两个字节值 List 实参并返回一个字节值 List。此操作以原子方式加载一个值,将其与另一个值组合,并存储该组合。它返回已加载的值。 It performs the following steps when called:

  1. byteIndexInBuffer 为 ? ValidateAtomicAccessOnIntegerTypedArray(ta, index)。
  2. 如果 ta.[[ContentType]]bigint,则令 coerced 为 ? ToBigInt(value)。
  3. 否则,令 coerced𝔽(? ToIntegerOrInfinity(value))。
  4. 执行 ? RevalidateAtomicAccess(ta, byteIndexInBuffer)。
  5. bufferta.[[ViewedArrayBuffer]]
  6. elementTypeTypedArrayElementType(ta)。
  7. 返回 GetModifySetValueInBuffer(buffer, byteIndexInBuffer, elementType, coerced, op)。

25.4.3.18 ByteListBitwiseOp ( op, xBytes, yBytes )

The abstract operation ByteListBitwiseOp takes arguments op (&, ^, or |), xBytes (a List of byte values), and yBytes (a List of byte values) and returns a List of byte values. 该操作以原子方式对实参的所有字节值执行按位操作,并返回一个字节值 List。 It performs the following steps when called:

  1. 断言:xBytesyBytes 具有相同数量的元素。
  2. result 为新的空 List
  3. i 为 0。
  4. xBytes 的每个元素 xByte,执行:
    1. yByteyBytes[i]。
    2. 如果 op&,则
      1. resultByte 为对 xByteyByte 应用按位 AND 操作的结果。
    3. 否则,如果 op^,则
      1. resultByte 为对 xByteyByte 应用按位异或(XOR)操作的结果。
    4. 否则,
      1. 断言:op|
      2. resultByte 为对 xByteyByte 应用按位包含 OR 操作的结果。
    5. i 设置为 i + 1。
    6. resultByte 追加到 result
  5. 返回 result

25.4.3.19 ByteListEqual ( xBytes, yBytes )

The abstract operation ByteListEqual takes arguments xBytes (a List of byte values) and yBytes (a List of byte values) and returns a Boolean. It performs the following steps when called:

  1. 如果 xBytesyBytes 没有相同数量的元素,则返回 false
  2. i 为 0。
  3. xBytes 的每个元素 xByte,执行:
    1. yByteyBytes[i]。
    2. 如果 xByteyByte,则返回 false
    3. i 设置为 i + 1。
  4. 返回 true

25.4.4 Atomics.add ( ta, index, value )

此函数在被调用时执行以下步骤:

  1. add 为一个新的读-改-写修改函数,其参数为 (xBytes, yBytes),捕获 ta,并在被调用时以原子方式执行以下步骤:
    1. typeTypedArrayElementType(ta)。
    2. agentRecord 为 surrounding agentAgent Record
    3. isLittleEndianagentRecord.[[LittleEndian]]
    4. xRawBytesToNumeric(type, xBytes, isLittleEndian)。
    5. yRawBytesToNumeric(type, yBytes, isLittleEndian)。
    6. 如果 x 是 Number,则
      1. sumNumber::add(x, y)。
    7. 否则,
      1. 断言:x 是 BigInt。
      2. sumBigInt::add(x, y)。
    8. sumBytesNumericToRawBytes(type, sum, isLittleEndian)。
    9. 断言:sumBytesxBytesyBytes 具有相同数量的元素。
    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. bufferta.[[ViewedArrayBuffer]]
  3. blockbuffer.[[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. elementTypeTypedArrayElementType(ta)。
  8. elementSizeTypedArrayElementSize(ta)。
  9. agentRecord 为 surrounding agentAgent Record
  10. isLittleEndianagentRecord.[[LittleEndian]]
  11. expectedBytesNumericToRawBytes(elementType, expected, isLittleEndian)。
  12. replacementBytesNumericToRawBytes(elementType, replacement, isLittleEndian)。
  13. 如果 IsSharedArrayBuffer(buffer) 是 true,则
    1. rawBytesReadAtomicCompareExchangeInSharedBlock(block, byteIndexInBuffer, elementSize, expectedBytes, replacementBytes)。
  14. 否则,
    1. rawBytesRead 为长度为 elementSizeList,其元素是从 block[byteIndexInBuffer] 开始的 elementSize 个字节序列。
    2. 如果 ByteListEqual(rawBytesRead, expectedBytes) 是 true,则
      1. replacementBytes 的各个字节存储到 block 中,从 block[byteIndexInBuffer] 开始。
  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 为 surrounding agentAgent Record
  3. 如果 n = 1,则返回 agentRecord.[[IsLockFree1]]
  4. 如果 n = 2,则返回 agentRecord.[[IsLockFree2]]
  5. 如果 n = 4,则返回 true
  6. 如果 n = 8,则返回 agentRecord.[[IsLockFree8]]
  7. 返回 false
Note

此函数是一种优化原语。直觉是,如果原子原语(compareExchangeloadstoreaddsubandorxorexchange)在大小为 n 字节的数据上的原子步骤,会在 surrounding agent 不获取 n 个字节构成的数据之外的锁的情况下执行,那么 Atomics.isLockFree(n) 将返回 true。高性能算法会使用此函数来确定是在临界区中使用锁还是使用原子操作。如果某个原子原语不是无锁的,那么算法提供自己的锁通常更高效。

Atomics.isLockFree(4) 总是返回 true,因为这可以在所有已知相关硬件上得到支持。能够假定这一点通常会简化程序。

无论此函数返回的值如何,所有原子操作都保证是原子的。例如,它们绝不会有可见操作发生在该操作中间(例如,“tearing”)。

25.4.9 Atomics.load ( ta, index )

此函数在被调用时执行以下步骤:

  1. byteIndexInBuffer 为 ? ValidateAtomicAccessOnIntegerTypedArray(ta, index)。
  2. 执行 ? RevalidateAtomicAccess(ta, byteIndexInBuffer)。
  3. bufferta.[[ViewedArrayBuffer]]
  4. elementTypeTypedArrayElementType(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. 如果 countundefined,则
    1. count 设置为 +∞。
  4. 否则,
    1. intCount 为 ? ToIntegerOrInfinity(count)。
    2. count 设置为 max(intCount, 0)。
  5. bufferta.[[ViewedArrayBuffer]]
  6. blockbuffer.[[ArrayBufferData]]
  7. 如果 IsSharedArrayBuffer(buffer) 为 false,则返回 +0𝔽
  8. waiterListGetWaiterList(block, byteIndexInBuffer)。
  9. 执行 EnterCriticalSection(waiterList)。
  10. waitersRemoveWaiters(waiterList, count)。
  11. waiters 的每个元素 waiterRecord,执行
    1. 执行 NotifyWaiter(waiterList, waiterRecord)。
  12. 执行 LeaveCriticalSection(waiterList)。
  13. waitersCountwaiters 中元素的数量。
  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
Note 1

此方法是为实现自旋等待循环的程序设计的,例如互斥锁内部的自旋锁快速路径,用于向 CPU 提供一个提示,表明它正在等待某个值时自旋。除计时外,它没有可观察的行为。

如果底层架构的最佳实践建议在自旋循环中使用 pause 或 yield 指令,则期望实现实现这样的指令。例如,Intel 优化手册建议使用 pause 指令。

鼓励实现对暂停的最长时间设置内部上限,其量级为数十到数百纳秒。

Note 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. bufferta.[[ViewedArrayBuffer]]
  6. elementTypeTypedArrayElementType(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. typeTypedArrayElementType(ta)。
    2. agentRecord 为周围代理的代理记录。
    3. isLittleEndianagentRecord.[[LittleEndian]]
    4. xRawBytesToNumeric(type, xBytes, isLittleEndian)。
    5. yRawBytesToNumeric(type, yBytes, isLittleEndian)。
    6. 如果 x 是一个 Number,则
      1. differenceNumber::subtract(x, y)。
    7. 否则,
      1. 断言:x 是一个 BigInt。
      2. differenceBigInt::subtract(x, y)。
    8. differenceBytesNumericToRawBytes(type, difference, isLittleEndian)。
    9. 断言:differenceBytesxBytesyBytes 具有相同数量的元素。
    10. 返回 differenceBytes
  2. 返回 ? AtomicReadModifyWrite(ta, index, value, subtract)。

25.4.15 Atomics.wait ( ta, index, value, timeout )

此函数将周围代理放入等待队列并将其挂起,直到收到通知或等待超时为止,返回一个用于区分这些情况的字符串。

调用时,它执行以下步骤:

  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% 属性的初始值是字符串值 "Atomics"

此属性具有属性特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

25.5 JSON 对象

JSON 对象:

  • %JSON%
  • 全局对象"JSON" 属性的初始值。
  • 普通对象
  • 包含两个函数 parsestringify,用于解析和构造 JSON 文本。
  • 具有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%
  • 没有 [[Construct]] 内部方法;它不能作为构造器与 new 操作符一起使用。
  • 没有 [[Call]] 内部方法;它不能作为函数调用。

JSON 数据交换格式定义于 ECMA-404。本规范中使用的 JSON 交换格式正是 ECMA-404 所描述的格式。JSON.parseJSON.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. unfilteredparseResult.[[Value]]
  4. 如果 IsCallable(reviver) 是 false,则返回 unfiltered
  5. rootOrdinaryObjectCreate(%Object.prototype%)。
  6. rootName 为空 String。
  7. 执行 ! CreateDataPropertyOrThrow(root, rootName, unfiltered)。
  8. snapshotCreateJSONParseRecord(parseResult.[[ParseNode]], rootName, unfiltered)。
  9. 返回 ? InternalizeJSONProperty(root, rootName, reviver, snapshot)。

此函数的 "length" 属性是 2𝔽

25.5.2.1 ParseJSON ( text )

The abstract operation ParseJSON takes argument text (a String) and returns either a normal completion containing a Record with fields [[ParseNode]] (a Parse Node) and [[Value]] (an ECMAScript language value), or a throw completion. It performs the following steps when called:

  1. 如果 StringToCodePoints(text) 不是 ECMA-404 中指定的有效 JSON 文本,则抛出 SyntaxError 异常。
  2. scriptString"("text");"字符串连接
  3. scriptParseText(scriptString, Script)。
  4. 注:13.2.5.1 中定义的早期错误规则对上述 ParseText 调用具有特殊处理。
  5. 断言:scriptParse Node
  6. result 为 ! scriptEvaluation
  7. 注:13.2.5.6 中定义的 PropertyDefinitionEvaluation 语义对上述求值具有特殊处理。
  8. 断言:result 是 String、Number、Boolean、由 ArrayLiteralObjectLiteral 定义的 Object,或 null
  9. 返回 Record { [[ParseNode]]: script, [[Value]]: result }。

符合实现的 JSON.parse 不允许扩展 JSON 语法。如果实现希望支持修改或扩展的 JSON 交换格式,则必须通过定义不同的解析函数来实现。

Note 1

有效 JSON 文本是 ECMAScript PrimaryExpression 语法的子集。步骤 1 验证 jsonString 符合该子集,而步骤 8 断言求值返回适当类型的值。

不过,由于 13.2.5.6 在 ParseJSON 期间具有不同表现,同一源文本作为 PrimaryExpression 求值时可能产生与作为 JSON 求值时不同的结果。此外,对对象字面量中重复 "__proto__" 属性的早期错误,同样不适用于 ParseJSON,这意味着并非所有被 ParseJSON 接受的文本都作为 PrimaryExpression 有效,尽管它们匹配语法。

Note 2

在对象中存在重复 name String 的情况下,同一键的词法上在前的值应被覆盖。

25.5.2.2 JSON Parse Record

JSON Parse Record 是一种 Record 值,用于描述从 JSON 文本解析出的值的初始状态。

JSON Parse Record 具有 Table 76 中列出的字段。

Table 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 )

The abstract operation CreateJSONParseRecord takes arguments parseNode (a Parse Node), key (a property name), and value (an ECMAScript language value) and returns a JSON Parse Record. 它递归地组合从 JSON 文本解析出的 parseNode 和由其求值产生的 value。 It performs the following steps when called:

  1. typedValueNodeShallowestContainedJSONValue(parseNode)。
  2. 断言:typedValueNode 不是 empty
  3. elements 为新的空 List
  4. entries 为新的空 List
  5. 如果 value 是 Object,则
    1. isArray 为 ! IsArray(value)。
    2. 如果 isArraytrue,则
      1. 断言:typedValueNodeArrayLiteral Parse Node
      2. contentNodestypedValueNodeJSONArrayLiteralContentNodes
      3. lengthcontentNodes 中元素的数量。
      4. valueLength 为 ! LengthOfArrayLike(value)。
      5. 断言:valueLengthlength
      6. index 为 0。
      7. 重复,只要 index < length
        1. propertyName 为 ! ToString(𝔽(index))。
        2. elementParseRecordCreateJSONParseRecord(contentNodes[index], propertyName, ! Get(value, propertyName))。
        3. elementParseRecord 追加到 elements
        4. index 设置为 index + 1。
    3. 否则,
      1. 断言:typedValueNodeObjectLiteral Parse Node
      2. propertyNodestypedValueNodePropertyDefinitionNodes
      3. 注:因为 value 是从 JSON 文本产生且尚未被修改,所以它的所有属性键都是 String,并且会被穷尽枚举。
      4. keys 为 ! EnumerableOwnProperties(value, key)。
      5. keys 的每个 String propertyKey,执行:
        1. 注:当 JSON 文本为单个对象指定多个具有相同名称的 name/value 对(例如 {"a":"lost","a":"kept"})时,所得 ECMAScript 对象对应属性的值由具有该名称的最后一对指定。
        2. propertyDefinitionempty
        3. propertyNodes 的每个 Parse Node propertyNode,执行:
          1. propertyNamepropertyNodePropName
          2. 如果 propertyNamepropertyKey,则将 propertyDefinition 设置为 propertyNode
        4. 断言:propertyDefinition PropertyDefinition : PropertyName : AssignmentExpression
        5. propertyValueNodepropertyDefinitionAssignmentExpression
        6. entryParseRecordCreateJSONParseRecord(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 )

The abstract operation InternalizeJSONProperty takes arguments holder (an Object), name (a String), reviver (a function object), and parseRecord (a JSON Parse Record or empty) and returns either a normal completion containing an ECMAScript language value or a throw completion.

Note

此算法有意在 [[Delete]]CreateDataProperty 返回 false 时不抛出异常。

它在被调用时执行以下步骤:

  1. value 为 ? Get(holder, name)。
  2. contextOrdinaryObjectCreate(%Object.prototype%)。
  3. 如果 parseRecordJSON Parse RecordSameValue(parseRecord.[[Value]], value) 是 true,则
    1. 如果 value 不是 Object,则
      1. parseNodeparseRecord.[[ParseNode]]
      2. 断言:parseNode 既不是 ArrayLiteral Parse Node,也不是 ObjectLiteral Parse Node
      3. sourceTextparseNode 匹配的源文本
      4. 执行 ! CreateDataPropertyOrThrow(context, "source", CodePointsToString(sourceText))。
    2. elementRecordsparseRecord.[[Elements]]
    3. entryRecordsparseRecord.[[Entries]]
  4. 否则,
    1. elementRecords 为新的空 List
    2. entryRecords 为新的空 List
  5. 如果 value 是 Object,则
    1. isArray 为 ? IsArray(value)。
    2. 如果 isArraytrue,则
      1. elementRecordsLengthelementRecords 中元素的数量。
      2. length 为 ? LengthOfArrayLike(value)。
      3. index 为 0。
      4. 重复,只要 index < length
        1. propertyKey 为 ! ToString(𝔽(index))。
        2. 如果 index < elementRecordsLength,则令 elementRecordelementRecords[index];否则令 elementRecordempty
        3. newElement 为 ? InternalizeJSONProperty(value, propertyKey, reviver, elementRecord)。
        4. 如果 newElementundefined,则
          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,则令 entryRecordentry;否则令 entryRecordempty
        2. newElement 为 ? InternalizeJSONProperty(value, propertyKey, reviver, entryRecord)。
        3. 如果 newElementundefined,则
          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 )

The abstract operation ShallowestContainedJSONValue takes argument root (a Parse Node) and returns a Parse Node or empty. 它对以 root 为根的解析树执行广度优先搜索,并返回第一个属于对应于 JSON 值的非终结符实例的节点,如果不存在这样的节点则返回 empty。 It performs the following steps when called:

  1. activeFunc活动函数对象
  2. 断言:activeFuncJSON.parse 内置函数对象(见 JSON.parse)。
  3. types 为 « NullLiteral, BooleanLiteral, NumericLiteral, StringLiteral, ArrayLiteral, ObjectLiteral, UnaryExpression »。
  4. unaryExprempty
  5. queue 为 « root »。
  6. 重复,只要 queue 不为空,
    1. candidatequeue 的第一个元素。
    2. queue 中移除第一个元素。
    3. queuedChildrenfalse
    4. types 的每个非终结符 type,执行:
      1. 如果 candidatetype 的实例,则
        1. 注:在 JSON 语法中,number token 可以表示负值。在 ECMAScript 中,取负表示为一元操作,其中 UnaryExpression 解析为 - 后跟派生的 UnaryExpression
        2. 如果 typeUnaryExpression,则
          1. 如果 candidate 的父节点不是 UnaryExpression Parse Node,则将 unaryExpr 设置为 candidate
        3. 否则,如果 typeNumericLiteral,则
          1. 断言:candidate 包含unaryExpr 中。
          2. 返回 unaryExpr
        4. 否则,
          1. 返回 candidate
      2. 如果 queuedChildrenfalsecandidate 是非终结符的实例,且 candidate Contains typetrue,则
        1. children 为一个 List,按顺序包含 candidate 的每个子节点。
        2. queue 设置为 queuechildren列表连接
        3. queuedChildren 设置为 true
  7. 返回 empty

25.5.2.6 Static Semantics: JSONArrayLiteralContentNodes

The syntax-directed operation JSONArrayLiteralContentNodes takes no arguments and returns a List of Parse Nodes. It is defined piecewise over the following productions:

ArrayLiteral : [ Elisionopt ] [ ElementList ] [ ElementList , Elisionopt ]
  1. 断言:Elision 不存在。
  2. 如果 ElementList 不存在,则返回新的空 List
  3. 返回 ElementListJSONArrayLiteralContentNodes
ElementList : Elisionopt AssignmentExpression
  1. 断言:Elision 不存在。
  2. 返回 « AssignmentExpression »。
ElementList : ElementList , Elisionopt AssignmentExpression
  1. 断言:Elision 不存在。
  2. elements 为派生的 ElementListJSONArrayLiteralContentNodes
  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. objOrdinaryObjectCreate(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. propertyListundefined
  4. replacerFuncundefined
  5. 如果 replacer 是 Object,则
    1. 如果 IsCallable(replacer) 是 true,则
      1. replacerFunc 设置为 replacer
    2. 否则,
      1. isArray 为 ? IsArray(replacer)。
      2. 如果 isArraytrue,则
        1. propertyList 设置为新的空 List
        2. length 为 ? LengthOfArrayLike(replacer)。
        3. k 为 0。
        4. 重复,只要 k < length
          1. propertyKey 为 ! ToString(𝔽(k))。
          2. propertyValue 为 ? Get(replacer, propertyKey)。
          3. itemundefined
          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 不是 undefinedpropertyList包含 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,则令 gapspace;否则令 gapspace 从 0 到 10 的子字符串
  9. 否则,
    1. gap 为空 String。
  10. wrapperOrdinaryObjectCreate(%Object.prototype%)。
  11. 执行 ! CreateDataPropertyOrThrow(wrapper, 空 String, value)。
  12. stateJSON Serialization Record { [[ReplacerFunction]]: replacerFunc, [[Stack]]: stack, [[Indent]]: indent, [[Gap]]: gap, [[PropertyList]]: propertyList }。
  13. 返回 ? SerializeJSONProperty(state, 空 String, wrapper)。

此函数的 "length" 属性是 3𝔽

Note 1

JSON 结构允许嵌套到任意深度,但它们必须是无环的。如果 value 是或包含循环结构,则此函数必须抛出 TypeError 异常。以下是一个不能被字符串化的值的示例:

a = [];
a[0] = a;
my_text = JSON.stringify(a); // 这必须抛出 TypeError。
Note 2

符号性原始值按如下方式渲染:

  • null 值在 JSON 文本中渲染为 String 值 "null"
  • undefined 值不会被渲染。
  • true 值在 JSON 文本中渲染为 String 值 "true"
  • false 值在 JSON 文本中渲染为 String 值 "false"
Note 3

String 值用 QUOTATION MARK (") 码元包裹。码元 "\\ 前缀转义。控制字符码元替换为转义序列 \uHHHH,或较短形式 \b(BACKSPACE)、\f(FORM FEED)、\n(LINE FEED)、\r(CARRIAGE RETURN)、\t(CHARACTER TABULATION)。

Note 4

有限数值会像调用 ToString(number) 一样被字符串化。NaNInfinity 不论符号如何,都表示为 String 值 "null"

Note 5

没有 JSON 表示的值(例如 undefined 和函数)不会产生 String。相反,它们产生 undefined 值。在数组中,这些值表示为 String 值 "null"。在对象中,不可表示的值会导致该属性被排除在字符串化之外。

Note 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 是一种 Record 值,用于启用对 JSON 格式的序列化。

JSON Serialization Record 具有 Table 77 中列出的字段。

Table 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 )

The abstract operation SerializeJSONProperty takes arguments state (a JSON Serialization Record), key (a String), and holder (an Object) and returns either a normal completion containing either a String or undefined, or a throw completion. It performs the following steps when called:

  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. 如果 valuenull,则返回 "null"
  6. 如果 valuetrue,则返回 "true"
  7. 如果 valuefalse,则返回 "false"
  8. 如果 value 是 String,则返回 QuoteJSONString(value)。
  9. 如果 value 是 Number,则
    1. 如果 value有限的,则返回 ! ToString(value)。
    2. 返回 "null"
  10. 如果 value 是 BigInt,则抛出 TypeError 异常。
  11. 如果 value 是 Object 且 IsCallable(value) 是 false,则
    1. isArray 为 ? IsArray(value)。
    2. 如果 isArraytrue,则
      1. 返回 ? SerializeJSONArray(state, value)。
    3. 返回 ? SerializeJSONObject(state, value)。
  12. 返回 undefined

25.5.4.3 QuoteJSONString ( value )

The abstract operation QuoteJSONString takes argument value (a String) and returns a String. 它用 0x0022(QUOTATION MARK)码元包裹 value,并转义其中的某些其他码元。此操作将 value 解释为 UTF-16 编码码点的序列,如 6.1.4 中所述。 It performs the following steps when called:

  1. product 为仅由码元 0x0022(QUOTATION MARK)组成的 String 值。
  2. StringToCodePoints(value) 的每个码点 codePoint,执行:
    1. 如果 codePoint 列于 Table 78 的 “Code Point” 列中,则
      1. product 设置为 product 与对应行的 “Escape Sequence” 列中为 codePoint 指定的转义序列的字符串连接
    2. 否则,如果 codePoint 的数值小于 0x0020(SPACE),或 codePoint 的数值与 leading surrogate 或 trailing surrogate 的数值相同,则
      1. unit 为数值等于 codePoint 数值的码元。
      2. product 设置为 productUnicodeEscape(unit) 的字符串连接
    3. 否则,
      1. product 设置为 productUTF16EncodeCodePoint(codePoint) 的字符串连接
  3. product 设置为 product 和码元 0x0022(QUOTATION MARK)的字符串连接
  4. 返回 product
Table 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 )

The abstract operation UnicodeEscape takes argument codeUnit (a code unit) and returns a String. 它将 codeUnit 表示为 Unicode 转义序列。 It performs the following steps when called:

  1. ncodeUnit 的数值。
  2. 断言:n ≤ 0xFFFF。
  3. hexn 的 String 表示,格式化为小写十六进制数。
  4. 返回码元 0x005C(REVERSE SOLIDUS)、"u"StringPad(hex, 4, "0", start) 的字符串连接

25.5.4.5 SerializeJSONObject ( state, value )

The abstract operation SerializeJSONObject takes arguments state (a JSON Serialization Record) and value (an Object) and returns either a normal completion containing a String or a throw completion. 它序列化一个对象。 It performs the following steps when called:

  1. 如果 state.[[Stack]] 包含 value,则抛出 TypeError 异常,因为该结构是循环的。
  2. value 追加到 state.[[Stack]]
  3. stepBackstate.[[Indent]]
  4. state.[[Indent]] 设置为 state.[[Indent]]state.[[Gap]]字符串连接
  5. 如果 state.[[PropertyList]] 不是 undefined,则
    1. keysstate.[[PropertyList]]
  6. 否则,
    1. keys 为 ? EnumerableOwnProperties(value, key)。
  7. partial 为新的空 List
  8. keys 的每个元素 propertyKey,执行:
    1. stringP 为 ? SerializeJSONProperty(state, propertyKey, value)。
    2. 如果 stringP 不是 undefined,则
      1. memberQuoteJSONString(propertyKey)。
      2. member 设置为 member":"字符串连接
      3. 如果 state.[[Gap]] 不是空 String,则
        1. member 设置为 member 和码元 0x0020(SPACE)的字符串连接
      4. member 设置为 memberstringP字符串连接
      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 分隔。separator String 既不插入在第一个 String 之前,也不插入在最后一个 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 )

The abstract operation SerializeJSONArray takes arguments state (a JSON Serialization Record) and value (an Object) and returns either a normal completion containing a String or a throw completion. 它序列化一个数组。 It performs the following steps when called:

  1. 如果 state.[[Stack]] 包含 value,则抛出 TypeError 异常,因为该结构是循环的。
  2. value 追加到 state.[[Stack]]
  3. stepBackstate.[[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. 如果 stringPundefined,则
      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 分隔。separator String 既不插入在第一个 String 之前,也不插入在最后一个 String 之后。
      3. final"["、码元 0x000A(LINE FEED)、state.[[Indent]]properties、码元 0x000A(LINE FEED)、stepBack"]"字符串连接
  11. 移除 state.[[Stack]] 的最后一个元素。
  12. state.[[Indent]] 设置为 stepBack
  13. 返回 final
Note

数组的表示仅包含+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 是一种对象,用于在不阻止目标对象或 symbol 被垃圾回收的情况下引用它。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. weakRefthis 值。
  2. 执行 ? RequireInternalSlot(weakRef, [[WeakRefTarget]])。
  3. 返回 WeakRefDeref(weakRef)。
Note

如果 WeakRef 返回的 target 值不是 undefined,则在 ECMAScript 代码的当前执行完成之前,不应对该 target 值进行垃圾回收。AddToKeptObjects 操作确保读取一致性得以维持。

let target = { foo() {} };
let weakRef = new WeakRef(target);

// ... later ...

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 )

The abstract operation WeakRefDeref takes argument weakRef (a WeakRef) and returns an ECMAScript language value. It performs the following steps when called:

  1. targetweakRef.[[WeakRefTarget]]
  2. 如果 target 不是 empty,则
    1. 执行 AddToKeptObjects(target)。
    2. 返回 target
  3. 返回 undefined
Note

抽象操作与 WeakRef.prototype.deref 分开定义,严格来说是为了能够简洁地定义活性。

26.1.5 WeakRef 实例的属性

WeakRef 实例是普通对象,继承自 WeakRef 原型对象的属性。WeakRef 实例还具有 [[WeakRefTarget]] 内部槽。

26.2 FinalizationRegistry 对象

FinalizationRegistry 是一种对象,用于管理在目标对象和 symbol 被垃圾回收时执行的清理操作的注册和注销。

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. finalizationRegistrythis 值。
  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. cellRecord { [[WeakRefTarget]]: target, [[HeldValue]]: heldValue, [[UnregisterToken]]: unregisterToken }。
  7. cell 追加到 finalizationRegistry.[[Cells]]
  8. 返回 undefined
Note

根据本规范中的算法和定义,当 finalizationRegistry.[[Cells]] 包含 cell 时,cell.[[HeldValue]] 是活的;不过,这并不一定意味着 cell.[[UnregisterToken]]cell.[[Target]] 是活的。例如,以对象自身作为 unregister token 注册该对象,并不会使该对象永远保持存活。

26.2.3.3 FinalizationRegistry.prototype.unregister ( unregisterToken )

此方法在被调用时执行以下步骤:

  1. finalizationRegistrythis 值。
  2. 执行 ? RequireInternalSlot(finalizationRegistry, [[Cells]])。
  3. 如果 CanBeHeldWeakly(unregisterToken) 是 false,则抛出 TypeError 异常。
  4. removedfalse
  5. finalizationRegistry.[[Cells]] 的每个 Record { [[WeakRefTarget]], [[HeldValue]], [[UnregisterToken]] } cell,执行:
    1. 如果 cell.[[UnregisterToken]] 不是 emptySameValue(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 接口包含 Table 79 中描述的属性:

Table 79: Iterable 接口必需属性
属性 要求
%Symbol.iterator% 返回 iterator 对象的函数 返回的对象必须符合 iterator 接口

27.1.1.2 Iterator 接口

实现 iterator 接口的对象必须包含 Table 80 中的属性。这类对象也可以实现 Table 81 中的属性。

Table 80: Iterator 接口必需属性
属性 要求
"next" 返回 IteratorResult 对象的函数 返回的对象必须符合 IteratorResult 接口。如果先前对某个 iteratornext 方法的调用已返回一个 "done" 属性为 true 的 IteratorResult 对象,则随后对该对象的 next 方法的所有调用也应返回一个 "done" 属性为 true 的 IteratorResult 对象。不过,此要求不会被强制执行。
Note 1

可以向 next 函数传递实参,但其解释和有效性取决于目标 iterator。for-of 语句和其他 iterator 的常见使用者不会传递任何实参,因此预期以这种方式使用的 iterator 对象必须准备好处理无实参调用的情况。

Table 81: Iterator 接口可选属性
属性 要求
"return" 返回 IteratorResult 对象的函数 返回的对象必须符合 IteratorResult 接口。调用此方法会通知 iterator 对象,调用者不打算再对该 iterator 进行任何 next 方法调用。返回的 IteratorResult 对象通常会有一个值为 true"done" 属性,以及一个 "value" 属性,其值为传给 return 方法的实参。不过,此要求不会被强制执行。
"throw" 返回 IteratorResult 对象的函数 返回的对象必须符合 IteratorResult 接口。调用此方法会通知 iterator 对象,调用者已检测到错误条件。该实参可用于标识错误条件,并且通常会是一个异常对象。典型响应是 throw 作为实参传入的值。如果该方法没有 throw,则返回的 IteratorResult 对象通常会有一个值为 true"done" 属性。
Note 2

通常,这些方法的调用者应在调用前检查其是否存在。某些 ECMAScript 语言特性,包括 for-ofyield* 和数组解构,会在执行存在性检查后调用这些方法。大多数接受 iterable 对象作为实参的 ECMAScript 库函数也会有条件地调用它们。

27.1.1.3 Async Iterable 接口

async iterable 接口包含 Table 82 中描述的属性:

Table 82: Async Iterable 接口必需属性
属性 要求
%Symbol.asyncIterator% 返回 async iterator 对象的函数 返回的对象必须符合 async iterator 接口

27.1.1.4 Async Iterator 接口

实现 async iterator 接口的对象必须包含 Table 83 中的属性。这类对象也可以实现 Table 84 中的属性。

Table 83: Async Iterator 接口必需属性
属性 要求
"next" 返回 IteratorResult 对象 promise 的函数

返回的 promise 在被兑现时,必须以符合 IteratorResult 接口的对象兑现。如果先前对某个 async iteratornext 方法的调用已返回一个其 "done" 属性为 true 的 IteratorResult 对象的 promise,则随后对该对象的 next 方法的所有调用也应返回一个其 "done" 属性为 true 的 IteratorResult 对象的 promise。不过,此要求不会被强制执行。

此外,作为兑现值的 IteratorResult 对象应具有一个 "value" 属性,其值不是 promise(也不是“thenable”)。不过,此要求也不会被强制执行。

Note 1

可以向 next 函数传递实参,但其解释和有效性取决于目标 async iterator。for-await-of 语句和其他 async iterator 的常见使用者不会传递任何实参,因此预期以这种方式使用的 async iterator 对象必须准备好处理无实参调用的情况。

Table 84: Async Iterator 接口可选属性
属性 要求
"return" 返回 IteratorResult 对象 promise 的函数

返回的 promise 在被兑现时,必须以符合 IteratorResult 接口的对象兑现。调用此方法会通知 async iterator 对象,调用者不打算再对该 async iterator 进行任何 next 方法调用。返回的 promise 会以一个 IteratorResult 对象兑现,该对象通常会有一个值为 true"done" 属性,以及一个 "value" 属性,其值为传给 return 方法的实参。不过,此要求不会被强制执行。

此外,作为兑现值的 IteratorResult 对象应具有一个 "value" 属性,其值不是 promise(也不是“thenable”)。如果实参值以典型方式使用,则如果它是一个被拒绝的 promise,应返回一个以相同理由拒绝的 promise;如果它是一个已兑现的 promise,则其兑现值应作为返回 promise 的 IteratorResult 对象兑现值的 "value" 属性。不过,这些要求也不会被强制执行。

"throw" 返回 IteratorResult 对象 promise 的函数

返回的 promise 在被兑现时,必须以符合 IteratorResult 接口的对象兑现。调用此方法会通知 async iterator 对象,调用者已检测到错误条件。该实参可用于标识错误条件,并且通常会是一个异常对象。典型响应是返回一个以传入实参值为拒绝理由的被拒绝 promise。

如果返回的 promise 被兑现,则 IteratorResult 对象兑现值通常会有一个值为 true"done" 属性。此外,它应具有一个 "value" 属性,其值不是 promise(也不是“thenable”),但此要求不会被强制执行。

Note 2

通常,这些方法的调用者应在调用前检查其是否存在。某些 ECMAScript 语言特性,包括 for-await-ofyield*,会在执行存在性检查后调用这些方法。

27.1.1.5 IteratorResult 接口

IteratorResult 接口包含 Table 85 中列出的属性:

Table 85: IteratorResult 接口属性
属性 要求
"done" Boolean 这是 iterator next 方法调用的结果状态。如果已到达 iterator 的末尾,则 "done"true。如果尚未到达末尾,则 "done"false,且有值可用。如果不存在 "done" 属性(无论是自有属性还是继承属性),则认为其值为 false
"value" ECMAScript 语言值 如果 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 值, undefined, "Iterator Helper")。

27.1.2.1.2 %IteratorHelperPrototype%.return ( )

  1. objthis 值。
  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. completionReturnCompletion(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. 如果 methodundefined,则抛出 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. innerAlivetrue
      5. 重复,只要 innerAlivetrue
        1. innerValue 为 ? IteratorStepValue(iteratorRecord)。
        2. 如果 innerValuedone,则
          1. innerAlive 设置为 false
        3. 否则,
          1. completionCompletion(Yield(innerValue))。
          2. 如果 completion 是 abrupt completion,则
            1. 返回 ? IteratorClose(iteratorRecord, completion)。
    2. 返回 ReturnCompletion(undefined)。
  4. genCreateIteratorFromClosure(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. 如果 hasInstancetrue,则
    1. 返回 iteratorRecord.[[Iterator]]
  4. wrapperOrdinaryObjectCreate(%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. objthis 值。
  2. 执行 ? RequireInternalSlot(obj, [[Iterated]])。
  3. iteratorRecordobj.[[Iterated]]
  4. 返回 ? Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]])。

27.1.3.2.2.1.2 %WrapForValidIteratorPrototype%.return ( )

  1. objthis 值。
  2. 执行 ? RequireInternalSlot(obj, [[Iterated]])。
  3. iteratorobj.[[Iterated]].[[Iterator]]
  4. 断言:iterator 是 Object。
  5. returnMethod 为 ? GetMethod(iterator, "return")。
  6. 如果 returnMethodundefined,则
    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. 如果 modeundefined,则将 mode 设置为 "shortest"
  5. 如果 mode 不是 "shortest""longest""strict" 之一,则抛出 TypeError 异常。
  6. paddingOptionundefined
  7. 如果 mode"longest",则
    1. paddingOption 设置为 ? Get(options, "padding")。
    2. 如果 paddingOption 不是 undefinedpaddingOption 不是 Object,则抛出 TypeError 异常。
  8. iters 为新的空 List
  9. padding 为新的空 List
  10. inputIter 为 ? GetIterator(iterables, sync)。
  11. nextnot-started
  12. 重复,只要 next 不是 done
    1. next 设置为 Completion(IteratorStepValue(inputIter))。
    2. IfAbruptCloseIterators(next, iters)。
    3. 如果 next 不是 done,则
      1. iterCompletion(GetIteratorFlattenable(next, reject-primitives))。
      2. needClosing 为 « inputIter » 和 iters列表连接
      3. IfAbruptCloseIterators(iter, needClosing)。
      4. iter 追加到 iters
  13. iterCountiters 中元素的数量。
  14. 如果 mode"longest",则
    1. 如果 paddingOptionundefined,则
      1. 重复 iterCount 次:
        1. undefined 追加到 padding
    2. 否则,
      1. paddingIterCompletion(GetIterator(paddingOption, sync))。
      2. IfAbruptCloseIterators(paddingIter, iters)。
      3. usingIteratortrue
      4. 重复 iterCount 次:
        1. 如果 usingIteratortrue,则
          1. next 设置为 Completion(IteratorStepValue(paddingIter))。
          2. IfAbruptCloseIterators(next, iters)。
          3. 如果 nextdone,则
            1. usingIterator 设置为 false
          4. 否则,
            1. next 追加到 padding
        2. 如果 usingIteratorfalse,则将 undefined 追加到 padding
      5. 如果 usingIteratortrue,则
        1. completionCompletion(IteratorClose(paddingIter, NormalCompletion(unused)))。
        2. IfAbruptCloseIterators(completion, iters)。
  15. finishResults 为一个新的 Abstract Closure,其参数为 (results),不捕获任何内容,并在被调用时执行以下步骤:
    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. 如果 modeundefined,则将 mode 设置为 "shortest"
  5. 如果 mode 不是 "shortest""longest""strict" 之一,则抛出 TypeError 异常。
  6. paddingOptionundefined
  7. 如果 mode"longest",则
    1. paddingOption 设置为 ? Get(options, "padding")。
    2. 如果 paddingOption 不是 undefinedpaddingOption 不是 Object,则抛出 TypeError 异常。
  8. iters 为新的空 List
  9. padding 为新的空 List
  10. allKeys 为 ? iterables.[[OwnPropertyKeys]]()。
  11. keys 为新的空 List
  12. allKeys 的每个元素 key,执行:
    1. propertyDescCompletion(iterables.[[GetOwnProperty]](key))。
    2. IfAbruptCloseIterators(propertyDesc, iters)。
    3. 如果 propertyDesc 不是 undefinedpropertyDesc.[[Enumerable]]true,则
      1. valueCompletion(Get(iterables, key))。
      2. IfAbruptCloseIterators(value, iters)。
      3. 如果 value 不是 undefined,则
        1. key 追加到 keys
        2. iterCompletion(GetIteratorFlattenable(value, reject-primitives))。
        3. IfAbruptCloseIterators(iter, iters)。
        4. iter 追加到 iters
  13. iterCountiters 中元素的数量。
  14. 如果 mode"longest",则
    1. 如果 paddingOptionundefined,则
      1. 重复 iterCount 次:
        1. undefined 追加到 padding
    2. 否则,
      1. keys 的每个元素 key,执行:
        1. valueCompletion(Get(paddingOption, key))。
        2. IfAbruptCloseIterators(value, iters)。
        3. value 追加到 padding
  15. finishResults 为一个新的 Abstract Closure,其参数为 (results),捕获 keysiterCount,并在被调用时执行以下步骤:
    1. objOrdinaryObjectCreate(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 原型对象

Note

本规范中定义的所有实现 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 }。[[Get]][[Set]] 特性定义如下:

27.1.3.3.1.1 get Iterator.prototype.constructor

[[Get]] 特性的值是一个不需要实参的内置函数。它在被调用时执行以下步骤:

  1. 返回 %Iterator%

27.1.3.3.1.2 set Iterator.prototype.constructor

[[Set]] 特性的值是一个接受实参 v 的内置函数。它在被调用时执行以下步骤:

  1. 执行 ? SetterThatIgnoresPrototypeProperties(this 值, %Iterator.prototype%, "constructor", v)。
  2. 返回 undefined
Note

不同于大多数内置原型上的 "constructor" 属性,出于 Web 兼容性原因,此属性必须是访问器。

27.1.3.3.2 Iterator.prototype.drop ( limit )

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. 如果 obj 不是 Object,则抛出 TypeError 异常。
  3. iteratedIterator Record { [[Iterator]]: obj, [[NextMethod]]: undefined, [[Done]]: false }。
  4. numberLimitCompletion(ToNumber(limit))。
  5. IfAbruptCloseIterator(numberLimit, iterated)。
  6. 如果 numberLimitNaN,则
    1. errorThrowCompletion(一个新创建的 RangeError 对象)。
    2. 返回 ? IteratorClose(iterated, error)。
  7. intLimit 为 ! ToIntegerOrInfinity(numberLimit)。
  8. 如果 intLimit < 0,则
    1. errorThrowCompletion(一个新创建的 RangeError 对象)。
    2. 返回 ? IteratorClose(iterated, error)。
  9. iterated 设置为 ? GetIteratorDirect(obj)。
  10. closure 为一个新的无参数 Abstract Closure,它捕获 iteratedintLimit,并在被调用时执行以下步骤:
    1. remainingintLimit
    2. 重复,只要 remaining > 0,
      1. 如果 remaining ≠ +∞,则
        1. remaining 设置为 remaining - 1。
      2. next 为 ? IteratorStep(iterated)。
      3. 如果 nextdone,则返回 ReturnCompletion(undefined)。
    3. 重复,
      1. value 为 ? IteratorStepValue(iterated)。
      2. 如果 valuedone,则返回 ReturnCompletion(undefined)。
      3. completionCompletion(Yield(value))。
      4. IfAbruptCloseIterator(completion, iterated)。
  11. resultCreateIteratorFromClosure(closure, "Iterator Helper", %IteratorHelperPrototype%, « [[UnderlyingIterators]] »)。
  12. result.[[UnderlyingIterators]] 设置为 « iterated »。
  13. 返回 result

27.1.3.3.3 Iterator.prototype.every ( predicate )

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. 如果 obj 不是 Object,则抛出 TypeError 异常。
  3. iteratedIterator Record { [[Iterator]]: obj, [[NextMethod]]: undefined, [[Done]]: false }。
  4. 如果 IsCallable(predicate) 是 false,则
    1. errorThrowCompletion(一个新创建的 TypeError 对象)。
    2. 返回 ? IteratorClose(iterated, error)。
  5. iterated 设置为 ? GetIteratorDirect(obj)。
  6. counter 为 0。
  7. 重复,
    1. value 为 ? IteratorStepValue(iterated)。
    2. 如果 valuedone,则返回 true
    3. resultCompletion(Call(predicate, undefined, « value, 𝔽(counter) »))。
    4. IfAbruptCloseIterator(result, iterated)。
    5. 如果 ToBoolean(result) 是 false,则返回 ? IteratorClose(iterated, NormalCompletion(false))。
    6. counter 设置为 counter + 1。

27.1.3.3.4 Iterator.prototype.filter ( predicate )

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. 如果 obj 不是 Object,则抛出 TypeError 异常。
  3. iteratedIterator Record { [[Iterator]]: obj, [[NextMethod]]: undefined, [[Done]]: false }。
  4. 如果 IsCallable(predicate) 是 false,则
    1. errorThrowCompletion(一个新创建的 TypeError 对象)。
    2. 返回 ? IteratorClose(iterated, error)。
  5. iterated 设置为 ? GetIteratorDirect(obj)。
  6. closure 为一个新的无参数 Abstract Closure,它捕获 iteratedpredicate,并在被调用时执行以下步骤:
    1. counter 为 0。
    2. 重复,
      1. value 为 ? IteratorStepValue(iterated)。
      2. 如果 valuedone,则返回 ReturnCompletion(undefined)。
      3. selectedCompletion(Call(predicate, undefined, « value, 𝔽(counter) »))。
      4. IfAbruptCloseIterator(selected, iterated)。
      5. 如果 ToBoolean(selected) 是 true,则
        1. completionCompletion(Yield(value))。
        2. IfAbruptCloseIterator(completion, iterated)。
      6. counter 设置为 counter + 1。
  7. resultCreateIteratorFromClosure(closure, "Iterator Helper", %IteratorHelperPrototype%, « [[UnderlyingIterators]] »)。
  8. result.[[UnderlyingIterators]] 设置为 « iterated »。
  9. 返回 result

27.1.3.3.5 Iterator.prototype.find ( predicate )

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. 如果 obj 不是 Object,则抛出 TypeError 异常。
  3. iteratedIterator Record { [[Iterator]]: obj, [[NextMethod]]: undefined, [[Done]]: false }。
  4. 如果 IsCallable(predicate) 是 false,则
    1. errorThrowCompletion(一个新创建的 TypeError 对象)。
    2. 返回 ? IteratorClose(iterated, error)。
  5. iterated 设置为 ? GetIteratorDirect(obj)。
  6. counter 为 0。
  7. 重复,
    1. value 为 ? IteratorStepValue(iterated)。
    2. 如果 valuedone,则返回 undefined
    3. resultCompletion(Call(predicate, undefined, « value, 𝔽(counter) »))。
    4. IfAbruptCloseIterator(result, iterated)。
    5. 如果 ToBoolean(result) 是 true,则返回 ? IteratorClose(iterated, NormalCompletion(value))。
    6. counter 设置为 counter + 1。

27.1.3.3.6 Iterator.prototype.flatMap ( mapper )

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. 如果 obj 不是 Object,则抛出 TypeError 异常。
  3. iteratedIterator Record { [[Iterator]]: obj, [[NextMethod]]: undefined, [[Done]]: false }。
  4. 如果 IsCallable(mapper) 是 false,则
    1. errorThrowCompletion(一个新创建的 TypeError 对象)。
    2. 返回 ? IteratorClose(iterated, error)。
  5. iterated 设置为 ? GetIteratorDirect(obj)。
  6. closure 为一个新的无参数 Abstract Closure,它捕获 iteratedmapper,并在被调用时执行以下步骤:
    1. counter 为 0。
    2. 重复,
      1. value 为 ? IteratorStepValue(iterated)。
      2. 如果 valuedone,则返回 ReturnCompletion(undefined)。
      3. mappedCompletion(Call(mapper, undefined, « value, 𝔽(counter) »))。
      4. IfAbruptCloseIterator(mapped, iterated)。
      5. innerIteratorCompletion(GetIteratorFlattenable(mapped, reject-primitives))。
      6. IfAbruptCloseIterator(innerIterator, iterated)。
      7. innerAlivetrue
      8. 重复,只要 innerAlivetrue
        1. innerValueCompletion(IteratorStepValue(innerIterator))。
        2. IfAbruptCloseIterator(innerValue, iterated)。
        3. 如果 innerValuedone,则
          1. innerAlive 设置为 false
        4. 否则,
          1. completionCompletion(Yield(innerValue))。
          2. 如果 completion 是 abrupt completion,则
            1. backupCompletionCompletion(IteratorClose(innerIterator, completion))。
            2. IfAbruptCloseIterator(backupCompletion, iterated)。
            3. 返回 ? IteratorClose(iterated, completion)。
      9. counter 设置为 counter + 1。
  7. resultCreateIteratorFromClosure(closure, "Iterator Helper", %IteratorHelperPrototype%, « [[UnderlyingIterators]] »)。
  8. result.[[UnderlyingIterators]] 设置为 « iterated »。
  9. 返回 result

27.1.3.3.7 Iterator.prototype.forEach ( procedure )

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. 如果 obj 不是 Object,则抛出 TypeError 异常。
  3. iteratedIterator Record { [[Iterator]]: obj, [[NextMethod]]: undefined, [[Done]]: false }。
  4. 如果 IsCallable(procedure) 是 false,则
    1. errorThrowCompletion(一个新创建的 TypeError 对象)。
    2. 返回 ? IteratorClose(iterated, error)。
  5. iterated 设置为 ? GetIteratorDirect(obj)。
  6. counter 为 0。
  7. 重复,
    1. value 为 ? IteratorStepValue(iterated)。
    2. 如果 valuedone,则返回 undefined
    3. resultCompletion(Call(procedure, undefined, « value, 𝔽(counter) »))。
    4. IfAbruptCloseIterator(result, iterated)。
    5. counter 设置为 counter + 1。

27.1.3.3.8 Iterator.prototype.map ( mapper )

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. 如果 obj 不是 Object,则抛出 TypeError 异常。
  3. iteratedIterator Record { [[Iterator]]: obj, [[NextMethod]]: undefined, [[Done]]: false }。
  4. 如果 IsCallable(mapper) 是 false,则
    1. errorThrowCompletion(一个新创建的 TypeError 对象)。
    2. 返回 ? IteratorClose(iterated, error)。
  5. iterated 设置为 ? GetIteratorDirect(obj)。
  6. closure 为一个新的无参数 Abstract Closure,它捕获 iteratedmapper,并在被调用时执行以下步骤:
    1. counter 为 0。
    2. 重复,
      1. value 为 ? IteratorStepValue(iterated)。
      2. 如果 valuedone,则返回 ReturnCompletion(undefined)。
      3. mappedCompletion(Call(mapper, undefined, « value, 𝔽(counter) »))。
      4. IfAbruptCloseIterator(mapped, iterated)。
      5. completionCompletion(Yield(mapped))。
      6. IfAbruptCloseIterator(completion, iterated)。
      7. counter 设置为 counter + 1。
  7. resultCreateIteratorFromClosure(closure, "Iterator Helper", %IteratorHelperPrototype%, « [[UnderlyingIterators]] »)。
  8. result.[[UnderlyingIterators]] 设置为 « iterated »。
  9. 返回 result

27.1.3.3.9 Iterator.prototype.reduce ( reducer [ , initialValue ] )

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. 如果 obj 不是 Object,则抛出 TypeError 异常。
  3. iteratedIterator Record { [[Iterator]]: obj, [[NextMethod]]: undefined, [[Done]]: false }。
  4. 如果 IsCallable(reducer) 是 false,则
    1. errorThrowCompletion(一个新创建的 TypeError 对象)。
    2. 返回 ? IteratorClose(iterated, error)。
  5. iterated 设置为 ? GetIteratorDirect(obj)。
  6. 如果 initialValue 不存在,则
    1. accumulator 为 ? IteratorStepValue(iterated)。
    2. 如果 accumulatordone,则抛出 TypeError 异常。
    3. counter 为 1。
  7. 否则,
    1. accumulatorinitialValue
    2. counter 为 0。
  8. 重复,
    1. value 为 ? IteratorStepValue(iterated)。
    2. 如果 valuedone,则返回 accumulator
    3. resultCompletion(Call(reducer, undefined, « accumulator, value, 𝔽(counter) »))。
    4. IfAbruptCloseIterator(result, iterated)。
    5. accumulator 设置为 result
    6. counter 设置为 counter + 1。

27.1.3.3.10 Iterator.prototype.some ( predicate )

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. 如果 obj 不是 Object,则抛出 TypeError 异常。
  3. iteratedIterator Record { [[Iterator]]: obj, [[NextMethod]]: undefined, [[Done]]: false }。
  4. 如果 IsCallable(predicate) 是 false,则
    1. errorThrowCompletion(一个新创建的 TypeError 对象)。
    2. 返回 ? IteratorClose(iterated, error)。
  5. iterated 设置为 ? GetIteratorDirect(obj)。
  6. counter 为 0。
  7. 重复,
    1. value 为 ? IteratorStepValue(iterated)。
    2. 如果 valuedone,则返回 false
    3. resultCompletion(Call(predicate, undefined, « value, 𝔽(counter) »))。
    4. IfAbruptCloseIterator(result, iterated)。
    5. 如果 ToBoolean(result) 是 true,则返回 ? IteratorClose(iterated, NormalCompletion(true))。
    6. counter 设置为 counter + 1。

27.1.3.3.11 Iterator.prototype.take ( limit )

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. 如果 obj 不是 Object,则抛出 TypeError 异常。
  3. iteratedIterator Record { [[Iterator]]: obj, [[NextMethod]]: undefined, [[Done]]: false }。
  4. numberLimitCompletion(ToNumber(limit))。
  5. IfAbruptCloseIterator(numberLimit, iterated)。
  6. 如果 numberLimitNaN,则
    1. errorThrowCompletion(一个新创建的 RangeError 对象)。
    2. 返回 ? IteratorClose(iterated, error)。
  7. intLimit 为 ! ToIntegerOrInfinity(numberLimit)。
  8. 如果 intLimit < 0,则
    1. errorThrowCompletion(一个新创建的 RangeError 对象)。
    2. 返回 ? IteratorClose(iterated, error)。
  9. iterated 设置为 ? GetIteratorDirect(obj)。
  10. closure 为一个新的无参数 Abstract Closure,它捕获 iteratedintLimit,并在被调用时执行以下步骤:
    1. remainingintLimit
    2. 重复,
      1. 如果 remaining = 0,则
        1. 返回 ? IteratorClose(iterated, ReturnCompletion(undefined))。
      2. 如果 remaining ≠ +∞,则
        1. remaining 设置为 remaining - 1。
      3. value 为 ? IteratorStepValue(iterated)。
      4. 如果 valuedone,则返回 ReturnCompletion(undefined)。
      5. completionCompletion(Yield(value))。
      6. IfAbruptCloseIterator(completion, iterated)。
  11. resultCreateIteratorFromClosure(closure, "Iterator Helper", %IteratorHelperPrototype%, « [[UnderlyingIterators]] »)。
  12. result.[[UnderlyingIterators]] 设置为 « iterated »。
  13. 返回 result

27.1.3.3.12 Iterator.prototype.toArray ( )

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. 如果 obj 不是 Object,则抛出 TypeError 异常。
  3. iterated 为 ? GetIteratorDirect(obj)。
  4. items 为新的空 List
  5. 重复,
    1. value 为 ? IteratorStepValue(iterated)。
    2. 如果 valuedone,则返回 CreateArrayFromList(items)。
    3. value 追加到 items

27.1.3.3.13 Iterator.prototype [ %Symbol.dispose% ] ( )

调用此方法时,它执行以下步骤:

  1. objthis 值。
  2. return 为 ? GetMethod(obj, "return")。
  3. 如果 return 不是 undefined,则
    1. 执行 ? Call(return, obj)。
  4. 返回 undefined

此方法的 "name" 属性的值是 "[Symbol.dispose]"

27.1.3.3.14 Iterator.prototype [ %Symbol.iterator% ] ( )

此函数在被调用时执行以下步骤:

  1. 返回 this 值。

此函数的 "name" 属性的值是 "[Symbol.iterator]"

27.1.3.3.15 Iterator.prototype [ %Symbol.toStringTag% ]

Iterator.prototype[%Symbol.toStringTag%]访问器属性,其特性为 { [[Enumerable]]: false, [[Configurable]]: true }。[[Get]][[Set]] 特性定义如下:

27.1.3.3.15.1 get Iterator.prototype [ %Symbol.toStringTag% ]

[[Get]] 特性的值是一个不需要实参的内置函数。它在被调用时执行以下步骤:

  1. 返回 "Iterator"

27.1.3.3.15.2 set Iterator.prototype [ %Symbol.toStringTag% ]

[[Set]] 特性的值是一个接受实参 v 的内置函数。它在被调用时执行以下步骤:

  1. 执行 ? SetterThatIgnoresPrototypeProperties(this 值, %Iterator.prototype%, %Symbol.toStringTag%, v)。
  2. 返回 undefined
Note

不同于大多数内置原型上的 %Symbol.toStringTag% 属性,出于 Web 兼容性原因,此属性必须是访问器。

27.1.3.4 Iterator 的抽象操作

27.1.3.4.1 IteratorZip ( iters, mode, padding, finishResults )

The abstract operation IteratorZip takes arguments iters (a List of Iterator Records), mode ("shortest", "longest", or "strict"), padding (a List of ECMAScript language values), and finishResults (an Abstract Closure that takes a List of ECMAScript language values and returns an ECMAScript language value) and returns a Generator. It performs the following steps when called:

  1. iterCountiters 中元素的数量。
  2. openItersiters 的副本。
  3. closure 为一个新的无参数 Abstract Closure,它捕获 itersiterCountopenItersmodepaddingfinishResults,并在被调用时执行以下步骤:
    1. 如果 iterCount = 0,则返回 ReturnCompletion(undefined)。
    2. 重复,
      1. results 为新的空 List
      2. 断言:openIters 不是空。
      3. 对满足 0 ≤ i < iterCount 的每个整数 i,按升序执行:
        1. iteriters[i]。
        2. 如果 iternull,则
          1. 断言:mode"longest"
          2. resultpadding[i]。
        3. 否则,
          1. resultCompletion(IteratorStepValue(iter))。
          2. 如果 result 是 abrupt completion,则
            1. openIters 中移除 iter
            2. 返回 ? IteratorCloseAll(openIters, result)。
          3. result 设置为 ! result
          4. 如果 resultdone,则
            1. openIters 中移除 iter
            2. 如果 mode"shortest",则
              1. 返回 ? IteratorCloseAll(openIters, ReturnCompletion(undefined))。
            3. 否则,如果 mode"strict",则
              1. 如果 i ≠ 0,则
                1. 返回 ? IteratorCloseAll(openIters, ThrowCompletion(一个新创建的 TypeError 对象))。
              2. 对满足 1 ≤ k < iterCount 的每个整数 k,按升序执行:
                1. 断言:iters[k] 不是 null
                2. openCompletion(IteratorStep(iters[k]))。
                3. 如果 open 是 abrupt completion,则
                  1. openIters 中移除 iters[k]。
                  2. 返回 ? IteratorCloseAll(openIters, open)。
                4. open 设置为 ! open
                5. 如果 opendone,则
                  1. openIters 中移除 iters[k]。
                6. 否则,
                  1. 返回 ? IteratorCloseAll(openIters, ThrowCompletion(一个新创建的 TypeError 对象))。
              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. completionCompletion(Yield(results))。
      6. IfAbruptCloseIterators(completion, openIters)。
  4. genCreateIteratorFromClosure(closure, "Iterator Helper", %IteratorHelperPrototype%, « [[UnderlyingIterators]] »)。
  5. gen.[[UnderlyingIterators]] 设置为 openIters
  6. 返回 gen

27.1.4 %AsyncIteratorPrototype% 对象

%AsyncIteratorPrototype% 对象:

Note

本规范中定义的所有实现 async iterator 接口的对象也都继承自 %AsyncIteratorPrototype%。ECMAScript 代码也可以定义继承自 %AsyncIteratorPrototype% 的对象。%AsyncIteratorPrototype% 对象提供了一个位置,可在其中添加适用于所有 async iterator 对象的其他方法。

27.1.4.1 %AsyncIteratorPrototype% [ %Symbol.asyncDispose% ] ( )

调用此方法时,它执行以下步骤:

  1. objthis 值。
  2. promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  3. returnCompletion(GetMethod(obj, "return"))。
  4. IfAbruptRejectPromise(return, promiseCapability)。
  5. 如果 returnundefined,则
    1. 执行 ! Call(promiseCapability.[[Resolve]], undefined, « undefined »)。
  6. 否则,
    1. resultCompletion(Call(return, obj, « »))。
    2. IfAbruptRejectPromise(result, promiseCapability)。
    3. resultWrapperCompletion(PromiseResolve(%Promise%, result))。
    4. IfAbruptRejectPromise(resultWrapper, promiseCapability)。
    5. unwrap 为一个新的抽象闭包,该闭包没有参数,不捕获任何内容,并在被调用时执行以下步骤:
      1. 返回 undefined
    6. onFulfilledCreateBuiltinFunction(unwrap, 1, "", « »)。
    7. 执行 PerformPromiseThen(resultWrapper, onFulfilled, undefined, promiseCapability)。
  7. 返回 promiseCapability.[[Promise]]

此方法的 "name" 属性的值是 "[Symbol.asyncDispose]"

27.1.4.2 %AsyncIteratorPrototype% [ %Symbol.asyncIterator% ] ( )

此函数在被调用时执行以下步骤:

  1. 返回 this 值。

此函数的 "name" 属性的值是 "[Symbol.asyncIterator]"

27.1.5 Async-from-Sync Iterator 对象

Async-from-Sync Iterator 对象是一种 async iterator,用于适配特定的同步 iterator。ECMAScript 代码永远无法直接访问 Async-from-Sync Iterator 对象。Async-from-Sync Iterator 对象没有命名构造器。相反,Async-from-Sync Iterator 对象根据需要由 CreateAsyncFromSyncIterator 抽象操作创建。

27.1.5.1 CreateAsyncFromSyncIterator ( syncIteratorRecord )

The abstract operation CreateAsyncFromSyncIterator takes argument syncIteratorRecord (an Iterator Record) and returns an Iterator Record. 它用于从同步 Iterator Record 创建 async Iterator Record。 It performs the following steps when called:

  1. asyncIteratorOrdinaryObjectCreate(%AsyncFromSyncIteratorPrototype%, « [[SyncIteratorRecord]] »)。
  2. asyncIterator.[[SyncIteratorRecord]] 设置为 syncIteratorRecord
  3. nextMethod 为 ! Get(asyncIterator, "next")。
  4. iteratorRecordIterator Record { [[Iterator]]: asyncIterator, [[NextMethod]]: nextMethod, [[Done]]: false }。
  5. 返回 iteratorRecord

27.1.5.2 %AsyncFromSyncIteratorPrototype% 对象

%AsyncFromSyncIteratorPrototype% 对象:

27.1.5.2.1 %AsyncFromSyncIteratorPrototype%.next ( [ value ] )

  1. objthis 值。
  2. 断言:obj 是具有 [[SyncIteratorRecord]] 内部槽的 Object。
  3. promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  4. syncIteratorRecordobj.[[SyncIteratorRecord]]
  5. 如果 value 存在,则
    1. resultCompletion(IteratorNext(syncIteratorRecord, value))。
  6. 否则,
    1. resultCompletion(IteratorNext(syncIteratorRecord))。
  7. IfAbruptRejectPromise(result, promiseCapability)。
  8. 返回 AsyncFromSyncIteratorContinuation(result, promiseCapability, syncIteratorRecord, true)。

27.1.5.2.2 %AsyncFromSyncIteratorPrototype%.return ( [ value ] )

  1. objthis 值。
  2. 断言:obj 是具有 [[SyncIteratorRecord]] 内部槽的 Object。
  3. promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  4. syncIteratorRecordobj.[[SyncIteratorRecord]]
  5. syncIteratorsyncIteratorRecord.[[Iterator]]
  6. returnCompletion(GetMethod(syncIterator, "return"))。
  7. IfAbruptRejectPromise(return, promiseCapability)。
  8. 如果 returnundefined,则
    1. iteratorResultCreateIteratorResultObject(value, true)。
    2. 执行 ! Call(promiseCapability.[[Resolve]], undefined, « iteratorResult »)。
    3. 返回 promiseCapability.[[Promise]]
  9. 如果 value 存在,则
    1. resultCompletion(Call(return, syncIterator, « value »))。
  10. 否则,
    1. resultCompletion(Call(return, syncIterator))。
  11. IfAbruptRejectPromise(result, promiseCapability)。
  12. 如果 result 不是 Object,则
    1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « 一个新创建的 TypeError 对象 »)。
    2. 返回 promiseCapability.[[Promise]]
  13. 返回 AsyncFromSyncIteratorContinuation(result, promiseCapability, syncIteratorRecord, false)。

27.1.5.2.3 %AsyncFromSyncIteratorPrototype%.throw ( [ value ] )

Note
在本规范中,value 总是被提供,但为了与 %AsyncFromSyncIteratorPrototype%.return ( [ value ] ) 保持一致,仍将其保留为可选。
  1. objthis 值。
  2. 断言:obj 是具有 [[SyncIteratorRecord]] 内部槽的 Object。
  3. promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  4. syncIteratorRecordobj.[[SyncIteratorRecord]]
  5. syncIteratorsyncIteratorRecord.[[Iterator]]
  6. throwCompletion(GetMethod(syncIterator, "throw"))。
  7. IfAbruptRejectPromise(throw, promiseCapability)。
  8. 如果 throwundefined,则
    1. 注:如果 syncIterator 没有 throw 方法,则关闭它,使其在我们拒绝 capability 之前有机会进行清理。
    2. closeCompletionNormalCompletion(empty)。
    3. resultCompletion(IteratorClose(syncIteratorRecord, closeCompletion))。
    4. IfAbruptRejectPromise(result, promiseCapability)。
    5. 注:下一步抛出 TypeError,以指示存在协议违例:syncIterator 没有 throw 方法。
    6. 注:如果关闭 syncIterator 没有抛出异常,则该操作的结果会被忽略,即使它产生一个被拒绝的 promise。
    7. 执行 ! Call(promiseCapability.[[Reject]], undefined, « 一个新创建的 TypeError 对象 »)。
    8. 返回 promiseCapability.[[Promise]]
  9. 如果 value 存在,则
    1. resultCompletion(Call(throw, syncIterator, « value »))。
  10. 否则,
    1. resultCompletion(Call(throw, syncIterator))。
  11. IfAbruptRejectPromise(result, promiseCapability)。
  12. 如果 result 不是 Object,则
    1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « 一个新创建的 TypeError 对象 »)。
    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 实例最初创建时具有 Table 86 中列出的内部槽。

Table 86: Async-from-Sync Iterator 实例的内部槽
内部槽 类型 描述
[[SyncIteratorRecord]] Iterator Record 表示正在被适配的原始同步 iterator

27.1.5.4 AsyncFromSyncIteratorContinuation ( result, promiseCapability, syncIteratorRecord, closeOnRejection )

The abstract operation AsyncFromSyncIteratorContinuation takes arguments result (an Object), promiseCapability (a PromiseCapability Record for an intrinsic %Promise%), syncIteratorRecord (an Iterator Record), and closeOnRejection (a Boolean) and returns a Promise. It performs the following steps when called:

  1. 注:由于 promiseCapability 派生自固有 %Promise%,因此下面使用 IfAbruptRejectPromise 所导致的对 promiseCapability.[[Reject]] 的调用保证不会抛出。
  2. doneCompletion(IteratorComplete(result))。
  3. IfAbruptRejectPromise(done, promiseCapability)。
  4. valueCompletion(IteratorValue(result))。
  5. IfAbruptRejectPromise(value, promiseCapability)。
  6. valueWrapperCompletion(PromiseResolve(%Promise%, value))。
  7. 如果 valueWrapper 是 abrupt completion,donefalse,且 closeOnRejectiontrue,则
    1. valueWrapper 设置为 Completion(IteratorClose(syncIteratorRecord, valueWrapper))。
  8. IfAbruptRejectPromise(valueWrapper, promiseCapability)。
  9. unwrap 为一个新的 Abstract Closure,其参数为 (v),捕获 done,并在被调用时执行以下步骤:
    1. 返回 CreateIteratorResultObject(v, done)。
  10. onFulfilledCreateBuiltinFunction(unwrap, 1, "", « »)。
  11. 注:onFulfilled 用于在处理 IteratorResult 对象的 "value" 属性时等待其值(如果它是 promise),并将结果重新包装到新的“已解包”IteratorResult 对象中。
  12. 如果 donetruecloseOnRejectionfalse,则
    1. onRejectedundefined
  13. 否则,
    1. closeIterator 为一个新的 Abstract Closure,其参数为 (error),捕获 syncIteratorRecord,并在被调用时执行以下步骤:
      1. 返回 ? IteratorClose(syncIteratorRecord, ThrowCompletion(error))。
    2. onRejectedCreateBuiltinFunction(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 接口包含 Table 87 中描述的属性:

Table 87: Disposable 接口必需属性
属性 要求
%Symbol.dispose% 一个函数对象

调用此方法会通知 Disposable 对象:调用者不打算继续使用此对象。此方法应执行任何必要逻辑,以对资源执行显式清理,包括但不限于文件系统句柄、流、宿主对象等。当此方法抛出异常时,通常意味着无法显式释放该资源。

对同一个对象多次调用此方法时,应避免对已经处置的资源重复执行清理逻辑,并且不应抛出异常,即使第一次调用时曾抛出异常也是如此。不过,此要求不会被强制执行。

当通过 usingawait using 声明使用 Disposable 对象时,在直接包含该声明的 BlockModule 求值完成后,该资源将被自动处置。

27.2.1.2 AsyncDisposable 接口

AsyncDisposable 接口包含 Table 88 中描述的属性:

Table 88: AsyncDisposable 接口必需属性
属性 要求
%Symbol.asyncDispose% 一个返回 promise 的函数对象

调用此方法会通知 AsyncDisposable 对象:调用者不打算继续使用此对象。此方法应执行任何必要逻辑,以对资源执行显式清理,包括但不限于文件系统句柄、流、宿主对象等。当此方法返回的 promise 被拒绝时,通常意味着无法显式释放该资源。直到所得 Promise 被兑现前,AsyncDisposable 对象不被视为已“处置”。

对同一个对象多次调用此方法时,应避免对已经处置的资源重复执行清理逻辑,并且不应抛出异常或返回被拒绝的 promise,即使第一次调用时曾抛出异常或返回被拒绝的 promise 也是如此。不过,此要求不会被强制执行。

当通过 await using 声明使用 AsyncDisposable 对象时,在直接包含该声明的 BlockModule 求值完成后,该资源将被自动处置。

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]] 设置为一个新的空列表。
  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%
  • 具有一个值为 %Object.prototype%[[Prototype]] 内部槽。
  • 是一个普通对象
  • 没有 [[DisposableState]] 内部槽,也没有 DisposableStack 实例的任何其他内部槽。

27.3.3.1 DisposableStack.prototype.adopt ( value, onDispose )

调用此方法时,它执行以下步骤:

  1. disposableStackthis 值。
  2. 执行 ? RequireInternalSlot(disposableStack, [[DisposableState]])。
  3. 如果 disposableStack.[[DisposableState]]disposed,则抛出 ReferenceError 异常。
  4. 如果 IsCallable(onDispose) 是 false,则抛出 TypeError 异常。
  5. closure 为一个新的抽象闭包,该闭包没有参数,捕获 valueonDispose,并在被调用时执行以下步骤:
    1. 返回 ? Call(onDispose, undefined, « value »)。
  6. funcCreateBuiltinFunction(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. disposableStackthis 值。
  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. disposableStackthis 值。
  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. disposableStackthis 值。
  2. 执行 ? RequireInternalSlot(disposableStack, [[DisposableState]])。
  3. 如果 disposableStack.[[DisposableState]]disposed,则返回 true
  4. 返回 false

27.3.3.6 DisposableStack.prototype.move ( )

调用此方法时,它执行以下步骤:

  1. disposableStackthis 值。
  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]] 设置为一个新的空列表。
  8. disposableStack.[[DisposableState]] 设置为 disposed
  9. 返回 newDisposableStack

27.3.3.7 DisposableStack.prototype.use ( value )

调用此方法时,它执行以下步骤:

  1. disposableStackthis 值。
  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% 属性的初始值是 %DisposableStack.prototype.dispose%,定义于 27.3.3.4

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 实例最初创建时带有 Table 89 中描述的内部槽。

Table 89: DisposableStack 实例的内部槽
内部槽 类型 描述
[[DisposableState]] pendingdisposed 支配可处置栈将如何响应对其 %Symbol.dispose% 方法的传入调用。
[[DisposableResourceStack]] 一个 DisposableResource 记录的列表 在可处置栈被处置时要处置的资源。资源按其初始化顺序添加,并按相反顺序处置。

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]] 设置为一个新的空列表。
  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%
  • 具有一个值为 %Object.prototype%[[Prototype]] 内部槽。
  • 是一个普通对象
  • 没有 [[AsyncDisposableState]] 内部槽,也没有 AsyncDisposableStack 实例的任何其他内部槽。

27.4.3.1 AsyncDisposableStack.prototype.adopt ( value, onDisposeAsync )

调用此方法时,它执行以下步骤:

  1. asyncDisposableStackthis 值。
  2. 执行 ? RequireInternalSlot(asyncDisposableStack, [[AsyncDisposableState]])。
  3. 如果 asyncDisposableStack.[[AsyncDisposableState]]disposed,则抛出 ReferenceError 异常。
  4. 如果 IsCallable(onDisposeAsync) 是 false,则抛出 TypeError 异常。
  5. closure 为一个新的抽象闭包,该闭包没有参数,捕获 valueonDisposeAsync,并在被调用时执行以下步骤:
    1. 返回 ? Call(onDisposeAsync, undefined, « value »)。
  6. funcCreateBuiltinFunction(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. asyncDisposableStackthis 值。
  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 ( )

调用此 async 方法时,它执行以下步骤:

  1. asyncDisposableStackthis 值。
  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. asyncDisposableStackthis 值。
  2. 执行 ? RequireInternalSlot(asyncDisposableStack, [[AsyncDisposableState]])。
  3. 如果 asyncDisposableStack.[[AsyncDisposableState]]disposed,则返回 true
  4. 返回 false

27.4.3.6 AsyncDisposableStack.prototype.move ( )

调用此方法时,它执行以下步骤:

  1. asyncDisposableStackthis 值。
  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]] 设置为一个新的空列表。
  8. asyncDisposableStack.[[AsyncDisposableState]] 设置为 disposed
  9. 返回 newAsyncDisposableStack

27.4.3.7 AsyncDisposableStack.prototype.use ( value )

调用此方法时,它执行以下步骤:

  1. asyncDisposableStackthis 值。
  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% 属性的初始值是 %AsyncDisposableStack.prototype.disposeAsync%,定义于 27.4.3.4

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 实例最初创建时带有 Table 90 中描述的内部槽。

Table 90: AsyncDisposableStack 实例的内部槽
内部槽 类型 描述
[[AsyncDisposableState]] pendingdisposed 支配可处置栈将如何响应对其 %Symbol.asyncDispose% 方法的传入调用。
[[DisposableResourceStack]] 一个 DisposableResource 记录的列表 在可处置栈被处置时要处置的资源。资源按其初始化顺序添加,并按相反顺序处置。

27.5 Promise 对象

Promise 是一种对象,用作延迟(并且可能是异步的)计算最终结果的占位符。

任何 Promise 都处于三种互斥状态之一:已兑现已拒绝待定

  • 如果 p.then(f, r) 会立即入队一个 Job 来调用函数 f,则 promise p 已兑现。
  • 如果 p.then(f, r) 会立即入队一个 Job 来调用函数 r,则 promise p 已拒绝。
  • 如果 promise 既未兑现也未拒绝,则它是待定的。

如果 promise 不是待定的,即如果它已兑现或已拒绝,则称该 promise 已敲定

如果 promise 已敲定,或者它已被“锁定”为匹配另一个 promise 的状态,则该 promise 是已解决的。尝试解决或拒绝一个已解决的 promise 没有效果。如果 promise 不是已解决的,则它是未解决的。未解决的 promise 总是处于待定状态。已解决的 promise 可以是待定、已兑现或已拒绝。

27.5.1 Promise 抽象操作

27.5.1.1 PromiseCapability Record

PromiseCapability Record 是一种 Record 值,用于封装 Promise 或类 promise 对象,以及能够解决或拒绝该 promise 的函数。PromiseCapability Record 由 NewPromiseCapability 抽象操作产生。

PromiseCapability Record 具有 Table 91 中列出的字段。

Table 91: PromiseCapability Record 字段
字段名 含义
[[Promise]] Object 可用作 promise 的对象。
[[Resolve]] function object 用于解决给定 promise 的函数。
[[Reject]] function object 用于拒绝给定 promise 的函数。

27.5.1.1.1 IfAbruptRejectPromise ( value, capability )

IfAbruptRejectPromise 是一系列使用 PromiseCapability Record 的算法步骤的简写。形式如下的算法步骤:

  1. IfAbruptRejectPromise(value, capability)。

与以下内容含义相同:

  1. 断言:valueCompletion Record
  2. 如果 value 是 abrupt completion,则
    1. 执行 ? Call(capability.[[Reject]], undefined, « value.[[Value]] »)。
    2. 返回 capability.[[Promise]]
  3. value 设置为 ! value

27.5.1.2 PromiseReaction Record

PromiseReaction Record 是一种 Record 值,用于存储当 promise 以给定值变为已解决或已拒绝时应如何作出反应的信息。PromiseReaction Record 由 PerformPromiseThen 抽象操作创建,并由 NewPromiseReactionJob 返回的 Abstract Closure 使用。

PromiseReaction Record 具有 Table 92 中列出的字段。

Table 92: PromiseReaction Record 字段
字段名 含义
[[Capability]] PromiseCapability Recordundefined Record 为其提供 reaction handler 的 promise 的 capability。
[[Type]] fulfillreject [[Handler]]empty 时,[[Type]] 用于允许特定于敲定类型的行为。
[[Handler]] JobCallback Recordempty 应应用于传入值的函数,其返回值将支配派生 promise 会发生什么。如果 [[Handler]]empty,则改用一个取决于 [[Type]] 值的函数。

27.5.1.3 CreateResolvingFunctions ( toResolve )

The abstract operation CreateResolvingFunctions takes argument toResolve (a Promise) and returns a Record with fields [[Resolve]] (a function object) and [[Reject]] (a function object). It performs the following steps when called:

  1. promiseOrEmptyRecord { [[Value]]: toResolve }。
  2. resolveSteps 为一个新的 Abstract Closure,其参数为 (resolution),捕获 promiseOrEmpty,并在被调用时执行以下步骤:
    1. 如果 promiseOrEmpty.[[Value]]empty,则返回 undefined
    2. promisepromiseOrEmpty.[[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. thenCompletion(Get(resolution, "then"))。
    7. 如果 then 是 abrupt completion,则
      1. 执行 RejectPromise(promise, then.[[Value]])。
      2. 返回 undefined
    8. thenActionthen.[[Value]]
    9. 如果 IsCallable(thenAction) 是 false,则
      1. 执行 FulfillPromise(promise, resolution)。
      2. 返回 undefined
    10. thenJobCallbackHostMakeJobCallback(thenAction)。
    11. jobNewPromiseResolveThenableJob(promise, resolution, thenJobCallback)。
    12. 执行 HostEnqueuePromiseJob(job.[[Job]], job.[[Realm]])。
    13. 返回 undefined
  3. resolveCreateBuiltinFunction(resolveSteps, 1, "", « »)。
  4. rejectSteps 为一个新的 Abstract Closure,其参数为 (reason),捕获 promiseOrEmpty,并在被调用时执行以下步骤:
    1. 如果 promiseOrEmpty.[[Value]]empty,则返回 undefined
    2. promisepromiseOrEmpty.[[Value]]
    3. promiseOrEmpty.[[Value]] 设置为 empty
    4. 执行 RejectPromise(promise, reason)。
    5. 返回 undefined
  5. rejectCreateBuiltinFunction(rejectSteps, 1, "", « »)。
  6. 返回 Record { [[Resolve]]: resolve, [[Reject]]: reject }。

27.5.1.4 FulfillPromise ( promise, value )

The abstract operation FulfillPromise takes arguments promise (a Promise) and value (an ECMAScript language value) and returns unused. It performs the following steps when called:

  1. 断言:promise.[[PromiseState]]pending
  2. reactionspromise.[[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 )

The abstract operation NewPromiseCapability takes argument ctor (an ECMAScript language value) and returns either a normal completion containing a PromiseCapability Record or a throw completion. 它尝试以类似内置 Promise 构造器的方式,将 ctor 用作构造器来创建 promise,并提取其 resolvereject 函数。该 promise 加上 resolvereject 函数用于初始化新的 PromiseCapability Record。 It performs the following steps when called:

  1. 如果 IsConstructor(ctor) 是 false,则抛出 TypeError 异常。
  2. 注:假定 ctor 是支持 Promise 构造器参数约定的构造函数(见 27.5.3.1)。
  3. resolvingFuncsRecord { [[Resolve]]: undefined, [[Reject]]: undefined }。
  4. executorClosure 为一个新的 Abstract Closure,其参数为 (resolve, reject),捕获 resolvingFuncs,并在被调用时执行以下步骤:
    1. 如果 resolvingFuncs.[[Resolve]] 不是 undefined,则抛出 TypeError 异常。
    2. 如果 resolvingFuncs.[[Reject]] 不是 undefined,则抛出 TypeError 异常。
    3. resolvingFuncs.[[Resolve]] 设置为 resolve
    4. resolvingFuncs.[[Reject]] 设置为 reject
    5. 返回 NormalCompletion(undefined)。
  5. executorCreateBuiltinFunction(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]] }。
Note

抽象操作支持 Promise 子类化,因为它对任何会以与 Promise 构造器相同方式调用所传 executor 函数实参的构造器都是泛型的。它用于将 Promise 构造器的静态方法泛化到任何子类。

27.5.1.6 IsPromise ( arg )

The abstract operation IsPromise takes argument arg (an ECMAScript language value) and returns a Boolean. 它检查对象上的 promise 品牌。 It performs the following steps when called:

  1. 如果 arg 不是 Object,则返回 false
  2. 如果 arg 没有 [[PromiseState]] 内部槽,则返回 false
  3. 返回 true

27.5.1.7 RejectPromise ( promise, reason )

The abstract operation RejectPromise takes arguments promise (a Promise) and reason (an ECMAScript language value) and returns unused. It performs the following steps when called:

  1. 断言:promise.[[PromiseState]]pending
  2. reactionspromise.[[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 )

The abstract operation TriggerPromiseReactions takes arguments reactions (a List of PromiseReaction Records) and arg (an ECMAScript language value) and returns unused. 它为 reactions 中的每个 Record 入队一个新的 Job。每个这样的 Job 会处理 PromiseReaction Record[[Type]][[Handler]],并且如果 [[Handler]] 不是 empty,则以给定实参调用它。如果 [[Handler]]empty,则行为由 [[Type]] 决定。 It performs the following steps when called:

  1. reactions 的每个元素 reaction,执行:
    1. jobNewPromiseReactionJob(reaction, arg)。
    2. 执行 HostEnqueuePromiseJob(job.[[Job]], job.[[Realm]])。
  2. 返回 unused

27.5.1.9 HostPromiseRejectionTracker ( promise, operation )

The host-defined abstract operation HostPromiseRejectionTracker takes arguments promise (a Promise) and operation ("reject" or "handle") and returns unused. 它允许宿主环境跟踪 promise 拒绝。

HostPromiseRejectionTracker 的默认实现是返回 unused

Note 1

HostPromiseRejectionTracker 在两种场景中被调用:

  • 当 promise 在没有任何 handler 的情况下被拒绝时,它会以 operation 实参设置为 "reject" 被调用。
  • 当第一次向已拒绝的 promise 添加 handler 时,它会以 operation 实参设置为 "handle" 被调用。

HostPromiseRejectionTracker 的典型实现可能会尝试向开发者通知未处理的拒绝,同时也会小心地在这类先前通知之后因附加新 handler 而失效时通知开发者。

Note 2

如果 operation"handle",实现不应以会干扰垃圾回收的方式持有对 promise 的引用。如果 operation"reject",则实现可以持有对 promise 的引用,因为预期拒绝是少见的,并且不在热代码路径上。

27.5.2 Promise Job

27.5.2.1 NewPromiseReactionJob ( reaction, arg )

The abstract operation NewPromiseReactionJob takes arguments reaction (a PromiseReaction Record) and arg (an ECMAScript language value) and returns a Record with fields [[Job]] (a Job Abstract Closure) and [[Realm]] (a Realm Record or null). 它返回一个新的 Job Abstract Closure,该 Closure 会将适当的 handler 应用于传入值,并使用该 handler 的返回值来解决或拒绝与该 handler 关联的派生 promise。 It performs the following steps when called:

  1. job 为一个新的无参数 Job Abstract Closure,它捕获 reactionarg,并在被调用时执行以下步骤:
    1. promiseCapabilityreaction.[[Capability]]
    2. typereaction.[[Type]]
    3. handlerreaction.[[Handler]]
    4. 如果 handlerempty,则
      1. 如果 typefulfill,则
        1. handlerResultNormalCompletion(arg)。
      2. 否则,
        1. 断言:typereject
        2. handlerResultThrowCompletion(arg)。
    5. 否则,
      1. handlerResultCompletion(HostCallJobCallback(handler, undefined, « arg »))。
    6. 如果 promiseCapabilityundefined,则
      1. 断言:handlerResult 不是 abrupt completion。
      2. 返回 empty
    7. 断言:promiseCapabilityPromiseCapability Record
    8. 如果 handlerResult 是 abrupt completion,则
      1. 返回 ? Call(promiseCapability.[[Reject]], undefined, « handlerResult.[[Value]] »)。
    9. 返回 ? Call(promiseCapability.[[Resolve]], undefined, « handlerResult.[[Value]] »)。
  2. handlerRealmnull
  3. 如果 reaction.[[Handler]] 不是 empty,则
    1. getHandlerRealmResultCompletion(GetFunctionRealm(reaction.[[Handler]].[[Callback]]))。
    2. 如果 getHandlerRealmResult 是 normal completion,则将 handlerRealm 设置为 getHandlerRealmResult.[[Value]]
    3. 否则,将 handlerRealm 设置为当前 Realm Record
    4. 注:除非 handler 是 undefined,否则 handlerRealm 永远不是 null。当 handler 是已撤销 Proxy 且没有 ECMAScript 代码运行时,handlerRealm 用于创建错误对象。
  4. 返回 Record { [[Job]]: job, [[Realm]]: handlerRealm }。

27.5.2.2 NewPromiseResolveThenableJob ( promiseToResolve, thenable, then )

The abstract operation NewPromiseResolveThenableJob takes arguments promiseToResolve (a Promise), thenable (an Object), and then (a JobCallback Record) and returns a Record with fields [[Job]] (a Job Abstract Closure) and [[Realm]] (a Realm Record). It performs the following steps when called:

  1. job 为一个新的无参数 Job Abstract Closure,它捕获 promiseToResolvethenablethen,并在被调用时执行以下步骤:
    1. resolvingFuncsCreateResolvingFunctions(promiseToResolve)。
    2. thenCallResultCompletion(HostCallJobCallback(then, thenable, « resolvingFuncs.[[Resolve]], resolvingFuncs.[[Reject]] »))。
    3. 如果 thenCallResult 是 abrupt completion,则
      1. 返回 ? Call(resolvingFuncs.[[Reject]], undefined, « thenCallResult.[[Value]] »)。
    4. 返回 ! thenCallResult
  2. getThenRealmResultCompletion(GetFunctionRealm(then.[[Callback]]))。
  3. 如果 getThenRealmResult 是 normal completion,则令 thenRealmgetThenRealmResult.[[Value]]
  4. 否则,令 thenRealm当前 Realm Record
  5. 注:thenRealm 永远不是 null。当 then.[[Callback]] 是已撤销 Proxy 且没有代码运行时,thenRealm 用于创建错误对象。
  6. 返回 Record { [[Job]]: job, [[Realm]]: thenRealm }。
Note

Job 使用所提供的 thenable 及其 then 方法来解决给定 promise。此过程必须作为 Job 发生,以确保 then 方法的求值发生在任何 surrounding code 的求值完成之后。

27.5.3 Promise 构造器

Promise 构造器:

  • %Promise%
  • 全局对象"Promise" 属性的初始值。
  • 在作为构造器调用时创建并初始化一个新的 Promise。
  • 不意图作为函数调用,并且以这种方式调用时会抛出异常。
  • 可以用作类定义的 extends 子句中的值。打算继承指定 Promise 行为的子类构造函数,必须包含一次对 Promise 构造函数super 调用,以创建并初始化子类实例,使其具备支持 PromisePromise.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. resolvingFuncsCreateResolvingFunctions(promise)。
  10. completionCompletion(Call(executor, undefined, « resolvingFuncs.[[Resolve]], resolvingFuncs.[[Reject]] »))。
  11. 如果 completion 是 abrupt completion,则
    1. 执行 ? Call(resolvingFuncs.[[Reject]], undefined, « completion.[[Value]] »)。
  12. 返回 promise
Note

executor 实参必须是 function object。它被调用以启动和报告此 Promise 所表示的可能延迟动作的完成情况。executor 以两个实参调用:resolvereject。这些函数可由 executor 函数使用,以报告延迟计算的最终完成或失败。从 executor 函数返回并不表示延迟动作已完成,而只表示最终执行该延迟动作的请求已被接受。

传给 executor 函数的 resolve 函数接受单个实参。executor 代码最终可以调用 resolve 函数,以指示它希望解决关联的 Promise。传给 resolve 函数的实参表示延迟动作的最终值,可以是实际的兑现值,也可以是另一个 promise,如果该 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. ctorthis 值。
  2. promiseCapability 为 ? NewPromiseCapability(ctor)。
  3. promiseResolveCompletion(GetPromiseResolve(ctor))。
  4. IfAbruptRejectPromise(promiseResolve, promiseCapability)。
  5. iteratorRecordCompletion(GetIterator(iterable, sync))。
  6. IfAbruptRejectPromise(iteratorRecord, promiseCapability)。
  7. resultCompletion(PerformPromiseAll(iteratorRecord, ctor, promiseCapability, promiseResolve))。
  8. 如果 result 是 abrupt completion,则
    1. 如果 iteratorRecord.[[Done]]false,则将 result 设置为 Completion(IteratorClose(iteratorRecord, result))。
    2. IfAbruptRejectPromise(result, promiseCapability)。
  9. 返回 ! result
Note

此函数要求其 this 值是支持 Promise 构造器参数约定的构造函数

27.5.4.1.1 GetPromiseResolve ( promiseCtor )

The abstract operation GetPromiseResolve takes argument promiseCtor (a constructor) and returns either a normal completion containing a function object or a throw completion. It performs the following steps when called:

  1. promiseResolve 为 ? Get(promiseCtor, "resolve")。
  2. 如果 IsCallable(promiseResolve) 是 false,则抛出 TypeError 异常。
  3. 返回 promiseResolve

27.5.4.1.2 PerformPromiseAll ( iteratorRecord, ctor, resultCapability, promiseResolve )

The abstract operation PerformPromiseAll takes arguments iteratorRecord (an Iterator Record), ctor (a constructor), resultCapability (a PromiseCapability Record), and promiseResolve (a function object) and returns either a normal completion containing an Object or a throw completion. It performs the following steps when called:

  1. values 为新的空 List
  2. 注:remainingElementsCount 从 1 而不是 0 开始,以确保 resultCapability.[[Resolve]] 只被调用一次,即使存在行为不当的 "then" 在输入 iterator 耗尽之前调用传入的回调。
  3. remainingElementsCountRecord { [[Value]]: 1 }。
  4. index 为 0。
  5. 重复,
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 nextdone,则
      1. remainingElementsCount.[[Value]] 设置为 remainingElementsCount.[[Value]] - 1。
      2. 如果 remainingElementsCount.[[Value]] = 0,则
        1. valuesArrayCreateArrayFromList(values)。
        2. 执行 ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »)。
      3. 返回 resultCapability.[[Promise]]
    3. undefined 追加到 values
    4. nextPromise 为 ? Call(promiseResolve, ctor, « next »)。
    5. fulfilledSteps 为一个新的 Abstract Closure,其参数为 (value),捕获 valuesresultCapabilityremainingElementsCount,并在被调用时执行以下步骤:
      1. activeFunc活动函数对象
      2. 如果 activeFunc.[[AlreadyCalled]]true,则返回 undefined
      3. activeFunc.[[AlreadyCalled]] 设置为 true
      4. thisIndexactiveFunc.[[Index]]
      5. values[thisIndex] 设置为 value
      6. remainingElementsCount.[[Value]] 设置为 remainingElementsCount.[[Value]] - 1。
      7. 如果 remainingElementsCount.[[Value]] = 0,则
        1. valuesArrayCreateArrayFromList(values)。
        2. 返回 ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »)。
      8. 返回 undefined
    6. onFulfilledCreateBuiltinFunction(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. ctorthis 值。
  2. promiseCapability 为 ? NewPromiseCapability(ctor)。
  3. promiseResolveCompletion(GetPromiseResolve(ctor))。
  4. IfAbruptRejectPromise(promiseResolve, promiseCapability)。
  5. iteratorRecordCompletion(GetIterator(iterable, sync))。
  6. IfAbruptRejectPromise(iteratorRecord, promiseCapability)。
  7. resultCompletion(PerformPromiseAllSettled(iteratorRecord, ctor, promiseCapability, promiseResolve))。
  8. 如果 result 是 abrupt completion,则
    1. 如果 iteratorRecord.[[Done]]false,则将 result 设置为 Completion(IteratorClose(iteratorRecord, result))。
    2. IfAbruptRejectPromise(result, promiseCapability)。
  9. 返回 ! result
Note

此函数要求其 this 值是支持 Promise 构造器参数约定的构造函数

27.5.4.2.1 PerformPromiseAllSettled ( iteratorRecord, ctor, resultCapability, promiseResolve )

The abstract operation PerformPromiseAllSettled takes arguments iteratorRecord (an Iterator Record), ctor (a constructor), resultCapability (a PromiseCapability Record), and promiseResolve (a function object) and returns either a normal completion containing an Object or a throw completion. It performs the following steps when called:

  1. values 为新的空 List
  2. 注:remainingElementsCount 从 1 而不是 0 开始,以确保 resultCapability.[[Resolve]] 只被调用一次,即使存在行为不当的 "then" 在输入 iterator 耗尽之前调用传入的某个回调。
  3. remainingElementsCountRecord { [[Value]]: 1 }。
  4. index 为 0。
  5. 重复,
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 nextdone,则
      1. remainingElementsCount.[[Value]] 设置为 remainingElementsCount.[[Value]] - 1。
      2. 如果 remainingElementsCount.[[Value]] = 0,则
        1. valuesArrayCreateArrayFromList(values)。
        2. 执行 ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »)。
      3. 返回 resultCapability.[[Promise]]
    3. undefined 追加到 values
    4. nextPromise 为 ? Call(promiseResolve, ctor, « next »)。
    5. alreadyCalledRecord { [[Value]]: false }。
    6. fulfilledSteps 为一个新的 Abstract Closure,其参数为 (value),捕获 valuesresultCapabilityremainingElementsCount,并在被调用时执行以下步骤:
      1. activeFunc活动函数对象
      2. 如果 activeFunc.[[AlreadyCalled]].[[Value]]true,则返回 undefined
      3. activeFunc.[[AlreadyCalled]].[[Value]] 设置为 true
      4. objOrdinaryObjectCreate(%Object.prototype%)。
      5. 执行 ! CreateDataPropertyOrThrow(obj, "status", "fulfilled")。
      6. 执行 ! CreateDataPropertyOrThrow(obj, "value", value)。
      7. thisIndexactiveFunc.[[Index]]
      8. values[thisIndex] 设置为 obj
      9. remainingElementsCount.[[Value]] 设置为 remainingElementsCount.[[Value]] - 1。
      10. 如果 remainingElementsCount.[[Value]] = 0,则
        1. valuesArrayCreateArrayFromList(values)。
        2. 返回 ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »)。
      11. 返回 undefined
    7. onFulfilledCreateBuiltinFunction(fulfilledSteps, 1, "", « [[AlreadyCalled]], [[Index]] »)。
    8. onFulfilled.[[AlreadyCalled]] 设置为 alreadyCalled
    9. onFulfilled.[[Index]] 设置为 index
    10. rejectedSteps 为一个新的 Abstract Closure,其参数为 (error),捕获 valuesresultCapabilityremainingElementsCount,并在被调用时执行以下步骤:
      1. activeFunc活动函数对象
      2. 如果 activeFunc.[[AlreadyCalled]].[[Value]]true,则返回 undefined
      3. activeFunc.[[AlreadyCalled]].[[Value]] 设置为 true
      4. objOrdinaryObjectCreate(%Object.prototype%)。
      5. 执行 ! CreateDataPropertyOrThrow(obj, "status", "rejected")。
      6. 执行 ! CreateDataPropertyOrThrow(obj, "reason", error)。
      7. thisIndexactiveFunc.[[Index]]
      8. values[thisIndex] 设置为 obj
      9. remainingElementsCount.[[Value]] 设置为 remainingElementsCount.[[Value]] - 1。
      10. 如果 remainingElementsCount.[[Value]] = 0,则
        1. valuesArrayCreateArrayFromList(values)。
        2. 返回 ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »)。
      11. 返回 undefined
    11. onRejectedCreateBuiltinFunction(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. ctorthis 值。
  2. promiseCapability 为 ? NewPromiseCapability(ctor)。
  3. promiseResolveCompletion(GetPromiseResolve(ctor))。
  4. IfAbruptRejectPromise(promiseResolve, promiseCapability)。
  5. iteratorRecordCompletion(GetIterator(iterable, sync))。
  6. IfAbruptRejectPromise(iteratorRecord, promiseCapability)。
  7. resultCompletion(PerformPromiseAny(iteratorRecord, ctor, promiseCapability, promiseResolve))。
  8. 如果 result 是 abrupt completion,则
    1. 如果 iteratorRecord.[[Done]]false,则将 result 设置为 Completion(IteratorClose(iteratorRecord, result))。
    2. IfAbruptRejectPromise(result, promiseCapability)。
  9. 返回 ! result
Note

此函数要求其 this 值是支持 Promise 构造器参数约定的构造函数

27.5.4.3.1 PerformPromiseAny ( iteratorRecord, ctor, resultCapability, promiseResolve )

The abstract operation PerformPromiseAny takes arguments iteratorRecord (an Iterator Record), ctor (a constructor), resultCapability (a PromiseCapability Record), and promiseResolve (a function object) and returns either a normal completion containing an Object or a throw completion. It performs the following steps when called:

  1. errors 为新的空 List
  2. 注:remainingElementsCount 从 1 而不是 0 开始,以确保 resultCapability.[[Reject]] 只被调用一次,即使存在行为不当的 "then" 在输入 iterator 耗尽之前调用传入的回调。
  3. remainingElementsCountRecord { [[Value]]: 1 }。
  4. index 为 0。
  5. 重复,
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 nextdone,则
      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 为一个新的 Abstract Closure,其参数为 (error),捕获 errorsresultCapabilityremainingElementsCount,并在被调用时执行以下步骤:
      1. activeFunc活动函数对象
      2. 如果 activeFunc.[[AlreadyCalled]]true,则返回 undefined
      3. activeFunc.[[AlreadyCalled]] 设置为 true
      4. thisIndexactiveFunc.[[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. onRejectedCreateBuiltinFunction(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 相同。它在运行此算法时会将所传 iterable 的所有元素解决为 promise。

  1. ctorthis 值。
  2. promiseCapability 为 ? NewPromiseCapability(ctor)。
  3. promiseResolveCompletion(GetPromiseResolve(ctor))。
  4. IfAbruptRejectPromise(promiseResolve, promiseCapability)。
  5. iteratorRecordCompletion(GetIterator(iterable, sync))。
  6. IfAbruptRejectPromise(iteratorRecord, promiseCapability)。
  7. resultCompletion(PerformPromiseRace(iteratorRecord, ctor, promiseCapability, promiseResolve))。
  8. 如果 result 是 abrupt completion,则
    1. 如果 iteratorRecord.[[Done]]false,则将 result 设置为 Completion(IteratorClose(iteratorRecord, result))。
    2. IfAbruptRejectPromise(result, promiseCapability)。
  9. 返回 ! result
Note 1

如果 iterable 实参不产生任何值,或者如果 iterable 产生的 promise 都永远不敲定,则此方法返回的待定 promise 永远不会被敲定。

Note 2

此函数期望其 this 值是支持 Promise 构造器参数约定的构造函数。它还期望其 this 值提供 resolve 方法。

27.5.4.5.1 PerformPromiseRace ( iteratorRecord, ctor, resultCapability, promiseResolve )

The abstract operation PerformPromiseRace takes arguments iteratorRecord (an Iterator Record), ctor (a constructor), resultCapability (a PromiseCapability Record), and promiseResolve (a function object) and returns either a normal completion containing an Object or a throw completion. It performs the following steps when called:

  1. 重复,
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 nextdone,则
      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. ctorthis 值。
  2. promiseCapability 为 ? NewPromiseCapability(ctor)。
  3. 执行 ? Call(promiseCapability.[[Reject]], undefined, « reason »)。
  4. 返回 promiseCapability.[[Promise]]
Note

此函数期望其 this 值是支持 Promise 构造器参数约定的构造函数

27.5.4.7 Promise.resolve ( resolution )

此函数要么返回一个以所传实参解决的新 promise,要么如果该实参是由此构造器产生的 promise,则返回该实参自身。

  1. ctorthis 值。
  2. 如果 ctor 不是 Object,则抛出 TypeError 异常。
  3. 返回 ? PromiseResolve(ctor, resolution)。
Note

此函数期望其 this 值是支持 Promise 构造器参数约定的构造函数

27.5.4.7.1 PromiseResolve ( ctor, resolution )

The abstract operation PromiseResolve takes arguments ctor (an Object) and resolution (an ECMAScript language value) and returns either a normal completion containing an Object or a throw completion. 它返回一个以 resolution 解决的新 promise。 It performs the following steps when called:

  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. ctorthis 值。
  2. 如果 ctor 不是 Object,则抛出 TypeError 异常。
  3. promiseCapability 为 ? NewPromiseCapability(ctor)。
  4. statusCompletion(Call(callback, undefined, args))。
  5. 如果 status 是 abrupt completion,则
    1. 执行 ? Call(promiseCapability.[[Reject]], undefined, « status.[[Value]] »)。
  6. 否则,
    1. 执行 ? Call(promiseCapability.[[Resolve]], undefined, « status.[[Value]] »)。
  7. 返回 promiseCapability.[[Promise]]
Note

此函数期望其 this 值是支持 Promise 构造器参数约定的构造函数

27.5.4.9 Promise.withResolvers ( )

此函数返回一个具有三个属性的对象:一个新的 promise,以及与其关联的 resolvereject 函数。

  1. ctorthis 值。
  2. promiseCapability 为 ? NewPromiseCapability(ctor)。
  3. objOrdinaryObjectCreate(%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 值。

此函数的 "name" 属性的值是 "get [Symbol.species]"

Note

Promise 原型方法通常使用其 this 值的构造器来创建派生对象。不过,子类构造器可以通过重新定义其 %Symbol.species% 属性来覆盖该默认行为。

27.5.5 Promise 原型对象的属性

Promise 原型对象

  • %Promise.prototype%
  • 具有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%
  • 普通对象
  • 没有 [[PromiseState]] 内部槽,也没有 Promise 实例的任何其他内部槽。

27.5.5.1 Promise.prototype.catch ( onRejected )

此方法在被调用时执行以下步骤:

  1. promisethis 值。
  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. promisethis 值。
  2. 如果 promise 不是 Object,则抛出 TypeError 异常。
  3. ctor 为 ? SpeciesConstructor(promise, %Promise%)。
  4. 断言:IsConstructor(ctor) 是 true
  5. 如果 IsCallable(onFinally) 是 false,则
    1. thenFinallyonFinally
    2. catchFinallyonFinally
  6. 否则,
    1. thenFinallyClosure 为一个新的 Abstract Closure,其参数为 (value),捕获 onFinallyctor,并在被调用时执行以下步骤:
      1. result 为 ? Call(onFinally, undefined)。
      2. p 为 ? PromiseResolve(ctor, result)。
      3. returnValue 为一个新的无参数 Abstract Closure,它捕获 value,并在被调用时执行以下步骤:
        1. 返回 NormalCompletion(value)。
      4. valueThunkCreateBuiltinFunction(returnValue, 0, "", « »)。
      5. 返回 ? Invoke(p, "then", « valueThunk »)。
    2. thenFinallyCreateBuiltinFunction(thenFinallyClosure, 1, "", « »)。
    3. catchFinallyClosure 为一个新的 Abstract Closure,其参数为 (reason),捕获 onFinallyctor,并在被调用时执行以下步骤:
      1. result 为 ? Call(onFinally, undefined)。
      2. p 为 ? PromiseResolve(ctor, result)。
      3. throwReason 为一个新的无参数 Abstract Closure,它捕获 reason,并在被调用时执行以下步骤:
        1. 抛出 reason
      4. throwerCreateBuiltinFunction(throwReason, 0, "", « »)。
      5. 返回 ? Invoke(p, "then", « thrower »)。
    4. catchFinallyCreateBuiltinFunction(catchFinallyClosure, 1, "", « »)。
  7. 返回 ? Invoke(promise, "then", « thenFinally, catchFinally »)。

27.5.5.4 Promise.prototype.then ( onFulfilled, onRejected )

此方法在被调用时执行以下步骤:

  1. promisethis 值。
  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 ] )

The abstract operation PerformPromiseThen takes arguments promise (a Promise), onFulfilled (an ECMAScript language value), and onRejected (an ECMAScript language value) and optional argument resultCapability (a PromiseCapability Record) and returns an Object or undefined. 它使用 onFulfilledonRejected 作为 promise 的敲定动作,对 promise 执行 “then” 操作。如果传入了 resultCapability,则结果通过更新 resultCapability 的 promise 来存储。如果未传入,则 PerformPromiseThen 是由规范内部操作调用,其结果并不重要。 It performs the following steps when called:

  1. 断言:IsPromise(promise) 是 true
  2. 如果 resultCapability 不存在,则
    1. resultCapability 设置为 undefined
  3. 如果 IsCallable(onFulfilled) 是 false,则
    1. onFulfilledJobCallbackempty
  4. 否则,
    1. onFulfilledJobCallbackHostMakeJobCallback(onFulfilled)。
  5. 如果 IsCallable(onRejected) 是 false,则
    1. onRejectedJobCallbackempty
  6. 否则,
    1. onRejectedJobCallbackHostMakeJobCallback(onRejected)。
  7. fulfillReactionPromiseReaction Record { [[Capability]]: resultCapability, [[Type]]: fulfill, [[Handler]]: onFulfilledJobCallback }。
  8. rejectReactionPromiseReaction Record { [[Capability]]: resultCapability, [[Type]]: reject, [[Handler]]: onRejectedJobCallback }。
  9. 如果 promise.[[PromiseState]]pending,则
    1. fulfillReaction 追加到 promise.[[PromiseFulfillReactions]]
    2. rejectReaction 追加到 promise.[[PromiseRejectReactions]]
  10. 否则,如果 promise.[[PromiseState]]fulfilled,则
    1. valuepromise.[[PromiseResult]]
    2. fulfillJobNewPromiseReactionJob(fulfillReaction, value)。
    3. 执行 HostEnqueuePromiseJob(fulfillJob.[[Job]], fulfillJob.[[Realm]])。
  11. 否则,
    1. 断言:promise.[[PromiseState]]rejected
    2. reasonpromise.[[PromiseResult]]
    3. 如果 promise.[[PromiseIsHandled]]false,则执行 HostPromiseRejectionTracker(promise, "handle")。
    4. rejectJobNewPromiseReactionJob(rejectReaction, reason)。
    5. 执行 HostEnqueuePromiseJob(rejectJob.[[Job]], rejectJob.[[Realm]])。
  12. promise.[[PromiseIsHandled]] 设置为 true
  13. 如果 resultCapabilityundefined,则返回 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 实例最初创建时具有 Table 93 中描述的内部槽。

Table 93: Promise 实例的内部槽
内部槽 类型 描述
[[PromiseState]] pending, fulfilled, or rejected 支配 promise 将如何对传入的 then 方法调用作出反应。
[[PromiseResult]] ECMAScript 语言值empty promise 已被兑现或拒绝所用的值(如果有)。当且仅当 [[PromiseState]]pending 时为 empty
[[PromiseFulfillReactions]] PromiseReaction RecordList 当/如果 promise 从 pending 状态转换到 fulfilled 状态时要处理的 Record
[[PromiseRejectReactions]] PromiseReaction RecordList 当/如果 promise 从 pending 状态转换到 rejected 状态时要处理的 Record
[[PromiseIsHandled]] Boolean 指示 promise 是否曾经具有兑现或拒绝 handler;用于未处理拒绝跟踪。

27.6 GeneratorFunction 对象

GeneratorFunction 是通常通过求值 GeneratorDeclarationGeneratorExpressionGeneratorMethod 创建的函数。它们也可以通过调用 %GeneratorFunction% 固有对象来创建。

Figure 6 (Informative): Generator 对象关系
大量纵横交错的框和箭头。

27.6.1 GeneratorFunction 构造器

GeneratorFunction 构造器:

  • %GeneratorFunction%
  • Function 的子类。
  • 在作为函数而不是构造器调用时创建并初始化一个新的 GeneratorFunction。因此,函数调用 GeneratorFunction (…) 等价于具有相同实参的对象创建表达式 new GeneratorFunction (…)
  • 可以用作类定义的 extends 子句的值。意图继承指定 GeneratorFunction 行为的子类构造器,必须包含对 GeneratorFunction 构造器的 super 调用,以创建并初始化具有内置 GeneratorFunction 行为所需内部槽的子类实例。所有用于定义 generator function 对象的 ECMAScript 语法形式都会创建 GeneratorFunction 的直接实例。没有语法方式可以创建 GeneratorFunction 子类的实例。

27.6.1.1 GeneratorFunction ( ...paramArgs, bodyArg )

最后一个实参(如果有)指定 generator function 的主体(可执行代码);任何在前的实参指定形式参数。

此函数在被调用时执行以下步骤:

  1. activeFunc活动函数对象
  2. 如果 bodyArg 不存在,则将 bodyArg 设置为空 String。
  3. 返回 ? CreateDynamicFunction(activeFunc, NewTarget, generator, paramArgs, bodyArg)。
Note

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 函数对象,并且具有 Table 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 function 的 "prototype" 属性的初始值。当使用 [[Call]] 调用 generator function 对象时,该 prototype 属性的值用于初始化新创建的 Generator 的 [[Prototype]] 内部槽。

此属性具有特性 { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }。

Note

不同于 Function 实例,作为 GeneratorFunction 的 "prototype" 属性值的对象没有一个值为该 GeneratorFunction 实例的 "constructor" 属性。

27.7 AsyncGeneratorFunction 对象

AsyncGeneratorFunction 是通常通过求值 AsyncGeneratorDeclarationAsyncGeneratorExpressionAsyncGeneratorMethod 语法产生式创建的函数。它们也可以通过调用 %AsyncGeneratorFunction% 固有对象来创建。

27.7.1 AsyncGeneratorFunction 构造器

AsyncGeneratorFunction 构造器:

  • %AsyncGeneratorFunction%
  • Function 的子类。
  • 在作为函数而不是构造器调用时创建并初始化一个新的 AsyncGeneratorFunction。因此,函数调用 AsyncGeneratorFunction (...) 等价于具有相同实参的对象创建表达式 new AsyncGeneratorFunction (...)
  • 可以用作类定义的 extends 子句的值。意图继承指定 AsyncGeneratorFunction 行为的子类构造器,必须包含对 AsyncGeneratorFunction 构造器的 super 调用,以创建并初始化具有内置 AsyncGeneratorFunction 行为所需内部槽的子类实例。所有用于定义 async generator function 对象的 ECMAScript 语法形式都会创建 AsyncGeneratorFunction 的直接实例。没有语法方式可以创建 AsyncGeneratorFunction 子类的实例。

27.7.1.1 AsyncGeneratorFunction ( ...paramArgs, bodyArg )

最后一个实参(如果有)指定 async generator function 的主体(可执行代码);任何在前的实参指定形式参数。

此函数在被调用时执行以下步骤:

  1. activeFunc活动函数对象
  2. 如果 bodyArg 不存在,则将 bodyArg 设置为空 String。
  3. 返回 ? CreateDynamicFunction(activeFunc, NewTarget, async-generator, paramArgs, bodyArg)。
Note

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 函数对象,并且具有 Table 26 中列出的内部槽。所有这类实例的 [[IsClassConstructor]] 内部槽的值都是 false

每个 AsyncGeneratorFunction 实例具有以下自有属性:

27.7.4.1 length

"length" 属性的值是一个整数 Number,指示 AsyncGeneratorFunction 通常期望的实参数量。不过,语言允许以其他数量的实参调用函数。当 AsyncGeneratorFunction 以不同于其 "length" 属性所指定数量的实参数量调用时,其行为取决于该函数。

此属性具有特性 { [[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 function 的 "prototype" 属性的初始值。当使用 [[Call]] 调用 generator function 对象时,该 prototype 属性的值用于初始化新创建的 AsyncGenerator 的 [[Prototype]] 内部槽。

此属性具有特性 { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }。

Note

不同于 function 实例,作为 AsyncGeneratorFunction 的 "prototype" 属性值的对象没有一个值为该 AsyncGeneratorFunction 实例的 "constructor" 属性。

27.8 Generator 对象

Generator 通过调用 generator function 创建,并且同时符合 iterator 接口iterable 接口

Generator 实例直接继承创建该实例的 generator function 的 "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, empty)。

27.8.1.3 %GeneratorPrototype%.return ( value )

此方法在被调用时执行以下步骤:

  1. genthis 值。
  2. completionReturnCompletion(value)。
  3. 返回 ? GeneratorResumeAbrupt(gen, completion, empty)。

27.8.1.4 %GeneratorPrototype%.throw ( exception )

此方法在被调用时执行以下步骤:

  1. genthis 值。
  2. completionThrowCompletion(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 实例最初创建时具有 Table 94 中描述的内部槽。

Table 94: Generator 实例的内部槽
内部槽 类型 描述
[[GeneratorState]] suspended-start, suspended-yield, executing, or completed generator 的当前执行状态。
[[GeneratorContext]] execution context 执行此 generator 的代码时使用的执行上下文。
[[GeneratorBrand]] String 或 empty 用于区分不同种类 generator 的品牌。由 ECMAScript 源文本声明的 generator 的 [[GeneratorBrand]] 始终是 empty

27.8.3 Generator 抽象操作

27.8.3.1 GeneratorStart ( gen, genBody )

The abstract operation GeneratorStart takes arguments gen (a Generator) and genBody (a FunctionBody Parse Node or an Abstract Closure with no parameters) and returns unused. It performs the following steps when called:

  1. 断言:gen.[[GeneratorState]]suspended-start
  2. genContext 为运行中的执行上下文。
  3. genContext 的 Generator 组件设置为 gen
  4. closure 为一个新的无参数 Abstract Closure,它捕获 genBody,并在被调用时执行以下步骤:
    1. acGenContext 为运行中的执行上下文。
    2. acGenacGenContext 的 Generator 组件。
    3. 如果 genBodyParse Node,则
      1. resultgenBody 的求值的 Completion
    4. 否则,
      1. 断言:genBody 是无参数 Abstract Closure
      2. resultCompletion(genBody())。
    5. 断言:如果我们返回到这里,则该 generator 要么抛出了异常,要么执行了隐式或显式 return。
    6. 从执行上下文栈中移除 acGenContext,并将执行上下文栈顶部的执行上下文恢复为运行中的执行上下文。
    7. acGen.[[GeneratorState]] 设置为 completed
    8. 注:一旦 generator 进入 completed 状态,它就永远不会离开该状态,其关联执行上下文也永远不会恢复。此时可以丢弃与 acGen 关联的任何执行状态。
    9. 如果 result 是 normal completion,则
      1. resultValueundefined
    10. 否则,如果 result 是 return completion,则
      1. resultValueresult.[[Value]]
    11. 否则,
      1. 断言:result 是 throw completion。
      2. 返回 ? result
    12. 返回 NormalCompletion(CreateIteratorResultObject(resultValue, true))。
  5. 设置 genContext 的代码求值状态,使得当该执行上下文恢复求值时,将以无实参调用 closure
  6. gen.[[GeneratorContext]] 设置为 genContext
  7. 返回 unused

27.8.3.2 GeneratorValidate ( gen, genBrand )

The abstract operation GeneratorValidate takes arguments gen (an ECMAScript language value) and genBrand (a String or empty) and returns either a normal completion containing one of suspended-start, suspended-yield, or completed, or a throw completion. It performs the following steps when called:

  1. 执行 ? RequireInternalSlot(gen, [[GeneratorState]])。
  2. 执行 ? RequireInternalSlot(gen, [[GeneratorBrand]])。
  3. 如果 gen.[[GeneratorBrand]] 不是 genBrand,则抛出 TypeError 异常。
  4. 断言:gen 具有 [[GeneratorContext]] 内部槽。
  5. stategen.[[GeneratorState]]
  6. 如果 stateexecuting,则抛出 TypeError 异常。
  7. 返回 state

27.8.3.3 GeneratorResume ( gen, value, genBrand )

The abstract operation GeneratorResume takes arguments gen (an ECMAScript language value), value (an ECMAScript language value or empty), and genBrand (a String or empty) and returns either a normal completion containing an ECMAScript language value or a throw completion. It performs the following steps when called:

  1. state 为 ? GeneratorValidate(gen, genBrand)。
  2. 如果 statecompleted,则返回 CreateIteratorResultObject(undefined, true)。
  3. 断言:statesuspended-startsuspended-yield
  4. genContextgen.[[GeneratorContext]]
  5. gen.[[GeneratorState]] 设置为 executing
  6. 返回 ? RunSuspendedContext(genContext, NormalCompletion(value))。

27.8.3.4 GeneratorResumeAbrupt ( gen, abruptCompletion, genBrand )

The abstract operation GeneratorResumeAbrupt takes arguments gen (an ECMAScript language value), abruptCompletion (a return completion or a throw completion), and genBrand (a String or empty) and returns either a normal completion containing an ECMAScript language value or a throw completion. It performs the following steps when called:

  1. state 为 ? GeneratorValidate(gen, genBrand)。
  2. 如果 statesuspended-start,则
    1. gen.[[GeneratorState]] 设置为 completed
    2. 注:一旦 generator 进入 completed 状态,它就永远不会离开该状态,其关联执行上下文也永远不会恢复。此时可以丢弃与 gen 关联的任何执行状态。
    3. state 设置为 completed
  3. 如果 statecompleted,则
    1. 如果 abruptCompletion 是 return completion,则
      1. 返回 CreateIteratorResultObject(abruptCompletion.[[Value]], true)。
    2. 返回 ? abruptCompletion
  4. 断言:statesuspended-yield
  5. genContextgen.[[GeneratorContext]]
  6. gen.[[GeneratorState]] 设置为 executing
  7. 返回 ? RunSuspendedContext(genContext, abruptCompletion)。

27.8.3.5 GetGeneratorKind ( )

The abstract operation GetGeneratorKind takes no arguments and returns non-generator, sync, or async. It performs the following steps when called:

  1. genContext 为运行中的执行上下文。
  2. 如果 genContext 没有 Generator 组件,则返回 non-generator
  3. gengenContext 的 Generator 组件。
  4. 如果 gen 具有 [[AsyncGeneratorState]] 内部槽,则返回 async
  5. 返回 sync

27.8.3.6 GeneratorYield ( iteratorResult )

The abstract operation GeneratorYield takes argument iteratorResult (an Object that conforms to the IteratorResult interface) and returns either a normal completion containing an ECMAScript language value or an abrupt completion. It performs the following steps when called:

  1. genContext 为运行中的执行上下文。
  2. 断言:genContext 是一个生成器的执行上下文。
  3. gengenContext 的 Generator 组件的值。
  4. 断言:GetGeneratorKind() 是 sync
  5. gen.[[GeneratorState]] 设置为 suspended-yield
  6. 返回 ? RunCallerContext(iteratorResult)。

27.8.3.7 Yield ( arg )

The abstract operation Yield takes argument arg (an ECMAScript language value) and returns either a normal completion containing an ECMAScript language value or an abrupt completion. It performs the following steps when called:

  1. genKindGetGeneratorKind()。
  2. 如果 genKindasync,则返回 ? AsyncGeneratorYield(? Await(arg))。
  3. 返回 ? GeneratorYield(CreateIteratorResultObject(arg, false))。

27.8.3.8 CreateIteratorFromClosure ( closure, genBrand, genProto [ , extraSlots ] )

The abstract operation CreateIteratorFromClosure takes arguments closure (an Abstract Closure with no parameters), genBrand (a String or empty), and genProto (an Object) and optional argument extraSlots (a List of names of internal slots) and returns a Generator. It performs the following steps when called:

  1. 注:closure 可以包含 Yield 操作的使用,以产生 IteratorResult 对象。
  2. 如果 extraSlots 不存在,则将 extraSlots 设置为新的空 List
  3. internalSlotsListextraSlots 和 « [[GeneratorState]], [[GeneratorContext]], [[GeneratorBrand]] » 的列表连接
  4. genOrdinaryObjectCreate(genProto, internalSlotsList)。
  5. gen.[[GeneratorBrand]] 设置为 genBrand
  6. gen.[[GeneratorState]] 设置为 suspended-start
  7. callerContext 为运行中的执行上下文。
  8. calleeContext 为新的执行上下文。
  9. calleeContext 的 Function 设置为 null
  10. calleeContextRealm 设置为当前 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 function 创建,并且同时符合 async iterator 接口async iterable 接口

AsyncGenerator 实例直接继承创建该实例的 async generator function 的 "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. genthis 值。
  2. promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  3. resultCompletion(AsyncGeneratorValidate(gen, empty))。
  4. IfAbruptRejectPromise(result, promiseCapability)。
  5. stategen.[[AsyncGeneratorState]]
  6. 如果 statecompleted,则
    1. iteratorResultCreateIteratorResultObject(undefined, true)。
    2. 执行 ! Call(promiseCapability.[[Resolve]], undefined, « iteratorResult »)。
    3. 返回 promiseCapability.[[Promise]]
  7. completionNormalCompletion(value)。
  8. 执行 AsyncGeneratorEnqueue(gen, completion, promiseCapability)。
  9. 如果 statesuspended-startsuspended-yield,则
    1. 执行 AsyncGeneratorResume(gen, completion)。
  10. 否则,
    1. 断言:stateexecutingdraining-queue
  11. 返回 promiseCapability.[[Promise]]

27.9.1.3 %AsyncGeneratorPrototype%.return ( value )

  1. genthis 值。
  2. promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  3. resultCompletion(AsyncGeneratorValidate(gen, empty))。
  4. IfAbruptRejectPromise(result, promiseCapability)。
  5. completionReturnCompletion(value)。
  6. 执行 AsyncGeneratorEnqueue(gen, completion, promiseCapability)。
  7. stategen.[[AsyncGeneratorState]]
  8. 如果 statesuspended-startcompleted,则
    1. gen.[[AsyncGeneratorState]] 设置为 draining-queue
    2. 执行 AsyncGeneratorAwaitReturn(gen)。
  9. 否则,如果 statesuspended-yield,则
    1. 执行 AsyncGeneratorResume(gen, completion)。
  10. 否则,
    1. 断言:stateexecutingdraining-queue
  11. 返回 promiseCapability.[[Promise]]

27.9.1.4 %AsyncGeneratorPrototype%.throw ( exception )

  1. genthis 值。
  2. promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  3. resultCompletion(AsyncGeneratorValidate(gen, empty))。
  4. IfAbruptRejectPromise(result, promiseCapability)。
  5. stategen.[[AsyncGeneratorState]]
  6. 如果 statesuspended-start,则
    1. gen.[[AsyncGeneratorState]] 设置为 completed
    2. state 设置为 completed
  7. 如果 statecompleted,则
    1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « exception »)。
    2. 返回 promiseCapability.[[Promise]]
  8. completionThrowCompletion(exception)。
  9. 执行 AsyncGeneratorEnqueue(gen, completion, promiseCapability)。
  10. 如果 statesuspended-yield,则
    1. 执行 AsyncGeneratorResume(gen, completion)。
  11. 否则,
    1. 断言:stateexecutingdraining-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 实例最初创建时具有下面描述的内部槽:

Table 95: AsyncGenerator 实例的内部槽
内部槽 类型 描述
[[AsyncGeneratorState]] suspended-start, suspended-yield, executing, draining-queue, or completed async generator 的当前执行状态。
[[AsyncGeneratorContext]] execution context 执行此 async generator 的代码时使用的执行上下文。
[[AsyncGeneratorQueue]] AsyncGeneratorRequest RecordList 表示恢复 async generator 请求的 Record。除状态转换期间外,当且仅当 [[AsyncGeneratorState]]executingdraining-queue 时,它才非空。
[[GeneratorBrand]] String 或 empty 用于区分不同种类 async generator 的品牌。由 ECMAScript 源文本声明的 async generator 的 [[GeneratorBrand]] 始终是 empty

27.9.3 AsyncGenerator 抽象操作

27.9.3.1 AsyncGeneratorRequest Record

AsyncGeneratorRequest 是一种 Record 值,用于存储 async generator 应如何恢复的信息,并包含用于兑现或拒绝相应 promise 的 capability。

它们具有以下字段:

Table 96: AsyncGeneratorRequest Record 字段
字段名 含义
[[Completion]] Completion Record 应用来恢复 async generator 的 Completion Record
[[Capability]] PromiseCapability Record 与此请求关联的 promise capability。

27.9.3.2 AsyncGeneratorStart ( gen, genBody )

The abstract operation AsyncGeneratorStart takes arguments gen (an AsyncGenerator) and genBody (a FunctionBody Parse Node or an Abstract Closure with no parameters) and returns unused. It performs the following steps when called:

  1. 断言:gen.[[AsyncGeneratorState]]suspended-start
  2. genContext 为运行中的执行上下文。
  3. genContext 的 Generator 组件设置为 gen
  4. closure 为一个新的无参数 Abstract Closure,它捕获 genBody,并在被调用时执行以下步骤:
    1. acGenContext 为运行中的执行上下文。
    2. acGenacGenContext 的 Generator 组件。
    3. 如果 genBodyParse Node,则
      1. resultgenBody 的求值的 Completion
    4. 否则,
      1. 断言:genBody 是无参数 Abstract Closure
      2. resultCompletion(genBody())。
    5. 断言:如果我们返回到这里,则该 async generator 要么抛出了异常,要么执行了隐式或显式 return。
    6. 从执行上下文栈中移除 acGenContext,并将执行上下文栈顶部的执行上下文恢复为运行中的执行上下文。
    7. acGen.[[AsyncGeneratorState]] 设置为 draining-queue
    8. 如果 result 是 normal completion,则将 result 设置为 NormalCompletion(undefined)。
    9. 如果 result 是 return completion,则将 result 设置为 NormalCompletion(result.[[Value]])。
    10. 执行 AsyncGeneratorCompleteStep(acGen, result, true)。
    11. 执行 AsyncGeneratorDrainQueue(acGen)。
    12. 返回 NormalCompletion(undefined)。
  5. 设置 genContext 的代码求值状态,使得当该执行上下文恢复求值时,将以无实参调用 closure
  6. gen.[[AsyncGeneratorContext]] 设置为 genContext
  7. gen.[[AsyncGeneratorQueue]] 设置为新的空 List
  8. 返回 unused

27.9.3.3 AsyncGeneratorValidate ( gen, genBrand )

The abstract operation AsyncGeneratorValidate takes arguments gen (an ECMAScript language value) and genBrand (a String or empty) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

  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 )

The abstract operation AsyncGeneratorEnqueue takes arguments gen (an AsyncGenerator), completion (a Completion Record), and promiseCapability (a PromiseCapability Record) and returns unused. It performs the following steps when called:

  1. requestAsyncGeneratorRequest { [[Completion]]: completion, [[Capability]]: promiseCapability }。
  2. request 追加到 gen.[[AsyncGeneratorQueue]]
  3. 返回 unused

27.9.3.5 AsyncGeneratorCompleteStep ( gen, completion, done [ , realm ] )

The abstract operation AsyncGeneratorCompleteStep takes arguments gen (an AsyncGenerator), completion (a Completion Record), and done (a Boolean) and optional argument realm (a Realm Record) and returns unused. It performs the following steps when called:

  1. 断言:gen.[[AsyncGeneratorQueue]] 不是空。
  2. nextgen.[[AsyncGeneratorQueue]] 的第一个元素。
  3. gen.[[AsyncGeneratorQueue]] 中移除第一个元素。
  4. promiseCapabilitynext.[[Capability]]
  5. valuecompletion.[[Value]]
  6. 如果 completion 是 throw completion,则
    1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « value »)。
  7. 否则,
    1. 断言:completion 是 normal completion。
    2. 如果 realm 存在,则
      1. oldRealm 为运行中的执行上下文的 Realm
      2. 将运行中的执行上下文的 Realm 设置为 realm
      3. iteratorResultCreateIteratorResultObject(value, done)。
      4. 将运行中的执行上下文的 Realm 设置为 oldRealm
    3. 否则,
      1. iteratorResultCreateIteratorResultObject(value, done)。
    4. 执行 ! Call(promiseCapability.[[Resolve]], undefined, « iteratorResult »)。
  8. 返回 unused

27.9.3.6 AsyncGeneratorResume ( gen, completion )

The abstract operation AsyncGeneratorResume takes arguments gen (an AsyncGenerator) and completion (a Completion Record) and returns unused. It performs the following steps when called:

  1. 断言:gen.[[AsyncGeneratorState]]suspended-startsuspended-yield
  2. genContextgen.[[AsyncGeneratorContext]]
  3. gen.[[AsyncGeneratorState]] 设置为 executing
  4. 执行 ! RunSuspendedContext(genContext, completion)。
  5. 返回 unused

27.9.3.7 AsyncGeneratorUnwrapYieldResumption ( resumptionValue )

The abstract operation AsyncGeneratorUnwrapYieldResumption takes argument resumptionValue (a Completion Record) and returns either a normal completion containing an ECMAScript language value or an abrupt completion. It performs the following steps when called:

  1. 如果 resumptionValue 不是 return completion,则返回 ? resumptionValue
  2. awaitedCompletion(Await(resumptionValue.[[Value]]))。
  3. 如果 awaited 是 throw completion,则返回 ? awaited
  4. 断言:awaited 是 normal completion。
  5. 返回 ReturnCompletion(awaited.[[Value]])。

27.9.3.8 AsyncGeneratorYield ( arg )

The abstract operation AsyncGeneratorYield takes argument arg (an ECMAScript language value) and returns either a normal completion containing an ECMAScript language value or an abrupt completion. It performs the following steps when called:

  1. genContext 为运行中的执行上下文。
  2. 断言:genContext 是一个生成器的执行上下文。
  3. gengenContext 的 Generator 组件的值。
  4. 断言:GetGeneratorKind() 是 async
  5. completionNormalCompletion(arg)。
  6. 断言:执行上下文栈至少有两个元素。
  7. previousContext 为执行上下文栈中从栈顶数第二个元素。
  8. previousRealmpreviousContextRealm
  9. 执行 AsyncGeneratorCompleteStep(gen, completion, false, previousRealm)。
  10. queuegen.[[AsyncGeneratorQueue]]
  11. 如果 queue 非空,则
    1. 注:执行会继续,而不会挂起该生成器。
    2. toYieldqueue 的第一个元素。
    3. resumptionValueCompletion(toYield.[[Completion]])。
    4. 返回 ? AsyncGeneratorUnwrapYieldResumption(resumptionValue)。
  12. gen.[[AsyncGeneratorState]] 设置为 suspended-yield
  13. resumptionValueCompletion(RunCallerContext(undefined))。
  14. 返回 ? AsyncGeneratorUnwrapYieldResumption(resumptionValue)。

27.9.3.9 AsyncGeneratorAwaitReturn ( gen )

The abstract operation AsyncGeneratorAwaitReturn takes argument gen (an AsyncGenerator) and returns unused. It performs the following steps when called:

  1. 断言:gen.[[AsyncGeneratorState]]draining-queue
  2. queuegen.[[AsyncGeneratorQueue]]
  3. 断言:queue 不是空。
  4. nextqueue 的第一个元素。
  5. completionCompletion(next.[[Completion]])。
  6. 断言:completion 是 return completion。
  7. promiseCompletionCompletion(PromiseResolve(%Promise%, completion.[[Value]]))。
  8. 如果 promiseCompletion 是 abrupt completion,则
    1. 执行 AsyncGeneratorCompleteStep(gen, promiseCompletion, true)。
    2. 执行 AsyncGeneratorDrainQueue(gen)。
    3. 返回 unused
  9. 断言:promiseCompletion 是 normal completion。
  10. promisepromiseCompletion.[[Value]]
  11. fulfilledClosure 为一个新的 Abstract Closure,其参数为 (value),捕获 gen,并在被调用时执行以下步骤:
    1. 断言:gen.[[AsyncGeneratorState]]draining-queue
    2. resultNormalCompletion(value)。
    3. 执行 AsyncGeneratorCompleteStep(gen, result, true)。
    4. 执行 AsyncGeneratorDrainQueue(gen)。
    5. 返回 NormalCompletion(undefined)。
  12. onFulfilledCreateBuiltinFunction(fulfilledClosure, 1, "", « »)。
  13. rejectedClosure 为一个新的 Abstract Closure,其参数为 (reason),捕获 gen,并在被调用时执行以下步骤:
    1. 断言:gen.[[AsyncGeneratorState]]draining-queue
    2. resultThrowCompletion(reason)。
    3. 执行 AsyncGeneratorCompleteStep(gen, result, true)。
    4. 执行 AsyncGeneratorDrainQueue(gen)。
    5. 返回 NormalCompletion(undefined)。
  14. onRejectedCreateBuiltinFunction(rejectedClosure, 1, "", « »)。
  15. 执行 PerformPromiseThen(promise, onFulfilled, onRejected)。
  16. 返回 unused

27.9.3.10 AsyncGeneratorDrainQueue ( gen )

The abstract operation AsyncGeneratorDrainQueue takes argument gen (an AsyncGenerator) and returns unused. 它清空 generator 的 AsyncGeneratorQueue,直到遇到持有 return completion 的 AsyncGeneratorRequest。 It performs the following steps when called:

  1. 断言:gen.[[AsyncGeneratorState]]draining-queue
  2. queuegen.[[AsyncGeneratorQueue]]
  3. 重复,只要 queue 不是空,
    1. nextqueue 的第一个元素。
    2. completionCompletion(next.[[Completion]])。
    3. 如果 completion 是 return completion,则
      1. 执行 AsyncGeneratorAwaitReturn(gen)。
      2. 返回 unused
    4. 如果 completion 是 normal completion,则
      1. completion 设置为 NormalCompletion(undefined)。
    5. 执行 AsyncGeneratorCompleteStep(gen, completion, true)。
  4. gen.[[AsyncGeneratorState]] 设置为 completed
  5. 返回 unused

27.10 AsyncFunction 对象

AsyncFunction 是通常通过求值 AsyncFunctionDeclarationAsyncFunctionExpressionAsyncMethodAsyncArrowFunction 创建的函数。它们也可以通过调用 %AsyncFunction% 固有对象来创建。

27.10.1 AsyncFunction 构造器

AsyncFunction 构造器:

  • %AsyncFunction%
  • Function 的子类。
  • 在作为函数而不是构造器调用时创建并初始化一个新的 AsyncFunction。因此,函数调用 AsyncFunction(…) 等价于具有相同实参的对象创建表达式 new AsyncFunction(…)
  • 可以用作类定义的 extends 子句的值。意图继承指定 AsyncFunction 行为的子类构造器,必须包含对 AsyncFunction 构造器的 super 调用,以创建并初始化具有内置 async function 行为所需内部槽的子类实例。所有用于定义 async function 对象的 ECMAScript 语法形式都会创建 AsyncFunction 的直接实例。没有语法方式可以创建 AsyncFunction 子类的实例。

27.10.1.1 AsyncFunction ( ...paramArgs, bodyArg )

最后一个实参(如果有)指定 async function 的主体(可执行代码)。任何在前的实参指定形式参数。

此函数在被调用时执行以下步骤:

  1. activeFunc活动函数对象
  2. 如果 bodyArg 不存在,则将 bodyArg 设置为空 String。
  3. 返回 ? CreateDynamicFunction(activeFunc, NewTarget, async, paramArgs, bodyArg)。
Note
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 函数对象,并且具有 Table 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 )

The abstract operation AsyncFunctionStart takes arguments promiseCapability (a PromiseCapability Record) and asyncFuncBody (a FunctionBody Parse Node, an ExpressionBody Parse Node, or an Abstract Closure with no parameters) and returns unused. It performs the following steps when called:

  1. runningContext 为运行中的执行上下文。
  2. asyncContextrunningContext 的副本。
  3. 注:复制执行状态是 AsyncBlockStart 恢复其执行所必需的。恢复一个当前正在执行的上下文是未良定义的。
  4. 执行 AsyncBlockStart(promiseCapability, asyncFuncBody, asyncContext)。
  5. 返回 unused

27.10.5.2 AsyncBlockStart ( promiseCapability, asyncBody, asyncContext )

The abstract operation AsyncBlockStart takes arguments promiseCapability (a PromiseCapability Record), asyncBody (a Parse Node or an Abstract Closure with no parameters), and asyncContext (an execution context) and returns unused. It performs the following steps when called:

  1. closure 为一个新的无参数 Abstract Closure,它捕获 promiseCapabilityasyncBody,并在被调用时执行以下步骤:
    1. acAsyncContext 为运行中的执行上下文。
    2. 如果 asyncBodyParse Node,则
      1. resultasyncBody 的求值的 Completion
    3. 否则,
      1. 断言:asyncBody 是无参数 Abstract Closure
      2. resultCompletion(asyncBody())。
    4. 断言:如果我们返回到这里,则该 async function 要么抛出了异常,要么执行了隐式或显式 return;所有等待都已完成。
    5. 从执行上下文栈中移除 acAsyncContext,并将执行上下文栈顶部的执行上下文恢复为运行中的执行上下文。
    6. 如果 result 是 normal completion,则
      1. 执行 ! Call(promiseCapability.[[Resolve]], undefined, « undefined »)。
    7. 否则,如果 result 是 return completion,则
      1. 执行 ! Call(promiseCapability.[[Resolve]], undefined, « result.[[Value]] »)。
    8. 否则,
      1. 断言:result 是 throw completion。
      2. 执行 ! Call(promiseCapability.[[Reject]], undefined, « result.[[Value]] »)。
    9. 返回 NormalCompletion(unused)。
  2. 设置 asyncContext 的代码求值状态,使得当该执行上下文恢复求值时,将以无实参调用 closure
  3. result 为 ! RunSuspendedContext(asyncContext, NormalCompletion(empty))。
  4. 断言:resultunused
  5. 注:result 值的可能来源是 Await,或者如果 async function 没有等待任何内容,则为上面的步骤 1.i
  6. 返回 unused

27.10.5.3 Await ( arg )

The abstract operation Await takes argument arg (an ECMAScript language value) and returns either a normal completion containing either an ECMAScript language value or empty, or a throw completion. It performs the following steps when called:

  1. asyncContext 为运行中的执行上下文。
  2. promise 为 ? PromiseResolve(%Promise%, arg)。
  3. fulfilledClosure 为一个新的抽象闭包,其参数为 (v),它捕获 asyncContext 并在被调用时执行以下步骤:
    1. 执行 Completion(RunSuspendedContext(asyncContext, NormalCompletion(v)))。
    2. 注:RunSuspendedContext 返回的完成记录会被有意忽略。
    3. 返回 NormalCompletion(undefined)。
  4. onFulfilledCreateBuiltinFunction(fulfilledClosure, 1, "", « »)。
  5. rejectedClosure 为一个新的抽象闭包,其参数为 (reason),它捕获 asyncContext 并在被调用时执行以下步骤:
    1. 执行 Completion(RunSuspendedContext(asyncContext, ThrowCompletion(reason)))。
    2. 注:RunSuspendedContext 返回的完成记录会被有意忽略。
    3. 返回 NormalCompletion(undefined)。
  6. onRejectedCreateBuiltinFunction(rejectedClosure, 1, "", « »)。
  7. 执行 PerformPromiseThen(promise, onFulfilled, onRejected)。
  8. 返回 ? RunCallerContext(empty)。

28 反射

28.1 Reflect 对象

Reflect 对象:

  • %Reflect%
  • 全局对象"Reflect" 属性的初始值。
  • 普通对象
  • 具有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%
  • 不是函数对象
  • 没有 [[Construct]] 内部方法;不能与 new 运算符一起用作构造器。
  • 没有 [[Call]] 内部方法;不能作为函数调用。

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. revocableProxyactiveFunc.[[RevocableProxy]]
    3. 如果 revocableProxynull,则返回 NormalCompletion(undefined)。
    4. activeFunc.[[RevocableProxy]] 设为 null
    5. 断言:revocableProxy 是一个 Proxy 异质对象
    6. revocableProxy.[[ProxyTarget]] 设为 null
    7. revocableProxy.[[ProxyHandler]] 设为 null
    8. 返回 NormalCompletion(undefined)。
  3. revokerCreateBuiltinFunction(revokerClosure, 0, "", « [[RevocableProxy]] »)。
  4. revoker.[[RevocableProxy]] 设为 proxy
  5. resultOrdinaryObjectCreate(%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 没有构造函数。相反,对于每个被包含 NameSpaceImportImportDeclaration 导入的模块,都会创建一个这样的对象。

除了 10.4.6 中指定的属性外,每个 Module Namespace Object 还具有以下自有属性:

28.3.1 %Symbol.toStringTag%

%Symbol.toStringTag% 属性的初始值是 String 值 "Module"

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

29 内存模型

内存一致性模型,或称内存模型,指定 Shared Data Block 事件的可能排序,这些事件源自访问由 SharedArrayBuffer 支撑的 TypedArray 实例,以及源自 Atomics 对象上的方法。当程序没有数据竞争(定义如下)时,事件的排序表现为顺序一致,即表现为来自每个 agent 的动作交错。当程序有数据竞争时,共享内存操作可能表现为顺序不一致。例如,程序可能表现出违反因果性的行为及其他令人惊讶之处。这些令人惊讶之处源自编译器转换和 CPU 的设计(例如乱序执行和推测执行)。内存模型既定义了程序表现出顺序一致行为的精确条件,也定义了从数据竞争中读取到的可能值。也就是说,不存在未定义行为。

内存模型被定义为对在求值期间由 SharedArrayBuffer 上的抽象操作或 Atomics 对象上的方法引入的 Memory event 的关系约束。

Note

本节提供一个关于由 SharedArrayBuffer 上的抽象操作引入的 Memory event 的公理化模型。需要强调的是,与本规范其余部分不同,该模型不能以算法方式表达。抽象操作对事件的非确定性引入,是 ECMAScript 求值操作语义与内存模型公理语义之间的接口。这些事件的语义通过考虑一次求值中所有事件的图来定义。它们既不是静态语义,也不是运行时语义。这里没有已展示的算法实现,而是一组约束,用来确定某个特定事件图是被允许还是不被允许。

29.1 内存模型基础

共享内存访问(读和写)分为两组:原子访问和数据访问,定义如下。原子访问是顺序一致的,即,在一个 agent cluster 中所有 agent 都同意的严格全序事件排序。非原子访问没有所有 agent 都同意的严格全序,即无序。

Note 1

不支持弱于顺序一致且强于无序的排序,例如 release-acquire。

Shared Data Block eventReadSharedMemoryWriteSharedMemoryReadModifyWriteSharedMemory Recordread event 是 ReadSharedMemory 或 ReadModifyWriteSharedMemory。write event 是 WriteSharedMemory 或 ReadModifyWriteSharedMemory。

Table 97: ReadSharedMemory Event 字段
字段名 含义
[[Order]] seq-cstunordered 内存模型为该事件保证的最弱排序。
[[NoTear]] Boolean 此事件是否允许从与此事件内存范围相等的多个 write event 中读取。
[[Block]] Shared Data Block 该事件操作的块。
[[ByteIndex]] 非负整数 [[Block]] 中该读的字节地址。
[[ElementSize]] 非负整数 该读的大小。
Table 98: WriteSharedMemory Event 字段
字段名 含义
[[Order]] seq-cstunorderedinit 内存模型为该事件保证的最弱排序。
[[NoTear]] Boolean 此事件是否允许被与此事件内存范围相等的多个 read event 读取。
[[Block]] Shared Data Block 该事件操作的块。
[[ByteIndex]] 非负整数 [[Block]] 中该写的字节地址。
[[ElementSize]] 非负整数 该写的大小。
[[Payload]] 字节值List 将被其他事件读取的字节值 List
Table 99: ReadModifyWriteSharedMemory Event 字段
字段名 含义
[[Order]] seq-cst 读-改-写事件总是顺序一致的。
[[NoTear]] true 读-改-写事件不能撕裂。
[[Block]] Shared Data Block 该事件操作的块。
[[ByteIndex]] 非负整数 [[Block]] 中该读-改-写的字节地址。
[[ElementSize]] 非负整数 该读-改-写的大小。
[[Payload]] 字节值List 要传给 [[ModifyOp]]字节值 List
[[ModifyOp]] 读-改-写修改函数 一个 Abstract Closure,它从读取到的字节值 List[[Payload]] 返回修改后的字节值 List

共享数据块事件由抽象操作或 Atomics 对象上的方法引入候选执行的 Agent Events 记录中。某些操作还会引入同步事件,它们没有字段,纯粹用于直接约束其他事件的允许排序。最后,还有宿主特定事件。内存事件是共享数据块事件、同步事件或这样的宿主特定事件。

令共享数据块事件 e内存范围为从 e.[[ByteIndex]]包含)到 e.[[ByteIndex]] + e.[[ElementSize]](不包含)这一间隔内所有整数的集合。当两个事件具有相同的 [[Block]][[ByteIndex]][[ElementSize]] 时,这两个事件的内存范围相等。当两个事件具有相同的 [[Block]]、范围不相等且它们的交集非空时,这两个事件的内存范围重叠。当两个事件没有相同的 [[Block]],或者它们的范围既不相等也不重叠时,这两个事件的内存范围不相交。

Note 2

应予以考虑的宿主特定同步事件的示例包括:将 SharedArrayBuffer 从一个代理发送到另一个代理(例如,在浏览器中通过 postMessage)、启动和停止代理,以及通过共享内存以外的通道在代理集群内进行通信。对于某个特定执行 execution,这些事件由宿主通过 host-synchronizes-with 严格偏序提供。此外,宿主可以向 execution.[[EventList]] 添加宿主特定同步事件,以便参与 is-agent-order-before 关系。

在候选执行内,事件按下面定义的关系排序。

29.2 Agent Events Record

Agent Events Record 是具有以下字段的 Record

Table 100: Agent Events Record 字段
字段名 含义
[[AgentSignifier]] agent signifier 其求值产生了此排序的 agent
[[EventList]] Memory event 的 List 在求值期间,事件被追加到该 List
[[AgentSynchronizesWith]] Synchronize event 对的 List 由操作语义引入的 Synchronize 关系。

29.3 Chosen Value Record

Chosen Value Record 是具有以下字段的 Record

Table 101: Chosen Value Record 字段
字段名 含义
[[Event]] Shared Data Block event 为此 chosen value 引入的 ReadSharedMemoryReadModifyWriteSharedMemory event。
[[ChosenValue]] 字节值List 在求值期间非确定性选择的字节。

29.4 Candidate Execution

agent cluster 的求值的 candidate execution 是具有以下字段的 Record

Table 102: Candidate Execution Record 字段
字段名 含义
[[EventsRecords]] Agent Events RecordList agent 映射到在求值期间追加的 Memory event 的 List
[[ChosenValues]] Chosen Value RecordList ReadSharedMemoryReadModifyWriteSharedMemory event 映射到求值期间选择的字节值 List

空 candidate execution 是其字段为空 List 的 candidate execution Record

29.5 内存模型的抽象操作

29.5.1 EventSet ( execution )

The abstract operation EventSet takes argument execution (a candidate execution) and returns a Set of Memory events. It performs the following steps when called:

  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 )

The abstract operation SharedDataBlockEventSet takes argument execution (a candidate execution) and returns a Set of Shared Data Block events. It performs the following steps when called:

  1. events 为空 Set。
  2. EventSet(execution) 的每个 Memory event event,执行:
    1. 如果 eventShared Data Block event,则将 event 添加到 events
  3. 返回 events

29.5.3 HostEventSet ( execution )

The abstract operation HostEventSet takes argument execution (a candidate execution) and returns a Set of Memory events. It performs the following steps when called:

  1. 返回一个新的 Set,其中包含 EventSet(execution) 中所有不在 SharedDataBlockEventSet(execution) 中的元素。

29.5.4 ComposeWriteEventBytes ( execution, byteIndex, writes )

The abstract operation ComposeWriteEventBytes takes arguments execution (a candidate execution), byteIndex (a non-negative integer), and writes (a List of either WriteSharedMemory or ReadModifyWriteSharedMemory events) and returns a List of byte values. It performs the following steps when called:

  1. byteLocationbyteIndex
  2. bytesRead 为新的空 List
  3. writes 的每个元素 writeEvent,执行:
    1. 断言:writeEvent内存范围包含 byteLocation
    2. payloadIndexbyteLocation - writeEvent.[[ByteIndex]]
    3. 如果 writeEventWriteSharedMemory event,则
      1. bytewriteEvent.[[Payload]][payloadIndex]。
    4. 否则,
      1. 断言:writeEventReadModifyWriteSharedMemory event。
      2. bytesValueOfReadEvent(execution, writeEvent)。
      3. bytesModifiedwriteEvent.[[ModifyOp]](bytes, writeEvent.[[Payload]])。
      4. bytebytesModified[payloadIndex]。
    5. byte 追加到 bytesRead
    6. byteLocation 设置为 byteLocation + 1。
  4. 返回 bytesRead
Note 1

读-改-写修改 [[ModifyOp]] 由 Atomics 对象上引入 ReadModifyWriteSharedMemory event 的函数属性给出。

Note 2

抽象操作write eventList 组合成字节值List。它用于 ReadSharedMemoryReadModifyWriteSharedMemory event 的事件语义。

29.5.5 ValueOfReadEvent ( execution, readEvent )

The abstract operation ValueOfReadEvent takes arguments execution (a candidate execution) and readEvent (a ReadSharedMemory or ReadModifyWriteSharedMemory event) and returns a List of byte values. It performs the following steps when called:

  1. writesexecution 中的 reads-bytes-from(readEvent)。
  2. 断言:writes 是长度等于 readEvent.[[ElementSize]]WriteSharedMemoryReadModifyWriteSharedMemory event 的 List
  3. 返回 ComposeWriteEventBytes(execution, readEvent.[[ByteIndex]], writes)。

29.6 Candidate Execution 的关系

以下关系和数学函数以特定 candidate execution 为参数,并对其 Memory event 排序。

29.6.1 is-agent-order-before

对于 candidate execution execution,其 is-agent-order-before 关系是 Memory event 上满足以下条件的最小关系。

  • 对于事件 eventAeventB,如果在 execution.[[EventsRecords]] 中存在某个 Agent Events Record eventsRecord,使得 eventsRecord.[[EventList]] 同时包含 eventAeventB,并且 eventAeventsRecord.[[EventList]]List 顺序中位于 eventB 之前,则 eventAexecution 中 is-agent-order-before eventB
Note

每个 agent 在求值期间按每个 agent严格全序引入事件。这是这些严格全序的并集。

29.6.2 reads-bytes-from

对于 candidate execution execution,其 reads-bytes-from 函数是一个数学函数,它将 SharedDataBlockEventSet(execution) 中的 Memory event 映射到 SharedDataBlockEventSet(execution) 中事件的 List,并满足以下条件。

candidate execution 总是允许存在 reads-bytes-from 函数。

29.6.3 reads-from

对于 candidate execution execution,其 reads-from 关系是 Memory event 上满足以下条件的最小关系。

29.6.4 host-synchronizes-with

对于 candidate execution execution,其 host-synchronizes-with 关系是宿主提供的宿主特定 Memory event 上的严格偏序,并且至少满足以下条件。

  • 如果 eventAexecution 中 host-synchronizes-with eventB,则 HostEventSet(execution) 包含 eventAeventB
  • execution 中,host-synchronizes-with 与 is-agent-order-before 的并集中没有环。
Note 1

对于 candidate execution execution 中的两个宿主特定事件 eventAeventBeventAexecution 中 host-synchronizes-with eventB 蕴含 eventAexecutionhappens-before eventB

Note 2

此关系允许宿主提供额外的同步机制,例如 HTML worker 之间的 postMessage

29.6.5 synchronizes-with

对于 candidate execution execution,其 synchronizes-with 关系是 Memory event 上满足以下条件的最小关系。

  • 对于事件 readEventwriteEvent,如果 readEventexecutionreads-from writeEventreadEvent.[[Order]]seq-cstwriteEvent.[[Order]]seq-cst,且 readEventwriteEvent 具有相等的内存范围,则 writeEventexecution 中 synchronizes-with readEvent
  • execution.[[EventsRecords]] 的每个元素 eventsRecord,以下为真。
    • 对于事件 eventAeventB,如果 eventsRecord.[[AgentSynchronizesWith]] 包含 (eventA, eventB),则 eventAexecution 中 synchronizes-with eventB
  • 对于事件 eventAeventB,如果 eventAexecutionhost-synchronizes-with eventB,则 eventAexecution 中 synchronizes-with eventB
Note 1

由于内存模型文献中的约定,在 candidate execution execution 中,是 write event synchronizes-with read event,而不是 read event synchronizes-with write event

Note 2

candidate execution execution 中,init 事件不参与此关系,而是由 happens-before 直接约束。

Note 3

candidate execution execution 中,并非所有通过 reads-from 关联的 seq-cst 事件都通过 synchronizes-with 关联。只有同时具有相等内存范围的事件才通过 synchronizes-with 关联。

Note 4

对于 candidate execution execution 中的 Shared Data Block event readEventwriteEvent,如果 writeEvent synchronizes-with readEvent,则 readEvent 可以 reads-from writeEvent 以外的其他写。

29.6.6 happens-before

对于 candidate execution execution,其 happens-before 关系是 Memory event 上满足以下条件的最小关系。

  • 对于事件 eventAeventB,如果以下任一条件为真,则 eventAexecution 中 happens-before eventB

    • eventAexecutionis-agent-order-before eventB
    • eventAexecutionsynchronizes-with eventB
    • SharedDataBlockEventSet(execution) 同时包含 eventAeventBeventA.[[Order]]init,且 eventAeventB 具有重叠的内存范围
    • 存在事件 eventC,使得 eventAexecution 中 happens-before eventC,并且 eventCexecution 中 happens-before eventB
Note

因为 happens-before 是 agent-order 的超集,所以 candidate execution 与 ECMAScript 的单线程求值语义一致。

29.7 有效执行的属性

29.7.1 有效的 Chosen Read

如果以下算法返回 true,则 candidate execution execution 具有有效的 chosen read。

  1. SharedDataBlockEventSet(execution) 的每个 ReadSharedMemoryReadModifyWriteSharedMemory event readEvent,执行:
    1. chosenValueRecordexecution.[[ChosenValues]] 中其 [[Event]] 字段为 readEvent 的元素。
    2. chosenValuechosenValueRecord.[[ChosenValue]]
    3. readValueValueOfReadEvent(execution, readEvent)。
    4. chosenLengthchosenValue 中元素的数量。
    5. readLengthreadValue 中元素的数量。
    6. 如果 chosenLengthreadLength,则
      1. 返回 false
    7. 如果对于从 0(含)到 chosenLength(不含)区间内的某个整数 ichosenValue[i] ≠ readValue[i],则
      1. 返回 false
  2. 返回 true

29.7.2 相干读

如果以下算法返回 true,则 candidate execution execution 具有相干读。

  1. SharedDataBlockEventSet(execution) 的每个 ReadSharedMemoryReadModifyWriteSharedMemory event readEvent,执行:
    1. writesexecution 中的 reads-bytes-from(readEvent)。
    2. byteLocationreadEvent.[[ByteIndex]]
    3. writes 的每个元素 writeEvent,执行:
      1. 如果 readEventexecutionhappens-before writeEvent,则
        1. 返回 false
      2. 如果存在一个 WriteSharedMemoryReadModifyWriteSharedMemory event value,其内存范围包含 byteLocation,使得 writeEventexecutionhappens-before value,且 valueexecutionhappens-before readEvent,则
        1. 返回 false
      3. byteLocation 设置为 byteLocation + 1。
  2. 返回 true

29.7.3 无撕裂读

如果以下算法返回 true,则 candidate execution execution 具有无撕裂读。

  1. SharedDataBlockEventSet(execution) 的每个 ReadSharedMemoryReadModifyWriteSharedMemory event readEvent,执行:
    1. 如果 readEvent.[[NoTear]]true,则
      1. 断言:readEvent.[[ByteIndex]] 除以 readEvent.[[ElementSize]] 的余数为 0。
      2. 对满足如下条件的每个 Memory event writeEvent 执行:readEventexecutionreads-from writeEvent,并且 writeEvent.[[NoTear]]true
        1. 如果 readEventwriteEvent 具有相等的内存范围,并且存在 Memory event value,使得 valuewriteEvent 具有相等的内存范围value.[[NoTear]]truewriteEventvalue 不是同一个 Shared Data Block event,且 readEventexecutionreads-from value,则
          1. 返回 false
  2. 返回 true
Note

Shared Data Block event 是通过访问整数 TypedArray 引入时,该事件的 [[NoTear]] 字段为 true;当通过访问浮点 TypedArray 或 DataView 引入时,为 false

直观地说,此要求表示,当通过整数 TypedArray 以对齐方式访问某个内存范围时,在与具有相等范围的其他 write event数据竞争中,必须有一个该范围上的单一 write event “胜出”。更精确地说,此要求表示,对齐的 read event 不能读取由多个不同 write event 的字节组成的值,而这些 write event 全都具有相等范围。不过,对齐的 read event 可以从多个具有重叠范围的 write event 中读取。

29.7.4 顺序一致的原子操作

对于 candidate execution executionis-memory-order-beforeEventSet(execution) 中所有 Memory event 的严格全序,并满足以下条件。

如果 candidate execution 允许存在 is-memory-order-before 关系,则它具有顺序一致的原子操作。

Note 3

虽然 is-memory-order-before 包含 EventSet(execution) 中的所有事件,但在 execution 中不受 happens-beforesynchronizes-with 约束的事件被允许出现在该排序中的任何位置。

29.7.5 有效执行

如果以下全部为真,则 candidate execution execution 是有效执行(或简称 execution)。

  • 宿主execution 提供 host-synchronizes-with 关系。
  • execution 允许存在作为严格偏序happens-before 关系。
  • execution 具有有效的 chosen read。
  • execution 具有相干读。
  • execution 具有无撕裂读。
  • execution 具有顺序一致的原子操作。

所有程序至少有一个有效执行。

29.8 竞争

对于 execution execution,以及包含SharedDataBlockEventSet(execution) 中的事件 eventAeventB,如果以下算法返回 true,则 eventAeventB 处于竞争

  1. 如果 eventAeventB 不是同一个 Shared Data Block event,则
    1. 如果并非 eventAexecutionhappens-before eventBeventBexecutionhappens-before eventA,则
      1. 如果 eventAWriteSharedMemoryReadModifyWriteSharedMemory event,eventBWriteSharedMemoryReadModifyWriteSharedMemory event,并且 eventAeventB 没有不相交的内存范围,则
        1. 返回 true
      2. 如果 eventAexecutionreads-from eventB,或 eventBexecutionreads-from eventA,则
        1. 返回 true
  2. 返回 false

29.9 数据竞争

对于 execution execution,以及包含SharedDataBlockEventSet(execution) 中的事件 eventAeventB,如果以下算法返回 true,则 eventAeventB 处于数据竞争

  1. 如果 eventAeventBexecution 中处于 竞争,则
    1. 如果 eventA.[[Order]] 不是 seq-csteventB.[[Order]] 不是 seq-cst,则
      1. 返回 true
    2. 如果 eventAeventB 具有重叠的内存范围,则
      1. 返回 true
  2. 返回 false

29.10 数据竞争自由

如果 execution execution 中不存在两个在 SharedDataBlockEventSet(execution) 中且处于数据竞争的事件,则 execution数据竞争自由的。

如果程序的所有执行都是数据竞争自由的,则该程序是数据竞争自由的。

内存模型保证数据竞争自由程序的所有事件具有顺序一致性。

29.11 共享内存指南

Note 1

以下是针对使用共享内存的 ECMAScript 程序员的指南。

我们建议保持程序数据竞争自由,即,使得不可能在同一内存位置上存在并发的非原子操作。数据竞争自由程序具有交错语义,其中每个 agent 的求值语义中的每一步彼此交错。对于数据竞争自由程序,没有必要理解内存模型的细节。这些细节不太可能建立起有助于更好编写 ECMAScript 的直觉。

更一般地,即使程序不是数据竞争自由的,只要原子操作不参与任何数据竞争,并且发生竞争的操作都具有相同的访问大小,它也可能具有可预测行为。安排原子操作不参与竞争的最简单方式是确保原子操作和非原子操作使用不同的内存单元,并且不使用不同大小的原子访问同时访问相同单元。实际上,程序应尽可能将共享内存视为强类型。仍然不能依赖发生竞争的非原子访问的排序和时机,但如果内存被视为强类型,则发生竞争的访问不会“撕裂”(其值的位不会混合)。

Note 2

以下是针对为使用共享内存的程序编写编译器转换的 ECMAScript 实现者的指南。

最好允许大多数在单 agent 设置中有效的程序转换在多 agent 设置中也有效,以确保多 agent 程序中每个 agent 的性能与在单 agent 设置中一样好。这些转换通常很难判断。我们概述了一些关于程序转换的规则,这些规则意图作为规范性规则(因为它们由内存模型蕴含,或强于内存模型所蕴含的内容),但可能并不详尽。这些规则意图适用于那些发生在构成 is-agent-order-before 关系的 Memory event 被引入之前的程序转换。

agent-order slice 为与单个 agent 相关的 is-agent-order-before 关系的子集。

read event可能读取值为该事件在所有有效执行中的 ValueOfReadEvent 的所有值的集合。

在没有共享内存的情况下对 agent-order slice 有效的任何转换,在存在共享内存的情况下也是有效的,但有以下例外。

  • 原子操作刻在石头上:程序转换不得导致任何 [[Order]]seq-cstShared Data Block eventis-agent-order-before 关系中移除,也不得导致它们相互重排序,或在 agent-order slice 内与 [[Order]]unordered 的事件重排序。

    (实践中,对重排序的禁止会迫使编译器假定每个 seq-cst 操作都是同步,并包含在最终的 is-memory-order-before 关系中;在没有跨 agent 程序分析的情况下,它通常也必须这样假定。它还会迫使编译器假定每个 callee 对 memory-order 的影响未知的调用都可能包含 seq-cst 操作。)

  • 读必须稳定:任何给定的共享内存读在一次执行中只能观察到单个值。

    (例如,如果程序中语义上单个读被执行多次,则随后允许程序只观察到所读取值中的一个。称为 rematerialization 的转换可能违反此规则。)

  • 写必须稳定:所有对共享内存的可观察写都必须源自一次执行中的程序语义。

    (例如,转换不得引入某些可观察写,例如通过在较大位置上使用读-改-写操作来写入较小数据、向内存写入程序不可能写入的值,或将刚读取的值写回其读取位置,而该位置在读取之后可能已被另一个 agent 覆写。)

  • 可能读取值必须非空:程序转换不能导致共享内存读的可能读取值变为空。

    (反直觉地,此规则实际上限制了对写的转换,因为写在内存模型中具有作用力,就其能被 read event 读取而言。例如,写可以在两个 seq-cst 操作之间移动、合并,有时也可重排序,但转换不得移除每个更新某个位置的写;必须保留某个写。)

仍然有效的转换示例包括:合并来自同一位置的多个非原子读、重排序非原子读、引入推测性非原子读、合并对同一位置的多个非原子写、重排序对不同位置的非原子写,以及即使影响终止也将非原子读提升出循环。通常要注意,别名化的 TypedArray 会使证明位置不同变得困难。

Note 3

以下是针对为共享内存访问生成机器代码的 ECMAScript 实现者的指南。

对于内存模型不弱于 ARM 或 Power 的体系结构,非原子 store 和 load 可以编译为目标体系结构上的裸 store 和 load。原子 store 和 load 可以编译为保证顺序一致性的指令。如果不存在这样的指令,则应使用内存屏障,例如在裸 store 或 load 的两侧放置屏障。读-改-写操作可以编译为目标体系结构上的读-改-写指令,例如 x86 上带 LOCK 前缀的指令、ARM 上的 load-exclusive/store-exclusive 指令,以及 Power 上的 load-link/store-conditional 指令。

具体而言,内存模型意图允许如下代码生成。

  • 假定程序中的每个原子操作都是必要的。
  • 原子操作永远不会彼此重排,也不会与非原子操作重排。
  • 始终假定函数会执行原子操作。
  • 原子操作绝不会实现为在更大数据上的读-改-写操作;如果平台没有适当大小的原子操作,则实现为非无锁原子操作。(我们已经假定每个平台都具有所有相关大小的普通内存访问操作。)

朴素代码生成使用以下模式:

  • 常规 load 和 store 编译为单个 load 和 store 指令。
  • 无锁原子 load 和 store 编译为完整(顺序一致)栅栏、常规 load 或 store,以及完整栅栏。
  • 无锁原子读-改-写访问编译为完整栅栏、原子读-改-写指令序列,以及完整栅栏。
  • 非无锁原子操作编译为获取 spinlock、完整栅栏、一系列非原子 load 和 store 指令、完整栅栏,以及释放 spinlock。

只要某个内存范围上的原子操作不与非原子写或不同大小的原子操作发生竞争,该映射就是正确的。不过,这已经是我们所需要的一切:内存模型实际上会将参与竞争的原子操作降级为非原子状态。另一方面,朴素映射相当强:它允许原子操作用作顺序一致栅栏,而内存模型实际上并不保证这一点。

在遵守内存模型约束的前提下,也允许对这些基本模式进行局部改进。例如:

  • 存在明显的平台相关改进,可以移除冗余栅栏。例如,在 x86 上,无锁原子 load 和 store 周围的栅栏总是可以省略,除了 store 之后的栅栏;并且无锁读-改-写指令不需要栅栏,因为这些都使用带 LOCK 前缀的指令。在许多平台上存在几种强度的栅栏,并且可以在某些上下文中使用较弱栅栏而不破坏顺序一致性。
  • 大多数现代平台都支持 ECMAScript 原子操作所需所有数据大小的无锁原子操作。如果需要非无锁原子操作,围绕原子操作主体的栅栏通常可以折叠到加锁和解锁步骤中。对于非无锁原子操作,最简单的解决方案是每个 SharedArrayBuffer 使用一个锁字。
  • 还存在更复杂的平台相关局部改进,需要一些代码分析。例如,两个背靠背栅栏通常与单个栅栏具有相同效果,因此如果为连续的两个原子操作生成代码,只需用单个栅栏分隔它们。在 x86 上,甚至可以省略分隔原子 store 的单个栅栏,因为 store 之后的栅栏只用于将该 store 与后续 load 分隔开。

Annex A (informative) 语法摘要

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 :: 0 NonZeroDigit 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 NonOctalDigit LegacyOctalLikeDecimalIntegerLiteral NonOctalDigit NonOctalDecimalIntegerLiteral DecimalDigit LegacyOctalLikeDecimalIntegerLiteral :: 0 OctalDigit LegacyOctalLikeDecimalIntegerLiteral 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] ) ( Expression[+In, ?Yield, ?Await] , ) ( ) ( ... 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] } { PropertyDefinitionList[?Yield, ?Await] , } 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, ?Tagged] SubstitutionTemplate[Yield, Await, Tagged] : TemplateHead Expression[+In, ?Yield, ?Await] TemplateSpans[?Yield, ?Await, ?Tagged] TemplateSpans[Yield, Await, Tagged] : TemplateTail TemplateMiddleList[?Yield, ?Await, ?Tagged] TemplateTail TemplateMiddleList[Yield, Await, Tagged] : TemplateMiddle Expression[+In, ?Yield, ?Await] TemplateMiddleList[?Yield, ?Await, ?Tagged] 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] ) ( ArgumentList[?Yield, ?Await] , ) 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] } { AssignmentPropertyList[?Yield, ?Await] , AssignmentRestProperty[?Yield, ?Await]opt } 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] } { BindingPropertyList[?Yield, ?Await] , BindingRestProperty[?Yield, ?Await]opt } 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 } { ImportsList , } 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 } { ExportsList , } 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 时区偏移字符串格式

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 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] 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 & - ! # % , : ; < = > @ ` ~

Annex B (normative) Web 浏览器的附加 ECMAScript 特性

当 ECMAScript 宿主是 Web 浏览器时,本附录中定义的 ECMAScript 语言语法和语义是必需的。如果 ECMAScript 宿主不是 Web 浏览器,本附录的内容是规范性的但可选。

本附录中定义的一些特性在本附录中规定,另一些则在本文档主体中规定。

当某个特性在主体中规定时,它影响本文档的每个位置都会在彩色框中用“Normative Optional”字样标记。此外,如果该特性涉及算法或早期错误规则中的特定措辞,则由“宿主支持”相关特性的条件来保护。Web 浏览器必须支持所有这类特性。

Note

本附录描述 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

类似于包含行终止符代码点的 MultiLineCommentSingleLineHTMLCloseComment 为了句法语法解析的目的被视为 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 _ Note

当相同的左侧同时以 [+UnicodeMode] 和 [~UnicodeMode] 守卫出现时,是为了控制消歧优先级。

B.1.2.1 Static Semantics: 早期错误

22.2.1.1 的语义按如下方式扩展:

ExtendedAtom :: InvalidBracedQuantifier
  • 如果任何源文本被此产生式匹配,则为语法错误。

此外,以下产生式的规则通过添加高亮文本进行修改:

NonemptyClassRanges :: ClassAtom - ClassAtom ClassContents NonemptyClassRangesNoDash :: ClassAtomNoDash - ClassAtom ClassContents

B.1.2.2 Static Semantics: CountLeftCapturingParensWithin 和 CountLeftCapturingParensBefore

CountLeftCapturingParensWithinCountLeftCapturingParensBefore 的定义中,对“ Atom :: ( GroupSpecifieropt Disjunction ) ”的引用应解释为表示“ Atom :: ( GroupSpecifieropt Disjunction ) ”或“ ExtendedAtom :: ( GroupSpecifieropt Disjunction ) ”。

B.1.2.3 Static Semantics: IsCharacterClass

22.2.1.6 的语义按如下方式扩展:

ClassAtomNoDash :: \ [lookahead = c]
  1. 返回 false

B.1.2.4 Static Semantics: CharacterValue

22.2.1.7 的语义按如下方式扩展:

ClassAtomNoDash :: \ [lookahead = c]
  1. 返回 U+005C(REVERSE SOLIDUS)的数值。
ClassEscape :: c ClassControlLetter
  1. codePoint 为由 ClassControlLetter 匹配的代码点。
  2. icodePoint 的数值。
  3. 返回 i 除以 32 的余数。
CharacterEscape :: LegacyOctalEscapeSequence
  1. 返回 LegacyOctalEscapeSequence 的 MV(见 12.9.4.3)。

B.1.2.5 Runtime Semantics: CompileSubpattern

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

Assertion :: (?= Disjunction ) Assertion :: (?! Disjunction ) 产生式的 CompileAssertion 规则也用于 QuantifiableAssertion 产生式,但将 QuantifiableAssertion 替换为 Assertion

B.1.2.7 Runtime Semantics: CompileAtom

Atom :: PatternCharacter 外,Atom 产生式的 CompileAtom 规则也用于 ExtendedAtom 产生式,但将 ExtendedAtom 替换为 Atom。还会添加以下带参数 direction 的规则:

ExtendedAtom :: \ [lookahead = c]
  1. charSet包含单个字符 \ U+005C(REVERSE SOLIDUS)的 CharSet
  2. 返回 CharacterSetMatcher(regexpRecord, charSet, false, direction)。
ExtendedAtom :: ExtendedPatternCharacter
  1. charExtendedPatternCharacter 表示的字符。
  2. charSet包含字符 char 的单元素 CharSet
  3. 返回 CharacterSetMatcher(regexpRecord, charSet, false, direction)。

B.1.2.8 Runtime Semantics: CompileToCharSet

22.2.2.9 的语义按如下方式扩展:

以下两个规则替换 CompileToCharSet 的对应规则。

NonemptyClassRanges :: ClassAtom - ClassAtom ClassContents
  1. charSet 为以 regexpRecord 为实参的第一个 ClassAtomCompileToCharSet
  2. otherSet 为以 regexpRecord 为实参的第二个 ClassAtomCompileToCharSet
  3. remainingSet 为以 regexpRecord 为实参的 ClassContentsCompileToCharSet
  4. rangeSetCharacterRangeOrUnion(regexpRecord, charSet, otherSet)。
  5. 返回 rangeSetremainingSet 的并集。
NonemptyClassRangesNoDash :: ClassAtomNoDash - ClassAtom ClassContents
  1. charSet 为以 regexpRecord 为实参的 ClassAtomNoDashCompileToCharSet
  2. otherSet 为以 regexpRecord 为实参的 ClassAtomCompileToCharSet
  3. remainingSet 为以 regexpRecord 为实参的 ClassContentsCompileToCharSet
  4. rangeSetCharacterRangeOrUnion(regexpRecord, charSet, otherSet)。
  5. 返回 rangeSetremainingSet 的并集。

此外,以下规则被添加到 CompileToCharSet

ClassEscape :: c ClassControlLetter
  1. charValue 为此 ClassEscapeCharacterValue
  2. char 为字符值为 charValue 的字符。
  3. 返回包含单个字符 charCharSet
ClassAtomNoDash :: \ [lookahead = c]
  1. 返回包含单个字符 \ U+005C(REVERSE SOLIDUS)的 CharSet
Note
此产生式只能从字符类内的序列 \c 到达,其中该序列后面没有可接受的控制字符。

B.1.2.8.1 CharacterRangeOrUnion ( regexpRecord, charSet, otherSet )

The abstract operation CharacterRangeOrUnion takes arguments regexpRecord (a RegExp Record), charSet (a CharSet), and otherSet (a CharSet) and returns a CharSet. It performs the following steps when called:

  1. 如果 HasEitherUnicodeFlag(regexpRecord) 是 false,则
    1. 如果 charSet 不恰好包含一个字符,或 otherSet 不恰好包含一个字符,则
      1. remainingSet包含单个字符 - U+002D(HYPHEN-MINUS)的 CharSet
      2. 返回 CharSet charSetotherSetremainingSet 的并集。
  2. 返回 CharacterRange(charSet, otherSet)。

B.1.2.9 Static Semantics: ParsePattern ( patternText, u, v )

22.2.3.4 的语义按如下方式扩展:

抽象操作 ParsePattern 接受实参 patternText(Unicode 代码点序列)、u(Boolean)和 v(Boolean)。它在被调用时执行以下步骤:

  1. 如果 vtrueutrue,则
    1. parseResult包含一个或多个 SyntaxError 对象的 List
  2. 否则,如果 vtrue,则
    1. parseResultParseText(patternText, Pattern[+UnicodeMode, +UnicodeSetsMode, +NamedCaptureGroups])。
  3. 否则,如果 utrue,则
    1. parseResultParseText(patternText, Pattern[+UnicodeMode, ~UnicodeSetsMode, +NamedCaptureGroups])。
  4. 否则,
    1. parseResultParseText(patternText, Pattern[~UnicodeMode, ~UnicodeSetsMode, ~NamedCaptureGroups])。
    2. 如果 parseResultParse NodeparseResult 包含 GroupName,则
      1. parseResult 设置为 ParseText(patternText, Pattern[~UnicodeMode, ~UnicodeSetsMode, +NamedCaptureGroups])。
  5. 返回 parseResult

B.2 附加内置属性

当 ECMAScript 宿主是 Web 浏览器时,定义标准内置对象的以下附加属性。

B.2.1 全局对象的附加属性

Table 103 中的条目被添加到 Table 6

Table 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. lengthstring 的长度。
  3. result 为空 String。
  4. unescapedSet 为 ASCII word characters 和 "@*+-./"字符串连接
  5. k 为 0。
  6. 重复,只要 k < length
    1. codeUnitstring 中索引 k 处的代码单元。
    2. 如果 unescapedSet 包含 codeUnit,则
      1. nextPartcodeUnit
    3. 否则,
      1. codeUnitNumbercodeUnit 的数值。
      2. 如果 codeUnitNumber < 256,则
        1. hexcodeUnitNumber 的 String 表示,格式化为大写十六进制数。
        2. nextPart"%"StringPad(hex, 2, "0", start) 的字符串连接
      3. 否则,
        1. hexcodeUnitNumber 的 String 表示,格式化为大写十六进制数。
        2. nextPart"%u"StringPad(hex, 4, "0", start) 的字符串连接
    4. result 设置为 resultnextPart字符串连接
    5. k 设置为 k + 1。
  7. 返回 result
Note

该编码部分基于 RFC 1738 中描述的编码,但本标准中规定的整个编码在上文中描述,不考虑 RFC 1738 的内容。此编码不反映 RFC 3986 对 RFC 1738 所作的变更。

B.2.1.2 unescape ( string )

此函数是全局对象的一个属性。它计算 String 值的新版本,其中每个可能由 escape 函数引入的转义序列都会被替换为它所表示的代码单元。

它是 %unescape% 固有对象。

它在被调用时执行以下步骤:

  1. string 设置为 ? ToString(string)。
  2. lengthstring 的长度。
  3. result 为空 String。
  4. k 为 0。
  5. 重复,只要 k < length
    1. codeUnitstring 中索引 k 处的代码单元。
    2. 如果 codeUnit 是代码单元 0x0025(PERCENT SIGN),则
      1. hexDigits 为空 String。
      2. optionalAdvance 为 0。
      3. 如果 k + 5 < lengthstring 中索引 k + 1 处的代码单元是代码单元 0x0075(LATIN SMALL LETTER U),则
        1. hexDigits 设置为 stringk + 2 到 k + 6 的子串。
        2. optionalAdvance 设置为 5。
      4. 否则,如果 k + 3 ≤ length,则
        1. hexDigits 设置为 stringk + 1 到 k + 3 的子串。
        2. optionalAdvance 设置为 2。
      5. parseResultParseText(hexDigits, HexDigits[~Sep])。
      6. 如果 parseResultParse Node,则
        1. codeUnitNumberparseResult 的 MV。
        2. codeUnit 设置为其数值为 codeUnitNumber 的代码单元。
        3. k 设置为 k + optionalAdvance
    3. result 设置为 resultcodeUnit字符串连接
    4. k 设置为 k + 1。
  6. 返回 result

B.2.2 String.prototype 对象的附加属性

B.2.2.1 String.prototype.substr ( start, length )

此方法返回将 this 值转换为 String 结果的一个子串,从索引 start 开始并持续 length 个代码单元(如果 lengthundefined,则直到 String 末尾)。如果 start 为负数,则将其视为 sourceLength + start,其中 sourceLength 是该 String 的长度。结果是 String 值,而不是 String 对象。

它在被调用时执行以下步骤:

  1. objthis 值。
  2. 执行 ? RequireObjectCoercible(obj)。
  3. string 为 ? ToString(obj)。
  4. sizestring 的长度。
  5. intStart 为 ? ToIntegerOrInfinity(start)。
  6. 如果 intStart = -∞,则将 intStart 设置为 0。
  7. 否则,如果 intStart < 0,则将 intStart 设置为 max(size + intStart, 0)。
  8. 否则,将 intStart 设置为 min(intStart, size)。
  9. 如果 lengthundefined,则令 intLengthsize;否则令 intLength 为 ? ToIntegerOrInfinity(length)。
  10. intLength 设置为把 intLength 夹在 0 和 size 之间的结果。
  11. intEndmin(intStart + intLength, size)。
  12. 返回 stringintStartintEnd 的子串。
Note

此方法有意为泛型方法;它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

B.2.2.2 String.prototype.anchor ( name )

此方法在被调用时执行以下步骤:

  1. stringthis 值。
  2. 返回 ? CreateHTML(string, "a", "name", name)。

B.2.2.2.1 CreateHTML ( contents, tag, attr, attrValue )

The abstract operation CreateHTML takes arguments contents (an ECMAScript language value), tag (a String), attr (a String), and attrValue (an ECMAScript language value) and returns either a normal completion containing a String or a throw completion. It performs the following steps when called:

  1. 执行 ? RequireObjectCoercible(contents)。
  2. contentsString 为 ? ToString(contents)。
  3. part1"<"tag字符串连接
  4. 如果 attr 不是空 String,则
    1. attrValueString 为 ? ToString(attrValue)。
    2. escapedAttrValue 为与 attrValueString 相同的 String 值,但 attrValueString 中每个代码单元 0x0022(QUOTATION MARK)的出现都被替换为六个代码单元序列 "&quot;"
    3. part1 设置为以下各项的字符串连接
      • part1
      • 代码单元 0x0020(SPACE)
      • attr
      • 代码单元 0x003D(EQUALS SIGN)
      • 代码单元 0x0022(QUOTATION MARK)
      • escapedAttrValue
      • 代码单元 0x0022(QUOTATION MARK)
  5. part2part1">"字符串连接
  6. part3part2contentsString字符串连接
  7. part4part3"</"tag">"字符串连接
  8. 返回 part4

B.2.2.3 String.prototype.big ( )

此方法在被调用时执行以下步骤:

  1. stringthis 值。
  2. 返回 ? CreateHTML(string, "big", "", "")。

B.2.2.4 String.prototype.blink ( )

此方法在被调用时执行以下步骤:

  1. stringthis 值。
  2. 返回 ? CreateHTML(string, "blink", "", "")。

B.2.2.5 String.prototype.bold ( )

此方法在被调用时执行以下步骤:

  1. stringthis 值。
  2. 返回 ? CreateHTML(string, "b", "", "")。

B.2.2.6 String.prototype.fixed ( )

此方法在被调用时执行以下步骤:

  1. stringthis 值。
  2. 返回 ? CreateHTML(string, "tt", "", "")。

B.2.2.7 String.prototype.fontcolor ( colour )

此方法在被调用时执行以下步骤:

  1. stringthis 值。
  2. 返回 ? CreateHTML(string, "font", "color", colour)。

B.2.2.8 String.prototype.fontsize ( size )

此方法在被调用时执行以下步骤:

  1. stringthis 值。
  2. 返回 ? CreateHTML(string, "font", "size", size)。

B.2.2.9 String.prototype.italics ( )

此方法在被调用时执行以下步骤:

  1. stringthis 值。
  2. 返回 ? CreateHTML(string, "i", "", "")。

B.2.2.10 String.prototype.link ( url )

此方法在被调用时执行以下步骤:

  1. stringthis 值。
  2. 返回 ? CreateHTML(string, "a", "href", url)。

B.2.2.11 String.prototype.small ( )

此方法在被调用时执行以下步骤:

  1. stringthis 值。
  2. 返回 ? CreateHTML(string, "small", "", "")。

B.2.2.12 String.prototype.strike ( )

此方法在被调用时执行以下步骤:

  1. stringthis 值。
  2. 返回 ? CreateHTML(string, "strike", "", "")。

B.2.2.13 String.prototype.sub ( )

此方法在被调用时执行以下步骤:

  1. stringthis 值。
  2. 返回 ? CreateHTML(string, "sub", "", "")。

B.2.2.14 String.prototype.sup ( )

此方法在被调用时执行以下步骤:

  1. stringthis 值。
  2. 返回 ? CreateHTML(string, "sup", "", "")。

B.2.2.15 String.prototype.trimLeft ( )

Note

首选属性 "trimStart""trimLeft" 属性主要是为与旧代码兼容而提供。建议在新的 ECMAScript 代码中使用 "trimStart" 属性。

"trimLeft" 属性的初始值是 %String.prototype.trimStart%,定义于 22.1.3.34

B.2.2.16 String.prototype.trimRight ( )

Note

首选属性 "trimEnd""trimRight" 属性主要是为与旧代码兼容而提供。建议在新的 ECMAScript 代码中使用 "trimEnd" 属性。

"trimRight" 属性的初始值是 %String.prototype.trimEnd%,定义于 22.1.3.33

B.2.3 Date.prototype 对象的附加属性

B.2.3.1 Date.prototype.getYear ( )

Note

几乎所有用途都首选 getFullYear 方法,因为它避免了“2000 年问题”。

此方法在被调用时执行以下步骤:

  1. dateObjthis 值。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. tvdateObj.[[DateValue]]
  4. 如果 tvNaN,则返回 NaN
  5. 返回 YearFromTime(LocalTime(tv)) - 1900𝔽

B.2.3.2 Date.prototype.setYear ( year )

Note

几乎所有用途都首选 setFullYear 方法,因为它避免了“2000 年问题”。

此方法在被调用时执行以下步骤:

  1. dateObjthis 值。
  2. 执行 ? RequireInternalSlot(dateObj, [[DateValue]])。
  3. timedateObj.[[DateValue]]
  4. year 为 ? ToNumber(year)。
  5. 如果 timeNaN,则将 time 设置为 +0𝔽;否则将 time 设置为 LocalTime(time)。
  6. fullYearMakeFullYear(year)。
  7. dayMakeDay(fullYear, MonthFromTime(time), DateFromTime(time))。
  8. dateMakeDate(day, TimeWithinDay(time))。
  9. utcTimestampTimeClip(UTC(date))。
  10. dateObj.[[DateValue]] 设置为 utcTimestamp
  11. 返回 utcTimestamp

B.2.3.3 Date.prototype.toGMTString ( )

Note

首选 toUTCString 方法。此方法主要是为与旧代码兼容而提供。

"toGMTString" 属性的初始值是 %Date.prototype.toUTCString%,定义于 21.4.4.43

B.2.4 RegExp.prototype 对象的附加属性

B.2.4.1 RegExp.prototype.compile ( pattern, flags )

此方法在被调用时执行以下步骤:

  1. objthis 值。
  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)。
Note

此方法用新的模式和标志完全重新初始化 this 值 RegExp。实现可以将此方法的使用解释为一种断言,即所得 RegExp 对象将被多次使用,因此是额外优化的候选。

B.3 其他附加特性

B.3.1 带标签的函数声明

在 ECMAScript 2015 之前,LabelledStatement 的规范不允许把语句标签与 FunctionDeclaration 相关联。然而,带标签的 FunctionDeclaration 是非严格代码允许的扩展,大多数浏览器宿主的 ECMAScript 实现都支持该扩展。在 ECMAScript 2015 及更高版本中,LabelledStatement 的语法产生式允许使用 FunctionDeclaration 作为 LabelledItem,但 14.13.1 包含一条早期错误规则,如果出现这种情况则产生语法错误。然后会修改该规则,以便在宿主支持此特性的情况下,在非严格代码中抑制该语法错误。

Note

WithStatementIfStatementIterationStatement早期错误规则阻止这些语句在非严格代码中包含带标签的 FunctionDeclaration

B.3.2 块级函数声明的 Web 遗留兼容性语义

在 ECMAScript 2015 之前,ECMAScript 规范没有定义 FunctionDeclaration 作为 Block 语句的 StatementList 元素出现的情况。然而,对这种 FunctionDeclaration 形式的支持是允许的扩展,大多数浏览器宿主的 ECMAScript 实现都允许它们。不幸的是,这类声明的语义在这些实现之间有所不同。由于这些语义差异,使用 Block 级函数声明的现有 Web ECMAScript 源文本,只有在其用法仅依赖所有浏览器实现对这类声明的语义交集时,才能在浏览器实现之间可移植。以下是落入该交集语义的用例:

  1. 函数在单个块内声明并且只在该块内引用。

  2. 函数在单个 Block 内声明并可能使用,但也被一个不包含在同一 Block 内的内部函数定义引用。

    • 一个或多个 FunctionDeclaration 出现在外围函数 g 的函数代码中,其 BindingIdentifier 是名称 f,并且该声明嵌套在 Block 内。
    • g 的函数代码中没有其他不是 var 声明的 f 声明。
    • 作为 IdentifierReferencef 可能出现在包含 f 声明的 BlockStatementList 内。
    • 在嵌套于 g 内的另一个函数 h 中,至少有一次作为 IdentifierReferencef 出现,并且没有其他 f 声明遮蔽来自 h 内部的对 f 的引用。
    • h 的所有调用都发生在 f 的声明已被求值之后。
  3. 函数在单个块内声明并可能使用,但也在后续块中被引用。

第一个用例与 ECMAScript 2015 为 Block 级函数声明提供的语义可互操作。任何采用该用例的既有 ECMAScript 源文本,都将使用条款 101415 定义的块级函数声明语义运行。

第二和第三个用例的 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 的一条早期错误规则来实现。

Note

运行时,这类绑定在 VariableDeclarationEnvironment 中实例化。它们不会遮蔽由 CatchParameter 引入的同名绑定,因此这类 var 声明的 Initializer 会赋值给相应的 catch 参数,而不是 var 绑定。

此修改后的行为也适用于包含Catch 子句的 Block 中的直接 eval 调用所引入的 varfunction 声明。此变更通过修改 EvalDeclarationInstantiation 中的步骤 3.d.i.2.a.i13.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]

此产生式仅在解析非严格代码时适用。

8.3.1ContainsDuplicateLabels静态语义通过以下内容扩充:

ForInOfStatement : for ( var BindingIdentifier Initializer in Expression ) Statement
  1. 返回以 labelSet 为实参的 StatementContainsDuplicateLabels

8.3.2ContainsUndefinedBreakTarget静态语义通过以下内容扩充:

ForInOfStatement : for ( var BindingIdentifier Initializer in Expression ) Statement
  1. 返回以 labelSet 为实参的 StatementContainsUndefinedBreakTarget

8.3.3ContainsUndefinedContinueTarget静态语义通过以下内容扩充:

ForInOfStatement : for ( var BindingIdentifier Initializer in Expression ) Statement
  1. 返回以 iterationSet 和 « » 为实参的 StatementContainsUndefinedContinueTarget

14.7.5.2IsDestructuring静态语义通过以下内容扩充:

BindingIdentifier : Identifier yield await
  1. 返回 false

8.2.8VarDeclaredNames静态语义通过以下内容扩充:

ForInOfStatement : for ( var BindingIdentifier Initializer in Expression ) Statement
  1. names1BindingIdentifierBoundNames
  2. names2StatementVarDeclaredNames
  3. 返回 names1names2列表连接

8.2.9VarScopedDeclarations静态语义通过以下内容扩充:

ForInOfStatement : for ( var BindingIdentifier Initializer in Expression ) Statement
  1. decls1 为 « BindingIdentifier »。
  2. decls2StatementVarScopedDeclarations
  3. 返回 decls1decls2列表连接

14.7.5.5ForInOfLoopEvaluation运行时语义通过以下内容扩充:

ForInOfStatement : for ( var BindingIdentifier Initializer in Expression ) Statement
  1. bindingIdBindingIdentifierStringValue
  2. lhs 为 ? ResolveBinding(bindingId)。
  3. 如果 IsAnonymousFunctionDefinition(Initializer) 是 true,则
    1. value 为以 bindingId 为实参的 InitializerNamedEvaluation
  4. 否则,
    1. rhs 为 ? 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]] 内部槽的对象,在 ToBooleanIsLooselyEqual 抽象操作中,以及作为 typeof 运算符的操作数使用时,行为类似于 undefined

Note

具有 [[IsHTMLDDA]] 内部槽的对象永远不会由本规范创建。然而,Web 浏览器中的 document.all 对象是一个具有此槽的宿主定义 exotic object,它为 Web 兼容性目的而存在。此类对象没有其他已知示例,并且实现不应创建任何这类对象,document.all 除外。

此特性在以下位置涉及特殊语义:

B.3.7 HostMakeJobCallback 中的非默认行为

HostMakeJobCallback 抽象操作允许作为 Web 浏览器的宿主指定非默认行为。

B.3.8 HostEnsureCanAddPrivateElement 中的非默认行为

HostEnsureCanAddPrivateElement 抽象操作允许作为 Web 浏览器的宿主指定非默认行为。

B.3.9 函数调用赋值目标的运行时错误

当函数调用(13.3.6)在非严格代码中用作赋值目标时,不产生早期错误,而是在赋值求值期间抛出 ReferenceError 异常。

Note

当赋值目标是 AssignmentExpressionLeftHandSideExpression 时,赋值运算符必须是 =AssignmentOperator;特别地,这里的允许不适用于逻辑赋值运算符(??=&&=||=)。

AssignmentTargetType CallExpression : CoverCallExpressionAndAsyncArrowHead CallExpression : CallExpression Arguments 的步骤 1

Annex C (informative) ECMAScript 的严格模式

严格模式限制和例外

Annex D (informative) 宿主分层点

关于宿主的定义,见 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]]:见 Table 20

Script Record 上的 [[HostDefined]]:见 Table 35

Module Record 上的 [[HostDefined]]:见 Table 39

JobCallback Record 上的 [[HostDefined]]:见 Table 24

[[IsHTMLDDA]]:见 B.3.6

D.3 宿主定义对象

全局对象:见条款 19

D.4 运行 Job

调用 Job Abstract Closure 前的准备步骤和调用后的清理步骤。见 9.5

D.5 Exotic Object 的内部方法

对于本规范中未规定的任何 exotic object,Table 4 中任何基本内部方法。

D.6 内置对象和方法

本规范中未定义的任何内置对象和方法,除非受 17.1 限制。

Annex E (informative) ECMAScript 2015 中可能影响兼容性的修正和澄清

9.1.1.4.14-9.1.1.4.17 第 5 版和第 5.1 版使用属性存在性测试来确定与新的全局声明对应的全局对象属性是否已经存在。ECMAScript 2015 使用自有属性存在性测试。这对应于 Web 浏览器最常实现的行为。

10.4.2.1:第 5 版将当前数组长度的捕获移到了数组索引或新 length 值的整数转换之前。然而,如果转换过程具有改变数组长度的副作用,则捕获的 length 值可能变得无效。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:先前版本没有规定当时间值NaNDate.prototype.toString 返回的值。ECMAScript 2015 规定结果为 String 值 "Invalid Date"

22.2.4.122.2.6.13.1:RegExp 实例的 "source" 属性值中的任何 LineTerminator 代码点都必须使用转义序列表达。第 5.1 版只要求转义 /

22.2.6.822.2.6.11:在先前版本中,String.prototype.matchString.prototype.replace 的规范在模式实参是设置了 global 标志的 RegExp 值的情况下是不正确的。先前规范规定,对于每次尝试匹配模式,如果 lastIndex 没有变化,则应将其递增 1。正确行为是,只有当模式匹配空 String 时,才应将 lastIndex 递增 1。

23.1.3.30:先前版本没有规定 Array.prototype.sort 如何解释 comparator 返回的 NaN 值。ECMAScript 2015 规定,这样的值被视为 comparator 返回了 +0𝔽。ECMAScript 2015 还规定,对 comparator 返回的结果应用 ToNumber。在先前版本中,不是 Number 值comparator 结果的效果是实现定义的。实践中,实现会调用 ToNumber

Annex F (informative) 引入与先前版本不兼容性的新增和变更

6.2.5:在 ECMAScript 2015 中,Function 调用不允许返回 Reference Record

7.1.4.1:在 ECMAScript 2015 中,应用于 String 值的 ToNumber 现在会识别并转换 BinaryIntegerLiteralOctalIntegerLiteral 数值字符串。在先前版本中,这类字符串会被转换为 NaN

9.3:在 ECMAScript 2018 中,Template 对象基于 Parse Node(源位置)规范化,而不是像先前版本中那样,在一个 Realm 内跨该模板字面量或 tagged template 的所有出现进行规范化。

12.2:在 ECMAScript 2016 中,强制要求 Unicode 8.0.0 或更高版本,而 ECMAScript 2015 强制要求 Unicode 5.1。特别是,这导致 U+180E MONGOLIAN VOWEL SEPARATOR 从 Space_SeparatorZs)类别移到 FormatCf)类别(自 Unicode 6.3.0 起),该字符在 ECMAScript 2015 中因此被视为空白。这会导致空白敏感方法的行为不同。例如,"\u180E".trim().length 在先前版本中为 0,但在 ECMAScript 2016 及更高版本中为 1。此外,ECMAScript 2017 强制要求始终使用 Unicode Standard 的最新版本。

12.7:在 ECMAScript 2015 中,有效的 IdentifierName 代码点以 Unicode 属性“ID_Start”和“ID_Continue”来规定。在先前版本中,有效的 IdentifierNameIdentifier 代码点通过枚举各种 Unicode 代码点类别来规定。

12.10.1:在 ECMAScript 2015 中,如果 do-while 语句末尾缺少分号,自动分号插入会添加一个分号。此变更使规范与大多数现有实现的实际行为保持一致。

13.2.5.1:在 ECMAScript 2015 中,对象初始化器中具有重复属性名不再是早期错误

13.15.1:在 ECMAScript 2015 中,包含对不可变绑定(例如 FunctionExpression 的函数名)赋值的严格模式代码不会产生早期错误。相反,它会产生运行时错误。

14.2:在 ECMAScript 2015 中,以 token let 开头、后跟输入元素 LineTerminator 再后跟 IdentifierStatementListLexicalDeclaration 的开始。在先前版本中,自动分号插入总会在 Identifier 输入元素之前插入分号。

14.5:在 ECMAScript 2015 中,以 token let 开头、后跟 token [StatementListItemLexicalDeclaration 的开始。在先前版本中,这样的序列会是 ExpressionStatement 的开始。

14.6.2:在 ECMAScript 2015 中,IfStatement 的正常结果永远不是值 empty。如果没有求值任何 Statement 部分,或求值的 Statement 部分产生包含 empty 的 normal completion,则 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 的 normal completion。如果 IterationStatementStatement 部分没有被求值,或 Statement 部分的最终求值产生 [[Value]]empty 的 normal completion,则对 IterationStatement 求值的结果是 [[Value]]undefined 的 normal completion。

14.11.2:在 ECMAScript 2015 中,对 WithStatement 求值的结果永远不是 [[Value]]empty 的 normal completion。如果 WithStatementStatement 部分的求值产生 [[Value]]empty 的 normal completion,则对 WithStatement 求值的结果是 [[Value]]undefined 的 normal completion。

14.12.4:在 ECMAScript 2015 中,对 SwitchStatement 求值的结果永远不是 [[Value]]empty 的 normal completion。如果 SwitchStatementCaseBlock 部分的求值产生 [[Value]]empty 的 normal completion,则对 SwitchStatement 求值的结果是 [[Value]]undefined 的 normal completion。

14.15:在 ECMAScript 2015 中,如果 Catch 子句包含Catch 子句参数中出现的同一 Identifier 对应的 var 声明,则为早期错误。在先前版本中,这种变量声明会在外围变量环境中实例化,但声明的 Initializer 值会被赋给 Catch 参数。

14.1519.2.1.3:在 ECMAScript 2015 中,如果 Catch 子句求值一个非严格直接 eval,其 eval 代码包含绑定与 Catch 子句参数中出现的同一 IdentifiervarFunctionDeclaration 声明,则会抛出运行时 SyntaxError

14.15.3:在 ECMAScript 2015 中,TryStatement 的结果永远不是值 empty。如果 TryStatementBlock 部分求值为包含 empty 的 normal completion,则 TryStatement 的结果为 undefined。如果 TryStatementBlock 部分求值为 throw completion,并且它具有求值为包含 empty 的 normal completion 的 Catch 部分,那么如果没有 Finally 子句,或其 Finally 子句求值为 empty normal completion,则 TryStatement 的结果是 undefined

15.4.5 在 ECMAScript 2015 中,在 ObjectLiteral 中作为访问器属性 [[Get]][[Set]] 特性值创建的函数对象不是构造器函数,并且它们没有 "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 中,bound function 的 [[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 Standard 规范等价的 String 视为相同。在先前版本中,实现被允许忽略规范等价性,而可以改用按位比较。

22.1.3.2822.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,则会创建一个新的 RegExp 实例,它与 pattern 相同,只是 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.427.9.3.6:在 ECMAScript 2019 中,await 入队的 Job 数量被减少,这可能会在 then() 调用和 await 表达式之间的解决顺序上产生可观察差异。

参考文献

  1. IEEE 754-2019浮点算术 IEEE 标准。Institute of Electrical and Electronic Engineers,纽约(2019) Note

    IEEE 754-2008 和 IEEE 754-2019 之间没有影响 ECMA-262 规范的规范性变更。

  2. Unicode Standard,可见于 <https://unicode.org/versions/latest>
  3. Unicode Technical Note #5:应用中的规范等价性,可见于 <https://unicode.org/notes/tn5/>
  4. Unicode Technical Standard #10:Unicode 排序算法,可见于 <https://unicode.org/reports/tr10/>
  5. Unicode Standard Annex #15,Unicode 规范化形式,可见于 <https://unicode.org/reports/tr15/>
  6. Unicode Standard Annex #18:Unicode 正则表达式,可见于 <https://unicode.org/reports/tr18/>
  7. Unicode Standard Annex #24:Unicode Script 属性,可见于 <https://unicode.org/reports/tr24/>
  8. Unicode Standard Annex #31,Unicode 标识符和模式语法,可见于 <https://unicode.org/reports/tr31/>
  9. Unicode Standard Annex #44:Unicode 字符数据库,可见于 <https://unicode.org/reports/tr44/>
  10. Unicode Technical Standard #51:Unicode Emoji,可见于 <https://unicode.org/reports/tr51/>
  11. IANA 时区数据库,可见于 <https://www.iana.org/time-zones>
  12. ISO 8601:2004(E) 数据元素和交换格式 — 信息交换 — 日期和时间的表示
  13. RFC 1738 “统一资源定位符(URL)”,可见于 <https://tools.ietf.org/html/rfc1738>
  14. RFC 2396 “统一资源标识符(URI):通用语法”,可见于 <https://tools.ietf.org/html/rfc2396>
  15. RFC 3629 “UTF-8,ISO 10646 的一种转换格式”,可见于 <https://tools.ietf.org/html/rfc3629>
  16. RFC 7231 “超文本传输协议(HTTP/1.1):语义和内容”,可见于 <https://tools.ietf.org/html/rfc7231>

本规范在 GitHub 上以一种名为 Ecmarkup 的纯文本源格式编写。Ecmarkup 是一种 HTML 和 Markdown 方言,提供用于以纯文本编写 Ecma 规范并将规范处理为功能完整的 HTML 呈现的框架和工具集,其呈现遵循本文档的编辑约定。Ecmarkup 构建于并集成了其他一些格式和技术,包括用于定义语法的 Grammarkdown,以及用于编写算法步骤的 Ecmarkdown。本规范的 PDF 呈现使用打印样式表生成,该样式表利用了 CSS Paged Media 规范,并使用 PrinceXML 进行转换。

本规范的先前版本使用 Word 编写——构成本版基础的 Ecmarkup 源文本,是通过自动转换工具将 ECMAScript 2015 Word 文档转换为 Ecmarkup 而生成的。

Copyright & Software License

Ecma International

Rue du Rhone 114

CH-1204 Geneva

Tel: +41 22 849 6000

Fax: +41 22 849 6001

Web: https://ecma-international.org/

Software License

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.