ECMA-262 草案 / 2025年5月19日

ECMAScript® 2026 语言规范

关于本规范

位于 https://tc39.es/ecma262/ 的文档是最准确和最新的 ECMAScript 规范。它包含最新年度快照的内容以及自该快照以来的所有 已完成提案 (那些在 提案流程 中达到第4阶段的提案,因此已在多个实现中实现,将包含在下一个实际修订版中)。

本文档提供 单页版多页版

为本规范做贡献

本规范在 GitHub 上借助 ECMAScript 社区的帮助进行开发。有多种方式可以为本规范的开发做出贡献:

有关本文档创建方式的更多信息,请参阅版权页

介绍

本 Ecma 标准定义了 ECMAScript 2026 语言。这是 ECMAScript 语言规范的第十七版。自 1997 年第一版发布以来,ECMAScript 已经发展成为世界上最广泛使用的通用编程语言之一。它最为人所知的是作为嵌入在 Web 浏览器中的语言,但也被广泛应用于服务器和嵌入式应用程序。

ECMAScript 基于几种原创技术,最著名的是 JavaScript(Netscape)和 JScript(Microsoft)。该语言由 Brendan Eich 在 Netscape 发明,首次出现在该公司的 Navigator 2.0 浏览器中。它出现在 Netscape 的所有后续浏览器中,以及从 Internet Explorer 3.0 开始的所有 Microsoft 浏览器中。

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

该 Ecma 标准已提交给 ISO/IEC JTC 1,按照快速通道程序通过,并于 1998 年 4 月批准为国际标准 ISO/IEC 16262。1998 年 6 月的 Ecma 大会批准了 ECMA-262 的第二版,以保持与 ISO/IEC 16262 完全一致。第一版和第二版之间的变化在性质上是编辑性的。

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

第三版发布后,ECMAScript 与万维网结合实现了大规模应用,成为几乎所有 Web 浏览器支持的编程语言。为开发 ECMAScript 第四版做了大量工作。然而,这项工作没有完成,也没有作为 ECMAScript 第四版发布,但其中一些内容被纳入了第六版的开发中。

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

第五版已提交给 ISO/IEC JTC 1,按照快速通道程序通过,并批准为国际标准 ISO/IEC 16262:2011。ECMAScript 标准的 5.1 版纳入了小幅更正,与 ISO/IEC 16262:2011 文本相同。5.1 版于 2011 年 6 月由 Ecma 大会通过。

第六版的重点开发始于 2009 年,当时第五版正在准备发布。然而,这之前进行了大量的实验和语言增强设计工作,可以追溯到 1999 年第三版的发布。从很真实的意义上说,第六版的完成是十五年努力的顶峰。这一版的目标包括为大型应用程序、库创建以及将 ECMAScript 用作其他语言的编译目标提供更好的支持。它的一些主要增强功能包括模块、类声明、词法块作用域、迭代器和生成器、用于异步编程的 promise、解构模式和适当的尾调用。ECMAScript 内置库得到扩展,支持额外的数据抽象,包括映射、集合和二进制数值数组,以及对字符串和正则表达式中 Unicode 补充字符的额外支持。内置功能也通过子类化变得可扩展。第六版为常规的、增量的语言和库增强提供了基础。第六版于 2015 年 6 月由大会通过。

ECMAScript 2016 是在 Ecma TC39 新的年度发布节奏和开放开发过程下发布的第一个 ECMAScript 版本。从 ECMAScript 2015 源文档构建了一个纯文本源文档,作为完全在 GitHub 上进一步开发的基础。在这个标准开发的一年中,提交了数百个拉取请求和问题,代表了数千个错误修复、编辑修复和其他改进。此外,还开发了许多软件工具来帮助这一工作,包括 Ecmarkup、Ecmarkdown 和 Grammarkdown。ES2016 还包括对新指数运算符的支持,并向 Array.prototype 添加了一个名为 includes 的新方法。

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

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

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

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

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

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

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

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

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

代表众多组织的数十名个人在 Ecma TC39 内对本版本和以前版本的开发做出了非常重要的贡献。此外,已经形成了一个充满活力的社区来支持 TC39 的 ECMAScript 工作。这个社区审查了许多草案,提交了数千个错误报告,进行了实现实验,贡献了测试套件,并向全球开发者社区介绍了 ECMAScript。不幸的是,无法识别和承认每个为这一努力做出贡献的个人和组织。

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

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

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

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

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

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

1 范围

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

2 一致性

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

ECMAScript 的一致性实现必须按照最新版本的 Unicode 标准和 ISO/IEC 10646 来解释源文本输入。

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

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

ECMAScript 的一致性实现可以支持本规范中未描述的程序和正则表达式语法。特别是,ECMAScript 的一致性实现可以支持使用本规范子条款 12.7.2 中注明的任何"未来保留字"的程序语法。

ECMAScript 的一致性实现不得实现子条款 17.1 中列为禁止扩展的任何扩展。

ECMAScript 的一致性实现不得重新定义任何不是实现定义实现近似宿主定义的功能。

ECMAScript 的一致性实现可以选择实现或不实现规范可选子条款。如果实现了任何规范可选行为,则必须实现包含规范可选条款中的所有行为。规范可选条款在本规范中用彩色框中的"规范可选"字样表示,如下所示。

2.1 示例规范可选条款标题

示例条款内容。

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

2.2 示例遗留条款标题

示例条款内容。

2.3 示例遗留规范可选条款标题

示例条款内容。

3 规范性引用

以下引用文档对于本文档的应用是必不可少的。对于注明日期的引用,只适用所引用的版本。对于未注明日期的引用,适用引用文档的最新版本(包括任何修订)。

IEEE 754-2019IEEE 浮点运算标准

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

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

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

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

4 概述

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

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

ECMAScript 最初被设计用作脚本语言,但现已广泛用作通用编程语言。脚本语言是一种编程语言,用于操作、自定义和自动化现有系统的设施。在这样的系统中,有用的功能已经通过用户界面可用,脚本语言是将该功能暴露给程序控制的机制。通过这种方式,现有系统被称为提供对象和设施的宿主环境,这完善了脚本语言的功能。脚本语言旨在供专业和非专业程序员使用。

ECMAScript 最初被设计为Web 脚本语言,提供在浏览器中活跃网页并作为基于 Web 的客户端-服务器架构的一部分执行服务器计算的机制。ECMAScript 现在用于为各种宿主环境提供核心脚本功能。因此,核心语言在本文档中独立于任何特定的宿主环境进行规定。

ECMAScript 的使用已经超越了简单的脚本编写,现在用于许多不同环境和规模中编程任务的全谱。随着 ECMAScript 使用的扩展,它提供的功能和设施也在扩展。ECMAScript 现在是一种功能齐全的通用编程语言。

4.1 Web 脚本

Web 浏览器为客户端计算提供 ECMAScript 宿主环境,例如,包括表示窗口、菜单、弹出窗口、对话框、文本区域、锚点、框架、历史记录、cookie 和输入/输出的对象。此外,宿主环境提供了将脚本代码附加到事件(如焦点变化、页面和图像加载、卸载、错误和中止、选择、表单提交和鼠标操作)的方法。脚本代码出现在 HTML 中,显示的页面是用户界面元素和固定及计算文本和图像的组合。脚本代码对用户交互是响应式的,不需要主程序。

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

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

4.2 宿主和实现

为了帮助将 ECMAScript 集成到宿主环境中,本规范将某些设施(例如,抽象操作)的定义,无论是全部还是部分,推迟到本规范之外的来源。编辑上,本规范区分了以下几种推迟类型。

实现是进一步定义附录 D 中列举的设施或那些标记为实现定义实现近似的设施的外部来源。在非正式使用中,实现指的是具体的产物,如特定的 Web 浏览器。

实现定义设施是将其定义推迟到外部来源而无需进一步限定的设施。本规范不对特定行为提出任何建议,符合规范的实现可以在本规范提出的约束内自由选择任何行为。

实现近似设施是将其定义推迟到外部来源同时推荐理想行为的设施。虽然符合规范的实现可以在本规范提出的约束内自由选择任何行为,但鼓励它们努力接近理想。某些数学运算,如Math.exp,是实现近似的。

宿主是进一步定义附录 D 中列出的设施但不进一步定义其他实现定义实现近似设施的外部来源。在非正式使用中,宿主指的是所有实现的集合,如所有 Web 浏览器的集合,它们通过附录 D 以相同方式与本规范接口。宿主通常是外部规范,如 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 和九种不同类型的类型化数组,其元素都有特定的数值数据表示;键值集合,包括 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隐式引用,以此类推;这称为原型链。当对对象中的属性进行引用时,该引用是对原型链中包含该名称属性的第一个对象中该名称的属性的引用。换句话说,首先检查直接提到的对象是否有这样的属性;如果该对象包含命名属性,那就是引用所指的属性;如果该对象不包含命名属性,则接下来检查该对象的原型;以此类推。

图 1:对象/原型关系
一个包含许多框和箭头的图像。

在基于类的面向对象语言中,一般来说,状态由实例承载,方法由类承载,继承只是结构和行为的继承。在 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 的严格模式语法和语义在个别ECMAScript 源文本单元级别上明确进行,如 11.2.2 中所述。因为严格模式在语法源文本单元级别上被选择,严格模式只施加在这样的源文本单元内具有局部效果的限制。严格模式不限制或修改必须在多个源文本单元中一致运行的 ECMAScript 语义的任何方面。完整的 ECMAScript 程序可以由严格模式和非严格模式ECMAScript 源文本单元组成。在这种情况下,严格模式只在实际执行在严格模式源文本单元中定义的代码时应用。

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

4.4 术语和定义

就本文档而言,以下术语和定义适用。

4.4.1 实现近似

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

4.4.2 实现定义

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

4.4.3 宿主定义

实现定义相同

编辑上,见条款 4.2

4.4.4 类型

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

4.4.5 原始值

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

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

4.4.6 对象

Object 类型的成员

对象是属性的集合,并且有一个原型对象。原型可能是 null

4.4.7 构造函数

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

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

4.4.8 原型

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

构造函数创建对象时,该对象隐式引用构造函数"prototype" 属性以解决属性引用。构造函数"prototype" 属性可以通过程序表达式 constructor.prototype 引用,添加到对象原型的属性通过继承被所有共享该原型的对象共享。或者,可以使用 Object.create 内置函数创建具有明确指定原型的新对象。

4.4.9 普通对象

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

4.4.10 异质对象

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

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

4.4.11 标准对象

语义由本规范定义的对象

4.4.12 内置对象

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

标准内置对象在本规范中定义。ECMAScript 实现可以指定和提供本规范中未描述的其他类型的内置对象。

4.4.13 undefined 值

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

4.4.14 Undefined 类型

唯一值为 undefined 值的类型

4.4.15 null 值

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

4.4.16 Null 类型

唯一值为 null 值的类型

4.4.17 Boolean 值

Boolean 类型的成员

只有两个 Boolean 值,truefalse

4.4.18 Boolean 类型

由原始值 truefalse 组成的类型

4.4.19 Boolean 对象

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

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

4.4.20 String 值

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

String 值是String 类型的成员。序列中的每个整数值通常表示 UTF-16 文本的单个 16 位单元。但是,ECMAScript 对值没有任何限制或要求,除了它们必须是 16 位无符号整数

4.4.21 String 类型

所有可能 String 值的集合

4.4.22 String 对象

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

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

4.4.23 Number 值

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

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

4.4.24 Number 类型

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

4.4.25 Number 对象

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

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

4.4.26 Infinity

正无限 Number 值的 Number 值

4.4.27 NaN

IEEE 754-2019 NaN("非数字")值的 Number 值

4.4.28 BigInt 值

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

4.4.29 BigInt 类型

所有可能 BigInt 值的集合

4.4.30 BigInt 对象

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

4.4.31 Symbol 值

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

4.4.32 Symbol 类型

所有可能 Symbol 值的集合

4.4.33 Symbol 对象

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

4.4.34 函数

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

除了其属性外,函数包含可执行代码和状态,这些决定了调用时的行为。函数的代码可能用 ECMAScript 编写,也可能不是。

4.4.35 内置函数

是函数的内置对象

内置函数的例子包括 parseIntMath.exp宿主或实现可能提供本规范中未描述的其他内置函数。

4.4.36 内置构造函数

构造函数的内置函数

内置构造函数的例子包括 ObjectFunction宿主或实现可能提供本规范中未描述的其他内置构造函数

4.4.37 属性

对象的一部分,将键(String 值或 Symbol 值)与值关联

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

4.4.38 方法

作为属性值的函数

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

4.4.39 内置方法

是内置函数的方法

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

4.4.40 特性

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

4.4.41 自有属性

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

4.4.42 继承属性

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

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 标记。这些标记是 ECMAScript 语言的保留字、标识符、字面量和标点符号。此外,行终止符虽然不被视作标记,但也成为输入元素流的一部分,并指导自动分号插入(12.10)的过程。简单的空白和单行注释会被丢弃,不会出现在句法文法的输入元素流中。如果 MultiLineComment(即形式为 /**/ 的注释,无论其是否跨越多行)不包含行终止符,则同样会被简单丢弃;但如果 MultiLineComment 包含一个或多个行终止符,则它会被替换为单个行终止符,该行终止符成为句法文法输入元素流的一部分。

ECMAScript 的 RegExp 文法在章节 22.2.1 中给出。此文法的终结符也是由 SourceCharacter 定义的代码点。它定义了一组产生式,从目标符号 Pattern 开始,描述如何将代码点序列转换为正则表达式模式。

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

5.1.3 数值字符串文法

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

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

5.1.4 语法文法

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

当代码点流要被解析为 ECMAScript ScriptModule 时,首先通过反复应用词法文法将其转换为输入元素流;然后通过单次应用语法文法解析此输入元素流。如果输入元素流中的标记无法解析为目标非终结符(ScriptModule)的单个实例且没有剩余标记,则输入流在语法上是错误的。

当解析成功时,它构造一个解析树,这是一个根树结构,其中每个节点都是一个解析节点。每个解析节点是文法中符号的一个实例;它表示可以从该符号派生的源文本范围。表示整个源文本的解析树根节点是解析的目标符号的实例。当解析节点是非终结符的实例时,它也是以该非终结符作为左侧的某个产生式的实例。此外,它有零个或多个子节点,对应产生式右侧的每个符号:每个子节点都是对应符号实例的解析节点。

为每次解析器调用实例化新的解析节点,即使是相同源文本的解析也从不重用。当且仅当解析节点表示相同的源文本范围、是相同文法符号的实例且来自相同的解析器调用时,才被认为是同一个解析节点

注 1

多次解析相同的字符串将导致不同的解析节点。例如,考虑:

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

每次调用 eval 都将 str 的值转换为 ECMAScript 源文本并执行独立的解析,创建自己独立的解析节点树。即使每次解析都操作从相同字符串值派生的源文本,这些树也是不同的。

注 2
解析节点是规范产物,实现不需要使用类似的数据结构。

语法文法的产生式以仅一个冒号":"作为标点符号来区分。

章节 1316 中呈现的语法文法并不完整地说明哪些标记序列被接受为正确的 ECMAScript ScriptModule。某些额外的标记序列也被接受,即那些如果只在序列的某些位置(如行结束符字符之前)添加分号就会被文法描述的序列。此外,如果行结束符字符出现在某些"尴尬"位置,那么文法描述的某些标记序列不被认为是可接受的。

在某些情况下,为了避免歧义,语法文法使用广义产生式,允许不构成有效 ECMAScript ScriptModule 的标记序列。例如,这种技术用于对象字面量和对象解构模式。在这种情况下,提供更严格的补充文法来进一步限制可接受的标记序列。通常,早期错误规则会声明,在某些上下文中,"P 必须覆盖一个 N",其中 P 是解析节点(广义产生式的实例),N 是补充文法中的非终结符。这意味着:

  1. 最初由 P 匹配的标记序列使用 N 作为目标符号重新解析。如果 N 接受文法参数,则设置为最初解析 P 时使用的相同值。
  2. 如果标记序列可以解析为 N 的单个实例且没有剩余标记,则:
    1. 我们将 N 的该实例(对于给定的 P 是唯一的解析节点)称为"被 P 覆盖N"。
    2. N 及其派生产生式的所有早期错误规则也适用于被 P 覆盖的 N
  3. 否则(如果解析失败),这是早期语法错误。

5.1.5 文法符号

5.1.5.1 终结符号

在 ECMAScript 文法中,一些终结符号以 固定宽度 字体显示。 这些符号必须在源文本中完全按照所写的方式出现。以这种方式指定的所有终结符号代码点 都应理解为来自基本拉丁块的适当 Unicode 代码点,而不是来自其他 Unicode 范围的任何类似代码点。 终结符号中的代码点不能用 \ UnicodeEscapeSequence 表示。

在终结符号为单个 Unicode 代码点的文法中(即词法、正则表达式和数字字符串文法), 产生式中出现的多个连续固定宽度代码点是相同代码点序列的简写, 写作独立的终结符号。

例如,产生式:

HexIntegerLiteral :: 0x HexDigits

是以下的简写:

HexIntegerLiteral :: 0 x HexDigits

相比之下,在语法文法中,连续的固定宽度代码点是单个终结符号。

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

  • 在词法和正则表达式文法中,没有常规打印表示的 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]" 出现在产生式的右侧, 它表示只有当标记序列 seq 是紧随其后的输入标记序列的前缀时,才能使用该产生式。类似地,"[lookahead ∈ set]"(其中 set 是标记序列的 有限非空集合)表示只有当 set 中的某个元素是紧随其后的标记序列的前缀时,才能使用该产生式。为了方便起见,集合也可以写作非终结符,在这种情况下,它代表该非终结符可以展开为的所有标记序列的集合。如果非终结符能够展开为无限多个不同的标记序列,则认为这是编辑错误。

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

作为示例,给定定义:

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

定义:

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

匹配字母 n 后跟一个或多个十进制数字(其中第一个数字是偶数),或者一个十进制数字后面不跟另一个十进制数字。

注意,当这些短语在语法文法中使用时,可能无法明确地识别紧随其后的标记序列,因为确定后续标记需要知道在后续位置使用哪个词法目标符号。因此,当这些在语法文法中使用时,如果标记序列 seq 出现在前瞻限制中(包括作为序列集合的一部分),并且词法目标符号的选择可能改变 seq 是否为结果标记序列的前缀,则认为这是编辑错误。

5.1.5.8 [no LineTerminator here]

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

ThrowStatement : throw [no LineTerminator here] Expression ;

表示如果在脚本的 throw 标记和 Expression 之间出现 LineTerminator,则不能使用该产生式。

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

5.1.5.9 but not

产生式的右侧可以通过使用短语 "but not" 然后指出要排除的展开来指定某些展开是不被允许的。例如,产生式:

Identifier :: IdentifierName but not ReservedWord

意味着非终结符 Identifier 可以被任何能够替换 IdentifierName 的代码点序列所替换,但前提是相同的代码点序列不能替换 ReservedWord

5.1.5.10 描述性短语

最后,少数非终结符通过无衬线字体的描述性短语来描述,这是在列出所有选择不切实际的情况下:

SourceCharacter :: any Unicode code point

5.2 算法约定

本规范通常使用编号列表来指定算法中的步骤。这些算法用于精确指定 ECMAScript 语言构造所需的语义。这些算法并非旨在暗示使用任何特定的实现技术。实际上,可能存在更有效的算法来实现给定的特性。

算法可以使用有序的、逗号分隔的别名序列进行显式参数化,这些别名可以在算法步骤中用于引用在该位置传入的参数。可选参数用方括号([ , name ])表示,在算法步骤中与必需参数没有区别。剩余参数可以出现在参数列表的末尾,用前导省略号(, ...name)表示。剩余参数将捕获在必需参数和可选参数之后提供的所有参数到一个 列表中。如果没有此类附加参数,则该 列表为空。

算法步骤可以细分为顺序的子步骤。子步骤是缩进的,并且它们本身可以进一步划分为缩进的子步骤。使用大纲编号约定来标识子步骤,第一级子步骤用小写字母标记,第二级子步骤用小写罗马数字标记。如果需要三个以上的级别,则这些规则会重复,第四级使用数字标签。例如:

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

一个步骤或子步骤可以写成一个“if”谓词,该谓词对其子步骤进行条件限制。在这种情况下,仅当谓词为真时才应用子步骤。如果一个步骤或子步骤以单词“else”开头,则它是一个谓词,该谓词是同一级别上在前的“if”谓词步骤的否定。

一个步骤可以指定其子步骤的迭代应用。

以“断言:”开头的步骤断言其算法的不变条件。此类断言用于明确算法中否则将是隐式的不变量。此类断言不增加额外的语义要求,因此实现无需检查。它们仅用于阐明算法。

算法步骤可以使用“令 xsomeValue”的形式为任何值声明命名别名。这些别名是引用式的,即 xsomeValue 都引用相同的基础数据,对其中任何一个的修改对两者都可见。希望避免这种引用式行为的算法步骤应显式复制右侧的值:“令 xsomeValue 的副本”会创建 someValue 的浅拷贝。

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

5.2.1 抽象操作

为了便于在规范的多个部分中使用,一些算法(称为抽象操作)被命名并以参数化函数形式编写,以便可以从其他算法中按名称引用它们。抽象操作通常使用函数应用样式(如 OperationName(arg1, arg2))进行引用。一些抽象操作被视为类规范抽象的多态分派方法。此类方法式抽象操作通常使用方法应用样式(如 someValue.OperationName(arg1, arg2))进行引用。

5.2.2 语法导向操作

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

当算法与产生式备选方案相关联时,该备选方案通常不带任何“[ ]”语法注释。此类注释仅影响备选方案的语法识别,对备选方案的相关语义没有影响。

语法导向操作通过使用以下算法中的步骤 134 的约定,使用解析节点以及可选的其他参数来调用:

  1. statusSomeNonTerminal 的 SyntaxDirectedOperation。
  2. someParseNode 为某个源文本的解析结果。
  3. 执行 someParseNode 的 SyntaxDirectedOperation。
  4. 执行 someParseNode 的 SyntaxDirectedOperation,参数为 "value"

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

: { 语句列表 }

但是 求值 操作没有将算法与该产生式关联起来。在这种情况下,求值 操作隐式地包含一个形式如下的关联:

运行时语义:求值

: { 语句列表 }
  1. 返回 语句列表求值

5.2.3 运行时语义

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

5.2.3.1 Completion ( completionRecord )

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

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

5.2.3.2 抛出异常

算法步骤中说要抛出异常,例如:

  1. 抛出一个 TypeError 异常。

与以下含义相同:

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

5.2.3.3 ReturnIfAbrupt

算法步骤中说或等效于:

  1. ReturnIfAbrupt(argument)。

与以下含义相同:

  1. 断言argument 是一个 完成记录
  2. 如果 argument 是一个 突然完成,则返回 Completion(argument)。
  3. 否则,将 argument 设置为 argument.[[Value]]

算法步骤中说或等效于:

  1. ReturnIfAbrupt(AbstractOperation())。

与以下含义相同:

  1. hygienicTemp 为 AbstractOperation()。
  2. 断言hygienicTemp 是一个 完成记录
  3. 如果 hygienicTemp 是一个 突然完成,则返回 Completion(hygienicTemp)。
  4. 否则,将 hygienicTemp 设置为 hygienicTemp.[[Value]]

其中 hygienicTemp 是临时的,并且仅在与 ReturnIfAbrupt 相关的步骤中可见。

算法步骤中说或等效于:

  1. result 为 AbstractOperation(ReturnIfAbrupt(argument))。

与以下含义相同:

  1. 断言argument 是一个 完成记录
  2. 如果 argument 是一个 突然完成,则返回 Completion(argument)。
  3. 否则,将 argument 设置为 argument.[[Value]]
  4. result 为 AbstractOperation(argument)。

5.2.3.4 ReturnIfAbrupt 简写

? 为前缀的 抽象操作语法导向操作的调用表示应将 ReturnIfAbrupt 应用于结果 完成记录。例如,步骤:

  1. ? OperationName()。

等效于以下步骤:

  1. ReturnIfAbrupt(OperationName())。

类似地,对于方法应用样式,步骤:

  1. someValue.OperationName()。

等效于:

  1. ReturnIfAbrupt(someValue.OperationName())。

类似地,前缀 ! 用于指示以下抽象操作或 语法导向操作的调用永远不会返回 突然完成,并且应使用结果 完成记录[[Value]] 字段代替操作的返回值。例如,步骤:

  1. val 为 ! OperationName()。

等效于以下步骤:

  1. val 为 OperationName()。
  2. 断言val 是一个 正常完成
  3. val 设置为 val.[[Value]]

语法导向操作运行时语义通过在操作调用前放置 !? 来使用此简写:

  1. 执行 ! NonTerminal 的 SyntaxDirectedOperation。

5.2.3.5 隐式正常完成

在声明返回 完成记录抽象操作内的算法中,以及在所有内置函数中,返回值首先传递给 NormalCompletion,并使用其结果。此规则不适用于 Completion 算法内,或者当返回的值在该步骤中明确标记为 完成记录时;这些情况是:

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

  1. 返回 true

与以下任何一种含义相同:

  1. 返回 NormalCompletion(true)。

  1. completionNormalCompletion(true)。
  2. 返回 Completion(completion)。

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

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

  1. 返回 ? completion

以下示例将是编辑错误,因为正在返回一个 完成记录,而没有在该步骤中进行注释。

  1. completionNormalCompletion(true)。
  2. 返回 completion

5.2.4 静态语义

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

静态语义规则具有名称,并且通常使用算法定义。命名的静态语义规则与语法产生式相关联,具有多个备选定义的产生式通常会为每个备选方案的每个适用的命名静态语义规则提供一个不同的算法。

一种特殊的静态语义规则是早期错误规则早期错误规则定义了与特定语法产生式相关的早期错误条件(参见第 17 条)。本规范的算法中并未显式调用大多数早期错误规则的求值。一致性实现必须在首次求值 脚本模块之前,验证用于解析该 脚本模块的产生式的所有早期错误规则。如果违反了任何早期错误规则,则该 脚本模块无效且无法求值

5.2.5 数学运算

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

  • 数学值:任意实数,用作默认数值类型。
  • 扩展数学值数学值以及 +∞ 和 -∞。
  • 数字IEEE 754-2019 binary64(双精度浮点)值。
  • BigIntsECMAScript 语言值,以一一对应的方式表示任意整数

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

通常,当本规范引用一个数值时,例如在短语“y 的长度”或“由四个十六进制数字表示的整数...”中,而没有明确指定数值种类时,该短语指的是一个数学值。引用数字或 BigInt 值的短语会明确注释;例如,“...中代码点数量的数字值”或“...的BigInt 值”。

当本规范中使用术语整数时,它指的是一个数学值,该值在整数集合中,除非另有说明。当本规范中使用术语整数数字值时,它指的是一个有限数字值,其数学值整数集合中。

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

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

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

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

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

短语“将 x 限制lowerupper 之间”的结果(其中 x 是一个扩展数学值lowerupper数学值lowerupper)是:如果 x < lower 则为 lower,如果 x > upper 则为 upper,否则为 x

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

注意

floor(x) = x - (x 1)

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

数学函数 minmaxabsfloortruncate 未针对数字和 BigInts 定义,任何使用非数学值参数的这些方法的用法在本规范中都应视为编辑错误。

从下界 a 到上界 b区间是一个可能是无限的、可能是空的、相同数值类型的数值集合。每个界限将被描述为包含的或排除的,但不能两者都是。有四种区间,如下所示:

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

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

5.2.6 值表示法

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

5.2.7 同一性

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

从本规范的角度来看,“是”用于比较两个值的相等性,如“如果 booltrue,则 ...”,而“包含”用于使用相等性比较在列表中搜索值,如“如果 list 包含一个 记录 r 使得 r.[[Foo]]true,则 ...”。值的规范同一性决定了这些比较的结果,并且在本规范中是公理性的。

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

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

对于所有 ECMAScript 语言值,规范同一性与语言同一性一致,但由 Symbol.for 产生的 Symbol 值除外。无规范同一性和无语言同一性的 ECMAScript 语言值undefinednull布尔值字符串数字BigInts。有规范同一性和语言同一性的 ECMAScript 语言值是并非由 Symbol.for 产生的 Symbols对象。由 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 字符串类型

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

不解释字符串内容的 ECMAScript 操作不应用任何进一步的语义。解释字符串值的操作将每个元素视为单个 UTF-16 代码单元。但是,ECMAScript 不限制这些代码单元的值或它们之间的关系,因此将字符串内容进一步解释为以 UTF-16 编码的 Unicode 码点序列的操作必须考虑到格式错误的子序列。此类操作对数值在 闭区间 0xD800 到 0xDBFF(由 Unicode 标准定义为前导代理项,或更正式地称为高位代理代码单元)内的每个代码单元以及数值在 闭区间 0xDC00 到 0xDFFF(定义为后尾代理项,或更正式地称为低位代理代码单元)内的每个代码单元应用以下规则进行特殊处理:

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

注意

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

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

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

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

6.1.4.1 StringIndexOf ( string, searchValue, fromIndex )

抽象操作 StringIndexOf 接受参数 string (一个字符串)、searchValue (一个字符串) 和 fromIndex (一个非负整数),并返回一个非负整数not-found。调用时它执行以下步骤:

  1. lenstring 的长度。
  2. 如果 searchValue 是空字符串且 fromIndexlen,则返回 fromIndex
  3. searchLensearchValue 的长度。
  4. 对于每个整数 i,使得 fromIndexilen - searchLen,按升序执行:
    1. candidatestringii + searchLen子字符串
    2. 如果 candidatesearchValue,则返回 i
  5. 返回 not-found
注1

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

注2

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

6.1.4.2 StringLastIndexOf ( string, searchValue, fromIndex )

抽象操作 StringLastIndexOf 接受参数 string (一个字符串)、searchValue (一个字符串) 和 fromIndex (一个非负整数),并返回一个非负整数not-found。调用时它执行以下步骤:

  1. lenstring 的长度。
  2. searchLensearchValue 的长度。
  3. 断言fromIndex + searchLenlen
  4. 对于每个整数 i,使得 0 ≤ ifromIndex,按降序执行:
    1. candidatestringii + searchLen子字符串
    2. 如果 candidatesearchValue,则返回 i
  5. 返回 not-found
注意

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

6.1.5 Symbol 类型

Symbol 类型是所有可用作对象属性键(6.1.7)的非字符串值的集合。

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

每个 Symbol 值都不可变地持有一个关联值,称为 [[Description]],该值要么是 undefined,要么是字符串值。

6.1.5.1 知名符号

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

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

注意
本规范的先前版本使用 @@name 形式的表示法,而当前版本将使用 %Symbol.name%。特别是,使用了以下名称:@@asyncIterator、@@hasInstance、@@isConcatSpreadable、@@iterator、@@match、@@matchAll、@@replace、@@search、@@species、@@split、@@toPrimitive、@@toStringTag 和 @@unscopables。
表 1:知名符号
规范名称 [[Description]] 值和用途
%Symbol.asyncIterator% "Symbol.asyncIterator" 一个返回对象默认异步迭代器的方法。由 for-await-of 语句的语义调用。
%Symbol.hasInstance% "Symbol.hasInstance" 一个确定构造函数对象是否将一个对象识别为该构造函数的实例的方法。由 instanceof 运算符的语义调用。
%Symbol.isConcatSpreadable% "Symbol.isConcatSpreadable" 一个布尔值属性,如果为 true,则表示一个对象应由 Array.prototype.concat 展平为其数组元素。
%Symbol.iterator% "Symbol.iterator" 一个返回对象默认迭代器的方法。由 for-of 语句的语义调用。
%Symbol.match% "Symbol.match" 一个正则表达式方法,用于将正则表达式与字符串进行匹配。由 String.prototype.match 方法调用。
%Symbol.matchAll% "Symbol.matchAll" 一个正则表达式方法,返回一个迭代器,该迭代器产生正则表达式与字符串匹配的结果。由 String.prototype.matchAll 方法调用。
%Symbol.replace% "Symbol.replace" 一个正则表达式方法,用于替换字符串中匹配的子字符串。由 String.prototype.replace 方法调用。
%Symbol.search% "Symbol.search" 一个正则表达式方法,返回字符串中与正则表达式匹配的索引。由 String.prototype.search 方法调用。
%Symbol.species% "Symbol.species" 一个函数值属性,是用于创建派生对象的构造函数
%Symbol.split% "Symbol.split" 一个正则表达式方法,用于在与正则表达式匹配的索引处拆分字符串。由 String.prototype.split 方法调用。
%Symbol.toPrimitive% "Symbol.toPrimitive" 一个将对象转换为相应原始值的方法。由 ToPrimitive 抽象操作调用。
%Symbol.toStringTag% "Symbol.toStringTag" 一个字符串值属性,用于创建对象的默认字符串描述。由内置方法 Object.prototype.toString 访问。
%Symbol.unscopables% "Symbol.unscopables" 一个对象值属性,其自身和继承的属性名称是从关联对象的 with 环境绑定中排除的属性名称。

6.1.6 数字类型

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

表 2:数字类型操作
操作 示例源 由 ... 的 求值 语义调用 结果
Number::unaryMinus -x 一元 - 运算符 Number
BigInt::unaryMinus BigInt
Number::bitwiseNOT ~x 按位非运算符 (~) 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 ( argument ) String
BigInt::toString

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

注意

ECMAScript 的第一版及后续版本为某些运算符提供了可能损失精度或截断的隐式数字转换。为了向后兼容,这些遗留的隐式转换得以保留,但为了最大限度地减少程序员出错的机会,并为未来版本中广义值类型的选择留有余地,BigInt 不提供这些转换。

6.1.6.1 Number 类型

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

注意

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

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

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

注意,既有正零也有负零。为简洁起见,出于说明目的,这些值也分别用符号 +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 运算符仅处理特定范围内的整数,例如闭区间 [-231, 231 - 1] 或闭区间 [0, 216 - 1]。这些运算符接受 Number 类型的任何值,但首先将每个此类值转换为预期范围内的整数值。请参见 7.1 中数字转换操作的说明。

6.1.6.1.1 Number::unaryMinus ( x )

抽象操作 Number::unaryMinus 接受参数 x (一个 Number) 并返回一个 Number。调用时它执行以下步骤:

  1. 如果 xNaN,则返回 NaN
  2. 返回 x 的负值;即,计算一个具有相同大小但符号相反的 Number。

6.1.6.1.2 Number::bitwiseNOT ( x )

抽象操作 Number::bitwiseNOT 接受参数 x (一个 Number) 并返回一个整数 Number。调用时它执行以下步骤:

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

6.1.6.1.3 Number::exponentiate ( base, exponent )

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

  1. 如果 exponentNaN,则返回 NaN
  2. 如果 exponent+0𝔽-0𝔽,则返回 1𝔽
  3. 如果 baseNaN,则返回 NaN
  4. 如果 base+∞𝔽,则
    1. 如果 exponent > +0𝔽,则返回 +∞𝔽。否则,返回 +0𝔽
  5. 如果 base-∞𝔽,则
    1. 如果 exponent > +0𝔽,则
      1. 如果 exponent 是一个奇数整数 Number,则返回 -∞𝔽。否则,返回 +∞𝔽
    2. 否则,
      1. 如果 exponent 是一个奇数整数 Number,则返回 -0𝔽。否则,返回 +0𝔽
  6. 如果 base+0𝔽,则
    1. 如果 exponent > +0𝔽,则返回 +0𝔽。否则,返回 +∞𝔽
  7. 如果 base-0𝔽,则
    1. 如果 exponent > +0𝔽,则
      1. 如果 exponent 是一个奇数整数 Number,则返回 -0𝔽。否则,返回 +0𝔽
    2. 否则,
      1. 如果 exponent 是一个奇数整数 Number,则返回 -∞𝔽。否则,返回 +∞𝔽
  8. 断言base有限的,并且既不是 +0𝔽 也不是 -0𝔽
  9. 如果 exponent+∞𝔽,则
    1. 如果 abs((base)) > 1,则返回 +∞𝔽
    2. 如果 abs((base)) = 1,则返回 NaN
    3. 如果 abs((base)) < 1,则返回 +0𝔽
  10. 如果 exponent-∞𝔽,则
    1. 如果 abs((base)) > 1,则返回 +0𝔽
    2. 如果 abs((base)) = 1,则返回 NaN
    3. 如果 abs((base)) < 1,则返回 +∞𝔽
  11. 断言exponent有限的,并且既不是 +0𝔽 也不是 -0𝔽
  12. 如果 base < -0𝔽exponent 不是一个整数 Number,则返回 NaN
  13. 返回一个实现近似的 Number 值,表示 (base) 的 (exponent) 次幂的结果。
注意

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 )

抽象操作 Number::multiply 接受参数 x (一个 Number) 和 y (一个 Number) 并返回一个 Number。它根据 IEEE 754-2019 二进制双精度算术规则执行乘法,产生 xy 的乘积。调用时它执行以下步骤:

  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))。
注意

有限精度乘法是可交换的,但并非总是结合的。

6.1.6.1.5 Number::divide ( x, y )

抽象操作 Number::divide 接受参数 x (一个 Number) 和 y (一个 Number) 并返回一个 Number。它根据 IEEE 754-2019 二进制双精度算术规则执行除法,产生 xy 的商,其中 x 是被除数,y 是除数。调用时它执行以下步骤:

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

6.1.6.1.6 Number::remainder ( n, d )

抽象操作 Number::remainder 接受参数 n (一个 Number) 和 d (一个 Number) 并返回一个 Number。它产生其操作数隐式除法的余数,其中 n 是被除数,d 是除数。调用时它执行以下步骤:

  1. 如果 nNaNdNaN,则返回 NaN
  2. 如果 n+∞𝔽-∞𝔽,则返回 NaN
  3. 如果 d+∞𝔽-∞𝔽,则返回 n
  4. 如果 d+0𝔽-0𝔽,则返回 NaN
  5. 如果 n+0𝔽-0𝔽,则返回 n
  6. 断言nd有限的且非零。
  7. quotient(n) / (d)。
  8. qtruncate(quotient)。
  9. r(n) - ((d) × q)。
  10. 如果 r = 0 且 n < -0𝔽,则返回 -0𝔽
  11. 返回 𝔽(r)。
注1

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

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

6.1.6.1.7 Number::add ( x, y )

抽象操作 Number::add 接受参数 x (一个 Number) 和 y (一个 Number) 并返回一个 Number。它根据 IEEE 754-2019 二进制双精度算术规则执行加法,产生其参数的和。调用时它执行以下步骤:

  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))。
注意

有限精度加法是可交换的,但并非总是结合的。

6.1.6.1.8 Number::subtract ( x, y )

抽象操作 Number::subtract 接受参数 x (一个 Number) 和 y (一个 Number) 并返回一个 Number。它执行减法,产生其操作数的差;x 是被减数,y 是减数。调用时它执行以下步骤:

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

x - y 总是产生与 x + (-y) 相同的结果。

6.1.6.1.9 Number::leftShift ( x, y )

抽象操作 Number::leftShift 接受参数 x (一个 Number) 和 y (一个 Number) 并返回一个整数 Number。调用时它执行以下步骤:

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

6.1.6.1.10 Number::signedRightShift ( x, y )

抽象操作 Number::signedRightShift 接受参数 x (一个 Number) 和 y (一个 Number) 并返回一个整数 Number。调用时它执行以下步骤:

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

6.1.6.1.11 Number::unsignedRightShift ( x, y )

抽象操作 Number::unsignedRightShift 接受参数 x (一个 Number) 和 y (一个 Number) 并返回一个整数 Number。调用时它执行以下步骤:

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

6.1.6.1.12 Number::lessThan ( x, y )

抽象操作 Number::lessThan 接受参数 x (一个 Number) 和 y (一个 Number) 并返回一个 Boolean 或 undefined。调用时它执行以下步骤:

  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。否则,返回 false

6.1.6.1.13 Number::equal ( x, y )

抽象操作 Number::equal 接受参数 x (一个 Number) 和 y (一个 Number) 并返回一个 Boolean。调用时它执行以下步骤:

  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 )

抽象操作 Number::sameValue 接受参数 x (一个 Number) 和 y (一个 Number) 并返回一个 Boolean。调用时它执行以下步骤:

  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 )

抽象操作 Number::sameValueZero 接受参数 x (一个 Number) 和 y (一个 Number) 并返回一个 Boolean。调用时它执行以下步骤:

  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 )

抽象操作 NumberBitwiseOp 接受参数 op (&^|)、x (一个 Number) 和 y (一个 Number) 并返回一个整数 Number。调用时它执行以下步骤:

  1. lNum 为 ! ToInt32(x)。
  2. rNum 为 ! ToInt32(y)。
  3. lBits 为表示 (lNum) 的 32 位二进制补码位串。
  4. rBits 为表示 (rNum) 的 32 位二进制补码位串。
  5. 如果 op&,则
    1. result 为对 lBitsrBits 应用按位与运算的结果。
  6. 否则,如果 op^,则
    1. result 为对 lBitsrBits 应用按位异或 (XOR) 运算的结果。
  7. 否则,
    1. 断言op|
    2. result 为对 lBitsrBits 应用按位或运算的结果。
  8. 返回由 32 位二进制补码位串 result 表示的整数Number 值

6.1.6.1.17 Number::bitwiseAND ( x, y )

抽象操作 Number::bitwiseAND 接受参数 x (一个 Number) 和 y (一个 Number) 并返回一个整数 Number。调用时它执行以下步骤:

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

6.1.6.1.18 Number::bitwiseXOR ( x, y )

抽象操作 Number::bitwiseXOR 接受参数 x (一个 Number) 和 y (一个 Number) 并返回一个整数 Number。调用时它执行以下步骤:

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

6.1.6.1.19 Number::bitwiseOR ( x, y )

抽象操作 Number::bitwiseOR 接受参数 x (一个 Number) 和 y (一个 Number) 并返回一个整数 Number。调用时它执行以下步骤:

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

6.1.6.1.20 Number::toString ( x, radix )

抽象操作 Number::toString 接受参数 x (一个 Number) 和 radix (一个闭区间 [2, 36] 内的整数) 并返回一个 String。它使用基数为 radix 的位置数字系统将 x 表示为字符串。使用基数 r 表示数字时使用的数字取自 "0123456789abcdefghijklmnopqrstuvwxyz" 的前 r 个代码单元(按顺序)。大小大于或等于 1𝔽 的数字的表示永远不包含前导零。调用时它执行以下步骤:

  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. 否则,
      1. 断言n ≤ 0。
      2. 返回以下各项的字符串连接
        • 代码单元 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) 的十进制表示的代码单元
注1

以下观察结果可能对实现有所帮助,但并非本标准的规范性要求的一部分:

  • 如果 x 是除 -0𝔽 之外的任何 Number 值,则 ToNumber(ToString(x)) 是 x。
  • s 的最低有效位不一定由步骤 5 中列出的要求唯一确定。
注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 整除。
注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). 1990年11月30日。可从以下网址获取:
https://ampl.com/_archive/first-website/REFS/rounding.pdf。 相关代码可从以下网址获取:
http://netlib.sandia.gov/fp/dtoa.c
http://netlib.sandia.gov/fp/g_fmt.c 也可以在各种 netlib 镜像站点找到。

6.1.6.2 BigInt 类型

BigInt 类型表示一个整数值。该值可以是任意大小,不限于特定的位宽。一般来说,除非另有说明,操作被设计为返回精确的基于数学的答案。对于二进制操作,BigInt 表现为二进制补码字符串,负数被视为左侧无限设置位。

6.1.6.2.1 BigInt::unaryMinus ( x )

抽象操作 BigInt::unaryMinus 接受参数 x(一个 BigInt)并返回一个 BigInt。调用时执行以下步骤:

  1. 如果 x = 0,返回 0
  2. 返回 -x

6.1.6.2.2 BigInt::bitwiseNOT ( x )

抽象操作 BigInt::bitwiseNOT 接受参数 x(一个 BigInt)并返回一个 BigInt。它返回 x 的一的补码。调用时执行以下步骤:

  1. 返回 -x - 1

6.1.6.2.3 BigInt::exponentiate ( base, exponent )

抽象操作 BigInt::exponentiate 接受参数 base(一个 BigInt)和 exponent(一个 BigInt),返回包含 BigInt 的正常完成或抛出完成。调用时执行以下步骤:

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

6.1.6.2.4 BigInt::multiply ( x, y )

抽象操作 BigInt::multiply 接受参数 x(一个 BigInt)和 y(一个 BigInt)并返回一个 BigInt。调用时执行以下步骤:

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

6.1.6.2.5 BigInt::divide ( x, y )

抽象操作 BigInt::divide 接受参数 x(一个 BigInt)和 y(一个 BigInt),返回包含 BigInt 的正常完成或抛出完成。调用时执行以下步骤:

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

6.1.6.2.6 BigInt::remainder ( n, d )

抽象操作 BigInt::remainder 接受参数 n(一个 BigInt)和 d(一个 BigInt),返回包含 BigInt 的正常完成或抛出完成。调用时执行以下步骤:

  1. 如果 d = 0,抛出 RangeError 异常。
  2. 如果 n = 0,返回 0
  3. quotient(n) / (d)。
  4. q(truncate(quotient))。
  5. 返回 n - (d × q)。
注意
结果的符号是被除数的符号。

6.1.6.2.7 BigInt::add ( x, y )

抽象操作 BigInt::add 接受参数 x(一个 BigInt)和 y(一个 BigInt)并返回一个 BigInt。调用时执行以下步骤:

  1. 返回 x + y

6.1.6.2.8 BigInt::subtract ( x, y )

抽象操作 BigInt::subtract 接受参数 x(一个 BigInt)和 y(一个 BigInt)并返回一个 BigInt。调用时执行以下步骤:

  1. 返回 x - y

6.1.6.2.9 BigInt::leftShift ( x, y )

抽象操作 BigInt::leftShift 接受参数 x(一个 BigInt)和 y(一个 BigInt)并返回一个 BigInt。调用时执行以下步骤:

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

6.1.6.2.10 BigInt::signedRightShift ( x, y )

抽象操作 BigInt::signedRightShift 接受参数 x(一个 BigInt)和 y(一个 BigInt)并返回一个 BigInt。调用时执行以下步骤:

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

6.1.6.2.11 BigInt::unsignedRightShift ( x, y )

抽象操作 BigInt::unsignedRightShift 接受参数 x(一个 BigInt)和 y(一个 BigInt)并返回抛出完成。调用时执行以下步骤:

  1. 抛出 TypeError 异常。

6.1.6.2.12 BigInt::lessThan ( x, y )

抽象操作 BigInt::lessThan 接受参数 x(一个 BigInt)和 y(一个 BigInt)并返回一个布尔值。调用时执行以下步骤:

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

6.1.6.2.13 BigInt::equal ( x, y )

抽象操作 BigInt::equal 接受参数 x(一个 BigInt)和 y(一个 BigInt)并返回一个布尔值。调用时执行以下步骤:

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

6.1.6.2.14 BinaryAnd ( x, y )

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

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

6.1.6.2.15 BinaryOr ( x, y )

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

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

6.1.6.2.16 BinaryXor ( x, y )

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

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

6.1.6.2.17 BigIntBitwiseOp ( op, x, y )

抽象操作 BigIntBitwiseOp 接受参数 op&^|)、x(一个 BigInt)和 y(一个 BigInt)并返回一个 BigInt。调用时执行以下步骤:

  1. 设置 x(x)。
  2. 设置 y(y)。
  3. result 为 0。
  4. shift 为 0。
  5. 重复执行,直到 (x = 0 或 x = -1) 且 (y = 0 或 y = -1):
    1. xDigitx modulo 2。
    2. yDigity modulo 2。
    3. 如果 op&,则
      1. 设置 resultresult + 2shift × BinaryAnd(xDigit, yDigit)。
    4. 否则如果 op|,则
      1. 设置 resultresult + 2shift × BinaryOr(xDigit, yDigit)。
    5. 否则,
      1. 断言op^
      2. 设置 resultresult + 2shift × BinaryXor(xDigit, yDigit)。
    6. 设置 shiftshift + 1。
    7. 设置 x 为 (x - xDigit) / 2。
    8. 设置 y 为 (y - yDigit) / 2。
  6. 如果 op&,则
    1. tmpBinaryAnd(x modulo 2, y modulo 2)。
  7. 否则如果 op|,则
    1. tmpBinaryOr(x modulo 2, y modulo 2)。
  8. 否则,
    1. 断言op^
    2. tmpBinaryXor(x modulo 2, y modulo 2)。
  9. 如果 tmp ≠ 0,则
    1. 设置 resultresult - 2shift
    2. 注意:这扩展了符号。
  10. 返回 resultBigInt 值

6.1.6.2.18 BigInt::bitwiseAND ( x, y )

抽象操作 BigInt::bitwiseAND 接受参数 x(一个 BigInt)和 y(一个 BigInt)并返回一个 BigInt。调用时执行以下步骤:

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

6.1.6.2.19 BigInt::bitwiseXOR ( x, y )

抽象操作 BigInt::bitwiseXOR 接受参数 x(一个 BigInt)和 y(一个 BigInt)并返回一个 BigInt。调用时执行以下步骤:

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

6.1.6.2.20 BigInt::bitwiseOR ( x, y )

抽象操作 BigInt::bitwiseOR 接受参数 x(一个 BigInt)和 y(一个 BigInt)并返回一个 BigInt。调用时执行以下步骤:

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

6.1.6.2.21 BigInt::toString ( x, radix )

抽象操作 BigInt::toString 接受参数 x(一个 BigInt)和 radix(一个在 2 到 36 的闭区间内的整数)并返回一个字符串。它使用基数为 radix 的位置记数法将 x 表示为字符串。在基数为 r 的 BigInt 表示中使用的数字取自 "0123456789abcdefghijklmnopqrstuvwxyz" 的前 r 个代码单元。除了 0 之外的 BigInt 表示从不包含前导零。调用时执行以下步骤:

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

6.1.7 Object 类型

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

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

对象的属性使用属性键唯一标识。属性键要么是字符串,要么是符号。所有字符串和符号(包括空字符串)都可以作为属性键属性名字符串类型的属性键

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

注意

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

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

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

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

6.1.7.1 属性特性

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

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

6.1.7.2 对象内部方法和内部槽

在 ECMAScript 中,对象的实际语义通过称为内部方法的算法指定。ECMAScript 引擎中的每个对象都与一组定义其运行时行为的内部方法相关联。这些内部方法不是 ECMAScript 语言的一部分。它们由本规范纯粹为了解释目的而定义。但是,ECMAScript 实现中的每个对象都必须按照与其关联的内部方法所指定的方式行为。实现这一点的确切方式由实现决定。

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

内部槽对应于与对象关联并由各种 ECMAScript 规范算法使用的内部状态。内部槽不是对象属性,它们不被继承。根据特定的内部槽规范,这种状态可能由任何ECMAScript 语言类型的值或特定 ECMAScript 规范类型值组成。除非明确指定,否则内部槽作为创建对象过程的一部分分配,并且不能动态添加到对象中。除非另有指定,内部槽的初始值是 undefined。本规范中的各种算法创建具有内部槽的对象。但是,ECMAScript 语言没有提供将内部槽与对象关联的直接方法。

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

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

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

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

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

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

本规范通过对象的内部方法识别不同种类的异质对象。行为上等同于特定种类异质对象(如数组异质对象绑定函数异质对象)但没有为该种类指定的相同内部方法集合的对象,不被识别为该种类的异质对象

表 4和其他类似表的"签名"列描述了每个内部方法的调用模式。调用模式总是包括描述性参数名称的括号列表。如果参数名称与 ECMAScript 类型名称相同,则该名称描述参数值的所需类型。如果内部方法明确返回值,其参数列表后跟符号"→"和返回值的类型名称。签名中使用的类型名称指的是第6节中定义的类型,并由以下附加名称扩展。"any"意味着该值可能是任何ECMAScript 语言类型

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

内部方法隐式返回完成记录,要么是包装其调用模式中显示的返回类型值的正常完成,要么是抛出完成

表 4:基本内部方法
内部方法 签名 描述
[[GetPrototypeOf]] ( ) Object | Null 确定为此对象提供继承属性的对象。null 值表示没有继承属性。
[[SetPrototypeOf]] (Object | Null) Boolean 将此对象与提供继承属性的另一个对象关联。传递 null 表示没有继承属性。返回 true 表示操作成功完成,或 false 表示操作不成功。
[[IsExtensible]] ( ) Boolean 确定是否允许向此对象添加额外属性。
[[PreventExtensions]] ( ) Boolean 控制是否可以向此对象添加新属性。如果操作成功则返回 true,如果操作不成功则返回 false
[[GetOwnProperty]] (propertyKey) Undefined | Property Descriptor 返回此对象键为 propertyKey 的自有属性的属性描述符,如果不存在这样的属性则返回 undefined
[[DefineOwnProperty]] (propertyKey, PropertyDescriptor) Boolean 创建或更改键为 propertyKey 的自有属性,使其具有 PropertyDescriptor 描述的状态。如果该属性成功创建/更新则返回 true,如果无法创建或更新该属性则返回 false
[[HasProperty]] (propertyKey) 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 返回一个列表,其元素是对象的所有自有属性键

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

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

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

6.1.7.3 基本内部方法的不变式

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

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

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

定义:

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

返回值:

任何内部方法返回的值必须是一个完成记录,具有以下之一:

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

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

[[GetPrototypeOf]] ( )

  • 正常返回类型是 Object 或 Null。
  • 如果目标是不可扩展的,并且 [[GetPrototypeOf]] 返回值 V,那么将来对 [[GetPrototypeOf]] 的所有调用都应该返回与 V SameValue 相同的值。
注意 2

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

[[SetPrototypeOf]] ( V )

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

[[IsExtensible]] ( )

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

[[PreventExtensions]] ( )

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

[[GetOwnProperty]] ( P )

  • 正常返回类型是属性描述符或 Undefined。
  • 如果返回值是属性描述符,它必须是一个完全填充的属性描述符
  • 如果 P 被描述为不可配置、不可写的自有数据属性,将来对 [[GetOwnProperty]] ( P ) 的所有调用必须返回其 [[Value]]P[[Value]] 特性为SameValue属性描述符
  • 如果 P 的除 [[Writable]][[Value]] 之外的特性可能随时间改变,或者属性可能被删除,那么 P[[Configurable]] 特性必须是 true
  • 如果 [[Writable]] 特性可能从 false 变为 true,那么 [[Configurable]] 特性必须是 true
  • 如果目标是不可扩展的并且 P 是不存在的,那么将来在目标上对 [[GetOwnProperty]] (P) 的所有调用必须将 P 描述为不存在的(即 [[GetOwnProperty]] (P) 必须返回 undefined)。
注意 3

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

[[DefineOwnProperty]] ( P, Desc )

  • 正常返回类型是 Boolean。
  • 如果 P 之前被观察为目标的不可配置自有属性,那么 [[DefineOwnProperty]] 必须返回 false,除非以下之一:
    1. P 是可写的数据属性。不可配置的可写数据属性可以更改为不可配置的不可写数据属性
    2. Desc 的所有特性都与 P 的特性为SameValue
  • 如果目标是不可扩展的并且 P 是不存在的自有属性,那么 [[DefineOwnProperty]] (P, Desc) 必须返回 false。也就是说,不可扩展的目标对象不能用新属性扩展。

[[HasProperty]] ( P )

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

[[Get]] ( P, Receiver )

  • 正常返回类型是任何ECMAScript 语言类型
  • 如果 P 之前被观察为目标的值为 V 的不可配置、不可写的自有数据属性,那么 [[Get]] 必须返回与 V SameValue 相同的值。
  • 如果 P 之前被观察为目标的 [[Get]] 特性为 undefined 的不可配置自有访问器属性,那么 [[Get]] 操作必须返回 undefined

[[Set]] ( P, V, Receiver )

  • 正常返回类型是 Boolean。
  • 如果 P 之前被观察为目标的不可配置、不可写的自有数据属性,那么 [[Set]] 必须返回 false,除非 VP[[Value]] 特性为SameValue
  • 如果 P 之前被观察为目标的 [[Set]] 特性为 undefined 的不可配置自有访问器属性,那么 [[Set]] 操作必须返回 false

[[Delete]] ( P )

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

[[OwnPropertyKeys]] ( )

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

[[Call]] ( )

[[Construct]] ( )

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

6.1.7.4 知名内置对象

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

在本规范中,像 %name% 这样的引用意味着与当前关联的、对应于该名称的内置对象。像 %name.a.b% 这样的引用意味着,就像在任何 ECMAScript 代码被评估之前访问内置对象 %name% 的 "a" 属性的值的 "b" 属性一样。当前及其内置对象的确定在9.4中描述。知名内置对象列在表 6中。

表 6:知名内置对象
内置名称 全局名称 ECMAScript 语言关联
%AggregateError% AggregateError AggregateError 构造器20.5.7.1
%Array% Array Array 构造器23.1.1
%ArrayBuffer% ArrayBuffer ArrayBuffer 构造器25.1.4
%ArrayIteratorPrototype% 数组迭代器对象的原型(23.1.5
%AsyncFromSyncIteratorPrototype% 异步-从-同步迭代器对象的原型(27.1.6
%AsyncFunction% 异步函数对象构造器27.7.1
%AsyncGeneratorFunction% 异步生成器函数对象构造器27.4.1
%AsyncGeneratorPrototype% 异步生成器对象的原型(27.6
%AsyncIteratorPrototype% 所有标准内置异步迭代器对象间接继承的对象
%Atomics% Atomics Atomics 对象(25.4
%BigInt% BigInt BigInt 构造器21.2.1
%BigInt64Array% BigInt64Array BigInt64Array 构造器23.2
%BigUint64Array% BigUint64Array BigUint64Array 构造器23.2
%Boolean% Boolean Boolean 构造器20.3.1
%DataView% DataView DataView 构造器25.3.2
%Date% Date Date 构造器21.4.2
%decodeURI% decodeURI decodeURI 函数(19.2.6.1
%decodeURIComponent% decodeURIComponent decodeURIComponent 函数(19.2.6.2
%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 迭代器对象的原型(14.7.5.10
%Function% Function Function 构造器20.2.1
%GeneratorFunction% 生成器函数对象构造器27.3.1
%GeneratorPrototype% 生成器对象的原型(27.5
%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% 迭代器辅助对象的原型(27.1.2.1
%JSON% JSON JSON 对象(25.5
%Map% Map Map 构造器24.1.1
%MapIteratorPrototype% Map 迭代器对象的原型(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.2.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 字符串迭代器对象的原型(22.2.9
%Set% Set Set 构造器24.2.2
%SetIteratorPrototype% Set 迭代器对象的原型(24.2.6
%SharedArrayBuffer% SharedArrayBuffer SharedArrayBuffer 构造器25.2.3
%String% String String 构造器22.1.1
%StringIteratorPrototype% 字符串迭代器对象的原型(22.1.5
%Symbol% Symbol Symbol 构造器20.4.1
%SyntaxError% SyntaxError SyntaxError 构造器20.5.5.4
%ThrowTypeError% 一个无条件抛出新的%TypeError%实例的函数对象
%TypedArray% 所有类型化数组构造器的超类(23.2.1
%TypeError% TypeError TypeError 构造器20.5.5.5
%Uint8Array% Uint8Array Uint8Array 构造器23.2
%Uint8ClampedArray% Uint8ClampedArray Uint8ClampedArray 构造器23.2
%Uint16Array% Uint16Array Uint16Array 构造器23.2
%Uint32Array% Uint32Array Uint32Array 构造器23.2
%URIError% URIError URIError 构造器20.5.5.6
%WeakMap% WeakMap WeakMap 构造器24.3.1
%WeakRef% WeakRef WeakRef 构造器26.1.1
%WeakSet% WeakSet WeakSet 构造器24.4.1
%WrapForValidIteratorPrototype% Iterator.from 返回的包装迭代器对象的原型(27.1.3.2.1.1
注意

表 102中的附加条目。

6.2 ECMAScript 规范类型

规范类型对应于在算法中用于描述 ECMAScript 语言构造和ECMAScript 语言类型语义的元值。规范类型包括引用记录列表完成记录属性描述符环境记录抽象闭包数据块。规范类型值是规范工件,不一定对应于 ECMAScript 实现中的任何特定实体。规范类型值可用于描述 ECMAScript 表达式求值的中间结果,但此类值不能存储为对象的属性或 ECMAScript 语言变量的值。

6.2.1 枚举规范类型

枚举是规范内部的值,不能从 ECMAScript 代码直接观察到。枚举使用无衬线字体表示。例如,完成记录[[Type]] 字段取值如 normalreturnthrow。枚举除了名称之外没有其他特征。枚举的名称除了将其与其他枚举区分开来之外没有其他目的,并且不暗示其在上下文中的用法或含义。

6.2.2 列表和记录规范类型

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

当算法遍历列表的元素而不指定顺序时,使用的顺序是列表中元素的顺序。

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

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

当应用于字符串列表时,短语"按字典序码元顺序排序"意味着按每个码元的数值排序,直到较短字符串的长度,如果所有都相等,则较短的字符串排在较长的字符串之前,如抽象操作IsLessThan中所述。

记录类型用于描述本规范算法中的数据聚合。记录类型值由一个或多个命名字段组成。每个字段的值是ECMAScript 语言值或规范值。字段名总是用双括号括起来,例如 [[Value]]

为了在本规范中方便表示,可以使用类似对象字面量的语法来表达记录值。例如,{ [[Field1]]: 42, [[Field2]]: false, [[Field3]]: empty } 定义了一个有三个字段的记录值,每个字段都初始化为特定值。字段名顺序不重要。任何未明确列出的字段都被认为是缺失的。

在规范文本和算法中,可以使用点记法来引用记录值的特定字段。例如,如果 R 是前一段中显示的记录,那么 R.[[Field2]] 是"R 中名为 [[Field2]] 的字段"的简写。

常用记录字段组合的模式可以被命名,该名称可以用作字面量记录值的前缀,以标识所描述的特定类型的聚合。例如:PropertyDescriptor { [[Value]]: 42, [[Writable]]: false, [[Configurable]]: true }。

6.2.3 集合和关系规范类型

集合类型用于解释在内存模型中使用的无序元素集合。它不同于同名的 ECMAScript 集合类型。为了消除歧义,ECMAScript 集合的实例在本规范中始终称为"Set 对象"。集合类型的值是元素的简单集合,其中没有元素出现超过一次。元素可以添加到集合中或从集合中移除。集合可以进行并集、交集或相减操作。

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

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

  • 对于 R 域中的所有 abc

    • a R a 不成立,并且
    • 如果 a R bb R c,那么 a R c
注意 1

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

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

  • 对于 R 域中的所有 abc

    • aba R bb R a,并且
    • a R a 不成立,并且
    • 如果 a R bb R c,那么 a R c
注意 2

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

6.2.4 完成记录规范类型

完成记录规范类型用于解释值和控制流的运行时传播,例如执行非本地控制转移的语句(breakcontinuereturnthrow)的行为。

完成记录具有表 7中定义的字段。

表 7:完成记录字段
字段名 含义
[[Type]] normalbreakcontinuereturnthrow 发生的完成类型。
[[Value]] 完成记录之外的任何值 产生的值。
[[Target]] 一个字符串或 empty 定向控制转移的目标标签。

以下简写术语有时用于指代完成记录。

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

本规范中定义的可调用对象只返回正常完成或 throw 完成。返回任何其他类型的完成记录被认为是编辑错误。

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

6.2.4.1 NormalCompletion ( value )

抽象操作 NormalCompletion 接受参数 value(除完成记录之外的任何值)并返回一个正常完成。它在被调用时执行以下步骤:

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

6.2.4.2 ThrowCompletion ( value )

抽象操作 ThrowCompletion 接受参数 value(一个ECMAScript 语言值)并返回一个throw 完成。它在被调用时执行以下步骤:

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

6.2.4.3 ReturnCompletion ( value )

抽象操作 ReturnCompletion 接受参数 value(一个ECMAScript 语言值)并返回一个return 完成。它在被调用时执行以下步骤:

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

6.2.4.4 UpdateEmpty ( completionRecord, value )

抽象操作 UpdateEmpty 接受参数 completionRecord(一个完成记录)和 value(除完成记录之外的任何值)并返回一个完成记录。它在被调用时执行以下步骤:

  1. 断言:如果 completionRecordreturn 完成throw 完成,那么 completionRecord.[[Value]] 不是 empty
  2. 如果 completionRecord.[[Value]] 不是 empty,返回 ? completionRecord
  3. 返回完成记录 { [[Type]]: completionRecord.[[Type]], [[Value]]: value, [[Target]]: completionRecord.[[Target]] }。

6.2.5 引用记录规范类型

引用记录类型用于解释诸如 deletetypeof、赋值运算符、super 关键字和其他语言特性的行为。例如,赋值的左操作数应该产生一个引用记录。

引用记录是一个已解析的名称或(可能尚未解析的)属性绑定;其字段由表 8定义。

表 8:引用记录字段
字段名 含义
[[Base]] 一个ECMAScript 语言值、一个环境记录unresolvable 持有绑定的值或环境记录[[Base]]unresolvable 表示绑定无法解析。
[[ReferencedName]] 一个ECMAScript 语言值或一个私有名称 绑定的名称。如果 [[Base]] 值是环境记录,则总是字符串。否则,在执行ToPropertyKey之前,可能是字符串或符号以外的ECMAScript 语言值
[[Strict]] 一个布尔值 如果引用记录起源于严格模式代码,则为 true,否则为 false
[[ThisValue]] 一个ECMAScript 语言值empty 如果不是 empty,则引用记录表示使用 super 关键字表达的属性绑定;它被称为超级引用记录,其 [[Base]] 值永远不会是环境记录。在这种情况下,[[ThisValue]] 字段保存创建引用记录时的 this 值。

本规范中使用以下抽象操作来操作引用记录:

6.2.5.1 IsPropertyReference ( V )

抽象操作 IsPropertyReference 接受参数 V(一个引用记录)并返回一个布尔值。它在被调用时执行以下步骤:

  1. 如果 V.[[Base]]unresolvable,返回 false
  2. 如果 V.[[Base]]环境记录,返回 false;否则返回 true

6.2.5.2 IsUnresolvableReference ( V )

抽象操作 IsUnresolvableReference 接受参数 V(一个引用记录)并返回一个布尔值。它在被调用时执行以下步骤:

  1. 如果 V.[[Base]]unresolvable,返回 true;否则返回 false

6.2.5.3 IsSuperReference ( V )

抽象操作 IsSuperReference 接受参数 V(一个引用记录)并返回一个布尔值。它在被调用时执行以下步骤:

  1. 如果 V.[[ThisValue]] 不是 empty,返回 true;否则返回 false

6.2.5.4 IsPrivateReference ( V )

抽象操作 IsPrivateReference 接受参数 V(一个引用记录)并返回一个布尔值。它在被调用时执行以下步骤:

  1. 如果 V.[[ReferencedName]]私有名称,返回 true;否则返回 false

6.2.5.5 GetValue ( V )

抽象操作 GetValue 接受参数 V(一个引用记录或一个ECMAScript 语言值)并返回一个包含ECMAScript 语言值正常完成或一个突然完成。它在被调用时执行以下步骤:

  1. 如果 V 不是引用记录,返回 V
  2. 如果IsUnresolvableReference(V) 是 true,抛出 ReferenceError 异常。
  3. 如果IsPropertyReference(V) 是 true,那么
    1. baseObj 为 ? ToObject(V.[[Base]])。
    2. 如果IsPrivateReference(V) 是 true,那么
      1. 返回 ? PrivateGet(baseObj, V.[[ReferencedName]])。
    3. 如果 V.[[ReferencedName]] 不是属性键,那么
      1. V.[[ReferencedName]] 为 ? ToPropertyKey(V.[[ReferencedName]])。
    4. 返回 ? baseObj.[[Get]](V.[[ReferencedName]], GetThisValue(V))。
  4. 否则,
    1. baseV.[[Base]]
    2. 断言base环境记录
    3. 返回 ? base.GetBindingValue(V.[[ReferencedName]], V.[[Strict]])(参见9.1)。
注意

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

6.2.5.6 PutValue ( V, W )

抽象操作 PutValue 接受参数 V(一个引用记录或一个ECMAScript 语言值)和 W(一个ECMAScript 语言值)并返回一个包含 unused正常完成或一个突然完成。它在被调用时执行以下步骤:

  1. 如果 V 不是引用记录,抛出 ReferenceError 异常。
  2. 如果IsUnresolvableReference(V) 是 true,那么
    1. 如果 V.[[Strict]]true,抛出 ReferenceError 异常。
    2. globalObjGetGlobalObject()。
    3. 执行 ? Set(globalObj, V.[[ReferencedName]], W, false)。
    4. 返回 unused
  3. 如果IsPropertyReference(V) 是 true,那么
    1. baseObj 为 ? ToObject(V.[[Base]])。
    2. 如果IsPrivateReference(V) 是 true,那么
      1. 返回 ? PrivateSet(baseObj, V.[[ReferencedName]], W)。
    3. 如果 V.[[ReferencedName]] 不是属性键,那么
      1. V.[[ReferencedName]] 为 ? ToPropertyKey(V.[[ReferencedName]])。
    4. succeeded 为 ? baseObj.[[Set]](V.[[ReferencedName]], W, GetThisValue(V))。
    5. 如果 succeededfalseV.[[Strict]]true,抛出 TypeError 异常。
    6. 返回 unused
  4. 否则,
    1. baseV.[[Base]]
    2. 断言base环境记录
    3. 返回 ? base.SetMutableBinding(V.[[ReferencedName]], W, V.[[Strict]])(参见9.1)。
注意

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

6.2.5.7 GetThisValue ( V )

抽象操作 GetThisValue 接受参数 V(一个引用记录)并返回一个ECMAScript 语言值。它在被调用时执行以下步骤:

  1. 断言IsPropertyReference(V) 是 true
  2. 如果IsSuperReference(V) 是 true,返回 V.[[ThisValue]];否则返回 V.[[Base]]

6.2.5.8 InitializeReferencedBinding ( V, W )

抽象操作 InitializeReferencedBinding 接受参数 V(一个引用记录)和 W(一个ECMAScript 语言值)并返回一个包含 unused正常完成或一个突然完成。它在被调用时执行以下步骤:

  1. 断言IsUnresolvableReference(V) 是 false
  2. baseV.[[Base]]
  3. 断言base环境记录
  4. 返回 ? base.InitializeBinding(V.[[ReferencedName]], W)。

6.2.5.9 MakePrivateReference ( baseValue, privateIdentifier )

抽象操作 MakePrivateReference 接受参数 baseValue(一个ECMAScript 语言值)和 privateIdentifier(一个字符串)并返回一个引用记录。它在被调用时执行以下步骤:

  1. privateEnv运行执行上下文的 PrivateEnvironment。
  2. 断言privateEnv 不是 null
  3. privateNameResolvePrivateIdentifier(privateEnv, privateIdentifier)。
  4. 返回引用记录 { [[Base]]: baseValue, [[ReferencedName]]: privateName, [[Strict]]: true, [[ThisValue]]: empty }。

6.2.6 属性描述符规范类型

属性描述符类型用于解释对象属性特性的操作和具体化。属性描述符是一个具有零个或多个字段的记录,其中每个字段的名称是一个特性名称,其值是6.1.7.1中指定的相应特性值。本规范中用于标记属性描述符记录字面量描述的模式名称是"PropertyDescriptor"。

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

本规范中使用以下抽象操作来操作属性描述符值:

6.2.6.1 IsAccessorDescriptor ( Desc )

抽象操作 IsAccessorDescriptor 接受参数 Desc(一个属性描述符)并返回一个布尔值。它在被调用时执行以下步骤:

  1. 如果 Desc[[Get]] 字段,返回 true
  2. 如果 Desc[[Set]] 字段,返回 true
  3. 返回 false

6.2.6.2 IsDataDescriptor ( Desc )

抽象操作 IsDataDescriptor 接受参数 Desc(一个属性描述符)并返回一个布尔值。它在被调用时执行以下步骤:

  1. 如果 Desc[[Value]] 字段,返回 true
  2. 如果 Desc[[Writable]] 字段,返回 true
  3. 返回 false

6.2.6.3 IsGenericDescriptor ( Desc )

抽象操作 IsGenericDescriptor 接受参数 Desc(一个属性描述符)并返回一个布尔值。它在被调用时执行以下步骤:

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

6.2.6.4 FromPropertyDescriptor ( Desc )

抽象操作 FromPropertyDescriptor 接受参数 Desc(一个属性描述符undefined)并返回一个对象或 undefined。它在被调用时执行以下步骤:

  1. 如果 Descundefined,返回 undefined
  2. objOrdinaryObjectCreate(%Object.prototype%)。
  3. 断言obj 是一个可扩展的普通对象,没有自有属性。
  4. 如果 Desc[[Value]] 字段,那么
    1. 执行 ! CreateDataPropertyOrThrow(obj, "value", Desc.[[Value]])。
  5. 如果 Desc[[Writable]] 字段,那么
    1. 执行 ! CreateDataPropertyOrThrow(obj, "writable", Desc.[[Writable]])。
  6. 如果 Desc[[Get]] 字段,那么
    1. 执行 ! CreateDataPropertyOrThrow(obj, "get", Desc.[[Get]])。
  7. 如果 Desc[[Set]] 字段,那么
    1. 执行 ! CreateDataPropertyOrThrow(obj, "set", Desc.[[Set]])。
  8. 如果 Desc[[Enumerable]] 字段,那么
    1. 执行 ! CreateDataPropertyOrThrow(obj, "enumerable", Desc.[[Enumerable]])。
  9. 如果 Desc[[Configurable]] 字段,那么
    1. 执行 ! CreateDataPropertyOrThrow(obj, "configurable", Desc.[[Configurable]])。
  10. 返回 obj

6.2.6.5 ToPropertyDescriptor ( Obj )

抽象操作 ToPropertyDescriptor 接受参数 Obj(一个ECMAScript 语言值)并返回一个包含属性描述符正常完成或一个throw 完成。它在被调用时执行以下步骤:

  1. 如果 Obj 不是对象,抛出 TypeError 异常。
  2. desc 为一个新的属性描述符,初始时没有字段。
  3. hasEnumerable 为 ? HasProperty(Obj, "enumerable")。
  4. 如果 hasEnumerabletrue,那么
    1. enumerableToBoolean(? Get(Obj, "enumerable"))。
    2. desc.[[Enumerable]]enumerable
  5. hasConfigurable 为 ? HasProperty(Obj, "configurable")。
  6. 如果 hasConfigurabletrue,那么
    1. configurableToBoolean(? Get(Obj, "configurable"))。
    2. desc.[[Configurable]]configurable
  7. hasValue 为 ? HasProperty(Obj, "value")。
  8. 如果 hasValuetrue,那么
    1. value 为 ? Get(Obj, "value")。
    2. desc.[[Value]]value
  9. hasWritable 为 ? HasProperty(Obj, "writable")。
  10. 如果 hasWritabletrue,那么
    1. writableToBoolean(? Get(Obj, "writable"))。
    2. desc.[[Writable]]writable
  11. hasGet 为 ? HasProperty(Obj, "get")。
  12. 如果 hasGettrue,那么
    1. getter 为 ? Get(Obj, "get")。
    2. 如果IsCallable(getter) 是 falsegetter 不是 undefined,抛出 TypeError 异常。
    3. desc.[[Get]]getter
  13. hasSet 为 ? HasProperty(Obj, "set")。
  14. 如果 hasSettrue,那么
    1. setter 为 ? Get(Obj, "set")。
    2. 如果IsCallable(setter) 是 falsesetter 不是 undefined,抛出 TypeError 异常。
    3. desc.[[Set]]setter
  15. 如果 desc[[Get]] 字段或 desc[[Set]] 字段,那么
    1. 如果 desc[[Value]] 字段或 desc[[Writable]] 字段,抛出 TypeError 异常。
  16. 返回 desc

6.2.6.6 CompletePropertyDescriptor ( Desc )

抽象操作 CompletePropertyDescriptor 接受参数 Desc(一个属性描述符)并返回 unused。它在被调用时执行以下步骤:

  1. like记录 { [[Value]]: undefined, [[Writable]]: false, [[Get]]: undefined, [[Set]]: undefined, [[Enumerable]]: false, [[Configurable]]: false }。
  2. 如果IsGenericDescriptor(Desc) 是 trueIsDataDescriptor(Desc) 是 true,那么
    1. 如果 Desc 没有 [[Value]] 字段,设 Desc.[[Value]]like.[[Value]]
    2. 如果 Desc 没有 [[Writable]] 字段,设 Desc.[[Writable]]like.[[Writable]]
  3. 否则,
    1. 如果 Desc 没有 [[Get]] 字段,设 Desc.[[Get]]like.[[Get]]
    2. 如果 Desc 没有 [[Set]] 字段,设 Desc.[[Set]]like.[[Set]]
  4. 如果 Desc 没有 [[Enumerable]] 字段,设 Desc.[[Enumerable]]like.[[Enumerable]]
  5. 如果 Desc 没有 [[Configurable]] 字段,设 Desc.[[Configurable]]like.[[Configurable]]
  6. 返回 unused

6.2.7 环境记录规范类型

环境记录类型用于解释嵌套函数和块中名称解析的行为。此类型及其操作在9.1中定义。

6.2.8 抽象闭包规范类型

抽象闭包规范类型用于引用算法步骤以及一系列值。抽象闭包是元值,使用函数调用样式调用,例如 closure(arg1, arg2)。与抽象操作类似,调用执行抽象闭包描述的算法步骤。

在创建抽象闭包的算法步骤中,值使用动词"capture"后跟别名列表来捕获。当创建抽象闭包时,它捕获当时与每个别名关联的值。在指定调用抽象闭包时要执行的算法的步骤中,每个捕获的值都通过用于捕获该值的别名来引用。

如果抽象闭包返回完成记录,该完成记录必须是正常完成throw 完成

抽象闭包作为其他算法的一部分内联创建,如以下示例所示。

  1. addend 为 41。
  2. closure 为一个新的抽象闭包,参数为 (x),捕获 addend 并在调用时执行以下步骤:
    1. 返回 x + addend
  3. valclosure(1)。
  4. 断言val 是 42。

6.2.9 数据块

数据块规范类型用于描述一个不同且可变的字节大小(8位)数值序列。字节值闭区间从 0 到 255 的整数。数据块值使用固定数量的字节创建,每个字节的初始值为 0。

为了在本规范中表示方便,可以使用类似数组的语法来访问数据块值的各个字节。此表示法将数据块值表示为基于 0 的整数索引字节序列。例如,如果 db 是一个 5 字节的数据块值,则可以使用 db[2] 来访问其第 3 个字节。

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

共享数据块的语义通过内存模型使用共享数据块事件定义。下面的抽象操作引入共享数据块事件,并作为评估语义和内存模型事件语义之间的接口。这些事件形成一个候选执行内存模型对其起过滤器作用。请参考内存模型以获取完整语义。

共享数据块事件内存模型中定义的记录建模。

本规范中使用以下抽象操作来操作数据块值:

6.2.9.1 CreateByteDataBlock ( size )

抽象操作 CreateByteDataBlock 接受参数 size(一个非负整数)并返回一个包含数据块正常完成或一个throw 完成。它在被调用时执行以下步骤:

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

6.2.9.2 CreateSharedByteDataBlock ( size )

抽象操作 CreateSharedByteDataBlock 接受参数 size(一个非负整数)并返回一个包含共享数据块正常完成或一个throw 完成。它在被调用时执行以下步骤:

  1. db 为一个新的共享数据块值,由 size 个字节组成。如果无法创建这样的共享数据块,抛出 RangeError 异常。
  2. execution周围代理代理记录[[CandidateExecution]] 字段。
  3. eventsRecordexecution.[[EventsRecords]][[AgentSignifier]]AgentSignifier() 的代理事件记录
  4. zero 为 « 0 »。
  5. 对于 db 的每个索引 i,执行
    1. WriteSharedMemory { [[Order]]: init, [[NoTear]]: true, [[Block]]: db, [[ByteIndex]]: i, [[ElementSize]]: 1, [[Payload]]: zero } 追加到 eventsRecord.[[EventList]]
  6. 返回 db

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

抽象操作 CopyDataBlockBytes 接受参数 toBlock(一个数据块或一个共享数据块)、toIndex(一个非负整数)、fromBlock(一个数据块或一个共享数据块)、fromIndex(一个非负整数)和 count(一个非负整数)并返回 unused。它在被调用时执行以下步骤:

  1. 断言fromBlocktoBlock 是不同的值。
  2. fromSizefromBlock 中的字节数。
  3. 断言fromIndex + countfromSize
  4. toSizetoBlock 中的字节数。
  5. 断言toIndex + counttoSize
  6. 重复,当 count > 0 时,
    1. 如果 fromBlock共享数据块,那么
      1. execution周围代理代理记录[[CandidateExecution]] 字段。
      2. eventsRecordexecution.[[EventsRecords]][[AgentSignifier]]AgentSignifier() 的代理事件记录
      3. bytes 为一个列表,其唯一元素是一个非确定性选择的字节值
      4. 注意:在实现中,bytes 是底层硬件上非原子读取指令的结果。非确定性是内存模型对描述弱一致性硬件可观察行为的语义规定。
      5. readEventReadSharedMemory { [[Order]]: unordered, [[NoTear]]: true, [[Block]]: fromBlock, [[ByteIndex]]: fromIndex, [[ElementSize]]: 1 }。
      6. readEvent 追加到 eventsRecord.[[EventList]]
      7. 选择值记录 { [[Event]]: readEvent, [[ChosenValue]]: bytes } 追加到 execution.[[ChosenValues]]
      8. 如果 toBlock共享数据块,那么
        1. WriteSharedMemory { [[Order]]: unordered, [[NoTear]]: true, [[Block]]: toBlock, [[ByteIndex]]: toIndex, [[ElementSize]]: 1, [[Payload]]: bytes } 追加到 eventsRecord.[[EventList]]
      9. 否则,
        1. toBlock[toIndex] 为 bytes[0]。
    2. 否则,
      1. 断言toBlock 不是共享数据块
      2. toBlock[toIndex] 为 fromBlock[fromIndex]。
    3. toIndextoIndex + 1。
    4. fromIndexfromIndex + 1。
    5. countcount - 1。
  7. 返回 unused

6.2.10 PrivateElement 规范类型

PrivateElement 类型是一个记录,用于私有类字段、方法和访问器的规范。虽然属性描述符不用于私有元素,但私有字段的行为类似于不可配置、不可枚举、可写的数据属性,私有方法的行为类似于不可配置、不可枚举、不可写的数据属性,私有访问器的行为类似于不可配置、不可枚举的访问器属性

PrivateElement 类型的值是记录值,其字段由表 9定义。这些值被称为PrivateElement

表 9:PrivateElement 字段
字段名 出现该字段的 [[Kind]] 字段值 含义
[[Key]] 全部 一个私有名称 字段、方法或访问器的名称。
[[Kind]] 全部 fieldmethodaccessor 元素的类型。
[[Value]] fieldmethod 一个ECMAScript 语言值 字段的值。
[[Get]] accessor 一个函数对象undefined 私有访问器的 getter。
[[Set]] accessor 一个函数对象undefined 私有访问器的 setter。

6.2.11 ClassFieldDefinition 记录规范类型

ClassFieldDefinition 类型是一个记录,用于类字段的规范。

ClassFieldDefinition 类型的值是记录值,其字段由表 10定义。这些值被称为ClassFieldDefinition 记录

表 10:ClassFieldDefinition 记录字段
字段名 含义
[[Name]] 一个私有名称、字符串或符号 字段的名称。
[[Initializer]] 一个 ECMAScript 函数对象empty 字段的初始化器(如果有)。

6.2.12 私有名称

私有名称规范类型用于描述一个全局唯一值(即使与其他私有名称在其他方面无法区分,该值也与任何其他私有名称不同),它表示私有类元素(字段、方法或访问器)的键。每个私有名称都有一个关联的不可变 [[Description]],它是一个字符串值。私有名称可以通过PrivateFieldAddPrivateMethodOrAccessorAdd安装在任何 ECMAScript 对象上,然后使用PrivateGetPrivateSet进行读取或写入。

6.2.13 ClassStaticBlockDefinition 记录规范类型

ClassStaticBlockDefinition 记录是一个记录值,用于封装类静态初始化块的可执行代码。

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

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

7 抽象操作

这些操作不是 ECMAScript 语言的一部分;定义它们仅是为了帮助说明 ECMAScript 语言的语义。其他更专门的抽象操作在本规范中都有定义。

7.1 类型转换

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

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

7.1.1 ToPrimitive ( input [ , preferredType ] )

抽象操作 ToPrimitive 接受参数 input(一个ECMAScript 语言值)和可选参数 preferredTypestringnumber)并返回一个包含ECMAScript 语言值正常完成或一个throw 完成。它将其 input 参数转换为非对象类型。如果对象能够转换为多个原始类型,它可以使用可选提示 preferredType 来偏向该类型。它在被调用时执行以下步骤:

  1. 如果 input 是对象,那么
    1. exoticToPrim 为 ? GetMethod(input, %Symbol.toPrimitive%)。
    2. 如果 exoticToPrim 不是 undefined,那么
      1. 如果 preferredType 不存在,那么
        1. hint"default"
      2. 否则如果 preferredTypestring,那么
        1. hint"string"
      3. 否则,
        1. 断言preferredTypenumber
        2. hint"number"
      4. result 为 ? Call(exoticToPrim, input, « hint »)。
      5. 如果 result 不是对象,返回 result
      6. 抛出 TypeError 异常。
    3. 如果 preferredType 不存在,设 preferredTypenumber
    4. 返回 ? OrdinaryToPrimitive(input, preferredType)。
  2. 返回 input
注意

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

7.1.1.1 OrdinaryToPrimitive ( O, hint )

抽象操作 OrdinaryToPrimitive 接受参数 O(一个对象)和 hintstringnumber)并返回一个包含ECMAScript 语言值正常完成或一个throw 完成。它在被调用时执行以下步骤:

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

7.1.2 ToBoolean ( argument )

抽象操作 ToBoolean 接受参数 argument(一个ECMAScript 语言值)并返回一个布尔值。它将 argument 转换为布尔类型的值。它在被调用时执行以下步骤:

  1. 如果 argument 是布尔值,返回 argument
  2. 如果 argumentundefinednull+0𝔽-0𝔽NaN0 或空字符串之一,返回 false
  3. 注意:此步骤在章节 B.3.6.1 中被替换。
  4. 返回 true

7.1.3 ToNumeric ( value )

抽象操作 ToNumeric 接受参数 value(一个ECMAScript 语言值)并返回一个包含数字或 BigInt 的正常完成,或一个throw 完成。它返回转换为数字或 BigInt 的 value。它在被调用时执行以下步骤:

  1. primValue 为 ? ToPrimitive(value, number)。
  2. 如果 primValue 是 BigInt,返回 primValue
  3. 返回 ? ToNumber(primValue)。

7.1.4 ToNumber ( argument )

抽象操作 ToNumber 接受参数 argument(一个ECMAScript 语言值)并返回一个包含数字的正常完成或一个throw 完成。它将 argument 转换为数字类型的值。它在被调用时执行以下步骤:

  1. 如果 argument 是数字,返回 argument
  2. 如果 argument 是符号或 BigInt,抛出 TypeError 异常。
  3. 如果 argumentundefined,返回 NaN
  4. 如果 argumentnullfalse,返回 +0𝔽
  5. 如果 argumenttrue,返回 1𝔽
  6. 如果 argument 是字符串,返回 StringToNumber(argument)。
  7. 断言argument 是对象
  8. primValue 为 ? ToPrimitive(argument, number)。
  9. 断言primValue 不是对象
  10. 返回 ? ToNumber(primValue)。

7.1.4.1 ToNumber 应用于字符串类型

抽象操作 StringToNumber 指定如何使用以下语法将字符串值转换为数字值。

语法

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

注意

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

7.1.4.1.1 StringToNumber ( str )

抽象操作 StringToNumber 接受参数 str(一个字符串)并返回一个数字。它在被调用时执行以下步骤:

  1. literalParseText(str, StringNumericLiteral)。
  2. 如果 literal 是错误的列表,返回 NaN
  3. 返回 literalStringNumericValue

7.1.4.1.2 运行时语义:StringNumericValue

语法导向操作 StringNumericValue 不接受参数并返回一个数字。

注意

StringNumericLiteral 到数字值的转换总体上类似于确定 NumericLiteralNumericValue(参见 12.9.3),但一些细节不同。

它在以下产生式上分段定义:

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

7.1.4.1.3 RoundMVResult ( n )

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

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

7.1.5 ToIntegerOrInfinity ( argument )

抽象操作 ToIntegerOrInfinity 接受参数 argument(一个ECMAScript 语言值)并返回一个包含整数、+∞ 或 -∞ 的正常完成或一个throw 完成。它将 argument 转换为表示其数字值的整数(小数部分被截断),或者当该数字值是无限时转换为 +∞ 或 -∞。它在被调用时执行以下步骤:

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

7.1.6 ToInt32 ( argument )

抽象操作 ToInt32 接受参数 argument(一个ECMAScript 语言值)并返回一个包含整数数字正常完成或一个throw 完成。它将 argument 转换为从 𝔽(-231) 到 𝔽(231 - 1) 的闭区间内的 232整数数字值之一。它在被调用时执行以下步骤:

  1. number 为 ? ToNumber(argument)。
  2. 如果 number 不是有限的number+0𝔽-0𝔽,返回 +0𝔽
  3. inttruncate((number))。
  4. int32bitint modulo 232
  5. 如果 int32bit ≥ 231,返回 𝔽(int32bit - 232);否则返回 𝔽(int32bit)。
注意

根据 ToInt32 的上述定义:

  • ToInt32 抽象操作是幂等的:如果应用于它产生的结果,第二次应用不会改变该值。
  • 对于所有值 x,ToInt32(ToUint32(x)) 与 ToInt32(x) 是相同的值。(为了保持这个后续属性,+∞𝔽-∞𝔽 被映射为 +0𝔽。)
  • ToInt32 将 -0𝔽 映射为 +0𝔽

7.1.7 ToUint32 ( argument )

抽象操作 ToUint32 接受参数 argument(一个ECMAScript 语言值)并返回一个包含整数数字正常完成或一个throw 完成。它将 argument 转换为从 +0𝔽𝔽(232 - 1) 的闭区间内的 232整数数字值之一。它在被调用时执行以下步骤:

  1. number 为 ? ToNumber(argument)。
  2. 如果 number 不是有限的number+0𝔽-0𝔽,返回 +0𝔽
  3. inttruncate((number))。
  4. int32bitint modulo 232
  5. 返回 𝔽(int32bit)。
注意

根据 ToUint32 的上述定义:

  • 步骤 5 是 ToUint32 和 ToInt32 之间的唯一区别。
  • ToUint32 抽象操作是幂等的:如果应用于它产生的结果,第二次应用不会改变该值。
  • 对于所有值 x,ToUint32(ToInt32(x)) 与 ToUint32(x) 是相同的值。(为了保持这个后续属性,+∞𝔽-∞𝔽 被映射为 +0𝔽。)
  • ToUint32 将 -0𝔽 映射为 +0𝔽

7.1.8 ToInt16 ( argument )

抽象操作 ToInt16 接受参数 argument(一个ECMAScript 语言值)并返回一个包含整数数字正常完成或一个throw 完成。它将 argument 转换为从 𝔽(-215) 到 𝔽(215 - 1) 的闭区间内的 216整数数字值之一。它在被调用时执行以下步骤:

  1. number 为 ? ToNumber(argument)。
  2. 如果 number 不是有限的number+0𝔽-0𝔽,返回 +0𝔽
  3. inttruncate((number))。
  4. int16bitint modulo 216
  5. 如果 int16bit ≥ 215,返回 𝔽(int16bit - 216);否则返回 𝔽(int16bit)。

7.1.9 ToUint16 ( argument )

抽象操作 ToUint16 接受参数 argument(一个ECMAScript 语言值)并返回一个包含整数数字正常完成或一个throw 完成。它将 argument 转换为从 +0𝔽𝔽(216 - 1) 的闭区间内的 216整数数字值之一。它在被调用时执行以下步骤:

  1. number 为 ? ToNumber(argument)。
  2. 如果 number 不是有限的number+0𝔽-0𝔽,返回 +0𝔽
  3. inttruncate((number))。
  4. int16bitint modulo 216
  5. 返回 𝔽(int16bit)。
注意

根据 ToUint16 的上述定义:

  • 在步骤 4 中将 232 替换为 216ToUint32 和 ToUint16 之间的唯一区别。
  • ToUint16 将 -0𝔽 映射为 +0𝔽

7.1.10 ToInt8 ( argument )

抽象操作 ToInt8 接受参数 argument(一个ECMAScript 语言值)并返回一个包含整数数字正常完成或一个throw 完成。它将 argument 转换为从 -128𝔽127𝔽闭区间内的 28整数数字值之一。它在被调用时执行以下步骤:

  1. number 为 ? ToNumber(argument)。
  2. 如果 number 不是有限的number+0𝔽-0𝔽,返回 +0𝔽
  3. inttruncate((number))。
  4. int8bitint modulo 28
  5. 如果 int8bit ≥ 27,返回 𝔽(int8bit - 28);否则返回 𝔽(int8bit)。

7.1.11 ToUint8 ( argument )

抽象操作 ToUint8 接受参数 argument(一个ECMAScript 语言值)并返回一个包含整数数字正常完成或一个throw 完成。它将 argument 转换为从 +0𝔽255𝔽闭区间内的 28整数数字值之一。它在被调用时执行以下步骤:

  1. number 为 ? ToNumber(argument)。
  2. 如果 number 不是有限的number+0𝔽-0𝔽,返回 +0𝔽
  3. inttruncate((number))。
  4. int8bitint modulo 28
  5. 返回 𝔽(int8bit)。

7.1.12 ToUint8Clamp ( argument )

抽象操作 ToUint8Clamp 接受参数 argument(一个ECMAScript 语言值)并返回一个包含整数数字正常完成或一个throw 完成。它将 argument 限制并舍入为从 +0𝔽255𝔽闭区间内的 28整数数字值之一。它在被调用时执行以下步骤:

  1. number 为 ? ToNumber(argument)。
  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)。否则,返回 𝔽(f + 1)。
注意

与大多数其他 ECMAScript 整数转换操作不同,ToUint8Clamp 舍入而不是截断非整数值。它还使用"舍入到最近偶数"的平分策略,这与 Math.round 的"舍入到更大值"平分策略不同。

7.1.13 ToBigInt ( argument )

抽象操作 ToBigInt 接受参数 argument(一个ECMAScript 语言值)并返回一个包含 BigInt 的正常完成或一个throw 完成。它将 argument 转换为 BigInt 值,或者如果需要从数字进行隐式转换则抛出异常。它在被调用时执行以下步骤:

  1. prim 为 ? ToPrimitive(argument, number)。
  2. 返回 prim表 12 中对应的值。
表 12:BigInt 转换
参数类型 结果
Undefined 抛出 TypeError 异常。
Null 抛出 TypeError 异常。
Boolean 如果 primtrue 返回 1n,如果 primfalse 返回 0n
BigInt 返回 prim
Number 抛出 TypeError 异常。
String
  1. nStringToBigInt(prim)。
  2. 如果 nundefined,抛出 SyntaxError 异常。
  3. 返回 n
Symbol 抛出 TypeError 异常。

7.1.14 StringToBigInt ( str )

抽象操作 StringToBigInt 接受参数 str(一个字符串)并返回一个 BigInt 或 undefined。它在被调用时执行以下步骤:

  1. literalParseText(str, StringIntegerLiteral)。
  2. 如果 literal 是错误的列表,返回 undefined
  3. mvliteral 的 MV。
  4. 断言mv 是一个整数
  5. 返回 (mv)。

7.1.14.1 StringIntegerLiteral 语法

StringToBigInt 使用以下语法。

语法

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

7.1.14.2 运行时语义:MV

7.1.15 ToBigInt64 ( argument )

抽象操作 ToBigInt64 接受参数 argument(一个ECMAScript 语言值)并返回一个包含 BigInt 的正常完成或一个throw 完成。它将 argument 转换为从 (-263) 到 (263 - 1) 的闭区间内的 264 个 BigInt 值之一。它在被调用时执行以下步骤:

  1. n 为 ? ToBigInt(argument)。
  2. int64bit(n) modulo 264
  3. 如果 int64bit ≥ 263,返回 (int64bit - 264);否则返回 (int64bit)。

7.1.16 ToBigUint64 ( argument )

抽象操作 ToBigUint64 接受参数 argument(一个ECMAScript 语言值)并返回一个包含 BigInt 的正常完成或一个throw 完成。它将 argument 转换为从 0(264 - 1) 的闭区间内的 264 个 BigInt 值之一。它在被调用时执行以下步骤:

  1. n 为 ? ToBigInt(argument)。
  2. int64bit(n) modulo 264
  3. 返回 (int64bit)。

7.1.17 ToString ( argument )

抽象操作 ToString 接受参数 argument(一个ECMAScript 语言值)并返回一个包含字符串的正常完成或一个throw 完成。它将 argument 转换为字符串类型的值。它在被调用时执行以下步骤:

  1. 如果 argument 是字符串,返回 argument
  2. 如果 argument 是符号,抛出 TypeError 异常。
  3. 如果 argumentundefined,返回 "undefined"
  4. 如果 argumentnull,返回 "null"
  5. 如果 argumenttrue,返回 "true"
  6. 如果 argumentfalse,返回 "false"
  7. 如果 argument 是数字,返回 Number::toString(argument, 10)。
  8. 如果 argument 是 BigInt,返回 BigInt::toString(argument, 10)。
  9. 断言argument 是对象
  10. primValue 为 ? ToPrimitive(argument, string)。
  11. 断言primValue 不是对象
  12. 返回 ? ToString(primValue)。

7.1.18 ToObject ( argument )

抽象操作 ToObject 接受参数 argument(一个ECMAScript 语言值)并返回一个包含对象的正常完成或一个throw 完成。它根据表 13argument 转换为对象类型的值:

表 13:ToObject 转换
参数类型 结果
Undefined 抛出 TypeError 异常。
Null 抛出 TypeError 异常。
Boolean 返回一个新的布尔对象,其 [[BooleanData]] 内部槽设置为 argument。有关布尔对象的描述,请参见 20.3
Number 返回一个新的数字对象,其 [[NumberData]] 内部槽设置为 argument。有关数字对象的描述,请参见 21.1
String 返回一个新的字符串对象,其 [[StringData]] 内部槽设置为 argument。有关字符串对象的描述,请参见 22.1
Symbol 返回一个新的符号对象,其 [[SymbolData]] 内部槽设置为 argument。有关符号对象的描述,请参见 20.4
BigInt 返回一个新的 BigInt 对象,其 [[BigIntData]] 内部槽设置为 argument。有关 BigInt 对象的描述,请参见 21.2
Object 返回 argument

7.1.19 ToPropertyKey ( argument )

抽象操作 ToPropertyKey 接受参数 argument(一个ECMAScript 语言值)并返回一个包含属性键正常完成或一个throw 完成。它将 argument 转换为可用作属性键的值。它在被调用时执行以下步骤:

  1. key 为 ? ToPrimitive(argument, string)。
  2. 如果 key 是符号,那么
    1. 返回 key
  3. 返回 ! ToString(key)。

7.1.20 ToLength ( argument )

抽象操作 ToLength 接受参数 argument(一个ECMAScript 语言值)并返回一个包含非负整数数字正常完成或一个throw 完成。它将 argument 限制并截断为适合用作类数组对象长度的非负整数数字。它在被调用时执行以下步骤:

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

7.1.21 CanonicalNumericIndexString ( argument )

抽象操作 CanonicalNumericIndexString 接受参数 argument(一个字符串)并返回一个数字或 undefined。如果 argument"-0" 或完全匹配某个数字值 nToString(n),它返回相应的数字值。否则,它返回 undefined。它在被调用时执行以下步骤:

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

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

7.1.22 ToIndex ( value )

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

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

7.2 测试和比较操作

7.2.1 RequireObjectCoercible ( argument )

抽象操作 RequireObjectCoercible 接受参数 argument(一个ECMAScript 语言值)并返回一个包含ECMAScript 语言值正常完成或一个throw 完成。如果 argument 是不能使用 ToObject 转换为对象的值,它抛出错误。它由表 14 定义:

表 14:RequireObjectCoercible 结果
参数类型 结果
Undefined 抛出 TypeError 异常。
Null 抛出 TypeError 异常。
Boolean 返回 argument
Number 返回 argument
String 返回 argument
Symbol 返回 argument
BigInt 返回 argument
Object 返回 argument

7.2.2 IsArray ( argument )

抽象操作 IsArray 接受参数 argument(一个ECMAScript 语言值)并返回一个包含布尔值的正常完成或一个throw 完成。它在被调用时执行以下步骤:

  1. 如果 argument 不是对象,返回 false
  2. 如果 argument数组异质对象,返回 true
  3. 如果 argument代理异质对象,那么
    1. 执行 ? ValidateNonRevokedProxy(argument)。
    2. proxyTargetargument.[[ProxyTarget]]
    3. 返回 ? IsArray(proxyTarget)。
  4. 返回 false

7.2.3 IsCallable ( argument )

抽象操作 IsCallable 接受参数 argument(一个ECMAScript 语言值)并返回一个布尔值。它确定 argument 是否是具有 [[Call]] 内部方法的可调用函数。它在被调用时执行以下步骤:

  1. 如果 argument 不是对象,返回 false
  2. 如果 argument[[Call]] 内部方法,返回 true
  3. 返回 false

7.2.4 IsConstructor ( argument )

抽象操作 IsConstructor 接受参数 argument(一个ECMAScript 语言值)并返回一个布尔值。它确定 argument 是否是具有 [[Construct]] 内部方法的函数对象。它在被调用时执行以下步骤:

  1. 如果 argument 不是对象,返回 false
  2. 如果 argument[[Construct]] 内部方法,返回 true
  3. 返回 false

7.2.5 IsExtensible ( O )

抽象操作 IsExtensible 接受参数 O(一个对象)并返回一个包含布尔值的正常完成或一个throw 完成。它用于确定是否可以向 O 添加其他属性。它在被调用时执行以下步骤:

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

7.2.6 IsRegExp ( argument )

抽象操作 IsRegExp 接受参数 argument(一个ECMAScript 语言值)并返回一个包含布尔值的正常完成或一个throw 完成。它在被调用时执行以下步骤:

  1. 如果 argument 不是对象,返回 false
  2. matcher 为 ? Get(argument, %Symbol.match%)。
  3. 如果 matcher 不是 undefined,返回 ToBoolean(matcher)。
  4. 如果 argument[[RegExpMatcher]] 内部槽,返回 true
  5. 返回 false

7.2.7 静态语义:IsStringWellFormedUnicode ( string )

抽象操作 IsStringWellFormedUnicode 接受参数 string(一个字符串)并返回一个布尔值。它将 string 解释为 UTF-16 编码代码点的序列,如6.1.4 中所述,并确定它是否是一个格式正确的 UTF-16 序列。它在被调用时执行以下步骤:

  1. lenstring 的长度。
  2. k 为 0。
  3. 重复,当 k < len 时,
    1. cpCodePointAt(string, k)。
    2. 如果 cp.[[IsUnpairedSurrogate]]true,返回 false
    3. kk + cp.[[CodeUnitCount]]
  4. 返回 true

7.2.8 SameType ( x, y )

抽象操作 SameType 接受参数 x(一个ECMAScript 语言值)和 y(一个ECMAScript 语言值)并返回一个布尔值。它确定两个参数是否为相同类型。它在被调用时执行以下步骤:

  1. 如果 xundefinedyundefined,返回 true
  2. 如果 xnullynull,返回 true
  3. 如果 x 是布尔值y 是布尔值,返回 true
  4. 如果 x 是数字y 是数字,返回 true
  5. 如果 x 是 BigInty 是 BigInt,返回 true
  6. 如果 x 是符号y 是符号,返回 true
  7. 如果 x 是字符串y 是字符串,返回 true
  8. 如果 x 是对象y 是对象,返回 true
  9. 返回 false

7.2.9 SameValue ( x, y )

抽象操作 SameValue 接受参数 x(一个ECMAScript 语言值)和 y(一个ECMAScript 语言值)并返回一个布尔值。它确定两个参数是否为相同值。它在被调用时执行以下步骤:

  1. 如果 SameType(x, y) 是 false,返回 false
  2. 如果 x 是数字,那么
    1. 返回 Number::sameValue(x, y)。
  3. 返回 SameValueNonNumber(x, y)。
注意

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

7.2.10 SameValueZero ( x, y )

抽象操作 SameValueZero 接受参数 x(一个ECMAScript 语言值)和 y(一个ECMAScript 语言值)并返回一个布尔值。它确定两个参数是否为相同值(忽略 +0𝔽-0𝔽 之间的区别)。它在被调用时执行以下步骤:

  1. 如果 SameType(x, y) 是 false,返回 false
  2. 如果 x 是数字,那么
    1. 返回 Number::sameValueZero(x, y)。
  3. 返回 SameValueNonNumber(x, y)。
注意

SameValueZero 与 SameValue 的区别仅在于它将 +0𝔽-0𝔽 视为等价。

7.2.11 SameValueNonNumber ( x, y )

抽象操作 SameValueNonNumber 接受参数 x(一个ECMAScript 语言值,但不是数字)和 y(一个ECMAScript 语言值,但不是数字)并返回一个布尔值。它在被调用时执行以下步骤:

  1. 断言SameType(x, y) 是 true
  2. 如果 xnullundefined,返回 true
  3. 如果 x 是 BigInt,那么
    1. 返回 BigInt::equal(x, y)。
  4. 如果 x 是字符串,那么
    1. 如果 xy 有相同的长度且在相同位置有相同的代码单元,返回 true;否则,返回 false
  5. 如果 x 是布尔值,那么
    1. 如果 xy 都是 true 或都是 false,返回 true;否则,返回 false
  6. 注意:所有其他ECMAScript 语言值按标识进行比较。
  7. 如果 xy,返回 true;否则,返回 false
注意 1
为了说明目的,即使不必要,此算法中的某些情况也被单独处理。
注意 2
"xy"的具体含义详见5.2.7

7.2.12 IsLessThan ( x, y, LeftFirst )

抽象操作 IsLessThan 接受参数 x(一个ECMAScript 语言值)、y(一个ECMAScript 语言值)和 LeftFirst(一个布尔值)并返回一个包含布尔值或 undefined正常完成,或一个throw 完成。它为比较 x < y 提供语义,返回 truefalseundefined(表示至少一个操作数是 NaN)。LeftFirst 标志用于控制对 xy 执行可能具有可见副作用的操作的顺序。这是必要的,因为 ECMAScript 指定表达式的从左到右求值。如果 LeftFirsttruex 参数对应于出现在 y 参数对应表达式左侧的表达式。如果 LeftFirstfalse,则相反,必须在 x 之前对 y 执行操作。它在被调用时执行以下步骤:

  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 是字符串py 是字符串,那么
    1. lxpx 的长度。
    2. lypy 的长度。
    3. 对于每个整数 i,满足 0 ≤ i < min(lx, ly),按升序执行
      1. cxpx 中索引 i 处代码单元的数值。
      2. cypy 中索引 i 处代码单元的数值。
      3. 如果 cx < cy,返回 true
      4. 如果 cx > cy,返回 false
    4. 如果 lx < ly,返回 true。否则,返回 false
  4. 否则,
    1. 如果 px 是 BigIntpy 是字符串,那么
      1. nyStringToBigInt(py)。
      2. 如果 nyundefined,返回 undefined
      3. 返回 BigInt::lessThan(px, ny)。
    2. 如果 px 是字符串py 是 BigInt,那么
      1. nxStringToBigInt(px)。
      2. 如果 nxundefined,返回 undefined
      3. 返回 BigInt::lessThan(nx, py)。
    3. 注意:因为 pxpy 是原始值,求值顺序不重要。
    4. nx 为 ? ToNumeric(px)。
    5. ny 为 ? ToNumeric(py)。
    6. 如果 SameType(nx, ny) 是 true,那么
      1. 如果 nx 是数字,那么
        1. 返回 Number::lessThan(nx, ny)。
      2. 否则,
        1. 断言nx 是 BigInt
        2. 返回 BigInt::lessThan(nx, ny)。
    7. 断言nx 是 BigIntny 是数字,或 nx 是数字ny 是 BigInt
    8. 如果 nxnyNaN,返回 undefined
    9. 如果 nx-∞𝔽ny+∞𝔽,返回 true
    10. 如果 nx+∞𝔽ny-∞𝔽,返回 false
    11. 如果 (nx) < (ny),返回 true;否则返回 false
注意 1

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

注意 2

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

7.2.13 IsLooselyEqual ( x, y )

抽象操作 IsLooselyEqual 接受参数 x(一个ECMAScript 语言值)和 y(一个ECMAScript 语言值)并返回一个包含布尔值的正常完成或一个throw 完成。它为 == 运算符提供语义。它在被调用时执行以下步骤:

  1. 如果 SameType(x, y) 是 true,那么
    1. 返回 IsStrictlyEqual(x, y)。
  2. 如果 xnullyundefined,返回 true
  3. 如果 xundefinedynull,返回 true
  4. 注意:此步骤在B.3.6.2 节中被替换。
  5. 如果 x 是数字y 是字符串,返回 ! IsLooselyEqual(x, ! ToNumber(y))。
  6. 如果 x 是字符串y 是数字,返回 ! IsLooselyEqual(! ToNumber(x), y)。
  7. 如果 x 是 BigInty 是字符串,那么
    1. nStringToBigInt(y)。
    2. 如果 nundefined,返回 false
    3. 返回 ! IsLooselyEqual(x, n)。
  8. 如果 x 是字符串y 是 BigInt,返回 ! IsLooselyEqual(y, x)。
  9. 如果 x 是布尔值,返回 ! IsLooselyEqual(! ToNumber(x), y)。
  10. 如果 y 是布尔值,返回 ! IsLooselyEqual(x, ! ToNumber(y))。
  11. 如果 x 是字符串、数字、BigInt 或符号,且 y 是对象,返回 ! IsLooselyEqual(x, ? ToPrimitive(y))。
  12. 如果 x 是对象y 是字符串、数字、BigInt 或符号,返回 ! IsLooselyEqual(? ToPrimitive(x), y)。
  13. 如果 x 是 BigInty 是数字,或如果 x 是数字y 是 BigInt,那么
    1. 如果 x 不是有限的y 不是有限的,返回 false
    2. 如果 (x) = (y),返回 true;否则返回 false
  14. 返回 false

7.2.14 IsStrictlyEqual ( x, y )

抽象操作 IsStrictlyEqual 接受参数 x(一个ECMAScript 语言值)和 y(一个ECMAScript 语言值)并返回一个布尔值。它为 === 运算符提供语义。它在被调用时执行以下步骤:

  1. 如果 SameType(x, y) 是 false,返回 false
  2. 如果 x 是数字,那么
    1. 返回 Number::equal(x, y)。
  3. 返回 SameValueNonNumber(x, y)。
注意

此算法与 SameValue 算法在处理有符号零和 NaN 方面有所不同。

7.3 对象操作

7.3.1 MakeBasicObject ( internalSlotsList )

抽象操作 MakeBasicObject 接受参数 internalSlotsList(一个内部槽名称的列表)并返回一个对象。它是所有算法创建的 ECMAScript 对象的源头,包括普通对象异质对象。它提取了创建所有对象时使用的通用步骤,并集中了对象创建过程。它在被调用时执行以下步骤:

  1. internalSlotsListinternalSlotsList 和 « [[PrivateElements]] » 的列表连接
  2. obj 为一个新创建的对象,为 internalSlotsList 中的每个名称都有一个内部槽。
  3. 注意:如对象内部方法和内部槽中所述,除非另有规定,每个这样的内部槽的初始值都是 undefined
  4. obj.[[PrivateElements]] 为一个新的空列表
  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
注意

在本规范中,异质对象是在诸如 ArrayCreateBoundFunctionCreate抽象操作中创建的,首先调用 MakeBasicObject 来获得一个基本的基础对象,然后覆盖该对象的一些或所有内部方法。为了封装异质对象的创建,对象的基本内部方法永远不会在这些操作之外被修改。

7.3.2 Get ( O, P )

抽象操作 Get 接受参数 O(一个对象)和 P(一个属性键)并返回一个包含一个ECMAScript 语言值正常完成或一个throw 完成。它用于检索对象的特定属性的值。它在被调用时执行以下步骤:

  1. 返回 ? O.[[Get]](P, O)。

7.3.3 GetV ( V, P )

抽象操作 GetV 接受参数 V(一个ECMAScript 语言值)和 P(一个属性键)并返回一个包含一个ECMAScript 语言值正常完成或一个throw 完成。它用于检索ECMAScript 语言值的特定属性的值。如果该值不是对象,则使用适合该值类型的包装器对象执行属性查找。它在被调用时执行以下步骤:

  1. O 为 ? ToObject(V)。
  2. 返回 ? O.[[Get]](P, V)。

7.3.4 Set ( O, P, V, Throw )

抽象操作 Set 接受参数 O(一个对象)、P(一个属性键)、V(一个ECMAScript 语言值)和 Throw(一个布尔值)并返回一个包含 unused正常完成或一个throw 完成。它用于设置对象的特定属性的值。V 是该属性的新值。它在被调用时执行以下步骤:

  1. success 为 ? O.[[Set]](P, V, O)。
  2. 如果 successfalseThrowtrue,抛出 TypeError 异常。
  3. 返回 unused

7.3.5 CreateDataProperty ( O, P, V )

抽象操作 CreateDataProperty 接受参数 O(一个对象)、P(一个属性键)和 V(一个ECMAScript 语言值)并返回一个包含布尔值的正常完成或一个throw 完成。它用于创建对象的新自有属性。它在被调用时执行以下步骤:

  1. newDesc 为 PropertyDescriptor { [[Value]]: V, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true }。
  2. 返回 ? O.[[DefineOwnProperty]](P, newDesc)。
注意

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

7.3.6 CreateDataPropertyOrThrow ( O, P, V )

抽象操作 CreateDataPropertyOrThrow 接受参数 O(一个对象)、P(一个属性键)和 V(一个ECMAScript 语言值)并返回一个包含 unused正常完成或一个throw 完成。它用于创建对象的新自有属性。如果请求的属性更新无法执行,它抛出 TypeError 异常。它在被调用时执行以下步骤:

  1. success 为 ? CreateDataProperty(O, P, V)。
  2. 如果 successfalse,抛出 TypeError 异常。
  3. 返回 unused
注意

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

7.3.7 CreateNonEnumerableDataPropertyOrThrow ( O, P, V )

抽象操作 CreateNonEnumerableDataPropertyOrThrow 接受参数 O(一个对象)、P(一个属性键)和 V(一个ECMAScript 语言值)并返回 unused。它用于创建普通对象的新的不可枚举自有属性。它在被调用时执行以下步骤:

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

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

7.3.8 DefinePropertyOrThrow ( O, P, desc )

抽象操作 DefinePropertyOrThrow 接受参数 O(一个对象)、P(一个属性键)和 desc(一个属性描述符)并返回一个包含 unused正常完成或一个throw 完成。它用于以一种方式调用对象的 [[DefineOwnProperty]] 内部方法,如果请求的属性更新无法执行,将抛出 TypeError 异常。它在被调用时执行以下步骤:

  1. success 为 ? O.[[DefineOwnProperty]](P, desc)。
  2. 如果 successfalse,抛出 TypeError 异常。
  3. 返回 unused

7.3.9 DeletePropertyOrThrow ( O, P )

抽象操作 DeletePropertyOrThrow 接受参数 O(一个对象)和 P(一个属性键)并返回一个包含 unused正常完成或一个throw 完成。它用于删除对象的特定自有属性。如果属性不可配置,它抛出异常。它在被调用时执行以下步骤:

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

7.3.10 GetMethod ( V, P )

抽象操作 GetMethod 接受参数 V(一个ECMAScript 语言值)和 P(一个属性键)并返回一个包含一个函数对象undefined正常完成,或一个throw 完成。它用于获取ECMAScript 语言值的特定属性的值,当该属性的值预期是一个函数时。它在被调用时执行以下步骤:

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

7.3.11 HasProperty ( O, P )

抽象操作 HasProperty 接受参数 O(一个对象)和 P(一个属性键)并返回一个包含布尔值的正常完成或一个throw 完成。它用于确定对象是否具有指定属性键的属性。该属性可能是自有的或继承的。它在被调用时执行以下步骤:

  1. 返回 ? O.[[HasProperty]](P)。

7.3.12 HasOwnProperty ( O, P )

抽象操作 HasOwnProperty 接受参数 O(一个对象)和 P(一个属性键)并返回一个包含布尔值的正常完成或一个throw 完成。它用于确定对象是否具有指定属性键的自有属性。它在被调用时执行以下步骤:

  1. desc 为 ? O.[[GetOwnProperty]](P)。
  2. 如果 descundefined,返回 false
  3. 返回 true

7.3.13 Call ( F, V [ , argumentsList ] )

抽象操作 Call 接受参数 F(一个ECMAScript 语言值)和 V(一个ECMAScript 语言值)以及可选参数 argumentsList(一个ECMAScript 语言值列表)并返回一个包含一个ECMAScript 语言值正常完成或一个throw 完成。它用于调用函数对象[[Call]] 内部方法。F函数对象V 是作为 [[Call]]this 值的ECMAScript 语言值argumentsList 是传递给内部方法相应参数的值。如果 argumentsList 不存在,则使用一个新的空列表作为其值。它在被调用时执行以下步骤:

  1. 如果 argumentsList 不存在,设 argumentsList 为一个新的空列表
  2. 如果 IsCallable(F) 是 false,抛出 TypeError 异常。
  3. 返回 ? F.[[Call]](V, argumentsList)。

7.3.14 Construct ( F [ , argumentsList [ , newTarget ] ] )

抽象操作 Construct 接受参数 F(一个构造器)以及可选参数 argumentsList(一个ECMAScript 语言值列表)和 newTarget(一个构造器)并返回一个包含对象的正常完成或一个throw 完成。它用于调用函数对象[[Construct]] 内部方法。argumentsListnewTarget 是要作为内部方法相应参数传递的值。如果 argumentsList 不存在,则使用一个新的空列表作为其值。如果 newTarget 不存在,则使用 F 作为其值。它在被调用时执行以下步骤:

  1. 如果 newTarget 不存在,设 newTargetF
  2. 如果 argumentsList 不存在,设 argumentsList 为一个新的空列表
  3. 返回 ? F.[[Construct]](argumentsList, newTarget)。
注意

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

7.3.15 SetIntegrityLevel ( O, level )

抽象操作 SetIntegrityLevel 接受参数 O(一个对象)和 levelsealedfrozen)并返回一个包含布尔值的正常完成或一个throw 完成。它用于固定对象自有属性的集合。它在被调用时执行以下步骤:

  1. status 为 ? O.[[PreventExtensions]]()。
  2. 如果 statusfalse,返回 false
  3. keys 为 ? O.[[OwnPropertyKeys]]()。
  4. 如果 levelsealed,那么
    1. 对于 keys 的每个元素 k,执行
      1. 执行 ? DefinePropertyOrThrow(O, k, PropertyDescriptor { [[Configurable]]: false })。
  5. 否则,
    1. 断言levelfrozen
    2. 对于 keys 的每个元素 k,执行
      1. currentDesc 为 ? O.[[GetOwnProperty]](k)。
      2. 如果 currentDesc 不是 undefined,那么
        1. 如果 IsAccessorDescriptor(currentDesc) 是 true,那么
          1. desc 为 PropertyDescriptor { [[Configurable]]: false }。
        2. 否则,
          1. desc 为 PropertyDescriptor { [[Configurable]]: false, [[Writable]]: false }。
        3. 执行 ? DefinePropertyOrThrow(O, k, desc)。
  6. 返回 true

7.3.16 TestIntegrityLevel ( O, level )

抽象操作 TestIntegrityLevel 接受参数 O(一个对象)和 levelsealedfrozen)并返回一个包含布尔值的正常完成或一个throw 完成。它用于确定对象自有属性的集合是否被固定。它在被调用时执行以下步骤:

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

7.3.17 CreateArrayFromList ( elements )

抽象操作 CreateArrayFromList 接受参数 elements(一个ECMAScript 语言值列表)并返回一个数组。它用于创建一个由 elements 提供元素的数组。它在被调用时执行以下步骤:

  1. array 为 ! ArrayCreate(0)。
  2. n 为 0。
  3. 对于 elements 的每个元素 e,执行
    1. 执行 ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(n)), e)。
    2. nn + 1。
  4. 返回 array

7.3.18 LengthOfArrayLike ( obj )

抽象操作 LengthOfArrayLike 接受参数 obj(一个对象)并返回一个包含非负整数正常完成或一个throw 完成。它返回类数组对象的 "length" 属性的值。它在被调用时执行以下步骤:

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

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

注意 1
通常,类数组对象还会有一些带有整数索引名称的属性。但是,这不是此定义的要求。
注意 2
数组和字符串对象是类数组对象的例子。

7.3.19 CreateListFromArrayLike ( obj [ , validElementTypes ] )

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

  1. 如果 validElementTypes 不存在,设 validElementTypesall
  2. 如果 obj 不是对象,抛出 TypeError 异常。
  3. len 为 ? LengthOfArrayLike(obj)。
  4. list 为一个新的空列表
  5. index 为 0。
  6. 重复,当 index < len 时,
    1. indexName 为 ! ToString(𝔽(index))。
    2. next 为 ? Get(obj, indexName)。
    3. 如果 validElementTypesproperty-keynext 不是属性键,抛出 TypeError 异常。
    4. next 追加到 list
    5. indexindex + 1。
  7. 返回 list

7.3.20 Invoke ( V, P [ , argumentsList ] )

抽象操作 Invoke 接受参数 V(一个ECMAScript 语言值)和 P(一个属性键)以及可选参数 argumentsList(一个ECMAScript 语言值列表)并返回一个包含一个ECMAScript 语言值正常完成或一个throw 完成。它用于调用ECMAScript 语言值的方法属性。V 既作为属性的查找点,也作为调用的 this 值。argumentsList 是传递给方法的参数值列表。如果 argumentsList 不存在,则使用一个新的空列表作为其值。它在被调用时执行以下步骤:

  1. 如果 argumentsList 不存在,设 argumentsList 为一个新的空列表
  2. func 为 ? GetV(V, P)。
  3. 返回 ? Call(func, V, argumentsList)。

7.3.21 OrdinaryHasInstance ( C, O )

抽象操作 OrdinaryHasInstance 接受参数 C(一个ECMAScript 语言值)和 O(一个ECMAScript 语言值)并返回一个包含布尔值的正常完成或一个throw 完成。它实现了确定 O 是否继承自 C 提供的实例对象继承路径的默认算法。它在被调用时执行以下步骤:

  1. 如果 IsCallable(C) 是 false,返回 false
  2. 如果 C[[BoundTargetFunction]] 内部槽,那么
    1. BCC.[[BoundTargetFunction]]
    2. 返回 ? InstanceofOperator(O, BC)。
  3. 如果 O 不是对象,返回 false
  4. P 为 ? Get(C, "prototype")。
  5. 如果 P 不是对象,抛出 TypeError 异常。
  6. 重复,
    1. O 为 ? O.[[GetPrototypeOf]]()。
    2. 如果 Onull,返回 false
    3. 如果 SameValue(P, O) 是 true,返回 true

7.3.22 SpeciesConstructor ( O, defaultConstructor )

抽象操作 SpeciesConstructor 接受参数 O(一个对象)和 defaultConstructor(一个构造器)并返回一个包含一个构造器正常完成或一个throw 完成。它用于检索应该用于创建从 O 派生的新对象的构造器defaultConstructor 是当从 O 开始无法找到构造器 %Symbol.species% 属性时要使用的构造器。它在被调用时执行以下步骤:

  1. C 为 ? Get(O, "constructor")。
  2. 如果 Cundefined,返回 defaultConstructor
  3. 如果 C 不是对象,抛出 TypeError 异常。
  4. S 为 ? Get(C, %Symbol.species%)。
  5. 如果 Sundefinednull,返回 defaultConstructor
  6. 如果 IsConstructor(S) 是 true,返回 S
  7. 抛出 TypeError 异常。

7.3.23 EnumerableOwnProperties ( O, kind )

抽象操作 EnumerableOwnProperties 接受参数 O(一个对象)和 kindkeyvaluekey+value)并返回一个包含ECMAScript 语言值列表正常完成或一个throw 完成。它在被调用时执行以下步骤:

  1. ownKeys 为 ? O.[[OwnPropertyKeys]]()。
  2. results 为一个新的空列表
  3. 对于 ownKeys 的每个元素 key,执行
    1. 如果 key 是字符串,那么
      1. desc 为 ? O.[[GetOwnProperty]](key)。
      2. 如果 desc 不是 undefineddesc.[[Enumerable]]true,那么
        1. 如果 kindkey,那么
          1. key 追加到 results
        2. 否则,
          1. value 为 ? Get(O, key)。
          2. 如果 kindvalue,那么
            1. value 追加到 results
          3. 否则,
            1. 断言kindkey+value
            2. entryCreateArrayFromListkey, value »)。
            3. entry 追加到 results
  4. 返回 results

7.3.24 GetFunctionRealm ( obj )

抽象操作 GetFunctionRealm 接受参数 obj(一个函数对象)并返回一个包含一个Realm Record正常完成或一个throw 完成。它在被调用时执行以下步骤:

  1. 如果 obj[[Realm]] 内部槽,那么
    1. 返回 obj.[[Realm]]
  2. 如果 obj绑定函数异质对象,那么
    1. boundTargetFunctionobj.[[BoundTargetFunction]]
    2. 返回 ? GetFunctionRealm(boundTargetFunction)。
  3. 如果 obj代理异质对象,那么
    1. 执行 ? ValidateNonRevokedProxy(obj)。
    2. proxyTargetobj.[[ProxyTarget]]
    3. 断言proxyTarget 是一个函数对象
    4. 返回 ? GetFunctionRealm(proxyTarget)。
  4. 返回当前 Realm Record
注意

只有当 obj 是一个没有 [[Realm]] 内部槽的非标准函数异质对象时,才会执行步骤4

7.3.25 CopyDataProperties ( target, source, excludedItems )

抽象操作 CopyDataProperties 接受参数 target(一个对象)、source(一个ECMAScript 语言值)和 excludedItems(一个属性键列表)并返回一个包含 unused正常完成或一个throw 完成。它在被调用时执行以下步骤:

  1. 如果 sourceundefinednull,返回 unused
  2. from 为 ! ToObject(source)。
  3. keys 为 ? from.[[OwnPropertyKeys]]()。
  4. 对于 keys 的每个元素 nextKey,执行
    1. excludedfalse
    2. 对于 excludedItems 的每个元素 e,执行
      1. 如果 SameValue(e, nextKey) 是 true,那么
        1. excludedtrue
    3. 如果 excludedfalse,那么
      1. desc 为 ? from.[[GetOwnProperty]](nextKey)。
      2. 如果 desc 不是 undefineddesc.[[Enumerable]]true,那么
        1. propValue 为 ? Get(from, nextKey)。
        2. 执行 ! CreateDataPropertyOrThrow(target, nextKey, propValue)。
  5. 返回 unused
注意

这里传入的目标总是一个新创建的对象,在抛出错误的情况下不能直接访问。

7.3.26 PrivateElementFind ( O, P )

抽象操作 PrivateElementFind 接受参数 O(一个对象)和 P(一个私有名称)并返回一个PrivateElementempty。它在被调用时执行以下步骤:

  1. 如果 O.[[PrivateElements]] 包含一个PrivateElement pe,其中 pe.[[Key]]P,那么
    1. 返回 pe
  2. 返回 empty

7.3.27 PrivateFieldAdd ( O, P, value )

抽象操作 PrivateFieldAdd 接受参数 O(一个对象)、P(一个私有名称)和 value(一个ECMAScript 语言值)并返回一个包含 unused正常完成或一个throw 完成。它在被调用时执行以下步骤:

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

7.3.28 PrivateMethodOrAccessorAdd ( O, method )

抽象操作 PrivateMethodOrAccessorAdd 接受参数 O(一个对象)和 method(一个PrivateElement)并返回一个包含 unused正常完成或一个throw 完成。它在被调用时执行以下步骤:

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

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

7.3.29 HostEnsureCanAddPrivateElement ( O )

宿主定义的抽象操作 HostEnsureCanAddPrivateElement 接受参数 O(一个对象)并返回一个包含 unused正常完成或一个throw 完成。它允许宿主环境阻止向特定的宿主定义的异质对象添加私有元素。

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

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

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

7.3.30 PrivateGet ( O, P )

抽象操作 PrivateGet 接受参数 O(一个对象)和 P(一个私有名称)并返回一个包含一个ECMAScript 语言值正常完成或一个throw 完成。它在被调用时执行以下步骤:

  1. entryPrivateElementFind(O, P)。
  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, O)。

7.3.31 PrivateSet ( O, P, value )

抽象操作 PrivateSet 接受参数 O(一个对象)、P(一个私有名称)和 value(一个ECMAScript 语言值)并返回一个包含 unused正常完成或一个throw 完成。它在被调用时执行以下步骤:

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

7.3.32 DefineField ( receiver, fieldRecord )

抽象操作 DefineField 接受参数 receiver(一个对象)和 fieldRecord(一个ClassFieldDefinition Record)并返回一个包含 unused正常完成或一个throw 完成。它在被调用时执行以下步骤:

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

7.3.33 InitializeInstanceElements ( O, constructor )

抽象操作 InitializeInstanceElements 接受参数 O(一个对象)和 constructor(一个 ECMAScript 函数对象)并返回一个包含 unused正常完成或一个throw 完成。它在被调用时执行以下步骤:

  1. methodsconstructor.[[PrivateMethods]] 的值。
  2. 对于 methods 的每个PrivateElement method,执行
    1. 执行 ? PrivateMethodOrAccessorAdd(O, method)。
  3. fieldsconstructor.[[Fields]] 的值。
  4. 对于 fields 的每个元素 fieldRecord,执行
    1. 执行 ? DefineField(O, fieldRecord)。
  5. 返回 unused

7.3.34 AddValueToKeyedGroup ( groups, key, value )

抽象操作 AddValueToKeyedGroup 接受参数 groups(一个记录列表,具有字段 [[Key]](一个ECMAScript 语言值)和 [[Elements]](一个ECMAScript 语言值列表))、key(一个ECMAScript 语言值)和 value(一个ECMAScript 语言值)并返回 unused。它在被调用时执行以下步骤:

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

7.3.35 GroupBy ( items, callback, keyCoercion )

抽象操作 GroupBy 接受参数 items(一个ECMAScript 语言值)、callback(一个ECMAScript 语言值)和 keyCoercionpropertycollection)并返回一个包含记录列表正常完成(具有字段 [[Key]](一个ECMAScript 语言值)和 [[Elements]](一个ECMAScript 语言值列表))或一个throw 完成。它在被调用时执行以下步骤:

  1. 执行 ? RequireObjectCoercible(items)。
  2. 如果 IsCallable(callback) 是 false,抛出 TypeError 异常。
  3. groups 为一个新的空列表
  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. keyCompletion(ToPropertyKey(key))。
      2. IfAbruptCloseIterator(key, iteratorRecord)。
    8. 否则,
      1. 断言keyCoercioncollection
      2. keyCanonicalizeKeyedCollectionKey(key)。
    9. 执行 AddValueToKeyedGroup(groups, key, value)。
    10. kk + 1。

7.3.36 SetterThatIgnoresPrototypeProperties ( thisValue, home, p, v )

抽象操作 SetterThatIgnoresPrototypeProperties 接受参数 thisValue(一个ECMAScript 语言值)、home(一个对象)、p(一个属性键)和 v(一个ECMAScript 语言值)并返回一个包含 unused正常完成或一个throw 完成。它在被调用时执行以下步骤:

  1. 如果 thisValue 不是对象,那么
    1. 抛出 TypeError 异常。
  2. 如果 SameValue(thisValue, home) 是 true,那么
    1. 注意:这里抛出异常模拟了在严格模式代码中对 home 对象上不可写数据属性的赋值。
    2. 抛出 TypeError 异常。
  3. desc 为 ? thisValue.[[GetOwnProperty]](p)。
  4. 如果 descundefined,那么
    1. 执行 ? CreateDataPropertyOrThrow(thisValue, p, v)。
  5. 否则,
    1. 执行 ? Set(thisValue, p, v, true)。
  6. 返回 unused

7.4 迭代器对象上的操作

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

7.4.1 迭代器记录

迭代器记录是一个记录值,用于封装一个迭代器异步迭代器以及其 next 方法。

迭代器记录具有表 15中列出的字段。

表 15:迭代器记录字段
字段名称 含义
[[Iterator]] 一个对象 符合迭代器接口异步迭代器接口的对象。
[[NextMethod]] 一个ECMAScript 语言值 [[Iterator]] 对象的 next 方法。
[[Done]] 一个布尔值 迭代器是否已完成或已关闭。

7.4.2 GetIteratorDirect ( obj )

抽象操作 GetIteratorDirect 接受参数 obj(一个对象)并返回一个包含一个迭代器记录正常完成或一个throw 完成。它在被调用时执行以下步骤:

  1. nextMethod 为 ? Get(obj, "next")。
  2. iteratorRecord迭代器记录 { [[Iterator]]: obj, [[NextMethod]]: nextMethod, [[Done]]: false }。
  3. 返回 iteratorRecord

7.4.3 GetIteratorFromMethod ( obj, method )

抽象操作 GetIteratorFromMethod 接受参数 obj(一个ECMAScript 语言值)和 method(一个函数对象)并返回一个包含一个迭代器记录正常完成或一个throw 完成。它在被调用时执行以下步骤:

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

7.4.4 GetIterator ( obj, kind )

抽象操作 GetIterator 接受参数 obj(一个ECMAScript 语言值)和 kindsyncasync)并返回一个包含一个迭代器记录正常完成或一个throw 完成。它在被调用时执行以下步骤:

  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 )

抽象操作 GetIteratorFlattenable 接受参数 obj(一个ECMAScript 语言值)和 primitiveHandlingiterate-string-primitivesreject-primitives)并返回一个包含一个迭代器记录正常完成或一个throw 完成。它在被调用时执行以下步骤:

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

7.4.6 IteratorNext ( iteratorRecord [ , value ] )

抽象操作 IteratorNext 接受参数 iteratorRecord(一个迭代器记录)和可选参数 value(一个ECMAScript 语言值)并返回一个包含一个对象的正常完成或一个throw 完成。它在被调用时执行以下步骤:

  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 不是对象,那么
    1. iteratorRecord.[[Done]]true
    2. 抛出 TypeError 异常。
  6. 返回 result

7.4.7 IteratorComplete ( iteratorResult )

抽象操作 IteratorComplete 接受参数 iteratorResult(一个对象)并返回一个包含一个布尔值的正常完成或一个throw 完成。它在被调用时执行以下步骤:

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

7.4.8 IteratorValue ( iteratorResult )

抽象操作 IteratorValue 接受参数 iteratorResult(一个对象)并返回一个包含一个ECMAScript 语言值正常完成或一个throw 完成。它在被调用时执行以下步骤:

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

7.4.9 IteratorStep ( iteratorRecord )

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

  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 )

抽象操作 IteratorStepValue 接受参数 iteratorRecord(一个迭代器记录)并返回一个包含一个ECMAScript 语言值done正常完成,或一个throw 完成。它通过调用 iteratorRecord.[[NextMethod]]iteratorRecord.[[Iterator]] 请求下一个值,并返回 done(表示迭代器已到达末尾)或来自IteratorResult 对象的值(如果下一个值可用)。它在被调用时执行以下步骤:

  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 )

抽象操作 IteratorClose 接受参数 iteratorRecord(一个迭代器记录)和 completion(一个完成记录)并返回一个完成记录。它用于通知迭代器应该执行它在到达完成状态时通常要执行的任何操作。它在被调用时执行以下步骤:

  1. 断言iteratorRecord.[[Iterator]] 是一个对象
  2. iteratoriteratorRecord.[[Iterator]]
  3. innerResultCompletion(GetMethod(iterator, "return"))。
  4. 如果 innerResult正常完成,那么
    1. returninnerResult.[[Value]]
    2. 如果 returnundefined,返回 ? completion
    3. innerResultCompletion(Call(return, iterator))。
  5. 如果 completionthrow 完成,返回 ? completion
  6. 如果 innerResultthrow 完成,返回 ? innerResult
  7. 如果 innerResult.[[Value]] 不是对象,抛出 TypeError 异常。
  8. 返回 ? completion

7.4.12 IfAbruptCloseIterator ( value, iteratorRecord )

IfAbruptCloseIterator 是使用迭代器记录的算法步骤序列的简写。形式为以下的算法步骤:

  1. IfAbruptCloseIterator(value, iteratorRecord)。

与以下含义相同:

  1. 断言value 是一个完成记录
  2. 如果 value异常完成,返回 ? IteratorClose(iteratorRecord, value)。
  3. 否则,设 value 为 ! value

7.4.13 AsyncIteratorClose ( iteratorRecord, completion )

抽象操作 AsyncIteratorClose 接受参数 iteratorRecord(一个迭代器记录)和 completion(一个完成记录)并返回一个完成记录。它用于通知异步迭代器应该执行它在到达完成状态时通常要执行的任何操作。它在被调用时执行以下步骤:

  1. 断言iteratorRecord.[[Iterator]] 是一个对象
  2. iteratoriteratorRecord.[[Iterator]]
  3. innerResultCompletion(GetMethod(iterator, "return"))。
  4. 如果 innerResult正常完成,那么
    1. returninnerResult.[[Value]]
    2. 如果 returnundefined,返回 ? completion
    3. innerResultCompletion(Call(return, iterator))。
    4. 如果 innerResult正常完成,设 innerResultCompletion(Await(innerResult.[[Value]]))。
  5. 如果 completionthrow 完成,返回 ? completion
  6. 如果 innerResultthrow 完成,返回 ? innerResult
  7. 如果 innerResult.[[Value]] 不是对象,抛出 TypeError 异常。
  8. 返回 ? completion

7.4.14 CreateIteratorResultObject ( value, done )

抽象操作 CreateIteratorResultObject 接受参数 value(一个ECMAScript 语言值)和 done(一个布尔值)并返回一个符合IteratorResult 接口的对象。它创建一个符合IteratorResult 接口的对象。它在被调用时执行以下步骤:

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

7.4.15 CreateListIteratorRecord ( list )

抽象操作 CreateListIteratorRecord 接受参数 list(一个包含ECMAScript 语言值列表)并返回一个迭代器记录。它创建一个迭代器记录,其 [[NextMethod]] 返回 list 的连续元素。它在被调用时执行以下步骤:

  1. closure 为一个新的抽象闭包,它没有参数,捕获 list,并在被调用时执行以下步骤:
    1. 对于 list 的每个元素 E,执行
      1. 执行 ? GeneratorYield(CreateIteratorResultObject(E, false))。
    2. 返回 NormalCompletion(undefined)。
  2. iteratorCreateIteratorFromClosure(closure, empty, %Iterator.prototype%)。
  3. 返回迭代器记录 { [[Iterator]]: iterator, [[NextMethod]]: %GeneratorPrototype.next%, [[Done]]: false }。
注意

列表迭代器对象永远不会直接暴露给 ECMAScript 代码。

7.4.16 IteratorToList ( iteratorRecord )

抽象操作 IteratorToList 接受参数 iteratorRecord(一个迭代器记录)并返回一个包含一个列表(包含ECMAScript 语言值)的正常完成或一个throw 完成。它在被调用时执行以下步骤:

  1. values 为一个新的空列表
  2. 重复,
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 nextdone,那么
      1. 返回 values
    3. next 追加到 values

8 语法定向操作

除了本节中定义的操作外,专用的语法定向操作在本规范中各处都有定义。

8.1 运行时语义:Evaluation

语法定向操作 Evaluation 不接受参数并返回一个完成记录

注意
此操作的定义分布在本规范的"ECMAScript 语言"章节中。每个定义都出现在相关产生式的定义出现之后。

8.2 作用域分析

8.2.1 静态语义:BoundNames

语法定向操作 BoundNames 不接受参数并返回一个字符串的列表

注意

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

它在以下产生式上分段定义:

BindingIdentifier : Identifier
  1. 返回一个列表,其唯一元素是 IdentifierStringValue
BindingIdentifier : yield
  1. 返回 « "yield" »。
BindingIdentifier : await
  1. 返回 « "await" »。
LexicalDeclaration : LetOrConst 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. 返回一个新的空列表
ObjectBindingPattern : { BindingPropertyList , BindingRestProperty }
  1. names1BindingPropertyListBoundNames
  2. names2BindingRestPropertyBoundNames
  3. 返回 names1names2列表连接
ArrayBindingPattern : [ Elisionopt ]
  1. 返回一个新的空列表
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. 返回一个新的空列表
FormalParameters : FormalParameterList , FunctionRestParameter
  1. names1FormalParameterListBoundNames
  2. names2FunctionRestParameterBoundNames
  3. 返回 names1names2列表连接
FormalParameterList : FormalParameterList , FormalParameter
  1. names1FormalParameterListBoundNames
  2. names2FormalParameterBoundNames
  3. 返回 names1names2列表连接
ArrowParameters : CoverParenthesizedExpressionAndArrowParameterList
  1. formals 为被 CoverParenthesizedExpressionAndArrowParameterList 覆盖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. head 为被 CoverCallExpressionAndAsyncArrowHead 覆盖AsyncArrowHead
  2. 返回 headBoundNames
ImportDeclaration : import ImportClause FromClause WithClauseopt ;
  1. 返回 ImportClauseBoundNames
ImportDeclaration : import ModuleSpecifier WithClauseopt ;
  1. 返回一个新的空列表
ImportClause : ImportedDefaultBinding , NameSpaceImport
  1. names1ImportedDefaultBindingBoundNames
  2. names2NameSpaceImportBoundNames
  3. 返回 names1names2列表连接
ImportClause : ImportedDefaultBinding , NamedImports
  1. names1ImportedDefaultBindingBoundNames
  2. names2NamedImportsBoundNames
  3. 返回 names1names2列表连接
NamedImports : { }
  1. 返回一个新的空列表
ImportsList : ImportsList , ImportSpecifier
  1. names1ImportsListBoundNames
  2. names2ImportSpecifierBoundNames
  3. 返回 names1names2列表连接
ImportSpecifier : ModuleExportName as ImportedBinding
  1. 返回 ImportedBindingBoundNames
ExportDeclaration : export ExportFromClause FromClause WithClauseopt ; export NamedExports ;
  1. 返回一个新的空列表
ExportDeclaration : export VariableStatement
  1. 返回 VariableStatementBoundNames
ExportDeclaration : export Declaration
  1. 返回 DeclarationBoundNames
ExportDeclaration : export default HoistableDeclaration
  1. declarationNamesHoistableDeclarationBoundNames
  2. 如果 declarationNames 不包含元素 "*default*",则将 "*default*" 追加到 declarationNames
  3. 返回 declarationNames
ExportDeclaration : export default ClassDeclaration
  1. declarationNamesClassDeclarationBoundNames
  2. 如果 declarationNames 不包含元素 "*default*",则将 "*default*" 追加到 declarationNames
  3. 返回 declarationNames
ExportDeclaration : export default AssignmentExpression ;
  1. 返回 « "*default*" »。

8.2.2 静态语义:DeclarationPart

语法定向操作 DeclarationPart 不接受参数并返回一个解析节点。它在以下产生式上分段定义:

HoistableDeclaration : FunctionDeclaration
  1. 返回 FunctionDeclaration
HoistableDeclaration : GeneratorDeclaration
  1. 返回 GeneratorDeclaration
HoistableDeclaration : AsyncFunctionDeclaration
  1. 返回 AsyncFunctionDeclaration
HoistableDeclaration : AsyncGeneratorDeclaration
  1. 返回 AsyncGeneratorDeclaration
Declaration : ClassDeclaration
  1. 返回 ClassDeclaration
Declaration : LexicalDeclaration
  1. 返回 LexicalDeclaration

8.2.3 静态语义:IsConstantDeclaration

语法定向操作 IsConstantDeclaration 不接受参数并返回一个布尔值。它在以下产生式上分段定义:

LexicalDeclaration : LetOrConst BindingList ;
  1. 返回 LetOrConstIsConstantDeclaration
LetOrConst : let
  1. 返回 false
LetOrConst : const
  1. 返回 true
FunctionDeclaration : function BindingIdentifier ( FormalParameters ) { FunctionBody } function ( FormalParameters ) { FunctionBody } GeneratorDeclaration : function * BindingIdentifier ( FormalParameters ) { GeneratorBody } function * ( FormalParameters ) { GeneratorBody } AsyncGeneratorDeclaration : async function * BindingIdentifier ( FormalParameters ) { AsyncGeneratorBody } async function * ( FormalParameters ) { AsyncGeneratorBody } AsyncFunctionDeclaration : async function BindingIdentifier ( FormalParameters ) { AsyncFunctionBody } async function ( FormalParameters ) { AsyncFunctionBody }
  1. 返回 false
ClassDeclaration : class BindingIdentifier ClassTail class ClassTail
  1. 返回 false
ExportDeclaration : export ExportFromClause FromClause ; export NamedExports ; export default AssignmentExpression ;
  1. 返回 false
注意

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

8.2.4 静态语义:词法声明的名称 (LexicallyDeclaredNames)

语法导向操作 LexicallyDeclaredNames 不接受参数,并返回一个字符串列表。它根据以下产生式分段定义:

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

Script 的顶层,函数声明被视为类似 var 声明,而不是类似词法声明。

注 2

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

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

Module 的顶层,函数声明被视为类似词法声明,而不是类似 var 声明。

8.2.5 静态语义:词法作用域声明 (LexicallyScopedDeclarations)

语法导向操作 LexicallyScopedDeclarations 不接受参数,并返回一个解析节点列表。它根据以下产生式分段定义:

StatementList : StatementList StatementListItem
  1. declarations1StatementListLexicallyScopedDeclarations
  2. declarations2StatementListItemLexicallyScopedDeclarations
  3. 返回 declarations1declarations2列表连接
StatementListItem : Statement
  1. 如果 Statement Statement : LabelledStatement ,则返回 LabelledStatementLexicallyScopedDeclarations
  2. 返回一个新的空列表
StatementListItem : Declaration
  1. 返回一个列表,其唯一元素是 DeclarationDeclarationPart
CaseBlock : { }
  1. 返回一个新的空列表
CaseBlock : { CaseClausesopt DefaultClause CaseClausesopt }
  1. 如果第一个 CaseClauses 存在,令 declarations1 为第一个 CaseClausesLexicallyScopedDeclarations
  2. 否则,令 declarations1 为一个新的空列表
  3. declarations2DefaultClauseLexicallyScopedDeclarations
  4. 如果第二个 CaseClauses 存在,令 declarations3 为第二个 CaseClausesLexicallyScopedDeclarations
  5. 否则,令 declarations3 为一个新的空列表
  6. 返回 declarations1declarations2declarations3列表连接
CaseClauses : CaseClauses CaseClause
  1. declarations1CaseClausesLexicallyScopedDeclarations
  2. declarations2CaseClauseLexicallyScopedDeclarations
  3. 返回 declarations1declarations2列表连接
CaseClause : case Expression : StatementListopt
  1. 如果 StatementList 存在,则返回 StatementListLexicallyScopedDeclarations
  2. 返回一个新的空列表
DefaultClause : default : StatementListopt
  1. 如果 StatementList 存在,则返回 StatementListLexicallyScopedDeclarations
  2. 返回一个新的空列表
LabelledStatement : LabelIdentifier : LabelledItem
  1. 返回 LabelledItemLexicallyScopedDeclarations
LabelledItem : Statement
  1. 返回一个新的空列表
LabelledItem : FunctionDeclaration
  1. 返回 « FunctionDeclaration »。
FunctionStatementList : [空]
  1. 返回一个新的空列表
FunctionStatementList : StatementList
  1. 返回 StatementListTopLevelLexicallyScopedDeclarations
ClassStaticBlockStatementList : [空]
  1. 返回一个新的空列表
ClassStaticBlockStatementList : StatementList
  1. 返回 StatementListTopLevelLexicallyScopedDeclarations
ConciseBody : ExpressionBody
  1. 返回一个新的空列表
AsyncConciseBody : ExpressionBody
  1. 返回一个新的空列表
Script : [空]
  1. 返回一个新的空列表
ScriptBody : StatementList
  1. 返回 StatementListTopLevelLexicallyScopedDeclarations
Module : [空]
  1. 返回一个新的空列表
ModuleItemList : ModuleItemList ModuleItem
  1. declarations1ModuleItemListLexicallyScopedDeclarations
  2. declarations2ModuleItemLexicallyScopedDeclarations
  3. 返回 declarations1declarations2列表连接
ModuleItem : ImportDeclaration
  1. 返回一个新的空列表
ExportDeclaration : export ExportFromClause FromClause WithClauseopt ; export NamedExports ; export VariableStatement
  1. 返回一个新的空列表
ExportDeclaration : export Declaration
  1. 返回一个列表,其唯一元素是 DeclarationDeclarationPart
ExportDeclaration : export default HoistableDeclaration
  1. 返回一个列表,其唯一元素是 HoistableDeclarationDeclarationPart
ExportDeclaration : export default ClassDeclaration
  1. 返回一个列表,其唯一元素是 ClassDeclaration
ExportDeclaration : export default AssignmentExpression ;
  1. 返回一个列表,其唯一元素是这个 ExportDeclaration

8.2.6 静态语义:VarDeclaredNames

语法导向操作 VarDeclaredNames 不接受参数,并返回一个字符串列表。它根据以下产生式分段定义:

Statement : EmptyStatement ExpressionStatement ContinueStatement BreakStatement ReturnStatement ThrowStatement DebuggerStatement
  1. 返回一个新的空列表
Block : { }
  1. 返回一个新的空列表
StatementList : StatementList StatementListItem
  1. names1StatementListVarDeclaredNames
  2. names2StatementListItemVarDeclaredNames
  3. 返回 names1names2列表连接
StatementListItem : Declaration
  1. 返回一个新的空列表
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列表连接

本节由附录 B.3.5 扩展。

WithStatement : with ( Expression ) Statement
  1. 返回 StatementVarDeclaredNames
SwitchStatement : switch ( Expression ) CaseBlock
  1. 返回 CaseBlockVarDeclaredNames
CaseBlock : { }
  1. 返回一个新的空列表
CaseBlock : { CaseClausesopt DefaultClause CaseClausesopt }
  1. 如果第一个 CaseClauses 存在,令 names1 为第一个 CaseClausesVarDeclaredNames
  2. 否则,令 names1 为一个新的空列表
  3. names2DefaultClauseVarDeclaredNames
  4. 如果第二个 CaseClauses 存在,令 names3 为第二个 CaseClausesVarDeclaredNames
  5. 否则,令 names3 为一个新的空列表
  6. 返回 names1names2names3列表连接
CaseClauses : CaseClauses CaseClause
  1. names1CaseClausesVarDeclaredNames
  2. names2CaseClauseVarDeclaredNames
  3. 返回 names1names2列表连接
CaseClause : case Expression : StatementListopt
  1. 如果 StatementList 存在,则返回 StatementListVarDeclaredNames
  2. 返回一个新的空列表
DefaultClause : default : StatementListopt
  1. 如果 StatementList 存在,则返回 StatementListVarDeclaredNames
  2. 返回一个新的空列表
LabelledStatement : LabelIdentifier : LabelledItem
  1. 返回 LabelledItemVarDeclaredNames
LabelledItem : FunctionDeclaration
  1. 返回一个新的空列表
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 : [空]
  1. 返回一个新的空列表
FunctionStatementList : StatementList
  1. 返回 StatementListTopLevelVarDeclaredNames
ClassStaticBlockStatementList : [空]
  1. 返回一个新的空列表
ClassStaticBlockStatementList : StatementList
  1. 返回 StatementListTopLevelVarDeclaredNames
ConciseBody : ExpressionBody
  1. 返回一个新的空列表
AsyncConciseBody : ExpressionBody
  1. 返回一个新的空列表
Script : [空]
  1. 返回一个新的空列表
ScriptBody : StatementList
  1. 返回 StatementListTopLevelVarDeclaredNames
ModuleItemList : ModuleItemList ModuleItem
  1. names1ModuleItemListVarDeclaredNames
  2. names2ModuleItemVarDeclaredNames
  3. 返回 names1names2列表连接
ModuleItem : ImportDeclaration
  1. 返回一个新的空列表
ModuleItem : ExportDeclaration
  1. 如果 ExportDeclarationexport VariableStatement,则返回 ExportDeclarationBoundNames
  2. 返回一个新的空列表

8.2.7 静态语义:VarScopedDeclarations

语法导向操作 VarScopedDeclarations 不接受参数,返回一个包含 解析节点列表。它针对以下产生式分段定义:

Statement : EmptyStatement ExpressionStatement ContinueStatement BreakStatement ReturnStatement ThrowStatement DebuggerStatement
  1. 返回一个新的空列表
Block : { }
  1. 返回一个新的空列表
StatementList : StatementList StatementListItem
  1. declarations1StatementListVarScopedDeclarations
  2. declarations2StatementListItemVarScopedDeclarations
  3. 返回 declarations1declarations2列表连接
StatementListItem : Declaration
  1. 返回一个新的空列表
VariableDeclarationList : VariableDeclaration
  1. 返回 « VariableDeclaration »。
VariableDeclarationList : VariableDeclarationList , VariableDeclaration
  1. declarations1VariableDeclarationListVarScopedDeclarations
  2. 返回 declarations1 和 « VariableDeclaration » 的 列表连接
IfStatement : if ( Expression ) Statement else Statement
  1. declarations1 为第一个 StatementVarScopedDeclarations
  2. declarations2 为第二个 StatementVarScopedDeclarations
  3. 返回 declarations1declarations2列表连接
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. declarations1VariableDeclarationListVarScopedDeclarations
  2. declarations2StatementVarScopedDeclarations
  3. 返回 declarations1declarations2列表连接
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. declarations1 为 « ForBinding »。
  2. declarations2StatementVarScopedDeclarations
  3. 返回 declarations1declarations2列表连接

本节由附录 B.3.5 扩展。

WithStatement : with ( Expression ) Statement
  1. 返回 StatementVarScopedDeclarations
SwitchStatement : switch ( Expression ) CaseBlock
  1. 返回 CaseBlockVarScopedDeclarations
CaseBlock : { }
  1. 返回一个新的空列表
CaseBlock : { CaseClausesopt DefaultClause CaseClausesopt }
  1. 如果第一个 CaseClauses 存在,令 declarations1 为第一个 CaseClausesVarScopedDeclarations
  2. 否则,令 declarations1 为一个新的空列表
  3. declarations2DefaultClauseVarScopedDeclarations
  4. 如果第二个 CaseClauses 存在,令 declarations3 为第二个 CaseClausesVarScopedDeclarations
  5. 否则,令 declarations3 为一个新的空列表
  6. 返回 declarations1declarations2declarations3列表连接
CaseClauses : CaseClauses CaseClause
  1. declarations1CaseClausesVarScopedDeclarations
  2. declarations2CaseClauseVarScopedDeclarations
  3. 返回 declarations1declarations2列表连接
CaseClause : case Expression : StatementListopt
  1. 如果 StatementList 存在,返回 StatementListVarScopedDeclarations
  2. 返回一个新的空列表
DefaultClause : default : StatementListopt
  1. 如果 StatementList 存在,返回 StatementListVarScopedDeclarations
  2. 返回一个新的空列表
LabelledStatement : LabelIdentifier : LabelledItem
  1. 返回 LabelledItemVarScopedDeclarations
LabelledItem : FunctionDeclaration
  1. 返回一个新的空列表
TryStatement : try Block Catch
  1. declarations1BlockVarScopedDeclarations
  2. declarations2CatchVarScopedDeclarations
  3. 返回 declarations1declarations2列表连接
TryStatement : try Block Finally
  1. declarations1BlockVarScopedDeclarations
  2. declarations2FinallyVarScopedDeclarations
  3. 返回 declarations1declarations2列表连接
TryStatement : try Block Catch Finally
  1. declarations1BlockVarScopedDeclarations
  2. declarations2CatchVarScopedDeclarations
  3. declarations3FinallyVarScopedDeclarations
  4. 返回 declarations1declarations2declarations3列表连接
Catch : catch ( CatchParameter ) Block
  1. 返回 BlockVarScopedDeclarations
FunctionStatementList : [空]
  1. 返回一个新的空 列表
FunctionStatementList : StatementList
  1. 返回 StatementListTopLevelVarScopedDeclarations
ClassStaticBlockStatementList : [空]
  1. 返回一个新的空 列表
ClassStaticBlockStatementList : StatementList
  1. 返回 StatementListTopLevelVarScopedDeclarations
ConciseBody : ExpressionBody
  1. 返回一个新的空 列表
AsyncConciseBody : ExpressionBody
  1. 返回一个新的空 列表
Script : [空]
  1. 返回一个新的空 列表
ScriptBody : StatementList
  1. 返回 StatementListTopLevelVarScopedDeclarations
Module : [空]
  1. 返回一个新的空 列表
ModuleItemList : ModuleItemList ModuleItem
  1. declarations1ModuleItemListVarScopedDeclarations
  2. declarations2ModuleItemVarScopedDeclarations
  3. 返回 declarations1declarations2列表连接
ModuleItem : ImportDeclaration
  1. 返回一个新的空 列表
ModuleItem : ExportDeclaration
  1. 如果 ExportDeclarationexport VariableStatement,返回 VariableStatementVarScopedDeclarations
  2. 返回一个新的空 列表

8.2.8 静态语义:TopLevelLexicallyDeclaredNames

语法导向操作 TopLevelLexicallyDeclaredNames 不接受参数并返回一个字符串的 列表。它在以下产生式上分段定义:

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

在函数或脚本的顶层,函数声明被当作 var 声明处理,而不是词法声明。

8.2.9 静态语义:TopLevelLexicallyScopedDeclarations

语法导向操作 TopLevelLexicallyScopedDeclarations 不接受参数并返回一个 解析节点列表。它在以下产生式上分段定义:

StatementList : StatementList StatementListItem
  1. declarations1StatementListTopLevelLexicallyScopedDeclarations
  2. declarations2StatementListItemTopLevelLexicallyScopedDeclarations
  3. 返回 declarations1declarations2列表连接
StatementListItem : Statement
  1. 返回一个新的空 列表
StatementListItem : Declaration
  1. 如果 Declaration Declaration : HoistableDeclaration ,那么
    1. 返回一个新的空 列表
  2. 返回 « Declaration »。

8.2.10 静态语义:TopLevelVarDeclaredNames

语法导向操作 TopLevelVarDeclaredNames 不接受参数并返回一个字符串的 列表。它在以下产生式上分段定义:

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

在函数或脚本的顶层,内部函数声明被当作 var 声明处理。

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

8.2.11 静态语义:TopLevelVarScopedDeclarations

语法导向操作 TopLevelVarScopedDeclarations 不接受参数并返回一个 解析节点列表。它在以下产生式上分段定义:

StatementList : StatementList StatementListItem
  1. declarations1StatementListTopLevelVarScopedDeclarations
  2. declarations2StatementListItemTopLevelVarScopedDeclarations
  3. 返回 declarations1declarations2列表连接
StatementListItem : Statement
  1. 如果 Statement Statement : LabelledStatement ,返回 StatementTopLevelVarScopedDeclarations
  2. 返回 StatementVarScopedDeclarations
StatementListItem : Declaration
  1. 如果 Declaration Declaration : HoistableDeclaration ,那么
    1. declarationHoistableDeclarationDeclarationPart
    2. 返回 « declaration »。
  2. 返回一个新的空 列表
LabelledStatement : LabelIdentifier : LabelledItem
  1. 返回 LabelledItemTopLevelVarScopedDeclarations
LabelledItem : Statement
  1. 如果 Statement Statement : LabelledStatement ,返回 StatementTopLevelVarScopedDeclarations
  2. 返回 StatementVarScopedDeclarations
LabelledItem : FunctionDeclaration
  1. 返回 « FunctionDeclaration »。

8.3 标签

8.3.1 静态语义:ContainsDuplicateLabels

语法导向操作 ContainsDuplicateLabels 接受参数 labelSet(一个字符串的 列表)并返回一个布尔值。它在以下产生式上分段定义:

Statement : VariableStatement EmptyStatement ExpressionStatement ContinueStatement BreakStatement ReturnStatement ThrowStatement DebuggerStatement Block : { } StatementListItem : Declaration
  1. 返回 false
StatementList : StatementList StatementListItem
  1. hasDuplicates 为以参数 labelSet 调用 StatementListContainsDuplicateLabels
  2. 如果 hasDuplicatestrue,返回 true
  3. 返回以参数 labelSet 调用 StatementListItemContainsDuplicateLabels
IfStatement : if ( Expression ) Statement else Statement
  1. hasDuplicate 为以参数 labelSet 调用第一个 StatementContainsDuplicateLabels
  2. 如果 hasDuplicatetrue,返回 true
  3. 返回以参数 labelSet 调用第二个 StatementContainsDuplicateLabels
IfStatement : if ( Expression ) Statement
  1. 返回以参数 labelSet 调用 StatementContainsDuplicateLabels
DoWhileStatement : do Statement while ( Expression ) ;
  1. 返回以参数 labelSet 调用 StatementContainsDuplicateLabels
WhileStatement : while ( Expression ) Statement
  1. 返回以参数 labelSet 调用 StatementContainsDuplicateLabels
ForStatement : for ( Expressionopt ; Expressionopt ; Expressionopt ) Statement for ( var VariableDeclarationList ; Expressionopt ; Expressionopt ) Statement for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement
  1. 返回以参数 labelSet 调用 StatementContainsDuplicateLabels
ForInOfStatement : for ( LeftHandSideExpression in Expression ) Statement for ( var ForBinding in Expression ) Statement for ( ForDeclaration in Expression ) Statement for ( LeftHandSideExpression of AssignmentExpression ) Statement for ( var ForBinding of AssignmentExpression ) Statement for ( ForDeclaration of AssignmentExpression ) Statement for await ( LeftHandSideExpression of AssignmentExpression ) Statement for await ( var ForBinding of AssignmentExpression ) Statement for await ( ForDeclaration of AssignmentExpression ) Statement
  1. 返回以参数 labelSet 调用 StatementContainsDuplicateLabels
注意

此部分由附录 B.3.5 扩展。

WithStatement : with ( Expression ) Statement
  1. 返回以参数 labelSet 调用 StatementContainsDuplicateLabels
SwitchStatement : switch ( Expression ) CaseBlock
  1. 返回以参数 labelSet 调用 CaseBlockContainsDuplicateLabels
CaseBlock : { }
  1. 返回 false
CaseBlock : { CaseClausesopt DefaultClause CaseClausesopt }
  1. 如果第一个 CaseClauses 存在,那么
    1. 如果以参数 labelSet 调用第一个 CaseClausesContainsDuplicateLabelstrue,返回 true
  2. 如果以参数 labelSet 调用 DefaultClauseContainsDuplicateLabelstrue,返回 true
  3. 如果第二个 CaseClauses 不存在,返回 false
  4. 返回以参数 labelSet 调用第二个 CaseClausesContainsDuplicateLabels
CaseClauses : CaseClauses CaseClause
  1. hasDuplicates 为以参数 labelSet 调用 CaseClausesContainsDuplicateLabels
  2. 如果 hasDuplicatestrue,返回 true
  3. 返回以参数 labelSet 调用 CaseClauseContainsDuplicateLabels
CaseClause : case Expression : StatementListopt
  1. 如果 StatementList 存在,返回以参数 labelSet 调用 StatementListContainsDuplicateLabels
  2. 返回 false
DefaultClause : default : StatementListopt
  1. 如果 StatementList 存在,返回以参数 labelSet 调用 StatementListContainsDuplicateLabels
  2. 返回 false
LabelledStatement : LabelIdentifier : LabelledItem
  1. labelLabelIdentifierStringValue
  2. 如果 labelSet 包含 label,返回 true
  3. newLabelSetlabelSet 和 « label » 的 列表连接
  4. 返回以参数 newLabelSet 调用 LabelledItemContainsDuplicateLabels
LabelledItem : FunctionDeclaration
  1. 返回 false
TryStatement : try Block Catch
  1. hasDuplicates 为以参数 labelSet 调用 BlockContainsDuplicateLabels
  2. 如果 hasDuplicatestrue,返回 true
  3. 返回以参数 labelSet 调用 CatchContainsDuplicateLabels
TryStatement : try Block Finally
  1. hasDuplicates 为以参数 labelSet 调用 BlockContainsDuplicateLabels
  2. 如果 hasDuplicatestrue,返回 true
  3. 返回以参数 labelSet 调用 FinallyContainsDuplicateLabels
TryStatement : try Block Catch Finally
  1. 如果以参数 labelSet 调用 BlockContainsDuplicateLabelstrue,返回 true
  2. 如果以参数 labelSet 调用 CatchContainsDuplicateLabelstrue,返回 true
  3. 返回以参数 labelSet 调用 FinallyContainsDuplicateLabels
Catch : catch ( CatchParameter ) Block
  1. 返回以参数 labelSet 调用 BlockContainsDuplicateLabels
FunctionStatementList : [空]
  1. 返回 false
ClassStaticBlockStatementList : [空]
  1. 返回 false
ModuleItemList : ModuleItemList ModuleItem
  1. hasDuplicates 为以参数 labelSet 调用 ModuleItemListContainsDuplicateLabels
  2. 如果 hasDuplicatestrue,返回 true
  3. 返回以参数 labelSet 调用 ModuleItemContainsDuplicateLabels
ModuleItem : ImportDeclaration ExportDeclaration
  1. 返回 false

8.3.2 静态语义:ContainsUndefinedBreakTarget

语法导向操作 ContainsUndefinedBreakTarget 接受参数 labelSet (一个字符串的 列表)并返回一个布尔值。它在以下产生式上分段定义:

Statement : VariableStatement EmptyStatement ExpressionStatement ContinueStatement ReturnStatement ThrowStatement DebuggerStatement Block : { } StatementListItem : Declaration
  1. 返回 false
StatementList : StatementList StatementListItem
  1. hasUndefinedLabels 为以参数 labelSet 调用 StatementListContainsUndefinedBreakTarget
  2. 如果 hasUndefinedLabelstrue,返回 true
  3. 返回以参数 labelSet 调用 StatementListItemContainsUndefinedBreakTarget
IfStatement : if ( Expression ) Statement else Statement
  1. hasUndefinedLabels 为以参数 labelSet 调用第一个 StatementContainsUndefinedBreakTarget
  2. 如果 hasUndefinedLabelstrue,返回 true
  3. 返回以参数 labelSet 调用第二个 StatementContainsUndefinedBreakTarget
IfStatement : if ( Expression ) Statement
  1. 返回以参数 labelSet 调用 StatementContainsUndefinedBreakTarget
DoWhileStatement : do Statement while ( Expression ) ;
  1. 返回以参数 labelSet 调用 StatementContainsUndefinedBreakTarget
WhileStatement : while ( Expression ) Statement
  1. 返回以参数 labelSet 调用 StatementContainsUndefinedBreakTarget
ForStatement : for ( Expressionopt ; Expressionopt ; Expressionopt ) Statement for ( var VariableDeclarationList ; Expressionopt ; Expressionopt ) Statement for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement
  1. 返回以参数 labelSet 调用 StatementContainsUndefinedBreakTarget
ForInOfStatement : for ( LeftHandSideExpression in Expression ) Statement for ( var ForBinding in Expression ) Statement for ( ForDeclaration in Expression ) Statement for ( LeftHandSideExpression of AssignmentExpression ) Statement for ( var ForBinding of AssignmentExpression ) Statement for ( ForDeclaration of AssignmentExpression ) Statement for await ( LeftHandSideExpression of AssignmentExpression ) Statement for await ( var ForBinding of AssignmentExpression ) Statement for await ( ForDeclaration of AssignmentExpression ) Statement
  1. 返回以参数 labelSet 调用 StatementContainsUndefinedBreakTarget

本节由附录 B.3.5 扩展。

BreakStatement : break ;
  1. 返回 false
BreakStatement : break LabelIdentifier ;
  1. 如果 labelSet 不包含 LabelIdentifierStringValue,返回 true
  2. 返回 false
WithStatement : with ( Expression ) Statement
  1. 返回以参数 labelSet 调用 StatementContainsUndefinedBreakTarget
SwitchStatement : switch ( Expression ) CaseBlock
  1. 返回以参数 labelSet 调用 CaseBlockContainsUndefinedBreakTarget
CaseBlock : { }
  1. 返回 false
CaseBlock : { CaseClausesopt DefaultClause CaseClausesopt }
  1. 如果第一个 CaseClauses 存在,那么
    1. 如果以参数 labelSet 调用第一个 CaseClausesContainsUndefinedBreakTargettrue,返回 true
  2. 如果以参数 labelSet 调用 DefaultClauseContainsUndefinedBreakTargettrue,返回 true
  3. 如果第二个 CaseClauses 不存在,返回 false
  4. 返回以参数 labelSet 调用第二个 CaseClausesContainsUndefinedBreakTarget
CaseClauses : CaseClauses CaseClause
  1. hasUndefinedLabels 为以参数 labelSet 调用 CaseClausesContainsUndefinedBreakTarget
  2. 如果 hasUndefinedLabelstrue,返回 true
  3. 返回以参数 labelSet 调用 CaseClauseContainsUndefinedBreakTarget
CaseClause : case Expression : StatementListopt
  1. 如果 StatementList 存在,返回以参数 labelSet 调用 StatementListContainsUndefinedBreakTarget
  2. 返回 false
DefaultClause : default : StatementListopt
  1. 如果 StatementList 存在,返回以参数 labelSet 调用 StatementListContainsUndefinedBreakTarget
  2. 返回 false
LabelledStatement : LabelIdentifier : LabelledItem
  1. labelLabelIdentifierStringValue
  2. newLabelSetlabelSet 和 « label » 的 列表连接
  3. 返回以参数 newLabelSet 调用 LabelledItemContainsUndefinedBreakTarget
LabelledItem : FunctionDeclaration
  1. 返回 false
TryStatement : try Block Catch
  1. hasUndefinedLabels 为以参数 labelSet 调用 BlockContainsUndefinedBreakTarget
  2. 如果 hasUndefinedLabelstrue,返回 true
  3. 返回以参数 labelSet 调用 CatchContainsUndefinedBreakTarget
TryStatement : try Block Finally
  1. hasUndefinedLabels 为以参数 labelSet 调用 BlockContainsUndefinedBreakTarget
  2. 如果 hasUndefinedLabelstrue,返回 true
  3. 返回以参数 labelSet 调用 FinallyContainsUndefinedBreakTarget
TryStatement : try Block Catch Finally
  1. 如果以参数 labelSet 调用 BlockContainsUndefinedBreakTargettrue,返回 true
  2. 如果以参数 labelSet 调用 CatchContainsUndefinedBreakTargettrue,返回 true
  3. 返回以参数 labelSet 调用 FinallyContainsUndefinedBreakTarget
Catch : catch ( CatchParameter ) Block
  1. 返回以参数 labelSet 调用 BlockContainsUndefinedBreakTarget
FunctionStatementList : [empty]
  1. 返回 false
ClassStaticBlockStatementList : [empty]
  1. 返回 false
ModuleItemList : ModuleItemList ModuleItem
  1. hasUndefinedLabels 为以参数 labelSet 调用 ModuleItemListContainsUndefinedBreakTarget
  2. 如果 hasUndefinedLabelstrue,返回 true
  3. 返回以参数 labelSet 调用 ModuleItemContainsUndefinedBreakTarget
ModuleItem : ImportDeclaration ExportDeclaration
  1. 返回 false

8.3.3 静态语义:ContainsUndefinedContinueTarget

语法导向操作 ContainsUndefinedContinueTarget 接受参数 iterationSet(一个字符串的 列表)和 labelSet(一个字符串的 列表)并返回一个布尔值。它在以下产生式上分段定义:

Statement : VariableStatement EmptyStatement ExpressionStatement BreakStatement ReturnStatement ThrowStatement DebuggerStatement Block : { } StatementListItem : Declaration
  1. 返回 false
Statement : BlockStatement
  1. 返回以参数 iterationSet 和 « » 调用 BlockStatementContainsUndefinedContinueTarget
BreakableStatement : IterationStatement
  1. newIterationSetiterationSetlabelSet列表连接
  2. 返回以参数 newIterationSet 和 « » 调用 IterationStatementContainsUndefinedContinueTarget
StatementList : StatementList StatementListItem
  1. hasUndefinedLabels 为以参数 iterationSet 和 « » 调用 StatementListContainsUndefinedContinueTarget
  2. 如果 hasUndefinedLabelstrue,返回 true
  3. 返回以参数 iterationSet 和 « » 调用 StatementListItemContainsUndefinedContinueTarget
IfStatement : if ( Expression ) Statement else Statement
  1. hasUndefinedLabels 为以参数 iterationSet 和 « » 调用第一个 StatementContainsUndefinedContinueTarget
  2. 如果 hasUndefinedLabelstrue,返回 true
  3. 返回以参数 iterationSet 和 « » 调用第二个 StatementContainsUndefinedContinueTarget
IfStatement : if ( Expression ) Statement
  1. 返回以参数 iterationSet 和 « » 调用 StatementContainsUndefinedContinueTarget
DoWhileStatement : do Statement while ( Expression ) ;
  1. 返回以参数 iterationSet 和 « » 调用 StatementContainsUndefinedContinueTarget
WhileStatement : while ( Expression ) Statement
  1. 返回以参数 iterationSet 和 « » 调用 StatementContainsUndefinedContinueTarget
ForStatement : for ( Expressionopt ; Expressionopt ; Expressionopt ) Statement for ( var VariableDeclarationList ; Expressionopt ; Expressionopt ) Statement for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement
  1. 返回以参数 iterationSet 和 « » 调用 StatementContainsUndefinedContinueTarget
ForInOfStatement : for ( LeftHandSideExpression in Expression ) Statement for ( var ForBinding in Expression ) Statement for ( ForDeclaration in Expression ) Statement for ( LeftHandSideExpression of AssignmentExpression ) Statement for ( var ForBinding of AssignmentExpression ) Statement for ( ForDeclaration of AssignmentExpression ) Statement for await ( LeftHandSideExpression of AssignmentExpression ) Statement for await ( var ForBinding of AssignmentExpression ) Statement for await ( ForDeclaration of AssignmentExpression ) Statement
  1. 返回以参数 iterationSet 和 « » 调用 StatementContainsUndefinedContinueTarget

本节由附录 B.3.5 扩展。

ContinueStatement : continue ;
  1. 返回 false
ContinueStatement : continue LabelIdentifier ;
  1. 如果 iterationSet 不包含 LabelIdentifierStringValue,返回 true
  2. 返回 false
WithStatement : with ( Expression ) Statement
  1. 返回以参数 iterationSet 和 « » 调用 StatementContainsUndefinedContinueTarget
SwitchStatement : switch ( Expression ) CaseBlock
  1. 返回以参数 iterationSet 和 « » 调用 CaseBlockContainsUndefinedContinueTarget
CaseBlock : { }
  1. 返回 false
CaseBlock : { CaseClausesopt DefaultClause CaseClausesopt }
  1. 如果第一个 CaseClauses 存在,那么
    1. 如果以参数 iterationSet 和 « » 调用第一个 CaseClausesContainsUndefinedContinueTargettrue,返回 true
  2. 如果以参数 iterationSet 和 « » 调用 DefaultClauseContainsUndefinedContinueTargettrue,返回 true
  3. 如果第二个 CaseClauses 不存在,返回 false
  4. 返回以参数 iterationSet 和 « » 调用第二个 CaseClausesContainsUndefinedContinueTarget
CaseClauses : CaseClauses CaseClause
  1. hasUndefinedLabels 为以参数 iterationSet 和 « » 调用 CaseClausesContainsUndefinedContinueTarget
  2. 如果 hasUndefinedLabelstrue,返回 true
  3. 返回以参数 iterationSet 和 « » 调用 CaseClauseContainsUndefinedContinueTarget
CaseClause : case Expression : StatementListopt
  1. 如果 StatementList 存在,返回以参数 iterationSet 和 « » 调用 StatementListContainsUndefinedContinueTarget
  2. 返回 false
DefaultClause : default : StatementListopt
  1. 如果 StatementList 存在,返回以参数 iterationSet 和 « » 调用 StatementListContainsUndefinedContinueTarget
  2. 返回 false
LabelledStatement : LabelIdentifier : LabelledItem
  1. labelLabelIdentifierStringValue
  2. newLabelSetlabelSet 和 « label » 的 列表连接
  3. 返回以参数 iterationSetnewLabelSet 调用 LabelledItemContainsUndefinedContinueTarget
LabelledItem : FunctionDeclaration
  1. 返回 false
TryStatement : try Block Catch
  1. hasUndefinedLabels 为以参数 iterationSet 和 « » 调用 BlockContainsUndefinedContinueTarget
  2. 如果 hasUndefinedLabelstrue,返回 true
  3. 返回以参数 iterationSet 和 « » 调用 CatchContainsUndefinedContinueTarget
TryStatement : try Block Finally
  1. hasUndefinedLabels 为以参数 iterationSet 和 « » 调用 BlockContainsUndefinedContinueTarget
  2. 如果 hasUndefinedLabelstrue,返回 true
  3. 返回以参数 iterationSet 和 « » 调用 FinallyContainsUndefinedContinueTarget
TryStatement : try Block Catch Finally
  1. 如果以参数 iterationSet 和 « » 调用 BlockContainsUndefinedContinueTargettrue,返回 true
  2. 如果以参数 iterationSet 和 « » 调用 CatchContainsUndefinedContinueTargettrue,返回 true
  3. 返回以参数 iterationSet 和 « » 调用 FinallyContainsUndefinedContinueTarget
Catch : catch ( CatchParameter ) Block
  1. 返回以参数 iterationSet 和 « » 调用 BlockContainsUndefinedContinueTarget
FunctionStatementList : [empty]
  1. 返回 false
ClassStaticBlockStatementList : [empty]
  1. 返回 false
ModuleItemList : ModuleItemList ModuleItem
  1. hasUndefinedLabels 为以参数 iterationSet 和 « » 调用 ModuleItemListContainsUndefinedContinueTarget
  2. 如果 hasUndefinedLabelstrue,返回 true
  3. 返回以参数 iterationSet 和 « » 调用 ModuleItemContainsUndefinedContinueTarget
ModuleItem : ImportDeclaration ExportDeclaration
  1. 返回 false

8.4 函数名推断

8.4.1 静态语义:HasName

语法导向操作 HasName 不接受任何参数并返回一个布尔值。它在以下产生式上分段定义:

PrimaryExpression : CoverParenthesizedExpressionAndArrowParameterList
  1. expr 为被 CoverParenthesizedExpressionAndArrowParameterList 覆盖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 静态语义:IsFunctionDefinition

语法导向操作 IsFunctionDefinition 不接受任何参数并返回一个布尔值。它在以下产生式上分段定义:

PrimaryExpression : CoverParenthesizedExpressionAndArrowParameterList
  1. expr 为被 CoverParenthesizedExpressionAndArrowParameterList 覆盖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 AwaitExpression 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 静态语义:IsAnonymousFunctionDefinition ( expr )

抽象操作 IsAnonymousFunctionDefinition 接受参数 expr(一个 AssignmentExpression 解析节点、一个 Initializer 解析节点,或一个 Expression 解析节点)并返回一个布尔值。它确定其参数是否为不绑定名称的函数定义。当被调用时执行以下步骤:

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

8.4.4 静态语义:IsIdentifierRef

语法导向操作 IsIdentifierRef 不接受任何参数并返回一个布尔值。它在以下产生式上分段定义:

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 运行时语义:NamedEvaluation

语法导向操作 NamedEvaluation 接受参数 name(一个 属性键或一个 私有名称)并返回要么 包含 函数对象的正常完成,要么 中断完成。它在以下产生式上分段定义:

PrimaryExpression : CoverParenthesizedExpressionAndArrowParameterList
  1. expr 为被 CoverParenthesizedExpressionAndArrowParameterList 覆盖ParenthesizedExpression
  2. 返回 ? expr 以参数 name 执行的 NamedEvaluation
ParenthesizedExpression : ( Expression )
  1. 断言IsAnonymousFunctionDefinition(Expression) 是 true
  2. 返回 ? Expression 以参数 name 执行的 NamedEvaluation
FunctionExpression : function ( FormalParameters ) { FunctionBody }
  1. 返回 FunctionExpression 以参数 name 执行的 InstantiateOrdinaryFunctionExpression
GeneratorExpression : function * ( FormalParameters ) { GeneratorBody }
  1. 返回 GeneratorExpression 以参数 name 执行的 InstantiateGeneratorFunctionExpression
AsyncGeneratorExpression : async function * ( FormalParameters ) { AsyncGeneratorBody }
  1. 返回 AsyncGeneratorExpression 以参数 name 执行的 InstantiateAsyncGeneratorFunctionExpression
AsyncFunctionExpression : async function ( FormalParameters ) { AsyncFunctionBody }
  1. 返回 AsyncFunctionExpression 以参数 name 执行的 InstantiateAsyncFunctionExpression
ArrowFunction : ArrowParameters => ConciseBody
  1. 返回 ArrowFunction 以参数 name 执行的 InstantiateArrowFunctionExpression
AsyncArrowFunction : async AsyncArrowBindingIdentifier => AsyncConciseBody CoverCallExpressionAndAsyncArrowHead => AsyncConciseBody
  1. 返回 AsyncArrowFunction 以参数 name 执行的 InstantiateAsyncArrowFunctionExpression
ClassExpression : class ClassTail
  1. value 为 ? ClassTail 以参数 undefinedname 执行的 ClassDefinitionEvaluation
  2. 设置 value.[[SourceText]]ClassExpression 匹配的源文本
  3. 返回 value

8.5 包含 (Contains)

8.5.1 静态语义:包含 (Contains)

语法导向操作 包含 (Contains) 接受参数 symbol (一个语法符号) 并返回一个布尔值。

本规范中所有未在下面列出的语法产生式备选都隐式具有以下 包含 (Contains) 的默认定义:

  1. 对于此 解析节点 的每个子节点 child,执行:
    1. 如果 childsymbol 的实例,返回 true
    2. 如果 child 是一个非终结符的实例,则:
      1. containedchild 包含 symbol 的结果。
      2. 如果 containedtrue,返回 true
  2. 返回 false
函数声明 : function 绑定标识符 ( 形式参数 ) { 函数体 } function ( 形式参数 ) { 函数体 } 函数表达式 : function 绑定标识符opt ( 形式参数 ) { 函数体 } 生成器声明 : function * 绑定标识符 ( 形式参数 ) { 生成器体 } function * ( 形式参数 ) { 生成器体 } 生成器表达式 : function * 绑定标识符opt ( 形式参数 ) { 生成器体 } 异步生成器声明 : async function * 绑定标识符 ( 形式参数 ) { 异步生成器体 } async function * ( 形式参数 ) { 异步生成器体 } 异步生成器表达式 : async function * 绑定标识符opt ( 形式参数 ) { 异步生成器体 } 异步函数声明 : async function 绑定标识符 ( 形式参数 ) { 异步函数体 } async function ( 形式参数 ) { 异步函数体 } 异步函数表达式 : async function 绑定标识符opt ( 形式参数 ) { 异步函数体 }
  1. 返回 false
注 1

依赖于子结构的静态语义规则通常不深入函数定义。

类尾 : 类继承opt { 类体 }
  1. 如果 symbol类体,返回 true
  2. 如果 symbol类继承,则:
    1. 如果 类继承 存在,返回 true;否则返回 false
  3. 如果 类继承 存在,则:
    1. 如果 类继承 包含 symboltrue,返回 true
  4. 返回以 symbol 为参数的 类体计算属性包含 的结果。
注 2

依赖于子结构的静态语义规则通常不深入类体,除了 属性名

类静态块 : static { 类静态块体 }
  1. 返回 false
注 3

依赖于子结构的静态语义规则通常不深入 static 初始化块。

箭头函数 : 箭头参数 => 简洁体
  1. 如果 symbol 不是 NewTargetSuperPropertySuperCallsuperthis 之一,返回 false
  2. 如果 箭头参数 包含 symboltrue,返回 true
  3. 返回 简洁体 包含 symbol
箭头参数 : 覆盖带括号的表达式和箭头参数列表
  1. formals 为被 覆盖带括号的表达式和箭头参数列表 覆盖箭头形式参数
  2. 返回 formals 包含 symbol
异步箭头函数 : async 异步箭头绑定标识符 => 异步简洁体
  1. 如果 symbol 不是 NewTargetSuperPropertySuperCallsuperthis 之一,返回 false
  2. 返回 异步简洁体 包含 symbol
异步箭头函数 : 覆盖调用表达式和异步箭头头部 => 异步简洁体
  1. 如果 symbol 不是 NewTargetSuperPropertySuperCallsuperthis 之一,返回 false
  2. head 为被 覆盖调用表达式和异步箭头头部 覆盖异步箭头头部
  3. 如果 head 包含 symboltrue,返回 true
  4. 返回 异步简洁体 包含 symbol
注 4

包含 (Contains) 用于检测 箭头函数异步箭头函数new.targetthissuper 的使用情况。

属性定义 : 方法定义
  1. 如果 symbol方法定义,返回 true
  2. 返回以 symbol 为参数的 方法定义计算属性包含 的结果。
字面量属性名 : 标识符名称
  1. 返回 false
成员表达式 : 成员表达式 . 标识符名称
  1. 如果 成员表达式 包含 symboltrue,返回 true
  2. 返回 false
Super属性 : super . 标识符名称
  1. 如果 symbol保留字 super,返回 true
  2. 返回 false
调用表达式 : 调用表达式 . 标识符名称
  1. 如果 调用表达式 包含 symboltrue,返回 true
  2. 返回 false
可选链 : ?. 标识符名称
  1. 返回 false
可选链 : 可选链 . 标识符名称
  1. 如果 可选链 包含 symboltrue,返回 true
  2. 返回 false

8.5.2 静态语义:计算属性包含 (ComputedPropertyContains)

语法导向操作 计算属性包含 (ComputedPropertyContains) 接受参数 symbol (一个语法符号) 并返回一个布尔值。它在以下产生式中分段定义:

类元素名称 : 私有标识符 属性名 : 字面量属性名
  1. 返回 false
属性名 : 计算属性名
  1. 返回 计算属性名 包含 symbol 的结果。
方法定义 : 类元素名称 ( 唯一形式参数 ) { 函数体 } get 类元素名称 ( ) { 函数体 } set 类元素名称 ( 属性设置器参数列表 ) { 函数体 }
  1. 返回以 symbol 为参数的 类元素名称计算属性包含 的结果。
生成器方法 : * 类元素名称 ( 唯一形式参数 ) { 生成器体 }
  1. 返回以 symbol 为参数的 类元素名称计算属性包含 的结果。
异步生成器方法 : async * 类元素名称 ( 唯一形式参数 ) { 异步生成器体 }
  1. 返回以 symbol 为参数的 类元素名称计算属性包含 的结果。
类元素列表 : 类元素列表 类元素
  1. inList 为以 symbol 为参数的 类元素列表计算属性包含
  2. 如果 inListtrue,返回 true
  3. 返回以 symbol 为参数的 类元素计算属性包含 的结果。
类元素 : 类静态块
  1. 返回 false
类元素 : ;
  1. 返回 false
异步方法 : async 类元素名称 ( 唯一形式参数 ) { 异步函数体 }
  1. 返回以 symbol 为参数的 类元素名称计算属性包含 的结果。
字段定义 : 类元素名称 初始化器opt
  1. 返回以 symbol 为参数的 类元素名称计算属性包含 的结果。

8.6 杂项

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

8.6.1 运行时语义:InstantiateFunctionObject

语法导向操作 InstantiateFunctionObject 接收参数 env (一个 环境记录) 和 privateEnv (一个 私有环境记录null),并返回一个 ECMAScript 函数对象。它在以下产生式上分段定义:

FunctionDeclaration : function BindingIdentifier ( FormalParameters ) { FunctionBody } function ( FormalParameters ) { FunctionBody }
  1. 返回 InstantiateOrdinaryFunctionObject,其参数为 FunctionDeclaration,以及参数 envprivateEnv
GeneratorDeclaration : function * BindingIdentifier ( FormalParameters ) { GeneratorBody } function * ( FormalParameters ) { GeneratorBody }
  1. 返回 InstantiateGeneratorFunctionObject,其参数为 GeneratorDeclaration,以及参数 envprivateEnv
AsyncGeneratorDeclaration : async function * BindingIdentifier ( FormalParameters ) { AsyncGeneratorBody } async function * ( FormalParameters ) { AsyncGeneratorBody }
  1. 返回 InstantiateAsyncGeneratorFunctionObject,其参数为 AsyncGeneratorDeclaration,以及参数 envprivateEnv
AsyncFunctionDeclaration : async function BindingIdentifier ( FormalParameters ) { AsyncFunctionBody } async function ( FormalParameters ) { AsyncFunctionBody }
  1. 返回 InstantiateAsyncFunctionObject,其参数为 AsyncFunctionDeclaration,以及参数 envprivateEnv

8.6.2 运行时语义:BindingInitialization

语法导向操作 BindingInitialization 接受参数 value(一个 ECMAScript 语言值)和 environment(一个 环境记录undefined),并返回一个 包含 unused 的正常完成,或者一个 异常完成

注意

undefined 作为 environment 传递,以指示应使用 PutValue 操作来分配初始化值。对于 var 语句和某些 非严格函数 的形式参数列表(参见 10.2.11)就是这种情况。在这些情况下,词法绑定会在其初始化程序的评估之前被提升和预初始化。

它在以下产生式上分段定义:

BindingIdentifier : Identifier
  1. nameIdentifierStringValue
  2. 返回 ? InitializeBoundName(name, value, environment).
BindingIdentifier : yield
  1. 返回 ? InitializeBoundName("yield", value, environment).
BindingIdentifier : await
  1. 返回 ? InitializeBoundName("await", value, environment).
BindingPattern : ObjectBindingPattern
  1. 执行 ? RequireObjectCoercible(value).
  2. 返回 ? BindingInitialization(ObjectBindingPattern with arguments valueenvironment.
BindingPattern : ArrayBindingPattern
  1. iteratorRecord 为 ? GetIterator(value, sync).
  2. resultCompletion(IteratorBindingInitialization of ArrayBindingPattern with arguments iteratorRecordenvironment).
  3. 如果 iteratorRecord.[[Done]]false,则返回 ? IteratorClose(iteratorRecord, result).
  4. 返回 ? result.
ObjectBindingPattern : { }
  1. 返回 unused.
ObjectBindingPattern : { BindingPropertyList } { BindingPropertyList , }
  1. 执行 ? PropertyBindingInitialization(BindingPropertyList with arguments valueenvironment.
  2. 返回 unused.
ObjectBindingPattern : { BindingRestProperty }
  1. excludedNames 为一个新的空 列表
  2. 返回 ? RestBindingInitialization(BindingRestProperty with arguments value, environment, 和 excludedNames.
ObjectBindingPattern : { BindingPropertyList , BindingRestProperty }
  1. excludedNames 为 ? PropertyBindingInitialization(BindingPropertyList with arguments valueenvironment.
  2. 返回 ? RestBindingInitialization(BindingRestProperty with arguments value, environment, 和 excludedNames.

8.6.2.1 InitializeBoundName ( name, value, environment )

抽象操作 InitializeBoundName 接受参数 name(一个字符串)、value(一个 ECMAScript 语言值)和 environment(一个 环境记录undefined),并返回一个 包含 unused 的正常完成,或者一个 异常完成。调用时,它执行以下步骤:

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

8.6.3 运行时语义:IteratorBindingInitialization

语法导向操作 IteratorBindingInitialization 接受参数 iteratorRecord(一个迭代器记录)和 environment (一个环境记录undefined),并返回包含 unused正常完成异常完成

environment 传递 undefined 时,表示应该使用PutValue 操作来分配初始化值。这是非严格函数的形式参数列表的情况。在这种情况下,形式参数绑定被预初始化,以处理具有相同名称的多个参数的可能性。

它在以下产生式上分段定义:

ArrayBindingPattern : [ ]
  1. 返回 unused
ArrayBindingPattern : [ Elision ]
  1. 返回 ? IteratorDestructuringAssignmentEvaluation of Elision with argument iteratorRecord
ArrayBindingPattern : [ Elisionopt BindingRestElement ]
  1. 如果 Elision 存在,则
    1. 执行 ? IteratorDestructuringAssignmentEvaluation of Elision with argument iteratorRecord
  2. 返回 ? IteratorBindingInitialization of BindingRestElement with arguments iteratorRecord and environment
ArrayBindingPattern : [ BindingElementList , Elision ]
  1. 执行 ? IteratorBindingInitialization of BindingElementList with arguments iteratorRecord and environment
  2. 返回 ? IteratorDestructuringAssignmentEvaluation of Elision with argument iteratorRecord
ArrayBindingPattern : [ BindingElementList , Elisionopt BindingRestElement ]
  1. 执行 ? IteratorBindingInitialization of BindingElementList with arguments iteratorRecord and environment
  2. 如果 Elision 存在,则
    1. 执行 ? IteratorDestructuringAssignmentEvaluation of Elision with argument iteratorRecord
  3. 返回 ? IteratorBindingInitialization of BindingRestElement with arguments iteratorRecord and environment
BindingElementList : BindingElementList , BindingElisionElement
  1. 执行 ? IteratorBindingInitialization of BindingElementList with arguments iteratorRecord and environment
  2. 返回 ? IteratorBindingInitialization of BindingElisionElement with arguments iteratorRecord and environment
BindingElisionElement : Elision BindingElement
  1. 执行 ? IteratorDestructuringAssignmentEvaluation of Elision with argument iteratorRecord
  2. 返回 ? IteratorBindingInitialization of BindingElement with arguments iteratorRecord and environment
SingleNameBinding : BindingIdentifier Initializeropt
  1. bindingIdBindingIdentifierStringValue
  2. lhs 为 ? ResolveBinding(bindingId, environment)。
  3. vundefined
  4. 如果 iteratorRecord.[[Done]]false,则
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 next 不是 done,则
      1. 设置 vnext
  5. 如果 Initializer 存在且 vundefined,则
    1. 如果 IsAnonymousFunctionDefinition(Initializer) 是 true,则
      1. 设置 v 为 ? NamedEvaluation of Initializer with argument bindingId
    2. 否则,
      1. defaultValue 为 ? Evaluation of Initializer
      2. 设置 v 为 ? GetValue(defaultValue)。
  6. 如果 environmentundefined,则返回 ? PutValue(lhs, v)。
  7. 返回 ? InitializeReferencedBinding(lhs, v)。
BindingElement : BindingPattern Initializeropt
  1. vundefined
  2. 如果 iteratorRecord.[[Done]]false,则
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 next 不是 done,则
      1. 设置 vnext
  3. 如果 Initializer 存在且 vundefined,则
    1. defaultValue 为 ? Evaluation of Initializer
    2. 设置 v 为 ? GetValue(defaultValue)。
  4. 返回 ? BindingInitialization of BindingPattern with arguments v and environment
BindingRestElement : ... BindingIdentifier
  1. lhs 为 ? ResolveBinding(BindingIdentifierStringValue, environment)。
  2. A 为 ! ArrayCreate(0)。
  3. n 为 0。
  4. 重复,
    1. nextdone
    2. 如果 iteratorRecord.[[Done]]false,则
      1. 设置 next 为 ? IteratorStepValue(iteratorRecord)。
    3. 如果 nextdone,则
      1. 如果 environmentundefined,则返回 ? PutValue(lhs, A)。
      2. 返回 ? InitializeReferencedBinding(lhs, A)。
    4. 执行 ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(n)), next)。
    5. 设置 nn + 1。
BindingRestElement : ... BindingPattern
  1. A 为 ! ArrayCreate(0)。
  2. n 为 0。
  3. 重复,
    1. nextdone
    2. 如果 iteratorRecord.[[Done]]false,则
      1. 设置 next 为 ? IteratorStepValue(iteratorRecord)。
    3. 如果 nextdone,则
      1. 返回 ? BindingInitialization of BindingPattern with arguments A and environment
    4. 执行 ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(n)), next)。
    5. 设置 nn + 1。
FormalParameters : [empty]
  1. 返回 unused
FormalParameters : FormalParameterList , FunctionRestParameter
  1. 执行 ? IteratorBindingInitialization of FormalParameterList with arguments iteratorRecord and environment
  2. 返回 ? IteratorBindingInitialization of FunctionRestParameter with arguments iteratorRecord and environment
FormalParameterList : FormalParameterList , FormalParameter
  1. 执行 ? IteratorBindingInitialization of FormalParameterList with arguments iteratorRecord and environment
  2. 返回 ? IteratorBindingInitialization of FormalParameter with arguments iteratorRecord and environment
ArrowParameters : BindingIdentifier
  1. vundefined
  2. 断言iteratorRecord.[[Done]]false
  3. next 为 ? IteratorStepValue(iteratorRecord)。
  4. 如果 next 不是 done,则
    1. 设置 vnext
  5. 返回 ? BindingInitialization of BindingIdentifier with arguments v and environment
ArrowParameters : CoverParenthesizedExpressionAndArrowParameterList
  1. formals 为被 CoverParenthesizedExpressionAndArrowParameterList 覆盖ArrowFormalParameters
  2. 返回 ? IteratorBindingInitialization of formals with arguments iteratorRecord and environment
AsyncArrowBindingIdentifier : BindingIdentifier
  1. vundefined
  2. 断言iteratorRecord.[[Done]]false
  3. next 为 ? IteratorStepValue(iteratorRecord)。
  4. 如果 next 不是 done,则
    1. 设置 vnext
  5. 返回 ? BindingInitialization of BindingIdentifier with arguments v and environment

8.6.4 静态语义:AssignmentTargetType

语法导向操作 AssignmentTargetType 不接受参数并返回 simpleinvalid。它在以下产生式上分段定义:

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. expr 为被 CoverParenthesizedExpressionAndArrowParameterList 覆盖ParenthesizedExpression
  2. 返回 exprAssignmentTargetType
PrimaryExpression : this Literal ArrayLiteral ObjectLiteral FunctionExpression ClassExpression GeneratorExpression AsyncFunctionExpression AsyncGeneratorExpression RegularExpressionLiteral TemplateLiteral CallExpression : CoverCallExpressionAndAsyncArrowHead SuperCall ImportCall CallExpression Arguments 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 AwaitExpression 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 静态语义:PropName

语法导向操作 PropName 不接受参数并返回一个字符串或 empty。它在以下产生式上分段定义:

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. nbrNumericLiteralNumericValue
  2. 返回 ! ToString(nbr)。
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

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

9.1 环境记录

环境记录是一种规范类型, 用于定义标识符与特定变量和函数的关联,基于 ECMAScript代码的词法嵌套结构。通常环境记录与ECMAScript代码的某些特定语法结构相关联, 如函数声明块语句try语句catch子句。每次求值这样的代码时, 都会创建一个新的环境记录来记录该代码创建的标识符绑定。

每个环境记录都有一个[[OuterEnv]]字段,它要么是 null,要么是对外部环境记录的引用。这用于建模环境记录值的逻辑嵌套。 (内部)环境记录的外部引用是对逻辑上围绕内部环境记录的环境记录的引用。 外部环境记录当然可能有自己的外部环境记录。一个环境记录可以作为多个内部环境记录的外部环境。 例如,如果一个函数声明 包含两个嵌套的函数声明, 那么每个嵌套函数的环境记录都将以周围函数的当前求值的环境记录作为其外部环境记录。

环境记录纯粹是规范机制,不需要对应于ECMAScript实现的任何特定构件。 ECMAScript程序不可能直接访问或操作这样的值。

9.1.1 环境记录类型层次结构

环境记录可以看作存在于一个简单的面向对象层次结构中, 其中环境记录是一个 抽象类,有三个具体子类:声明式环境记录对象环境记录全局环境记录函数环境记录模块环境记录声明式环境记录的子类。

环境记录抽象类 包含表16中定义的抽象规范方法。 这些抽象方法对于每个具体子类都有不同的具体算法。

表16:环境记录的抽象方法
方法 目的
HasBinding(N) 确定环境记录 是否具有字符串值N的绑定。如果有则返回 true,如果没有则返回false
CreateMutableBinding(N, D) 环境记录中 创建一个新的但未初始化的可变绑定。 字符串值N是绑定名称的文本。如果布尔参数Dtrue,则绑定可以随后被删除。
CreateImmutableBinding(N, S) 环境记录中 创建一个新的但未初始化的不可变绑定。 字符串值N是绑定名称的文本。如果Strue,那么在初始化后尝试设置它时 总是会抛出异常,无论引用该绑定的操作的严格模式设置如何。
InitializeBinding(N, V) 设置环境记录中 已存在但未初始化的绑定的值。 字符串值N是绑定名称的文本。V是 绑定的值,是任何ECMAScript语言类型的值。
SetMutableBinding(N, V, S) 设置环境记录中 已存在的可变绑定的值。 字符串值N是绑定名称的文本。V是 绑定的值,可能是任何ECMAScript语言类型的值。S是布尔值标志。如果Strue且绑定无法设置,则抛出 TypeError异常。
GetBindingValue(N, S) 环境记录返回 已存在绑定的值。 字符串值N是绑定名称的文本。S 用于标识源自严格模式代码或 其他需要严格模式引用语义的引用。如果Strue且绑定不存在,则抛出 ReferenceError异常。如果绑定存在但未初始化, 则抛出ReferenceError,无论S的值如何。
DeleteBinding(N) 环境记录删除绑定。字符串值N是 绑定名称的文本。如果N的绑定存在,则移除绑定并 返回true。如果绑定存在但无法移除, 则返回false。如果绑定不存在,则返回 true
HasThisBinding() 确定环境记录 是否建立this绑定。如果建立则返回true, 如果不建立则返回false
HasSuperBinding() 确定环境记录 是否建立super方法绑定。如果建立则返回 true,如果不建立则返回false。 如果返回true,则暗示环境记录函数环境记录, 但反向推导不成立。
WithBaseObject() 如果此环境记录with语句关联,则返回with对象。 否则,返回undefined

9.1.1.1 声明式环境记录

每个声明式环境记录都与包含变量、常量、let、类、模块、导入和/或函数声明的ECMAScript程序作用域相关联。声明式环境记录绑定其作用域内包含的声明所定义的标识符集合。

9.1.1.1.1 HasBinding ( N )

声明式环境记录 envRec的HasBinding具体方法接受参数N (字符串)并返回包含布尔值的正常完成。它确定参数标识符是否是记录绑定的标识符之一。调用时执行以下步骤:

  1. 如果envRec具有N的绑定,返回 true
  2. 返回false

9.1.1.1.2 CreateMutableBinding ( N, D )

声明式环境记录 envRec的CreateMutableBinding具体方法接受参数N(字符串) 和D(布尔值)并返回包含 unused正常完成。它为名称N创建一个新的未初始化的可变绑定。此环境记录中不得已存在N的绑定。如果Dtrue,则新绑定被标记为可删除的。调用时执行以下步骤:

  1. 断言envRec不已经具有N的绑定。
  2. envRec中为N创建可变绑定并记录它是未初始化的。如果Dtrue,记录新创建的绑定可以被后续的DeleteBinding调用删除。
  3. 返回unused

9.1.1.1.3 CreateImmutableBinding ( N, S )

声明式环境记录 envRec的CreateImmutableBinding具体方法接受参数N(字符串) 和S(布尔值)并返回包含 unused正常完成。它为名称N创建一个新的未初始化的不可变绑定。此环境记录中不得已存在N的绑定。如果Strue,则新绑定被标记为严格绑定。调用时执行以下步骤:

  1. 断言envRec不已经具有N的绑定。
  2. envRec中为N创建不可变绑定并记录它是未初始化的。如果Strue,记录新创建的绑定是严格绑定。
  3. 返回unused

9.1.1.1.4 InitializeBinding ( N, V )

声明式环境记录 envRec的InitializeBinding具体方法接受参数N(字符串) 和VECMAScript语言值) 并返回包含 unused正常完成。它用于将名称为N的标识符的当前绑定的绑定值设置为值VN的未初始化绑定必须已经存在。调用时执行以下步骤:

  1. 断言envRec必须具有N的未初始化绑定。
  2. envRecN的绑定值设置为V
  3. 记录envRecN的绑定已被初始化。
  4. 返回unused

9.1.1.1.5 SetMutableBinding ( N, V, S )

声明式环境记录 envRec的SetMutableBinding具体方法接受参数N(字符串)、 VECMAScript语言值) 和S(布尔值)并返回包含 unused正常完成抛出完成。它尝试将名称为N的标识符的当前绑定的绑定值更改为值VN的绑定通常已经存在,但在罕见情况下可能不存在。如果绑定是不可变绑定,当Strue时抛出TypeError。调用时执行以下步骤:

  1. 如果envRec没有N的绑定,则
    1. 如果Strue,抛出ReferenceError异常。
    2. 执行! envRec.CreateMutableBinding(N, true)。
    3. 执行! envRec.InitializeBinding(N, V)。
    4. 返回unused
  2. 如果envRecN的绑定是严格绑定,将S设置为true
  3. 如果envRecN的绑定尚未初始化,则
    1. 抛出ReferenceError异常。
  4. 否则如果envRecN的绑定是可变绑定,则
    1. 将其绑定值更改为V
  5. 否则,
    1. 断言:这是尝试更改不可变绑定的值。
    2. 如果Strue,抛出TypeError异常。
  6. 返回unused

导致步骤1缺失绑定的ECMAScript代码示例是:

function f() { eval("var x; x = (delete x, 0);"); }

9.1.1.1.6 GetBindingValue ( N, S )

声明式环境记录 envRec的GetBindingValue具体方法接受参数N(字符串) 和S(布尔值)并返回包含ECMAScript语言值正常完成抛出完成。它返回名称为N的绑定标识符的值。如果绑定存在但未初始化,则抛出ReferenceError,无论S的值如何。调用时执行以下步骤:

  1. 断言envRec具有N的绑定。
  2. 如果envRecN的绑定是未初始化绑定,抛出ReferenceError异常。
  3. 返回envRec中当前绑定到N的值。

9.1.1.1.7 DeleteBinding ( N )

声明式环境记录 envRec的DeleteBinding具体方法接受参数N(字符串) 并返回包含布尔值的正常完成。它只能删除已明确指定为可删除的绑定。调用时执行以下步骤:

  1. 断言envRec具有N的绑定。
  2. 如果envRecN的绑定无法删除,返回false
  3. envRec中移除N的绑定。
  4. 返回true

9.1.1.1.8 HasThisBinding ( )

声明式环境记录 envRec的HasThisBinding具体方法不接受参数并返回false。调用时执行以下步骤:

  1. 返回false

常规声明式环境记录(即既不是函数环境记录也不是模块环境记录的记录)不提供this绑定。

9.1.1.1.9 HasSuperBinding ( )

声明式环境记录 envRec的HasSuperBinding具体方法不接受参数并返回false。调用时执行以下步骤:

  1. 返回false

常规声明式环境记录(即既不是函数环境记录也不是模块环境记录的记录)不提供super绑定。

9.1.1.1.10 WithBaseObject ( )

声明式环境记录 envRec的WithBaseObject具体方法不接受参数并返回undefined。调用时执行以下步骤:

  1. 返回undefined

9.1.1.2 对象环境记录

每个对象环境记录 都与一个称为其绑定对象的对象相关联。对象环境记录绑定一组字符串标识符名称, 这些名称直接对应于其绑定对象的属性名称。不是标识符名称形式的字符串的属性键不包含在绑定标识符集合中。无论其[[Enumerable]]属性的设置如何,自有属性和继承属性都包含在集合中。由于属性可以动态地从对象中添加和删除,对象环境记录绑定的标识符集合可能会作为任何添加或删除属性操作的副作用而发生变化。作为这种副作用结果创建的任何绑定都被认为是可变绑定,即使相应属性的Writable属性是false。对象环境记录不存在不可变绑定。

with语句(14.11)创建的对象环境记录可以提供其绑定对象作为函数调用中使用的隐式this值。这种能力由布尔值[[IsWithEnvironment]]字段控制。

对象环境记录具有表17中列出的附加状态字段。

表17:对象环境记录的附加字段
字段名称 含义
[[BindingObject]] 一个对象 环境记录的绑定对象。
[[IsWithEnvironment]] 布尔值 指示此环境记录是否为with语句创建。

9.1.1.2.1 HasBinding ( N )

对象环境记录 envRec的HasBinding具体方法接受参数N(字符串) 并返回包含布尔值的正常完成抛出完成。它确定其关联的绑定对象是否具有名称为N的属性。调用时执行以下步骤:

  1. bindingObjectenvRec.[[BindingObject]]
  2. foundBinding为? HasProperty(bindingObject, N)。
  3. 如果foundBindingfalse,返回false
  4. 如果envRec.[[IsWithEnvironment]]false,返回true
  5. unscopables为? Get(bindingObject, %Symbol.unscopables%)。
  6. 如果unscopables是对象,则
    1. blockedToBoolean(? Get(unscopables, N))。
    2. 如果blockedtrue,返回false
  7. 返回true

9.1.1.2.2 CreateMutableBinding ( N, D )

对象环境记录 envRec的CreateMutableBinding具体方法接受参数N(字符串)和D(布尔值) 并返回包含 unused正常完成抛出完成。它在环境记录的关联绑定对象中创建一个名称为N的属性,并将其初始化为值undefined。如果Dtrue,新属性的[[Configurable]]属性设置为true;否则设置为false。调用时执行以下步骤:

  1. bindingObjectenvRec.[[BindingObject]]
  2. 执行? DefinePropertyOrThrow(bindingObject, N, PropertyDescriptor { [[Value]]: undefined, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: D })。
  3. 返回unused

通常envRec不会有N的绑定,但如果有,DefinePropertyOrThrow的语义可能导致现有绑定被替换或遮蔽,或导致返回异常完成

9.1.1.2.3 CreateImmutableBinding ( N, S )

对象环境记录的CreateImmutableBinding具体方法在本规范中从未使用。

9.1.1.2.4 InitializeBinding ( N, V )

对象环境记录 envRec的InitializeBinding具体方法接受参数N(字符串)和VECMAScript语言值) 并返回包含 unused正常完成抛出完成。它用于将名称为N的标识符的当前绑定的绑定值设置为值V。调用时执行以下步骤:

  1. 执行? envRec.SetMutableBinding(N, V, false)。
  2. 返回unused

在本规范中,对对象环境记录的CreateMutableBinding的所有使用之后都紧跟相同名称的InitializeBinding调用。因此,本规范不显式跟踪对象环境记录中绑定的初始化状态。

9.1.1.2.5 SetMutableBinding ( N, V, S )

对象环境记录 envRec的SetMutableBinding具体方法接受参数N(字符串)、VECMAScript语言值) 和S(布尔值)并返回包含 unused正常完成抛出完成。它尝试将环境记录关联绑定对象的名称为N的属性的值设置为值V。名称为N的属性通常已经存在,但如果不存在或当前不可写,错误处理由S确定。调用时执行以下步骤:

  1. bindingObjectenvRec.[[BindingObject]]
  2. stillExists为? HasProperty(bindingObject, N)。
  3. 如果stillExistsfalseStrue,抛出ReferenceError异常。
  4. 执行? Set(bindingObject, N, V, S)。
  5. 返回unused

9.1.1.2.6 GetBindingValue ( N, S )

对象环境记录 envRec的GetBindingValue具体方法接受参数N(字符串)和S(布尔值) 并返回包含ECMAScript语言值正常完成抛出完成。它返回其关联绑定对象的名称为N的属性的值。该属性应该已经存在,但如果不存在,结果取决于S。调用时执行以下步骤:

  1. bindingObjectenvRec.[[BindingObject]]
  2. value为? HasProperty(bindingObject, N)。
  3. 如果valuefalse,则
    1. 如果Sfalse,返回undefined;否则抛出ReferenceError异常。
  4. 返回? Get(bindingObject, N)。

9.1.1.2.7 DeleteBinding ( N )

对象环境记录 envRec的DeleteBinding具体方法接受参数N(字符串) 并返回包含布尔值的正常完成抛出完成。它只能删除对应于环境对象的[[Configurable]]属性值为true的属性的绑定。调用时执行以下步骤:

  1. bindingObjectenvRec.[[BindingObject]]
  2. 返回? bindingObject.[[Delete]](N)。

9.1.1.2.8 HasThisBinding ( )

对象环境记录 envRec的HasThisBinding具体方法不接受参数并返回false。调用时执行以下步骤:

  1. 返回false

对象环境记录不提供this绑定。

9.1.1.2.9 HasSuperBinding ( )

对象环境记录 envRec的HasSuperBinding具体方法不接受参数并返回false。调用时执行以下步骤:

  1. 返回false

对象环境记录不提供super绑定。

9.1.1.2.10 WithBaseObject ( )

对象环境记录 envRec的WithBaseObject具体方法不接受参数并返回对象或undefined。调用时执行以下步骤:

  1. 如果envRec.[[IsWithEnvironment]]true,返回envRec.[[BindingObject]]
  2. 否则,返回undefined

9.1.1.3 函数环境记录

函数环境记录是一个声明式环境记录,用于表示函数的顶层作用域,如果函数不是箭头函数,则提供this绑定。如果函数不是箭头函数并且引用super,其函数环境记录还包含用于在函数内执行super方法调用的状态。

函数环境记录具有表18中列出的附加状态字段。

表18:函数环境记录的附加字段
字段名称 含义
[[ThisValue]] 一个ECMAScript语言值 这是用于此函数调用的this值。
[[ThisBindingStatus]] lexicalinitializeduninitialized 如果值是lexical,这是一个箭头函数,不具有本地this值。
[[FunctionObject]] 一个ECMAScript函数对象 调用导致创建此环境记录函数对象
[[NewTarget]] 一个构造函数undefined 如果此环境记录[[Construct]]内部方法创建,[[NewTarget]][[Construct]]newTarget参数的值。否则,其值为undefined

函数环境记录支持表16中列出的所有声明式环境记录方法,除了HasThisBinding和HasSuperBinding,所有这些方法都共享相同的规范。此外,函数环境记录支持表19中列出的方法:

表19:函数环境记录的附加方法
方法 目的
GetThisBinding() 返回此环境记录this绑定的值。如果this绑定尚未初始化,则抛出ReferenceError

9.1.1.3.1 BindThisValue ( envRec, V )

抽象操作BindThisValue接受参数envRec(一个函数环境记录)和V(一个ECMAScript语言值) 并返回包含 unused正常完成抛出完成。它设置envRec.[[ThisValue]]并记录它已被初始化。调用时执行以下步骤:

  1. 断言envRec.[[ThisBindingStatus]]不是lexical
  2. 如果envRec.[[ThisBindingStatus]]initialized,抛出ReferenceError异常。
  3. 设置envRec.[[ThisValue]]V
  4. 设置envRec.[[ThisBindingStatus]]initialized
  5. 返回unused

9.1.1.3.2 HasThisBinding ( )

函数环境记录 envRec的HasThisBinding具体方法不接受参数并返回布尔值。调用时执行以下步骤:

  1. 如果envRec.[[ThisBindingStatus]]lexical,返回false;否则,返回true

9.1.1.3.3 HasSuperBinding ( )

函数环境记录 envRec的HasSuperBinding具体方法不接受参数并返回布尔值。调用时执行以下步骤:

  1. 如果envRec.[[ThisBindingStatus]]lexical,返回false
  2. 如果envRec.[[FunctionObject]].[[HomeObject]]undefined,返回false;否则,返回true

9.1.1.3.4 GetThisBinding ( )

函数环境记录 envRec的GetThisBinding具体方法不接受参数并返回包含ECMAScript语言值正常完成抛出完成。调用时执行以下步骤:

  1. 断言envRec.[[ThisBindingStatus]]不是lexical
  2. 如果envRec.[[ThisBindingStatus]]uninitialized,抛出ReferenceError异常。
  3. 返回envRec.[[ThisValue]]

9.1.1.3.5 GetSuperBase ( envRec )

抽象操作GetSuperBase接受参数envRec(一个函数环境记录)并返回对象、nullundefined。它返回作为envRec中绑定的super属性访问基础的对象。值undefined表示这种访问将产生运行时错误。调用时执行以下步骤:

  1. homeenvRec.[[FunctionObject]].[[HomeObject]]
  2. 如果homeundefined,返回undefined
  3. 断言home是一个普通对象
  4. 返回! home.[[GetPrototypeOf]]()。

9.1.1.4 全局环境记录

全局环境记录用于表示被在共同领域中处理的所有ECMAScript 脚本元素所共享的最外层作用域。全局环境记录为内置全局变量(第19章)、全局对象的属性以及在脚本中出现的所有顶级声明(8.2.98.2.11)提供绑定。

全局环境记录在逻辑上是单个记录,但它被指定为一个封装对象环境记录声明式环境记录的复合体。对象环境记录以关联领域记录全局对象为基础对象。这个全局对象是全局环境记录的GetThisBinding具体方法返回的值。全局环境记录的对象环境记录组件包含所有内置全局变量的绑定(第19章)以及由全局代码中的函数声明生成器声明异步函数声明异步生成器声明变量语句引入的所有绑定。全局代码中所有其他ECMAScript声明的绑定包含在全局环境记录的声明式环境记录组件中。

属性可以直接在全局对象上创建。因此,全局环境记录的对象环境记录组件可能包含由函数声明生成器声明异步函数声明异步生成器声明变量声明声明显式创建的绑定和作为全局对象属性隐式创建的绑定。为了识别哪些绑定是使用声明显式创建的,全局环境记录维护一个使用CreateGlobalVarBindingCreateGlobalFunctionBinding抽象操作绑定的名称列表。

全局环境记录具有表20中列出的附加字段和表21中列出的附加方法。

表20:全局环境记录的附加字段
字段名称 含义
[[ObjectRecord]] 一个对象环境记录 绑定对象是全局对象。它包含全局内置绑定以及关联领域的全局代码中的函数声明生成器声明异步函数声明异步生成器声明变量声明绑定。
[[GlobalThisValue]] 一个对象 在全局作用域中this返回的值。宿主可以提供任何ECMAScript对象值。
[[DeclarativeRecord]] 一个声明式环境记录 包含关联领域代码的全局代码中除函数声明生成器声明异步函数声明异步生成器声明变量声明绑定外的所有声明的绑定。
表21:全局环境记录的附加方法
方法 目的
GetThisBinding() 返回此环境记录this绑定的值。

9.1.1.4.1 HasBinding ( N )

全局环境记录 envRec的HasBinding具体方法接受参数N(字符串) 并返回包含布尔值的正常完成抛出完成。它确定参数标识符是否是记录绑定的标识符之一。调用时执行以下步骤:

  1. DclRecenvRec.[[DeclarativeRecord]]
  2. 如果! DclRec.HasBinding(N)是true, 返回true
  3. ObjRecenvRec.[[ObjectRecord]]
  4. 返回? ObjRec.HasBinding(N)。

9.1.1.4.2 CreateMutableBinding ( N, D )

全局环境记录 envRec的CreateMutableBinding具体方法接受参数N(字符串)和D(布尔值) 并返回包含 unused正常完成抛出完成。它为名称N创建一个新的未初始化的可变绑定。绑定在关联的声明式记录中创建。声明式记录中不得已存在N的绑定。如果Dtrue,则新绑定被标记为可删除的。调用时执行以下步骤:

  1. DclRecenvRec.[[DeclarativeRecord]]
  2. 如果! DclRec.HasBinding(N)是true, 抛出TypeError异常。
  3. 返回! DclRec.CreateMutableBinding(N, D)。

9.1.1.4.3 CreateImmutableBinding ( N, S )

全局环境记录 envRec的CreateImmutableBinding具体方法接受参数N(字符串)和S(布尔值) 并返回包含 unused正常完成抛出完成。它为名称N创建一个新的未初始化的不可变绑定。此环境记录中不得已存在N的绑定。如果Strue,则新绑定被标记为严格绑定。调用时执行以下步骤:

  1. DclRecenvRec.[[DeclarativeRecord]]
  2. 如果! DclRec.HasBinding(N)是true, 抛出TypeError异常。
  3. 返回! DclRec.CreateImmutableBinding(N, S)。

9.1.1.4.4 InitializeBinding ( N, V )

全局环境记录 envRec的InitializeBinding具体方法接受参数N(字符串)和VECMAScript语言值) 并返回包含 unused正常完成抛出完成。它用于将名称为N的标识符的当前绑定的绑定值设置为值VN的未初始化绑定必须已经存在。调用时执行以下步骤:

  1. DclRecenvRec.[[DeclarativeRecord]]
  2. 如果! DclRec.HasBinding(N)是true, 则
    1. 返回! DclRec.InitializeBinding(N, V)。
  3. 断言: 如果绑定存在,它必须在对象环境记录中。
  4. ObjRecenvRec.[[ObjectRecord]]
  5. 返回? ObjRec.InitializeBinding(N, V)。

9.1.1.4.5 SetMutableBinding ( N, V, S )

全局环境记录 envRec的SetMutableBinding具体方法接受参数N(字符串)、VECMAScript语言值) 和S(布尔值)并返回包含 unused正常完成抛出完成。它尝试将名称为N的标识符的当前绑定的绑定值更改为值V。如果绑定是不可变绑定且Strue,则抛出TypeError。名称为N的属性通常已经存在,但如果不存在或当前不可写,错误处理由S确定。调用时执行以下步骤:

  1. DclRecenvRec.[[DeclarativeRecord]]
  2. 如果! DclRec.HasBinding(N)是true, 则
    1. 返回? DclRec.SetMutableBinding(N, V, S)。
  3. ObjRecenvRec.[[ObjectRecord]]
  4. 返回? ObjRec.SetMutableBinding(N, V, S)。

9.1.1.4.6 GetBindingValue ( N, S )

全局环境记录 envRec的GetBindingValue具体方法接受参数N(字符串) 和S(布尔值)并返回包含ECMAScript语言值正常完成抛出完成。它返回名称为N的绑定标识符的值。如果绑定是未初始化绑定,则抛出ReferenceError异常。名称为N的属性通常已经存在,但如果不存在或当前不可写,错误处理由S确定。调用时执行以下步骤:

  1. DclRecenvRec.[[DeclarativeRecord]]
  2. 如果! DclRec.HasBinding(N)是true, 则
    1. 返回? DclRec.GetBindingValue(N, S)。
  3. ObjRecenvRec.[[ObjectRecord]]
  4. 返回? ObjRec.GetBindingValue(N, S)。

9.1.1.4.7 DeleteBinding ( N )

全局环境记录 envRec的DeleteBinding具体方法接受参数N(字符串) 并返回包含布尔值的正常完成抛出完成。它只能删除已明确指定为可删除的绑定。调用时执行以下步骤:

  1. DclRecenvRec.[[DeclarativeRecord]]
  2. 如果! DclRec.HasBinding(N)是true, 则
    1. 返回! DclRec.DeleteBinding(N)。
  3. ObjRecenvRec.[[ObjectRecord]]
  4. globalObjectObjRec.[[BindingObject]]
  5. existingProp为? HasOwnProperty(globalObject, N)。
  6. 如果existingProptrue,则
    1. 返回? ObjRec.DeleteBinding(N)。
  7. 返回true

9.1.1.4.8 HasThisBinding ( )

全局环境记录 envRec的HasThisBinding具体方法不接受参数并返回true。调用时执行以下步骤:

  1. 返回true

全局环境记录总是提供this绑定。

9.1.1.4.9 HasSuperBinding ( )

全局环境记录 envRec的HasSuperBinding具体方法不接受参数并返回false。调用时执行以下步骤:

  1. 返回false

全局环境记录不提供super绑定。

9.1.1.4.10 WithBaseObject ( )

全局环境记录 envRec的WithBaseObject具体方法不接受参数并返回undefined。调用时执行以下步骤:

  1. 返回undefined

9.1.1.4.11 GetThisBinding ( )

全局环境记录 envRec的GetThisBinding具体方法不接受参数并返回包含对象的正常完成。调用时执行以下步骤:

  1. 返回envRec.[[GlobalThisValue]]

9.1.1.4.12 HasLexicalDeclaration ( envRec, N )

抽象操作HasLexicalDeclaration接受参数envRec(一个全局环境记录) 和N(字符串)并返回布尔值。它确定参数标识符是否在envRec中有使用词法声明如词法声明类声明创建的绑定。调用时执行以下步骤:

  1. DclRecenvRec.[[DeclarativeRecord]]
  2. 返回! DclRec.HasBinding(N)。

9.1.1.4.13 HasRestrictedGlobalProperty ( envRec, N )

抽象操作HasRestrictedGlobalProperty接受参数envRec(一个全局环境记录) 和N(字符串)并返回包含布尔值的正常完成抛出完成。它确定参数标识符是否是全局对象的属性名称,该属性不得被全局词法绑定遮蔽。调用时执行以下步骤:

  1. ObjRecenvRec.[[ObjectRecord]]
  2. globalObjectObjRec.[[BindingObject]]
  3. existingProp为? globalObject.[[GetOwnProperty]](N)。
  4. 如果existingPropundefined,返回false
  5. 如果existingProp.[[Configurable]]true,返回false
  6. 返回true

属性可能存在于全局对象上,这些属性是直接创建的而不是使用var或函数声明声明的。不能创建与全局对象的不可配置属性同名的全局词法绑定。全局属性"undefined"就是这样一个属性的例子。

9.1.1.4.14 CanDeclareGlobalVar ( envRec, N )

抽象操作CanDeclareGlobalVar接受参数envRec(一个全局环境记录) 和N(字符串)并返回包含布尔值的正常完成抛出完成。它确定如果为相同参数N调用相应的CreateGlobalVarBinding调用是否会成功。允许冗余的var声明和对预先存在的全局对象属性的var声明。调用时执行以下步骤:

  1. ObjRecenvRec.[[ObjectRecord]]
  2. globalObjectObjRec.[[BindingObject]]
  3. hasProperty为? HasOwnProperty(globalObject, N)。
  4. 如果hasPropertytrue,返回true
  5. 返回? IsExtensible(globalObject)。

9.1.1.4.15 CanDeclareGlobalFunction ( envRec, N )

抽象操作CanDeclareGlobalFunction接受参数envRec(一个全局环境记录) 和N(字符串)并返回包含布尔值的正常完成抛出完成。它确定如果为相同参数N调用相应的CreateGlobalFunctionBinding调用是否会成功。调用时执行以下步骤:

  1. ObjRecenvRec.[[ObjectRecord]]
  2. globalObjectObjRec.[[BindingObject]]
  3. existingProp为? globalObject.[[GetOwnProperty]](N)。
  4. 如果existingPropundefined,返回? IsExtensible(globalObject)。
  5. 如果existingProp.[[Configurable]]true,返回true
  6. 如果IsDataDescriptor(existingProp) 是trueexistingProp有属性值{ [[Writable]]: true, [[Enumerable]]: true },返回true
  7. 返回false

9.1.1.4.16 CreateGlobalVarBinding ( envRec, N, D )

抽象操作CreateGlobalVarBinding接受参数envRec(一个全局环境记录)、N(字符串)和D(布尔值) 并返回包含 unused正常完成抛出完成。它在关联的对象环境记录中创建并初始化可变绑定。如果绑定已经存在,则重用它并假定已初始化。调用时执行以下步骤:

  1. ObjRecenvRec.[[ObjectRecord]]
  2. globalObjectObjRec.[[BindingObject]]
  3. hasProperty为? HasOwnProperty(globalObject, N)。
  4. extensible为? IsExtensible(globalObject)。
  5. 如果hasPropertyfalseextensibletrue,则
    1. 执行? ObjRec.CreateMutableBinding(N, D)。
    2. 执行? ObjRec.InitializeBinding(N, undefined)。
  6. 返回unused

9.1.1.4.17 CreateGlobalFunctionBinding ( envRec, N, V, D )

抽象操作CreateGlobalFunctionBinding接受参数envRec(一个全局环境记录)、N(字符串)、VECMAScript语言值) 和D(布尔值)并返回包含 unused正常完成抛出完成。它在关联的对象环境记录中创建并初始化可变绑定。如果绑定已经存在,则替换它。调用时执行以下步骤:

  1. ObjRecenvRec.[[ObjectRecord]]
  2. globalObjectObjRec.[[BindingObject]]
  3. existingProp为? globalObject.[[GetOwnProperty]](N)。
  4. 如果existingPropundefinedexistingProp.[[Configurable]]true,则
    1. desc为属性描述符{ [[Value]]: V, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: D }。
  5. 否则,
    1. desc为属性描述符{ [[Value]]: V }。
  6. 执行? DefinePropertyOrThrow(globalObject, N, desc)。
  7. 执行? Set(globalObject, N, V, false)。
  8. 返回unused

全局函数声明总是表示为全局对象的自有属性。如果可能,现有的自有属性会被重新配置为具有标准的属性值集合。步骤7等效于调用InitializeBinding具体方法所做的操作,如果globalObject是代理,将产生相同的代理陷阱调用序列。

9.1.1.5 模块环境记录

模块环境记录是一个 声明式环境记录,用于表示 ECMAScript 模块的外部作用域。除了普通的可变和不可变绑定之外,模块环境记录还提供不可变的导入绑定,这些绑定提供对存在于另一个 环境记录中的目标绑定的间接访问。

模块环境记录支持 声明式环境记录表 16 中列出的所有方法,除了 GetBindingValue、DeleteBinding、HasThisBinding 和 GetThisBinding 之外,所有这些方法都共享相同的规范。此外,模块环境记录支持 表 22 中列出的方法:

表 22:模块环境记录的附加方法
方法 目的
GetThisBinding() 返回此 环境记录this 绑定的值。

9.1.1.5.1 GetBindingValue ( N, S )

模块环境记录 envRec 的 GetBindingValue 具体方法接收参数 N(一个字符串)和 S(一个布尔值),并返回 包含 ECMAScript 语言值的正常完成或 抛出完成。它返回名称为 N 的绑定标识符的值。但是,如果绑定是间接绑定,则返回目标绑定的值。如果绑定存在但未初始化,则抛出 ReferenceError。调用时执行以下步骤:

  1. 断言Strue
  2. 断言envRec 有一个 N 的绑定。
  3. 如果 N 的绑定是间接绑定,那么
    1. MN2 为创建此 N 绑定时提供的间接值。
    2. targetEnvM.[[Environment]]
    3. 如果 targetEnvempty,抛出 ReferenceError 异常。
    4. 返回 ? targetEnv.GetBindingValue(N2, true)。
  4. 如果 envRecN 的绑定是未初始化的绑定,抛出 ReferenceError 异常。
  5. 返回 envRec 中当前绑定到 N 的值。

S 将始终为 true,因为 模块始终是 严格模式代码

9.1.1.5.2 DeleteBinding ( N )

模块环境记录的 DeleteBinding 具体方法在本规范中从未使用。

模块环境记录仅在严格代码中使用,并且早期错误规则防止在严格代码中将 delete 操作符应用于会解析为 模块环境记录绑定的 引用记录。参见 13.5.1.1

9.1.1.5.3 HasThisBinding ( )

模块环境记录 envRec 的 HasThisBinding 具体方法不接收参数,返回 true。调用时执行以下步骤:

  1. 返回 true

模块环境记录始终提供 this 绑定。

9.1.1.5.4 GetThisBinding ( )

模块环境记录 envRec 的 GetThisBinding 具体方法不接收参数,返回 包含 undefined 的正常完成。调用时执行以下步骤:

  1. 返回 undefined

9.1.1.5.5 CreateImportBinding ( envRec, N, M, N2 )

抽象操作 CreateImportBinding 接收参数 envRec(一个 模块环境记录)、N(一个字符串)、M(一个 模块记录)和 N2(一个字符串),并返回 unused。它为名称 N 创建一个新的已初始化的不可变间接绑定。envRec 中不能已经存在 N 的绑定。N2 是存在于 M模块环境记录中的绑定的名称。对新绑定值的访问将间接访问目标绑定的绑定值。调用时执行以下步骤:

  1. 断言envRec 还没有 N 的绑定。
  2. 断言: 当 M.[[Environment]] 被实例化时,它将有一个 N2 的直接绑定。
  3. envRec 中为 N 创建一个不可变的间接绑定,该绑定引用 MN2 作为其目标绑定,并记录该绑定已初始化。
  4. 返回 unused

9.1.2 环境记录操作

本规范中使用以下抽象操作来操作环境记录

9.1.2.1 GetIdentifierReference ( env, name, strict )

抽象操作 GetIdentifierReference 接收参数 env(一个环境记录null)、name(一个字符串)和 strict(一个布尔值),并返回包含引用记录的正常完成或抛出完成。调用时执行以下步骤:

  1. 如果 envnull,那么
    1. 返回引用记录 { [[Base]]: unresolvable, [[ReferencedName]]: name, [[Strict]]: strict, [[ThisValue]]: empty }。
  2. exists 为 ? env.HasBinding(name)。
  3. 如果 existstrue,那么
    1. 返回引用记录 { [[Base]]: env, [[ReferencedName]]: name, [[Strict]]: strict, [[ThisValue]]: empty }。
  4. 否则,
    1. outerenv.[[OuterEnv]]
    2. 返回 ? GetIdentifierReference(outer, name, strict)。

9.1.2.2 NewDeclarativeEnvironment ( E )

抽象操作 NewDeclarativeEnvironment 接收参数 E(一个环境记录null),并返回一个声明式环境记录。调用时执行以下步骤:

  1. env 为一个不包含绑定的新声明式环境记录
  2. 设置 env.[[OuterEnv]]E
  3. 返回 env

9.1.2.3 NewObjectEnvironment ( O, W, E )

抽象操作 NewObjectEnvironment 接收参数 O(一个对象)、W(一个布尔值)和 E(一个环境记录null),并返回一个对象环境记录。调用时执行以下步骤:

  1. env 为一个新的对象环境记录
  2. 设置 env.[[BindingObject]]O
  3. 设置 env.[[IsWithEnvironment]]W
  4. 设置 env.[[OuterEnv]]E
  5. 返回 env

9.1.2.4 NewFunctionEnvironment ( F, newTarget )

抽象操作 NewFunctionEnvironment 接收参数 F(一个 ECMAScript 函数对象)和 newTarget(一个对象或 undefined),并返回一个函数环境记录。调用时执行以下步骤:

  1. env 为一个不包含绑定的新函数环境记录
  2. 设置 env.[[FunctionObject]]F
  3. 如果 F.[[ThisMode]]lexical,设置 env.[[ThisBindingStatus]]lexical
  4. 否则,设置 env.[[ThisBindingStatus]]uninitialized
  5. 设置 env.[[NewTarget]]newTarget
  6. 设置 env.[[OuterEnv]]F.[[Environment]]
  7. 返回 env

9.1.2.5 NewGlobalEnvironment ( G, thisValue )

抽象操作 NewGlobalEnvironment 接收参数 G(一个对象)和 thisValue(一个对象),并返回一个全局环境记录。调用时执行以下步骤:

  1. objRecNewObjectEnvironment(G, false, null)。
  2. dclRecNewDeclarativeEnvironment(null)。
  3. env 为一个新的全局环境记录
  4. 设置 env.[[ObjectRecord]]objRec
  5. 设置 env.[[GlobalThisValue]]thisValue
  6. 设置 env.[[DeclarativeRecord]]dclRec
  7. 设置 env.[[OuterEnv]]null
  8. 返回 env

9.1.2.6 NewModuleEnvironment ( E )

抽象操作 NewModuleEnvironment 接收参数 E(一个环境记录),并返回一个模块环境记录。调用时执行以下步骤:

  1. env 为一个不包含绑定的新模块环境记录
  2. 设置 env.[[OuterEnv]]E
  3. 返回 env

9.2 私有环境记录

私有环境记录是一种规范机制,用于基于 ECMAScript 代码中 类声明类表达式的词法嵌套结构来跟踪私有名称。它们类似于但区别于环境记录。每个私有环境记录都与一个 类声明类表达式关联。每次求值这样的类时,都会创建一个新的私有环境记录来记录该类声明的私有名称

每个私有环境记录都具有表 23中定义的字段。

表 23:私有环境记录字段
字段名称 值类型 含义
[[OuterPrivateEnvironment]] 一个私有环境记录null 最近的包含类的私有环境记录。如果与此私有环境记录关联的类不包含在任何其他类中,则为 null
[[Names]] 私有名称列表 此类声明的私有名称

9.2.1 私有环境记录操作

本规范中使用以下抽象操作来操作私有环境记录

9.2.1.1 NewPrivateEnvironment ( outerPrivateEnv )

抽象操作 NewPrivateEnvironment 接收参数 outerPrivateEnv(一个私有环境记录null),并返回一个私有环境记录。调用时执行以下步骤:

  1. names 为一个新的空列表
  2. 返回私有环境记录 { [[OuterPrivateEnvironment]]: outerPrivateEnv, [[Names]]: names }。

9.2.1.2 ResolvePrivateIdentifier ( privateEnv, identifier )

抽象操作 ResolvePrivateIdentifier 接收参数 privateEnv(一个私有环境记录)和 identifier(一个字符串),并返回一个私有名称。调用时执行以下步骤:

  1. namesprivateEnv.[[Names]]
  2. 对于 names 的每个私有名称 pn,执行
    1. 如果 pn.[[Description]]identifier,那么
      1. 返回 pn
  3. outerPrivateEnvprivateEnv.[[OuterPrivateEnvironment]]
  4. 断言outerPrivateEnv 不是 null
  5. 返回 ResolvePrivateIdentifier(outerPrivateEnv, identifier)。

9.3 领域

在求值之前,所有 ECMAScript 代码都必须与一个领域关联。从概念上讲,一个领域由一组内建对象、一个 ECMAScript 全局环境、在该全局环境作用域内加载的所有 ECMAScript 代码以及其他关联的状态和资源组成。

在本规范中,领域表示为具有表 24中指定字段的领域记录

表 24:领域记录字段
字段名称 含义
[[AgentSignifier]] 一个代理标识符 拥有此领域代理
[[Intrinsics]] 一个记录,其字段名称是内建键,其值是对象 与此领域关联的代码使用的内建值
[[GlobalObject]] 一个对象 领域全局对象
[[GlobalEnv]] 一个全局环境记录 领域的全局环境
[[TemplateMap]] 具有字段 [[Site]](一个模板字面量解析节点)和 [[Array]](一个数组)的记录列表

模板对象使用其领域记录[[TemplateMap]] 为每个领域单独规范化。每个 [[Site]] 值是一个解析节点,是一个模板字面量。关联的 [[Array]] 值是传递给标签函数的相应模板对象。

注 1
一旦解析节点变得不可达,相应的 [[Array]] 也变得不可达,如果实现从 [[TemplateMap]] 列表中移除该对,这是不可观察的。
[[LoadedModules]] 已加载 ModuleRequest 记录列表

从此领域导入的说明符字符串到已解析模块记录的映射。列表不包含两个不同的记录 r1r2,使得 ModuleRequestsEqual(r1, r2) 为 true

注 2
HostLoadImportedModule16.2.1.10 注 1)中所述,领域记录中的 [[LoadedModules]] 仅在没有活动脚本或模块的上下文中运行 import() 表达式时使用。
[[HostDefined]] 任何值(默认值为 undefined 为需要将附加信息与领域记录关联的宿主保留的字段。

9.3.1 InitializeHostDefinedRealm ( )

抽象操作 InitializeHostDefinedRealm 不接收参数,并返回包含 unused 的正常完成或抛出完成。调用时执行以下步骤:

  1. realm 为一个新的领域记录
  2. 执行 CreateIntrinsics(realm)。
  3. 设置 realm.[[AgentSignifier]]AgentSignifier()。
  4. 设置 realm.[[TemplateMap]] 为一个新的空列表
  5. newContext 为一个新的执行上下文
  6. 设置 newContext 的 Function 为 null
  7. 设置 newContext领域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 ( realmRec )

抽象操作 CreateIntrinsics 接收参数 realmRec(一个领域记录),并返回 unused。调用时执行以下步骤:

  1. 设置 realmRec.[[Intrinsics]] 为一个新的记录
  2. 使用表 6中列出的值设置 realmRec.[[Intrinsics]] 的字段。字段名称是表第一列中列出的名称。每个字段的值是一个新的对象值,完全且递归地填充了属性值,如子句1928中每个对象的规范所定义。所有对象属性值都是新创建的对象值。所有作为内建函数对象的值都通过执行 CreateBuiltinFunction(steps, length, name, slots, realmRec, prototype) 创建,其中 steps 是本规范提供的该函数的定义,name 是函数 "name" 属性的初始值,length 是函数 "length" 属性的初始值,slots 是函数指定的内部插槽名称的列表(如果有),prototype 是函数 [[Prototype]] 内部插槽的指定值。内建对象及其属性的创建必须有序,以避免依赖尚未创建的对象。
  3. 执行 AddRestrictedFunctionProperties(realmRec.[[Intrinsics]].[[%Function.prototype%]], realmRec)。
  4. 返回 unused

9.3.3 SetDefaultGlobalBindings ( realmRec )

抽象操作 SetDefaultGlobalBindings 接收参数 realmRec(一个领域记录),并返回包含 unused 的正常完成或抛出完成。调用时执行以下步骤:

  1. globalrealmRec.[[GlobalObject]]
  2. 对于子句19中指定的全局对象的每个属性,执行
    1. name属性名称的字符串值。
    2. desc 为该属性的完全填充的数据属性描述符,包含该属性的指定特性。对于19.219.319.4中列出的属性,[[Value]] 特性的值是来自 realmRec 的相应内建对象。
    3. 执行 ? DefinePropertyOrThrow(global, name, desc)。
  3. 返回 unused

9.4 执行上下文

执行上下文是一种规范设备,用于跟踪 ECMAScript 实现对代码的运行时求值。在任何时候,每个代理最多有一个实际在执行代码的执行上下文。这被称为代理运行执行上下文。本规范中对运行执行上下文的所有引用都指周围代理运行执行上下文

执行上下文栈用于跟踪执行上下文。运行执行上下文始终是该栈的顶部元素。每当控制从与当前运行执行上下文关联的可执行代码转移到与该执行上下文不关联的可执行代码时,就会创建一个新的执行上下文。新创建的执行上下文被推入栈中并成为运行执行上下文

执行上下文包含跟踪其关联代码的执行进度所需的任何实现特定状态。每个执行上下文至少具有表 25中列出的状态组件。

表 25:所有执行上下文的状态组件
组件 目的
代码求值状态 执行、暂停和恢复与此执行上下文关联的代码求值所需的任何状态。
Function 如果此执行上下文正在求值函数对象的代码,则此组件的值为该函数对象。如果上下文正在求值脚本模块的代码,则值为 null
领域 关联代码访问 ECMAScript 资源的领域记录
ScriptOrModule 关联代码起源的模块记录脚本记录。如果没有起源脚本或模块,如在InitializeHostDefinedRealm中创建的原始执行上下文的情况,则值为 null

运行执行上下文对代码的求值可能在本规范内定义的各个点被暂停。一旦运行执行上下文被暂停,不同的执行上下文可能成为运行执行上下文并开始求值其代码。在稍后的某个时间,被暂停的执行上下文可能再次成为运行执行上下文并在之前被暂停的点继续求值其代码。运行执行上下文状态在执行上下文间的转换通常以类似栈的后进先出方式发生。然而,某些 ECMAScript 特性需要运行执行上下文的非 LIFO 转换。

运行执行上下文领域组件的值也被称为当前领域记录运行执行上下文的 Function 组件的值也被称为活动函数对象

ECMAScript 代码执行上下文具有表 26中列出的附加状态组件。

表 26:ECMAScript 代码执行上下文的附加状态组件
组件 目的
LexicalEnvironment 标识用于解析此执行上下文内代码进行的标识符引用的环境记录
VariableEnvironment 标识保存此执行上下文变量语句创建的绑定的环境记录
PrivateEnvironment 标识保存最近的包含类中类元素创建的私有名称私有环境记录。如果没有包含类,则为 null

执行上下文的 LexicalEnvironment 和 VariableEnvironment 组件始终是环境记录

表示生成器求值的执行上下文具有表 27中列出的附加状态组件。

表 27:生成器执行上下文的附加状态组件
组件 目的
Generator 执行上下文正在求值的生成器。

在大多数情况下,只有运行执行上下文执行上下文栈的顶部)被本规范内的算法直接操作。因此,当使用术语"LexicalEnvironment"和"VariableEnvironment"而不加限定时,它们指的是运行执行上下文的这些组件。

执行上下文纯粹是一种规范机制,不需要对应 ECMAScript 实现的任何特定工件。ECMAScript 代码不可能直接访问或观察执行上下文。

9.4.1 GetActiveScriptOrModule ( )

抽象操作 GetActiveScriptOrModule 不接收参数,并返回脚本记录模块记录null。它用于基于运行执行上下文确定运行的脚本或模块。调用时执行以下步骤:

  1. 如果执行上下文栈为空,返回 null
  2. ec执行上下文栈上 ScriptOrModule 组件不为 null 的最顶层执行上下文
  3. 如果不存在这样的执行上下文,返回 null。否则,返回 ec 的 ScriptOrModule。

9.4.2 ResolveBinding ( name [ , env ] )

抽象操作 ResolveBinding 接收参数 name(一个字符串)和可选参数 env(一个环境记录undefined),并返回包含引用记录的正常完成或抛出完成。它用于确定 name 的绑定。env 可用于显式提供要搜索绑定的环境记录。调用时执行以下步骤:

  1. 如果 env 不存在或 envundefined,那么
    1. 设置 env运行执行上下文的 LexicalEnvironment。
  2. 断言env 是一个环境记录
  3. strictIsStrict(正在求值的语法产生式)。
  4. 返回 ? GetIdentifierReference(env, name, strict)。

ResolveBinding 的结果始终是一个引用记录,其 [[ReferencedName]] 字段为 name

9.4.3 GetThisEnvironment ( )

抽象操作 GetThisEnvironment 不接收参数,并返回一个环境记录。它找到当前提供关键字 this 绑定的环境记录。调用时执行以下步骤:

  1. env运行执行上下文的 LexicalEnvironment。
  2. 重复,
    1. existsenv.HasThisBinding()。
    2. 如果 existstrue,返回 env
    3. outerenv.[[OuterEnv]]
    4. 断言outer 不是 null
    5. 设置 envouter

步骤2中的循环将始终终止,因为环境列表总是以具有 this 绑定的全局环境结束。

9.4.5 ResolveThisBinding ( )

抽象操作 ResolveThisBinding 不接收参数,并返回包含ECMAScript 语言值的正常完成或抛出完成。它使用运行执行上下文的 LexicalEnvironment 确定关键字 this 的绑定。调用时执行以下步骤:

  1. envRecGetThisEnvironment()。
  2. 返回 ? envRec.GetThisBinding()。

9.4.5 GetNewTarget ( )

抽象操作 GetNewTarget 不接收参数,并返回一个对象或 undefined。它使用运行执行上下文的 LexicalEnvironment 确定 NewTarget 值。调用时执行以下步骤:

  1. envRecGetThisEnvironment()。
  2. 断言envRec 有一个 [[NewTarget]] 字段。
  3. 返回 envRec.[[NewTarget]]

9.4.6 GetGlobalObject ( )

抽象操作 GetGlobalObject 不接收参数,并返回一个对象。它返回当前运行执行上下文使用的全局对象。调用时执行以下步骤:

  1. currentRealm当前领域记录
  2. 返回 currentRealm.[[GlobalObject]]

9.5 作业和宿主操作入队作业

作业是一个无参数的抽象闭包,当没有其他 ECMAScript 计算正在进行时,它启动 ECMAScript 计算。

作业由特定代理中的 ECMAScript 宿主环境调度执行。本规范描述了宿主钩子 HostEnqueueGenericJobHostEnqueueFinalizationRegistryCleanupJobHostEnqueuePromiseJobHostEnqueueTimeoutJob来调度作业。本规范中的宿主钩子按对作业调度施加的附加约束进行组织。宿主可以定义调度作业的附加抽象操作。这些操作接受作业抽象闭包领域(一个领域记录null)作为参数。如果提供了领域记录,这些操作调度作业在将来某个时间在提供的领域中执行,在拥有该领域代理中。如果为领域提供null,则作业不会求值 ECMAScript 代码。它们的实现必须符合以下要求:

注 1
宿主环境不需要在调度方面统一对待作业。例如,Web 浏览器和 Node.js 将 Promise 处理作业视为比其他工作更高的优先级;未来的特性可能添加不被视为如此高优先级的作业

在任何特定时间,scriptOrModule(一个脚本记录、一个模块记录null)是活动脚本或模块,如果所有以下条件都为真:

在任何特定时间,如果所有以下条件都为真,则执行准备求值 ECMAScript 代码

注 2

宿主环境可以通过将执行上下文推入执行上下文栈来准备执行求值代码。具体步骤是实现定义的。

领域的具体选择取决于宿主环境。这个初始执行上下文领域仅在调用任何回调函数之前使用。当调用与作业相关的回调函数(如 Promise 处理程序)时,调用会推入自己的执行上下文领域

特定类型的作业有附加的一致性要求。

9.5.1 作业回调记录

作业回调记录是用于存储函数对象宿主定义值的记录值。通过宿主入队的作业调用的函数对象可能有附加的宿主定义上下文。为了传播状态,作业抽象闭包不应该直接捕获和调用函数对象。相反,使用HostMakeJobCallbackHostCallJobCallback

例如,WHATWG HTML 规范(https://html.spec.whatwg.org/)使用宿主定义值来为 Promise 回调传播现任设置对象。

作业回调记录具有表 28中列出的字段。

表 28:作业回调记录字段
字段名称 含义
[[Callback]] 一个函数对象 调用作业时要调用的函数。
[[HostDefined]] 任何值(默认值为empty 宿主保留使用的字段。

9.5.2 HostMakeJobCallback ( callback )

宿主定义的抽象操作 HostMakeJobCallback 接收参数 callback(一个函数对象),并返回一个作业回调记录

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

HostMakeJobCallback 的默认实现在调用时执行以下步骤:

  1. 返回作业回调记录 { [[Callback]]: callback, [[HostDefined]]: empty }。

非 Web 浏览器的 ECMAScript 宿主必须使用 HostMakeJobCallback 的默认实现。

这在回调被传递给负责其最终调度和运行的函数时调用。例如,promise.then(thenAction) 在调用 Promise.prototype.then 时对 thenAction 调用 MakeJobCallback,而不是在调度反应作业时。

9.5.3 HostCallJobCallback ( jobCallback, V, argumentsList )

宿主定义的抽象操作 HostCallJobCallback 接收参数 jobCallback(一个作业回调记录)、V(一个ECMAScript 语言值)和 argumentsListECMAScript 语言值列表),并返回包含ECMAScript 语言值的正常完成或抛出完成

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

  • 它必须执行并返回Call(jobCallback.[[Callback]], V, argumentsList)的结果。

这个要求意味着宿主不能改变本规范中定义的函数对象[[Call]]行为。

HostCallJobCallback 的默认实现在调用时执行以下步骤:

  1. 断言IsCallable(jobCallback.[[Callback]]) 是true
  2. 返回 ? Call(jobCallback.[[Callback]], V, argumentsList)。

非 Web 浏览器的 ECMAScript 宿主必须使用 HostCallJobCallback 的默认实现。

9.5.4 HostEnqueueGenericJob ( job, realm )

宿主定义的抽象操作 HostEnqueueGenericJob 接收参数 job(一个作业抽象闭包)和realm(一个领域记录),并返回unused。它在由realm.[[AgentSignifier]]表示的代理中的领域 realm 中调度job在将来某个时间执行。与此算法一起使用的抽象闭包旨在无附加约束(如优先级和排序)地调度。

HostEnqueueGenericJob 的实现必须符合9.5中的要求。

9.5.5 HostEnqueuePromiseJob ( job, realm )

宿主定义的抽象操作 HostEnqueuePromiseJob 接收参数 job(一个作业抽象闭包)和realm(一个领域记录null),并返回unused。它调度job在将来某个时间执行。与此算法一起使用的抽象闭包旨在与 Promise 处理相关,或者以与 Promise 处理操作相等的优先级调度。

HostEnqueuePromiseJob 的实现必须符合9.5中的要求以及以下要求:

NewPromiseResolveThenableJob返回的作业realm通常是在then函数对象上调用GetFunctionRealm的结果。NewPromiseReactionJob返回的作业realm通常是在处理程序不是undefined时在处理程序上调用GetFunctionRealm的结果。如果处理程序是undefined,则realmnull。对于两种类型的作业,当GetFunctionRealm异常完成(即在被撤销的代理上调用)时,realmGetFunctionRealm调用时的当前领域记录。当realmnull时,不会求值用户 ECMAScript 代码,也不会创建新的 ECMAScript 对象(例如错误对象)。例如,WHATWG HTML 规范(https://html.spec.whatwg.org/)使用realm来检查运行脚本的能力和入口概念。

9.5.6 HostEnqueueTimeoutJob ( timeoutJob, realm, milliseconds )

宿主定义的抽象操作 HostEnqueueTimeoutJob 接收参数 timeoutJob(一个作业抽象闭包)、realm(一个领域记录)和milliseconds(一个非负有限数字),并返回unused。它在由realm.[[AgentSignifier]]表示的代理中的领域 realm 中调度timeoutJob在至少milliseconds毫秒后执行。

HostEnqueueTimeoutJob 的实现必须符合9.5中的要求。

9.6 代理

代理包含一组 ECMAScript 执行上下文、一个执行上下文栈、一个运行执行上下文、一个代理记录和一个执行线程。除了执行线程之外,代理的组成部分专属于该代理

代理执行线程在该代理执行上下文上独立于其他代理执行算法步骤,但是一个执行线程可以被多个代理用作执行线程,只要共享该线程的代理都没有[[CanBlock]]字段为true代理记录

注 1

例如,一些 Web 浏览器在浏览器窗口的多个不相关选项卡之间共享单个执行线程

代理执行线程正在执行算法步骤时,该代理是那些步骤的周围代理。这些步骤使用周围代理来访问在该代理内持有的规范级执行对象:运行执行上下文执行上下文栈代理记录的字段。

代理标识符是用于标识代理的全局唯一不透明值。

表 29:代理记录字段
字段名称 含义
[[LittleEndian]] 布尔值 当算法GetValueFromBufferSetValueInBuffer需要时为isLittleEndian参数计算的默认值。选择是实现定义的,应该是对实现最有效的选择。一旦该值被观察到,它就不能改变。
[[CanBlock]] 布尔值 确定代理是否可以阻塞。
[[Signifier]] 一个代理标识符 在其代理集群内唯一标识代理
[[IsLockFree1]] 布尔值 如果对单字节值的原子操作是无锁的,则为true,否则为false
[[IsLockFree2]] 布尔值 如果对双字节值的原子操作是无锁的,则为true,否则为false
[[IsLockFree8]] 布尔值 如果对八字节值的原子操作是无锁的,则为true,否则为false
[[CandidateExecution]] 一个候选执行记录 参见内存模型
[[KeptAlive]] 对象或符号的列表 初始为一个新的空列表,表示要保持活跃直到当前作业结束的对象和/或符号列表。
[[ModuleAsyncEvaluationCount]] 一个整数 初始为 0,用于为异步或具有异步依赖的模块的[[AsyncEvaluationOrder]]字段分配唯一的递增值。

一旦[[Signifier]][[IsLockFree1]][[IsLockFree2]]的值被代理集群中的任何代理观察到,它们就不能改变。

注 2

[[IsLockFree1]][[IsLockFree2]]的值不一定由硬件决定,也可能反映可能随时间和 ECMAScript 实现而变化的实现选择。

没有[[IsLockFree4]]字段:4 字节原子操作总是无锁的。

实际上,如果原子操作是用任何类型的锁实现的,则该操作不是无锁的。无锁并不意味着无等待:对于完成无锁原子操作可能需要多少个机器步骤没有上限。

大小为n的原子访问是无锁的,并不意味着大小为n的非原子访问的(感知的)原子性,具体来说,非原子访问仍然可能作为几个单独的内存访问序列来执行。详见ReadSharedMemoryWriteSharedMemory

注 3

代理是一种规范机制,不需要对应 ECMAScript 实现的任何特定工件。

9.6.1 AgentSignifier ( )

抽象操作 AgentSignifier 不接收参数,并返回一个代理标识符。调用时执行以下步骤:

  1. AR周围代理代理记录
  2. 返回AR.[[Signifier]]

9.6.2 AgentCanSuspend ( )

抽象操作 AgentCanSuspend 不接收参数,并返回一个布尔值。调用时执行以下步骤:

  1. AR周围代理代理记录
  2. 返回AR.[[CanBlock]]

在某些环境中,给定代理暂停可能不合理。例如,在 Web 浏览器环境中,禁止暂停文档的主事件处理线程可能是合理的,而仍然允许工作线程的事件处理线程暂停。

9.6.3 IncrementModuleAsyncEvaluationCount ( )

抽象操作 IncrementModuleAsyncEvaluationCount 不接收参数,并返回一个整数。调用时执行以下步骤:

  1. AR周围代理代理记录
  2. countAR.[[ModuleAsyncEvaluationCount]]
  3. 设置AR.[[ModuleAsyncEvaluationCount]]count + 1。
  4. 返回count

此值仅用于跟踪挂起模块之间的相对求值顺序。当没有挂起模块时,实现可以不可观察地将[[ModuleAsyncEvaluationCount]]重置为 0。

9.7 代理集群

代理集群是可以通过操作共享内存进行通信的代理的最大集合。

注 1

不同代理内的程序可以通过未指定的方式共享内存。至少,SharedArrayBuffers 的后备内存可以在集群中的代理之间共享。

可能存在可以通过消息传递进行通信但不能共享内存的代理;它们永远不在同一个代理集群中。

每个代理都恰好属于一个代理集群。

注 2

集群中的代理不需要在某个特定时间点都处于活跃状态。如果代理 A 创建另一个代理 B,之后 A 终止且 B 创建代理 C,如果 A 可以与 B 共享一些内存且 B 可以与 C 共享一些内存,则这三个代理在同一个集群中。

集群内的所有代理在其各自代理记录中的[[LittleEndian]]字段必须具有相同的值。

注 3

如果代理集群内不同的代理具有不同的[[LittleEndian]]值,则很难将共享内存用于多字节数据。

集群内的所有代理在其各自代理记录中的[[IsLockFree1]]字段必须具有相同的值;[[IsLockFree2]]字段也是如此。

集群内的所有代理在其各自代理记录中的[[Signifier]]字段必须具有不同的值。

嵌入可以在代理不知情或不配合的情况下停用(停止前进进度)或激活(恢复前进进度)代理。如果嵌入这样做,它不得让集群中的某些代理保持活跃状态,而集群中的其他代理被无限期地停用。

注 4

前述限制的目的是避免代理因为另一个代理被停用而死锁或饥饿的情况。例如,如果具有独立于任何窗口中文档的生命周期的 HTML 共享工作线程被允许与这种独立文档的专用工作线程共享内存,并且文档及其专用工作线程在专用工作线程持有锁时被停用(例如,文档被推入其窗口的历史记录),然后共享工作线程尝试获取锁,那么共享工作线程将被阻塞,直到专用工作线程再次被激活(如果有的话)。与此同时,试图从其他窗口访问共享工作线程的其他工作线程将饥饿。

此限制的含义是,不属于嵌入中同一暂停/唤醒集合的代理之间将无法共享内存。

嵌入可以在代理集群的其他代理事先不知情或不配合的情况下终止代理。如果代理不是通过自身或集群中另一个代理的程序动作终止,而是被集群外部的力量终止,那么嵌入必须选择两种策略之一:要么终止集群中的所有代理,要么提供可靠的 API,允许集群中的代理进行协调,使得集群的至少一个剩余成员能够检测到终止,终止数据包含足够的信息来标识被终止的代理

注 5

这种类型的终止的例子包括:操作系统或用户终止在单独进程中运行的代理;嵌入本身终止与其他代理在同一进程中运行的代理,当按代理的资源计算表明该代理失控时。

以下每个规范值以及从它们可传递到达的值都恰好属于一个代理集群。

在集群中任何代理对任何 ECMAScript 代码进行任何求值之前,集群中所有代理代理记录[[CandidateExecution]]字段被设置为初始候选执行。初始候选执行是一个空候选执行,其[[EventsRecords]]字段是一个列表,为每个代理包含一个代理事件记录,其[[AgentSignifier]]字段是该代理代理标识符,并且其[[EventList]][[AgentSynchronizesWith]]字段是空的列表

注 6

代理集群中的所有代理在其代理记录[[CandidateExecution]]字段中共享相同的候选执行候选执行内存模型使用的规范机制。

注 7

代理集群是一种规范机制,不需要对应 ECMAScript 实现的任何特定工件。

9.8 前进进度

代理取得前进进度是指其根据本规范执行求值步骤。

代理运行执行上下文同步且无限期地等待外部事件时,该代理变为阻塞状态。只有代理记录[[CanBlock]]字段为true代理才能在这种意义上变为阻塞状态。非阻塞代理是指不处于阻塞状态的代理。

实现必须确保:

这与内存模型中的活跃性保证一起,确保所有seq-cst写入最终对所有代理变为可观察的。

9.9 WeakRef 和 FinalizationRegistry 目标的处理模型

9.9.1 目标

本规范不保证任何对象或符号会被垃圾回收。不活跃的对象或符号可能在很长时间后被释放,或者永远不被释放。因此,本规范在描述由垃圾回收触发的行为时使用"可能"一词。

WeakRefsFinalizationRegistrys的语义基于在特定时间点发生的两个操作:

这两个动作(ClearKeptObjectsCleanupFinalizationRegistry)都不能中断同步 ECMAScript 执行。因为宿主可能组装更长的同步 ECMAScript 执行运行,本规范将ClearKeptObjectsCleanupFinalizationRegistry的调度推迟到宿主环境

一些 ECMAScript 实现包括在后台运行的垃圾收集器实现,包括当 ECMAScript 处于空闲状态时。让宿主环境调度CleanupFinalizationRegistry允许它恢复 ECMAScript 执行以运行终结器工作,这可能释放持有的值,减少整体内存使用。

9.9.2 活跃性

对于某个对象和/或符号集合S,关于S假设 WeakRef 无关执行是指这样的执行:其引用对象是S元素的WeakRef的抽象操作WeakRefDeref总是返回undefined

注 1
WeakRef无关性与活跃性一起捕获两个概念。一是WeakRef本身不会使其引用对象保持活跃。二是活跃性中的循环并不意味着值是活跃的。具体来说,如果确定v的活跃性依赖于确定WeakRef引用对象r的活跃性,则r的活跃性不能假设v的活跃性,这将是循环推理。
注 2
WeakRef无关性是在对象或符号集合上定义的,而不是在单个值上定义的,以考虑循环。如果它是在单个值上定义的,那么循环中的WeakRef引用对象将被认为是活跃的,即使其身份只能通过循环中的其他WeakRef引用对象观察到。
注 3
通俗地说,如果包含单个对象或符号的每个集合都是活跃的,我们就说该对象或符号是活跃的。

在求值期间的任何时点,如果满足以下任一条件,则对象和/或符号集合S被认为是活跃的

  • S中的任何元素都包含在任何代理[[KeptAlive]]列表中。
  • 存在一个关于S的有效未来假设 WeakRef 无关执行,该执行观察S中任何值的身份。
注 4
上述第二个条件旨在捕获这样的直觉:如果值的身份可以通过非WeakRef方式观察到,则该值是活跃的。值的身份可以通过观察严格相等比较或观察值被用作 Map 中的键来观察。
注 5

对象或符号在字段、内部槽或属性中的存在并不意味着该值是活跃的。例如,如果所讨论的值从未传回程序,那么它就无法被观察到。

WeakMap 中的键、WeakSet 的成员以及FinalizationRegistry单元记录的[[WeakRefTarget]][[UnregisterToken]]字段都是这种情况。

上述定义意味着,如果 WeakMap 中的键不是活跃的,那么其对应的值也不一定是活跃的。

注 6
活跃性是保证引擎不得清空哪些WeakRefs的下界。这里定义的活跃性是不可判定的。实际上,引擎使用保守的近似,如可达性。预期会有很大的实现自由度。

9.9.3 执行

在任何时候,如果对象和/或符号集合S不是活跃的,ECMAScript 实现可以原子地执行以下步骤:

  1. 对于S的每个元素value,执行
    1. 对于每个ref.[[WeakRefTarget]]valueWeakRef ref,执行
      1. 设置ref.[[WeakRefTarget]]empty
    2. 对于每个fg.[[Cells]]包含cell.[[WeakRefTarget]]value记录 cellFinalizationRegistry fg,执行
      1. 设置cell.[[WeakRefTarget]]empty
      2. 可选地,执行HostEnqueueFinalizationRegistryCleanupJob(fg)。
    3. 对于每个map.[[WeakMapData]]包含r.[[Key]]value记录 r的 WeakMap map,执行
      1. 设置r.[[Key]]empty
      2. 设置r.[[Value]]empty
    4. 对于每个set.[[WeakSetData]]包含value的 WeakSet set,执行
      1. 用值为empty的元素替换set.[[WeakSetData]]中值为value的元素。
注 1

与活跃性定义一起,本条款规定了实现可以应用于WeakRefs的优化。

可以在不观察对象身份的情况下访问对象。诸如死变量消除和对身份未被观察的非逃逸对象属性的标量替换等优化是允许的。因此,这些优化被允许可观察地清空指向此类对象的WeakRefs

另一方面,如果对象的身份是可观察的,并且该对象在WeakRef[[WeakRefTarget]]内部槽中,则禁止可观察地清空WeakRef的重新物化等优化。

因为调用HostEnqueueFinalizationRegistryCleanupJob是可选的,FinalizationRegistry中的注册对象不一定使该FinalizationRegistry保持活跃。实现可以因任何原因省略FinalizationRegistry回调,例如,如果FinalizationRegistry本身变为死亡,或者应用程序正在关闭。

注 2

实现没有义务为非活跃对象或符号的最大集合清空WeakRefs

如果实现选择一个非活跃集合S来清空WeakRefs,此定义要求它同时清空S中所有值的WeakRefs。换句话说,实现清空指向值vWeakRef而不清空其他WeakRefs(如果不清空,可能导致观察到v值的执行)是不符合规范的。

9.9.4 宿主钩子

9.9.4.1 HostEnqueueFinalizationRegistryCleanupJob ( finalizationRegistry )

宿主定义的抽象操作 HostEnqueueFinalizationRegistryCleanupJob 接收参数finalizationRegistry(一个FinalizationRegistry),并返回unused

cleanupJob为捕获finalizationRegistry的无参数新作业抽象闭包,调用时执行以下步骤:

  1. cleanupResultCompletion(CleanupFinalizationRegistry(finalizationRegistry))。
  2. 如果cleanupResult异常完成,执行任何宿主定义的错误报告步骤。
  3. 返回unused

HostEnqueueFinalizationRegistryCleanupJob 的实现调度cleanupJob在将来某个时间执行(如果可能)。它还必须符合9.5中的要求。

9.10 ClearKeptObjects ( )

抽象操作 ClearKeptObjects 不接收参数,并返回unused。预期 ECMAScript 实现在同步 ECMAScript 执行序列完成时调用 ClearKeptObjects。调用时执行以下步骤:

  1. agentRecord周围代理代理记录
  2. 设置agentRecord.[[KeptAlive]]为一个新的空列表
  3. 返回unused

9.11 AddToKeptObjects ( value )

抽象操作 AddToKeptObjects 接收参数value(一个对象或符号),并返回unused。调用时执行以下步骤:

  1. agentRecord周围代理代理记录
  2. value追加到agentRecord.[[KeptAlive]]
  3. 返回unused
当抽象操作 AddToKeptObjects 使用目标对象或符号调用时,它将目标添加到一个列表中,该列表将强引用目标,直到调用ClearKeptObjects

9.12 CleanupFinalizationRegistry ( finalizationRegistry )

抽象操作 CleanupFinalizationRegistry 接收参数finalizationRegistry(一个FinalizationRegistry),并返回包含unused正常完成抛出完成。调用时执行以下步骤:

  1. 断言finalizationRegistry具有[[Cells]][[CleanupCallback]]内部槽。
  2. callbackfinalizationRegistry.[[CleanupCallback]]
  3. finalizationRegistry.[[Cells]]包含cell.[[WeakRefTarget]]empty记录 cell时,实现可以执行以下步骤:
    1. 选择任何这样的cell
    2. finalizationRegistry.[[Cells]]中移除cell
    3. 执行? HostCallJobCallback(callback, undefined, « cell.[[HeldValue]] »)。
  4. 返回unused

9.13 CanBeHeldWeakly ( v )

抽象操作 CanBeHeldWeakly 接收参数v(一个ECMAScript 语言值),并返回一个布尔值。当且仅当v适合用作弱引用时,它返回true。只有适合用作弱引用的值才能作为 WeakMap 的键、WeakSet 的元素、WeakRef的目标或FinalizationRegistry的目标之一。调用时执行以下步骤:

  1. 如果v是对象,返回true
  2. 如果v是符号KeyForSymbol(v)为undefined,返回true
  3. 返回false

没有语言身份的语言值可以在没有先前引用的情况下体现,并且不适合用作弱引用。由Symbol.for产生的符号值与其他符号值不同,没有语言身份,不适合用作弱引用。知名符号可能永远不会被回收,但仍被视为适合用作弱引用,因为它们数量有限,因此可以通过各种实现方法进行管理。但是,在活跃 WeakMap 中与知名符号关联的任何值都不太可能被回收,并且在实现中可能"泄漏"内存资源。

10 普通对象和异构对象行为

10.1 普通对象内部方法和内部槽

所有普通对象都有一个名为[[Prototype]]的内部槽。此内部槽的值要么是null,要么是一个对象,用于实现继承。假设一个名为P的属性在普通对象 O中不存在,但在其[[Prototype]]对象上存在。如果P引用[[Prototype]]对象上的一个数据属性O对于get访问会继承它,使其表现得好像PO的一个属性。如果P引用[[Prototype]]对象上的一个可写数据属性,对OP的set访问会在O上创建一个名为P的新数据属性。如果P引用[[Prototype]]对象上的一个不可写数据属性,对OP的set访问会失败。如果P引用[[Prototype]]对象上的一个访问器属性O会继承该访问器用于get访问和set访问。

每个普通对象都有一个布尔值[[Extensible]]内部槽,用于满足6.1.7.3中指定的可扩展性相关内部方法不变量。也就是说,一旦对象的[[Extensible]]内部槽的值被设置为false,就不再可能向对象添加属性、修改对象的[[Prototype]]内部槽的值,或随后将[[Extensible]]的值更改为true

在以下算法描述中,假设O是一个普通对象P是一个属性键值,V是任何ECMAScript语言值Desc是一个属性描述符记录。

每个普通对象内部方法都委托给同名的抽象操作。如果这样的抽象操作依赖于另一个内部方法,那么内部方法在O上被调用,而不是直接调用同名的抽象操作。这些语义确保当普通对象内部方法应用于异构对象时,它们重写的内部方法会被调用。

10.1.1 [[GetPrototypeOf]] ( )

普通对象 O[[GetPrototypeOf]]内部方法不接受参数,返回一个包含Object或null正常完成。调用时执行以下步骤:

  1. 返回 OrdinaryGetPrototypeOf(O)。

10.1.1.1 OrdinaryGetPrototypeOf ( O )

抽象操作OrdinaryGetPrototypeOf接受参数O(一个Object),返回一个Object或null。调用时执行以下步骤:

  1. 返回 O.[[Prototype]]

10.1.2 [[SetPrototypeOf]] ( V )

普通对象 O[[SetPrototypeOf]]内部方法接受参数V(一个Object或null),返回一个包含Boolean的正常完成。调用时执行以下步骤:

  1. 返回 OrdinarySetPrototypeOf(O, V)。

10.1.2.1 OrdinarySetPrototypeOf ( O, V )

抽象操作OrdinarySetPrototypeOf接受参数O(一个Object)和V(一个Object或null),返回一个Boolean。调用时执行以下步骤:

  1. currentO.[[Prototype]]
  2. 如果 SameValue(V, current) 为 true,返回 true
  3. extensibleO.[[Extensible]]
  4. 如果 extensiblefalse,返回 false
  5. pV
  6. donefalse
  7. 重复,当 donefalse 时,
    1. 如果 pnull,那么
      1. 设置 donetrue
    2. 否则如果 SameValue(p, O) 为 true,那么
      1. 返回 false
    3. 否则,
      1. 如果 p.[[GetPrototypeOf]] 不是10.1.1中定义的普通对象内部方法,设置 donetrue
      2. 否则,设置 pp.[[Prototype]]
  8. 设置 O.[[Prototype]]V
  9. 返回 true

步骤7中的循环保证在仅包含使用[[GetPrototypeOf]][[SetPrototypeOf]]普通对象定义的对象的任何原型链中都不会出现循环。

10.1.3 [[IsExtensible]] ( )

普通对象 O[[IsExtensible]]内部方法不接受参数,返回一个包含Boolean的正常完成。调用时执行以下步骤:

  1. 返回 OrdinaryIsExtensible(O)。

10.1.3.1 OrdinaryIsExtensible ( O )

抽象操作OrdinaryIsExtensible接受参数O(一个Object),返回一个Boolean。调用时执行以下步骤:

  1. 返回 O.[[Extensible]]

10.1.4 [[PreventExtensions]] ( )

普通对象 O[[PreventExtensions]]内部方法不接受参数,返回一个包含true正常完成。调用时执行以下步骤:

  1. 返回 OrdinaryPreventExtensions(O)。

10.1.4.1 OrdinaryPreventExtensions ( O )

抽象操作OrdinaryPreventExtensions接受参数O(一个Object),返回true。调用时执行以下步骤:

  1. 设置 O.[[Extensible]]false
  2. 返回 true

10.1.5 [[GetOwnProperty]] ( P )

普通对象 O[[GetOwnProperty]]内部方法接受参数P(一个属性键),返回一个包含属性描述符undefined正常完成。调用时执行以下步骤:

  1. 返回 OrdinaryGetOwnProperty(O, P)。

10.1.5.1 OrdinaryGetOwnProperty ( O, P )

抽象操作OrdinaryGetOwnProperty接受参数O(一个Object)和P(一个属性键),返回一个属性描述符undefined。调用时执行以下步骤:

  1. 如果 O 没有键为 P 的自有属性,返回 undefined
  2. D 为一个新创建的没有字段的属性描述符
  3. XO 的键为 P 的自有属性。
  4. 如果 X 是一个数据属性,那么
    1. 设置 D.[[Value]]X[[Value]]特性的值。
    2. 设置 D.[[Writable]]X[[Writable]]特性的值。
  5. 否则,
    1. 断言X 是一个访问器属性
    2. 设置 D.[[Get]]X[[Get]]特性的值。
    3. 设置 D.[[Set]]X[[Set]]特性的值。
  6. 设置 D.[[Enumerable]]X[[Enumerable]]特性的值。
  7. 设置 D.[[Configurable]]X[[Configurable]]特性的值。
  8. 返回 D

10.1.6 [[DefineOwnProperty]] ( P, Desc )

普通对象 O[[DefineOwnProperty]]内部方法接受参数P(一个属性键)和Desc(一个属性描述符),返回包含Boolean的正常完成抛出完成。调用时执行以下步骤:

  1. 返回 ? OrdinaryDefineOwnProperty(O, P, Desc)。

10.1.6.1 OrdinaryDefineOwnProperty ( O, P, Desc )

抽象操作OrdinaryDefineOwnProperty接受参数O(一个Object)、P(一个属性键)和Desc(一个属性描述符),返回包含Boolean的正常完成抛出完成。调用时执行以下步骤:

  1. current 为 ? O.[[GetOwnProperty]](P)。
  2. extensible 为 ? IsExtensible(O)。
  3. 返回 ValidateAndApplyPropertyDescriptor(O, P, extensible, Desc, current)。

10.1.6.2 IsCompatiblePropertyDescriptor ( Extensible, Desc, Current )

抽象操作IsCompatiblePropertyDescriptor接受参数Extensible(一个Boolean)、Desc(一个属性描述符)和Current(一个属性描述符undefined),返回一个Boolean。调用时执行以下步骤:

  1. 返回 ValidateAndApplyPropertyDescriptor(undefined, "", Extensible, Desc, Current)。

10.1.6.3 ValidateAndApplyPropertyDescriptor ( O, P, extensible, Desc, current )

抽象操作ValidateAndApplyPropertyDescriptor接受参数O(一个Object或undefined)、P(一个属性键)、extensible(一个Boolean)、Desc(一个属性描述符)和current(一个属性描述符undefined),返回一个Boolean。当且仅当Desc可以作为具有指定extensibility和当前属性current的对象的属性应用,同时维护不变量时,它返回true。当这种应用是可能的且O不是undefined时,它对名为P的属性执行此操作(必要时创建该属性)。调用时执行以下步骤:

  1. 断言P是一个属性键
  2. 如果 currentundefined,那么
    1. 如果 extensiblefalse,返回 false
    2. 如果 Oundefined,返回 true
    3. 如果 IsAccessorDescriptor(Desc) 为 true,那么
      1. 在对象O上创建一个名为P的自有访问器属性,其[[Get]][[Set]][[Enumerable]][[Configurable]]特性分别设置为Desc中对应字段的值(如果Desc有该字段),否则设置为该特性的默认值
    4. 否则,
      1. 在对象O上创建一个名为P的自有数据属性,其[[Value]][[Writable]][[Enumerable]][[Configurable]]特性分别设置为Desc中对应字段的值(如果Desc有该字段),否则设置为该特性的默认值
    5. 返回 true
  3. 断言current是一个完全填充的属性描述符
  4. 如果 Desc 没有任何字段,返回 true
  5. 如果 current.[[Configurable]]false,那么
    1. 如果 Desc[[Configurable]]字段且Desc.[[Configurable]]true,返回 false
    2. 如果 Desc[[Enumerable]]字段且Desc.[[Enumerable]] 不等于 current.[[Enumerable]],返回 false
    3. 如果 IsGenericDescriptor(Desc) 为 falseIsAccessorDescriptor(Desc) 不等于 IsAccessorDescriptor(current),返回 false
    4. 如果 IsAccessorDescriptor(current) 为 true,那么
      1. 如果 Desc[[Get]]字段且SameValue(Desc.[[Get]], current.[[Get]]) 为 false,返回 false
      2. 如果 Desc[[Set]]字段且SameValue(Desc.[[Set]], current.[[Set]]) 为 false,返回 false
    5. 否则如果 current.[[Writable]]false,那么
      1. 如果 Desc[[Writable]]字段且Desc.[[Writable]]true,返回 false
      2. 注:SameValueNaN值返回true,这些值可能通过其他方式区分。在此处返回确保O的任何现有属性保持未修改。
      3. 如果 Desc[[Value]]字段,返回 SameValue(Desc.[[Value]], current.[[Value]])。
  6. 如果 O 不是 undefined,那么
    1. 如果 IsDataDescriptor(current) 为 trueIsAccessorDescriptor(Desc) 为 true,那么
      1. 如果 Desc[[Configurable]]字段,令 configurableDesc.[[Configurable]];否则令 configurablecurrent.[[Configurable]]
      2. 如果 Desc[[Enumerable]]字段,令 enumerableDesc.[[Enumerable]];否则令 enumerablecurrent.[[Enumerable]]
      3. 将对象O的名为P的属性替换为一个访问器属性,其[[Configurable]][[Enumerable]]特性分别设置为configurableenumerable,其[[Get]][[Set]]特性设置为Desc中对应字段的值(如果Desc有该字段),否则设置为该特性的默认值
    2. 否则如果 IsAccessorDescriptor(current) 为 trueIsDataDescriptor(Desc) 为 true,那么
      1. 如果 Desc[[Configurable]]字段,令 configurableDesc.[[Configurable]];否则令 configurablecurrent.[[Configurable]]
      2. 如果 Desc[[Enumerable]]字段,令 enumerableDesc.[[Enumerable]];否则令 enumerablecurrent.[[Enumerable]]
      3. 将对象O的名为P的属性替换为一个数据属性,其[[Configurable]][[Enumerable]]特性分别设置为configurableenumerable,其[[Value]][[Writable]]特性设置为Desc中对应字段的值(如果Desc有该字段),否则设置为该特性的默认值
    3. 否则,
      1. 对于Desc的每个字段,将对象O的名为P的属性的对应特性设置为该字段的值。
  7. 返回 true

10.1.7 [[HasProperty]] ( P )

普通对象 O[[HasProperty]]内部方法接受参数P(一个属性键),返回包含Boolean的正常完成抛出完成。调用时执行以下步骤:

  1. 返回 ? OrdinaryHasProperty(O, P)。

10.1.7.1 OrdinaryHasProperty ( O, P )

抽象操作OrdinaryHasProperty接受参数O(一个Object)和P(一个属性键),返回包含Boolean的正常完成抛出完成。调用时执行以下步骤:

  1. hasOwn 为 ? O.[[GetOwnProperty]](P)。
  2. 如果 hasOwn 不是 undefined,返回 true
  3. parent 为 ? O.[[GetPrototypeOf]]()。
  4. 如果 parent 不是 null,那么
    1. 返回 ? parent.[[HasProperty]](P)。
  5. 返回 false

10.1.8 [[Get]] ( P, Receiver )

普通对象 O[[Get]]内部方法接受参数P(一个属性键)和Receiver(一个ECMAScript语言值),返回包含ECMAScript语言值正常完成抛出完成。调用时执行以下步骤:

  1. 返回 ? OrdinaryGet(O, P, Receiver)。

10.1.8.1 OrdinaryGet ( O, P, Receiver )

抽象操作OrdinaryGet接受参数O(一个Object)、P(一个属性键)和Receiver(一个ECMAScript语言值),返回包含ECMAScript语言值正常完成抛出完成。调用时执行以下步骤:

  1. desc 为 ? O.[[GetOwnProperty]](P)。
  2. 如果 descundefined,那么
    1. parent 为 ? O.[[GetPrototypeOf]]()。
    2. 如果 parentnull,返回 undefined
    3. 返回 ? parent.[[Get]](P, Receiver)。
  3. 如果 IsDataDescriptor(desc) 为 true,返回 desc.[[Value]]
  4. 断言IsAccessorDescriptor(desc) 为 true
  5. getterdesc.[[Get]]
  6. 如果 getterundefined,返回 undefined
  7. 返回 ? Call(getter, Receiver)。

10.1.9 [[Set]] ( P, V, Receiver )

普通对象 O[[Set]]内部方法接受参数P(一个属性键)、V(一个ECMAScript语言值)和Receiver(一个ECMAScript语言值),返回包含Boolean的正常完成抛出完成。调用时执行以下步骤:

  1. 返回 ? OrdinarySet(O, P, V, Receiver)。

10.1.9.1 OrdinarySet ( O, P, V, Receiver )

抽象操作OrdinarySet接受参数O(一个Object)、P(一个属性键)、V(一个ECMAScript语言值)和Receiver(一个ECMAScript语言值),返回包含Boolean的正常完成抛出完成。调用时执行以下步骤:

  1. ownDesc 为 ? O.[[GetOwnProperty]](P)。
  2. 返回 ? OrdinarySetWithOwnDescriptor(O, P, V, Receiver, ownDesc)。

10.1.9.2 OrdinarySetWithOwnDescriptor ( O, P, V, Receiver, ownDesc )

抽象操作OrdinarySetWithOwnDescriptor接受参数O(一个Object)、P(一个属性键)、V(一个ECMAScript语言值)、Receiver(一个ECMAScript语言值)和ownDesc(一个属性描述符undefined),返回包含Boolean的正常完成抛出完成。调用时执行以下步骤:

  1. 如果 ownDescundefined,那么
    1. parent 为 ? O.[[GetPrototypeOf]]()。
    2. 如果 parent 不是 null,那么
      1. 返回 ? parent.[[Set]](P, V, Receiver)。
    3. 否则,
      1. 设置 ownDesc 为属性描述符 { [[Value]]: undefined, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true }。
  2. 如果 IsDataDescriptor(ownDesc) 为 true,那么
    1. 如果 ownDesc.[[Writable]]false,返回 false
    2. 如果 Receiver 不是Object,返回 false
    3. existingDescriptor 为 ? Receiver.[[GetOwnProperty]](P)。
    4. 如果 existingDescriptor 不是 undefined,那么
      1. 如果 IsAccessorDescriptor(existingDescriptor) 为 true,返回 false
      2. 如果 existingDescriptor.[[Writable]]false, 返回 false
      3. valueDesc 为属性描述符 { [[Value]]: V }。
      4. 返回 ? Receiver.[[DefineOwnProperty]](P, valueDesc)。
    5. 否则,
      1. 断言Receiver 当前没有属性 P
      2. 返回 ? CreateDataProperty(Receiver, P, V)。
  3. 断言IsAccessorDescriptor(ownDesc) 为 true
  4. setterownDesc.[[Set]]
  5. 如果 setterundefined,返回 false
  6. 执行 ? Call(setter, Receiver, « V »)。
  7. 返回 true

10.1.10 [[Delete]] ( P )

普通对象 O[[Delete]]内部方法接受参数P(一个属性键),返回包含Boolean的正常完成抛出完成。调用时执行以下步骤:

  1. 返回 ? OrdinaryDelete(O, P)。

10.1.10.1 OrdinaryDelete ( O, P )

抽象操作OrdinaryDelete接受参数O(一个Object)和P(一个属性键),返回包含Boolean的正常完成抛出完成。调用时执行以下步骤:

  1. desc 为 ? O.[[GetOwnProperty]](P)。
  2. 如果 descundefined,返回 true
  3. 如果 desc.[[Configurable]]true,那么
    1. O 中移除名为 P 的自有属性。
    2. 返回 true
  4. 返回 false

10.1.11 [[OwnPropertyKeys]] ( )

普通对象 O[[OwnPropertyKeys]]内部方法不接受参数,返回一个包含属性键列表正常完成。调用时执行以下步骤:

  1. 返回 OrdinaryOwnPropertyKeys(O)。

10.1.11.1 OrdinaryOwnPropertyKeys ( O )

抽象操作OrdinaryOwnPropertyKeys接受参数O(一个Object),返回一个属性键列表。调用时执行以下步骤:

  1. keys 为一个新的空列表
  2. 对于 O 的每个自有属性键 P,满足 P数组索引,按升序数字索引顺序,执行
    1. P 追加到 keys
  3. 对于 O 的每个自有属性键 P,满足 P 是字符串P 不是数组索引,按属性创建的升序时间顺序,执行
    1. P 追加到 keys
  4. 对于 O 的每个自有属性键 P,满足 P 是Symbol,按属性创建的升序时间顺序,执行
    1. P 追加到 keys
  5. 返回 keys

10.1.12 OrdinaryObjectCreate ( proto [ , additionalInternalSlotsList ] )

抽象操作OrdinaryObjectCreate接受参数proto(一个Object或null)和可选参数additionalInternalSlotsList(内部插槽名称的列表),返回一个Object。它用于指定新普通对象的运行时创建。additionalInternalSlotsList包含除[[Prototype]][[Extensible]]之外必须作为对象一部分定义的附加内部插槽的名称。如果未提供additionalInternalSlotsList,则使用一个新的空列表。调用时执行以下步骤:

  1. internalSlotsList 为 « [[Prototype]], [[Extensible]] »。
  2. 如果 additionalInternalSlotsList 存在,设置 internalSlotsListinternalSlotsListadditionalInternalSlotsList列表连接
  3. OMakeBasicObject(internalSlotsList)。
  4. 设置 O.[[Prototype]]proto
  5. 返回 O

虽然OrdinaryObjectCreate除了调用MakeBasicObject之外没有做更多的事情,但它的使用传达了创建普通对象而不是奇异对象的意图。因此,在本规范中,任何随后以会使结果变成非普通对象的方式修改对象内部方法的算法都不会调用它。创建奇异对象的操作直接调用MakeBasicObject

10.1.13 OrdinaryCreateFromConstructor ( constructor, intrinsicDefaultProto [ , internalSlotsList ] )

抽象操作OrdinaryCreateFromConstructor接受参数constructor(一个函数对象)和intrinsicDefaultProto(一个字符串)以及可选参数internalSlotsList(内部插槽名称的列表),返回包含Object的正常完成抛出完成。它创建一个普通对象,其[[Prototype]]值从构造器"prototype"属性中检索(如果存在)。否则,由intrinsicDefaultProto命名的内在值用于[[Prototype]]internalSlotsList包含必须作为对象一部分定义的附加内部插槽的名称。如果未提供internalSlotsList,则使用一个新的空列表。调用时执行以下步骤:

  1. 断言intrinsicDefaultProto是本规范的内在对象名称。对应的对象必须是旨在用作对象的[[Prototype]]值的内在值。
  2. proto 为 ? GetPrototypeFromConstructor(constructor, intrinsicDefaultProto)。
  3. 如果 internalSlotsList 存在,令 slotsListinternalSlotsList
  4. 否则,令 slotsList 为一个新的空列表
  5. 返回 OrdinaryObjectCreate(proto, slotsList)。

10.1.14 GetPrototypeFromConstructor ( constructor, intrinsicDefaultProto )

抽象操作GetPrototypeFromConstructor接受参数constructor(一个函数对象)和intrinsicDefaultProto(一个字符串),返回包含Object的正常完成抛出完成。它确定应该用于创建对应于特定构造器的对象的[[Prototype]]值。该值从构造器"prototype"属性中检索(如果存在)。否则,由intrinsicDefaultProto命名的内在值用于[[Prototype]]。调用时执行以下步骤:

  1. 断言intrinsicDefaultProto是本规范的内在对象名称。对应的对象必须是旨在用作对象的[[Prototype]]值的内在值。
  2. proto 为 ? Get(constructor, "prototype")。
  3. 如果 proto 不是Object,那么
    1. realm 为 ? GetFunctionRealm(constructor)。
    2. 设置 protorealm 的名为 intrinsicDefaultProto 的内在对象。
  4. 返回 proto

如果constructor不提供[[Prototype]]值,则使用的默认值从constructor函数的领域获得,而不是从运行执行上下文获得。

10.1.15 RequireInternalSlot ( O, internalSlot )

抽象操作RequireInternalSlot接受参数O(一个ECMAScript语言值)和internalSlot(一个内部插槽名称),返回包含unused正常完成抛出完成。除非O 是Object且具有给定的内部插槽,否则它会抛出异常。调用时执行以下步骤:

  1. 如果 O 不是Object,抛出 TypeError 异常。
  2. 如果 O 没有 internalSlot 内部插槽,抛出 TypeError 异常。
  3. 返回 unused

10.2 ECMAScript函数对象

ECMAScript函数对象封装了在词法环境上封闭的参数化ECMAScript代码,并支持该代码的动态评估。ECMAScript函数对象是一个普通对象,具有与其他普通对象相同的内部插槽和相同的内部方法。ECMAScript函数对象的代码可以是严格模式代码11.2.2)或非严格代码。代码为严格模式代码的ECMAScript函数对象称为严格函数。代码不是严格模式代码的称为非严格函数

除了[[Extensible]][[Prototype]]之外,ECMAScript函数对象还具有表30中列出的内部插槽。

表30:ECMAScript函数对象的内部插槽
内部插槽 类型 描述
[[Environment]] 一个环境记录 函数封闭的环境记录。在评估函数代码时用作外部环境。
[[PrivateEnvironment]] 一个私有环境记录null 函数封闭的私有名称私有环境记录。如果此函数在语法上不包含在类中,则为null。在评估函数代码时用作内部类的外部私有环境。
[[FormalParameters]] 一个解析节点 定义函数形式参数列表的源文本的根解析节点。
[[ECMAScriptCode]] 一个解析节点 定义函数体的源文本的根解析节点。
[[ConstructorKind]] basederived 函数是否为派生类构造器
[[Realm]] 一个领域记录 创建函数的领域,它提供在评估函数时访问的任何内在对象。
[[ScriptOrModule]] 一个脚本记录或一个模块记录 创建函数的脚本或模块。
[[ThisMode]] lexicalstrictglobal 定义如何在函数的形式参数和代码体中解释this引用。lexical表示this引用词法封闭函数的this值。strict表示this值完全按照函数调用提供的使用。global表示undefinednullthis值被解释为对全局对象的引用,任何其他this值首先传递给ToObject
[[Strict]] 一个Boolean 如果这是严格函数则为true,如果这是非严格函数则为false
[[HomeObject]] 一个Object 如果函数使用super,这是其[[GetPrototypeOf]]提供super属性查找开始的对象的对象。
[[SourceText]] Unicode代码点序列 定义函数的源文本
[[Fields]] 类字段定义记录列表 如果函数是类,这是表示类的非静态字段和相应初始化器的记录列表。
[[PrivateMethods]] 私有元素列表 如果函数是类,这是表示类的非静态私有方法和访问器的列表。
[[ClassFieldInitializerName]] 一个字符串、一个Symbol、一个私有名称empty 如果函数是作为类字段的初始化器创建的,则为字段的命名评估使用的名称;否则为empty
[[IsClassConstructor]] 一个Boolean 指示函数是否为类构造器。(如果为true,调用函数的[[Call]]将立即抛出TypeError异常。)

所有ECMAScript函数对象都有此处定义的[[Call]]内部方法。同时也是构造器的ECMAScript函数另外还有[[Construct]]内部方法。

10.2.1 [[Call]] ( thisArgument, argumentsList )

ECMAScript函数对象 F[[Call]]内部方法接受参数thisArgument(一个ECMAScript语言值)和argumentsListECMAScript语言值列表),返回包含ECMAScript语言值正常完成抛出完成。调用时执行以下步骤:

  1. callerContext运行执行上下文
  2. calleeContextPrepareForOrdinaryCall(F, undefined)。
  3. 断言calleeContext现在是运行执行上下文
  4. 如果 F.[[IsClassConstructor]]true,那么
    1. error 为新创建的 TypeError 对象。
    2. 注:errorcalleeContext中使用F的关联领域记录创建。
    3. 执行上下文栈中移除calleeContext并恢复callerContext运行执行上下文
    4. 返回 ThrowCompletion(error)。
  5. 执行 OrdinaryCallBindThis(F, calleeContext, thisArgument)。
  6. resultCompletion(OrdinaryCallEvaluateBody(F, argumentsList))。
  7. 执行上下文栈中移除calleeContext并恢复callerContext运行执行上下文
  8. 如果 result返回完成,返回 result.[[Value]]
  9. 断言result抛出完成
  10. 返回 ? result

当在步骤7中从执行上下文栈中移除calleeContext时,如果它被挂起并保留以供可访问的生成器稍后恢复,则不得销毁它。

10.2.1.1 PrepareForOrdinaryCall ( F, newTarget )

抽象操作PrepareForOrdinaryCall接受参数F(一个ECMAScript函数对象)和newTarget(一个Object或undefined),返回一个执行上下文。调用时执行以下步骤:

  1. callerContext运行执行上下文
  2. calleeContext 为新的ECMAScript代码执行上下文
  3. 设置 calleeContext 的Function为 F
  4. calleeRealmF.[[Realm]]
  5. 设置 calleeContext领域calleeRealm
  6. 设置 calleeContext 的ScriptOrModule为 F.[[ScriptOrModule]]
  7. localEnvNewFunctionEnvironment(F, newTarget)。
  8. 设置 calleeContext 的LexicalEnvironment为 localEnv
  9. 设置 calleeContext 的VariableEnvironment为 localEnv
  10. 设置 calleeContext 的PrivateEnvironment为 F.[[PrivateEnvironment]]
  11. 如果 callerContext 尚未挂起,挂起 callerContext
  12. calleeContext 推入执行上下文栈calleeContext现在是运行执行上下文
  13. 注:此点之后产生的任何异常对象都与 calleeRealm 关联。
  14. 返回 calleeContext

10.2.1.2 OrdinaryCallBindThis ( F, calleeContext, thisArgument )

抽象操作OrdinaryCallBindThis接受参数F(一个ECMAScript函数对象)、calleeContext(一个执行上下文)和thisArgument(一个ECMAScript语言值),返回unused。调用时执行以下步骤:

  1. thisModeF.[[ThisMode]]
  2. 如果 thisModelexical,返回 unused
  3. calleeRealmF.[[Realm]]
  4. localEnvcalleeContext 的LexicalEnvironment。
  5. 如果 thisModestrict,那么
    1. thisValuethisArgument
  6. 否则,
    1. 如果 thisArgumentundefinednull,那么
      1. globalEnvcalleeRealm.[[GlobalEnv]]
      2. 断言globalEnv全局环境记录
      3. thisValueglobalEnv.[[GlobalThisValue]]
    2. 否则,
      1. thisValue 为 ! ToObject(thisArgument)。
      2. 注:ToObject使用calleeRealm产生包装器对象。
  7. 断言localEnv函数环境记录
  8. 断言:下一步永远不会返回突然完成,因为localEnv.[[ThisBindingStatus]]不是initialized
  9. 执行 ! BindThisValue(localEnv, thisValue)。
  10. 返回 unused

10.2.1.3 运行时语义:EvaluateBody

语法导向操作EvaluateBody接受参数functionObject(一个ECMAScript函数对象)和argumentsListECMAScript语言值列表),返回返回完成抛出完成。它在以下产生式上分段定义:

FunctionBody : FunctionStatementList
  1. 返回 ? FunctionBodyEvaluateFunctionBody,参数为 functionObjectargumentsList
ConciseBody : ExpressionBody
  1. 返回 ? ConciseBodyEvaluateConciseBody,参数为 functionObjectargumentsList
GeneratorBody : FunctionBody
  1. 返回 ? GeneratorBodyEvaluateGeneratorBody,参数为 functionObjectargumentsList
AsyncGeneratorBody : FunctionBody
  1. 返回 ? AsyncGeneratorBodyEvaluateAsyncGeneratorBody,参数为 functionObjectargumentsList
AsyncFunctionBody : FunctionBody
  1. 返回 ? AsyncFunctionBodyEvaluateAsyncFunctionBody,参数为 functionObjectargumentsList
AsyncConciseBody : ExpressionBody
  1. 返回 ? AsyncConciseBodyEvaluateAsyncConciseBody,参数为 functionObjectargumentsList
Initializer : = AssignmentExpression
  1. 断言argumentsList为空。
  2. 断言functionObject.[[ClassFieldInitializerName]]不是empty
  3. 如果 IsAnonymousFunctionDefinition(AssignmentExpression) 为 true,那么
    1. value 为 ? InitializerNamedEvaluation,参数为 functionObject.[[ClassFieldInitializerName]]
  4. 否则,
    1. rhs 为 ? AssignmentExpressionEvaluation
    2. value 为 ? GetValue(rhs)。
  5. 返回 ReturnCompletion(value)。

尽管字段初始化器构成函数边界,但调用FunctionDeclarationInstantiation没有任何可观察的效果,因此被省略。

ClassStaticBlockBody : ClassStaticBlockStatementList
  1. 断言argumentsList为空。
  2. 返回 ? ClassStaticBlockBodyEvaluateClassStaticBlockBody,参数为 functionObject

10.2.1.4 OrdinaryCallEvaluateBody ( F, argumentsList )

抽象操作OrdinaryCallEvaluateBody接受参数F(一个ECMAScript函数对象)和argumentsListECMAScript语言值列表),返回返回完成抛出完成。调用时执行以下步骤:

  1. 返回 ? F.[[ECMAScriptCode]]EvaluateBody,参数为 FargumentsList

10.2.2 [[Construct]] ( argumentsList, newTarget )

ECMAScript函数对象 F[[Construct]]内部方法接受参数argumentsListECMAScript语言值列表)和newTarget(一个构造器),返回包含Object的正常完成抛出完成。调用时执行以下步骤:

  1. callerContext运行执行上下文
  2. kindF.[[ConstructorKind]]
  3. 如果 kindbase,那么
    1. thisArgument 为 ? OrdinaryCreateFromConstructor(newTarget, "%Object.prototype%")。
  4. calleeContextPrepareForOrdinaryCall(F, newTarget)。
  5. 断言calleeContext现在是运行执行上下文
  6. 如果 kindbase,那么
    1. 执行 OrdinaryCallBindThis(F, calleeContext, thisArgument)。
    2. initializeResultCompletion(InitializeInstanceElements(thisArgument, F))。
    3. 如果 initializeResult突然完成,那么
      1. 执行上下文栈中移除calleeContext并恢复callerContext运行执行上下文
      2. 返回 ? initializeResult
  7. constructorEnvcalleeContext 的LexicalEnvironment。
  8. resultCompletion(OrdinaryCallEvaluateBody(F, argumentsList))。
  9. 执行上下文栈中移除calleeContext并恢复callerContext运行执行上下文
  10. 如果 result抛出完成,那么
    1. 返回 ? result
  11. 断言result返回完成
  12. 如果 result.[[Value]] 是Object,返回 result.[[Value]]
  13. 如果 kindbase,返回 thisArgument
  14. 如果 result.[[Value]] 不是 undefined,抛出 TypeError 异常。
  15. thisBinding 为 ? constructorEnv.GetThisBinding()。
  16. 断言thisBinding 是Object
  17. 返回 thisBinding

10.2.3 OrdinaryFunctionCreate ( functionPrototype, sourceText, ParameterList, Body, thisMode, env, privateEnv )

抽象操作OrdinaryFunctionCreate接受参数functionPrototype(一个Object)、sourceText(Unicode代码点序列)、ParameterList(一个解析节点)、Body(一个解析节点)、thisModelexical-thisnon-lexical-this)、env(一个环境记录)和privateEnv(一个私有环境记录null),返回一个ECMAScript函数对象。它用于指定运行时创建具有默认[[Call]]内部方法且没有[[Construct]]内部方法的新函数(尽管随后可能通过诸如MakeConstructor之类的操作添加一个)。sourceText是要创建的函数的语法定义的源文本。调用时执行以下步骤:

  1. internalSlotsList表30中列出的内部插槽。
  2. FOrdinaryObjectCreate(functionPrototype, internalSlotsList)。
  3. 设置 F.[[Call]]10.2.1中指定的定义。
  4. 设置 F.[[SourceText]]sourceText
  5. 设置 F.[[FormalParameters]]ParameterList
  6. 设置 F.[[ECMAScriptCode]]Body
  7. StrictIsStrict(Body)。
  8. 设置 F.[[Strict]]Strict
  9. 如果 thisModelexical-this,设置 F.[[ThisMode]]lexical
  10. 否则,如果 Stricttrue,设置 F.[[ThisMode]]strict
  11. 否则,设置 F.[[ThisMode]]global
  12. 设置 F.[[IsClassConstructor]]false
  13. 设置 F.[[Environment]]env
  14. 设置 F.[[PrivateEnvironment]]privateEnv
  15. 设置 F.[[ScriptOrModule]]GetActiveScriptOrModule()。
  16. 设置 F.[[Realm]]当前领域记录
  17. 设置 F.[[HomeObject]]undefined
  18. 设置 F.[[Fields]] 为新的空列表
  19. 设置 F.[[PrivateMethods]] 为新的空列表
  20. 设置 F.[[ClassFieldInitializerName]]empty
  21. lenParameterListExpectedArgumentCount
  22. 执行 SetFunctionLength(F, len)。
  23. 返回 F

10.2.4 AddRestrictedFunctionProperties ( F, realm )

抽象操作AddRestrictedFunctionProperties接受参数F(一个函数对象)和realm(一个领域记录),返回unused。调用时执行以下步骤:

  1. 断言realm.[[Intrinsics]].[[%ThrowTypeError%]]存在且已被初始化。
  2. throwerrealm.[[Intrinsics]].[[%ThrowTypeError%]]。
  3. 执行 ! DefinePropertyOrThrow(F, "caller", PropertyDescriptor { [[Get]]: thrower, [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: true })。
  4. 执行 ! DefinePropertyOrThrow(F, "arguments", PropertyDescriptor { [[Get]]: thrower, [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: true })。
  5. 返回 unused

10.2.4.1 %ThrowTypeError% ( )

此函数是%ThrowTypeError%内在对象。

它是一个匿名的内置函数对象,为每个领域定义一次。

调用时执行以下步骤:

  1. 抛出 TypeError 异常。

此函数的[[Extensible]]内部插槽的值为false

此函数的"length"属性具有特性{ [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

此函数的"name"属性具有特性{ [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

10.2.5 MakeConstructor ( F [ , writablePrototype [ , prototype ] ] )

抽象操作MakeConstructor接受参数F(一个ECMAScript函数对象或内置函数对象)和可选参数writablePrototype(一个Boolean)和prototype(一个Object),返回unused。它将F转换为构造器。调用时执行以下步骤:

  1. 如果 F 是ECMAScript函数对象,那么
    1. 断言IsConstructor(F) 为 false
    2. 断言F是一个可扩展对象,且没有"prototype"自身属性。
    3. 设置 F.[[Construct]]10.2.2中指定的定义。
  2. 否则,
    1. 设置 F.[[Construct]]10.3.2中指定的定义。
  3. 设置 F.[[ConstructorKind]]base
  4. 如果 writablePrototype 不存在,设置 writablePrototypetrue
  5. 如果 prototype 不存在,那么
    1. 设置 prototypeOrdinaryObjectCreate(%Object.prototype%)。
    2. 执行 ! DefinePropertyOrThrow(prototype, "constructor", PropertyDescriptor { [[Value]]: F, [[Writable]]: writablePrototype, [[Enumerable]]: false, [[Configurable]]: true })。
  6. 执行 ! DefinePropertyOrThrow(F, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: writablePrototype, [[Enumerable]]: false, [[Configurable]]: false })。
  7. 返回 unused

10.2.6 MakeClassConstructor ( F )

抽象操作MakeClassConstructor接受参数F(一个ECMAScript函数对象),返回unused。调用时执行以下步骤:

  1. 断言F.[[IsClassConstructor]]false
  2. 设置 F.[[IsClassConstructor]]true
  3. 返回 unused

10.2.7 MakeMethod ( F, homeObject )

抽象操作MakeMethod接受参数F(一个ECMAScript函数对象)和homeObject(一个Object),返回unused。它将F配置为方法。调用时执行以下步骤:

  1. 断言homeObject普通对象
  2. 设置 F.[[HomeObject]]homeObject
  3. 返回 unused

10.2.8 DefineMethodProperty ( homeObject, key, closure, enumerable )

抽象操作DefineMethodProperty接受参数homeObject(一个Object)、key(一个属性键私有名称)、closure(一个函数对象)和enumerable(一个Boolean),返回包含私有元素unused正常完成,或突然完成。调用时执行以下步骤:

  1. 断言homeObject是普通的、可扩展的对象。
  2. 如果 key私有名称,那么
    1. 返回 私有元素 { [[Key]]: key, [[Kind]]: method, [[Value]]: closure }。
  3. 否则,
    1. desc 为PropertyDescriptor { [[Value]]: closure, [[Writable]]: true, [[Enumerable]]: enumerable, [[Configurable]]: true }。
    2. 执行 ? DefinePropertyOrThrow(homeObject, key, desc)。
    3. 注:DefinePropertyOrThrow仅在尝试定义key"prototype"的类静态方法时返回突然完成
    4. 返回 unused

10.2.9 SetFunctionName ( F, name [ , prefix ] )

抽象操作SetFunctionName接受参数F(一个函数对象)和name(一个属性键私有名称)和可选参数prefix(一个String),返回unused。它为F添加"name"属性。调用时执行以下步骤:

  1. 断言F是可扩展对象且没有"name"自身属性。
  2. 如果 name 是Symbol,那么
    1. descriptionname[[Description]]值。
    2. 如果 descriptionundefined,设置 name 为空字符串。
    3. 否则,设置 name"["description"]"字符串连接
  3. 否则,如果 name私有名称,那么
    1. 设置 namename.[[Description]]
  4. 如果 F[[InitialName]]内部插槽,那么
    1. 设置 F.[[InitialName]]name
  5. 如果 prefix 存在,那么
    1. 设置 nameprefix、代码单元0x0020(空格)和name字符串连接
    2. 如果 F[[InitialName]]内部插槽,那么
      1. 可选地,设置 F.[[InitialName]]name
  6. 执行 ! DefinePropertyOrThrow(F, "name", PropertyDescriptor { [[Value]]: name, [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true })。
  7. 返回 unused

10.2.10 SetFunctionLength ( F, length )

抽象操作SetFunctionLength接受参数F(一个函数对象)和length(非负整数或+∞),返回unused。它为F添加"length"属性。调用时执行以下步骤:

  1. 断言F是可扩展对象且没有"length"自身属性。
  2. 执行 ! DefinePropertyOrThrow(F, "length", PropertyDescriptor { [[Value]]: 𝔽(length), [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true })。
  3. 返回 unused

10.2.11 FunctionDeclarationInstantiation ( func, argumentsList )

抽象操作FunctionDeclarationInstantiation接受参数func(一个ECMAScript函数对象)和argumentsListECMAScript语言值列表),返回包含unused正常完成突然完成func是正在为其建立执行上下文函数对象

注1

当为评估ECMAScript函数建立执行上下文时,会创建新的函数环境记录,并在该环境记录中实例化每个形参的绑定。函数体中的每个声明也会被实例化。如果函数的形参不包含任何默认值初始化器,则函数体声明会在与参数相同的环境记录中实例化。如果存在默认值参数初始化器,则为函数体声明创建第二个环境记录。形参和函数作为FunctionDeclarationInstantiation的一部分被初始化。所有其他绑定在函数体评估期间被初始化。

调用时执行以下步骤:

  1. calleeContext运行执行上下文
  2. codefunc.[[ECMAScriptCode]]
  3. strictfunc.[[Strict]]
  4. formalsfunc.[[FormalParameters]]
  5. parameterNamesformalsBoundNames
  6. 如果 parameterNames 有任何重复条目,令 hasDuplicatestrue。否则,令 hasDuplicatesfalse
  7. simpleParameterListformalsIsSimpleParameterList
  8. hasParameterExpressionsformalsContainsExpression
  9. varNamescodeVarDeclaredNames
  10. varDeclarationscodeVarScopedDeclarations
  11. lexicalNamescodeLexicallyDeclaredNames
  12. functionNames 为新的空列表
  13. functionsToInitialize 为新的空列表
  14. 对于 varDeclarations 的每个元素 d,按反向列表顺序,执行
    1. 如果 d 既不是VariableDeclaration,也不是ForBinding,也不是BindingIdentifier,那么
      1. 断言d 要么是FunctionDeclaration,要么是GeneratorDeclaration,要么是AsyncFunctionDeclaration,要么是AsyncGeneratorDeclaration
      2. fndBoundNames的唯一元素。
      3. 如果 functionNames 不包含 fn,那么
        1. fn 作为第一个元素插入 functionNames
        2. 注:如果有多个同名函数声明,使用最后一个声明。
        3. d 作为第一个元素插入 functionsToInitialize
  15. argumentsObjectNeededtrue
  16. 如果 func.[[ThisMode]]lexical,那么
    1. 注:箭头函数从不有arguments对象。
    2. 设置 argumentsObjectNeededfalse
  17. 否则,如果 parameterNames 包含 "arguments",那么
    1. 设置 argumentsObjectNeededfalse
  18. 否则,如果 hasParameterExpressionsfalse,那么
    1. 如果 functionNames 包含 "arguments"lexicalNames 包含 "arguments",那么
      1. 设置 argumentsObjectNeededfalse
  19. 如果 stricttruehasParameterExpressionsfalse,那么
    1. 注:由于严格模式代码中对eval的调用不能创建在eval之外可见的新绑定,因此参数只需要单一的环境记录
    2. envcalleeContext 的LexicalEnvironment。
  20. 否则,
    1. 注:需要单独的环境记录以确保形参列表中直接eval调用创建的绑定位于声明参数的环境之外。
    2. calleeEnvcalleeContext 的LexicalEnvironment。
    3. envNewDeclarativeEnvironment(calleeEnv)。
    4. 断言calleeContext 的VariableEnvironment和 calleeEnv 是同一个环境记录
    5. 设置 calleeContext 的LexicalEnvironment为 env
  21. 对于 parameterNames 的每个字符串 paramName,执行
    1. alreadyDeclared 为 ! env.HasBinding(paramName)。
    2. 注:早期错误确保重复参数名只能出现在没有参数默认值或剩余参数的非严格函数中。
    3. 如果 alreadyDeclaredfalse,那么
      1. 执行 ! env.CreateMutableBinding(paramName, false)。
      2. 如果 hasDuplicatestrue,那么
        1. 执行 ! env.InitializeBinding(paramName, undefined)。
  22. 如果 argumentsObjectNeededtrue,那么
    1. 如果 stricttruesimpleParameterListfalse,那么
      1. aoCreateUnmappedArgumentsObject(argumentsList)。
    2. 否则,
      1. 注:映射的参数对象仅为没有剩余参数、任何参数默认值初始化器或任何解构参数的非严格函数提供。
      2. aoCreateMappedArgumentsObject(func, formals, argumentsList, env)。
    3. 如果 stricttrue,那么
      1. 执行 ! env.CreateImmutableBinding("arguments", false)。
      2. 注:在严格模式代码中,早期错误防止尝试赋值给此绑定,因此其可变性不可观察。
    4. 否则,
      1. 执行 ! env.CreateMutableBinding("arguments", false)。
    5. 执行 ! env.InitializeBinding("arguments", ao)。
    6. parameterBindingsparameterNames 和 « "arguments" » 的列表连接
  23. 否则,
    1. parameterBindingsparameterNames
  24. iteratorRecordCreateListIteratorRecord(argumentsList)。
  25. 如果 hasDuplicatestrue,那么
    1. 执行 ? formalsIteratorBindingInitialization,参数为 iteratorRecordundefined
  26. 否则,
    1. 执行 ? formalsIteratorBindingInitialization,参数为 iteratorRecordenv
  27. 如果 hasParameterExpressionsfalse,那么
    1. 注:参数和顶级var只需要单一的环境记录
    2. instantiatedVarNames列表 parameterBindings 的副本。
    3. 对于 varNames 的每个元素 n,执行
      1. 如果 instantiatedVarNames 不包含 n,那么
        1. n 追加到 instantiatedVarNames
        2. 执行 ! env.CreateMutableBinding(n, false)。
        3. 执行 ! env.InitializeBinding(n, undefined)。
    4. varEnvenv
  28. 否则,
    1. 注:需要单独的环境记录以确保形参列表中表达式创建的闭包不能看到函数体中的声明。
    2. varEnvNewDeclarativeEnvironment(env)。
    3. 设置 calleeContext 的VariableEnvironment为 varEnv
    4. instantiatedVarNames 为新的空列表
    5. 对于 varNames 的每个元素 n,执行
      1. 如果 instantiatedVarNames 不包含 n,那么
        1. n 追加到 instantiatedVarNames
        2. 执行 ! varEnv.CreateMutableBinding(n, false)。
        3. 如果 parameterBindings 不包含 n,或如果 functionNames 包含 n,那么
          1. initialValueundefined
        4. 否则,
          1. initialValue 为 ! env.GetBindingValue(n, false)。
        5. 执行 ! varEnv.InitializeBinding(n, initialValue)。
        6. 注:与形参同名的var最初具有与相应初始化参数相同的值。
  29. 注:附录B.3.2.1在此处添加了额外的步骤。
  30. 如果 strictfalse,那么
    1. lexEnvNewDeclarativeEnvironment(varEnv)。
    2. 注:非严格函数对顶级词法声明使用单独的环境记录,以便直接eval可以确定eval代码引入的任何var作用域声明是否与预先存在的顶级词法作用域声明冲突。这对于严格函数不是必需的,因为严格的直接eval总是将所有声明放入新的环境记录中。
  31. 否则,
    1. lexEnvvarEnv
  32. 设置 calleeContext 的LexicalEnvironment为 lexEnv
  33. lexDeclarationscodeLexicallyScopedDeclarations
  34. 对于 lexDeclarations 的每个元素 d,执行
    1. 注:词法声明的名称不能与函数/生成器声明、形参或var名称相同。词法声明的名称仅在此处实例化但未初始化。
    2. 对于 dBoundNames的每个元素 dn,执行
      1. 如果 dIsConstantDeclarationtrue,那么
        1. 执行 ! lexEnv.CreateImmutableBinding(dn, true)。
      2. 否则,
        1. 执行 ! lexEnv.CreateMutableBinding(dn, false)。
  35. privateEnvcalleeContext 的PrivateEnvironment。
  36. 对于 functionsToInitialize 的每个解析节点 f,执行
    1. fnfBoundNames的唯一元素。
    2. fofInstantiateFunctionObject,参数为 lexEnvprivateEnv
    3. 执行 ! varEnv.SetMutableBinding(fn, fo, false)。
  37. 返回 unused
注2

B.3.2为上述算法提供了扩展,这对于与早于ECMAScript 2015的ECMAScript的Web浏览器实现的向后兼容性是必需的。

10.3 内置函数对象

内置函数对象普通对象;它必须满足10.1中规定的普通对象的要求。

除了每个普通对象所需的内部插槽(见10.1)之外,内置函数对象还必须具有以下内部插槽:

  • [[Realm]],一个领域记录,表示创建函数的领域
  • [[InitialName]],一个字符串,是函数的初始名称。它被20.2.3.5使用。

内置函数对象[[Prototype]]内部插槽的初始值是%Function.prototype%,除非另有规定。

内置函数对象必须具有符合10.3.1中定义的[[Call]]内部方法。

内置函数对象当且仅当它被描述为"构造器",或者本规范中的某个算法明确设置其[[Construct]]内部方法时,才具有[[Construct]]内部方法。这样的[[Construct]]内部方法必须符合10.3.2中的定义。

实现可以提供本规范中未定义的其他内置函数对象

10.3.1 [[Call]] ( thisArgument, argumentsList )

内置函数对象 F[[Call]]内部方法接受参数thisArgumentECMAScript语言值)和argumentsListECMAScript语言值列表),返回包含ECMAScript语言值正常完成抛出完成。调用时执行以下步骤:

  1. 返回 ? BuiltinCallOrConstruct(F, thisArgument, argumentsList, undefined)。

10.3.2 [[Construct]] ( argumentsList, newTarget )

内置函数对象 F[[Construct]]内部方法(当该方法存在时)接受参数argumentsListECMAScript语言值列表)和newTarget(一个构造器),返回包含Object的正常完成抛出完成。调用时执行以下步骤:

  1. result 为 ? BuiltinCallOrConstruct(F, uninitialized, argumentsList, newTarget)。
  2. 断言result 是Object
  3. 返回 result

10.3.3 BuiltinCallOrConstruct ( F, thisArgument, argumentsList, newTarget )

抽象操作BuiltinCallOrConstruct接受参数F(内置函数对象)、thisArgumentECMAScript语言值uninitialized)、argumentsListECMAScript语言值列表)和newTarget构造器undefined),返回包含ECMAScript语言值正常完成抛出完成。调用时执行以下步骤:

  1. callerContext运行执行上下文
  2. 如果 callerContext 尚未被挂起,挂起 callerContext
  3. calleeContext 为新的执行上下文
  4. 设置 calleeContext 的Function为 F
  5. calleeRealmF.[[Realm]]
  6. 设置 calleeContext领域calleeRealm
  7. 设置 calleeContext 的ScriptOrModule为 null
  8. 执行 calleeContext 的任何必要的实现定义的初始化。
  9. calleeContext 推入执行上下文栈calleeContext 现在是运行执行上下文
  10. result完成记录,其为评估结果,以符合 F 规范的方式评估 F。如果 thisArgumentuninitialized,则 this 值未初始化;否则,thisArgument 提供 this 值。argumentsList 提供具名参数。newTarget 提供NewTarget值。
  11. 注:如果 F 在本文档中定义,"F 的规范"是通过算法步骤或其他方式为其指定的行为。
  12. 执行上下文栈中移除 calleeContext 并将 callerContext 恢复为运行执行上下文
  13. 返回 ? result

当从执行上下文栈中移除 calleeContext 时,如果它已被挂起并被可访问的生成器保留以供稍后恢复,则不得销毁它。

10.3.4 CreateBuiltinFunction ( behaviour, length, name, additionalInternalSlotsList [ , realm [ , prototype [ , prefix ] ] ] )

抽象操作CreateBuiltinFunction接受参数behaviour抽象闭包、一组算法步骤或本规范中提供的函数行为的某些其他定义)、length(非负整数或+∞)、name属性键私有名称)和additionalInternalSlotsList(内部插槽名称的列表)和可选参数realm领域记录)、prototype(Object或null)和prefix(字符串),返回内置函数对象additionalInternalSlotsList 包含必须作为对象的一部分定义的其他内部插槽的名称。此操作创建内置函数对象。调用时执行以下步骤:

  1. 如果 realm 不存在,设置 realm当前领域记录
  2. 如果 prototype 不存在,设置 prototyperealm.[[Intrinsics]].[[%Function.prototype%]]。
  3. internalSlotsList列表,包含10.3为即将创建的内置函数对象所需的所有内部插槽的名称。
  4. additionalInternalSlotsList 的元素追加到 internalSlotsList
  5. func 为新的内置函数对象,当调用时,使用提供的参数作为 behaviour 指定的相应参数的值,执行 behaviour 描述的操作。新的函数对象具有名称为 internalSlotsList 元素的内部插槽,以及 [[InitialName]] 内部插槽。
  6. 设置 func.[[Prototype]]prototype
  7. 设置 func.[[Extensible]]true
  8. 设置 func.[[Realm]]realm
  9. 设置 func.[[InitialName]]null
  10. 执行 SetFunctionLength(func, length)。
  11. 如果 prefix 不存在,那么
    1. 执行 SetFunctionName(func, name)。
  12. 否则,
    1. 执行 SetFunctionName(func, name, prefix)。
  13. 返回 func

本规范中定义的每个内置函数都是通过调用CreateBuiltinFunction抽象操作创建的。

10.4 内置异质对象内部方法和插槽

本规范定义了几种内置异质对象。这些对象通常表现得像普通对象,除了一些特定情况。以下异质对象使用普通对象的内部方法,除非在下面明确指定了其他方法:

10.4.1 绑定函数异质对象

绑定函数异质对象是一个异质对象,它包装另一个函数对象绑定函数异质对象是可调用的(它有[[Call]]内部方法,可能有[[Construct]]内部方法)。调用绑定函数异质对象通常会调用其包装的函数。

如果对象的[[Call]]和(如果适用)[[Construct]]内部方法使用以下实现,其他基本内部方法使用10.1中的定义,则该对象是绑定函数异质对象。这些方法在BoundFunctionCreate中安装。

绑定函数异质对象没有表30中列出的ECMAScript函数对象的内部插槽。相反,除了[[Prototype]][[Extensible]]之外,它们还有表31中列出的内部插槽。

表31:绑定函数异质对象的内部插槽
内部插槽 类型 描述
[[BoundTargetFunction]] 可调用对象 被包装的函数对象
[[BoundThis]] ECMAScript语言值 调用包装函数时总是作为this值传递的值。
[[BoundArguments]] ECMAScript语言值列表 一个值列表,其元素用作对包装函数的任何调用的前几个参数。

10.4.1.1 [[Call]] ( thisArgument, argumentsList )

绑定函数异质对象 F[[Call]]内部方法接受参数thisArgumentECMAScript语言值)和argumentsListECMAScript语言值列表),返回包含ECMAScript语言值正常完成抛出完成。调用时执行以下步骤:

  1. targetF.[[BoundTargetFunction]]
  2. boundThisF.[[BoundThis]]
  3. boundArgsF.[[BoundArguments]]
  4. argsboundArgsargumentsList列表连接
  5. 返回 ? Call(target, boundThis, args)。

10.4.1.2 [[Construct]] ( argumentsList, newTarget )

绑定函数异质对象 F[[Construct]]内部方法接受参数argumentsListECMAScript语言值列表)和newTarget构造器),返回包含对象的正常完成抛出完成。调用时执行以下步骤:

  1. targetF.[[BoundTargetFunction]]
  2. 断言IsConstructor(target) 为 true
  3. boundArgsF.[[BoundArguments]]
  4. argsboundArgsargumentsList列表连接
  5. 如果 SameValue(F, newTarget) 为 true,设置 newTargettarget
  6. 返回 ? Construct(target, args, newTarget)。

10.4.1.3 BoundFunctionCreate ( targetFunction, boundThis, boundArgs )

抽象操作BoundFunctionCreate接受参数targetFunction函数对象)、boundThisECMAScript语言值)和boundArgsECMAScript语言值列表),返回包含函数对象正常完成抛出完成。它用于指定新绑定函数异质对象的创建。调用时执行以下步骤:

  1. proto 为 ? targetFunction.[[GetPrototypeOf]]()。
  2. internalSlotsList 为 « [[Prototype]], [[Extensible]] » 和表31中列出的内部插槽的列表连接
  3. objMakeBasicObject(internalSlotsList)。
  4. 设置 obj.[[Prototype]]proto
  5. 按照10.4.1.1中的描述设置 obj.[[Call]]
  6. 如果 IsConstructor(targetFunction) 为 true,那么
    1. 按照10.4.1.2中的描述设置 obj.[[Construct]]
  7. 设置 obj.[[BoundTargetFunction]]targetFunction
  8. 设置 obj.[[BoundThis]]boundThis
  9. 设置 obj.[[BoundArguments]]boundArgs
  10. 返回 obj

10.4.2 数组异质对象

数组是一个异质对象,它对数组索引属性键给予特殊处理(见6.1.7)。属性名数组索引的属性也称为元素。每个数组都有一个不可配置的"length"属性,其值始终是非负整数,其数学值严格小于232"length"属性的值在数值上大于名称为数组索引的每个自有属性的名称;每当创建或更改数组的自有属性时,会根据需要调整其他属性以维持此不变性。具体来说,每当添加名称为数组索引的自有属性时,如有必要,"length"属性的值会更改为该数组索引的数值加一;每当"length"属性的值更改时,名称为数组索引且值不小于新长度的每个自有属性都会被删除。此约束仅适用于数组的自有属性,不受可能从其原型继承的"length"数组索引属性的影响。

如果对象的[[DefineOwnProperty]]内部方法使用以下实现,其他基本内部方法使用10.1中的定义,则该对象是数组异质对象(或简称数组)。这些方法在ArrayCreate中安装。

10.4.2.1 [[DefineOwnProperty]] ( P, Desc )

数组异质对象 A[[DefineOwnProperty]]内部方法接受参数P属性键)和Desc属性描述符),返回包含布尔值的正常完成抛出完成。调用时执行以下步骤:

  1. 如果 P"length",那么
    1. 返回 ? ArraySetLength(A, Desc)。
  2. 否则,如果 P数组索引,那么
    1. lengthDescOrdinaryGetOwnProperty(A, "length")。
    2. 断言lengthDesc 不是 undefined
    3. 断言IsDataDescriptor(lengthDesc) 为 true
    4. 断言lengthDesc.[[Configurable]]false
    5. lengthlengthDesc.[[Value]]
    6. 断言length 是非负整数
    7. index 为 ! ToUint32(P)。
    8. 如果 indexlengthlengthDesc.[[Writable]]false,返回 false
    9. succeeded 为 ! OrdinaryDefineOwnProperty(A, P, Desc)。
    10. 如果 succeededfalse,返回 false
    11. 如果 indexlength,那么
      1. 设置 lengthDesc.[[Value]]index + 1𝔽
      2. 设置 succeeded 为 ! OrdinaryDefineOwnProperty(A, "length", lengthDesc)。
      3. 断言succeededtrue
    12. 返回 true
  3. 返回 ? OrdinaryDefineOwnProperty(A, P, Desc)。

10.4.2.2 ArrayCreate ( length [ , proto ] )

抽象操作ArrayCreate接受参数length(非负整数)和可选参数proto(对象),返回包含数组异质对象正常完成抛出完成。它用于指定新数组的创建。调用时执行以下步骤:

  1. 如果 length > 232 - 1,抛出 RangeError 异常。
  2. 如果 proto 不存在,设置 proto%Array.prototype%
  3. AMakeBasicObject[[Prototype]], [[Extensible]] »)。
  4. 设置 A.[[Prototype]]proto
  5. 按照10.4.2.1中指定的设置 A.[[DefineOwnProperty]]
  6. 执行 ! OrdinaryDefineOwnProperty(A, "length", PropertyDescriptor { [[Value]]: 𝔽(length), [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  7. 返回 A

10.4.2.3 ArraySpeciesCreate ( originalArray, length )

抽象操作ArraySpeciesCreate接受参数originalArray(对象)和length(非负整数),返回包含对象的正常完成抛出完成。它用于指定使用从originalArray派生的构造器函数创建新数组或类似对象。它不强制构造器函数返回数组。调用时执行以下步骤:

  1. isArray 为 ? IsArray(originalArray)。
  2. 如果 isArrayfalse,返回 ? ArrayCreate(length)。
  3. C 为 ? Get(originalArray, "constructor")。
  4. 如果 IsConstructor(C) 为 true,那么
    1. thisRealm当前领域记录
    2. realmC 为 ? GetFunctionRealm(C)。
    3. 如果 thisRealmrealmC 不是同一个领域记录,那么
      1. 如果 SameValue(C, realmC.[[Intrinsics]].[[%Array%]]) 为 true,设置 Cundefined
  5. 如果 C 是对象,那么
    1. 设置 C 为 ? Get(C, %Symbol.species%)。
    2. 如果 Cnull,设置 Cundefined
  6. 如果 Cundefined,返回 ? ArrayCreate(length)。
  7. 如果 IsConstructor(C) 为 false,抛出 TypeError 异常。
  8. 返回 ? Construct(C, « 𝔽(length) »)。

如果originalArray是使用不是运行执行上下文领域领域的标准内置数组构造器创建的,那么使用运行执行上下文领域创建新数组。这与Web浏览器的历史行为保持兼容,这些浏览器历史上对现在使用ArraySpeciesCreate定义的Array.prototype方法有这种行为。

10.4.2.4 ArraySetLength ( A, Desc )

抽象操作ArraySetLength接受参数A(数组)和Desc属性描述符),返回包含布尔值的正常完成抛出完成。调用时执行以下步骤:

  1. 如果 Desc 没有 [[Value]] 字段,那么
    1. 返回 ! OrdinaryDefineOwnProperty(A, "length", Desc)。
  2. newLenDescDesc 的副本。
  3. newLen 为 ? ToUint32(Desc.[[Value]])。
  4. numberLen 为 ? ToNumber(Desc.[[Value]])。
  5. 如果 SameValueZero(newLen, numberLen) 为 false,抛出 RangeError 异常。
  6. 设置 newLenDesc.[[Value]]newLen
  7. oldLenDescOrdinaryGetOwnProperty(A, "length")。
  8. 断言oldLenDesc 不是 undefined
  9. 断言IsDataDescriptor(oldLenDesc) 为 true
  10. 断言oldLenDesc.[[Configurable]]false
  11. oldLenoldLenDesc.[[Value]]
  12. 如果 newLenoldLen,那么
    1. 返回 ! OrdinaryDefineOwnProperty(A, "length", newLenDesc)。
  13. 如果 oldLenDesc.[[Writable]]false,返回 false
  14. 如果 newLenDesc 没有 [[Writable]] 字段或 newLenDesc.[[Writable]]true,那么
    1. newWritabletrue
  15. 否则,
    1. 注:如果任何元素无法删除,将[[Writable]]属性设置为false会被延迟。
    2. newWritablefalse
    3. 设置 newLenDesc.[[Writable]]true
  16. succeeded 为 ! OrdinaryDefineOwnProperty(A, "length", newLenDesc)。
  17. 如果 succeededfalse,返回 false
  18. 对于 A 的每个自有属性键 P,如果 P数组索引且 ! ToUint32(P) ≥ newLen,按数值索引降序执行
    1. deleteSucceeded 为 ! A.[[Delete]](P)。
    2. 如果 deleteSucceededfalse,那么
      1. 设置 newLenDesc.[[Value]] 为 ! ToUint32(P) + 1𝔽
      2. 如果 newWritablefalse,设置 newLenDesc.[[Writable]]false
      3. 执行 ! OrdinaryDefineOwnProperty(A, "length", newLenDesc)。
      4. 返回 false
  19. 如果 newWritablefalse,那么
    1. 设置 succeeded 为 ! OrdinaryDefineOwnProperty(A, "length", PropertyDescriptor { [[Writable]]: false })。
    2. 断言succeededtrue
  20. 返回 true

在步骤34中,如果Desc.[[Value]]是对象,则其valueOf方法会被调用两次。这是传统行为,从本规范第2版开始就以此效果进行了指定。

10.4.3 字符串异质对象

字符串对象是一个异质对象,它封装一个字符串值并暴露对应于字符串值各个码元元素的虚拟整数索引的数据属性字符串异质对象总是有一个名为"length"数据属性,其值是封装的字符串值的长度。码元数据属性"length"属性都是不可写和不可配置的。

如果对象的[[GetOwnProperty]][[DefineOwnProperty]][[OwnPropertyKeys]]内部方法使用以下实现,其他基本内部方法使用10.1中的定义,则该对象是字符串异质对象(或简称字符串对象)。这些方法在StringCreate中安装。

字符串异质对象具有与普通对象相同的内部插槽。它们还有一个[[StringData]]内部插槽。

10.4.3.1 [[GetOwnProperty]] ( P )

字符串异质对象 S[[GetOwnProperty]]内部方法接受参数P属性键),返回包含属性描述符undefined正常完成。调用时执行以下步骤:

  1. descOrdinaryGetOwnProperty(S, P)。
  2. 如果 desc 不是 undefined,返回 desc
  3. 返回 StringGetOwnProperty(S, P)。

10.4.3.2 [[DefineOwnProperty]] ( P, Desc )

字符串异质对象 S[[DefineOwnProperty]]内部方法接受参数P属性键)和Desc属性描述符),返回包含布尔值的正常完成。调用时执行以下步骤:

  1. stringDescStringGetOwnProperty(S, P)。
  2. 如果 stringDesc 不是 undefined,那么
    1. extensibleS.[[Extensible]]
    2. 返回 IsCompatiblePropertyDescriptor(extensible, Desc, stringDesc)。
  3. 返回 ! OrdinaryDefineOwnProperty(S, P, Desc)。

10.4.3.3 [[OwnPropertyKeys]] ( )

字符串异质对象 O[[OwnPropertyKeys]]内部方法不接受参数,返回包含属性键列表正常完成。调用时执行以下步骤:

  1. keys 为新的空列表
  2. strO.[[StringData]]
  3. 断言str 是字符串
  4. lenstr 的长度。
  5. 对于每个整数 i,0 ≤ i < len,按升序执行
    1. 将 ! ToString(𝔽(i)) 追加到 keys
  6. 对于 O 的每个自有属性键 P,如果 P数组索引且 ! ToIntegerOrInfinity(P) ≥ len,按数值索引升序执行
    1. P 追加到 keys
  7. 对于 O 的每个自有属性键 P,如果 P 是字符串P 不是数组索引,按属性创建的时间升序执行
    1. P 追加到 keys
  8. 对于 O 的每个自有属性键 P,如果 P 是Symbol,按属性创建的时间升序执行
    1. P 追加到 keys
  9. 返回 keys

10.4.3.4 StringCreate ( value, prototype )

抽象操作StringCreate接受参数value(字符串)和prototype(对象),返回字符串异质对象。它用于指定新字符串异质对象的创建。调用时执行以下步骤:

  1. SMakeBasicObject[[Prototype]], [[Extensible]], [[StringData]] »)。
  2. 设置 S.[[Prototype]]prototype
  3. 设置 S.[[StringData]]value
  4. 按照10.4.3.1中指定的设置 S.[[GetOwnProperty]]
  5. 按照10.4.3.2中指定的设置 S.[[DefineOwnProperty]]
  6. 按照10.4.3.3中指定的设置 S.[[OwnPropertyKeys]]
  7. lengthvalue 的长度。
  8. 执行 ! DefinePropertyOrThrow(S, "length", PropertyDescriptor { [[Value]]: 𝔽(length), [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false })。
  9. 返回 S

10.4.3.5 StringGetOwnProperty ( S, P )

抽象操作StringGetOwnProperty接受参数S(具有[[StringData]]内部插槽的对象)和P属性键),返回属性描述符undefined。调用时执行以下步骤:

  1. 如果 P 不是字符串,返回 undefined
  2. indexCanonicalNumericIndexString(P)。
  3. 如果 index 不是整数,返回 undefined
  4. 如果 index-0𝔽index < -0𝔽,返回 undefined
  5. strS.[[StringData]]
  6. 断言str 是字符串
  7. lenstr 的长度。
  8. 如果 (index) ≥ len,返回 undefined
  9. resultStrstr(index) 到 (index) + 1 的子字符串
  10. 返回 PropertyDescriptor { [[Value]]: resultStr, [[Writable]]: false, [[Enumerable]]: true, [[Configurable]]: false }。

10.4.4 Arguments 异质对象

大多数ECMAScript函数向其代码提供一个arguments对象。根据函数定义的特征,其arguments对象要么是普通对象,要么是arguments异质对象Arguments异质对象是一个异质对象,其数组索引属性映射到其关联ECMAScript函数调用的形式参数绑定。

如果对象的内部方法使用以下实现,其他未在此指定的方法使用10.1中的实现,则该对象是arguments异质对象。这些方法在CreateMappedArgumentsObject中安装。

注1

虽然CreateUnmappedArgumentsObject被归组到此子句中,但它创建的是普通对象,而不是arguments异质对象

Arguments异质对象具有与普通对象相同的内部插槽。它们还有一个[[ParameterMap]]内部插槽。普通arguments对象也有一个[[ParameterMap]]内部插槽,其值始终是undefined。对于普通argument对象,[[ParameterMap]]内部插槽仅被Object.prototype.toString20.1.3.6)用于识别它们。

注2

Arguments异质对象整数索引的数据属性,其数值名称值小于对应函数对象的形式参数数量,最初与函数执行上下文中对应的参数绑定共享其值。这意味着更改属性会更改参数绑定的对应值,反之亦然。如果删除然后重新定义此类属性,或者将属性更改为访问器属性,则此对应关系会被破坏。如果arguments对象是普通对象,其属性值只是传递给函数的参数的副本,属性值与形式参数值之间没有动态链接。

注3

ParameterMap对象及其属性值被用作指定arguments对象与参数绑定对应关系的设备。ParameterMap对象和作为其属性值的对象不能从ECMAScript代码中直接观察到。ECMAScript实现不需要实际创建或使用此类对象来实现指定的语义。

注4

普通arguments对象定义一个名为"callee"的不可配置访问器属性,访问时抛出TypeError异常。"callee"属性对于arguments异质对象有更具体的含义,这些对象仅为某些类别的非严格函数创建。在普通变体中定义此属性是为了确保符合标准的ECMAScript实现不会以任何其他方式定义它。

注5

Arguments异质对象的ECMAScript实现历史上包含一个名为"caller"访问器属性。在ECMAScript 2017之前,本规范包括在普通arguments对象上定义抛出"caller"属性的定义。由于实现不再包含此扩展,ECMAScript 2017放弃了对抛出"caller"访问器的要求。

10.4.4.1 [[GetOwnProperty]] ( P )

Arguments异质对象 args[[GetOwnProperty]]内部方法接受参数P属性键),返回包含属性描述符undefined正常完成。调用时执行以下步骤:

  1. descOrdinaryGetOwnProperty(args, P)。
  2. 如果 descundefined,返回 undefined
  3. mapargs.[[ParameterMap]]
  4. isMapped 为 ! HasOwnProperty(map, P)。
  5. 如果 isMappedtrue,那么
    1. 设置 desc.[[Value]] 为 ! Get(map, P)。
  6. 返回 desc

10.4.4.2 [[DefineOwnProperty]] ( P, Desc )

Arguments异质对象 args[[DefineOwnProperty]]内部方法接受参数P属性键)和Desc属性描述符),返回包含布尔值的正常完成。调用时执行以下步骤:

  1. mapargs.[[ParameterMap]]
  2. isMapped 为 ! HasOwnProperty(map, P)。
  3. newArgDescDesc
  4. 如果 isMappedtrueIsDataDescriptor(Desc) 为 true,那么
    1. 如果 Desc 没有 [[Value]] 字段,Desc[[Writable]] 字段,且 Desc.[[Writable]]false,那么
      1. 设置 newArgDescDesc 的副本。
      2. 设置 newArgDesc.[[Value]] 为 ! Get(map, P)。
  5. allowed 为 ! OrdinaryDefineOwnProperty(args, P, newArgDesc)。
  6. 如果 allowedfalse,返回 false
  7. 如果 isMappedtrue,那么
    1. 如果 IsAccessorDescriptor(Desc) 为 true,那么
      1. 执行 ! map.[[Delete]](P)。
    2. 否则,
      1. 如果 Desc[[Value]] 字段,那么
        1. 断言:以下Set将成功,因为由arguments对象映射的形式参数总是可写的。
        2. 执行 ! Set(map, P, Desc.[[Value]], false)。
      2. 如果 Desc[[Writable]] 字段且 Desc.[[Writable]]false,那么
        1. 执行 ! map.[[Delete]](P)。
  8. 返回 true

10.4.4.3 [[Get]] ( P, Receiver )

Arguments异质对象 args[[Get]]内部方法接受参数P属性键)和ReceiverECMAScript语言值),返回包含ECMAScript语言值正常完成抛出完成。调用时执行以下步骤:

  1. mapargs.[[ParameterMap]]
  2. isMapped 为 ! HasOwnProperty(map, P)。
  3. 如果 isMappedfalse,那么
    1. 返回 ? OrdinaryGet(args, P, Receiver)。
  4. 否则,
    1. 断言map 包含 P 的形式参数映射。
    2. 返回 ! Get(map, P)。

10.4.4.4 [[Set]] ( P, V, Receiver )

Arguments异质对象 args[[Set]]内部方法接受参数P属性键)、VECMAScript语言值)和ReceiverECMAScript语言值),返回包含布尔值的正常完成抛出完成。调用时执行以下步骤:

  1. 如果 SameValue(args, Receiver) 为 false,那么
    1. isMappedfalse
  2. 否则,
    1. mapargs.[[ParameterMap]]
    2. isMapped 为 ! HasOwnProperty(map, P)。
  3. 如果 isMappedtrue,那么
    1. 断言:以下Set将成功,因为由arguments对象映射的形式参数总是可写的。
    2. 执行 ! Set(map, P, V, false)。
  4. 返回 ? OrdinarySet(args, P, V, Receiver)。

10.4.4.5 [[Delete]] ( P )

Arguments异质对象 args[[Delete]]内部方法接受参数P属性键),返回包含布尔值的正常完成抛出完成。调用时执行以下步骤:

  1. mapargs.[[ParameterMap]]
  2. isMapped 为 ! HasOwnProperty(map, P)。
  3. result 为 ? OrdinaryDelete(args, P)。
  4. 如果 resulttrueisMappedtrue,那么
    1. 执行 ! map.[[Delete]](P)。
  5. 返回 result

10.4.4.6 CreateUnmappedArgumentsObject ( argumentsList )

抽象操作CreateUnmappedArgumentsObject接受参数argumentsListECMAScript语言值列表),返回普通对象。调用时执行以下步骤:

  1. lenargumentsList 中元素的数量。
  2. objOrdinaryObjectCreate(%Object.prototype%, « [[ParameterMap]] »)。
  3. 设置 obj.[[ParameterMap]]undefined
  4. 执行 ! DefinePropertyOrThrow(obj, "length", PropertyDescriptor { [[Value]]: 𝔽(len), [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true })。
  5. index 为 0。
  6. 重复,当 index < len 时,
    1. valargumentsList[index]。
    2. 执行 ! CreateDataPropertyOrThrow(obj, ! ToString(𝔽(index)), val)。
    3. 设置 indexindex + 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, argumentsList, env )

抽象操作CreateMappedArgumentsObject接受参数func(对象)、formals解析节点)、argumentsListECMAScript语言值列表)和env环境记录),返回arguments异质对象。调用时执行以下步骤:

  1. 断言formals 不包含剩余参数、任何绑定模式或任何初始化器。它可能包含重复标识符。
  2. lenargumentsList 中元素的数量。
  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. parameterNamesformalsBoundNames
  13. numberOfParametersparameterNames 中元素的数量。
  14. index 为 0。
  15. 重复,当 index < len 时,
    1. valargumentsList[index]。
    2. 执行 ! CreateDataPropertyOrThrow(obj, ! ToString(𝔽(index)), val)。
    3. 设置 indexindex + 1。
  16. 执行 ! DefinePropertyOrThrow(obj, "length", PropertyDescriptor { [[Value]]: 𝔽(len), [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true })。
  17. mappedNames 为新的空列表
  18. 设置 indexnumberOfParameters - 1。
  19. 重复,当 index ≥ 0 时,
    1. nameparameterNames[index]。
    2. 如果 mappedNames 不包含 name,那么
      1. name 追加到 mappedNames
      2. 如果 index < len,那么
        1. gMakeArgGetter(name, env)。
        2. pMakeArgSetter(name, env)。
        3. 执行 ! map.[[DefineOwnProperty]](! ToString(𝔽(index)), PropertyDescriptor { [[Set]]: p, [[Get]]: g, [[Enumerable]]: false, [[Configurable]]: true })。
    3. 设置 indexindex - 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, env )

抽象操作MakeArgGetter接受参数name(字符串)和env环境记录),返回函数对象。它创建一个内置函数对象,执行时返回在env中为name绑定的值。调用时执行以下步骤:

  1. getterClosure 为新的抽象闭包,没有参数,捕获nameenv,调用时执行以下步骤:
    1. 返回 env.GetBindingValue(name, false)。
  2. getterCreateBuiltinFunction(getterClosure, 0, "", « »)。
  3. 注:getter 从不直接被ECMAScript代码访问。
  4. 返回 getter

10.4.4.7.2 MakeArgSetter ( name, env )

抽象操作MakeArgSetter接受参数name(字符串)和env环境记录),返回函数对象。它创建一个内置函数对象,执行时在env中为name设置绑定的值。调用时执行以下步骤:

  1. setterClosure 为新的抽象闭包,参数为(value),捕获nameenv,调用时执行以下步骤:
    1. 返回 ! env.SetMutableBinding(name, value, false)。
  2. setterCreateBuiltinFunction(setterClosure, 1, "", « »)。
  3. 注:setter 从不直接被ECMAScript代码访问。
  4. 返回 setter

10.4.5 TypedArray 异质对象

TypedArray 是一个 异质对象,它对作为 规范数字字符串属性键 执行特殊处理,使用界内的 整数索引 子集来索引统一类型的元素,并强制执行其余部分不存在且不引起原型链遍历的不变性。

因为对于任何数字 nToString(n) 都是一个 规范数字字符串,实现可以将数字视为 属性键 用于 TypedArrays,而无需实际执行字符串转换。

TypedArrays 除了与 普通对象 相同的内部插槽外,还有 [[ViewedArrayBuffer]][[ArrayLength]][[ByteOffset]][[ContentType]][[TypedArrayName]] 内部插槽。

如果一个对象的 [[PreventExtensions]][[GetOwnProperty]][[HasProperty]][[DefineOwnProperty]][[Get]][[Set]][[Delete]][[OwnPropertyKeys]] 内部方法使用本节中的定义,并且其他基本内部方法使用 10.1 中找到的定义,则该对象是一个 TypedArray。这些方法由 TypedArrayCreate 安装。

10.4.5.1 [[PreventExtensions]] ( )

TypedArray O[[PreventExtensions]] 内部方法不接受参数并返回一个 包含 布尔值的正常完成。它在被调用时执行以下步骤:

  1. 注:6.1.7.3 中指定的可扩展性相关的不变性不允许此方法在 O 可以获得(或失去然后重新获得)属性时返回 true,这可能发生在当其底层缓冲区被调整大小时具有 整数索引 名称的属性上。
  2. 如果 IsTypedArrayFixedLength(O) 是 false,返回 false
  3. 返回 OrdinaryPreventExtensions(O)。

10.4.5.2 [[GetOwnProperty]] ( P )

TypedArray O[[GetOwnProperty]] 内部方法接受参数 P(一个 属性键)并返回一个 包含 属性描述符undefined 的正常完成。它在被调用时执行以下步骤:

  1. 如果 P 是一个字符串,那么
    1. numericIndexCanonicalNumericIndexString(P)。
    2. 如果 numericIndex 不是 undefined,那么
      1. valueTypedArrayGetElement(O, numericIndex)。
      2. 如果 valueundefined,返回 undefined
      3. 返回属性描述符 { [[Value]]: value[[Writable]]: true[[Enumerable]]: true[[Configurable]]: true }。
  2. 返回 OrdinaryGetOwnProperty(O, P)。

10.4.5.3 [[HasProperty]] ( P )

TypedArray O[[HasProperty]] 内部方法接受参数 P(一个 属性键)并返回 包含 布尔值的正常完成或 抛出完成。它在被调用时执行以下步骤:

  1. 如果 P 是一个字符串,那么
    1. numericIndexCanonicalNumericIndexString(P)。
    2. 如果 numericIndex 不是 undefined,返回 IsValidIntegerIndex(O, numericIndex)。
  2. 返回 ? OrdinaryHasProperty(O, P)。

10.4.5.4 [[DefineOwnProperty]] ( P, Desc )

TypedArray O[[DefineOwnProperty]] 内部方法接受参数 P(一个 属性键)和 Desc(一个 属性描述符)并返回 包含 布尔值的正常完成或 抛出完成。它在被调用时执行以下步骤:

  1. 如果 P 是一个字符串,那么
    1. numericIndexCanonicalNumericIndexString(P)。
    2. 如果 numericIndex 不是 undefined,那么
      1. 如果 IsValidIntegerIndex(O, numericIndex) 是 false,返回 false
      2. 如果 Desc 有一个 [[Configurable]] 字段且 Desc.[[Configurable]]false,返回 false
      3. 如果 Desc 有一个 [[Enumerable]] 字段且 Desc.[[Enumerable]]false,返回 false
      4. 如果 IsAccessorDescriptor(Desc) 是 true,返回 false
      5. 如果 Desc 有一个 [[Writable]] 字段 且 Desc.[[Writable]]false,返回 false
      6. 如果 Desc 有一个 [[Value]] 字段, 执行 ? TypedArraySetElement(O, numericIndex, Desc.[[Value]])。
      7. 返回 true
  2. 返回 ! OrdinaryDefineOwnProperty(O, P, Desc)。

10.4.5.5 [[Get]] ( P, Receiver )

TypedArray O[[Get]] 内部方法接受参数 P(一个 属性键)和 Receiver(一个 ECMAScript 语言值)并返回 包含 ECMAScript 语言值 的正常完成或 抛出完成。它在被调用时执行以下步骤:

  1. 如果 P 是一个字符串,那么
    1. numericIndexCanonicalNumericIndexString(P)。
    2. 如果 numericIndex 不是 undefined,那么
      1. 返回 TypedArrayGetElement(O, numericIndex)。
  2. 返回 ? OrdinaryGet(O, P, Receiver)。

10.4.5.6 [[Set]] ( P, V, Receiver )

TypedArray O[[Set]] 内部方法接受参数 P(一个 属性键)、V(一个 ECMAScript 语言值)和 Receiver(一个 ECMAScript 语言值)并返回 包含 布尔值的正常完成或 抛出完成。它在被调用时执行以下步骤:

  1. 如果 P 是一个字符串,那么
    1. numericIndexCanonicalNumericIndexString(P)。
    2. 如果 numericIndex 不是 undefined,那么
      1. 如果 SameValue(O, Receiver) 是 true,那么
        1. 执行 ? TypedArraySetElement(O, numericIndex, V)。
        2. 返回 true
      2. 如果 IsValidIntegerIndex(O, numericIndex) 是 false,返回 true
  2. 返回 ? OrdinarySet(O, P, V, Receiver)。

10.4.5.7 [[Delete]] ( P )

TypedArray O[[Delete]] 内部方法接受参数 P(一个 属性键)并返回 包含 布尔值的正常完成。它在被调用时执行以下步骤:

  1. 如果 P 是一个字符串,那么
    1. numericIndexCanonicalNumericIndexString(P)。
    2. 如果 numericIndex 不是 undefined,那么
      1. 如果 IsValidIntegerIndex(O, numericIndex) 是 false,返回 true;否则返回 false
  2. 返回 ! OrdinaryDelete(O, P)。

10.4.5.8 [[OwnPropertyKeys]] ( )

TypedArray O[[OwnPropertyKeys]] 内部方法不接受参数并返回 包含 属性键列表 的正常完成。它在被调用时执行以下步骤:

  1. taRecordMakeTypedArrayWithBufferWitnessRecord(O, seq-cst)。
  2. keys 为一个新的空 列表
  3. 如果 IsTypedArrayOutOfBounds(taRecord) 是 false,那么
    1. lengthTypedArrayLength(taRecord)。
    2. 对于每个满足 0 ≤ i < length整数 i,按升序,执行
      1. 将 ! ToString(𝔽(i)) 追加到 keys
  4. 对于 O 的每个自己的 属性键 P,使得 P 是一个字符串P 不是一个 整数索引,按属性创建的升序时间顺序,执行
    1. P 追加到 keys
  5. 对于 O 的每个自己的 属性键 P,使得 P 是一个符号,按属性创建的升序时间顺序,执行
    1. P 追加到 keys
  6. 返回 keys

10.4.5.9 TypedArray 带缓冲区见证记录

TypedArray 带缓冲区见证记录 是一个用于封装 TypedArray 以及所查看缓冲区的缓存字节长度的 记录 值。当所查看的缓冲区是 可增长的 SharedArrayBuffer 时,它用于帮助确保字节长度数据块的单个共享内存读取事件。

TypedArray 带缓冲区见证记录具有 表 32 中列出的字段。

表 32:TypedArray 带缓冲区见证记录 字段
字段名称 含义
[[Object]] 一个 TypedArray 其缓冲区字节长度被加载的 TypedArray
[[CachedBufferByteLength]] 一个非负 整数detached 创建 记录 时对象的 [[ViewedArrayBuffer]] 的字节长度。

10.4.5.10 MakeTypedArrayWithBufferWitnessRecord ( obj, order )

抽象操作 MakeTypedArrayWithBufferWitnessRecord 接受参数 obj(一个 TypedArray)和 orderseq-cstunordered)并返回一个 TypedArray 带缓冲区见证记录。它在被调用时执行以下步骤:

  1. bufferobj.[[ViewedArrayBuffer]]
  2. 如果 IsDetachedBuffer(buffer) 是 true,那么
    1. byteLengthdetached
  3. 否则,
    1. byteLengthArrayBufferByteLength(buffer, order)。
  4. 返回 TypedArray 带缓冲区见证记录 { [[Object]]: obj, [[CachedBufferByteLength]]: byteLength }。

10.4.5.11 TypedArrayCreate ( prototype )

抽象操作 TypedArrayCreate 接受参数 prototype(一个对象)并返回一个 TypedArray。它用于指定新 TypedArrays 的创建。它在被调用时执行以下步骤:

  1. internalSlotsList 为 « [[Prototype]][[Extensible]][[ViewedArrayBuffer]][[TypedArrayName]][[ContentType]][[ByteLength]][[ByteOffset]][[ArrayLength]] »。
  2. AMakeBasicObject(internalSlotsList)。
  3. 设置 A.[[PreventExtensions]]10.4.5.1 中所指定。
  4. 设置 A.[[GetOwnProperty]]10.4.5.2 中所指定。
  5. 设置 A.[[HasProperty]]10.4.5.3 中所指定。
  6. 设置 A.[[DefineOwnProperty]]10.4.5.4 中所指定。
  7. 设置 A.[[Get]]10.4.5.5 中所指定。
  8. 设置 A.[[Set]]10.4.5.6 中所指定。
  9. 设置 A.[[Delete]]10.4.5.7 中所指定。
  10. 设置 A.[[OwnPropertyKeys]]10.4.5.8 中所指定。
  11. 设置 A.[[Prototype]]prototype
  12. 返回 A

10.4.5.12 TypedArrayByteLength ( taRecord )

抽象操作 TypedArrayByteLength 接受参数 taRecord(一个 TypedArray 带缓冲区见证记录)并返回一个非负 整数。它在被调用时执行以下步骤:

  1. 如果 IsTypedArrayOutOfBounds(taRecord) 是 true,返回 0。
  2. lengthTypedArrayLength(taRecord)。
  3. 如果 length = 0,返回 0。
  4. OtaRecord.[[Object]]
  5. 如果 O.[[ByteLength]] 不是 auto,返回 O.[[ByteLength]]
  6. elementSizeTypedArrayElementSize(O)。
  7. 返回 length × elementSize

10.4.5.13 TypedArrayLength ( taRecord )

抽象操作 TypedArrayLength 接受参数 taRecord(一个 TypedArray 带缓冲区见证记录)并返回一个非负 整数。它在被调用时执行以下步骤:

  1. 断言IsTypedArrayOutOfBounds(taRecord) 是 false
  2. OtaRecord.[[Object]]
  3. 如果 O.[[ArrayLength]] 不是 auto,返回 O.[[ArrayLength]]
  4. 断言IsFixedLengthArrayBuffer(O.[[ViewedArrayBuffer]]) 是 false
  5. byteOffsetO.[[ByteOffset]]
  6. elementSizeTypedArrayElementSize(O)。
  7. byteLengthtaRecord.[[CachedBufferByteLength]]
  8. 断言byteLength 不是 detached
  9. 返回 floor((byteLength - byteOffset) / elementSize)。

10.4.5.14 IsTypedArrayOutOfBounds ( taRecord )

抽象操作 IsTypedArrayOutOfBounds 接受参数 taRecord(一个 TypedArray 带缓冲区见证记录)并返回一个布尔值。它检查对象的任何数字属性是否引用了在底层缓冲区边界内不包含的索引处的值。它在被调用时执行以下步骤:

  1. OtaRecord.[[Object]]
  2. bufferByteLengthtaRecord.[[CachedBufferByteLength]]
  3. 断言IsDetachedBuffer(O.[[ViewedArrayBuffer]]) 是 true 当且仅当 bufferByteLengthdetached
  4. 如果 bufferByteLengthdetached,返回 true
  5. byteOffsetStartO.[[ByteOffset]]
  6. 如果 O.[[ArrayLength]]auto,那么
    1. byteOffsetEndbufferByteLength
  7. 否则,
    1. elementSizeTypedArrayElementSize(O)。
    2. byteOffsetEndbyteOffsetStart + O.[[ArrayLength]] × elementSize
  8. 如果 byteOffsetStart > bufferByteLengthbyteOffsetEnd > bufferByteLength,返回 true
  9. 注:0长度的 TypedArrays 不被认为是越界的。
  10. 返回 false

10.4.5.15 IsTypedArrayFixedLength ( O )

抽象操作 IsTypedArrayFixedLength 接受参数 O(一个 TypedArray)并返回一个布尔值。它在被调用时执行以下步骤:

  1. 如果 O.[[ArrayLength]]auto,返回 false
  2. bufferO.[[ViewedArrayBuffer]]
  3. 如果 IsFixedLengthArrayBuffer(buffer) 是 falseIsSharedArrayBuffer(buffer) 是 false,返回 false
  4. 返回 true

10.4.5.16 IsValidIntegerIndex ( O, index )

抽象操作 IsValidIntegerIndex 接受参数 O(一个 TypedArray)和 index(一个数字)并返回一个布尔值。它在被调用时执行以下步骤:

  1. 如果 IsDetachedBuffer(O.[[ViewedArrayBuffer]]) 是 true,返回 false
  2. 如果 index 不是一个 整数数字,返回 false
  3. 如果 index-0𝔽index < -0𝔽,返回 false
  4. taRecordMakeTypedArrayWithBufferWitnessRecord(O, unordered)。
  5. 注:当 O 的支持缓冲区是 可增长的 SharedArrayBuffer 时,边界检查不是同步操作。
  6. 如果 IsTypedArrayOutOfBounds(taRecord) 是 true,返回 false
  7. lengthTypedArrayLength(taRecord)。
  8. 如果 (index) ≥ length,返回 false
  9. 返回 true

10.4.5.17 TypedArrayGetElement ( O, index )

抽象操作 TypedArrayGetElement 接受参数 O(一个 TypedArray)和 index(一个数字)并返回一个数字、一个 BigInt 或 undefined。它在被调用时执行以下步骤:

  1. 如果 IsValidIntegerIndex(O, index) 是 false,返回 undefined
  2. offsetO.[[ByteOffset]]
  3. elementSizeTypedArrayElementSize(O)。
  4. byteIndexInBuffer 为 ((index) × elementSize) + offset
  5. elementTypeTypedArrayElementType(O)。
  6. 返回 GetValueFromBuffer(O.[[ViewedArrayBuffer]], byteIndexInBuffer, elementType, true, unordered)。

10.4.5.18 TypedArraySetElement ( O, index, value )

抽象操作 TypedArraySetElement 接受参数 O(一个 TypedArray)、index(一个数字)和 value(一个 ECMAScript 语言值)并返回 包含 unused 的正常完成或 抛出完成。它在被调用时执行以下步骤:

  1. 如果 O.[[ContentType]]bigint,让 numValue 为 ? ToBigInt(value)。
  2. 否则,让 numValue 为 ? ToNumber(value)。
  3. 如果 IsValidIntegerIndex(O, index) 是 true,那么
    1. offsetO.[[ByteOffset]]
    2. elementSizeTypedArrayElementSize(O)。
    3. byteIndexInBuffer 为 ((index) × elementSize) + offset
    4. elementTypeTypedArrayElementType(O)。
    5. 执行 SetValueInBuffer(O.[[ViewedArrayBuffer]], byteIndexInBuffer, elementType, numValue, true, unordered)。
  4. 返回 unused

此操作总是显得成功,但是当尝试写入 TypedArray 的末尾之外或写入由分离的 ArrayBuffer 支持的 TypedArray 时,它没有效果。

10.4.5.19 IsArrayBufferViewOutOfBounds ( O )

抽象操作 IsArrayBufferViewOutOfBounds 接受参数 O(一个 TypedArray 或一个 DataView)并返回一个布尔值。它检查 TypedArray 的任何数字属性或 DataView 对象的方法是否可以引用在底层数据块边界内不包含的索引处的值。此抽象操作作为上游规范的便利而存在。它在被调用时执行以下步骤:

  1. 如果 O 有一个 [[DataView]] 内部插槽,那么
    1. viewRecordMakeDataViewWithBufferWitnessRecord(O, seq-cst)。
    2. 返回 IsViewOutOfBounds(viewRecord)。
  2. taRecordMakeTypedArrayWithBufferWitnessRecord(O, seq-cst)。
  3. 返回 IsTypedArrayOutOfBounds(taRecord)。

10.4.6 模块命名空间异质对象

模块命名空间异质对象 是一个 异质对象,它暴露从 ECMAScript 模块 导出的绑定(参见 16.2.3)。模块命名空间异质对象 的字符串键自己的属性与 模块 导出的绑定名称之间存在一对一的对应关系。导出的绑定包括使用 export * 导出项间接导出的任何绑定。每个字符串值自己的 属性键 是对应导出绑定名称的 StringValue。这些是 模块命名空间异质对象 的唯一字符串键属性。每个这样的属性都具有属性 { [[Writable]]: true[[Enumerable]]: true[[Configurable]]: false }。模块命名空间异质对象 是不可扩展的。

如果一个对象的 [[GetPrototypeOf]][[SetPrototypeOf]][[IsExtensible]][[PreventExtensions]][[GetOwnProperty]][[DefineOwnProperty]][[HasProperty]][[Get]][[Set]][[Delete]][[OwnPropertyKeys]] 内部方法使用本节中的定义,并且其他基本内部方法使用 10.1 中找到的定义,则该对象是一个 模块命名空间异质对象。这些方法由 ModuleNamespaceCreate 安装。

模块命名空间异质对象 具有 表 33 中定义的内部插槽。

表 33:模块命名空间异质对象的内部插槽
内部插槽 类型 描述
[[Module]] 一个 模块记录 此命名空间暴露其导出的 模块记录
[[Exports]] 一个字符串的 列表 一个 列表,其元素是作为此对象自己的属性暴露的导出名称的字符串值。该列表按 字典代码单元顺序 排序。

10.4.6.1 [[GetPrototypeOf]] ( )

模块命名空间异质对象[[GetPrototypeOf]] 内部方法不接受参数并返回 包含 null 的正常完成。它在被调用时执行以下步骤:

  1. 返回 null

10.4.6.2 [[SetPrototypeOf]] ( V )

模块命名空间异质对象 O[[SetPrototypeOf]] 内部方法接受参数 V(一个对象或 null)并返回 包含 布尔值的正常完成。它在被调用时执行以下步骤:

  1. 返回 ! SetImmutablePrototype(O, V)。

10.4.6.3 [[IsExtensible]] ( )

模块命名空间异质对象[[IsExtensible]] 内部方法不接受参数并返回 包含 false 的正常完成。它在被调用时执行以下步骤:

  1. 返回 false

10.4.6.4 [[PreventExtensions]] ( )

模块命名空间异质对象[[PreventExtensions]] 内部方法不接受参数并返回 包含 true 的正常完成。它在被调用时执行以下步骤:

  1. 返回 true

10.4.6.5 [[GetOwnProperty]] ( P )

模块命名空间异质对象 O[[GetOwnProperty]] 内部方法接受参数 P(一个 属性键)并返回 包含 属性描述符undefined 的正常完成,或 抛出完成。它在被调用时执行以下步骤:

  1. 如果 P 是一个符号,返回 OrdinaryGetOwnProperty(O, P)。
  2. exportsO.[[Exports]]
  3. 如果 exports 不包含 P,返回 undefined
  4. value 为 ? O.[[Get]](P, O)。
  5. 返回属性描述符 { [[Value]]: value[[Writable]]: true[[Enumerable]]: true[[Configurable]]: false }。

10.4.6.6 [[DefineOwnProperty]] ( P, Desc )

模块命名空间异质对象 O[[DefineOwnProperty]] 内部方法接受参数 P(一个 属性键)和 Desc(一个 属性描述符)并返回 包含 布尔值的正常完成或 抛出完成。它在被调用时执行以下步骤:

  1. 如果 P 是一个符号,返回 ! OrdinaryDefineOwnProperty(O, P, Desc)。
  2. current 为 ? O.[[GetOwnProperty]](P)。
  3. 如果 currentundefined,返回 false
  4. 如果 Desc 有一个 [[Configurable]] 字段且 Desc.[[Configurable]]true,返回 false
  5. 如果 Desc 有一个 [[Enumerable]] 字段且 Desc.[[Enumerable]]false,返回 false
  6. 如果 IsAccessorDescriptor(Desc) 是 true,返回 false
  7. 如果 Desc 有一个 [[Writable]] 字段且 Desc.[[Writable]]false,返回 false
  8. 如果 Desc 有一个 [[Value]] 字段,返回 SameValue(Desc.[[Value]], current.[[Value]])。
  9. 返回 true

10.4.6.7 [[HasProperty]] ( P )

模块命名空间异质对象 O[[HasProperty]] 内部方法接受参数 P(一个 属性键)并返回 包含 布尔值的正常完成。它在被调用时执行以下步骤:

  1. 如果 P 是一个符号,返回 ! OrdinaryHasProperty(O, P)。
  2. exportsO.[[Exports]]
  3. 如果 exports 包含 P,返回 true
  4. 返回 false

10.4.6.8 [[Get]] ( P, Receiver )

模块命名空间异质对象 O[[Get]] 内部方法接受参数 P(一个 属性键)和 Receiver(一个 ECMAScript 语言值)并返回 包含 ECMAScript 语言值 的正常完成或 抛出完成。它在被调用时执行以下步骤:

  1. 如果 P 是一个符号,那么
    1. 返回 ! OrdinaryGet(O, P, Receiver)。
  2. exportsO.[[Exports]]
  3. 如果 exports 不包含 P,返回 undefined
  4. mO.[[Module]]
  5. bindingm.ResolveExport(P)。
  6. 断言binding 是一个 ResolvedBinding 记录
  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)。

ResolveExport 是无副作用的。每当使用特定的 exportNameresolveSet 对作为参数调用此操作时,它必须返回相同的结果。实现可能选择预计算或缓存每个 模块命名空间异质对象[[Exports]] 的 ResolveExport 结果。

10.4.6.9 [[Set]] ( P, V, Receiver )

模块命名空间异质对象[[Set]] 内部方法接受参数 P(一个 属性键)、V(一个 ECMAScript 语言值)和 Receiver(一个 ECMAScript 语言值)并返回 包含 false 的正常完成。它在被调用时执行以下步骤:

  1. 返回 false

10.4.6.10 [[Delete]] ( P )

模块命名空间异质对象 O[[Delete]] 内部方法接受参数 P(一个 属性键)并返回 包含 布尔值的正常完成。它在被调用时执行以下步骤:

  1. 如果 P 是一个符号,那么
    1. 返回 ! OrdinaryDelete(O, P)。
  2. exportsO.[[Exports]]
  3. 如果 exports 包含 P,返回 false
  4. 返回 true

10.4.6.11 [[OwnPropertyKeys]] ( )

模块命名空间异质对象 O[[OwnPropertyKeys]] 内部方法不接受参数并返回 包含 属性键列表 的正常完成。它在被调用时执行以下步骤:

  1. exportsO.[[Exports]]
  2. symbolKeysOrdinaryOwnPropertyKeys(O)。
  3. 返回 exportssymbolKeys列表连接

10.4.6.12 ModuleNamespaceCreate ( module, exports )

抽象操作 ModuleNamespaceCreate 接受参数 module(一个 模块记录)和 exports(一个字符串的 列表)并返回一个 模块命名空间异质对象。它用于指定新 模块命名空间异质对象 的创建。它在被调用时执行以下步骤:

  1. 断言module.[[Namespace]]empty
  2. internalSlotsList表 33 中列出的内部插槽。
  3. MMakeBasicObject(internalSlotsList)。
  4. 设置 M 的基本内部方法为 10.4.6 中指定的定义。
  5. 设置 M.[[Module]]module
  6. sortedExports 为一个 列表,其元素是 exports 的元素,按 字典代码单元顺序 排序。
  7. 设置 M.[[Exports]]sortedExports
  8. 创建 M 的自己的属性,对应于 28.3 中的定义。
  9. 设置 module.[[Namespace]]M
  10. 返回 M

10.4.7 不可变原型异质对象

不可变原型异质对象 是一个 异质对象,它具有一个 [[Prototype]] 内部插槽,一旦初始化后就不会更改。

如果一个对象的 [[SetPrototypeOf]] 内部方法使用以下实现,则该对象是一个 不可变原型异质对象。(其他基本内部方法可以使用任何实现,取决于所涉及的特定 不可变原型异质对象。)

与其他 异质对象 不同,没有为 不可变原型异质对象 提供专门的创建抽象操作。这是因为它们仅被 %Object.prototype%宿主环境 使用,而在 宿主环境 中,相关对象可能在其他方面也是异质的,因此需要它们自己的专门创建操作。

10.4.7.1 [[SetPrototypeOf]] ( V )

不可变原型异质对象 O[[SetPrototypeOf]] 内部方法接受参数 V(一个对象或 null)并返回 包含 布尔值的正常完成或 抛出完成。它在被调用时执行以下步骤:

  1. 返回 ? SetImmutablePrototype(O, V)。

10.4.7.2 SetImmutablePrototype ( O, V )

抽象操作 SetImmutablePrototype 接受参数 O(一个对象)和 V(一个对象或 null)并返回 包含 布尔值的正常完成或 抛出完成。它在被调用时执行以下步骤:

  1. current 为 ? O.[[GetPrototypeOf]]()。
  2. 如果 SameValue(V, current) 是 true,返回 true
  3. 返回 false

10.5 代理对象内部方法和内部插槽

代理对象是一个 异质对象,其基本内部方法部分使用 ECMAScript 代码实现。每个代理对象都有一个名为 [[ProxyHandler]] 的内部插槽。[[ProxyHandler]] 的值是一个对象,称为代理的处理器对象,或者是 null。处理器对象的方法(参见 表 34)可用于增强代理对象一个或多个内部方法的实现。每个代理对象还有一个名为 [[ProxyTarget]] 的内部插槽,其值要么是一个对象,要么是 null。这个对象称为代理的目标对象

如果一个对象的基本内部方法(包括 [[Call]][[Construct]],如果适用)使用本节中的定义,则该对象是一个 代理异质对象。这些内部方法在 ProxyCreate 中安装。

表 34:代理处理器方法
内部方法 处理器方法
[[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

当调用处理器方法来提供代理对象内部方法的实现时,处理器方法将代理的目标对象作为参数传递。代理的处理器对象不一定具有与每个基本内部方法相对应的方法。如果处理器对象没有与内部陷阱相对应的方法,则在代理上调用内部方法会导致在代理的目标对象上调用相应的内部方法。

代理对象的 [[ProxyHandler]][[ProxyTarget]] 内部插槽在创建对象时总是被初始化,通常不能被修改。某些代理对象以允许它们随后被撤销的方式创建。当代理被撤销时,其 [[ProxyHandler]][[ProxyTarget]] 内部插槽被设置为 null,导致该代理对象上内部方法的后续调用抛出 TypeError 异常。

因为代理对象允许通过任意 ECMAScript 代码提供内部方法的实现,所以可以定义一个代理对象,其处理器方法违反了 6.1.7.3 中定义的不变量。6.1.7.3 中定义的一些内部方法不变量是基本的完整性不变量。这些不变量由本节中指定的代理对象内部方法显式强制执行。ECMAScript 实现必须在所有可能的不变量违反的情况下保持健壮。

在以下算法描述中,假设 O 是一个 ECMAScript 代理对象,P 是一个 属性键 值,V 是任何 ECMAScript 语言值Desc 是一个 属性描述符 记录。

10.5.1 [[GetPrototypeOf]] ( )

代理异质对象 O[[GetPrototypeOf]] 内部方法不接受参数并返回 包含 对象或 null 的正常完成,或 抛出完成。它在被调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(O)。
  2. targetO.[[ProxyTarget]]
  3. handlerO.[[ProxyHandler]]
  4. 断言handler 是一个对象
  5. trap 为 ? GetMethod(handler, "getPrototypeOf")。
  6. 如果 trapundefined,那么
    1. 返回 ? target.[[GetPrototypeOf]]()。
  7. handlerProto 为 ? Call(trap, handler, « target »)。
  8. 如果 handlerProto 不是一个对象handlerProto 不是 null,抛出一个 TypeError 异常。
  9. extensibleTarget 为 ? IsExtensible(target)。
  10. 如果 extensibleTargettrue,返回 handlerProto
  11. targetProto 为 ? target.[[GetPrototypeOf]]()。
  12. 如果 SameValue(handlerProto, targetProto) 是 false,抛出一个 TypeError 异常。
  13. 返回 handlerProto

代理对象的 [[GetPrototypeOf]] 强制执行以下不变量:

  • [[GetPrototypeOf]] 的结果必须是一个对象或 null
  • 如果目标对象不可扩展,应用于代理对象的 [[GetPrototypeOf]] 必须返回与应用于代理对象的目标对象的 [[GetPrototypeOf]] 相同的值。

10.5.2 [[SetPrototypeOf]] ( V )

代理异质对象 O[[SetPrototypeOf]] 内部方法接受参数 V(一个对象或 null)并返回 包含 布尔值的正常完成或 抛出完成。它在被调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(O)。
  2. targetO.[[ProxyTarget]]
  3. handlerO.[[ProxyHandler]]
  4. 断言handler 是一个对象
  5. trap 为 ? GetMethod(handler, "setPrototypeOf")。
  6. 如果 trapundefined,那么
    1. 返回 ? target.[[SetPrototypeOf]](V)。
  7. booleanTrapResultToBoolean(? Call(trap, handler, « target, V »))。
  8. 如果 booleanTrapResultfalse,返回 false
  9. extensibleTarget 为 ? IsExtensible(target)。
  10. 如果 extensibleTargettrue,返回 true
  11. targetProto 为 ? target.[[GetPrototypeOf]]()。
  12. 如果 SameValue(V, targetProto) 是 false,抛出一个 TypeError 异常。
  13. 返回 true

代理对象的 [[SetPrototypeOf]] 强制执行以下不变量:

  • [[SetPrototypeOf]] 的结果 是一个布尔值
  • 如果目标对象不可扩展,参数值必须与应用于目标对象的 [[GetPrototypeOf]] 的结果相同。

10.5.3 [[IsExtensible]] ( )

代理异质对象 O[[IsExtensible]] 内部方法不接受参数并返回 包含 布尔值的正常完成或 抛出完成。它在被调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(O)。
  2. targetO.[[ProxyTarget]]
  3. handlerO.[[ProxyHandler]]
  4. 断言handler 是一个对象
  5. trap 为 ? GetMethod(handler, "isExtensible")。
  6. 如果 trapundefined,那么
    1. 返回 ? IsExtensible(target)。
  7. booleanTrapResultToBoolean(? Call(trap, handler, « target »))。
  8. targetResult 为 ? IsExtensible(target)。
  9. 如果 booleanTrapResult 不是 targetResult,抛出一个 TypeError 异常。
  10. 返回 booleanTrapResult

代理对象的 [[IsExtensible]] 强制执行以下不变量:

  • [[IsExtensible]] 的结果 是一个布尔值
  • 应用于代理对象的 [[IsExtensible]] 必须返回与应用于代理对象的目标对象的 [[IsExtensible]] 相同的值。

10.5.4 [[PreventExtensions]] ( )

代理异质对象 O[[PreventExtensions]] 内部方法不接受参数并返回 包含 布尔值的正常完成或 抛出完成。它在被调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(O)。
  2. targetO.[[ProxyTarget]]
  3. handlerO.[[ProxyHandler]]
  4. 断言handler 是一个对象
  5. trap 为 ? GetMethod(handler, "preventExtensions")。
  6. 如果 trapundefined,那么
    1. 返回 ? target.[[PreventExtensions]]()
  7. booleanTrapResultToBoolean(? Call(trap, handler, « target »))。
  8. 如果 booleanTrapResulttrue,那么
    1. extensibleTarget 为 ? IsExtensible(target)。
    2. 如果 extensibleTargettrue,抛出一个 TypeError 异常。
  9. 返回 booleanTrapResult

代理对象的 [[PreventExtensions]] 强制执行以下不变量:

  • [[PreventExtensions]] 的结果 是一个布尔值
  • 应用于代理对象的 [[PreventExtensions]] 仅在应用于代理对象的目标对象的 [[IsExtensible]]false 时才返回 true

10.5.5 [[GetOwnProperty]] ( P )

代理异质对象 O[[GetOwnProperty]] 内部方法接受参数 P(一个 属性键)并返回 包含 属性描述符undefined 的正常完成,或 抛出完成。它在被调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(O)。
  2. targetO.[[ProxyTarget]]
  3. handlerO.[[ProxyHandler]]
  4. 断言handler 是一个对象
  5. trap 为 ? GetMethod(handler, "getOwnPropertyDescriptor")。
  6. 如果 trapundefined,那么
    1. 返回 ? target.[[GetOwnProperty]](P)。
  7. trapResultObj 为 ? Call(trap, handler, « target, P »)。
  8. 如果 trapResultObj 不是一个对象trapResultObj 不是 undefined,抛出一个 TypeError 异常。
  9. targetDesc 为 ? target.[[GetOwnProperty]](P)。
  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

代理对象的 [[GetOwnProperty]] 强制执行以下不变量:

  • [[GetOwnProperty]] 的结果必须是一个对象或 undefined
  • 如果属性作为目标对象的不可配置自有属性存在,则不能报告该属性不存在。
  • 如果属性作为不可扩展目标对象的自有属性存在,则不能报告该属性不存在。
  • 如果属性不作为目标对象的自有属性存在且目标对象不可扩展,则不能报告该属性存在。
  • 除非属性作为目标对象的不可配置自有属性存在,否则不能报告该属性为不可配置。
  • 除非属性作为目标对象的不可配置、不可写自有属性存在,否则不能报告该属性既不可配置又不可写。

10.5.6 [[DefineOwnProperty]] ( P, Desc )

代理异质对象 O[[DefineOwnProperty]] 内部方法接受参数 P(一个 属性键)和 Desc(一个 属性描述符)并返回 包含 布尔值的正常完成或 抛出完成。它在被调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(O)。
  2. targetO.[[ProxyTarget]]
  3. handlerO.[[ProxyHandler]]
  4. 断言handler 是一个对象
  5. trap 为 ? GetMethod(handler, "defineProperty")。
  6. 如果 trapundefined,那么
    1. 返回 ? target.[[DefineOwnProperty]](P, Desc)。
  7. descObjFromPropertyDescriptor(Desc)。
  8. booleanTrapResultToBoolean(? Call(trap, handler, « target, P, descObj »))。
  9. 如果 booleanTrapResultfalse,返回 false
  10. targetDesc 为 ? target.[[GetOwnProperty]](P)。
  11. extensibleTarget 为 ? IsExtensible(target)。
  12. 如果 Desc 有一个 [[Configurable]] 字段且 Desc.[[Configurable]]false,那么
    1. settingConfigFalsetrue
  13. 否则,
    1. settingConfigFalsefalse
  14. 如果 targetDescundefined,那么
    1. 如果 extensibleTargetfalse,抛出一个 TypeError 异常。
    2. 如果 settingConfigFalsetrue,抛出一个 TypeError 异常。
  15. 否则,
    1. 如果 IsCompatiblePropertyDescriptor(extensibleTarget, Desc, targetDesc) 是 false,抛出一个 TypeError 异常。
    2. 如果 settingConfigFalsetruetargetDesc.[[Configurable]]true,抛出一个 TypeError 异常。
    3. 如果 IsDataDescriptor(targetDesc) 是 truetargetDesc.[[Configurable]]false,且 targetDesc.[[Writable]]true,那么
      1. 如果 Desc 有一个 [[Writable]] 字段且 Desc.[[Writable]]false,抛出一个 TypeError 异常。
  16. 返回 true

代理对象的 [[DefineOwnProperty]] 强制执行以下不变量:

  • [[DefineOwnProperty]] 的结果 是一个布尔值
  • 如果目标对象不可扩展,则不能添加属性。
  • 除非目标对象存在相应的不可配置自有属性,否则属性不能为不可配置。
  • 除非目标对象存在相应的不可配置、不可写自有属性,否则不可配置属性不能为不可写。
  • 如果属性有相应的目标对象属性,则使用 [[DefineOwnProperty]] 将该属性的 属性描述符 应用于目标对象不会抛出异常。

10.5.7 [[HasProperty]] ( P )

代理异质对象 O[[HasProperty]] 内部方法接受参数 P(一个 属性键)并返回 包含 布尔值的正常完成或 抛出完成。它在被调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(O)。
  2. targetO.[[ProxyTarget]]
  3. handlerO.[[ProxyHandler]]
  4. 断言handler 是一个对象
  5. trap 为 ? GetMethod(handler, "has")。
  6. 如果 trapundefined,那么
    1. 返回 ? target.[[HasProperty]](P)。
  7. booleanTrapResultToBoolean(? Call(trap, handler, « target, P »))。
  8. 如果 booleanTrapResultfalse,那么
    1. targetDesc 为 ? target.[[GetOwnProperty]](P)。
    2. 如果 targetDesc 不是 undefined,那么
      1. 如果 targetDesc.[[Configurable]]false,抛出一个 TypeError 异常。
      2. extensibleTarget 为 ? IsExtensible(target)。
      3. 如果 extensibleTargetfalse,抛出一个 TypeError 异常。
  9. 返回 booleanTrapResult

代理对象的 [[HasProperty]] 强制执行以下不变量:

  • [[HasProperty]] 的结果 是一个布尔值
  • 如果属性作为目标对象的不可配置自有属性存在,则不能报告该属性不存在。
  • 如果属性作为目标对象的自有属性存在且目标对象不可扩展,则不能报告该属性不存在。

10.5.8 [[Get]] ( P, Receiver )

代理异质对象 O[[Get]] 内部方法接受参数 P(一个 属性键)和 Receiver(一个 ECMAScript 语言值)并返回 包含 ECMAScript 语言值 的正常完成或 抛出完成。它在被调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(O)。
  2. targetO.[[ProxyTarget]]
  3. handlerO.[[ProxyHandler]]
  4. 断言handler 是一个对象
  5. trap 为 ? GetMethod(handler, "get")。
  6. 如果 trapundefined,那么
    1. 返回 ? target.[[Get]](P, Receiver)。
  7. trapResult 为 ? Call(trap, handler, « target, P, Receiver »)。
  8. targetDesc 为 ? target.[[GetOwnProperty]](P)。
  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

代理对象的 [[Get]] 强制执行以下不变量:

  • 如果目标对象属性是不可写、不可配置的自有 数据属性,则为属性报告的值必须与相应目标对象属性的值相同。
  • 如果相应的目标对象属性是不可配置的自有 访问器属性,且其 [[Get]] 特性为 undefined,则为属性报告的值必须是 undefined

10.5.9 [[Set]] ( P, V, Receiver )

代理异质对象 O[[Set]] 内部方法接受参数 P(一个 属性键)、V(一个 ECMAScript 语言值)和 Receiver(一个 ECMAScript 语言值)并返回 包含 布尔值的正常完成或 抛出完成。它在被调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(O)。
  2. targetO.[[ProxyTarget]]
  3. handlerO.[[ProxyHandler]]
  4. 断言handler 是一个对象
  5. trap 为 ? GetMethod(handler, "set")。
  6. 如果 trapundefined,那么
    1. 返回 ? target.[[Set]](P, V, Receiver)。
  7. booleanTrapResultToBoolean(? Call(trap, handler, « target, P, V, Receiver »))。
  8. 如果 booleanTrapResultfalse,返回 false
  9. targetDesc 为 ? target.[[GetOwnProperty]](P)。
  10. 如果 targetDesc 不是 undefinedtargetDesc.[[Configurable]]false,那么
    1. 如果 IsDataDescriptor(targetDesc) 是 truetargetDesc.[[Writable]]false,那么
      1. 如果 SameValue(V, targetDesc.[[Value]]) 是 false,抛出一个 TypeError 异常。
    2. 如果 IsAccessorDescriptor(targetDesc) 是 true,那么
      1. 如果 targetDesc.[[Set]]undefined,抛出一个 TypeError 异常。
  11. 返回 true

代理对象的 [[Set]] 强制执行以下不变量:

  • [[Set]] 的结果 是一个布尔值
  • 如果相应的目标对象属性是不可写、不可配置的自有 数据属性,则不能将属性的值更改为与相应目标对象属性的值不同。
  • 如果相应的目标对象属性是不可配置的自有 访问器属性,且其 [[Set]] 特性为 undefined,则不能设置属性的值。

10.5.10 [[Delete]] ( P )

代理异质对象 O[[Delete]] 内部方法接受参数 P(一个 属性键)并返回 包含 布尔值的正常完成或 抛出完成。它在被调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(O)。
  2. targetO.[[ProxyTarget]]
  3. handlerO.[[ProxyHandler]]
  4. 断言handler 是一个对象
  5. trap 为 ? GetMethod(handler, "deleteProperty")。
  6. 如果 trapundefined,那么
    1. 返回 ? target.[[Delete]](P)。
  7. booleanTrapResultToBoolean(? Call(trap, handler, « target, P »))。
  8. 如果 booleanTrapResultfalse,返回 false
  9. targetDesc 为 ? target.[[GetOwnProperty]](P)。
  10. 如果 targetDescundefined,返回 true
  11. 如果 targetDesc.[[Configurable]]false,抛出一个 TypeError 异常。
  12. extensibleTarget 为 ? IsExtensible(target)。
  13. 如果 extensibleTargetfalse,抛出一个 TypeError 异常。
  14. 返回 true

代理对象的 [[Delete]] 强制执行以下不变量:

  • [[Delete]] 的结果 是一个布尔值
  • 如果属性作为目标对象的不可配置自有属性存在,则不能报告该属性被删除。
  • 如果属性作为目标对象的自有属性存在且目标对象不可扩展,则不能报告该属性被删除。

10.5.11 [[OwnPropertyKeys]] ( )

代理异质对象 O[[OwnPropertyKeys]] 内部方法不接受参数并返回 包含 列表 的正常完成(该列表包含 属性键)或 抛出完成。它在被调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(O)。
  2. targetO.[[ProxyTarget]]
  3. handlerO.[[ProxyHandler]]
  4. 断言handler 是一个对象
  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 是一个包含 属性键列表
  13. 断言targetKeys 不包含重复条目。
  14. targetConfigurableKeys 为一个新的空 列表
  15. targetNonconfigurableKeys 为一个新的空 列表
  16. targetKeys 的每个元素 key,执行
    1. desc 为 ? target.[[GetOwnProperty]](key)。
    2. 如果 desc 不是 undefineddesc.[[Configurable]]false,那么
      1. key 追加到 targetNonconfigurableKeys
    3. 否则,
      1. key 追加到 targetConfigurableKeys
  17. 如果 extensibleTargettruetargetNonconfigurableKeys 是空的,那么
    1. 返回 trapResult
  18. uncheckedResultKeys 为一个 列表,其元素是 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

代理对象的 [[OwnPropertyKeys]] 强制执行以下不变量:

  • [[OwnPropertyKeys]] 的结果是一个 列表
  • 返回的 列表 不包含重复条目。
  • 返回的 列表 的每个元素都是一个 属性键
  • 结果 列表 必须包含目标对象所有不可配置自有属性的键。
  • 如果目标对象不可扩展,则结果 列表 必须包含目标对象自有属性的所有键,且不包含其他值。

10.5.12 [[Call]] ( thisArgument, argumentsList )

代理异质对象 O[[Call]] 内部方法接受参数 thisArgument(一个 ECMAScript 语言值)和 argumentsList(一个包含 ECMAScript 语言值列表)并返回 包含 ECMAScript 语言值 的正常完成或 抛出完成。它在被调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(O)。
  2. targetO.[[ProxyTarget]]
  3. handlerO.[[ProxyHandler]]
  4. 断言handler 是一个对象
  5. trap 为 ? GetMethod(handler, "apply")。
  6. 如果 trapundefined,那么
    1. 返回 ? Call(target, thisArgument, argumentsList)。
  7. argArrayCreateArrayFromList(argumentsList)。
  8. 返回 ? Call(trap, handler, « target, thisArgument, argArray »)。

代理异质对象 只有在其 [[ProxyTarget]] 内部插槽的初始值是具有 [[Call]] 内部方法的对象时,才具有 [[Call]] 内部方法。

10.5.13 [[Construct]] ( argumentsList, newTarget )

代理异质对象 O[[Construct]] 内部方法接受参数 argumentsList(一个包含 ECMAScript 语言值列表)和 newTarget(一个 构造函数)并返回 包含 对象的正常完成或 抛出完成。它在被调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(O)。
  2. targetO.[[ProxyTarget]]
  3. 断言IsConstructor(target) 是 true
  4. handlerO.[[ProxyHandler]]
  5. 断言handler 是一个对象
  6. trap 为 ? GetMethod(handler, "construct")。
  7. 如果 trapundefined,那么
    1. 返回 ? Construct(target, argumentsList, newTarget)。
  8. argArrayCreateArrayFromList(argumentsList)。
  9. newObj 为 ? Call(trap, handler, « target, argArray, newTarget »)。
  10. 如果 newObj 不是一个对象,抛出一个 TypeError 异常。
  11. 返回 newObj
注 1

代理异质对象 只有在其 [[ProxyTarget]] 内部插槽的初始值是具有 [[Construct]] 内部方法的对象时,才具有 [[Construct]] 内部方法。

注 2

代理对象的 [[Construct]] 强制执行以下不变量:

  • [[Construct]] 的结果必须是一个对象。

10.5.14 ValidateNonRevokedProxy ( proxy )

抽象操作 ValidateNonRevokedProxy 接受参数 proxy(一个 代理异质对象)并返回 包含 unused 的正常完成或 抛出完成。如果 proxy 已被撤销,它会抛出一个 TypeError 异常。它在被调用时执行以下步骤:

  1. 如果 proxy.[[ProxyTarget]]null,抛出一个 TypeError 异常。
  2. 断言proxy.[[ProxyHandler]] 不是 null
  3. 返回 unused

10.5.15 ProxyCreate ( target, handler )

抽象操作 ProxyCreate 接受参数 target(一个 ECMAScript 语言值)和 handler(一个 ECMAScript 语言值)并返回 包含 代理异质对象 的正常完成或 抛出完成。它用于指定新代理对象的创建。它在被调用时执行以下步骤:

  1. 如果 target 不是一个对象,抛出一个 TypeError 异常。
  2. 如果 handler 不是一个对象,抛出一个 TypeError 异常。
  3. PMakeBasicObject[[ProxyHandler]], [[ProxyTarget]] »)。
  4. P 的基本内部方法(除了 [[Call]][[Construct]])设置为 10.5 中指定的定义。
  5. 如果 IsCallable(target) 是 true,那么
    1. 按照 10.5.12 中的指定设置 P.[[Call]]
    2. 如果 IsConstructor(target) 是 true,那么
      1. 按照 10.5.13 中的指定设置 P.[[Construct]]
  6. 设置 P.[[ProxyTarget]]target
  7. 设置 P.[[ProxyHandler]]handler
  8. 返回 P

11 ECMAScript 语言:源文本

11.1 源文本

语法

SourceCharacter :: 任何 Unicode 码点

ECMAScript 源文本是一个 Unicode 码点序列。所有从 U+0000 到 U+10FFFF 的 Unicode 码点值,包括代理码点,都可以出现在 ECMAScript 语法允许的 ECMAScript 源文本中。用于存储和交换 ECMAScript 源文本的实际编码与本规范无关。无论外部源文本编码如何,符合要求的 ECMAScript 实现都会将源文本处理为等效的 SourceCharacter 值序列,每个 SourceCharacter 都是一个 Unicode 码点。符合要求的 ECMAScript 实现不需要对源文本执行任何规范化,也不需要表现得好像它们正在执行源文本规范化。

组合字符序列的组成部分被视为单独的 Unicode 码点,即使用户可能认为整个序列是一个字符。

在字符串字面量、正则表达式字面量、模板字面量和标识符中,任何 Unicode 码点也可以使用明确表示码点数值的 Unicode 转义序列来表示。在注释中,这样的转义序列作为注释的一部分被有效忽略。

ECMAScript 在 Unicode 转义序列的行为上与 Java 编程语言不同。在 Java 程序中,如果 Unicode 转义序列 \u000A 出现在单行注释中,它会被解释为行终止符(Unicode 码点 U+000A 是换行符 (LF)),因此下一个码点不是注释的一部分。同样,如果 Unicode 转义序列 \u000A 出现在 Java 程序的字符串字面量中,它同样被解释为行终止符,这在字符串字面量中是不允许的——必须写 \n 而不是 \u000A 来使换行符 (LF) 成为字符串字面量值的一部分。在 ECMAScript 程序中,出现在注释中的 Unicode 转义序列永远不会被解释,因此不能促成注释的终止。同样,出现在 ECMAScript 程序字符串字面量中的 Unicode 转义序列总是对字面量有贡献,永远不会被解释为行终止符或可能终止字符串字面量的码点。

11.1.1 静态语义:UTF16EncodeCodePoint ( cp )

抽象操作 UTF16EncodeCodePoint 接受参数 cp(一个 Unicode 码点)并返回一个字符串。它在被调用时执行以下步骤:

  1. 断言:0 ≤ cp ≤ 0x10FFFF。
  2. 如果 cp ≤ 0xFFFF,返回由数值为 cp 的码元组成的字符串值。
  3. cu1 为数值为 floor((cp - 0x10000) / 0x400) + 0xD800 的码元。
  4. cu2 为数值为 ((cp - 0x10000) modulo 0x400) + 0xDC00 的码元。
  5. 返回 cu1cu2字符串连接

11.1.2 静态语义:CodePointsToString ( text )

抽象操作 CodePointsToString 接受参数 text(一个 Unicode 码点序列)并返回一个字符串。它将 text 转换为字符串值,如 6.1.4 中所述。它在被调用时执行以下步骤:

  1. result 为空字符串。
  2. 对于 text 的每个码点 cp,执行
    1. 设置 resultresultUTF16EncodeCodePoint(cp) 的 字符串连接
  3. 返回 result

11.1.3 静态语义:UTF16SurrogatePairToCodePoint ( lead, trail )

抽象操作 UTF16SurrogatePairToCodePoint 接受参数 lead(一个码元)和 trail(一个码元)并返回一个码点。形成 UTF-16 代理对 的两个码元被转换为码点。它在被调用时执行以下步骤:

  1. 断言lead 是一个 前导代理trail 是一个 后尾代理
  2. cp 为 (lead - 0xD800) × 0x400 + (trail - 0xDC00) + 0x10000。
  3. 返回码点 cp

11.1.4 静态语义:CodePointAt ( string, position )

抽象操作 CodePointAt 接受参数 string(一个字符串)和 position(一个非负 整数)并返回一个具有字段 [[CodePoint]](一个码点)、[[CodeUnitCount]] (一个正 整数)和 [[IsUnpairedSurrogate]](一个布尔值)的 记录。它将 string 解释为 UTF-16 编码的码点序列,如 6.1.4 中所述,并从中读取一个从索引 position 处的码元开始的单个码点。它在被调用时执行以下步骤:

  1. sizestring 的长度。
  2. 断言position ≥ 0 且 position < size
  3. firststring 中索引 position 处的码元。
  4. cp 为数值等于 first 数值的码点。
  5. 如果 first 既不是 前导代理 也不是 后尾代理,那么
    1. 返回 记录 { [[CodePoint]]: cp, [[CodeUnitCount]]: 1, [[IsUnpairedSurrogate]]: false }。
  6. 如果 first后尾代理position + 1 = size,那么
    1. 返回 记录 { [[CodePoint]]: cp, [[CodeUnitCount]]: 1, [[IsUnpairedSurrogate]]: true }。
  7. secondstring 中索引 position + 1 处的码元。
  8. 如果 second 不是 后尾代理,那么
    1. 返回 记录 { [[CodePoint]]: cp, [[CodeUnitCount]]: 1, [[IsUnpairedSurrogate]]: true }。
  9. 设置 cpUTF16SurrogatePairToCodePoint(first, second)。
  10. 返回 记录 { [[CodePoint]]: cp, [[CodeUnitCount]]: 2, [[IsUnpairedSurrogate]]: false }。

11.1.5 静态语义:StringToCodePoints ( string )

抽象操作 StringToCodePoints 接受参数 string(一个字符串)并返回一个码点的 列表。它返回将 string 解释为 UTF-16 编码的 Unicode 文本所产生的 Unicode 码点序列,如 6.1.4 中所述。它在被调用时执行以下步骤:

  1. codePoints 为一个新的空 列表
  2. sizestring 的长度。
  3. position 为 0。
  4. 重复,当 position < size 时,
    1. cpCodePointAt(string, position)。
    2. cp.[[CodePoint]] 追加到 codePoints
    3. 设置 positionposition + cp.[[CodeUnitCount]]
  5. 返回 codePoints

11.1.6 静态语义:ParseText ( sourceText, goalSymbol )

抽象操作 ParseText 接受参数 sourceText(一个字符串或 Unicode 码点序列)和 goalSymbol(ECMAScript 语法中的一个非终结符)并返回一个 解析节点 或一个非空的 SyntaxError 对象 列表。它在被调用时执行以下步骤:

  1. 如果 sourceText 是一个字符串,设置 sourceTextStringToCodePoints(sourceText)。
  2. 尝试使用 goalSymbol 作为 目标符号 来解析 sourceText,并分析解析结果以查找任何 早期错误 条件。解析和 早期错误 检测可以以 实现定义 的方式交错进行。
  3. 如果解析成功且未发现 早期错误,返回解析产生的解析树根部的 解析节点goalSymbol 的一个实例)。
  4. 否则,返回一个包含一个或多个表示解析错误和/或 早期错误SyntaxError 对象的 列表。如果存在多个解析错误或 早期错误,列表中错误对象的数量和顺序是 实现定义 的,但至少必须存在一个。
注 1

考虑一个在特定点有 早期错误,在后面的点也有语法错误的文本。一个先执行解析阶段再执行 早期错误 阶段的实现可能会报告语法错误而不继续进行 早期错误 阶段。一个交错进行这两个活动的实现可能会报告 早期错误 而不继续查找语法错误。第三种实现可能会报告两个错误。所有这些行为都是符合要求的。

注 2

另见第 17 章。

11.2 源代码类型

ECMAScript 代码有四种类型:

注 1

函数代码通常作为函数定义(15.2)、箭头函数定义 (15.3)、方法定义 (15.4)、生成器函数定义 (15.5)、异步函数定义 (15.8)、异步生成器函数定义 (15.6) 和异步箭头函数(15.9)的主体提供。 函数代码也派生自 Function 构造函数20.2.1.1)、GeneratorFunction 构造函数27.3.1.1)和 AsyncFunction 构造函数27.7.1.1)的参数。

注 2

BindingIdentifier 包含在函数代码中的实际效果是,严格模式代码 的早期错误会应用于作为函数名称的 BindingIdentifier,该函数的主体包含 "use strict" 指令,即使周围的代码不是 严格模式代码

11.2.1 指令序言和 Use Strict 指令

指令序言是作为 FunctionBodyScriptBodyModuleBody 的初始 StatementListItemModuleItem 出现的最长 ExpressionStatement 序列,并且序列中的每个 ExpressionStatement 完全由一个 StringLiteral 标记后跟一个分号组成。分号可以显式出现,也可以通过自动分号插入(12.10)插入。一个 指令序言 可以是一个空序列。

Use Strict 指令指令序言 中的一个 ExpressionStatement,其 StringLiteral 是精确的码点序列 "use strict"'use strict'。一个 Use Strict 指令 不能包含 EscapeSequenceLineContinuation

一个 指令序言 可能包含多个 Use Strict 指令。但是,如果发生这种情况,实现可能会发出警告。

指令序言ExpressionStatement 在包含的产生式求值期间正常求值。实现可以为那些不是 Use Strict 指令 且出现在 指令序言 中的 ExpressionStatement 定义实现特定的含义。如果存在适当的通知机制,当实现在 指令序言 中遇到一个不是 Use Strict 指令 且没有由实现定义的含义的 ExpressionStatement 时,应发出警告。

11.2.2 严格模式代码

ECMAScript 句法单元可以使用非限制性或严格模式语法和语义(4.3.2)进行处理。在以下情况下,代码被解释为 严格模式代码

不是严格模式代码的 ECMAScript 代码称为 非严格代码

11.2.2.1 静态语义:IsStrict ( node )

抽象操作 IsStrict 接受参数 node(一个 解析节点)并返回一个布尔值。它在被调用时执行以下步骤:

  1. 如果 node 匹配的源文本严格模式代码,返回 true;否则返回 false

11.2.3 非 ECMAScript 函数

ECMAScript 实现可以支持对函数 奇异对象 的求值,其求值行为以某种 宿主定义 的可执行代码形式表示,而不是 ECMAScript 源文本。从调用或被此类 函数对象 调用的 ECMAScript 代码的角度来看,函数对象 是在 ECMAScript 代码中定义的还是内置函数是不可观察的。

12 ECMAScript 语言:词法语法

ECMAScript 脚本模块 的源文本首先被转换为输入元素序列,这些输入元素是标记、行终止符、注释或空白符。源文本从左到右扫描,重复地取尽可能长的码点序列作为下一个输入元素。

在某些情况下,词法输入元素的识别对消费输入元素的句法语法上下文很敏感。这需要词法语法具有多个 目标符号InputElementHashbangOrRegExp 目标用于 脚本模块 的开始。InputElementRegExpOrTemplateTail 目标用于允许 RegularExpressionLiteralTemplateMiddleTemplateTail 的句法语法上下文中。InputElementRegExp 目标符号 用于所有允许 RegularExpressionLiteral 但不允许 TemplateMiddleTemplateTail 的句法语法上下文中。InputElementTemplateTail 目标用于所有允许 TemplateMiddleTemplateTail 但不允许 RegularExpressionLiteral 的句法语法上下文中。在所有其他上下文中,InputElementDiv 用作词法 目标符号

使用多个词法目标确保不存在会影响自动分号插入的词法歧义。例如,不存在既允许前导除法或除法赋值又允许前导 RegularExpressionLiteral 的句法语法上下文。这不受分号插入的影响(参见 12.10);在如下例子中:

a = b
/hi/g.exec(c).map(d);

其中 LineTerminator 后第一个非空白、非注释码点是 U+002F(斜线),且句法上下文允许除法或除法赋值,则不会在 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" 的字符,如从左到右标记或从右到左标记)是在缺乏用于此目的的高级协议(如标记语言)的情况下用于控制文本范围格式的控制代码。

允许格式控制字符出现在源文本中是有用的,以便于编辑和显示。所有格式控制字符都可以在注释中以及字符串字面量、模板字面量和正则表达式字面量中使用。

U+FEFF(零宽度无间断空格)是一个格式控制字符,主要用于文本的开头,以将其标记为 Unicode 并允许检测文本的编码和字节顺序。用于此目的的 <ZWNBSP> 字符有时也可能出现在文本开头之后,例如作为连接文件的结果。在 ECMAScript 源文本 中,<ZWNBSP> 码点在注释、字符串字面量、模板字面量和正则表达式字面量之外被视为空白字符(参见 12.2)。

12.2 空白符

空白码点用于改善源文本的可读性并将标记(不可分割的词法单元)彼此分离,但在其他方面是无关紧要的。空白码点可以出现在任意两个标记之间以及输入的开始或结束处。空白码点可以出现在 StringLiteralRegularExpressionLiteralTemplateTemplateSubstitutionTail 中,在这些地方它们被视为构成字面量值一部分的重要码点。它们也可以出现在 Comment 中,但不能出现在任何其他类型的标记内。

ECMAScript 空白码点列在 表 35 中。

表 35:空白码点
码点 名称 缩写
U+0009 字符制表符 <TAB>
U+000B 行制表符 <VT>
U+000C 换页符 (FF) <FF>
U+FEFF 零宽度无间断空格 <ZWNBSP>
通用类别 "Space_Separator" 中的任何码点 <USP>
注 1

U+0020(空格)和 U+00A0(无间断空格)码点是 <USP> 的一部分。

注 2

除了 表 35 中列出的码点外,ECMAScript WhiteSpace 有意排除了所有具有 Unicode "White_Space" 属性但未归类为通用类别 "Space_Separator"("Zs")的码点。

语法

WhiteSpace :: <TAB> <VT> <FF> <ZWNBSP> <USP>

12.3 行终止符

与空白码点一样,行终止符码点用于改善源文本的可读性并将标记(不可分割的词法单元)彼此分离。但是,与空白码点不同,行终止符对句法语法的行为有一定影响。通常,行终止符可以出现在任意两个标记之间,但在句法语法禁止的少数地方则不行。行终止符还会影响自动分号插入的过程(12.10)。行终止符不能出现在任何标记内,除了 StringLiteralTemplateTemplateSubstitutionTail。<LF> 和 <CR> 行终止符不能出现在 StringLiteral 标记内,除非作为 LineContinuation 的一部分。

行终止符可以出现在 MultiLineComment 内,但不能出现在 SingleLineComment 内。

行终止符被包含在正则表达式中 \s 类匹配的空白码点集合中。

ECMAScript 行终止符码点列在 表 36 中。

表 36:行终止符码点
码点 Unicode 名称 缩写
U+000A 换行符 (LF) <LF>
U+000D 回车符 (CR) <CR>
U+2028 行分隔符 <LS>
U+2029 段分隔符 <PS>

只有 表 36 中的 Unicode 码点被视为行终止符。其他换行或断行的 Unicode 码点不被视为行终止符,但如果它们满足 表 35 中列出的要求,则被视为空白符。序列 <CR><LF> 通常用作行终止符。为了报告行号的目的,它应该被视为单个 SourceCharacter

语法

LineTerminator :: <LF> <CR> <LS> <PS> LineTerminatorSequence :: <LF> <CR> [lookahead ≠ <LF>] <LS> <PS> <CR> <LF>

12.4 注释

注释可以是单行或多行的。多行注释不能嵌套。

由于单行注释可以包含除 LineTerminator 码点之外的任何 Unicode 码点,并且由于标记总是尽可能长的一般规则,单行注释总是由从 // 标记到行尾的所有码点组成。但是,行尾的 LineTerminator 不被认为是单行注释的一部分;它由词法语法单独识别,并成为句法语法输入元素流的一部分。这一点非常重要,因为这意味着单行注释的存在或不存在不会影响自动分号插入的过程(参见 12.10)。

注释的行为类似空白符并被丢弃,除非 MultiLineComment 包含行终止符码点,则整个注释在句法语法解析时被视为 LineTerminator

语法

Comment :: MultiLineComment SingleLineComment MultiLineComment :: /* MultiLineCommentCharsopt */ MultiLineCommentChars :: MultiLineNotAsteriskChar MultiLineCommentCharsopt * PostAsteriskCommentCharsopt PostAsteriskCommentChars :: MultiLineNotForwardSlashOrAsteriskChar MultiLineCommentCharsopt * PostAsteriskCommentCharsopt MultiLineNotAsteriskChar :: SourceCharacter but not * MultiLineNotForwardSlashOrAsteriskChar :: SourceCharacter but not one of / or * SingleLineComment :: // SingleLineCommentCharsopt SingleLineCommentChars :: SingleLineCommentChar SingleLineCommentCharsopt SingleLineCommentChar :: SourceCharacter but not LineTerminator

本节中的许多产生式在 B.1.1 节中给出了替代定义

12.5 Hashbang 注释

Hashbang 注释对位置敏感,与其他类型的注释一样,从句法语法的输入元素流中被丢弃。

语法

HashbangComment :: #! SingleLineCommentCharsopt

12.6 标记

语法

CommonToken :: IdentifierName PrivateIdentifier Punctuator NumericLiteral StringLiteral Template

DivPunctuatorRegularExpressionLiteralRightBracePunctuatorTemplateSubstitutionTail 产生式派生出额外的标记,这些标记不包含在 CommonToken 产生式中。

12.7 名称和关键字

IdentifierNameReservedWord 是根据 Unicode 标准附件 #31《标识符和模式语法》中给定的默认标识符语法进行解释的标记,但有一些小的修改。ReservedWordIdentifierName 的一个枚举子集。句法语法将 Identifier 定义为不是 ReservedWordIdentifierName。Unicode 标识符语法基于 Unicode 标准规定的字符属性。所有符合的 ECMAScript 实现必须将最新版本 Unicode 标准中指定类别的 Unicode 码点视为属于那些类别。ECMAScript 实现可以识别在 Unicode 标准后续版本中定义的标识符码点。

注 1

本标准规定了特定的码点添加:U+0024(美元符号)和 U+005F(下划线)允许出现在 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 :: 任何具有 Unicode 属性 "ID_Start" 的 Unicode 码点 UnicodeIDContinue :: 任何具有 Unicode 属性 "ID_Continue" 的 Unicode 码点

非终结符 UnicodeEscapeSequence 的定义在 12.9.4 中给出。

注 2

非终结符 IdentifierPart 通过 UnicodeIDContinue 派生 _

注 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,且具有与原始 IdentifierName 完全相同的 SourceCharacter 元素序列。本规范中对 IdentifierName 的所有解释都基于它们的实际码点,无论是否使用转义序列来贡献任何特定码点。

根据 Unicode 标准规范等价的两个 IdentifierName相等的,除非在替换每个 UnicodeEscapeSequence 后,它们由完全相同的码点序列表示。

12.7.1.1 静态语义:早期错误

IdentifierStart :: \ UnicodeEscapeSequence IdentifierPart :: \ UnicodeEscapeSequence

12.7.1.2 静态语义:IdentifierCodePoints

语法导向操作 IdentifierCodePoints 不接受参数并返回码点的 列表。它在以下产生式上分段定义:

IdentifierName :: IdentifierStart
  1. cpIdentifierStartIdentifierCodePoint
  2. 返回 « cp »。
IdentifierName :: IdentifierName IdentifierPart
  1. cps 为派生的 IdentifierNameIdentifierCodePoints
  2. cpIdentifierPartIdentifierCodePoint
  3. 返回 cps 和 « cp » 的 列表连接

12.7.1.3 静态语义:IdentifierCodePoint

语法导向操作 IdentifierCodePoint 不接受参数并返回一个码点。它在以下产生式上分段定义:

IdentifierStart :: IdentifierStartChar
  1. 返回 IdentifierStartChar 匹配的码点。
IdentifierPart :: IdentifierPartChar
  1. 返回 IdentifierPartChar 匹配的码点。
UnicodeEscapeSequence :: u Hex4Digits
  1. 返回数值等于 Hex4Digits 的 MV 的码点。
UnicodeEscapeSequence :: u{ CodePoint }
  1. 返回数值等于 CodePoint 的 MV 的码点。

12.7.2 关键字和保留字

关键字是匹配 IdentifierName 但也有句法用途的标记;也就是说,它在某些句法产生式中以固定宽度字体直接出现。ECMAScript 的关键字包括 ifwhileasyncawait 等等。

保留字是不能用作标识符的 IdentifierName。许多关键字是保留字,但有些不是,有些只在特定上下文中保留。ifwhile 是保留字。await 只在异步函数和模块内保留。async 不是保留的;它可以无限制地用作变量名或语句标签。

本规范使用语法产生式和 早期错误 规则的组合来指定哪些名称是有效标识符,哪些是保留字。下面 ReservedWord 列表中的所有标记,除了 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 注 1

根据 5.1.5,语法中的关键字匹配特定 SourceCharacter 元素的文字序列。关键字中的码点不能用 \ UnicodeEscapeSequence 表示。

IdentifierName 可以包含 \ UnicodeEscapeSequence,但不可能通过拼写 els\u{65} 来声明名为 "else" 的变量。13.1.1 中的 早期错误 规则排除了与保留字具有相同 StringValue 的标识符。

注 2

enum 目前在本规范中未用作关键字。它是一个未来保留字,留作未来语言扩展中用作关键字。

类似地,implementsinterfacepackageprivateprotectedpublic严格模式代码 中是未来保留字。

注 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 布尔字面量

语法

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

例如:3in 是一个错误,而不是两个输入元素 3in

12.9.3.1 静态语义:早期错误

NumericLiteral :: LegacyOctalIntegerLiteral DecimalIntegerLiteral :: NonOctalDecimalIntegerLiteral
  • 如果 IsStrict(this production) 是 true,则这是语法错误。
非严格代码 中,此语法是 遗留 的。

12.9.3.2 静态语义:MV

数值字面量表示 Number 类型BigInt 类型 的值。

12.9.3.3 静态语义:NumericValue

语法导向操作 NumericValue 不接受参数并返回一个 Number 或 BigInt。它在以下产生式上分段定义:

NumericLiteral :: DecimalLiteral
  1. 返回 RoundMVResult(DecimalLiteral 的 MV)。
NumericLiteral :: NonDecimalIntegerLiteral
  1. 返回 𝔽(NonDecimalIntegerLiteral 的 MV)。
NumericLiteral :: LegacyOctalIntegerLiteral
  1. 返回 𝔽(LegacyOctalIntegerLiteral 的 MV)。
NumericLiteral :: NonDecimalIntegerLiteral BigIntLiteralSuffix
  1. 返回 NonDecimalIntegerLiteral 的 MV 的 BigInt 值
DecimalBigIntegerLiteral :: 0 BigIntLiteralSuffix
  1. 返回 0
DecimalBigIntegerLiteral :: NonZeroDigit BigIntLiteralSuffix
  1. 返回 NonZeroDigit 的 MV 的 BigInt 值
DecimalBigIntegerLiteral :: NonZeroDigit DecimalDigits BigIntLiteralSuffix NonZeroDigit NumericLiteralSeparator DecimalDigits BigIntLiteralSuffix
  1. nDecimalDigits 中的码点数,不包括所有 NumericLiteralSeparator 的出现。
  2. mv 为(NonZeroDigit 的 MV × 10n)加上 DecimalDigits 的 MV。
  3. 返回 (mv)。

12.9.4 字符串字面量

注 1

字符串字面量是用单引号或双引号括起来的 0 个或多个 Unicode 码点。Unicode 码点也可以用转义序列表示。除了结束引号码点、U+005C(反斜杠)、U+000D(回车符)和 U+000A(换行符)之外,所有码点都可以直接出现在字符串字面量中。任何码点都可以以转义序列的形式出现。字符串字面量求值为 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 中给出。SourceCharacter11.1 中定义。

注 2

<LF> 和 <CR> 不能出现在字符串字面量中,除非作为 LineContinuation 的一部分来产生空码点序列。在字符串字面量的 String 值中包含它们的正确方法是使用转义序列,如 \n\u000A

12.9.4.1 静态语义:早期错误

EscapeSequence :: LegacyOctalEscapeSequence NonOctalDecimalEscapeSequence
  • 如果 IsStrict(this production) 是 true,则这是语法错误。
注 1
非严格代码 中,此语法是 遗留 的。
注 2

字符串字面量可能出现在将封闭代码置于 严格模式Use Strict 指令 之前,实现必须注意对这类字面量强制执行上述规则。例如,以下源文本包含语法错误:

function invalid() { "\7"; "use strict"; }

12.9.4.2 静态语义:SV

语法导向操作 SV 不接受参数并返回一个 String。

字符串字面量表示 String 类型 的值。SV 通过对字符串字面量的各个部分进行递归应用来为字符串字面量产生 String 值。作为此过程的一部分,字符串字面量内的一些 Unicode 码点被解释为具有 数学值,如下所述或在 12.9.3 中所述。

表 37:字符串单字符转义序列
转义序列 码元值 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 静态语义:MV

12.9.5 正则表达式字面量

注 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 注 2

正则表达式字面量不能为空;码元序列 // 不是表示空正则表达式字面量,而是开始单行注释。要指定空正则表达式,请使用:/(?:)/

12.9.5.1 静态语义:BodyText

语法导向操作 BodyText 不接受参数并返回源文本。它在以下产生式上分段定义:

RegularExpressionLiteral :: / RegularExpressionBody / RegularExpressionFlags
  1. 返回被识别为 RegularExpressionBody 的源文本。

12.9.5.2 静态语义:FlagText

语法导向操作 FlagText 不接受参数并返回源文本。它在以下产生式上分段定义:

RegularExpressionLiteral :: / RegularExpressionBody / RegularExpressionFlags
  1. 返回被识别为 RegularExpressionFlags 的源文本。

12.9.6 模板字面量词法组件

语法

Template :: NoSubstitutionTemplate TemplateHead NoSubstitutionTemplate :: ` TemplateCharactersopt ` TemplateHead :: ` TemplateCharactersopt ${ TemplateSubstitutionTail :: TemplateMiddle TemplateTail TemplateMiddle :: } TemplateCharactersopt ${ TemplateTail :: } TemplateCharactersopt ` TemplateCharacters :: TemplateCharacter TemplateCharactersopt TemplateCharacter :: $ [lookahead ≠ {] \ TemplateEscapeSequence \ NotEscapeSequence LineContinuation LineTerminatorSequence SourceCharacter but not one of ` or \ or $ or LineTerminator TemplateEscapeSequence :: CharacterEscapeSequence 0 [lookahead ∉ DecimalDigit] HexEscapeSequence UnicodeEscapeSequence NotEscapeSequence :: 0 DecimalDigit DecimalDigit but not 0 x [lookahead ∉ HexDigit] x HexDigit [lookahead ∉ HexDigit] u [lookahead ∉ HexDigit] [lookahead ≠ {] u HexDigit [lookahead ∉ HexDigit] u HexDigit HexDigit [lookahead ∉ HexDigit] u HexDigit HexDigit HexDigit [lookahead ∉ HexDigit] u { [lookahead ∉ HexDigit] u { NotCodePoint [lookahead ∉ HexDigit] u { CodePoint [lookahead ∉ HexDigit] [lookahead ≠ }] NotCodePoint :: HexDigits[~Sep] but only if the MV of HexDigits > 0x10FFFF CodePoint :: HexDigits[~Sep] but only if the MV of HexDigits ≤ 0x10FFFF

TemplateSubstitutionTailInputElementTemplateTail 替代词法目标使用。

12.9.6.1 静态语义:TV

语法导向操作 TV 不接受参数并返回 String 或 undefined。模板字面量组件被 TV 解释为 String 类型 的值。TV 用于构造模板对象的索引组件(通俗地说,模板值)。在 TV 中,转义序列被转义序列表示的 Unicode 码点的 UTF-16 码元替换。

12.9.6.2 静态语义:TRV

语法导向操作 TRV 不接受参数并返回 String。模板字面量组件被 TRV 解释为 String 类型 的值。TRV 用于构造模板对象的原始组件(通俗地说,模板原始值)。TRV 类似于 TV,区别在于在 TRV 中,转义序列按照它们在字面量中出现的方式被解释。

TV 排除 LineContinuation 的码元,而 TRV 包含它们。<CR><LF> 和 <CR> LineTerminatorSequence 对于 TV 和 TRV 都被规范化为 <LF>。需要显式的 TemplateEscapeSequence 来包含 <CR> 或 <CR><LF> 序列。

12.10 自动分号插入

大多数 ECMAScript 语句和声明必须以分号结尾。这些分号可以始终显式地出现在源文本中。但是,为了方便起见,在某些情况下可以从源文本中省略这些分号。这些情况通过说分号在这些情况下被自动插入到源代码标记流中来描述。

12.10.1 自动分号插入规则

在以下规则中,"标记"是指使用当前词法目标符号确定的实际识别的词法标记,如第 12 章所述。

分号插入有三个基本规则:

  1. 当从左到右解析源文本时,遇到语法的任何产生式都不允许的标记(称为违规标记),如果满足以下一个或多个条件,则在违规标记之前自动插入分号:

    • 违规标记与前一个标记之间至少有一个 LineTerminator 分隔。
    • 违规标记是 }
    • 前一个标记是 ),插入的分号将被解析为 do-while 语句的终止分号(14.7.2)。
  2. 当从左到右解析源文本时,遇到标记输入流的结尾,并且解析器无法将输入标记流解析为目标非终结符的单个实例,则在输入流的结尾自动插入分号。
  3. 当从左到右解析源文本时,遇到语法的某些产生式允许的标记,但该产生式是受限产生式,并且该标记将是紧接着受限产生式中注释"[no LineTerminator here]"之后的终结符或非终结符的第一个标记(因此这样的标记称为受限标记),并且受限标记与前一个标记之间至少有一个 LineTerminator 分隔,则在受限标记之前自动插入分号。

但是,前述规则有一个额外的覆盖条件:如果分号随后会被解析为空语句,或者该分号会成为 for 语句头部中的两个分号之一(参见 14.7.4),则永远不会自动插入分号。

以下是语法中唯一的受限产生式:

UpdateExpression[Yield, Await] : LeftHandSideExpression[?Yield, ?Await] [no LineTerminator here] ++ LeftHandSideExpression[?Yield, ?Await] [no LineTerminator here] -- 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,则在 ++-- 标记之前自动插入分号。
  • 当遇到 continuebreakreturnthrowyield 标记,并且在下一个标记之前遇到 LineTerminator 时,在 continuebreakreturnthrowyield 标记之后自动插入分号。
  • 当箭头函数参数后面在 => 标记之前有 LineTerminator 时,自动插入分号,标点符号会导致语法错误。
  • async 标记后面在 functionIdentifierName( 标记之前有 LineTerminator 时,自动插入分号,async 标记不被视为与后续标记相同表达式或类元素的一部分。
  • async 标记后面在 * 标记之前有 LineTerminator 时,自动插入分号,标点符号会导致语法错误。

给 ECMAScript 程序员的实际建议是:

  • 后缀 ++-- 运算符应该与其操作数在同一行。
  • returnthrow 语句中的 Expressionyield 表达式中的 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;
注 1

表达式 a + b 不被视为 return 语句要返回的值,因为 LineTerminator 将其与标记 return 分开。

源代码

a = b
++c

通过自动分号插入转换为以下内容:

a = b;
++c;
注 2

标记 ++ 不被视为应用于变量 b 的后缀运算符,因为 LineTerminator 出现在 b++ 之间。

源代码

if (a > b)
else c = d

不是有效的 ECMAScript 句子,并且不会被自动分号插入在 else 标记之前更改,即使在该点语法的任何产生式都不适用,因为自动插入的分号随后会被解析为空语句。

源代码

a = b + c
(d + e).print()

不会被自动分号插入转换,因为第二行开始的括号表达式可以被解释为函数调用的参数列表:

a = b + c(d + e).print()

在赋值语句必须以左括号开始的情况下,程序员最好在前一个语句的末尾提供显式分号,而不是依赖自动分号插入。

12.10.3 自动分号插入的有趣情况

本节是非规范性的。

ECMAScript 程序可以通过依赖自动分号插入以很少分号的风格编写。如上所述,分号不会在每个换行符处插入,自动分号插入可能依赖于跨行终止符的多个标记。

随着新的语法特性被添加到 ECMAScript 中,可能会添加额外的语法产生式,这些产生式会导致依赖自动分号插入的行在解析时改变语法产生式。

就本节而言,如果自动分号插入的情况是可能插入或不插入分号的地方,取决于其前面的源文本,则被认为是有趣的。本节的其余部分描述了这个版本的 ECMAScript 中自动分号插入的许多有趣情况。

12.10.3.1 语句列表中自动分号插入的有趣情况

StatementList 中,许多 StatementListItem 以分号结尾,这些分号可以使用自动分号插入省略。根据上述规则,在结束表达式的行末尾,如果下一行以以下任何内容开始,则需要分号:

  • 左括号 (()。没有分号时,两行一起被视为 CallExpression
  • 左方括号 ([)。没有分号时,两行一起被视为属性访问,而不是 ArrayLiteralArrayAssignmentPattern
  • 模板字面量 (`)。没有分号时,两行一起被解释为带标签的模板(13.3.11),前面的表达式作为 MemberExpression
  • 一元 +-。没有分号时,两行一起被解释为使用相应二元运算符。
  • 正则表达式字面量。没有分号时,两行一起可能被解析为 / MultiplicativeOperator,例如如果正则表达式有标志。

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

yieldawait 在语法中被允许作为 BindingIdentifier,并在下面的静态语义中被禁止,以防止在以下情况中自动分号插入

let
await 0;

13.1.1 静态语义:早期错误

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

IdentifierNameStringValue 规范化 IdentifierName 中的任何 Unicode 转义序列,因此这些转义不能用于编写代码点序列与 ReservedWord 相同的 Identifier

13.1.2 静态语义:StringValue

语法导向操作 StringValue 不接受参数并返回 String。它在以下产生式上分段定义:

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(数字符号)与 IdentifierNameStringValue字符串连接
ModuleExportName : StringLiteral
  1. 返回 StringLiteralSV

13.1.3 运行时语义:Evaluation

IdentifierReference : Identifier
  1. 返回 ? ResolveBinding(IdentifierStringValue)。
IdentifierReference : yield
  1. 返回 ? ResolveBinding("yield")。
IdentifierReference : await
  1. 返回 ? ResolveBinding("await")。
注 1

求值 IdentifierReference 的结果总是 Reference 类型的值。

注 2

非严格代码中,关键字 yield 可以用作标识符。求值 IdentifierReference 解析 yield 的绑定,就像它是 Identifier 一样。早期错误限制确保这种求值只能在非严格代码中发生。

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 运行时语义:Evaluation

PrimaryExpression : this
  1. 返回 ? ResolveThisBinding()。

13.2.2 标识符引用

关于 IdentifierReference,请参见 13.1

13.2.3 字面量

语法

Literal : NullLiteral BooleanLiteral NumericLiteral StringLiteral

13.2.3.1 运行时语义:Evaluation

Literal : NullLiteral
  1. 返回 null
Literal : BooleanLiteral
  1. 如果 BooleanLiteral 是标记 false,返回 false
  2. 如果 BooleanLiteral 是标记 true,返回 true
Literal : NumericLiteral
  1. 返回 NumericLiteralNumericValue,如 12.9.3 中定义。
Literal : StringLiteral
  1. 返回 StringLiteralSV,如 12.9.4.2 中定义。

13.2.4 数组初始化器

ArrayLiteral 是一个表达式,描述使用零个或多个表达式的列表来初始化数组,每个表达式代表一个数组元素,包含在方括号中。元素不需要是字面量;每次求值数组初始化器时都会对它们进行求值。

数组元素可以在元素列表的开头、中间或末尾省略。当元素列表中的逗号前面没有 AssignmentExpression(即开头的逗号或另一个逗号后面的逗号)时,缺失的数组元素会增加数组的长度并增加后续元素的索引。省略的数组元素未定义。如果在数组末尾省略了元素,该元素不会增加数组的长度。

语法

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 运行时语义:ArrayAccumulation

语法导向操作 ArrayAccumulation 接受参数 array(一个数组)和 nextIndex(一个整数)并返回包含一个整数正常完成或一个突然完成。它在以下产生式上分段定义:

Elision : ,
  1. lennextIndex + 1。
  2. 执行 ? Set(array, "length", 𝔽(len), true)。
  3. 注:如果 len 超过 232 - 1,上述步骤会抛出异常。
  4. 返回 len
Elision : Elision ,
  1. 返回 ? Elision 与参数 array 和 (nextIndex + 1) 的 ArrayAccumulation
ElementList : Elisionopt AssignmentExpression
  1. 如果 Elision 存在,则
    1. 设置 nextIndex 为 ? Elision 与参数 arraynextIndexArrayAccumulation
  2. initResult 为 ? AssignmentExpressionEvaluation
  3. initValue 为 ? GetValue(initResult)。
  4. 执行 ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(nextIndex)), initValue)。
  5. 返回 nextIndex + 1。
ElementList : Elisionopt SpreadElement
  1. 如果 Elision 存在,则
    1. 设置 nextIndex 为 ? Elision 与参数 arraynextIndexArrayAccumulation
  2. 返回 ? SpreadElement 与参数 arraynextIndexArrayAccumulation
ElementList : ElementList , Elisionopt AssignmentExpression
  1. 设置 nextIndex 为 ? ElementList 与参数 arraynextIndexArrayAccumulation
  2. 如果 Elision 存在,则
    1. 设置 nextIndex 为 ? Elision 与参数 arraynextIndexArrayAccumulation
  3. initResult 为 ? AssignmentExpressionEvaluation
  4. initValue 为 ? GetValue(initResult)。
  5. 执行 ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(nextIndex)), initValue)。
  6. 返回 nextIndex + 1。
ElementList : ElementList , Elisionopt SpreadElement
  1. 设置 nextIndex 为 ? ElementList 与参数 arraynextIndexArrayAccumulation
  2. 如果 Elision 存在,则
    1. 设置 nextIndex 为 ? Elision 与参数 arraynextIndexArrayAccumulation
  3. 返回 ? SpreadElement 与参数 arraynextIndexArrayAccumulation
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. 设置 nextIndexnextIndex + 1。

使用 CreateDataPropertyOrThrow 来确保为数组定义自己的属性,即使标准内置的Array 原型对象已经以会阻止使用 [[Set]] 创建新自己属性的方式被修改。

13.2.4.2 运行时语义:Evaluation

ArrayLiteral : [ Elisionopt ]
  1. array 为 ! ArrayCreate(0)。
  2. 如果 Elision 存在,则
    1. 执行 ? Elision 与参数 array 和 0 的 ArrayAccumulation
  3. 返回 array
ArrayLiteral : [ ElementList ]
  1. array 为 ! ArrayCreate(0)。
  2. 执行 ? ElementList 与参数 array 和 0 的 ArrayAccumulation
  3. 返回 array
ArrayLiteral : [ ElementList , Elisionopt ]
  1. array 为 ! ArrayCreate(0)。
  2. nextIndex 为 ? ElementList 与参数 array 和 0 的 ArrayAccumulation
  3. 如果 Elision 存在,则
    1. 执行 ? Elision 与参数 arraynextIndexArrayAccumulation
  4. 返回 array

13.2.5 对象初始化器

注 1

对象初始化器是一个表达式,描述对象的初始化,以类似字面量的形式编写。它是零个或多个属性键和关联值的对的列表,包含在花括号中。值不需要是字面量;每次求值对象初始化器时都会对它们进行求值。

语法

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] 注 2

MethodDefinition15.4 中定义。

注 3

在某些上下文中,ObjectLiteral 用作更受限制的次级语法的覆盖语法。CoverInitializedName 产生式是完全覆盖这些次级语法所必需的。但是,在期望实际 ObjectLiteral 的正常上下文中,使用此产生式会导致早期语法错误。

13.2.5.1 静态语义:早期错误

PropertyDefinition : MethodDefinition

除了描述实际的对象初始化器之外,ObjectLiteral 产生式还用作 ObjectAssignmentPattern 的覆盖语法,并且可能被识别为 CoverParenthesizedExpressionAndArrowParameterList 的一部分。当 ObjectLiteral 出现在需要 ObjectAssignmentPattern 的上下文中时,以下早期错误规则适用。此外,在最初解析 CoverParenthesizedExpressionAndArrowParameterListCoverCallExpressionAndAsyncArrowHead 时,它们也不适用。

PropertyDefinition : CoverInitializedName
  • 如果任何源文本与此产生式匹配,则是语法错误。
注 1

此产生式的存在是为了让 ObjectLiteral 可以作为 ObjectAssignmentPattern 的覆盖语法。它不能出现在实际的对象初始化器中。

ObjectLiteral : { PropertyDefinitionList } { PropertyDefinitionList , } 注 2

PropertyNameList 返回的列表不包括使用 ComputedPropertyName 定义的属性名。

13.2.5.2 静态语义:IsComputedPropertyKey

语法导向操作 IsComputedPropertyKey 不接受参数并返回布尔值。它在以下产生式上分段定义:

PropertyName : LiteralPropertyName
  1. 返回 false
PropertyName : ComputedPropertyName
  1. 返回 true

13.2.5.3 静态语义:PropertyNameList

语法导向操作 PropertyNameList 不接受参数并返回字符串的列表。它在以下产生式上分段定义:

PropertyDefinitionList : PropertyDefinition
  1. propNamePropertyDefinitionPropName
  2. 如果 propNameempty,返回新的空列表
  3. 返回 « propName »。
PropertyDefinitionList : PropertyDefinitionList , PropertyDefinition
  1. listPropertyDefinitionListPropertyNameList
  2. propNamePropertyDefinitionPropName
  3. 如果 propNameempty,返回 list
  4. 返回 list 和 « propName » 的列表连接

13.2.5.4 运行时语义:Evaluation

ObjectLiteral : { }
  1. 返回 OrdinaryObjectCreate(%Object.prototype%)。
ObjectLiteral : { PropertyDefinitionList } { PropertyDefinitionList , }
  1. objOrdinaryObjectCreate(%Object.prototype%)。
  2. 执行 ? PropertyDefinitionList 与参数 objPropertyDefinitionEvaluation
  3. 返回 obj
LiteralPropertyName : IdentifierName
  1. 返回 IdentifierNameStringValue
LiteralPropertyName : StringLiteral
  1. 返回 StringLiteralSV
LiteralPropertyName : NumericLiteral
  1. nbrNumericLiteralNumericValue
  2. 返回 ! ToString(nbr)。
ComputedPropertyName : [ AssignmentExpression ]
  1. exprValue 为 ? AssignmentExpressionEvaluation
  2. propName 为 ? GetValue(exprValue)。
  3. 返回 ? ToPropertyKey(propName)。

13.2.5.5 运行时语义:PropertyDefinitionEvaluation

语法导向操作 PropertyDefinitionEvaluation 接受参数 object(一个对象)并返回包含 unused正常完成突然完成。它在以下产生式上分段定义:

PropertyDefinitionList : PropertyDefinitionList , PropertyDefinition
  1. 执行 ? PropertyDefinitionList 与参数 objectPropertyDefinitionEvaluation
  2. 执行 ? PropertyDefinition 与参数 objectPropertyDefinitionEvaluation
  3. 返回 unused
PropertyDefinition : ... AssignmentExpression
  1. exprValue 为 ? AssignmentExpressionEvaluation
  2. fromValue 为 ? GetValue(exprValue)。
  3. excludedNames 为新的空列表
  4. 执行 ? CopyDataProperties(object, fromValue, excludedNames)。
  5. 返回 unused
PropertyDefinition : IdentifierReference
  1. propNameIdentifierReferenceStringValue
  2. exprValue 为 ? IdentifierReferenceEvaluation
  3. propValue 为 ? GetValue(exprValue)。
  4. 断言object 是一个普通的、可扩展的、没有不可配置属性的对象。
  5. 执行 ! CreateDataPropertyOrThrow(object, propName, propValue)。
  6. 返回 unused
PropertyDefinition : PropertyName : AssignmentExpression
  1. propKey 为 ? PropertyNameEvaluation
  2. 如果此 PropertyDefinition 包含在正在为 ParseJSON 求值的 Script 中(参见 ParseJSON 的步骤 6),则
    1. isProtoSetterfalse
  3. 否则,如果 propKey"__proto__" 并且 PropertyNameIsComputedPropertyKeyfalse,则
    1. isProtoSettertrue
  4. 否则,
    1. isProtoSetterfalse
  5. 如果 IsAnonymousFunctionDefinition(AssignmentExpression) 是 true 并且 isProtoSetterfalse,则
    1. propValue 为 ? AssignmentExpression 与参数 propKeyNamedEvaluation
  6. 否则,
    1. exprValueRef 为 ? AssignmentExpressionEvaluation
    2. propValue 为 ? GetValue(exprValueRef)。
  7. 如果 isProtoSettertrue,则
    1. 如果 propValue 是对象propValuenull,则
      1. 执行 ! object.[[SetPrototypeOf]](propValue)。
    2. 返回 unused
  8. 断言object 是一个普通的、可扩展的、没有不可配置属性的对象。
  9. 执行 ! CreateDataPropertyOrThrow(object, propKey, propValue)。
  10. 返回 unused
PropertyDefinition : MethodDefinition
  1. 执行 ? MethodDefinition 与参数 objecttrueMethodDefinitionEvaluation
  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 静态语义:早期错误

PrimaryExpression : RegularExpressionLiteral

13.2.7.2 静态语义:IsValidRegularExpressionLiteral ( literal )

抽象操作 IsValidRegularExpressionLiteral 接受参数 literal(一个 RegularExpressionLiteral 解析节点)并返回布尔值。它确定其参数是否是有效的正则表达式字面量。调用时执行以下步骤:

  1. flagsliteralFlagText
  2. 如果 flags 包含除 dgimsuvy 之外的任何码点,或者如果 flags 包含任何码点超过一次,返回 false
  3. 如果 flags 包含 u,令 utrue;否则令 ufalse
  4. 如果 flags 包含 v,令 vtrue;否则令 vfalse
  5. patternTextliteralBodyText
  6. 如果 ufalsevfalse,则
    1. stringValueCodePointsToString(patternText)。
    2. 设置 patternText 为通过将 stringValue 的每个 16 位元素解释为 Unicode BMP 码点而产生的码点序列。UTF-16 解码不应用于这些元素。
  7. parseResultParsePattern(patternText, u, v)。
  8. 如果 parseResult解析节点,返回 true;否则返回 false

13.2.7.3 运行时语义: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 静态语义:早期错误

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 静态语义:TemplateStrings

语法导向操作 TemplateStrings 接受参数 raw(布尔值)并返回字符串或 undefined列表。它在以下产生式上分段定义:

TemplateLiteral : NoSubstitutionTemplate
  1. 返回 « TemplateString(NoSubstitutionTemplate, raw) »。
SubstitutionTemplate : TemplateHead Expression TemplateSpans
  1. head 为 « TemplateString(TemplateHead, raw) »。
  2. tailTemplateSpans 使用参数 rawTemplateStrings
  3. 返回 headtail列表连接
TemplateSpans : TemplateTail
  1. 返回 « TemplateString(TemplateTail, raw) »。
TemplateSpans : TemplateMiddleList TemplateTail
  1. middleTemplateMiddleList 使用参数 rawTemplateStrings
  2. tail 为 « TemplateString(TemplateTail, raw) »。
  3. 返回 middletail列表连接
TemplateMiddleList : TemplateMiddle Expression
  1. 返回 « TemplateString(TemplateMiddle, raw) »。
TemplateMiddleList : TemplateMiddleList TemplateMiddle Expression
  1. frontTemplateMiddleList 使用参数 rawTemplateStrings
  2. last 为 « TemplateString(TemplateMiddle, raw) »。
  3. 返回 frontlast列表连接

13.2.8.3 静态语义:TemplateString ( templateToken, raw )

抽象操作 TemplateString 接受参数 templateToken(一个 NoSubstitutionTemplate 解析节点TemplateHead 解析节点TemplateMiddle 解析节点,或 TemplateTail 解析节点)和 raw(布尔值)并返回字符串或 undefined。调用时执行以下步骤:

  1. 如果 rawtrue,则
    1. stringtemplateTokenTRV
  2. 否则,
    1. stringtemplateTokenTV
  3. 返回 string

如果 rawfalsetemplateToken 包含 NotEscapeSequence,此操作返回 undefined。在所有其他情况下,它返回字符串。

13.2.8.4 GetTemplateObject ( templateLiteral )

抽象操作 GetTemplateObject 接受参数 templateLiteral(一个解析节点)并返回数组。调用时执行以下步骤:

  1. realm当前领域记录
  2. templateRegistryrealm.[[TemplateMap]]
  3. 对于 templateRegistry 的每个元素 e,执行
    1. 如果 e.[[Site]]templateLiteral同一个解析节点,则
      1. 返回 e.[[Array]]
  4. rawStringstemplateLiteral 使用参数 trueTemplateStrings
  5. 断言rawStrings 是字符串的列表
  6. cookedStringstemplateLiteral 使用参数 falseTemplateStrings
  7. count列表 cookedStrings 中的元素数量。
  8. 断言count ≤ 232 - 1。
  9. template 为 ! ArrayCreate(count)。
  10. rawObj 为 ! ArrayCreate(count)。
  11. index 为 0。
  12. 重复,当 index < count 时,
    1. prop 为 ! ToString(𝔽(index))。
    2. cookedValuecookedStrings[index]。
    3. 执行 ! DefinePropertyOrThrow(template, prop, PropertyDescriptor { [[Value]]: cookedValue, [[Writable]]: false, [[Enumerable]]: true, [[Configurable]]: false })。
    4. rawValue 为字符串值 rawStrings[index]。
    5. 执行 ! DefinePropertyOrThrow(rawObj, prop, PropertyDescriptor { [[Value]]: rawValue, [[Writable]]: false, [[Enumerable]]: true, [[Configurable]]: false })。
    6. 设置 indexindex + 1。
  13. 执行 ! SetIntegrityLevel(rawObj, frozen)。
  14. 执行 ! DefinePropertyOrThrow(template, "raw", PropertyDescriptor { [[Value]]: rawObj, [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false })。
  15. 执行 ! SetIntegrityLevel(template, frozen)。
  16. 记录 { [[Site]]: templateLiteral, [[Array]]: template } 附加到 realm.[[TemplateMap]]
  17. 返回 template
注 1

模板对象的创建不能导致突然完成

注 2

领域程序代码中的每个 TemplateLiteral 都与一个唯一的模板对象相关联,该对象用于带标签模板的求值(13.2.8.6)。模板对象被冻结,每次求值特定带标签模板时都使用相同的模板对象。模板对象是在首次求值 TemplateLiteral 时惰性创建,还是在首次求值前急切创建,是实现选择,ECMAScript 代码无法观察到。

注 3

本规范的未来版本可能定义模板对象的附加不可枚举属性。

13.2.8.5 运行时语义:SubstitutionEvaluation

语法导向操作 SubstitutionEvaluation 不接受参数并返回包含 ECMAScript 语言值列表正常完成突然完成。它在以下产生式上分段定义:

TemplateSpans : TemplateTail
  1. 返回新的空列表
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 运行时语义:Evaluation

TemplateLiteral : NoSubstitutionTemplate
  1. 返回 NoSubstitutionTemplateTV,如 12.9.6 中定义。
SubstitutionTemplate : TemplateHead Expression TemplateSpans
  1. headTemplateHeadTV,如 12.9.6 中定义。
  2. subRef 为 ? ExpressionEvaluation
  3. sub 为 ? GetValue(subRef)。
  4. middle 为 ? ToString(sub)。
  5. tail 为 ? TemplateSpansEvaluation
  6. 返回 headmiddletail字符串连接
注 1

应用于 Expression 值的字符串转换语义类似于 String.prototype.concat 而不是 + 运算符。

TemplateSpans : TemplateTail
  1. 返回 TemplateTailTV,如 12.9.6 中定义。
TemplateSpans : TemplateMiddleList TemplateTail
  1. head 为 ? TemplateMiddleListEvaluation
  2. tailTemplateTailTV,如 12.9.6 中定义。
  3. 返回 headtail字符串连接
TemplateMiddleList : TemplateMiddle Expression
  1. headTemplateMiddleTV,如 12.9.6 中定义。
  2. subRef 为 ? ExpressionEvaluation
  3. sub 为 ? GetValue(subRef)。
  4. middle 为 ? ToString(sub)。
  5. 返回 headmiddle字符串连接
注 2

应用于 Expression 值的字符串转换语义类似于 String.prototype.concat 而不是 + 运算符。

TemplateMiddleList : TemplateMiddleList TemplateMiddle Expression
  1. rest 为 ? TemplateMiddleListEvaluation
  2. middleTemplateMiddleTV,如 12.9.6 中定义。
  3. subRef 为 ? ExpressionEvaluation
  4. sub 为 ? GetValue(subRef)。
  5. last 为 ? ToString(sub)。
  6. 返回 restmiddlelast字符串连接
注 3

应用于 Expression 值的字符串转换语义类似于 String.prototype.concat 而不是 + 运算符。

13.2.9 分组运算符

13.2.9.1 静态语义:早期错误

PrimaryExpression : CoverParenthesizedExpressionAndArrowParameterList

13.2.9.2 运行时语义:Evaluation

PrimaryExpression : CoverParenthesizedExpressionAndArrowParameterList
  1. expr 为被 CoverParenthesizedExpressionAndArrowParameterList 覆盖ParenthesizedExpression
  2. 返回 ? exprEvaluation
ParenthesizedExpression : ( Expression )
  1. 返回 ? ExpressionEvaluation。这可能是引用类型。

此算法不对 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 静态语义:早期错误

OptionalChain : ?. TemplateLiteral OptionalChain TemplateLiteral
  • 如果任何源文本与此产生式匹配,则是语法错误。

此产生式的存在是为了防止自动分号插入规则(12.10)应用于以下代码:

a?.b
`c`

这样它就不会被解释为两个有效的语句。目的是与没有可选链的类似代码保持一致:

a.b
`c`

这是一个有效的语句,其中不应用自动分号插入。

ImportMeta : import . meta

13.3.2 属性访问器

属性通过名称进行访问,可以使用点记法:

或括号记法:

点记法通过以下语法转换解释:

在行为上等同于

MemberExpression [ <identifier-name-string> ]

同样地

在行为上等同于

CallExpression [ <identifier-name-string> ]

其中 <identifier-name-string> 是 IdentifierNameStringValue

13.3.2.1 运行时语义:Evaluation

MemberExpression : MemberExpression [ Expression ]
  1. baseReference 为 ? MemberExpressionEvaluation
  2. baseValue 为 ? GetValue(baseReference)。
  3. strict 为此 MemberExpressionIsStrict
  4. 返回 ? EvaluatePropertyAccessWithExpressionKey(baseValue, Expression, strict)。
MemberExpression : MemberExpression . IdentifierName
  1. baseReference 为 ? MemberExpressionEvaluation
  2. baseValue 为 ? GetValue(baseReference)。
  3. strict 为此 MemberExpressionIsStrict
  4. 返回 EvaluatePropertyAccessWithIdentifierKey(baseValue, IdentifierName, strict)。
MemberExpression : MemberExpression . PrivateIdentifier
  1. baseReference 为 ? MemberExpressionEvaluation
  2. baseValue 为 ? GetValue(baseReference)。
  3. fieldNameStringPrivateIdentifierStringValue
  4. 返回 MakePrivateReference(baseValue, fieldNameString)。
CallExpression : CallExpression [ Expression ]
  1. baseReference 为 ? CallExpressionEvaluation
  2. baseValue 为 ? GetValue(baseReference)。
  3. strict 为此 CallExpressionIsStrict
  4. 返回 ? EvaluatePropertyAccessWithExpressionKey(baseValue, Expression, strict)。
CallExpression : CallExpression . IdentifierName
  1. baseReference 为 ? CallExpressionEvaluation
  2. baseValue 为 ? GetValue(baseReference)。
  3. strict 为此 CallExpressionIsStrict
  4. 返回 EvaluatePropertyAccessWithIdentifierKey(baseValue, IdentifierName, strict)。
CallExpression : CallExpression . PrivateIdentifier
  1. baseReference 为 ? CallExpressionEvaluation
  2. baseValue 为 ? GetValue(baseReference)。
  3. fieldNameStringPrivateIdentifierStringValue
  4. 返回 MakePrivateReference(baseValue, fieldNameString)。

13.3.3 EvaluatePropertyAccessWithExpressionKey ( baseValue, expression, strict )

抽象操作 EvaluatePropertyAccessWithExpressionKey 接受参数 baseValue(一个 ECMAScript 语言值)、 expression(一个 Expression 解析节点)和 strict(一个布尔值),返回包含 引用记录正常完成突然完成。当调用时执行以下步骤:

  1. propertyNameReference 为 ? expressionEvaluation
  2. propertyNameValue 为 ? GetValue(propertyNameReference)。
  3. 注:在大多数情况下,ToPropertyKey 将在此步骤之后立即对 propertyNameValue 执行。但是,在 a[b] = c 的情况下,它将直到 c 求值之后才执行。
  4. 返回引用记录 { [[Base]]: baseValue, [[ReferencedName]]: propertyNameValue, [[Strict]]: strict, [[ThisValue]]: empty }。

13.3.4 EvaluatePropertyAccessWithIdentifierKey ( baseValue, identifierName, strict )

抽象操作 EvaluatePropertyAccessWithIdentifierKey 接受参数 baseValue(一个 ECMAScript 语言值)、 identifierName(一个 IdentifierName 解析节点)和 strict(一个布尔值),返回一个 引用记录。当调用时执行以下步骤:

  1. propertyNameStringidentifierNameStringValue
  2. 返回引用记录 { [[Base]]: baseValue, [[ReferencedName]]: propertyNameString, [[Strict]]: strict, [[ThisValue]]: empty }。

13.3.5 new 运算符

13.3.5.1 运行时语义:Evaluation

NewExpression : new NewExpression
  1. 返回 ? EvaluateNew(NewExpression, empty)。
MemberExpression : new MemberExpression Arguments
  1. 返回 ? EvaluateNew(MemberExpression, Arguments)。

13.3.5.1.1 EvaluateNew ( constructExpr, arguments )

抽象操作 EvaluateNew 接受参数 constructExpr(一个 NewExpression 解析节点或一个 MemberExpression 解析节点)和 argumentsempty 或一个 Arguments 解析节点),返回包含 ECMAScript 语言值正常完成突然完成。当调用时执行以下步骤:

  1. ref 为 ? constructExprEvaluation
  2. constructor 为 ? GetValue(ref)。
  3. 如果 argumentsempty,则
    1. argList 为新的空列表
  4. 否则,
    1. argList 为 ? argumentsArgumentListEvaluation
  5. 如果 IsConstructor(constructor) 是 false,抛出 TypeError 异常。
  6. 返回 ? Construct(constructor, argList)。

13.3.6 函数调用

13.3.6.1 运行时语义:Evaluation

CallExpression : CoverCallExpressionAndAsyncArrowHead
  1. expr 为被 CoverCallExpressionAndAsyncArrowHead 覆盖CallMemberExpression
  2. memberExprexprMemberExpression
  3. argumentsexprArguments
  4. ref 为 ? memberExprEvaluation
  5. func 为 ? GetValue(ref)。
  6. 如果 ref引用记录IsPropertyReference(ref) 是 false,且 ref.[[ReferencedName]]"eval",则
    1. 如果 SameValue(func, %eval%) 是 true,则
      1. argList 为 ? argumentsArgumentListEvaluation
      2. 如果 argList 没有元素,返回 undefined
      3. evalArgargList 的第一个元素。
      4. 如果此 CallExpressionIsStricttrue,则令 strictCallertrue。否则令 strictCallerfalse
      5. 返回 ? PerformEval(evalArg, strictCaller, true)。
  7. thisCall 为此 CallExpression
  8. tailCallIsInTailPosition(thisCall)。
  9. 返回 ? EvaluateCall(func, ref, arguments, tailCall)。

执行步骤 6.a.vCallExpression 求值是直接 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, ref, arguments, tailPosition )

抽象操作 EvaluateCall 接受参数 func(一个 ECMAScript 语言值)、 ref(一个 ECMAScript 语言值引用记录)、 arguments(一个 解析节点)和 tailPosition(一个布尔值),返回包含 ECMAScript 语言值正常完成突然完成。当调用时执行以下步骤:

  1. 如果 ref引用记录,则
    1. 如果 IsPropertyReference(ref) 是 true,则
      1. thisValueGetThisValue(ref)。
    2. 否则,
      1. refEnvref.[[Base]]
      2. 断言refEnv环境记录
      3. thisValuerefEnv.WithBaseObject()。
  2. 否则,
    1. thisValueundefined
  3. argList 为 ? argumentsArgumentListEvaluation
  4. 如果 func 不是对象,抛出 TypeError 异常。
  5. 如果 IsCallable(func) 是 false,抛出 TypeError 异常。
  6. 如果 tailPositiontrue,执行 PrepareForTailCall()。
  7. 返回 ? Call(func, thisValue, argList)。

13.3.7 super 关键字

13.3.7.1 运行时语义:Evaluation

SuperProperty : super [ Expression ]
  1. envGetThisEnvironment()。
  2. actualThis 为 ? env.GetThisBinding()。
  3. propertyNameReference 为 ? ExpressionEvaluation
  4. propertyNameValue 为 ? GetValue(propertyNameReference)。
  5. strict 为此 SuperPropertyIsStrict
  6. 注:在大多数情况下,ToPropertyKey 将在此步骤之后立即对 propertyNameValue 执行。但是,在 super[b] = c 的情况下,它将直到 c 求值之后才执行。
  7. 返回 MakeSuperPropertyReference(actualThis, propertyNameValue, strict)。
SuperProperty : super . IdentifierName
  1. envGetThisEnvironment()。
  2. actualThis 为 ? env.GetThisBinding()。
  3. propertyKeyIdentifierNameStringValue
  4. strict 为此 SuperPropertyIsStrict
  5. 返回 MakeSuperPropertyReference(actualThis, propertyKey, strict)。
SuperCall : super Arguments
  1. newTargetGetNewTarget()。
  2. 断言newTarget构造器
  3. funcGetSuperConstructor()。
  4. argList 为 ? ArgumentsArgumentListEvaluation
  5. 如果 IsConstructor(func) 是 false,抛出 TypeError 异常。
  6. result 为 ? Construct(func, argList, newTarget)。
  7. thisERGetThisEnvironment()。
  8. 断言thisER函数环境记录
  9. 执行 ? BindThisValue(thisER, result)。
  10. FthisER.[[FunctionObject]]
  11. 断言F 是 ECMAScript 函数对象
  12. 执行 ? InitializeInstanceElements(result, F)。
  13. 返回 result

13.3.7.2 GetSuperConstructor ( )

抽象操作 GetSuperConstructor 不接受参数,返回一个 ECMAScript 语言值。当调用时执行以下步骤:

  1. envRecGetThisEnvironment()。
  2. 断言envRec函数环境记录
  3. activeFunctionenvRec.[[FunctionObject]]
  4. 断言activeFunction 是 ECMAScript 函数对象
  5. superConstructor 为 ! activeFunction.[[GetPrototypeOf]]()。
  6. 返回 superConstructor

13.3.7.3 MakeSuperPropertyReference ( actualThis, propertyKey, strict )

抽象操作 MakeSuperPropertyReference 接受参数 actualThis(一个 ECMAScript 语言值)、 propertyKey(一个 ECMAScript 语言值)和 strict(一个布尔值),返回一个 Super 引用记录。当调用时执行以下步骤:

  1. envGetThisEnvironment()。
  2. 断言env.HasSuperBinding() 是 true
  3. 断言env函数环境记录
  4. baseValueGetSuperBase(env)。
  5. 返回引用记录 { [[Base]]: baseValue, [[ReferencedName]]: propertyKey, [[Strict]]: strict, [[ThisValue]]: actualThis }。

13.3.8 参数列表

参数列表的求值产生一个值的 列表

13.3.8.1 运行时语义:ArgumentListEvaluation

语法制导操作 ArgumentListEvaluation 不接受参数,返回包含 ECMAScript 语言值列表正常完成突然完成。它在以下产生式上分段定义:

Arguments : ( )
  1. 返回新的空列表
ArgumentList : AssignmentExpression
  1. ref 为 ? AssignmentExpressionEvaluation
  2. arg 为 ? GetValue(ref)。
  3. 返回 « arg »。
ArgumentList : ... AssignmentExpression
  1. 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 是可能为空的列表
  5. 返回 « firstSub » 和 restSub列表连接

13.3.9 可选链

可选链是一个或多个属性访问和函数调用的链,其中第一个以标记 ?. 开始。

13.3.9.1 运行时语义:Evaluation

OptionalExpression : MemberExpression OptionalChain
  1. baseReference 为 ? MemberExpressionEvaluation
  2. baseValue 为 ? GetValue(baseReference)。
  3. 如果 baseValueundefinednull,则
    1. 返回 undefined
  4. 返回 ? OptionalChainbaseValuebaseReference 为参数的 ChainEvaluation
OptionalExpression : CallExpression OptionalChain
  1. baseReference 为 ? CallExpressionEvaluation
  2. baseValue 为 ? GetValue(baseReference)。
  3. 如果 baseValueundefinednull,则
    1. 返回 undefined
  4. 返回 ? OptionalChainbaseValuebaseReference 为参数的 ChainEvaluation
OptionalExpression : OptionalExpression OptionalChain
  1. baseReference 为 ? OptionalExpressionEvaluation
  2. baseValue 为 ? GetValue(baseReference)。
  3. 如果 baseValueundefinednull,则
    1. 返回 undefined
  4. 返回 ? OptionalChainbaseValuebaseReference 为参数的 ChainEvaluation

13.3.9.2 运行时语义:ChainEvaluation

语法制导操作 ChainEvaluation 接受参数 baseValue(一个 ECMAScript 语言值)和 baseReference(一个 ECMAScript 语言值引用记录),返回包含 ECMAScript 语言值引用记录正常完成,或突然完成。它在以下产生式上分段定义:

OptionalChain : ?. Arguments
  1. thisChain 为此 OptionalChain
  2. tailCallIsInTailPosition(thisChain)。
  3. 返回 ? EvaluateCall(baseValue, baseReference, Arguments, tailCall)。
OptionalChain : ?. [ Expression ]
  1. strict 为此 OptionalChainIsStrict
  2. 返回 ? EvaluatePropertyAccessWithExpressionKey(baseValue, Expression, strict)。
OptionalChain : ?. IdentifierName
  1. strict 为此 OptionalChainIsStrict
  2. 返回 EvaluatePropertyAccessWithIdentifierKey(baseValue, IdentifierName, strict)。
OptionalChain : ?. PrivateIdentifier
  1. fieldNameStringPrivateIdentifierStringValue
  2. 返回 MakePrivateReference(baseValue, fieldNameString)。
OptionalChain : OptionalChain Arguments
  1. optionalChainOptionalChain
  2. newReference 为 ? optionalChainbaseValuebaseReference 为参数的 ChainEvaluation
  3. newValue 为 ? GetValue(newReference)。
  4. thisChain 为此 OptionalChain
  5. tailCallIsInTailPosition(thisChain)。
  6. 返回 ? EvaluateCall(newValue, newReference, Arguments, tailCall)。
OptionalChain : OptionalChain [ Expression ]
  1. optionalChainOptionalChain
  2. newReference 为 ? optionalChainbaseValuebaseReference 为参数的 ChainEvaluation
  3. newValue 为 ? GetValue(newReference)。
  4. strict 为此 OptionalChainIsStrict
  5. 返回 ? EvaluatePropertyAccessWithExpressionKey(newValue, Expression, strict)。
OptionalChain : OptionalChain . IdentifierName
  1. optionalChainOptionalChain
  2. newReference 为 ? optionalChainbaseValuebaseReference 为参数的 ChainEvaluation
  3. newValue 为 ? GetValue(newReference)。
  4. strict 为此 OptionalChainIsStrict
  5. 返回 EvaluatePropertyAccessWithIdentifierKey(newValue, IdentifierName, strict)。
OptionalChain : OptionalChain . PrivateIdentifier
  1. optionalChainOptionalChain
  2. newReference 为 ? optionalChainbaseValuebaseReference 为参数的 ChainEvaluation
  3. newValue 为 ? GetValue(newReference)。
  4. fieldNameStringPrivateIdentifierStringValue
  5. 返回 MakePrivateReference(newValue, fieldNameString)。

13.3.10 Import 调用

13.3.10.1 运行时语义:Evaluation

ImportCall : import ( AssignmentExpression ,opt )
  1. 返回 ? EvaluateImportCall(AssignmentExpression)。
ImportCall : import ( AssignmentExpression , AssignmentExpression ,opt )
  1. 返回 ? EvaluateImportCall(第一个 AssignmentExpression, 第二个 AssignmentExpression)。

13.3.10.2 EvaluateImportCall ( specifierExpression [ , optionsExpression ] )

抽象操作 EvaluateImportCall 接受参数 specifierExpression(一个 解析节点)和可选参数 optionsExpression(一个 解析节点),返回包含 Promise 的正常完成突然完成。当调用时执行以下步骤:

  1. referrerGetActiveScriptOrModule()。
  2. 如果 referrernull,设置 referrer当前 Realm 记录
  3. specifierRef 为 ? specifierExpressionEvaluation
  4. specifier 为 ? GetValue(specifierRef)。
  5. 如果 optionsExpression 存在,则
    1. optionsRef 为 ? optionsExpressionEvaluation
    2. options 为 ? GetValue(optionsRef)。
  6. 否则,
    1. optionsundefined
  7. promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  8. specifierStringCompletion(ToString(specifier))。
  9. IfAbruptRejectPromise(specifierString, promiseCapability)。
  10. attributes 为新的空列表
  11. 如果 options 不是 undefined,则
    1. 如果 options 不是对象,则
      1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « 新创建的 TypeError 对象 »)。
      2. 返回 promiseCapability.[[Promise]]
    2. attributesObjCompletion(Get(options, "with"))。
    3. IfAbruptRejectPromise(attributesObj, promiseCapability)。
    4. 如果 attributesObj 不是 undefined,则
      1. 如果 attributesObj 不是对象,则
        1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « 新创建的 TypeError 对象 »)。
        2. 返回 promiseCapability.[[Promise]]
      2. entriesCompletion(EnumerableOwnProperties(attributesObj, key+value))。
      3. IfAbruptRejectPromise(entries, promiseCapability)。
      4. 对于 entries 的每个元素 entry,执行
        1. key 为 ! Get(entry, "0")。
        2. value 为 ! Get(entry, "1")。
        3. 如果 key 是字符串,则
          1. 如果 value 不是字符串,则
            1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « 新创建的 TypeError 对象 »)。
            2. 返回 promiseCapability.[[Promise]]
          2. ImportAttribute 记录 { [[Key]]: key, [[Value]]: value } 附加到 attributes
    5. 如果 AllImportAttributesSupported(attributes) 是 false,则
      1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « 新创建的 TypeError 对象 »)。
      2. 返回 promiseCapability.[[Promise]]
    6. 按照其 [[Key]] 字段的字典序对 attributes 进行排序,将每个此类字段的值视为 UTF-16 代码单元值的序列。注:此排序仅在禁止宿主基于属性枚举的顺序改变行为这一点上是可观察的。
  12. moduleRequest 为新的ModuleRequest 记录 { [[Specifier]]: specifierString, [[Attributes]]: attributes }。
  13. 执行 HostLoadImportedModule(referrer, moduleRequest, empty, promiseCapability)。
  14. 返回 promiseCapability.[[Promise]]

13.3.10.3 ContinueDynamicImport ( promiseCapability, moduleCompletion )

抽象操作 ContinueDynamicImport 接受参数 promiseCapability(一个 PromiseCapability 记录)和 moduleCompletion包含 模块记录正常完成抛出完成),返回 unused。它完成最初由 import() 调用开始的动态导入过程,适当地解决或拒绝由该调用返回的 promise。当调用时执行以下步骤:

  1. 如果 moduleCompletion突然完成,则
    1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « moduleCompletion.[[Value]] »)。
    2. 返回 unused
  2. modulemoduleCompletion.[[Value]]
  3. loadPromisemodule.LoadRequestedModules()。
  4. rejectedClosure 为新的抽象闭包,参数为 (reason),捕获 promiseCapability 并在调用时执行以下步骤:
    1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « reason »)。
    2. 返回 unused
  5. onRejectedCreateBuiltinFunction(rejectedClosure, 1, "", « »)。
  6. linkAndEvaluateClosure 为新的抽象闭包,无参数,捕获 modulepromiseCapabilityonRejected 并在调用时执行以下步骤:
    1. linkCompletion(module.Link())。
    2. 如果 link突然完成,则
      1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « link.[[Value]] »)。
      2. 返回 unused
    3. evaluatePromisemodule.Evaluate()。
    4. fulfilledClosure 为新的抽象闭包,无参数,捕获 modulepromiseCapability 并在调用时执行以下步骤:
      1. namespaceGetModuleNamespace(module)。
      2. 执行 ! Call(promiseCapability.[[Resolve]], undefined, « namespace »)。
      3. 返回 unused
    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 标记模板

标记模板是一个函数调用,其中调用的参数来源于 TemplateLiteral (13.2.8)。实际参数包括模板对象(13.2.8.4)和通过求值嵌入在 TemplateLiteral 中的表达式产生的值。

13.3.11.1 运行时语义: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 运行时语义:Evaluation

NewTarget : new . target
  1. 返回 GetNewTarget()。
ImportMeta : import . meta
  1. moduleGetActiveScriptOrModule()。
  2. 断言module源文本模块记录
  3. importMetamodule.[[ImportMeta]]
  4. 如果 importMetaempty,则
    1. 设置 importMetaOrdinaryObjectCreate(null)。
    2. importMetaValuesHostGetImportMetaProperties(module)。
    3. 对于 importMetaValues 的每个记录 { [[Key]], [[Value]] } p,执行
      1. 执行 ! CreateDataPropertyOrThrow(importMeta, p.[[Key]], p.[[Value]])。
    4. 执行 HostFinalizeImportMeta(importMeta, module)。
    5. 设置 module.[[ImportMeta]]importMeta
    6. 返回 importMeta
  5. 否则,
    1. 断言importMeta 是对象
    2. 返回 importMeta

13.3.12.1.1 HostGetImportMetaProperties ( moduleRecord )

宿主定义的抽象操作 HostGetImportMetaProperties 接受参数 moduleRecord(一个模块记录),返回包含字段 [[Key]](一个属性键)和 [[Value]](一个ECMAScript 语言值)的记录列表。它允许宿主为从 import.meta 返回的对象提供属性键和值。

HostGetImportMetaProperties 的默认实现是返回新的空列表

13.3.12.1.2 HostFinalizeImportMeta ( importMeta, moduleRecord )

宿主定义的抽象操作 HostFinalizeImportMeta 接受参数 importMeta(一个对象)和 moduleRecord(一个模块记录),返回 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 静态语义:早期错误

UpdateExpression : LeftHandSideExpression ++ LeftHandSideExpression -- UpdateExpression : ++ UnaryExpression -- UnaryExpression

13.4.2 后缀递增运算符

13.4.2.1 运行时语义:Evaluation

UpdateExpression : LeftHandSideExpression ++
  1. lhs 为 ? LeftHandSideExpressionEvaluation
  2. oldValue 为 ? ToNumeric(? GetValue(lhs))。
  3. 如果 oldValue 是数字,则
    1. newValueNumber::add(oldValue, 1𝔽)。
  4. 否则,
    1. 断言oldValue 是 BigInt
    2. newValueBigInt::add(oldValue, 1)。
  5. 执行 ? PutValue(lhs, newValue)。
  6. 返回 oldValue

13.4.3 后缀递减运算符

13.4.3.1 运行时语义:Evaluation

UpdateExpression : LeftHandSideExpression --
  1. lhs 为 ? LeftHandSideExpressionEvaluation
  2. oldValue 为 ? ToNumeric(? GetValue(lhs))。
  3. 如果 oldValue 是数字,则
    1. newValueNumber::subtract(oldValue, 1𝔽)。
  4. 否则,
    1. 断言oldValue 是 BigInt
    2. newValueBigInt::subtract(oldValue, 1)。
  5. 执行 ? PutValue(lhs, newValue)。
  6. 返回 oldValue

13.4.4 前缀递增运算符

13.4.4.1 运行时语义:Evaluation

UpdateExpression : ++ UnaryExpression
  1. expr 为 ? UnaryExpressionEvaluation
  2. oldValue 为 ? ToNumeric(? GetValue(expr))。
  3. 如果 oldValue 是数字,则
    1. newValueNumber::add(oldValue, 1𝔽)。
  4. 否则,
    1. 断言oldValue 是 BigInt
    2. newValueBigInt::add(oldValue, 1)。
  5. 执行 ? PutValue(expr, newValue)。
  6. 返回 newValue

13.4.5 前缀递减运算符

13.4.5.1 运行时语义:Evaluation

UpdateExpression : -- UnaryExpression
  1. expr 为 ? UnaryExpressionEvaluation
  2. oldValue 为 ? ToNumeric(? GetValue(expr))。
  3. 如果 oldValue 是数字,则
    1. newValueNumber::subtract(oldValue, 1𝔽)。
  4. 否则,
    1. 断言oldValue 是 BigInt
    2. newValueBigInt::subtract(oldValue, 1)。
  5. 执行 ? PutValue(expr, newValue)。
  6. 返回 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] AwaitExpression[?Yield]

13.5.1 delete 运算符

13.5.1.1 静态语义:早期错误

UnaryExpression : delete UnaryExpression

最后一条规则意味着如 delete (((foo))) 这样的表达式由于第一条规则的递归应用而产生早期错误

13.5.1.2 运行时语义:Evaluation

UnaryExpression : delete UnaryExpression
  1. ref 为 ? UnaryExpressionEvaluation
  2. 如果 ref 不是引用记录,返回 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. 如果 deleteStatusfalse 并且 ref.[[Strict]]true,抛出 TypeError 异常。
    7. 返回 deleteStatus
  5. 否则,
    1. baseref.[[Base]]
    2. 断言base环境记录
    3. 返回 ? base.DeleteBinding(ref.[[ReferencedName]])。
注 1

delete 运算符出现在严格模式代码中时,如果其 UnaryExpression 是对变量、函数参数或函数名的直接引用,则抛出 SyntaxError 异常。此外,如果 delete 运算符出现在严格模式代码中并且要删除的属性具有属性 { [[Configurable]]: false }(或者无法删除),则抛出 TypeError 异常。

注 2

可能在步骤 4.c 中创建的对象在上述抽象操作和普通对象 [[Delete]] 内部方法之外是不可访问的。实现可能选择避免实际创建该对象。

13.5.2 void 运算符

13.5.2.1 运行时语义:Evaluation

UnaryExpression : void UnaryExpression
  1. expr 为 ? UnaryExpressionEvaluation
  2. 执行 ? GetValue(expr)。
  3. 返回 undefined

即使不使用 GetValue 的值,也必须调用它,因为它可能有可观察的副作用。

13.5.3 typeof 运算符

13.5.3.1 运行时语义:Evaluation

UnaryExpression : typeof UnaryExpression
  1. val 为 ? UnaryExpressionEvaluation
  2. 如果 val引用记录,则
    1. 如果 IsUnresolvableReference(val) 是 true,返回 "undefined"
  3. 设置 val 为 ? GetValue(val)。
  4. 如果 valundefined,返回 "undefined"
  5. 如果 valnull,返回 "object"
  6. 如果 val 是字符串,返回 "string"
  7. 如果 val 是符号,返回 "symbol"
  8. 如果 val 是布尔值,返回 "boolean"
  9. 如果 val 是数字,返回 "number"
  10. 如果 val 是 BigInt,返回 "bigint"
  11. 断言val 是对象
  12. 注:此步骤在 B.3.6.3 节中被替换。
  13. 如果 val 具有 [[Call]] 内部槽,返回 "function"
  14. 返回 "object"

13.5.4 一元 + 运算符

一元 + 运算符将其操作数转换为数字类型

13.5.4.1 运行时语义:Evaluation

UnaryExpression : + UnaryExpression
  1. expr 为 ? UnaryExpressionEvaluation
  2. 返回 ? ToNumber(? GetValue(expr))。

13.5.5 一元 - 运算符

一元 - 运算符将其操作数转换为数值然后对其取反。对 +0𝔽 取反产生 -0𝔽,对 -0𝔽 取反产生 +0𝔽

13.5.5.1 运行时语义:Evaluation

UnaryExpression : - UnaryExpression
  1. expr 为 ? UnaryExpressionEvaluation
  2. oldValue 为 ? ToNumeric(? GetValue(expr))。
  3. 如果 oldValue 是数字,则
    1. 返回 Number::unaryMinus(oldValue)。
  4. 否则,
    1. 断言oldValue 是 BigInt
    2. 返回 BigInt::unaryMinus(oldValue)。

13.5.6 按位非运算符(~

13.5.6.1 运行时语义:Evaluation

UnaryExpression : ~ UnaryExpression
  1. expr 为 ? UnaryExpressionEvaluation
  2. oldValue 为 ? ToNumeric(? GetValue(expr))。
  3. 如果 oldValue 是数字,则
    1. 返回 Number::bitwiseNOT(oldValue)。
  4. 否则,
    1. 断言oldValue 是 BigInt
    2. 返回 BigInt::bitwiseNOT(oldValue)。

13.5.7 逻辑非运算符(!

13.5.7.1 运行时语义: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 运行时语义:Evaluation

ExponentiationExpression : UpdateExpression ** ExponentiationExpression
  1. 返回 ? EvaluateStringOrNumericBinaryExpression(UpdateExpression, **, ExponentiationExpression)。

13.7 乘法运算符

语法

MultiplicativeExpression[Yield, Await] : ExponentiationExpression[?Yield, ?Await] MultiplicativeExpression[?Yield, ?Await] MultiplicativeOperator ExponentiationExpression[?Yield, ?Await] MultiplicativeOperator : one of * / %
  • * 运算符执行乘法,产生其操作数的乘积。
  • / 运算符执行除法,产生其操作数的商。
  • % 运算符产生隐含除法中其操作数的余数。

13.7.1 运行时语义:Evaluation

MultiplicativeExpression : MultiplicativeExpression MultiplicativeOperator ExponentiationExpression
  1. opTextMultiplicativeOperator 匹配的源文本
  2. 返回 ? EvaluateStringOrNumericBinaryExpression(MultiplicativeExpression, opText, ExponentiationExpression)。

13.8 加法运算符

语法

AdditiveExpression[Yield, Await] : MultiplicativeExpression[?Yield, ?Await] AdditiveExpression[?Yield, ?Await] + MultiplicativeExpression[?Yield, ?Await] AdditiveExpression[?Yield, ?Await] - MultiplicativeExpression[?Yield, ?Await]

13.8.1 加法运算符(+

加法运算符执行字符串连接或数值加法。

13.8.1.1 运行时语义:Evaluation

AdditiveExpression : AdditiveExpression + MultiplicativeExpression
  1. 返回 ? EvaluateStringOrNumericBinaryExpression(AdditiveExpression, +, MultiplicativeExpression)。

13.8.2 减法运算符(-

- 运算符执行减法,产生其操作数的差。

13.8.2.1 运行时语义:Evaluation

AdditiveExpression : AdditiveExpression - MultiplicativeExpression
  1. 返回 ? EvaluateStringOrNumericBinaryExpression(AdditiveExpression, -, MultiplicativeExpression)。

13.9 按位移位运算符

语法

ShiftExpression[Yield, Await] : AdditiveExpression[?Yield, ?Await] ShiftExpression[?Yield, ?Await] << AdditiveExpression[?Yield, ?Await] ShiftExpression[?Yield, ?Await] >> AdditiveExpression[?Yield, ?Await] ShiftExpression[?Yield, ?Await] >>> AdditiveExpression[?Yield, ?Await]

13.9.1 左移运算符(<<

对左操作数执行按位左移操作,移位量由右操作数指定。

13.9.1.1 运行时语义:Evaluation

ShiftExpression : ShiftExpression << AdditiveExpression
  1. 返回 ? EvaluateStringOrNumericBinaryExpression(ShiftExpression, <<, AdditiveExpression)。

13.9.2 有符号右移运算符(>>

对左操作数执行符号填充的按位右移操作,移位量由右操作数指定。

13.9.2.1 运行时语义:Evaluation

ShiftExpression : ShiftExpression >> AdditiveExpression
  1. 返回 ? EvaluateStringOrNumericBinaryExpression(ShiftExpression, >>, AdditiveExpression)。

13.9.3 无符号右移运算符(>>>

对左操作数执行零填充的按位右移操作,移位量由右操作数指定。

13.9.3.1 运行时语义:Evaluation

ShiftExpression : ShiftExpression >>> AdditiveExpression
  1. 返回 ? EvaluateStringOrNumericBinaryExpression(ShiftExpression, >>>, AdditiveExpression)。

13.10 关系运算符

注 1

关系运算符的求值结果总是布尔类型,反映运算符所命名的关系是否在其两个操作数之间成立。

语法

RelationalExpression[In, Yield, Await] : ShiftExpression[?Yield, ?Await] RelationalExpression[?In, ?Yield, ?Await] < ShiftExpression[?Yield, ?Await] RelationalExpression[?In, ?Yield, ?Await] > ShiftExpression[?Yield, ?Await] RelationalExpression[?In, ?Yield, ?Await] <= ShiftExpression[?Yield, ?Await] RelationalExpression[?In, ?Yield, ?Await] >= ShiftExpression[?Yield, ?Await] RelationalExpression[?In, ?Yield, ?Await] instanceof ShiftExpression[?Yield, ?Await] [+In] RelationalExpression[+In, ?Yield, ?Await] in ShiftExpression[?Yield, ?Await] [+In] PrivateIdentifier in ShiftExpression[?Yield, ?Await] 注 2

需要 [In] 语法参数来避免关系表达式中的 in 运算符与 for 语句中的 in 运算符混淆。

13.10.1 运行时语义:Evaluation

RelationalExpression : RelationalExpression < ShiftExpression
  1. lRef 为 ? RelationalExpressionEvaluation
  2. lVal 为 ? GetValue(lRef)。
  3. rRef 为 ? ShiftExpressionEvaluation
  4. rVal 为 ? GetValue(rRef)。
  5. r 为 ? IsLessThan(lVal, rVal, true)。
  6. 如果 rundefined,返回 false。否则,返回 r
RelationalExpression : RelationalExpression > ShiftExpression
  1. lRef 为 ? RelationalExpressionEvaluation
  2. lVal 为 ? GetValue(lRef)。
  3. rRef 为 ? ShiftExpressionEvaluation
  4. rVal 为 ? GetValue(rRef)。
  5. r 为 ? IsLessThan(rVal, lVal, false)。
  6. 如果 rundefined,返回 false。否则,返回 r
RelationalExpression : RelationalExpression <= ShiftExpression
  1. lRef 为 ? RelationalExpressionEvaluation
  2. lVal 为 ? GetValue(lRef)。
  3. rRef 为 ? ShiftExpressionEvaluation
  4. rVal 为 ? GetValue(rRef)。
  5. r 为 ? IsLessThan(rVal, lVal, false)。
  6. 如果 rtrueundefined,返回 false。否则,返回 true
RelationalExpression : RelationalExpression >= ShiftExpression
  1. lRef 为 ? RelationalExpressionEvaluation
  2. lVal 为 ? GetValue(lRef)。
  3. rRef 为 ? ShiftExpressionEvaluation
  4. rVal 为 ? GetValue(rRef)。
  5. r 为 ? IsLessThan(lVal, rVal, true)。
  6. 如果 rtrueundefined,返回 false。否则,返回 true
RelationalExpression : RelationalExpression instanceof ShiftExpression
  1. lRef 为 ? RelationalExpressionEvaluation
  2. lVal 为 ? GetValue(lRef)。
  3. rRef 为 ? ShiftExpressionEvaluation
  4. rVal 为 ? GetValue(rRef)。
  5. 返回 ? InstanceofOperator(lVal, rVal)。
RelationalExpression : RelationalExpression in ShiftExpression
  1. lRef 为 ? RelationalExpressionEvaluation
  2. lVal 为 ? GetValue(lRef)。
  3. rRef 为 ? ShiftExpressionEvaluation
  4. rVal 为 ? GetValue(rRef)。
  5. 如果 rVal 不是对象,抛出 TypeError 异常。
  6. 返回 ? HasProperty(rVal, ? ToPropertyKey(lVal))。
RelationalExpression : PrivateIdentifier in ShiftExpression
  1. privateIdentifierPrivateIdentifierStringValue
  2. rRef 为 ? ShiftExpressionEvaluation
  3. rVal 为 ? GetValue(rRef)。
  4. 如果 rVal 不是对象,抛出 TypeError 异常。
  5. privateEnv正在运行的执行上下文的 PrivateEnvironment。
  6. 断言privateEnv 不是 null
  7. privateNameResolvePrivateIdentifier(privateEnv, privateIdentifier)。
  8. 如果 PrivateElementFind(rVal, privateName) 不是 empty,返回 true
  9. 返回 false

13.10.2 InstanceofOperator ( V, target )

抽象操作 InstanceofOperator 接受参数 VECMAScript 语言值)和 targetECMAScript 语言值)并且返回包含布尔值的正常完成抛出完成。它实现用于确定 V 是否为 target 实例的通用算法,通过咨询 target%Symbol.hasInstance% 方法,或如果不存在,则确定 target"prototype" 属性的值是否存在于 V 的原型链中。调用时执行以下步骤:

  1. 如果 target 不是对象,抛出 TypeError 异常。
  2. instOfHandler 为 ? GetMethod(target, %Symbol.hasInstance%)。
  3. 如果 instOfHandler 不是 undefined,则
    1. 返回 ToBoolean(? Call(instOfHandler, target, « V »))。
  4. 如果 IsCallable(target) 是 false,抛出 TypeError 异常。
  5. 返回 ? OrdinaryHasInstance(target, V)。

步骤 45 提供与 ECMAScript 早期版本的兼容性,这些版本没有使用 %Symbol.hasInstance% 方法来定义 instanceof 运算符语义。如果对象没有定义或继承 %Symbol.hasInstance%,它使用默认的 instanceof 语义。

13.11 相等运算符

相等运算符的求值结果总是布尔类型,反映运算符所命名的关系是否在其两个操作数之间成立。

语法

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 运行时语义:Evaluation

EqualityExpression : EqualityExpression == RelationalExpression
  1. lRef 为 ? EqualityExpressionEvaluation
  2. lVal 为 ? GetValue(lRef)。
  3. rRef 为 ? RelationalExpressionEvaluation
  4. rVal 为 ? GetValue(rRef)。
  5. 返回 ? IsLooselyEqual(rVal, lVal)。
EqualityExpression : EqualityExpression != RelationalExpression
  1. lRef 为 ? EqualityExpressionEvaluation
  2. lVal 为 ? GetValue(lRef)。
  3. rRef 为 ? RelationalExpressionEvaluation
  4. rVal 为 ? GetValue(rRef)。
  5. r 为 ? IsLooselyEqual(rVal, lVal)。
  6. 如果 rtrue,返回 false。否则,返回 true
EqualityExpression : EqualityExpression === RelationalExpression
  1. lRef 为 ? EqualityExpressionEvaluation
  2. lVal 为 ? GetValue(lRef)。
  3. rRef 为 ? RelationalExpressionEvaluation
  4. rVal 为 ? GetValue(rRef)。
  5. 返回 IsStrictlyEqual(rVal, lVal)。
EqualityExpression : EqualityExpression !== RelationalExpression
  1. lRef 为 ? EqualityExpressionEvaluation
  2. lVal 为 ? GetValue(lRef)。
  3. rRef 为 ? RelationalExpressionEvaluation
  4. rVal 为 ? GetValue(rRef)。
  5. rIsStrictlyEqual(rVal, lVal)。
  6. 如果 rtrue,返回 false。否则,返回 true
注 1

根据上述相等性定义:

  • 字符串比较可以通过以下方式强制进行:`${a}` == `${b}`
  • 数值比较可以通过以下方式强制进行:+a == +b
  • 布尔比较可以通过以下方式强制进行:!a == !b
注 2

相等运算符维持以下不变性:

  • A != B 等价于 !(A == B)
  • A == B 等价于 B == A,除了 AB 的求值顺序。
注 3

相等运算符并不总是传递的。例如,可能有两个不同的 String 对象,每个代表相同的 String 值;每个 String 对象都会被 == 运算符认为等于 String 值,但两个 String 对象彼此不相等。例如:

  • new String("a") == "a""a" == new String("a") 都是 true
  • new String("a") == new String("a")false
注 4

字符串的比较使用简单的代码单元值序列相等性测试。没有尝试使用 Unicode 规范中定义的更复杂的、面向语义的字符或字符串相等性和排序定义。因此,根据 Unicode 标准规范相等的字符串值可能测试为不相等。实际上,此算法假设两个字符串都已经是规范化形式。

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 运行时语义: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]

&&|| 运算符产生的值不一定是布尔类型。产生的值总是两个操作数表达式之一的值。

13.13.1 运行时语义:Evaluation

LogicalANDExpression : LogicalANDExpression && BitwiseORExpression
  1. lRef 为 ? LogicalANDExpressionEvaluation
  2. lVal 为 ? GetValue(lRef)。
  3. 如果 ToBoolean(lVal) 是 false,返回 lVal
  4. rRef 为 ? BitwiseORExpressionEvaluation
  5. 返回 ? GetValue(rRef)。
LogicalORExpression : LogicalORExpression || LogicalANDExpression
  1. lRef 为 ? LogicalORExpressionEvaluation
  2. lVal 为 ? GetValue(lRef)。
  3. 如果 ToBoolean(lVal) 是 true,返回 lVal
  4. rRef 为 ? LogicalANDExpressionEvaluation
  5. 返回 ? GetValue(rRef)。
CoalesceExpression : CoalesceExpressionHead ?? BitwiseORExpression
  1. lRef 为 ? CoalesceExpressionHeadEvaluation
  2. lVal 为 ? GetValue(lRef)。
  3. 如果 lValundefinednull,则
    1. rRef 为 ? BitwiseORExpressionEvaluation
    2. 返回 ? GetValue(rRef)。
  4. 否则,
    1. 返回 lVal

13.14 条件运算符 ( ? : )

语法

ConditionalExpression[In, Yield, Await] : ShortCircuitExpression[?In, ?Yield, ?Await] ShortCircuitExpression[?In, ?Yield, ?Await] ? AssignmentExpression[+In, ?Yield, ?Await] : AssignmentExpression[?In, ?Yield, ?Await]

ECMAScript 中 ConditionalExpression 的语法与 C 和 Java 中的语法略有不同,后者允许第二个子表达式是 Expression,但限制第三个表达式必须是 ConditionalExpression。ECMAScript 中这种差异的动机是允许赋值表达式由条件的任一分支控制,并消除作为中间表达式的逗号表达式这种令人困惑且相当无用的情况。

13.14.1 运行时语义:Evaluation

ConditionalExpression : ShortCircuitExpression ? AssignmentExpression : AssignmentExpression
  1. lRef 为 ? ShortCircuitExpressionEvaluation
  2. lValToBoolean(? GetValue(lRef))。
  3. 如果 lValtrue,则
    1. trueRef 为 ? 第一个 AssignmentExpressionEvaluation
    2. 返回 ? GetValue(trueRef)。
  4. 否则,
    1. falseRef 为 ? 第二个 AssignmentExpressionEvaluation
    2. 返回 ? 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 静态语义:早期错误

AssignmentExpression : LeftHandSideExpression = AssignmentExpression AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression LeftHandSideExpression &&= AssignmentExpression LeftHandSideExpression ||= AssignmentExpression LeftHandSideExpression ??= AssignmentExpression

13.15.2 运行时语义:Evaluation

AssignmentExpression : LeftHandSideExpression = AssignmentExpression
  1. 如果 LeftHandSideExpression 既不是 ObjectLiteral 也不是 ArrayLiteral,则
    1. lRef 为 ? LeftHandSideExpressionEvaluation
    2. 如果 IsAnonymousFunctionDefinition(AssignmentExpression) 是 trueLeftHandSideExpressionIsIdentifierReftrue,则
      1. lhsLeftHandSideExpressionStringValue
      2. rVal 为 ? AssignmentExpression 以参数 lhs 进行的 NamedEvaluation
    3. 否则,
      1. rRef 为 ? AssignmentExpressionEvaluation
      2. rVal 为 ? GetValue(rRef)。
    4. 执行 ? PutValue(lRef, rVal)。
    5. 返回 rVal
  2. assignmentPattern 为由 LeftHandSideExpression 覆盖AssignmentPattern
  3. rRef 为 ? AssignmentExpressionEvaluation
  4. rVal 为 ? GetValue(rRef)。
  5. 执行 ? assignmentPattern 以参数 rVal 进行的 DestructuringAssignmentEvaluation
  6. 返回 rVal
AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression
  1. lRef 为 ? LeftHandSideExpressionEvaluation
  2. lVal 为 ? GetValue(lRef)。
  3. rRef 为 ? AssignmentExpressionEvaluation
  4. rVal 为 ? GetValue(rRef)。
  5. assignmentOpTextAssignmentOperator 匹配的源代码文本
  6. opText 为下表中与 assignmentOpText 关联的 Unicode 代码点序列:
    assignmentOpText opText
    **= **
    *= *
    /= /
    %= %
    += +
    -= -
    <<= <<
    >>= >>
    >>>= >>>
    &= &
    ^= ^
    |= |
  7. r 为 ? ApplyStringOrNumericBinaryOperator(lVal, opText, rVal)。
  8. 执行 ? PutValue(lRef, r)。
  9. 返回 r
AssignmentExpression : LeftHandSideExpression &&= AssignmentExpression
  1. lRef 为 ? LeftHandSideExpressionEvaluation
  2. lVal 为 ? GetValue(lRef)。
  3. 如果 ToBoolean(lVal) 是 false,返回 lVal
  4. 如果 IsAnonymousFunctionDefinition(AssignmentExpression) 是 trueLeftHandSideExpressionIsIdentifierReftrue,则
    1. lhsLeftHandSideExpressionStringValue
    2. rVal 为 ? AssignmentExpression 以参数 lhs 进行的 NamedEvaluation
  5. 否则,
    1. rRef 为 ? AssignmentExpressionEvaluation
    2. rVal 为 ? GetValue(rRef)。
  6. 执行 ? PutValue(lRef, rVal)。
  7. 返回 rVal
AssignmentExpression : LeftHandSideExpression ||= AssignmentExpression
  1. lRef 为 ? LeftHandSideExpressionEvaluation
  2. lVal 为 ? GetValue(lRef)。
  3. 如果 ToBoolean(lVal) 是 true,返回 lVal
  4. 如果 IsAnonymousFunctionDefinition(AssignmentExpression) 是 trueLeftHandSideExpressionIsIdentifierReftrue,则
    1. lhsLeftHandSideExpressionStringValue
    2. rVal 为 ? AssignmentExpression 以参数 lhs 进行的 NamedEvaluation
  5. 否则,
    1. rRef 为 ? AssignmentExpressionEvaluation
    2. rVal 为 ? GetValue(rRef)。
  6. 执行 ? PutValue(lRef, rVal)。
  7. 返回 rVal
AssignmentExpression : LeftHandSideExpression ??= AssignmentExpression
  1. lRef 为 ? LeftHandSideExpressionEvaluation
  2. lVal 为 ? GetValue(lRef)。
  3. 如果 lVal 既不是 undefined 也不是 null, 返回 lVal
  4. 如果 IsAnonymousFunctionDefinition(AssignmentExpression) 是 trueLeftHandSideExpressionIsIdentifierReftrue,则
    1. lhsLeftHandSideExpressionStringValue
    2. rVal 为 ? AssignmentExpression 以参数 lhs 进行的 NamedEvaluation
  5. 否则,
    1. rRef 为 ? AssignmentExpressionEvaluation
    2. rVal 为 ? GetValue(rRef)。
  6. 执行 ? PutValue(lRef, rVal)。
  7. 返回 rVal

当此表达式出现在严格模式代码中时,如果步骤 1.d2222 中的 lRef 是不可解析的引用,这是运行时错误。如果是,则抛出 ReferenceError 异常。此外,如果步骤 8666 中的 lRef 引用具有属性值 { [[Writable]]: false } 的数据属性,或引用具有属性值 { [[Set]]: undefined } 的访问器属性,或引用对象的不存在属性且该对象的 IsExtensible 谓词返回值 false,这是运行时错误。在这些情况下会抛出 TypeError 异常。

13.15.3 ApplyStringOrNumericBinaryOperator ( lVal, opText, rVal )

抽象操作 ApplyStringOrNumericBinaryOperator 接受参数 lVal(一个ECMAScript 语言值)、 opText***/%+-<<>>>>>&^|)和 rVal(一个ECMAScript 语言值),并返回包含 String、BigInt 或 Number 的正常完成,或抛出完成。当调用时,它执行以下步骤:

  1. 如果 opText+,则
    1. lPrim 为 ? ToPrimitive(lVal)。
    2. rPrim 为 ? ToPrimitive(rVal)。
    3. 如果 lPrim 是 StringrPrim 是 String,则
      1. lStr 为 ? ToString(lPrim)。
      2. rStr 为 ? ToString(rPrim)。
      3. 返回 lStrrStr字符串拼接
    4. 设置 lVallPrim
    5. 设置 rValrPrim
  2. 注:此时,这必须是数值运算。
  3. lNum 为 ? ToNumeric(lVal)。
  4. rNum 为 ? ToNumeric(rVal)。
  5. 如果 SameType(lNum, rNum) 是 false,抛出 TypeError 异常。
  6. 如果 lNum 是 BigInt,则
    1. 如果 opText**,返回 ? BigInt::exponentiate(lNum, rNum)。
    2. 如果 opText/,返回 ? BigInt::divide(lNum, rNum)。
    3. 如果 opText%,返回 ? BigInt::remainder(lNum, rNum)。
    4. 如果 opText>>>,返回 ? BigInt::unsignedRightShift(lNum, rNum)。
    5. operation 为下表中与 opText 关联的抽象操作:
      opText operation
      * BigInt::multiply
      + BigInt::add
      - BigInt::subtract
      << BigInt::leftShift
      >> BigInt::signedRightShift
      & BigInt::bitwiseAND
      ^ BigInt::bitwiseXOR
      | BigInt::bitwiseOR
  7. 否则,
    1. 断言lNum 是 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(lNum, rNum)。
注 1

在步骤 1.a1.b 中对 ToPrimitive 的调用中没有提供提示。除 Date 外的所有标准对象都将缺少提示处理为给定 number;Date 将缺少提示处理为给定 string异质对象可能以其他方式处理缺少提示的情况。

注 2

步骤 1.cIsLessThan 算法的步骤 3 不同,使用逻辑或运算而不是逻辑与运算。

13.15.4 EvaluateStringOrNumericBinaryExpression ( leftOperand, opText, rightOperand )

抽象操作 EvaluateStringOrNumericBinaryExpression 接受参数 leftOperand(一个解析节点)、opText(一个 Unicode 代码点序列)和 rightOperand(一个解析节点),并返回包含 String、BigInt 或 Number 的正常完成,或异常完成。当调用时,它执行以下步骤:

  1. lRef 为 ? leftOperandEvaluation
  2. lVal 为 ? GetValue(lRef)。
  3. rRef 为 ? rightOperandEvaluation
  4. rVal 为 ? GetValue(rRef)。
  5. 返回 ? ApplyStringOrNumericBinaryOperator(lVal, opText, rVal)。

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 静态语义:早期错误

AssignmentProperty : IdentifierReference Initializeropt AssignmentRestProperty : ... DestructuringAssignmentTarget DestructuringAssignmentTarget : LeftHandSideExpression

13.15.5.2 运行时语义:DestructuringAssignmentEvaluation

语法导向操作 DestructuringAssignmentEvaluation 接受参数 value(一个ECMAScript 语言值),并返回包含 unused正常完成异常完成。 它在以下产生式上分段定义:

ObjectAssignmentPattern : { }
  1. 执行 ? RequireObjectCoercible(value)。
  2. 返回 unused
ObjectAssignmentPattern : { AssignmentPropertyList } { AssignmentPropertyList , }
  1. 执行 ? RequireObjectCoercible(value)。
  2. 执行 ? AssignmentPropertyList 以参数 value 进行的 PropertyDestructuringAssignmentEvaluation
  3. 返回 unused
ObjectAssignmentPattern : { AssignmentRestProperty }
  1. 执行 ? RequireObjectCoercible(value)。
  2. excludedNames 为一个新的空列表
  3. 返回 ? AssignmentRestProperty 以参数 valueexcludedNames 进行的 RestDestructuringAssignmentEvaluation
ObjectAssignmentPattern : { AssignmentPropertyList , AssignmentRestProperty }
  1. 执行 ? RequireObjectCoercible(value)。
  2. excludedNames 为 ? AssignmentPropertyList 以参数 value 进行的 PropertyDestructuringAssignmentEvaluation
  3. 返回 ? AssignmentRestProperty 以参数 valueexcludedNames 进行的 RestDestructuringAssignmentEvaluation
ArrayAssignmentPattern : [ ]
  1. iteratorRecord 为 ? GetIterator(value, sync)。
  2. 返回 ? IteratorClose(iteratorRecord, NormalCompletion(unused))。
ArrayAssignmentPattern : [ Elision ]
  1. iteratorRecord 为 ? GetIterator(value, sync)。
  2. resultCompletion(Elision 以参数 iteratorRecord 进行的 IteratorDestructuringAssignmentEvaluation)。
  3. 如果 iteratorRecord.[[Done]]false,返回 ? IteratorClose(iteratorRecord, result)。
  4. 返回 result
ArrayAssignmentPattern : [ Elisionopt AssignmentRestElement ]
  1. iteratorRecord 为 ? GetIterator(value, sync)。
  2. 如果存在 Elision,则
    1. statusCompletion(Elision 以参数 iteratorRecord 进行的 IteratorDestructuringAssignmentEvaluation)。
    2. 如果 status异常完成,则
      1. 断言iteratorRecord.[[Done]]true
      2. 返回 ? status
  3. resultCompletion(AssignmentRestElement 以参数 iteratorRecord 进行的 IteratorDestructuringAssignmentEvaluation)。
  4. 如果 iteratorRecord.[[Done]]false,返回 ? IteratorClose(iteratorRecord, result)。
  5. 返回 result
ArrayAssignmentPattern : [ AssignmentElementList ]
  1. iteratorRecord 为 ? GetIterator(value, sync)。
  2. resultCompletion(AssignmentElementList 以参数 iteratorRecord 进行的 IteratorDestructuringAssignmentEvaluation)。
  3. 如果 iteratorRecord.[[Done]]false,返回 ? IteratorClose(iteratorRecord, result)。
  4. 返回 result
ArrayAssignmentPattern : [ AssignmentElementList , Elisionopt AssignmentRestElementopt ]
  1. iteratorRecord 为 ? GetIterator(value, sync)。
  2. statusCompletion(AssignmentElementList 以参数 iteratorRecord 进行的 IteratorDestructuringAssignmentEvaluation)。
  3. 如果 status异常完成,则
    1. 如果 iteratorRecord.[[Done]]false,返回 ? IteratorClose(iteratorRecord, status)。
    2. 返回 ? status
  4. 如果存在 Elision,则
    1. 设置 statusCompletion(Elision 以参数 iteratorRecord 进行的 IteratorDestructuringAssignmentEvaluation)。
    2. 如果 status异常完成,则
      1. 断言iteratorRecord.[[Done]]true
      2. 返回 ? status
  5. 如果存在 AssignmentRestElement,则
    1. 设置 statusCompletion(AssignmentRestElement 以参数 iteratorRecord 进行的 IteratorDestructuringAssignmentEvaluation)。
  6. 如果 iteratorRecord.[[Done]]false,返回 ? IteratorClose(iteratorRecord, status)。
  7. 返回 ? status

13.15.5.3 运行时语义:PropertyDestructuringAssignmentEvaluation

语法导向操作 PropertyDestructuringAssignmentEvaluation 接受参数 value(一个ECMAScript 语言值),并返回包含属性键列表正常完成异常完成。它收集所有解构的属性键的列表。它在以下产生式上分段定义:

AssignmentPropertyList : AssignmentPropertyList , AssignmentProperty
  1. propertyNames 为 ? AssignmentPropertyList 以参数 value 进行的 PropertyDestructuringAssignmentEvaluation
  2. nextNames 为 ? AssignmentProperty 以参数 value 进行的 PropertyDestructuringAssignmentEvaluation
  3. 返回 propertyNamesnextNames列表拼接
AssignmentProperty : IdentifierReference Initializeropt
  1. PIdentifierReferenceStringValue
  2. lRef 为 ? ResolveBinding(P)。
  3. v 为 ? GetV(value, P)。
  4. 如果存在 Initializervundefined,则
    1. 如果 IsAnonymousFunctionDefinition(Initializer) 是 true,则
      1. 设置 v 为 ? Initializer 以参数 P 进行的 NamedEvaluation
    2. 否则,
      1. defaultValue 为 ? InitializerEvaluation
      2. 设置 v 为 ? GetValue(defaultValue)。
  5. 执行 ? PutValue(lRef, v)。
  6. 返回 « P »。
AssignmentProperty : PropertyName : AssignmentElement
  1. name 为 ? PropertyNameEvaluation
  2. 执行 ? AssignmentElement 以参数 valuename 进行的 KeyedDestructuringAssignmentEvaluation
  3. 返回 « name »。

13.15.5.4 运行时语义:RestDestructuringAssignmentEvaluation

语法导向操作 RestDestructuringAssignmentEvaluation 接受参数 value(一个ECMAScript 语言值)和 excludedNames属性键列表),并返回包含 unused正常完成异常完成。 它在以下产生式上分段定义:

AssignmentRestProperty : ... DestructuringAssignmentTarget
  1. lRef 为 ? DestructuringAssignmentTargetEvaluation
  2. restObjOrdinaryObjectCreate(%Object.prototype%)。
  3. 执行 ? CopyDataProperties(restObj, value, excludedNames)。
  4. 返回 ? PutValue(lRef, restObj)。

13.15.5.5 运行时语义:IteratorDestructuringAssignmentEvaluation

语法导向操作 IteratorDestructuringAssignmentEvaluation 接受参数 iteratorRecord(一个迭代器记录),并返回包含 unused正常完成异常完成。 它在以下产生式上分段定义:

AssignmentElementList : AssignmentElisionElement
  1. 返回 ? AssignmentElisionElement 以参数 iteratorRecord 进行的 IteratorDestructuringAssignmentEvaluation
AssignmentElementList : AssignmentElementList , AssignmentElisionElement
  1. 执行 ? AssignmentElementList 以参数 iteratorRecord 进行的 IteratorDestructuringAssignmentEvaluation
  2. 返回 ? AssignmentElisionElement 以参数 iteratorRecord 进行的 IteratorDestructuringAssignmentEvaluation
AssignmentElisionElement : AssignmentElement
  1. 返回 ? AssignmentElement 以参数 iteratorRecord 进行的 IteratorDestructuringAssignmentEvaluation
AssignmentElisionElement : Elision AssignmentElement
  1. 执行 ? Elision 以参数 iteratorRecord 进行的 IteratorDestructuringAssignmentEvaluation
  2. 返回 ? AssignmentElement 以参数 iteratorRecord 进行的 IteratorDestructuringAssignmentEvaluation
Elision : ,
  1. 如果 iteratorRecord.[[Done]]false,则
    1. 执行 ? IteratorStep(iteratorRecord)。
  2. 返回 unused
Elision : Elision ,
  1. 执行 ? Elision 以参数 iteratorRecord 进行的 IteratorDestructuringAssignmentEvaluation
  2. 如果 iteratorRecord.[[Done]]false,则
    1. 执行 ? IteratorStep(iteratorRecord)。
  3. 返回 unused
AssignmentElement : DestructuringAssignmentTarget Initializeropt
  1. 如果 DestructuringAssignmentTarget 既不是 ObjectLiteral 也不是 ArrayLiteral,则
    1. lRef 为 ? DestructuringAssignmentTargetEvaluation
  2. valueundefined
  3. 如果 iteratorRecord.[[Done]]false,则
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 next 不是 done,则
      1. 设置 valuenext
  4. 如果存在 Initializervalueundefined,则
    1. 如果 IsAnonymousFunctionDefinition(Initializer) 是 trueDestructuringAssignmentTargetIsIdentifierReftrue,则
      1. targetDestructuringAssignmentTargetStringValue
      2. v 为 ? Initializer 以参数 target 进行的 NamedEvaluation
    2. 否则,
      1. defaultValue 为 ? InitializerEvaluation
      2. v 为 ? GetValue(defaultValue)。
  5. 否则,
    1. vvalue
  6. 如果 DestructuringAssignmentTargetObjectLiteralArrayLiteral,则
    1. nestedAssignmentPattern 为被 DestructuringAssignmentTarget 覆盖AssignmentPattern
    2. 返回 ? nestedAssignmentPattern 以参数 v 进行的 DestructuringAssignmentEvaluation
  7. 返回 ? PutValue(lRef, v)。

通过在访问迭代器或计算 Initializer 之前先计算不是解构模式的 DestructuringAssignmentTarget,来维持从左到右的求值顺序。

AssignmentRestElement : ... DestructuringAssignmentTarget
  1. 如果 DestructuringAssignmentTarget 既不是 ObjectLiteral 也不是 ArrayLiteral,则
    1. lRef 为 ? DestructuringAssignmentTargetEvaluation
  2. A 为 ! ArrayCreate(0)。
  3. n 为 0。
  4. 重复,只要 iteratorRecord.[[Done]]false
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 next 不是 done,则
      1. 执行 ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(n)), next)。
      2. 设置 nn + 1。
  5. 如果 DestructuringAssignmentTarget 既不是 ObjectLiteral 也不是 ArrayLiteral,则
    1. 返回 ? PutValue(lRef, A)。
  6. nestedAssignmentPattern 为被 DestructuringAssignmentTarget 覆盖AssignmentPattern
  7. 返回 ? nestedAssignmentPattern 以参数 A 进行的 DestructuringAssignmentEvaluation

13.15.5.6 运行时语义:KeyedDestructuringAssignmentEvaluation

语法导向操作 KeyedDestructuringAssignmentEvaluation 接受参数 value(一个ECMAScript 语言值)和 propertyName(一个属性键),并返回包含 unused正常完成异常完成。 它在以下产生式上分段定义:

AssignmentElement : DestructuringAssignmentTarget Initializeropt
  1. 如果 DestructuringAssignmentTarget 既不是 ObjectLiteral 也不是 ArrayLiteral,则
    1. lRef 为 ? DestructuringAssignmentTargetEvaluation
  2. v 为 ? GetV(value, propertyName)。
  3. 如果存在 Initializervundefined,则
    1. 如果 IsAnonymousFunctionDefinition(Initializer) 是 trueDestructuringAssignmentTargetIsIdentifierReftrue,则
      1. targetDestructuringAssignmentTargetStringValue
      2. rhsValue 为 ? Initializer 以参数 target 进行的 NamedEvaluation
    2. 否则,
      1. defaultValue 为 ? InitializerEvaluation
      2. rhsValue 为 ? GetValue(defaultValue)。
  4. 否则,
    1. rhsValuev
  5. 如果 DestructuringAssignmentTargetObjectLiteralArrayLiteral,则
    1. assignmentPattern 为被 DestructuringAssignmentTarget 覆盖AssignmentPattern
    2. 返回 ? assignmentPattern 以参数 rhsValue 进行的 DestructuringAssignmentEvaluation
  6. 返回 ? PutValue(lRef, rhsValue)。

13.16 逗号操作符 ( , )

语法

Expression[In, Yield, Await] : AssignmentExpression[?In, ?Yield, ?Await] Expression[?In, ?Yield, ?Await] , AssignmentExpression[?In, ?Yield, ?Await]

13.16.1 运行时语义:Evaluation

Expression : Expression , AssignmentExpression
  1. lRef 为 ? ExpressionEvaluation
  2. 执行 ? GetValue(lRef)。
  3. rRef 为 ? AssignmentExpressionEvaluation
  4. 返回 ? GetValue(rRef)。

必须调用 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 运行时语义:Evaluation

HoistableDeclaration : GeneratorDeclaration AsyncFunctionDeclaration AsyncGeneratorDeclaration
  1. 返回 empty
HoistableDeclaration : FunctionDeclaration
  1. 返回 ? FunctionDeclarationEvaluation
BreakableStatement : IterationStatement SwitchStatement
  1. newLabelSet 为一个新的空列表
  2. 返回 ? 此 BreakableStatement 以参数 newLabelSet 进行的 LabelledEvaluation

14.2

语法

BlockStatement[Yield, Await, Return] : Block[?Yield, ?Await, ?Return] Block[Yield, Await, Return] : { StatementList[?Yield, ?Await, ?Return]opt } StatementList[Yield, Await, Return] : StatementListItem[?Yield, ?Await, ?Return] StatementList[?Yield, ?Await, ?Return] StatementListItem[?Yield, ?Await, ?Return] StatementListItem[Yield, Await, Return] : Statement[?Yield, ?Await, ?Return] Declaration[?Yield, ?Await]

14.2.1 静态语义:早期错误

Block : { StatementList }

14.2.2 运行时语义:Evaluation

Block : { }
  1. 返回 empty
Block : { StatementList }
  1. oldEnv运行中执行上下文的 LexicalEnvironment。
  2. blockEnvNewDeclarativeEnvironment(oldEnv)。
  3. 执行 BlockDeclarationInstantiation(StatementList, blockEnv)。
  4. 设置运行中执行上下文的 LexicalEnvironment 为 blockEnv
  5. blockValueCompletion(StatementListEvaluation)。
  6. 设置运行中执行上下文的 LexicalEnvironment 为 oldEnv
  7. 返回 ? blockValue
注1

无论控制如何离开 Block,LexicalEnvironment 总是恢复到其之前的状态。

StatementList : StatementList StatementListItem
  1. sl 为 ? StatementListEvaluation
  2. sCompletion(StatementListItemEvaluation)。
  3. 返回 ? UpdateEmpty(s, sl)。
注2

StatementList 的值是 StatementList 中最后一个产生值的项的值。例如,以下对 eval 函数的调用都返回值 1:

eval("1;;;;;")
eval("1;{}")
eval("1;var a;")

14.2.3 BlockDeclarationInstantiation ( code, env )

抽象操作 BlockDeclarationInstantiation 接受参数 code(一个解析节点)和 env(一个声明式环境记录),并返回 unusedcode 是对应于块主体的解析节点env 是要在其中创建绑定的环境记录

当计算 BlockCaseBlock 时,会创建一个新的声明式环境记录,并且块中声明的每个块作用域变量、常量、函数或类的绑定会在环境记录中实例化。

调用时执行以下步骤:

  1. declarationscodeLexicallyScopedDeclarations
  2. privateEnv运行中执行上下文的 PrivateEnvironment。
  3. 对于 declarations 的每个元素 d,执行
    1. 对于 dBoundNames 的每个元素 dn,执行
      1. 如果 dIsConstantDeclarationtrue,则
        1. 执行 ! env.CreateImmutableBinding(dn, true)。
      2. 否则,
        1. 执行 ! env.CreateMutableBinding(dn, false)。注:此步骤在 B.3.2.6 节中被替换。
    2. 如果 dFunctionDeclarationGeneratorDeclarationAsyncFunctionDeclarationAsyncGeneratorDeclaration,则
      1. fndBoundNames 的唯一元素。
      2. fod 以参数 envprivateEnv 进行的 InstantiateFunctionObject
      3. 执行 ! env.InitializeBinding(fn, fo)。 注:此步骤在 B.3.2.6 节中被替换。
  4. 返回 unused

14.3 声明和变量语句

14.3.1 Let 和 Const 声明

letconst 声明定义的变量作用域限定在运行中执行上下文的 LexicalEnvironment。这些变量在其包含的环境记录实例化时创建,但在变量的 LexicalBinding 被计算之前不能以任何方式访问。由带有 InitializerLexicalBinding 定义的变量在 LexicalBinding 被计算时(而不是在变量创建时)被赋予其 InitializerAssignmentExpression 的值。如果 let 声明中的 LexicalBinding 没有 Initializer,则在 LexicalBinding 被计算时,该变量被赋值为 undefined

语法

LexicalDeclaration[In, Yield, Await] : LetOrConst BindingList[?In, ?Yield, ?Await] ; LetOrConst : let const BindingList[In, Yield, Await] : LexicalBinding[?In, ?Yield, ?Await] BindingList[?In, ?Yield, ?Await] , LexicalBinding[?In, ?Yield, ?Await] LexicalBinding[In, Yield, Await] : BindingIdentifier[?Yield, ?Await] Initializer[?In, ?Yield, ?Await]opt BindingPattern[?Yield, ?Await] Initializer[?In, ?Yield, ?Await]

14.3.1.1 静态语义:早期错误

LexicalDeclaration : LetOrConst BindingList ; LexicalBinding : BindingIdentifier Initializeropt

14.3.1.2 运行时语义:Evaluation

LexicalDeclaration : LetOrConst BindingList ;
  1. 执行 ? BindingListEvaluation
  2. 返回 empty
BindingList : BindingList , LexicalBinding
  1. 执行 ? BindingListEvaluation
  2. 返回 ? LexicalBindingEvaluation
LexicalBinding : BindingIdentifier
  1. lhs 为 ! ResolveBinding(BindingIdentifierStringValue)。
  2. 执行 ! InitializeReferencedBinding(lhs, undefined)。
  3. 返回 empty

静态语义规则确保这种形式的 LexicalBinding 永远不会出现在 const 声明中。

LexicalBinding : BindingIdentifier Initializer
  1. bindingIdBindingIdentifierStringValue
  2. lhs 为 ! ResolveBinding(bindingId)。
  3. 如果 IsAnonymousFunctionDefinition(Initializer) 是 true,则
    1. value 为 ? Initializer 以参数 bindingId 进行的 NamedEvaluation
  4. 否则,
    1. rhs 为 ? InitializerEvaluation
    2. value 为 ? GetValue(rhs)。
  5. 执行 ! InitializeReferencedBinding(lhs, value)。
  6. 返回 empty
LexicalBinding : BindingPattern Initializer
  1. rhs 为 ? InitializerEvaluation
  2. value 为 ? GetValue(rhs)。
  3. env运行中执行上下文的 LexicalEnvironment。
  4. 返回 ? BindingPattern 以参数 valueenv 进行的 BindingInitialization

14.3.2 变量语句

var 语句声明的变量作用域限定在运行中执行上下文的 VariableEnvironment。var 变量在其包含的环境记录实例化时创建,并在创建时初始化为 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 运行时语义: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 为 ? Initializer 以参数 bindingId 进行的 NamedEvaluation
  4. 否则,
    1. rhs 为 ? InitializerEvaluation
    2. value 为 ? GetValue(rhs)。
  5. 执行 ? PutValue(lhs, value)。
  6. 返回 empty

如果 VariableDeclaration 嵌套在 with 语句中,且 VariableDeclaration 中的 BindingIdentifier 与 with 语句的对象环境记录的绑定对象的属性名相同,则步骤 5 将把 value 赋值给该属性,而不是赋值给 Identifier 的 VariableEnvironment 绑定。

VariableDeclaration : BindingPattern Initializer
  1. rhs 为 ? InitializerEvaluation
  2. rVal 为 ? GetValue(rhs)。
  3. 返回 ? BindingPattern 以参数 rValundefined 进行的 BindingInitialization

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 运行时语义:PropertyBindingInitialization

语法制导操作 PropertyBindingInitialization 接受参数 value(一个ECMAScript 语言值)和 environment(一个环境记录undefined),并返回包含列表属性键的正常完成或突然完成。它收集所有已绑定属性名的列表。它在以下产生式上分段定义:

BindingPropertyList : BindingPropertyList , BindingProperty
  1. boundNames 为 ? BindingPropertyList 以参数 valueenvironment 进行的 PropertyBindingInitialization
  2. nextNames 为 ? BindingProperty 以参数 valueenvironment 进行的 PropertyBindingInitialization
  3. 返回 boundNamesnextNames列表连接
BindingProperty : SingleNameBinding
  1. nameSingleNameBindingBoundNames 的唯一元素。
  2. 执行 ? SingleNameBinding 以参数 valueenvironmentname 进行的 KeyedBindingInitialization
  3. 返回 « name »。
BindingProperty : PropertyName : BindingElement
  1. P 为 ? PropertyNameEvaluation
  2. 执行 ? BindingElement 以参数 valueenvironmentP 进行的 KeyedBindingInitialization
  3. 返回 « P »。

14.3.3.2 运行时语义:RestBindingInitialization

语法制导操作 RestBindingInitialization 接受参数 value (一个ECMAScript 语言值)、 environment(一个环境记录undefined)和 excludedNames(一个列表,包含属性键),并返回包含 unused 的正常完成或突然完成。它在以下产生式上分段定义:

BindingRestProperty : ... BindingIdentifier
  1. lhs 为 ? ResolveBinding(BindingIdentifierStringValueenvironment)。
  2. restObjOrdinaryObjectCreate(%Object.prototype%)。
  3. 执行 ? CopyDataProperties(restObjvalueexcludedNames)。
  4. 如果 environmentundefined,返回 ? PutValue(lhsrestObj)。
  5. 返回 ? InitializeReferencedBinding(lhsrestObj)。

14.3.3.3 运行时语义:KeyedBindingInitialization

语法制导操作 KeyedBindingInitialization 接受参数 value (一个ECMAScript 语言值)、 environment(一个环境记录undefined)和 propertyName(一个属性键),并返回包含 unused 的正常完成或突然完成

当为 environment 传递 undefined 时,表示应该使用 PutValue 操作来分配初始化值。这是非严格函数的形参列表的情况。在这种情况下,形参绑定会被预初始化,以处理可能存在多个同名参数的情况。

它在以下产生式上分段定义:

BindingElement : BindingPattern Initializeropt
  1. v 为 ? GetV(valuepropertyName)。
  2. 如果存在 Initializervundefined,则
    1. defaultValue 为 ? InitializerEvaluation
    2. 设置 v 为 ? GetValue(defaultValue)。
  3. 返回 ? BindingPattern 以参数 venvironment 进行的 BindingInitialization
SingleNameBinding : BindingIdentifier Initializeropt
  1. bindingIdBindingIdentifierStringValue
  2. lhs 为 ? ResolveBinding(bindingIdenvironment)。
  3. v 为 ? GetV(valuepropertyName)。
  4. 如果存在 Initializervundefined,则
    1. 如果 IsAnonymousFunctionDefinition(Initializer) 是 true,则
      1. 设置 v 为 ? Initializer 以参数 bindingId 进行的 NamedEvaluation
    2. 否则,
      1. defaultValue 为 ? InitializerEvaluation
      2. 设置 v 为 ? GetValue(defaultValue)。
  5. 如果 environmentundefined,返回 ? PutValue(lhsv)。
  6. 返回 ? InitializeReferencedBinding(lhsv)。

14.4 空语句

语法

EmptyStatement : ;

14.4.1 运行时语义:Evaluation

EmptyStatement : ;
  1. 返回 empty

14.5 表达式语句

语法

ExpressionStatement[Yield, Await] : [lookahead ∉ { {, function, async [no LineTerminator here] function, class, let [ }] Expression[+In, ?Yield, ?Await] ;

ExpressionStatement 不能以 U+007B(左花括号)开头,因为这可能会与 Block 产生歧义。ExpressionStatement 不能以 functionclass 关键字开头,因为这会与 FunctionDeclarationGeneratorDeclarationClassDeclaration 产生歧义。 ExpressionStatement 不能以 async function 开头,因为这会与 AsyncFunctionDeclarationAsyncGeneratorDeclaration 产生歧义。ExpressionStatement 不能以两个词法单元序列 let [ 开头,因为这会与 let LexicalDeclaration 产生歧义,其第一个 LexicalBindingArrayBindingPattern

14.5.1 运行时语义: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]
前瞻限制 [lookahead ≠ else] 以通常的方式解决了经典的"悬空 else"问题。也就是说,当关联的 if 的选择在其他方面模糊时,else 与候选 if 中最近的(最内层的)关联。

14.6.1 静态语义:早期错误

IfStatement : if ( Expression ) Statement else Statement IfStatement : if ( Expression ) Statement

只有在实现B.3.1 中指定的扩展时,才需要应用此规则。

14.6.2 运行时语义: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(stmtCompletionundefined)。
IfStatement : if ( Expression ) Statement
  1. exprRef 为 ? ExpressionEvaluation
  2. exprValueToBoolean(? GetValue(exprRef))。
  3. 如果 exprValuefalse,则
    1. 返回 undefined
  4. 否则,
    1. stmtCompletionCompletion(StatementEvaluation)。
    2. 返回 ? UpdateEmpty(stmtCompletionundefined)。

14.7 迭代语句

语法

IterationStatement[Yield, Await, Return] : DoWhileStatement[?Yield, ?Await, ?Return] WhileStatement[?Yield, ?Await, ?Return] ForStatement[?Yield, ?Await, ?Return] ForInOfStatement[?Yield, ?Await, ?Return]

14.7.1 语义

14.7.1.1 LoopContinues ( completion, labelSet )

抽象操作 LoopContinues 接受参数 completion(一个完成记录) 和 labelSet(一个列表,包含字符串),并返回一个布尔值。调用时执行以下步骤:

  1. 如果 completion正常完成,返回 true
  2. 如果 completion 不是continue 完成,返回 false
  3. 如果 completion.[[Target]]empty,返回 true
  4. 如果 labelSet 包含 completion.[[Target]],返回 true
  5. 返回 false

IterationStatementStatement 部分内,可以使用 ContinueStatement 来开始新的迭代。

14.7.1.2 运行时语义:LoopEvaluation

语法制导操作 LoopEvaluation 接受参数 labelSet(一个列表,包含字符串),并返回包含ECMAScript 语言值的正常完成或突然完成。它在以下产生式上分段定义:

IterationStatement : DoWhileStatement
  1. 返回 ? DoWhileStatement 以参数 labelSet 进行的 DoWhileLoopEvaluation
IterationStatement : WhileStatement
  1. 返回 ? WhileStatement 以参数 labelSet 进行的 WhileLoopEvaluation
IterationStatement : ForStatement
  1. 返回 ? ForStatement 以参数 labelSet 进行的 ForLoopEvaluation
IterationStatement : ForInOfStatement
  1. 返回 ? ForInOfStatement 以参数 labelSet 进行的 ForInOfLoopEvaluation

14.7.2 do-while 语句

语法

DoWhileStatement[Yield, Await, Return] : do Statement[?Yield, ?Await, ?Return] while ( Expression[+In, ?Yield, ?Await] ) ;

14.7.2.1 静态语义:早期错误

DoWhileStatement : do Statement while ( Expression ) ;

只有在实现B.3.1 中指定的扩展时,才需要应用此规则。

14.7.2.2 运行时语义:DoWhileLoopEvaluation

语法制导操作 DoWhileLoopEvaluation 接受参数 labelSet(一个列表,包含字符串),并返回包含ECMAScript 语言值的正常完成或突然完成。它在以下产生式上分段定义:

DoWhileStatement : do Statement while ( Expression ) ;
  1. Vundefined
  2. 重复,
    1. stmtResultCompletion(StatementEvaluation)。
    2. 如果 LoopContinues(stmtResultlabelSet) 是 false,返回 ? UpdateEmpty(stmtResultV)。
    3. 如果 stmtResult.[[Value]] 不是 empty,设置 VstmtResult.[[Value]]
    4. exprRef 为 ? ExpressionEvaluation
    5. exprValue 为 ? GetValue(exprRef)。
    6. 如果 ToBoolean(exprValue) 是 false,返回 V

14.7.3 while 语句

语法

WhileStatement[Yield, Await, Return] : while ( Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return]

14.7.3.1 静态语义:早期错误

WhileStatement : while ( Expression ) Statement

只有在实现B.3.1 中指定的扩展时,才需要应用此规则。

14.7.3.2 运行时语义:WhileLoopEvaluation

语法制导操作 WhileLoopEvaluation 接受参数 labelSet(一个列表,包含字符串),并返回包含ECMAScript 语言值的正常完成或突然完成。它在以下产生式上分段定义:

WhileStatement : while ( Expression ) Statement
  1. Vundefined
  2. 重复,
    1. exprRef 为 ? ExpressionEvaluation
    2. exprValue 为 ? GetValue(exprRef)。
    3. 如果 ToBoolean(exprValue) 是 false,返回 V
    4. stmtResultCompletion(StatementEvaluation)。
    5. 如果 LoopContinues(stmtResultlabelSet) 是 false,返回 ? UpdateEmpty(stmtResultV)。
    6. 如果 stmtResult.[[Value]] 不是 empty,设置 VstmtResult.[[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 静态语义:早期错误

ForStatement : for ( Expressionopt ; Expressionopt ; Expressionopt ) Statement for ( var VariableDeclarationList ; Expressionopt ; Expressionopt ) Statement for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement

只有在实现B.3.1 中指定的扩展时,才需要应用此规则。

ForStatement : for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement

14.7.4.2 运行时语义:ForLoopEvaluation

语法制导操作 ForLoopEvaluation 接受参数 labelSet(一个列表,包含字符串),并返回包含ECMAScript 语言值的正常完成或突然完成。它在以下产生式上分段定义:

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(testincrementStatement,« », labelSet)。
ForStatement : for ( var VariableDeclarationList ; Expressionopt ; Expressionopt ) Statement
  1. 执行 ? VariableDeclarationListEvaluation
  2. 如果第一个 Expression 存在,令 test 为第一个 Expression;否则,令 testempty
  3. 如果第二个 Expression 存在,令 increment 为第二个 Expression;否则,令 incrementempty
  4. 返回 ? ForBodyEvaluation(testincrementStatement,« », labelSet)。
ForStatement : for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement
  1. oldEnv运行中执行上下文的 LexicalEnvironment。
  2. loopEnvNewDeclarativeEnvironment(oldEnv)。
  3. isConstLexicalDeclarationIsConstantDeclaration
  4. boundNamesLexicalDeclarationBoundNames
  5. boundNames 的每个元素 dn,执行
    1. 如果 isConsttrue,则
      1. 执行 ! loopEnv.CreateImmutableBinding(dntrue)。
    2. 否则,
      1. 执行 ! loopEnv.CreateMutableBinding(dnfalse)。
  6. 设置运行中执行上下文的 LexicalEnvironment 为 loopEnv
  7. forDclCompletion(LexicalDeclarationEvaluation)。
  8. 如果 forDcl突然完成,则
    1. 设置运行中执行上下文的 LexicalEnvironment 为 oldEnv
    2. 返回 ? forDcl
  9. 如果 isConstfalse,令 perIterationLetsboundNames;否则令 perIterationLets 为新的空列表
  10. 如果第一个 Expression 存在,令 test 为第一个 Expression;否则,令 testempty
  11. 如果第二个 Expression 存在,令 increment 为第二个 Expression;否则,令 incrementempty
  12. bodyResultCompletion(ForBodyEvaluation(testincrementStatementperIterationLetslabelSet))。
  13. 设置运行中执行上下文的 LexicalEnvironment 为 oldEnv
  14. 返回 ? bodyResult

14.7.4.3 ForBodyEvaluation ( test, increment, stmt, perIterationBindings, labelSet )

抽象操作 ForBodyEvaluation 接受参数 test(一个 Expression 解析节点empty)、increment(一个 Expression 解析节点empty)、stmt(一个 Statement 解析节点)、perIterationBindings(一个列表,包含字符串)和 labelSet(一个列表,包含字符串),并返回包含ECMAScript 语言值的正常完成或突然完成。调用时执行以下步骤:

  1. Vundefined
  2. 执行 ? CreatePerIterationEnvironment(perIterationBindings)。
  3. 重复,
    1. 如果 test 不是 empty,则
      1. testRef 为 ? testEvaluation
      2. testValue 为 ? GetValue(testRef)。
      3. 如果 ToBoolean(testValue) 是 false,返回 V
    2. resultCompletion(stmtEvaluation)。
    3. 如果 LoopContinues(resultlabelSet) 是 false,返回 ? UpdateEmpty(resultV)。
    4. 如果 result.[[Value]] 不是 empty,设置 Vresult.[[Value]]
    5. 执行 ? CreatePerIterationEnvironment(perIterationBindings)。
    6. 如果 increment 不是 empty,则
      1. incRef 为 ? incrementEvaluation
      2. 执行 ? GetValue(incRef)。

14.7.4.4 CreatePerIterationEnvironment ( perIterationBindings )

抽象操作 CreatePerIterationEnvironment 接受参数 perIterationBindings(一个列表,包含字符串),并返回包含 unused 的正常完成或throw 完成。调用时执行以下步骤:

  1. 如果 perIterationBindings 有任何元素,则
    1. lastIterationEnv运行中执行上下文的 LexicalEnvironment。
    2. outerlastIterationEnv.[[OuterEnv]]
    3. 断言outer 不是 null
    4. thisIterationEnvNewDeclarativeEnvironment(outer)。
    5. perIterationBindings 的每个元素 bn,执行
      1. 执行 ! thisIterationEnv.CreateMutableBinding(bnfalse)。
      2. lastValue 为 ? lastIterationEnv.GetBindingValue(bntrue)。
      3. 执行 ! thisIterationEnv.InitializeBinding(bnlastValue)。
    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] in Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] for ( ForDeclaration[?Yield, ?Await] 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] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] for ( ForDeclaration[?Yield, ?Await] 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] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] [+Await] for await ( ForDeclaration[?Yield, ?Await] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] ForDeclaration[Yield, Await] : LetOrConst ForBinding[?Yield, ?Await] ForBinding[Yield, Await] : BindingIdentifier[?Yield, ?Await] BindingPattern[?Yield, ?Await]

本节由附录B.3.5 扩展。

14.7.5.1 静态语义:早期错误

ForInOfStatement : for ( LeftHandSideExpression in Expression ) Statement for ( var ForBinding in Expression ) Statement for ( ForDeclaration in Expression ) Statement for ( LeftHandSideExpression of AssignmentExpression ) Statement for ( var ForBinding of AssignmentExpression ) Statement for ( ForDeclaration of AssignmentExpression ) Statement for await ( LeftHandSideExpression of AssignmentExpression ) Statement for await ( var ForBinding of AssignmentExpression ) Statement for await ( ForDeclaration of AssignmentExpression ) Statement

只有在实现B.3.1 中指定的扩展时,才需要应用此规则。

ForInOfStatement : for ( LeftHandSideExpression in Expression ) Statement for ( LeftHandSideExpression of AssignmentExpression ) Statement for await ( LeftHandSideExpression of AssignmentExpression ) Statement ForInOfStatement : for ( ForDeclaration in Expression ) Statement for ( ForDeclaration of AssignmentExpression ) Statement for await ( ForDeclaration of AssignmentExpression ) Statement

14.7.5.2 静态语义:IsDestructuring

语法制导操作 IsDestructuring 不接受参数并返回布尔值。它在以下产生式上分段定义:

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

本节由附录B.3.5 扩展。

14.7.5.3 运行时语义:ForDeclarationBindingInitialization

语法制导操作 ForDeclarationBindingInitialization 接受参数 value(一个ECMAScript 语言值)和 environment(一个环境记录undefined),并返回包含 unused 的正常完成或突然完成

传递 undefined 作为 environment 表示应该使用 PutValue 操作来分配初始化值。这是 var 语句和某些非严格函数的形式参数列表的情况(见10.2.11)。在这些情况下,词法绑定被提升并在其初始化程序求值之前预初始化。

它在以下产生式上分段定义:

ForDeclaration : LetOrConst ForBinding
  1. 返回 ? ForBinding 以参数 valueenvironment 进行的 BindingInitialization

14.7.5.4 运行时语义:ForDeclarationBindingInstantiation

语法制导操作 ForDeclarationBindingInstantiation 接受参数 environment(一个声明式环境记录)并返回 unused。它在以下产生式上分段定义:

ForDeclaration : LetOrConst ForBinding
  1. ForBindingBoundNames 的每个元素 name,执行
    1. 如果 LetOrConstIsConstantDeclarationtrue,则
      1. 执行 ! environment.CreateImmutableBinding(nametrue)。
    2. 否则,
      1. 执行 ! environment.CreateMutableBinding(namefalse)。
  2. 返回 unused

14.7.5.5 运行时语义:ForInOfLoopEvaluation

语法制导操作 ForInOfLoopEvaluation 接受参数 labelSet(一个包含字符串的列表),并返回包含ECMAScript 语言值的正常完成或突然完成。它在以下产生式上分段定义:

ForInOfStatement : for ( LeftHandSideExpression in Expression ) Statement
  1. keyResult 为 ? ForIn/OfHeadEvaluation(« », Expression, enumerate)。
  2. 返回 ? ForIn/OfBodyEvaluation(LeftHandSideExpression, Statement, keyResult, enumerate, assignment, labelSet)。
ForInOfStatement : for ( var ForBinding in Expression ) Statement
  1. keyResult 为 ? ForIn/OfHeadEvaluation(« », Expression, enumerate)。
  2. 返回 ? ForIn/OfBodyEvaluation(ForBinding, Statement, keyResult, enumerate, var-binding, labelSet)。
ForInOfStatement : for ( ForDeclaration in Expression ) Statement
  1. keyResult 为 ? ForIn/OfHeadEvaluation(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)。

本节由附录B.3.5 扩展。

14.7.5.6 ForIn/OfHeadEvaluation ( uninitializedBoundNames, expr, iterationKind )

抽象操作 ForIn/OfHeadEvaluation 接受参数 uninitializedBoundNames(一个包含字符串的列表)、 expr(一个 Expression 解析节点或一个 AssignmentExpression 解析节点),以及 iterationKindenumerateiterateasync-iterate),并返回包含迭代器记录的正常完成或突然完成。它在被调用时执行以下步骤:

  1. oldEnv运行执行上下文的 LexicalEnvironment。
  2. 如果 uninitializedBoundNames 不为空,则
    1. 断言uninitializedBoundNames 没有重复的条目。
    2. newEnvNewDeclarativeEnvironment(oldEnv)。
    3. uninitializedBoundNames 的每个字符串 name,执行
      1. 执行 ! newEnv.CreateMutableBinding(name, false)。
    4. 设置运行执行上下文的 LexicalEnvironment 为 newEnv
  3. exprRefCompletion(Evaluation of expr)。
  4. 设置运行执行上下文的 LexicalEnvironment 为 oldEnv
  5. exprValue 为 ? GetValue(? exprRef)。
  6. 如果 iterationKindenumerate,则
    1. 如果 exprValueundefinednull,则
      1. 返回 完成记录 { [[Type]]: break, [[Value]]: empty, [[Target]]: empty }。
    2. obj 为 ! ToObject(exprValue)。
    3. iteratorEnumerateObjectProperties(obj)。
    4. nextMethod 为 ! GetV(iterator, "next")。
    5. 返回迭代器记录 { [[Iterator]]: iterator, [[NextMethod]]: nextMethod, [[Done]]: false }。
  7. 否则,
    1. 断言iterationKinditerateasync-iterate
    2. 如果 iterationKindasync-iterate,令 iteratorKindasync
    3. 否则,令 iteratorKindsync
    4. 返回 ? GetIterator(exprValue, iteratorKind)。

14.7.5.7 ForIn/OfBodyEvaluation ( lhs, stmt, iteratorRecord, iterationKind, lhsKind, labelSet [ , iteratorKind ] )

抽象操作 ForIn/OfBodyEvaluation 接受参数 lhs(一个解析节点)、stmt(一个 Statement 解析节点)、iteratorRecord(一个迭代器记录)、iterationKindenumerateiterate)、lhsKindassignmentvar-bindinglexical-binding)、labelSet(一个包含字符串的列表)以及可选参数 iteratorKindsyncasync),并返回包含ECMAScript 语言值的正常完成或突然完成。它在被调用时执行以下步骤:

  1. 如果 iteratorKind 不存在,设置 iteratorKindsync
  2. oldEnv运行执行上下文的 LexicalEnvironment。
  3. Vundefined
  4. destructuringlhsIsDestructuring
  5. 如果 destructuringtruelhsKindassignment,则
    1. 断言lhs 是一个 LeftHandSideExpression
    2. assignmentPattern 为被 lhs 覆盖AssignmentPattern
  6. 重复,
    1. nextResult 为 ? Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]])。
    2. 如果 iteratorKindasync,设置 nextResult 为 ? Await(nextResult)。
    3. 如果 nextResult 不是对象,抛出 TypeError 异常。
    4. done 为 ? IteratorComplete(nextResult)。
    5. 如果 donetrue,返回 V
    6. nextValue 为 ? IteratorValue(nextResult)。
    7. 如果 lhsKindassignmentvar-binding,则
      1. 如果 destructuringtrue,则
        1. 如果 lhsKindassignment, 则
          1. statusCompletion(以参数 nextValueassignmentPattern 进行的 DestructuringAssignmentEvaluation)。
        2. 否则,
          1. 断言lhsKindvar-binding
          2. 断言lhs 是一个 ForBinding
          3. statusCompletion(以参数 nextValueundefinedlhs 进行的 BindingInitialization)。
      2. 否则,
        1. lhsRefCompletion(Evaluation of lhs)。(它可能被重复求值。)
        2. 如果 lhsRef突然完成,则
          1. statuslhsRef
        3. 否则,
          1. statusCompletion(PutValue(lhsRef.[[Value]], nextValue))。
    8. 否则,
      1. 断言lhsKindlexical-binding
      2. 断言lhs 是一个 ForDeclaration
      3. iterationEnvNewDeclarativeEnvironment(oldEnv)。
      4. 以参数 iterationEnvlhs 执行 ForDeclarationBindingInstantiation
      5. 设置运行执行上下文的 LexicalEnvironment 为 iterationEnv
      6. 如果 destructuringtrue,则
        1. statusCompletion(以参数 nextValueiterationEnvlhs 进行的 ForDeclarationBindingInitialization)。
      7. 否则,
        1. 断言lhs 绑定单个名称。
        2. lhsNamelhsBoundNames 的唯一元素。
        3. lhsRef 为 ! ResolveBinding(lhsName)。
        4. statusCompletion(InitializeReferencedBinding(lhsRef, nextValue))。
    9. 如果 status突然完成,则
      1. 设置运行执行上下文的 LexicalEnvironment 为 oldEnv
      2. 如果 iteratorKindasync,返回 ? AsyncIteratorClose(iteratorRecord, status)。
      3. 如果 iterationKindenumerate, 则
        1. 返回 ? status
      4. 否则,
        1. 断言iterationKinditerate
        2. 返回 ? IteratorClose(iteratorRecord, status)。
    10. resultCompletion(Evaluation of stmt)。
    11. 设置运行执行上下文的 LexicalEnvironment 为 oldEnv
    12. 如果 LoopContinues(result, labelSet) 是 false,则
      1. 如果 iterationKindenumerate, 则
        1. 返回 ? UpdateEmpty(result, V)。
      2. 否则,
        1. 断言iterationKinditerate
        2. 设置 statusCompletion(UpdateEmpty(result, V))。
        3. 如果 iteratorKindasync, 返回 ? AsyncIteratorClose(iteratorRecord, status)。
        4. 返回 ? IteratorClose(iteratorRecord, status)。
    13. 如果 result.[[Value]] 不是 empty,设置 Vresult.[[Value]]

14.7.5.8 运行时语义:Evaluation

BindingIdentifier : Identifier yield await
  1. bindingIdBindingIdentifierStringValue
  2. 返回 ? ResolveBinding(bindingId)。

14.7.5.9 EnumerateObjectProperties ( O )

抽象操作 EnumerateObjectProperties 接受参数 O(一个对象),并返回一个迭代器对象。它在被调用时执行以下步骤:

  1. 返回一个迭代器对象,其 next 方法遍历 O 的所有可枚举属性的字符串值键。该迭代器对象永远不能直接被 ECMAScript 代码访问。枚举属性的机制和顺序没有指定,但必须符合下面指定的规则。

迭代器throwreturn 方法是 null 且永远不会被调用。迭代器next 方法处理对象属性以确定属性键是否应该作为迭代器值返回。返回的属性键不包括 Symbol 键。目标对象的属性可能在枚举期间被删除。在被迭代器next 方法处理之前被删除的属性将被忽略。如果在枚举期间向目标对象添加新属性,则不保证新添加的属性会在活跃的枚举中被处理。属性名在任何枚举中最多被迭代器next 方法返回一次。

枚举目标对象的属性包括枚举其原型的属性,以及原型的原型,依此类推,递归进行;但如果原型的属性与已经被迭代器next 方法处理过的属性同名,则该原型属性不会被处理。在确定原型对象的属性是否已被处理时,不考虑 [[Enumerable]] 特性的值。原型对象的可枚举属性名必须通过调用 EnumerateObjectProperties 并传递原型对象作为参数来获得。EnumerateObjectProperties 必须通过调用目标对象的 [[OwnPropertyKeys]] 内部方法来获得目标对象的自有属性键。目标对象的属性特性必须通过调用其 [[GetOwnProperty]] 内部方法来获得。

此外,如果 O 或其原型链中的任何对象都不是代理异质对象TypedArray模块命名空间异质对象或实现提供的异质对象,则迭代器必须表现得如同由 CreateForInIterator(O) 给出的迭代器一样,直到发生以下情况之一:

  • O 或其原型链中对象的 [[Prototype]] 内部槽的值发生变化,
  • O 或其原型链中的对象删除了一个属性,
  • O 的原型链中的对象添加了一个属性,或
  • O 或其原型链中对象的属性的 [[Enumerable]] 特性值发生变化。
注 1

ECMAScript 实现不需要直接实现14.7.5.10.2.1 中的算法。它们可以选择任何实现,只要其行为不偏离该算法,除非违反了上一段中的约束之一。

以下是符合这些规则的 ECMAScript 生成器函数的信息性定义:

function* EnumerateObjectProperties(obj) {
    const visited = new Set();
    for (const key of Reflect.ownKeys(obj)) {
    if (typeof key === "symbol") continue;
    const desc = Reflect.getOwnPropertyDescriptor(obj, key);
    if (desc) {
        visited.add(key);
        if (desc.enumerable) yield key;
    }
    }
    const proto = Reflect.getPrototypeOf(obj);
    if (proto === null) return;
    for (const protoKey of EnumerateObjectProperties(proto)) {
    if (!visited.has(protoKey)) yield protoKey;
    }
}
注 2
选择不要求实现匹配 CreateForInIterator异质对象列表,是因为历史上实现在这些情况下的行为有所不同,而在所有其他情况下是一致的。

14.7.5.10 For-In 迭代器对象

For-In 迭代器是表示对某个特定对象进行特定迭代的对象。For-In 迭代器对象永远不能直接被 ECMAScript 代码访问;它们只是为了说明 EnumerateObjectProperties 的行为而存在。

14.7.5.10.1 CreateForInIterator ( object )

抽象操作 CreateForInIterator 接受参数 object(一个对象),并返回一个 For-In 迭代器。它用于创建一个 For-In 迭代器对象,该对象以特定顺序遍历 object 的自有和继承的可枚举字符串属性。它在被调用时执行以下步骤:

  1. iteratorOrdinaryObjectCreate(%ForInIteratorPrototype%, « [[Object]], [[ObjectWasVisited]], [[VisitedKeys]], [[RemainingKeys]] »)。
  2. 设置 iterator.[[Object]]object
  3. 设置 iterator.[[ObjectWasVisited]]false
  4. 设置 iterator.[[VisitedKeys]] 为一个新的空列表
  5. 设置 iterator.[[RemainingKeys]] 为一个新的空列表
  6. 返回 iterator

14.7.5.10.2 %ForInIteratorPrototype% 对象

%ForInIteratorPrototype% 对象:

14.7.5.10.2.1 %ForInIteratorPrototype%.next ( )

  1. Othis 值。
  2. 断言O 是对象
  3. 断言O 具有 For-In 迭代器实例的所有内部槽(14.7.5.10.3)。
  4. objectO.[[Object]]
  5. 重复,
    1. 如果 O.[[ObjectWasVisited]]false,则
      1. keys 为 ? object.[[OwnPropertyKeys]]()
      2. keys 的每个元素 key,执行
        1. 如果 key 是字符串,则
          1. key 追加到 O.[[RemainingKeys]]
      3. 设置 O.[[ObjectWasVisited]]true
    2. 重复,当 O.[[RemainingKeys]] 不为空时,
      1. rO.[[RemainingKeys]] 的第一个元素。
      2. O.[[RemainingKeys]] 中移除第一个元素。
      3. 如果 O.[[VisitedKeys]] 不包含 r,则
        1. desc 为 ? object.[[GetOwnProperty]](r)。
        2. 如果 desc 不是 undefined,则
          1. r 追加到 O.[[VisitedKeys]]
          2. 如果 desc.[[Enumerable]]true,返回 CreateIteratorResultObject(r, false)。
    3. 设置 object 为 ? object.[[GetPrototypeOf]]()
    4. 设置 O.[[Object]]object
    5. 设置 O.[[ObjectWasVisited]]false
    6. 如果 objectnull,返回 CreateIteratorResultObject(undefined, true)。

14.7.5.10.3 For-In 迭代器实例的属性

For-In 迭代器实例是普通对象,它们从 %ForInIteratorPrototype% 内在对象继承属性。For-In 迭代器实例最初使用 表 38 中列出的内部槽创建。

表 38:For-In 迭代器实例的内部槽
内部槽 类型 描述
[[Object]] 一个对象 正在迭代其属性的对象值。
[[ObjectWasVisited]] 一个布尔值 如果迭代器已在 [[Object]] 上调用了 [[OwnPropertyKeys]],则为 true,否则为 false
[[VisitedKeys]] 一个包含字符串的列表 到目前为止已被此迭代器发出的值。
[[RemainingKeys]] 一个包含字符串的列表 在迭代其原型的属性之前(如果其原型不是 null),当前对象剩余要发出的值。

14.8 continue 语句

语法

ContinueStatement[Yield, Await] : continue ; continue [no LineTerminator here] LabelIdentifier[?Yield, ?Await] ;

14.8.1 静态语义:早期错误

ContinueStatement : continue ; continue LabelIdentifier ;

14.8.2 运行时语义:Evaluation

ContinueStatement : continue ;
  1. 返回 完成记录 { [[Type]]: continue, [[Value]]: empty, [[Target]]: empty }。
ContinueStatement : continue LabelIdentifier ;
  1. labelLabelIdentifierStringValue
  2. 返回 完成记录 { [[Type]]: continue, [[Value]]: empty, [[Target]]: label }。

14.9 break 语句

语法

BreakStatement[Yield, Await] : break ; break [no LineTerminator here] LabelIdentifier[?Yield, ?Await] ;

14.9.1 静态语义:早期错误

BreakStatement : break ;

14.9.2 运行时语义:Evaluation

BreakStatement : break ;
  1. 返回 完成记录 { [[Type]]: break, [[Value]]: empty, [[Target]]: empty }。
BreakStatement : break LabelIdentifier ;
  1. labelLabelIdentifierStringValue
  2. 返回 完成记录 { [[Type]]: break, [[Value]]: empty, [[Target]]: label }。

14.10 return 语句

语法

ReturnStatement[Yield, Await] : return ; return [no LineTerminator here] Expression[+In, ?Yield, ?Await] ;

return 语句使函数停止执行,并且在大多数情况下将值返回给调用者。如果省略了 Expression,则返回值是 undefined。否则,返回值是 Expression 的值。根据周围的上下文,return 语句可能实际上不会将值返回给调用者。例如,在 try 块中,return 语句的完成记录可能在对 finally 块进行求值期间被另一个完成记录替换。

14.10.1 运行时语义:Evaluation

ReturnStatement : return ;
  1. 返回 ReturnCompletion(undefined)。
ReturnStatement : return Expression ;
  1. exprRef 为 ? Evaluation of Expression
  2. exprValue 为 ? GetValue(exprRef)。
  3. 如果 GetGeneratorKind() 是 async,设置 exprValue 为 ? Await(exprValue)。
  4. 返回 ReturnCompletion(exprValue)。

14.11 with 语句

注 1

不鼓励在新的 ECMAScript 代码中使用Legacy with 语句。考虑在严格模式代码非严格代码中都允许的替代方案,例如解构赋值

语法

WithStatement[Yield, Await, Return] : with ( Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] 注 2

with 语句将计算对象的对象环境记录添加到运行执行上下文的词法环境中。然后使用这个增强的词法环境执行语句。最后,恢复原始的词法环境。

14.11.1 静态语义:早期错误

WithStatement : with ( Expression ) Statement

只有在实现了B.3.1 中指定的扩展时,才需要应用第二条规则。

14.11.2 运行时语义:Evaluation

WithStatement : with ( Expression ) Statement
  1. val 为 ? Evaluation of Expression
  2. obj 为 ? ToObject(? GetValue(val))。
  3. oldEnv运行执行上下文的 LexicalEnvironment。
  4. newEnvNewObjectEnvironment(obj, true, oldEnv)。
  5. 设置运行执行上下文的 LexicalEnvironment 为 newEnv
  6. CCompletion(Evaluation of Statement)。
  7. 设置运行执行上下文的 LexicalEnvironment 为 oldEnv
  8. 返回 ? UpdateEmpty(C, undefined)。

无论控制如何离开嵌入的 Statement,无论是正常方式还是通过某种形式的突然完成或异常,LexicalEnvironment 总是恢复到其原来的状态。

14.12 switch 语句

语法

SwitchStatement[Yield, Await, Return] : switch ( Expression[+In, ?Yield, ?Await] ) CaseBlock[?Yield, ?Await, ?Return] CaseBlock[Yield, Await, Return] : { CaseClauses[?Yield, ?Await, ?Return]opt } { CaseClauses[?Yield, ?Await, ?Return]opt DefaultClause[?Yield, ?Await, ?Return] CaseClauses[?Yield, ?Await, ?Return]opt } CaseClauses[Yield, Await, Return] : CaseClause[?Yield, ?Await, ?Return] CaseClauses[?Yield, ?Await, ?Return] CaseClause[?Yield, ?Await, ?Return] CaseClause[Yield, Await, Return] : case Expression[+In, ?Yield, ?Await] : StatementList[?Yield, ?Await, ?Return]opt DefaultClause[Yield, Await, Return] : default : StatementList[?Yield, ?Await, ?Return]opt

14.12.1 静态语义:早期错误

SwitchStatement : switch ( Expression ) CaseBlock

14.12.2 运行时语义:CaseBlockEvaluation

语法制导操作 CaseBlockEvaluation 接受参数 input(一个 ECMAScript 语言值)并 返回一个 包含 ECMAScript 语言值正常完成突然完成。它按以下产生式分段定义:

CaseBlock : { }
  1. 返回 undefined
CaseBlock : { CaseClauses }
  1. Vundefined
  2. ACaseClauses 中按源文本顺序排列的 CaseClause 项的 列表
  3. foundfalse
  4. 对于 A 中的每个 CaseClause C,执行
    1. 如果 foundfalse,则
      1. 设置 found 为 ? CaseClauseIsSelected(C, input)。
    2. 如果 foundtrue,则
      1. RCompletion(Evaluation of C)。
      2. 如果 R.[[Value]] 不是 empty,设置 VR.[[Value]]
      3. 如果 R突然完成,返回 ? UpdateEmpty(R, V)。
  5. 返回 V
CaseBlock : { CaseClausesopt DefaultClause CaseClausesopt }
  1. Vundefined
  2. 如果第一个 CaseClauses 存在,则
    1. A 为第一个 CaseClauses 中按源文本顺序排列的 CaseClause 项的 列表
  3. 否则,
    1. A 为一个新的空 列表
  4. foundfalse
  5. 对于 A 中的每个 CaseClause C,执行
    1. 如果 foundfalse,则
      1. 设置 found 为 ? CaseClauseIsSelected(C, input)。
    2. 如果 foundtrue,则
      1. RCompletion(Evaluation of C)。
      2. 如果 R.[[Value]] 不是 empty,设置 VR.[[Value]]
      3. 如果 R突然完成,返回 ? UpdateEmpty(R, V)。
  6. foundInBfalse
  7. 如果第二个 CaseClauses 存在,则
    1. B 为第二个 CaseClauses 中按源文本顺序排列的 CaseClause 项的 列表
  8. 否则,
    1. B 为一个新的空 列表
  9. 如果 foundfalse,则
    1. 对于 B 中的每个 CaseClause C,执行
      1. 如果 foundInBfalse,则
        1. 设置 foundInB 为 ? CaseClauseIsSelected(C, input)。
      2. 如果 foundInBtrue,则
        1. RCompletion(Evaluation of CaseClause C)。
        2. 如果 R.[[Value]] 不是 empty,设置 VR.[[Value]]
        3. 如果 R突然完成,返回 ? UpdateEmpty(R, V)。
  10. 如果 foundInBtrue,返回 V
  11. defaultRCompletion(Evaluation of DefaultClause)。
  12. 如果 defaultR.[[Value]] 不是 empty,设置 VdefaultR.[[Value]]
  13. 如果 defaultR突然完成,返回 ? UpdateEmpty(defaultR, V)。
  14. 注:以下是对第二个 CaseClauses 的另一次完整迭代。
  15. 对于 B 中的每个 CaseClause C,执行
    1. RCompletion(Evaluation of CaseClause C)。
    2. 如果 R.[[Value]] 不是 empty,设置 VR.[[Value]]
    3. 如果 R突然完成,返回 ? UpdateEmpty(R, V)。
  16. 返回 V

14.12.3 CaseClauseIsSelected ( C, input )

抽象操作 CaseClauseIsSelected 接受参数 C(一个 CaseClause 解析节点)和 input(一个 ECMAScript 语言值)并 返回一个 包含 Boolean 的 正常完成突然完成。它 确定 C 是否匹配 input。调用时执行以下步骤:

  1. 断言C 是产生式 CaseClause : case Expression : StatementListopt 的实例。
  2. exprRef 为 ? Evaluation of CExpression
  3. clauseSelector 为 ? GetValue(exprRef)。
  4. 返回 IsStrictlyEqual(input, clauseSelector)。

此操作不执行 CStatementList(如果有)。CaseBlock 算法使用其 返回值来确定从哪个 StatementList 开始执行。

14.12.4 运行时语义:Evaluation

SwitchStatement : switch ( Expression ) CaseBlock
  1. exprRef 为 ? Evaluation of Expression
  2. switchValue 为 ? GetValue(exprRef)。
  3. oldEnv运行执行上下文 的 LexicalEnvironment。
  4. blockEnvNewDeclarativeEnvironment(oldEnv)。
  5. 执行 BlockDeclarationInstantiation(CaseBlock, blockEnv)。
  6. 设置 运行执行上下文 的 LexicalEnvironment 为 blockEnv
  7. RCompletion(CaseBlockEvaluation of CaseBlock with argument switchValue)。
  8. 设置 运行执行上下文 的 LexicalEnvironment 为 oldEnv
  9. 返回 R

无论控制如何离开 SwitchStatement,LexicalEnvironment 总是恢复到之前的状态。

CaseClause : case Expression :
  1. 返回 empty
CaseClause : case Expression : StatementList
  1. 返回 ? Evaluation of StatementList
DefaultClause : default :
  1. 返回 empty
DefaultClause : default : StatementList
  1. 返回 ? Evaluation of StatementList

14.13 标签语句

语法

LabelledStatement[Yield, Await, Return] : LabelIdentifier[?Yield, ?Await] : LabelledItem[?Yield, ?Await, ?Return] LabelledItem[Yield, Await, Return] : Statement[?Yield, ?Await, ?Return] FunctionDeclaration[?Yield, ?Await, ~Default]

一个 Statement 可以用标签作为前缀。标签语句只与带标签的 breakcontinue 语句结合使用。ECMAScript 没有 goto 语句。一个 Statement 可以是 LabelledStatement 的一部分, 而它本身又可以是另一个 LabelledStatement 的一部分,以此类推。以这种方式引入的标签在描述各个语句的语义时统称为"当前标签集"。

14.13.1 静态语义:早期错误

LabelledItem : FunctionDeclaration
  • 如果任何源文本匹配此产生式,则是语法错误。

此规则的替代定义在 B.3.1 中提供。

14.13.2 静态语义:IsLabelledFunction ( stmt )

抽象操作 IsLabelledFunction 接受参数 stmt(一个 Statement 解析节点)并返回一个 Boolean。调用时执行以下步骤:

  1. 如果 stmt 不是 LabelledStatement,返回 false
  2. itemstmtLabelledItem
  3. 如果 item LabelledItem : FunctionDeclaration ,返回 true
  4. subStmtitemStatement
  5. 返回 IsLabelledFunction(subStmt)。

14.13.3 运行时语义:Evaluation

LabelledStatement : LabelIdentifier : LabelledItem
  1. 返回 ? LabelledEvaluation of this LabelledStatement with argument « »。

14.13.4 运行时语义:LabelledEvaluation

语法制导操作 LabelledEvaluation 接受参数 labelSet(一个 字符串的 列表)并 返回一个 包含 ECMAScript 语言值empty正常完成,或 突然完成。它按以下产生式分段定义:

BreakableStatement : IterationStatement
  1. stmtResultCompletion(LoopEvaluation of IterationStatement with argument labelSet)。
  2. 如果 stmtResultbreak 完成,则
    1. 如果 stmtResult.[[Target]]empty,则
      1. 如果 stmtResult.[[Value]]empty,设置 stmtResultNormalCompletion(undefined)。
      2. 否则,设置 stmtResultNormalCompletion(stmtResult.[[Value]])。
  3. 返回 ? stmtResult
BreakableStatement : SwitchStatement
  1. stmtResultCompletion(Evaluation of SwitchStatement)。
  2. 如果 stmtResultbreak 完成,则
    1. 如果 stmtResult.[[Target]]empty,则
      1. 如果 stmtResult.[[Value]]empty,设置 stmtResultNormalCompletion(undefined)。
      2. 否则,设置 stmtResultNormalCompletion(stmtResult.[[Value]])。
  3. 返回 ? stmtResult
注 1

BreakableStatement 是可以通过无标签的 BreakStatement 退出的语句。

LabelledStatement : LabelIdentifier : LabelledItem
  1. labelLabelIdentifierStringValue
  2. newLabelSetlabelSet 和 « label » 的 列表连接
  3. stmtResultCompletion(LabelledEvaluation of LabelledItem with argument newLabelSet)。
  4. 如果 stmtResultbreak 完成stmtResult.[[Target]]label,则
    1. 设置 stmtResultNormalCompletion(stmtResult.[[Value]])。
  5. 返回 ? stmtResult
LabelledItem : FunctionDeclaration
  1. 返回 ? Evaluation of FunctionDeclaration
Statement : BlockStatement VariableStatement EmptyStatement ExpressionStatement IfStatement ContinueStatement BreakStatement ReturnStatement WithStatement ThrowStatement TryStatement DebuggerStatement
  1. 返回 ? Evaluation of Statement
注 2

Statement 中仅有两个产生式对 LabelledEvaluation 具有特殊语义:BreakableStatementLabelledStatement

14.14 throw 语句

语法

ThrowStatement[Yield, Await] : throw [no LineTerminator here] Expression[+In, ?Yield, ?Await] ;

14.14.1 运行时语义:Evaluation

ThrowStatement : throw Expression ;
  1. exprRef 为 ? Evaluation of Expression
  2. exprValue 为 ? GetValue(exprRef)。
  3. 返回 ThrowCompletion(exprValue)。

14.15 try 语句

语法

TryStatement[Yield, Await, Return] : try Block[?Yield, ?Await, ?Return] Catch[?Yield, ?Await, ?Return] try Block[?Yield, ?Await, ?Return] Finally[?Yield, ?Await, ?Return] try Block[?Yield, ?Await, ?Return] Catch[?Yield, ?Await, ?Return] Finally[?Yield, ?Await, ?Return] Catch[Yield, Await, Return] : catch ( CatchParameter[?Yield, ?Await] ) Block[?Yield, ?Await, ?Return] catch Block[?Yield, ?Await, ?Return] Finally[Yield, Await, Return] : finally Block[?Yield, ?Await, ?Return] CatchParameter[Yield, Await] : BindingIdentifier[?Yield, ?Await] BindingPattern[?Yield, ?Await]

try 语句包含一个可能发生异常情况的代码块,比如运行时错误或 throw 语句。catch 子句提供异常处理代码。当 catch 子句捕获异常时,其 CatchParameter 绑定到该异常。

14.15.1 静态语义:早期错误

Catch : catch ( CatchParameter ) Block

此产生式的替代 静态语义B.3.4 中给出。

14.15.2 运行时语义:CatchClauseEvaluation

语法制导操作 CatchClauseEvaluation 接受参数 thrownValue(一个 ECMAScript 语言值)并 返回一个 包含 ECMAScript 语言值empty正常完成,或 突然完成。它按以下产生式分段定义:

Catch : catch ( CatchParameter ) Block
  1. oldEnv运行执行上下文 的 LexicalEnvironment。
  2. catchEnvNewDeclarativeEnvironment(oldEnv)。
  3. 对于 CatchParameterBoundNames 中的每个元素 argName,执行
    1. 执行 ! catchEnv.CreateMutableBinding(argName, false)。
  4. 设置 运行执行上下文 的 LexicalEnvironment 为 catchEnv
  5. statusCompletion(BindingInitialization of CatchParameter with arguments thrownValue and catchEnv)。
  6. 如果 status突然完成,则
    1. 设置 运行执行上下文 的 LexicalEnvironment 为 oldEnv
    2. 返回 ? status
  7. BCompletion(Evaluation of Block)。
  8. 设置 运行执行上下文 的 LexicalEnvironment 为 oldEnv
  9. 返回 ? B
Catch : catch Block
  1. 返回 ? Evaluation of Block

无论控制如何离开 Block,LexicalEnvironment 总是恢复到之前的状态。

14.15.3 运行时语义:Evaluation

TryStatement : try Block Catch
  1. BCompletion(Evaluation of Block)。
  2. 如果 Bthrow 完成,令 CCompletion(CatchClauseEvaluation of Catch with argument B.[[Value]])。
  3. 否则,令 CB
  4. 返回 ? UpdateEmpty(C, undefined)。
TryStatement : try Block Finally
  1. BCompletion(Evaluation of Block)。
  2. FCompletion(Evaluation of Finally)。
  3. 如果 F正常完成,设置 FB
  4. 返回 ? UpdateEmpty(F, undefined)。
TryStatement : try Block Catch Finally
  1. BCompletion(Evaluation of Block)。
  2. 如果 Bthrow 完成,令 CCompletion(CatchClauseEvaluation of Catch with argument B.[[Value]])。
  3. 否则,令 CB
  4. FCompletion(Evaluation of Finally)。
  5. 如果 F正常完成,设置 FC
  6. 返回 ? UpdateEmpty(F, undefined)。

14.16 debugger 语句

语法

DebuggerStatement : debugger ;

14.16.1 运行时语义:Evaluation

计算 DebuggerStatement 可能允许实现在调试器下运行时触发断点。如果调试器不存在或不活跃,此语句没有可观察的效果。

DebuggerStatement : debugger ;
  1. 如果 实现定义的 调试设施可用且已启用,则
    1. 执行 实现定义的 调试动作。
    2. 返回一个新的 实现定义的 完成记录
  2. 否则,
    1. 返回 empty

15 ECMAScript 语言:函数和类

各种 ECMAScript 语言元素会导致创建 ECMAScript 函数对象10.2)。这些函数的 Evaluation 从执行其 [[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 静态语义:早期错误

UniqueFormalParameters : FormalParameters FormalParameters : FormalParameterList

相同 BindingIdentifierFormalParameterList 中的多次出现 只允许出现在具有简单参数列表且未在 严格模式代码 中定义的函数中。

15.1.2 静态语义:ContainsExpression

语法制导操作 ContainsExpression 不接受参数并返回一个 Boolean。它按以下产生式分段定义:

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 静态语义:IsSimpleParameterList

语法制导操作 IsSimpleParameterList 不接受参数并返回一个 Boolean。它按以下产生式分段定义:

BindingElement : BindingPattern
  1. 返回 false
BindingElement : BindingPattern Initializer
  1. 返回 false
SingleNameBinding : BindingIdentifier
  1. 返回 true
SingleNameBinding : BindingIdentifier Initializer
  1. 返回 false
FormalParameters : [empty]
  1. 返回 true
FormalParameters : FunctionRestParameter
  1. 返回 false
FormalParameters : FormalParameterList , FunctionRestParameter
  1. 返回 false
FormalParameterList : FormalParameterList , FormalParameter
  1. 如果 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 静态语义:HasInitializer

语法制导操作 HasInitializer 不接受参数并返回一个 Boolean。它按以下产生式分段定义:

BindingElement : BindingPattern
  1. 返回 false
BindingElement : BindingPattern Initializer
  1. 返回 true
SingleNameBinding : BindingIdentifier
  1. 返回 false
SingleNameBinding : BindingIdentifier Initializer
  1. 返回 true
FormalParameterList : FormalParameterList , FormalParameter
  1. 如果 FormalParameterListHasInitializertrue,返回 true
  2. 返回 FormalParameterHasInitializer

15.1.5 静态语义:ExpectedArgumentCount

语法制导操作 ExpectedArgumentCount 不接受参数并返回一个非负 整数。它按以下产生式分段定义:

FormalParameters : [empty] FunctionRestParameter
  1. 返回 0。
FormalParameters : FormalParameterList , FunctionRestParameter
  1. 返回 FormalParameterListExpectedArgumentCount

FormalParameterList 的 ExpectedArgumentCount 是在剩余参数或第一个具有初始化器的 FormalParameter 左侧的 FormalParameters 的数量。没有初始化器的 FormalParameter 可以出现在第一个有初始化器的参数之后,但这样的参数被认为是可选的,其默认值为 undefined

FormalParameterList : FormalParameter
  1. 如果 FormalParameterHasInitializertrue,返回 0。
  2. 返回 1。
FormalParameterList : FormalParameterList , FormalParameter
  1. countFormalParameterListExpectedArgumentCount
  2. 如果 FormalParameterListHasInitializertrueFormalParameterHasInitializertrue,返回 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 静态语义:早期错误

FunctionDeclaration : function BindingIdentifier ( FormalParameters ) { FunctionBody } function ( FormalParameters ) { FunctionBody } FunctionExpression : function BindingIdentifieropt ( FormalParameters ) { FunctionBody }

FunctionBodyLexicallyDeclaredNames 不包括使用 var 或 function 声明绑定的标识符。

FunctionBody : FunctionStatementList

15.2.2 静态语义:FunctionBodyContainsUseStrict

语法制导操作 FunctionBodyContainsUseStrict 不接受参数并返回一个 Boolean。它按以下产生式分段定义:

FunctionBody : FunctionStatementList
  1. 如果 FunctionBody指令序言 包含一个 Use Strict 指令,返回 true;否则,返回 false

15.2.3 运行时语义:EvaluateFunctionBody

语法制导操作 EvaluateFunctionBody 接受参数 functionObject(一个 ECMAScript 函数对象)和 argumentsList(一个 ECMAScript 语言值List)并返回一个 return completionthrow completion。它按以下产生式分段定义:

FunctionBody : FunctionStatementList
  1. 执行 ? FunctionDeclarationInstantiation(functionObject, argumentsList)。
  2. 执行 ? Evaluation of FunctionStatementList
  3. 注:如果前面的步骤产生了一个 normal completion,那么求值通过继续执行到 FunctionStatementList 的末尾而结束。
  4. 返回 ReturnCompletion(undefined)。

15.2.4 运行时语义:InstantiateOrdinaryFunctionObject

语法制导操作 InstantiateOrdinaryFunctionObject 接受参数 env(一个 Environment Record)和 privateEnv(一个 PrivateEnvironment Recordnull)并返回一个 ECMAScript 函数对象。它按以下产生式分段定义:

FunctionDeclaration : function BindingIdentifier ( FormalParameters ) { FunctionBody }
  1. nameBindingIdentifierStringValue
  2. sourceTextFunctionDeclaration 匹配的源文本
  3. FOrdinaryFunctionCreate(%Function.prototype%, sourceText, FormalParameters, FunctionBody, non-lexical-this, env, privateEnv)。
  4. 执行 SetFunctionName(F, name)。
  5. 执行 MakeConstructor(F)。
  6. 返回 F
FunctionDeclaration : function ( FormalParameters ) { FunctionBody }
  1. sourceTextFunctionDeclaration 匹配的源文本
  2. FOrdinaryFunctionCreate(%Function.prototype%, sourceText, FormalParameters, FunctionBody, non-lexical-this, env, privateEnv)。
  3. 执行 SetFunctionName(F, "default")。
  4. 执行 MakeConstructor(F)。
  5. 返回 F

匿名 FunctionDeclaration 只能作为 export default 声明的一部分出现,因此其函数代码总是 严格模式代码

15.2.5 运行时语义:InstantiateOrdinaryFunctionExpression

语法制导操作 InstantiateOrdinaryFunctionExpression 接受可选参数 name(一个 属性键私有名称)并返回一个 ECMAScript 函数对象。它按以下产生式分段定义:

FunctionExpression : function ( FormalParameters ) { FunctionBody }
  1. 如果不存在 name,设置 name""
  2. env运行执行上下文 的 LexicalEnvironment。
  3. privateEnv运行执行上下文 的 PrivateEnvironment。
  4. sourceTextFunctionExpression 匹配的源文本
  5. closureOrdinaryFunctionCreate(%Function.prototype%, sourceText, FormalParameters, FunctionBody, non-lexical-this, env, privateEnv)。
  6. 执行 SetFunctionName(closure, name)。
  7. 执行 MakeConstructor(closure)。
  8. 返回 closure
FunctionExpression : function BindingIdentifier ( FormalParameters ) { FunctionBody }
  1. 断言name 不存在。
  2. 设置 nameBindingIdentifierStringValue
  3. outerEnv运行执行上下文 的 LexicalEnvironment。
  4. funcEnvNewDeclarativeEnvironment(outerEnv)。
  5. 执行 ! funcEnv.CreateImmutableBinding(name, false)。
  6. privateEnv运行执行上下文 的 PrivateEnvironment。
  7. sourceTextFunctionExpression 匹配的源文本
  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

FunctionExpression 中的 BindingIdentifier 可以从 FunctionExpressionFunctionBody 内部引用,以允许函数递归地调用自身。然而,与 FunctionDeclaration 不同,FunctionExpression 中的 BindingIdentifier 不能从包围 FunctionExpression 的作用域中引用,也不会影响该作用域。

15.2.6 运行时语义:Evaluation

FunctionDeclaration : function BindingIdentifier ( FormalParameters ) { FunctionBody }
  1. 返回 empty
注 1

B.3.2 中提供了替代语义。

FunctionDeclaration : function ( FormalParameters ) { FunctionBody }
  1. 返回 empty
FunctionExpression : function BindingIdentifieropt ( FormalParameters ) { FunctionBody }
  1. 返回 FunctionExpressionInstantiateOrdinaryFunctionExpression
注 2

对于使用 FunctionDeclarationFunctionExpression 定义的每个函数,都会自动创建一个 "prototype" 属性,以允许该函数被用作 构造函数

FunctionStatementList : [empty]
  1. 返回 undefined

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 静态语义:早期错误

ArrowFunction : ArrowParameters => ConciseBody ArrowParameters : CoverParenthesizedExpressionAndArrowParameterList

15.3.2 静态语义:ConciseBodyContainsUseStrict

语法制导操作 ConciseBodyContainsUseStrict 不接受参数并返回一个 Boolean。它按以下产生式分段定义:

ConciseBody : ExpressionBody
  1. 返回 false
ConciseBody : { FunctionBody }
  1. 返回 FunctionBodyFunctionBodyContainsUseStrict

15.3.3 运行时语义:EvaluateConciseBody

语法制导操作 EvaluateConciseBody 接受参数 functionObject(一个 ECMAScript 函数对象)和 argumentsList(一个 ECMAScript 语言值List)并返回一个 return completionthrow completion。它按以下产生式分段定义:

ConciseBody : ExpressionBody
  1. 执行 ? FunctionDeclarationInstantiation(functionObject, argumentsList)。
  2. 返回 ? Evaluation of ExpressionBody

15.3.4 运行时语义:InstantiateArrowFunctionExpression

语法制导操作 InstantiateArrowFunctionExpression 接受可选参数 name(一个 属性键私有名称)并返回一个 ECMAScript 函数对象。它按以下产生式分段定义:

ArrowFunction : ArrowParameters => ConciseBody
  1. 如果不存在 name,设置 name""
  2. env运行执行上下文 的 LexicalEnvironment。
  3. privateEnv运行执行上下文 的 PrivateEnvironment。
  4. sourceTextArrowFunction 匹配的源文本
  5. closureOrdinaryFunctionCreate(%Function.prototype%, sourceText, ArrowParameters, ConciseBody, lexical-this, env, privateEnv)。
  6. 执行 SetFunctionName(closure, name)。
  7. 返回 closure

ArrowFunction 不为 argumentssuperthisnew.target 定义局部绑定。ArrowFunction 内对 argumentssuperthisnew.target 的任何引用都必须解析为词法封闭环境中的绑定。通常这会是紧邻封闭函数的函数环境。尽管 ArrowFunction 可能包含对 super 的引用,但在步骤 5 中创建的 函数对象 不会通过执行 MakeMethod 而成为方法。引用 superArrowFunction 总是包含在非 ArrowFunction 中,实现 super 所需的状态可以通过被 ArrowFunction函数对象 捕获的 env 访问。

15.3.5 运行时语义:Evaluation

ArrowFunction : ArrowParameters => ConciseBody
  1. 返回 ArrowFunctionInstantiateArrowFunctionExpression
ExpressionBody : AssignmentExpression
  1. exprRef 为 ? Evaluation of AssignmentExpression
  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 静态语义:早期错误

MethodDefinition : ClassElementName ( UniqueFormalParameters ) { FunctionBody } MethodDefinition : set ClassElementName ( PropertySetParameterList ) { FunctionBody }

15.4.2 静态语义:HasDirectSuper

语法制导操作 HasDirectSuper 不接受参数并返回一个 Boolean。它按以下产生式分段定义:

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 静态语义:SpecialMethod

语法制导操作 SpecialMethod 不接受参数并返回一个 Boolean。它按以下产生式分段定义:

MethodDefinition : ClassElementName ( UniqueFormalParameters ) { FunctionBody }
  1. 返回 false
MethodDefinition : GeneratorMethod AsyncMethod AsyncGeneratorMethod get ClassElementName ( ) { FunctionBody } set ClassElementName ( PropertySetParameterList ) { FunctionBody }
  1. 返回 true

15.4.4 运行时语义:DefineMethod

语法制导操作 DefineMethod 接受参数 object(一个 Object)和可选参数 functionPrototype(一个 Object)并返回 包含一个 Record(字段为 [[Key]](一个 属性键)和 [[Closure]](一个 ECMAScript 函数对象))的 normal completionabrupt completion。它按以下产生式分段定义:

MethodDefinition : ClassElementName ( UniqueFormalParameters ) { FunctionBody }
  1. propKey 为 ? Evaluation of ClassElementName
  2. env运行执行上下文 的 LexicalEnvironment。
  3. privateEnv运行执行上下文 的 PrivateEnvironment。
  4. 如果存在 functionPrototype,那么
    1. prototypefunctionPrototype
  5. 否则,
    1. prototype%Function.prototype%
  6. sourceTextMethodDefinition 匹配的源文本
  7. closureOrdinaryFunctionCreate(prototype, sourceText, UniqueFormalParameters, FunctionBody, non-lexical-this, env, privateEnv)。
  8. 执行 MakeMethod(closure, object)。
  9. 返回 Record { [[Key]]: propKey, [[Closure]]: closure }。

15.4.5 运行时语义:MethodDefinitionEvaluation

语法制导操作 MethodDefinitionEvaluation 接受参数 object(一个 Object)和 enumerable(一个 Boolean)并返回 包含 PrivateElementunusednormal completion,或 abrupt completion。它按以下产生式分段定义:

MethodDefinition : ClassElementName ( UniqueFormalParameters ) { FunctionBody }
  1. methodDefMethodDefinition 以参数 object 的 ? DefineMethod
  2. 执行 SetFunctionName(methodDef.[[Closure]], methodDef.[[Key]])。
  3. 返回 ? DefineMethodProperty(object, methodDef.[[Key]], methodDef.[[Closure]], enumerable)。
MethodDefinition : get ClassElementName ( ) { FunctionBody }
  1. propKey 为 ? Evaluation of ClassElementName
  2. env运行执行上下文 的 LexicalEnvironment。
  3. privateEnv运行执行上下文 的 PrivateEnvironment。
  4. sourceTextMethodDefinition 匹配的源文本
  5. formalParameterList 为产生式 FormalParameters : [empty] 的实例。
  6. closureOrdinaryFunctionCreate(%Function.prototype%, sourceText, formalParameterList, FunctionBody, non-lexical-this, env, privateEnv)。
  7. 执行 MakeMethod(closure, object)。
  8. 执行 SetFunctionName(closure, propKey, "get")。
  9. 如果 propKey私有名称,那么
    1. 返回 PrivateElement { [[Key]]: propKey, [[Kind]]: accessor, [[Get]]: closure, [[Set]]: undefined }。
  10. 否则,
    1. desc 为 PropertyDescriptor { [[Get]]: closure, [[Enumerable]]: enumerable, [[Configurable]]: true }。
    2. 执行 ? DefinePropertyOrThrow(object, propKey, desc)。
    3. 返回 unused
MethodDefinition : set ClassElementName ( PropertySetParameterList ) { FunctionBody }
  1. propKey 为 ? Evaluation of ClassElementName
  2. env运行执行上下文 的 LexicalEnvironment。
  3. privateEnv运行执行上下文 的 PrivateEnvironment。
  4. sourceTextMethodDefinition 匹配的源文本
  5. closureOrdinaryFunctionCreate(%Function.prototype%, sourceText, PropertySetParameterList, FunctionBody, non-lexical-this, env, privateEnv)。
  6. 执行 MakeMethod(closure, object)。
  7. 执行 SetFunctionName(closure, propKey, "set")。
  8. 如果 propKey私有名称,那么
    1. 返回 PrivateElement { [[Key]]: propKey, [[Kind]]: accessor, [[Get]]: undefined, [[Set]]: closure }。
  9. 否则,
    1. desc 为 PropertyDescriptor { [[Set]]: closure, [[Enumerable]]: enumerable, [[Configurable]]: true }。
    2. 执行 ? DefinePropertyOrThrow(object, propKey, desc)。
    3. 返回 unused
GeneratorMethod : * ClassElementName ( UniqueFormalParameters ) { GeneratorBody }
  1. propKey 为 ? Evaluation of ClassElementName
  2. env运行执行上下文 的 LexicalEnvironment。
  3. privateEnv运行执行上下文 的 PrivateEnvironment。
  4. sourceTextGeneratorMethod 匹配的源文本
  5. closureOrdinaryFunctionCreate(%GeneratorFunction.prototype%, sourceText, UniqueFormalParameters, GeneratorBody, non-lexical-this, env, privateEnv)。
  6. 执行 MakeMethod(closure, object)。
  7. 执行 SetFunctionName(closure, propKey)。
  8. prototypeOrdinaryObjectCreate(%GeneratorPrototype%)。
  9. 执行 ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  10. 返回 ? DefineMethodProperty(object, propKey, closure, enumerable)。
AsyncGeneratorMethod : async * ClassElementName ( UniqueFormalParameters ) { AsyncGeneratorBody }
  1. propKey 为 ? Evaluation of ClassElementName
  2. env运行执行上下文 的 LexicalEnvironment。
  3. privateEnv运行执行上下文 的 PrivateEnvironment。
  4. sourceTextAsyncGeneratorMethod 匹配的源文本
  5. closureOrdinaryFunctionCreate(%AsyncGeneratorFunction.prototype%, sourceText, UniqueFormalParameters, AsyncGeneratorBody, non-lexical-this, env, privateEnv)。
  6. 执行 MakeMethod(closure, object)。
  7. 执行 SetFunctionName(closure, propKey)。
  8. prototypeOrdinaryObjectCreate(%AsyncGeneratorPrototype%)。
  9. 执行 ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  10. 返回 ? DefineMethodProperty(object, propKey, closure, enumerable)。
AsyncMethod : async ClassElementName ( UniqueFormalParameters ) { AsyncFunctionBody }
  1. propKey 为 ? Evaluation of ClassElementName
  2. env运行执行上下文 的 LexicalEnvironment。
  3. privateEnv运行执行上下文 的 PrivateEnvironment。
  4. sourceTextAsyncMethod 匹配的源文本
  5. closureOrdinaryFunctionCreate(%AsyncFunction.prototype%, sourceText, UniqueFormalParameters, AsyncFunctionBody, non-lexical-this, env, privateEnv)。
  6. 执行 MakeMethod(closure, object)。
  7. 执行 SetFunctionName(closure, propKey)。
  8. 返回 ? DefineMethodProperty(object, propKey, closure, enumerable)。

15.5 生成器函数定义

语法

GeneratorDeclaration[Yield, Await, Default] : function * BindingIdentifier[?Yield, ?Await] ( FormalParameters[+Yield, ~Await] ) { GeneratorBody } [+Default] function * ( FormalParameters[+Yield, ~Await] ) { GeneratorBody } GeneratorExpression : function * BindingIdentifier[+Yield, ~Await]opt ( FormalParameters[+Yield, ~Await] ) { GeneratorBody } GeneratorMethod[Yield, Await] : * ClassElementName[?Yield, ?Await] ( UniqueFormalParameters[+Yield, ~Await] ) { GeneratorBody } GeneratorBody : FunctionBody[+Yield, ~Await] YieldExpression[In, Await] : yield yield [no LineTerminator here] AssignmentExpression[?In, +Yield, ?Await] yield [no LineTerminator here] * AssignmentExpression[?In, +Yield, ?Await] 注 1

紧跟在 yield 后面的语法上下文需要使用 InputElementRegExpOrTemplateTail 词法目标。

注 2

YieldExpression 不能在生成器函数的 FormalParameters 中使用,因为作为 FormalParameters 一部分的任何表达式都在生成的 Generator 处于可恢复状态之前被求值。

注 3

与 Generators 相关的 抽象操作27.5.3 中定义。

15.5.1 静态语义:早期错误

GeneratorMethod : * ClassElementName ( UniqueFormalParameters ) { GeneratorBody } GeneratorDeclaration : function * BindingIdentifier ( FormalParameters ) { GeneratorBody } function * ( FormalParameters ) { GeneratorBody } GeneratorExpression : function * BindingIdentifieropt ( FormalParameters ) { GeneratorBody }

15.5.2 运行时语义:EvaluateGeneratorBody

语法制导操作 EvaluateGeneratorBody 接受参数 functionObject(一个 ECMAScript 函数对象)和 argumentsList(一个 List of ECMAScript 语言值),并返回 throw completionreturn completion。它按以下产生式分段定义:

GeneratorBody : FunctionBody
  1. 执行 ? FunctionDeclarationInstantiation(functionObject, argumentsList)。
  2. G 为 ? OrdinaryCreateFromConstructor(functionObject, "%GeneratorPrototype%", « [[GeneratorState]], [[GeneratorContext]], [[GeneratorBrand]] »)。
  3. 设置 G.[[GeneratorBrand]]empty
  4. 设置 G.[[GeneratorState]]suspended-start
  5. 执行 GeneratorStart(G, FunctionBody)。
  6. 返回 ReturnCompletion(G)。

15.5.3 运行时语义:InstantiateGeneratorFunctionObject

语法制导操作 InstantiateGeneratorFunctionObject 接受参数 env(一个 Environment Record)和 privateEnv(一个 PrivateEnvironment Recordnull),并返回一个 ECMAScript 函数对象。它按以下产生式分段定义:

GeneratorDeclaration : function * BindingIdentifier ( FormalParameters ) { GeneratorBody }
  1. nameBindingIdentifierStringValue
  2. sourceTextGeneratorDeclaration 匹配的源文本
  3. FOrdinaryFunctionCreate(%GeneratorFunction.prototype%, sourceText, FormalParameters, GeneratorBody, non-lexical-this, env, privateEnv)。
  4. 执行 SetFunctionName(F, name)。
  5. prototypeOrdinaryObjectCreate(%GeneratorPrototype%)。
  6. 执行 ! DefinePropertyOrThrow(F, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  7. 返回 F
GeneratorDeclaration : function * ( FormalParameters ) { GeneratorBody }
  1. sourceTextGeneratorDeclaration 匹配的源文本
  2. FOrdinaryFunctionCreate(%GeneratorFunction.prototype%, sourceText, FormalParameters, GeneratorBody, non-lexical-this, env, privateEnv)。
  3. 执行 SetFunctionName(F, "default")。
  4. prototypeOrdinaryObjectCreate(%GeneratorPrototype%)。
  5. 执行 ! DefinePropertyOrThrow(F, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  6. 返回 F

匿名的 GeneratorDeclaration 只能作为 export default 声明的一部分出现,因此其函数代码总是 严格模式代码

15.5.4 运行时语义:InstantiateGeneratorFunctionExpression

语法制导操作 InstantiateGeneratorFunctionExpression 接受可选参数 name(一个 属性键私有名称),并返回一个 ECMAScript 函数对象。它按以下产生式分段定义:

GeneratorExpression : function * ( FormalParameters ) { GeneratorBody }
  1. 如果 name 不存在,设置 name""
  2. env运行执行上下文 的 LexicalEnvironment。
  3. privateEnv运行执行上下文 的 PrivateEnvironment。
  4. sourceTextGeneratorExpression 匹配的源文本
  5. closureOrdinaryFunctionCreate(%GeneratorFunction.prototype%, sourceText, FormalParameters, GeneratorBody, non-lexical-this, env, privateEnv)。
  6. 执行 SetFunctionName(closure, name)。
  7. prototypeOrdinaryObjectCreate(%GeneratorPrototype%)。
  8. 执行 ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  9. 返回 closure
GeneratorExpression : function * BindingIdentifier ( FormalParameters ) { GeneratorBody }
  1. 断言name 不存在。
  2. 设置 nameBindingIdentifierStringValue
  3. outerEnv运行执行上下文 的 LexicalEnvironment。
  4. funcEnvNewDeclarativeEnvironment(outerEnv)。
  5. 执行 ! funcEnv.CreateImmutableBinding(name, false)。
  6. privateEnv运行执行上下文 的 PrivateEnvironment。
  7. sourceTextGeneratorExpression 匹配的源文本
  8. closureOrdinaryFunctionCreate(%GeneratorFunction.prototype%, sourceText, FormalParameters, GeneratorBody, non-lexical-this, funcEnv, privateEnv)。
  9. 执行 SetFunctionName(closure, name)。
  10. prototypeOrdinaryObjectCreate(%GeneratorPrototype%)。
  11. 执行 ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  12. 执行 ! funcEnv.InitializeBinding(name, closure)。
  13. 返回 closure
注释

GeneratorExpression 中的 BindingIdentifier 可以从 GeneratorExpressionFunctionBody 内部引用,以允许生成器代码递归调用自身。然而,与 GeneratorDeclaration 不同,GeneratorExpression 中的 BindingIdentifier 不能从包围 GeneratorExpression 的作用域中引用,也不会影响该作用域。

15.5.5 运行时语义:Evaluation

GeneratorExpression : function * BindingIdentifieropt ( FormalParameters ) { GeneratorBody }
  1. 返回 GeneratorExpressionInstantiateGeneratorFunctionExpression
YieldExpression : yield
  1. 返回 ? Yield(undefined)。
YieldExpression : yield AssignmentExpression
  1. exprRef 为 ? Evaluation of AssignmentExpression
  2. value 为 ? GetValue(exprRef)。
  3. 返回 ? Yield(value)。
YieldExpression : yield * AssignmentExpression
  1. generatorKindGetGeneratorKind()。
  2. 断言generatorKindsyncasync
  3. exprRef 为 ? Evaluation of AssignmentExpression
  4. value 为 ? GetValue(exprRef)。
  5. iteratorRecord 为 ? GetIterator(value, generatorKind)。
  6. iteratoriteratorRecord.[[Iterator]]
  7. receivedNormalCompletion(undefined)。
  8. 重复,
    1. 如果 received 是一个 normal completion,那么
      1. innerResult 为 ? Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]], « received.[[Value]] »)。
      2. 如果 generatorKindasync,设置 innerResult 为 ? Await(innerResult)。
      3. 如果 innerResult 不是 Object,抛出 TypeError 异常。
      4. done 为 ? IteratorComplete(innerResult)。
      5. 如果 donetrue,那么
        1. 返回 ? IteratorValue(innerResult)。
      6. 如果 generatorKindasync,设置 receivedCompletion(AsyncGeneratorYield(? IteratorValue(innerResult)))。
      7. 否则,设置 receivedCompletion(GeneratorYield(innerResult))。
    2. 否则如果 received 是一个 throw completion,那么
      1. throw 为 ? GetMethod(iterator, "throw")。
      2. 如果 throw 不是 undefined,那么
        1. innerResult 为 ? Call(throw, iterator, « received.[[Value]] »)。
        2. 如果 generatorKindasync,设置 innerResult 为 ? Await(innerResult)。
        3. 注释:来自内部 迭代器 throw 方法的异常会被传播。来自内部 throw 方法的 Normal completion 的处理方式与内部 next 类似。
        4. 如果 innerResult 不是 Object,抛出 TypeError 异常。
        5. done 为 ? IteratorComplete(innerResult)。
        6. 如果 donetrue,那么
          1. 返回 ? IteratorValue(innerResult)。
        7. 如果 generatorKindasync,设置 receivedCompletion(AsyncGeneratorYield(? IteratorValue(innerResult)))。
        8. 否则,设置 receivedCompletion(GeneratorYield(innerResult))。
      3. 否则,
        1. 注释:如果 iterator 没有 throw 方法,这个 throw 将终止 yield* 循环。但首先我们需要给 iterator 一个清理的机会。
        2. closeCompletionNormalCompletion(empty)。
        3. 如果 generatorKindasync,执行 ? 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. 设置 valuereceived.[[Value]]
        2. 如果 generatorKindasync,那么
          1. 设置 value 为 ? Await(value)。
        3. 返回 ReturnCompletion(value)。
      4. innerReturnResult 为 ? Call(return, iterator, « received.[[Value]] »)。
      5. 如果 generatorKindasync,设置 innerReturnResult 为 ? Await(innerReturnResult)。
      6. 如果 innerReturnResult 不是 Object,抛出 TypeError 异常。
      7. done 为 ? IteratorComplete(innerReturnResult)。
      8. 如果 donetrue,那么
        1. 设置 value 为 ? IteratorValue(innerReturnResult)。
        2. 返回 ReturnCompletion(value)。
      9. 如果 generatorKindasync,设置 receivedCompletion(AsyncGeneratorYield(? IteratorValue(innerReturnResult)))。
      10. 否则,设置 receivedCompletion(GeneratorYield(innerReturnResult))。

15.6 异步生成器函数定义

语法

AsyncGeneratorDeclaration[Yield, Await, Default] : async [no LineTerminator here] function * BindingIdentifier[?Yield, ?Await] ( FormalParameters[+Yield, +Await] ) { AsyncGeneratorBody } [+Default] async [no LineTerminator here] function * ( FormalParameters[+Yield, +Await] ) { AsyncGeneratorBody } AsyncGeneratorExpression : async [no LineTerminator here] function * BindingIdentifier[+Yield, +Await]opt ( FormalParameters[+Yield, +Await] ) { AsyncGeneratorBody } AsyncGeneratorMethod[Yield, Await] : async [no LineTerminator here] * ClassElementName[?Yield, ?Await] ( UniqueFormalParameters[+Yield, +Await] ) { AsyncGeneratorBody } AsyncGeneratorBody : FunctionBody[+Yield, +Await] 注释 1

YieldExpressionAwaitExpression 不能在异步生成器函数的 FormalParameters 中使用,因为作为 FormalParameters 一部分的任何表达式都在生成的 AsyncGenerator 处于可恢复状态之前被求值。

注释 2

与 AsyncGenerators 相关的 抽象操作27.6.3 中定义。

15.6.1 静态语义:早期错误

AsyncGeneratorMethod : async * ClassElementName ( UniqueFormalParameters ) { AsyncGeneratorBody } AsyncGeneratorDeclaration : async function * BindingIdentifier ( FormalParameters ) { AsyncGeneratorBody } async function * ( FormalParameters ) { AsyncGeneratorBody } AsyncGeneratorExpression : async function * BindingIdentifieropt ( FormalParameters ) { AsyncGeneratorBody }

15.6.2 运行时语义:EvaluateAsyncGeneratorBody

语法制导操作 EvaluateAsyncGeneratorBody 接受参数 functionObject(一个 ECMAScript 函数对象)和 argumentsList(一个 List of ECMAScript 语言值),并返回 throw completionreturn completion。它按以下产生式分段定义:

AsyncGeneratorBody : FunctionBody
  1. 执行 ? FunctionDeclarationInstantiation(functionObject, argumentsList)。
  2. generator 为 ? OrdinaryCreateFromConstructor(functionObject, "%AsyncGeneratorPrototype%", « [[AsyncGeneratorState]], [[AsyncGeneratorContext]], [[AsyncGeneratorQueue]], [[GeneratorBrand]] »)。
  3. 设置 generator.[[GeneratorBrand]]empty
  4. 设置 generator.[[AsyncGeneratorState]]suspended-start
  5. 执行 AsyncGeneratorStart(generator, FunctionBody)。
  6. 返回 ReturnCompletion(generator)。

15.6.3 运行时语义:InstantiateAsyncGeneratorFunctionObject

语法制导操作 InstantiateAsyncGeneratorFunctionObject 接受参数 env(一个 Environment Record)和 privateEnv(一个 PrivateEnvironment Recordnull),并返回一个 ECMAScript 函数对象。它按以下产生式分段定义:

AsyncGeneratorDeclaration : async function * BindingIdentifier ( FormalParameters ) { AsyncGeneratorBody }
  1. nameBindingIdentifierStringValue
  2. sourceTextAsyncGeneratorDeclaration 匹配的源文本
  3. FOrdinaryFunctionCreate(%AsyncGeneratorFunction.prototype%, sourceText, FormalParameters, AsyncGeneratorBody, non-lexical-this, env, privateEnv)。
  4. 执行 SetFunctionName(F, name)。
  5. prototypeOrdinaryObjectCreate(%AsyncGeneratorPrototype%)。
  6. 执行 ! DefinePropertyOrThrow(F, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  7. 返回 F
AsyncGeneratorDeclaration : async function * ( FormalParameters ) { AsyncGeneratorBody }
  1. sourceTextAsyncGeneratorDeclaration 匹配的源文本
  2. FOrdinaryFunctionCreate(%AsyncGeneratorFunction.prototype%, sourceText, FormalParameters, AsyncGeneratorBody, non-lexical-this, env, privateEnv)。
  3. 执行 SetFunctionName(F, "default")。
  4. prototypeOrdinaryObjectCreate(%AsyncGeneratorPrototype%)。
  5. 执行 ! DefinePropertyOrThrow(F, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  6. 返回 F
注释

匿名的 AsyncGeneratorDeclaration 只能作为 export default 声明的一部分出现。

15.6.4 运行时语义:InstantiateAsyncGeneratorFunctionExpression

语法制导操作 InstantiateAsyncGeneratorFunctionExpression 接受可选参数 name(一个 属性键私有名称),并返回一个 ECMAScript 函数对象。它按以下产生式分段定义:

AsyncGeneratorExpression : async function * ( FormalParameters ) { AsyncGeneratorBody }
  1. 如果 name 不存在,设置 name""
  2. env运行执行上下文 的 LexicalEnvironment。
  3. privateEnv运行执行上下文 的 PrivateEnvironment。
  4. sourceTextAsyncGeneratorExpression 匹配的源文本
  5. closureOrdinaryFunctionCreate(%AsyncGeneratorFunction.prototype%, sourceText, FormalParameters, AsyncGeneratorBody, non-lexical-this, env, privateEnv)。
  6. 执行 SetFunctionName(closure, name)。
  7. prototypeOrdinaryObjectCreate(%AsyncGeneratorPrototype%)。
  8. 执行 ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  9. 返回 closure
AsyncGeneratorExpression : async function * BindingIdentifier ( FormalParameters ) { AsyncGeneratorBody }
  1. 断言name 不存在。
  2. 设置 nameBindingIdentifierStringValue
  3. outerEnv运行执行上下文 的 LexicalEnvironment。
  4. funcEnvNewDeclarativeEnvironment(outerEnv)。
  5. 执行 ! funcEnv.CreateImmutableBinding(name, false)。
  6. privateEnv运行执行上下文 的 PrivateEnvironment。
  7. sourceTextAsyncGeneratorExpression 匹配的源文本
  8. closureOrdinaryFunctionCreate(%AsyncGeneratorFunction.prototype%, sourceText, FormalParameters, AsyncGeneratorBody, non-lexical-this, funcEnv, privateEnv)。
  9. 执行 SetFunctionName(closure, name)。
  10. prototypeOrdinaryObjectCreate(%AsyncGeneratorPrototype%)。
  11. 执行 ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  12. 执行 ! funcEnv.InitializeBinding(name, closure)。
  13. 返回 closure
注释

AsyncGeneratorExpression 中的 BindingIdentifier 可以从 AsyncGeneratorExpressionAsyncGeneratorBody 内部引用,以允许生成器代码递归调用自身。然而,与 AsyncGeneratorDeclaration 不同,AsyncGeneratorExpression 中的 BindingIdentifier 不能从包围 AsyncGeneratorExpression 的作用域中引用,也不会影响该作用域。

15.6.5 运行时语义: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 注释

类定义始终是 严格模式代码

15.7.1 静态语义:早期错误

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 静态语义:ClassElementKind

语法制导操作 ClassElementKind 不接受参数,返回 constructor-methodnon-constructor-methodempty。它按以下产生式分段定义:

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 静态语义:ConstructorMethod

语法制导操作 ConstructorMethod 不接受参数,返回一个 ClassElement 解析节点empty。它按以下产生式分段定义:

ClassElementList : ClassElement
  1. 如果 ClassElementClassElementKindconstructor-method,返回 ClassElement
  2. 返回 empty
ClassElementList : ClassElementList ClassElement
  1. headClassElementListConstructorMethod
  2. 如果 head 不是 empty,返回 head
  3. 如果 ClassElementClassElementKindconstructor-method,返回 ClassElement
  4. 返回 empty
注释

早期错误规则确保只有一个名为 "constructor" 的方法定义,并且它不是 访问器属性 或生成器定义。

15.7.4 静态语义:IsStatic

语法制导操作 IsStatic 不接受参数,返回一个布尔值。它按以下产生式分段定义:

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 静态语义:NonConstructorElements

语法制导操作 NonConstructorElements 不接受参数,返回一个 List of ClassElement 解析节点。它按以下产生式分段定义:

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 静态语义:PrototypePropertyNameList

语法制导操作 PrototypePropertyNameList 不接受参数,返回一个 List of 属性键。它按以下产生式分段定义:

ClassElementList : ClassElement
  1. propNameClassElementPropName
  2. 如果 propNameempty,返回一个新的空 List
  3. 如果 ClassElementIsStatictrue,返回一个新的空 List
  4. 返回 « propName »。
ClassElementList : ClassElementList ClassElement
  1. listClassElementListPrototypePropertyNameList
  2. propNameClassElementPropName
  3. 如果 propNameempty,返回 list
  4. 如果 ClassElementIsStatictrue,返回 list
  5. 返回 list 和 « propName » 的 列表连接

15.7.7 静态语义:AllPrivateIdentifiersValid

语法制导操作 AllPrivateIdentifiersValid 接受参数 names(一个 List of Strings),返回一个布尔值。

本规范中每个未在下面列出的语法产生式替代都隐含地具有以下 AllPrivateIdentifiersValid 的默认定义:

  1. 对于此 解析节点 的每个子节点 child,执行
    1. 如果 child 是非终结符的实例,则
      1. 如果 childAllPrivateIdentifiersValid 在参数 names 下是 false,返回 false
  2. 返回 true
MemberExpression : MemberExpression . PrivateIdentifier
  1. 如果 names 包含 PrivateIdentifierStringValue,则
    1. 返回 MemberExpressionAllPrivateIdentifiersValid 在参数 names 下的结果。
  2. 返回 false
CallExpression : CallExpression . PrivateIdentifier
  1. 如果 names 包含 PrivateIdentifierStringValue,则
    1. 返回 CallExpressionAllPrivateIdentifiersValid 在参数 names 下的结果。
  2. 返回 false
OptionalChain : ?. PrivateIdentifier
  1. 如果 names 包含 PrivateIdentifierStringValue,返回 true
  2. 返回 false
OptionalChain : OptionalChain . PrivateIdentifier
  1. 如果 names 包含 PrivateIdentifierStringValue,则
    1. 返回 OptionalChainAllPrivateIdentifiersValid 在参数 names 下的结果。
  2. 返回 false
ClassBody : ClassElementList
  1. newNamesnamesClassBodyPrivateBoundIdentifiers列表连接
  2. 返回 ClassElementListAllPrivateIdentifiersValid 在参数 newNames 下的结果。
RelationalExpression : PrivateIdentifier in ShiftExpression
  1. 如果 names 包含 PrivateIdentifierStringValue,则
    1. 返回 ShiftExpressionAllPrivateIdentifiersValid 在参数 names 下的结果。
  2. 返回 false

15.7.8 静态语义:PrivateBoundIdentifiers

语法制导操作 PrivateBoundIdentifiers 不接受参数,返回一个 List of Strings。它按以下产生式分段定义:

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 静态语义:ContainsArguments

语法制导操作 ContainsArguments 不接受参数,返回一个布尔值。

本规范中每个未在下面列出的语法产生式替代都隐含地具有以下 ContainsArguments 的默认定义:

  1. 对于此 解析节点 的每个子节点 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 运行时语义:ClassFieldDefinitionEvaluation

语法制导操作 ClassFieldDefinitionEvaluation 接受参数 homeObject(一个 Object),返回一个 正常完成包含 一个 ClassFieldDefinition Record 或一个 突然完成。它按以下产生式分段定义:

FieldDefinition : ClassElementName Initializeropt
  1. name 为 ? ClassElementNameEvaluation
  2. 如果 Initializer 存在,则
    1. formalParameterList 为产生式 FormalParameters : [empty] 的一个实例。
    2. env正在运行的执行上下文 的 LexicalEnvironment。
    3. privateEnv正在运行的执行上下文 的 PrivateEnvironment。
    4. sourceText 为空的 Unicode 代码点序列。
    5. initializerOrdinaryFunctionCreate(%Function.prototype%, sourceText, formalParameterList, Initializer, non-lexical-this, env, privateEnv)。
    6. 执行 MakeMethod(initializer, homeObject)。
    7. 设置 initializer.[[ClassFieldInitializerName]]name
  3. 否则,
    1. initializerempty
  4. 返回 ClassFieldDefinition Record { [[Name]]: name, [[Initializer]]: initializer }。
注释
initializer 创建的函数永远不能被 ECMAScript 代码直接访问。

15.7.11 运行时语义:ClassStaticBlockDefinitionEvaluation

语法制导操作 ClassStaticBlockDefinitionEvaluation 接受参数 homeObject(一个 Object),返回一个 ClassStaticBlockDefinition Record。它按以下产生式分段定义:

ClassStaticBlock : static { ClassStaticBlockBody }
  1. lex正在运行的执行上下文 的 LexicalEnvironment。
  2. privateEnv正在运行的执行上下文 的 PrivateEnvironment。
  3. sourceText 为空的 Unicode 代码点序列。
  4. formalParameters 为产生式 FormalParameters : [empty] 的一个实例。
  5. bodyFunctionOrdinaryFunctionCreate(%Function.prototype%, sourceText, formalParameters, ClassStaticBlockBody, non-lexical-this, lex, privateEnv)。
  6. 执行 MakeMethod(bodyFunction, homeObject)。
  7. 返回 ClassStaticBlockDefinition Record { [[BodyFunction]]: bodyFunction }。
注释
函数 bodyFunction 永远不能被 ECMAScript 代码直接访问。

15.7.12 运行时语义:EvaluateClassStaticBlockBody

语法制导操作 EvaluateClassStaticBlockBody 接受参数 functionObject(一个 ECMAScript 函数对象),返回一个 返回完成 或一个 抛出完成。它按以下产生式分段定义:

ClassStaticBlockBody : ClassStaticBlockStatementList
  1. 断言functionObject 是由 ClassStaticBlockDefinitionEvaluation 步骤 5 创建的合成函数。
  2. 执行 ! FunctionDeclarationInstantiation(functionObject, « »)。
  3. 执行 ? ClassStaticBlockStatementListEvaluation
  4. 返回 ReturnCompletion(undefined)。

15.7.13 运行时语义:ClassElementEvaluation

语法制导操作 ClassElementEvaluation 接受参数 object(一个 Object),返回一个 正常完成包含 一个 ClassFieldDefinition Record、一个 ClassStaticBlockDefinition Record、一个 PrivateElementunused,或一个 突然完成。它按以下产生式分段定义:

ClassElement : FieldDefinition ; static FieldDefinition ;
  1. 返回 ? FieldDefinitionClassFieldDefinitionEvaluation,参数为 object
ClassElement : MethodDefinition static MethodDefinition
  1. 返回 ? MethodDefinitionMethodDefinitionEvaluation,参数为 objectfalse
ClassElement : ClassStaticBlock
  1. 返回 ClassStaticBlockClassStaticBlockDefinitionEvaluation,参数为 object
ClassElement : ;
  1. 返回 unused

15.7.14 运行时语义:ClassDefinitionEvaluation

语法制导操作 ClassDefinitionEvaluation 接受参数 classBinding(一个 String 或 undefined)和 className(一个 属性键 或一个 Private Name),返回一个 正常完成包含 一个 函数对象 或一个 突然完成

注释

为了便于规范,私有方法和访问器与私有字段一起包含在类实例的 [[PrivateElements]] 槽中。但是,任何给定对象要么拥有给定类定义的所有私有方法和访问器,要么一个都没有。这个特性的设计使得实现可以选择使用不需要单独跟踪每个方法或访问器的策略来实现私有方法和访问器。

例如,实现可以直接将实例私有方法与其相应的 Private Name 关联,并为每个对象跟踪哪些类 构造函数 曾以该对象作为其 this 值运行过。然后在对象上查找实例私有方法就包括检查定义该方法的类 构造函数 是否已被用于初始化该对象,然后返回与 Private Name 关联的方法。

这与私有字段不同:因为字段初始化器可能在类实例化期间抛出异常,单个对象可能拥有给定类的私有字段的某个真子集,因此私有字段通常必须单独跟踪。

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

ClassTail : ClassHeritageopt { ClassBodyopt }
  1. env正在运行的执行上下文 的 LexicalEnvironment。
  2. classEnvNewDeclarativeEnvironment(env)。
  3. 如果 classBinding 不是 undefined,则
    1. 执行 ! classEnv.CreateImmutableBinding(classBinding, true)。
  4. outerPrivateEnvironment正在运行的执行上下文 的 PrivateEnvironment。
  5. classPrivateEnvironmentNewPrivateEnvironment(outerPrivateEnvironment)。
  6. 如果 ClassBody 存在,则
    1. 对于 ClassBodyPrivateBoundIdentifiers 中的每个 String dn,执行
      1. 如果 classPrivateEnvironment.[[Names]] 包含一个 Private Name pn 使得 pn.[[Description]]dn,则
        1. 断言:这只可能发生在 getter/setter 对。
      2. 否则,
        1. name 为一个新的 Private Name,其 [[Description]]dn
        2. name 追加到 classPrivateEnvironment.[[Names]]
  7. 如果 ClassHeritage 不存在,则
    1. protoParent%Object.prototype%
    2. constructorParent%Function.prototype%
  8. 否则,
    1. 设置 正在运行的执行上下文 的 LexicalEnvironment 为 classEnv
    2. 注释:当求值 ClassHeritage 时,正在运行的执行上下文 的 PrivateEnvironment 是 outerPrivateEnvironment
    3. superclassRefCompletion(ClassHeritageEvaluation)。
    4. 设置 正在运行的执行上下文 的 LexicalEnvironment 为 env
    5. superclass 为 ? GetValue(? superclassRef)。
    6. 如果 superclassnull,则
      1. protoParentnull
      2. constructorParent%Function.prototype%
    7. 否则,如果 IsConstructor(superclass) 是 false,则
      1. 抛出 TypeError 异常。
    8. 否则,
      1. protoParent 为 ? Get(superclass, "prototype")。
      2. 如果 protoParent 不是对象protoParent 不是 null,抛出 TypeError 异常。
      3. constructorParentsuperclass
  9. protoOrdinaryObjectCreate(protoParent)。
  10. 如果 ClassBody 不存在,令 constructorempty
  11. 否则,令 constructorClassBodyConstructorMethod
  12. 设置 正在运行的执行上下文 的 LexicalEnvironment 为 classEnv
  13. 设置 正在运行的执行上下文 的 PrivateEnvironment 为 classPrivateEnvironment
  14. 如果 constructorempty,则
    1. defaultConstructor 为一个新的 抽象闭包,不接受参数,不捕获任何值,调用时执行以下步骤:
      1. args 为通过 [[Call]][[Construct]] 传递给此函数的参数 List
      2. 如果 NewTarget 是 undefined,抛出 TypeError 异常。
      3. F活跃函数对象
      4. 如果 F.[[ConstructorKind]]derived,则
        1. 注释:此分支的行为类似于 constructor(...args) { super(...args); }。最显著的区别是,虽然前述 ECMAScript 源文本 会可观察地调用 %Array.prototype% 上的 %Symbol.iterator% 方法,但此函数不会。
        2. func 为 ! F.[[GetPrototypeOf]]()。
        3. 如果 IsConstructor(func) 是 false,抛出 TypeError 异常。
        4. result 为 ? Construct(func, args, NewTarget)。
      5. 否则,
        1. 注释:此分支的行为类似于 constructor() {}
        2. result 为 ? OrdinaryCreateFromConstructor(NewTarget, "%Object.prototype%")。
      6. 执行 ? InitializeInstanceElements(result, F)。
      7. 返回 result
    2. FCreateBuiltinFunction(defaultConstructor, 0, className, « [[ConstructorKind]], [[SourceText]] », 当前 Realm Record, constructorParent)。
  15. 否则,
    1. constructorInfo 为 ! constructorDefineMethod,参数为 protoconstructorParent
    2. FconstructorInfo.[[Closure]]
    3. 执行 MakeClassConstructor(F)。
    4. 执行 SetFunctionName(F, className)。
  16. 执行 MakeConstructor(F, false, proto)。
  17. 如果 ClassHeritage 存在,设置 F.[[ConstructorKind]]derived
  18. 执行 ! DefineMethodProperty(proto, "constructor", F, false)。
  19. 如果 ClassBody 不存在,令 elements 为一个新的空 List
  20. 否则,令 elementsClassBodyNonConstructorElements
  21. instancePrivateMethods 为一个新的空 List
  22. staticPrivateMethods 为一个新的空 List
  23. instanceFields 为一个新的空 List
  24. staticElements 为一个新的空 List
  25. 对于 elements 中的每个 ClassElement e,执行
    1. 如果 eIsStaticfalse,则
      1. elementCompletion(eClassElementEvaluation,参数为 proto)。
    2. 否则,
      1. elementCompletion(eClassElementEvaluation,参数为 F)。
    3. 如果 element 是一个 突然完成,则
      1. 设置 正在运行的执行上下文 的 LexicalEnvironment 为 env
      2. 设置 正在运行的执行上下文 的 PrivateEnvironment 为 outerPrivateEnvironment
      3. 返回 ? element
    4. 设置 element 为 ! element
    5. 如果 element 是一个 PrivateElement,则
      1. 断言element.[[Kind]]methodaccessor
      2. 如果 eIsStaticfalse,令 containerinstancePrivateMethods
      3. 否则,令 containerstaticPrivateMethods
      4. 如果 container 包含一个 PrivateElement pe 使得 pe.[[Key]]element.[[Key]],则
        1. 断言element.[[Kind]]pe.[[Kind]] 都是 accessor
        2. 如果 element.[[Get]]undefined,则
          1. combinedPrivateElement { [[Key]]: element.[[Key]], [[Kind]]: accessor, [[Get]]: pe.[[Get]], [[Set]]: element.[[Set]] }。
        3. 否则,
          1. combinedPrivateElement { [[Key]]: element.[[Key]], [[Kind]]: accessor, [[Get]]: element.[[Get]], [[Set]]: pe.[[Set]] }。
        4. container 中将 pe 替换为 combined
      5. 否则,
        1. element 追加到 container
    6. 否则,如果 element 是一个 ClassFieldDefinition Record,则
      1. 如果 eIsStaticfalse,将 element 追加到 instanceFields
      2. 否则,将 element 追加到 staticElements
    7. 否则,如果 element 是一个 ClassStaticBlockDefinition Record,则
      1. element 追加到 staticElements
  26. 设置 正在运行的执行上下文 的 LexicalEnvironment 为 env
  27. 如果 classBinding 不是 undefined,则
    1. 执行 ! classEnv.InitializeBinding(classBinding, F)。
  28. 设置 F.[[PrivateMethods]]instancePrivateMethods
  29. 设置 F.[[Fields]]instanceFields
  30. 对于 staticPrivateMethods 中的每个 PrivateElement method,执行
    1. 执行 ! PrivateMethodOrAccessorAdd(F, method)。
  31. 对于 staticElements 中的每个元素 elementRecord,执行
    1. 如果 elementRecord 是一个 ClassFieldDefinition Record,则
      1. resultCompletion(DefineField(F, elementRecord))。
    2. 否则,
      1. 断言elementRecord 是一个 ClassStaticBlockDefinition Record
      2. resultCompletion(Call(elementRecord.[[BodyFunction]], F))。
    3. 如果 result 是一个 突然完成,则
      1. 设置 正在运行的执行上下文 的 PrivateEnvironment 为 outerPrivateEnvironment
      2. 返回 ? result
  32. 设置 正在运行的执行上下文 的 PrivateEnvironment 为 outerPrivateEnvironment
  33. 返回 F

15.7.15 运行时语义:BindingClassDeclarationEvaluation

语法制导操作 BindingClassDeclarationEvaluation 不接受参数,返回一个 正常完成包含 一个 函数对象 或一个 突然完成。它按以下产生式分段定义:

ClassDeclaration : class BindingIdentifier ClassTail
  1. classNameBindingIdentifierStringValue
  2. value 为 ? ClassTailClassDefinitionEvaluation,参数为 classNameclassName
  3. 设置 value.[[SourceText]]ClassDeclaration 匹配的源文本
  4. env正在运行的执行上下文 的 LexicalEnvironment。
  5. 执行 ? InitializeBoundName(className, value, env)。
  6. 返回 value
ClassDeclaration : class ClassTail
  1. value 为 ? ClassTailClassDefinitionEvaluation,参数为 undefined"default"
  2. 设置 value.[[SourceText]]ClassDeclaration 匹配的源文本
  3. 返回 value
注释

ClassDeclaration : class ClassTail 只作为 ExportDeclaration 的一部分出现,其绑定的建立作为该产生式的求值操作的一部分处理。参见 16.2.3.7

15.7.16 运行时语义:Evaluation

ClassDeclaration : class BindingIdentifier ClassTail
  1. 执行 ? 此 ClassDeclarationBindingClassDeclarationEvaluation
  2. 返回 empty
注释

ClassDeclaration : class ClassTail 只作为 ExportDeclaration 的一部分出现,从不直接求值。

ClassExpression : class ClassTail
  1. value 为 ? ClassTailClassDefinitionEvaluation,参数为 undefined""
  2. 设置 value.[[SourceText]]ClassExpression 匹配的源文本
  3. 返回 value
ClassExpression : class BindingIdentifier ClassTail
  1. classNameBindingIdentifierStringValue
  2. value 为 ? ClassTailClassDefinitionEvaluation,参数为 classNameclassName
  3. 设置 value.[[SourceText]]ClassExpression 匹配的源文本
  4. 返回 value
ClassElementName : PrivateIdentifier
  1. privateIdentifierPrivateIdentifierStringValue
  2. privateEnvRec正在运行的执行上下文 的 PrivateEnvironment。
  3. namesprivateEnvRec.[[Names]]
  4. 断言names 中恰好有一个元素是 Private Name,其 [[Description]]privateIdentifier
  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] 注释 1

当存在 [Await] 参数时,await 被解析为 AwaitExpression关键字[Await] 参数在以下上下文的顶层存在,尽管根据非终结符(如 FunctionBody),在某些上下文中该参数可能不存在:

Script 是语法目标符号时,当不存在 [Await] 参数时,await 可能被解析为标识符。这包括以下上下文:

注释 2

YieldExpression 不同,省略 AwaitExpression 的操作数是语法错误。你必须等待某些东西。

15.8.1 静态语义:早期错误

AsyncMethod : async ClassElementName ( UniqueFormalParameters ) { AsyncFunctionBody } AsyncFunctionDeclaration : async function BindingIdentifier ( FormalParameters ) { AsyncFunctionBody } async function ( FormalParameters ) { AsyncFunctionBody } AsyncFunctionExpression : async function BindingIdentifieropt ( FormalParameters ) { AsyncFunctionBody }

15.8.2 运行时语义:InstantiateAsyncFunctionObject

语法制导操作 InstantiateAsyncFunctionObject 接受参数 env(一个 Environment Record)和 privateEnv(一个 PrivateEnvironment Recordnull),返回一个 ECMAScript 函数对象。它按以下产生式分段定义:

AsyncFunctionDeclaration : async function BindingIdentifier ( FormalParameters ) { AsyncFunctionBody }
  1. nameBindingIdentifierStringValue
  2. sourceTextAsyncFunctionDeclaration 匹配的源文本
  3. FOrdinaryFunctionCreate(%AsyncFunction.prototype%, sourceText, FormalParameters, AsyncFunctionBody, non-lexical-this, env, privateEnv)。
  4. 执行 SetFunctionName(F, name)。
  5. 返回 F
AsyncFunctionDeclaration : async function ( FormalParameters ) { AsyncFunctionBody }
  1. sourceTextAsyncFunctionDeclaration 匹配的源文本
  2. FOrdinaryFunctionCreate(%AsyncFunction.prototype%, sourceText, FormalParameters, AsyncFunctionBody, non-lexical-this, env, privateEnv)。
  3. 执行 SetFunctionName(F, "default")。
  4. 返回 F

15.8.3 运行时语义:InstantiateAsyncFunctionExpression

语法制导操作 InstantiateAsyncFunctionExpression 接受可选参数 name(一个 属性键 或一个 Private Name),返回一个 ECMAScript 函数对象。它按以下产生式分段定义:

AsyncFunctionExpression : async function ( FormalParameters ) { AsyncFunctionBody }
  1. 如果 name 不存在,设置 name""
  2. env正在运行的执行上下文 的 LexicalEnvironment。
  3. privateEnv正在运行的执行上下文 的 PrivateEnvironment。
  4. sourceTextAsyncFunctionExpression 匹配的源文本
  5. closureOrdinaryFunctionCreate(%AsyncFunction.prototype%, sourceText, FormalParameters, AsyncFunctionBody, non-lexical-this, env, privateEnv)。
  6. 执行 SetFunctionName(closure, name)。
  7. 返回 closure
AsyncFunctionExpression : async function BindingIdentifier ( FormalParameters ) { AsyncFunctionBody }
  1. 断言name 不存在。
  2. 设置 nameBindingIdentifierStringValue
  3. outerEnv正在运行的执行上下文 的 LexicalEnvironment。
  4. funcEnvNewDeclarativeEnvironment(outerEnv)。
  5. 执行 ! funcEnv.CreateImmutableBinding(name, false)。
  6. privateEnv正在运行的执行上下文 的 PrivateEnvironment。
  7. sourceTextAsyncFunctionExpression 匹配的源文本
  8. closureOrdinaryFunctionCreate(%AsyncFunction.prototype%, sourceText, FormalParameters, AsyncFunctionBody, non-lexical-this, funcEnv, privateEnv)。
  9. 执行 SetFunctionName(closure, name)。
  10. 执行 ! funcEnv.InitializeBinding(name, closure)。
  11. 返回 closure
注释

AsyncFunctionExpression 中的 BindingIdentifier 可以从 AsyncFunctionExpressionAsyncFunctionBody 内部引用,以允许函数递归调用自身。但是,与 FunctionDeclaration 不同,AsyncFunctionExpression 中的 BindingIdentifier 不能从包围 AsyncFunctionExpression 的作用域中引用,也不影响该作用域。

15.8.4 运行时语义:EvaluateAsyncFunctionBody

语法制导操作 EvaluateAsyncFunctionBody 接受参数 functionObject(一个 ECMAScript 函数对象)和 argumentsList(一个 List of ECMAScript 语言值),返回一个 返回完成。它按以下产生式分段定义:

AsyncFunctionBody : FunctionBody
  1. promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  2. completionCompletion(FunctionDeclarationInstantiation(functionObject, argumentsList))。
  3. 如果 completion 是一个 突然完成,则
    1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « completion.[[Value]] »)。
  4. 否则,
    1. 执行 AsyncFunctionStart(promiseCapability, FunctionBody)。
  5. 返回 ReturnCompletion(promiseCapability.[[Promise]])。

15.8.5 运行时语义:Evaluation

AsyncFunctionExpression : async function BindingIdentifieropt ( FormalParameters ) { AsyncFunctionBody }
  1. 返回 AsyncFunctionExpressionInstantiateAsyncFunctionExpression
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 静态语义:早期错误

AsyncArrowFunction : async AsyncArrowBindingIdentifier => AsyncConciseBody AsyncArrowFunction : CoverCallExpressionAndAsyncArrowHead => AsyncConciseBody

15.9.2 静态语义:AsyncConciseBodyContainsUseStrict

语法制导操作 AsyncConciseBodyContainsUseStrict 不接受参数,返回一个 Boolean。它按以下产生式分段定义:

AsyncConciseBody : ExpressionBody
  1. 返回 false
AsyncConciseBody : { AsyncFunctionBody }
  1. 返回 AsyncFunctionBodyFunctionBodyContainsUseStrict

15.9.3 运行时语义:EvaluateAsyncConciseBody

语法制导操作 EvaluateAsyncConciseBody 接受参数 functionObject(一个 ECMAScript 函数对象)和 argumentsList(一个 List of ECMAScript 语言值),返回一个 返回完成。它按以下产生式分段定义:

AsyncConciseBody : ExpressionBody
  1. promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  2. completionCompletion(FunctionDeclarationInstantiation(functionObject, argumentsList))。
  3. 如果 completion 是一个 突然完成,则
    1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « completion.[[Value]] »)。
  4. 否则,
    1. 执行 AsyncFunctionStart(promiseCapability, ExpressionBody)。
  5. 返回 ReturnCompletion(promiseCapability.[[Promise]])。

15.9.4 运行时语义:InstantiateAsyncArrowFunctionExpression

语法制导操作 InstantiateAsyncArrowFunctionExpression 接受可选参数 name(一个 属性键 或一个 Private Name),返回一个 ECMAScript 函数对象。它按以下产生式分段定义:

AsyncArrowFunction : async AsyncArrowBindingIdentifier => AsyncConciseBody
  1. 如果 name 不存在,设置 name""
  2. env正在运行的执行上下文 的 LexicalEnvironment。
  3. privateEnv正在运行的执行上下文 的 PrivateEnvironment。
  4. sourceTextAsyncArrowFunction 匹配的源文本
  5. parametersAsyncArrowBindingIdentifier
  6. closureOrdinaryFunctionCreate(%AsyncFunction.prototype%, sourceText, parameters, AsyncConciseBody, lexical-this, env, privateEnv)。
  7. 执行 SetFunctionName(closure, name)。
  8. 返回 closure
AsyncArrowFunction : CoverCallExpressionAndAsyncArrowHead => AsyncConciseBody
  1. 如果 name 不存在,设置 name""
  2. env正在运行的执行上下文 的 LexicalEnvironment。
  3. privateEnv正在运行的执行上下文 的 PrivateEnvironment。
  4. sourceTextAsyncArrowFunction 匹配的源文本
  5. head 为被 CoverCallExpressionAndAsyncArrowHead 覆盖AsyncArrowHead
  6. parametersheadArrowFormalParameters
  7. closureOrdinaryFunctionCreate(%AsyncFunction.prototype%, sourceText, parameters, AsyncConciseBody, lexical-this, env, privateEnv)。
  8. 执行 SetFunctionName(closure, name)。
  9. 返回 closure

15.9.5 运行时语义:Evaluation

AsyncArrowFunction : async AsyncArrowBindingIdentifier => AsyncConciseBody CoverCallExpressionAndAsyncArrowHead => AsyncConciseBody
  1. 返回 AsyncArrowFunctionInstantiateAsyncArrowFunctionExpression

15.10 尾位置调用

15.10.1 静态语义:IsInTailPosition ( call )

抽象操作 IsInTailPosition 接受参数 call(一个 CallExpression 解析节点、一个 MemberExpression 解析节点,或一个 OptionalChain 解析节点),返回一个 Boolean。调用时执行以下步骤:

  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. 返回 body 以参数 call 进行的 HasCallInTailPosition 的结果。
注释

尾位置调用仅在 严格模式代码 中定义,因为有一个常见的非标准语言扩展(参见 10.2.4)可以观察调用者上下文链。

15.10.2 静态语义:HasCallInTailPosition

语法制导操作 HasCallInTailPosition 接受参数 call(一个 CallExpression 解析节点、一个 MemberExpression 解析节点,或一个 OptionalChain 解析节点),返回一个 Boolean。

注释 1

call 是一个 解析节点,表示特定范围的源文本。当以下算法将 call 与另一个 解析节点 进行比较时,这是测试它们是否表示相同的源文本。

注释 2

紧接着返回调用结果的 GetValue 的潜在尾位置调用也是可能的尾位置调用。函数调用不能返回 Reference Record,因此这样的 GetValue 操作将总是返回与实际函数调用结果相同的值。

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

StatementList : StatementList StatementListItem
  1. hasStatementList 以参数 call 进行的 HasCallInTailPosition
  2. 如果 hastrue,返回 true
  3. 返回 StatementListItem 以参数 call 进行的 HasCallInTailPosition
FunctionStatementList : [empty] StatementListItem : Declaration Statement : VariableStatement EmptyStatement ExpressionStatement ContinueStatement BreakStatement ThrowStatement DebuggerStatement Block : { } ReturnStatement : return ; LabelledItem : FunctionDeclaration ForInOfStatement : for ( LeftHandSideExpression of AssignmentExpression ) Statement for ( var ForBinding of AssignmentExpression ) Statement for ( ForDeclaration of AssignmentExpression ) Statement CaseBlock : { }
  1. 返回 false
IfStatement : if ( Expression ) Statement else Statement
  1. has 为第一个 Statement 以参数 call 进行的 HasCallInTailPosition
  2. 如果 hastrue,返回 true
  3. 返回第二个 Statement 以参数 call 进行的 HasCallInTailPosition
IfStatement : if ( Expression ) Statement DoWhileStatement : do Statement while ( Expression ) ; WhileStatement : while ( Expression ) Statement ForStatement : for ( Expressionopt ; Expressionopt ; Expressionopt ) Statement for ( var VariableDeclarationList ; Expressionopt ; Expressionopt ) Statement for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement ForInOfStatement : for ( LeftHandSideExpression in Expression ) Statement for ( var ForBinding in Expression ) Statement for ( ForDeclaration in Expression ) Statement WithStatement : with ( Expression ) Statement
  1. 返回 Statement 以参数 call 进行的 HasCallInTailPosition
LabelledStatement : LabelIdentifier : LabelledItem
  1. 返回 LabelledItem 以参数 call 进行的 HasCallInTailPosition
ReturnStatement : return Expression ;
  1. 返回 Expression 以参数 call 进行的 HasCallInTailPosition
SwitchStatement : switch ( Expression ) CaseBlock
  1. 返回 CaseBlock 以参数 call 进行的 HasCallInTailPosition
CaseBlock : { CaseClausesopt DefaultClause CaseClausesopt }
  1. hasfalse
  2. 如果存在第一个 CaseClauses,将 has 设置为第一个 CaseClauses 以参数 call 进行的 HasCallInTailPosition
  3. 如果 hastrue,返回 true
  4. has 设置为 DefaultClause 以参数 call 进行的 HasCallInTailPosition
  5. 如果 hastrue,返回 true
  6. 如果存在第二个 CaseClauses,将 has 设置为第二个 CaseClauses 以参数 call 进行的 HasCallInTailPosition
  7. 返回 has
CaseClauses : CaseClauses CaseClause
  1. hasCaseClauses 以参数 call 进行的 HasCallInTailPosition
  2. 如果 hastrue,返回 true
  3. 返回 CaseClause 以参数 call 进行的 HasCallInTailPosition
CaseClause : case Expression : StatementListopt DefaultClause : default : StatementListopt
  1. 如果存在 StatementList,返回 StatementList 以参数 call 进行的 HasCallInTailPosition
  2. 返回 false
TryStatement : try Block Catch
  1. 返回 Catch 以参数 call 进行的 HasCallInTailPosition
TryStatement : try Block Finally try Block Catch Finally
  1. 返回 Finally 以参数 call 进行的 HasCallInTailPosition
Catch : catch ( CatchParameter ) Block
  1. 返回 Block 以参数 call 进行的 HasCallInTailPosition
AssignmentExpression : YieldExpression ArrowFunction AsyncArrowFunction LeftHandSideExpression = AssignmentExpression LeftHandSideExpression AssignmentOperator AssignmentExpression LeftHandSideExpression &&= AssignmentExpression LeftHandSideExpression ||= AssignmentExpression LeftHandSideExpression ??= AssignmentExpression BitwiseANDExpression : BitwiseANDExpression & EqualityExpression BitwiseXORExpression : BitwiseXORExpression ^ BitwiseANDExpression BitwiseORExpression : BitwiseORExpression | BitwiseXORExpression EqualityExpression : EqualityExpression == RelationalExpression EqualityExpression != RelationalExpression EqualityExpression === RelationalExpression EqualityExpression !== RelationalExpression RelationalExpression : RelationalExpression < ShiftExpression RelationalExpression > ShiftExpression RelationalExpression <= ShiftExpression RelationalExpression >= ShiftExpression RelationalExpression instanceof ShiftExpression RelationalExpression in ShiftExpression PrivateIdentifier in ShiftExpression ShiftExpression : ShiftExpression << AdditiveExpression ShiftExpression >> AdditiveExpression ShiftExpression >>> AdditiveExpression AdditiveExpression : AdditiveExpression + MultiplicativeExpression AdditiveExpression - MultiplicativeExpression MultiplicativeExpression : MultiplicativeExpression MultiplicativeOperator ExponentiationExpression ExponentiationExpression : UpdateExpression ** ExponentiationExpression UpdateExpression : LeftHandSideExpression ++ LeftHandSideExpression -- ++ UnaryExpression -- UnaryExpression UnaryExpression : delete UnaryExpression void UnaryExpression typeof UnaryExpression + UnaryExpression - UnaryExpression ~ UnaryExpression ! UnaryExpression AwaitExpression 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. 返回 AssignmentExpression 以参数 call 进行的 HasCallInTailPosition
ConditionalExpression : ShortCircuitExpression ? AssignmentExpression : AssignmentExpression
  1. has 为第一个 AssignmentExpression 以参数 call 进行的 HasCallInTailPosition
  2. 如果 hastrue,返回 true
  3. 返回第二个 AssignmentExpression 以参数 call 进行的 HasCallInTailPosition
LogicalANDExpression : LogicalANDExpression && BitwiseORExpression
  1. 返回 BitwiseORExpression 以参数 call 进行的 HasCallInTailPosition
LogicalORExpression : LogicalORExpression || LogicalANDExpression
  1. 返回 LogicalANDExpression 以参数 call 进行的 HasCallInTailPosition
CoalesceExpression : CoalesceExpressionHead ?? BitwiseORExpression
  1. 返回 BitwiseORExpression 以参数 call 进行的 HasCallInTailPosition
CallExpression : CoverCallExpressionAndAsyncArrowHead CallExpression Arguments CallExpression TemplateLiteral
  1. 如果此 CallExpressioncall,返回 true
  2. 返回 false
OptionalExpression : MemberExpression OptionalChain CallExpression OptionalChain OptionalExpression OptionalChain
  1. 返回 OptionalChain 以参数 call 进行的 HasCallInTailPosition
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. 返回 expr 以参数 call 进行的 HasCallInTailPosition
ParenthesizedExpression : ( Expression )
  1. 返回 Expression 以参数 call 进行的 HasCallInTailPosition

15.10.3 PrepareForTailCall ( )

抽象操作 PrepareForTailCall 不接受参数,返回 unused。调用时执行以下步骤:

  1. 断言:当前 执行上下文 随后不会用于任何 ECMAScript 代码或内置函数的求值。在调用此抽象操作之后对 Call 的调用将在执行任何此类求值之前创建并推入一个新的 执行上下文
  2. 丢弃与当前 执行上下文 关联的所有资源。
  3. 返回 unused

尾位置调用必须在调用目标函数之前释放与当前执行函数 执行上下文 关联的任何瞬态内部资源,或重用这些资源来支持目标函数。

注释

例如,尾位置调用应该仅按目标函数的激活记录大小超出调用函数激活记录大小的量来增长实现的激活记录栈。如果目标函数的激活记录更小,则栈的总大小应该减少。

16 ECMAScript 语言:脚本和模块

16.1 脚本

语法

Script : ScriptBodyopt ScriptBody : StatementList[~Yield, ~Await, ~Return]

16.1.1 静态语义:早期错误

Script : ScriptBody ScriptBody : StatementList

16.1.2 静态语义:ScriptIsStrict

语法制导操作 ScriptIsStrict 不接受参数,返回一个 Boolean。它按以下产生式分段定义:

Script : ScriptBodyopt
  1. 如果 ScriptBody 存在且 ScriptBody指令序言 包含一个 Use Strict 指令,返回 true;否则,返回 false

16.1.3 运行时语义:Evaluation

Script : [empty]
  1. 返回 undefined

16.1.4 脚本记录

脚本记录 封装了关于被求值脚本的信息。每个脚本记录包含 表 39 中列出的字段。

表 39:脚本记录 字段
字段名 值类型 含义
[[Realm]] 一个 Realm Record 创建此脚本的 realm
[[ECMAScriptCode]] 一个 Script 解析节点 解析此脚本源文本的结果。
[[LoadedModules]] 一个 LoadedModuleRequest RecordsList 从此脚本导入的说明符字符串到已解析的 Module Record 的映射。该列表不包含两个不同的 Records r1r2,使得 ModuleRequestsEqual(r1, r2) 是 true
[[HostDefined]] 任何东西(默认值是 empty 为需要将附加信息与脚本关联的 宿主环境 预留的字段。

16.1.5 ParseScript ( sourceText, realm, hostDefined )

抽象操作 ParseScript 接受参数 sourceTextECMAScript 源文本)、realm(一个 Realm Record)和 hostDefined(任何东西),返回一个 脚本记录 或一个非空的 SyntaxError 对象 List。它基于将 sourceText 解析为 Script 的结果创建一个 脚本记录。调用时执行以下步骤:

  1. scriptParseText(sourceText, Script)。
  2. 如果 script 是一个错误的 List,返回 script
  3. 返回 脚本记录 { [[Realm]]: realm, [[ECMAScriptCode]]: script, [[LoadedModules]]: « », [[HostDefined]]: hostDefined }。
注释

实现可以在对该脚本源文本执行 ParseScript 之前解析脚本源文本并分析其早期错误条件。但是,任何错误的报告必须推迟到本规范实际对该源文本执行 ParseScript 的时候。

16.1.6 ScriptEvaluation ( scriptRecord )

抽象操作 ScriptEvaluation 接受参数 scriptRecord(一个 脚本记录),返回包含一个 ECMAScript 语言值正常完成 或一个 突然完成。调用时执行以下步骤:

  1. globalEnvscriptRecord.[[Realm]].[[GlobalEnv]]
  2. scriptContext 为一个新的 ECMAScript 代码执行上下文
  3. 设置 scriptContext 的 Function 为 null
  4. 设置 scriptContextRealmscriptRecord.[[Realm]]
  5. 设置 scriptContext 的 ScriptOrModule 为 scriptRecord
  6. 设置 scriptContext 的 VariableEnvironment 为 globalEnv
  7. 设置 scriptContext 的 LexicalEnvironment 为 globalEnv
  8. 设置 scriptContext 的 PrivateEnvironment 为 null
  9. 挂起 正在运行的执行上下文
  10. scriptContext 推入 执行上下文栈scriptContext 现在是 正在运行的执行上下文
  11. scriptscriptRecord.[[ECMAScriptCode]]
  12. resultCompletion(GlobalDeclarationInstantiation(script, globalEnv))。
  13. 如果 result 是一个 正常完成,则
    1. 设置 resultCompletion(scriptEvaluation)。
    2. 如果 result 是一个 正常完成result.[[Value]]empty,则
      1. 设置 resultNormalCompletion(undefined)。
  14. 挂起 scriptContext 并将其从 执行上下文栈 中移除。
  15. 断言执行上下文栈 不为空。
  16. 恢复现在位于 执行上下文栈 顶部的上下文作为 正在运行的执行上下文
  17. 返回 ? result

16.1.7 GlobalDeclarationInstantiation ( script, env )

抽象操作 GlobalDeclarationInstantiation 接受参数 script(一个 Script 解析节点)和 env(一个 全局环境记录),返回包含 unused正常完成 或一个 抛出完成script 是正在为其建立 执行上下文Scriptenv 是要在其中创建绑定的全局环境。

注释 1

当为求值脚本建立 执行上下文 时,声明在当前全局环境中实例化。代码中声明的每个全局绑定都被实例化。

调用时执行以下步骤:

  1. lexNamesscriptLexicallyDeclaredNames
  2. varNamesscriptVarDeclaredNames
  3. 对于 lexNames 的每个元素 name,执行
    1. 如果 HasLexicalDeclaration(env, name) 是 true,抛出一个 SyntaxError 异常。
    2. hasRestrictedGlobal 为 ? HasRestrictedGlobalProperty(env, name)。
    3. 注释:全局 varfunction 绑定(除了由非严格 直接 eval 引入的那些)是不可配置的,因此是受限制的全局属性。
    4. 如果 hasRestrictedGlobaltrue,抛出一个 SyntaxError 异常。
  4. 对于 varNames 的每个元素 name,执行
    1. 如果 HasLexicalDeclaration(env, name) 是 true,抛出一个 SyntaxError 异常。
  5. varDeclarationsscriptVarScopedDeclarations
  6. functionsToInitialize 为一个新的空 List
  7. declaredFunctionNames 为一个新的空 List
  8. 对于 varDeclarations 的每个元素 d,按反向 List 顺序,执行
    1. 如果 d 不是 VariableDeclarationForBindingBindingIdentifier,则
      1. 断言dFunctionDeclarationGeneratorDeclarationAsyncFunctionDeclarationAsyncGeneratorDeclaration
      2. 注释:如果同一个名称有多个函数声明,使用最后的声明。
      3. fndBoundNames 的唯一元素。
      4. 如果 declaredFunctionNames 不包含 fn,则
        1. fnDefinable 为 ? CanDeclareGlobalFunction(env, fn)。
        2. 如果 fnDefinablefalse,抛出一个 TypeError 异常。
        3. fn 追加到 declaredFunctionNames
        4. d 作为 functionsToInitialize 的第一个元素插入。
  9. declaredVarNames 为一个新的空 List
  10. 对于 varDeclarations 的每个元素 d,执行
    1. 如果 dVariableDeclarationForBindingBindingIdentifier,则
      1. 对于 dBoundNames 的每个字符串 vn,执行
        1. 如果 declaredFunctionNames 不包含 vn,则
          1. vnDefinable 为 ? CanDeclareGlobalVar(env, vn)。
          2. 如果 vnDefinablefalse,抛出一个 TypeError 异常。
          3. 如果 declaredVarNames 不包含 vn,则
            1. vn 追加到 declaredVarNames
  11. 注释:如果 全局对象 是一个 普通对象,则在此算法步骤之后不会发生异常终止。但是,如果 全局对象 是一个 Proxy 异质对象,它可能表现出在以下某些步骤中导致异常终止的行为。
  12. 注释:附录 B.3.2.2 在此处添加了附加步骤。
  13. lexDeclarationsscriptLexicallyScopedDeclarations
  14. privateEnvnull
  15. 对于 lexDeclarations 的每个元素 d,执行
    1. 注释:词法声明的名称仅在此处实例化但不初始化。
    2. 对于 dBoundNames 的每个元素 dn,执行
      1. 如果 dIsConstantDeclarationtrue,则
        1. 执行 ? env.CreateImmutableBinding(dn, true)。
      2. 否则,
        1. 执行 ? env.CreateMutableBinding(dn, false)。
  16. 对于 functionsToInitialize 的每个 解析节点 f,执行
    1. fnfBoundNames 的唯一元素。
    2. fof 以参数 envprivateEnv 进行的 InstantiateFunctionObject
    3. 执行 ? CreateGlobalFunctionBinding(env, fn, fo, false)。
  17. 对于 declaredVarNames 的每个字符串 vn,执行
    1. 执行 ? CreateGlobalVarBinding(env, vn, false)。
  18. 返回 unused
注释 2

16.1.1 中指定的 早期错误 防止了函数/var 声明与 let/const/class 声明之间的名称冲突,以及单个 Script 内包含的声明的 let/const/class 绑定的重新声明。但是,这种跨越多个 Script 的冲突和重新声明在 GlobalDeclarationInstantiation 期间被检测为运行时错误。如果检测到任何此类错误,则不会为脚本实例化绑定。但是,如果 全局对象 使用 Proxy 异质对象 定义,则冲突声明的运行时测试可能不可靠,导致 突然完成 和一些全局声明未被实例化。如果发生这种情况,Script 的代码不会被求值。

与显式的 var 或 function 声明不同,直接在 全局对象 上创建的属性会导致可能被 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 静态语义:早期错误

ModuleBody : ModuleItemList

重复 ExportedNames 规则 意味着在 ModuleBody 中包含多个 export default ExportDeclaration 项是语法错误。在 Module 求值之前的模块链接期间检查与冲突或重复声明相关的其他错误条件。如果检测到任何此类错误,则不会对 Module 进行求值。

ModuleExportName : StringLiteral

16.2.1.2 静态语义:ImportedLocalNames ( importEntries )

抽象操作 ImportedLocalNames 接受参数 importEntries(一个 List of ImportEntry Records)并返回一个字符串的 List。它创建一个包含所有由 importEntries 定义的本地名称绑定的 List。调用时它执行以下步骤:

  1. localNames 为一个新的空 List
  2. 对于 importEntries 的每个 ImportEntry Record i,执行
    1. i.[[LocalName]] 追加到 localNames
  3. 返回 localNames

16.2.1.3 ModuleRequest 记录

ModuleRequest Record 表示带有给定导入属性的模块导入请求。它由以下字段组成:

表 40:ModuleRequest Record 字段
字段名称 值类型 含义
[[Specifier]] 一个字符串 模块说明符
[[Attributes]] 一个 List of ImportAttribute Records 导入属性

LoadedModuleRequest Record 表示模块导入请求以及结果 Module Record。它由表 表 40 中定义的相同字段组成,并添加了 [[Module]]

表 41:LoadedModuleRequest Record 字段
字段名称 值类型 含义
[[Specifier]] 一个字符串 模块说明符
[[Attributes]] 一个 List of ImportAttribute Records 导入属性
[[Module]] 一个 Module Record 与此模块请求对应的已加载模块

ImportAttribute Record 由以下字段组成:

表 42:ImportAttribute Record 字段
字段名称 值类型 含义
[[Key]] 一个字符串 属性键
[[Value]] 一个字符串 属性值

16.2.1.3.1 ModuleRequestsEqual ( left, right )

抽象操作 ModuleRequestsEqual 接受参数 left(一个 ModuleRequest Record 或一个 LoadedModuleRequest Record) 和 right(一个 ModuleRequest Record 或一个 LoadedModuleRequest Record) 并返回一个布尔值。调用时它执行以下步骤:

  1. 如果 left.[[Specifier]] 不是 right.[[Specifier]],返回 false
  2. leftAttrsleft.[[Attributes]]
  3. rightAttrsright.[[Attributes]]
  4. leftAttrsCountleftAttrs 中元素的数量。
  5. rightAttrsCountrightAttrs 中元素的数量。
  6. 如果 leftAttrsCountrightAttrsCount,返回 false
  7. 对于 leftAttrs 的每个 ImportAttribute Record l,执行
    1. 如果 rightAttrs 不包含一个 ImportAttribute Record r 使得 l.[[Key]]r.[[Key]]l.[[Value]]r.[[Value]],返回 false
  8. 返回 true

16.2.1.4 静态语义:ModuleRequests

语法导向操作 ModuleRequests 不接受参数并返回一个 List of ModuleRequest Records。它对以下产生式逐段定义:

Module : [empty]
  1. 返回一个新的空 List
ModuleItemList : ModuleItem
  1. 返回 ModuleItemModuleRequests
ModuleItemList : ModuleItemList ModuleItem
  1. requestsModuleItemListModuleRequests
  2. additionalRequestsModuleItemModuleRequests
  3. 对于 additionalRequests 的每个 ModuleRequest Record mr,执行
    1. 如果 requests 不包含一个 ModuleRequest Record mr2 使得 ModuleRequestsEqual(mr, mr2) 是 true,那么
      1. mr 追加到 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. attributesWithClauseWithClauseToAttributes
  3. 返回一个 List,其唯一元素是 ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: attributes }。
ImportDeclaration : import ModuleSpecifier ;
  1. specifierModuleSpecifierSV
  2. 返回一个 List,其唯一元素是 ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: « » }。
ImportDeclaration : import ModuleSpecifier WithClause ;
  1. specifierModuleSpecifierSV
  2. attributesWithClauseWithClauseToAttributes
  3. 返回一个 List,其唯一元素是 ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: attributes }。
ExportDeclaration : export ExportFromClause FromClause ;
  1. specifierFromClauseSV
  2. 返回一个 List,其唯一元素是 ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: « » }。
ExportDeclaration : export ExportFromClause FromClause WithClause ;
  1. specifierFromClauseSV
  2. attributesWithClauseWithClauseToAttributes
  3. 返回一个 List,其唯一元素是 ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: attributes }。
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 值是 Record 规范类型的值,可以认为存在于一个简单的面向对象层次结构中,其中 Module Record 是一个抽象类,具有抽象和具体子类。本规范定义了名为 Cyclic Module Record 的抽象子类及其名为 Source Text Module Record 的具体子类。其他规范和实现可以定义对应于它们定义的替代模块定义设施的额外 Module Record 子类。

Module Record 定义了 表 43 中列出的字段。所有 Module Definition 子类至少包含这些字段。Module Record 还定义了 表 44 中的抽象方法列表。所有 Module definition 子类必须提供这些抽象方法的具体实现。

表 43:Module Record 字段
字段名称 值类型 含义
[[Realm]] 一个 Realm Record 创建此模块的 Realm
[[Environment]] 一个 Module Environment Recordempty 包含此模块顶级绑定的 Environment Record。此字段在模块链接时设置。
[[Namespace]] 一个对象或 empty 如果为此模块创建了模块命名空间对象(28.3)。
[[HostDefined]] 任何内容(默认值为 undefined 为需要将附加信息与模块关联的 宿主环境 保留的字段。
表 44:Module Records 的抽象方法
方法 目的
LoadRequestedModules([hostDefined])

通过递归加载所有依赖项为链接准备模块,并返回一个 promise。

GetExportedNames([exportStarSet])

返回从此模块直接或间接导出的所有名称的列表。

在调用此方法之前,LoadRequestedModules 必须已成功完成。

ResolveExport(exportName [, resolveSet])

返回此模块导出的名称的绑定。绑定由 ResolvedBinding Record 表示,形式为 { [[Module]]: Module Record, [[BindingName]]: String | namespace }。如果导出是没有任何模块中直接绑定的模块命名空间对象,[[BindingName]] 将设置为 namespace。如果名称无法解析,返回 null,如果找到多个绑定,返回 ambiguous

每次使用特定的 exportNameresolveSet 对作为参数调用此操作时,必须返回相同的结果。

在调用此方法之前,LoadRequestedModules 必须已成功完成。

Link()

通过传递性地解析所有模块依赖项并创建 Module Environment Record 为求值准备模块。

在调用此方法之前,LoadRequestedModules 必须已成功完成。

Evaluate()

返回用于此模块及其依赖项求值的 promise,在成功求值或已成功求值时解析,在求值错误或已求值失败时拒绝。如果 promise 被拒绝,期望 宿主 处理 promise 拒绝并重新抛出求值错误。

在调用此方法之前,Link 必须已成功完成。

16.2.1.5.1 EvaluateModuleSync ( module )

抽象操作 EvaluateModuleSync 接受参数 module(一个 Module Record)并返回 一个 正常完成,包含 unused 或一个 抛出完成。它同步求值 module,前提是调用者保证 module 的求值将返回一个已经结算的 promise。调用时它执行以下步骤:

  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. 返回 ThrowCompletion(promise.[[PromiseResult]])。
  5. 返回 unused

16.2.1.6 循环模块记录

Cyclic Module Record 用于表示可以与 Cyclic Module Record 类型的子类的其他模块参与依赖循环的模块的信息。不是 Cyclic Module Record 类型的子类的 Module Records 不得与 Source Text Module Records 参与依赖循环。

除了 表 43 中定义的字段外,Cyclic Module Records 还具有 表 45 中列出的附加字段

表 45:Cyclic Module Records 的附加字段
字段名称 值类型 含义
[[Status]] newunlinkedlinkinglinkedevaluatingevaluating-asyncevaluated 初始为 new。随着模块在其生命周期中的进展,按顺序转换为 unlinkedlinkinglinkedevaluating、 可能是 evaluating-asyncevaluatedevaluating-async 表示此模块排队等待在其异步依赖完成时执行,或者它是一个 [[HasTLA]] 字段为 true 的模块,已执行并等待顶级完成。
[[EvaluationError]] 一个 抛出完成empty 表示求值期间发生的异常的 抛出完成。如果没有发生异常或 [[Status]] 不是 evaluated,则为 undefined
[[DFSIndex]] 一个 整数empty 仅在 Link 和 Evaluate 期间使用的辅助字段。如果 [[Status]]linkingevaluating, 此非负数记录模块在依赖图的深度优先遍历中首次访问的点。
[[DFSAncestorIndex]] 一个 整数empty 仅在 Link 和 Evaluate 期间使用的辅助字段。如果 [[Status]]linkingevaluating, 这是模块自己的 [[DFSIndex]] 或同一强连通分量中"较早"模块的该值。
[[RequestedModules]] ModuleRequest RecordsList 与此模块中的导入关联的 ModuleRequest RecordsList。该 List 按导入的源文本出现顺序排列。
[[LoadedModules]] LoadedModuleRequest RecordsList 从此记录表示的模块用于请求导入具有相对导入属性的模块的说明符字符串到已解析的 Module Record 的映射。该列表不包含两个不同的 Records r1r2,使得 ModuleRequestsEqual(r1, r2) 为 true
[[CycleRoot]] 一个 Cyclic Module Recordempty 循环的第一个访问模块,强连通分量的根 DFS 祖先。对于不在循环中的模块,这将是模块本身。一旦 Evaluate 完成,模块的 [[DFSAncestorIndex]] 是其 [[CycleRoot]][[DFSIndex]]
[[HasTLA]] 一个布尔值 此模块是否单独异步(例如,如果它是包含顶级等待的 Source Text Module Record)。具有异步依赖项并不意味着此字段为 true。此字段在模块解析后不得更改。
[[AsyncEvaluationOrder]] unset、一个 整数done 此字段初始设置为 unset,对于完全同步的模块保持 unset。对于自身异步或具有异步依赖项的模块,它设置为一个 整数,该整数确定 16.2.1.6.1.3.4 排队执行待处理模块的顺序。 一旦待处理模块被执行,该字段设置为 done
[[TopLevelCapability]] 一个 PromiseCapability Recordempty 如果此模块是某个循环的 [[CycleRoot]],并且在该循环中的某个模块上调用了 Evaluate(),此字段包含该整个求值的 PromiseCapability Record。它用于解决从 Evaluate() 抽象方法返回的 Promise 对象。除非为这些依赖项中的某些启动了顶级 Evaluate(),否则该字段对于该模块的任何依赖项都将是 empty
[[AsyncParentModules]] Cyclic Module RecordsList 如果此模块或依赖项的 [[HasTLA]]true,并且执行正在进行中,这会跟踪此模块的顶级执行作业的父导入器。这些父模块在此模块成功完成执行之前不会开始执行。
[[PendingAsyncDependencies]] 一个 整数empty 如果此模块有任何异步依赖项,这会跟踪此模块剩余要执行的异步依赖模块数量。 当此字段达到 0 且没有执行错误时,具有异步依赖项的模块将被执行。

除了 表 44 中定义的方法外,Cyclic Module Records 还具有 表 46 中列出的附加方法

表 46:Cyclic Module Records 的附加抽象方法
方法 目的
InitializeEnvironment() 初始化模块的 Environment Record,包括解析所有导入的绑定,并创建模块的 执行上下文
ExecuteModule([promiseCapability]) 在其 执行上下文 内求值模块的代码。 如果此模块的 [[HasTLA]]true,则传递一个 PromiseCapability Record 作为参数,并且期望该方法解析或拒绝给定的能力。在这种情况下,该方法不得抛出异常,而应在必要时拒绝 PromiseCapability Record

GraphLoadingState Record 是一个 Record,包含有关模块图加载过程的信息。它用于在调用 HostLoadImportedModule 后继续加载。每个 GraphLoadingState Record 都有 表 47 中定义的字段:

表 47:GraphLoadingState Record 字段
字段名称 值类型 含义
[[PromiseCapability]] 一个 PromiseCapability Record 加载过程完成时要解析的 promise。
[[IsLoading]] 一个布尔值 如果加载过程尚未完成,无论是成功还是出现错误,它都是 true。
[[PendingModulesCount]] 一个非负 整数 它跟踪待处理的 HostLoadImportedModule 调用数量。
[[Visited]] Cyclic Module RecordsList 它是当前加载过程已加载的 Cyclic Module Records 的列表,以避免循环依赖的无限循环。
[[HostDefined]] 任何内容(默认值为 empty 它包含从 LoadRequestedModules 调用者传递到 HostLoadImportedModule宿主定义 数据。

16.2.1.6.1 Module Record 抽象方法的实现

以下是 Cyclic Module Record 的具体方法,它们实现了 表 44 中定义的相应 Module Record 抽象方法。

16.2.1.6.1.1 LoadRequestedModules ( [ hostDefined ] )

Cyclic Module Record module 的 LoadRequestedModules 具体方法接受可选参数 hostDefined(任何内容)并返回一个 Promise。它填充 module 依赖图中所有 Module Records[[LoadedModules]](大部分工作由辅助函数 InnerModuleLoading 完成)。它接受一个可选的 hostDefined 参数,该参数传递给 HostLoadImportedModule 钩子。调用时执行以下步骤:

  1. 如果 hostDefined 不存在,让 hostDefinedempty
  2. pc 为 ! NewPromiseCapability(%Promise%)。
  3. stateGraphLoadingState Record { [[IsLoading]]: true[[PendingModulesCount]]: 1,[[Visited]]: « »,[[PromiseCapability]]: pc[[HostDefined]]: hostDefined }。
  4. 执行 InnerModuleLoading(state, module)。
  5. 返回 pc.[[Promise]]
注意
hostDefined 参数可用于传递获取导入模块所需的附加信息。例如,HTML 使用它为 <link rel="preload" as="..."> 标签设置正确的 fetch 目标。 import() 表达式从不设置 hostDefined 参数。

16.2.1.6.1.1.1 InnerModuleLoading ( state, module )

抽象操作 InnerModuleLoading 接受参数 state(一个 GraphLoadingState Record)和 module(一个 Module Record)并返回 unused。它被 LoadRequestedModules 用于递归执行 module 依赖图的实际加载过程。调用时执行以下步骤:

  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 )

抽象操作 ContinueModuleLoading 接受参数 state(一个 GraphLoadingState Record)和 moduleCompletion(一个 包含 Module Record正常完成 或一个 抛出 完成)并返回 unused。它用于在调用 HostLoadImportedModule 后重新进入加载过程。 调用时执行以下步骤:

  1. 如果 state.[[IsLoading]]false,返回 unused
  2. 如果 moduleCompletion正常 完成,那么
    1. 执行 InnerModuleLoading(state, moduleCompletion.[[Value]])。
  3. 否则,
    1. 设置 state.[[IsLoading]]false
    2. 执行 ! Call(state.[[PromiseCapability]].[[Reject]], undefined, « moduleCompletion.[[Value]] »)。
  4. 返回 unused

16.2.1.6.1.2 Link ( )

Cyclic Module Record module 的 Link 具体方法不接受参数,并返回一个 包含 unused正常 完成 或一个 抛出 完成。成功时,Link 将此模块的 [[Status]]unlinked 转换为 linked。失败时,抛出异常并且此模块的 [[Status]] 保持为 unlinked。(大部分工作由辅助函数 InnerModuleLinking 完成。)调用时执行以下步骤:

  1. 断言module.[[Status]]unlinkedlinkedevaluating-asyncevaluated 之一。
  2. stack 为一个新的空 List
  3. resultCompletion(InnerModuleLinking(module, stack, 0))。
  4. 如果 result突然完成,那么
    1. 对于 stack 的每个 Cyclic Module Record m,执行
      1. 断言m.[[Status]]linking
      2. 设置 m.[[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 )

抽象操作 InnerModuleLinking 接受参数 module(一个 Module Record)、 stackCyclic Module RecordsList)和 index(一个非负 整数),并返回一个 包含 非负 整数正常完成 或一个 抛出 完成。它被 Link 用于对 module 以及依赖图中的所有其他模块递归执行实际的链接过程。stackindex 参数,以及模块的 [[DFSIndex]][[DFSAncestorIndex]] 字段,跟踪深度优先搜索(DFS)遍历。特别地,[[DFSAncestorIndex]] 用于发现强连通分量(SCC),使得 SCC 中的所有模块一起转换为 linked。调用时执行以下步骤:

  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. 设置 module.[[DFSIndex]]index
  6. 设置 module.[[DFSAncestorIndex]]index
  7. 设置 indexindex + 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. 断言requiredModule.[[Status]]linking 当且仅当 stack 包含 requiredModule
      3. 如果 requiredModule.[[Status]]linking,那么
        1. 设置 module.[[DFSAncestorIndex]]min(module.[[DFSAncestorIndex]], requiredModule.[[DFSAncestorIndex]])。
  10. 执行 ? module.InitializeEnvironment()。
  11. 断言modulestack 中恰好出现一次。
  12. 断言module.[[DFSAncestorIndex]]module.[[DFSIndex]]
  13. 如果 module.[[DFSAncestorIndex]] = module.[[DFSIndex]],那么
    1. donefalse
    2. 重复,当 donefalse 时,
      1. requiredModulestack 的最后一个元素。
      2. 移除 stack 的最后一个元素。
      3. 断言requiredModuleCyclic Module Record
      4. 设置 requiredModule.[[Status]]linked
      5. 如果 requiredModulemodule 是同一个 Module Record,设置 donetrue
  14. 返回 index

16.2.1.6.1.3 Evaluate ( )

Cyclic Module Record module 的 Evaluate 具体方法不接受参数并返回一个 Promise。Evaluate 将此模块的 [[Status]]linked 转换为 evaluating-asyncevaluated。当第一次在给定强连通分量中的模块上调用时,Evaluate 创建并返回一个 Promise,该 Promise 在模块完成求值时解析。此 Promise 存储在该分量的 [[CycleRoot]][[TopLevelCapability]] 字段中。在该分量中任何模块上后续调用 Evaluate 都会返回相同的 Promise。(大部分工作由辅助函数 InnerModuleEvaluation 完成。)调用时执行以下步骤:

  1. 断言:此次 Evaluate 调用不会与 surrounding agent 内的另一次 Evaluate 调用同时发生。
  2. 断言module.[[Status]]linkedevaluating-asyncevaluated 之一。
  3. 如果 module.[[Status]]evaluating-asyncevaluated, 设置 modulemodule.[[CycleRoot]]
  4. 如果 module.[[TopLevelCapability]] 不是 empty,那么
    1. 返回 module.[[TopLevelCapability]].[[Promise]]
  5. stack 为一个新的空 List
  6. capability 为 ! NewPromiseCapability(%Promise%)。
  7. 设置 module.[[TopLevelCapability]]capability
  8. resultCompletion(InnerModuleEvaluation(module, stack, 0))。
  9. 如果 result突然完成,那么
    1. 对于 stack 的每个 Cyclic Module Record m,执行
      1. 断言m.[[Status]]evaluating
      2. 断言m.[[AsyncEvaluationOrder]]unset
      3. 设置 m.[[Status]]evaluated
      4. 设置 m.[[EvaluationError]]result
    2. 断言module.[[Status]]evaluated
    3. 断言module.[[EvaluationError]]result 是相同的 Completion Record
    4. 执行 ! Call(capability.[[Reject]], undefined, « result.[[Value]] »)。
  10. 否则,
    1. 断言module.[[Status]]evaluating-asyncevaluated
    2. 断言module.[[EvaluationError]]empty
    3. 如果 module.[[Status]]evaluated,那么
      1. 注意:这意味着 module 的求值同步完成。
      2. 断言module.[[AsyncEvaluationOrder]]unset
      3. 执行 ! Call(capability.[[Resolve]], undefined, « undefined »)。
    4. 断言stack 是空的。
  11. 返回 capability.[[Promise]]

16.2.1.6.1.3.1 InnerModuleEvaluation ( module, stack, index )

抽象操作 InnerModuleEvaluation 接受参数 module(一个 Module Record)、 stackCyclic Module RecordsList)和 index(一个非负 整数),并返回一个 包含 非负 整数正常完成 或一个 抛出 完成。它被 Evaluate 用于对 module 以及依赖图中的所有其他模块递归执行实际的求值过程。stackindex 参数,以及 module[[DFSIndex]][[DFSAncestorIndex]] 字段,其使用方式与 InnerModuleLinking 中相同。调用时执行以下步骤:

  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. 设置 module.[[DFSIndex]]index
  7. 设置 module.[[DFSAncestorIndex]]index
  8. 设置 module.[[PendingAsyncDependencies]] 为 0。
  9. 设置 indexindex + 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. 断言requiredModule.[[Status]]evaluating 当且仅当 stack 包含 requiredModule
      3. 如果 requiredModule.[[Status]]evaluating,那么
        1. 设置 module.[[DFSAncestorIndex]]min(module.[[DFSAncestorIndex]], requiredModule.[[DFSAncestorIndex]])。
      4. 否则,
        1. 设置 requiredModulerequiredModule.[[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]]module.[[DFSIndex]]
  16. 如果 module.[[DFSAncestorIndex]] = module.[[DFSIndex]],那么
    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,设置 donetrue
      8. 设置 requiredModule.[[CycleRoot]]module
  17. 返回 index
注意 1

模块在被 InnerModuleEvaluation 遍历时处于 evaluating 状态。模块在执行完成时处于 evaluated 状态,或者在执行期间如果其 [[HasTLA]] 字段为 true 或具有异步依赖时处于 evaluating-async 状态。

注意 2

当异步循环不是 evaluating 时,依赖于异步循环模块的任何模块将通过 [[CycleRoot]] 依赖于循环根的执行。这确保循环状态可以通过其根模块状态作为单个强连通分量进行处理。

16.2.1.6.1.3.2 ExecuteAsyncModule ( module )

抽象操作 ExecuteAsyncModule 接受参数 module(一个 Cyclic Module Record)并返回 unused。调用时执行以下步骤:

  1. 断言module.[[Status]]evaluatingevaluating-async
  2. 断言module.[[HasTLA]]true
  3. capability 为 ! NewPromiseCapability(%Promise%)。
  4. fulfilledClosure 为一个新的 Abstract Closure, 不接受参数,捕获 module,并在调用时执行以下步骤:
    1. 执行 AsyncModuleExecutionFulfilled(module)。
    2. 返回 undefined
  5. onFulfilledCreateBuiltinFunction(fulfilledClosure, 0, "", « »)。
  6. rejectedClosure 为一个新的 Abstract Closure, 接受参数 (error),捕获 module,并在调用时执行以下步骤:
    1. 执行 AsyncModuleExecutionRejected(module, error)。
    2. 返回 undefined
  7. onRejectedCreateBuiltinFunction(rejectedClosure, 0, "", « »)。
  8. 执行 PerformPromiseThen(capability.[[Promise]], onFulfilled, onRejected)。
  9. 执行 ! module.ExecuteModule(capability)。
  10. 返回 unused

16.2.1.6.1.3.3 GatherAvailableAncestors ( module, execList )

抽象操作 GatherAvailableAncestors 接受参数 module (一个 Cyclic Module Record)和 execListCyclic Module RecordsList)并返回 unused。调用时执行以下步骤:

  1. 对于 module.[[AsyncParentModules]] 的每个 Cyclic Module Record m,执行
    1. 如果 execList 不包含 mm.[[CycleRoot]].[[EvaluationError]]empty,那么
      1. 断言m.[[Status]]evaluating-async
      2. 断言m.[[EvaluationError]]empty
      3. 断言m.[[AsyncEvaluationOrder]]整数
      4. 断言m.[[PendingAsyncDependencies]] > 0。
      5. 设置 m.[[PendingAsyncDependencies]]m.[[PendingAsyncDependencies]] - 1。
      6. 如果 m.[[PendingAsyncDependencies]] = 0,那么
        1. m 追加到 execList
        2. 如果 m.[[HasTLA]]false,执行 GatherAvailableAncestors(m, execList)。
  2. 返回 unused
注意

当根 module 的异步执行完成时,此函数确定能够在此完成时同步执行的模块列表,将它们填充到 execList 中。

16.2.1.6.1.3.4 AsyncModuleExecutionFulfilled ( module )

抽象操作 AsyncModuleExecutionFulfilled 接受参数 module(一个 Cyclic Module Record)并返回 unused。调用时执行以下步骤:

  1. 如果 module.[[Status]]evaluated,那么
    1. 断言module.[[EvaluationError]] 不是 empty
    2. 返回 unused
  2. 断言module.[[Status]]evaluating-async
  3. 断言module.[[AsyncEvaluationOrder]]整数
  4. 断言module.[[EvaluationError]]empty
  5. 设置 module.[[AsyncEvaluationOrder]]done
  6. 设置 module.[[Status]]evaluated
  7. 如果 module.[[TopLevelCapability]] 不是 empty,那么
    1. 断言module.[[CycleRoot]]module 是同一个 Module Record
    2. 执行 ! Call(module.[[TopLevelCapability]].[[Resolve]], undefined, « undefined »)。
  8. execList 为一个新的空 List
  9. 执行 GatherAvailableAncestors(module, execList)。
  10. 断言execList 的所有元素都将其 [[AsyncEvaluationOrder]] 字段设置为 整数[[PendingAsyncDependencies]] 字段设置为 0,[[EvaluationError]] 字段设置为 empty
  11. sortedExecList 为一个 List, 其元素是 execList 的元素,按其 [[AsyncEvaluationOrder]] 字段升序排序。
  12. 对于 sortedExecList 的每个 Cyclic Module Record m,执行
    1. 如果 m.[[Status]]evaluated,那么
      1. 断言m.[[EvaluationError]] 不是 empty
    2. 否则,如果 m.[[HasTLA]]true,那么
      1. 执行 ExecuteAsyncModule(m)。
    3. 否则,
      1. resultm.ExecuteModule()
      2. 如果 result突然完成,那么
        1. 执行 AsyncModuleExecutionRejected(m, result.[[Value]])。
      3. 否则,
        1. 设置 m.[[AsyncEvaluationOrder]]done
        2. 设置 m.[[Status]]evaluated
        3. 如果 m.[[TopLevelCapability]] 不是 empty,那么
          1. 断言m.[[CycleRoot]]m 是同一个 Module Record
          2. 执行 ! Call(m.[[TopLevelCapability]].[[Resolve]], undefined, « undefined »)。
  13. 返回 unused

16.2.1.6.1.3.5 AsyncModuleExecutionRejected ( module, error )

抽象操作 AsyncModuleExecutionRejected 接受参数 module(一个 Cyclic Module Record)和 error(一个 ECMAScript 语言值)并返回 unused。调用时执行以下步骤:

  1. 如果 module.[[Status]]evaluated,那么
    1. 断言module.[[EvaluationError]] 不是 empty
    2. 返回 unused
  2. 断言module.[[Status]]evaluating-async
  3. 断言module.[[AsyncEvaluationOrder]]整数
  4. 断言module.[[EvaluationError]]empty
  5. 设置 module.[[EvaluationError]]ThrowCompletion(error)。
  6. 设置 module.[[Status]]evaluated
  7. 设置 module.[[AsyncEvaluationOrder]]done
  8. 注意:module.[[AsyncEvaluationOrder]] 设置为 done 是为了与 AsyncModuleExecutionFulfilled 保持对称。 在 InnerModuleEvaluation 中, 当模块的 [[EvaluationError]] 内部槽不是 empty 时,其 [[AsyncEvaluationOrder]] 内部槽的值未被使用。
  9. 对于 module.[[AsyncParentModules]] 的每个 Cyclic Module Record m,执行
    1. 执行 AsyncModuleExecutionRejected(m, error)。
  10. 如果 module.[[TopLevelCapability]] 不是 empty,那么
    1. 断言module.[[CycleRoot]]module 是同一个 Module Record
    2. 执行 ! Call(module.[[TopLevelCapability]].[[Reject]], undefined, « error »)。
  11. 返回 unused

16.2.1.6.2 循环模块记录图示例

这个非规范性章节提供了一系列常见模块图链接和求值的示例,特别关注错误如何发生。

首先考虑以下简单的模块图:

图 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(),这将成功完成,返回一个解析为 undefined 的 Promise(再次按假设),递归地首先求值 C,然后是 B。此时每个模块的 [[Status]] 将是 evaluated

然后考虑在成功调用 A.LoadRequestedModules() 后涉及链接错误的情况。如果 CInnerModuleLinking 成功,但之后 B 失败,例如因为它导入了 C 不提供的内容,那么原始的 A.Link() 将失败,AB[[Status]] 保持 unlinked。 不过,C[[Status]] 已变为 linked

最后,考虑在成功调用 Link() 后涉及求值错误的情况。如果 CInnerModuleEvaluation 成功,但之后 B 失败,例如因为 B 包含抛出异常的代码,那么原始的 A.Evaluate() 将失败,返回一个被拒绝的 Promise。生成的异常将记录在 AB[[EvaluationError]] 字段中,它们的 [[Status]] 将变为 evaluatedC 也将变为 evaluated,但与 AB 相反,它将保持没有 [[EvaluationError]],因为它成功完成了求值。 存储异常确保任何时候 宿主 尝试通过调用它们的 Evaluate() 方法重用 AB 时,它将遇到相同的异常。(宿主 不需要重用 Cyclic Module Records;类似地,宿主 不需要暴露这些方法抛出的异常对象。然而,规范启用了这样的用法。)

现在考虑一种不同类型的错误条件:

图 3:具有无法解析模块的模块图
一个模块图,其中模块 A 依赖于一个缺失(无法解析)的模块,用 ??? 表示

在这种情况下,模块 A 声明对某个其他模块的依赖,但该模块不存在 Module Record,即 HostLoadImportedModule 在被询问时调用 FinishLoadingImportedModule 时传递异常。这可能由于各种原因发生,例如对应的资源不存在,或者资源存在但 ParseModule 在尝试解析生成的源文本时返回一些错误。宿主 可以选择通过传递给 FinishLoadingImportedModule 的完成来暴露失败原因。 在任何情况下,这个异常导致加载失败,这使得 A[[Status]] 保持 new

这里加载、链接和求值错误之间的差异是由于以下特征:

  • 求值 必须只执行一次,因为它可能导致副作用;因此记住求值是否已经执行很重要,即使不成功。(在错误情况下,记住异常也是有意义的,因为否则后续的 Evaluate() 调用将必须合成一个新的异常。)
  • 另一方面,链接是无副作用的,因此即使失败,也可以稍后重试而不会有问题。
  • 加载与 宿主 密切交互,对于其中一些,可能希望允许用户重试失败的加载(例如,如果失败是由临时不良网络条件引起的)。

现在,考虑一个有循环的模块图:

图 4:循环模块图
一个模块图,其中模块 A 依赖于模块 B 和 C,但模块 B 也依赖于模块 A

这里我们假设入口点是模块 A,因此 宿主 通过调用 A.LoadRequestedModules() 进行,这对 A 执行 InnerModuleLoading。 这反过来对 BC 调用 InnerModuleLoading。 由于循环,这再次对 A 触发 InnerModuleLoading, 但此时它是无操作的,因为 A 的依赖加载已经在这个 LoadRequestedModules 过程中被触发。当图中的所有模块都被成功加载时,它们的 [[Status]] 同时从 new 转换为 unlinked

然后 宿主 通过调用 A.Link() 继续,这对 A 执行 InnerModuleLinking。 这反过来对 B 调用 InnerModuleLinking。 由于循环,这再次对 A 触发 InnerModuleLinking, 但此时它是无操作的,因为 A.[[Status]] 已经是 linking。 当控制回到 A 并且对 C 触发 InnerModuleLinking 时,B.[[Status]] 本身保持 linking。 在这返回后,C.[[Status]]linkedAB 一起从 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 的模块,通过 AsyncModuleExecutionRejected 算法贯穿整个依赖图。因此 AB 都变为 evaluated,异常记录在 AB[[EvaluationError]] 字段中,而 C 保持为 evaluated,没有 [[EvaluationError]]

最后,考虑一个有循环的模块图,其中所有模块都异步完成:

图 5:异步循环模块图
一个模块图,其中模块 A 依赖于模块 B 和 C,模块 B 依赖于模块 D,模块 C 依赖于模块 D 和 E,模块 D 依赖于模块 A

加载和链接像之前一样发生,所有模块最终的 [[Status]] 设置为 linked

调用 A.Evaluate() 对 ABD 调用 InnerModuleEvaluation, 它们都转换为 evaluating。然后再次对 A 调用 InnerModuleEvaluation, 这是无操作的,因为它已经是 evaluating。此时,D.[[PendingAsyncDependencies]] 是 0,因此调用 ExecuteAsyncModule(D), 我们用一个新的 PromiseCapability 调用 D.ExecuteModule,跟踪 D 的异步执行。我们展开回到对 BInnerModuleEvaluation, 设置 B.[[PendingAsyncDependencies]] 为 1,B.[[AsyncEvaluationOrder]] 为 1。我们展开回到对 A 的原始 InnerModuleEvaluation, 设置 A.[[PendingAsyncDependencies]] 为 1。在 A 依赖项循环的下一次迭代中,我们对 C 调用 InnerModuleEvaluation, 因此对 D(再次无操作)和 E。由于 E 没有依赖项且不是循环的一部分,我们以与 D 相同的方式调用 ExecuteAsyncModule(E), E 立即从堆栈中移除。我们再次展开到对 CInnerModuleEvaluation, 设置 C.[[AsyncEvaluationOrder]] 为 3。现在我们完成对 A 依赖项的循环,设置 A.[[AsyncEvaluationOrder]] 为 4,并从堆栈中移除整个强连通分量,同时将所有模块转换为 evaluating-async。此时,模块的字段如 表 48 所示。

表 48:初始 Evaluate() 调用后的模块字段
字段
模块
A B C D E
[[DFSIndex]] 0 1 3 2 4
[[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]] 设置为 evaluatedC.[[PendingAsyncDependencies]] 递减为 1。更新模块的字段如 表 49 所示。

表 49:模块 E 完成执行后的模块字段
字段
模块
C E
[[DFSIndex]] 3 4
[[DFSAncestorIndex]] 0 4
[[Status]] evaluating-async evaluated
[[AsyncEvaluationOrder]] 3 2
[[AsyncParentModules]] « A » « C »
[[PendingAsyncDependencies]] 1(D 0

D 接下来完成(因为它是唯一仍在执行的模块)。当发生这种情况时,再次调用 AsyncModuleExecutionFulfilledD.[[Status]] 设置为 evaluated。其可用于执行的祖先是 B (其 [[AsyncEvaluationOrder]] 是 1)和 C (其 [[AsyncEvaluationOrder]] 是 3),因此 B 将首先处理: B.[[PendingAsyncDependencies]] 递减为 0,对 B 调用 ExecuteAsyncModule, 它开始执行。C.[[PendingAsyncDependencies]] 也递减为 0,C 开始执行(如果 B 包含 await,可能与 B 并行)。更新模块的字段如 表 50 所示。

表 50:模块 D 完成执行后的模块字段
字段
模块
B C D
[[DFSIndex]] 1 3 2
[[DFSAncestorIndex]] 0 0 0
[[Status]] evaluating-async evaluating-async evaluated
[[AsyncEvaluationOrder]] 1 3 0
[[AsyncParentModules]] « A » « A » « B, C »
[[PendingAsyncDependencies]] 0 0 0

让我们假设 C 接下来完成执行。当发生这种情况时,再次调用 AsyncModuleExecutionFulfilledC.[[Status]] 设置为 evaluatedA.[[PendingAsyncDependencies]] 递减为 1。更新模块的字段如 表 51 所示。

表 51:模块 C 完成执行后的模块字段
字段
模块
A C
[[DFSIndex]] 0 3
[[DFSAncestorIndex]] 0 0
[[Status]] evaluating-async evaluated
[[AsyncEvaluationOrder]] 4 3
[[AsyncParentModules]] « » « A »
[[PendingAsyncDependencies]] 1(B 0

然后,B 完成执行。当发生这种情况时,再次调用 AsyncModuleExecutionFulfilledB.[[Status]] 设置为 evaluatedA.[[PendingAsyncDependencies]] 递减为 0,因此调用 ExecuteAsyncModule, 它开始执行。更新模块的字段如 表 52 所示。

表 52:模块 B 完成执行后的模块字段
字段
模块
A B
[[DFSIndex]] 0 1
[[DFSAncestorIndex]] 0 0
[[Status]] evaluating-async evaluated
[[AsyncEvaluationOrder]] 4 1
[[AsyncParentModules]] « » « A »
[[PendingAsyncDependencies]] 0 0

最后,A 完成执行。当发生这种情况时,再次调用 AsyncModuleExecutionFulfilledA.[[Status]] 设置为 evaluated。此时,A.[[TopLevelCapability]] 中的 Promise(从 A.Evaluate() 返回)被解析,这结束了对此模块图的处理。更新模块的字段如 表 53 所示。

表 53:模块 A 完成执行后的模块字段
字段
模块
A
[[DFSIndex]] 0
[[DFSAncestorIndex]] 0
[[Status]] evaluated
[[AsyncEvaluationOrder]] 4
[[AsyncParentModules]] « »
[[PendingAsyncDependencies]] 0

或者,考虑失败情况,其中 CB 完成执行之前执行失败并返回错误。当发生这种情况时,调用 AsyncModuleExecutionRejected, 它设置 C.[[Status]]evaluatedC.[[EvaluationError]] 为错误。然后通过对每个 AsyncParentModules 执行 AsyncModuleExecutionRejected 将此错误传播到所有 AsyncParentModules。更新模块的字段如 表 54 所示。

表 54:模块 C 出错完成后的模块字段
字段
模块
A C
[[DFSIndex]] 0 3
[[DFSAncestorIndex]] 0 0
[[Status]] evaluated evaluated
[[AsyncEvaluationOrder]] 4 3
[[AsyncParentModules]] « » « A »
[[PendingAsyncDependencies]] 1(B 0
[[EvaluationError]] empty C 的求值错误

A 将被拒绝,错误与 C 相同,因为 C 将用 C 的错误对 A 调用 AsyncModuleExecutionRejectedA.[[Status]] 设置为 evaluated。此时 A.[[TopLevelCapability]] 中的 Promise(从 A.Evaluate() 返回)被拒绝。更新模块的字段如 表 55 所示。

表 55:模块 A 被拒绝后的模块字段
字段
模块
A
[[DFSIndex]] 0
[[DFSAncestorIndex]] 0
[[Status]] evaluated
[[AsyncEvaluationOrder]] 4
[[AsyncParentModules]] « »
[[PendingAsyncDependencies]] 0
[[EvaluationError]] C求值 错误

然后,B 完成执行且没有错误。当发生这种情况时,再次调用 AsyncModuleExecutionFulfilledB.[[Status]] 设置为 evaluated。对 B 调用 GatherAvailableAncestors。 然而,A.[[CycleRoot]]A,它有求值错误,因此它不会被添加到返回的 sortedExecList 中,AsyncModuleExecutionFulfilled 将返回而不进行进一步处理。B 的任何未来导入者将从 C 设置在循环根 A 上的求值错误中解析 B.[[CycleRoot]].[[EvaluationError]] 的拒绝。更新模块的字段如 表 56 所示。

表 56:模块 B 在错误图中完成执行后的模块字段
字段
模块
A B
[[DFSIndex]] 0 1
[[DFSAncestorIndex]] 0 0
[[Status]] evaluated evaluated
[[AsyncEvaluationOrder]] 4 1
[[AsyncParentModules]] « » « A »
[[PendingAsyncDependencies]] 0 0
[[EvaluationError]] C求值 错误 empty

16.2.1.7 源文本模块记录

源文本模块记录用于表示从使用 目标符号 Module 解析的 ECMAScript 源文本11)定义的模块信息。其字段包含关于模块导入和导出名称的摘要信息,其具体方法使用这些摘要来链接和求值模块。

源文本模块记录可以与抽象 Module Record 类型的其他子类存在于模块图中,并且可以与 Cyclic Module Record 类型的其他子类参与循环。

除了在 表 45 中定义的字段外,源文本模块记录还有在 表 57 中列出的其他字段。每个字段最初在 ParseModule 中设置。

表 57:源文本模块记录的附加字段
字段名称 值类型 含义
[[ECMAScriptCode]] 一个 解析节点 使用 Module 作为 目标符号 解析此模块源文本的结果。
[[Context]] 一个 ECMAScript 代码执行上下文empty 与此模块关联的 执行上下文。在模块环境初始化之前为 empty
[[ImportMeta]] 一个对象或 empty 通过 import.meta 元属性暴露的对象。在被 ECMAScript 代码访问之前为 empty
[[ImportEntries]] 一个 列表,包含 ImportEntry 记录 从此模块代码派生的 ImportEntry 记录的 列表
[[LocalExportEntries]] 一个 列表,包含 ExportEntry 记录 从此模块代码派生的 ExportEntry 记录的 列表,对应于模块内发生的声明。
[[IndirectExportEntries]] 一个 列表,包含 ExportEntry 记录 从此模块代码派生的 ExportEntry 记录的 列表,对应于模块内发生的重新导出导入或来自 export * as namespace 声明的导出。
[[StarExportEntries]] 一个 列表,包含 ExportEntry 记录 从此模块代码派生的 ExportEntry 记录的 列表,对应于模块内发生的 export * 声明,不包括 export * as namespace 声明。

ImportEntry 记录是一个 记录,摘要了关于单个声明性导入的信息。每个 ImportEntry 记录都有在 表 58 中定义的字段:

表 58:ImportEntry 记录字段
字段名称 值类型 含义
[[ModuleRequest]] 一个 ModuleRequest 记录 表示 ImportDeclarationModuleSpecifier 和导入属性的 ModuleRequest 记录
[[ImportName]] 一个字符串或 namespace-object [[ModuleRequest]] 标识的模块导出所需绑定的名称。值 namespace-object 表示导入请求是针对目标模块的命名空间对象。
[[LocalName]] 一个字符串 用于从导入模块内部本地访问导入值的名称。
注 1

表 59 给出了用于表示语法导入形式的 ImportEntry 记录字段的示例:

表 59(信息性):导入形式到 ImportEntry 记录的映射
导入语句形式 [[ModuleRequest]] [[ImportName]] [[LocalName]]
import v from "mod"; "mod" "default" "v"
import * as ns from "mod"; "mod" namespace-object "ns"
import {x} from "mod"; "mod" "x" "x"
import {x as v} from "mod"; "mod" "x" "v"
import "mod"; 不创建 ImportEntry 记录

ExportEntry 记录是一个 记录,摘要了关于单个声明性导出的信息。每个 ExportEntry 记录都有在 表 60 中定义的字段:

表 60:ExportEntry 记录字段
字段名称 值类型 含义
[[ExportName]] 一个字符串或 null 此模块用于导出此绑定的名称。
[[ModuleRequest]] 一个 ModuleRequest 记录null 表示 ExportDeclarationModuleSpecifier 和导入属性的 ModuleRequest 记录。 如果 ExportDeclaration 没有 ModuleSpecifier,则为 null
[[ImportName]] 一个字符串、nullallall-but-default [[ModuleRequest]] 标识的模块导出所需绑定的名称。 如果 ExportDeclaration 没有 ModuleSpecifier,则为 nullall 用于 export * as ns from "mod" 声明。 all-but-default 用于 export * from "mod" 声明。
[[LocalName]] 一个字符串或 null 用于从导入模块内部本地访问导出值的名称。如果导出值在模块内部不可本地访问,则为 null
注 2

表 61 给出了用于表示语法导出形式的 ExportEntry 记录字段的示例:

表 61(信息性):导出形式到 ExportEntry 记录的映射
导出语句形式 [[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" all null

以下定义指定了 源文本模块记录所需的具体方法和其他 抽象操作

16.2.1.7.1 ParseModule ( sourceText, realm, hostDefined )

抽象操作 ParseModule 接受参数 sourceTextECMAScript 源文本)、realm(一个 Realm Record)和 hostDefined(任意值),返回一个 源文本模块记录或一个非空的 列表,包含 SyntaxError 对象。它基于将 sourceText 作为 Module 解析的结果创建一个 源文本模块记录。调用时执行以下步骤:

  1. bodyParseText(sourceText, Module)。
  2. 如果 body 是一个错误的 列表,返回 body
  3. requestedModulesbodyModuleRequests
  4. importEntriesbodyImportEntries
  5. importedBoundNamesImportedLocalNames(importEntries)。
  6. indirectExportEntries 为一个新的空 列表
  7. localExportEntries 为一个新的空 列表
  8. starExportEntries 为一个新的空 列表
  9. exportEntriesbodyExportEntries
  10. 对于 exportEntries 中的每个 ExportEntry Record ee,执行
    1. 如果 ee.[[ModuleRequest]]null,那么
      1. 如果 importedBoundNames 不包含 ee.[[LocalName]],那么
        1. ee 附加到 localExportEntries
      2. 否则,
        1. ieimportEntries[[LocalName]]ee.[[LocalName]] 的元素。
        2. 如果 ie.[[ImportName]]namespace-object,那么
          1. 注:这是对导入模块命名空间对象的重新导出。
          2. ee 附加到 localExportEntries
        3. 否则,
          1. 注:这是对单个名称的重新导出。
          2. ExportEntry Record { [[ModuleRequest]]: ie.[[ModuleRequest]], [[ImportName]]: ie.[[ImportName]], [[LocalName]]: null, [[ExportName]]: ee.[[ExportName]] } 附加到 indirectExportEntries
    2. 否则如果 ee.[[ImportName]]all-but-default,那么
      1. 断言ee.[[ExportName]]null
      2. ee 附加到 starExportEntries
    3. 否则,
      1. ee 附加到 indirectExportEntries
  11. asyncbody Contains await
  12. 返回 源文本模块记录 { [[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, [[DFSIndex]]: empty, [[DFSAncestorIndex]]: empty }。

实现可能在对该模块源文本求值 ParseModule 之前解析模块源文本并分析其早期错误条件。然而,任何错误的报告都必须推迟到本规范实际对该源文本执行 ParseModule 的时刻。

16.2.1.7.2 模块记录抽象方法的实现

以下是 源文本模块记录的具体方法,实现了 表 44 中定义的相应 模块记录抽象方法。

16.2.1.7.2.1 GetExportedNames ( [ exportStarSet ] )

源文本模块记录 module 的 GetExportedNames 具体方法接受可选参数 exportStarSet(一个包含 源文本模块记录列表),返回一个包含字符串的 列表。调用时执行以下步骤:

  1. 断言module.[[Status]] 不是 new
  2. 如果 exportStarSet 不存在,设 exportStarSet 为一个新的空 列表
  3. 如果 exportStarSet 包含 module,那么
    1. 断言:我们已达到 export * 循环的起点。
    2. 返回一个新的空 列表
  4. module 附加到 exportStarSet
  5. exportedNames 为一个新的空 列表
  6. 对于 module.[[LocalExportEntries]] 中的每个 ExportEntry Record e,执行
    1. 断言module 为此导出提供直接绑定。
    2. 断言e.[[ExportName]] 不是 null
    3. e.[[ExportName]] 附加到 exportedNames
  7. 对于 module.[[IndirectExportEntries]] 中的每个 ExportEntry Record e,执行
    1. 断言module 为此导出导入特定绑定。
    2. 断言e.[[ExportName]] 不是 null
    3. e.[[ExportName]] 附加到 exportedNames
  8. 对于 module.[[StarExportEntries]] 中的每个 ExportEntry Record e,执行
    1. 断言e.[[ModuleRequest]] 不是 null
    2. requestedModuleGetImportedModule(module, e.[[ModuleRequest]])。
    3. starNamesrequestedModule.GetExportedNames(exportStarSet)。
    4. 对于 starNames 的每个元素 n,执行
      1. 如果 n 不是 "default",那么
        1. 如果 exportedNames 不包含 n,那么
          1. n 附加到 exportedNames
  9. 返回 exportedNames

GetExportedNames 不会过滤掉或为具有歧义星号导出绑定的名称抛出异常。

16.2.1.7.2.2 ResolveExport ( exportName [ , resolveSet ] )

源文本模块记录 module 的 ResolveExport 具体方法接受参数 exportName(一个字符串)和可选参数 resolveSet(一个包含字段 [[Module]](一个 模块记录)和 [[ExportName]](一个字符串)的 记录列表),返回一个 ResolvedBinding Recordnullambiguous

ResolveExport 尝试将导入绑定解析为实际的定义模块和本地绑定名称。定义模块可能是调用此方法的 模块记录所表示的模块,或该模块导入的其他模块。参数 resolveSet 用于检测未解析的循环导入/导出路径。如果到达的特定 模块记录exportName 的配对已在 resolveSet 中,则遇到了导入循环。在递归调用 ResolveExport 之前,由 moduleexportName 组成的配对会添加到 resolveSet

如果找到定义模块,返回一个 ResolvedBinding Record { [[Module]], [[BindingName]] }。此记录标识最初请求导出的已解析绑定,除非这是没有本地绑定的命名空间导出。在这种情况下,[[BindingName]] 将设置为 namespace。如果没有找到定义或请求被发现是循环的,返回 null。如果请求被发现是歧义的,返回 ambiguous

调用时执行以下步骤:

  1. 断言module.[[Status]] 不是 new
  2. 如果 resolveSet 不存在,设 resolveSet 为一个新的空 列表
  3. 对于 resolveSet 中的每个 记录 { [[Module]], [[ExportName]] } r,执行
    1. 如果 moduler.[[Module]] 是同一个 模块记录exportNamer.[[ExportName]],那么
      1. 断言:这是一个循环导入请求。
      2. 返回 null
  4. 记录 { [[Module]]: module, [[ExportName]]: exportName } 附加到 resolveSet
  5. 对于 module.[[LocalExportEntries]] 中的每个 ExportEntry Record e,执行
    1. 如果 e.[[ExportName]]exportName,那么
      1. 断言module 为此导出提供直接绑定。
      2. 返回 ResolvedBinding Record { [[Module]]: module, [[BindingName]]: e.[[LocalName]] }。
  6. 对于 module.[[IndirectExportEntries]] 中的每个 ExportEntry Record e,执行
    1. 如果 e.[[ExportName]]exportName,那么
      1. 断言e.[[ModuleRequest]] 不是 null
      2. importedModuleGetImportedModule(module, e.[[ModuleRequest]])。
      3. 如果 e.[[ImportName]]all,那么
        1. 断言module 不为此导出提供直接绑定。
        2. 返回 ResolvedBinding Record { [[Module]]: importedModule, [[BindingName]]: namespace }。
      4. 否则,
        1. 断言module 为此导出导入特定绑定。
        2. 断言e.[[ImportName]] 是一个字符串
        3. 返回 importedModule.ResolveExport(e.[[ImportName]], resolveSet)。
  7. 如果 exportName"default",那么
    1. 断言:此模块没有显式定义 default 导出。
    2. 返回 null
    3. 注:default 导出不能由 export * from "mod" 声明提供。
  8. starResolutionnull
  9. 对于 module.[[StarExportEntries]] 中的每个 ExportEntry Record e,执行
    1. 断言e.[[ModuleRequest]] 不是 null
    2. importedModuleGetImportedModule(module, e.[[ModuleRequest]])。
    3. resolutionimportedModule.ResolveExport(exportName, resolveSet)。
    4. 如果 resolutionambiguous,返回 ambiguous
    5. 如果 resolution 不是 null,那么
      1. 断言resolution 是一个 ResolvedBinding Record
      2. 如果 starResolutionnull,那么
        1. starResolutionresolution
      3. 否则,
        1. 断言:有多个包含请求名称的 * 导入。
        2. 如果 resolution.[[Module]]starResolution.[[Module]] 不是同一个 模块记录,返回 ambiguous
        3. 如果 resolution.[[BindingName]] 不是 starResolution.[[BindingName]]resolution.[[BindingName]]starResolution.[[BindingName]] 中的任一个是 namespace,返回 ambiguous
        4. 如果 resolution.[[BindingName]] 是一个字符串starResolution.[[BindingName]] 是一个字符串,且 resolution.[[BindingName]] 不是 starResolution.[[BindingName]],返回 ambiguous
  10. 返回 starResolution

16.2.1.7.3 循环模块记录抽象方法的实现

以下是 源文本模块记录的具体方法,实现了 表 46 中定义的相应 循环模块记录抽象方法。

16.2.1.7.3.1 InitializeEnvironment ( )

源文本模块记录 module 的 InitializeEnvironment 具体方法不接受参数,返回 包含 unused 的正常完成,或 抛出完成。调用时执行以下步骤:

  1. 对于 module.[[IndirectExportEntries]] 中的每个 ExportEntry Record e,执行
    1. 断言e.[[ExportName]] 不是 null
    2. resolutionmodule.ResolveExport(e.[[ExportName]])。
    3. 如果 resolutionnullambiguous,抛出 SyntaxError 异常。
    4. 断言resolution 是一个 ResolvedBinding Record
  2. 断言module 的所有命名导出都是可解析的。
  3. realmmodule.[[Realm]]
  4. 断言realm 不是 undefined
  5. envNewModuleEnvironment(realm.[[GlobalEnv]])。
  6. module.[[Environment]]env
  7. 对于 module.[[ImportEntries]] 中的每个 ImportEntry Record in,执行
    1. importedModuleGetImportedModule(module, in.[[ModuleRequest]])。
    2. 如果 in.[[ImportName]]namespace-object,那么
      1. namespaceGetModuleNamespace(importedModule)。
      2. 执行 ! env.CreateImmutableBinding(in.[[LocalName]], true)。
      3. 执行 ! env.InitializeBinding(in.[[LocalName]], namespace)。
    3. 否则,
      1. resolutionimportedModule.ResolveExport(in.[[ImportName]])。
      2. 如果 resolutionnullambiguous,抛出 SyntaxError 异常。
      3. 如果 resolution.[[BindingName]]namespace,那么
        1. namespaceGetModuleNamespace(resolution.[[Module]])。
        2. 执行 ! env.CreateImmutableBinding(in.[[LocalName]], true)。
        3. 执行 ! env.InitializeBinding(in.[[LocalName]], namespace)。
      4. 否则,
        1. 执行 CreateImportBinding(env, in.[[LocalName]], resolution.[[Module]], resolution.[[BindingName]])。
  8. moduleContext 为一个新的 ECMAScript 代码执行上下文
  9. moduleContext 的 Function 为 null
  10. 断言module.[[Realm]] 不是 undefined
  11. moduleContextRealmmodule.[[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. varDeclarationscodeVarScopedDeclarations
  20. declaredVarNames 为一个新的空 列表
  21. 对于 varDeclarations 的每个元素 d,执行
    1. 对于 dBoundNames 的每个元素 dn,执行
      1. 如果 declaredVarNames 不包含 dn,那么
        1. 执行 ! env.CreateMutableBinding(dn, false)。
        2. 执行 ! env.InitializeBinding(dn, undefined)。
        3. dn 附加到 declaredVarNames
  22. lexDeclarationscodeLexicallyScopedDeclarations
  23. privateEnvnull
  24. 对于 lexDeclarations 的每个元素 d,执行
    1. 对于 dBoundNames 的每个元素 dn,执行
      1. 如果 dIsConstantDeclarationtrue,那么
        1. 执行 ! env.CreateImmutableBinding(dn, true)。
      2. 否则,
        1. 执行 ! env.CreateMutableBinding(dn, false)。
      3. 如果 dFunctionDeclarationGeneratorDeclarationAsyncFunctionDeclarationAsyncGeneratorDeclaration,那么
        1. fodInstantiateFunctionObject,参数为 envprivateEnv
        2. 执行 ! env.InitializeBinding(dn, fo)。
  25. 执行上下文栈 中移除 moduleContext
  26. 返回 unused

16.2.1.7.3.2 ExecuteModule ( [ capability ] )

源文本模块记录 module 的 ExecuteModule 具体方法接受可选参数 capability(一个 PromiseCapability Record),返回 包含 unused 的正常完成,或 抛出完成。调用时执行以下步骤:

  1. moduleContext 为一个新的 ECMAScript 代码执行上下文
  2. moduleContext 的 Function 为 null
  3. moduleContextRealmmodule.[[Realm]]
  4. moduleContext 的 ScriptOrModule 为 module
  5. 断言module 已被链接,其模块环境中的声明已被实例化。
  6. moduleContext 的 VariableEnvironment 为 module.[[Environment]]
  7. moduleContext 的 LexicalEnvironment 为 module.[[Environment]]
  8. 暂停 运行的执行上下文
  9. 如果 module.[[HasTLA]]false,那么
    1. 断言capability 不存在。
    2. moduleContext 压入 执行上下文栈moduleContext 现在是 运行的执行上下文
    3. resultCompletion(module.[[ECMAScriptCode]]Evaluation)。
    4. 暂停 moduleContext 并从 执行上下文栈 中移除它。
    5. 恢复现在位于 执行上下文栈 顶部的上下文作为 运行的执行上下文
    6. 如果 result 是一个 异常完成,那么
      1. 返回 ? result
  10. 否则,
    1. 断言capability 是一个 PromiseCapability Record
    2. 执行 AsyncBlockStart(capability, module.[[ECMAScriptCode]], moduleContext)。
  11. 返回 unused

16.2.1.8 合成模块记录

合成模块记录用于表示由规范定义的模块的信息。其导出名称在创建时静态定义,而其对应的值可以通过 SetSyntheticModuleExport 随时间变化。它没有导入或依赖项。

合成模块记录可用于定义各种模块类型:例如,JSON 模块或 CSS 模块。

除了 表 43 中定义的字段外,合成模块记录还具有 表 62 中列出的附加字段。

表 62:合成模块记录的附加字段
字段名称 值类型 含义
[[ExportNames]] 字符串的 列表 模块的导出名称。此列表不包含重复项。
[[EvaluationSteps]] 一个 抽象闭包 在模块求值时执行的初始化逻辑,以 合成模块记录作为其唯一参数。它不得修改 [[ExportNames]]。它可能返回一个 异常完成

16.2.1.8.1 CreateDefaultExportSyntheticModule ( defaultExport )

抽象操作 CreateDefaultExportSyntheticModule 接受参数 defaultExport(一个 ECMAScript 语言值),返回一个 合成模块记录。它创建一个默认导出为 defaultExport合成模块记录。调用时执行以下步骤:

  1. realm当前 Realm Record
  2. setDefaultExport 为一个新的 抽象闭包,参数为 (module),捕获 defaultExport 并在调用时执行以下步骤:
    1. 执行 SetSyntheticModuleExport(module, "default", defaultExport)。
    2. 返回 NormalCompletion(unused)。
  3. 返回 合成模块记录 { [[Realm]]: realm, [[Environment]]: empty, [[Namespace]]: empty, [[HostDefined]]: undefined, [[ExportNames]]: « "default" », [[EvaluationSteps]]: setDefaultExport }。

16.2.1.8.2 ParseJSONModule ( source )

抽象操作 ParseJSONModule 接受参数 source(一个字符串),返回 包含一个 合成模块记录的正常完成,或 抛出完成。调用时执行以下步骤:

  1. json 为 ? ParseJSON(source)。
  2. 返回 CreateDefaultExportSyntheticModule(json)。

16.2.1.8.3 SetSyntheticModuleExport ( module, exportName, exportValue )

抽象操作 SetSyntheticModuleExport 接受参数 module(一个 合成模块记录)、exportName(一个字符串)和 exportValue(一个 ECMAScript 语言值),返回 unused。它可用于设置或更改 合成模块记录现有导出的导出值。调用时执行以下步骤:

  1. 断言module.[[ExportNames]] 包含 exportName
  2. envRecmodule.[[Environment]]
  3. 断言envRec 不是 empty
  4. 执行 envRec.SetMutableBinding(exportName, exportValue, true)。
  5. 返回 unused

16.2.1.8.4 模块记录抽象方法的实现

以下是 合成模块记录的具体方法,实现了 表 44 中定义的相应 模块记录抽象方法。

16.2.1.8.4.1 LoadRequestedModules ( )

合成模块记录 module 的 LoadRequestedModules 具体方法不接受参数,返回一个 Promise。调用时执行以下步骤:

  1. 返回 ! PromiseResolve(%Promise%, undefined)。
合成模块记录没有依赖项。

16.2.1.8.4.2 GetExportedNames ( )

合成模块记录 module 的 GetExportedNames 具体方法不接受参数,返回一个包含字符串的 列表。调用时执行以下步骤:

  1. 返回 module.[[ExportNames]]

16.2.1.8.4.3 ResolveExport ( exportName )

合成模块记录 module 的 ResolveExport 具体方法接受参数 exportName(一个字符串),返回一个 ResolvedBinding Recordnull。调用时执行以下步骤:

  1. 如果 module.[[ExportNames]] 不包含 exportName,返回 null
  2. 返回 ResolvedBinding Record { [[Module]]: module, [[BindingName]]: exportName }。

16.2.1.8.4.4 Link ( )

合成模块记录 module 的 Link 具体方法不接受参数,返回 包含 unused 的正常完成。调用时执行以下步骤:

  1. realmmodule.[[Realm]]
  2. envNewModuleEnvironment(realm.[[GlobalEnv]])。
  3. module.[[Environment]]env
  4. 对于 module.[[ExportNames]] 的每个字符串 exportName,执行
    1. 执行 ! env.CreateMutableBinding(exportName, false)。
    2. 执行 ! env.InitializeBinding(exportName, undefined)。
  5. 返回 NormalCompletion(unused)。

16.2.1.8.4.5 Evaluate ( )

合成模块记录 module 的 Evaluate 具体方法不接受参数,返回一个 Promise。调用时执行以下步骤:

  1. moduleContext 为一个新的 ECMAScript 代码执行上下文
  2. moduleContext 的 Function 为 null
  3. moduleContextRealmmodule.[[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. pc 为 ! NewPromiseCapability(%Promise%)。
  14. IfAbruptRejectPromise(result, pc)。
  15. 执行 ! Call(pc.[[Resolve]], undefined, « undefined »)。
  16. 返回 pc.[[Promise]]

16.2.1.9 GetImportedModule ( referrer, request )

抽象操作 GetImportedModule 接受参数 referrer(一个 循环模块记录)和 request(一个 ModuleRequest Record),返回一个 模块记录。调用时执行以下步骤:

  1. records 为一个 列表,由 referrer.[[LoadedModules]] 中满足 ModuleRequestsEqual(r, request) 为 true 的每个 LoadedModuleRequest Record r 组成。
  2. 断言records 恰好有一个元素,因为在调用此抽象操作之前,LoadRequestedModules 已在 referrer 上成功完成。
  3. recordrecords 的唯一元素。
  4. 返回 record.[[Module]]

16.2.1.10 HostLoadImportedModule ( referrer, moduleRequest, hostDefined, payload )

宿主定义的抽象操作 HostLoadImportedModule 接受参数 referrer(一个 脚本记录、一个 循环模块记录或一个 Realm Record)、moduleRequest(一个 ModuleRequest Record)、hostDefined(任何值)和 payload(一个 GraphLoadingState Record 或一个 PromiseCapability Record),返回 unused

注 1

referrer 可以是 Realm Record 的一个例子是在 Web 浏览器 宿主中。在那里,如果用户点击由以下代码给出的控件

<button type="button" onclick="import('./foo.mjs')">Click me</button>

import() 表达式运行时,将没有 活动脚本或模块。更一般地,这可能发生在 宿主将具有 null ScriptOrModule 组件的 执行上下文推入 执行上下文栈的任何情况下。

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

执行的实际过程是 宿主定义的,但通常包括执行加载适当的 模块记录所需的任何 I/O 操作。多个不同的 (referrer, moduleRequest.[[Specifier]], moduleRequest.[[Attributes]]) 三元组可能映射到同一个 模块记录实例。实际的映射语义是 宿主定义的,但通常作为映射过程的一部分,会对 specifier 应用规范化过程。典型的规范化过程包括扩展相对和缩写路径说明符等操作。

注 2

上述文本要求 宿主在使用 type: "json" 导入时支持 JSON 模块(并且 HostLoadImportedModule 正常完成),但它不禁止 宿主在不使用 type: "json" 导入时支持 JSON 模块。

16.2.1.11 FinishLoadingImportedModule ( referrer, moduleRequest, payload, result )

抽象操作 FinishLoadingImportedModule 接受参数 referrer(一个 脚本记录、一个 循环模块记录或一个 Realm Record)、moduleRequest(一个 ModuleRequest Record)、payload(一个 GraphLoadingState Record 或一个 PromiseCapability Record)和 result包含一个 模块记录的正常完成或 抛出完成),返回 unused。调用时执行以下步骤:

  1. 如果 result正常完成,那么
    1. 如果 referrer.[[LoadedModules]] 包含一个 LoadedModuleRequest Record record,使得 ModuleRequestsEqual(record, moduleRequest) 为 true,那么
      1. 断言record.[[Module]]result.[[Value]] 是同一个 模块记录
    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 ( attributes )

抽象操作 AllImportAttributesSupported 接受参数 attributes(一个包含 ImportAttribute Records列表),返回一个布尔值。调用时执行以下步骤:

  1. supportedHostGetSupportedImportAttributes()。
  2. 对于 attributes 的每个 ImportAttribute Record attribute,执行
    1. 如果 supported 不包含 attribute.[[Key]],返回 false
  3. 返回 true

16.2.1.12.1 HostGetSupportedImportAttributes ( )

宿主定义的抽象操作 HostGetSupportedImportAttributes 不接受参数,返回一个包含字符串的 列表。它允许 宿主环境指定它们支持的导入属性。只有具有受支持键的属性才会提供给 宿主

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

  • 它必须返回一个包含字符串的 列表,每个字符串表示一个受支持的属性。
  • 每次调用此操作时,它必须返回相同的 列表,包含相同顺序的相同内容。

HostGetSupportedImportAttributes 的默认实现是返回一个新的空 列表

要求 宿主指定其受支持的导入属性,而不是将所有属性传递给 宿主并让其选择要处理哪些属性的目的,是确保不受支持的属性在不同 宿主之间以一致的方式处理。

16.2.1.13 GetModuleNamespace ( module )

抽象操作 GetModuleNamespace 接受参数 module模块记录具体子类的实例),返回一个模块命名空间对象。它检索表示 module 导出的模块命名空间对象,在第一次请求时惰性创建它,并将其存储在 module.[[Namespace]] 中以供将来检索。调用时执行以下步骤:

  1. 断言:如果 module循环模块记录,那么 module.[[Status]] 不是 newunlinked
  2. namespacemodule.[[Namespace]]
  3. 如果 namespaceempty,那么
    1. exportedNamesmodule.GetExportedNames()。
    2. unambiguousNames 为一个新的空 列表
    3. 对于 exportedNames 的每个元素 name,执行
      1. resolutionmodule.ResolveExport(name)。
      2. 如果 resolutionResolvedBinding Record,将 name 附加到 unambiguousNames
    4. namespaceModuleNamespaceCreate(module, unambiguousNames)。
  4. 返回 namespace

GetModuleNamespace 永远不会抛出异常。相反,无法解析的名称在此时简单地从命名空间中排除。除非它们都是未在任何地方明确请求的歧义星号导出,否则稍后会导致真正的链接错误。

16.2.1.14 运行时语义:求值

Module : [empty]
  1. 返回 undefined
ModuleBody : ModuleItemList
  1. resultCompletion(ModuleItemList求值)。
  2. 如果 result正常完成result.[[Value]]empty,那么
    1. 返回 undefined
  3. 返回 ? result
ModuleItemList : ModuleItemList ModuleItem
  1. sl 为 ? ModuleItemList求值
  2. sCompletion(ModuleItem求值)。
  3. 返回 ? UpdateEmpty(s, sl)。

ModuleItemList 的值是 ModuleItemList 中最后一个产生值的项的值。

ModuleItem : ImportDeclaration
  1. 返回 empty

16.2.2 导入

语法

ImportDeclaration : import ImportClause FromClause WithClauseopt ; import ModuleSpecifier WithClauseopt ; ImportClause : ImportedDefaultBinding NameSpaceImport NamedImports ImportedDefaultBinding , NameSpaceImport ImportedDefaultBinding , NamedImports ImportedDefaultBinding : ImportedBinding NameSpaceImport : * as ImportedBinding NamedImports : { } { ImportsList } { 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 静态语义:早期错误

ModuleItem : ImportDeclaration WithClause : with { WithEntries ,opt }

16.2.2.2 静态语义:ImportEntries

语法导向操作 ImportEntries 不接受参数,返回一个包含 ImportEntry Records列表。它在以下产生式上分段定义:

Module : [empty]
  1. 返回一个新的空 列表
ModuleItemList : ModuleItemList ModuleItem
  1. entries1ModuleItemListImportEntries
  2. entries2ModuleItemImportEntries
  3. 返回 entries1entries2列表连接
ModuleItem : ExportDeclaration StatementListItem
  1. 返回一个新的空 列表
ImportDeclaration : import ImportClause FromClause WithClauseopt ;
  1. moduleImportDeclarationModuleRequests 的唯一元素。
  2. 返回 ImportClause 以参数 moduleImportEntriesForModule
ImportDeclaration : import ModuleSpecifier WithClauseopt ;
  1. 返回一个新的空 列表

16.2.2.3 静态语义:ImportEntriesForModule

语法导向操作 ImportEntriesForModule 接受参数 module(一个 ModuleRequest Record),返回一个包含 ImportEntry Records列表。它在以下产生式上分段定义:

ImportClause : ImportedDefaultBinding , NameSpaceImport
  1. entries1ImportedDefaultBinding 以参数 moduleImportEntriesForModule
  2. entries2NameSpaceImport 以参数 moduleImportEntriesForModule
  3. 返回 entries1entries2列表连接
ImportClause : ImportedDefaultBinding , NamedImports
  1. entries1ImportedDefaultBinding 以参数 moduleImportEntriesForModule
  2. entries2NamedImports 以参数 moduleImportEntriesForModule
  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-object, [[LocalName]]: localName }。
  3. 返回 « entry »。
NamedImports : { }
  1. 返回一个新的空 列表
ImportsList : ImportsList , ImportSpecifier
  1. specs1ImportsList 以参数 moduleImportEntriesForModule
  2. specs2ImportSpecifier 以参数 moduleImportEntriesForModule
  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 静态语义:WithClauseToAttributes

语法导向操作 WithClauseToAttributes 不接受参数,返回一个包含 ImportAttribute Records列表。它在以下产生式上分段定义:

WithClause : with { }
  1. 返回一个新的空 列表
WithClause : with { WithEntries ,opt }
  1. attributesWithEntriesWithClauseToAttributes
  2. 根据 attributes[[Key]] 字段的字典序对其进行排序,将每个这样的字段值视为 UTF-16 代码单元值的序列。注:此排序仅在禁止 宿主根据属性枚举的顺序改变行为时可观察到。
  3. 返回 attributes
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 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 静态语义:早期错误

ExportDeclaration : export NamedExports ;

上述规则意味着 NamedExports 的每个 ReferencedBindings 都被视为 IdentifierReference

16.2.3.2 静态语义:ExportedBindings

语法导向操作 ExportedBindings 不接受参数,返回一个字符串 列表

ExportedBindings 是与 ModuleExportedNames 明确关联的本地绑定名称。

它在以下产生式上分段定义:

ModuleItemList : ModuleItemList ModuleItem
  1. names1ModuleItemListExportedBindings
  2. names2ModuleItemExportedBindings
  3. 返回 names1names2列表连接
ModuleItem : ImportDeclaration StatementListItem
  1. 返回一个新的空 列表
ExportDeclaration : export ExportFromClause FromClause WithClauseopt ;
  1. 返回一个新的空 列表
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. 返回一个新的空 列表
ExportsList : ExportsList , ExportSpecifier
  1. names1ExportsListExportedBindings
  2. names2ExportSpecifierExportedBindings
  3. 返回 names1names2列表连接
ExportSpecifier : ModuleExportName
  1. 返回一个 列表,其唯一元素是 ModuleExportNameStringValue
ExportSpecifier : ModuleExportName as ModuleExportName
  1. 返回一个 列表,其唯一元素是第一个 ModuleExportNameStringValue

16.2.3.3 静态语义:ExportedNames

语法导向操作 ExportedNames 不接受参数,返回一个字符串 列表

ExportedNames 是 Module 明确映射到其本地名称绑定之一的外部可见名称。

它在以下产生式上分段定义:

ModuleItemList : ModuleItemList ModuleItem
  1. names1ModuleItemListExportedNames
  2. names2ModuleItemExportedNames
  3. 返回 names1names2列表连接
ModuleItem : ExportDeclaration
  1. 返回 ExportDeclarationExportedNames
ModuleItem : ImportDeclaration StatementListItem
  1. 返回一个新的空 列表
ExportDeclaration : export ExportFromClause FromClause WithClauseopt ;
  1. 返回 ExportFromClauseExportedNames
ExportFromClause : *
  1. 返回一个新的空 列表
ExportFromClause : * as ModuleExportName
  1. 返回一个 列表,其唯一元素是 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. 返回一个新的空 列表
ExportsList : ExportsList , ExportSpecifier
  1. names1ExportsListExportedNames
  2. names2ExportSpecifierExportedNames
  3. 返回 names1names2列表连接
ExportSpecifier : ModuleExportName
  1. 返回一个 列表,其唯一元素是 ModuleExportNameStringValue
ExportSpecifier : ModuleExportName as ModuleExportName
  1. 返回一个 列表,其唯一元素是第二个 ModuleExportNameStringValue

16.2.3.4 静态语义:ExportEntries

语法导向操作 ExportEntries 不接受参数,返回一个包含 ExportEntry Records列表。它在以下产生式上分段定义:

Module : [empty]
  1. 返回一个新的空 列表
ModuleItemList : ModuleItemList ModuleItem
  1. entries1ModuleItemListExportEntries
  2. entries2ModuleItemExportEntries
  3. 返回 entries1entries2列表连接
ModuleItem : ImportDeclaration StatementListItem
  1. 返回一个新的空 列表
ExportDeclaration : export ExportFromClause FromClause WithClauseopt ;
  1. moduleExportDeclarationModuleRequests 的唯一元素。
  2. 返回 ExportFromClause 以参数 moduleExportEntriesForModule
ExportDeclaration : export NamedExports ;
  1. 返回 NamedExports 以参数 nullExportEntriesForModule
ExportDeclaration : export VariableStatement
  1. entries 为一个新的空 列表
  2. namesVariableStatementBoundNames
  3. 对于 names 的每个元素 name,执行
    1. ExportEntry Record { [[ModuleRequest]]: null, [[ImportName]]: null, [[LocalName]]: name, [[ExportName]]: name } 追加到 entries
  4. 返回 entries
ExportDeclaration : export Declaration
  1. entries 为一个新的空 列表
  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. 返回一个 列表,其唯一元素是一个新的 ExportEntry Record { [[ModuleRequest]]: null, [[ImportName]]: null, [[LocalName]]: localName, [[ExportName]]: "default" }。
ExportDeclaration : export default ClassDeclaration
  1. namesClassDeclarationBoundNames
  2. localNamenames 的唯一元素。
  3. 返回一个 列表,其唯一元素是一个新的 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 »。

"*default*" 在本规范中用作匿名默认导出值的合成名称。详见 此注释

16.2.3.5 静态语义:ExportEntriesForModule

语法导向操作 ExportEntriesForModule 接受参数 module(一个 ModuleRequest Recordnull)并返回一个包含 ExportEntry Records列表。它在以下产生式上分段定义:

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]]: all, [[LocalName]]: null, [[ExportName]]: exportName }。
  3. 返回 « entry »。
NamedExports : { }
  1. 返回一个新的空 列表
ExportsList : ExportsList , ExportSpecifier
  1. specs1ExportsList 以参数 moduleExportEntriesForModule
  2. specs2ExportSpecifier 以参数 moduleExportEntriesForModule
  3. 返回 specs1specs2列表连接
ExportSpecifier : ModuleExportName
  1. sourceNameModuleExportNameStringValue
  2. 如果 modulenull,那么
    1. localNamesourceName
    2. importNamenull
  3. 否则,
    1. localNamenull
    2. importNamesourceName
  4. 返回一个 列表,其唯一元素是一个新的 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. 返回一个 列表,其唯一元素是一个新的 ExportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: importName, [[LocalName]]: localName, [[ExportName]]: exportName }。

16.2.3.6 静态语义:ReferencedBindings

语法导向操作 ReferencedBindings 不接受参数,返回一个包含 解析节点列表。它在以下产生式上分段定义:

NamedExports : { }
  1. 返回一个新的空 列表
ExportsList : ExportsList , ExportSpecifier
  1. names1ExportsListReferencedBindings
  2. names2ExportSpecifierReferencedBindings
  3. 返回 names1names2列表连接
ExportSpecifier : ModuleExportName as ModuleExportName
  1. 返回第一个 ModuleExportNameReferencedBindings
ModuleExportName : IdentifierName
  1. 返回一个 列表,其唯一元素是 IdentifierName
ModuleExportName : StringLiteral
  1. 返回一个 列表,其唯一元素是 StringLiteral

16.2.3.7 运行时语义: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. env正在运行的执行上下文 的 LexicalEnvironment。
    2. 执行 ? InitializeBoundName("*default*", value, env)。
  4. 返回 empty
ExportDeclaration : export default AssignmentExpression ;
  1. 如果 IsAnonymousFunctionDefinition(AssignmentExpression) 是 true,那么
    1. value 为 ? AssignmentExpression 以参数 "default"NamedEvaluation
  2. 否则,
    1. rhs 为 ? AssignmentExpressionEvaluation
    2. value 为 ? GetValue(rhs)。
  3. env正在运行的执行上下文 的 LexicalEnvironment。
  4. 执行 ? InitializeBoundName("*default*", value, env)。
  5. 返回 empty

17 错误处理和语言扩展

实现必须在评估相关的 ECMAScript 语言结构时报告大部分错误。早期错误是可以在评估包含错误的 Script 中的任何结构之前检测和报告的错误。早期错误的存在会阻止结构的评估。实现必须在 ParseScript 中解析 Script 时报告 Script 中的 早期错误Module 中的 早期错误Module 将要被评估的时候报告,并且 Module 永远不会被初始化。eval 代码中的 早期错误在调用 eval 时报告,并阻止 eval 代码的评估。所有不是 早期错误的错误都是运行时错误。

实现必须将本规范的"静态语义:早期错误"子条款中列出的任何条件的出现报告为 早期错误

即使编译器可以证明结构在任何情况下都不能无错误地执行,实现也不应将其他类型的错误视为 早期错误。实现可以在这种情况下发出早期警告,但它不应该在相关结构实际执行之前报告错误。

实现应按规定报告所有错误,除了以下情况:

17.1 禁止的扩展

实现不得以以下方式扩展本规范:

18 ECMAScript 标准内置对象

每当 ECMAScript ScriptModule 开始执行时,都有某些内置对象可用。其中,全局对象是执行程序的全局环境的一部分。其他对象可以作为 全局对象的初始属性访问,或者作为可访问的内置对象的属性间接访问。

除非另有规定,可作为函数调用的内置对象是内置 函数对象,具有 10.3 中描述的特性。除非另有规定,内置对象的 [[Extensible]] 内部插槽最初具有值 true。每个内置 函数对象都有一个 [[Realm]] 内部插槽,其值是对象最初为其创建的 境界Realm Record

许多内置对象都是函数:它们可以用参数调用。其中一些还是 构造器:它们是用于与 new 操作符一起使用的函数。对于每个内置函数,本规范描述了该函数所需的参数和该 函数对象的属性。对于每个内置 构造器,本规范还描述了该 构造器的原型对象的属性以及调用该 构造器new 表达式返回的特定对象实例的属性。

除非在特定函数的描述中另有规定,如果内置函数或 构造器给定的参数少于函数指定要求的参数,该函数或 构造器的行为应完全如同已给定了足够的附加参数,每个这样的参数都是 undefined 值。这样的缺失参数被认为是"不存在的",并且可以通过规范算法以这种方式识别。在特定函数的描述中,术语"this 值"和"NewTarget"具有 10.3 中给出的含义。

除非在特定函数的描述中另有规定,如果所描述的内置函数或 构造器给定的参数比函数指定允许的更多,则额外的参数由调用评估然后被函数忽略。但是,实现可以定义与这些参数相关的实现特定行为,只要该行为不是简单基于额外参数存在而抛出 TypeError 异常。

注 1

鼓励向内置函数集添加附加功能的实现通过添加新函数而不是向现有函数添加新参数来实现。

除非另有规定,每个内置函数和每个内置 构造器都将 Function 原型对象作为其 [[Prototype]] 内部插槽的值,该对象是表达式 Function.prototype20.2.3)的初始值。

除非另有规定,每个内置原型对象都将 Object 原型对象作为其 [[Prototype]] 内部插槽的值,该对象是表达式 Object.prototype20.1.3)的初始值,除了 Object 原型对象本身。

如果本规范通过算法步骤定义内置 构造器的行为,那么这就是它在 [[Call]][[Construct]] 目的上的行为。如果这样的算法需要区分这两种情况,它会检查 NewTarget 是否为 undefined,这表示 [[Call]] 调用。

未被标识为 构造器的内置 函数对象不实现 [[Construct]] 内部方法,除非在特定函数的描述中另有规定。

不是 构造器的内置 函数对象没有 "prototype" 属性,除非在特定函数的描述中另有规定。

本规范中定义的每个内置函数都是通过调用 CreateBuiltinFunction 抽象操作(10.3.4)创建的。lengthname 参数的值是 "length""name" 属性的初始值,如下所述。prefix 参数的值也在下面类似地讨论。

每个内置 函数对象,包括 构造器,都有一个 "length" 属性,其值是非负的 整数。除非另有规定,此值是函数描述的子条款标题中显示的必需参数数。可选参数和剩余参数不包括在参数计数中。

注 2

例如,Array 原型对象"map" 属性的初始值的 函数对象在子条款标题"Array.prototype.map (callback [ , thisArg])"下描述,显示了两个命名参数 callback 和 thisArg,后者是可选的;因此该 函数对象"length" 属性的值是 1𝔽

除非另有规定,内置 函数对象"length" 属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

每个内置 函数对象,包括 构造器,都有一个 "name" 属性,其值 是一个字符串。除非另有规定,此值是本规范中给予函数的名称。被标识为匿名函数的函数使用空字符串作为 "name" 属性的值。对于被指定为对象属性的函数,名称值是用于访问函数的 属性名字符串。被指定为内置属性的 get 或 set 访问器函数的函数在调用 CreateBuiltinFunction 时将 "get""set"(分别)传递给 prefix 参数。

对于 属性键 是 Symbol 值的每个内置函数,"name" 属性的值被显式指定。如果这样的显式指定值以前缀 "get ""set " 开头,并且为其指定的函数是内置属性的 get 或 set 访问器函数,则不带前缀的值传递给 name 参数,并且值 "get""set"(分别)在调用 CreateBuiltinFunction 时传递给 prefix 参数。

除非另有规定,内置 函数对象"name" 属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

条款 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 ( x )

此函数是 %eval% 内置对象。

当被调用时执行以下步骤:

  1. 返回 ? PerformEval(x, false, false)。

19.2.1.1 PerformEval ( x, strictCaller, direct )

抽象操作 PerformEval 接受参数 x(一个 ECMAScript 语言值)、strictCaller(一个布尔值)和 direct(一个布尔值),返回一个包含 ECMAScript 语言值正常完成或一个 抛出完成。当被调用时执行以下步骤:

  1. 断言:如果 directfalse,那么 strictCaller 也是 false
  2. 如果 x 不是字符串,返回 x
  3. evalRealm当前 Realm Record
  4. 注:在 直接 eval 的情况下,evalRealmeval 调用者和 eval 函数本身的 境界
  5. 执行 ? HostEnsureCanCompileStrings(evalRealm, « », x, direct)。
  6. inFunctionfalse
  7. inMethodfalse
  8. inDerivedConstructorfalse
  9. inClassFieldInitializerfalse
  10. 如果 directtrue,那么
    1. thisEnvRecGetThisEnvironment()。
    2. 如果 thisEnvRec 是一个 函数环境记录,那么
      1. FthisEnvRec.[[FunctionObject]]
      2. inFunctiontrue
      3. inMethodthisEnvRec.HasSuperBinding()。
      4. 如果 F.[[ConstructorKind]]derived,设 inDerivedConstructortrue
      5. classFieldInitializerNameF.[[ClassFieldInitializerName]]
      6. 如果 classFieldInitializerName 不是 empty,设 inClassFieldInitializertrue
  11. 实现定义的顺序执行以下子步骤,可能交替进行解析和错误检测:
    1. scriptParseText(x, Script)。
    2. 如果 script 是一个错误的 列表,抛出 SyntaxError 异常。
    3. 如果 script Contains ScriptBodyfalse,返回 undefined
    4. bodyscriptScriptBody
    5. 如果 inFunctionfalsebody Contains NewTarget, 抛出 SyntaxError 异常。
    6. 如果 inMethodfalsebody Contains SuperProperty,抛出 SyntaxError 异常。
    7. 如果 inDerivedConstructorfalsebody Contains SuperCall, 抛出 SyntaxError 异常。
    8. 如果 inClassFieldInitializertruebodyContainsArgumentstrue,抛出 SyntaxError 异常。
  12. 如果 strictCallertrue,设 strictEvaltrue
  13. 否则,设 strictEvalscriptScriptIsStrict
  14. runningContext正在运行的执行上下文
  15. 注:如果 directtruerunningContext 将是执行 直接 eval执行上下文。如果 directfalserunningContext 将是调用 eval 函数的 执行上下文
  16. 如果 directtrue,那么
    1. lexEnvNewDeclarativeEnvironment(runningContext 的 LexicalEnvironment)。
    2. varEnvrunningContext 的 VariableEnvironment。
    3. privateEnvrunningContext 的 PrivateEnvironment。
  17. 否则,
    1. lexEnvNewDeclarativeEnvironment(evalRealm.[[GlobalEnv]])。
    2. varEnvevalRealm.[[GlobalEnv]]
    3. privateEnvnull
  18. 如果 strictEvaltrue,设 varEnvlexEnv
  19. 如果 runningContext 尚未挂起,挂起 runningContext
  20. evalContext 为一个新的 ECMAScript 代码执行上下文
  21. evalContext 的 Function 为 null
  22. evalContextRealmevalRealm
  23. evalContext 的 ScriptOrModule 为 runningContext 的 ScriptOrModule。
  24. evalContext 的 VariableEnvironment 为 varEnv
  25. evalContext 的 LexicalEnvironment 为 lexEnv
  26. evalContext 的 PrivateEnvironment 为 privateEnv
  27. evalContext 推入 执行上下文栈evalContext 现在是 正在运行的执行上下文
  28. resultCompletion(EvalDeclarationInstantiation(body, varEnv, lexEnv, privateEnv, strictEval))。
  29. 如果 result 是一个 正常完成,那么
    1. resultCompletion(bodyEvaluation)。
  30. 如果 result 是一个 正常完成result.[[Value]]empty,那么
    1. resultNormalCompletion(undefined)。
  31. 挂起 evalContext 并将其从 执行上下文栈中移除。
  32. 恢复现在位于 执行上下文栈顶部的上下文作为 正在运行的执行上下文
  33. 返回 ? result

如果调用上下文的代码或 eval 代码是 严格模式代码,那么 eval 代码不能在调用 eval 的调用上下文的变量环境中实例化变量或函数绑定。相反,这些绑定在只有 eval 代码可访问的新 VariableEnvironment 中实例化。由 letconstclass 声明引入的绑定总是在新的 LexicalEnvironment 中实例化。

19.2.1.2 HostEnsureCanCompileStrings ( calleeRealm, parameterStrings, bodyString, direct )

宿主定义的抽象操作 HostEnsureCanCompileStrings 接受参数 calleeRealm(一个 Realm Record)、parameterStrings(一个字符串的 列表)、bodyString(一个字符串)和 direct(一个布尔值),返回一个包含 unused正常完成或一个 抛出完成。它允许 宿主环境阻止某些允许开发者将字符串解释和评估为 ECMAScript 代码的 ECMAScript 函数。

parameterStrings 表示在使用函数 构造器之一时将连接在一起以构建参数列表的字符串。bodyString 表示函数体或传递给 eval 调用的字符串。direct 表示评估是否是 直接 eval

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

19.2.1.3 EvalDeclarationInstantiation ( body, varEnv, lexEnv, privateEnv, strict )

抽象操作 EvalDeclarationInstantiation 接受参数 body(一个 ScriptBody 解析节点)、varEnv(一个 环境记录)、lexEnv(一个 声明式环境记录)、privateEnv(一个 私有环境记录null)和 strict(一个布尔值),返回一个包含 unused正常完成或一个 抛出完成。当被调用时执行以下步骤:

  1. varNamesbodyVarDeclaredNames
  2. varDeclarationsbodyVarScopedDeclarations
  3. 如果 strictfalse,那么
    1. 如果 varEnv 是一个 全局环境记录,那么
      1. 对于 varNames 的每个元素 name,执行
        1. 如果 HasLexicalDeclaration(varEnv, name) 是 true,抛出 SyntaxError 异常。
        2. 注:eval 不会创建被全局词法声明遮蔽的全局 var 声明。
    2. thisEnvlexEnv
    3. 断言:以下循环将终止。
    4. 重复,当 thisEnvvarEnv 不是同一个 环境记录时,
      1. 如果 thisEnv 不是对象 环境记录,那么
        1. 注:with 语句的环境不能包含任何词法声明,因此不需要检查 var/let 提升冲突。
        2. 对于 varNames 的每个元素 name,执行
          1. 如果 ! thisEnv.HasBinding(name) 是 true,那么
            1. 抛出 SyntaxError 异常。
            2. 注:附录 B.3.4 为上述步骤定义了替代语义。
          2. 注:直接 eval 不会将 var 声明提升到同名的词法声明之上。
      2. thisEnvthisEnv.[[OuterEnv]]
  4. privateIdentifiers 为一个新的空 列表
  5. pointerprivateEnv
  6. 重复,当 pointer 不是 null 时,
    1. 对于 pointer.[[Names]] 的每个 私有名称 binding,执行
      1. 如果 privateIdentifiers 不包含 binding.[[Description]],将 binding.[[Description]] 添加到 privateIdentifiers
    2. pointerpointer.[[OuterPrivateEnvironment]]
  7. 如果 body 以参数 privateIdentifiersAllPrivateIdentifiersValidfalse,抛出 SyntaxError 异常。
  8. functionsToInitialize 为一个新的空 列表
  9. declaredFunctionNames 为一个新的空 列表
  10. 对于 varDeclarations 的每个元素 d,以反向 列表顺序,执行
    1. 如果 d 不是 VariableDeclarationForBindingBindingIdentifier,那么
      1. 断言dFunctionDeclarationGeneratorDeclarationAsyncFunctionDeclarationAsyncGeneratorDeclaration
      2. 注:如果同一个名称有多个函数声明,使用最后一个声明。
      3. fndBoundNames 的唯一元素。
      4. 如果 declaredFunctionNames 不包含 fn,那么
        1. 如果 varEnv 是一个 全局环境记录,那么
          1. fnDefinable 为 ? CanDeclareGlobalFunction(varEnv, fn)。
          2. 如果 fnDefinablefalse,抛出 TypeError 异常。
        2. fn 添加到 declaredFunctionNames
        3. d 插入为 functionsToInitialize 的第一个元素。
  11. declaredVarNames 为一个新的空 列表
  12. 对于 varDeclarations 的每个元素 d,执行
    1. 如果 dVariableDeclarationForBindingBindingIdentifier,那么
      1. 对于 dBoundNames 的每个字符串 vn,执行
        1. 如果 declaredFunctionNames 不包含 vn,那么
          1. 如果 varEnv 是一个 全局环境记录,那么
            1. vnDefinable 为 ? CanDeclareGlobalVar(varEnv, vn)。
            2. 如果 vnDefinablefalse,抛出 TypeError 异常。
          2. 如果 declaredVarNames 不包含 vn,那么
            1. vn 添加到 declaredVarNames
  13. 注:附录 B.3.2.3 在此处添加额外的步骤。
  14. 注:除非 varEnv 是一个 全局环境记录全局对象是一个 Proxy 异质对象,否则在此算法步骤之后不会发生异常终止。
  15. lexDeclarationsbodyLexicallyScopedDeclarations
  16. 对于 lexDeclarations 的每个元素 d,执行
    1. 注:词法声明的名称仅在此处实例化但不初始化。
    2. 对于 dBoundNames 的每个元素 dn,执行
      1. 如果 dIsConstantDeclarationtrue,那么
        1. 执行 ? lexEnv.CreateImmutableBinding(dn, true)。
      2. 否则,
        1. 执行 ? lexEnv.CreateMutableBinding(dn, false)。
  17. 对于 functionsToInitialize 的每个 解析节点 f,执行
    1. fnfBoundNames 的唯一元素。
    2. fof 以参数 lexEnvprivateEnvInstantiateFunctionObject
    3. 如果 varEnv 是一个 全局环境记录,那么
      1. 执行 ? CreateGlobalFunctionBinding(varEnv, fn, fo, true)。
    4. 否则,
      1. bindingExists 为 ! varEnv.HasBinding(fn)。
      2. 如果 bindingExistsfalse,那么
        1. 注:由于步骤 14 之前的验证,以下调用不能返回 异常完成
        2. 执行 ! varEnv.CreateMutableBinding(fn, true)。
        3. 执行 ! varEnv.InitializeBinding(fn, fo)。
      3. 否则,
        1. 执行 ! varEnv.SetMutableBinding(fn, fo, false)。
  18. 对于 declaredVarNames 的每个字符串 vn,执行
    1. 如果 varEnv 是一个 全局环境记录,那么
      1. 执行 ? CreateGlobalVarBinding(varEnv, vn, true)。
    2. 否则,
      1. bindingExists 为 ! varEnv.HasBinding(vn)。
      2. 如果 bindingExistsfalse,那么
        1. 注:由于步骤 14 之前的验证,以下调用不能返回 异常完成
        2. 执行 ! varEnv.CreateMutableBinding(vn, true)。
        3. 执行 ! varEnv.InitializeBinding(vn, undefined)。
  19. 返回 unused

此算法的替代版本在 B.3.4 中描述。

19.2.2 isFinite ( number )

此函数是 %isFinite% 内置对象。

当被调用时执行以下步骤:

  1. num 为 ? ToNumber(number)。
  2. 如果 num 不是 有限的,返回 false
  3. 否则,返回 true

19.2.3 isNaN ( number )

此函数是 %isNaN% 内置对象。

当被调用时执行以下步骤:

  1. num 为 ? ToNumber(number)。
  2. 如果 numNaN,返回 true
  3. 否则,返回 false

ECMAScript 代码测试值 X 是否为 NaN 的可靠方法是使用形式为 X !== X 的表达式。当且仅当 XNaN 时,结果将是 true

19.2.4 parseFloat ( string )

此函数根据对 string 参数内容作为十进制字面量的解释产生一个数值。

它是 %parseFloat% 内置对象。

当被调用时执行以下步骤:

  1. inputString 为 ? ToString(string)。
  2. trimmedString 为 ! TrimString(inputString, start)。
  3. trimmedStringToCodePoints(trimmedString)。
  4. trimmedPrefix 为满足 StrDecimalLiteral 语法的 trimmed 的最长前缀,可能是 trimmed 本身。如果没有这样的前缀,返回 NaN
  5. parsedNumberParseText(trimmedPrefix, StrDecimalLiteral)。
  6. 断言parsedNumber 是一个 解析节点
  7. 返回 parsedNumberStringNumericValue

此函数可能仅将 string 的前导部分解释为数值;它忽略任何不能解释为十进制字面量表示法一部分的代码单元,并且不会给出任何此类代码单元被忽略的指示。

19.2.5 parseInt ( string, radix )

此函数根据指定的 radixstring 内容的解释产生一个 整数。忽略 string 中的前导空白。如果 radix 强制转换为 0(例如当它是 undefined 时),则假设为 10,除非数字表示以 "0x""0X" 开头,在这种情况下假设为 16。如果 radix 是 16,数字表示可以可选地以 "0x""0X" 开头。

它是 %parseInt% 内置对象。

当被调用时执行以下步骤:

  1. inputString 为 ? ToString(string)。
  2. S 为 ! TrimString(inputString, start)。
  3. sign 为 1。
  4. 如果 S 不为空且 S 的第一个代码单元是代码单元 0x002D(连字符减号),设 sign 为 -1。
  5. 如果 S 不为空且 S 的第一个代码单元是代码单元 0x002B(加号)或代码单元 0x002D(连字符减号),设 SS 从索引 1 开始的 子字符串
  6. R(? ToInt32(radix))。
  7. stripPrefixtrue
  8. 如果 R ≠ 0,那么
    1. 如果 R < 2 或 R > 36,返回 NaN
    2. 如果 R ≠ 16,设 stripPrefixfalse
  9. 否则,
    1. R 为 10。
  10. 如果 stripPrefixtrue,那么
    1. 如果 S 的长度至少为 2 且 S 的前两个代码单元是 "0x""0X",那么
      1. SS 从索引 2 开始的 子字符串
      2. R 为 16。
  11. 如果 S 包含不是基数-R 数字的代码单元,设 endS 中第一个这样的代码单元的索引;否则,设 endS 的长度。
  12. ZS 从 0 到 end子字符串
  13. 如果 Z 为空,返回 NaN
  14. mathInt 为以基数-R 表示法表示的 Z 所表示的 整数值,使用字母 AZaz 表示值 10 到 35 的数字。(但是,如果 R = 10 且 Z 包含超过 20 个有效数字,实现可以选择将第 20 个之后的每个有效数字替换为 0 数字;如果 R 不是 2、4、8、10、16 或 32 之一,那么 mathInt 可能是一个 实现近似的 整数,表示 Z 在基数-R 表示法中表示的 整数值。)
  15. 如果 mathInt = 0,那么
    1. 如果 sign = -1,返回 -0𝔽
    2. 返回 +0𝔽
  16. 返回 𝔽(sign × mathInt)。

此函数可能仅将 string 的前导部分解释为 整数值;它忽略任何不能解释为 整数表示法一部分的代码单元,并且不会给出任何此类代码单元被忽略的指示。

19.2.6 URI 处理函数

统一资源标识符(URI)是标识资源(例如网页或文件)和访问它们的传输协议(例如 HTTP 或 FTP)的字符串。ECMAScript 语言本身不提供对使用 URI 的任何支持,除了本节中描述的编码和解码 URI 的函数。encodeURIdecodeURI 旨在与完整的 URI 一起工作;它们假设任何保留字符都旨在具有特殊含义(例如,作为分隔符),因此不进行编码。encodeURIComponentdecodeURIComponent 旨在与 URI 的各个组件一起工作;它们假设任何保留字符表示文本,必须编码以避免在组件是完整 URI 的一部分时具有特殊含义。

注 1

保留字符集基于 RFC 2396,不反映更新的 RFC 3986 引入的更改。

注 2

许多 ECMAScript 实现提供操作网页的附加函数和方法;这些函数超出了本标准的范围。

19.2.6.1 decodeURI ( encodedURI )

此函数计算 URI 的新版本,其中每个可能由 encodeURI 函数引入的转义序列和 UTF-8 编码都被其表示的代码点的 UTF-16 编码替换。不可能由 encodeURI 引入的转义序列不被替换。

它是 %decodeURI% 内置对象。

当被调用时执行以下步骤:

  1. uriString 为 ? ToString(encodedURI)。
  2. preserveEscapeSet";/?:@&=+$,#"
  3. 返回 ? Decode(uriString, preserveEscapeSet)。

19.2.6.2 decodeURIComponent ( encodedURIComponent )

此函数计算 URI 的新版本,其中每个可能由 encodeURIComponent 函数引入的转义序列和 UTF-8 编码都被其表示的代码点的 UTF-16 编码替换。

它是 %decodeURIComponent% 内置对象。

当被调用时执行以下步骤:

  1. componentString 为 ? ToString(encodedURIComponent)。
  2. preserveEscapeSet 为空字符串。
  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 为空字符串。
  3. 返回 ? Encode(componentString, extraUnescaped)。

19.2.6.5 Encode ( string, extraUnescaped )

抽象操作 Encode 接受参数 string(一个字符串)和 extraUnescaped(一个字符串),返回一个包含字符串的 正常完成或一个 抛出完成。它执行 URI 编码和转义,将 string 解释为 6.1.4 中描述的 UTF-16 编码代码点序列。如果字符在 RFC 2396 中被标识为未保留的或出现在 extraUnescaped 中,则不进行转义。当被调用时执行以下步骤:

  1. lenstring 的长度。
  2. R 为空字符串。
  3. alwaysUnescapedASCII 单词字符"-.!~*'()"字符串连接
  4. unescapedSetalwaysUnescapedextraUnescaped字符串连接
  5. k 为 0。
  6. 重复,当 k < len 时,
    1. Cstring 中索引 k 处的代码单元。
    2. 如果 unescapedSet 包含 C,那么
      1. kk + 1。
      2. RRC字符串连接
    3. 否则,
      1. cpCodePointAt(string, k)。
      2. 如果 cp.[[IsUnpairedSurrogate]]true,抛出 URIError 异常。
      3. kk + cp.[[CodeUnitCount]]
      4. Octets 为通过对 cp.[[CodePoint]] 应用 UTF-8 变换得到的八位字节的 列表
      5. 对于 Octets 的每个元素 octet,执行
        1. hexoctet 的字符串表示,格式化为大写十六进制数。
        2. RR"%"StringPad(hex, 2, "0", start) 的 字符串连接
  7. 返回 R

因为百分号编码用于表示单个八位字节,所以单个代码点可能表示为多个连续的转义序列(其 8 位 UTF-8 代码单元的每一个对应一个)。

19.2.6.6 Decode ( string, preserveEscapeSet )

抽象操作 Decode 接受参数 string(一个字符串)和 preserveEscapeSet(一个字符串),返回一个包含字符串的 正常完成或一个 抛出完成。它执行 URI 反转义和解码,保留与 preserveEscapeSet 中的基本拉丁字符对应的任何转义序列。当被调用时执行以下步骤:

  1. lenstring 的长度。
  2. R 为空字符串。
  3. k 为 0。
  4. 重复,当 k < len 时,
    1. Cstring 中索引 k 处的代码单元。
    2. SC
    3. 如果 C 是代码单元 0x0025(百分号),那么
      1. 如果 k + 3 > len,抛出 URIError 异常。
      2. escapestringkk + 3 的 子字符串
      3. BParseHexOctet(string, k + 1)。
      4. 如果 B 不是一个 整数,抛出 URIError 异常。
      5. kk + 2。
      6. nB 中前导 1 位的数量。
      7. 如果 n = 0,那么
        1. asciiChar 为数值为 B 的代码单元。
        2. 如果 preserveEscapeSet 包含 asciiChar,设 Sescape。否则,设 SasciiChar
      8. 否则,
        1. 如果 n = 1 或 n > 4,抛出 URIError 异常。
        2. Octets 为 « B »。
        3. j 为 1。
        4. 重复,当 j < n 时,
          1. kk + 1。
          2. 如果 k + 3 > len,抛出 URIError 异常。
          3. 如果 string 中索引 k 处的代码单元不是代码单元 0x0025(百分号),抛出 URIError 异常。
          4. continuationByteParseHexOctet(string, k + 1)。
          5. 如果 continuationByte 不是一个 整数,抛出 URIError 异常。
          6. continuationByte 添加到 Octets
          7. kk + 2。
          8. jj + 1。
        5. 断言Octets 的长度是 n
        6. 如果 Octets 不包含 Unicode 代码点的有效 UTF-8 编码,抛出 URIError 异常。
        7. V 为通过对 Octets 应用 UTF-8 变换获得的代码点,即从八位字节的 列表到 21 位值。
        8. SUTF16EncodeCodePoint(V)。
    4. RRS字符串连接
    5. kk + 1。
  5. 返回 R

RFC 3629 禁止解码无效的 UTF-8 八位字节序列。例如,无效序列 0xC0 0x80 不得解码为代码单元 0x0000。Decode 算法的实现在遇到此类无效序列时必须抛出 URIError

19.2.6.7 ParseHexOctet ( string, position )

抽象操作 ParseHexOctet 接受参数 string(一个字符串)和 position(一个非负 整数),返回一个非负 整数或一个非空的 SyntaxError 对象的 列表。它解析 string 中指定 position 处的两个十六进制字符序列为一个无符号 8 位 整数。当被调用时执行以下步骤:

  1. lenstring 的长度。
  2. 断言position + 2 ≤ len
  3. hexDigitsstringpositionposition + 2 的 子字符串
  4. parseResultParseText(hexDigits, HexDigits[~Sep])。
  5. 如果 parseResult 不是一个 解析节点,返回 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 BigInt ( . . . )

参见 21.2.1

19.3.5 BigInt64Array ( . . . )

参见 23.2.5

19.3.6 BigUint64Array ( . . . )

参见 23.2.5

19.3.7 Boolean ( . . . )

参见 20.3.1

19.3.8 DataView ( . . . )

参见 25.3.2

19.3.9 Date ( . . . )

参见 21.4.2

19.3.10 Error ( . . . )

参见 20.5.1

19.3.11 EvalError ( . . . )

参见 20.5.5.1

19.3.12 FinalizationRegistry ( . . . )

参见 26.2.1

19.3.13 Float16Array ( . . . )

参见 23.2.5

19.3.14 Float32Array ( . . . )

参见 23.2.5

19.3.15 Float64Array ( . . . )

参见 23.2.5

19.3.16 Function ( . . . )

参见 20.2.1

19.3.17 Int8Array ( . . . )

参见 23.2.5

19.3.18 Int16Array ( . . . )

参见 23.2.5

19.3.19 Int32Array ( . . . )

参见 23.2.5

19.3.20 Iterator ( . . . )

参见 27.1.3.1

19.3.21 Map ( . . . )

参见 24.1.1

19.3.22 Number ( . . . )

参见 21.1.1

19.3.23 Object ( . . . )

参见 20.1.1

19.3.24 Promise ( . . . )

参见 27.2.3

19.3.25 Proxy ( . . . )

参见 28.2.1

19.3.26 RangeError ( . . . )

参见 20.5.5.2

19.3.27 ReferenceError ( . . . )

参见 20.5.5.3

19.3.28 RegExp ( . . . )

参见 22.2.4

19.3.29 Set ( . . . )

参见 24.2.2

19.3.30 SharedArrayBuffer ( . . . )

参见 25.2.3

19.3.31 String ( . . . )

参见 22.1.1

19.3.32 Symbol ( . . . )

参见 20.4.1

19.3.33 SyntaxError ( . . . )

参见 20.5.5.4

19.3.34 TypeError ( . . . )

参见 20.5.5.5

19.3.35 Uint8Array ( . . . )

参见 23.2.5

19.3.36 Uint8ClampedArray ( . . . )

参见 23.2.5

19.3.37 Uint16Array ( . . . )

参见 23.2.5

19.3.38 Uint32Array ( . . . )

参见 23.2.5

19.3.39 URIError ( . . . )

参见 20.5.5.6

19.3.40 WeakMap ( . . . )

参见 24.3.1

19.3.41 WeakRef ( . . . )

参见 26.1.1

19.3.42 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%
  • 有一个 "length" 属性,其值是 1𝔽
  • 有以下附加属性:

20.1.2.1 Object.assign ( target, ...sources )

此函数从一个或多个源对象复制所有可枚举自有属性的值到 target 对象。

当被调用时执行以下步骤:

  1. to 为 ? ToObject(target)。
  2. 如果只传递了一个参数,返回 to
  3. 对于 sources 的每个元素 nextSource,执行
    1. 如果 nextSource 既不是 undefined 也不是 null,那么
      1. from 为 ! ToObject(nextSource)。
      2. keys 为 ? from.[[OwnPropertyKeys]]()
      3. 对于 keys 的每个元素 nextKey,执行
        1. desc 为 ? from.[[GetOwnProperty]](nextKey)。
        2. 如果 desc 不是 undefineddesc.[[Enumerable]]true,那么
          1. propValue 为 ? Get(from, nextKey)。
          2. 执行 ? Set(to, nextKey, propValue, true)。
  4. 返回 to

此函数的 "length" 属性是 2𝔽

20.1.2.2 Object.create ( O, Properties )

此函数创建一个具有指定原型的新对象。

当被调用时执行以下步骤:

  1. 如果 O 不是一个对象O 不是 null,抛出 TypeError 异常。
  2. objOrdinaryObjectCreate(O)。
  3. 如果 Properties 不是 undefined,那么
    1. 返回 ? ObjectDefineProperties(obj, Properties)。
  4. 返回 obj

20.1.2.3 Object.defineProperties ( O, Properties )

此函数添加自有属性和/或更新对象现有自有属性的特性。

当被调用时执行以下步骤:

  1. 如果 O 不是一个对象,抛出 TypeError 异常。
  2. 返回 ? ObjectDefineProperties(O, Properties)。

20.1.2.3.1 ObjectDefineProperties ( O, Properties )

抽象操作 ObjectDefineProperties 接受参数 O(一个对象)和 Properties(一个 ECMAScript 语言值),返回一个包含对象的 正常完成或一个 抛出完成。当被调用时执行以下步骤:

  1. props 为 ? ToObject(Properties)。
  2. keys 为 ? props.[[OwnPropertyKeys]]()
  3. descriptors 为一个新的空 列表
  4. 对于 keys 的每个元素 nextKey,执行
    1. propDesc 为 ? props.[[GetOwnProperty]](nextKey)。
    2. 如果 propDesc 不是 undefinedpropDesc.[[Enumerable]]true,那么
      1. descObj 为 ? Get(props, nextKey)。
      2. desc 为 ? ToPropertyDescriptor(descObj)。
      3. 记录 { [[Key]]: nextKey, [[Descriptor]]: desc } 追加到 descriptors
  5. 对于 descriptors 的每个元素 property,执行
    1. 执行 ? DefinePropertyOrThrow(O, property.[[Key]], property.[[Descriptor]])。
  6. 返回 O

20.1.2.4 Object.defineProperty ( O, P, Attributes )

此函数添加一个自有属性和/或更新对象现有自有属性的特性。

当被调用时执行以下步骤:

  1. 如果 O 不是一个对象,抛出 TypeError 异常。
  2. key 为 ? ToPropertyKey(P)。
  3. desc 为 ? ToPropertyDescriptor(Attributes)。
  4. 执行 ? DefinePropertyOrThrow(O, key, desc)。
  5. 返回 O

20.1.2.5 Object.entries ( O )

此函数在被调用时执行以下步骤:

  1. obj 为 ? ToObject(O)。
  2. entryList 为 ? EnumerableOwnProperties(obj, key+value)。
  3. 返回 CreateArrayFromList(entryList)。

20.1.2.6 Object.freeze ( O )

此函数在被调用时执行以下步骤:

  1. 如果 O 不是一个对象,返回 O
  2. status 为 ? SetIntegrityLevel(O, frozen)。
  3. 如果 statusfalse,抛出 TypeError 异常。
  4. 返回 O

20.1.2.7 Object.fromEntries ( iterable )

此函数在被调用时执行以下步骤:

  1. 执行 ? RequireObjectCoercible(iterable)。
  2. objOrdinaryObjectCreate(%Object.prototype%)。
  3. 断言obj 是一个可扩展的 普通对象,没有自有属性。
  4. closure 为一个新的 抽象闭包,参数为 (key, value),捕获 obj,当被调用时执行以下步骤:
    1. propertyKey 为 ? ToPropertyKey(key)。
    2. 执行 ! CreateDataPropertyOrThrow(obj, propertyKey, value)。
    3. 返回 undefined
  5. adderCreateBuiltinFunction(closure, 2, "", « »)。
  6. 返回 ? AddEntriesFromIterable(obj, iterable, adder)。
adder 创建的函数永远不会直接被 ECMAScript 代码访问。

20.1.2.8 Object.getOwnPropertyDescriptor ( O, P )

此函数在被调用时执行以下步骤:

  1. obj 为 ? ToObject(O)。
  2. key 为 ? ToPropertyKey(P)。
  3. desc 为 ? obj.[[GetOwnProperty]](key)。
  4. 返回 FromPropertyDescriptor(desc)。

20.1.2.9 Object.getOwnPropertyDescriptors ( O )

此函数在被调用时执行以下步骤:

  1. obj 为 ? ToObject(O)。
  2. ownKeys 为 ? obj.[[OwnPropertyKeys]]()
  3. descriptorsOrdinaryObjectCreate(%Object.prototype%)。
  4. 对于 ownKeys 的每个元素 key,执行
    1. desc 为 ? obj.[[GetOwnProperty]](key)。
    2. descriptorFromPropertyDescriptor(desc)。
    3. 如果 descriptor 不是 undefined,执行 ! CreateDataPropertyOrThrow(descriptors, key, descriptor)。
  5. 返回 descriptors

20.1.2.10 Object.getOwnPropertyNames ( O )

此函数在被调用时执行以下步骤:

  1. 返回 CreateArrayFromList(? GetOwnPropertyKeys(O, string))。

20.1.2.11 Object.getOwnPropertySymbols ( O )

此函数在被调用时执行以下步骤:

  1. 返回 CreateArrayFromList(? GetOwnPropertyKeys(O, symbol))。

20.1.2.11.1 GetOwnPropertyKeys ( O, type )

抽象操作 GetOwnPropertyKeys 接受参数 O(一个 ECMAScript 语言值)和 typestringsymbol),返回一个包含 属性键列表正常完成或一个 抛出完成。当被调用时执行以下步骤:

  1. obj 为 ? ToObject(O)。
  2. keys 为 ? obj.[[OwnPropertyKeys]]()
  3. nameList 为一个新的空 列表
  4. 对于 keys 的每个元素 nextKey,执行
    1. 如果 nextKey 是一个符号typesymbol,或者如果 nextKey 是一个字符串typestring,那么
      1. nextKey 追加到 nameList
  5. 返回 nameList

20.1.2.12 Object.getPrototypeOf ( O )

此函数在被调用时执行以下步骤:

  1. obj 为 ? ToObject(O)。
  2. 返回 ? obj.[[GetPrototypeOf]]()

20.1.2.13 Object.groupBy ( items, callback )

callback 应该是一个接受两个参数的函数。groupBy 按升序为 items 中的每个元素调用一次 callback,并构造一个新对象。callback 返回的每个值都被强制转换为 属性键。对于每个这样的 属性键,结果对象有一个属性,其键是该 属性键,其值是一个数组,包含 callback 返回值强制转换为该键的所有元素。

callback 用两个参数调用:元素的值和元素的索引。

groupBy 的返回值是一个不继承自 %Object.prototype% 的对象。

此函数在被调用时执行以下步骤:

  1. groups 为 ? GroupBy(items, callback, property)。
  2. objOrdinaryObjectCreate(null)。
  3. 对于 groups 的每个 记录 { [[Key]], [[Elements]] } g,执行
    1. elementsCreateArrayFromList(g.[[Elements]])。
    2. 执行 ! CreateDataPropertyOrThrow(obj, g.[[Key]], elements)。
  4. 返回 obj

20.1.2.14 Object.hasOwn ( O, P )

此函数在被调用时执行以下步骤:

  1. obj 为 ? ToObject(O)。
  2. key 为 ? ToPropertyKey(P)。
  3. 返回 ? HasOwnProperty(obj, key)。

20.1.2.15 Object.is ( value1, value2 )

此函数在被调用时执行以下步骤:

  1. 返回 SameValue(value1, value2)。

20.1.2.16 Object.isExtensible ( O )

此函数在被调用时执行以下步骤:

  1. 如果 O 不是一个对象,返回 false
  2. 返回 ? IsExtensible(O)。

20.1.2.17 Object.isFrozen ( O )

此函数在被调用时执行以下步骤:

  1. 如果 O 不是一个对象,返回 true
  2. 返回 ? TestIntegrityLevel(O, frozen)。

20.1.2.18 Object.isSealed ( O )

此函数在被调用时执行以下步骤:

  1. 如果 O 不是一个对象,返回 true
  2. 返回 ? TestIntegrityLevel(O, sealed)。

20.1.2.19 Object.keys ( O )

此函数在被调用时执行以下步骤:

  1. obj 为 ? ToObject(O)。
  2. keyList 为 ? EnumerableOwnProperties(obj, key)。
  3. 返回 CreateArrayFromList(keyList)。

20.1.2.20 Object.preventExtensions ( O )

此函数在被调用时执行以下步骤:

  1. 如果 O 不是一个对象,返回 O
  2. status 为 ? O.[[PreventExtensions]]()
  3. 如果 statusfalse,抛出 TypeError 异常。
  4. 返回 O

20.1.2.21 Object.prototype

Object.prototype 的初始值是 Object 原型对象

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.1.2.22 Object.seal ( O )

此函数在被调用时执行以下步骤:

  1. 如果 O 不是一个对象,返回 O
  2. status 为 ? SetIntegrityLevel(O, sealed)。
  3. 如果 statusfalse,抛出 TypeError 异常。
  4. 返回 O

20.1.2.23 Object.setPrototypeOf ( O, proto )

此函数在被调用时执行以下步骤:

  1. O 为 ? RequireObjectCoercible(O)。
  2. 如果 proto 不是一个对象proto 不是 null,抛出 TypeError 异常。
  3. 如果 O 不是一个对象,返回 O
  4. status 为 ? O.[[SetPrototypeOf]](proto)。
  5. 如果 statusfalse,抛出 TypeError 异常。
  6. 返回 O

20.1.2.24 Object.values ( O )

此函数在被调用时执行以下步骤:

  1. obj 为 ? ToObject(O)。
  2. valueList 为 ? EnumerableOwnProperties(obj, 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 ( V )

此方法在被调用时执行以下步骤:

  1. P 为 ? ToPropertyKey(V)。
  2. O 为 ? ToObject(this 值)。
  3. 返回 ? HasOwnProperty(O, P)。

步骤 12 的顺序是为了确保,即使 this 值是 undefinednull,在此规范的以前版本中步骤 1 会抛出的任何异常都将继续被抛出。

20.1.3.3 Object.prototype.isPrototypeOf ( V )

此方法在被调用时执行以下步骤:

  1. 如果 V 不是一个对象,返回 false
  2. O 为 ? ToObject(this 值)。
  3. 重复,
    1. V 为 ? V.[[GetPrototypeOf]]()
    2. 如果 Vnull,返回 false
    3. 如果 SameValue(O, V) 是 true,返回 true

步骤 12 的顺序保持了此规范的以前版本为 V 不是对象且 this 值是 undefinednull 的情况指定的行为。

20.1.3.4 Object.prototype.propertyIsEnumerable ( V )

此方法在被调用时执行以下步骤:

  1. P 为 ? ToPropertyKey(V)。
  2. O 为 ? ToObject(this 值)。
  3. desc 为 ? O.[[GetOwnProperty]](P)。
  4. 如果 descundefined,返回 false
  5. 返回 desc.[[Enumerable]]
注 1

此方法不考虑原型链中的对象。

注 2

步骤 12 的顺序是为了确保,即使 this 值是 undefinednull,在此规范的以前版本中步骤 1 会抛出的任何异常都将继续被抛出。

20.1.3.5 Object.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] )

此方法在被调用时执行以下步骤:

  1. Othis 值。
  2. 返回 ? Invoke(O, "toString")。

此方法的可选参数未被使用,但旨在对应 ECMA-402 toLocaleString 方法使用的参数模式。不包含 ECMA-402 支持的实现不得将这些参数位置用于其他目的。

注 1

此方法为没有区域敏感的 toString 行为的对象提供通用的 toLocaleString 实现。ArrayNumberDate%TypedArray% 提供它们自己的区域敏感的 toLocaleString 方法。

注 2

ECMA-402 故意不为此默认实现提供替代方案。

20.1.3.6 Object.prototype.toString ( )

此方法在被调用时执行以下步骤:

  1. 如果 this 值是 undefined,返回 "[object Undefined]"
  2. 如果 this 值是 null,返回 "[object Null]"
  3. O 为 ! ToObject(this 值)。
  4. isArray 为 ? IsArray(O)。
  5. 如果 isArraytrue,设 builtinTag"Array"
  6. 否则如果 O 有一个 [[ParameterMap]] 内部槽,设 builtinTag"Arguments"
  7. 否则如果 O 有一个 [[Call]] 内部方法,设 builtinTag"Function"
  8. 否则如果 O 有一个 [[ErrorData]] 内部槽,设 builtinTag"Error"
  9. 否则如果 O 有一个 [[BooleanData]] 内部槽,设 builtinTag"Boolean"
  10. 否则如果 O 有一个 [[NumberData]] 内部槽,设 builtinTag"Number"
  11. 否则如果 O 有一个 [[StringData]] 内部槽,设 builtinTag"String"
  12. 否则如果 O 有一个 [[DateValue]] 内部槽,设 builtinTag"Date"
  13. 否则如果 O 有一个 [[RegExpMatcher]] 内部槽,设 builtinTag"RegExp"
  14. 否则,设 builtinTag"Object"
  15. tag 为 ? Get(O, %Symbol.toStringTag%)。
  16. 如果 tag 不是一个字符串,设 tagbuiltinTag
  17. 返回 "[object "tag"]"字符串连接

历史上,此方法偶尔被用来访问 [[Class]] 内部槽的字符串值,该内部槽在此规范的以前版本中用作各种内建对象的名义类型标签。上述 toString 的定义为使用 toString 作为那些特定类型的内建对象测试的遗留代码保持兼容性。它不为其他类型的内建或程序定义的对象提供可靠的类型测试机制。此外,程序可以以会使此类遗留类型测试的可靠性失效的方式使用 %Symbol.toStringTag%

20.1.3.7 Object.prototype.valueOf ( )

此方法在被调用时执行以下步骤:

  1. 返回 ? ToObject(this 值)。

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. O 为 ? ToObject(this 值)。
  2. 返回 ? O.[[GetPrototypeOf]]()

20.1.3.8.2 set Object.prototype.__proto__

[[Set]] 特性的值是一个接受参数 proto 的内建函数。当被调用时执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. 如果 proto 不是一个对象proto 不是 null,返回 undefined
  3. 如果 O 不是一个对象,返回 undefined
  4. status 为 ? O.[[SetPrototypeOf]](proto)。
  5. 如果 statusfalse,抛出 TypeError 异常。
  6. 返回 undefined

20.1.3.9 遗留的 Object.prototype 访问器方法

20.1.3.9.1 Object.prototype.__defineGetter__ ( P, getter )

此方法在被调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. 如果 IsCallable(getter) 是 false,抛出 TypeError 异常。
  3. desc 为 PropertyDescriptor { [[Get]]: getter[[Enumerable]]: true[[Configurable]]: true }。
  4. key 为 ? ToPropertyKey(P)。
  5. 执行 ? DefinePropertyOrThrow(O, key, desc)。
  6. 返回 undefined

20.1.3.9.2 Object.prototype.__defineSetter__ ( P, setter )

此方法在被调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. 如果 IsCallable(setter) 是 false,抛出 TypeError 异常。
  3. desc 为 PropertyDescriptor { [[Set]]: setter[[Enumerable]]: true[[Configurable]]: true }。
  4. key 为 ? ToPropertyKey(P)。
  5. 执行 ? DefinePropertyOrThrow(O, key, desc)。
  6. 返回 undefined

20.1.3.9.3 Object.prototype.__lookupGetter__ ( P )

此方法在被调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. key 为 ? ToPropertyKey(P)。
  3. 重复,
    1. desc 为 ? O.[[GetOwnProperty]](key)。
    2. 如果 desc 不是 undefined,那么
      1. 如果 IsAccessorDescriptor(desc) 是 true,返回 desc.[[Get]]
      2. 返回 undefined
    3. O 为 ? O.[[GetPrototypeOf]]()
    4. 如果 Onull,返回 undefined

20.1.3.9.4 Object.prototype.__lookupSetter__ ( P )

此方法在被调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. key 为 ? ToPropertyKey(P)。
  3. 重复,
    1. desc 为 ? O.[[GetOwnProperty]](key)。
    2. 如果 desc 不是 undefined,那么
      1. 如果 IsAccessorDescriptor(desc) 是 true,返回 desc.[[Set]]
      2. 返回 undefined
    3. O 为 ? O.[[GetPrototypeOf]]()
    4. 如果 Onull,返回 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 ( ...parameterArgs, bodyArg )

最后一个参数(如果有的话)指定函数的主体(可执行代码);任何前面的参数指定形式参数。

此函数在被调用时执行以下步骤:

  1. C活动函数对象
  2. 如果 bodyArg 不存在,设 bodyArg 为空字符串。
  3. 返回 ? CreateDynamicFunction(C, NewTarget, normal, parameterArgs, bodyArg)。

为要指定的每个形式参数都有一个参数是允许的但不是必需的。例如,以下三个表达式都产生相同的结果:

new Function("a", "b", "c", "return a+b+c")
                new Function("a, b, c", "return a+b+c")
                new Function("a,b", "c", "return a+b+c")

20.2.1.1.1 CreateDynamicFunction ( constructor, newTarget, kind, parameterArgs, bodyArg )

抽象操作 CreateDynamicFunction 接受参数 constructor(一个 构造器)、newTarget(一个 构造器undefined)、kindnormalgeneratorasyncasync-generator)、parameterArgsECMAScript 语言值列表)和 bodyArg(一个 ECMAScript 语言值),返回一个 包含 ECMAScript 函数对象正常完成或一个 抛出完成constructor 是执行此操作的 构造器函数。newTarget 是最初应用 new构造器parameterArgsbodyArg 反映传递给 constructor 的参数值。当被调用时执行以下步骤:

  1. 如果 newTargetundefined,设 newTargetconstructor
  2. 如果 kindnormal,那么
    1. prefix"function"
    2. exprSym 为语法符号 FunctionExpression
    3. bodySym 为语法符号 FunctionBody[~Yield, ~Await]
    4. parameterSym 为语法符号 FormalParameters[~Yield, ~Await]
    5. fallbackProto"%Function.prototype%"
  3. 否则如果 kindgenerator,那么
    1. prefix"function*"
    2. exprSym 为语法符号 GeneratorExpression
    3. bodySym 为语法符号 GeneratorBody
    4. parameterSym 为语法符号 FormalParameters[+Yield, ~Await]
    5. fallbackProto"%GeneratorFunction.prototype%"
  4. 否则如果 kindasync,那么
    1. prefix"async function"
    2. exprSym 为语法符号 AsyncFunctionExpression
    3. bodySym 为语法符号 AsyncFunctionBody
    4. parameterSym 为语法符号 FormalParameters[~Yield, +Await]
    5. fallbackProto"%AsyncFunction.prototype%"
  5. 否则,
    1. 断言kindasync-generator
    2. prefix"async function*"
    3. exprSym 为语法符号 AsyncGeneratorExpression
    4. bodySym 为语法符号 AsyncGeneratorBody
    5. parameterSym 为语法符号 FormalParameters[+Yield, +Await]
    6. fallbackProto"%AsyncGeneratorFunction.prototype%"
  6. argCountparameterArgs 中元素的数量。
  7. parameterStrings 为一个新的空 列表
  8. 对于 parameterArgs 的每个元素 arg,执行
    1. 将 ? ToString(arg) 追加到 parameterStrings
  9. bodyString 为 ? ToString(bodyArg)。
  10. currentRealm当前 Realm 记录
  11. 执行 ? HostEnsureCanCompileStrings(currentRealm, parameterStrings, bodyString, false)。
  12. P 为空字符串。
  13. 如果 argCount > 0,那么
    1. PparameterStrings[0]。
    2. k 为 1。
    3. 重复,当 k < argCount 时,
      1. nextArgStringparameterStrings[k]。
      2. PP","(逗号)和 nextArgString字符串连接
      3. kk + 1。
  14. bodyParseString 为 0x000A(换行符)、bodyString 和 0x000A(换行符)的 字符串连接
  15. sourceStringprefix" anonymous("P、0x000A(换行符)、") {"bodyParseString"}"字符串连接
  16. sourceTextStringToCodePoints(sourceString)。
  17. parametersParseText(P, parameterSym)。
  18. 如果 parameters 是一个错误的 列表,抛出 SyntaxError 异常。
  19. bodyParseText(bodyParseString, bodySym)。
  20. 如果 body 是一个错误的 列表,抛出 SyntaxError 异常。
  21. 注:参数和主体分别解析以确保各自都是有效的。例如,new Function("/*", "*/ ) {") 不会计算为函数。
  22. 注:如果达到这一步,sourceText 必须具有 exprSym 的语法(尽管反向含义不成立)。接下来两步的目的是执行直接应用于 exprSym 的任何早期错误规则。
  23. exprParseText(sourceText, exprSym)。
  24. 如果 expr 是一个错误的 列表,抛出 SyntaxError 异常。
  25. proto 为 ? GetPrototypeFromConstructor(newTarget, fallbackProto)。
  26. envcurrentRealm.[[GlobalEnv]]
  27. privateEnvnull
  28. FOrdinaryFunctionCreate(proto, sourceText, parameters, body, non-lexical-this, env, privateEnv)。
  29. 执行 SetFunctionName(F, "anonymous")。
  30. 如果 kindgenerator,那么
    1. prototypeOrdinaryObjectCreate(%GeneratorPrototype%)。
    2. 执行 ! DefinePropertyOrThrow(F, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  31. 否则如果 kindasync-generator,那么
    1. prototypeOrdinaryObjectCreate(%AsyncGeneratorPrototype%)。
    2. 执行 ! DefinePropertyOrThrow(F, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  32. 否则如果 kindnormal,那么
    1. 执行 MakeConstructor(F)。
  33. 注:kindasync 的函数不可构造且没有 [[Construct]] 内部方法或 "prototype" 属性。
  34. 返回 F

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" 属性,其值是空字符串。

Function 原型对象被指定为 函数对象,以确保与在 ECMAScript 2015 规范之前创建的 ECMAScript 代码的兼容性。

20.2.3.1 Function.prototype.apply ( thisArg, argArray )

此方法在被调用时执行以下步骤:

  1. functhis 值。
  2. 如果 IsCallable(func) 是 false,抛出 TypeError 异常。
  3. 如果 argArrayundefinednull,那么
    1. 执行 PrepareForTailCall()。
    2. 返回 ? Call(func, thisArg)。
  4. argList 为 ? CreateListFromArrayLike(argArray)。
  5. 执行 PrepareForTailCall()。
  6. 返回 ? Call(func, thisArg, argList)。
注 1

thisArg 值被不加修改地传递作为 this 值。这是与第3版的变化,在第3版中,undefinednullthisArg 被替换为 全局对象,并且 ToObject 被应用于所有其他值,该结果被传递作为 this 值。尽管 thisArg 被不加修改地传递,非严格函数在进入函数时仍然执行这些转换。

注 2

如果 func 是箭头函数或 绑定函数外来对象,那么 thisArg 将在步骤 6 的函数 [[Call]] 中被忽略。

20.2.3.2 Function.prototype.bind ( thisArg, ...args )

此方法在被调用时执行以下步骤:

  1. Targetthis 值。
  2. 如果 IsCallable(Target) 是 false,抛出 TypeError 异常。
  3. F 为 ? BoundFunctionCreate(Target, thisArg, args)。
  4. L 为 0。
  5. targetHasLength 为 ? HasOwnProperty(Target, "length")。
  6. 如果 targetHasLengthtrue,那么
    1. targetLen 为 ? Get(Target, "length")。
    2. 如果 targetLen 是一个数值,那么
      1. 如果 targetLen+∞𝔽,那么
        1. L 为 +∞。
      2. 否则如果 targetLen-∞𝔽,那么
        1. L 为 0。
      3. 否则,
        1. targetLenAsInt 为 ! ToIntegerOrInfinity(targetLen)。
        2. 断言targetLenAsInt有限的
        3. argCountargs 中元素的数量。
        4. Lmax(targetLenAsInt - argCount, 0)。
  7. 执行 SetFunctionLength(F, L)。
  8. targetName 为 ? Get(Target, "name")。
  9. 如果 targetName 不是字符串,设 targetName 为空字符串。
  10. 执行 SetFunctionName(F, targetName, "bound")。
  11. 返回 F
注 1

使用 Function.prototype.bind 创建的 函数对象外来对象。它们也没有 "prototype" 属性。

注 2

如果 Target 是箭头函数或 绑定函数外来对象,那么传递给此方法的 thisArg 将不会被后续对 F 的调用使用。

20.2.3.3 Function.prototype.call ( thisArg, ...args )

此方法在被调用时执行以下步骤:

  1. functhis 值。
  2. 如果 IsCallable(func) 是 false,抛出 TypeError 异常。
  3. 执行 PrepareForTailCall()。
  4. 返回 ? Call(func, thisArg, args)。
注 1

thisArg 值被不加修改地传递作为 this 值。这是与第3版的变化,在第3版中,undefinednullthisArg 被替换为 全局对象,并且 ToObject 被应用于所有其他值,该结果被传递作为 this 值。尽管 thisArg 被不加修改地传递,非严格函数在进入函数时仍然执行这些转换。

注 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 值。
  2. 如果 func 是一个对象func 有一个 [[SourceText]] 内部槽,func.[[SourceText]] 是一个 Unicode 码点序列,并且 HostHasSourceTextAvailable(func) 是 true,那么
    1. 返回 CodePointsToString(func.[[SourceText]])。
  3. 如果 func 是一个 内建函数对象,返回 func实现定义的字符串源代码表示。该表示必须具有 NativeFunction 的语法。另外,如果 func 有一个 [[InitialName]] 内部槽且 func.[[InitialName]] 是一个字符串,返回的字符串中与 NativeFunctionAccessoropt PropertyName 匹配的部分必须是 func.[[InitialName]] 的值。
  4. 如果 func 是一个对象IsCallable(func) 是 true,返回 func实现定义的字符串源代码表示。该表示必须具有 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% ] ( V )

此方法在被调用时执行以下步骤:

  1. Fthis 值。
  2. 返回 ? OrdinaryHasInstance(F, V)。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

这是大多数函数继承的 %Symbol.hasInstance% 的默认实现。%Symbol.hasInstance%instanceof 操作符调用,以确定值是否是特定 构造器的实例。诸如

v instanceof F

的表达式计算为

F[%Symbol.hasInstance%](v)

构造器函数可以通过在函数上公开不同的 %Symbol.hasInstance% 方法来控制哪些对象被 instanceof 识别为其实例。

此属性是不可写和不可配置的,以防止可能用于全局暴露绑定函数目标函数的篡改。

此方法的 "name" 属性的值是 "[Symbol.hasInstance]"

20.2.4 Function 实例

每个 Function 实例都是一个 ECMAScript 函数对象,并具有 表 30 中列出的内部槽。使用 Function.prototype.bind 方法(20.2.3.2)创建的 函数对象具有 表 31 中列出的内部槽。

Function 实例有以下属性:

20.2.4.1 length

"length" 属性的值是一个 整数,表示函数期望的典型参数数量。但是,语言允许使用其他数量的参数调用函数。当使用的参数数量与其 "length" 属性指定的数量不同时,函数的行为取决于该函数。此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

20.2.4.2 name

"name" 属性的值 是一个字符串,用于描述该函数。该名称没有语义意义,但通常是在 ECMAScript 源文本中的定义点用来引用函数的变量或 属性名。此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

本规范没有关联上下文名称的匿名函数对象使用空字符串作为 "name" 属性的值。

20.2.4.3 prototype

可以用作 构造器的 Function 实例有一个 "prototype" 属性。每当创建这样的 Function 实例时,还会创建另一个 普通对象,并且它是函数的 "prototype" 属性的初始值。除非另有说明,"prototype" 属性的值用于初始化当该函数作为 构造器调用时所创建对象的 [[Prototype]] 内部槽。

此属性有特性 { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }。

使用 Function.prototype.bind 创建的 函数对象,或通过求值 MethodDefinition(不是 GeneratorMethodAsyncGeneratorMethod)或 ArrowFunction 创建的函数对象没有 "prototype" 属性。

20.2.5 HostHasSourceTextAvailable ( func )

宿主定义的抽象操作 HostHasSourceTextAvailable 接受参数 func(一个 函数对象)并返回一个布尔值。它允许 宿主环境阻止为 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. bToBoolean(value)。
  2. 如果 NewTarget 是 undefined,返回 b
  3. O 为 ? OrdinaryCreateFromConstructor(NewTarget, "%Boolean.prototype%", « [[BooleanData]] »)。
  4. O.[[BooleanData]]b
  5. 返回 O

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. b 为 ? ThisBooleanValue(this value)。
  2. 如果 btrue,返回 "true";否则返回 "false"

20.3.3.3 Boolean.prototype.valueOf ( )

此方法在被调用时执行以下步骤:

  1. 返回 ? ThisBooleanValue(this value)。

20.3.3.3.1 ThisBooleanValue ( value )

抽象操作 ThisBooleanValue 接受参数 value(一个 ECMAScript 语言值)并返回一个 包含布尔值的 正常完成或一个 抛出完成。当被调用时执行以下步骤:

  1. 如果 value 是一个布尔值,返回 value
  2. 如果 value 是一个对象value 有一个 [[BooleanData]] 内部槽,那么
    1. bvalue.[[BooleanData]]
    2. 断言b 是一个布尔值
    3. 返回 b
  3. 抛出 TypeError 异常。

20.3.4 Boolean 实例的属性

Boolean 实例是从 Boolean 原型对象继承属性的 普通对象。Boolean 实例有一个 [[BooleanData]] 内部槽。[[BooleanData]] 内部槽是此 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.asyncIterator%表 1)。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.2 Symbol.for ( key )

此函数在被调用时执行以下步骤:

  1. stringKey 为 ? ToString(key)。
  2. 对于 GlobalSymbolRegistry 列表的每个元素 e,执行
    1. 如果 e.[[Key]]stringKey, 返回 e.[[Symbol]]
  3. 断言GlobalSymbolRegistry 列表当前不包含 stringKey 的条目。
  4. newSymbol 为一个新的 Symbol,其 [[Description]]stringKey
  5. 将 GlobalSymbolRegistry 记录 { [[Key]]: stringKey, [[Symbol]]: newSymbol } 追加到 GlobalSymbolRegistry 列表
  6. 返回 newSymbol

GlobalSymbolRegistry 列表是一个只能追加的 列表,全局可用。它被所有 Realm 共享。在任何 ECMAScript 代码的求值之前,它被初始化为一个新的空 列表。GlobalSymbolRegistry 列表的元素是具有 表 63 中定义的结构的 记录

表 63:GlobalSymbolRegistry 记录字段
字段名 用法
[[Key]] 一个字符串 用于全局标识 Symbol 的字符串键。
[[Symbol]] 一个 Symbol 可以从任何 Realm 检索的符号。

20.4.2.3 Symbol.hasInstance

Symbol.hasInstance 的初始值是众所周知的符号 %Symbol.hasInstance%表 1)。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.4 Symbol.isConcatSpreadable

Symbol.isConcatSpreadable 的初始值是众所周知的符号 %Symbol.isConcatSpreadable%表 1)。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.5 Symbol.iterator

Symbol.iterator 的初始值是众所周知的符号 %Symbol.iterator%表 1)。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.6 Symbol.keyFor ( sym )

此函数在被调用时执行以下步骤:

  1. 如果 sym 不是 Symbol,抛出 TypeError 异常。
  2. 返回 KeyForSymbol(sym)。

20.4.2.7 Symbol.match

Symbol.match 的初始值是众所周知的符号 %Symbol.match%表 1)。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.8 Symbol.matchAll

Symbol.matchAll 的初始值是众所周知的符号 %Symbol.matchAll%表 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.replace%表 1)。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.11 Symbol.search

Symbol.search 的初始值是众所周知的符号 %Symbol.search%表 1)。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.12 Symbol.species

Symbol.species 的初始值是众所周知的符号 %Symbol.species%表 1)。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.13 Symbol.split

Symbol.split 的初始值是众所周知的符号 %Symbol.split%表 1)。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.14 Symbol.toPrimitive

Symbol.toPrimitive 的初始值是众所周知的符号 %Symbol.toPrimitive%表 1)。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.15 Symbol.toStringTag

Symbol.toStringTag 的初始值是众所周知的符号 %Symbol.toStringTag%表 1)。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.16 Symbol.unscopables

Symbol.unscopables 的初始值是众所周知的符号 %Symbol.unscopables%表 1)。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.3 Symbol 原型对象的属性

Symbol 原型对象

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. sthis 值。
  2. sym 为 ? ThisSymbolValue(s)。
  3. 返回 sym.[[Description]]

20.4.3.3 Symbol.prototype.toString ( )

此方法在被调用时执行以下步骤:

  1. sym 为 ? ThisSymbolValue(this value)。
  2. 返回 SymbolDescriptiveString(sym)。

20.4.3.3.1 SymbolDescriptiveString ( sym )

抽象操作 SymbolDescriptiveString 接受参数 sym(一个 Symbol)并返回一个字符串。当被调用时执行以下步骤:

  1. descsym[[Description]] 值。
  2. 如果 descundefined,设 desc 为空字符串。
  3. 断言desc 是一个字符串
  4. 返回 "Symbol("desc")"字符串连接

20.4.3.4 Symbol.prototype.valueOf ( )

此方法在被调用时执行以下步骤:

  1. 返回 ? ThisSymbolValue(this value)。

20.4.3.4.1 ThisSymbolValue ( value )

抽象操作 ThisSymbolValue 接受参数 value(一个 ECMAScript 语言值)并返回一个 包含 Symbol 的 正常完成或一个 抛出完成。当被调用时执行以下步骤:

  1. 如果 value 是一个 Symbol,返回 value
  2. 如果 value 是一个对象value 有一个 [[SymbolData]] 内部槽,那么
    1. svalue.[[SymbolData]]
    2. 断言s 是一个 Symbol
    3. 返回 s
  3. 抛出 TypeError 异常。

20.4.3.5 Symbol.prototype [ %Symbol.toPrimitive% ] ( hint )

此方法被 ECMAScript 语言操作符调用,以将 Symbol 对象转换为原始值。

当被调用时执行以下步骤:

  1. 返回 ? ThisSymbolValue(this value)。

参数被忽略。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

此方法的 "name" 属性的值是 "[Symbol.toPrimitive]"

20.4.3.6 Symbol.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是字符串值 "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 KeyForSymbol ( sym )

抽象操作 KeyForSymbol 接受参数 sym(一个 Symbol)并返回一个字符串或 undefined。如果 symGlobalSymbolRegistry 列表中,将返回用于注册 sym 的字符串。当被调用时执行以下步骤:

  1. 对于 GlobalSymbolRegistry 列表的每个元素 e,执行
    1. 如果 SameValue(e.[[Symbol]], sym) 是 true,返回 e.[[Key]]
  2. 断言GlobalSymbolRegistry 列表当前不包含 sym 的条目。
  3. 返回 undefined

20.5 Error 对象

当运行时错误发生时,Error 对象的实例作为异常被抛出。Error 对象也可以作为用户定义异常类的基对象。

当 ECMAScript 实现检测到运行时错误时,它会抛出在 20.5.5 中定义的 NativeError 对象之一的新实例,或在 20.5.7 中定义的 AggregateError 对象的新实例。

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. O 为 ? OrdinaryCreateFromConstructor(newTarget, "%Error.prototype%", « [[ErrorData]] »)。
  3. 如果 message 不是 undefined,那么
    1. msg 为 ? ToString(message)。
    2. 执行 CreateNonEnumerableDataPropertyOrThrow(O, "message", msg)。
  4. 执行 ? InstallErrorCause(O, options)。
  5. 返回 O

20.5.2 Error 构造器的属性

Error 构造器

20.5.2.1 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 的初始值是空字符串。

20.5.3.3 Error.prototype.name

Error.prototype.name 的初始值是 "Error"

20.5.3.4 Error.prototype.toString ( )

此方法在被调用时执行以下步骤:

  1. Othis 值。
  2. 如果 O 不是对象,抛出 TypeError 异常。
  3. name 为 ? Get(O, "name")。
  4. 如果 nameundefined,设 name"Error";否则设 name 为 ? ToString(name)。
  5. msg 为 ? Get(O, "message")。
  6. 如果 msgundefined,设 msg 为空字符串;否则设 msg 为 ? ToString(msg)。
  7. 如果 name 是空字符串,返回 msg
  8. 如果 msg 是空字符串,返回 name
  9. 返回 name、代码单元 0x003A(冒号)、代码单元 0x0020(空格)和 msg字符串连接

20.5.4 Error 实例的属性

Error 实例是从 Error 原型对象继承属性的 普通对象,并有一个值为 undefined[[ErrorData]] 内部槽。[[ErrorData]] 的唯一指定用途是在 Object.prototype.toString 中将 Error、AggregateError 和 NativeError 实例标识为 Error 对象。

20.5.5 本标准中使用的原生 Error 类型

当检测到运行时错误时,会抛出下面 NativeError 对象之一或 AggregateError 对象的新实例。所有 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%

TypeError 用于表示不成功的操作,当其他 NativeError 对象都不适合表示失败原因时使用。

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. O 为 ? OrdinaryCreateFromConstructor(newTarget, "%NativeError.prototype%", « [[ErrorData]] »)。
  3. 如果 message 不是 undefined,那么
    1. msg 为 ? ToString(message)。
    2. 执行 CreateNonEnumerableDataPropertyOrThrow(O, "message", msg)。
  4. 执行 ? InstallErrorCause(O, options)。
  5. 返回 O

在步骤 2 中传递的字符串的实际值是 "%EvalError.prototype%""%RangeError.prototype%""%ReferenceError.prototype%""%SyntaxError.prototype%""%TypeError.prototype%""%URIError.prototype%" 中的一个,对应于正在定义的 NativeError 构造器

20.5.6.2 NativeError 构造器的属性

每个 NativeError 构造器

  • 有一个 [[Prototype]] 内部槽,其值是 %Error%
  • 有一个 "name" 属性,其值是字符串值 "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" 属性的初始值是空字符串。

20.5.6.3.3 NativeError.prototype.name

给定 NativeError 构造器的原型的 "name" 属性的初始值是由 构造器名称(代替 NativeError 使用的名称)组成的字符串值。

20.5.6.4 NativeError 实例的属性

NativeError 实例是从其 NativeError 原型对象继承属性的 普通对象,并有一个值为 undefined[[ErrorData]] 内部槽。[[ErrorData]] 的唯一指定用途是被 Object.prototype.toString20.1.3.6)用来标识 Error、AggregateError 或 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. O 为 ? OrdinaryCreateFromConstructor(newTarget, "%AggregateError.prototype%", « [[ErrorData]] »)。
  3. 如果 message 不是 undefined,那么
    1. msg 为 ? ToString(message)。
    2. 执行 CreateNonEnumerableDataPropertyOrThrow(O, "message", msg)。
  4. 执行 ? InstallErrorCause(O, options)。
  5. errorsList 为 ? IteratorToList(? GetIterator(errors, sync))。
  6. 执行 ! DefinePropertyOrThrow(O, "errors", PropertyDescriptor { [[Configurable]]: true, [[Enumerable]]: false, [[Writable]]: true, [[Value]]: CreateArrayFromList(errorsList) })。
  7. 返回 O

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 的初始值是空字符串。

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、AggregateError 或 NativeError 实例。

20.5.8 Error 对象的抽象操作

20.5.8.1 InstallErrorCause ( O, options )

抽象操作 InstallErrorCause 接受参数 O(一个对象)和 options(一个 ECMAScript 语言值),并返回一个 包含 unused正常完成或一个 抛出完成。当 options 上存在 "cause" 属性时,它用于在 O 上创建一个 "cause" 属性。当被调用时执行以下步骤:

  1. 如果 options 是一个对象且 ? HasProperty(options, "cause") 是 true,那么
    1. cause 为 ? Get(options, "cause")。
    2. 执行 CreateNonEnumerableDataPropertyOrThrow(O, "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. prim 为 ? ToNumeric(value)。
    2. 如果 prim 是 BigInt,设 n𝔽((prim))。
    3. 否则,设 nprim
  2. 否则,
    1. n+0𝔽
  3. 如果 NewTarget 是 undefined,返回 n
  4. O 为 ? OrdinaryCreateFromConstructor(NewTarget, "%Number.prototype%", « [[NumberData]] »)。
  5. 设置 O.[[NumberData]]n
  6. 返回 O

21.1.2 Number 构造器的属性

Number 构造器

21.1.2.1 Number.EPSILON

Number.EPSILON 的值是 1 与大于 1 的可表示为 Number 值的最小值之间差值的幅度的 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

此函数与全局 isNaN 函数(19.2.3)的不同之处在于,它在确定参数是否为 NaN 之前不会将其转换为 Number。

21.1.2.5 Number.isSafeInteger ( number )

当且仅当 nNumber 值不是任何其他 整数Number 值时,整数 n 是"安全整数"。

此函数在被调用时执行以下步骤:

  1. 如果 number整数 Number,那么
    1. 如果 abs((number)) ≤ 253 - 1,返回 true
  2. 返回 false

21.1.2.6 Number.MAX_SAFE_INTEGER

由于 IEEE 754-2019 精度限制所必需的舍入行为,每个大于 Number.MAX_SAFE_INTEGER整数Number 值都与至少一个其他 整数共享。因此,这些大幅度的 整数不是 安全的,并且不保证能准确表示为 Number 值,甚至不保证彼此可区分。例如,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

由于 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]] 内部槽的对象。

方法规范中的短语"此 Number 值"是指通过将方法调用的 this 值作为参数调用抽象操作 ThisNumberValue 返回的结果。

21.1.3.1 Number.prototype.constructor

Number.prototype.constructor 的初始值是 %Number%

21.1.3.2 Number.prototype.toExponential ( fractionDigits )

此方法返回一个字符串,包含以十进制指数记法表示的此 Number 值,有效数字的小数点前有一位数字,小数点后有 fractionDigits 位数字。如果 fractionDigitsundefined,它包含尽可能多的有效数字位数以唯一地指定 Number(就像在 ToString 中一样,除了在这种情况下 Number 总是以指数记法输出)。

当被调用时执行以下步骤:

  1. x 为 ? ThisNumberValue(this value)。
  2. f 为 ? ToIntegerOrInfinity(fractionDigits)。
  3. 断言:如果 fractionDigitsundefined,那么 f 是 0。
  4. 如果 x 不是 有限的,返回 Number::toString(x, 10)。
  5. 如果 f < 0 或 f > 100,抛出 RangeError 异常。
  6. 设置 x(x)。
  7. s 为空字符串。
  8. 如果 x < 0,那么
    1. 设置 s"-"
    2. 设置 x 为 -x
  9. 如果 x = 0,那么
    1. m 为由 f + 1 个代码单元 0x0030(数字零)组成的字符串值。
    2. e 为 0。
  10. 否则,
    1. 如果 fractionDigits 不是 undefined,那么
      1. en整数,使得 10fn < 10f + 1n × 10e - f - x 尽可能接近零。如果有两组这样的 en,选择使 n × 10e - f 更大的 en
    2. 否则,
      1. enff整数,使得 ff ≥ 0,10ffn < 10ff + 1𝔽(n × 10e - ff) 是 𝔽(x), 且 ff 尽可能小。注意 n 的十进制表示有 ff + 1 位数字,n 不能被 10 整除,且 n 的最低有效位不一定由这些条件唯一确定。
      2. 设置 fff
    3. m 为由 n 的十进制表示的数字组成的字符串值(按顺序,没有前导零)。
  11. 如果 f ≠ 0,那么
    1. am 的第一个代码单元。
    2. bm 的其他 f 个代码单元。
    3. 设置 ma"."b字符串连接
  12. 如果 e = 0,那么
    1. c"+"
    2. d"0"
  13. 否则,
    1. 如果 e > 0,那么
      1. c"+"
    2. 否则,
      1. 断言e < 0。
      2. c"-"
      3. 设置 e 为 -e
    3. d 为由 e 的十进制表示的数字组成的字符串值(按顺序,没有前导零)。
  14. 设置 mm"e"cd字符串连接
  15. 返回 sm字符串连接

对于提供比上述规则要求更准确转换的实现,建议将以下步骤 10.b.i 的替代版本用作指导:

  1. enf整数,使得 f ≥ 0, 10fn < 10f + 1𝔽(n × 10e - f) 是 𝔽(x),且 f 尽可能小。如果 n 有多种可能性,选择使 𝔽(n × 10e - f) 在值上最接近 𝔽(x) 的 n 值。如果有两个这样的可能 n 值,选择偶数的那个。

21.1.3.3 Number.prototype.toFixed ( fractionDigits )

注 1

此方法返回一个字符串,包含以十进制定点记法表示的此 Number 值,小数点后有 fractionDigits 位数字。如果 fractionDigitsundefined,假定为 0。

当被调用时执行以下步骤:

  1. x 为 ? ThisNumberValue(this value)。
  2. f 为 ? ToIntegerOrInfinity(fractionDigits)。
  3. 断言:如果 fractionDigitsundefined,那么 f 是 0。
  4. 如果 f 不是 有限的,抛出 RangeError 异常。
  5. 如果 f < 0 或 f > 100,抛出 RangeError 异常。
  6. 如果 x 不是 有限的,返回 Number::toString(x, 10)。
  7. 设置 x(x)。
  8. s 为空字符串。
  9. 如果 x < 0,那么
    1. 设置 s"-"
    2. 设置 x 为 -x
  10. 如果 x ≥ 1021,那么
    1. m 为 ! ToString(𝔽(x))。
  11. 否则,
    1. n 为一个 整数,使得 n / 10f - x 尽可能接近零。如果有两个这样的 n,选择较大的 n
    2. 如果 n = 0,设 m"0"。否则,设 m 为由 n 的十进制表示的数字组成的字符串值(按顺序,没有前导零)。
    3. 如果 f ≠ 0,那么
      1. km 的长度。
      2. 如果 kf,那么
        1. z 为由 f + 1 - k 个代码单元 0x0030(数字零)组成的字符串值。
        2. 设置 mzm字符串连接
        3. 设置 kf + 1。
      3. am 的前 k - f 个代码单元。
      4. bm 的其他 f 个代码单元。
      5. 设置 ma"."b字符串连接
  12. 返回 sm字符串连接
注 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,则使用此方法的以下规范:

此方法产生一个字符串值,该值表示根据 宿主环境当前区域设置的约定格式化的此 Number 值。此方法是 实现定义的,允许(但不鼓励)它返回与 toString 相同的内容。

此方法的可选参数的含义在 ECMA-402 规范中定义;不包含 ECMA-402 支持的实现不得将这些参数位置用于任何其他用途。

21.1.3.5 Number.prototype.toPrecision ( precision )

此方法返回一个字符串,包含以十进制指数记法表示的此 Number 值,有效数字的小数点前有一位数字,小数点后有 precision - 1 位数字,或者以十进制定点记法表示,有 precision 个有效数字。如果 precisionundefined,它改为调用 ToString

当被调用时执行以下步骤:

  1. x 为 ? ThisNumberValue(this value)。
  2. 如果 precisionundefined,返回 ! ToString(x)。
  3. p 为 ? ToIntegerOrInfinity(precision)。
  4. 如果 x 不是 有限的,返回 Number::toString(x, 10)。
  5. 如果 p < 1 或 p > 100,抛出 RangeError 异常。
  6. 设置 x(x)。
  7. s 为空字符串。
  8. 如果 x < 0,那么
    1. 设置 s 为代码单元 0x002D(连字符减号)。
    2. 设置 x 为 -x
  9. 如果 x = 0,那么
    1. m 为由 p 个代码单元 0x0030(数字零)组成的字符串值。
    2. e 为 0。
  10. 否则,
    1. en整数,使得 10p - 1n < 10pn × 10e - p + 1 - x 尽可能接近零。如果有两组这样的 en,选择使 n × 10e - p + 1 更大的 en
    2. m 为由 n 的十进制表示的数字组成的字符串值(按顺序,没有前导零)。
    3. 如果 e < -6 或 ep,那么
      1. 断言e ≠ 0。
      2. 如果 p ≠ 1,那么
        1. am 的第一个代码单元。
        2. bm 的其他 p - 1 个代码单元。
        3. 设置 ma"."b字符串连接
      3. 如果 e > 0,那么
        1. c 为代码单元 0x002B(加号)。
      4. 否则,
        1. 断言e < 0。
        2. c 为代码单元 0x002D(连字符减号)。
        3. 设置 e 为 -e
      5. d 为由 e 的十进制表示的数字组成的字符串值(按顺序,没有前导零)。
      6. 返回 sm、代码单元 0x0065(拉丁小写字母 E)、cd字符串连接
  11. 如果 e = p - 1,返回 sm字符串连接
  12. 如果 e ≥ 0,那么
    1. 设置 mm 的前 e + 1 个代码单元、代码单元 0x002E(句号)和 m 的其余 p - (e + 1) 个代码单元的 字符串连接
  13. 否则,
    1. 设置 m 为代码单元 0x0030(数字零)、代码单元 0x002E(句号)、-(e + 1) 个代码单元 0x0030(数字零)和字符串 m字符串连接
  14. 返回 sm字符串连接

21.1.3.6 Number.prototype.toString ( [ radix ] )

可选的 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不是 Number 或 Number 对象,它会抛出 TypeError 异常。因此,它不能转移到其他类型的对象上用作方法。

此方法的 "length" 属性是 1𝔽

21.1.3.7 Number.prototype.valueOf ( )

  1. 返回 ? ThisNumberValue(this value)。

21.1.3.7.1 ThisNumberValue ( value )

抽象操作 ThisNumberValue 接受参数 value(一个 ECMAScript 语言值),并返回一个 包含 Number 的 正常完成或一个 抛出完成。当被调用时执行以下步骤:

  1. 如果 value 是 Number,返回 value
  2. 如果 value 是对象value[[NumberData]] 内部槽,那么
    1. nvalue.[[NumberData]]
    2. 断言n 是 Number
    3. 返回 n
  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. prim 为 ? ToPrimitive(value, number)。
  3. 如果 prim 是 Number,返回 ? NumberToBigInt(prim)。
  4. 否则,返回 ? ToBigInt(prim)。

21.2.1.1.1 NumberToBigInt ( number )

抽象操作 NumberToBigInt 接受参数 number(一个 Number),并返回一个 包含 BigInt 的 正常完成或一个 抛出完成。当被调用时执行以下步骤:

  1. 如果 number 不是 整数 Number, 抛出 RangeError 异常。
  2. 返回 ((number))。

21.2.2 BigInt 构造器的属性

BigInt 构造器

21.2.2.1 BigInt.asIntN ( bits, bigint )

此函数在被调用时执行以下步骤:

  1. 设置 bits 为 ? ToIndex(bits)。
  2. 设置 bigint 为 ? ToBigInt(bigint)。
  3. mod(bigint) modulo 2bits
  4. 如果 mod ≥ 2bits - 1,返回 (mod - 2bits);否则,返回 (mod)。

21.2.2.2 BigInt.asUintN ( bits, bigint )

此函数在被调用时执行以下步骤:

  1. 设置 bits 为 ? ToIndex(bits)。
  2. 设置 bigint 为 ? ToBigInt(bigint)。
  3. 返回 ((bigint) modulo 2bits)。

21.2.2.3 BigInt.prototype

BigInt.prototype 的初始值是 BigInt 原型对象

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.2.3 BigInt 原型对象的属性

BigInt 原型对象

方法规范中的短语"此 BigInt 值"是指通过将方法调用的 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,则使用此方法的以下规范:

此方法产生一个字符串值,该值表示根据 宿主环境当前区域设置的约定格式化的此 BigInt 值。此方法是 实现定义的,允许(但不鼓励)它返回与 toString 相同的内容。

此方法的可选参数的含义在 ECMA-402 规范中定义;不包含 ECMA-402 支持的实现不得将这些参数位置用于任何其他用途。

21.2.3.3 BigInt.prototype.toString ( [ radix ] )

可选的 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不是 BigInt 或 BigInt 对象,它会抛出 TypeError 异常。因此,它不能转移到其他类型的对象上用作方法。

21.2.3.4 BigInt.prototype.valueOf ( )

  1. 返回 ? ThisBigIntValue(this value)。

21.2.3.4.1 ThisBigIntValue ( value )

抽象操作 ThisBigIntValue 接受参数 value(一个 ECMAScript 语言值),并返回一个 包含 BigInt 的 正常完成或一个 抛出完成。当被调用时执行以下步骤:

  1. 如果 value 是 BigInt,返回 value
  2. 如果 value 是对象value[[BigIntData]] 内部槽,那么
    1. 断言value.[[BigIntData]] 是 BigInt
    2. 返回 value.[[BigIntData]]
  3. 抛出 TypeError 异常。

21.2.3.5 BigInt.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是字符串值 "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]] 内部方法;它不能作为函数被调用。

在此规范中,短语"xNumber 值"具有在 6.1.6.1 中定义的技术含义。

21.3.1 Math 对象的值属性

21.3.1.1 Math.E

e(自然对数的底)的 Number 值,约为 2.7182818284590452354。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.3.1.2 Math.LN10

10 的自然对数的 Number 值,约为 2.302585092994046。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.3.1.3 Math.LN2

2 的自然对数的 Number 值,约为 0.6931471805599453。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.3.1.4 Math.LOG10E

e(自然对数的底)的以 10 为底的对数的 Number 值;此值约为 0.4342944819032518。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

Math.LOG10E 的值约为 Math.LN10 值的倒数。

21.3.1.5 Math.LOG2E

e(自然对数的底)的以 2 为底的对数的 Number 值;此值约为 1.4426950408889634。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

Math.LOG2E 的值约为 Math.LN2 值的倒数。

21.3.1.6 Math.PI

π(圆的周长与其直径的比值)的 Number 值,约为 3.1415926535897932。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.3.1.7 Math.SQRT1_2

½ 的平方根的 Number 值,约为 0.7071067811865476。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

Math.SQRT1_2 的值约为 Math.SQRT2 值的倒数。

21.3.1.8 Math.SQRT2

2 的平方根的 Number 值,约为 1.4142135623730951。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.3.1.9 Math [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是字符串值 "Math"

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

21.3.2 Math 对象的函数属性

函数 acosacoshasinasinhatanatanhatan2cbrtcoscoshexpexpm1hypotloglog1plog2log10powrandomsinsinhtantanh 的行为在此处未被精确指定,除了要求对表示感兴趣的边界情况的某些参数值有特定结果。对于其他参数值,这些函数意图计算熟悉的数学函数结果的近似值,但在近似算法的选择上允许一定的灵活性。总的意图是实现者应该能够在给定硬件平台上为 ECMAScript 使用与该平台上 C 程序员可用的相同数学库。

虽然算法的选择留给实现,但建议(但不是本标准规定的)实现使用 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. 返回一个实现近似的 Number 值,表示 (n) 的反余弦值。

21.3.2.3 Math.acosh ( x )

此函数返回 x 的反双曲余弦值。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+∞𝔽,返回 n
  3. 如果 n1𝔽,返回 +0𝔽
  4. 如果 n < 1𝔽,返回 NaN
  5. 返回一个实现近似的 Number 值,表示 (n) 的反双曲余弦值。

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. 返回一个实现近似的 Number 值,表示 (n) 的反正弦值。

21.3.2.5 Math.asinh ( x )

此函数返回 x 的反双曲正弦值。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 n 不是有限的n+0𝔽-0𝔽,返回 n
  3. 返回一个实现近似的 Number 值,表示 (n) 的反双曲正弦值。

21.3.2.6 Math.atan ( x )

此函数返回 x 的反正切值。结果以弧度表示,在从 𝔽(-π / 2) 到 𝔽(π / 2) 的闭区间内。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+0𝔽,或 -0𝔽 之一,返回 n
  3. 如果 n+∞𝔽,返回一个实现近似的 Number 值,表示 π / 2。
  4. 如果 n-∞𝔽,返回一个实现近似的 Number 值,表示 -π / 2。
  5. 返回一个实现近似的 Number 值,表示 (n) 的反正切值。

21.3.2.7 Math.atanh ( x )

此函数返回 x 的反双曲正切值。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+0𝔽,或 -0𝔽 之一,返回 n
  3. 如果 n > 1𝔽n < -1𝔽,返回 NaN
  4. 如果 n1𝔽,返回 +∞𝔽
  5. 如果 n-1𝔽,返回 -∞𝔽
  6. 返回一个实现近似的 Number 值,表示 (n) 的反双曲正切值。

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+∞𝔽,返回一个实现近似的 Number 值,表示 π / 4。
    2. 如果 nx-∞𝔽,返回一个实现近似的 Number 值,表示 3π / 4。
    3. 返回一个实现近似的 Number 值,表示 π / 2。
  5. 如果 ny-∞𝔽,则
    1. 如果 nx+∞𝔽,返回一个实现近似的 Number 值,表示 -π / 4。
    2. 如果 nx-∞𝔽,返回一个实现近似的 Number 值,表示 -3π / 4。
    3. 返回一个实现近似的 Number 值,表示 -π / 2。
  6. 如果 ny+0𝔽,则
    1. 如果 nx > +0𝔽nx+0𝔽,返回 +0𝔽
    2. 返回一个实现近似的 Number 值,表示 π。
  7. 如果 ny-0𝔽,则
    1. 如果 nx > +0𝔽nx+0𝔽,返回 -0𝔽
    2. 返回一个实现近似的 Number 值,表示 -π。
  8. 断言ny有限的且既不是 +0𝔽 也不是 -0𝔽
  9. 如果 ny > +0𝔽,则
    1. 如果 nx+∞𝔽,返回 +0𝔽
    2. 如果 nx-∞𝔽,返回一个实现近似的 Number 值,表示 π。
    3. 如果 nx+0𝔽-0𝔽,返回一个实现近似的 Number 值,表示 π / 2。
  10. 如果 ny < -0𝔽,则
    1. 如果 nx+∞𝔽,返回 -0𝔽
    2. 如果 nx-∞𝔽,返回一个实现近似的 Number 值,表示 -π。
    3. 如果 nx+0𝔽-0𝔽,返回一个实现近似的 Number 值,表示 -π / 2。
  11. 断言nx有限的且既不是 +0𝔽 也不是 -0𝔽
  12. rabs((ny) / (nx)) 的反正切值。
  13. 如果 nx < -0𝔽,则
    1. 如果 ny > +0𝔽,设 r 为 π - r
    2. 否则,设 r 为 -π + r
  14. 否则,
    1. 如果 ny < -0𝔽,设 r 为 -r
  15. 返回一个实现近似的 Number 值,表示 r

21.3.2.9 Math.cbrt ( x )

此函数返回 x 的立方根。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 n 不是有限的n+0𝔽-0𝔽,返回 n
  3. 返回一个实现近似的 Number 值,表示 (n) 的立方根。

21.3.2.10 Math.ceil ( x )

此函数返回不小于 x 的最小(最接近 -∞)整数 Number 值。如果 x 已经是一个整数 Number,结果就是 x

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 n 不是有限的n+0𝔽-0𝔽,返回 n
  3. 如果 n < -0𝔽n > -1𝔽,返回 -0𝔽
  4. 如果 n 是一个整数 Number,返回 n
  5. 返回不小于 n 的最小(最接近 -∞)整数 Number 值。
注意

Math.ceil(x) 的值与 -Math.floor(-x) 的值相同。

21.3.2.11 Math.clz32 ( x )

此函数在被调用时执行以下步骤:

  1. n 为 ? ToUint32(x)。
  2. pn 的无符号 32 位二进制表示中前导零位的数量。
  3. 返回 𝔽(p)。
注意

如果 n+0𝔽-0𝔽,此方法返回 32𝔽。如果 n 的 32 位二进制编码的最高有效位是 1,此方法返回 +0𝔽

21.3.2.12 Math.cos ( x )

此函数返回 x 的余弦值。参数以弧度表示。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 n 不是有限的,返回 NaN
  3. 如果 n+0𝔽-0𝔽,返回 1𝔽
  4. 返回一个实现近似的 Number 值,表示 (n) 的余弦值。

21.3.2.13 Math.cosh ( x )

此函数返回 x 的双曲余弦值。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN,返回 NaN
  3. 如果 n+∞𝔽-∞𝔽,返回 +∞𝔽
  4. 如果 n+0𝔽-0𝔽,返回 1𝔽
  5. 返回一个实现近似的 Number 值,表示 (n) 的双曲余弦值。
注意

Math.cosh(x) 的值与 (Math.exp(x) + Math.exp(-x)) / 2 的值相同。

21.3.2.14 Math.exp ( x )

此函数返回 x 的指数函数(ex 次幂,其中 e 是自然对数的底)。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+∞𝔽,返回 n
  3. 如果 n+0𝔽-0𝔽,返回 1𝔽
  4. 如果 n-∞𝔽,返回 +0𝔽
  5. 返回一个实现近似的 Number 值,表示 (n) 的指数函数。

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. 返回一个实现近似的 Number 值,表示 exp - 1。

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 值。
注意

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 值。
注意

此操作与先转换为 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 为一个新的空列表
  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𝔽,设 onlyZerofalse
  6. 如果 onlyZerotrue,返回 +0𝔽
  7. 返回一个实现近似的 Number 值,表示 coerced 元素的数学值的平方和的平方根。

此函数的 "length" 属性是 2𝔽

注意

实现应当注意避免当此函数以两个或更多参数调用时,在朴素实现中容易发生的溢出和下溢导致的精度损失。

21.3.2.20 Math.imul ( x, y )

此函数在被调用时执行以下步骤:

  1. a(? ToUint32(x))。
  2. b(? ToUint32(y))。
  3. product 为 (a × b) 232
  4. 如果 product ≥ 231,返回 𝔽(product - 232);否则返回 𝔽(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. 返回一个实现近似的 Number 值,表示 (n) 的自然对数。

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. 返回一个实现近似的 Number 值,表示 1 + (n) 的自然对数。

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. 返回一个实现近似的 Number 值,表示 (n) 的以 10 为底的对数。

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. 返回一个实现近似的 Number 值,表示 (n) 的以 2 为底的对数。

21.3.2.25 Math.max ( ...args )

给定零个或多个参数,此函数对每个参数调用 ToNumber 并返回结果值中的最大值。

它在被调用时执行以下步骤:

  1. coerced 为一个新的空列表
  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,设 highestnumber
  5. 返回 highest
注意

确定最大值的值比较使用 IsLessThan 算法完成,但是 +0𝔽 被认为大于 -0𝔽

此函数的 "length" 属性是 2𝔽

21.3.2.26 Math.min ( ...args )

给定零个或多个参数,此函数对每个参数调用 ToNumber 并返回结果值中的最小值。

它在被调用时执行以下步骤:

  1. coerced 为一个新的空列表
  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,设 lowestnumber
  5. 返回 lowest
注意

确定最小值的值比较使用 IsLessThan 算法完成,但是 +0𝔽 被认为大于 -0𝔽

此函数的 "length" 属性是 2𝔽

21.3.2.27 Math.pow ( base, exponent )

此函数在被调用时执行以下步骤:

  1. base 为 ? ToNumber(base)。
  2. exponent 为 ? ToNumber(exponent)。
  3. 返回 Number::exponentiate(base, exponent)。

21.3.2.28 Math.random ( )

此函数返回一个具有正号的 Number 值,大于或等于 +0𝔽 但严格小于 1𝔽, 使用实现定义的算法或策略随机或伪随机选择,在该范围内具有近似均匀分布。

为不同领域创建的每个 Math.random 函数必须从连续调用中产生不同的值序列。

21.3.2.29 Math.round ( x )

此函数返回最接近 x 且为整数的 Number 值。如果两个整数 Numberx 的距离相等,则结果是更接近 +∞ 的 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。
注意 1

Math.round(3.5) 返回 4,但 Math.round(-3.5) 返回 -3。

注意 2

Math.round(x) 的值并不总是与 Math.floor(x + 0.5) 的值相同。当 x-0𝔽x 小于 -0𝔽 但大于或等于 -0.5𝔽 时,Math.round(x) 返回 -0𝔽,但 Math.floor(x + 0.5) 返回 +0𝔽Math.round(x) 也可能因为计算 x + 0.5 时的内部舍入而与 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. 返回一个实现近似的 Number 值,表示 (n) 的正弦值。

21.3.2.32 Math.sinh ( x )

此函数返回 x 的双曲正弦值。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 n 不是有限的n+0𝔽-0𝔽,返回 n
  3. 返回一个实现近似的 Number 值,表示 (n) 的双曲正弦值。
注意

Math.sinh(x) 的值与 (Math.exp(x) - Math.exp(-x)) / 2 的值相同。

21.3.2.33 Math.sqrt ( x )

此函数返回 x 的平方根。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+0𝔽-0𝔽,或 +∞𝔽 之一,返回 n
  3. 如果 n < -0𝔽,返回 NaN
  4. 返回 𝔽((n) 的平方根)。

21.3.2.34 Math.tan ( x )

此函数返回 x 的正切值。参数以弧度表示。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+0𝔽,或 -0𝔽 之一,返回 n
  3. 如果 n+∞𝔽-∞𝔽,返回 NaN
  4. 返回一个实现近似的 Number 值,表示 (n) 的正切值。

21.3.2.35 Math.tanh ( x )

此函数返回 x 的双曲正切值。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+0𝔽,或 -0𝔽 之一,返回 n
  3. 如果 n+∞𝔽,返回 1𝔽
  4. 如果 n-∞𝔽,返回 -1𝔽
  5. 返回一个实现近似的 Number 值,表示 (n) 的双曲正切值。
注意

Math.tanh(x) 的值与 (Math.exp(x) - Math.exp(-x)) / (Math.exp(x) + Math.exp(-x)) 的值相同。

21.3.2.36 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. 返回最接近 n 且朝向 +0𝔽 方向的整数 Number

21.4 Date 对象

21.4.1 Date 对象概述和抽象操作的定义

以下抽象操作时间值(在 21.4.1.1 中定义)进行操作。注意,在任何情况下,如果这些函数的任何参数是 NaN,结果将是 NaN

21.4.1.1 时间值和时间范围

ECMAScript 中的时间测量类似于 POSIX 中的时间测量,特别是共享以前推格里高利历为基础的定义,以 1970 年 1 月 1 日 UTC 午夜开始为纪元,并且将每一天计算为恰好 86,400 秒(每秒为 1000 毫秒)。

ECMAScript 时间值是一个 Number,要么是一个有限整数 Number,表示精确到毫秒的时间瞬间,要么是 NaN,表示没有特定的时间瞬间。是 24 × 60 × 60 × 1000 = 86,400,000 的倍数(即,对于某个整数 d 为 86,400,000 × d)的时间值表示在纪元之后 d 个完整 UTC 天(负 d 表示在纪元之前)的 UTC 天开始时的瞬间。任何其他有限时间值 t 相对于最大的前导时间值 s(其为这样的倍数)定义,并表示在与 s 相同的 UTC 天内但在它之后 (t - 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 毫秒。这产生了一个支持的时间值范围,恰好相对于 1970 年 1 月 1 日 UTC 午夜为 -100,000,000 天到 100,000,000 天。

1970 年 1 月 1 日 UTC 午夜开始的确切时刻由时间值 +0𝔽 表示。

注意

在前推格里高利历中,闰年恰好是那些既能被 4 整除,又能被 400 整除或不能被 100 整除的年份。

前推格里高利历的 400 年周期包含 97 个闰年。这产生平均每年 365.2425 天,即 31,556,952,000 毫秒。因此,Number 能以毫秒精度精确表示的最大范围大约是相对于 1970 年的 -285,426 到 285,426 年。本节中指定的时间值支持的较小范围大约是相对于 1970 年的 -273,790 到 273,790 年。

21.4.1.2 时间相关常量

这些常量被以下部分的算法引用。

HoursPerDay = 24
MinutesPerHour = 60
SecondsPerMinute = 60
msPerSecond = 1000𝔽
msPerMinute = 60000𝔽 = msPerSecond × 𝔽(SecondsPerMinute)
msPerHour = 3600000𝔽 = msPerMinute × 𝔽(MinutesPerHour)
msPerDay = 86400000𝔽 = msPerHour × 𝔽(HoursPerDay)

21.4.1.3 Day ( t )

抽象操作 Day 接受参数 t(一个有限时间值)并返回一个整数 Number。它返回 t 所在天的天数。它在被调用时执行以下步骤:

  1. 返回 𝔽(floor((t / msPerDay)))。

21.4.1.4 TimeWithinDay ( t )

抽象操作 TimeWithinDay 接受参数 t(一个有限时间值)并返回一个在从 +0𝔽(包含)到 msPerDay(不包含)的区间内的整数 Number。它返回自 t 所在天开始以来的毫秒数。它在被调用时执行以下步骤:

  1. 返回 𝔽((t) (msPerDay))。

21.4.1.5 DaysInYear ( y )

抽象操作 DaysInYear 接受参数 y(一个整数 Number)并返回 365𝔽366𝔽。它返回年份 y 中的天数。闰年有 366 天;所有其他年份有 365 天。它在被调用时执行以下步骤:

  1. ry(y)。
  2. 如果 (ry 400) = 0,返回 366𝔽
  3. 如果 (ry 100) = 0,返回 365𝔽
  4. 如果 (ry 4) = 0,返回 366𝔽
  5. 返回 365𝔽

21.4.1.6 DayFromYear ( y )

抽象操作 DayFromYear 接受参数 y(一个整数 Number)并返回一个整数 Number。它返回年份 y 第一天的天数。它在被调用时执行以下步骤:

  1. ry(y)。
  2. 注意:在以下步骤中, numYears1numYears4numYears100numYears400 分别表示在纪元和年份 y 开始之间发生的可被 1、4、100 和 400 整除的年数。如果 y纪元之前,该数字为负数。
  3. numYears1 为 (ry - 1970)。
  4. numYears4floor((ry - 1969) / 4)。
  5. numYears100floor((ry - 1901) / 100)。
  6. numYears400floor((ry - 1601) / 400)。
  7. 返回 𝔽(365 × numYears1 + numYears4 - numYears100 + numYears400)。

21.4.1.7 TimeFromYear ( y )

抽象操作 TimeFromYear 接受参数 y(一个整数 Number)并返回一个时间值。它返回年份 y 开始的时间值。它在被调用时执行以下步骤:

  1. 返回 msPerDay × DayFromYear(y)。

21.4.1.8 YearFromTime ( t )

抽象操作 YearFromTime 接受参数 t(一个有限时间值)并返回一个整数 Number。它返回 t 所在的年份。它在被调用时执行以下步骤:

  1. 返回最大的整数 Number y(最接近 +∞),使得 TimeFromYear(y) ≤ t

21.4.1.9 DayWithinYear ( t )

抽象操作 DayWithinYear 接受参数 t(一个有限时间值)并返回一个在从 +0𝔽365𝔽闭区间内的整数 Number。它在被调用时执行以下步骤:

  1. 返回 Day(t) - DayFromYear(YearFromTime(t))。

21.4.1.10 InLeapYear ( t )

抽象操作 InLeapYear 接受参数 t(一个有限时间值)并返回 +0𝔽1𝔽。如果 t 在闰年内,它返回 1𝔽,否则返回 +0𝔽。它在被调用时执行以下步骤:

  1. 如果 DaysInYear(YearFromTime(t)) 是 366𝔽,返回 1𝔽;否则返回 +0𝔽

21.4.1.11 MonthFromTime ( t )

抽象操作 MonthFromTime 接受参数 t(一个有限时间值)并返回一个在从 +0𝔽11𝔽闭区间内的整数 Number。它返回一个标识 t 所在月份的 Number。月份值 +0𝔽 指定一月;1𝔽 指定二月;2𝔽 指定三月; 3𝔽 指定四月;4𝔽 指定五月;5𝔽 指定六月; 6𝔽 指定七月;7𝔽 指定八月;8𝔽 指定九月; 9𝔽 指定十月;10𝔽 指定十一月;11𝔽 指定十二月。注意 MonthFromTime(+0𝔽) = +0𝔽,对应于 1970 年 1 月 1 日星期四。它在被调用时执行以下步骤:

  1. inLeapYearInLeapYear(t)。
  2. dayWithinYearDayWithinYear(t)。
  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 ( t )

抽象操作 DateFromTime 接受参数 t(一个有限时间值)并返回一个在从 1𝔽31𝔽闭区间内的整数 Number。它返回 t 所在月份的日期。它在被调用时执行以下步骤:

  1. inLeapYearInLeapYear(t)。
  2. dayWithinYearDayWithinYear(t)。
  3. monthMonthFromTime(t)。
  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 ( t )

抽象操作 WeekDay 接受参数 t(一个有限时间值)并返回一个在从 +0𝔽6𝔽闭区间内的整数 Number。它返回一个标识 t 所在星期几的 Number。星期值 +0𝔽 指定星期日;1𝔽 指定星期一;2𝔽 指定星期二; 3𝔽 指定星期三;4𝔽 指定星期四;5𝔽 指定星期五; 6𝔽 指定星期六。注意 WeekDay(+0𝔽) = 4𝔽,对应于 1970 年 1 月 1 日星期四。它在被调用时执行以下步骤:

  1. 返回 𝔽((Day(t) + 4𝔽) 7)。

21.4.1.14 HourFromTime ( t )

抽象操作 HourFromTime 接受参数 t(一个有限时间值)并返回一个在从 +0𝔽23𝔽闭区间内的整数 Number。它返回 t 所在天的小时。它在被调用时执行以下步骤:

  1. 返回 𝔽(floor((t / msPerHour)) HoursPerDay)。

21.4.1.15 MinFromTime ( t )

抽象操作 MinFromTime 接受参数 t(一个有限时间值)并返回一个在从 +0𝔽59𝔽闭区间内的整数 Number。它返回 t 所在小时的分钟。它在被调用时执行以下步骤:

  1. 返回 𝔽(floor((t / msPerMinute)) MinutesPerHour)。

21.4.1.16 SecFromTime ( t )

抽象操作 SecFromTime 接受参数 t(一个有限时间值)并返回一个在从 +0𝔽59𝔽闭区间内的整数 Number。它返回 t 所在分钟的秒数。它在被调用时执行以下步骤:

  1. 返回 𝔽(floor((t / msPerSecond)) SecondsPerMinute)。

21.4.1.17 msFromTime ( t )

抽象操作 msFromTime 接受参数 t(一个有限时间值)并返回一个在从 +0𝔽999𝔽闭区间内的整数 Number。它返回 t 所在秒的毫秒数。它在被调用时执行以下步骤:

  1. 返回 𝔽((t) (msPerSecond))。

21.4.1.18 GetUTCEpochNanoseconds ( year, month, day, hour, minute, second, millisecond, microsecond, nanosecond )

抽象操作 GetUTCEpochNanoseconds 接受参数 year(一个整数)、 month(一个在 1 到 12 的闭区间内的整数)、day(一个在 1 到 31 的闭区间内的整数)、hour(一个在 0 到 23 的闭区间内的整数)、minute(一个在 0 到 59 的闭区间内的整数)、second(一个在 0 到 59 的闭区间内的整数)、millisecond(一个在 0 到 999 的闭区间内的整数)、microsecond(一个在 0 到 999 的闭区间内的整数)和 nanosecond(一个在 0 到 999 的闭区间内的整数)并返回一个 BigInt。返回值表示自纪元以来对应于给定 ISO 8601 日历日期和 UTC 挂钟时间的纳秒数。它在被调用时执行以下步骤:

  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 的闭区间内的代码单元组成的字符串。ECMAScript 实现支持的时区可能是可用命名时区,由 AvailableNamedTimeZoneIdentifiers 返回的时区标识符记录[[Identifier]] 字段表示,或者是偏移时区,由 IsTimeZoneOffsetString 返回 true 的字符串表示。

主要时区标识符是可用命名时区的首选标识符。 非主要时区标识符是不是主要时区标识符的可用命名时区标识符。 可用命名时区标识符要么是主要时区标识符,要么是非主要时区标识符。 每个可用命名时区标识符恰好与一个可用命名时区关联。 每个可用命名时区恰好与一个主要时区标识符和零个或多个非主要时区标识符关联。

ECMAScript 实现必须支持标识符为 "UTC" 的可用命名时区,该标识符必须是 UTC 时区的主要时区标识符。 此外,实现可以支持任意数量的其他可用命名时区。

遵循 ECMA-402 国际化 API 规范中描述的时区要求的实现称为时区感知的。 时区感知实现必须支持对应于 IANA 时区数据库的 Zone 和 Link 名称的可用命名时区,并且仅支持这些名称。 在时区感知实现中,主要时区标识符是 Zone 名称,非主要时区标识符是 Link 名称,分别在 IANA 时区数据库中,除非被 ECMA-402 规范中指定的 AvailableNamedTimeZoneIdentifiers 特别覆盖。 不支持整个 IANA 时区数据库的实现仍然建议使用 IANA 时区数据库名称作为标识符来表示时区。

21.4.1.20 GetNamedTimeZoneEpochNanoseconds ( timeZoneIdentifier, year, month, day, hour, minute, second, millisecond, microsecond, nanosecond )

实现定义的抽象操作 GetNamedTimeZoneEpochNanoseconds 接受参数 timeZoneIdentifier(一个字符串)、year(一个整数)、month(一个在 1 到 12 的闭区间内的整数)、day(一个在 1 到 31 的闭区间内的整数)、hour(一个在 0 到 23 的闭区间内的整数)、minute(一个在 0 到 59 的闭区间内的整数)、second(一个在 0 到 59 的闭区间内的整数)、millisecond(一个在 0 到 999 的闭区间内的整数)、microsecond(一个在 0 到 999 的闭区间内的整数)和 nanosecond(一个在 0 到 999 的闭区间内的整数)并返回一个 BigInt 的列表。 返回的列表中的每个值表示自纪元以来对应于给定 ISO 8601 日历日期和在由 timeZoneIdentifier 标识的命名时区中的挂钟时间的纳秒数。

当输入表示由于负时区转换(例如夏令时结束或由于时区规则变更导致时区偏移减少)而多次出现的本地时间时,返回的列表将有多个元素,并将按数值升序排序。 当输入表示由于正时区转换(例如夏令时开始或由于时区规则变更导致时区偏移增加)而跳过的本地时间时,返回的列表将为空。 否则,返回的列表将有一个元素。

GetNamedTimeZoneEpochNanoseconds 的默认实现,用于不包含任何时区本地政治规则的 ECMAScript 实现,在被调用时执行以下步骤:

  1. 断言timeZoneIdentifier"UTC"
  2. epochNanosecondsGetUTCEpochNanoseconds(year, month, day, hour, minute, second, millisecond, microsecond, nanosecond)。
  3. 返回 « epochNanoseconds »。
注意

时区感知实现(建议所有其他实现也如此)需要使用 IANA 时区数据库 https://www.iana.org/time-zones/ 的时区信息。

2017 年 11 月 5 日在 America/New_York 的凌晨 1:30 重复了两次,所以 GetNamedTimeZoneEpochNanoseconds("America/New_York", 2017, 11, 5, 1, 30, 0, 0, 0, 0) 将返回一个长度为 2 的列表,其中第一个元素表示 05:30 UTC(对应于 UTC 偏移 -04:00 的 01:30 美国东部夏令时),第二个元素表示 06:30 UTC(对应于 UTC 偏移 -05:00 的 01:30 美国东部标准时间)。

2017 年 3 月 12 日在 America/New_York 的凌晨 2:30 不存在,所以 GetNamedTimeZoneEpochNanoseconds("America/New_York", 2017, 3, 12, 2, 30, 0, 0, 0, 0) 将返回一个空的列表

21.4.1.21 GetNamedTimeZoneOffsetNanoseconds ( timeZoneIdentifier, epochNanoseconds )

实现定义的抽象操作 GetNamedTimeZoneOffsetNanoseconds 接受参数 timeZoneIdentifier(一个字符串)和 epochNanoseconds(一个 BigInt)并返回一个整数

返回的整数表示由 timeZoneIdentifier 标识的命名时区在对应于相对于纪元epochNanoseconds 的瞬间的 UTC 偏移,均以纳秒为单位。

GetNamedTimeZoneOffsetNanoseconds 的默认实现,用于不包含任何时区本地政治规则的 ECMAScript 实现,在被调用时执行以下步骤:

  1. 断言timeZoneIdentifier"UTC"
  2. 返回 0。
注意

时区偏移值可能是正数或负数。

21.4.1.22 时区标识符记录

时区标识符记录是一个记录,用于描述一个可用命名时区标识符及其对应的主要时区标识符

时区标识符记录具有表 64 中列出的字段。

表 64:时区标识符记录字段
字段名 含义
[[Identifier]] 一个字符串 实现支持的可用命名时区标识符
[[PrimaryIdentifier]] 一个字符串 [[Identifier]] 解析到的主要时区标识符
注意

如果 [[Identifier]] 是一个主要时区标识符,那么 [[Identifier]] 就是 [[PrimaryIdentifier]]

21.4.1.23 AvailableNamedTimeZoneIdentifiers ( )

实现定义的抽象操作 AvailableNamedTimeZoneIdentifiers 不接受参数并返回一个时区标识符记录列表。 其结果描述此实现中所有可用命名时区标识符,以及对应于每个可用命名时区标识符主要时区标识符。 该列表根据每个时区标识符记录[[Identifier]] 字段排序。

时区感知实现,包括所有实现 ECMA-402 国际化 API 的实现,必须按照 ECMA-402 规范中指定的方式实现 AvailableNamedTimeZoneIdentifiers 抽象操作。 对于不是时区感知的实现,AvailableNamedTimeZoneIdentifiers 在被调用时执行以下步骤:

  1. 如果实现不包含任何时区的本地政治规则,那么
    1. 返回 « 时区标识符记录 { [[Identifier]]: "UTC", [[PrimaryIdentifier]]: "UTC" } »。
  2. identifiers 为按字典序代码单元顺序排序的唯一可用命名时区标识符列表
  3. result 为一个新的空列表
  4. 对于 identifiers 的每个元素 identifier,执行
    1. primaryidentifier
    2. 如果 identifier 是此实现中的非主要时区标识符并且 identifier 不是 "UTC",那么
      1. primary 为与 identifier 关联的主要时区标识符
      2. 注意:实现可能需要迭代解析 identifier 以获得主要时区标识符
    3. record时区标识符记录 { [[Identifier]]: identifier, [[PrimaryIdentifier]]: primary }。
    4. record 附加到 result
  5. 断言result 包含一个时区标识符记录 r,使得 r.[[Identifier]]"UTC" 并且 r.[[PrimaryIdentifier]]"UTC"
  6. 返回 result

21.4.1.24 SystemTimeZoneIdentifier ( )

实现定义的抽象操作 SystemTimeZoneIdentifier 不接受参数并返回一个字符串。 它返回一个表示宿主环境当前时区的字符串,该字符串要么是一个表示 UTC 偏移的字符串(IsTimeZoneOffsetString 对其返回 true),要么是一个主要时区标识符。 它在被调用时执行以下步骤:

  1. 如果实现仅支持 UTC 时区,返回 "UTC"
  2. systemTimeZoneString 为表示宿主环境当前时区的字符串,要么是一个主要时区标识符,要么是一个偏移时区标识符。
  3. 返回 systemTimeZoneString
注意

为了确保实现在 Date 对象的方法中通常提供的功能级别,建议 SystemTimeZoneIdentifier 返回对应于宿主环境时区设置的 IANA 时区名称(如果存在的话)。 GetNamedTimeZoneEpochNanosecondsGetNamedTimeZoneOffsetNanoseconds 必须反映该时区中标准时间和夏令时的本地政治规则(如果存在这些规则)。

例如,如果宿主环境是系统上的浏览器,用户选择了美国东部时间作为他们的时区, SystemTimeZoneIdentifier 返回 "America/New_York"

21.4.1.25 LocalTime ( t )

抽象操作 LocalTime 接受参数 t(一个有限时间值)并返回一个整数 Number。 它将 t 从 UTC 转换为本地时间。 应该使用在 t 时刻生效的标准时间和夏令时的本地政治规则来按照本节规定的方式确定结果。 它在被调用时执行以下步骤:

  1. systemTimeZoneIdentifierSystemTimeZoneIdentifier()。
  2. 如果 IsTimeZoneOffsetString(systemTimeZoneIdentifier) 是 true,那么
    1. offsetNsParseTimeZoneOffsetString(systemTimeZoneIdentifier)。
  3. 否则,
    1. offsetNsGetNamedTimeZoneOffsetNanoseconds(systemTimeZoneIdentifier, ((t) × 106))。
  4. offsetMstruncate(offsetNs / 106)。
  5. 返回 t + 𝔽(offsetMs)。
注意 1

如果实现中没有本地时间 t 的政治规则,结果就是 t,因为 SystemTimeZoneIdentifier 返回 "UTC"GetNamedTimeZoneOffsetNanoseconds 返回 0。

注意 2

时区感知实现(建议所有其他实现也如此)需要使用 IANA 时区数据库 https://www.iana.org/time-zones/ 的时区信息。

注意 3

在负时区转换时,当有重复时间时(例如夏令时结束或时区调整减少),两个不同的输入时间值 tUTC 会转换为相同的本地时间 tlocal

LocalTime(UTC(tlocal)) 不一定总是等于 tlocal。相应地,UTC(LocalTime(tUTC)) 不一定总是等于 tUTC

21.4.1.26 UTC ( t )

抽象操作 UTC 接受参数 t(一个 Number)并返回一个时间值。 它将 t 从本地时间转换为 UTC 时间值。 应该使用在 t 时刻生效的标准时间和夏令时的本地政治规则来按照本节规定的方式确定结果。 它在被调用时执行以下步骤:

  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 的最大整数 Number,使得 possibleInstantsBefore 不为空(即,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。

注意 1

时区感知实现(建议所有其他实现也如此)需要使用 IANA 时区数据库 https://www.iana.org/time-zones/ 的时区信息。

2017 年 11 月 5 日在 America/New_York 的凌晨 1:30 重复了两次(回退),但必须解释为 1:30 AM UTC-04 而不是 1:30 AM UTC-05。 在 UTC(TimeClip(MakeDate(MakeDay(2017, 10, 5), MakeTime(1, 30, 0, 0)))) 中,offsetMs 的值是 -4 × msPerHour

2017 年 3 月 12 日在 America/New_York 的凌晨 2:30 不存在,但必须解释为 2:30 AM UTC-05(相当于 3:30 AM UTC-04)。 在 UTC(TimeClip(MakeDate(MakeDay(2017, 2, 12), MakeTime(2, 30, 0, 0)))) 中,offsetMs 的值是 -5 × msPerHour

注意 2

UTC(LocalTime(tUTC)) 不一定总是等于 tUTC。相应地,LocalTime(UTC(tlocal)) 不一定总是等于 tlocal

21.4.1.27 MakeTime ( hour, min, sec, ms )

抽象操作 MakeTime 接受参数 hour(一个 Number)、min(一个 Number)、sec(一个 Number)和 ms(一个 Number)并返回一个 Number。它 计算毫秒数。它在被调用时执行以下步骤:

  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
注意

MakeTime 中的算术是浮点算术,它不满足结合律,所以操作必须按正确的顺序执行。

21.4.1.28 MakeDay ( year, month, date )

抽象操作 MakeDay 接受参数 year(一个 Number)、month (一个 Number)和 date(一个 Number)并返回一个 Number。它计算天数。它在被调用时执行以下步骤:

  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. 找到一个有限时间值 t,使得 YearFromTime(t) 是 ymMonthFromTime(t) 是 mn,并且 DateFromTime(t) 是 1𝔽;但如果这不可能(因为某些 参数超出范围),返回 NaN
  9. 返回 Day(t) + dt - 1𝔽

21.4.1.29 MakeDate ( day, time )

抽象操作 MakeDate 接受参数 day(一个 Number)和 time (一个 Number)并返回一个 Number。它计算毫秒数。它在被调用时执行以下步骤:

  1. 如果 day 不是有限的或 time 不是有限的,返回 NaN
  2. tvday × msPerDay + time
  3. 如果 tv 不是有限的,返回 NaN
  4. 返回 tv

21.4.1.30 MakeFullYear ( year )

抽象操作 MakeFullYear 接受参数 year(一个 Number)并返回一个整数 NumberNaN。它返回与 year整数部分关联的完整年份,将闭区间 0 到 99 中的任何值解释为自 1900 年开始以来的年数。为了与推算格里高利历保持一致,"完整年份"定义为自第 0 年(公元前 1 年)开始以来完整年份的有符号计数。它在被调用时执行以下步骤:

  1. 如果 yearNaN,返回 NaN
  2. truncated 为 ! ToIntegerOrInfinity(year)。
  3. 如果 truncated闭区间 0 到 99 中,返回 1900𝔽 + 𝔽(truncated)。
  4. 返回 𝔽(truncated)。

21.4.1.31 TimeClip ( time )

抽象操作 TimeClip 接受参数 time(一个 Number)并返回一个 Number。它计算毫秒数。它在被调用时执行以下步骤:

  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
    

包含超出边界或不符合要求元素的字符串不是此格式的有效实例。

注意 1

由于每一天都以午夜开始和结束,00:0024:00 这两种表示法可用于区分可能与一个日期关联的两个午夜。这意味着以下两种表示法指的是完全相同的时间点:1995-02-04T24:001995-02-05T00:00。将后一种形式解释为"日历日的结束"与 ISO 8601 一致,尽管该规范将其保留用于描述时间间隔,并且不允许在单个时间点的表示中使用。

注意 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,而不回退到实现特定的行为或启发式。

注意

带有扩展年份的日期时间值示例:

-271821-04-20T00:00:00Z 公元前 271822 年
-000001-01-01T00:00:00Z 公元前 2 年
+000000-01-01T00:00:00Z 公元前 1 年
+000001-01-01T00:00:00Z 公元 1 年
+001970-01-01T00:00:00Z 公元 1970 年
+002009-12-15T00:00:00Z 公元 2009 年
+275760-09-13T00:00:00Z 公元 275760 年

21.4.1.33 时区偏移字符串格式

ECMAScript 定义了一个来源于 ISO 8601 的 UTC 偏移字符串交换格式。 该格式由以下语法描述。

语法

UTCOffset ::: ASCIISign Hour ASCIISign Hour HourSubcomponents[+Extended] ASCIISign Hour HourSubcomponents[~Extended] ASCIISign ::: one of + - Hour ::: 0 DecimalDigit 1 DecimalDigit 20 21 22 23 HourSubcomponents[Extended] ::: TimeSeparator[?Extended] MinuteSecond TimeSeparator[?Extended] MinuteSecond TimeSeparator[?Extended] MinuteSecond TemporalDecimalFractionopt TimeSeparator[Extended] ::: [+Extended] : [~Extended] [empty] MinuteSecond ::: 0 DecimalDigit 1 DecimalDigit 2 DecimalDigit 3 DecimalDigit 4 DecimalDigit 5 DecimalDigit TemporalDecimalFraction ::: TemporalDecimalSeparator DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator ::: one of . ,

21.4.1.33.1 IsTimeZoneOffsetString ( offsetString )

抽象操作 IsTimeZoneOffsetString 接受参数 offsetString(一个 String)并返回一个 Boolean。返回值指示 offsetString 是否符合 UTCOffset 给出的语法。它在被调用时执行以下步骤:

  1. parseResultParseText(offsetString, UTCOffset)。
  2. 如果 parseResult 是一个错误的列表,返回 false
  3. 返回 true

21.4.1.33.2 ParseTimeZoneOffsetString ( offsetString )

抽象操作 ParseTimeZoneOffsetString 接受参数 offsetString (一个 String)并返回一个整数。返回值是对应于字符串 offsetString 的 UTC 偏移,以纳秒为单位。它在被调用时执行以下步骤:

  1. parseResultParseText(offsetString, UTCOffset)。
  2. 断言parseResult 不是一个错误的列表
  3. 断言parseResult 包含一个 ASCIISign 解析节点
  4. parsedSignparseResult 中包含的 ASCIISign 解析节点匹配的源文本
  5. 如果 parsedSign 是单个代码点 U+002D(连字符减号),那么
    1. sign 为 -1。
  6. 否则,
    1. sign 为 1。
  7. 注意:下面 StringToNumber 的应用不会丢失精度,因为每个解析值都保证是一个足够短的十进制数字字符串。
  8. 断言parseResult 包含一个 Hour 解析节点
  9. parsedHoursparseResult 中包含的 Hour 解析节点匹配的源文本
  10. hours(StringToNumber(CodePointsToString(parsedHours)))。
  11. 如果 parseResult 不包含 MinuteSecond 解析节点,那么
    1. minutes 为 0。
  12. 否则,
    1. parsedMinutesparseResult 中包含的第一个 MinuteSecond 解析节点匹配的源文本
    2. minutes(StringToNumber(CodePointsToString(parsedMinutes)))。
  13. 如果 parseResult 不包含两个 MinuteSecond 解析节点,那么
    1. seconds 为 0。
  14. 否则,
    1. parsedSecondsparseResult 中包含的第二个 MinuteSecond 解析节点匹配的源文本
    2. seconds(StringToNumber(CodePointsToString(parsedSeconds)))。
  15. 如果 parseResult 不包含 TemporalDecimalFraction 解析节点,那么
    1. nanoseconds 为 0。
  16. 否则,
    1. parsedFractionparseResult 中包含的 TemporalDecimalFraction 解析节点匹配的源文本
    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)的字符串。
  • 是一个其行为根据参数数量和类型而不同的函数。
  • 可作为类定义中 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 是一个对象value 具有 [[DateValue]] 内部槽,则
      1. tvvalue.[[DateValue]]
    3. 否则,
      1. v 为 ? ToPrimitive(value)。
      2. 如果 v 是字符串,则
        1. 断言:下一步永远不会返回 非正常完成,因为 v 是字符串
        2. tv 为以与 parse 方法 (21.4.3.2) 完全相同的方式解析 v 作为日期的结果。
      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. O 为 ? OrdinaryCreateFromConstructor(NewTarget, "%Date.prototype%", « [[DateValue]] »)。
  7. 设置 O.[[DateValue]]dv
  8. 返回 O

21.4.3 Date 构造函数的属性

Date 构造函数

  • 具有 [[Prototype]] 内部槽,其值为 %Function.prototype%
  • 具有值为 7𝔽"length" 属性。
  • 具有以下属性:

21.4.3.1 Date.now ( )

此函数返回表示调用时 UTC 日期和时间的 时间值

21.4.3.2 Date.parse ( string )

此函数对其参数应用 ToString 运算符。如果 ToString 产生 非正常完成,则会立即返回该 Completion Record。否则,此函数将结果字符串作为日期和时间进行解释;返回一个 Number,即与该日期和时间对应的 UTC 时间值。字符串可能会被解释为本地时间、UTC 时间或其他时区的时间,具体取决于字符串的内容。函数首先尝试按照日期时间字符串格式 (21.4.1.32),包括扩展年份,解析该字符串。如果字符串不符合该格式,函数可以退回到实现相关的启发式算法或实现相关的日期格式。无法识别或包含越界格式元素值的字符串会导致该函数返回 NaN

如果字符串符合 日期时间字符串格式,则缺失的格式元素将用替代值补齐。当 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())

不要求产生与前三个表达式相同的数值,并且通常当传入的字符串不符合日期时间字符串格式 (21.4.1.32),且无法由 toStringtoUTCString 方法在该实现中产生时,该函数的返回值是 实现定义 的。

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𝔽

注意

此函数与 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. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,则返回 NaN
  5. 返回 DateFromTime(LocalTime(t))。

21.4.4.3 Date.prototype.getDay ( )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,则返回 NaN
  5. 返回 WeekDay(LocalTime(t))。

21.4.4.4 Date.prototype.getFullYear ( )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,则返回 NaN
  5. 返回 YearFromTime(LocalTime(t))。

21.4.4.5 Date.prototype.getHours ( )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,则返回 NaN
  5. 返回 HourFromTime(LocalTime(t))。

21.4.4.6 Date.prototype.getMilliseconds ( )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,则返回 NaN
  5. 返回 msFromTime(LocalTime(t))。

21.4.4.7 Date.prototype.getMinutes ( )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,则返回 NaN
  5. 返回 MinFromTime(LocalTime(t))。

21.4.4.8 Date.prototype.getMonth ( )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,则返回 NaN
  5. 返回 MonthFromTime(LocalTime(t))。

21.4.4.9 Date.prototype.getSeconds ( )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,则返回 NaN
  5. 返回 SecFromTime(LocalTime(t))。

21.4.4.10 Date.prototype.getTime ( )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. 返回 dateObject.[[DateValue]]

21.4.4.11 Date.prototype.getTimezoneOffset ( )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,则返回 NaN
  5. 返回 (t - LocalTime(t)) / msPerMinute

21.4.4.12 Date.prototype.getUTCDate ( )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,则返回 NaN
  5. 返回 DateFromTime(t)。

21.4.4.13 Date.prototype.getUTCDay ( )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,则返回 NaN
  5. 返回 WeekDay(t)。

21.4.4.14 Date.prototype.getUTCFullYear ( )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,则返回 NaN
  5. 返回 YearFromTime(t)。

21.4.4.15 Date.prototype.getUTCHours ( )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,则返回 NaN
  5. 返回 HourFromTime(t)。

21.4.4.16 Date.prototype.getUTCMilliseconds ( )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,则返回 NaN
  5. 返回 msFromTime(t)。

21.4.4.17 Date.prototype.getUTCMinutes ( )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,则返回 NaN
  5. 返回 MinFromTime(t)。

21.4.4.18 Date.prototype.getUTCMonth ( )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,则返回 NaN
  5. 返回 MonthFromTime(t)。

21.4.4.19 Date.prototype.getUTCSeconds ( )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,则返回 NaN
  5. 返回 SecFromTime(t)。

21.4.4.20 Date.prototype.setDate ( date )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. dt 为 ? ToNumber(date)。
  5. 如果 tNaN,则返回 NaN
  6. 设置 tLocalTime(t)。
  7. newDateMakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), dt), TimeWithinDay(t))。
  8. uTimeClip(UTC(newDate))。
  9. 设置 dateObject.[[DateValue]]u
  10. 返回 u

21.4.4.21 Date.prototype.setFullYear ( year [ , month [ , date ] ] )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. y 为 ? ToNumber(year)。
  5. 如果 tNaN,则设置 t+0𝔽;否则,设置 tLocalTime(t)。
  6. 如果 month 未给出,令 mMonthFromTime(t);否则,令 m 为 ? ToNumber(month)。
  7. 如果 date 未给出,令 dtDateFromTime(t);否则,令 dt 为 ? ToNumber(date)。
  8. newDateMakeDate(MakeDay(y, m, dt), TimeWithinDay(t))。
  9. uTimeClip(UTC(newDate))。
  10. 设置 dateObject.[[DateValue]]u
  11. 返回 u

该方法的 "length" 属性值为 3𝔽

注意

如果未给出 month,本方法表现为 month 的值为 getMonth()。如果未给出 date,则表现为 date 的值为 getDate()

21.4.4.22 Date.prototype.setHours ( hour [ , min [ , sec [ , ms ] ] ] )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. h 为 ? ToNumber(hour)。
  5. 如果 min 给出,令 m 为 ? ToNumber(min)。
  6. 如果 sec 给出,令 s 为 ? ToNumber(sec)。
  7. 如果 ms 给出,令 milli 为 ? ToNumber(ms)。
  8. 如果 tNaN,则返回 NaN
  9. 设置 tLocalTime(t)。
  10. 如果 min 未给出,令 mMinFromTime(t)。
  11. 如果 sec 未给出,令 sSecFromTime(t)。
  12. 如果 ms 未给出,令 millimsFromTime(t)。
  13. dateMakeDate(Day(t), MakeTime(h, m, s, milli))。
  14. uTimeClip(UTC(date))。
  15. 设置 dateObject.[[DateValue]]u
  16. 返回 u

该方法的 "length" 属性值为 4𝔽

注意

如果未给出 min,本方法表现为 min 的值为 getMinutes()。如果未给出 sec,则表现为 sec 的值为 getSeconds()。如果未给出 ms,则表现为 ms 的值为 getMilliseconds()

21.4.4.23 Date.prototype.setMilliseconds ( ms )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. ms 设为 ? ToNumber(ms)。
  5. 如果 tNaN,返回 NaN
  6. t 设为 LocalTime(t)。
  7. timeMakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms)。
  8. uTimeClip(UTC(MakeDate(Day(t), time)))。
  9. 设置 dateObject.[[DateValue]]u
  10. 返回 u

21.4.4.24 Date.prototype.setMinutes ( min [ , sec [ , ms ] ] )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. m 为 ? ToNumber(min)。
  5. 如果 sec 给出,令 s 为 ? ToNumber(sec)。
  6. 如果 ms 给出,令 milli 为 ? ToNumber(ms)。
  7. 如果 tNaN,返回 NaN
  8. 设置 tLocalTime(t)。
  9. 如果 sec 未给出,令 sSecFromTime(t)。
  10. 如果 ms 未给出,令 millimsFromTime(t)。
  11. dateMakeDate(Day(t), MakeTime(HourFromTime(t), m, s, milli))。
  12. uTimeClip(UTC(date))。
  13. 设置 dateObject.[[DateValue]]u
  14. 返回 u

该方法的 "length" 属性值为 3𝔽

注意

如果未给出 sec,本方法表现为 sec 的值为 getSeconds()。如果未给出 ms,则表现为 ms 的值为 getMilliseconds()

21.4.4.25 Date.prototype.setMonth ( month [ , date ] )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. m 为 ? ToNumber(month)。
  5. 如果 date 给出,令 dt 为 ? ToNumber(date)。
  6. 如果 tNaN,返回 NaN
  7. 设置 tLocalTime(t)。
  8. 如果 date 未给出,令 dtDateFromTime(t)。
  9. newDateMakeDate(MakeDay(YearFromTime(t), m, dt), TimeWithinDay(t))。
  10. uTimeClip(UTC(newDate))。
  11. 设置 dateObject.[[DateValue]]u
  12. 返回 u

该方法的 "length" 属性值为 2𝔽

注意

如果未给出 date,本方法表现为 date 的值为 getDate()

21.4.4.26 Date.prototype.setSeconds ( sec [ , ms ] )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. s 为 ? ToNumber(sec)。
  5. 如果 ms 给出,令 milli 为 ? ToNumber(ms)。
  6. 如果 tNaN,返回 NaN
  7. 设置 tLocalTime(t)。
  8. 如果 ms 未给出,令 millimsFromTime(t)。
  9. dateMakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), s, milli))。
  10. uTimeClip(UTC(date))。
  11. 设置 dateObject.[[DateValue]]u
  12. 返回 u

该方法的 "length" 属性值为 2𝔽

注意

如果未给出 ms,本方法表现为 ms 的值为 getMilliseconds()

21.4.4.27 Date.prototype.setTime ( time )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. t 为 ? ToNumber(time)。
  4. vTimeClip(t)。
  5. 设置 dateObject.[[DateValue]]v
  6. 返回 v

21.4.4.28 Date.prototype.setUTCDate ( date )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. dt 为 ? ToNumber(date)。
  5. 如果 tNaN,返回 NaN
  6. newDateMakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), dt), TimeWithinDay(t))。
  7. vTimeClip(newDate)。
  8. 设置 dateObject.[[DateValue]]v
  9. 返回 v

21.4.4.29 Date.prototype.setUTCFullYear ( year [ , month [ , date ] ] )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,则设置 t+0𝔽
  5. y 为 ? ToNumber(year)。
  6. 如果 month 未给出,令 mMonthFromTime(t); 否则,令 m 为 ? ToNumber(month)。
  7. 如果 date 未给出,令 dtDateFromTime(t); 否则,令 dt 为 ? ToNumber(date)。
  8. newDateMakeDate(MakeDay(y, m, dt), TimeWithinDay(t))。
  9. vTimeClip(newDate)。
  10. 设置 dateObject.[[DateValue]]v
  11. 返回 v

该方法的 "length" 属性值为 3𝔽

注意

如果未给出 month,本方法表现为 month 的值为 getUTCMonth()。如果未给出 date,则表现为 date 的值为 getUTCDate()

21.4.4.30 Date.prototype.setUTCHours ( hour [ , min [ , sec [ , ms ] ] ] )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. h 为 ? ToNumber(hour)。
  5. 如果 min 给出,令 m 为 ? ToNumber(min)。
  6. 如果 sec 给出,令 s 为 ? ToNumber(sec)。
  7. 如果 ms 给出,令 milli 为 ? ToNumber(ms)。
  8. 如果 tNaN,返回 NaN
  9. 如果 min 未给出,令 mMinFromTime(t)。
  10. 如果 sec 未给出,令 sSecFromTime(t)。
  11. 如果 ms 未给出,令 millimsFromTime(t)。
  12. dateMakeDate(Day(t), MakeTime(h, m, s, milli))。
  13. vTimeClip(date)。
  14. 设置 dateObject.[[DateValue]]v
  15. 返回 v

该方法的 "length" 属性值为 4𝔽

注意

如果未给出 min,本方法表现为 min 的值为 getUTCMinutes()。如果未给出 sec,则表现为 sec 的值为 getUTCSeconds()。如果未给出 ms,则表现为 ms 的值为 getUTCMilliseconds()

21.4.4.31 Date.prototype.setUTCMilliseconds ( ms )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. ms 设为 ? ToNumber(ms)。
  5. 如果 tNaN,返回 NaN
  6. timeMakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms)。
  7. vTimeClip(MakeDate(Day(t), time))。
  8. 设置 dateObject.[[DateValue]]v
  9. 返回 v

21.4.4.32 Date.prototype.setUTCMinutes ( min [ , sec [ , ms ] ] )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. m 为 ? ToNumber(min)。
  5. 如果 sec 给出,令 s 为 ? ToNumber(sec)。
  6. 如果 ms 给出,令 milli 为 ? ToNumber(ms)。
  7. 如果 tNaN,返回 NaN
  8. 如果 sec 未给出,令 sSecFromTime(t)。
  9. 如果 ms 未给出,令 millimsFromTime(t)。
  10. dateMakeDate(Day(t), MakeTime(HourFromTime(t), m, s, milli))。
  11. vTimeClip(date)。
  12. 设置 dateObject.[[DateValue]]v
  13. 返回 v

该方法的 "length" 属性值为 3𝔽

注意

如果未给出 sec,本方法表现为 sec 的值为 getUTCSeconds()。如果未给出 ms,则表现为 ms 的值为 getUTCMilliseconds()

21.4.4.33 Date.prototype.setUTCMonth ( month [ , date ] )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. m 为 ? ToNumber(month)。
  5. 如果 date 给出,令 dt 为 ? ToNumber(date)。
  6. 如果 tNaN,返回 NaN
  7. 如果 date 未给出,令 dtDateFromTime(t)。
  8. newDateMakeDate(MakeDay(YearFromTime(t), m, dt), TimeWithinDay(t))。
  9. vTimeClip(newDate)。
  10. 设置 dateObject.[[DateValue]]v
  11. 返回 v

该方法的 "length" 属性值为 2𝔽

注意

如果未给出 date,本方法表现为 date 的值为 getUTCDate()

21.4.4.34 Date.prototype.setUTCSeconds ( sec [ , ms ] )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. s 为 ? ToNumber(sec)。
  5. 如果 ms 给出,令 milli 为 ? ToNumber(ms)。
  6. 如果 tNaN,返回 NaN
  7. 如果 ms 未给出,令 millimsFromTime(t)。
  8. dateMakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), s, milli))。
  9. vTimeClip(date)。
  10. 设置 dateObject.[[DateValue]]v
  11. 返回 v

该方法的 "length" 属性值为 2𝔽

注意

如果未给出 ms,本方法表现为 ms 的值为 getUTCMilliseconds()

21.4.4.35 Date.prototype.toDateString ( )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tvdateObject.[[DateValue]]
  4. 如果 tvNaN,返回 "Invalid Date"
  5. tLocalTime(tv)。
  6. 返回 DateString(t)。

21.4.4.36 Date.prototype.toISOString ( )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tvdateObject.[[DateValue]]
  4. 如果 tvNaN,抛出 RangeError 异常。
  5. 断言tv 是一个 整数 Number
  6. 如果 tv 所对应的年份不能用 日期时间字符串格式 表示,则抛出 RangeError 异常。
  7. 返回 tv 在 UTC 时标下、日期时间字符串格式 的字符串表示,包括所有格式元素及 UTC 偏移 "Z"。

21.4.4.37 Date.prototype.toJSON ( key )

此方法为 JSON.stringify (25.5.2) 提供 Date 的字符串表示。

调用该方法时,执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. tv 为 ? ToPrimitive(O, number)。
  3. 如果 tv 是 Numbertv 不是 有限值,则返回 null
  4. 返回 ? Invoke(O, "toISOString")。
注意 1

参数会被忽略。

注意 2

此方法有意设计为泛型;它不要求其 this 值为 Date。因此,可以转移到其他类型的对象上作为方法使用。但该对象必须有 toISOString 方法。

21.4.4.38 Date.prototype.toLocaleDateString ( [ reserved1 [ , reserved2 ] ] )

包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按照 ECMA-402 规范实现此方法。如果 ECMAScript 实现未包含 ECMA-402 API,则使用以下规范:

该方法返回一个字符串值。字符串内容是实现定义的,但旨在以方便且易于理解的形式,表示当前时区下 Date 的“日期”部分,符合宿主环境当前区域设置的习惯。

本方法的可选参数含义在 ECMA-402 规范中定义;未包含 ECMA-402 支持的实现不得将这些参数位置用于其他用途。

21.4.4.39 Date.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] )

包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按照 ECMA-402 规范实现此方法。如果 ECMAScript 实现未包含 ECMA-402 API,则使用以下规范:

该方法返回一个字符串值。字符串内容是实现定义的,但旨在以方便且易于理解的形式,表示当前时区下的 Date,符合宿主环境当前区域设置的习惯。

本方法的可选参数含义在 ECMA-402 规范中定义;未包含 ECMA-402 支持的实现不得将这些参数位置用于其他用途。

21.4.4.40 Date.prototype.toLocaleTimeString ( [ reserved1 [ , reserved2 ] ] )

包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按照 ECMA-402 规范实现此方法。如果 ECMAScript 实现未包含 ECMA-402 API,则使用以下规范:

该方法返回一个字符串值。字符串内容是实现定义的,但旨在以方便且易于理解的形式,表示当前时区下 Date 的“时间”部分,符合宿主环境当前区域设置的习惯。

本方法的可选参数含义在 ECMA-402 规范中定义;未包含 ECMA-402 支持的实现不得将这些参数位置用于其他用途。

21.4.4.41 Date.prototype.toString ( )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tvdateObject.[[DateValue]]
  4. 返回 ToDateString(tv)。
注意 1

对于任何 Date d,如果 d.[[DateValue]] 能被 1000 整除,则 Date.parse(d.toString()) 的结果等于 d.valueOf()。参见21.4.3.2

注意 2

此方法不是泛型;如果其 this 值不是 Date,则会抛出 TypeError 异常。因此,不能转移到其他类型的对象用作方法。

21.4.4.41.1 TimeString ( tv )

抽象操作 TimeString 接受参数 tv(Number,但不是 NaN),返回一个字符串。调用时执行以下步骤:

  1. hourToZeroPaddedDecimalString((HourFromTime(tv)), 2)。
  2. minuteToZeroPaddedDecimalString((MinFromTime(tv)), 2)。
  3. secondToZeroPaddedDecimalString((SecFromTime(tv)), 2)。
  4. 返回 字符串拼接 hour":"minute":"second、0x0020(空格)、"GMT"

21.4.4.41.2 DateString ( tv )

抽象操作 DateString 接受参数 tv(Number,但不是 NaN),返回一个字符串。调用时执行以下步骤:

  1. weekday表 65 中编号为 WeekDay(tv) 的 Name。
  2. month表 66 中编号为 MonthFromTime(tv) 的 Name。
  3. dayToZeroPaddedDecimalString((DateFromTime(tv)), 2)。
  4. yvYearFromTime(tv)。
  5. 如果 yv+0𝔽yv > +0𝔽,则 yearSign 为空字符串;否则 yearSign"-"
  6. paddedYearToZeroPaddedDecimalString(abs((yv)), 4)。
  7. 返回 字符串拼接 weekday、0x0020(空格)、month、0x0020、day、0x0020、yearSignpaddedYear
表 65:一周中各天的名称
编号 名称
+0𝔽 "Sun"
1𝔽 "Mon"
2𝔽 "Tue"
3𝔽 "Wed"
4𝔽 "Thu"
5𝔽 "Fri"
6𝔽 "Sat"
表 66:一年中各月的名称
编号 名称
+0𝔽 "Jan"
1𝔽 "Feb"
2𝔽 "Mar"
3𝔽 "Apr"
4𝔽 "May"
5𝔽 "Jun"
6𝔽 "Jul"
7𝔽 "Aug"
8𝔽 "Sep"
9𝔽 "Oct"
10𝔽 "Nov"
11𝔽 "Dec"

21.4.4.41.3 TimeZoneString ( tv )

抽象操作 TimeZoneString 接受参数 tv整数 Number),返回一个字符串。调用时执行以下步骤:

  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 为一个实现定义的字符串,其值可以为空字符串,也可以是 0x0020(空格)、0x0028(左括号)、实现定义的时区名称和 0x0029(右括号)的字符串拼接。
  10. 返回 字符串拼接 offsetSignoffsetHouroffsetMintzName

21.4.4.41.4 ToDateString ( tv )

抽象操作 ToDateString 接受参数 tv整数 NumberNaN),返回一个字符串。调用时执行以下步骤:

  1. 如果 tvNaN,返回 "Invalid Date"
  2. tLocalTime(tv)。
  3. 返回 字符串拼接 DateString(t)、0x0020(空格)、TimeString(t) 和 TimeZoneString(tv)。

21.4.4.42 Date.prototype.toTimeString ( )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tvdateObject.[[DateValue]]
  4. 如果 tvNaN,返回 "Invalid Date"
  5. tLocalTime(tv)。
  6. 返回 字符串拼接 TimeString(t) 和 TimeZoneString(tv)。

21.4.4.43 Date.prototype.toUTCString ( )

该方法返回一个字符串值,表示与 this 值对应的时间点。字符串格式基于 RFC 7231 的 "HTTP-date",并推广以支持 ECMAScript Dates 支持的完整时间范围。

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tvdateObject.[[DateValue]]
  4. 如果 tvNaN,返回 "Invalid Date"
  5. weekday表 65 中编号为 WeekDay(tv) 的 Name。
  6. month表 66 中编号为 MonthFromTime(tv) 的 Name。
  7. dayToZeroPaddedDecimalString((DateFromTime(tv)), 2)。
  8. yvYearFromTime(tv)。
  9. 如果 yv+0𝔽yv > +0𝔽,则 yearSign 为空字符串;否则 yearSign"-"
  10. paddedYearToZeroPaddedDecimalString(abs((yv)), 4)。
  11. 返回 字符串拼接 weekday","、0x0020(空格)、day、0x0020、month、0x0020、yearSignpaddedYear、0x0020 和 TimeString(tv)。

21.4.4.44 Date.prototype.valueOf ( )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. 返回 dateObject.[[DateValue]]

21.4.4.45 Date.prototype [ %Symbol.toPrimitive% ] ( hint )

此方法被 ECMAScript 语言运算符调用,用于将 Date 转换为原始值。hint 的允许值为 "default""number""string"。Date 是内置 ECMAScript 对象中唯一将 "default" 视为等价于 "string" 的对象。所有其他内置 ECMAScript 对象都将 "default" 视为等价于 "number"

调用该方法时,执行以下步骤:

  1. Othis 值。
  2. 如果 O 不是对象,则抛出 TypeError 异常。
  3. 如果 hint"string""default",则
    1. tryFirststring
  4. 否则如果 hint"number",则
    1. tryFirstnumber
  5. 否则,
    1. 抛出 TypeError 异常。
  6. 返回 ? OrdinaryToPrimitive(O, tryFirst)。

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

本方法的 "name" 属性值为 "[Symbol.toPrimitive]"

21.4.5 Date 实例的属性

Date 实例是普通对象,继承自Date 原型对象的属性。Date 实例还拥有一个 [[DateValue]] 内部槽。[[DateValue]] 内部槽即该 Date 实例所表示的时间值

22 文本处理

22.1 字符串对象

22.1.1 String 构造函数

String 构造函数

  • %String%
  • "String" 属性在 全局对象 上的初始值。
  • 作为 构造函数 调用时,创建并初始化一个新的 String 对象。
  • 作为函数调用而非 构造函数 时,执行类型转换。
  • 可作为类定义中 extends 子句的值使用。打算继承指定 String 行为的子类 构造函数 必须包含对 String 构造函数super 调用,以用 [[StringData]] 内部槽创建并初始化子类实例。

22.1.1.1 String ( value )

当调用该函数时,执行以下步骤:

  1. 如果 value 未给出,则
    1. s 为空字符串。
  2. 否则,
    1. 如果 NewTarget 为 undefinedvalue 是 Symbol,则返回 SymbolDescriptiveString(value)。
    2. s 为 ? ToString(value)。
  3. 如果 NewTarget 为 undefined,返回 s
  4. 返回 StringCreate(s, ? GetPrototypeFromConstructor(NewTarget, "%String.prototype%"))。

22.1.2 String 构造函数的属性

String 构造函数

22.1.2.1 String.fromCharCode ( ...codeUnits )

该函数可以接收任意数量的参数,这些参数形成余参数 codeUnits

调用该函数时,执行以下步骤:

  1. result 为空字符串。
  2. 对于 codeUnits 中的每个元素 next,执行
    1. nextCU 为数值为 (? ToUint16(next)) 的码元。
    2. result 设为 字符串拼接 resultnextCU 的结果。
  3. 返回 result

该函数的 "length" 属性值为 1𝔽

22.1.2.2 String.fromCodePoint ( ...codePoints )

该函数可以接收任意数量的参数,这些参数形成余参数 codePoints

调用该函数时,执行以下步骤:

  1. result 为空字符串。
  2. 对于 codePoints 中的每个元素 next,执行
    1. nextCP 为 ? ToNumber(next)。
    2. 如果 nextCP 不是 整数 Number,抛出 RangeError 异常。
    3. 如果 (nextCP) < 0 或 (nextCP) > 0x10FFFF,抛出 RangeError 异常。
    4. result 设为 字符串拼接 resultUTF16EncodeCodePoint((nextCP)) 的结果。
  3. 断言:如果 codePoints 为空,则 result 为空字符串。
  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,返回空字符串。
  6. R 为空字符串。
  7. nextIndex 为 0。
  8. 重复,
    1. nextLiteralVal 为 ? Get(literals, ! ToString(𝔽(nextIndex)))。
    2. nextLiteral 为 ? ToString(nextLiteralVal)。
    3. R 设为 字符串拼接 RnextLiteral 的结果。
    4. 如果 nextIndex + 1 = literalCount,返回 R
    5. 如果 nextIndex < substitutionCount,则
      1. nextSubValsubstitutions[nextIndex]。
      2. nextSub 为 ? ToString(nextSubVal)。
      3. R 设为 字符串拼接 RnextSub 的结果。
    6. nextIndex 设为 nextIndex + 1。
注意

该函数用于作为标记模板(Tagged Template)(13.3.11)的标记函数使用。当以此方式调用时,第一个参数将是格式良好的模板对象,其余参数是替换值。

22.1.3 String 原型对象的属性

String 原型对象

  • %String.prototype%
  • 是 String 特殊对象,并拥有为此类对象规定的内部方法。
  • 有一个 [[StringData]] 内部槽,其值为空字符串。
  • 有一个 "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. O 为 ? RequireObjectCoercible(this 值)。
  2. S 为 ? ToString(O)。
  3. lenS 的长度。
  4. relativeIndex 为 ? ToIntegerOrInfinity(index)。
  5. 如果 relativeIndex ≥ 0,则
    1. krelativeIndex
  6. 否则,
    1. klen + relativeIndex
  7. 如果 k < 0 或 klen,返回 undefined
  8. 返回 substring Skk + 1。

22.1.3.2 String.prototype.charAt ( pos )

注 1

此方法返回包含在将此对象转换为 String 后的字符串中索引为 pos 的码元的单元素字符串。如果该索引处没有元素,则返回空字符串。结果是 String值,而不是 String 对象。

如果 pos整数 Number,则 x.charAt(pos) 的结果等价于 x.substring(pos, pos + 1)

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. S 为 ? ToString(O)。
  3. position 为 ? ToIntegerOrInfinity(pos)。
  4. sizeS 的长度。
  5. 如果 position < 0 或 positionsize,返回空字符串。
  6. 返回 substring Spositionposition + 1。
注 2

此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。

22.1.3.3 String.prototype.charCodeAt ( pos )

注 1

此方法返回一个 Number(一个非负的整数 Number,小于 216),表示将此对象转换为 String 后字符串中索引为 pos 处的码元的数值。如果该索引处没有元素,则结果为 NaN

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. S 为 ? ToString(O)。
  3. position 为 ? ToIntegerOrInfinity(pos)。
  4. sizeS 的长度。
  5. 如果 position < 0 或 positionsize,返回 NaN
  6. 返回 Number value for 字符串 S 中索引为 position 的码元的数值。
注 2

此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。

22.1.3.4 String.prototype.codePointAt ( pos )

注 1

此方法返回一个非负的整数 Number,小于等于 0x10FFFF𝔽,表示在将该对象转换为 String 后字符串中索引为 pos 处开始的 UTF-16 编码码点(6.1.4)的数值。如果该索引处没有元素,则结果为 undefined。如果 pos 处不是有效的 UTF-16 代理对 的开始,则结果为 pos 处的码元。

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. S 为 ? ToString(O)。
  3. position 为 ? ToIntegerOrInfinity(pos)。
  4. sizeS 的长度。
  5. 如果 position < 0 或 positionsize,返回 undefined
  6. cpCodePointAt(S, position)。
  7. 返回 𝔽(cp.[[CodePoint]])。
注 2

此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。

22.1.3.5 String.prototype.concat ( ...args )

注 1

调用此方法时,返回由 this 值(转换为 String)码元后跟每个参数转换为 String 后的码元组成的 String 值。结果是 String值,而不是 String 对象。

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. S 为 ? ToString(O)。
  3. RS
  4. 对于 args 中的每个元素 next,执行
    1. nextString 为 ? ToString(next)。
    2. R 设为 字符串拼接 RnextString 的结果。
  5. 返回 R

该方法的 "length" 属性值为 1𝔽

注 2

此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。

22.1.3.6 String.prototype.constructor

String.prototype.constructor 的初始值为 %String%

22.1.3.7 String.prototype.endsWith ( searchString [ , endPosition ] )

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. S 为 ? ToString(O)。
  3. isRegExp 为 ? IsRegExp(searchString)。
  4. 如果 isRegExptrue,抛出 TypeError 异常。
  5. searchStr 为 ? ToString(searchString)。
  6. lenS 的长度。
  7. 如果 endPositionundefined,令 poslen;否则令 pos 为 ? ToIntegerOrInfinity(endPosition)。
  8. endclamping pos 介于 0 和 len 之间的结果。
  9. searchLengthsearchStr 的长度。
  10. 如果 searchLength = 0,返回 true
  11. startend - searchLength
  12. 如果 start < 0,返回 false
  13. substringsubstring Sstartend
  14. 如果 substring 等于 searchStr,返回 true
  15. 返回 false
注 1

如果 searchString(转换为 String)码元序列与本对象(转换为 String)中从 endPosition - length(this) 开始的对应码元相同,则该方法返回 true,否则返回 false

注 2

如果第一个参数是 RegExp 抛出异常,是为了允许后续标准版本定义支持此类参数值的扩展。

注 3

此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。

22.1.3.8 String.prototype.includes ( searchString [ , position ] )

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. S 为 ? ToString(O)。
  3. isRegExp 为 ? IsRegExp(searchString)。
  4. 如果 isRegExptrue,抛出 TypeError 异常。
  5. searchStr 为 ? ToString(searchString)。
  6. pos 为 ? ToIntegerOrInfinity(position)。
  7. 断言:如果 positionundefined,则 pos 为 0。
  8. lenS 的长度。
  9. startclamping pos 介于 0 和 len 之间的结果。
  10. indexStringIndexOf(S, searchStr, start)。
  11. 如果 indexnot-found,返回 false
  12. 返回 true
注 1

如果 searchString 作为子串出现在将此对象转换为 String 后的结果中,且索引大于等于 position,则该函数返回 true;否则返回 false。如果 positionundefined,则默认值为 0,因此会搜索整个字符串。

注 2

如果第一个参数是 RegExp 抛出异常,是为了允许后续标准版本定义支持此类参数值的扩展。

注 3

此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。

22.1.3.9 String.prototype.indexOf ( searchString [ , position ] )

注 1

如果 searchString 作为子串出现在将此对象转换为 String 后的结果中,且索引大于等于 position,则返回最小的此类索引,否则返回 -1𝔽。如果 positionundefined,则假定为 +0𝔽,即搜索整个字符串。

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. S 为 ? ToString(O)。
  3. searchStr 为 ? ToString(searchString)。
  4. pos 为 ? ToIntegerOrInfinity(position)。
  5. 断言:如果 positionundefined,则 pos 为 0。
  6. lenS 的长度。
  7. startclamping pos 介于 0 和 len 之间的结果。
  8. resultStringIndexOf(S, searchStr, start)。
  9. 如果 resultnot-found,返回 -1𝔽
  10. 返回 𝔽(result)。
注 2

此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。

22.1.3.10 String.prototype.isWellFormed ( )

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. S 为 ? ToString(O)。
  3. 返回 IsStringWellFormedUnicode(S)。

22.1.3.11 String.prototype.lastIndexOf ( searchString [ , position ] )

注 1

如果 searchString 作为子串出现在将此对象转换为 String 后的结果中,且索引小于等于 position,则返回最大的此类索引,否则返回 -1𝔽。如果 positionundefined,则假定为字符串长度,即搜索整个字符串。

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. S 为 ? ToString(O)。
  3. searchStr 为 ? ToString(searchString)。
  4. numPos 为 ? ToNumber(position)。
  5. 断言:如果 positionundefined,则 numPosNaN
  6. 如果 numPosNaN,令 pos 为 +∞;否则,令 pos 为 ! ToIntegerOrInfinity(numPos)。
  7. lenS 的长度。
  8. searchLensearchStr 的长度。
  9. startclamping pos 介于 0 和 len - searchLen 之间的结果。
  10. resultStringLastIndexOf(S, searchStr, start)。
  11. 如果 resultnot-found,返回 -1𝔽
  12. 返回 𝔽(result)。
注 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 值(转换为字符串 S)与 that(转换为字符串 thatValue)进行实现定义的本地敏感字符串比较的结果。该结果旨在与 宿主环境当前区域设置的排序顺序相对应,当 S 排在 thatValue 之前时为负,排在之后时为正,否则为零(表示 SthatValue 之间无相对顺序)。

在执行比较前,该方法会按如下步骤准备字符串:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. S 为 ? ToString(O)。
  3. thatValue 为 ? ToString(that)。

本方法的第二和第三个可选参数的含义在 ECMA-402 规范中定义;未包含 ECMA-402 支持的实现不得将这些参数位置用于其他用途。

实际返回值为实现定义,以允许编码额外信息,但作为两个参数的方法时,要求作为一致的比较器,对所有字符串集合定义全序关系。该方法还要求根据 Unicode 标准识别和遵循规范等价,包括在比较可区分但规范等价的字符串时返回 +0𝔽

注 1

此方法本身不适合作为 Array.prototype.sort 的参数,因为后者需要两个参数的函数。

注 2

此方法可依赖 ECMAScript 环境从宿主环境获得的任意语言/区域敏感比较功能,并旨在按照宿主环境当前区域设置的习惯进行比较。但无论比较能力如何,本方法都必须根据 Unicode 标准识别和遵循规范等价——例如,以下比较都必须返回 +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 标准第 2 章和第 3 章,以及 Unicode Standard Annex #15, Unicode Normalization FormsUnicode Technical Note #5, Canonical Equivalence in Applications。另见 Unicode Technical Standard #10, Unicode Collation Algorithm

建议本方法不应遵循 Unicode 兼容等价或 Unicode 标准第 3 章第 3.7 节定义的兼容分解。

注 3

此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。

22.1.3.13 String.prototype.match ( regexp )

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. 如果 regexp 既不是 undefined 也不是 null,则
    1. matcher 为 ? GetMethod(regexp, %Symbol.match%)。
    2. 如果 matcher 不为 undefined,则
      1. 返回 ? Call(matcher, regexp, « O »)。
  3. S 为 ? ToString(O)。
  4. rx 为 ? RegExpCreate(regexp, undefined)。
  5. 返回 ? Invoke(rx, %Symbol.match%, « S »)。

此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。

22.1.3.14 String.prototype.matchAll ( regexp )

该方法对将 this 值表示的字符串与 regexp 进行正则表达式匹配,并返回一个迭代器,该迭代器会产生匹配结果。每个匹配结果是一个数组,其第一个元素为匹配到的字符串片段,后跟任何捕获组匹配到的片段。如果正则表达式从未匹配,返回的迭代器不会产生任何匹配结果。

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. 如果 regexp 既不是 undefined 也不是 null,则
    1. isRegExp 为 ? IsRegExp(regexp)。
    2. 如果 isRegExptrue,则
      1. flags 为 ? Get(regexp, "flags")。
      2. 执行 ? RequireObjectCoercible(flags)。
      3. 如果 ? ToString(flags) 不包含 "g",抛出 TypeError 异常。
    3. matcher 为 ? GetMethod(regexp, %Symbol.matchAll%)。
    4. 如果 matcher 不为 undefined,则
      1. 返回 ? Call(matcher, regexp, « O »)。
  3. S 为 ? ToString(O)。
  4. rx 为 ? RegExpCreate(regexp, "g")。
  5. 返回 ? Invoke(rx, %Symbol.matchAll%, « S »)。
注 1
此方法有意设计为泛型,不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。
注 2
String.prototype.split 类似,String.prototype.matchAll 通常不应改变其输入。

22.1.3.15 String.prototype.normalize ( [ form ] )

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. S 为 ? ToString(O)。
  3. 如果 formundefined,令 f"NFC"
  4. 否则,令 f 为 ? ToString(form)。
  5. 如果 f 不是 "NFC""NFD""NFKC""NFKD" 之一,则抛出 RangeError 异常。
  6. ns 为将 S最新 Unicode 标准,Normalization Forms 中由 f 命名的规范形式规范化后的字符串值。
  7. 返回 ns

此方法有意设计为泛型,不要求其 this 值为 String 对象。因此可以转移到其他类型的对象上作为方法使用。

22.1.3.16 String.prototype.padEnd ( maxLength [ , fillString ] )

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. 返回 ? StringPaddingBuiltinsImpl(O, maxLength, fillString, end)。

22.1.3.17 String.prototype.padStart ( maxLength [ , fillString ] )

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. 返回 ? StringPaddingBuiltinsImpl(O, maxLength, fillString, start)。

22.1.3.17.1 StringPaddingBuiltinsImpl ( O, maxLength, fillString, placement )

抽象操作 StringPaddingBuiltinsImpl 接收参数 OECMAScript 语言值)、maxLengthECMAScript 语言值)、fillStringECMAScript 语言值)和 placementstartend),返回字符串或抛出异常。调用时执行以下步骤:

  1. S 为 ? ToString(O)。
  2. intMaxLength(? ToLength(maxLength))。
  3. stringLengthS 的长度。
  4. 如果 intMaxLengthstringLength,返回 S
  5. 如果 fillStringundefined,设置 fillString 为仅包含码元 0x0020(空格)的字符串。
  6. 否则,设置 fillString 为 ? ToString(fillString)。
  7. 返回 StringPad(S, intMaxLength, fillString, placement)。

22.1.3.17.2 StringPad ( S, maxLength, fillString, placement )

抽象操作 StringPad 接收参数 S(字符串)、maxLength(非负整数)、fillString(字符串)和 placementstartend),返回字符串。调用时执行以下步骤:

  1. stringLengthS 的长度。
  2. 如果 maxLengthstringLength,返回 S
  3. 如果 fillString 为空字符串,返回 S
  4. fillLenmaxLength - stringLength
  5. truncatedStringFiller 为重复拼接 fillString 并截断为 fillLen 长度的字符串。
  6. 如果 placementstart,返回 字符串拼接 truncatedStringFillerS 的结果。
  7. 否则,返回 字符串拼接 StruncatedStringFiller 的结果。
注 1

maxLength 参数会被限制,不能小于 S 的长度。

注 2

fillString 参数的默认值为 " "(仅包含码元 0x0020 空格的字符串)。

22.1.3.17.3 ToZeroPaddedDecimalString ( n, minLength )

抽象操作 ToZeroPaddedDecimalString 接收参数 n(非负整数)和 minLength(非负整数),返回字符串。调用时执行以下步骤:

  1. Sn 的字符串表示,格式为十进制数。
  2. 返回 StringPad(S, minLength, "0", start)。

22.1.3.18 String.prototype.repeat ( count )

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. S 为 ? ToString(O)。
  3. n 为 ? ToIntegerOrInfinity(count)。
  4. 如果 n < 0 或 n = +∞,抛出 RangeError 异常。
  5. 如果 n = 0,返回空字符串。
  6. 返回由 S 拼接 n 次组成的字符串值。
注 1

此方法会创建由 this 值(转换为字符串)的码元重复 count 次组成的字符串值。

注 2

此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。

22.1.3.19 String.prototype.replace ( searchValue, replaceValue )

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. 如果 searchValue 既不是 undefined 也不是 null,则
    1. replacer 为 ? GetMethod(searchValue, %Symbol.replace%)。
    2. 如果 replacer 不为 undefined,则
      1. 返回 ? Call(replacer, searchValue, « O, replaceValue »)。
  3. string 为 ? ToString(O)。
  4. searchString 为 ? ToString(searchValue)。
  5. functionalReplaceIsCallable(replaceValue)。
  6. 如果 functionalReplacefalse,则
    1. replaceValue 设为 ? ToString(replaceValue)。
  7. searchLengthsearchString 的长度。
  8. positionStringIndexOf(string, searchString, 0)。
  9. 如果 positionnot-found,返回 string
  10. precedingsubstring string 从 0 到 position
  11. followingsubstring stringposition + searchLength
  12. 如果 functionalReplacetrue,则
    1. replacement 为 ? ToString(? Call(replaceValue, undefined, « searchString, 𝔽(position), string »))。
  13. 否则,
    1. 断言replaceValue 是 String
    2. captures 为新的空List
    3. replacement 为 ! GetSubstitution(searchString, string, position, captures, undefined, replaceValue)。
  14. 返回 字符串拼接 precedingreplacementfollowing

此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。

22.1.3.19.1 GetSubstitution ( matched, str, position, captures, namedCaptures, replacementTemplate )

抽象操作 GetSubstitution 接收参数 matched(字符串)、str(字符串)、position(非负整数)、captures(字符串或 undefinedList)、namedCaptures(对象或 undefined)、replacementTemplate(字符串),返回字符串或抛出异常。此抽象操作中,十进制数字是 0x0030 (DIGIT ZERO) 到 0x0039 (DIGIT NINE) 区间的码元。调用时执行以下步骤:

  1. stringLengthstr 的长度。
  2. 断言positionstringLength
  3. result 为空字符串。
  4. templateRemainderreplacementTemplate
  5. 重复,直到 templateRemainder 为空字符串,
    1. 注:以下步骤隔离 reftemplateRemainder 的前缀),确定 refReplacement(其替换内容),然后将该替换内容追加到 result
    2. 如果 templateRemainder"$$" 开头,则
      1. ref"$$"
      2. refReplacement"$"
    3. 否则,如果 templateRemainder"$`" 开头,则
      1. ref"$`"
      2. refReplacementsubstring str 从 0 到 position
    4. 否则,如果 templateRemainder"$&" 开头,则
      1. ref"$&"
      2. refReplacementmatched
    5. 否则,如果 templateRemainder"$'"(0x0024(美元符号)后接 0x0027(撇号))开头,则
      1. ref"$'"
      2. matchLengthmatched 的长度。
      3. tailPosposition + matchLength
      4. refReplacementsubstring strmin(tailPos, stringLength)。
      5. 注:tailPos 只有在该抽象操作由对 %RegExp.prototype% 的 %Symbol.replace% 内置方法调用,且对象的 "exec" 属性不是内置 %RegExp.prototype.exec% 时才会超过 stringLength
    6. 否则,如果 templateRemainder"$" 后跟 1 个或多个十进制数字开头,则
      1. 如果 templateRemainder"$" 后跟 2 个或更多十进制数字开头,令 digitCount 为 2,否则为 1。
      2. digitssubstring templateRemainder 从 1 到 1 + digitCount
      3. index(StringToNumber(digits))。
      4. 断言:0 ≤ index ≤ 99。
      5. captureLencaptures 的元素个数。
      6. 如果 index > captureLendigitCount = 2,则
        1. 注:两位数替换模式指定的索引超出捕获组数量时,视为一位数替换模式后跟一个字面数字。
        2. digitCount 为 1。
        3. digitssubstring digits 从 0 到 1。
        4. index(StringToNumber(digits))。
      7. refsubstring templateRemainder 从 0 到 1 + digitCount
      8. 如果 1 ≤ indexcaptureLen,则
        1. capturecaptures[index - 1]。
        2. 如果 captureundefined,则
          1. refReplacement 为空字符串。
        3. 否则,
          1. refReplacementcapture
      9. 否则,
        1. refReplacementref
    7. 否则,如果 templateRemainder"$<" 开头,则
      1. gtPosStringIndexOf(templateRemainder, ">", 0)。
      2. 如果 gtPosnot-foundnamedCapturesundefined,则
        1. ref"$<"
        2. refReplacementref
      3. 否则,
        1. refsubstring templateRemainder 从 0 到 gtPos + 1。
        2. groupNamesubstring templateRemainder 从 2 到 gtPos
        3. 断言namedCaptures 是对象
        4. capture 为 ? Get(namedCaptures, groupName)。
        5. 如果 captureundefined,则
          1. refReplacement 为空字符串。
        6. 否则,
          1. refReplacement 为 ? ToString(capture)。
    8. 否则,
      1. refsubstring templateRemainder 从 0 到 1。
      2. refReplacementref
    9. refLengthref 的长度。
    10. templateRemainder 设为 substring templateRemainderrefLength
    11. result 设为 字符串拼接 resultrefReplacement 的结果。
  6. 返回 result

22.1.3.20 String.prototype.replaceAll ( searchValue, replaceValue )

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. 如果 searchValue 既不是 undefined 也不是 null,则
    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, « O, replaceValue »)。
  3. string 为 ? ToString(O)。
  4. searchString 为 ? ToString(searchValue)。
  5. functionalReplaceIsCallable(replaceValue)。
  6. 如果 functionalReplacefalse,则
    1. replaceValue 设为 ? ToString(replaceValue)。
  7. searchLengthsearchString 的长度。
  8. advanceBymax(1, searchLength)。
  9. matchPositions 为新的空 List
  10. positionStringIndexOf(string, searchString, 0)。
  11. 重复,直到 positionnot-found
    1. position 添加到 matchPositions
    2. position 设为 StringIndexOf(string, searchString, position + advanceBy)。
  12. endOfLastMatch 为 0。
  13. result 为空字符串。
  14. 对于 matchPositions 中的每个元素 p,执行
    1. preservedsubstring stringendOfLastMatchp
    2. 如果 functionalReplacetrue,则
      1. replacement 为 ? ToString(? Call(replaceValue, undefined, « searchString, 𝔽(p), string »))。
    3. 否则,
      1. 断言replaceValue 是 String
      2. captures 为新的空List
      3. replacement 为 ! GetSubstitution(searchString, string, p, captures, undefined, replaceValue)。
    4. result 设为 字符串拼接 resultpreservedreplacement 的结果。
    5. endOfLastMatch 设为 p + searchLength
  15. 如果 endOfLastMatch < string 的长度,则
    1. result 设为 字符串拼接 resultsubstring stringendOfLastMatch
  16. 返回 result

22.1.3.21 String.prototype.search ( regexp )

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. 如果 regexp 既不是 undefined 也不是 null,则
    1. searcher 为 ? GetMethod(regexp, %Symbol.search%)。
    2. 如果 searcher 不为 undefined,则
      1. 返回 ? Call(searcher, regexp, « O »)。
  3. string 为 ? ToString(O)。
  4. rx 为 ? RegExpCreate(regexp, undefined)。
  5. 返回 ? Invoke(rx, %Symbol.search%, « string »)。

此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。

22.1.3.22 String.prototype.slice ( start, end )

该方法返回将此对象转换为字符串后的子串,从索引 start 开始,到但不包括索引 end(或若 endundefined,则直到字符串末尾)。如果 start 为负,则视为 sourceLength + start,其中 sourceLength 是字符串长度。如果 end 为负,则视为 sourceLength + end。结果是 String值,而不是 String 对象。

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. S 为 ? ToString(O)。
  3. lenS 的长度。
  4. intStart 为 ? ToIntegerOrInfinity(start)。
  5. 如果 intStart = -∞,令 from 为 0。
  6. 否则若 intStart < 0,令 frommax(len + intStart, 0)。
  7. 否则,令 frommin(intStart, len)。
  8. 如果 endundefined,令 intEndlen;否则令 intEnd 为 ? ToIntegerOrInfinity(end)。
  9. 如果 intEnd = -∞,令 to 为 0。
  10. 否则若 intEnd < 0,令 tomax(len + intEnd, 0)。
  11. 否则,令 tomin(intEnd, len)。
  12. 如果 fromto,返回空字符串。
  13. 返回 substring Sfromto

此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此可以转移到其他类型的对象上作为方法使用。

22.1.3.23 String.prototype.split ( separator, limit )

该方法返回一个数组,将此对象转换为字符串后的子串存储在其中。子串是通过从左到右查找 separator 的出现位置确定的;这些出现位置不会包含在返回数组的任何字符串中,而是用来分割字符串。separator 的值可以是任意长度的字符串,也可以是具有 %Symbol.split% 方法的对象(如 RegExp)。

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. 如果 separator 既不是 undefined 也不是 null,则
    1. splitter 为 ? GetMethod(separator, %Symbol.split%)。
    2. 如果 splitter 不为 undefined,则
      1. 返回 ? Call(splitter, separator, « O, limit »)。
  3. S 为 ? ToString(O)。
  4. 如果 limitundefined,令 lim 为 232 - 1;否则令 lim(? ToUint32(limit))。
  5. R 为 ? ToString(separator)。
  6. 如果 lim = 0,则
    1. 返回 CreateArrayFromList(« »)。
  7. 如果 separatorundefined,则
    1. 返回 CreateArrayFromListS »)。
  8. separatorLengthR 的长度。
  9. 如果 separatorLength = 0,则
    1. strLenS 的长度。
    2. outLenclamping lim 在 0 和 strLen 之间的结果。
    3. headsubstring S 从 0 到 outLen
    4. codeUnits 为一个 List,包含 head 的所有码元。
    5. 返回 CreateArrayFromList(codeUnits)。
  10. 如果 S 为空字符串,返回 CreateArrayFromListS »)。
  11. substrings 为新的空 List
  12. i 为 0。
  13. jStringIndexOf(S, R, 0)。
  14. 重复,直到 jnot-found
    1. Tsubstring Sij
    2. T 添加到 substrings
    3. 如果 substrings 的元素个数为 lim,返回 CreateArrayFromList(substrings)。
    4. i 设为 j + separatorLength
    5. j 设为 StringIndexOf(S, R, i)。
  15. Tsubstring Si
  16. T 添加到 substrings
  17. 返回 CreateArrayFromList(substrings)。
注 1

separator 的值可以为空字符串。在这种情况下,separator 不会匹配输入字符串开头或结尾的空子串,也不会匹配前一个分隔符匹配后结尾的空子串。如果 separator 为空字符串,则字符串被拆分为单个码元元素;结果数组的长度等于字符串的长度,每个子串只包含一个码元。

如果 this 值(或其转换结果)为空字符串,则结果取决于 separator 能否匹配空字符串。如果可以,结果数组不包含任何元素;否则,结果数组包含一个元素,即空字符串。

如果 separatorundefined,结果数组只包含一个字符串,即 this 的值(转换为字符串)。如果 limit 不为 undefined,则输出数组会被截断为不超过 limit 个元素。

注 2

此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。

22.1.3.24 String.prototype.startsWith ( searchString [ , position ] )

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. S 为 ? ToString(O)。
  3. isRegExp 为 ? IsRegExp(searchString)。
  4. 如果 isRegExptrue,抛出 TypeError 异常。
  5. searchStr 为 ? ToString(searchString)。
  6. lenS 的长度。
  7. 如果 positionundefined,令 pos 为 0;否则令 pos 为 ? ToIntegerOrInfinity(position)。
  8. startclamping pos 在 0 和 len 之间的结果。
  9. searchLengthsearchStr 的长度。
  10. 如果 searchLength = 0,返回 true
  11. endstart + searchLength
  12. 如果 end > len,返回 false
  13. substringsubstring Sstartend
  14. 如果 substring 等于 searchStr,返回 true
  15. 返回 false
注 1

如果 searchString(转换为字符串)的码元序列与本对象(转换为字符串)从 position 开始的对应码元相同,则返回 true,否则返回 false

注 2

如果第一个参数是 RegExp 抛出异常,是为了允许后续标准版本定义支持此类参数值的扩展。

注 3

此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。

22.1.3.25 String.prototype.substring ( start, end )

该方法返回将此对象转换为字符串后的子串,从索引 start 开始,到但不包括字符串的索引 end(或若 endundefined,则直到字符串末尾)。结果是 String值,而不是 String 对象。

如果任一参数为 NaN 或负数,则用零替换;如果任一参数严格大于字符串长度,则用字符串长度替换。

如果 start 严格大于 end,则交换两者。

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. S 为 ? ToString(O)。
  3. lenS 的长度。
  4. intStart 为 ? ToIntegerOrInfinity(start)。
  5. 如果 endundefined,令 intEndlen;否则令 intEnd 为 ? ToIntegerOrInfinity(end)。
  6. finalStartclamping intStart 在 0 和 len 之间的结果。
  7. finalEndclamping intEnd 在 0 和 len 之间的结果。
  8. frommin(finalStart, finalEnd)。
  9. tomax(finalStart, finalEnd)。
  10. 返回 substring Sfromto

此方法有意设计为泛型;它不要求其 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 支持的实现不得将这些参数位置用于其他用途。

此方法有意设计为泛型;它不要求其 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 支持的实现不得将这些参数位置用于其他用途。

此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。

22.1.3.28 String.prototype.toLowerCase ( )

该方法将 String 值作为 UTF-16 编码码点序列解释,如 6.1.4 中描述。

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. S 为 ? ToString(O)。
  3. sTextStringToCodePoints(S)。
  4. lowerText 为根据 Unicode 默认大小写转换算法对 sText 执行 toLowercase。
  5. LCodePointsToString(lowerText)。
  6. 返回 L

结果必须依据 Unicode 字符数据库中的区域无关大小写映射得出(这不仅包括 UnicodeData.txt 文件,还包括伴随的 SpecialCasing.txt 文件中所有区域无关的映射)。

注 1

某些码点的大小写映射可能产生多个码点。在这种情况下,结果字符串的长度可能与源字符串不同。由于 toUpperCasetoLowerCase 都具有上下文相关行为,这些方法并不对称。换言之,s.toUpperCase().toLowerCase() 不一定等于 s.toLowerCase()

注 2

此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。

22.1.3.29 String.prototype.toString ( )

调用该方法时,执行以下步骤:

  1. 返回 ? ThisStringValue(this 值)。

对于 String 对象,此方法恰好返回与 valueOf 方法相同的值。

22.1.3.30 String.prototype.toUpperCase ( )

该方法将 String 值作为 UTF-16 编码码点序列解释,如 6.1.4 中描述。

其行为与 String.prototype.toLowerCase 完全相同,只是字符串使用 Unicode 默认大小写转换的 toUppercase 算法进行映射。

此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。

22.1.3.31 String.prototype.toWellFormed ( )

该方法返回此对象的字符串表示,将所有不是代理对一部分的前导代理项尾随代理项替换为 U+FFFD(替换字符)。

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. S 为 ? ToString(O)。
  3. strLenS 的长度。
  4. k 为 0。
  5. result 为空字符串。
  6. 重复,直到 k < strLen
    1. cpCodePointAt(S, k)。
    2. 如果 cp.[[IsUnpairedSurrogate]]true,则
      1. result 设为 字符串拼接 result 和 0xFFFD(替换字符)的结果。
    3. 否则,
      1. result 设为 字符串拼接 resultUTF16EncodeCodePoint(cp.[[CodePoint]]) 的结果。
    4. k 设为 k + cp.[[CodeUnitCount]]
  7. 返回 result

22.1.3.32 String.prototype.trim ( )

该方法将 String 值作为 UTF-16 编码码点序列解释,如 6.1.4 中描述。

调用该方法时,执行以下步骤:

  1. Sthis 值。
  2. 返回 ? TrimString(S, start+end)。

此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。

22.1.3.32.1 TrimString ( string, where )

抽象操作 TrimString 接收参数 stringECMAScript 语言值)和 wherestartendstart+end),返回字符串或抛出异常。它将 string 解释为 UTF-16 编码码点序列,如 6.1.4 规定。调用时执行以下步骤:

  1. str 为 ? RequireObjectCoercible(string)。
  2. S 为 ? ToString(str)。
  3. 如果 wherestart,则
    1. TS 去除前导空白后的字符串值。
  4. 否则若 whereend,则
    1. TS 去除尾随空白后的字符串值。
  5. 否则,
    1. 断言wherestart+end
    2. TS 去除前导和尾随空白后的字符串值。
  6. 返回 T

空白的定义为 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. Sthis 值。
  2. 返回 ? TrimString(S, end)。

此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。

22.1.3.34 String.prototype.trimStart ( )

该方法将 String 值作为 UTF-16 编码码点序列解释,如 6.1.4 中描述。

调用该方法时,执行以下步骤:

  1. Sthis 值。
  2. 返回 ? TrimString(S, start)。

此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。

22.1.3.35 String.prototype.valueOf ( )

调用该方法时,执行以下步骤:

  1. 返回 ? ThisStringValue(this 值)。

22.1.3.35.1 ThisStringValue ( value )

抽象操作 ThisStringValue 接收参数 valueECMAScript 语言值),返回字符串或抛出异常。调用时执行以下步骤:

  1. 如果 value 是 String,返回 value
  2. 如果 value 是对象value 具有 [[StringData]] 内部槽,则
    1. svalue.[[StringData]]
    2. 断言s 是 String
    3. 返回 s
  3. 抛出 TypeError 异常。

22.1.3.36 String.prototype [ %Symbol.iterator% ] ( )

该方法返回一个迭代器对象,用于遍历字符串值的每个码点,每次返回一个字符串值。

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. s 为 ? ToString(O)。
  3. closure 为新的抽象闭包,无参数,捕获 s,并在被调用时执行以下步骤:
    1. lens 的长度。
    2. position 为 0。
    3. 重复,直到 position < len
      1. cpCodePointAt(s, position)。
      2. nextIndexposition + cp.[[CodeUnitCount]]
      3. resultStringsubstring spositionnextIndex
      4. position 设为 nextIndex
      5. 执行 ? GeneratorYield(CreateIteratorResultObject(resultString, false))。
    4. 返回 undefined
  4. 返回 CreateIteratorFromClosure(closure, "%StringIteratorPrototype%", %StringIteratorPrototype%)。

该方法的 "name" 属性值为 "[Symbol.iterator]"

22.1.4 String 实例的属性

String 实例是 String 特殊对象,并具有为此类对象规定的内部方法。String 实例继承自 String 原型对象 的属性。String 实例还具有 [[StringData]] 内部槽。[[StringData]] 内部槽是该 String 对象所表示的 String 值。

String 实例具有 "length" 属性,以及一组具有 整数索引名称的可枚举属性。

22.1.4.1 length

该 String 对象所表示的 String 值中的元素数量。

一旦 String 对象被初始化,此属性不可更改。它具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

22.1.5 String 迭代器对象

String 迭代器是表示对某个特定 String 实例对象的某次特定迭代的对象。String 迭代器对象没有命名的构造函数。而是通过调用 String 实例对象的某些方法创建 String 迭代器对象。

22.1.5.1 %StringIteratorPrototype% 对象

%StringIteratorPrototype% 对象:

22.1.5.1.1 %StringIteratorPrototype%.next ( )

  1. 返回 ? GeneratorResume(this 值, empty, "%StringIteratorPrototype%")。

22.1.5.1.2 %StringIteratorPrototype% [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值为字符串值 "String Iterator"

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

22.2 RegExp(正则表达式)对象

RegExp 对象包含一个正则表达式和相关的标志(flags)。

正则表达式的形式和功能模仿了 Perl 5 编程语言中的正则表达式机制。

22.2.1 模式(Patterns)

RegExp 构造函数 对输入模式字符串应用以下语法。如果该语法无法将字符串解释为 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 HexTrailSurrogateu HexLeadSurrogate

HexLeadSurrogate :: Hex4Digits but only if the MV of Hex4Digits is in the inclusive interval from 0xD800 to 0xDBFF HexTrailSurrogate :: Hex4Digits but only if the MV of Hex4Digits is in the inclusive interval from 0xDC00 to 0xDFFF HexNonSurrogate :: Hex4Digits but only if the MV of Hex4Digits is not in the inclusive interval from 0xD800 to 0xDFFF IdentityEscape[UnicodeMode] :: [+UnicodeMode] SyntaxCharacter [+UnicodeMode] / [~UnicodeMode] SourceCharacter but not UnicodeIDContinue DecimalEscape :: NonZeroDigit DecimalDigits[~Sep]opt [lookahead ∉ DecimalDigit] CharacterClassEscape[UnicodeMode] :: d D s S w W [+UnicodeMode] p{ UnicodePropertyValueExpression } [+UnicodeMode] P{ UnicodePropertyValueExpression } UnicodePropertyValueExpression :: UnicodePropertyName = UnicodePropertyValue LoneUnicodePropertyNameOrValue UnicodePropertyName :: UnicodePropertyNameCharacters UnicodePropertyNameCharacters :: UnicodePropertyNameCharacter UnicodePropertyNameCharactersopt UnicodePropertyValue :: UnicodePropertyValueCharacters LoneUnicodePropertyNameOrValue :: UnicodePropertyValueCharacters UnicodePropertyValueCharacters :: UnicodePropertyValueCharacter UnicodePropertyValueCharactersopt UnicodePropertyValueCharacter :: UnicodePropertyNameCharacter DecimalDigit UnicodePropertyNameCharacter :: AsciiLetter _ CharacterClass[UnicodeMode, UnicodeSetsMode] :: [ [lookahead ≠ ^] ClassContents[?UnicodeMode, ?UnicodeSetsMode] ] [^ ClassContents[?UnicodeMode, ?UnicodeSetsMode] ] ClassContents[UnicodeMode, UnicodeSetsMode] :: [empty] [~UnicodeSetsMode] NonemptyClassRanges[?UnicodeMode] [+UnicodeSetsMode] ClassSetExpression NonemptyClassRanges[UnicodeMode] :: ClassAtom[?UnicodeMode] ClassAtom[?UnicodeMode] NonemptyClassRangesNoDash[?UnicodeMode] ClassAtom[?UnicodeMode] - ClassAtom[?UnicodeMode] ClassContents[?UnicodeMode, ~UnicodeSetsMode] NonemptyClassRangesNoDash[UnicodeMode] :: ClassAtom[?UnicodeMode] ClassAtomNoDash[?UnicodeMode] NonemptyClassRangesNoDash[?UnicodeMode] ClassAtomNoDash[?UnicodeMode] - ClassAtom[?UnicodeMode] ClassContents[?UnicodeMode, ~UnicodeSetsMode] ClassAtom[UnicodeMode] :: - ClassAtomNoDash[?UnicodeMode] ClassAtomNoDash[UnicodeMode] :: SourceCharacter but not one of \ or ] or - \ ClassEscape[?UnicodeMode] ClassEscape[UnicodeMode] :: b [+UnicodeMode] - CharacterClassEscape[?UnicodeMode] CharacterEscape[?UnicodeMode] ClassSetExpression :: ClassUnion ClassIntersection ClassSubtraction ClassUnion :: ClassSetRange ClassUnionopt ClassSetOperand ClassUnionopt ClassIntersection :: ClassSetOperand && [lookahead ≠ &] ClassSetOperand ClassIntersection && [lookahead ≠ &] ClassSetOperand ClassSubtraction :: ClassSetOperand -- ClassSetOperand ClassSubtraction -- ClassSetOperand ClassSetRange :: ClassSetCharacter - ClassSetCharacter ClassSetOperand :: NestedClass ClassStringDisjunction ClassSetCharacter NestedClass :: [ [lookahead ≠ ^] ClassContents[+UnicodeMode, +UnicodeSetsMode] ] [^ ClassContents[+UnicodeMode, +UnicodeSetsMode] ] \ CharacterClassEscape[+UnicodeMode] 注 1

此处前两行等价于 CharacterClass。

ClassStringDisjunction :: \q{ ClassStringDisjunctionContents } ClassStringDisjunctionContents :: ClassString ClassString | ClassStringDisjunctionContents ClassString :: [empty] NonEmptyClassString NonEmptyClassString :: ClassSetCharacter NonEmptyClassStringopt ClassSetCharacter :: [lookahead ∉ ClassSetReservedDoublePunctuator] SourceCharacter but not ClassSetSyntaxCharacter \ CharacterEscape[+UnicodeMode] \ ClassSetReservedPunctuator \b ClassSetReservedDoublePunctuator :: one of && !! ## $$ %% ** ++ ,, .. :: ;; << == >> ?? @@ ^^ `` ~~ ClassSetSyntaxCharacter :: one of ( ) [ ] { } / - \ | ClassSetReservedPunctuator :: one of & - ! # % , : ; < = > @ ` ~ 注 2

本节中的多项产生式在 B.1.2 节中给出了替代定义。

22.2.1.1 静态语义:早期错误(Static Semantics: Early Errors)

本节在 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 静态语义:CountLeftCapturingParensWithin (node)

抽象操作 CountLeftCapturingParensWithin 接收参数 node(一个 解析节点),返回一个非负整数。它返回 node 中左捕获括号的数量。左捕获括号是任何与以下产生式的 ( 终结符匹配的 ( 模式字符:

Atom :: ( GroupSpecifieropt Disjunction )

本节在 B.1.2.2 中有补充。

调用时,执行以下步骤:

  1. 断言node正则表达式模式语法中的某个产生式的实例。
  2. 返回 node 内部所包含的以下解析节点的数量:
Atom :: ( GroupSpecifieropt Disjunction )

解析节点

22.2.1.3 静态语义:CountLeftCapturingParensBefore (node)

抽象操作 CountLeftCapturingParensBefore 接收参数 node(一个 解析节点),返回一个非负整数。它返回封闭模式中出现在 node 左侧的左捕获括号的数量。

本节在 B.1.2.2 中有补充。

调用时,执行以下步骤:

  1. 断言node正则表达式模式语法中的某个产生式的实例。
  2. pattern 为包含 nodePattern
  3. 返回 pattern 内部,出现在 node 之前或包含 node 的以下解析节点的数量:
Atom :: ( GroupSpecifieropt Disjunction )

解析节点

22.2.1.4 静态语义:MightBothParticipate (x, y)

抽象操作 MightBothParticipate 接收参数 x(一个 解析节点)和 y(一个 解析节点),返回布尔值。调用时,执行以下步骤:

  1. 断言xy 拥有同一个封闭的 Pattern
  2. 如果该封闭 Pattern 包含如下 Disjunction :: Alternative | Disjunction 解析节点,使得 x 包含于 Alternative 中且 y 包含于派生的 Disjunction 中,或者 x 包含于派生的 Disjunction 中且 y 包含于 Alternative 中,则返回 false
  3. 返回 true

22.2.1.5 静态语义:CapturingGroupNumber

语法定向操作 CapturingGroupNumber 无参数,返回正整数

本节在 B.1.2.1 中有补充。

在以下产生式中分段定义:

DecimalEscape :: NonZeroDigit
  1. 返回 NonZeroDigit 的 MV。
DecimalEscape :: NonZeroDigit DecimalDigits
  1. nDecimalDigits 中码点的数量。
  2. 返回 (NonZeroDigit 的 MV × 10nDecimalDigits 的 MV)。

NonZeroDigit 的 MV” 和 “DecimalDigits 的 MV” 的定义见 12.9.3

22.2.1.6 静态语义:IsCharacterClass

语法定向操作 IsCharacterClass 无参数,返回布尔值。

本节在 B.1.2.3 中有补充。

在以下产生式中分段定义:

ClassAtom :: - ClassAtomNoDash :: SourceCharacter 但不是 \]- 之一 ClassEscape :: b - CharacterEscape
  1. 返回 false
ClassEscape :: CharacterClassEscape
  1. 返回 true

22.2.1.7 静态语义:CharacterValue

语法定向操作 CharacterValue 无参数,返回非负整数

注 1

本节在 B.1.2.4 中有补充。

在以下产生式中分段定义:

ClassAtom :: -
  1. 返回 U+002D(连字符 HYPHEN-MINUS)的数值。
ClassAtomNoDash :: SourceCharacter但不是 \]- 之一
  1. chSourceCharacter 匹配的码点。
  2. 返回 ch 的数值。
ClassEscape :: b
  1. 返回 U+0008(退格 BACKSPACE)的数值。
ClassEscape :: -
  1. 返回 U+002D(连字符 HYPHEN-MINUS)的数值。
CharacterEscape :: ControlEscape
  1. 按照 表 67 返回数值。
表 67: 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. chAsciiLetter 匹配的码点。
  2. ich 的数值。
  3. 返回 i 除以 32 的余数。
CharacterEscape :: 0 [lookahead ∉ DecimalDigit]
  1. 返回 U+0000(NULL)的数值。
注 2

\0 表示 <NUL> 字符,且不能后跟十进制数字。

CharacterEscape :: HexEscapeSequence
  1. 返回 HexEscapeSequence 的 MV。
RegExpUnicodeEscapeSequence :: u HexLeadSurrogate \u HexTrailSurrogate
  1. leadCharacterValue of HexLeadSurrogate
  2. trailCharacterValue of HexTrailSurrogate
  3. cpUTF16SurrogatePairToCodePoint(lead, trail)。
  4. 返回 cp 的数值。
RegExpUnicodeEscapeSequence :: u Hex4Digits
  1. 返回 Hex4Digits 的 MV。
RegExpUnicodeEscapeSequence :: u{ CodePoint }
  1. 返回 CodePoint 的 MV。
HexLeadSurrogate :: Hex4Digits HexTrailSurrogate :: Hex4Digits HexNonSurrogate :: Hex4Digits
  1. 返回 Hex4Digits 的 MV。
CharacterEscape :: IdentityEscape
  1. chIdentityEscape 匹配的码点。
  2. 返回 ch 的数值。
ClassSetCharacter :: SourceCharacter但不是 ClassSetSyntaxCharacter
  1. chSourceCharacter 匹配的码点。
  2. 返回 ch 的数值。
ClassSetCharacter :: \ ClassSetReservedPunctuator
  1. chClassSetReservedPunctuator 匹配的码点。
  2. 返回 ch 的数值。
ClassSetCharacter :: \b
  1. 返回 U+0008(退格 BACKSPACE)的数值。

22.2.1.8 静态语义:MayContainStrings

语法定向操作 MayContainStrings 无参数,返回布尔值。它在以下产生式中分段定义:

CharacterClassEscape :: d D s S w W P{ UnicodePropertyValueExpression } UnicodePropertyValueExpression :: UnicodePropertyName = UnicodePropertyValue NestedClass :: [^ ClassContents ] ClassContents :: [empty] NonemptyClassRanges ClassSetOperand :: ClassSetCharacter
  1. 返回 false
UnicodePropertyValueExpression :: LoneUnicodePropertyNameOrValue
  1. 如果 source text matched by LoneUnicodePropertyNameOrValue表 71“属性名”列中列出的字符串的二进制属性,则返回 true
  2. 返回 false
ClassUnion :: ClassSetRange ClassUnionopt
  1. 如果 ClassUnion 存在,返回 MayContainStrings of ClassUnion
  2. 返回 false
ClassUnion :: ClassSetOperand ClassUnionopt
  1. 如果 MayContainStrings of ClassSetOperandtrue,返回 true
  2. 如果 ClassUnion 存在,返回 MayContainStrings of ClassUnion
  3. 返回 false
ClassIntersection :: ClassSetOperand && ClassSetOperand
  1. 如果 MayContainStrings of 第一个 ClassSetOperandfalse,返回 false
  2. 如果 MayContainStrings of 第二个 ClassSetOperandfalse,返回 false
  3. 返回 true
ClassIntersection :: ClassIntersection && ClassSetOperand
  1. 如果 MayContainStrings of ClassIntersectionfalse,返回 false
  2. 如果 MayContainStrings of ClassSetOperandfalse,返回 false
  3. 返回 true
ClassSubtraction :: ClassSetOperand -- ClassSetOperand
  1. 返回第一个 MayContainStrings of ClassSetOperand
ClassSubtraction :: ClassSubtraction -- ClassSetOperand
  1. 返回 MayContainStrings of ClassSubtraction
ClassStringDisjunctionContents :: ClassString | ClassStringDisjunctionContents
  1. 如果 MayContainStrings of ClassStringtrue,返回 true
  2. 返回 MayContainStrings of ClassStringDisjunctionContents
ClassString :: [empty]
  1. 返回 true
ClassString :: NonEmptyClassString
  1. 返回 MayContainStrings of NonEmptyClassString
NonEmptyClassString :: ClassSetCharacter NonEmptyClassStringopt
  1. 如果 NonEmptyClassString 存在,返回 true
  2. 返回 false

22.2.1.9 静态语义:GroupSpecifiersThatMatch (thisGroupName)

抽象操作 GroupSpecifiersThatMatch 接收参数 thisGroupName(一个 GroupName 解析节点),返回 List 类型的 GroupSpecifier 解析节点。调用时,执行如下步骤:

  1. nameCapturingGroupName of thisGroupName
  2. pattern 为包含 thisGroupNamePattern
  3. result 为一个新的空 List
  4. 对于 pattern 包含的每个 GroupSpecifier gs,执行:
    1. 如果 gsCapturingGroupName 等于 name,则:
      1. gs 添加至 result
  5. 返回 result

22.2.1.10 静态语义:CapturingGroupName

语法定向操作 CapturingGroupName 无参数,返回字符串。它在以下产生式中分段定义:

GroupName :: < RegExpIdentifierName >
  1. idTextUnescapedRegExpIdentifierCodePoints of RegExpIdentifierName
  2. 返回 CodePointsToString(idTextUnescaped)。

22.2.1.11 静态语义:RegExpIdentifierCodePoints

语法定向操作 RegExpIdentifierCodePoints 无参数,返回码点 List。它在以下产生式中分段定义:

RegExpIdentifierName :: RegExpIdentifierStart
  1. cpRegExpIdentifierCodePoint of RegExpIdentifierStart
  2. 返回 « cp »。
RegExpIdentifierName :: RegExpIdentifierName RegExpIdentifierPart
  1. cps 为派生的 RegExpIdentifierCodePoints of RegExpIdentifierName
  2. cpRegExpIdentifierCodePoint of RegExpIdentifierPart
  3. 返回 list-concatenation of cps 和 « cp »。

22.2.1.12 静态语义:RegExpIdentifierCodePoint

语法定向操作 RegExpIdentifierCodePoint 无参数,返回码点。它在以下产生式中分段定义:

RegExpIdentifierStart :: IdentifierStartChar
  1. 返回 IdentifierStartChar 匹配的码点。
RegExpIdentifierPart :: IdentifierPartChar
  1. 返回 IdentifierPartChar 匹配的码点。
RegExpIdentifierStart :: \ RegExpUnicodeEscapeSequence RegExpIdentifierPart :: \ RegExpUnicodeEscapeSequence
  1. 返回数值为 CharacterValue of RegExpUnicodeEscapeSequence 的码点。
RegExpIdentifierStart :: UnicodeLeadSurrogate UnicodeTrailSurrogate RegExpIdentifierPart :: UnicodeLeadSurrogate UnicodeTrailSurrogate
  1. leadUnicodeLeadSurrogate 匹配的码点的数值所对应的码元。
  2. trailUnicodeTrailSurrogate 匹配的码点的数值所对应的码元。
  3. 返回 UTF16SurrogatePairToCodePoint(lead, trail)。

22.2.2 模式语义(Pattern Semantics)

正则表达式模式会按照下述过程被转换为一个 抽象闭包(Abstract Closure)。实现可以使用比下文所列更高效的算法,只要结果一致。该 抽象闭包 用作 RegExp 对象的 [[RegExpMatcher]] 内部槽的值。

如果一个 Pattern 的关联标志既不包含 u 也不包含 v,则它是 BMP 模式。否则,它是 Unicode 模式。BMP 模式会针对被解释为由处于基本多文种平面(BMP)范围内的 Unicode 码点组成的 16 位值序列的字符串进行匹配。Unicode 模式则针对被解释为用 UTF-16 编码的 Unicode 码点序列的字符串进行匹配。在描述 BMP 模式行为时,“character” 表示单个 16 位的 Unicode BMP 码点。在描述 Unicode 模式行为时,“character” 表示一个 UTF-16 编码的码点(6.1.4)。无论哪种情况,“character value” 都指对应非编码码点的数值。

Pattern 的语法和语义定义为其源文本为一个 List,其中每个元素为 SourceCharacter,对应一个 Unicode 码点。如果 BMP 模式包含了非 BMP 的 SourceCharacter,则整个模式会被用 UTF-16 编码,并将该编码的各个码元作为 List 的元素。

例如,假设一个模式在源文本中表示为单个非 BMP 字符 U+1D11E(MUSICAL SYMBOL G CLEF)。作为 Unicode 模式解释时,它是一个仅包含该码点 U+1D11E 的元素(字符)List。然而,作为 BMP 模式解释时,它会首先被 UTF-16 编码,得到两个元素的 List,其码元分别为 0xD834 和 0xDD1E。

模式会以 ECMAScript 字符串值的形式传递给 RegExp 构造函数,其中非 BMP 字符已经用 UTF-16 编码。例如,该 MUSICAL SYMBOL G CLEF 单字符模式,表达为字符串值时,是长度为 2 的字符串,其元素为 0xD834 和 0xDD1E 码元。因此,若作为包含两个模式字符的 BMP 模式处理,不需要再对字符串做转换;但若作为 Unicode 模式处理,则需用 UTF16SurrogatePairToCodePoint 得到仅含一个模式字符(码点 U+1D11E)的 List

实现不一定真的需要进行这些 UTF-16 的转换,但本规范要求,模式匹配的语义要如同进行了这些转换一样。

22.2.2.1 符号说明(Notation)

下述描述使用以下内部数据结构:

  • CharSetElement(字符集元素)是以下两种实体之一:
    • rer.[[UnicodeSets]]false,CharSetElement 就是前述“模式语义”意义下的字符。
    • rer.[[UnicodeSets]]true,CharSetElement 是一个序列,其元素为“模式语义”意义下的字符。包括空序列、单字符序列和多字符序列。为了方便,处理这类 CharSetElement 时,单个字符和单字符序列可以互换。
  • CharSet(字符集)是 CharSetElement 的数学集合。
  • CaptureRange(捕获范围)是一个 Record { [[StartIndex]], [[EndIndex]] },表示捕获所包含的字符范围,其中 [[StartIndex]]整数,表示 Input 中范围的起始索引(包含),[[EndIndex]]整数,表示 Input 中范围的结束索引(不包含)。任何 CaptureRange 都必须满足 [[StartIndex]][[EndIndex]]
  • MatchState(匹配状态)是一个 Record { [[Input]], [[EndIndex]], [[Captures]] },其中 [[Input]] 是待匹配字符串的字符 List[[EndIndex]]整数[[Captures]] 是一个 List,每个元素对应模式中的一个 左捕获括号MatchStates 用于表达正则表达式匹配算法中的部分匹配状态。[[EndIndex]] 是当前为止最后一个已匹配输入字符的索引加一,[[Captures]] 保存捕获括号的结果。n[[Captures]] 元素,要么是 CaptureRange,表示第 n 个捕获括号捕获的范围,要么为 undefined 表示还未到达。由于回溯,匹配过程中可能同时存在多个 MatchStates
  • MatcherContinuation(匹配延续)是一个 抽象闭包,接收一个 MatchState 参数,返回一个 MatchStatefailureMatcherContinuation 试图将模式剩余部分(由闭包捕获的值指定)与 Input 匹配,从当前 MatchState 状态开始。如果匹配成功,返回最终到达的 MatchState,否则返回 failure
  • Matcher(匹配器)是一个 抽象闭包,接收两个参数——MatchStateMatcherContinuation,返回 MatchStatefailureMatcher 试图将模式的某一中间子模式(由闭包捕获的值指定)与 MatchState[[Input]] 匹配,从传入的中间状态开始。MatcherContinuation 参数应为匹配剩余模式的闭包。匹配子模式获得新的 MatchState 后,Matcher 会在此状态上调用 MatcherContinuation 检查剩余模式是否也能匹配。如果可以,返回 MatchState;否则,匹配器可能会在其选择点尝试不同的选择,不断调用 MatcherContinuation,直到成功或无可能性为止。

22.2.2.1.1 RegExp 记录(RegExp Records)

RegExp Record 是一个 Record,用于存储 RegExp 在编译及可能的匹配期间需要的信息。

它包含如下字段:

表 68: RegExp Record 字段
字段名 含义
[[IgnoreCase]] 布尔值 指示 RegExp 标志中是否出现 "i"
[[Multiline]] 布尔值 指示 RegExp 标志中是否出现 "m"
[[DotAll]] 布尔值 指示 RegExp 标志中是否出现 "s"
[[Unicode]] 布尔值 指示 RegExp 标志中是否出现 "u"
[[UnicodeSets]] 布尔值 指示 RegExp 标志中是否出现 "v"
[[CapturingGroupsCount]] 非负整数 RegExp 模式中的 左捕获括号 的数量

22.2.2.2 运行时语义:CompilePattern

语法定向操作 CompilePattern 接收参数 rer(一个 RegExp Record),返回一个 抽象闭包(Abstract Closure),该闭包接收一个字符 List 和一个非负 整数,返回一个 MatchStatefailure。它在以下产生式中分段定义:

Pattern :: Disjunction
  1. mCompileSubpattern of Disjunction,参数为 rerforward
  2. 返回一个新 抽象闭包,参数为 (Input, index),捕获 rerm,调用时执行以下步骤:
    1. 断言Input 为字符 List
    2. 断言:0 ≤ indexInput 的元素数量。
    3. c 为一个新 MatcherContinuation,参数 (y),不捕获任何内容,调用时:
      1. 断言yMatchState
      2. 返回 y
    4. caprer.[[CapturingGroupsCount]]undefinedList,索引从 1 到 rer.[[CapturingGroupsCount]]
    5. xMatchState { [[Input]]: Input, [[EndIndex]]: index, [[Captures]]: cap }。
    6. 返回 m(x, c)。

Pattern 会被编译为 抽象闭包(Abstract Closure)RegExpBuiltinExec 可以将该过程应用于字符 List 及其偏移量,以判断模式是否会正好从该偏移处开始匹配,并在匹配时获得捕获括号的值。本节算法允许编译过程中抛出 SyntaxError;但一旦编译成功,匹配时除非发生实现相关异常(如内存溢出)不会抛出异常。

22.2.2.3 运行时语义:CompileSubpattern

语法定向操作 CompileSubpattern 接收参数 rer(一个 RegExp Record)和 directionforwardbackward),返回一个 Matcher

注 1

本节在 B.1.2.5 中有补充。

在以下产生式中分段定义:

Disjunction :: Alternative | Disjunction
  1. m1CompileSubpattern of Alternative,参数为 rerdirection
  2. m2CompileSubpattern of Disjunction,参数为 rerdirection
  3. 返回 MatchTwoAlternatives(m1, m2)。
注 2

| 正则表达式操作符分隔两个备选项。模式首先尝试匹配左侧 Alternative(后接正则表达式剩余部分);如果失败,则尝试匹配右侧 Disjunction(后接剩余部分)。如果左侧 Alternative、右侧 Disjunction 和剩余部分都有选择点,则会先穷尽剩余部分的所有选择,再移动到右侧。若左侧所有选择用尽,则会尝试右侧。被 | 跳过的部分中的捕获括号,其值为 undefined 而非字符串。例如:

/a|ab/.exec("abc")

返回结果为 "a" 而非 "ab"。再例如:

/((a)|(ab))((c)|(bc))/.exec("abc")

返回数组:

["abc", "a", "a", undefined, "bc", undefined, "bc"]

而不是:

["abc", "ab", undefined, "ab", "c", "c", undefined]

两个备选项的尝试顺序与 direction 的值无关。

Alternative :: [empty]
  1. 返回 EmptyMatcher()。
Alternative :: Alternative Term
  1. m1CompileSubpattern of Alternative,参数为 rerdirection
  2. m2CompileSubpattern of Term,参数为 rerdirection
  3. 返回 MatchSequence(m1, m2, direction)。
注 3

连续的 Term 会尝试同时匹配 Input 的连续部分。当 directionforward 时,若左、右和剩余部分都有选择点,则会先穷尽剩余、再穷尽右侧、最后再穷尽左侧的选择。当 directionbackward 时,左、右的顺序交换。

Term :: Assertion
  1. 返回 CompileAssertion of Assertion,参数为 rer
注 4

所得 Matcherdirection 无关。

Term :: Atom
  1. 返回 CompileAtom of Atom,参数为 rerdirection
Term :: Atom Quantifier
  1. mCompileAtom of Atom,参数为 rerdirection
  2. qCompileQuantifier of Quantifier
  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, x, c, parenIndex, parenCount)

抽象操作 RepeatMatcher 接收参数 m(一个 Matcher)、min(非负 整数)、max(非负 整数 或 +∞)、greedy(布尔值)、xMatchState)、cMatcherContinuation)、parenIndex(非负 整数)、parenCount(非负 整数),返回一个 MatchStatefailure。调用时执行以下步骤:

  1. 如果 max = 0,返回 c(x)。
  2. d 为一个新 MatcherContinuation,参数 (y),捕获 mminmaxgreedyxcparenIndexparenCount,调用时:
    1. 断言yMatchState
    2. 如果 min = 0 且 y.[[EndIndex]] = x.[[EndIndex]],返回 failure
    3. 如果 min = 0,令 min2 为 0;否则,令 min2min - 1。
    4. 如果 max = +∞,令 max2 为 +∞;否则,令 max2max - 1。
    5. 返回 RepeatMatcher(m, min2, max2, greedy, y, c, parenIndex, parenCount)。
  3. capx.[[Captures]] 的副本。
  4. 对于 整数 k,在 闭区间 parenIndex + 1 到 parenIndex + parenCount,令 cap[k] = undefined
  5. Inputx.[[Input]]
  6. ex.[[EndIndex]]
  7. xrMatchState { [[Input]]: Input, [[EndIndex]]: e, [[Captures]]: cap }。
  8. 如果 min ≠ 0,返回 m(xr, d)。
  9. 如果 greedyfalse,则:
    1. zc(x)。
    2. 如果 z 不为 failure,返回 z
    3. 返回 m(xr, d)。
  10. zm(xr, d)。
  11. 如果 z 不为 failure,返回 z
  12. 返回 c(x)。
注 1

一个 Atom 后跟 Quantifier 时,会根据 Quantifier 指定的次数重复。Quantifier 可以是非贪婪的(尽量少匹配)或贪婪的(尽量多匹配)。重复的是 Atom 的模式本身,不同重复可匹配不同的输入子串。

注 2

如果 Atom 和剩余部分都有选择点,会先尽量多(或少,若非贪婪)匹配 Atom,再穷尽剩余选择,然后再回溯到上一次重复。可以用这种选择点顺序写出求最大公约数的正则表达式。

注 3

RepeatMatcher 的 步骤 4 每次重复时都会清除 Atom 的捕获结果。

注 4

RepeatMatcher 的 2.b 指出:当已满足最小重复次数时,若 Atom 匹配空字符串,则不再继续重复,防止无限循环。

22.2.2.3.2 EmptyMatcher ( )

抽象操作 EmptyMatcher 无参数,返回一个 Matcher。调用时执行以下步骤:

  1. 返回一个新 Matcher,参数 (x, c),不捕获任何内容,调用时:
    1. 断言xMatchState
    2. 断言cMatcherContinuation
    3. 返回 c(x)。

22.2.2.3.3 MatchTwoAlternatives (m1, m2)

抽象操作 MatchTwoAlternatives 接收参数 m1Matcher)和 m2Matcher),返回一个 Matcher。调用时执行以下步骤:

  1. 返回一个新 Matcher,参数 (x, c),捕获 m1m2,调用时:
    1. 断言xMatchState
    2. 断言cMatcherContinuation
    3. rm1(x, c)。
    4. rfailure,返回 r
    5. 返回 m2(x, c)。

22.2.2.3.4 MatchSequence (m1, m2, direction)

抽象操作 MatchSequence 接收参数 m1Matcher)、m2Matcher)、directionforwardbackward),返回一个 Matcher。调用时执行以下步骤:

  1. 如果 directionforward,则:
    1. 返回一个新 Matcher,参数 (x, c),捕获 m1m2,调用时:
      1. 断言xMatchState
      2. 断言cMatcherContinuation
      3. d 为一个新 MatcherContinuation,参数 (y),捕获 cm2,调用时:
        1. 断言yMatchState
        2. 返回 m2(y, c)。
      4. 返回 m1(x, d)。
  2. 否则:
    1. 断言directionbackward
    2. 返回一个新 Matcher,参数 (x, c),捕获 m1m2,调用时:
      1. 断言xMatchState
      2. 断言cMatcherContinuation
      3. d 为一个新 MatcherContinuation,参数 (y),捕获 cm1,调用时:
        1. 断言yMatchState
        2. 返回 m1(y, c)。
      4. 返回 m2(x, d)。

22.2.2.4 运行时语义:CompileAssertion

语法定向操作 CompileAssertion 接收参数 rerRegExp Record),返回一个 Matcher

注 1

本节在 B.1.2.6 中有补充。

在以下产生式中分段定义:

Assertion :: ^
  1. 返回一个新 Matcher,参数 (x, c),捕获 rer,调用时:
    1. 断言xMatchState
    2. 断言cMatcherContinuation
    3. Input = x.[[Input]]
    4. e = x.[[EndIndex]]
    5. 如果 e = 0,或 rer.[[Multiline]]trueInput[e - 1] 匹配 LineTerminator,则:
      1. 返回 c(x)。
    6. 返回 failure
注 2

即使正则表达式使用 y 标志,^ 也只会在 Input 开头或(若 rer.[[Multiline]]true)行首匹配。

Assertion :: $
  1. 返回一个新 Matcher,参数 (x, c),捕获 rer,调用时:
    1. 断言xMatchState
    2. 断言cMatcherContinuation
    3. Input = x.[[Input]]
    4. e = x.[[EndIndex]]
    5. InputLength = Input 的元素数量。
    6. 如果 e = InputLength,或 rer.[[Multiline]]trueInput[e] 匹配 LineTerminator,则:
      1. 返回 c(x)。
    7. 返回 failure
Assertion :: \b
  1. 返回一个新 Matcher,参数 (x, c),捕获 rer,调用时:
    1. 断言xMatchState
    2. 断言cMatcherContinuation
    3. Input = x.[[Input]]
    4. e = x.[[EndIndex]]
    5. a = IsWordChar(rer, Input, e - 1)。
    6. b = IsWordChar(rer, Input, e)。
    7. 如果 atruebfalse,或 afalsebtrue,返回 c(x)。
    8. 返回 failure
Assertion :: \B
  1. 返回一个新 Matcher,参数 (x, c),捕获 rer,调用时:
    1. 断言xMatchState
    2. 断言cMatcherContinuation
    3. Input = x.[[Input]]
    4. e = x.[[EndIndex]]
    5. a = IsWordChar(rer, Input, e - 1)。
    6. b = IsWordChar(rer, Input, e)。
    7. 如果 ab 同为 true 或同为 false,返回 c(x)。
    8. 返回 failure
Assertion :: (?= Disjunction )
  1. mCompileSubpattern of Disjunction,参数为 rerforward
  2. 返回一个新 Matcher,参数 (x, c),捕获 m,调用时:
    1. 断言xMatchState
    2. 断言cMatcherContinuation
    3. d 为一个新 MatcherContinuation,参数 (y),不捕获内容,调用时:
      1. 断言yMatchState
      2. 返回 y
    4. rm(x, d)。
    5. rfailure,返回 failure
    6. 断言rMatchState
    7. cap = r.[[Captures]]
    8. Input = x.[[Input]]
    9. xe = x.[[EndIndex]]
    10. zMatchState { [[Input]]: Input, [[EndIndex]]: xe, [[Captures]]: cap }。
    11. 返回 c(z)。
注 3

形式 (?= Disjunction ) 表示零宽度正向先行断言。其内部模式需在当前位置匹配成功,但当前位置不会推进。lookahead 内部无回溯。

Assertion :: (?! Disjunction )
  1. mCompileSubpattern of Disjunction,参数为 rerforward
  2. 返回一个新 Matcher,参数 (x, c),捕获 m,调用时:
    1. 断言xMatchState
    2. 断言cMatcherContinuation
    3. d 为一个新 MatcherContinuation,参数 (y),不捕获内容,调用时:
      1. 断言yMatchState
      2. 返回 y
    4. rm(x, d)。
    5. rfailure,返回 failure
    6. 返回 c(x)。
注 4

形式 (?! Disjunction ) 表示零宽度负向先行断言。其内部模式需在当前位置匹配失败。

Assertion :: (?<= Disjunction )
  1. mCompileSubpattern of Disjunction,参数为 rerbackward
  2. 返回一个新 Matcher,参数 (x, c),捕获 m,调用时:
    1. 断言xMatchState
    2. 断言cMatcherContinuation
    3. d 为一个新 MatcherContinuation,参数 (y),不捕获内容,调用时:
      1. 断言yMatchState
      2. 返回 y
    4. rm(x, d)。
    5. rfailure,返回 failure
    6. 断言rMatchState
    7. cap = r.[[Captures]]
    8. Input = x.[[Input]]
    9. xe = x.[[EndIndex]]
    10. zMatchState { [[Input]]: Input, [[EndIndex]]: xe, [[Captures]]: cap }。
    11. 返回 c(z)。
Assertion :: (?<! Disjunction )
  1. mCompileSubpattern of Disjunction,参数为 rerbackward
  2. 返回一个新 Matcher,参数 (x, c),捕获 m,调用时:
    1. 断言xMatchState
    2. 断言cMatcherContinuation
    3. d 为一个新 MatcherContinuation,参数 (y),不捕获内容,调用时:
      1. 断言yMatchState
      2. 返回 y
    4. rm(x, d)。
    5. rfailure,返回 failure
    6. 返回 c(x)。

22.2.2.4.1 IsWordChar (rer, Input, e)

抽象操作 IsWordChar 接收参数 rerRegExp Record)、Input(字符 List)、e整数),返回布尔值。调用时执行以下步骤:

  1. InputLength = Input 的元素数量。
  2. 如果 e = -1 或 e = InputLength,返回 false
  3. c = Input[e]。
  4. 如果 WordCharacters(rer) 包含 c,返回 true
  5. 返回 false

22.2.2.5 运行时语义:CompileQuantifier

语法定向操作 CompileQuantifier 无参数,返回一个包含字段 [[Min]](非负 整数)、[[Max]](非负 整数 或 +∞)、[[Greedy]](布尔值)的 Record。在以下产生式中分段定义:

Quantifier :: QuantifierPrefix
  1. qpCompileQuantifierPrefix of QuantifierPrefix
  2. 返回 Record { [[Min]]: qp.[[Min]], [[Max]]: qp.[[Max]], [[Greedy]]: true }。
Quantifier :: QuantifierPrefix ?
  1. qpCompileQuantifierPrefix of QuantifierPrefix
  2. 返回 Record { [[Min]]: qp.[[Min]], [[Max]]: qp.[[Max]], [[Greedy]]: false }。

22.2.2.6 运行时语义:CompileQuantifierPrefix

语法定向操作 CompileQuantifierPrefix 无参数,返回包含 [[Min]](非负 整数)、[[Max]](非负 整数 或 +∞)字段的 Record。在以下产生式中分段定义:

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 运行时语义:CompileAtom

语法定向操作 CompileAtom 接收参数 rerRegExp Record)和 directionforwardbackward),返回 Matcher

注 1

本节在 B.1.2.7 中有补充。

在以下产生式中分段定义:

Atom :: PatternCharacter
  1. chPatternCharacter 匹配的字符。
  2. A 为仅包含字符 ch 的单元素 CharSet
  3. 返回 CharacterSetMatcher(rer, A, false, direction)。
Atom :: .
  1. AAllCharacters(rer)。
  2. 如果 rer.[[DotAll]] 不为 true,则:
    1. A 中移除所有 LineTerminator 产生式右侧的码点对应的字符。
  3. 返回 CharacterSetMatcher(rer, A, false, direction)。
Atom :: CharacterClass
  1. ccCompileCharacterClass of CharacterClass,参数为 rer
  2. cs = cc.[[CharSet]]
  3. 如果 rer.[[UnicodeSets]]false,或 cs 的所有 CharSetElement 都是单字符(包括 cs 为空),则返回 CharacterSetMatcher(rer, cs, cc.[[Invert]], direction)。
  4. 断言cc.[[Invert]]false
  5. lmMatchers 的空 List
  6. 对于 cs 中每个包含多个字符的 CharSetElement s(按长度降序遍历),执行:
    1. cs2 为仅包含 s 最后一个码点的单元素 CharSet
    2. m2CharacterSetMatcher(rer, cs2, false, direction)。
    3. 对于 s 中每个码点 c1(从倒数第二个码点开始反向遍历),执行:
      1. cs1 为仅包含 c1 的单元素 CharSet
      2. m1CharacterSetMatcher(rer, cs1, false, direction)。
      3. m2 = MatchSequence(m1, m2, direction)。
    4. m2 添加到 lm
  7. singlescs 中所有单字符 CharSetElement 组成的 CharSet
  8. CharacterSetMatcher(rer, singles, false, direction) 添加到 lm
  9. 如果 cs 包含空序列,则将 EmptyMatcher() 添加到 lm
  10. m2lm 的最后一个 Matcher
  11. 对于 lm 中每个 Matcher m1(从倒数第二个元素开始反向遍历),执行:
    1. m2 = MatchTwoAlternatives(m1, m2)。
  12. 返回 m2
Atom :: ( GroupSpecifieropt Disjunction )
  1. mCompileSubpattern of Disjunction,参数为 rerdirection
  2. parenIndex = CountLeftCapturingParensBefore(Atom)。
  3. 返回一个新 Matcher,参数 (x, c),捕获 directionmparenIndex,调用时:
    1. 断言xMatchState
    2. 断言cMatcherContinuation
    3. d 为一个新 MatcherContinuation,参数 (y),捕获 xcdirectionparenIndex,调用时:
      1. 断言yMatchState
      2. capy.[[Captures]] 的副本。
      3. Input = x.[[Input]]
      4. xe = x.[[EndIndex]]
      5. ye = y.[[EndIndex]]
      6. 如果 directionforward,则:
        1. 断言xeye
        2. rCaptureRange { [[StartIndex]]: xe, [[EndIndex]]: ye }。
      7. 否则:
        1. 断言directionbackward
        2. 断言yexe
        3. rCaptureRange { [[StartIndex]]: ye, [[EndIndex]]: xe }。
      8. 设置 cap[parenIndex + 1] = r
      9. zMatchState { [[Input]]: Input, [[EndIndex]]: ye, [[Captures]]: cap }。
      10. 返回 c(z)。
    4. 返回 m(x, d)。
注 2

形如 ( Disjunction ) 的括号既用于分组,也用于保存匹配结果。可以通过反向引用、替换字符串或结果数组使用该结果。用 (?: ... ) 可禁用捕获行为。

Atom :: (? RegularExpressionModifiers : Disjunction )
  1. addModifierssource text matched by RegularExpressionModifiers
  2. removeModifiers 为空字符串。
  3. modifiedRer = UpdateModifiers(rer, CodePointsToString(addModifiers), removeModifiers)。
  4. 返回 CompileSubpattern of Disjunction,参数为 modifiedRerdirection
Atom :: (? RegularExpressionModifiers - RegularExpressionModifiers : Disjunction )
  1. addModifierssource text matched by 第一个 RegularExpressionModifiers
  2. removeModifierssource text matched by 第二个 RegularExpressionModifiers
  3. modifiedRer = UpdateModifiers(rer, CodePointsToString(addModifiers), CodePointsToString(removeModifiers))。
  4. 返回 CompileSubpattern of Disjunction,参数为 modifiedRerdirection
AtomEscape :: DecimalEscape
  1. nCapturingGroupNumber of DecimalEscape
  2. 断言nrer.[[CapturingGroupsCount]]
  3. 返回 BackreferenceMatcher(rer, « n », direction)。
注 3

形如 \ 后跟非零十进制数字 n 的转义序列,匹配第 n 个捕获括号的结果。括号数不足 n 是错误。若 n 个括号有但第 n 个未捕获内容,则反向引用总是成功。

AtomEscape :: CharacterEscape
  1. cvCharacterValue of CharacterEscape
  2. ch 为字符值为 cv 的字符。
  3. A 为仅包含字符 ch 的单元素 CharSet
  4. 返回 CharacterSetMatcher(rer, A, false, direction)。
AtomEscape :: CharacterClassEscape
  1. csCompileToCharSet of CharacterClassEscape,参数为 rer
  2. 如果 rer.[[UnicodeSets]]false,或 cs 的所有 CharSetElement 都是单字符(包括 cs 为空),则返回 CharacterSetMatcher(rer, cs, false, direction)。
  3. lmMatchers 的空 List
  4. 对于 cs 中每个包含多个字符的 CharSetElement s(按长度降序遍历),执行:
    1. cs2 为仅包含 s 最后一个码点的单元素 CharSet
    2. m2CharacterSetMatcher(rer, cs2, false, direction)。
    3. 对于 s 中每个码点 c1(从倒数第二个码点开始反向遍历),执行:
      1. cs1 为仅包含 c1 的单元素 CharSet
      2. m1CharacterSetMatcher(rer, cs1, false, direction)。
      3. m2 = MatchSequence(m1, m2, direction)。
    4. m2 添加到 lm
  5. singlescs 中所有单字符 CharSetElement 组成的 CharSet
  6. CharacterSetMatcher(rer, singles, false, direction) 添加到 lm
  7. 如果 cs 包含空序列,则将 EmptyMatcher() 添加到 lm
  8. m2lm 的最后一个 Matcher
  9. 对于 lm 中每个 Matcher m1(从倒数第二个元素开始反向遍历),执行:
    1. m2 = MatchTwoAlternatives(m1, m2)。
  10. 返回 m2
AtomEscape :: k GroupName
  1. matchingGroupSpecifiersGroupSpecifiersThatMatch(GroupName)。
  2. parenIndices 为一个新的空 List
  3. 对于 matchingGroupSpecifiers 中的每一个 GroupSpecifier groupSpecifier,执行:
    1. parenIndex = CountLeftCapturingParensBefore(groupSpecifier)。
    2. parenIndex 添加到 parenIndices
  4. 返回 BackreferenceMatcher(rer, parenIndices, direction)。

22.2.2.7.1 CharacterSetMatcher (rer, A, invert, direction)

抽象操作 CharacterSetMatcher 接收参数 rerRegExp Record)、ACharSet)、invert(布尔值)、directionforwardbackward),返回 Matcher。调用时执行如下步骤:

  1. 如果 rer.[[UnicodeSets]]true,则:
    1. 断言invertfalse
    2. 断言A 的每个 CharSetElement 都是单字符。
  2. 返回一个新 Matcher,参数 (x, c),捕获 rerAinvertdirection,调用时:
    1. 断言xMatchState
    2. 断言cMatcherContinuation
    3. Input = x.[[Input]]
    4. e = x.[[EndIndex]]
    5. directionforward,令 f = e + 1。
    6. 否则,令 f = e - 1。
    7. InputLength = Input 的元素数量。
    8. f < 0 或 f > InputLength,返回 failure
    9. index = min(e, f)。
    10. ch = Input[index]。
    11. cc = Canonicalize(rer, ch)。
    12. 如果存在 A 中仅含字符 aCharSetElement,且 Canonicalize(rer, a) 等于 cc,则 found = true,否则 found = false
    13. invertfalsefoundfalse,返回 failure
    14. inverttruefoundtrue,返回 failure
    15. cap = x.[[Captures]]
    16. y = MatchState { [[Input]]: Input, [[EndIndex]]: f, [[Captures]]: cap }。
    17. 返回 c(y)。

22.2.2.7.2 BackreferenceMatcher (rer, ns, direction)

抽象操作 BackreferenceMatcher 接收参数 rerRegExp Record)、ns(正 整数List)、directionforwardbackward),返回 Matcher。调用时执行如下步骤:

  1. 返回一个新 Matcher,参数 (x, c),捕获 rernsdirection,调用时:
    1. 断言xMatchState
    2. 断言cMatcherContinuation
    3. Input = x.[[Input]]
    4. cap = x.[[Captures]]
    5. r = undefined
    6. 对于 ns 中的每个 整数 n,执行:
      1. cap[n] 非 undefined,则:
        1. 断言rundefined
        2. r = cap[n]。
    7. rundefined,返回 c(x)。
    8. e = x.[[EndIndex]]
    9. rs = r.[[StartIndex]]
    10. re = r.[[EndIndex]]
    11. len = re - rs
    12. directionforward,令 f = e + len
    13. 否则,令 f = e - len
    14. InputLength = Input 的元素数量。
    15. f < 0 或 f > InputLength,返回 failure
    16. g = min(e, f)。
    17. 若存在 0(含)到 len(不含)间的 整数 i,使得 Canonicalize(rer, Input[rs+i]) ≠ Canonicalize(rer, Input[g+i]),返回 failure
    18. y = MatchState { [[Input]]: Input, [[EndIndex]]: f, [[Captures]]: cap }。
    19. 返回 c(y)。

22.2.2.7.3 Canonicalize (rer, ch)

抽象操作 Canonicalize 接收参数 rerRegExp Record)、ch(字符),返回一个字符。调用时执行如下步骤:

  1. HasEitherUnicodeFlag(rer) 为 truerer.[[IgnoreCase]]true,则:
    1. CaseFolding.txt 提供了 ch 的简单或通用大小写折叠映射,则返回应用该映射后的 ch
    2. 返回 ch
  2. rer.[[IgnoreCase]]false,返回 ch
  3. 断言ch 是 UTF-16 码元。
  4. cpch 的数值对应的码点。
  5. u 为根据 Unicode 默认大小写转换算法 toUppercase(« cp »)。
  6. uStr = CodePointsToString(u)。
  7. uStr 长度 ≠ 1,返回 ch
  8. cu = uStr 的唯一码元。
  9. ch 数值 ≥ 128 且 cu 数值 < 128,返回 ch
  10. 返回 cu

HasEitherUnicodeFlag(rer) 为 true 且大小写不敏感时,所有字符都用 Unicode 标准的简单大小写折叠映射进行大小写折叠再比较。简单映射总是映射为单一码点(如 ß 不会变为 ssSS)。但部分非Basic Latin字符可映射为Basic Latin内字符,如 ſ 会折叠为 s 会折叠为 k,因此如 /[a-z]/ui 可匹配这些字符。

HasEitherUnicodeFlag(rer) 为 false 时,映射基于 Unicode 默认大小写转换算法的 toUppercase,而不是 toCasefold,存在差异。例如 (U+2126)用 toUppercase 仍为自身,但 toCasefold 会变为 ω。所以 "\u2126" 能被 /[ω]/ui 匹配,不能被 /[ω]/i 匹配。非Basic Latin的字符不会映射到Basic Latin内字符。

22.2.2.7.4 UpdateModifiers (rer, add, remove)

抽象操作 UpdateModifiers 接收参数 rerRegExp Record)、add(字符串)、remove(字符串),返回一个 RegExp Record。调用时执行如下步骤:

  1. 断言addremove 没有公共元素。
  2. ignoreCase = rer.[[IgnoreCase]]
  3. multiline = rer.[[Multiline]]
  4. dotAll = rer.[[DotAll]]
  5. unicode = rer.[[Unicode]]
  6. unicodeSets = rer.[[UnicodeSets]]
  7. capturingGroupsCount = rer.[[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 运行时语义:CompileCharacterClass

语法定向操作 CompileCharacterClass 接收参数 rerRegExp Record),返回含字段 [[CharSet]]CharSet)和 [[Invert]](布尔值)的 Record。在以下产生式中分段定义:

CharacterClass :: [ ClassContents ]
  1. ACompileToCharSet of ClassContents,参数为 rer
  2. 返回 Record { [[CharSet]]: A, [[Invert]]: false }。
CharacterClass :: [^ ClassContents ]
  1. ACompileToCharSet of ClassContents,参数为 rer
  2. 如果 rer.[[UnicodeSets]]true,则:
    1. 返回 Record { [[CharSet]]: CharacterComplement(rer, A), [[Invert]]: false }。
  3. 返回 Record { [[CharSet]]: A, [[Invert]]: true }。

22.2.2.9 运行时语义:CompileToCharSet

语法定向操作 CompileToCharSet 接收参数 rerRegExp Record),返回 CharSet

注 1

本节在 B.1.2.8 中有补充。

在以下产生式中分段定义:

ClassContents :: [empty]
  1. 返回空 CharSet
NonemptyClassRanges :: ClassAtom NonemptyClassRangesNoDash
  1. A = CompileToCharSet of ClassAtom,参数为 rer
  2. B = CompileToCharSet of NonemptyClassRangesNoDash,参数为 rer
  3. 返回 AB 的并集。
NonemptyClassRanges :: ClassAtom - ClassAtom ClassContents
  1. A = CompileToCharSet of 第一个 ClassAtom,参数为 rer
  2. B = CompileToCharSet of 第二个 ClassAtom,参数为 rer
  3. C = CompileToCharSet of ClassContents,参数为 rer
  4. D = CharacterRange(A, B)。
  5. 返回 DC 的并集。
NonemptyClassRangesNoDash :: ClassAtomNoDash NonemptyClassRangesNoDash
  1. A = CompileToCharSet of ClassAtomNoDash,参数为 rer
  2. B = CompileToCharSet of NonemptyClassRangesNoDash,参数为 rer
  3. 返回 AB 的并集。
NonemptyClassRangesNoDash :: ClassAtomNoDash - ClassAtom ClassContents
  1. A = CompileToCharSet of ClassAtomNoDash,参数为 rer
  2. B = CompileToCharSet of ClassAtom,参数为 rer
  3. C = CompileToCharSet of ClassContents,参数为 rer
  4. D = CharacterRange(A, B)。
  5. 返回 DC 的并集。
注 2

ClassContents 可扩展为单个 ClassAtom 或由两个 ClassAtom 用连字符分隔的区间。后者情况下,ClassContents 包含两个 ClassAtom(含)之间的所有字符;如其中任一不是单字符(如 \w),或左端大于右端,则为错误。

注 3

即使忽略大小写,区间两端字符的大小写在区间确定时依然重要。例如 /[E-F]/i 只匹配 E, F, e, f,而 /[E-f]/i 匹配 Basic Latin 字母及 [, \, ], ^, _, `

注 4

- 可被当作字面量或区间。若在 ClassContents 首尾、区间端点、或区间后,视为字面量。

ClassAtom :: -
  1. 返回仅包含字符 - U+002D (HYPHEN-MINUS) 的 CharSet
ClassAtomNoDash :: SourceCharacter 但不能是 \]-
  1. 返回仅包含 SourceCharacter 匹配字符的 CharSet
ClassEscape :: b - CharacterEscape
  1. cv 为本 ClassEscapeCharacterValue
  2. c 为字符值为 cv 的字符。
  3. 返回仅包含字符 cCharSet
注 5

ClassAtom 可使用正则中允许的转义序列,除 \b\B 和反向引用外。类中 \b 表示退格符,\B 和反向引用会报错。在 ClassAtom 使用反向引用是错误的。

CharacterClassEscape :: d
  1. 返回包含字符 09 的十元素 CharSet
CharacterClassEscape :: D
  1. SCharacterClassEscape:: d 返回的 CharSet
  2. 返回 CharacterComplement(rer, S)。
CharacterClassEscape :: s
  1. 返回包含 WhiteSpaceLineTerminator 产生式右侧所有码点的 CharSet
CharacterClassEscape :: S
  1. SCharacterClassEscape:: s 返回的 CharSet
  2. 返回 CharacterComplement(rer, S)。
CharacterClassEscape :: w
  1. 返回 MaybeSimpleCaseFolding(rer, WordCharacters(rer))。
CharacterClassEscape :: W
  1. SCharacterClassEscape:: w 返回的 CharSet
  2. 返回 CharacterComplement(rer, S)。
CharacterClassEscape :: p{ UnicodePropertyValueExpression }
  1. 返回 CompileToCharSet of UnicodePropertyValueExpression,参数为 rer
CharacterClassEscape :: P{ UnicodePropertyValueExpression }
  1. SCompileToCharSet of UnicodePropertyValueExpression,参数为 rer
  2. 断言S 仅包含单一码点。
  3. 返回 CharacterComplement(rer, S)。
UnicodePropertyValueExpression :: UnicodePropertyName = UnicodePropertyValue
  1. pssource text matched by UnicodePropertyName
  2. pUnicodeMatchProperty(rer, ps)。
  3. 断言p表 69Property name and aliases” 列中列出的 Unicode 属性名或属性别名。
  4. vssource text matched by UnicodePropertyValue
  5. vUnicodeMatchPropertyValue(p, vs)。
  6. A 为包含所有在字符数据库定义中具有属性 p 且值为 v 的 Unicode 码点的 CharSet
  7. 返回 MaybeSimpleCaseFolding(rer, A)。
UnicodePropertyValueExpression :: LoneUnicodePropertyNameOrValue
  1. ssource text matched by LoneUnicodePropertyNameOrValue
  2. 如果 UnicodeMatchPropertyValue(General_Category, s) 是 PropertyValueAliases.txt 中 General_Category (gc) 属性的 Unicode 属性值或属性值别名,则:
    1. 返回包含所有字符数据库定义中属性 “General_Category” 值为 s 的 Unicode 码点的 CharSet
  3. pUnicodeMatchProperty(rer, s)。
  4. 断言p表 70 “Property name and aliases” 列中列出的二值 Unicode 属性或二值属性别名,或 表 71 “Property name” 列中列出的字符串的二值 Unicode 属性。
  5. A 为包含所有字符数据库定义中属性 p 值为 “True” 的 CharSetElements 的 CharSet
  6. 返回 MaybeSimpleCaseFolding(rer, A)。
ClassUnion :: ClassSetRange ClassUnionopt
  1. ACompileToCharSet of ClassSetRange,参数为 rer
  2. 如果 ClassUnion 存在,则:
    1. BCompileToCharSet of ClassUnion,参数为 rer
    2. 返回 CharSets AB 的并集。
  3. 返回 A
ClassUnion :: ClassSetOperand ClassUnionopt
  1. ACompileToCharSet of ClassSetOperand,参数为 rer
  2. 如果 ClassUnion 存在,则:
    1. BCompileToCharSet of ClassUnion,参数为 rer
    2. 返回 CharSets AB 的并集。
  3. 返回 A
ClassIntersection :: ClassSetOperand && ClassSetOperand
  1. ACompileToCharSet of 第一个 ClassSetOperand,参数为 rer
  2. BCompileToCharSet of 第二个 ClassSetOperand,参数为 rer
  3. 返回 CharSets AB 的交集。
ClassIntersection :: ClassIntersection && ClassSetOperand
  1. ACompileToCharSet of ClassIntersection,参数为 rer
  2. BCompileToCharSet of ClassSetOperand,参数为 rer
  3. 返回 CharSets AB 的交集。
ClassSubtraction :: ClassSetOperand -- ClassSetOperand
  1. A 为第一个 CompileToCharSet of ClassSetOperand,参数为 rer
  2. B 为第二个 CompileToCharSet of ClassSetOperand,参数为 rer
  3. 返回包含所有属于 A 但不属于 B 的 CharSetElements 的 CharSet
ClassSubtraction :: ClassSubtraction -- ClassSetOperand
  1. ACompileToCharSet of ClassSubtraction,参数为 rer
  2. BCompileToCharSet of ClassSetOperand,参数为 rer
  3. 返回包含所有属于 A 但不属于 B 的 CharSetElements 的 CharSet
ClassSetRange :: ClassSetCharacter - ClassSetCharacter
  1. A 为第一个 CompileToCharSet of ClassSetCharacter,参数为 rer
  2. B 为第二个 CompileToCharSet of ClassSetCharacter,参数为 rer
  3. 返回 MaybeSimpleCaseFolding(rer, CharacterRange(A, B))。
注 6

结果通常包含两个或更多区间。当 UnicodeSets 为 true 且 IgnoreCase 为 true 时,MaybeSimpleCaseFolding(rer, [Ā-č]) 只包含该区间中奇数码点。

ClassSetOperand :: ClassSetCharacter
  1. ACompileToCharSet of ClassSetCharacter,参数为 rer
  2. 返回 MaybeSimpleCaseFolding(rer, A)。
ClassSetOperand :: ClassStringDisjunction
  1. ACompileToCharSet of ClassStringDisjunction,参数为 rer
  2. 返回 MaybeSimpleCaseFolding(rer, A)。
ClassSetOperand :: NestedClass
  1. 返回 CompileToCharSet of NestedClass,参数为 rer
NestedClass :: [ ClassContents ]
  1. 返回 CompileToCharSet of ClassContents,参数为 rer
NestedClass :: [^ ClassContents ]
  1. ACompileToCharSet of ClassContents,参数为 rer
  2. 返回 CharacterComplement(rer, A)。
NestedClass :: \ CharacterClassEscape
  1. 返回 CompileToCharSet of CharacterClassEscape,参数为 rer
ClassStringDisjunction :: \q{ ClassStringDisjunctionContents }
  1. 返回 CompileToCharSet of ClassStringDisjunctionContents,参数为 rer
ClassStringDisjunctionContents :: ClassString
  1. sCompileClassSetString of ClassString,参数为 rer
  2. 返回仅包含字符串 sCharSet
ClassStringDisjunctionContents :: ClassString | ClassStringDisjunctionContents
  1. sCompileClassSetString of ClassString,参数为 rer
  2. A 为仅包含字符串 sCharSet
  3. BCompileToCharSet of ClassStringDisjunctionContents,参数为 rer
  4. 返回 CharSets AB 的并集。
ClassSetCharacter :: SourceCharacter 但不能是 ClassSetSyntaxCharacter \ CharacterEscape \ ClassSetReservedPunctuator
  1. cv 为本 ClassSetCharacterCharacterValue
  2. c 为字符值为 cv 的字符。
  3. 返回仅包含字符 cCharSet
ClassSetCharacter :: \b
  1. 返回仅包含字符 U+0008 (BACKSPACE) 的 CharSet

22.2.2.9.1 CharacterRange (A, B)

抽象操作 CharacterRange 接收参数 ACharSet)和 BCharSet),返回 CharSet。调用时执行如下步骤:

  1. 断言AB 各自仅包含一个字符。
  2. aA 中的唯一字符。
  3. bB 中的唯一字符。
  4. i 为字符 a 的字符值。
  5. j 为字符 b 的字符值。
  6. 断言ij
  7. 返回包含所有字符值在 ij(含)区间的字符的 CharSet

22.2.2.9.2 HasEitherUnicodeFlag (rer)

抽象操作 HasEitherUnicodeFlag 接收参数 rerRegExp Record),返回布尔值。调用时执行如下步骤:

  1. 如果 rer.[[Unicode]]truerer.[[UnicodeSets]]true,则:
    1. 返回 true
  2. 返回 false

22.2.2.9.3 WordCharacters (rer)

抽象操作 WordCharacters 接收参数 rerRegExp Record),返回 CharSet。返回正则表达式中 \b\B\w\W 所认为的“单词字符”。调用时执行如下步骤:

  1. basicWordChars 为包含所有 ASCII 单词字符CharSet
  2. extraWordChars 为包含所有字符 cCharSet,其中 c 不在 basicWordChars 内,但 Canonicalize(rer, c) 在 basicWordChars 内。
  3. 断言:除非 HasEitherUnicodeFlag(rer) 为 truerer.[[IgnoreCase]]true,否则 extraWordChars 为空。
  4. 返回 basicWordCharsextraWordChars 的并集。

22.2.2.9.4 AllCharacters (rer)

抽象操作 AllCharacters 接收参数 rerRegExp Record),返回 CharSet。根据正则表达式标志返回“所有字符”的集合。调用时执行如下步骤:

  1. 如果 rer.[[UnicodeSets]]truerer.[[IgnoreCase]]true
    1. 返回包含所有无 简单大小写折叠映射(即 scf(c)=c)的 Unicode 码点 cCharSet
  2. 否则若 HasEitherUnicodeFlag(rer) 为 true
    1. 返回包含所有码点值的 CharSet
  3. 否则:
    1. 返回包含所有码元值的 CharSet

22.2.2.9.5 MaybeSimpleCaseFolding (rer, A)

抽象操作 MaybeSimpleCaseFolding 接收参数 rerRegExp Record)、ACharSet),返回 CharSet。如果 rer.[[UnicodeSets]]falserer.[[IgnoreCase]]false,则返回 A。否则,使用 Unicode Character Database 中 简单大小写折叠scf(cp))的定义,对 A 的每个 CharSetElement 的每个码点字符做映射,并返回结果 CharSet。调用时执行如下步骤:

  1. 如果 rer.[[UnicodeSets]]falserer.[[IgnoreCase]]false,返回 A
  2. B 为一个新的空 CharSet
  3. A 的每一个 CharSetElement s,执行:
    1. t 为空字符序列。
    2. s 中每一个码点 cp,执行:
      1. scf(cp) 附加到 t
    3. t 添加到 B
  4. 返回 B

22.2.2.9.6 CharacterComplement (rer, S)

抽象操作 CharacterComplement 接收参数 rerRegExp Record)、SCharSet),返回 CharSet。调用时执行如下步骤:

  1. A = AllCharacters(rer)。
  2. 返回包含所有属于 A 但不属于 S 的 CharSetElements 的 CharSet

22.2.2.9.7 UnicodeMatchProperty (rer, p)

抽象操作 UnicodeMatchProperty 接收参数 rerRegExp Record)、pECMAScript 源文本),返回 Unicode 属性名。调用时执行如下步骤:

  1. 如果 rer.[[UnicodeSets]]truep表 71 “Property name” 列中的 Unicode 属性名,则:
    1. 返回 Unicode 码点 p 组成的 List
  2. 断言p表 69、“Property name and aliases” 或 表 70 中的 Unicode 属性名或属性别名。
  3. c 为该行 “Canonical property name” 列中给出的 p 的规范属性名。
  4. 返回 Unicode 码点 c 组成的 List

实现必须支持 表 69表 70表 71 中列出的 Unicode 属性名和别名。为保证互操作性,实现不得支持其他属性名或别名。

注 1

例如,Script_Extensions属性名)和 scx(属性别名)有效,但 script_extensionsScx 无效。

注 2

这些属性集合是 UTS18 RL1.2 要求的超集。

注 3

这些表中的拼写(包括大小写)与 Unicode Character Database 文件 PropertyAliases.txt 保持一致。该文件中的拼写是 保证稳定的

表 69:非二值(非布尔型)Unicode 属性别名及其规范属性名
属性名 及别名 规范 属性名
General_Category General_Category
gc
Script Script
sc
Script_Extensions Script_Extensions
scx
表 70:二值(布尔型)Unicode 属性别名及其规范属性名
属性名 及别名 规范 属性名
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
表 71:字符串的二值(布尔型)Unicode 属性
属性名
Basic_Emoji(基础表情符号)
Emoji_Keycap_Sequence(表情符号按键序列)
RGI_Emoji_Modifier_Sequence(RGI表情符号修饰符序列)
RGI_Emoji_Flag_Sequence(RGI表情符号旗帜序列)
RGI_Emoji_Tag_Sequence(RGI表情符号标签序列)
RGI_Emoji_ZWJ_Sequence(RGI表情符号ZWJ序列)
RGI_Emoji(RGI表情符号)

22.2.2.9.8 UnicodeMatchPropertyValue (p, v)

抽象操作 UnicodeMatchPropertyValue 接收参数 pECMAScript 源文本)和 vECMAScript 源文本),返回一个 Unicode 属性值。调用时执行如下步骤:

  1. 断言p表 69“规范属性名”列中列出的规范、无别名的 Unicode 属性名
  2. 断言vPropertyValueAliases.txt 中针对属性 p 列出的属性值或属性值别名。
  3. valuev 的规范属性值,其值为对应行“规范属性值”列中给出的内容。
  4. 返回 Unicode 码点 value 组成的 List

实现必须支持 表 69 中属性对应的 PropertyValueAliases.txt 文件中列出的 Unicode 属性值和属性值别名。为保证互操作性,实现不得支持其他属性值或属性值别名。

注 1

例如,XpeoOld_Persian 是有效的 Script_Extensions 属性值,但 xpeoOld Persian 无效。

注 2

此算法不同于 UAX44 中列出的符号值匹配规则:不会忽略大小写、空白、U+002D(连字符)和 U+005F(下划线),并且不支持 Is 前缀。

22.2.2.10 运行时语义:CompileClassSetString

语法定向操作 CompileClassSetString 接收参数 rerRegExp Record),返回一个字符序列。该操作按以下产生式分段定义:

ClassString :: [empty]
  1. 返回空的字符序列。
ClassString :: NonEmptyClassString
  1. 返回 CompileClassSetString of NonEmptyClassString,参数为 rer
NonEmptyClassString :: ClassSetCharacter NonEmptyClassString opt
  1. csCompileToCharSet of ClassSetCharacter,参数为 rer
  2. s1cs 的唯一 CharSetElement 的字符序列。
  3. 如果 NonEmptyClassString 存在,则:
    1. s2CompileClassSetString of NonEmptyClassString,参数为 rer
    2. 返回 s1s2 的拼接。
  4. 返回 s1

22.2.3 正则表达式创建的抽象操作

22.2.3.1 RegExpCreate ( P, F )

抽象操作 RegExpCreate 接收参数 P(一个 ECMAScript 语言值)和 F(字符串或 undefined),返回 包含对象的正常完成,或 抛出完成。调用时执行如下步骤:

  1. obj 为 ! RegExpAlloc(%RegExp%)。
  2. 返回 ? RegExpInitialize(obj, P, F)。

22.2.3.2 RegExpAlloc ( newTarget )

抽象操作 RegExpAlloc 接收参数 newTarget构造函数),返回 包含对象的正常完成,或 抛出完成。调用时执行如下步骤:

  1. obj 为 ? OrdinaryCreateFromConstructor(newTarget, "%RegExp.prototype%", « [[OriginalSource]], [[OriginalFlags]], [[RegExpRecord]], [[RegExpMatcher]] »)。
  2. 执行 ! DefinePropertyOrThrow(obj, "lastIndex", PropertyDescriptor { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  3. 返回 obj

22.2.3.3 RegExpInitialize ( obj, pattern, flags )

抽象操作 RegExpInitialize 接收参数 obj(对象)、patternECMAScript 语言值)、flagsECMAScript 语言值),返回 包含对象的正常完成,或 抛出完成。调用时执行如下步骤:

  1. 如果 patternundefined,令 P 为空字符串。
  2. 否则,令 P 为 ? ToString(pattern)。
  3. 如果 flagsundefined,令 F 为空字符串。
  4. 否则,令 F 为 ? ToString(flags)。
  5. 如果 F 包含除 "d""g""i""m""s""u""v""y" 以外的任何代码单元,或 F 中有任何代码单元出现多次,则抛出 SyntaxError 异常。
  6. 如果 F 包含 "i",令 i = true;否则 i = false
  7. 如果 F 包含 "m",令 m = true;否则 m = false
  8. 如果 F 包含 "s",令 s = true;否则 s = false
  9. 如果 F 包含 "u",令 u = true;否则 u = false
  10. 如果 F 包含 "v",令 v = true;否则 v = false
  11. 如果 utruevtrue,则
    1. patternText = StringToCodePoints(P)。
  12. 否则:
    1. patternText 为将 P 的每个 16 位元素按 Unicode BMP 码点解释的结果。不会对这些元素做 UTF-16 解码。
  13. parseResult = ParsePattern(patternText, u, v)。
  14. 如果 parseResult 是一个非空的 List,且包含 SyntaxError 对象,则抛出 SyntaxError 异常。
  15. 断言parseResult 是一个 Pattern 解析节点
  16. 设置 obj.[[OriginalSource]] = P
  17. 设置 obj.[[OriginalFlags]] = F
  18. capturingGroupsCount = CountLeftCapturingParensWithin(parseResult)。
  19. rerRegExp Record { [[IgnoreCase]]: i, [[Multiline]]: m, [[DotAll]]: s, [[Unicode]]: u, [[UnicodeSets]]: v, [[CapturingGroupsCount]]: capturingGroupsCount }。
  20. 设置 obj.[[RegExpRecord]] = rer
  21. 设置 obj.[[RegExpMatcher]] = CompilePattern of parseResult,参数为 rer
  22. 执行 ? Set(obj, "lastIndex", +0𝔽, true)。
  23. 返回 obj

22.2.3.4 静态语义:ParsePattern (patternText, u, v)

抽象操作 ParsePattern 接收参数 patternText(Unicode码点序列)、u(布尔值)、v(布尔值),返回一个 解析节点,或一个非空的 List(元素为 SyntaxError 对象)。

本节在 B.1.2.9 中有补充说明。

调用时执行如下步骤:

  1. 如果 vtrueutrue
    1. parseResult 为包含一个或多个 SyntaxError 对象的 List
  2. 否则,如果 vtrue
    1. parseResult = ParseText(patternText, Pattern[+UnicodeMode, +UnicodeSetsMode, +NamedCaptureGroups])。
  3. 否则,如果 utrue
    1. parseResult = ParseText(patternText, Pattern[+UnicodeMode, ~UnicodeSetsMode, +NamedCaptureGroups])。
  4. 否则:
    1. parseResult = ParseText(patternText, Pattern[~UnicodeMode, ~UnicodeSetsMode, +NamedCaptureGroups])。
  5. 返回 parseResult

22.2.4 RegExp 构造函数

RegExp 构造函数

  • %RegExp%
  • 全局对象"RegExp" 属性的初始值。
  • 作为 构造函数调用时,会创建并初始化一个新的 RegExp 对象。
  • 当作普通函数而非 构造函数调用时,返回一个新的 RegExp 对象,或者如果唯一参数本身就是 RegExp 对象,则返回该参数本身。
  • 可以作为类定义的 extends 子句的值。子类 构造函数 如果要继承指定的 RegExp 行为,必须包含对 RegExp 构造函数super 调用,以便用必要的内部插槽来创建并初始化子类实例。

22.2.4.1 RegExp ( pattern, flags )

该函数被调用时执行以下步骤:

  1. patternIsRegExp 为 ? IsRegExp(pattern)。
  2. 如果 NewTarget 是 undefined,则
    1. newTarget活动函数对象
    2. 如果 patternIsRegExptrueflagsundefined,则
      1. patternConstructor 为 ? Get(pattern, "constructor")。
      2. 如果 SameValue(newTarget, patternConstructor) 为 true,返回 pattern
  3. 否则,
    1. newTarget 为 NewTarget。
  4. 如果 pattern 是一个对象pattern[[RegExpMatcher]] 内部插槽,则
    1. Ppattern.[[OriginalSource]]
    2. 如果 flagsundefined,令 Fpattern.[[OriginalFlags]]
    3. 否则,令 Fflags
  5. 否则如果 patternIsRegExptrue,则
    1. P 为 ? Get(pattern, "source")。
    2. 如果 flagsundefined,则
      1. F 为 ? Get(pattern, "flags")。
    3. 否则,
      1. Fflags
  6. 否则,
    1. Ppattern
    2. Fflags
  7. O 为 ? RegExpAlloc(newTarget)。
  8. 返回 ? RegExpInitialize(O, P, F)。

如果 pattern 是通过 StringLiteral 传递的,会在该字符串被本函数处理前进行常规的转义序列替换。如果 pattern 必须包含一个转义序列以便被本函数识别,则必须在 StringLiteral 内对所有 U+005C(反斜杠)码点进行转义,以防止它们在形成 StringLiteral 内容时被移除。

22.2.5 RegExp 构造函数的属性

RegExp 构造函数

22.2.5.1 RegExp.escape ( S )

该函数返回 S 的一个副本,其中正则表达式模式中可能具有特殊含义的字符都被替换为等价的转义序列。

调用时执行以下步骤:

  1. 如果 S 不是字符串,抛出 TypeError 异常。
  2. escaped 为空字符串。
  3. cpListStringToCodePoints(S)。
  4. 对于 cpList 中的每个码点 cp,执行
    1. 如果 escaped 为空字符串,且 cp 匹配 十进制数字ASCII 字母, 则
      1. 注:转义首位数字可保证输出对应的模式文本在 \0 字符转义或 十进制转义(如 \1)后仍能匹配 S,不会被解释为前一转义序列的扩展。首位 ASCII 字母的转义同理,适用于 \c 后的情况。
      2. numericValuecp 的数值。
      3. hexNumber::toString(𝔽(numericValue), 16)。
      4. 断言hex 长度为 2。
      5. 设置 escaped 为字符串拼接 0x005C(反斜杠)、"x" 及 hex
    2. 否则,
      1. 设置 escapedescapedEncodeForRegExpEscape(cp) 的字符串拼接。
  5. 返回 escaped

虽然名字相似,EscapeRegExpPatternRegExp.escape 并不执行类似操作。前者用于将模式转义为字符串表示,后者用于将字符串转义为模式内部使用。

22.2.5.1.1 EncodeForRegExpEscape ( cp )

抽象操作 EncodeForRegExpEscape 接收参数 cp(码点),返回一个字符串。返回值即为匹配 cp 的模式 Pattern。如 cp 为空白字符或 ASCII 标点,则返回转义序列。否则,返回 cp 本身的字符串表示。调用时执行如下步骤:

  1. 如果 cp 匹配 SyntaxCharacter 或等于 U+002F(/),则
    1. 返回 0x005C(反斜杠)与 UTF16EncodeCodePoint(cp) 的字符串拼接。
  2. 否则,如果 cp表 67 的“Code Point”列中,则
    1. 返回 0x005C(反斜杠)与该行“ControlEscape”列字符串的字符串拼接。
  3. otherPunctuators 为字符串 ",-=<>#&!%:;@~'`" 与 0x0022(引号)。
  4. toEscapeStringToCodePoints(otherPunctuators)。
  5. 如果 toEscape 包含 cp,或 cp 匹配 WhiteSpaceLineTerminator,或 cp前导代理项尾随代理项数值相同,则
    1. cpNumcp 的数值。
    2. 如果 cpNum ≤ 0xFF,则
      1. hexNumber::toString(𝔽(cpNum), 16)。
      2. 返回 0x005C(反斜杠)、"x" 及 StringPad(hex, 2, "0", start) 的字符串拼接。
    3. escaped 为空字符串。
    4. codeUnitsUTF16EncodeCodePoint(cp)。
    5. 对于 codeUnits 中每个 code unit cu,执行
      1. 设置 escapedescapedUnicodeEscape(cu) 的字符串拼接。
    6. 返回 escaped
  6. 返回 UTF16EncodeCodePoint(cp)。

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]"

RegExp 原型方法通常使用其 this 值的 构造函数 来创建派生对象。但子类 构造函数 可以通过重定义其 %Symbol.species% 属性来覆盖此默认行为。

22.2.6 RegExp 原型对象的属性

RegExp 原型对象

  • %RegExp.prototype%
  • 是一个 普通对象
  • 不是 RegExp 实例,不具有 [[RegExpMatcher]] 内部插槽,也没有 RegExp 实例对象的其他内部插槽。
  • 拥有 [[Prototype]] 内部插槽,其值为 %Object.prototype%

RegExp 原型对象自身没有 "valueOf" 属性,但它从 Object 原型对象 继承了 "valueOf" 属性。

22.2.6.1 RegExp.prototype.constructor

RegExp.prototype.constructor 的初始值为 %RegExp%

22.2.6.2 RegExp.prototype.exec ( string )

该方法在 string 中搜索正则表达式的匹配项,并返回包含匹配结果的数组,若 string 不匹配则返回 null

调用时执行如下步骤:

  1. Rthis 值。
  2. 执行 ? RequireInternalSlot(R, [[RegExpMatcher]])。
  3. S 为 ? ToString(string)。
  4. 返回 ? RegExpBuiltinExec(R, S)。

22.2.6.3 get RegExp.prototype.dotAll

RegExp.prototype.dotAll 是一个 访问器属性,其 set 访问器函数为 undefined。get 访问器函数调用时执行如下步骤:

  1. Rthis 值。
  2. cu 为码元 0x0073(小写字母 s)。
  3. 返回 ? RegExpHasFlag(R, cu)。

22.2.6.4 get RegExp.prototype.flags

RegExp.prototype.flags 是一个 访问器属性,其 set 访问器函数为 undefined。get 访问器函数调用时执行如下步骤:

  1. Rthis 值。
  2. 如果 R 不是对象,抛出 TypeError 异常。
  3. codeUnits 为一个新的空 List
  4. hasIndicesToBoolean(? Get(R, "hasIndices"))。
  5. 如果 hasIndicestrue,将码元 0x0064(小写字母 d)添加到 codeUnits
  6. globalToBoolean(? Get(R, "global"))。
  7. 如果 globaltrue,将码元 0x0067(g)添加到 codeUnits
  8. ignoreCaseToBoolean(? Get(R, "ignoreCase"))。
  9. 如果 ignoreCasetrue,将码元 0x0069(i)添加到 codeUnits
  10. multilineToBoolean(? Get(R, "multiline"))。
  11. 如果 multilinetrue,将码元 0x006D(m)添加到 codeUnits
  12. dotAllToBoolean(? Get(R, "dotAll"))。
  13. 如果 dotAlltrue,将码元 0x0073(s)添加到 codeUnits
  14. unicodeToBoolean(? Get(R, "unicode"))。
  15. 如果 unicodetrue,将码元 0x0075(u)添加到 codeUnits
  16. unicodeSetsToBoolean(? Get(R, "unicodeSets"))。
  17. 如果 unicodeSetstrue,将码元 0x0076(v)添加到 codeUnits
  18. stickyToBoolean(? Get(R, "sticky"))。
  19. 如果 stickytrue,将码元 0x0079(y)添加到 codeUnits
  20. 返回由 List codeUnits 组成的字符串;若 codeUnits 为空,则返回空字符串。

22.2.6.4.1 RegExpHasFlag ( R, codeUnit )

抽象操作 RegExpHasFlag 接收参数 RECMAScript 语言值)和 codeUnit(码元),返回一个 包含布尔值或 undefined 的正常完成,或 抛出完成。调用时执行如下步骤:

  1. 如果 R 不是对象,抛出 TypeError 异常。
  2. 如果 R 没有 [[OriginalFlags]] 内部插槽,则
    1. 如果 SameValue(R, %RegExp.prototype%) 为 true,返回 undefined
    2. 否则,抛出 TypeError 异常。
  3. flagsR.[[OriginalFlags]]
  4. 如果 flags 包含 codeUnit,返回 true
  5. 返回 false

22.2.6.5 get RegExp.prototype.global

RegExp.prototype.global 是一个 访问器属性,其 set 访问器函数为 undefined。get 访问器函数调用时执行如下步骤:

  1. Rthis 值。
  2. cu 为码元 0x0067(g)。
  3. 返回 ? RegExpHasFlag(R, cu)。

22.2.6.6 get RegExp.prototype.hasIndices

RegExp.prototype.hasIndices 是一个 访问器属性,其 set 访问器函数为 undefined。get 访问器函数调用时执行如下步骤:

  1. Rthis 值。
  2. cu 为码元 0x0064(d)。
  3. 返回 ? RegExpHasFlag(R, cu)。

22.2.6.7 get RegExp.prototype.ignoreCase

RegExp.prototype.ignoreCase 是一个 访问器属性,其 set 访问器函数为 undefined。get 访问器函数调用时执行如下步骤:

  1. Rthis 值。
  2. cu 为码元 0x0069(i)。
  3. 返回 ? RegExpHasFlag(R, cu)。

22.2.6.8 RegExp.prototype [ %Symbol.match% ] ( string )

该方法调用时执行如下步骤:

  1. rxthis 值。
  2. 如果 rx 不是对象,抛出 TypeError 异常。
  3. S 为 ? ToString(string)。
  4. flags 为 ? ToString(? Get(rx, "flags"))。
  5. 如果 flags 不包含 "g",则
    1. 返回 ? RegExpExec(rx, S)。
  6. 否则,
    1. 如果 flags 包含 "u"flags 包含 "v",令 fullUnicodetrue。否则,令 fullUnicodefalse
    2. 执行 ? Set(rx, "lastIndex", +0𝔽, true)。
    3. A 为 ! ArrayCreate(0)。
    4. n 为 0。
    5. 重复,
      1. result 为 ? RegExpExec(rx, S)。
      2. 如果 resultnull,则
        1. 如果 n = 0,返回 null
        2. 返回 A
      3. 否则,
        1. matchStr 为 ? ToString(? Get(result, "0"))。
        2. 执行 ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(n)), matchStr)。
        3. 如果 matchStr 是空字符串,则
          1. thisIndex(? ToLength(? Get(rx, "lastIndex")))。
          2. nextIndexAdvanceStringIndex(S, thisIndex, fullUnicode)。
          3. 执行 ? Set(rx, "lastIndex", 𝔽(nextIndex), true)。
        4. 设置 nn + 1。

该方法的 "name" 属性值为 "[Symbol.match]"

%Symbol.match% 属性被 IsRegExp 抽象操作用于识别具有正则表达式基本行为的对象。如果缺少 %Symbol.match% 属性,或该属性的值经布尔转换不是 true,则表明该对象不应被当作正则表达式对象使用。

22.2.6.9 RegExp.prototype [ %Symbol.matchAll% ] ( string )

该方法调用时执行如下步骤:

  1. Rthis 值。
  2. 如果 R 不是对象,抛出 TypeError 异常。
  3. S 为 ? ToString(string)。
  4. C 为 ? SpeciesConstructor(R, %RegExp%)。
  5. flags 为 ? ToString(? Get(R, "flags"))。
  6. matcher 为 ? Construct(C, « R, flags »)。
  7. lastIndex 为 ? ToLength(? Get(R, "lastIndex"))。
  8. 执行 ? Set(matcher, "lastIndex", lastIndex, true)。
  9. 如果 flags 包含 "g",令 globaltrue
  10. 否则,令 globalfalse
  11. 如果 flags 包含 "u"flags 包含 "v",令 fullUnicodetrue
  12. 否则,令 fullUnicodefalse
  13. 返回 CreateRegExpStringIterator(matcher, S, global, fullUnicode)。

该方法的 "name" 属性值为 "[Symbol.matchAll]"

22.2.6.10 get RegExp.prototype.multiline

RegExp.prototype.multiline 是一个 访问器属性,其 set 访问器函数为 undefined。get 访问器函数调用时执行如下步骤:

  1. Rthis 值。
  2. cu 为码元 0x006D(m)。
  3. 返回 ? RegExpHasFlag(R, cu)。

22.2.6.11 RegExp.prototype [ %Symbol.replace% ] ( string, replaceValue )

该方法调用时执行如下步骤:

  1. rxthis 值。
  2. 如果 rx 不是对象,抛出 TypeError 异常。
  3. S 为 ? ToString(string)。
  4. lengthSS 的长度。
  5. functionalReplaceIsCallable(replaceValue)。
  6. 如果 functionalReplacefalse,则
    1. 设置 replaceValue 为 ? ToString(replaceValue)。
  7. flags 为 ? ToString(? Get(rx, "flags"))。
  8. 如果 flags 包含 "g",令 globaltrue;否则 globalfalse
  9. 如果 globaltrue,则
    1. 执行 ? Set(rx, "lastIndex", +0𝔽, true)。
  10. results 为一个新的空 List
  11. donefalse
  12. 重复,直到 donefalse
    1. result 为 ? RegExpExec(rx, S)。
    2. 如果 resultnull,则
      1. 设置 donetrue
    3. 否则,
      1. result 添加到 results
      2. 如果 globalfalse,则
        1. 设置 donetrue
      3. 否则,
        1. matchStr 为 ? ToString(? Get(result, "0"))。
        2. 如果 matchStr 是空字符串,则
          1. thisIndex(? ToLength(? Get(rx, "lastIndex")))。
          2. 如果 flags 包含 "u"flags 包含 "v",令 fullUnicodetrue;否则 fullUnicodefalse
          3. nextIndexAdvanceStringIndex(S, thisIndex, fullUnicode)。
          4. 执行 ? Set(rx, "lastIndex", 𝔽(nextIndex), true)。
  13. accumulatedResult 为空字符串。
  14. nextSourcePosition 为 0。
  15. 对于 results 中的每个元素 result,执行
    1. resultLength 为 ? LengthOfArrayLike(result)。
    2. nCapturesmax(resultLength - 1, 0)。
    3. matched 为 ? ToString(? Get(result, "0"))。
    4. matchLengthmatched 的长度。
    5. position 为 ? ToIntegerOrInfinity(? Get(result, "index"))。
    6. position 限制在 0 到 lengthS 之间。
    7. captures 为一个新的空 List
    8. n 为 1。
    9. 重复,直到 nnCaptures
      1. capN 为 ? Get(result, ! ToString(𝔽(n)))。
      2. 如果 capN 不为 undefined,则
        1. 设置 capN 为 ? ToString(capN)。
      3. capN 添加到 captures
      4. 注:当 n = 1 时,上一步将第一个元素放入 captures(索引 0)。更一般地,第 n 个捕获组(第 n 对括号捕获的字符)在 captures[n - 1]。
      5. 设置 nn + 1。
    10. namedCaptures 为 ? Get(result, "groups")。
    11. 如果 functionalReplacetrue,则
      1. replacerArgs 为 « matched »、captures 和 « 𝔽(position), S » 的列表拼接。
      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, S, position, captures, namedCaptures, replaceValue)。
    13. 如果 positionnextSourcePosition,则
      1. 注:position 通常不会倒退。如果发生,说明是行为异常的 RegExp 子类或通过副作用改变了 global 标志或 rx 的其它特性,此时对应替换会被忽略。
      2. 设置 accumulatedResultaccumulatedResultSnextSourcePositionposition 子串、和 replacementString 的字符串拼接。
      3. 设置 nextSourcePositionposition + matchLength
  16. 如果 nextSourcePositionlengthS,返回 accumulatedResult
  17. 返回 accumulatedResultSnextSourcePosition 开始的子串的字符串拼接。

该方法的 "name" 属性值为 "[Symbol.replace]"

22.2.6.12 RegExp.prototype [ %Symbol.search% ] ( string )

该方法调用时执行如下步骤:

  1. rxthis 值。
  2. 如果 rx 不是对象,抛出 TypeError 异常。
  3. S 为 ? ToString(string)。
  4. previousLastIndex 为 ? Get(rx, "lastIndex")。
  5. 如果 previousLastIndex 不为 +0𝔽,则
    1. 执行 ? Set(rx, "lastIndex", +0𝔽, true)。
  6. result 为 ? RegExpExec(rx, S)。
  7. currentLastIndex 为 ? Get(rx, "lastIndex")。
  8. 如果 SameValue(currentLastIndex, previousLastIndex) 为 false,则
    1. 执行 ? Set(rx, "lastIndex", previousLastIndex, true)。
  9. 如果 resultnull,返回 -1𝔽
  10. 返回 ? Get(result, "index")。

该方法的 "name" 属性值为 "[Symbol.search]"

本 RegExp 对象的 "lastIndex""global" 属性在执行搜索时会被忽略,并且 "lastIndex" 属性保持不变。

22.2.6.13 get RegExp.prototype.source

RegExp.prototype.source 是一个 访问器属性,其 set 访问器函数为 undefined。get 访问器函数调用时执行如下步骤:

  1. Rthis 值。
  2. 如果 R 不是对象,抛出 TypeError 异常。
  3. 如果 R 没有 [[OriginalSource]] 内部插槽,则
    1. 如果 SameValue(R, %RegExp.prototype%) 为 true,返回 "(?:)"
    2. 否则,抛出 TypeError 异常。
  4. 断言R 拥有 [[OriginalFlags]] 内部插槽。
  5. srcR.[[OriginalSource]]
  6. flagsR.[[OriginalFlags]]
  7. 返回 EscapeRegExpPattern(src, flags)。

22.2.6.13.1 EscapeRegExpPattern ( P, F )

抽象操作 EscapeRegExpPattern 接收参数 P(字符串)和 F(字符串),返回一个字符串。调用时执行如下步骤:

  1. 如果 F 包含 "v",则
    1. patternSymbolPattern[+UnicodeMode, +UnicodeSetsMode]
  2. 否则如果 F 包含 "u",则
    1. patternSymbolPattern[+UnicodeMode, ~UnicodeSetsMode]
  3. 否则:
    1. patternSymbolPattern[~UnicodeMode, ~UnicodeSetsMode]
  4. S 为形式为 patternSymbol 的字符串,其内容等价于将 P 按 UTF-16 编码的 Unicode 码点解释后得到的模式,并对部分码点按下述方式转义。S 可能与 P 相同,也可能不同;但对 S 作为 patternSymbol 求值所得的 抽象闭包 必须与构造对象的 [[RegExpMatcher]] 内部插槽给出的 抽象闭包 行为一致。对同一 PF 多次调用本操作,结果必须一致。
  5. pattern 中的 / 及所有 LineTerminator 码点须在 S 中转义,以确保 字符串拼接 "/"S"/"F 可作为 RegularExpressionLiteral 被解析,并与构造的正则表达式行为一致。如 P"/",则 S 可为 "\/""\u002F",但不能为 "/",否则 /// 后接 F 会被解析为 单行注释 而不是 正则表达式字面量。若 P 为空字符串,则 S 可为 "(?:)"
  6. 返回 S

尽管名字类似,RegExp.escape 与 EscapeRegExpPattern 并不执行类似操作。前者用于将字符串转义为可在模式中使用的内容,后者用于将模式转义为可作为字符串表示。

22.2.6.14 RegExp.prototype [ %Symbol.split% ] ( string, limit )

注 1

该方法返回一个数组,数组中存储了将 string 转换为字符串后的子串。这些子串是通过从左到右搜索 this 值正则表达式的匹配项确定的;这些匹配项不属于返回数组中的任何字符串,而是将字符串拆分开。

this 值可以是空正则表达式,也可以是能够匹配空字符串的正则表达式。在这种情况下,正则表达式不会匹配输入字符串开头或结尾的空子串,也不会匹配前一个分隔符匹配末尾的空子串。(例如,如果正则表达式匹配空字符串,则字符串会被拆分为单个码元元素;结果数组长度等于字符串长度,每个子串只包含一个码元。)某个索引处只考虑第一次匹配,即使回溯能得到非空子串匹配也不会采纳。(例如,/a*?/[Symbol.split]("ab") 的结果是 ["a", "b"],而 /a*/[Symbol.split]("ab") 的结果是 ["","b"]。)

如果 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. rxthis 值。
  2. 如果 rx 不是对象,抛出 TypeError 异常。
  3. S 为 ? ToString(string)。
  4. C 为 ? SpeciesConstructor(rx, %RegExp%)。
  5. flags 为 ? ToString(? Get(rx, "flags"))。
  6. 如果 flags 包含 "u"flags 包含 "v",令 unicodeMatchingtrue
  7. 否则,令 unicodeMatchingfalse
  8. 如果 flags 包含 "y",令 newFlagsflags
  9. 否则,令 newFlagsflags"y" 的字符串拼接。
  10. splitter 为 ? Construct(C, « rx, newFlags »)。
  11. A 为 ! ArrayCreate(0)。
  12. lengthA 为 0。
  13. 如果 limitundefined,令 lim 为 232 - 1;否则,令 lim(? ToUint32(limit))。
  14. 如果 lim = 0,返回 A
  15. 如果 S 是空字符串,则
    1. z 为 ? RegExpExec(splitter, S)。
    2. 如果 z 不为 null,返回 A
    3. 执行 ! CreateDataPropertyOrThrow(A, "0", S)。
    4. 返回 A
  16. sizeS 的长度。
  17. p 为 0。
  18. qp
  19. 重复,直到 q < size
    1. 执行 ? Set(splitter, "lastIndex", 𝔽(q), true)。
    2. z 为 ? RegExpExec(splitter, S)。
    3. 如果 znull,则
      1. 设置 qAdvanceStringIndex(S, q, unicodeMatching)。
    4. 否则,
      1. e(? ToLength(? Get(splitter, "lastIndex")))。
      2. e 限制为不大于 size
      3. 如果 e = p,则
        1. 设置 qAdvanceStringIndex(S, q, unicodeMatching)。
      4. 否则,
        1. Tsubstring of Spq
        2. 执行 ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(lengthA)), T)。
        3. 设置 lengthAlengthA + 1。
        4. 如果 lengthA = lim,返回 A
        5. 设置 pe
        6. numberOfCaptures 为 ? LengthOfArrayLike(z)。
        7. numberOfCaptures 限制为 numberOfCaptures - 1 与 0 之间的最大值。
        8. i 为 1。
        9. 重复,直到 inumberOfCaptures
          1. nextCapture 为 ? Get(z, ! ToString(𝔽(i)))。
          2. 执行 ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(lengthA)), nextCapture)。
          3. 设置 ii + 1。
          4. 设置 lengthAlengthA + 1。
          5. 如果 lengthA = lim,返回 A
        10. 设置 qp
  20. Tsubstring of Spsize
  21. 执行 ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(lengthA)), T)。
  22. 返回 A

该方法的 "name" 属性值为 "[Symbol.split]"

注 2

该方法会忽略本 RegExp 对象的 "global""sticky" 属性值。

22.2.6.15 get RegExp.prototype.sticky

RegExp.prototype.sticky 是一个 访问器属性,其 set 访问器函数为 undefined。get 访问器函数调用时执行如下步骤:

  1. Rthis 值。
  2. cu 为码元 0x0079(y)。
  3. 返回 ? RegExpHasFlag(R, cu)。

22.2.6.16 RegExp.prototype.test ( S )

该方法调用时执行如下步骤:

  1. Rthis 值。
  2. 如果 R 不是对象,抛出 TypeError 异常。
  3. string 为 ? ToString(S)。
  4. match 为 ? RegExpExec(R, string)。
  5. 如果 match 不为 null,返回 true;否则返回 false

22.2.6.17 RegExp.prototype.toString ( )

  1. Rthis 值。
  2. 如果 R 不是对象,抛出 TypeError 异常。
  3. pattern 为 ? ToString(? Get(R, "source"))。
  4. flags 为 ? ToString(? Get(R, "flags"))。
  5. result字符串拼接 "/"pattern"/"flags
  6. 返回 result

返回的字符串具有 RegularExpressionLiteral 的形式,求值后是另一个行为与本对象一致的 RegExp 对象。

22.2.6.18 get RegExp.prototype.unicode

RegExp.prototype.unicode 是一个 访问器属性,其 set 访问器函数为 undefined。get 访问器函数调用时执行如下步骤:

  1. Rthis 值。
  2. cu 为码元 0x0075(u)。
  3. 返回 ? RegExpHasFlag(R, cu)。

22.2.6.19 get RegExp.prototype.unicodeSets

RegExp.prototype.unicodeSets 是一个 访问器属性,其 set 访问器函数为 undefined。get 访问器函数调用时执行如下步骤:

  1. Rthis 值。
  2. cu 为码元 0x0076(v)。
  3. 返回 ? RegExpHasFlag(R, cu)。

22.2.7 正则匹配的抽象操作

22.2.7.1 RegExpExec ( R, S )

抽象操作 RegExpExec 接收参数 R(对象)和 S(字符串),返回 包含对象或 null 的正常完成,或 抛出完成。调用时执行如下步骤:

  1. exec 为 ? Get(R, "exec")。
  2. 如果 IsCallable(exec) 为 true,则
    1. result 为 ? Call(exec, R, « S »)。
    2. 如果 result 不是对象result 不是 null,抛出 TypeError 异常。
    3. 返回 result
  3. 执行 ? RequireInternalSlot(R, [[RegExpMatcher]])。
  4. 返回 ? RegExpBuiltinExec(R, S)。

如果未找到可调用的 "exec" 属性,本算法会退回内建正则匹配算法。这为针对早期版本编写的代码提供了兼容行为,此前大多数使用正则表达式的内建算法不会动态查找 "exec" 属性。

22.2.7.2 RegExpBuiltinExec ( R, S )

抽象操作 RegExpBuiltinExec 接收参数 R(初始化后的 RegExp 实例)和 S(字符串),返回 包含一个 数组异类对象null 的正常完成,或 抛出完成。调用时执行如下步骤:

  1. lengthS 的长度。
  2. lastIndex(? ToLength(? Get(R, "lastIndex")))。
  3. flagsR.[[OriginalFlags]]
  4. 如果 flags 包含 "g",令 globaltrue;否则为 false
  5. 如果 flags 包含 "y",令 stickytrue;否则为 false
  6. 如果 flags 包含 "d",令 hasIndicestrue;否则为 false
  7. 如果 globalfalsestickyfalse,将 lastIndex 设为 0。
  8. matcherR.[[RegExpMatcher]]
  9. 如果 flags 包含 "u"flags 包含 "v",令 fullUnicodetrue;否则为 false
  10. matchSucceededfalse
  11. 如果 fullUnicodetrue,令 inputStringToCodePoints(S);否则,令 input 为包含 S 各码元的 List
  12. 注:input 的每个元素都被视为一个字符。
  13. 重复,直到 matchSucceededfalse
    1. 如果 lastIndex > length,则
      1. 如果 globalstickytrue,则
        1. 执行 ? Set(R, "lastIndex", +0𝔽, true)。
      2. 返回 null
    2. inputIndexS 索引 lastIndex 处对应 input 的下标。
    3. rmatcher(input, inputIndex)。
    4. 如果 rfailure,则
      1. 如果 stickytrue,则
        1. 执行 ? Set(R, "lastIndex", +0𝔽, true)。
        2. 返回 null
      2. lastIndex 设为 AdvanceStringIndex(S, lastIndex, fullUnicode)。
    5. 否则,
      1. 断言rMatchState
      2. 设置 matchSucceededtrue
  14. er.[[EndIndex]]
  15. 如果 fullUnicodetrue,则将 e 设为 GetStringIndex(S, e)。
  16. 如果 globalstickytrue,则
    1. 执行 ? Set(R, "lastIndex", 𝔽(e), true)。
  17. nr.[[Captures]] 的元素数。
  18. 断言n = R.[[RegExpRecord]].[[CapturingGroupsCount]]
  19. 断言n < 232 - 1。
  20. A 为 ! ArrayCreate(n + 1)。
  21. 断言A"length" 数学值为 n + 1。
  22. 执行 ! CreateDataPropertyOrThrow(A, "index", 𝔽(lastIndex))。
  23. 执行 ! CreateDataPropertyOrThrow(A, "input", S)。
  24. matchMatch Record { [[StartIndex]]: lastIndex, [[EndIndex]]: e }。
  25. indices 为一个新的空 List
  26. groupNames 为一个新的空 List
  27. match 添加到 indices
  28. matchedSubstrGetMatchString(S, match)。
  29. 执行 ! CreateDataPropertyOrThrow(A, "0", matchedSubstr)。
  30. 如果 R 包含 GroupName
    1. groupsOrdinaryObjectCreate(null)。
    2. hasGroupstrue
  31. 否则,
    1. groupsundefined
    2. hasGroupsfalse
  32. 执行 ! CreateDataPropertyOrThrow(A, "groups", groups)。
  33. matchedGroupNames 为一个新的空 List
  34. 对于所有 1 ≤ in 的整数 i,升序执行
    1. captureIr.[[Captures]] 的第 i 个元素。
    2. 如果 captureIundefined
      1. capturedValueundefined
      2. undefined 添加到 indices
    3. 否则,
      1. captureStartcaptureI.[[StartIndex]]
      2. captureEndcaptureI.[[EndIndex]]
      3. 如果 fullUnicodetrue
        1. 设置 captureStartGetStringIndex(S, captureStart)。
        2. 设置 captureEndGetStringIndex(S, captureEnd)。
      4. captureMatch Record { [[StartIndex]]: captureStart, [[EndIndex]]: captureEnd }。
      5. capturedValueGetMatchString(S, capture)。
      6. capture 添加到 indices
    4. 执行 ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(i)), capturedValue)。
    5. 如果 R 的第 i 个捕获带有 GroupName
      1. s 为该 GroupNameCapturingGroupName
      2. 如果 matchedGroupNames 包含 s
        1. 断言capturedValueundefined
        2. undefined 添加到 groupNames
      3. 否则,
        1. 如果 capturedValue 不为 undefined,将 s 添加到 matchedGroupNames
        2. 注:如有多个同名分组,groups 可能已有属性 s。但因 groups 是普通对象,其属性均为可写数据属性,CreateDataPropertyOrThrow 调用必然成功。
        3. 执行 ! CreateDataPropertyOrThrow(groups, s, capturedValue)。
        4. s 添加到 groupNames
    6. 否则,
      1. undefined 添加到 groupNames
  35. 如果 hasIndicestrue
    1. indicesArrayMakeMatchIndicesIndexPairArray(S, indices, groupNames, hasGroups)。
    2. 执行 ! CreateDataPropertyOrThrow(A, "indices", indicesArray)。
  36. 返回 A

22.2.7.3 AdvanceStringIndex ( S, index, unicode )

抽象操作 AdvanceStringIndex 接收参数 S(字符串)、index(非负整数)、unicode(布尔值),返回一个整数。调用时执行如下步骤:

  1. 断言index ≤ 253 - 1。
  2. 如果 unicodefalse,返回 index + 1。
  3. lengthS 的长度。
  4. 如果 index + 1 ≥ length,返回 index + 1。
  5. cpCodePointAt(S, index)。
  6. 返回 index + cp.[[CodeUnitCount]]

22.2.7.4 GetStringIndex ( S, codePointIndex )

抽象操作 GetStringIndex 接收参数 S(字符串)和 codePointIndex(非负整数),返回一个非负整数。它将 S 作为 UTF-16 编码码点序列,根据 6.1.4,返回与码点索引 codePointIndex 对应的码元索引,若不存在则返回 S 的长度。调用时执行如下步骤:

  1. 如果 S 是空字符串,返回 0。
  2. lenS 的长度。
  3. codeUnitCount 为 0。
  4. codePointCount 为 0。
  5. 重复,直到 codeUnitCount < len
    1. 如果 codePointCount = codePointIndex,返回 codeUnitCount
    2. cpCodePointAt(S, codeUnitCount)。
    3. 设置 codeUnitCountcodeUnitCount + cp.[[CodeUnitCount]]
    4. 设置 codePointCountcodePointCount + 1。
  6. 返回 len

22.2.7.5 匹配记录(Match Records)

匹配记录(Match Record) 是一种 Record 值,用于封装正则匹配或捕获的起止索引。

匹配记录的字段列于 表 72

表 72:Match Record 字段
字段名 含义
[[StartIndex]] 非负 整数 匹配开始(包含)的字符串起始码元数。
[[EndIndex]] 一个 整数,且 ≥ [[StartIndex]] 匹配结束(不含)的字符串起始码元数。

22.2.7.6 GetMatchString ( S, match )

抽象操作 GetMatchString 接收参数 S(字符串)和 matchMatch Record),返回一个字符串。调用时执行如下步骤:

  1. 断言match.[[StartIndex]]match.[[EndIndex]]S 的长度。
  2. 返回 Smatch.[[StartIndex]]match.[[EndIndex]]子串

22.2.7.7 GetMatchIndexPair ( S, match )

抽象操作 GetMatchIndexPair 接收参数 S(字符串)和 matchMatch Record),返回一个数组。调用时执行如下步骤:

  1. 断言match.[[StartIndex]]match.[[EndIndex]]S 的长度。
  2. 返回 CreateArrayFromList𝔽(match.[[StartIndex]]), 𝔽(match.[[EndIndex]])»)。

22.2.7.8 MakeMatchIndicesIndexPairArray ( S, indices, groupNames, hasGroups )

抽象操作 MakeMatchIndicesIndexPairArray 接收参数 S(字符串)、indicesList,元素为 Match Recordsundefined)、groupNamesList,元素为字符串或 undefined)、hasGroups(布尔值),返回一个数组。调用时执行如下步骤:

  1. nindices 的元素数。
  2. 断言n < 232 - 1。
  3. 断言groupNamesn - 1 个元素。
  4. 注:groupNames 列表中的元素与 indices 列表自 indices[1] 起一一对应。
  5. A 为 ! ArrayCreate(n)。
  6. 如果 hasGroupstrue
    1. groupsOrdinaryObjectCreate(null)。
  7. 否则,
    1. groupsundefined
  8. 执行 ! CreateDataPropertyOrThrow(A, "groups", groups)。
  9. 对于 0 ≤ i < n 的每个整数 i,升序执行
    1. matchIndicesindices[i]。
    2. 如果 matchIndices 不为 undefined
      1. matchIndexPairGetMatchIndexPair(S, matchIndices)。
    3. 否则,
      1. matchIndexPairundefined
    4. 执行 ! CreateDataPropertyOrThrow(A, !ToString(𝔽(i)), matchIndexPair)。
    5. 如果 i > 0,
      1. sgroupNames[i - 1]。
      2. 如果 s 不为 undefined
        1. 断言groups 不为 undefined
        2. 注:如有多个同名分组,groups 可能已经有 s 属性。因 groups 是普通对象,属性均为可写数据属性,CreateDataPropertyOrThrow 调用必然成功。
        3. 执行 ! CreateDataPropertyOrThrow(groups, s, matchIndexPair)。
  10. 返回 A

22.2.8 RegExp 实例的属性

RegExp 实例是 普通对象,继承自 RegExp 原型对象。RegExp 实例具有内部插槽 [[OriginalSource]][[OriginalFlags]][[RegExpRecord]][[RegExpMatcher]][[RegExpMatcher]] 插槽的值是该正则对象 模式抽象闭包 表示。

在 ECMAScript 2015 之前,RegExp 实例被规范为拥有自身的数据属性 data properties "source""global""ignoreCase""multiline"。这些属性现在被规范为 RegExp.prototype访问器属性

RegExp 实例还具有以下属性:

22.2.8.1 lastIndex

"lastIndex" 属性的值指定下次匹配时从字符串的哪个索引开始。使用时会被强制转换为 整数类型 Number(参见 22.2.7.2)。该属性具有属性 { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }。

22.2.9 RegExp 字符串迭代器对象

RegExp 字符串迭代器是用于表示对某个特定字符串实例对象、针对某个特定 RegExp 实例对象进行迭代的对象。RegExp 字符串迭代器对象没有具名的 构造函数,而是通过调用某些 RegExp 实例对象的方法创建的。

22.2.9.1 CreateRegExpStringIterator ( R, S, global, fullUnicode )

抽象操作 CreateRegExpStringIterator 接收参数 R(对象)、S(字符串)、global(布尔值)、fullUnicode(布尔值),返回一个对象。调用时执行如下步骤:

  1. iteratorOrdinaryObjectCreate(%RegExpStringIteratorPrototype%, « [[IteratingRegExp]], [[IteratedString]], [[Global]], [[Unicode]], [[Done]] »)。
  2. 设置 iterator.[[IteratingRegExp]] = R
  3. 设置 iterator.[[IteratedString]] = S
  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. Othis 值。
  2. 如果 O 不是对象,抛出 TypeError 异常。
  3. 如果 O 不具有 RegExp 字符串迭代器对象实例的所有内部插槽(见 22.2.9.3),抛出 TypeError 异常。
  4. 如果 O.[[Done]]true
    1. 返回 CreateIteratorResultObject(undefined, true)。
  5. R = O.[[IteratingRegExp]]
  6. S = O.[[IteratedString]]
  7. global = O.[[Global]]
  8. fullUnicode = O.[[Unicode]]
  9. match 为 ? RegExpExec(R, S)。
  10. 如果 matchnull
    1. 设置 O.[[Done]] = true
    2. 返回 CreateIteratorResultObject(undefined, true)。
  11. 如果 globalfalse
    1. 设置 O.[[Done]] = true
    2. 返回 CreateIteratorResultObject(match, false)。
  12. matchStr 为 ? ToString(? Get(match, "0"))。
  13. 如果 matchStr 是空字符串,
    1. thisIndex(? ToLength(? Get(R, "lastIndex")))。
    2. nextIndexAdvanceStringIndex(S, thisIndex, fullUnicode)。
    3. 执行 ? Set(R, "lastIndex", 𝔽(nextIndex), true)。
  14. 返回 CreateIteratorResultObject(match, false)。

22.2.9.2.2 %RegExpStringIteratorPrototype% [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是字符串 "RegExp String Iterator"

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

22.2.9.3 RegExp 字符串迭代器实例的属性

RegExp 字符串迭代器 实例是 普通对象,继承自 %RegExpStringIteratorPrototype% 内置对象。RegExp 字符串迭代器 实例初始时拥有 表 73 所列的内部插槽。

表 73:RegExp 字符串迭代器实例的内部插槽
内部插槽 类型 描述
[[IteratingRegExp]] 对象 用于迭代的正则表达式。IsRegExp([[IteratingRegExp]]) 初始为 true
[[IteratedString]] 字符串 被迭代的字符串值。
[[Global]] 布尔值 指示 [[IteratingRegExp]] 是否为全局。
[[Unicode]] 布尔值 指示 [[IteratingRegExp]] 是否为 Unicode 模式。
[[Done]] 布尔值 指示迭代是否已完成。

23 索引集合

23.1 数组对象

数组是特殊对象,对某类属性名进行了特殊处理。关于此特殊处理的定义,见10.4.2

23.1.1 Array 构造函数

Array 构造函数

  • %Array%
  • 全局对象"Array" 属性的初始值。
  • 作为构造函数调用时,会创建并初始化一个新的数组。
  • 作为普通函数而不是构造函数调用时,也会创建并初始化一个新的数组。因此,函数调用 Array(…) 等价于使用相同参数的对象创建表达式 new Array(…)
  • 是一个其行为根据参数数量和类型而异的函数。
  • 可用作类定义中 extends 子句的值。打算继承数组特殊行为的子类构造函数,必须包含对 Array 构造函数super 调用,以初始化作为数组特殊对象的子类实例。然而,大多数 Array.prototype 方法是泛型方法,不依赖于其 this 值为数组特殊对象

23.1.1.1 Array ( ...values )

当调用该函数时,执行以下步骤:

  1. 如果 NewTarget 为 undefined,则令 newTarget活动函数对象;否则令 newTarget 为 NewTarget。
  2. proto 为 ? GetPrototypeFromConstructor(newTarget, "%Array.prototype%")。
  3. numberOfArgsvalues 中元素的数量。
  4. 如果 numberOfArgs = 0,则
    1. 返回 ! ArrayCreate(0, proto)。
  5. 否则如果 numberOfArgs = 1,则
    1. lenvalues[0]。
    2. array 为 ! ArrayCreate(0, proto)。
    3. 如果 len 不是数字类型,则
      1. 执行 ! CreateDataPropertyOrThrow(array, "0", len)。
      2. intLen1𝔽
    4. 否则,
      1. intLen 为 ! ToUint32(len)。
      2. 如果 SameValueZero(intLen, len) 为 false,则抛出 RangeError 异常。
    5. 执行 ! Set(array, "length", intLen, true)。
    6. 返回 array
  6. 否则,
    1. 断言numberOfArgs ≥ 2。
    2. array 为 ? ArrayCreate(numberOfArgs, proto)。
    3. k 为 0。
    4. 重复,直到 k < numberOfArgs
      1. Pk 为 ! ToString(𝔽(k))。
      2. itemKvalues[k]。
      3. 执行 ! CreateDataPropertyOrThrow(array, Pk, itemK)。
      4. kk + 1。
    5. 断言array"length" 属性的数学值为 numberOfArgs
    6. 返回 array

23.1.2 Array 构造函数的属性

Array 构造函数

  • 具有一个名为 [[Prototype]] 的内部槽,其值为 %Function.prototype%
  • 具有一个值为 1𝔽"length" 属性。
  • 具有以下属性:

23.1.2.1 Array.from ( items [ , mapper [ , thisArg ] ] )

当调用该方法时,执行以下步骤:

  1. Cthis 值。
  2. 如果 mapperundefined,则
    1. mappingfalse
  3. 否则,
    1. 如果 IsCallable(mapper) 为 false,则抛出 TypeError 异常。
    2. mappingtrue
  4. usingIterator 为 ? GetMethod(items, %Symbol.iterator%)。
  5. 如果 usingIterator 不为 undefined,则
    1. 如果 IsConstructor(C) 为 true,则
      1. A 为 ? Construct(C)。
    2. 否则,
      1. A 为 ! ArrayCreate(0)。
    3. iteratorRecord 为 ? GetIteratorFromMethod(items, usingIterator)。
    4. k 为 0。
    5. 重复,
      1. 如果 k ≥ 253 - 1,则
        1. errorThrowCompletion(新建的 TypeError 对象)。
        2. 返回 ? IteratorClose(iteratorRecord, error)。
      2. Pk 为 ! ToString(𝔽(k))。
      3. next 为 ? IteratorStepValue(iteratorRecord)。
      4. 如果 nextdone,则
        1. 执行 ? Set(A, "length", 𝔽(k), true)。
        2. 返回 A
      5. 如果 mappingtrue,则
        1. mappedValueCompletion(Call(mapper, thisArg, « next, 𝔽(k) »))。
        2. IfAbruptCloseIterator(mappedValue, iteratorRecord)。
      6. 否则,
        1. mappedValuenext
      7. defineStatusCompletion(CreateDataPropertyOrThrow(A, Pk, mappedValue))。
      8. IfAbruptCloseIterator(defineStatus, iteratorRecord)。
      9. kk + 1。
  6. 注:items 不是可迭代对象,因此假定其为类数组对象
  7. arrayLike 为 ! ToObject(items)。
  8. len 为 ? LengthOfArrayLike(arrayLike)。
  9. 如果 IsConstructor(C) 为 true,则
    1. A 为 ? Construct(C, « 𝔽(len) »)。
  10. 否则,
    1. A 为 ? ArrayCreate(len)。
  11. k 为 0。
  12. 重复,直到 k < len
    1. Pk 为 ! ToString(𝔽(k))。
    2. kValue 为 ? Get(arrayLike, Pk)。
    3. 如果 mappingtrue,则
      1. mappedValue 为 ? Call(mapper, thisArg, « kValue, 𝔽(k) »)。
    4. 否则,
      1. mappedValuekValue
    5. 执行 ? CreateDataPropertyOrThrow(A, Pk, mappedValue)。
    6. kk + 1。
  13. 执行 ? Set(A, "length", 𝔽(len), true)。
  14. 返回 A

该方法是有意设计为泛型工厂方法;它不要求其 this 值为 Array 构造函数。因此它可以被转移或继承到其它可用单一数字参数调用的构造函数

23.1.2.2 Array.isArray ( arg )

当调用该函数时,执行以下步骤:

  1. 返回 ? IsArray(arg)。

23.1.2.3 Array.of ( ...items )

当调用该方法时,执行以下步骤:

  1. lenitems 中元素的数量。
  2. lenNumber𝔽(len)。
  3. Cthis 值。
  4. 如果 IsConstructor(C) 为 true,则
    1. A 为 ? Construct(C, « lenNumber »)。
  5. 否则,
    1. A 为 ? ArrayCreate(len)。
  6. k 为 0。
  7. 重复,直到 k < len
    1. kValueitems[k]。
    2. Pk 为 ! ToString(𝔽(k))。
    3. 执行 ? CreateDataPropertyOrThrow(A, Pk, kValue)。
    4. kk + 1。
  8. 执行 ? Set(A, "length", lenNumber, true)。
  9. 返回 A

该方法是有意设计为泛型工厂方法;它不要求其 this 值为 Array 构造函数。因此它可以被转移或继承到其它可用单一数字参数调用的构造函数

23.1.2.4 Array.prototype

Array.prototype 的值为数组原型对象

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

23.1.2.5 get Array [ %Symbol.species% ]

Array[%Symbol.species%] 是一个 访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数被调用时执行以下步骤:

  1. 返回 this 值。

该函数的 "name" 属性值为 "get [Symbol.species]"

数组原型方法通常使用其 this 值的 constructor 来创建派生对象。然而,子类构造函数可以通过重写其 %Symbol.species% 属性来覆盖默认行为。

23.1.3 数组原型对象的属性

数组原型对象

  • %Array.prototype%
  • 数组特殊对象,并具有该类对象指定的内部方法。
  • 具有一个 "length" 属性,其初始值为+0𝔽,属性特性为 { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }。
  • 具有一个名为 [[Prototype]] 的内部槽,其值为 %Object.prototype%

数组原型对象被指定为数组特殊对象,以确保与 ECMAScript 2015 规范之前编写的 ECMAScript 代码兼容。

23.1.3.1 Array.prototype.at ( index )

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. relativeIndex 为 ? ToIntegerOrInfinity(index)。
  4. 如果 relativeIndex ≥ 0,则
    1. krelativeIndex
  5. 否则,
    1. klen + relativeIndex
  6. 如果 k < 0 或 klen,返回 undefined
  7. 返回 ? Get(O, ! ToString(𝔽(k)))。

23.1.3.2 Array.prototype.concat ( ...items )

该方法返回一个数组,包含该对象的数组元素后跟每个参数的数组元素。

调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. A 为 ? ArraySpeciesCreate(O, 0)。
  3. n 为 0。
  4. O 前置到 items
  5. items 的每个元素 E,执行
    1. spreadable 为 ? IsConcatSpreadable(E)。
    2. 如果 spreadabletrue,则
      1. len 为 ? LengthOfArrayLike(E)。
      2. 如果 n + len > 253 - 1,抛出 TypeError 异常。
      3. k 为 0。
      4. 重复,直到 k < len
        1. Pk 为 ! ToString(𝔽(k))。
        2. exists 为 ? HasProperty(E, Pk)。
        3. 如果 existstrue,则
          1. subElement 为 ? Get(E, Pk)。
          2. 执行 ? CreateDataPropertyOrThrow(A, ! ToString(𝔽(n)), subElement)。
        4. nn + 1。
        5. kk + 1。
    3. 否则,
      1. 注:E 作为单项加入而不是展开。
      2. 如果 n ≥ 253 - 1,抛出 TypeError 异常。
      3. 执行 ? CreateDataPropertyOrThrow(A, ! ToString(𝔽(n)), E)。
      4. nn + 1。
  6. 执行 ? Set(A, "length", 𝔽(n), true)。
  7. 返回 A

该方法的 "length" 属性为 1𝔽

注 1

在步骤 6 中显式设置 "length" 属性,是为了确保当 items 的最后一个非空元素有尾部空洞或 A 不是内建数组时长度正确。

注 2

该方法被设计为泛型;不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。

23.1.3.2.1 IsConcatSpreadable ( O )

抽象操作 IsConcatSpreadable 接收参数 O(一个 ECMAScript 语言值),并返回 包含 布尔值的正常完成,或 抛出完成。调用时执行以下步骤:

  1. 如果 O 不是对象,返回 false
  2. spreadable 为 ? Get(O, %Symbol.isConcatSpreadable%)。
  3. 如果 spreadable 不为 undefined,返回 ToBoolean(spreadable)。
  4. 返回 ? IsArray(O)。

23.1.3.3 Array.prototype.constructor

Array.prototype.constructor 的初始值为 %Array%

23.1.3.4 Array.prototype.copyWithin ( target, start [ , end ] )

注 1

end 参数是可选的。如果未提供,则使用 this 值的长度。

注 2

如果 target 为负数,则视为 length + target,其中 length 是数组的长度。如果 start 为负数,则视为 length + start。如果 end 为负数,则视为 length + end

调用该方法时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. relativeTarget 为 ? ToIntegerOrInfinity(target)。
  4. 如果 relativeTarget = -∞,令 to 为 0。
  5. 否则如果 relativeTarget < 0,令 tomax(len + relativeTarget, 0)。
  6. 否则,令 tomin(relativeTarget, len)。
  7. relativeStart 为 ? ToIntegerOrInfinity(start)。
  8. 如果 relativeStart = -∞,令 from 为 0。
  9. 否则如果 relativeStart < 0,令 frommax(len + relativeStart, 0)。
  10. 否则,令 frommin(relativeStart, len)。
  11. 如果 endundefined,令 relativeEndlen;否则令 relativeEnd 为 ? ToIntegerOrInfinity(end)。
  12. 如果 relativeEnd = -∞,令 final 为 0。
  13. 否则如果 relativeEnd < 0,令 finalmax(len + relativeEnd, 0)。
  14. 否则,令 finalmin(relativeEnd, len)。
  15. countmin(final - from, len - to)。
  16. 如果 from < toto < from + count,则
    1. direction 为 -1。
    2. 设置 fromfrom + count - 1。
    3. 设置 toto + count - 1。
  17. 否则,
    1. direction 为 1。
  18. 重复,直到 count > 0,
    1. fromKey 为 ! ToString(𝔽(from))。
    2. toKey 为 ! ToString(𝔽(to))。
    3. fromPresent 为 ? HasProperty(O, fromKey)。
    4. 如果 fromPresenttrue,则
      1. fromValue 为 ? Get(O, fromKey)。
      2. 执行 ? Set(O, toKey, fromValue, true)。
    5. 否则,
      1. 断言fromPresentfalse
      2. 执行 ? DeletePropertyOrThrow(O, toKey)。
    6. 设置 fromfrom + direction
    7. 设置 toto + direction
    8. 设置 countcount - 1。
  19. 返回 O
注 3

该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。

23.1.3.5 Array.prototype.entries ( )

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. 返回 CreateArrayIterator(O, key+value)。

23.1.3.6 Array.prototype.every ( callback [ , thisArg ] )

注 1

callback 应该是一个接受三个参数并返回可转换为布尔值的函数。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. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. 如果 IsCallable(callback) 为 false,抛出 TypeError 异常。
  4. k 为 0。
  5. 重复,直到 k < len
    1. Pk 为 ! ToString(𝔽(k))。
    2. kPresent 为 ? HasProperty(O, Pk)。
    3. 如果 kPresenttrue,则
      1. kValue 为 ? Get(O, Pk)。
      2. testResultToBoolean(? Call(callback, thisArg, « kValue, 𝔽(k), O »))。
      3. 如果 testResultfalse,返回 false
    4. 设置 kk + 1。
  6. 返回 true
注 2

该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。

23.1.3.7 Array.prototype.fill ( value [ , start [ , end ] ] )

注 1

start 参数是可选的。如果未提供,则使用 +0𝔽

end 参数是可选的。如果未提供,则使用 this 值的长度。

注 2

如果 start 为负数,则视为 length + start,其中 length 是数组的长度。如果 end 为负数,则视为 length + end

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. relativeStart 为 ? ToIntegerOrInfinity(start)。
  4. 如果 relativeStart = -∞,令 k 为 0。
  5. 否则如果 relativeStart < 0,令 kmax(len + relativeStart, 0)。
  6. 否则,令 kmin(relativeStart, len)。
  7. 如果 endundefined,令 relativeEndlen;否则令 relativeEnd 为 ? ToIntegerOrInfinity(end)。
  8. 如果 relativeEnd = -∞,令 final 为 0。
  9. 否则如果 relativeEnd < 0,令 finalmax(len + relativeEnd, 0)。
  10. 否则,令 finalmin(relativeEnd, len)。
  11. 重复,直到 k < final
    1. Pk 为 ! ToString(𝔽(k))。
    2. 执行 ? Set(O, Pk, value, true)。
    3. kk + 1。
  12. 返回 O
注 3

该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。

23.1.3.8 Array.prototype.filter ( callback [ , thisArg ] )

注 1

callback 应该是一个接受三个参数并返回可转换为布尔值的函数。filter 会按升序对数组中每个元素调用 callback 一次,并构造一个包含所有 callback 返回 true 的值的新数组。callback 只会对数组中实际存在的元素调用,不会对数组中缺失的元素调用。

如果提供了 thisArg 参数,则每次调用 callback 时都会用作 this 值。如果未提供,则使用 undefined

callback 被调用时有三个参数:元素的值、元素的索引、被遍历的对象。

filter 不会直接修改它所调用的对象,但该对象可能会被 callback 的调用修改。

filter 处理的元素范围在第一次调用 callback 前就已确定。调用 filter 之后添加到数组的元素不会被 callback 访问。如果数组中已存在的元素被修改,则传递给 callback 的值是在 filter 访问该元素时的值;在 filter 调用开始后被删除且尚未被访问的元素不会被访问。

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. 如果 IsCallable(callback) 为 false,抛出 TypeError 异常。
  4. A 为 ? ArraySpeciesCreate(O, 0)。
  5. k 为 0。
  6. to 为 0。
  7. 重复,直到 k < len
    1. Pk 为 ! ToString(𝔽(k))。
    2. kPresent 为 ? HasProperty(O, Pk)。
    3. 如果 kPresenttrue,则
      1. kValue 为 ? Get(O, Pk)。
      2. selectedToBoolean(? Call(callback, thisArg, « kValue, 𝔽(k), O »))。
      3. 如果 selectedtrue,则
        1. 执行 ? CreateDataPropertyOrThrow(A, ! ToString(𝔽(to)), kValue)。
        2. 设置 toto + 1。
    4. 设置 kk + 1。
  8. 返回 A
注 2

该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。

23.1.3.9 Array.prototype.find ( predicate [ , thisArg ] )

注 1

该方法会按索引升序对数组的每个元素调用 predicate 一次,直到找到一个 predicate 返回可转换为 true 的值的元素。如果找到这样的元素,find 会立即返回该元素的值。否则,find 返回 undefined

更多信息见 FindViaPredicate

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. findRec 为 ? FindViaPredicate(O, len, ascending, predicate, thisArg)。
  4. 返回 findRec.[[Value]]
注 2

该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。

23.1.3.10 Array.prototype.findIndex ( predicate [ , thisArg ] )

注 1

该方法会按索引升序对数组的每个元素调用 predicate 一次,直到找到一个 predicate 返回可转换为 true 的值的元素。如果找到这样的元素,findIndex 会立即返回该元素的索引。否则,findIndex 返回 -1。

更多信息见 FindViaPredicate

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. findRec 为 ? FindViaPredicate(O, len, ascending, predicate, thisArg)。
  4. 返回 findRec.[[Index]]
注 2

该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。

23.1.3.11 Array.prototype.findLast ( predicate [ , thisArg ] )

注 1

该方法会按索引降序对数组的每个元素调用 predicate 一次,直到找到一个 predicate 返回可转换为 true 的值的元素。如果找到这样的元素,findLast 会立即返回该元素的值。否则,findLast 返回 undefined

更多信息见 FindViaPredicate

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. findRec 为 ? FindViaPredicate(O, len, descending, predicate, thisArg)。
  4. 返回 findRec.[[Value]]
注 2

该方法被设计为泛型;它不要求其 this 值为数组对象。因此它可以转移到其他类型对象用作方法。

23.1.3.12 Array.prototype.findLastIndex ( predicate [ , thisArg ] )

注 1

该方法会按索引降序对数组的每个元素调用 predicate 一次,直到找到一个 predicate 返回可转换为 true 的值的元素。如果找到这样的元素,findLastIndex 会立即返回该元素的索引。否则,findLastIndex 返回 -1。

更多信息见 FindViaPredicate

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. findRec 为 ? FindViaPredicate(O, len, descending, predicate, thisArg)。
  4. 返回 findRec.[[Index]]
注 2

该方法被设计为泛型;它不要求其 this 值为数组对象。因此它可以转移到其他类型对象用作方法。

23.1.3.12.1 FindViaPredicate ( O, len, direction, predicate, thisArg )

抽象操作 FindViaPredicate 接收参数 O(一个对象)、len(一个非负整数)、directionascendingdescending)、predicate(一个ECMAScript 语言值)、和 thisArg(一个ECMAScript 语言值),返回一个包含字段 [[Index]](一个整数)和 [[Value]](一个ECMAScript 语言值)的记录,或抛出完成类型的 异常

O 应为类数组对象TypedArray。该操作会按 direction 指示的顺序(升序或降序)对 O 的每个元素调用 predicate,直到找到一个 predicate 返回可转换为 true 的值的元素。此时,该操作返回一个包含所找到元素索引和值的记录。如果未找到这样的元素,则返回一个 记录,其索引为 -1𝔽,值为 undefined

predicate 应为一个函数。对数组的每个元素调用时,传递三个参数:元素的值、元素的索引和被遍历的对象。其返回值会被转换为布尔值。

thisArg 会作为每次调用 predicate 时的 this 值。

该操作不会直接修改其调用的对象,但该对象可能会被 predicate 的调用修改。

处理的元素范围在首次调用 predicate 前(遍历开始前)就已确定。遍历后添加到数组的元素不会被 predicate 访问。如果数组中已存在的元素被修改,则传递给 predicate 的值为操作访问该元素时的值。在遍历开始后被删除且尚未被访问的元素依然会被访问,要么从原型获取,要么为 undefined

调用时执行以下步骤:

  1. 如果 IsCallable(predicate) 为 false,抛出 TypeError 异常。
  2. 如果 directionascending,则
    1. indices 为从 0(含)到 len(不含)区间内所有整数按升序排列的列表
  3. 否则,
    1. indices 为从 0(含)到 len(不含)区间内所有整数按降序排列的列表
  4. 对于 indices 中的每个整数 k,执行
    1. Pk 为 ! ToString(𝔽(k))。
    2. 注:如果 OTypedArray,则下面对 Get 的调用会返回正常完成类型。
    3. kValue 为 ? Get(O, Pk)。
    4. testResult 为 ? Call(predicate, thisArg, « kValue, 𝔽(k), O »)。
    5. 如果 ToBoolean(testResult) 为 true,则返回 记录 { [[Index]]: 𝔽(k), [[Value]]: kValue }。
  5. 返回 记录 { [[Index]]: -1𝔽, [[Value]]: undefined }.

23.1.3.13 Array.prototype.flat ( [ depth ] )

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. sourceLen 为 ? LengthOfArrayLike(O)。
  3. depthNum 为 1。
  4. 如果 depth 不等于 undefined,则
    1. 设置 depthNum 为 ? ToIntegerOrInfinity(depth)。
    2. 如果 depthNum < 0,设置 depthNum 为 0。
  5. A 为 ? ArraySpeciesCreate(O, 0)。
  6. 执行 ? FlattenIntoArray(A, O, sourceLen, 0, depthNum)。
  7. 返回 A

23.1.3.13.1 FlattenIntoArray ( target, source, sourceLen, start, depth [ , mapperFunction [ , thisArg ] ] )

抽象操作 FlattenIntoArray 接收参数 target(一个对象)、source(一个对象)、sourceLen(一个非负整数)、start(一个非负整数)、depth(一个非负整数或+∞),可选参数 mapperFunction(一个函数对象)、thisArg(一个ECMAScript 语言值),返回包含非负整数的正常完成,或抛出完成。调用时执行以下步骤:

  1. 断言:如果 mapperFunction 存在,则 IsCallable(mapperFunction) 为 truethisArg 存在,且 depth 为 1。
  2. targetIndexstart
  3. sourceIndex+0𝔽
  4. 重复,直到 (sourceIndex) < sourceLen
    1. P 为 ! ToString(sourceIndex)。
    2. exists 为 ? HasProperty(source, P)。
    3. 如果 existstrue,则
      1. element 为 ? Get(source, P)。
      2. 如果 mapperFunction 存在,则
        1. 设置 element 为 ? Call(mapperFunction, thisArg, « element, sourceIndex, source »)。
      3. shouldFlattenfalse
      4. 如果 depth > 0,则
        1. 设置 shouldFlatten 为 ? IsArray(element)。
      5. 如果 shouldFlattentrue,则
        1. 如果 depth = +∞,令 newDepth 为 +∞。
        2. 否则,令 newDepthdepth - 1。
        3. elementLen 为 ? LengthOfArrayLike(element)。
        4. 设置 targetIndex 为 ? FlattenIntoArray(target, element, elementLen, targetIndex, newDepth)。
      6. 否则,
        1. 如果 targetIndex ≥ 253 - 1,抛出 TypeError 异常。
        2. 执行 ? CreateDataPropertyOrThrow(target, ! ToString(𝔽(targetIndex)), element)。
        3. 设置 targetIndextargetIndex + 1。
    4. 设置 sourceIndexsourceIndex + 1𝔽
  5. 返回 targetIndex

23.1.3.14 Array.prototype.flatMap ( mapperFunction [ , thisArg ] )

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. sourceLen 为 ? LengthOfArrayLike(O)。
  3. 如果 IsCallable(mapperFunction) 为 false,抛出 TypeError 异常。
  4. A 为 ? ArraySpeciesCreate(O, 0)。
  5. 执行 ? FlattenIntoArray(A, O, sourceLen, 0, 1, mapperFunction, thisArg)。
  6. 返回 A

23.1.3.15 Array.prototype.forEach ( callback [ , thisArg ] )

注 1

callback 应该是一个接受三个参数的函数。forEach 对数组中实际存在的每个元素按升序调用 callback 一次。callback 只会对数组中实际存在的元素调用,不会对数组中缺失的元素调用。

如果提供了 thisArg 参数,则每次调用 callback 时都会用作 this 值。如果未提供,则使用 undefined

callback 被调用时有三个参数:元素的值、元素的索引、被遍历的对象。

forEach 不会直接修改它所调用的对象,但该对象可能会被 callback 的调用修改。

forEach 处理的元素范围在第一次调用 callback 前就已确定。调用 forEach 之后添加到数组的元素不会被 callback 访问。如果数组中已存在的元素被修改,则传递给 callback 的值是在 forEach 访问该元素时的值;在 forEach 调用开始后被删除且尚未被访问的元素不会被访问。

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. 如果 IsCallable(callback) 为 false,抛出 TypeError 异常。
  4. k 为 0。
  5. 重复,直到 k < len
    1. Pk 为 ! ToString(𝔽(k))。
    2. kPresent 为 ? HasProperty(O, Pk)。
    3. 如果 kPresenttrue,则
      1. kValue 为 ? Get(O, Pk)。
      2. 执行 ? Call(callback, thisArg, « kValue, 𝔽(k), O »)。
    4. 设置 kk + 1。
  6. 返回 undefined
注 2

该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。

23.1.3.16 Array.prototype.includes ( searchElement [ , fromIndex ] )

注 1

该方法会按升序将 searchElement 与数组的元素进行比较,使用 SameValueZero 算法,如果在任何位置找到,则返回 true;否则返回 false

可选的第二个参数 fromIndex 默认为 +0𝔽(即搜索整个数组)。如果它大于等于数组长度,则返回 false,即不会搜索数组。如果小于 -0𝔽,则用作从数组末尾的偏移来计算 fromIndex。如果计算得到的索引小于等于 +0𝔽,则会搜索整个数组。

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. 如果 len = 0,返回 false
  4. n 为 ? ToIntegerOrInfinity(fromIndex)。
  5. 断言:如果 fromIndexundefined,则 n 为 0。
  6. 如果 n = +∞,返回 false
  7. 否则如果 n = -∞,设置 n 为 0。
  8. 如果 n ≥ 0,则
    1. kn
  9. 否则,
    1. klen + n
    2. 如果 k < 0,设置 k 为 0。
  10. 重复,直到 k < len
    1. elementK 为 ? Get(O, ! ToString(𝔽(k)))。
    2. 如果 SameValueZero(searchElement, elementK) 为 true,返回 true
    3. 设置 kk + 1。
  11. 返回 false
注 2

该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。

注 3

该方法有意与类似的 indexOf 方法有两点不同。第一,它使用 SameValueZero 算法,而不是 IsStrictlyEqual,从而可以检测 NaN 数组元素。第二,它不会跳过缺失的数组元素,而是将它们视为 undefined

23.1.3.17 Array.prototype.indexOf ( searchElement [ , fromIndex ] )

该方法使用 IsStrictlyEqual 算法,按升序将 searchElement 与数组中的元素进行比较,如果在一个或多个索引处找到,则返回最小的那个索引;否则返回 -1𝔽

注 1

可选的第二个参数 fromIndex 默认为 +0𝔽(即搜索整个数组)。如果它大于等于数组长度,则返回 -1𝔽,即不会搜索数组。如果它小于 -0𝔽,则用作从数组末尾的偏移来计算 fromIndex。如果计算得到的索引小于等于 +0𝔽,则会搜索整个数组。

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. 如果 len = 0,返回 -1𝔽
  4. n 为 ? ToIntegerOrInfinity(fromIndex)。
  5. 断言:如果 fromIndexundefined,则 n 为 0。
  6. 如果 n = +∞,返回 -1𝔽
  7. 否则如果 n = -∞,设置 n 为 0。
  8. 如果 n ≥ 0,则
    1. kn
  9. 否则,
    1. klen + n
    2. 如果 k < 0,设置 k 为 0。
  10. 重复,直到 k < len
    1. Pk 为 ! ToString(𝔽(k))。
    2. kPresent 为 ? HasProperty(O, Pk)。
    3. 如果 kPresenttrue,则
      1. elementK 为 ? Get(O, Pk)。
      2. 如果 IsStrictlyEqual(searchElement, elementK) 为 true,返回 𝔽(k)。
    4. 设置 kk + 1。
  11. 返回 -1𝔽
注 2

该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。

23.1.3.18 Array.prototype.join ( separator )

该方法将数组的元素转换为字符串,然后用 separator 分隔这些字符串并连接起来。如果没有提供分隔符,则使用单个逗号作为分隔符。

调用时按照以下步骤执行:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. 如果 separatorundefined,令 sep","
  4. 否则,令 sep 为 ? ToString(separator)。
  5. R 为空字符串。
  6. k 为 0。
  7. 重复,直到 k < len
    1. 如果 k > 0,令 R字符串拼接 Rsep 的结果。
    2. element 为 ? Get(O, ! ToString(𝔽(k)))。
    3. 如果 element 既不是 undefined 也不是 null,则
      1. S 为 ? ToString(element)。
      2. R字符串拼接 RS 的结果。
    4. 设置 kk + 1。
  8. 返回 R

该方法被设计为泛型;它不要求其 this 值为数组。因此,它可以被转移到其他类型的对象上用作方法。

23.1.3.19 Array.prototype.keys ( )

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. 返回 CreateArrayIterator(O, key)。

23.1.3.20 Array.prototype.lastIndexOf ( searchElement [ , fromIndex ] )

注 1

该方法会按降序将 searchElement 与数组的元素比较,使用 IsStrictlyEqual 算法,如果在一个或多个索引处找到,则返回最大的那个索引;否则返回 -1𝔽

可选的第二个参数 fromIndex 默认为数组长度减一(即搜索整个数组)。如果它大于等于数组长度,则会搜索整个数组。如果它小于 -0𝔽,则用作从数组末尾的偏移来计算 fromIndex。如果计算得到的索引小于等于 +0𝔽,则返回 -1𝔽

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. 如果 len = 0,返回 -1𝔽
  4. 如果 fromIndex 存在,令 n 为 ? ToIntegerOrInfinity(fromIndex); 否则令 nlen - 1。
  5. 如果 n = -∞,返回 -1𝔽
  6. 如果 n ≥ 0,则
    1. kmin(n, len - 1)。
  7. 否则,
    1. klen + n
  8. 重复,直到 k ≥ 0,
    1. Pk 为 ! ToString(𝔽(k))。
    2. kPresent 为 ? HasProperty(O, Pk)。
    3. 如果 kPresenttrue,则
      1. elementK 为 ? Get(O, Pk)。
      2. 如果 IsStrictlyEqual(searchElement, elementK) 为 true,返回 𝔽(k)。
    4. 设置 kk - 1。
  9. 返回 -1𝔽
注 2

该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。

23.1.3.21 Array.prototype.map ( callback [ , thisArg ] )

注 1

callback 应该是一个接受三个参数的函数。map 会按升序对数组中每个元素调用 callback 一次,并用结果构造一个新数组。callback 只会对数组中实际存在的元素调用,不会对数组中缺失的元素调用。

如果提供了 thisArg 参数,则每次调用 callback 时都会用作 this 值。如果未提供,则使用 undefined

callback 被调用时有三个参数:元素的值、元素的索引、被遍历的对象。

map 不会直接修改它所调用的对象,但该对象可能会被 callback 的调用修改。

map 处理的元素范围在第一次调用 callback 前就已确定。调用 map 之后添加到数组的元素不会被 callback 访问。如果数组中已存在的元素被修改,则传递给 callback 的值是在 map 访问该元素时的值;在 map 调用开始后被删除且尚未被访问的元素不会被访问。

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. 如果 IsCallable(callback) 为 false,抛出 TypeError 异常。
  4. A 为 ? ArraySpeciesCreate(O, len)。
  5. k 为 0。
  6. 重复,直到 k < len
    1. Pk 为 ! ToString(𝔽(k))。
    2. kPresent 为 ? HasProperty(O, Pk)。
    3. 如果 kPresenttrue,则
      1. kValue 为 ? Get(O, Pk)。
      2. mappedValue 为 ? Call(callback, thisArg, « kValue, 𝔽(k), O »)。
      3. 执行 ? CreateDataPropertyOrThrow(A, Pk, mappedValue)。
    4. 设置 kk + 1。
  7. 返回 A
注 2

该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。

23.1.3.22 Array.prototype.pop ( )

注 1

该方法移除数组的最后一个元素并返回它。

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. 如果 len = 0,则
    1. 执行 ? Set(O, "length", +0𝔽, true)。
    2. 返回 undefined
  4. 否则,
    1. 断言len > 0。
    2. newLen𝔽(len - 1)。
    3. index 为 ! ToString(newLen)。
    4. element 为 ? Get(O, index)。
    5. 执行 ? DeletePropertyOrThrow(O, index)。
    6. 执行 ? Set(O, "length", newLen, true)。
    7. 返回 element
注 2

该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。

23.1.3.23 Array.prototype.push ( ...items )

注 1

该方法将参数按出现顺序追加到数组末尾。它返回数组的新长度。

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. argCountitems 中元素的数量。
  4. 如果 len + argCount > 253 - 1,抛出 TypeError 异常。
  5. 对于 items 的每个元素 E,执行
    1. 执行 ? Set(O, ! ToString(𝔽(len)), E, true)。
    2. 设置 lenlen + 1。
  6. 执行 ? Set(O, "length", 𝔽(len), true)。
  7. 返回 𝔽(len)。

该方法的 "length" 属性为 1𝔽

注 2

该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。

23.1.3.24 Array.prototype.reduce ( callback [ , initialValue ] )

注 1

callback 应为一个接受四个参数的函数。reduce 会对数组中第一个元素之后的每个元素按升序以函数形式调用 callback 一次。

callback 被调用时带四个参数:previousValue(上次调用 callback 的值)、currentValue(当前元素的值)、currentIndex 和被遍历的对象。首次调用 callback 时,previousValuecurrentValue 可能有两种情况。如果调用 reduce 时提供了 initialValue,则 previousValueinitialValuecurrentValue 为数组的第一个值。如果没有提供 initialValue,则 previousValue 为数组的第一个值,currentValue 为第二个值。如果数组为空且未提供 initialValue,会抛出 TypeError

reduce 不会直接修改其调用的对象,但对象可能会被 callback 的调用修改。

reduce 处理的元素范围在第一次调用 callback 前就已确定。调用 reduce 后添加到数组的元素不会被 callback 访问。如果数组中已存在的元素被修改,则传递给 callback 的值为 reduce 访问该元素时的值;在 reduce 调用开始后被删除且尚未被访问的元素不会被访问。

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. 如果 IsCallable(callback) 为 false,抛出 TypeError 异常。
  4. 如果 len = 0 且 initialValue 不存在,抛出 TypeError 异常。
  5. k 为 0。
  6. accumulatorundefined
  7. 如果 initialValue 存在,则
    1. 设置 accumulatorinitialValue
  8. 否则,
    1. kPresentfalse
    2. 重复,直到 kPresentfalsek < len
      1. Pk 为 ! ToString(𝔽(k))。
      2. 设置 kPresent 为 ? HasProperty(O, Pk)。
      3. 如果 kPresenttrue,则
        1. 设置 accumulator 为 ? Get(O, Pk)。
      4. 设置 kk + 1。
    3. 如果 kPresentfalse,抛出 TypeError 异常。
  9. 重复,直到 k < len
    1. Pk 为 ! ToString(𝔽(k))。
    2. kPresent 为 ? HasProperty(O, Pk)。
    3. 如果 kPresenttrue,则
      1. kValue 为 ? Get(O, Pk)。
      2. 设置 accumulator 为 ? Call(callback, undefined, « accumulator, kValue, 𝔽(k), O »)。
    4. 设置 kk + 1。
  10. 返回 accumulator
注 2

该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。

23.1.3.25 Array.prototype.reduceRight ( callback [ , initialValue ] )

注 1

callback 应为一个接受四个参数的函数。reduceRight 会对数组中第一个元素之后的每个元素按降序以函数形式调用 callback 一次。

callback 被调用时带四个参数:previousValue(上次调用 callback 的值)、currentValue(当前元素的值)、currentIndex 和被遍历的对象。首次调用该函数时,previousValuecurrentValue 可能有两种情况。如果调用 reduceRight 时提供了 initialValue,则 previousValueinitialValuecurrentValue 为数组的最后一个值。如果没有提供 initialValue,则 previousValue 为数组的最后一个值,currentValue 为倒数第二个值。如果数组为空且未提供 initialValue,会抛出 TypeError

reduceRight 不会直接修改其调用的对象,但对象可能会被 callback 的调用修改。

reduceRight 处理的元素范围在第一次调用 callback 前就已确定。调用 reduceRight 后添加到数组的元素不会被 callback 访问。如果数组中已存在的元素被 callback 修改,则传递给 callback 的值为 reduceRight 访问该元素时的值;在 reduceRight 调用开始后被删除且尚未被访问的元素不会被访问。

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. 如果 IsCallable(callback) 为 false,抛出 TypeError 异常。
  4. 如果 len = 0 且 initialValue 不存在,抛出 TypeError 异常。
  5. klen - 1。
  6. accumulatorundefined
  7. 如果 initialValue 存在,则
    1. 设置 accumulatorinitialValue
  8. 否则,
    1. kPresentfalse
    2. 重复,直到 kPresentfalsek ≥ 0,
      1. Pk 为 ! ToString(𝔽(k))。
      2. 设置 kPresent 为 ? HasProperty(O, Pk)。
      3. 如果 kPresenttrue,则
        1. 设置 accumulator 为 ? Get(O, Pk)。
      4. 设置 kk - 1。
    3. 如果 kPresentfalse,抛出 TypeError 异常。
  9. 重复,直到 k ≥ 0,
    1. Pk 为 ! ToString(𝔽(k))。
    2. kPresent 为 ? HasProperty(O, Pk)。
    3. 如果 kPresenttrue,则
      1. kValue 为 ? Get(O, Pk)。
      2. 设置 accumulator 为 ? Call(callback, undefined, « accumulator, kValue, 𝔽(k), O »)。
    4. 设置 kk - 1。
  10. 返回 accumulator
注 2

该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。

23.1.3.26 Array.prototype.reverse ( )

注 1

该方法重新排列数组元素,使其顺序颠倒。它返回反转后的数组。

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. middlefloor(len / 2)。
  4. lower 为 0。
  5. 重复,直到 lowermiddle
    1. upperlen - lower - 1。
    2. upperP 为 ! ToString(𝔽(upper))。
    3. lowerP 为 ! ToString(𝔽(lower))。
    4. lowerExists 为 ? HasProperty(O, lowerP)。
    5. 如果 lowerExiststrue,则
      1. lowerValue 为 ? Get(O, lowerP)。
    6. upperExists 为 ? HasProperty(O, upperP)。
    7. 如果 upperExiststrue,则
      1. upperValue 为 ? Get(O, upperP)。
    8. 如果 lowerExiststrueupperExiststrue,则
      1. 执行 ? Set(O, lowerP, upperValue, true)。
      2. 执行 ? Set(O, upperP, lowerValue, true)。
    9. 否则如果 lowerExistsfalseupperExiststrue,则
      1. 执行 ? Set(O, lowerP, upperValue, true)。
      2. 执行 ? DeletePropertyOrThrow(O, upperP)。
    10. 否则如果 lowerExiststrueupperExistsfalse,则
      1. 执行 ? DeletePropertyOrThrow(O, lowerP)。
      2. 执行 ? Set(O, upperP, lowerValue, true)。
    11. 否则,
      1. 断言lowerExistsupperExists 都为 false
      2. 注:无操作需要执行。
    12. 设置 lowerlower + 1。
  6. 返回 O
注 2

该方法被设计为泛型;它不要求其 this 值为数组。因此,它可以被转移到其他类型的对象上用作方法。

23.1.3.27 Array.prototype.shift ( )

该方法移除数组的第一个元素并返回它。

调用时按照以下步骤执行:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. 如果 len = 0,则
    1. 执行 ? Set(O, "length", +0𝔽, true)。
    2. 返回 undefined
  4. first 为 ? Get(O, "0")。
  5. k 为 1。
  6. 重复,直到 k < len
    1. from 为 ! ToString(𝔽(k))。
    2. to 为 ! ToString(𝔽(k - 1))。
    3. fromPresent 为 ? HasProperty(O, from)。
    4. 如果 fromPresenttrue,则
      1. fromValue 为 ? Get(O, from)。
      2. 执行 ? Set(O, to, fromValue, true)。
    5. 否则,
      1. 断言fromPresentfalse
      2. 执行 ? DeletePropertyOrThrow(O, to)。
    6. 设置 kk + 1。
  7. 执行 ? DeletePropertyOrThrow(O, ! ToString(𝔽(len - 1)))。
  8. 执行 ? Set(O, "length", 𝔽(len - 1), true)。
  9. 返回 first

该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。

23.1.3.28 Array.prototype.slice ( start, end )

该方法返回一个包含数组从元素 start 到(但不包括)元素 end 的元素的新数组(如果 endundefined,则一直到数组末尾)。如果 start 为负数,则视为 length + start,其中 length 是数组长度。如果 end 为负数,则视为 length + end,其中 length 是数组长度。

调用时按照以下步骤执行:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. relativeStart 为 ? ToIntegerOrInfinity(start)。
  4. 如果 relativeStart = -∞,令 k 为 0。
  5. 否则如果 relativeStart < 0,令 kmax(len + relativeStart, 0)。
  6. 否则,令 kmin(relativeStart, len)。
  7. 如果 endundefined,令 relativeEndlen;否则令 relativeEnd 为 ? ToIntegerOrInfinity(end)。
  8. 如果 relativeEnd = -∞,令 final 为 0。
  9. 否则如果 relativeEnd < 0,令 finalmax(len + relativeEnd, 0)。
  10. 否则,令 finalmin(relativeEnd, len)。
  11. countmax(final - k, 0)。
  12. A 为 ? ArraySpeciesCreate(O, count)。
  13. n 为 0。
  14. 重复,直到 k < final
    1. Pk 为 ! ToString(𝔽(k))。
    2. kPresent 为 ? HasProperty(O, Pk)。
    3. 如果 kPresenttrue,则
      1. kValue 为 ? Get(O, Pk)。
      2. 执行 ? CreateDataPropertyOrThrow(A, ! ToString(𝔽(n)), kValue)。
    4. 设置 kk + 1。
    5. 设置 nn + 1。
  15. 执行 ? Set(A, "length", 𝔽(n), true)。
  16. 返回 A
注 1

15 步显式设置 "length" 属性,旨在确保即使 A 不是内建数组时长度也是正确的。

注 2

该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。

23.1.3.29 Array.prototype.some ( callback [ , thisArg ] )

注 1

callback 应为一个接受三个参数并返回可转换为布尔值的函数。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. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. 如果 IsCallable(callback) 为 false,抛出 TypeError 异常。
  4. k 为 0。
  5. 重复,直到 k < len
    1. Pk 为 ! ToString(𝔽(k))。
    2. kPresent 为 ? HasProperty(O, Pk)。
    3. 如果 kPresenttrue,则
      1. kValue 为 ? Get(O, Pk)。
      2. testResultToBoolean(? Call(callback, thisArg, « kValue, 𝔽(k), O »))。
      3. 如果 testResulttrue,返回 true
    4. 设置 kk + 1。
  6. 返回 false
注 2

该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。

23.1.3.30 Array.prototype.sort ( comparator )

该方法对数组的元素进行排序。如果 comparator 不为 undefined,则应为一个接受两个参数 xy 的函数,若 x < y,返回负数;若 x > y,返回正数;否则返回零。

调用时按照以下步骤执行:

  1. 如果 comparator 不为 undefinedIsCallable(comparator) 为 false,抛出 TypeError 异常。
  2. obj 为 ? ToObject(this 值)。
  3. len 为 ? LengthOfArrayLike(obj)。
  4. SortCompare 为一个新的 抽象闭包,带参数 (x, y),捕获 comparator 并在调用时执行以下步骤:
    1. 返回 ? CompareArrayElements(x, y, comparator)。
  5. sortedList 为 ? SortIndexedProperties(obj, len, SortCompare, skip-holes)。
  6. itemCountsortedList 中元素的数量。
  7. j 为 0。
  8. 重复,直到 j < itemCount
    1. 执行 ? Set(obj, ! ToString(𝔽(j)), sortedList[j], true)。
    2. 设置 jj + 1。
  9. 注:第 SortIndexedProperties 步骤(见 5)使用 skip-holes。剩余索引会被删除,以保留排序前检测到并排除的空洞数量。
  10. 重复,直到 j < len
    1. 执行 ? DeletePropertyOrThrow(obj, ! ToString(𝔽(j)))。
    2. 设置 jj + 1。
  11. 返回 obj
注 1

由于不存在的属性值总是大于 undefined 属性值,而 undefined 总是大于任何其他值(见 CompareArrayElements),undefined 属性值总是排序到结果的末尾,其后是不存在的属性值。

注 2

在第 56 步骤中由 ToString 抽象操作 执行的方法调用,可能导致 SortCompare 行为不是一个 一致性比较器

注 3

该方法被设计为泛型;它不要求其 this 值为数组。因此,它可以被转移到其他类型的对象上用作方法。

23.1.3.30.1 SortIndexedProperties ( obj, len, SortCompare, holes )

抽象操作 SortIndexedProperties 接收参数 obj(一个对象)、len(一个非负整数)、SortCompare(一个带有两个参数的抽象闭包)、holesskip-holesread-through-holes),返回包含List 的正常完成,或抛出完成。调用时执行以下步骤:

  1. items 为一个新的空List
  2. k 为 0。
  3. 重复,直到 k < len
    1. Pk 为 ! ToString(𝔽(k))。
    2. 如果 holesskip-holes,则
      1. kRead 为 ? HasProperty(obj, Pk)。
    3. 否则,
      1. 断言holesread-through-holes
      2. kReadtrue
    4. 如果 kReadtrue,则
      1. kValue 为 ? Get(obj, Pk)。
      2. kValue 添加到 items
    5. 设置 kk + 1。
  4. 使用实现定义SortCompare 的调用序列items 进行排序。如果此过程中有任何调用返回 异常完成,则在进行任何进一步调用 SortCompare 前停止并返回该 Completion Record
  5. 返回 items

排序顺序(sort order)指的是上述算法中第 4 步执行后 items 的排列顺序。若 SortCompare 不是 items 元素的 一致性比较器,则 排序顺序实现定义。当通过 Array.prototype.sortArray.prototype.toSorted 调用 SortIndexedProperties 时,如果 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] 表示执行后 items[j]。

抽象闭包或函数 comparator 对于值集合 S 来说,如果对集合 S 中所有可能的值 abc(可能相同)均满足以下要求,则称其为 一致性比较器。记号 a <C b 表示 (comparator(a, b)) < 0a =C b 表示 (comparator(a, b)) = 0a >C b 表示 (comparator(a, b)) > 0

  • 对于给定的 ab,每次调用 comparator(a, b) 总是返回相同的值 v。此外,v 是一个 Number,且 v 不是 NaN。这意味着对于一对 aba <C ba =C ba >C b 三者必有其一为真。
  • 调用 comparator(a, b) 不会修改 obj 或其原型链上的任何对象。
  • a =C a(自反性)
  • 如果 a =C b,则 b =C a(对称性)
  • 如果 a =C bb =C c,则 a =C c(传递性)
  • 如果 a <C bb <C c,则 a <C c(传递性)
  • 如果 a >C bb >C c,则 a >C c(传递性)

上述条件是保证 comparator 将集合 S 划分为等价类并且这些等价类是全序所必需且充分的条件。

23.1.3.30.2 CompareArrayElements ( x, y, comparator )

抽象操作 CompareArrayElements 接收参数 x(一个ECMAScript 语言值)、y(一个ECMAScript 语言值)、comparator(一个函数对象undefined),返回包含Number 的正常完成,或异常完成。调用时执行以下步骤:

  1. 如果 xy 都是 undefined,返回 +0𝔽
  2. 如果 xundefined,返回 1𝔽
  3. 如果 yundefined,返回 -1𝔽
  4. 如果 comparator 不为 undefined,则
    1. v 为 ? ToNumber(? Call(comparator, undefined, « x, y »))。
    2. 如果 vNaN,返回 +0𝔽
    3. 返回 v
  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 )

注 1

该方法从整数索引 start 开始,删除数组中的 deleteCount 个元素,并用 items 的元素替换它们。它返回一个包含被删除元素(如有)的数组。

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. relativeStart 为 ? ToIntegerOrInfinity(start)。
  4. 如果 relativeStart = -∞,令 actualStart 为 0。
  5. 否则如果 relativeStart < 0,令 actualStartmax(len + relativeStart, 0)。
  6. 否则,令 actualStartmin(relativeStart, len)。
  7. itemCountitems 中元素的数量。
  8. 如果未传入 start,则
    1. actualDeleteCount 为 0。
  9. 否则如果未传入 deleteCount,则
    1. actualDeleteCountlen - actualStart
  10. 否则,
    1. dc 为 ? ToIntegerOrInfinity(deleteCount)。
    2. actualDeleteCount 为将 dc 限制在 0 到 len - actualStart 之间的结果。
  11. 如果 len + itemCount - actualDeleteCount > 253 - 1,抛出 TypeError 异常。
  12. A 为 ? ArraySpeciesCreate(O, actualDeleteCount)。
  13. k 为 0。
  14. 重复,直到 k < actualDeleteCount
    1. from 为 ! ToString(𝔽(actualStart + k))。
    2. 如果 ? HasProperty(O, from) 为 true,则
      1. fromValue 为 ? Get(O, from)。
      2. 执行 ? CreateDataPropertyOrThrow(A, ! ToString(𝔽(k)), fromValue)。
    3. 设置 kk + 1。
  15. 执行 ? Set(A, "length", 𝔽(actualDeleteCount), true)。
  16. 如果 itemCount < actualDeleteCount,则
    1. 设置 kactualStart
    2. 重复,直到 k < (len - actualDeleteCount),
      1. from 为 ! ToString(𝔽(k + actualDeleteCount))。
      2. to 为 ! ToString(𝔽(k + itemCount))。
      3. 如果 ? HasProperty(O, from) 为 true,则
        1. fromValue 为 ? Get(O, from)。
        2. 执行 ? Set(O, to, fromValue, true)。
      4. 否则,
        1. 执行 ? DeletePropertyOrThrow(O, to)。
      5. 设置 kk + 1。
    3. 设置 klen
    4. 重复,直到 k > (len - actualDeleteCount + itemCount),
      1. 执行 ? DeletePropertyOrThrow(O, ! ToString(𝔽(k - 1)))。
      2. 设置 kk - 1。
  17. 否则如果 itemCount > actualDeleteCount,则
    1. 设置 k 为 (len - actualDeleteCount)。
    2. 重复,直到 k > actualStart
      1. from 为 ! ToString(𝔽(k + actualDeleteCount - 1))。
      2. to 为 ! ToString(𝔽(k + itemCount - 1))。
      3. 如果 ? HasProperty(O, from) 为 true,则
        1. fromValue 为 ? Get(O, from)。
        2. 执行 ? Set(O, to, fromValue, true)。
      4. 否则,
        1. 执行 ? DeletePropertyOrThrow(O, to)。
      5. 设置 kk - 1。
  18. 设置 kactualStart
  19. 对于 items 的每个元素 E,执行
    1. 执行 ? Set(O, ! ToString(𝔽(k)), E, true)。
    2. 设置 kk + 1。
  20. 执行 ? Set(O, "length", 𝔽(len - actualDeleteCount + itemCount), true)。
  21. 返回 A
注 2

在第 1520 步中显式设置 "length" 属性,旨在确保即使操作对象不是内建数组时长度也是正确的。

注 3

该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。

23.1.3.32 Array.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] )

包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按照 ECMA-402 规范实现此方法。如果 ECMAScript 实现不包含 ECMA-402 API,则使用下面对该方法的规范。

注 1

ECMA-402 第一版未包含该方法的替代规范。

此方法的可选参数含义在 ECMA-402 规范中定义;不包含 ECMA-402 支持的实现不得将这些参数位置用于其他用途。

该方法调用时执行以下步骤:

  1. array 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(array)。
  3. separator 为适用于 宿主环境当前区域设置的 实现定义列表分隔符字符串值(如 ", ")。
  4. R 为空字符串。
  5. k 为 0。
  6. 重复,直到 k < len
    1. 如果 k > 0,令 R字符串拼接 Rseparator 的结果。
    2. element 为 ? Get(array, ! ToString(𝔽(k)))。
    3. 如果 element 既不是 undefined 也不是 null,则
      1. S 为 ? ToString(? Invoke(element, "toLocaleString"))。
      2. R字符串拼接 RS 的结果。
    4. 设置 kk + 1。
  7. 返回 R
注 2

该方法使用元素各自的 toLocaleString 方法将数组元素转换为字符串,然后用实现定义的、区分区域设置的分隔符字符串把这些字符串连接起来。此方法类似于 toString,但目的是生成符合 宿主环境当前区域习惯的本地化结果。

注 3

该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。

23.1.3.33 Array.prototype.toReversed ( )

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. A 为 ? ArrayCreate(len)。
  4. k 为 0。
  5. 重复,直到 k < len
    1. from 为 ! ToString(𝔽(len - k - 1))。
    2. Pk 为 ! ToString(𝔽(k))。
    3. fromValue 为 ? Get(O, from)。
    4. 执行 ! CreateDataPropertyOrThrow(A, Pk, fromValue)。
    5. 设置 kk + 1。
  6. 返回 A

23.1.3.34 Array.prototype.toSorted ( comparator )

该方法调用时执行以下步骤:

  1. 如果 comparator 不为 undefinedIsCallable(comparator) 为 false,抛出 TypeError 异常。
  2. O 为 ? ToObject(this 值)。
  3. len 为 ? LengthOfArrayLike(O)。
  4. A 为 ? ArrayCreate(len)。
  5. SortCompare 为一个新的 抽象闭包,带参数 (x, y),捕获 comparator 并在调用时执行以下步骤:
    1. 返回 ? CompareArrayElements(x, y, comparator)。
  6. sortedList 为 ? SortIndexedProperties(O, len, SortCompare, read-through-holes)。
  7. j 为 0。
  8. 重复,直到 j < len
    1. 执行 ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(j)), sortedList[j])。
    2. 设置 jj + 1。
  9. 返回 A

23.1.3.35 Array.prototype.toSpliced ( start, skipCount, ...items )

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. relativeStart 为 ? ToIntegerOrInfinity(start)。
  4. 如果 relativeStart = -∞,令 actualStart 为 0。
  5. 否则如果 relativeStart < 0,令 actualStartmax(len + relativeStart, 0)。
  6. 否则,令 actualStartmin(relativeStart, len)。
  7. insertCountitems 中元素的数量。
  8. 如果未传入 start,则
    1. actualSkipCount 为 0。
  9. 否则如果未传入 skipCount,则
    1. actualSkipCountlen - actualStart
  10. 否则,
    1. sc 为 ? ToIntegerOrInfinity(skipCount)。
    2. actualSkipCount 为将 sc 限制在 0 到 len - actualStart 之间的结果。
  11. newLenlen + insertCount - actualSkipCount
  12. 如果 newLen > 253 - 1,抛出 TypeError 异常。
  13. A 为 ? ArrayCreate(newLen)。
  14. i 为 0。
  15. ractualStart + actualSkipCount
  16. 重复,直到 i < actualStart
    1. Pi 为 ! ToString(𝔽(i))。
    2. iValue 为 ? Get(O, Pi)。
    3. 执行 ! CreateDataPropertyOrThrow(A, Pi, iValue)。
    4. 设置 ii + 1。
  17. 对于 items 的每个元素 E,执行
    1. Pi 为 ! ToString(𝔽(i))。
    2. 执行 ! CreateDataPropertyOrThrow(A, Pi, E)。
    3. 设置 ii + 1。
  18. 重复,直到 i < newLen
    1. Pi 为 ! ToString(𝔽(i))。
    2. from 为 ! ToString(𝔽(r))。
    3. fromValue 为 ? Get(O, from)。
    4. 执行 ! CreateDataPropertyOrThrow(A, Pi, fromValue)。
    5. 设置 ii + 1。
    6. 设置 rr + 1。
  19. 返回 A

23.1.3.36 Array.prototype.toString ( )

该方法调用时执行以下步骤:

  1. array 为 ? ToObject(this 值)。
  2. func 为 ? Get(array, "join")。
  3. 如果 IsCallable(func) 为 false,则将 func 设为内建函数 %Object.prototype.toString%。
  4. 返回 ? Call(func, array)。

该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。

23.1.3.37 Array.prototype.unshift ( ...items )

该方法将参数添加到数组的开头,其在数组中的顺序与参数列表中的顺序相同。

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. argCountitems 中元素的数量。
  4. 如果 argCount > 0,则
    1. 如果 len + argCount > 253 - 1,抛出 TypeError 异常。
    2. klen
    3. 重复,直到 k > 0,
      1. from 为 ! ToString(𝔽(k - 1))。
      2. to 为 ! ToString(𝔽(k + argCount - 1))。
      3. fromPresent 为 ? HasProperty(O, from)。
      4. 如果 fromPresenttrue,则
        1. fromValue 为 ? Get(O, from)。
        2. 执行 ? Set(O, to, fromValue, true)。
      5. 否则,
        1. 断言: fromPresentfalse
        2. 执行 ? DeletePropertyOrThrow(O, to)。
      6. 设置 kk - 1。
    4. j+0𝔽
    5. 对于 items 的每个元素 E,执行
      1. 执行 ? Set(O, ! ToString(j), E, true)。
      2. 设置 jj + 1𝔽
  5. 执行 ? Set(O, "length", 𝔽(len + argCount), true)。
  6. 返回 𝔽(len + argCount)。

该方法的 "length" 属性为 1𝔽

该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。

23.1.3.38 Array.prototype.values ( )

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. 返回 CreateArrayIterator(O, value)。

23.1.3.39 Array.prototype.with ( index, value )

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. relativeIndex 为 ? ToIntegerOrInfinity(index)。
  4. 如果 relativeIndex ≥ 0,令 actualIndexrelativeIndex
  5. 否则,令 actualIndexlen + relativeIndex
  6. 如果 actualIndexlenactualIndex < 0,抛出 RangeError 异常。
  7. A 为 ? ArrayCreate(len)。
  8. k 为 0。
  9. 重复,直到 k < len
    1. Pk 为 ! ToString(𝔽(k))。
    2. 如果 k = actualIndex,令 fromValuevalue
    3. 否则,令 fromValue 为 ? Get(O, Pk)。
    4. 执行 ! CreateDataPropertyOrThrow(A, Pk, fromValue)。
    5. 设置 kk + 1。
  10. 返回 A

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 }。

该对象的自有属性名是在 ECMAScript 2015 规范之前未作为 Array.prototype 标准属性包含的属性名。这些名称在 with 语句绑定时会被忽略,以保持现有代码的行为,这些代码可能在外部作用域中使用其中的某个名称作为绑定,而该作用域被 with 语句(其绑定对象为数组)所遮蔽。

"with" 未被包含在 unscopableList 中的原因是它已经是一个 保留字

23.1.4 数组实例的属性

数组实例是 数组特异对象,并具有为此类对象指定的内部方法。数组实例继承自 Array 原型对象 的属性。

数组实例有一个 "length" 属性,以及一组带有 数组索引 名称的可枚举属性。

23.1.4.1 length

Array 实例的 "length" 属性是一个 数据属性,其值总是数值上大于每个名称为 数组索引、且可配置的自有属性的名称。

"length" 属性最初拥有属性 { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }。

减少 "length" 属性的值会导致删除其 数组索引 介于旧值和新值之间的自有数组元素。但不可配置属性不能被删除。试图将数组的 "length" 属性设置为小于或等于现有不可配置 数组索引属性的最大数值自有 属性名 时,length 会被设置为比该不可配置数值自有 属性名 大 1 的数值。见 10.4.2.1

23.1.5 数组迭代器对象

数组迭代器是一个表示对某个特定数组实例对象的特定迭代的对象。数组迭代器对象没有命名的 构造函数。数组迭代器对象是通过调用数组实例对象的某些方法创建的。

23.1.5.1 CreateArrayIterator ( array, kind )

抽象操作 CreateArrayIterator 接收参数 array(一个对象)和 kindkey+valuekeyvalue),返回一个对象。用于为返回此类 迭代器 的 Array 方法创建 迭代器对象。调用时执行以下步骤:

  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. Othis 值。
  2. 如果 O 不是对象,抛出 TypeError 异常。
  3. 如果 O 不具有 数组迭代器实例(23.1.5.3)的所有内部槽,抛出 TypeError 异常。
  4. arrayO.[[IteratedArrayLike]]
  5. 如果 arrayundefined,返回 CreateIteratorResultObject(undefined, true)。
  6. indexO.[[ArrayLikeNextIndex]]
  7. kindO.[[ArrayLikeIterationKind]]
  8. 如果 array 具有 [[TypedArrayName]] 内部槽,则
    1. taRecordMakeTypedArrayWithBufferWitnessRecord(array, seq-cst)。
    2. 如果 IsTypedArrayOutOfBounds(taRecord) 为 true,抛出 TypeError 异常。
    3. lenTypedArrayLength(taRecord)。
  9. 否则,
    1. len 为 ? LengthOfArrayLike(array)。
  10. 如果 indexlen,则
    1. 设置 O.[[IteratedArrayLike]]undefined
    2. 返回 CreateIteratorResultObject(undefined, true)。
  11. 设置 O.[[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% 属性的初始值为字符串值 "Array Iterator"

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

23.1.5.3 数组迭代器实例的属性

数组迭代器实例是 普通对象,继承自 %ArrayIteratorPrototype% 内建对象的属性。数组迭代器实例创建时具有 表 74 中列出的内部槽。

表 74:数组迭代器实例的内部槽
内部槽 类型 描述
[[IteratedArrayLike]] 一个对象或 undefined 被迭代的 类数组对象
[[ArrayLikeNextIndex]] 非负整数 迭代器要检查的下一个元素的整数索引
[[ArrayLikeIterationKind]] key+valuekeyvalue 标识每次迭代返回什么类型值的值。

23.2 TypedArray 对象

TypedArray 展示了一个底层二进制数据缓冲区(25.1)的类数组视图。TypedArray 元素类型是所有 TypedArray 实例元素所具有的底层二进制标量数据类型。每种支持的元素类型都有一个不同的 TypedArray 构造函数,见 表 75表 75 中的每个 构造函数 都有一个对应的不同的原型对象。

表 75: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% 内建对象:

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. Cthis 值。
  2. 如果 IsConstructor(C) 为 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. lenvalues 中元素的数量。
    3. targetObj 为 ? TypedArrayCreateFromConstructor(C, « 𝔽(len) »)。
    4. k 为 0。
    5. 重复,直到 k < len
      1. Pk 为 ! ToString(𝔽(k))。
      2. kValuevalues 的第一个元素。
      3. values 移除第一个元素。
      4. 如果 mappingtrue,则
        1. mappedValue 为 ? Call(mapper, thisArg, « kValue, 𝔽(k) »)。
      5. 否则,
        1. mappedValuekValue
      6. 执行 ? Set(targetObj, Pk, mappedValue, true)。
      7. 设置 kk + 1。
    6. 断言values 现在是一个空的 List
    7. 返回 targetObj
  7. 注:source 不是 可迭代对象,所以假定它已经是 类数组对象
  8. arrayLike 为 ! ToObject(source)。
  9. len 为 ? LengthOfArrayLike(arrayLike)。
  10. targetObj 为 ? TypedArrayCreateFromConstructor(C, « 𝔽(len) »)。
  11. k 为 0。
  12. 重复,直到 k < len
    1. Pk 为 ! ToString(𝔽(k))。
    2. kValue 为 ? Get(arrayLike, Pk)。
    3. 如果 mappingtrue,则
      1. mappedValue 为 ? Call(mapper, thisArg, « kValue, 𝔽(k) »)。
    4. 否则,
      1. mappedValuekValue
    5. 执行 ? Set(targetObj, Pk, mappedValue, true)。
    6. 设置 kk + 1。
  13. 返回 targetObj

23.2.2.2 %TypedArray%.of ( ...items )

该方法被调用时执行以下步骤:

  1. lenitems 中元素的数量。
  2. Cthis 值。
  3. 如果 IsConstructor(C) 为 false,抛出 TypeError 异常。
  4. newObj 为 ? TypedArrayCreateFromConstructor(C, « 𝔽(len) »)。
  5. k 为 0。
  6. 重复,直到 k < len
    1. kValueitems[k]。
    2. Pk 为 ! ToString(𝔽(k))。
    3. 执行 ? Set(newObj, Pk, kValue, true)。
    4. 设置 kk + 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]"

%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. Othis 值。
  2. taRecord 为 ? ValidateTypedArray(O, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. relativeIndex 为 ? ToIntegerOrInfinity(index)。
  5. 如果 relativeIndex ≥ 0,则
    1. krelativeIndex
  6. 否则,
    1. klen + relativeIndex
  7. 如果 k < 0 或 klen,返回 undefined
  8. 返回 ! Get(O, ! ToString(𝔽(k)))。

23.2.3.2 get %TypedArray%.prototype.buffer

%TypedArray%.prototype.buffer 是一个 访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数被调用时执行以下步骤:

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[TypedArrayName]])。
  3. 断言O 具有 [[ViewedArrayBuffer]] 内部槽。
  4. bufferO.[[ViewedArrayBuffer]]
  5. 返回 buffer

23.2.3.3 get %TypedArray%.prototype.byteLength

%TypedArray%.prototype.byteLength 是一个 访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数被调用时执行以下步骤:

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[TypedArrayName]])。
  3. 断言O 具有 [[ViewedArrayBuffer]] 内部槽。
  4. taRecordMakeTypedArrayWithBufferWitnessRecord(O, seq-cst)。
  5. sizeTypedArrayByteLength(taRecord)。
  6. 返回 𝔽(size)。

23.2.3.4 get %TypedArray%.prototype.byteOffset

%TypedArray%.prototype.byteOffset 是一个 访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数被调用时执行以下步骤:

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[TypedArrayName]])。
  3. 断言O 具有 [[ViewedArrayBuffer]] 内部槽。
  4. taRecordMakeTypedArrayWithBufferWitnessRecord(O, seq-cst)。
  5. 如果 IsTypedArrayOutOfBounds(taRecord) 为 true,返回 +0𝔽
  6. offsetO.[[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. Othis 值。
  2. taRecord 为 ? ValidateTypedArray(O, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. relativeTarget 为 ? ToIntegerOrInfinity(target)。
  5. 如果 relativeTarget = -∞,令 targetIndex 为 0。
  6. 否则如果 relativeTarget < 0,令 targetIndexmax(len + relativeTarget, 0)。
  7. 否则,令 targetIndexmin(relativeTarget, len)。
  8. relativeStart 为 ? ToIntegerOrInfinity(start)。
  9. 如果 relativeStart = -∞,令 startIndex 为 0。
  10. 否则如果 relativeStart < 0,令 startIndexmax(len + relativeStart, 0)。
  11. 否则,令 startIndexmin(relativeStart, len)。
  12. 如果 endundefined,令 relativeEndlen;否则令 relativeEnd 为 ? ToIntegerOrInfinity(end)。
  13. 如果 relativeEnd = -∞,令 endIndex 为 0。
  14. 否则如果 relativeEnd < 0,令 endIndexmax(len + relativeEnd, 0)。
  15. 否则,令 endIndexmin(relativeEnd, len)。
  16. countmin(endIndex - startIndex, len - targetIndex)。
  17. 如果 count > 0,则
    1. 注:拷贝操作必须以保持源数据比特级编码的方式执行。
    2. bufferO.[[ViewedArrayBuffer]]
    3. 设置 taRecordMakeTypedArrayWithBufferWitnessRecord(O, seq-cst)。
    4. 如果 IsTypedArrayOutOfBounds(taRecord) 为 true,抛出 TypeError 异常。
    5. 设置 lenTypedArrayLength(taRecord)。
    6. elementSizeTypedArrayElementSize(O)。
    7. byteOffsetO.[[ByteOffset]]
    8. bufferByteLimit 为 (len × elementSize) + byteOffset
    9. toByteIndex 为 (targetIndex × elementSize) + byteOffset
    10. fromByteIndex 为 (startIndex × elementSize) + byteOffset
    11. countBytescount × elementSize
    12. 如果 fromByteIndex < toByteIndextoByteIndex < fromByteIndex + countBytes,则
      1. direction 为 -1。
      2. 设置 fromByteIndexfromByteIndex + countBytes - 1。
      3. 设置 toByteIndextoByteIndex + countBytes - 1。
    13. 否则,
      1. direction 为 1。
    14. 重复,直到 countBytes > 0,
      1. 如果 fromByteIndex < bufferByteLimittoByteIndex < bufferByteLimit,则
        1. valueGetValueFromBuffer(buffer, fromByteIndex, uint8, true, unordered)。
        2. 执行 SetValueInBuffer(buffer, toByteIndex, uint8, value, true, unordered)。
        3. 设置 fromByteIndexfromByteIndex + direction
        4. 设置 toByteIndextoByteIndex + direction
        5. 设置 countBytescountBytes - 1。
      2. 否则,
        1. 设置 countBytes 为 0。
  18. 返回 O

23.2.3.7 %TypedArray%.prototype.entries ( )

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. 执行 ? ValidateTypedArray(O, seq-cst)。
  3. 返回 CreateArrayIterator(O, key+value)。

23.2.3.8 %TypedArray%.prototype.every ( callback [ , thisArg ] )

该方法的参数解释和用法与 23.1.3.6 中定义的 Array.prototype.every 相同。

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. taRecord 为 ? ValidateTypedArray(O, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. 如果 IsCallable(callback) 为 false,抛出 TypeError 异常。
  5. k 为 0。
  6. 重复,直到 k < len
    1. Pk 为 ! ToString(𝔽(k))。
    2. kValue 为 ! Get(O, Pk)。
    3. testResultToBoolean(? Call(callback, thisArg, « kValue, 𝔽(k), O »))。
    4. 如果 testResultfalse,返回 false
    5. 设置 kk + 1。
  7. 返回 true

该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。

23.2.3.9 %TypedArray%.prototype.fill ( value [ , start [ , end ] ] )

该方法的参数解释和用法与 23.1.3.7 中定义的 Array.prototype.fill 相同。

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. taRecord 为 ? ValidateTypedArray(O, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. 如果 O.[[ContentType]]bigint,将 value 设为 ? ToBigInt(value)。
  5. 否则,将 value 设为 ? ToNumber(value)。
  6. relativeStart 为 ? ToIntegerOrInfinity(start)。
  7. 如果 relativeStart = -∞,令 startIndex 为 0。
  8. 否则如果 relativeStart < 0,令 startIndexmax(len + relativeStart, 0)。
  9. 否则,令 startIndexmin(relativeStart, len)。
  10. 如果 endundefined,令 relativeEndlen;否则令 relativeEnd 为 ? ToIntegerOrInfinity(end)。
  11. 如果 relativeEnd = -∞,令 endIndex 为 0。
  12. 否则如果 relativeEnd < 0,令 endIndexmax(len + relativeEnd, 0)。
  13. 否则,令 endIndexmin(relativeEnd, len)。
  14. 设置 taRecordMakeTypedArrayWithBufferWitnessRecord(O, seq-cst)。
  15. 如果 IsTypedArrayOutOfBounds(taRecord) 为 true,抛出 TypeError 异常。
  16. 设置 lenTypedArrayLength(taRecord)。
  17. 设置 endIndexmin(endIndex, len)。
  18. kstartIndex
  19. 重复,直到 k < endIndex
    1. Pk 为 ! ToString(𝔽(k))。
    2. 执行 ! Set(O, Pk, value, true)。
    3. 设置 kk + 1。
  20. 返回 O

23.2.3.10 %TypedArray%.prototype.filter ( callback [ , thisArg ] )

该方法的参数解释和用法与 23.1.3.8 中定义的 Array.prototype.filter 相同。

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. taRecord 为 ? ValidateTypedArray(O, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. 如果 IsCallable(callback) 为 false,抛出 TypeError 异常。
  5. kept 为一个新的空 List
  6. captured 为 0。
  7. k 为 0。
  8. 重复,直到 k < len
    1. Pk 为 ! ToString(𝔽(k))。
    2. kValue 为 ! Get(O, Pk)。
    3. selectedToBoolean(? Call(callback, thisArg, « kValue, 𝔽(k), O »))。
    4. 如果 selectedtrue,则
      1. kValue 添加到 kept
      2. 设置 capturedcaptured + 1。
    5. 设置 kk + 1。
  9. A 为 ? TypedArraySpeciesCreate(O, « 𝔽(captured) »)。
  10. n 为 0。
  11. 对于 kept 的每个元素 e,执行
    1. 执行 ! Set(A, ! ToString(𝔽(n)), e, true)。
    2. 设置 nn + 1。
  12. 返回 A

该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。

23.2.3.11 %TypedArray%.prototype.find ( predicate [ , thisArg ] )

该方法的参数解释和用法与 23.1.3.9 中定义的 Array.prototype.find 相同。

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. taRecord 为 ? ValidateTypedArray(O, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. findRec 为 ? FindViaPredicate(O, len, ascending, predicate, thisArg)。
  5. 返回 findRec.[[Value]]

该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。

23.2.3.12 %TypedArray%.prototype.findIndex ( predicate [ , thisArg ] )

该方法的参数解释和用法与 23.1.3.10 中定义的 Array.prototype.findIndex 相同。

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. taRecord 为 ? ValidateTypedArray(O, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. findRec 为 ? FindViaPredicate(O, len, ascending, predicate, thisArg)。
  5. 返回 findRec.[[Index]]

该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。

23.2.3.13 %TypedArray%.prototype.findLast ( predicate [ , thisArg ] )

该方法的参数解释和用法与 23.1.3.11 中定义的 Array.prototype.findLast 相同。

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. taRecord 为 ? ValidateTypedArray(O, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. findRec 为 ? FindViaPredicate(O, len, descending, predicate, thisArg)。
  5. 返回 findRec.[[Value]]

该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。

23.2.3.14 %TypedArray%.prototype.findLastIndex ( predicate [ , thisArg ] )

该方法的参数解释和用法与 23.1.3.12 中定义的 Array.prototype.findLastIndex 相同。

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. taRecord 为 ? ValidateTypedArray(O, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. findRec 为 ? FindViaPredicate(O, len, descending, predicate, thisArg)。
  5. 返回 findRec.[[Index]]

该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。

23.2.3.15 %TypedArray%.prototype.forEach ( callback [ , thisArg ] )

该方法的参数解释和用法与 23.1.3.15 中定义的 Array.prototype.forEach 相同。

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. taRecord 为 ? ValidateTypedArray(O, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. 如果 IsCallable(callback) 为 false,抛出 TypeError 异常。
  5. k 为 0。
  6. 重复,直到 k < len
    1. Pk 为 ! ToString(𝔽(k))。
    2. kValue 为 ! Get(O, Pk)。
    3. 执行 ? Call(callback, thisArg, « kValue, 𝔽(k), O »)。
    4. 设置 kk + 1。
  7. 返回 undefined

该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。

23.2.3.16 %TypedArray%.prototype.includes ( searchElement [ , fromIndex ] )

该方法的参数解释和用法与 23.1.3.16 中定义的 Array.prototype.includes 相同。

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. taRecord 为 ? ValidateTypedArray(O, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. 如果 len = 0,返回 false
  5. n 为 ? ToIntegerOrInfinity(fromIndex)。
  6. 断言:如果 fromIndexundefined,则 n 为 0。
  7. 如果 n = +∞,返回 false
  8. 否则如果 n = -∞,设置 n 为 0。
  9. 如果 n ≥ 0,则
    1. kn
  10. 否则,
    1. klen + n
    2. 如果 k < 0,设置 k 为 0。
  11. 重复,直到 k < len
    1. elementK 为 ! Get(O, ! ToString(𝔽(k)))。
    2. 如果 SameValueZero(searchElement, elementK) 为 true,返回 true
    3. 设置 kk + 1。
  12. 返回 false

该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。

23.2.3.17 %TypedArray%.prototype.indexOf ( searchElement [ , fromIndex ] )

该方法的参数解释和用法与 23.1.3.17 中定义的 Array.prototype.indexOf 相同。

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. taRecord 为 ? ValidateTypedArray(O, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. 如果 len = 0,返回 -1𝔽
  5. n 为 ? ToIntegerOrInfinity(fromIndex)。
  6. 断言:如果 fromIndexundefined,则 n 为 0。
  7. 如果 n = +∞,返回 -1𝔽
  8. 否则如果 n = -∞,设置 n 为 0。
  9. 如果 n ≥ 0,则
    1. kn
  10. 否则,
    1. klen + n
    2. 如果 k < 0,设置 k 为 0。
  11. 重复,直到 k < len
    1. Pk 为 ! ToString(𝔽(k))。
    2. kPresent 为 ! HasProperty(O, Pk)。
    3. 如果 kPresenttrue,则
      1. elementK 为 ! Get(O, Pk)。
      2. 如果 IsStrictlyEqual(searchElement, elementK) 为 true,返回 𝔽(k)。
    4. 设置 kk + 1。
  12. 返回 -1𝔽

该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。

23.2.3.18 %TypedArray%.prototype.join ( separator )

该方法的参数解释和用法与 23.1.3.18 中定义的 Array.prototype.join 相同。

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. taRecord 为 ? ValidateTypedArray(O, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. 如果 separatorundefined,令 sep","
  5. 否则,令 sep 为 ? ToString(separator)。
  6. R 为空字符串。
  7. k 为 0。
  8. 重复,直到 k < len
    1. 如果 k > 0,令 R字符串拼接 Rsep 的结果。
    2. element 为 ! Get(O, ! ToString(𝔽(k)))。
    3. 如果 element 不为 undefined,则
      1. S 为 ! ToString(element)。
      2. R字符串拼接 RS 的结果。
    4. 设置 kk + 1。
  9. 返回 R

该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。

23.2.3.19 %TypedArray%.prototype.keys ( )

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. 执行 ? ValidateTypedArray(O, seq-cst)。
  3. 返回 CreateArrayIterator(O, key)。

23.2.3.20 %TypedArray%.prototype.lastIndexOf ( searchElement [ , fromIndex ] )

该方法的参数解释和用法与 23.1.3.20 中定义的 Array.prototype.lastIndexOf 相同。

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. taRecord 为 ? ValidateTypedArray(O, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. 如果 len = 0,返回 -1𝔽
  5. 如果 fromIndex 被传入,令 n 为 ? ToIntegerOrInfinity(fromIndex);否则令 nlen - 1。
  6. 如果 n = -∞,返回 -1𝔽
  7. 如果 n ≥ 0,则
    1. kmin(n, len - 1)。
  8. 否则,
    1. klen + n
  9. 重复,直到 k ≥ 0,
    1. Pk 为 ! ToString(𝔽(k))。
    2. kPresent 为 ! HasProperty(O, Pk)。
    3. 如果 kPresenttrue,则
      1. elementK 为 ! Get(O, Pk)。
      2. 如果 IsStrictlyEqual(searchElement, elementK) 为 true,返回 𝔽(k)。
    4. 设置 kk - 1。
  10. 返回 -1𝔽

该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。

23.2.3.21 get %TypedArray%.prototype.length

%TypedArray%.prototype.length 是一个 访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数被调用时执行以下步骤:

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[TypedArrayName]])。
  3. 断言O 拥有 [[ViewedArrayBuffer]][[ArrayLength]] 内部槽。
  4. taRecordMakeTypedArrayWithBufferWitnessRecord(O, 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. Othis 值。
  2. taRecord 为 ? ValidateTypedArray(O, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. 如果 IsCallable(callback) 为 false,抛出 TypeError 异常。
  5. A 为 ? TypedArraySpeciesCreate(O, « 𝔽(len) »)。
  6. k 为 0。
  7. 重复,直到 k < len
    1. Pk 为 ! ToString(𝔽(k))。
    2. kValue 为 ! Get(O, Pk)。
    3. mappedValue 为 ? Call(callback, thisArg, « kValue, 𝔽(k), O »)。
    4. 执行 ? Set(A, Pk, mappedValue, true)。
    5. 设置 kk + 1。
  8. 返回 A

该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。

23.2.3.23 %TypedArray%.prototype.reduce ( callback [ , initialValue ] )

该方法的参数解释和用法与 23.1.3.24 中定义的 Array.prototype.reduce 相同。

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. taRecord 为 ? ValidateTypedArray(O, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. 如果 IsCallable(callback) 为 false,抛出 TypeError 异常。
  5. 如果 len = 0 且未传入 initialValue,抛出 TypeError 异常。
  6. k 为 0。
  7. accumulatorundefined
  8. 如果 initialValue 被传入,则
    1. accumulator 设为 initialValue
  9. 否则,
    1. Pk 为 ! ToString(𝔽(k))。
    2. accumulator 设为 ! Get(O, Pk)。
    3. 设置 kk + 1。
  10. 重复,直到 k < len
    1. Pk 为 ! ToString(𝔽(k))。
    2. kValue 为 ! Get(O, Pk)。
    3. accumulator 设为 ? Call(callback, undefined, « accumulator, kValue, 𝔽(k), O »)。
    4. 设置 kk + 1。
  11. 返回 accumulator

该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。

23.2.3.24 %TypedArray%.prototype.reduceRight ( callback [ , initialValue ] )

该方法的参数解释和用法与 23.1.3.25 中定义的 Array.prototype.reduceRight 相同。

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. taRecord 为 ? ValidateTypedArray(O, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. 如果 IsCallable(callback) 为 false,抛出 TypeError 异常。
  5. 如果 len = 0 且未传入 initialValue,抛出 TypeError 异常。
  6. klen - 1。
  7. accumulatorundefined
  8. 如果 initialValue 被传入,则
    1. accumulator 设为 initialValue
  9. 否则,
    1. Pk 为 ! ToString(𝔽(k))。
    2. accumulator 设为 ! Get(O, Pk)。
    3. 设置 kk - 1。
  10. 重复,直到 k ≥ 0,
    1. Pk 为 ! ToString(𝔽(k))。
    2. kValue 为 ! Get(O, Pk)。
    3. accumulator 设为 ? Call(callback, undefined, « accumulator, kValue, 𝔽(k), O »)。
    4. 设置 kk - 1。
  11. 返回 accumulator

该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。

23.2.3.25 %TypedArray%.prototype.reverse ( )

该方法的参数解释和用法与 23.1.3.26 中定义的 Array.prototype.reverse 相同。

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. taRecord 为 ? ValidateTypedArray(O, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. middlefloor(len / 2)。
  5. lower 为 0。
  6. 重复,直到 lowermiddle
    1. upperlen - lower - 1。
    2. upperP 为 ! ToString(𝔽(upper))。
    3. lowerP 为 ! ToString(𝔽(lower))。
    4. lowerValue 为 ! Get(O, lowerP)。
    5. upperValue 为 ! Get(O, upperP)。
    6. 执行 ! Set(O, lowerP, upperValue, true)。
    7. 执行 ! Set(O, upperP, lowerValue, true)。
    8. 设置 lowerlower + 1。
  7. 返回 O

该方法不是泛型的。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]] 内部槽的 对象,则
    1. 执行 ? SetTypedArrayFromTypedArray(target, targetOffset, source)。
  7. 否则,
    1. 执行 ? SetTypedArrayFromArrayLike(target, targetOffset, source)。
  8. 返回 undefined

该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。

23.2.3.26.1 SetTypedArrayFromTypedArray ( target, targetOffset, source )

抽象操作 SetTypedArrayFromTypedArray 接收参数 target(一个 TypedArray)、targetOffset(一个非负 整数或 +∞)、source(一个 TypedArray),并返回 正常完成,包含 unused抛出完成。它会在 target 从索引 targetOffset 开始,读取 source 的值设置多个值。调用时执行以下步骤:

  1. targetBuffertarget.[[ViewedArrayBuffer]]
  2. targetRecordMakeTypedArrayWithBufferWitnessRecord(target, seq-cst)。
  3. 如果 IsTypedArrayOutOfBounds(targetRecord) 为 true,抛出 TypeError 异常。
  4. targetLengthTypedArrayLength(targetRecord)。
  5. srcBuffersource.[[ViewedArrayBuffer]]
  6. srcRecordMakeTypedArrayWithBufferWitnessRecord(source, seq-cst)。
  7. 如果 IsTypedArrayOutOfBounds(srcRecord) 为 true,抛出 TypeError 异常。
  8. srcLengthTypedArrayLength(srcRecord)。
  9. targetTypeTypedArrayElementType(target)。
  10. targetElementSizeTypedArrayElementSize(target)。
  11. targetByteOffsettarget.[[ByteOffset]]
  12. srcTypeTypedArrayElementType(source)。
  13. srcElementSizeTypedArrayElementSize(source)。
  14. srcByteOffsetsource.[[ByteOffset]]
  15. 如果 targetOffset = +∞,抛出 RangeError 异常。
  16. 如果 srcLength + targetOffset > targetLength,抛出 RangeError 异常。
  17. 如果 target.[[ContentType]] 不等于 source.[[ContentType]],抛出 TypeError 异常。
  18. 如果 IsSharedArrayBuffer(srcBuffer) 为 trueIsSharedArrayBuffer(targetBuffer) 为 true,并且 srcBuffer.[[ArrayBufferData]] 等于 targetBuffer.[[ArrayBufferData]],则令 sameSharedArrayBuffertrue;否则,令 sameSharedArrayBufferfalse
  19. 如果 SameValue(srcBuffer, targetBuffer) 为 truesameSharedArrayBuffertrue,则
    1. srcByteLengthTypedArrayByteLength(srcRecord)。
    2. srcBuffer 设为 ? CloneArrayBuffer(srcBuffer, srcByteOffset, srcByteLength)。
    3. srcByteIndex 为 0。
  20. 否则,
    1. srcByteIndexsrcByteOffset
  21. targetByteIndex 为 (targetOffset × targetElementSize) + targetByteOffset
  22. limittargetByteIndex + (targetElementSize × srcLength)。
  23. 如果 srcType 等于 targetType,则
    1. 注:传输操作必须以保持源数据比特级编码的方式执行。
    2. 重复,直到 targetByteIndex < limit
      1. valueGetValueFromBuffer(srcBuffer, srcByteIndex, uint8, true, unordered)。
      2. 执行 SetValueInBuffer(targetBuffer, targetByteIndex, uint8, value, true, unordered)。
      3. 设置 srcByteIndexsrcByteIndex + 1。
      4. 设置 targetByteIndextargetByteIndex + 1。
  24. 否则,
    1. 重复,直到 targetByteIndex < limit
      1. valueGetValueFromBuffer(srcBuffer, srcByteIndex, srcType, true, unordered)。
      2. 执行 SetValueInBuffer(targetBuffer, targetByteIndex, targetType, value, true, unordered)。
      3. 设置 srcByteIndexsrcByteIndex + srcElementSize
      4. 设置 targetByteIndextargetByteIndex + targetElementSize
  25. 返回 unused

23.2.3.26.2 SetTypedArrayFromArrayLike ( target, targetOffset, source )

抽象操作 SetTypedArrayFromArrayLike 接收参数 target(一个 TypedArray)、targetOffset(一个非负 整数或 +∞)、source(一个 ECMAScript 语言值,但不是 TypedArray),并返回 正常完成,包含 unused抛出完成。它会在 target 从索引 targetOffset 开始,读取 source 的值设置多个值。调用时执行以下步骤:

  1. targetRecordMakeTypedArrayWithBufferWitnessRecord(target, seq-cst)。
  2. 如果 IsTypedArrayOutOfBounds(targetRecord) 为 true,抛出 TypeError 异常。
  3. targetLengthTypedArrayLength(targetRecord)。
  4. src 为 ? ToObject(source)。
  5. srcLength 为 ? LengthOfArrayLike(src)。
  6. 如果 targetOffset = +∞,抛出 RangeError 异常。
  7. 如果 srcLength + targetOffset > targetLength,抛出 RangeError 异常。
  8. k 为 0。
  9. 重复,直到 k < srcLength
    1. Pk 为 ! ToString(𝔽(k))。
    2. value 为 ? Get(src, Pk)。
    3. targetIndex𝔽(targetOffset + k)。
    4. 执行 ? TypedArraySetElement(target, targetIndex, value)。
    5. 设置 kk + 1。
  10. 返回 unused

23.2.3.27 %TypedArray%.prototype.slice ( start, end )

该方法的参数解释和用法与 23.1.3.28 中定义的 Array.prototype.slice 相同。

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. taRecord 为 ? ValidateTypedArray(O, seq-cst)。
  3. srcArrayLengthTypedArrayLength(taRecord)。
  4. relativeStart 为 ? ToIntegerOrInfinity(start)。
  5. 如果 relativeStart = -∞,令 startIndex 为 0。
  6. 否则如果 relativeStart < 0,令 startIndexmax(srcArrayLength + relativeStart, 0)。
  7. 否则,令 startIndexmin(relativeStart, srcArrayLength)。
  8. 如果 endundefined,令 relativeEndsrcArrayLength;否则令 relativeEnd 为 ? ToIntegerOrInfinity(end)。
  9. 如果 relativeEnd = -∞,令 endIndex 为 0。
  10. 否则如果 relativeEnd < 0,令 endIndexmax(srcArrayLength + relativeEnd, 0)。
  11. 否则,令 endIndexmin(relativeEnd, srcArrayLength)。
  12. countBytesmax(endIndex - startIndex, 0)。
  13. A 为 ? TypedArraySpeciesCreate(O, « 𝔽(countBytes) »)。
  14. 如果 countBytes > 0,则
    1. 设置 taRecordMakeTypedArrayWithBufferWitnessRecord(O, seq-cst)。
    2. 如果 IsTypedArrayOutOfBounds(taRecord) 为 true,抛出 TypeError 异常。
    3. 设置 endIndexmin(endIndex, TypedArrayLength(taRecord))。
    4. 设置 countBytesmax(endIndex - startIndex, 0)。
    5. srcTypeTypedArrayElementType(O)。
    6. targetTypeTypedArrayElementType(A)。
    7. 如果 srcType 等于 targetType,则
      1. 注:传输操作必须以保持源数据比特级编码的方式执行。
      2. srcBufferO.[[ViewedArrayBuffer]]
      3. targetBufferA.[[ViewedArrayBuffer]]
      4. elementSizeTypedArrayElementSize(O)。
      5. srcByteOffsetO.[[ByteOffset]]
      6. srcByteIndex 为 (startIndex × elementSize) + srcByteOffset
      7. targetByteIndexA.[[ByteOffset]]
      8. endByteIndextargetByteIndex + (countBytes × elementSize)。
      9. 重复,直到 targetByteIndex < endByteIndex
        1. valueGetValueFromBuffer(srcBuffer, srcByteIndex, uint8, true, unordered)。
        2. 执行 SetValueInBuffer(targetBuffer, targetByteIndex, uint8, value, true, unordered)。
        3. 设置 srcByteIndexsrcByteIndex + 1。
        4. 设置 targetByteIndextargetByteIndex + 1。
    8. 否则,
      1. n 为 0。
      2. kstartIndex
      3. 重复,直到 k < endIndex
        1. Pk 为 ! ToString(𝔽(k))。
        2. kValue 为 ! Get(O, Pk)。
        3. 执行 ! Set(A, ! ToString(𝔽(n)), kValue, true)。
        4. 设置 kk + 1。
        5. 设置 nn + 1。
  15. 返回 A

该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。

23.2.3.28 %TypedArray%.prototype.some ( callback [ , thisArg ] )

该方法的参数解释和用法与 23.1.3.29 中定义的 Array.prototype.some 相同。

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. taRecord 为 ? ValidateTypedArray(O, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. 如果 IsCallable(callback) 为 false,抛出 TypeError 异常。
  5. k 为 0。
  6. 重复,直到 k < len
    1. Pk 为 ! ToString(𝔽(k))。
    2. kValue 为 ! Get(O, Pk)。
    3. testResultToBoolean(? Call(callback, thisArg, « kValue, 𝔽(k), O »))。
    4. 如果 testResulttrue,返回 true
    5. 设置 kk + 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. lenTypedArrayLength(taRecord)。
  5. 注:以下闭包执行数值比较,而不是 23.1.3.30 中使用的字符串比较。
  6. SortCompare 为一个新的 抽象闭包,带参数 (x, y),捕获 comparator 并在调用时执行以下步骤:
    1. 返回 ? CompareTypedArrayElements(x, y, comparator)。
  7. sortedList 为 ? SortIndexedProperties(obj, len, SortCompare, read-through-holes)。
  8. j 为 0。
  9. 重复,直到 j < len
    1. 执行 ! Set(obj, ! ToString(𝔽(j)), sortedList[j], true)。
    2. 设置 jj + 1。
  10. 返回 obj

由于 NaN 总是大于任何其他值(见 CompareTypedArrayElements),当 comparator 未提供时,NaN 属性值总是排在结果的末尾。

23.2.3.30 %TypedArray%.prototype.subarray ( start, end )

该方法返回一个新的 TypedArray,其元素类型与此 TypedArray 的元素类型相同,ArrayBuffer 也与此 TypedArray 相同,引用 start(包含)到 end(不包含)区间内的元素。如果 startend 为负数,则它表示从数组末尾开始的索引,而不是从头开始。

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[TypedArrayName]])。
  3. 断言O 拥有 [[ViewedArrayBuffer]] 内部槽。
  4. bufferO.[[ViewedArrayBuffer]]
  5. srcRecordMakeTypedArrayWithBufferWitnessRecord(O, seq-cst)。
  6. 如果 IsTypedArrayOutOfBounds(srcRecord) 为 true,则
    1. srcLength 为 0。
  7. 否则,
    1. srcLengthTypedArrayLength(srcRecord)。
  8. relativeStart 为 ? ToIntegerOrInfinity(start)。
  9. 如果 relativeStart = -∞,令 startIndex 为 0。
  10. 否则如果 relativeStart < 0,令 startIndexmax(srcLength + relativeStart, 0)。
  11. 否则,令 startIndexmin(relativeStart, srcLength)。
  12. elementSizeTypedArrayElementSize(O)。
  13. srcByteOffsetO.[[ByteOffset]]
  14. beginByteOffsetsrcByteOffset + (startIndex × elementSize)。
  15. 如果 O.[[ArrayLength]]autoendundefined,则
    1. argumentsList 为 « buffer, 𝔽(beginByteOffset) »。
  16. 否则,
    1. 如果 endundefined,令 relativeEndsrcLength;否则令 relativeEnd 为 ? ToIntegerOrInfinity(end)。
    2. 如果 relativeEnd = -∞,令 endIndex 为 0。
    3. 否则如果 relativeEnd < 0,令 endIndexmax(srcLength + relativeEnd, 0)。
    4. 否则,令 endIndexmin(relativeEnd, srcLength)。
    5. newLengthmax(endIndex - startIndex, 0)。
    6. argumentsList 为 « buffer, 𝔽(beginByteOffset), 𝔽(newLength) »。
  17. 返回 ? TypedArraySpeciesCreate(O, argumentsList)。

该方法不是泛型的。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。如果其结果是 异常完成,则抛出该异常而不是执行算法。

如果 ECMAScript 实现包含 ECMA-402 国际化 API,则该方法基于 ECMA-402 规范中的 Array.prototype.toLocaleString 算法。

23.2.3.32 %TypedArray%.prototype.toReversed ( )

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. taRecord 为 ? ValidateTypedArray(O, seq-cst)。
  3. lengthTypedArrayLength(taRecord)。
  4. A 为 ? TypedArrayCreateSameType(O, « 𝔽(length) »)。
  5. k 为 0。
  6. 重复,直到 k < length
    1. from 为 ! ToString(𝔽(length - k - 1))。
    2. Pk 为 ! ToString(𝔽(k))。
    3. fromValue 为 ! Get(O, from)。
    4. 执行 ! Set(A, Pk, fromValue, true)。
    5. 设置 kk + 1。
  7. 返回 A

23.2.3.33 %TypedArray%.prototype.toSorted ( comparator )

该方法被调用时执行以下步骤:

  1. 如果 comparator 不为 undefinedIsCallable(comparator) 为 false,抛出 TypeError 异常。
  2. Othis 值。
  3. taRecord 为 ? ValidateTypedArray(O, seq-cst)。
  4. lenTypedArrayLength(taRecord)。
  5. A 为 ? TypedArrayCreateSameType(O, « 𝔽(len) »)。
  6. 注:以下闭包执行数值比较,而不是 23.1.3.34 中使用的字符串比较。
  7. SortCompare 为一个新的 抽象闭包,带参数 (x, y),捕获 comparator 并在调用时执行以下步骤:
    1. 返回 ? CompareTypedArrayElements(x, y, comparator)。
  8. sortedList 为 ? SortIndexedProperties(O, len, SortCompare, read-through-holes)。
  9. j 为 0。
  10. 重复,直到 j < len
    1. 执行 ! Set(A, ! ToString(𝔽(j)), sortedList[j], true)。
    2. 设置 jj + 1。
  11. 返回 A

23.2.3.34 %TypedArray%.prototype.toString ( )

"toString" 属性的初始值是 %Array.prototype.toString%,定义见 23.1.3.36

23.2.3.35 %TypedArray%.prototype.values ( )

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. 执行 ? ValidateTypedArray(O, seq-cst)。
  3. 返回 CreateArrayIterator(O, value)。

23.2.3.36 %TypedArray%.prototype.with ( index, value )

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. taRecord 为 ? ValidateTypedArray(O, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. relativeIndex 为 ? ToIntegerOrInfinity(index)。
  5. 如果 relativeIndex ≥ 0,令 actualIndexrelativeIndex
  6. 否则,令 actualIndexlen + relativeIndex
  7. 如果 O.[[ContentType]]bigint,令 numericValue 为 ? ToBigInt(value)。
  8. 否则,令 numericValue 为 ? ToNumber(value)。
  9. 如果 IsValidIntegerIndex(O, 𝔽(actualIndex)) 为 false,抛出 RangeError 异常。
  10. A 为 ? TypedArrayCreateSameType(O, « 𝔽(len) »)。
  11. k 为 0。
  12. 重复,直到 k < len
    1. Pk 为 ! ToString(𝔽(k))。
    2. 如果 k = actualIndex,令 fromValuenumericValue
    3. 否则,令 fromValue 为 ! Get(O, Pk)。
    4. 执行 ! Set(A, Pk, fromValue, true)。
    5. 设置 kk + 1。
  13. 返回 A

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. Othis 值。
  2. 如果 O 不是对象,返回 undefined
  3. 如果 O 没有 [[TypedArrayName]] 内部槽,返回 undefined
  4. nameO.[[TypedArrayName]]
  5. 断言name 是字符串
  6. 返回 name

该属性具有属性 { [[Enumerable]]: false, [[Configurable]]: true }。

该函数的 "name" 属性的初始值为 "get [Symbol.toStringTag]"

23.2.4 TypedArray 对象的抽象操作

23.2.4.1 TypedArraySpeciesCreate ( exemplar, argumentList )

抽象操作 TypedArraySpeciesCreate 接收参数 exemplar(一个 TypedArray)和 argumentList(一个 List,元素为 ECMAScript 语言值),返回 正常完成,包含一个 TypedArray抛出完成。它用于指定用从 exemplar 派生的 构造函数 创建新的 TypedArray。与 ArraySpeciesCreate 可以通过 %Symbol.species% 创建非数组对象不同,此操作强制要求该 构造函数 必须创建实际的 TypedArray。调用时执行以下步骤:

  1. defaultConstructor表 75 中与 exemplar.[[TypedArrayName]] 同名的内建对象。
  2. constructor 为 ? SpeciesConstructor(exemplar, defaultConstructor)。
  3. result 为 ? TypedArrayCreateFromConstructor(constructor, argumentList)。
  4. 断言result 拥有 [[TypedArrayName]][[ContentType]] 内部槽。
  5. 如果 result.[[ContentType]] 不等于 exemplar.[[ContentType]],抛出 TypeError 异常。
  6. 返回 result

23.2.4.2 TypedArrayCreateFromConstructor ( constructor, argumentList )

抽象操作 TypedArrayCreateFromConstructor 接收参数 constructor(一个 构造函数)和 argumentList(一个 List,元素为ECMAScript 语言值),返回 正常完成,包含一个 TypedArray抛出完成。它用于指定用 构造函数 创建新的 TypedArray。调用时执行以下步骤:

  1. newTypedArray 为 ? Construct(constructor, argumentList)。
  2. taRecord 为 ? ValidateTypedArray(newTypedArray, seq-cst)。
  3. 如果 argumentList 的元素数量为 1 且 argumentList[0] 是数字,则
    1. 如果 IsTypedArrayOutOfBounds(taRecord) 为 true,抛出 TypeError 异常。
    2. lengthTypedArrayLength(taRecord)。
    3. 如果 length < (argumentList[0]),抛出 TypeError 异常。
  4. 返回 newTypedArray

23.2.4.3 TypedArrayCreateSameType ( exemplar, argumentList )

抽象操作 TypedArrayCreateSameType 接收参数 exemplar(一个 TypedArray)和 argumentList(一个 List,元素为ECMAScript 语言值),返回 正常完成,包含一个 TypedArray抛出完成。它用于指定用从 exemplar 派生的 构造函数 创建新的 TypedArray。与 TypedArraySpeciesCreate 能通过 %Symbol.species% 构造自定义 TypedArray 子类不同,此操作始终使用内建 TypedArray 构造函数。调用时执行以下步骤:

  1. constructor表 75 中与 exemplar.[[TypedArrayName]] 同名的内建对象。
  2. result 为 ? TypedArrayCreateFromConstructor(constructor, argumentList)。
  3. 断言result 拥有 [[TypedArrayName]][[ContentType]] 内部槽。
  4. 断言result.[[ContentType]] 等于 exemplar.[[ContentType]]
  5. 返回 result

23.2.4.4 ValidateTypedArray ( O, order )

抽象操作 ValidateTypedArray 接收参数 O(一个 ECMAScript 语言值)和 orderseq-cstunordered),返回 正常完成,包含一个 TypedArray 带缓冲区见证记录抛出完成。调用时执行以下步骤:

  1. 执行 ? RequireInternalSlot(O, [[TypedArrayName]])。
  2. 断言O 拥有 [[ViewedArrayBuffer]] 内部槽。
  3. taRecordMakeTypedArrayWithBufferWitnessRecord(O, order)。
  4. 如果 IsTypedArrayOutOfBounds(taRecord) 为 true,抛出 TypeError 异常。
  5. 返回 taRecord

23.2.4.5 TypedArrayElementSize ( O )

抽象操作 TypedArrayElementSize 接收参数 O(一个 TypedArray),返回一个非负整数。调用时执行以下步骤:

  1. 返回 表 75O.[[TypedArrayName]] 指定的元素大小值。

23.2.4.6 TypedArrayElementType ( O )

抽象操作 TypedArrayElementType 接收参数 O(一个 TypedArray),返回 TypedArray 元素类型。调用时执行以下步骤:

  1. 返回 表 75O.[[TypedArrayName]] 指定的元素类型值。

23.2.4.7 CompareTypedArrayElements ( x, y, comparator )

抽象操作 CompareTypedArrayElements 接收参数 x(一个 Number 或 BigInt)、y(一个 Number 或 BigInt)、comparator(一个 函数对象undefined),返回 正常完成,包含一个 Number 或 异常完成。调用时执行以下步骤:

  1. 断言x 是 Numbery 是 Number,或者 x 是 BigInty 是 BigInt
  2. 如果 comparator 不为 undefined,则
    1. v 为 ? ToNumber(? Call(comparator, undefined, « x, y »))。
    2. 如果 vNaN,返回 +0𝔽
    3. 返回 v
  3. 如果 xy 都是 NaN,返回 +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𝔽
这执行的是数值比较,而不是 23.1.3.30.2 中的字符串比较。

23.2.5 TypedArray 构造函数

每个 TypedArray 构造函数

  • 是一个内建对象,结构如下所述,唯一的区别是 构造函数 名称不同于 TypedArray,见 表 75
  • 是一个函数,其行为会根据参数的数量和类型而异。对 TypedArray 的实际调用行为取决于传递给它的参数数量和类型。
  • 不应作为普通函数调用,否则会抛出异常。
  • 可以用作类定义的 extends 子句的值。想要继承指定 TypedArray 行为的子类 构造函数 必须包含对 TypedArray 构造函数super 调用,以用必要的内部状态创建和初始化子类实例,以支持 %TypedArray%.prototype 内建方法。

23.2.5.1 TypedArray ( ...args )

每个 TypedArray 构造函数 被调用时执行以下步骤:

  1. 如果 NewTarget 为 undefined,抛出 TypeError 异常。
  2. constructorName表 75 中为此 TypedArray 构造函数 指定的 构造函数 名称的字符串值。
  3. proto"%TypedArray.prototype%"
  4. numberOfArgsargs 的元素数量。
  5. 如果 numberOfArgs = 0,则
    1. 返回 ? AllocateTypedArray(constructorName, NewTarget, proto, 0)。
  6. 否则,
    1. firstArgumentargs[0]。
    2. 如果 firstArgument 是对象,则
      1. O 为 ? AllocateTypedArray(constructorName, NewTarget, proto)。
      2. 如果 firstArgument[[TypedArrayName]] 内部槽,则
        1. 执行 ? InitializeTypedArrayFromTypedArray(O, firstArgument)。
      3. 否则如果 firstArgument[[ArrayBufferData]] 内部槽,则
        1. 如果 numberOfArgs > 1,令 byteOffsetargs[1];否则令 byteOffsetundefined
        2. 如果 numberOfArgs > 2,令 lengthargs[2];否则令 lengthundefined
        3. 执行 ? InitializeTypedArrayFromArrayBuffer(O, firstArgument, byteOffset, length)。
      4. 否则,
        1. 断言firstArgument 是对象firstArgument 没有 [[TypedArrayName]][[ArrayBufferData]] 内部槽。
        2. usingIterator 为 ? GetMethod(firstArgument, %Symbol.iterator%)。
        3. 如果 usingIterator 不为 undefined,则
          1. values 为 ? IteratorToList(? GetIteratorFromMethod(firstArgument, usingIterator))。
          2. 执行 ? InitializeTypedArrayFromList(O, values)。
        4. 否则,
          1. 注:firstArgument 不是 可迭代对象,所以假定它已经是 类数组对象
          2. 执行 ? InitializeTypedArrayFromArrayLike(O, firstArgument)。
      5. 返回 O
    3. 否则,
      1. 断言firstArgument 不是对象
      2. elementLength 为 ? ToIndex(firstArgument)。
      3. 返回 ? AllocateTypedArray(constructorName, NewTarget, proto, elementLength)。

23.2.5.1.1 AllocateTypedArray ( constructorName, newTarget, defaultProto [ , length ] )

抽象操作 AllocateTypedArray 接收参数 constructorName(一个字符串,为 TypedArray 构造函数名称,见 表 75),newTarget(一个 构造函数),defaultProto(一个字符串),可选参数 length(一个非负整数),返回 正常完成,包含一个 TypedArray抛出完成。用于校验并创建 TypedArray 构造函数 的实例。如果传入了 length,还会分配一个相应长度的 ArrayBuffer,并与新的 TypedArray 实例关联。AllocateTypedArray 提供了 TypedArray 共享的通用语义。调用时执行以下步骤:

  1. proto 为 ? GetPrototypeFromConstructor(newTarget, defaultProto)。
  2. objTypedArrayCreate(proto)。
  3. 断言obj.[[ViewedArrayBuffer]]undefined
  4. 设置 obj.[[TypedArrayName]]constructorName
  5. 如果 constructorName"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 ( O, srcArray )

抽象操作 InitializeTypedArrayFromTypedArray 接收参数 O(一个 TypedArray)和 srcArray(一个 TypedArray),返回 正常完成,包含 unused抛出完成。调用时执行以下步骤:

  1. srcDatasrcArray.[[ViewedArrayBuffer]]
  2. elementTypeTypedArrayElementType(O)。
  3. elementSizeTypedArrayElementSize(O)。
  4. srcTypeTypedArrayElementType(srcArray)。
  5. srcElementSizeTypedArrayElementSize(srcArray)。
  6. srcByteOffsetsrcArray.[[ByteOffset]]
  7. srcRecordMakeTypedArrayWithBufferWitnessRecord(srcArray, seq-cst)。
  8. 如果 IsTypedArrayOutOfBounds(srcRecord) 为 true,抛出 TypeError 异常。
  9. elementLengthTypedArrayLength(srcRecord)。
  10. byteLengthelementSize × elementLength
  11. 如果 elementType 等于 srcType,则
    1. data 为 ? CloneArrayBuffer(srcData, srcByteOffset, byteLength)。
  12. 否则,
    1. data 为 ? AllocateArrayBuffer(%ArrayBuffer%, byteLength)。
    2. 如果 srcArray.[[ContentType]] 不等于 O.[[ContentType]],抛出 TypeError 异常。
    3. srcByteIndexsrcByteOffset
    4. targetByteIndex 为 0。
    5. countelementLength
    6. 重复,直到 count > 0,
      1. valueGetValueFromBuffer(srcData, srcByteIndex, srcType, true, unordered)。
      2. 执行 SetValueInBuffer(data, targetByteIndex, elementType, value, true, unordered)。
      3. 设置 srcByteIndexsrcByteIndex + srcElementSize
      4. 设置 targetByteIndextargetByteIndex + elementSize
      5. 设置 countcount - 1。
  13. 设置 O.[[ViewedArrayBuffer]]data
  14. 设置 O.[[ByteLength]]byteLength
  15. 设置 O.[[ByteOffset]] 为 0。
  16. 设置 O.[[ArrayLength]]elementLength
  17. 返回 unused

23.2.6 TypedArray 构造函数的属性

每个 TypedArray 构造函数

  • 拥有一个 [[Prototype]] 内部槽,其值为 %TypedArray%
  • 有一个 "length" 属性,其值为 3𝔽
  • 有一个 "name" 属性,其值为 构造函数表 75 中为其指定的字符串值。
  • 拥有以下属性:

23.2.6.1 TypedArray.BYTES_PER_ELEMENT

TypedArray.BYTES_PER_ELEMENT 的值为 表 75 中为 TypedArray 指定的元素大小值。

该属性具有属性 { [[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 的值为 表 75 中为 TypedArray 指定的元素大小值。

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

23.2.7.2 TypedArray.prototype.constructor

某给定 TypedArray 构造函数的原型的 "constructor" 属性的初始值为该 构造函数 本身。

23.2.8 TypedArray 实例的属性

TypedArray 实例是 TypedArrays。每个 TypedArray 实例继承自对应的 TypedArray 原型对象。每个 TypedArray 实例都有如下内部槽:[[TypedArrayName]][[ViewedArrayBuffer]][[ByteLength]][[ByteOffset]][[ArrayLength]]

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)。

如果参数 iterable 存在,期望它是一个实现了 %Symbol.iterator% 方法的对象,该方法返回一个 迭代器对象,它会生成一个包含两个元素的 类数组对象,第一个元素将用作 Map 的键,第二个元素作为与该键关联的值。

24.1.1.2 AddEntriesFromIterable ( target, iterable, adder )

抽象操作 AddEntriesFromIterable 接收参数 target(一个对象)、iterableECMAScript 语言值,但不是 undefinednull)、adder(一个 函数对象),返回 正常完成,包含一个 ECMAScript 语言值抛出完成adder 调用时其接收者为 target。调用时执行以下步骤:

  1. iteratorRecord 为 ? GetIterator(iterable, sync)。
  2. 重复,
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 nextdone,返回 target
    3. 如果 next 不是对象,则
      1. errorThrowCompletion(一个新创建的 TypeError 对象)。
      2. 返回 ? IteratorClose(iteratorRecord, error)。
    4. kCompletion(Get(next, "0"))。
    5. IfAbruptCloseIterator(k, iteratorRecord)。
    6. vCompletion(Get(next, "1"))。
    7. IfAbruptCloseIterator(v, iteratorRecord)。
    8. statusCompletion(Call(adder, target, « k, v »))。
    9. IfAbruptCloseIterator(status, iteratorRecord)。

参数 iterable 期望是一个实现了 %Symbol.iterator% 方法的对象,该方法返回一个 迭代器对象,它会生成一个包含两个元素的 类数组对象,第一个元素用作 Map 的键,第二个元素作为与该键关联的值。

24.1.2 Map 构造函数的属性

Map 构造函数

24.1.2.1 Map.groupBy ( items, callback )

callback 应该是一个接受两个参数的函数。groupBy 会按照升序对 items 中的每个元素调用 callback 一次,并构造一个新的 Map。每个 callback 返回的值会作为 Map 的键。对于每个这样的键,结果 Map 有一个键为该键、值为包含所有 callback 返回该键的元素的数组的条目。

callback 的两个参数分别是元素的值和索引。

groupBy 的返回值是一个 Map。

该函数被调用时执行以下步骤:

  1. groups 为 ? GroupBy(items, callback, collection)。
  2. map 为 ! Construct(%Map%)。
  3. 对于 groups 中的每个 Record { [[Key]], [[Elements]] } g,执行
    1. elementsCreateArrayFromList(g.[[Elements]])。
    2. entryRecord { [[Key]]: g.[[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]"

创建派生集合对象的方法应当调用 %Symbol.species% 以确定用于创建派生对象的 构造函数。子类 构造函数 可以重写 %Symbol.species% 以更改默认的 构造函数 分配。

24.1.3 Map 原型对象的属性

Map 原型对象

  • %Map.prototype%
  • 拥有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%
  • 是一个 普通对象
  • 没有 [[MapData]] 内部槽。

24.1.3.1 Map.prototype.clear ( )

该方法被调用时执行以下步骤:

  1. Mthis 值。
  2. 执行 ? RequireInternalSlot(M, [[MapData]])。
  3. 对于 M.[[MapData]] 中的每个 Record { [[Key]], [[Value]] } p,执行
    1. p.[[Key]] 设为 empty
    2. p.[[Value]] 设为 empty
  4. 返回 undefined

现有的 [[MapData]] List 会被保留,因为可能存在正在遍历该 ListMap 迭代器对象

24.1.3.2 Map.prototype.constructor

Map.prototype.constructor 的初始值为 %Map%

24.1.3.3 Map.prototype.delete ( key )

该方法被调用时执行以下步骤:

  1. Mthis 值。
  2. 执行 ? RequireInternalSlot(M, [[MapData]])。
  3. key 设为 CanonicalizeKeyedCollectionKey(key)。
  4. 对于 M.[[MapData]] 中的每个 Record { [[Key]], [[Value]] } p,执行
    1. 如果 p.[[Key]] 不为 emptySameValue(p.[[Key]], key) 为 true,则
      1. p.[[Key]] 设为 empty
      2. p.[[Value]] 设为 empty
      3. 返回 true
  5. 返回 false

empty 作为规范设备用来表示一个条目已被删除。实际实现可能会采取其他操作,比如在内部数据结构中物理删除该条目。

24.1.3.4 Map.prototype.entries ( )

该方法被调用时执行以下步骤:

  1. Mthis 值。
  2. 返回 ? CreateMapIterator(M, key+value)。

24.1.3.5 Map.prototype.forEach ( callback [ , thisArg ] )

该方法被调用时执行以下步骤:

  1. Mthis 值。
  2. 执行 ? RequireInternalSlot(M, [[MapData]])。
  3. 如果 IsCallable(callback) 为 false,抛出 TypeError 异常。
  4. entriesM.[[MapData]]
  5. numEntriesentries 的元素个数。
  6. index 为 0。
  7. 重复,直到 index < numEntries
    1. eentries[index]。
    2. 设置 indexindex + 1。
    3. 如果 e.[[Key]] 不为 empty,则
      1. 执行 ? Call(callback, thisArg, « e.[[Value]], e.[[Key]], M »)。
      2. 注:在 callback 执行期间 entries 的元素数量可能增加。
      3. 设置 numEntriesentries 的当前元素数量。
  8. 返回 undefined

callback 应该是一个接受三个参数的函数。forEach 会按照键的插入顺序对 Map 中每个键/值对调用 callback 一次。只有实际存在的 Map 键才会被调用 callback;已被删除的键不会被调用。

如果提供了 thisArg 参数,则该参数会作为每次调用 callback 时的 this 值。如果未提供,则使用 undefined

callback 的三个参数分别是项的值、项的键,以及被遍历的 Map。

forEach 本身不会直接修改被调用对象,但该对象可能会被 callback 的调用修改。map 的 [[MapData]] 的每个条目只会被访问一次。在 forEach 开始后添加的新键会被访问。如果某个键被访问后被删除并在 forEach 完成前重新添加,则该键会被再次访问。在 forEach 开始后但被访问前被删除的键不会被访问,除非该键在 forEach 完成前被再次添加。

24.1.3.6 Map.prototype.get ( key )

该方法被调用时执行以下步骤:

  1. Mthis 值。
  2. 执行 ? RequireInternalSlot(M, [[MapData]])。
  3. key 设为 CanonicalizeKeyedCollectionKey(key)。
  4. 对于 M.[[MapData]] 中的每个 Record { [[Key]], [[Value]] } p,执行
    1. 如果 p.[[Key]] 不为 emptySameValue(p.[[Key]], key) 为 true,返回 p.[[Value]]
  5. 返回 undefined

24.1.3.7 Map.prototype.has ( key )

该方法被调用时执行以下步骤:

  1. Mthis 值。
  2. 执行 ? RequireInternalSlot(M, [[MapData]])。
  3. key 设为 CanonicalizeKeyedCollectionKey(key)。
  4. 对于 M.[[MapData]] 中的每个 Record { [[Key]], [[Value]] } p,执行
    1. 如果 p.[[Key]] 不为 emptySameValue(p.[[Key]], key) 为 true,返回 true
  5. 返回 false

24.1.3.8 Map.prototype.keys ( )

该方法被调用时执行以下步骤:

  1. Mthis 值。
  2. 返回 ? CreateMapIterator(M, key)。

24.1.3.9 Map.prototype.set ( key, value )

该方法被调用时执行以下步骤:

  1. Mthis 值。
  2. 执行 ? RequireInternalSlot(M, [[MapData]])。
  3. key 设为 CanonicalizeKeyedCollectionKey(key)。
  4. 对于 M.[[MapData]] 中的每个 Record { [[Key]], [[Value]] } p,执行
    1. 如果 p.[[Key]] 不为 emptySameValue(p.[[Key]], key) 为 true,则
      1. p.[[Value]] 设为 value
      2. 返回 M
  5. pRecord { [[Key]]: key, [[Value]]: value }。
  6. p 添加到 M.[[MapData]]
  7. 返回 M

24.1.3.10 get Map.prototype.size

Map.prototype.size 是一个 访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数被调用时执行以下步骤:

  1. Mthis 值。
  2. 执行 ? RequireInternalSlot(M, [[MapData]])。
  3. count 为 0。
  4. 对于 M.[[MapData]] 中的每个 Record { [[Key]], [[Value]] } p,执行
    1. 如果 p.[[Key]] 不为 empty,则将 count 设为 count + 1。
  5. 返回 𝔽(count)。

24.1.3.11 Map.prototype.values ( )

该方法被调用时执行以下步骤:

  1. Mthis 值。
  2. 返回 ? CreateMapIterator(M, value)。

24.1.3.12 Map.prototype [ %Symbol.iterator% ] ( )

%Symbol.iterator% 属性的初始值为 %Map.prototype.entries%,定义见 24.1.3.4

24.1.3.13 Map.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值为字符串值 "Map"

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

24.1.4 Map 实例的属性

Map 实例是 普通对象,它们继承自 Map 原型的属性。Map 实例还拥有 [[MapData]] 内部槽。

24.1.5 Map 迭代器对象

Map 迭代器 是一个表示对某个特定 Map 实例对象的特定遍历的对象。Map 迭代器对象没有具名的 构造函数。相反,Map 迭代器对象是通过调用 Map 实例对象的某些方法创建的。

24.1.5.1 CreateMapIterator ( map, kind )

抽象操作 CreateMapIterator 接收参数 map(一个 ECMAScript 语言值)和 kindkey+valuekeyvalue),返回 正常完成,包含一个生成器,或 抛出完成。用于为返回此类 迭代器的 Map 方法创建 迭代器对象。调用时执行以下步骤:

  1. 执行 ? RequireInternalSlot(map, [[MapData]])。
  2. closure 为一个新的 抽象闭包,无参数,捕获 mapkind,调用时执行以下步骤:
    1. entriesmap.[[MapData]]
    2. index 为 0。
    3. numEntriesentries 的元素数量。
    4. 重复,直到 index < numEntries
      1. eentries[index]。
      2. 设置 indexindex + 1。
      3. 如果 e.[[Key]] 不为 empty,则
        1. 如果 kindkey,则
          1. resulte.[[Key]]
        2. 否则如果 kindvalue,则
          1. resulte.[[Value]]
        3. 否则,
          1. 断言kindkey+value
          2. resultCreateArrayFromListe.[[Key]], e.[[Value]] »)。
        4. 执行 ? GeneratorYield(CreateIteratorResultObject(result, false))。
        5. 注:在 GeneratorYield 挂起本抽象操作执行期间,entries 的元素数量可能增加。
        6. 设置 numEntriesentries 的元素数量。
    5. 返回 undefined
  3. 返回 CreateIteratorFromClosure(closure, "%MapIteratorPrototype%", %MapIteratorPrototype%)。

24.1.5.2 %MapIteratorPrototype% 对象

%MapIteratorPrototype% 对象:

24.1.5.2.1 %MapIteratorPrototype%.next ( )

  1. 返回 ? GeneratorResume(this 值, empty, "%MapIteratorPrototype%")。

24.1.5.2.2 %MapIteratorPrototype% [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值为字符串值 "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 记录

Set 记录是一个 Record 值,用于封装 Set 或类似对象的接口。

Set 记录具有 表 76 中列出的字段。

表 76: Set 记录 字段
字段名 含义
[[SetObject]] 一个对象 该 Set 或类似对象。
[[Size]] 一个非负的 整数 或 +∞ 该对象报告的大小。
[[Has]] 一个 函数对象 该对象的 has 方法。
[[Keys]] 一个 函数对象 该对象的 keys 方法。

24.2.1.2 GetSetRecord ( obj )

抽象操作 GetSetRecord 接收参数 obj(一个 ECMAScript 语言值),返回 正常完成,包含一个 Set 记录抛出完成。调用时执行以下步骤:

  1. 如果 obj 不是对象,抛出 TypeError 异常。
  2. rawSize 为 ? Get(obj, "size")。
  3. numSize 为 ? ToNumber(rawSize)。
  4. 注:如果 rawSizeundefined,则 numSize 会是 NaN
  5. 如果 numSizeNaN,抛出 TypeError 异常。
  6. intSize 为 ! ToIntegerOrInfinity(numSize)。
  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 记录 { [[SetObject]]: obj, [[Size]]: intSize, [[Has]]: has, [[Keys]]: keys }。

24.2.1.3 SetDataHas ( setData, value )

抽象操作 SetDataHas 接收参数 setData(一个 List,元素为 ECMAScript 语言值empty)和 value(一个 ECMAScript 语言值),返回一个布尔值。调用时执行以下步骤:

  1. 如果 SetDataIndex(setData, value) 为 not-found,返回 false
  2. 返回 true

24.2.1.4 SetDataIndex ( setData, value )

抽象操作 SetDataIndex 接收参数 setData(一个 List,元素为 ECMAScript 语言值empty)和 value(一个 ECMAScript 语言值),返回一个非负的 整数not-found。调用时执行以下步骤:

  1. value 设为 CanonicalizeKeyedCollectionKey(value)。
  2. sizesetData 的元素数量。
  3. index 为 0。
  4. 重复,直到 index < size
    1. esetData[index]。
    2. 如果 e 不为 emptye 等于 value,则
      1. 返回 index
    3. index 设为 index + 1。
  5. 返回 not-found

24.2.1.5 SetDataSize ( setData )

抽象操作 SetDataSize 接收参数 setData(一个 List,元素为 ECMAScript 语言值empty),返回一个非负 整数。调用时执行以下步骤:

  1. count 为 0。
  2. 对于 setData 的每个元素 e,执行
    1. 如果 e 不为 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]"

创建派生集合对象的方法应当调用 %Symbol.species% 以确定用于创建派生对象的 构造函数。子类 构造函数 可以重写 %Symbol.species% 以更改默认的 构造函数 分配。

24.2.4 Set 原型对象的属性

Set 原型对象

  • %Set.prototype%
  • 拥有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%
  • 是一个 普通对象
  • 没有 [[SetData]] 内部槽。

24.2.4.1 Set.prototype.add ( value )

该方法被调用时执行以下步骤:

  1. Sthis 值。
  2. 执行 ? RequireInternalSlot(S, [[SetData]]).
  3. value 设为 CanonicalizeKeyedCollectionKey(value)。
  4. 对于 S.[[SetData]] 的每个元素 e,执行
    1. 如果 e 不为 emptySameValue(e, value) 为 true,则
      1. 返回 S
  5. value 添加到 S.[[SetData]]
  6. 返回 S

24.2.4.2 Set.prototype.clear ( )

该方法被调用时执行以下步骤:

  1. Sthis 值。
  2. 执行 ? RequireInternalSlot(S, [[SetData]]).
  3. 对于 S.[[SetData]] 的每个元素 e,执行
    1. S.[[SetData]] 中值为 e 的元素替换为值为 empty 的元素。
  4. 返回 undefined

现有的 [[SetData]] List 会被保留,因为可能存在正在遍历该 ListSet 迭代器对象

24.2.4.3 Set.prototype.constructor

Set.prototype.constructor 的初始值为 %Set%

24.2.4.4 Set.prototype.delete ( value )

该方法被调用时执行以下步骤:

  1. Sthis 值。
  2. 执行 ? RequireInternalSlot(S, [[SetData]]).
  3. value 设为 CanonicalizeKeyedCollectionKey(value)。
  4. 对于 S.[[SetData]] 的每个元素 e,执行
    1. 如果 e 不为 emptySameValue(e, value) 为 true,则
      1. S.[[SetData]] 中值为 e 的元素替换为值为 empty 的元素。
      2. 返回 true
  5. 返回 false

empty 作为规范设备用来表示一个条目已被删除。实际实现可能会采取其他操作,比如在内部数据结构中物理删除该条目。

24.2.4.5 Set.prototype.difference ( other )

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[SetData]]).
  3. otherRec 为 ? GetSetRecord(other)。
  4. resultSetDataO.[[SetData]] 的一个副本。
  5. 如果 SetDataSize(O.[[SetData]]) ≤ otherRec.[[Size]],则
    1. thisSizeO.[[SetData]] 的元素数量。
    2. index 为 0。
    3. 重复,直到 index < thisSize
      1. eresultSetData[index]。
      2. 如果 e 不为 empty,则
        1. inOtherToBoolean(? Call(otherRec.[[Has]], otherRec.[[SetObject]], « e »))。
        2. 如果 inOthertrue,则
          1. resultSetData[index] 设为 empty
      3. index 设为 index + 1。
  6. 否则,
    1. keysIter 为 ? GetIteratorFromMethod(otherRec.[[SetObject]], otherRec.[[Keys]])。
    2. nextnot-started
    3. 重复,直到 next 不为 done
      1. next 设为 ? IteratorStepValue(keysIter)。
      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. Sthis 值。
  2. 返回 ? CreateSetIterator(S, key+value)。

对于遍历目的,Set 类似于每个条目的键和值都相同的 Map。

24.2.4.7 Set.prototype.forEach ( callback [ , thisArg ] )

该方法被调用时执行以下步骤:

  1. Sthis 值。
  2. 执行 ? RequireInternalSlot(S, [[SetData]])。
  3. 如果 IsCallable(callback) 为 false,抛出 TypeError 异常。
  4. entriesS.[[SetData]]
  5. numEntriesentries 的元素数量。
  6. index 为 0。
  7. 重复,直到 index < numEntries
    1. eentries[index]。
    2. 设置 indexindex + 1。
    3. 如果 e 不为 empty,则
      1. 执行 ? Call(callback, thisArg, « e, e, S »)。
      2. 注:在 callback 执行期间 entries 的数量可能增加。
      3. 设置 numEntriesentries 的当前元素数量。
  8. 返回 undefined

callback 应该是一个接受三个参数的函数。forEach 会按照值插入顺序对 Set 对象中每个存在的值调用 callback 一次。只有实际存在的 Set 值才会被调用 callback;已被删除的键不会被调用。

如果提供了 thisArg 参数,则其会用作每次调用 callback 时的 this 值。如果未提供,则使用 undefined

callback 会被传入三个参数:前两个参数是 Set 中包含的同一个值,第三个参数是正在遍历的 Set 对象。

回调函数采用三个参数是为了与 Map 和 Array 的 forEach 方法的回调一致。对于 Set,每个元素既视为键又视为值。

forEach 本身不会直接修改被调用对象,但该对象可能会被 callback 的调用修改。

每个值通常只会被访问一次。不过,如果某个值被访问后被删除并在 forEach 完成前重新添加,则该值会被再次访问。在 forEach 开始后但被访问前被删除的值不会被访问,除非该值在 forEach 完成前被再次添加。在 forEach 开始后添加的新值会被访问。

24.2.4.8 Set.prototype.has ( value )

该方法被调用时执行以下步骤:

  1. Sthis 值。
  2. 执行 ? RequireInternalSlot(S, [[SetData]])。
  3. value 设为 CanonicalizeKeyedCollectionKey(value)。
  4. 对于 S.[[SetData]] 的每个元素 e,执行
    1. 如果 e 不为 emptySameValue(e, value) 为 true,返回 true
  5. 返回 false

24.2.4.9 Set.prototype.intersection ( other )

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[SetData]])。
  3. otherRec 为 ? GetSetRecord(other)。
  4. resultSetData 为一个新的空 List
  5. 如果 SetDataSize(O.[[SetData]]) ≤ otherRec.[[Size]],则
    1. thisSizeO.[[SetData]] 的元素数量。
    2. index 为 0。
    3. 重复,直到 index < thisSize
      1. eO.[[SetData]][index]。
      2. 设置 indexindex + 1。
      3. 如果 e 不为 empty,则
        1. inOtherToBoolean(? Call(otherRec.[[Has]], otherRec.[[SetObject]], « e »))。
        2. 如果 inOthertrue,则
          1. 注:较早对 otherRec.[[Has]] 的调用可能会移除并重新添加 O.[[SetData]] 的元素,这可能导致同一元素在本遍历中被访问两次。
          2. 如果 SetDataHas(resultSetData, e) 为 false,则
            1. e 添加到 resultSetData
        3. 注:在 otherRec.[[Has]] 执行期间,O.[[SetData]] 的元素数量可能增加。
        4. 设置 thisSizeO.[[SetData]] 的当前元素数量。
  6. 否则,
    1. keysIter 为 ? GetIteratorFromMethod(otherRec.[[SetObject]], otherRec.[[Keys]])。
    2. nextnot-started
    3. 重复,直到 next 不为 done
      1. next 设为 ? IteratorStepValue(keysIter)。
      2. 如果 next 不为 done,则
        1. next 设为 CanonicalizeKeyedCollectionKey(next)。
        2. inThisSetDataHas(O.[[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. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[SetData]])。
  3. otherRec 为 ? GetSetRecord(other)。
  4. 如果 SetDataSize(O.[[SetData]]) ≤ otherRec.[[Size]],则
    1. thisSizeO.[[SetData]] 的元素数量。
    2. index 为 0。
    3. 重复,直到 index < thisSize
      1. eO.[[SetData]][index]。
      2. 设置 indexindex + 1。
      3. 如果 e 不为 empty,则
        1. inOtherToBoolean(? Call(otherRec.[[Has]], otherRec.[[SetObject]], « e »))。
        2. 如果 inOthertrue,返回 false
        3. 注:在 otherRec.[[Has]] 执行期间,O.[[SetData]] 的元素数量可能增加。
        4. 设置 thisSizeO.[[SetData]] 的当前元素数量。
  5. 否则,
    1. keysIter 为 ? GetIteratorFromMethod(otherRec.[[SetObject]], otherRec.[[Keys]])。
    2. nextnot-started
    3. 重复,直到 next 不为 done
      1. next 设为 ? IteratorStepValue(keysIter)。
      2. 如果 next 不为 done,则
        1. 如果 SetDataHas(O.[[SetData]], next) 为 true,则
          1. 执行 ? IteratorClose(keysIter, NormalCompletion(unused))。
          2. 返回 false
  6. 返回 true

24.2.4.11 Set.prototype.isSubsetOf ( other )

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[SetData]])。
  3. otherRec 为 ? GetSetRecord(other)。
  4. 如果 SetDataSize(O.[[SetData]]) > otherRec.[[Size]],返回 false
  5. thisSizeO.[[SetData]] 的元素数量。
  6. index 为 0。
  7. 重复,直到 index < thisSize
    1. eO.[[SetData]][index]。
    2. 设置 indexindex + 1。
    3. 如果 e 不为 empty,则
      1. inOtherToBoolean(? Call(otherRec.[[Has]], otherRec.[[SetObject]], « e »))。
      2. 如果 inOtherfalse,返回 false
      3. 注:在 otherRec.[[Has]] 执行期间,O.[[SetData]] 的元素数量可能增加。
      4. 设置 thisSizeO.[[SetData]] 的当前元素数量。
  8. 返回 true

24.2.4.12 Set.prototype.isSupersetOf ( other )

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[SetData]])。
  3. otherRec 为 ? GetSetRecord(other)。
  4. 如果 SetDataSize(O.[[SetData]]) < otherRec.[[Size]],返回 false
  5. keysIter 为 ? GetIteratorFromMethod(otherRec.[[SetObject]], otherRec.[[Keys]])。
  6. nextnot-started
  7. 重复,直到 next 不为 done
    1. next 设为 ? IteratorStepValue(keysIter)。
    2. 如果 next 不为 done,则
      1. 如果 SetDataHas(O.[[SetData]], next) 为 false,则
        1. 执行 ? IteratorClose(keysIter, NormalCompletion(unused))。
        2. 返回 false
  8. 返回 true

24.2.4.13 Set.prototype.keys ( )

"keys" 属性的初始值为 %Set.prototype.values%,定义见 24.2.4.17

对于遍历目的,Set 类似于每个条目的键和值都相同的 Map。

24.2.4.14 get Set.prototype.size

Set.prototype.size 是一个 访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数被调用时执行以下步骤:

  1. Sthis 值。
  2. 执行 ? RequireInternalSlot(S, [[SetData]])。
  3. sizeSetDataSize(S.[[SetData]])。
  4. 返回 𝔽(size)。

24.2.4.15 Set.prototype.symmetricDifference ( other )

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[SetData]])。
  3. otherRec 为 ? GetSetRecord(other)。
  4. keysIter 为 ? GetIteratorFromMethod(otherRec.[[SetObject]], otherRec.[[Keys]])。
  5. resultSetDataO.[[SetData]] 的一个副本。
  6. nextnot-started
  7. 重复,直到 next 不为 done
    1. next 设为 ? IteratorStepValue(keysIter)。
    2. 如果 next 不为 done,则
      1. next 设为 CanonicalizeKeyedCollectionKey(next)。
      2. resultIndexSetDataIndex(resultSetData, next)。
      3. 如果 resultIndexnot-found,令 alreadyInResultfalse。否则令 alreadyInResulttrue
      4. 如果 SetDataHas(O.[[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. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[SetData]])。
  3. otherRec 为 ? GetSetRecord(other)。
  4. keysIter 为 ? GetIteratorFromMethod(otherRec.[[SetObject]], otherRec.[[Keys]])。
  5. resultSetDataO.[[SetData]] 的一个副本。
  6. nextnot-started
  7. 重复,直到 next 不为 done
    1. next 设为 ? IteratorStepValue(keysIter)。
    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. Sthis 值。
  2. 返回 ? CreateSetIterator(S, 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% 属性的初始值为字符串值 "Set"

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

24.2.5 Set 实例的属性

Set 实例是 普通对象,它们继承自 Set 原型的属性。Set 实例还拥有 [[SetData]] 内部槽。

24.2.6 Set 迭代器对象

Set 迭代器 是一个 普通对象,结构如下定义,用于表示对某个特定 Set 实例对象的特定遍历。Set 迭代器对象没有具名的 构造函数。相反,Set 迭代器对象是通过调用 Set 实例对象的某些方法创建的。

24.2.6.1 CreateSetIterator ( set, kind )

抽象操作 CreateSetIterator 接收参数 set(一个 ECMAScript 语言值)和 kindkey+valuevalue),返回 正常完成,包含一个生成器,或 抛出完成。用于为返回此类 迭代器的 Set 方法创建 迭代器对象。调用时执行以下步骤:

  1. 执行 ? RequireInternalSlot(set, [[SetData]])。
  2. closure 为一个新的 抽象闭包,无参数,捕获 setkind,调用时执行以下步骤:
    1. index 为 0。
    2. entriesset.[[SetData]]
    3. numEntriesentries 的元素数量。
    4. 重复,直到 index < numEntries
      1. eentries[index]。
      2. 设置 indexindex + 1。
      3. 如果 e 不为 empty,则
        1. 如果 kindkey+value,则
          1. resultCreateArrayFromListe, e »)。
          2. 执行 ? GeneratorYield(CreateIteratorResultObject(result, false))。
        2. 否则,
          1. 断言kindvalue
          2. 执行 ? GeneratorYield(CreateIteratorResultObject(e, false))。
        3. 注:在 GeneratorYield 挂起本抽象操作执行期间,entries 的元素数量可能增加。
        4. 设置 numEntriesentries 的当前元素数量。
    5. 返回 undefined
  3. 返回 CreateIteratorFromClosure(closure, "%SetIteratorPrototype%", %SetIteratorPrototype%)。

24.2.6.2 %SetIteratorPrototype% 对象

%SetIteratorPrototype% 对象:

24.2.6.2.1 %SetIteratorPrototype%.next ( )

  1. 返回 ? GeneratorResume(this 值, empty, "%SetIteratorPrototype%")。

24.2.6.2.2 %SetIteratorPrototype% [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值为字符串值 "Set Iterator"

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

24.3 WeakMap 对象

WeakMap 是键/值对的集合,其中键是对象和/或符号,值可以是任意的 ECMAScript 语言值。WeakMap 可以用来查询是否包含某个特定键的键/值对,但没有机制用于枚举它所持有的所有键。在某些情况下,非 存活 的值会被从 WeakMap 的键中移除,详见 9.9.3

实现可能会对 WeakMap 的某个键/值对变得不可访问与被移除之间施加任意的延迟。如果这个延迟对 ECMAScript 程序是可观察的,则会带来不确定性,影响程序执行。因此,ECMAScript 的实现不得提供任何无需观察者持有该键即可观察 WeakMap 键的手段。

WeakMap 必须通过哈希表或其他机制实现,这些机制在平均情况下能提供次线性的键/值对访问时间。本规范中所用的数据结构仅用于描述 WeakMap 所需的可观察语义,而非实际的实现模型。

WeakMap 和 WeakSet 旨在为对象或符号动态关联状态,且如果没有 WeakMap 或 WeakSet 实例,该对象或符号变得不可访问并被垃圾回收机制回收时,不会“泄漏”内存资源。可以通过将 WeakMap 或 WeakSet 实例反向映射到每个对象/符号实现这一特性。或者,每个 WeakMap 或 WeakSet 实例可以内部存储其键和值数据,但这种方法需要 WeakMap/WeakSet 实现与垃圾回收器协作。下列参考文献介绍了对 WeakMap 和 WeakSet 实现可能有用的机制:

Barry Hayes. 1997. Ephemerons: a new finalization mechanism. 载于 Proceedings of the 12th ACM SIGPLAN conference on Object-oriented programming, systems, languages, and applications (OOPSLA '97), A. Michael Berman (编辑). 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)。

如果参数 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. Mthis 值。
  2. 执行 ? RequireInternalSlot(M, [[WeakMapData]])。
  3. 如果 CanBeHeldWeakly(key) 为 false,返回 false
  4. 对于 M.[[WeakMapData]] 中的每个 Record { [[Key]], [[Value]] } p,执行
    1. 如果 p.[[Key]] 不为 emptySameValue(p.[[Key]], key) 为 true,则
      1. p.[[Key]] 设为 empty
      2. p.[[Value]] 设为 empty
      3. 返回 true
  5. 返回 false

empty 作为规范设备用来表示一个条目已被删除。实际实现可能会采取其他操作,比如在内部数据结构中物理删除该条目。

24.3.3.3 WeakMap.prototype.get ( key )

该方法被调用时执行以下步骤:

  1. Mthis 值。
  2. 执行 ? RequireInternalSlot(M, [[WeakMapData]])。
  3. 如果 CanBeHeldWeakly(key) 为 false,返回 undefined
  4. 对于 M.[[WeakMapData]] 中的每个 Record { [[Key]], [[Value]] } p,执行
    1. 如果 p.[[Key]] 不为 emptySameValue(p.[[Key]], key) 为 true,返回 p.[[Value]]
  5. 返回 undefined

24.3.3.4 WeakMap.prototype.has ( key )

该方法被调用时执行以下步骤:

  1. Mthis 值。
  2. 执行 ? RequireInternalSlot(M, [[WeakMapData]])。
  3. 如果 CanBeHeldWeakly(key) 为 false,返回 false
  4. 对于 M.[[WeakMapData]] 中的每个 Record { [[Key]], [[Value]] } p,执行
    1. 如果 p.[[Key]] 不为 emptySameValue(p.[[Key]], key) 为 true,返回 true
  5. 返回 false

24.3.3.5 WeakMap.prototype.set ( key, value )

该方法被调用时执行以下步骤:

  1. Mthis 值。
  2. 执行 ? RequireInternalSlot(M, [[WeakMapData]])。
  3. 如果 CanBeHeldWeakly(key) 为 false,抛出 TypeError 异常。
  4. 对于 M.[[WeakMapData]] 中的每个 Record { [[Key]], [[Value]] } p,执行
    1. 如果 p.[[Key]] 不为 emptySameValue(p.[[Key]], key) 为 true,则
      1. p.[[Value]] 设为 value
      2. 返回 M
  5. pRecord { [[Key]]: key, [[Value]]: value }。
  6. p 添加到 M.[[WeakMapData]]
  7. 返回 M

24.3.3.6 WeakMap.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值为字符串值 "WeakMap"

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

24.3.4 WeakMap 实例的属性

WeakMap 实例是 普通对象,它们继承自 WeakMap 原型的属性。WeakMap 实例还拥有 [[WeakMapData]] 内部槽。

24.4 WeakSet 对象

WeakSet 是对象和/或符号的集合。在 WeakSet 的集合中,每个不同的对象或符号只能出现一次。WeakSet 可以用来查询是否包含某个特定值,但没有机制用于枚举它所持有的所有值。在某些情况下,非 存活 的值会被从 WeakSet 元素中移除,详见 9.9.3

实现可能会对 WeakSet 所包含的某个值变得不可访问与被移除之间施加任意的延迟。如果这个延迟对 ECMAScript 程序是可观察的,则会带来不确定性,影响程序执行。因此,ECMAScript 的实现不得提供任何无需观察者持有该值即可确定 WeakSet 是否包含该值的手段。

WeakSet 必须通过哈希表或其他机制实现,这些机制在平均情况下能提供次线性的元素访问时间。本规范中所用的数据结构仅用于描述 WeakSet 所需的可观察语义,而非实际的实现模型。

参见 24.3 中的注。

24.4.1 WeakSet 构造函数

WeakSet 构造函数

  • %WeakSet%
  • 全局对象"WeakSet" 属性的初始值。
  • 作为 构造函数 调用时会创建并初始化一个新的 WeakSet。
  • 不应作为普通函数调用,否则会抛出异常。
  • 可以用作类定义的 extends 子句的值。想要继承指定 WeakSet 行为的子类 构造函数 必须包含对 WeakSet 构造函数super 调用,以用必要的内部状态创建和初始化子类实例,以支持 WeakSet.prototype 内建方法。

24.4.1.1 WeakSet ( [ iterable ] )

该函数被调用时执行以下步骤:

  1. 如果 NewTarget 为 undefined,抛出 TypeError 异常。
  2. set 为 ? OrdinaryCreateFromConstructor(NewTarget, "%WeakSet.prototype%", « [[WeakSetData]] »)。
  3. 设置 set.[[WeakSetData]] 为一个新的空 List
  4. 如果 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. Sthis 值。
  2. 执行 ? RequireInternalSlot(S, [[WeakSetData]])。
  3. 如果 CanBeHeldWeakly(value) 为 false,抛出 TypeError 异常。
  4. 对于 S.[[WeakSetData]] 的每个元素 e,执行
    1. 如果 e 不为 emptySameValue(e, value) 为 true,则
      1. 返回 S
  5. value 添加到 S.[[WeakSetData]]
  6. 返回 S

24.4.3.2 WeakSet.prototype.constructor

WeakSet.prototype.constructor 的初始值为 %WeakSet%

24.4.3.3 WeakSet.prototype.delete ( value )

该方法被调用时执行以下步骤:

  1. Sthis 值。
  2. 执行 ? RequireInternalSlot(S, [[WeakSetData]])。
  3. 如果 CanBeHeldWeakly(value) 为 false,返回 false
  4. 对于 S.[[WeakSetData]] 的每个元素 e,执行
    1. 如果 e 不为 emptySameValue(e, value) 为 true,则
      1. S.[[WeakSetData]] 中值为 e 的元素替换为值为 empty 的元素。
      2. 返回 true
  5. 返回 false

empty 作为规范设备用来表示一个条目已被删除。实际实现可能会采取其他操作,比如在内部数据结构中物理删除该条目。

24.4.3.4 WeakSet.prototype.has ( value )

该方法被调用时执行以下步骤:

  1. Sthis 值。
  2. 执行 ? RequireInternalSlot(S, [[WeakSetData]])。
  3. 如果 CanBeHeldWeakly(value) 为 false,返回 false
  4. 对于 S.[[WeakSetData]] 的每个元素 e,执行
    1. 如果 e 不为 emptySameValue(e, value) 为 true,返回 true
  5. 返回 false

24.4.3.5 WeakSet.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值为字符串值 "WeakSet"

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

24.4.4 WeakSet 实例的属性

WeakSet 实例是 普通对象,它们继承自 WeakSet 原型的属性。WeakSet 实例还拥有 [[WeakSetData]] 内部槽。

24.5 键控集合的抽象操作

24.5.1 CanonicalizeKeyedCollectionKey ( key )

抽象操作 CanonicalizeKeyedCollectionKey 接收参数 key(一个 ECMAScript 语言值),并返回一个 ECMAScript 语言值。调用时执行以下步骤:

  1. 如果 key-0𝔽,返回 +0𝔽
  2. 返回 key

25 结构化数据

25.1 ArrayBuffer 对象

25.1.1 记号

本节、25.4 以及 29 中的描述使用了读-改-写修改函数内部数据结构。

读-改-写修改函数 是一个数学函数,被表示为一个抽象闭包,接收两个 List字节值 作为参数,并返回一个 List字节值。这些抽象闭包满足以下所有属性:

  • 它们以原子方式执行其所有算法步骤。
  • 它们的每个算法步骤都是不可观察的。

为帮助验证读-改-写修改函数的算法步骤是否构成了纯数学函数,推荐以下编辑约定:

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 ( constructor, byteLength [ , maxByteLength ] )

抽象操作 AllocateArrayBuffer 接收参数 constructor(一个 构造函数)、byteLength(非负整数),可选参数 maxByteLength(非负整数empty),返回一个 正常完成,包含 ArrayBuffer 或 抛出完成。用于创建 ArrayBuffer。调用时执行以下步骤:

  1. slots 为 « [[ArrayBufferData]], [[ArrayBufferByteLength]], [[ArrayBufferDetachKey]] »。
  2. 如果 maxByteLength 存在且不为 empty,令 allocatingResizableBuffertrue;否则令 allocatingResizableBufferfalse
  3. 如果 allocatingResizableBuffertrue,则
    1. 如果 byteLength > maxByteLength,抛出 RangeError 异常。
    2. [[ArrayBufferMaxByteLength]] 添加到 slots
  4. obj 为 ? OrdinaryCreateFromConstructor(constructor, "%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 )

抽象操作 ArrayBufferByteLength 接收参数 arrayBuffer(一个 ArrayBuffer 或 SharedArrayBuffer)和 orderseq-cstunordered),返回一个非负 整数。调用时执行以下步骤:

  1. 如果 IsSharedArrayBuffer(arrayBuffer) 为 truearrayBuffer[[ArrayBufferByteLengthData]] 内部槽,则
    1. bufferByteLengthBlockarrayBuffer.[[ArrayBufferByteLengthData]]
    2. rawLengthGetRawBytesFromSharedBlock(bufferByteLengthBlock, 0, biguint64, true, order)。
    3. isLittleEndian周围代理Agent Record[[LittleEndian]] 字段的值。
    4. 返回 (RawBytesToNumeric(biguint64, rawLength, isLittleEndian))。
  2. 断言IsDetachedBuffer(arrayBuffer) 为 false
  3. 返回 arrayBuffer.[[ArrayBufferByteLength]]

25.1.3.3 ArrayBufferCopyAndDetach ( arrayBuffer, newLength, preserveResizability )

抽象操作 ArrayBufferCopyAndDetach 接收参数 arrayBuffer(一个 ECMAScript 语言值)、newLength(一个 ECMAScript 语言值)、preserveResizabilitypreserve-resizabilityfixed-length),返回一个 正常完成,包含 ArrayBuffer 或 抛出完成。调用时执行以下步骤:

  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 )

抽象操作 IsDetachedBuffer 接收参数 arrayBuffer(一个 ArrayBuffer 或 SharedArrayBuffer),返回一个布尔值。调用时执行以下步骤:

  1. 如果 arrayBuffer.[[ArrayBufferData]]null,返回 true
  2. 返回 false

25.1.3.5 DetachArrayBuffer ( arrayBuffer [ , key ] )

抽象操作 DetachArrayBuffer 接收参数 arrayBuffer(一个 ArrayBuffer)和可选参数 key(任意值),返回 正常完成,包含 unused抛出完成。调用时执行以下步骤:

  1. 断言IsSharedArrayBuffer(arrayBuffer) 为 false
  2. 如果 key 不存在,设置 keyundefined
  3. 如果 arrayBuffer.[[ArrayBufferDetachKey]] 不等于 key,抛出 TypeError 异常。
  4. 设置 arrayBuffer.[[ArrayBufferData]]null
  5. 设置 arrayBuffer.[[ArrayBufferByteLength]] 为 0。
  6. 返回 unused

分离 ArrayBuffer 实例会将用作其底层存储的 Data Block 与此实例解除关联,并将缓冲区字节长度设为 0。

25.1.3.6 CloneArrayBuffer ( srcBuffer, srcByteOffset, srcLength )

抽象操作 CloneArrayBuffer 接收参数 srcBuffer(一个 ArrayBuffer 或 SharedArrayBuffer)、srcByteOffset(非负整数)、srcLength(非负整数),返回一个 正常完成,包含 ArrayBuffer 或 抛出完成。它会创建一个新的 ArrayBuffer,其数据是 srcBuffersrcByteOffset 起始,持续 srcLength 字节范围的数据的副本。调用时执行以下步骤:

  1. 断言IsDetachedBuffer(srcBuffer) 为 false
  2. targetBuffer 为 ? AllocateArrayBuffer(%ArrayBuffer%, srcLength)。
  3. srcBlocksrcBuffer.[[ArrayBufferData]]
  4. targetBlocktargetBuffer.[[ArrayBufferData]]
  5. 执行 CopyDataBlockBytes(targetBlock, 0, srcBlock, srcByteOffset, srcLength)。
  6. 返回 targetBuffer

25.1.3.7 GetArrayBufferMaxByteLengthOption ( options )

抽象操作 GetArrayBufferMaxByteLengthOption 接收参数 options(一个 ECMAScript 语言值),返回 正常完成,包含 非负整数empty,或 抛出完成。调用时执行以下步骤:

  1. 如果 options 不是一个对象,返回 empty
  2. maxByteLength 为 ? Get(options, "maxByteLength")。
  3. 如果 maxByteLengthundefined,返回 empty
  4. 返回 ? ToIndex(maxByteLength)。

25.1.3.8 HostResizeArrayBuffer ( buffer, newByteLength )

宿主定义抽象操作 HostResizeArrayBuffer 接收参数 buffer(一个 ArrayBuffer)和 newByteLength(非负整数),返回 正常完成,包含 handledunhandled,或 抛出完成。它为 宿主 提供机会执行 实现定义buffer 调整大小操作。如果 宿主 选择不处理 buffer 的调整大小,则可以返回 unhandled 以执行默认行为。

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

  • 该抽象操作不会分离 buffer
  • 如果该抽象操作以 handled 正常完成,则 buffer.[[ArrayBufferByteLength]]newByteLength

HostResizeArrayBuffer 的默认实现是返回 NormalCompletion(unhandled)。

25.1.3.9 IsFixedLengthArrayBuffer ( arrayBuffer )

抽象操作 IsFixedLengthArrayBuffer 接收参数 arrayBuffer(一个 ArrayBuffer 或 SharedArrayBuffer),返回布尔值。调用时执行以下步骤:

  1. 如果 arrayBuffer[[ArrayBufferMaxByteLength]] 内部槽,返回 false
  2. 返回 true

25.1.3.10 IsUnsignedElementType ( type )

抽象操作 IsUnsignedElementType 接收参数 type(一个 TypedArray 元素类型),返回布尔值。用于判断参数 type 是否是无符号 TypedArray 元素类型。调用时执行以下步骤:

  1. 如果 typeuint8uint8clampeduint16uint32biguint64 之一,返回 true
  2. 返回 false

25.1.3.11 IsUnclampedIntegerElementType ( type )

抽象操作 IsUnclampedIntegerElementType 接收参数 type(一个 TypedArray 元素类型),返回布尔值。用于判断参数 type 是否为 整数 类型的 TypedArray 元素类型(不包括 uint8clamped)。调用时执行以下步骤:

  1. 如果 typeint8uint8int16uint16int32uint32 之一,返回 true
  2. 返回 false

25.1.3.12 IsBigIntElementType ( type )

抽象操作 IsBigIntElementType 接收参数 type(一个 TypedArray 元素类型),返回布尔值。用于判断参数 type 是否为 BigInt 类型的 TypedArray 元素类型。调用时执行以下步骤:

  1. 如果 typebiguint64bigint64,返回 true
  2. 返回 false

25.1.3.13 IsNoTearConfiguration ( type, order )

抽象操作 IsNoTearConfiguration 接收参数 type(一个 TypedArray 元素类型)、orderseq-cstunorderedinit),返回布尔值。调用时执行以下步骤:

  1. 如果 IsUnclampedIntegerElementType(type) 为 true,返回 true
  2. 如果 IsBigIntElementType(type) 为 trueorder 既不是 init 也不是 unordered,返回 true
  3. 返回 false

25.1.3.14 RawBytesToNumeric ( type, rawBytes, isLittleEndian )

抽象操作 RawBytesToNumeric 接收参数 type(一个 TypedArray 元素类型)、rawBytes(一个 List字节值)、isLittleEndian(布尔值),返回 Number 或 BigInt。调用时执行以下步骤:

  1. elementSize表 75 中元素类型 type 指定的元素大小值。
  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 )

抽象操作 GetRawBytesFromSharedBlock 接收参数 block(一个 共享数据块)、byteIndex(非负整数)、typeTypedArray 元素类型)、isTypedArray(布尔值)、orderseq-cstunordered),返回一个 List,元素为 字节值。调用时执行以下步骤:

  1. elementSize表 75 中元素类型 type 对应的元素大小值。
  2. execution周围代理Agent Record[[CandidateExecution]] 字段。
  3. eventsRecordexecution.[[EventsRecords]][[AgentSignifier]] 等于 AgentSignifier() 的 Agent Events Record
  4. 如果 isTypedArraytrueIsNoTearConfiguration(type, order) 为 true,令 noTeartrue;否则令 noTearfalse
  5. rawValue 为一个长度为 elementSizeList,其元素为非确定性选取的 字节值
  6. 注:在实现中,rawValue 是底层硬件的非原子或原子读取指令的结果。该非确定性是 内存模型 的语义规定,用于描述弱一致性硬件的可观察行为。
  7. readEventReadSharedMemory { [[Order]]: order, [[NoTear]]: noTear, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize }。
  8. readEvent 添加到 eventsRecord.[[EventList]]
  9. Chosen Value Record { [[Event]]: readEvent, [[ChosenValue]]: rawValue } 添加到 execution.[[ChosenValues]]
  10. 返回 rawValue

25.1.3.16 GetValueFromBuffer ( arrayBuffer, byteIndex, type, isTypedArray, order [ , isLittleEndian ] )

抽象操作 GetValueFromBuffer 接收参数 arrayBuffer(一个 ArrayBuffer 或 SharedArrayBuffer)、byteIndex(非负整数)、typeTypedArray 元素类型)、isTypedArray(布尔值)、orderseq-cstunordered),可选参数 isLittleEndian(布尔值),返回 Number 或 BigInt。调用时执行以下步骤:

  1. 断言IsDetachedBuffer(arrayBuffer) 为 false
  2. 断言arrayBufferbyteIndex 开始有足够的字节以表示 type 类型的值。
  3. blockarrayBuffer.[[ArrayBufferData]]
  4. elementSize表 75 中元素类型 type 指定的元素大小值。
  5. 如果 IsSharedArrayBuffer(arrayBuffer) 为 true,则
    1. 断言block共享数据块
    2. rawValueGetRawBytesFromSharedBlock(block, byteIndex, type, isTypedArray, order)。
  6. 否则,
    1. rawValue 为一个 List,其元素为 block区间 byteIndex(含)到 byteIndex + elementSize(不含) 范围内的字节。
  7. 断言rawValue 的元素数量为 elementSize
  8. 如果 isLittleEndian 未传入,设置 isLittleEndian周围代理Agent Record[[LittleEndian]] 字段的值。
  9. 返回 RawBytesToNumeric(type, rawValue, isLittleEndian)。

25.1.3.17 NumericToRawBytes ( type, value, isLittleEndian )

抽象操作 NumericToRawBytes 接收参数 type(一个 TypedArray 元素类型)、value(Number 或 BigInt)、isLittleEndian(布尔值),返回一个 List,元素为 字节值。调用时执行以下步骤:

  1. 如果 typefloat16,则
    1. rawBytes 为一个 List,其元素为将 value 按 roundTiesToEven 模式转换为 IEEE 754-2019 binary16 格式的 2 字节,字节顺序为小端序。如果 valueNaN,则 rawBytes 可以设为任意实现选取的 IEEE 754-2019 binary16 NaN 编码。实现必须对每个可区分的 NaN 值始终选择相同的编码。
  2. 否则若 typefloat32,则
    1. rawBytes 为一个 List,其元素为将 value 按 roundTiesToEven 模式转换为 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. n表 75 中元素类型 type 指定的元素大小值。
    2. conversionOperation表 75 中元素类型 type 在转换操作列指定的抽象操作。
    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 ] )

抽象操作 SetValueInBuffer 接收参数 arrayBuffer(一个 ArrayBuffer 或 SharedArrayBuffer)、byteIndex(非负整数)、typeTypedArray 元素类型)、value(Number 或 BigInt)、isTypedArray(布尔值)、orderseq-cstunorderedinit),可选参数 isLittleEndian(布尔值),返回 unused。调用时执行以下步骤:

  1. 断言IsDetachedBuffer(arrayBuffer) 为 false
  2. 断言arrayBufferbyteIndex 开始有足够的字节以表示 type 类型的值。
  3. 断言: 如果 IsBigIntElementType(type) 为 true,则 value 必须为 BigInt;否则,value 必须为 Number
  4. blockarrayBuffer.[[ArrayBufferData]]
  5. elementSize表 75 中元素类型 type 指定的元素大小值。
  6. 如果 isLittleEndian 未传入,设置 isLittleEndian周围代理Agent Record[[LittleEndian]] 字段的值。
  7. rawBytesNumericToRawBytes(type, value, isLittleEndian)。
  8. 如果 IsSharedArrayBuffer(arrayBuffer) 为 true,则
    1. execution周围代理Agent Record[[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]]
  9. 否则,
    1. rawBytes 的各字节逐一存入 block,起始于 block[byteIndex]。
  10. 返回 unused

25.1.3.19 GetModifySetValueInBuffer ( arrayBuffer, byteIndex, type, value, op )

抽象操作 GetModifySetValueInBuffer 接收参数 arrayBuffer(一个 ArrayBuffer 或 SharedArrayBuffer)、byteIndex(非负整数)、typeTypedArray 元素类型)、value(Number 或 BigInt)、op读-改-写修改函数),返回 Number 或 BigInt。调用时执行以下步骤:

  1. 断言IsDetachedBuffer(arrayBuffer) 为 false
  2. 断言arrayBufferbyteIndex 开始有足够的字节以表示 type 类型的值。
  3. 断言: 如果 IsBigIntElementType(type) 为 true,则 value 必须为 BigInt;否则,value 必须为 Number
  4. blockarrayBuffer.[[ArrayBufferData]]
  5. elementSize表 75 中元素类型 type 指定的元素大小值。
  6. isLittleEndian周围代理Agent Record[[LittleEndian]] 字段的值。
  7. rawBytesNumericToRawBytes(type, value, isLittleEndian)。
  8. 如果 IsSharedArrayBuffer(arrayBuffer) 为 true,则
    1. execution周围代理Agent Record[[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]]
  9. 否则,
    1. rawBytesRead 为一个长度为 elementSizeList,其元素为从 block[byteIndex] 起始的 elementSize 个字节。
    2. rawBytesModifiedop(rawBytesRead, rawBytes)。
    3. rawBytesModified 的各字节逐一存入 block,起始于 block[byteIndex]。
  10. 返回 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 不是一个对象,返回 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]"

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. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[ArrayBufferData]])。
  3. 如果 IsSharedArrayBuffer(O) 为 true,抛出 TypeError 异常。
  4. 如果 IsDetachedBuffer(O) 为 true,返回 +0𝔽
  5. lengthO.[[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. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[ArrayBufferData]])。
  3. 如果 IsSharedArrayBuffer(O) 为 true,抛出 TypeError 异常。
  4. 返回 IsDetachedBuffer(O)。

25.1.6.4 get ArrayBuffer.prototype.maxByteLength

ArrayBuffer.prototype.maxByteLength 是一个 访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数被调用时执行以下步骤:

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[ArrayBufferData]])。
  3. 如果 IsSharedArrayBuffer(O) 为 true,抛出 TypeError 异常。
  4. 如果 IsDetachedBuffer(O) 为 true,返回 +0𝔽
  5. 如果 IsFixedLengthArrayBuffer(O) 为 true,则
    1. lengthO.[[ArrayBufferByteLength]]
  6. 否则,
    1. lengthO.[[ArrayBufferMaxByteLength]]
  7. 返回 𝔽(length)。

25.1.6.5 get ArrayBuffer.prototype.resizable

ArrayBuffer.prototype.resizable 是一个 访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数被调用时执行以下步骤:

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[ArrayBufferData]])。
  3. 如果 IsSharedArrayBuffer(O) 为 true,抛出 TypeError 异常。
  4. 如果 IsFixedLengthArrayBuffer(O) 为 false,返回 true;否则返回 false

25.1.6.6 ArrayBuffer.prototype.resize ( newLength )

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[ArrayBufferMaxByteLength]])。
  3. 如果 IsSharedArrayBuffer(O) 为 true,抛出 TypeError 异常。
  4. newByteLength 为 ? ToIndex(newLength)。
  5. 如果 IsDetachedBuffer(O) 为 true,抛出 TypeError 异常。
  6. 如果 newByteLength > O.[[ArrayBufferMaxByteLength]],抛出 RangeError 异常。
  7. hostHandled 为 ? HostResizeArrayBuffer(O, newByteLength)。
  8. 如果 hostHandledhandled,返回 undefined
  9. oldBlockO.[[ArrayBufferData]]
  10. newBlock 为 ? CreateByteDataBlock(newByteLength)。
  11. copyLengthmin(newByteLength, O.[[ArrayBufferByteLength]])。
  12. 执行 CopyDataBlockBytes(newBlock, 0, oldBlock, 0, copyLength)。
  13. 注:新 Data Block 的创建和从旧 Data Block 的数据复制都是不可观察的。实现可以将此方法实现为原地增长或缩减。
  14. 设置 O.[[ArrayBufferData]]newBlock
  15. 设置 O.[[ArrayBufferByteLength]]newByteLength
  16. 返回 undefined

25.1.6.7 ArrayBuffer.prototype.slice ( start, end )

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[ArrayBufferData]])。
  3. 如果 IsSharedArrayBuffer(O) 为 true,抛出 TypeError 异常。
  4. 如果 IsDetachedBuffer(O) 为 true,抛出 TypeError 异常。
  5. lenO.[[ArrayBufferByteLength]]
  6. relativeStart 为 ? ToIntegerOrInfinity(start)。
  7. 如果 relativeStart = -∞,令 first 为 0。
  8. 否则如果 relativeStart < 0,令 firstmax(len + relativeStart, 0)。
  9. 否则,令 firstmin(relativeStart, len)。
  10. 如果 endundefined,令 relativeEndlen;否则令 relativeEnd 为 ? ToIntegerOrInfinity(end)。
  11. 如果 relativeEnd = -∞,令 final 为 0。
  12. 否则如果 relativeEnd < 0,令 finalmax(len + relativeEnd, 0)。
  13. 否则,令 finalmin(relativeEnd, len)。
  14. newLenmax(final - first, 0)。
  15. ctor 为 ? SpeciesConstructor(O, %ArrayBuffer%)。
  16. new 为 ? Construct(ctor, « 𝔽(newLen) »)。
  17. 执行 ? RequireInternalSlot(new, [[ArrayBufferData]])。
  18. 如果 IsSharedArrayBuffer(new) 为 true,抛出 TypeError 异常。
  19. 如果 IsDetachedBuffer(new) 为 true,抛出 TypeError 异常。
  20. 如果 SameValue(new, O) 为 true,抛出 TypeError 异常。
  21. 如果 new.[[ArrayBufferByteLength]] < newLen,抛出 TypeError 异常。
  22. 注:上述步骤的副作用可能会分离或调整 O 的大小。
  23. 如果 IsDetachedBuffer(O) 为 true,抛出 TypeError 异常。
  24. fromBufO.[[ArrayBufferData]]
  25. toBufnew.[[ArrayBufferData]]
  26. currentLenO.[[ArrayBufferByteLength]]
  27. 如果 first < currentLen,则
    1. countmin(newLen, currentLen - first)。
    2. 执行 CopyDataBlockBytes(toBuf, 0, fromBuf, first, count)。
  28. 返回 new

25.1.6.8 ArrayBuffer.prototype.transfer ( [ newLength ] )

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. 返回 ? ArrayBufferCopyAndDetach(O, newLength, preserve-resizability)。

25.1.6.9 ArrayBuffer.prototype.transferToFixedLength ( [ newLength ] )

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. 返回 ? ArrayBufferCopyAndDetach(O, newLength, fixed-length)。

25.1.6.10 ArrayBuffer.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值为字符串值 "ArrayBuffer"

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

25.1.7 ArrayBuffer 实例的属性

ArrayBuffer 实例继承自 ArrayBuffer 原型对象 的属性。每个 ArrayBuffer 实例都有一个 [[ArrayBufferData]] 内部槽、一个 [[ArrayBufferByteLength]] 内部槽,以及一个 [[ArrayBufferDetachKey]] 内部槽。可调整大小的 ArrayBuffer 实例还拥有 [[ArrayBufferMaxByteLength]] 内部槽。

如果 ArrayBuffer 实例的 [[ArrayBufferData]]null,则视为已分离,所有用于访问或修改该 ArrayBuffer 实例中数据的操作都会失败。

如果 ArrayBuffer 实例的 [[ArrayBufferDetachKey]] 被设置为非 undefined 的值,则所有 DetachArrayBuffer 调用都必须传递相同的“detach key”作为参数,否则将抛出 TypeError。该内部槽只会被某些嵌入环境设置,而不会被本规范中的算法设置。

25.1.8 可调整长度 ArrayBuffer 指南

注 1

以下是针对使用 可调整长度 ArrayBuffer 的 ECMAScript 程序员的建议。

建议程序尽可能在其部署环境中进行测试。不同硬件设备的物理内存容量差异巨大。同样,虚拟内存子系统在不同的硬件设备和操作系统间也差异很大。在 64 位桌面 Web 浏览器上无内存溢出错误运行的应用程序,可能会在 32 位移动 Web 浏览器上耗尽内存。

可调整长度 ArrayBuffer"maxByteLength" 选项选择数值时,建议选择应用程序所需的最小值。建议 "maxByteLength" 不超过 1,073,741,824(230 字节或 1GiB)。

请注意,为特定最大值成功构造一个 可调整长度 ArrayBuffer,并不保证将来调整大小一定会成功。

注 2

以下是针对实现 可调整长度 ArrayBuffer 的 ECMAScript 实现者的建议。

可调整长度 ArrayBuffer 的实现可以为调整大小时复制、也可以通过预先保留虚拟内存实现原地扩展,或针对 构造函数"maxByteLength" 选项的不同值组合二者。

如果 宿主 是多租户(即同时运行多个 ECMAScript 应用,例如 Web 浏览器),且实现选择通过预留虚拟内存实现原地扩展,我们建议 32 位和 64 位实现对 "maxByteLength" ≥ 1GiB 到 1.5GiB 的值都抛出异常。这样可以减少单个应用耗尽虚拟内存地址空间的可能,也有助于减小互操作性风险。

如果 宿主 没有虚拟内存(如无 MMU 的嵌入式设备),或 宿主 只通过复制实现调整大小,则可以接受 "maxByteLength" 选项的任意 Number 值。但建议如果请求的内存块大小永远无法分配,则抛出 RangeError。例如,请求的大小大于设备可用最大内存。

25.2 SharedArrayBuffer 对象

25.2.1 固定长度和可增长 SharedArrayBuffer 对象

固定长度 SharedArrayBuffer 是指创建后字节长度不可更改的 SharedArrayBuffer。

可增长 SharedArrayBuffer 是指其字节长度可以在创建后通过调用 SharedArrayBuffer.prototype.grow ( newLength ) 进行增加的 SharedArrayBuffer。

所创建的 SharedArrayBuffer 对象的种类取决于传递给 SharedArrayBuffer ( length [ , options ] ) 的参数。

25.2.2 SharedArrayBuffer 对象的抽象操作

25.2.2.1 AllocateSharedArrayBuffer ( constructor, byteLength [ , maxByteLength ] )

抽象操作 AllocateSharedArrayBuffer 接收参数 constructor(一个 构造函数)、byteLength(非负整数),可选参数 maxByteLength(非负整数empty),返回一个 正常完成,包含 SharedArrayBuffer 或 抛出完成。用于创建 SharedArrayBuffer。调用时执行以下步骤:

  1. slots 为 « [[ArrayBufferData]] »。
  2. 如果 maxByteLength 存在且不为 empty,令 allocatingGrowableBuffertrue;否则令 allocatingGrowableBufferfalse
  3. 如果 allocatingGrowableBuffertrue,则
    1. 如果 byteLength > maxByteLength,抛出 RangeError 异常。
    2. [[ArrayBufferByteLengthData]][[ArrayBufferMaxByteLength]] 添加到 slots
  4. 否则,
    1. [[ArrayBufferByteLength]] 添加到 slots
  5. obj 为 ? OrdinaryCreateFromConstructor(constructor, "%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 )

抽象操作 IsSharedArrayBuffer 接收参数 obj(一个 ArrayBuffer 或 SharedArrayBuffer),返回布尔值。用于检测对象是 ArrayBuffer、SharedArrayBuffer 还是二者的子类型。调用时执行以下步骤:

  1. bufferDataobj.[[ArrayBufferData]]
  2. 如果 bufferDatanull,返回 false
  3. 如果 bufferDataData Block,返回 false
  4. 断言bufferData 是一个 Shared Data Block
  5. 返回 true

25.2.2.3 HostGrowSharedArrayBuffer ( buffer, newByteLength )

宿主定义抽象操作 HostGrowSharedArrayBuffer 接收参数 buffer(一个 SharedArrayBuffer)和 newByteLength(非负整数),返回 正常完成,包含 handledunhandled,或 抛出完成。该操作为 宿主 提供机会执行 实现定义buffer 扩容。如果 宿主 选择不处理 buffer 的扩容,则可返回 unhandled 以执行默认行为。

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

  • 如果该抽象操作不是以 unhandled 正常完成,并且 newByteLength < buffer 当前字节长度或 newByteLength > buffer.[[ArrayBufferMaxByteLength]],抛出 RangeError 异常。
  • isLittleEndian周围代理Agent Record[[LittleEndian]] 字段的值。如果该抽象操作以 handled 正常完成,则 周围代理候选执行 中将添加一个 WriteSharedMemoryReadModifyWriteSharedMemory 事件,其 [[Order]]seq-cst[[Payload]]NumericToRawBytes(biguint64, newByteLength, isLittleEndian),[[Block]]buffer.[[ArrayBufferByteLengthData]][[ByteIndex]] 为 0,[[ElementSize]] 为 8。这样可以确保对 SharedArrayBuffer.prototype.grow 的竞争调用不会“丢失”,即不会悄然无效。

上述第二点故意没有规定如何或何时读取 buffer 的当前字节长度。由于字节长度必须通过底层硬件上的原子读-改-写操作进行更新,采用 load-link/store-conditional 或 load-exclusive/store-exclusive 指令对的架构可能希望将配对指令保持在指令流中较近的位置。因此,SharedArrayBuffer.prototype.grow 自身不会在调用 HostGrowSharedArrayBuffer 前对 newByteLength 进行边界检查,也不要求何时读取当前字节长度。

这与 HostResizeArrayBuffer 形成对比,后者保证 newByteLength 的值在 0 到 buffer.[[ArrayBufferMaxByteLength]] 之间。

HostGrowSharedArrayBuffer 的默认实现是返回 NormalCompletion(unhandled)。

25.2.3 SharedArrayBuffer 构造函数

SharedArrayBuffer 构造函数

  • %SharedArrayBuffer%
  • 如果该属性存在,则是 全局对象"SharedArrayBuffer" 属性的初始值(见下文)。
  • 作为 构造函数 调用时会创建并初始化一个新的 SharedArrayBuffer。
  • 不应作为普通函数调用,否则会抛出异常。
  • 可以用作类定义的 extends 子句的值。想要继承指定 SharedArrayBuffer 行为的子类 构造函数 必须包含对 SharedArrayBuffer 构造函数super 调用,以用必要的内部状态创建和初始化子类实例,以支持 SharedArrayBuffer.prototype 内建方法。

如果 宿主 不提供对 SharedArrayBuffer 的并发访问,它可以省略 全局对象"SharedArrayBuffer" 属性。

ArrayBuffer 不同,SharedArrayBuffer 不会被分离,其内部 [[ArrayBufferData]] 槽也永远不会是 null

25.2.3.1 SharedArrayBuffer ( length [ , options ] )

该函数被调用时执行以下步骤:

  1. 如果 NewTarget 为 undefined,抛出 TypeError 异常。
  2. byteLength 为 ? ToIndex(length)。
  3. requestedMaxByteLength 为 ? GetArrayBufferMaxByteLengthOption(options)。
  4. 返回 ? AllocateSharedArrayBuffer(NewTarget, byteLength, requestedMaxByteLength)。

25.2.4 SharedArrayBuffer 构造函数的属性

SharedArrayBuffer 构造函数

25.2.4.1 SharedArrayBuffer.prototype

SharedArrayBuffer.prototype 的初始值为 SharedArrayBuffer 原型对象

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

25.2.4.2 get SharedArrayBuffer [ %Symbol.species% ]

SharedArrayBuffer[%Symbol.species%] 是一个 访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数被调用时执行以下步骤:

  1. 返回 this 值。

此函数的 "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. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[ArrayBufferData]])。
  3. 如果 IsSharedArrayBuffer(O) 为 false,抛出 TypeError 异常。
  4. lengthArrayBufferByteLength(O, seq-cst)。
  5. 返回 𝔽(length)。

25.2.5.2 SharedArrayBuffer.prototype.constructor

SharedArrayBuffer.prototype.constructor 的初始值为 %SharedArrayBuffer%

25.2.5.3 SharedArrayBuffer.prototype.grow ( newLength )

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[ArrayBufferMaxByteLength]])。
  3. 如果 IsSharedArrayBuffer(O) 为 false,抛出 TypeError 异常。
  4. newByteLength 为 ? ToIndex(newLength)。
  5. hostHandled 为 ? HostGrowSharedArrayBuffer(O, newByteLength)。
  6. 如果 hostHandledhandled,返回 undefined
  7. isLittleEndian周围代理Agent Record[[LittleEndian]] 字段的值。
  8. byteLengthBlockO.[[ArrayBufferByteLengthData]]
  9. currentByteLengthRawBytesGetRawBytesFromSharedBlock(byteLengthBlock, 0, biguint64, true, seq-cst)。
  10. newByteLengthRawBytesNumericToRawBytes(biguint64, (newByteLength), isLittleEndian)。
  11. 重复,
    1. 注:这是一个比较并交换循环,用于确保对同一缓冲区的并发增长操作有全序、不丢失且不会悄然无效。当循环能够尝试无竞争地增长时退出。
    2. currentByteLength(RawBytesToNumeric(biguint64, currentByteLengthRawBytes, isLittleEndian))。
    3. 如果 newByteLength = currentByteLength,返回 undefined
    4. 如果 newByteLength < currentByteLengthnewByteLength > O.[[ArrayBufferMaxByteLength]],抛出 RangeError 异常。
    5. byteLengthDeltanewByteLength - currentByteLength
    6. 如果无法创建由 byteLengthDelta 字节组成的新 共享数据块,抛出 RangeError 异常。
    7. 注:此处不会创建并使用新的 共享数据块。可增长 SharedArrayBuffer 的可观察行为通过在构造时分配最大值的 max 大小的 共享数据块 体现,本步骤用于要求实现遇到内存不足时必须抛出 RangeError
    8. readByteLengthRawBytesAtomicCompareExchangeInSharedBlock(byteLengthBlock, 0, 8, currentByteLengthRawBytes, newByteLengthRawBytes)。
    9. 如果 ByteListEqual(readByteLengthRawBytes, currentByteLengthRawBytes) 为 true,返回 undefined
    10. 设置 currentByteLengthRawBytesreadByteLengthRawBytes

比较-交换操作更新长度出现伪失败是不允许的。如果新长度的边界检查通过且实现未耗尽内存,则总会在 候选执行 中添加一个 ReadModifyWriteSharedMemory 事件(即比较-交换成功)。

对 SharedArrayBuffer.prototype.grow 的并发调用是全序的。例如,考虑两个竞争调用:sab.grow(10)sab.grow(20)。这两个调用中的一个保证会赢得竞争。即使 sab.grow(20) 先发生,sab.grow(10) 也绝不会导致 sab 变小;此时它会抛出 RangeError。

25.2.5.4 get SharedArrayBuffer.prototype.growable

SharedArrayBuffer.prototype.growable 是一个 访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数被调用时执行以下步骤:

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[ArrayBufferData]])。
  3. 如果 IsSharedArrayBuffer(O) 为 false,抛出 TypeError 异常。
  4. 如果 IsFixedLengthArrayBuffer(O) 为 false,返回 true;否则返回 false

25.2.5.5 get SharedArrayBuffer.prototype.maxByteLength

SharedArrayBuffer.prototype.maxByteLength 是一个 访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数被调用时执行以下步骤:

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[ArrayBufferData]])。
  3. 如果 IsSharedArrayBuffer(O) 为 false,抛出 TypeError 异常。
  4. 如果 IsFixedLengthArrayBuffer(O) 为 true,则
    1. lengthO.[[ArrayBufferByteLength]]
  5. 否则,
    1. lengthO.[[ArrayBufferMaxByteLength]]
  6. 返回 𝔽(length)。

25.2.5.6 SharedArrayBuffer.prototype.slice ( start, end )

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[ArrayBufferData]])。
  3. 如果 IsSharedArrayBuffer(O) 为 false,抛出 TypeError 异常。
  4. lenArrayBufferByteLength(O, seq-cst)。
  5. relativeStart 为 ? ToIntegerOrInfinity(start)。
  6. 如果 relativeStart = -∞,令 first 为 0。
  7. 否则如果 relativeStart < 0,令 firstmax(len + relativeStart, 0)。
  8. 否则,令 firstmin(relativeStart, len)。
  9. 如果 endundefined,令 relativeEndlen;否则令 relativeEnd 为 ? ToIntegerOrInfinity(end)。
  10. 如果 relativeEnd = -∞,令 final 为 0。
  11. 否则如果 relativeEnd < 0,令 finalmax(len + relativeEnd, 0)。
  12. 否则,令 finalmin(relativeEnd, len)。
  13. newLenmax(final - first, 0)。
  14. ctor 为 ? SpeciesConstructor(O, %SharedArrayBuffer%)。
  15. new 为 ? Construct(ctor, « 𝔽(newLen) »)。
  16. 执行 ? RequireInternalSlot(new, [[ArrayBufferData]])。
  17. 如果 IsSharedArrayBuffer(new) 为 false,抛出 TypeError 异常。
  18. 如果 new.[[ArrayBufferData]]O.[[ArrayBufferData]],抛出 TypeError 异常。
  19. 如果 ArrayBufferByteLength(new, seq-cst) < newLen,抛出 TypeError 异常。
  20. fromBufO.[[ArrayBufferData]]
  21. toBufnew.[[ArrayBufferData]]
  22. 执行 CopyDataBlockBytes(toBuf, 0, fromBuf, first, newLen)。
  23. 返回 new

25.2.5.7 SharedArrayBuffer.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值为字符串值 "SharedArrayBuffer"

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

25.2.6 SharedArrayBuffer 实例的属性

SharedArrayBuffer 实例继承自 SharedArrayBuffer 原型对象 的属性。每个 SharedArrayBuffer 实例都有一个 [[ArrayBufferData]] 内部槽。不可增长的 SharedArrayBuffer 实例还有一个 [[ArrayBufferByteLength]] 内部槽。可增长的 SharedArrayBuffer 实例有 [[ArrayBufferByteLengthData]] 内部槽和 [[ArrayBufferMaxByteLength]] 内部槽。

SharedArrayBuffer 实例与 ArrayBuffer 实例不同,永远不会被分离。

25.2.7 可增长 SharedArrayBuffer 指南

注 1

以下是针对使用 可增长 SharedArrayBuffer 的 ECMAScript 程序员的建议。

建议程序尽可能在其部署环境中进行测试。不同硬件设备的物理内存容量差异巨大。同样,虚拟内存子系统在不同的硬件设备和操作系统间也差异很大。在 64 位桌面 Web 浏览器上无内存溢出错误运行的应用程序,可能会在 32 位移动 Web 浏览器上耗尽内存。

可增长 SharedArrayBuffer"maxByteLength" 选项选择数值时,建议选择应用程序所需的最小值。建议 "maxByteLength" 不超过 1073741824(即 1GiB)。

请注意,为特定最大值成功构造一个 可增长 SharedArrayBuffer,并不保证将来扩容一定会成功。

并非所有对 可增长 SharedArrayBuffer 长度的读取都是同步 seq-cst 读取。用于 整数索引属性访问(如 u8[idx])的长度读取不是同步的。一般来说,在缺少显式同步的情况下,一次属性访问在范围内并不意味着同一 代理 中后续的属性访问也在范围内。相比之下,通过 SharedArrayBuffer 的 lengthbyteLength getter、%TypedArray%.prototype 以及 DataView.prototype 的显式长度读取是同步的。内置方法在判断 TypedArray 是否完全越界时进行的长度加载也是同步的。

注 2

以下是针对实现 可增长 SharedArrayBuffer 的 ECMAScript 实现者的建议。

建议 可增长 SharedArrayBuffer 通过预先保留虚拟内存实现原地增长。

因为 grow 操作可能与可增长 SharedArrayBuffer 的内存访问并行发生,内存模型 的约束要求即使是无序访问也不会“撕裂”(即其值的位不会混淆)。实际上,这意味着可增长 SharedArrayBuffer 的底层数据块不能通过复制方式扩容,除非暂停所有操作。我们不建议采用暂停世界的实现策略,因为这会产生串行化点且效率低下。

扩容后新增的内存必须从创建时起就表现为全零,包括对并发访问也是如此。这可以通过按需零填充的虚拟内存页实现,或通过手动清零时的细致同步实现。

对可增长 SharedArrayBuffer 的 TypedArray 视图的 整数索引属性访问,旨在与非可增长 SharedArrayBuffer 的 TypedArray 视图访问一样可优化,因为这些属性访问的长度加载不是同步的(见上方程序员指南)。例如,属性访问的越界检查仍然可以被提升到循环之外。

实际上,在没有虚拟内存的 宿主(如无 MMU 的嵌入式设备)上,通过复制方式实现 可增长 SharedArrayBuffer 是很难的。在这类宿主上的可增长 SharedArrayBuffer 的内存使用行为可能会与有虚拟内存的宿主差异很大。这类 宿主 应当向用户明确说明内存使用预期。

25.3 DataView 对象

25.3.1 DataView 对象的抽象操作

25.3.1.1 带 Buffer 见证记录的 DataView

带 Buffer 见证记录的 DataView 是一个 Record 类型的值,用于封装一个 DataView 以及被查看缓冲区的缓存字节长度。当被查看缓冲区是可增长的 SharedArrayBuffers 时,用来确保只发生一次对字节长度数据块的共享内存读取事件。

带 Buffer 见证记录的 DataView 拥有 表 77 列出的字段。

表 77:带 Buffer 见证记录的 DataView 字段
字段名 含义
[[Object]] 一个 DataView 被加载缓冲区字节长度的 DataView 对象。
[[CachedBufferByteLength]] 一个非负整数detached 创建该 Record 时对象的 [[ViewedArrayBuffer]] 的字节长度。

25.3.1.2 MakeDataViewWithBufferWitnessRecord ( obj, order )

抽象操作 MakeDataViewWithBufferWitnessRecord 接收参数 obj(一个 DataView)和 orderseq-cstunordered),返回一个 带 Buffer 见证记录的 DataView。调用时执行以下步骤:

  1. bufferobj.[[ViewedArrayBuffer]]
  2. 如果 IsDetachedBuffer(buffer) 为 true,则
    1. byteLengthdetached
  3. 否则,
    1. byteLengthArrayBufferByteLength(buffer, order)。
  4. 返回 带 Buffer 见证记录的 DataView { [[Object]]: obj, [[CachedBufferByteLength]]: byteLength }。

25.3.1.3 GetViewByteLength ( viewRecord )

抽象操作 GetViewByteLength 接收参数 viewRecord(一个 带 Buffer 见证记录的 DataView),返回一个非负整数。调用时执行以下步骤:

  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 )

抽象操作 IsViewOutOfBounds 接收参数 viewRecord(一个 带 Buffer 见证记录的 DataView),返回布尔值。调用时执行以下步骤:

  1. viewviewRecord.[[Object]]
  2. bufferByteLengthviewRecord.[[CachedBufferByteLength]]
  3. 断言IsDetachedBuffer(view.[[ViewedArrayBuffer]]) 为 true 当且仅当 bufferByteLengthdetached
  4. 如果 bufferByteLengthdetached,返回 true
  5. byteOffsetStartview.[[ByteOffset]]
  6. 如果 view.[[ByteLength]]auto,则
    1. byteOffsetEndbufferByteLength
  7. 否则,
    1. byteOffsetEndbyteOffsetStart + view.[[ByteLength]]
  8. 如果 byteOffsetStart > bufferByteLengthbyteOffsetEnd > bufferByteLength,返回 true
  9. 注:长度为 0 的 DataView 不视为越界。
  10. 返回 false

25.3.1.5 GetViewValue ( view, requestIndex, isLittleEndian, type )

抽象操作 GetViewValue 接收参数 view(一个 ECMAScript 语言值)、requestIndex(一个 ECMAScript 语言值)、isLittleEndian(一个 ECMAScript 语言值)、typeTypedArray 元素类型),返回 正常完成,包含 Number 或 BigInt,或 抛出完成。被 DataView 实例上的函数用来从视图缓冲区获取值。调用时执行以下步骤:

  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. elementSize表 75 中元素类型 type 指定的元素大小值。
  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 )

抽象操作 SetViewValue 接收参数 view(一个 ECMAScript 语言值)、requestIndex(一个 ECMAScript 语言值)、isLittleEndian(一个 ECMAScript 语言值)、typeTypedArray 元素类型)、valueECMAScript 语言值),返回 正常完成,包含 undefined抛出完成。被 DataView 实例上的函数用来将值存入视图缓冲区。调用时执行以下步骤:

  1. 执行 ? RequireInternalSlot(view, [[DataView]])。
  2. 断言view 拥有 [[ViewedArrayBuffer]] 内部槽。
  3. getIndex 为 ? ToIndex(requestIndex)。
  4. 如果 IsBigIntElementType(type) 为 true,令 numberValue 为 ? ToBigInt(value)。
  5. 否则,令 numberValue 为 ? 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. elementSize表 75 中元素类型 type 指定的元素大小值。
  13. 如果 getIndex + elementSize > viewSize,抛出 RangeError 异常。
  14. bufferIndexgetIndex + viewOffset
  15. 执行 SetValueInBuffer(view.[[ViewedArrayBuffer]], bufferIndex, type, numberValue, 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. O 为 ? 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. 设置 O.[[ViewedArrayBuffer]]buffer
  16. 设置 O.[[ByteLength]]viewByteLength
  17. 设置 O.[[ByteOffset]]offset
  18. 返回 O

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. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[DataView]])。
  3. 断言O 拥有 [[ViewedArrayBuffer]] 内部槽。
  4. bufferO.[[ViewedArrayBuffer]]
  5. 返回 buffer

25.3.4.2 get DataView.prototype.byteLength

DataView.prototype.byteLength 是一个 访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数被调用时执行以下步骤:

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[DataView]])。
  3. 断言O 拥有 [[ViewedArrayBuffer]] 内部槽。
  4. viewRecordMakeDataViewWithBufferWitnessRecord(O, 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. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[DataView]])。
  3. 断言O 拥有 [[ViewedArrayBuffer]] 内部槽。
  4. viewRecordMakeDataViewWithBufferWitnessRecord(O, seq-cst)。
  5. 如果 IsViewOutOfBounds(viewRecord) 为 true,抛出 TypeError 异常。
  6. offsetO.[[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,则设置 littleEndianfalse
  3. 返回 ? GetViewValue(view, byteOffset, littleEndian, float16).

25.3.4.8 DataView.prototype.getFloat32 ( byteOffset [ , littleEndian ] )

该方法被调用时执行以下步骤:

  1. viewthis 值。
  2. 如果未传入 littleEndian,则设置 littleEndianfalse
  3. 返回 ? GetViewValue(view, byteOffset, littleEndian, float32).

25.3.4.9 DataView.prototype.getFloat64 ( byteOffset [ , littleEndian ] )

该方法被调用时执行以下步骤:

  1. viewthis 值。
  2. 如果未传入 littleEndian,则设置 littleEndianfalse
  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,则设置 littleEndianfalse
  3. 返回 ? GetViewValue(view, byteOffset, littleEndian, int16).

25.3.4.12 DataView.prototype.getInt32 ( byteOffset [ , littleEndian ] )

该方法被调用时执行以下步骤:

  1. viewthis 值。
  2. 如果未传入 littleEndian,则设置 littleEndianfalse
  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,则设置 littleEndianfalse
  3. 返回 ? GetViewValue(view, byteOffset, littleEndian, uint16).

25.3.4.15 DataView.prototype.getUint32 ( byteOffset [ , littleEndian ] )

该方法被调用时执行以下步骤:

  1. viewthis 值。
  2. 如果未传入 littleEndian,则设置 littleEndianfalse
  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,则设置 littleEndianfalse
  3. 返回 ? SetViewValue(view, byteOffset, littleEndian, float16, value).

25.3.4.19 DataView.prototype.setFloat32 ( byteOffset, value [ , littleEndian ] )

该方法被调用时执行以下步骤:

  1. viewthis 值。
  2. 如果未传入 littleEndian,则设置 littleEndianfalse
  3. 返回 ? SetViewValue(view, byteOffset, littleEndian, float32, value).

25.3.4.20 DataView.prototype.setFloat64 ( byteOffset, value [ , littleEndian ] )

该方法被调用时执行以下步骤:

  1. viewthis 值。
  2. 如果未传入 littleEndian,则设置 littleEndianfalse
  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,则设置 littleEndianfalse
  3. 返回 ? SetViewValue(view, byteOffset, littleEndian, int16, value).

25.3.4.23 DataView.prototype.setInt32 ( byteOffset, value [ , littleEndian ] )

该方法被调用时执行以下步骤:

  1. viewthis 值。
  2. 如果未传入 littleEndian,则设置 littleEndianfalse
  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,则设置 littleEndianfalse
  3. 返回 ? SetViewValue(view, byteOffset, littleEndian, uint16, value).

25.3.4.26 DataView.prototype.setUint32 ( byteOffset, value [ , littleEndian ] )

该方法被调用时执行以下步骤:

  1. viewthis 值。
  2. 如果未传入 littleEndian,则设置 littleEndianfalse
  3. 返回 ? SetViewValue(view, byteOffset, littleEndian, uint32, value).

25.3.4.27 DataView.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值为字符串值 "DataView"

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

25.3.5 DataView 实例的属性

DataView 实例是普通对象,继承自 DataView 原型对象 的属性。每个 DataView 实例都有 [[DataView]][[ViewedArrayBuffer]][[ByteLength]][[ByteOffset]] 内部槽。

[[DataView]] 内部槽的值在本规范中不会被使用。该内部槽的简单存在用来标识通过 DataView 构造函数 创建的对象。

25.4 Atomics 对象

Atomics 对象:

  • %Atomics%
  • 全局对象"Atomics" 属性的初始值。
  • 是一个 普通对象
  • 拥有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%
  • 没有 [[Construct]] 内部方法;不能使用 new 运算符作为 构造函数 使用。
  • 没有 [[Call]] 内部方法;不能作为函数调用。

Atomics 对象提供能在共享内存数组单元上以不可分割(原子)方式操作的函数,以及允许 代理 等待和派发原语事件的函数。规范使用 Atomics 函数,可以让通过共享内存通信的多代理程序,即使在并行 CPU 上,也能以可理解的顺序执行。管理共享内存通信的规则由下文定义的 内存模型 提供。

关于 ECMAScript 中共享内存的编程和实现的参考指南,请参见 内存模型 一节末尾的注释。

25.4.1 Waiter 记录

Waiter 记录 是一个 Record 值,用于表示一次 Atomics.waitAtomics.waitAsync 调用。

Waiter 记录的字段见 表 78

表 78:Waiter 记录 字段
字段名 含义
[[AgentSignifier]] 一个 agent signifier 调用 Atomics.waitAtomics.waitAsync代理
[[PromiseCapability]] 一个 PromiseCapability 记录blocking 如果表示一次 Atomics.waitAsync 调用,则为结果 Promise,否则为 blocking
[[TimeoutTime]] 非负 扩展数学值 最早可能触发超时的时间;使用 时间值 计算。
[[Result]] "ok""timed-out" 调用的返回值。

25.4.2 WaiterList 记录

WaiterList 记录 用于解释通过 代理 进行 Atomics.waitAtomics.waitAsyncAtomics.notify 的等待与通知。

WaiterList 记录的字段见 表 79

表 79:WaiterList 记录 字段
字段名 含义
[[Waiters]] 一个 List ,元素为 Waiter 记录 等待在与该 WaiterList 相关联的位置上的 Atomics.waitAtomics.waitAsync 调用。
[[MostRecentLeaveEvent]] 一个 Synchronize 事件empty 最近一次离开其 临界区 的事件,如果从未进入过其 临界区,则为 empty

一个 WaiterList 中可以有多个 Waiter 记录 拥有相同的 代理标识符

代理簇 拥有一个 WaiterList 记录的存储区;该存储通过 (block, i) 索引,其中 block共享数据块iblock 内存的字节偏移。WaiterList 记录是 代理无关的:在 代理簇 中,任一 代理 按 (block, i) 查找 WaiterList 记录,结果都是相同的 WaiterList 记录。

每个 WaiterList 记录有一个 临界区,用于在求值期间控制对该 WaiterList 记录的独占访问。每次只有一个 代理 可进入 WaiterList 记录的临界区。进入和离开 WaiterList 记录临界区由 抽象操作 EnterCriticalSectionLeaveCriticalSection 控制。对 WaiterList 记录的操作——添加和移除等待的 代理、遍历代理列表、挂起和通知列表中的 代理、设置与获取 Synchronize 事件——只能由已进入该 WaiterList 记录临界区的 代理 执行。

25.4.3 Atomics 的抽象操作

25.4.3.1 ValidateIntegerTypedArray ( typedArray, waitable )

抽象操作 ValidateIntegerTypedArray 接收参数 typedArray(一个 ECMAScript 语言值)和 waitable(布尔值),返回 正常完成,包含 带 Buffer 见证记录的 TypedArray,或 抛出完成。调用时执行以下步骤:

  1. taRecord 为 ? ValidateTypedArray(typedArray, unordered)。
  2. 注:当 typedArray 的后备缓冲区为 可增长 SharedArrayBuffer 时,越界检查不是同步操作。
  3. 如果 waitabletrue,则
    1. 如果 typedArray.[[TypedArrayName]] 既不是 "Int32Array" 也不是 "BigInt64Array",抛出 TypeError 异常。
  4. 否则,
    1. typeTypedArrayElementType(typedArray)。
    2. 如果 IsUnclampedIntegerElementType(type) 为 falseIsBigIntElementType(type) 也为 false,抛出 TypeError 异常。
  5. 返回 taRecord

25.4.3.2 ValidateAtomicAccess ( taRecord, requestIndex )

抽象操作 ValidateAtomicAccess 接收参数 taRecord(一个 带 Buffer 见证记录的 TypedArray)和 requestIndex(一个 ECMAScript 语言值),返回 正常完成,包含 一个 整数,或 抛出完成。调用时执行以下步骤:

  1. lengthTypedArrayLength(taRecord)。
  2. accessIndex 为 ? ToIndex(requestIndex)。
  3. 断言accessIndex ≥ 0。
  4. 如果 accessIndexlength,抛出 RangeError 异常。
  5. typedArraytaRecord.[[Object]]
  6. elementSizeTypedArrayElementSize(typedArray)。
  7. offsettypedArray.[[ByteOffset]]
  8. 返回 (accessIndex × elementSize) + offset

25.4.3.3 ValidateAtomicAccessOnIntegerTypedArray ( typedArray, requestIndex )

抽象操作 ValidateAtomicAccessOnIntegerTypedArray 接收参数 typedArray(一个 ECMAScript 语言值)和 requestIndex(一个 ECMAScript 语言值),返回 正常完成,包含 一个 整数,或 抛出完成。调用时执行以下步骤:

  1. taRecord 为 ? ValidateIntegerTypedArray(typedArray, false)。
  2. 返回 ? ValidateAtomicAccess(taRecord, requestIndex)。

25.4.3.4 RevalidateAtomicAccess ( typedArray, byteIndexInBuffer )

抽象操作 RevalidateAtomicAccess 接收参数 typedArray(一个 TypedArray)和 byteIndexInBuffer(一个 整数),返回 正常完成,包含 unused抛出完成。 该操作在 Atomics 方法中所有参数强制类型转换完成后重新校验用于原子操作的缓冲区索引,因为参数转换可能有任意副作用,导致缓冲区越界。当 typedArray 的后备缓冲区为 SharedArrayBuffer 时,本操作不会抛出异常。调用时执行以下步骤:

  1. taRecordMakeTypedArrayWithBufferWitnessRecord(typedArray, unordered)。
  2. 注:当 typedArray 的后备缓冲区为 可增长 SharedArrayBuffer 时,越界检查不是同步操作。
  3. 如果 IsTypedArrayOutOfBounds(taRecord) 为 true,抛出 TypeError 异常。
  4. 断言byteIndexInBuffertypedArray.[[ByteOffset]]
  5. 如果 byteIndexInBuffertaRecord.[[CachedBufferByteLength]],抛出 RangeError 异常。
  6. 返回 unused

25.4.3.5 GetWaiterList ( block, i )

抽象操作 GetWaiterList 接收参数 block(一个 共享数据块)和 i(一个能被 4 整除的非负整数),返回一个 WaiterList 记录。调用时执行以下步骤:

  1. 断言ii + 3 是 block 内存中的有效字节偏移。
  2. 返回由二元组 (block, i) 引用的 WaiterList 记录

25.4.3.6 EnterCriticalSection ( WL )

抽象操作 EnterCriticalSection 接收参数 WL(一个 WaiterList 记录),返回 unused。调用时执行以下步骤:

  1. 断言当前代理 未处于任何 WaiterList 记录临界区 中。
  2. 等待直到没有 代理 处于 WL临界区,然后进入 WL临界区(不允许其他 代理 进入)。
  3. 如果 WL.[[MostRecentLeaveEvent]] 不为 empty,则
    1. 注:至少进入过一次临界区的 WL 会有一个由 LeaveCriticalSection 设置的 Synchronize 事件
    2. execution当前代理Agent Record[[CandidateExecution]] 字段。
    3. eventsRecordexecution.[[EventsRecords]][[AgentSignifier]]AgentSignifier() 的 Agent Events Record
    4. enterEvent 为新的 Synchronize 事件
    5. enterEvent 添加到 eventsRecord.[[EventList]]
    6. 将 (WL.[[MostRecentLeaveEvent]], enterEvent) 添加到 eventsRecord.[[AgentSynchronizesWith]]
  4. 返回 unused

当某个 代理 试图进入 临界区 时必须等待其它 代理 离开该区,则 EnterCriticalSection 存在 争用。无争用时,EnterCriticalSection 的调用顺序可观察为 FIFO。有争用时,实现可选择任意顺序,但不得导致某 代理 无限期等待。

25.4.3.7 LeaveCriticalSection ( WL )

抽象操作 LeaveCriticalSection 接收参数 WL(一个 WaiterList 记录),返回 unused。调用时执行以下步骤:

  1. 断言当前代理 正处于 WL临界区 中。
  2. execution当前代理Agent Record[[CandidateExecution]] 字段。
  3. eventsRecordexecution.[[EventsRecords]][[AgentSignifier]]AgentSignifier() 的 Agent Events Record
  4. leaveEvent 为新的 Synchronize 事件
  5. leaveEvent 添加到 eventsRecord.[[EventList]]
  6. 设置 WL.[[MostRecentLeaveEvent]]leaveEvent
  7. 离开 WL临界区
  8. 返回 unused

25.4.3.8 AddWaiter ( WL, waiterRecord )

抽象操作 AddWaiter 接收参数 WL(一个 WaiterList 记录)和 waiterRecord(一个 Waiter 记录),返回 unused。调用时执行以下步骤:

  1. 断言当前代理 正处于 WL临界区 中。
  2. 断言WL.[[Waiters]] 中没有其 [[PromiseCapability]] 字段等于 waiterRecord.[[PromiseCapability]][[AgentSignifier]] 字段等于 waiterRecord.[[AgentSignifier]]Waiter 记录
  3. waiterRecord 添加到 WL.[[Waiters]]
  4. 返回 unused

25.4.3.9 RemoveWaiter ( WL, waiterRecord )

抽象操作 RemoveWaiter 接收参数 WL(一个 WaiterList 记录)和 waiterRecord(一个 Waiter 记录),返回 unused。调用时执行以下步骤:

  1. 断言当前代理 正处于 WL临界区 中。
  2. 断言WL.[[Waiters]] 包含 waiterRecord
  3. WL.[[Waiters]] 中移除 waiterRecord
  4. 返回 unused

25.4.3.10 RemoveWaiters ( WL, c )

抽象操作 RemoveWaiters 接收参数 WL(一个 WaiterList 记录)和 c(一个非负整数或 +∞),返回 List,元素为 Waiter 记录。调用时执行以下步骤:

  1. 断言当前代理 正处于 WL临界区 中。
  2. lenWL.[[Waiters]] 的元素数量。
  3. nmin(c, len)。
  4. LList,其元素为 WL.[[Waiters]] 的前 n 个元素。
  5. WL.[[Waiters]] 中移除前 n 个元素。
  6. 返回 L

25.4.3.11 SuspendThisAgent ( WL, waiterRecord )

抽象操作 SuspendThisAgent 接收参数 WL(一个 WaiterList 记录)和 waiterRecord(一个 Waiter 记录),返回 unused。调用时执行以下步骤:

  1. 断言当前代理 正处于 WL临界区 中。
  2. 断言WL.[[Waiters]] 包含 waiterRecord
  3. thisAgentAgentSignifier()。
  4. 断言waiterRecord.[[AgentSignifier]] 等于 thisAgent
  5. 断言waiterRecord.[[PromiseCapability]]blocking
  6. 断言AgentCanSuspend() 为 true
  7. 执行 LeaveCriticalSection(WL) 并挂起 当前代理 直到时间为 waiterRecord.[[TimeoutTime]],整个操作应保证在离开 临界区 后到挂起生效前收到的通知不会丢失。当前代理 只能因为超时或因其他 代理 调用 NotifyWaiter 并传入 WLthisAgent(即通过 Atomics.notify 调用)而被唤醒。
  8. 执行 EnterCriticalSection(WL)。
  9. 返回 unused

25.4.3.12 NotifyWaiter ( WL, waiterRecord )

抽象操作 NotifyWaiter 接收参数 WL(一个 WaiterList 记录)和 waiterRecord(一个 Waiter 记录),返回 unused。调用时执行以下步骤:

  1. 断言当前代理 正处于 WL临界区 中。
  2. 如果 waiterRecord.[[PromiseCapability]]blocking,则
    1. 唤醒其标识符为 waiterRecord.[[AgentSignifier]]代理
    2. 注:这会使 代理SuspendThisAgent 中恢复执行。
  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

一个 代理 不应以任何方式访问其他 代理 的 promise 能力,除了将其传递给 宿主

25.4.3.13 EnqueueResolveInAgentJob ( agentSignifier, promiseCapability, resolution )

抽象操作 EnqueueResolveInAgentJob 接收参数 agentSignifier(一个 代理标识符)、promiseCapability(一个 PromiseCapability 记录)、resolution"ok""timed-out"),返回 unused。调用时执行以下步骤:

  1. resolveJob 为新的 作业 抽象闭包,无参数,捕获 agentSignifierpromiseCapabilityresolution,被调用时执行以下步骤:
    1. 断言AgentSignifier() 等于 agentSignifier
    2. 执行 ! Call(promiseCapability.[[Resolve]], undefined, « resolution »)。
    3. 返回 unused
  2. realmInTargetAgent 为 ! GetFunctionRealm(promiseCapability.[[Resolve]])。
  3. 断言agentSignifier 等于 realmInTargetAgent.[[AgentSignifier]]
  4. 执行 HostEnqueueGenericJob(resolveJob, realmInTargetAgent)。
  5. 返回 unused

25.4.3.14 DoWait ( mode, typedArray, index, value, timeout )

抽象操作 DoWait 接收参数 modesyncasync)、typedArray(一个 ECMAScript 语言值)、 index(一个 ECMAScript 语言值)、 value(一个 ECMAScript 语言值)和 timeout(一个 ECMAScript 语言值),返回 正常完成,包含 Object、"not-equal""timed-out""ok",或 抛出完成。调用时执行以下步骤:

  1. taRecord 为 ? ValidateIntegerTypedArray(typedArray, true)。
  2. buffertaRecord.[[Object]].[[ViewedArrayBuffer]]
  3. 如果 IsSharedArrayBuffer(buffer) 为 false,抛出 TypeError 异常。
  4. i 为 ? ValidateAtomicAccess(taRecord, index)。
  5. arrayTypeNametypedArray.[[TypedArrayName]]
  6. 如果 arrayTypeName"BigInt64Array",令 v 为 ? ToBigInt64(value)。
  7. 否则,令 v 为 ? ToInt32(value)。
  8. q 为 ? ToNumber(timeout)。
  9. 如果 qNaN+∞𝔽,令 t 为 +∞;否则如果 q-∞𝔽,令 t 为 0;否则令 tmax((q), 0)。
  10. 如果 modesyncAgentCanSuspend() 为 false,抛出 TypeError 异常。
  11. blockbuffer.[[ArrayBufferData]]
  12. offsettypedArray.[[ByteOffset]]
  13. byteIndexInBuffer 为 (i × 4) + offset
  14. WLGetWaiterList(block, byteIndexInBuffer)。
  15. 如果 modesync,则
    1. promiseCapabilityblocking
    2. resultObjectundefined
  16. 否则,
    1. promiseCapability 为 ! NewPromiseCapability(%Promise%)。
    2. resultObjectOrdinaryObjectCreate(%Object.prototype%)。
  17. 执行 EnterCriticalSection(WL)。
  18. elementTypeTypedArrayElementType(typedArray)。
  19. wGetValueFromBuffer(buffer, byteIndexInBuffer, elementType, true, seq-cst)。
  20. 如果 vw,则
    1. 执行 LeaveCriticalSection(WL)。
    2. 如果 modesync,返回 "not-equal"
    3. 执行 ! CreateDataPropertyOrThrow(resultObject, "async", false)。
    4. 执行 ! CreateDataPropertyOrThrow(resultObject, "value", "not-equal")。
    5. 返回 resultObject
  21. 如果 t = 0 且 modeasync,则
    1. 注:同步即时超时不做特殊处理。异步即时超时有特殊处理以快速失败并避免不必要的 Promise 任务。
    2. 执行 LeaveCriticalSection(WL)。
    3. 执行 ! CreateDataPropertyOrThrow(resultObject, "async", false)。
    4. 执行 ! CreateDataPropertyOrThrow(resultObject, "value", "timed-out")。
    5. 返回 resultObject
  22. thisAgentAgentSignifier()。
  23. now时间值(UTC),标识当前时间。
  24. additionalTimeout 为实现定义的非负数学值
  25. timeoutTime(now) + t + additionalTimeout
  26. 注:当 t 为 +∞ 时,timeoutTime 也为 +∞。
  27. waiterRecord 为新的 Waiter 记录 { [[AgentSignifier]]: thisAgent, [[PromiseCapability]]: promiseCapability, [[TimeoutTime]]: timeoutTime, [[Result]]: "ok" }。
  28. 执行 AddWaiter(WL, waiterRecord)。
  29. 如果 modesync,则
    1. 执行 SuspendThisAgent(WL, waiterRecord)。
  30. 否则如果 timeoutTime有限,则
    1. 执行 EnqueueAtomicsWaitAsyncTimeoutJob(WL, waiterRecord)。
  31. 执行 LeaveCriticalSection(WL)。
  32. 如果 modesync,返回 waiterRecord.[[Result]]
  33. 执行 ! CreateDataPropertyOrThrow(resultObject, "async", true)。
  34. 执行 ! CreateDataPropertyOrThrow(resultObject, "value", promiseCapability.[[Promise]])。
  35. 返回 resultObject

additionalTimeout 允许实现根据需要填充超时时间,比如降低功耗或粗化定时器分辨率以缓解计时攻击。该值在 DoWait 的不同调用之间可能不同。

25.4.3.15 EnqueueAtomicsWaitAsyncTimeoutJob ( WL, waiterRecord )

抽象操作 EnqueueAtomicsWaitAsyncTimeoutJob 接收参数 WL(一个 WaiterList 记录)和 waiterRecord(一个 Waiter 记录),返回 unused。调用时执行以下步骤:

  1. timeoutJob 为新的 作业 抽象闭包,无参数,捕获 WLwaiterRecord,被调用时执行以下步骤:
    1. 执行 EnterCriticalSection(WL)。
    2. 如果 WL.[[Waiters]] 包含 waiterRecord,则
      1. timeOfJobExecution时间值(UTC),标识当前时间。
      2. 断言(timeOfJobExecution) ≥ waiterRecord.[[TimeoutTime]] (忽略 时间值 可能的非单调性)。
      3. 设置 waiterRecord.[[Result]]"timed-out"
      4. 执行 RemoveWaiter(WL, waiterRecord)。
      5. 执行 NotifyWaiter(WL, waiterRecord)。
    3. 执行 LeaveCriticalSection(WL)。
    4. 返回 unused
  2. now时间值(UTC),标识当前时间。
  3. currentRealm当前 Realm 记录
  4. 执行 HostEnqueueTimeoutJob(timeoutJob, currentRealm, 𝔽(waiterRecord.[[TimeoutTime]]) - now).
  5. 返回 unused

25.4.3.16 AtomicCompareExchangeInSharedBlock ( block, byteIndexInBuffer, elementSize, expectedBytes, replacementBytes )

抽象操作 AtomicCompareExchangeInSharedBlock 接收参数 block(一个 共享数据块)、byteIndexInBuffer(一个 整数)、elementSize(一个非负整数)、expectedBytes(一个 List,元素为 字节值)、replacementBytes(一个 List,元素为 字节值),返回一个 List,元素为 字节值。调用时执行以下步骤:

  1. execution当前代理Agent Record[[CandidateExecution]] 字段。
  2. eventsRecordexecution.[[EventsRecords]][[AgentSignifier]]AgentSignifier() 的 Agent Events Record
  3. rawBytesRead 为一个长度为 elementSizeList,其元素为非确定性选择的 字节值
  4. 注:在实现中,rawBytesRead 是底层硬件上 load-link、load-exclusive 或读-改-写指令的结果。该非确定性由 内存模型 的语义规定,用于描述弱一致性硬件的可观测行为。
  5. 注:预期值与读取值的比较在 读改写修改函数 之外进行,以避免当预期值不等于读取值时产生不必要的强同步。
  6. 如果 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 }。
  7. 否则,
    1. eventReadSharedMemory { [[Order]]: seq-cst, [[NoTear]]: true, [[Block]]: block, [[ByteIndex]]: byteIndexInBuffer, [[ElementSize]]: elementSize }。
  8. event 添加到 eventsRecord.[[EventList]]
  9. Chosen Value 记录 { [[Event]]: event, [[ChosenValue]]: rawBytesRead } 添加到 execution.[[ChosenValues]]
  10. 返回 rawBytesRead

25.4.3.17 AtomicReadModifyWrite ( typedArray, index, value, op )

抽象操作 AtomicReadModifyWrite 接收参数 typedArray(一个 ECMAScript 语言值)、 index(一个 ECMAScript 语言值)、 value(一个 ECMAScript 语言值)、op(一个 读改写修改函数),返回 正常完成,包含 Number 或 BigInt,或 抛出完成op 接收两个 List(元素为 字节值)参数,返回一个 List(元素为 字节值)。该操作以原子方式加载一个值,与另一个值组合,并存储组合结果。返回被加载的值。调用时执行以下步骤:

  1. byteIndexInBuffer 为 ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index)。
  2. 如果 typedArray.[[ContentType]]bigint,令 v 为 ? ToBigInt(value)。
  3. 否则,令 v𝔽(? ToIntegerOrInfinity(value))。
  4. 执行 ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer)。
  5. buffertypedArray.[[ViewedArrayBuffer]]
  6. elementTypeTypedArrayElementType(typedArray)。
  7. 返回 GetModifySetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, op)。

25.4.3.18 ByteListBitwiseOp ( op, xBytes, yBytes )

抽象操作 ByteListBitwiseOp 接收参数 op&^|)、xBytes(一个 List,元素为 字节值)、yBytes(一个 List,元素为 字节值),返回 List,元素为 字节值。该操作以原子方式对参数的所有字节值执行按位操作,并返回 List,元素为 字节值。调用时执行以下步骤:

  1. 断言xBytesyBytes 拥有相同数量的元素。
  2. result 为新的空 List
  3. i 为 0。
  4. 对于 xBytes 的每个元素 xByte,执行
    1. yByteyBytes[i]。
    2. 如果 op&,则
      1. resultBytexByteyByte 执行按位与操作的结果。
    3. 否则如果 op^,则
      1. resultBytexByteyByte 执行按位异或操作的结果。
    4. 否则,
      1. 断言op|
      2. resultBytexByteyByte 执行按位或操作的结果。
    5. 设置 ii + 1。
    6. resultByte 添加到 result
  5. 返回 result

25.4.3.19 ByteListEqual ( xBytes, yBytes )

抽象操作 ByteListEqual 接收参数 xBytes(一个 List,元素为 字节值)和 yBytes(一个 List,元素为 字节值),返回一个布尔值。调用时执行以下步骤:

  1. 如果 xBytesyBytes 的元素数量不同,返回 false
  2. i 为 0。
  3. 对于 xBytes 的每个元素 xByte,执行
    1. yByteyBytes[i]。
    2. 如果 xByteyByte,返回 false
    3. 设置 ii + 1。
  4. 返回 true

25.4.4 Atomics.add ( typedArray, index, value )

该函数被调用时执行以下步骤:

  1. add 为一个新的 读改写修改函数,参数为 (xBytes, yBytes),捕获 typedArray,当被原子方式调用时,执行以下步骤:
    1. typeTypedArrayElementType(typedArray)。
    2. isLittleEndian当前代理Agent Record[[LittleEndian]] 字段的值。
    3. xRawBytesToNumeric(type, xBytes, isLittleEndian)。
    4. yRawBytesToNumeric(type, yBytes, isLittleEndian)。
    5. 如果 x 是 Number,则
      1. sumNumber::add(x, y)。
    6. 否则,
      1. 断言x 是 BigInt
      2. sumBigInt::add(x, y)。
    7. sumBytesNumericToRawBytes(type, sum, isLittleEndian)。
    8. 断言sumBytesxBytesyBytes 具有相同的元素数量。
    9. 返回 sumBytes
  2. 返回 ? AtomicReadModifyWrite(typedArray, index, value, add)。

25.4.5 Atomics.and ( typedArray, index, value )

该函数被调用时执行以下步骤:

  1. and 为一个新的 读改写修改函数,参数为 (xBytes, yBytes),不捕获任何变量,当被原子方式调用时执行以下步骤:
    1. 返回 ByteListBitwiseOp(&, xBytes, yBytes)。
  2. 返回 ? AtomicReadModifyWrite(typedArray, index, value, and)。

25.4.6 Atomics.compareExchange ( typedArray, index, expectedValue, replacementValue )

该函数被调用时执行以下步骤:

  1. byteIndexInBuffer 为 ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index)。
  2. buffertypedArray.[[ViewedArrayBuffer]]
  3. blockbuffer.[[ArrayBufferData]]
  4. 如果 typedArray.[[ContentType]]bigint,则
    1. expected 为 ? ToBigInt(expectedValue)。
    2. replacement 为 ? ToBigInt(replacementValue)。
  5. 否则,
    1. expected𝔽(? ToIntegerOrInfinity(expectedValue))。
    2. replacement𝔽(? ToIntegerOrInfinity(replacementValue))。
  6. 执行 ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer)。
  7. elementTypeTypedArrayElementType(typedArray)。
  8. elementSizeTypedArrayElementSize(typedArray)。
  9. isLittleEndian当前代理Agent Record[[LittleEndian]] 字段的值。
  10. expectedBytesNumericToRawBytes(elementType, expected, isLittleEndian)。
  11. replacementBytesNumericToRawBytes(elementType, replacement, isLittleEndian)。
  12. 如果 IsSharedArrayBuffer(buffer) 为 true,则
    1. rawBytesReadAtomicCompareExchangeInSharedBlock(block, byteIndexInBuffer, elementSize, expectedBytes, replacementBytes)。
  13. 否则,
    1. rawBytesRead 为一个长度为 elementSizeList,其元素为从 block[byteIndexInBuffer] 开始的 elementSize 个字节序列。
    2. 如果 ByteListEqual(rawBytesRead, expectedBytes) 为 true,则
      1. replacementBytes 的各字节依次存入 block,起始于 block[byteIndexInBuffer]。
  14. 返回 RawBytesToNumeric(elementType, rawBytesRead, isLittleEndian)。

25.4.7 Atomics.exchange ( typedArray, index, value )

该函数被调用时执行以下步骤:

  1. second 为一个新的 读改写修改函数,参数为 (oldBytes, newBytes),不捕获任何变量,当被原子方式调用时执行以下步骤:
    1. 返回 newBytes
  2. 返回 ? AtomicReadModifyWrite(typedArray, index, value, second)。

25.4.8 Atomics.isLockFree ( size )

该函数被调用时执行以下步骤:

  1. n 为 ? ToIntegerOrInfinity(size)。
  2. AR当前代理Agent Record
  3. 如果 n = 1,返回 AR.[[IsLockFree1]]
  4. 如果 n = 2,返回 AR.[[IsLockFree2]]
  5. 如果 n = 4,返回 true
  6. 如果 n = 8,返回 AR.[[IsLockFree8]]
  7. 返回 false

该函数是一个优化原语。直观理解是:如果对一个字节数为 n 的数据执行原子操作(compareExchangeloadstoreaddsubandorxorexchange)时,当前代理 不会获得该 n 字节之外的锁,则 Atomics.isLockFree(n) 会返回 true。高性能算法会用该函数判断是在临界区用锁还是原子操作。如果原子操作不是无锁的,算法通常自带锁效率更高。

Atomics.isLockFree(4) 总是返回 true,因为所有相关硬件都支持。可以假定此条件通常会简化程序。

无论该函数返回何值,所有原子操作都保证是原子的。例如,永远不会在操作中间有可见操作发生(如“撕裂”)。

25.4.9 Atomics.load ( typedArray, index )

该函数被调用时执行以下步骤:

  1. byteIndexInBuffer 为 ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index)。
  2. 执行 ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer)。
  3. buffertypedArray.[[ViewedArrayBuffer]]
  4. elementTypeTypedArrayElementType(typedArray)。
  5. 返回 GetValueFromBuffer(buffer, byteIndexInBuffer, elementType, true, seq-cst)。

25.4.10 Atomics.or ( typedArray, index, value )

该函数被调用时执行以下步骤:

  1. or 为一个新的 读改写修改函数,参数为 (xBytes, yBytes),不捕获任何变量,当被原子方式调用时执行以下步骤:
    1. 返回 ByteListBitwiseOp(|, xBytes, yBytes)。
  2. 返回 ? AtomicReadModifyWrite(typedArray, index, value, or)。

25.4.11 Atomics.store ( typedArray, index, value )

该函数被调用时执行以下步骤:

  1. byteIndexInBuffer 为 ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index)。
  2. 如果 typedArray.[[ContentType]]bigint,令 v 为 ? ToBigInt(value)。
  3. 否则,令 v𝔽(? ToIntegerOrInfinity(value))。
  4. 执行 ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer)。
  5. buffertypedArray.[[ViewedArrayBuffer]]
  6. elementTypeTypedArrayElementType(typedArray)。
  7. 执行 SetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, true, seq-cst)。
  8. 返回 v

25.4.12 Atomics.sub ( typedArray, index, value )

该函数被调用时执行以下步骤:

  1. subtract 为一个新的 读改写修改函数,参数为 (xBytes, yBytes),捕获 typedArray,当被原子方式调用时,执行以下步骤:
    1. typeTypedArrayElementType(typedArray)。
    2. isLittleEndian当前代理Agent Record[[LittleEndian]] 字段的值。
    3. xRawBytesToNumeric(type, xBytes, isLittleEndian)。
    4. yRawBytesToNumeric(type, yBytes, isLittleEndian)。
    5. 如果 x 是 Number,则
      1. differenceNumber::subtract(x, y)。
    6. 否则,
      1. 断言x 是 BigInt
      2. differenceBigInt::subtract(x, y)。
    7. differenceBytesNumericToRawBytes(type, difference, isLittleEndian)。
    8. 断言differenceBytesxBytesyBytes 具有相同的元素数量。
    9. 返回 differenceBytes
  2. 返回 ? AtomicReadModifyWrite(typedArray, index, value, subtract)。

25.4.13 Atomics.wait ( typedArray, index, value, timeout )

该函数会将当前代理放入等待队列并挂起,直到被通知或超时,返回区分这些情况的字符串。

被调用时执行以下步骤:

  1. 返回 ? DoWait(sync, typedArray, index, value, timeout)。

25.4.14 Atomics.waitAsync ( typedArray, index, value, timeout )

该函数返回一个 Promise,当调用的 代理 被通知或超时时被 resolve。

被调用时执行以下步骤:

  1. 返回 ? DoWait(async, typedArray, index, value, timeout)。

25.4.15 Atomics.notify ( typedArray, index, count )

该函数会通知一些在等待队列中休眠的代理

被调用时执行以下步骤:

  1. taRecord 为 ? ValidateIntegerTypedArray(typedArray, true)。
  2. byteIndexInBuffer 为 ? ValidateAtomicAccess(taRecord, index)。
  3. 如果 countundefined,则
    1. c 为 +∞。
  4. 否则,
    1. intCount 为 ? ToIntegerOrInfinity(count)。
    2. cmax(intCount, 0)。
  5. buffertypedArray.[[ViewedArrayBuffer]]
  6. blockbuffer.[[ArrayBufferData]]
  7. 如果 IsSharedArrayBuffer(buffer) 为 false,返回 +0𝔽
  8. WLGetWaiterList(block, byteIndexInBuffer)。
  9. 执行 EnterCriticalSection(WL)。
  10. SRemoveWaiters(WL, c)。
  11. 对于 S 的每个元素 W,执行
    1. 执行 NotifyWaiter(WL, W)。
  12. 执行 LeaveCriticalSection(WL)。
  13. nS 的元素数量。
  14. 返回 𝔽(n)。

25.4.16 Atomics.xor ( typedArray, index, value )

该函数被调用时执行以下步骤:

  1. xor 为一个新的 读改写修改函数,参数为 (xBytes, yBytes),不捕获任何变量,当被原子方式调用时执行以下步骤:
    1. 返回 ByteListBitwiseOp(^, xBytes, yBytes)。
  2. 返回 ? AtomicReadModifyWrite(typedArray, index, value, xor)。

25.4.17 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.parse ( text [ , reviver ] )

该函数用于解析 JSON 文本(JSON 格式的字符串),并生成一个 ECMAScript 语言值。JSON 格式用与 ECMAScript 字面量、数组初始化器和对象初始化器类似的语法来表示字面量、数组和对象。解析后,JSON 对象被实现为 ECMAScript 对象,JSON 数组实现为 ECMAScript 数组实例。JSON 字符串、数字、布尔值和 null 分别实现为 ECMAScript 字符串、数字、布尔值和 null

可选参数 reviver 是一个带有两个参数 keyvalue 的函数。它可以过滤和转换结果。该函数会对解析产生的每一个 key/value 对调用,其返回值会替代原始值。如果返回原值,则结构不变。如果返回 undefined,则该属性会从结果中删除。

  1. jsonString 为 ? ToString(text)。
  2. unfiltered 为 ? ParseJSON(jsonString)。
  3. 如果 IsCallable(reviver) 为 true,则
    1. rootOrdinaryObjectCreate(%Object.prototype%)。
    2. rootName 为空字符串。
    3. 执行 ! CreateDataPropertyOrThrow(root, rootName, unfiltered)。
    4. 返回 ? InternalizeJSONProperty(root, rootName, reviver)。
  4. 否则,
    1. 返回 unfiltered

该函数的 "length" 属性为 2𝔽

25.5.1.1 ParseJSON ( text )

抽象操作 ParseJSON 接收参数 text(一个字符串),返回 正常完成,包含一个 ECMAScript 语言值,或 抛出完成。调用时执行以下步骤:

  1. 如果 StringToCodePoints(text) 不是 ECMA-404 规定的有效 JSON 文本,则抛出 SyntaxError 异常。
  2. scriptString字符串拼接 "("text");" 的结果。
  3. scriptParseText(scriptString, Script)。
  4. 注:Early Error 规则在 13.2.5.1 对上述 ParseText 调用有特殊处理。
  5. 断言script 是一个 解析节点
  6. result 为 ! Evaluation(script) 的结果。
  7. 注:PropertyDefinitionEvaluation 语义在 13.2.5.5 对上述求值有特殊处理。
  8. 断言result 必须是字符串、数字、布尔值、由 ArrayLiteralObjectLiteral 定义的对象,或 null
  9. 返回 result

符合要求的 JSON.parse 实现不允许扩展 JSON 语法。如果实现希望支持修改或扩展的 JSON 交换格式,必须通过另一个解析函数实现。

注 1

有效的 JSON 文本是 ECMAScript PrimaryExpression 语法的子集。步骤 1 检查 jsonString 是否符合该子集,步骤 8 断言求值结果类型正确。

然而,由于 13.2.5.5 在 ParseJSON 期间行为不同,同一源文本作为 PrimaryExpression 和 JSON 求值结果可能不同。此外,对象字面量中重复的 "__proto__" 属性的 Early Error 在 ParseJSON 期间不适用,这意味着 ParseJSON 接受的文本并不都是有效的 PrimaryExpression,尽管语法匹配。

注 2

在对象内存在重复名称字符串时,词法上靠前的同名键对应的值会被后面的覆盖。

25.5.1.2 InternalizeJSONProperty ( holder, name, reviver )

抽象操作 InternalizeJSONProperty 接收参数 holder(对象)、name(字符串)、reviver函数对象),返回 正常完成,包含一个 ECMAScript 语言值抛出完成

本算法有意不在 [[Delete]]CreateDataProperty 返回 false 时抛出异常。

调用时执行以下步骤:

  1. val 为 ? Get(holder, name)。
  2. 如果 val 是对象,则
    1. isArray 为 ? IsArray(val)。
    2. 如果 isArraytrue,则
      1. len 为 ? LengthOfArrayLike(val)。
      2. I 为 0。
      3. I < len 时重复,
        1. prop 为 ! ToString(𝔽(I))。
        2. newElement 为 ? InternalizeJSONProperty(val, prop, reviver)。
        3. 如果 newElementundefined,则
          1. 执行 ? val.[[Delete]](prop)。
        4. 否则,
          1. 执行 ? CreateDataProperty(val, prop, newElement)。
        5. 设置 II + 1。
    3. 否则,
      1. keys 为 ? EnumerableOwnProperties(val, key)。
      2. 对于 keys 的每个字符串 P,执行
        1. newElement 为 ? InternalizeJSONProperty(val, P, reviver)。
        2. 如果 newElementundefined,则
          1. 执行 ? val.[[Delete]](P)。
        3. 否则,
          1. 执行 ? CreateDataProperty(val, P, newElement)。
  3. 返回 ? Call(reviver, holder, « name, val »)。

25.5.2 JSON.stringify ( value [ , replacer [ , space ] ] )

该函数返回一个表示 ECMAScript 语言值 的 UTF-16 编码 JSON 格式字符串,或 undefined。它可以接收三个参数。value 参数是一个 ECMAScript 语言值,通常是对象或数组,也可以是字符串、布尔值、数字或 null。可选参数 replacer 可以是一个函数,用于改变对象和数组的序列化方式,或者是一个字符串和数字数组,作为包含列表选择要序列化的对象属性。可选参数 space 是字符串或数字,允许在结果中插入空白以提高人类可读性。

被调用时执行以下步骤:

  1. stack 为一个新的空 List
  2. indent 为空字符串。
  3. PropertyListundefined
  4. ReplacerFunctionundefined
  5. 如果 replacer 是对象,则
    1. 如果 IsCallable(replacer) 为 true,则
      1. 设置 ReplacerFunctionreplacer
    2. 否则,
      1. isArray 为 ? IsArray(replacer)。
      2. 如果 isArraytrue,则
        1. 设置 PropertyList 为一个新的空 List
        2. len 为 ? LengthOfArrayLike(replacer)。
        3. k 为 0。
        4. k < len 时重复,
          1. prop 为 ! ToString(𝔽(k))。
          2. v 为 ? Get(replacer, prop)。
          3. itemundefined
          4. 如果 v 是字符串,则
            1. 设置 itemv
          5. 否则如果 v 是数字,则
            1. 设置 item 为 ! ToString(v)。
          6. 否则如果 v 是对象,则
            1. 如果 v[[StringData]][[NumberData]] 内部槽,则设置 item 为 ? ToString(v)。
          7. 如果 item 不为 undefinedPropertyList 不包含 item,则
            1. item 添加到 PropertyList
          8. 设置 kk + 1。
  6. 如果 space 是对象,则
    1. 如果 space[[NumberData]] 内部槽,则
      1. 设置 space 为 ? ToNumber(space)。
    2. 否则如果 space[[StringData]] 内部槽,则
      1. 设置 space 为 ? ToString(space)。
  7. 如果 space 是数字,则
    1. spaceMV 为 ! ToIntegerOrInfinity(space)。
    2. 设置 spaceMVmin(10, spaceMV)。
    3. 如果 spaceMV < 1,令 gap 为空字符串;否则令 gap 为包含 spaceMV 个 0x0020 (SPACE) 码元的字符串。
  8. 否则如果 space 是字符串,则
    1. 如果 space 长度 ≤ 10,令 gapspace;否则令 gapspace 的前 10 个字符。
  9. 否则,
    1. gap 为空字符串。
  10. wrapperOrdinaryObjectCreate(%Object.prototype%)。
  11. 执行 ! CreateDataPropertyOrThrow(wrapper, 空字符串, value)。
  12. stateJSON 序列化记录 { [[ReplacerFunction]]: ReplacerFunction, [[Stack]]: stack, [[Indent]]: indent, [[Gap]]: gap, [[PropertyList]]: PropertyList }。
  13. 返回 ? SerializeJSONProperty(state, 空字符串, wrapper)。

该函数的 "length" 属性为 3𝔽

注 1

JSON 结构可以任意嵌套,但必须无环。如果 value 是或包含循环结构,则该函数必须抛出 TypeError 异常。例如,以下值无法被序列化:

a = [];
a[0] = a;
my_text = JSON.stringify(a); // 这里必须抛出 TypeError。
注 2

符号原始值的序列化规则如下:

  • null 在 JSON 文本中以字符串 "null" 表示。
  • undefined 不被序列化。
  • true 在 JSON 文本中以字符串 "true" 表示。
  • false 在 JSON 文本中以字符串 "false" 表示。
注 3

字符串值用引号(")括起来。"\ 需用 \ 转义。控制字符替换为 \uHHHH 或更短的 \b(退格)、\f(换页)、\n(换行)、\r(回车)、\t(制表)。

注 4

有限 数字序列化如同调用 ToString(number)。NaNInfinity(无论正负)以字符串 "null" 表示。

注 5

没有 JSON 表示的值(如 undefined 和函数)不会产生字符串,而是产生 undefined。在数组中这些值以字符串 "null" 表示。在对象中无法表示的值会导致该属性被排除于序列化结果之外。

注 6

对象以 U+007B(左大括号)开头,后接零个或多个属性(用 U+002C 逗号分隔),以 U+007D(右大括号)结尾。属性为带引号的字符串表示属性名、U+003A(冒号)和序列化后的值。数组以 U+005B(左中括号)开头,后接零个或多个值(用 U+002C 逗号分隔),以 U+005D(右中括号)结尾。

25.5.2.1 JSON 序列化记录

JSON 序列化记录 是一个 Record 值,用于支持序列化为 JSON 格式。

JSON 序列化记录的字段见 表 80

表 80:JSON 序列化记录 字段
字段名 含义
[[ReplacerFunction]] 函数对象undefined 可为对象属性提供替换值的函数(来自 JSON.stringify 的 replacer 参数)。
[[PropertyList]] List 的字符串,或 undefined 序列化非数组对象时要包含的属性名(来自 JSON.stringify 的 replacer 参数)。
[[Gap]] 字符串 缩进单位(来自 JSON.stringify 的 space 参数)。
[[Stack]] List 的对象 正在序列化的嵌套对象集合。用于检测循环结构。
[[Indent]] 字符串 当前缩进。

25.5.2.2 SerializeJSONProperty ( state, key, holder )

抽象操作 SerializeJSONProperty 接收参数 stateJSON 序列化记录)、key(字符串)、holder(对象),返回 正常完成,包含 字符串或 undefined,或 抛出完成。调用时执行以下步骤:

  1. value 为 ? Get(holder, key)。
  2. 如果 value 是对象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 是对象,则
    1. 如果 value[[NumberData]] 内部槽,则
      1. 设置 value 为 ? ToNumber(value)。
    2. 否则如果 value[[StringData]] 内部槽,则
      1. 设置 value 为 ? ToString(value)。
    3. 否则如果 value[[BooleanData]] 内部槽,则
      1. 设置 valuevalue.[[BooleanData]]
    4. 否则如果 value[[BigIntData]] 内部槽,则
      1. 设置 valuevalue.[[BigIntData]]
  5. 如果 valuenull,返回 "null"
  6. 如果 valuetrue,返回 "true"
  7. 如果 valuefalse,返回 "false"
  8. 如果 value 是字符串,返回 QuoteJSONString(value)。
  9. 如果 value 是数字,则
    1. 如果 value有限,返回 ! ToString(value)。
    2. 返回 "null"
  10. 如果 value 是 BigInt,抛出 TypeError 异常。
  11. 如果 value 是对象IsCallable(value) 为 false,则
    1. isArray 为 ? IsArray(value)。
    2. 如果 isArraytrue,返回 ? SerializeJSONArray(state, value)。
    3. 返回 ? SerializeJSONObject(state, value)。
  12. 返回 undefined

25.5.2.3 QuoteJSONString ( value )

抽象操作 QuoteJSONString 接收参数 value(字符串),返回一个字符串。该操作将 value 用 0x0022(引号)码元包裹,并对其中某些码元进行转义。该操作将 value 作为 UTF-16 编码的码点序列处理,详见 6.1.4。调用时执行以下步骤:

  1. product 为仅包含 0x0022(引号)的字符串。
  2. 对于 StringToCodePoints(value) 的每个码点 C,执行
    1. 如果 C表 81“码点”列中,则
      1. 设置 productproduct 与该表对应“转义序列”的拼接结果。
    2. 否则如果 C 的数值小于 0x0020(空格),或 C 数值等于 前导代理项后继代理项,则
      1. unit 为其数值等于 C 的码元。
      2. 设置 productproductUnicodeEscape(unit) 的拼接结果。
    3. 否则,
      1. 设置 productproductUTF16EncodeCodePoint(C) 的拼接结果。
  3. 设置 productproduct 与 0x0022(引号)码元的拼接结果。
  4. 返回 product
表 81: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.2.4 UnicodeEscape ( C )

抽象操作 UnicodeEscape 接收参数 C(一个码元),返回一个字符串。它将 C 表示为 Unicode 转义序列。调用时执行以下步骤:

  1. nC 的数值。
  2. 断言n ≤ 0xFFFF。
  3. hexn 的字符串表示,格式为小写十六进制数。
  4. 返回 0x005C(反斜杠)、"u"StringPad(hex, 4, "0", start) 的字符串拼接结果。

25.5.2.5 SerializeJSONObject ( state, value )

抽象操作 SerializeJSONObject 接收参数 state(一个 JSON 序列化记录)和 value(对象),返回 正常完成,包含字符串,或 抛出完成。它会对一个对象进行序列化。调用时执行以下步骤:

  1. 如果 state.[[Stack]] 包含 value,则抛出 TypeError 异常,因为结构是循环的。
  2. value 添加到 state.[[Stack]]
  3. stepBackstate.[[Indent]]
  4. 设置 state.[[Indent]]state.[[Indent]]state.[[Gap]]字符串拼接结果。
  5. 如果 state.[[PropertyList]] 不为 undefined,则
    1. Kstate.[[PropertyList]]
  6. 否则,
    1. K 为 ? EnumerableOwnProperties(value, key)。
  7. partial 为新的空 List
  8. 对于 K 的每个元素 P,执行
    1. strP 为 ? SerializeJSONProperty(state, P, value)。
    2. 如果 strP 不为 undefined,则
      1. memberQuoteJSONString(P)。
      2. 设置 membermember":"字符串拼接结果。
      3. 如果 state.[[Gap]] 不为空字符串,则
        1. 设置 membermember 与 0x0020(空格)的字符串拼接结果。
      4. 设置 membermemberstrP字符串拼接结果。
      5. member 添加到 partial
  9. 如果 partial 为空,则
    1. final"{}"
  10. 否则,
    1. 如果 state.[[Gap]] 为空字符串,则
      1. properties 为将 partial 所有元素字符串用 0x002C(逗号)分隔拼接得到的字符串。逗号不出现在首尾。
      2. final字符串拼接 "{"properties"}"
    2. 否则,
      1. separator 为 0x002C(逗号)、0x000A(换行符)和 state.[[Indent]] 拼接的字符串。
      2. properties 为将 partial 所有元素字符串用 separator 分隔拼接得到的字符串,不在首尾插入分隔符。
      3. final字符串拼接 "{"、0x000A(换行)、 state.[[Indent]]properties、0x000A(换行)、stepBack"}" 的结果。
  11. 移除 state.[[Stack]] 的最后一个元素。
  12. 设置 state.[[Indent]]stepBack
  13. 返回 final

25.5.2.6 SerializeJSONArray ( state, value )

抽象操作 SerializeJSONArray 接收参数 stateJSON 序列化记录)和 valueECMAScript 语言值),返回 正常完成,包含字符串,或 抛出完成。它会对一个数组进行序列化。调用时执行以下步骤:

  1. 如果 state.[[Stack]] 包含 value,则抛出 TypeError 异常,因为结构是循环的。
  2. value 添加到 state.[[Stack]]
  3. stepBackstate.[[Indent]]
  4. 设置 state.[[Indent]]state.[[Indent]]state.[[Gap]]字符串拼接结果。
  5. partial 为新的空 List
  6. len 为 ? LengthOfArrayLike(value)。
  7. index 为 0。
  8. index < len 时重复,
    1. strP 为 ? SerializeJSONProperty(state, ! ToString(𝔽(index)), value)。
    2. 如果 strPundefined,则
      1. "null" 添加到 partial
    3. 否则,
      1. strP 添加到 partial
    4. 设置 indexindex + 1。
  9. 如果 partial 为空,则
    1. final"[]"
  10. 否则,
    1. 如果 state.[[Gap]] 为空字符串,则
      1. properties 为将 partial 所有元素字符串用 0x002C(逗号)分隔拼接得到的字符串。逗号不出现在首尾。
      2. final字符串拼接 "["properties"]"
    2. 否则,
      1. separator 为 0x002C(逗号)、0x000A(换行符)和 state.[[Indent]] 拼接的字符串。
      2. properties 为将 partial 所有元素字符串用 separator 分隔拼接得到的字符串,不在首尾插入分隔符。
      3. final字符串拼接 "["、0x000A(换行)、 state.[[Indent]]properties、0x000A(换行)、stepBack"]" 的结果。
  11. 移除 state.[[Stack]] 的最后一个元素。
  12. 设置 state.[[Indent]]stepBack
  13. 返回 final

数组的表现形式只包括区间 interval [+0𝔽, array.length) 内的元素。键不是 数组索引 的属性不会被序列化。数组以左中括号开头,元素用逗号分隔,右中括号结尾。

25.5.3 JSON [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值为字符串值 "JSON"

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

26 内存管理

26.1 WeakRef 对象

WeakRef 是一种对象,可以引用目标对象或符号,但不会阻止其被垃圾回收。WeakRef 可以被解引用以访问目标值(如果目标尚未被垃圾回收)。

26.1.1 WeakRef 构造函数

WeakRef 构造函数

  • %WeakRef%
  • 全局对象"WeakRef" 属性的初始值。
  • 作为构造函数被调用时,创建并初始化一个新的 WeakRef。
  • 不应作为函数调用,否则会抛出异常。
  • 可以用作类定义的 extends 子句中的值。希望继承指定 WeakRef 行为的子类构造函数,必须包含对 WeakRef 构造函数super 调用,以使用支持 WeakRef.prototype 内置方法所需的内部状态来创建和初始化子类实例。

26.1.1.1 WeakRef ( target )

该函数被调用时执行以下步骤:

  1. 如果 NewTarget 为 undefined,抛出 TypeError 异常。
  2. 如果 CanBeHeldWeakly(target) 为 false,抛出 TypeError 异常。
  3. weakRef 为 ? OrdinaryCreateFromConstructor(NewTarget, "%WeakRef.prototype%", « [[WeakRefTarget]] »)。
  4. 执行 AddToKeptObjects(target)。
  5. 设置 weakRef.[[WeakRefTarget]]target
  6. 返回 weakRef

26.1.2 WeakRef 构造函数的属性

WeakRef 构造函数

26.1.2.1 WeakRef.prototype

WeakRef.prototype 的初始值是 WeakRef 原型对象。

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

26.1.3 WeakRef 原型对象的属性

WeakRef 原型对象:

  • %WeakRef.prototype%
  • 有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%
  • 是一个 普通对象
  • 没有 [[WeakRefTarget]] 内部槽。

26.1.3.1 WeakRef.prototype.constructor

WeakRef.prototype.constructor 的初始值为 %WeakRef%

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

26.1.3.2 WeakRef.prototype.deref ( )

该方法被调用时执行以下步骤:

  1. weakRefthis 值。
  2. 执行 ? RequireInternalSlot(weakRef, [[WeakRefTarget]])。
  3. 返回 WeakRefDeref(weakRef)。

如果 WeakRef 返回的 target 值不为 undefined,则该 target 值在本次 ECMAScript 代码执行完成前不会被垃圾回收。AddToKeptObjects 操作确保读取一致性。

let target = { foo() {} };
let weakRef = new WeakRef(target);

// ... 稍后 ...

if (weakRef.deref()) {
  weakRef.deref().foo();
}

在上述例子中,如果第一次 deref 的结果不是 undefined,则第二次 deref 同样不会是 undefined

26.1.3.3 WeakRef.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值为字符串值 "WeakRef"

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

26.1.4 WeakRef 抽象操作

26.1.4.1 WeakRefDeref ( weakRef )

抽象操作 WeakRefDeref 接收参数 weakRef(一个 WeakRef),返回一个 ECMAScript 语言值。调用时执行以下步骤:

  1. targetweakRef.[[WeakRefTarget]]
  2. 如果 target 不为 empty,则
    1. 执行 AddToKeptObjects(target)。
    2. 返回 target
  3. 返回 undefined

该抽象操作与 WeakRef.prototype.deref 分开定义,目的是为了能够简洁地定义活性(liveness)。

26.1.5 WeakRef 实例的属性

WeakRef 实例是 普通对象,继承自 WeakRef 原型WeakRef 实例还具有 [[WeakRefTarget]] 内部槽。

26.2 FinalizationRegistry 对象

FinalizationRegistry 是用于管理目标对象和符号被垃圾回收时执行清理操作的注册与注销的对象。

26.2.1 FinalizationRegistry 构造函数

FinalizationRegistry 构造函数

  • %FinalizationRegistry%
  • "FinalizationRegistry" 属性在 全局对象 上的初始值。
  • 作为构造函数被调用时,创建并初始化一个新的 FinalizationRegistry。
  • 不应作为函数调用,否则会抛出异常。
  • 可以用作类定义的 extends 子句中的值。希望继承指定 FinalizationRegistry 行为的子类构造函数,必须包含对 FinalizationRegistry 构造函数super 调用,以使用支持 FinalizationRegistry.prototype 内置方法所需的内部状态来创建和初始化子类实例。

26.2.1.1 FinalizationRegistry ( cleanupCallback )

该函数被调用时执行以下步骤:

  1. 如果 NewTarget 为 undefined,抛出 TypeError 异常。
  2. 如果 IsCallable(cleanupCallback) 为 false,抛出 TypeError 异常。
  3. finalizationRegistry 为 ? OrdinaryCreateFromConstructor(NewTarget, "%FinalizationRegistry.prototype%", « [[Realm]], [[CleanupCallback]], [[Cells]] »)。
  4. fn当前函数对象
  5. 设置 finalizationRegistry.[[Realm]]fn.[[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. 设置 unregisterTokenempty
  6. cellRecord { [[WeakRefTarget]]: target, [[HeldValue]]: heldValue, [[UnregisterToken]]: unregisterToken }。
  7. cell 添加到 finalizationRegistry.[[Cells]]
  8. 返回 undefined

根据本规范中的算法和定义,当 finalizationRegistry.[[Cells]] 包含 cell 时,cell.[[HeldValue]]活跃的;但这不一定意味着 cell.[[UnregisterToken]]cell.[[Target]] 也是 活跃的。例如,将对象注册为其自身的注销 token 并不会让该对象永远存活。

26.2.3.3 FinalizationRegistry.prototype.unregister ( unregisterToken )

该方法被调用时执行以下步骤:

  1. finalizationRegistrythis 值。
  2. 执行 ? RequireInternalSlot(finalizationRegistry, [[Cells]])。
  3. 如果 CanBeHeldWeakly(unregisterToken) 为 false,抛出 TypeError 异常。
  4. removedfalse
  5. 对于 Record { [[WeakRefTarget]], [[HeldValue]], [[UnregisterToken]] } cell 属于 finalizationRegistry.[[Cells]],执行
    1. 如果 cell.[[UnregisterToken]] 不为 emptySameValue(cell.[[UnregisterToken]], unregisterToken) 为 true,则
      1. finalizationRegistry.[[Cells]] 移除 cell
      2. 设置 removedtrue
  6. 返回 removed

26.2.3.4 FinalizationRegistry.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值为字符串值 "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 可迭代接口

可迭代接口 包含 表 82 中描述的属性:

表 82:可迭代接口必需属性
属性 要求
%Symbol.iterator% 一个返回迭代器对象的函数 返回的对象必须符合迭代器接口

27.1.1.2 迭代器接口

实现迭代器接口的对象必须包含 表 83 所描述的属性。这类对象也可以实现 表 84 所述的属性。

表 83:迭代器接口必需属性
属性 要求
"next" 一个返回 IteratorResult 对象 的函数 返回的对象必须符合 IteratorResult 接口。如果对同一个迭代器next 方法的前一次调用返回了 IteratorResult 对象,其 "done" 属性为 true,那么对该对象后续的所有 next 方法调用也应返回 IteratorResult 对象,其 "done" 属性为 true。但该要求不强制执行。
注 1

参数可以传递给 next 函数,但具体解释和有效性取决于目标迭代器。for-of 语句和其他常见的迭代器使用者不会传递任何参数,因此期望以这种方式被使用的迭代器对象必须能够处理被无参调用的情况。

表 84:迭代器接口可选属性
属性 要求
"return" 一个返回 IteratorResult 对象 的函数 返回的对象必须符合 IteratorResult 接口。调用此方法通知 迭代器对象,调用者不打算再对该对象进行 next 方法调用。返回的 IteratorResult 对象 通常具有 "done" 属性值为 true"value" 属性值为 return 方法参数的值。但该要求不强制执行。
"throw" 一个返回 IteratorResult 对象 的函数 返回的对象必须符合 IteratorResult 接口。调用此方法通知 迭代器对象,调用者检测到错误条件。参数可用于标识错误,通常是异常对象。典型响应是 throw 该参数。如果方法未 throw,返回的 IteratorResult 对象 通常具有 "done" 属性值为 true
注 2

通常调用这些方法前应先检查其是否存在。某些 ECMAScript 语言特性(包括 for-ofyield* 和数组解构)在调用这些方法前会做存在性检查。大多数接受 可迭代对象作为参数的 ECMAScript 库函数也有条件地调用这些方法。

27.1.1.3 异步可迭代接口

异步可迭代接口 包含 表 85 所描述的属性:

表 85:异步 可迭代接口必需属性
属性 要求
%Symbol.asyncIterator% 一个返回 异步迭代器对象 的函数 返回的对象必须符合 异步迭代器接口

27.1.1.4 异步迭代器接口

实现异步迭代器接口的对象必须包含 表 86 中的属性。这类对象也可以实现 表 87 所述的属性。

表 86:异步 迭代器接口必需属性
属性 要求
"next" 一个返回 IteratorResult 对象 的 Promise 的函数

返回的 promise 被 fulfill 时,必须 fulfill 为一个符合 IteratorResult 接口 的对象。如果对同一个异步迭代器next 方法的前一次调用返回了一个 promise,该 promise fulfill 为 IteratorResult 对象,其 "done" 属性为 true,那么对该对象后续的所有 next 方法调用也应返回 fulfill 为 IteratorResult 对象,其 "done" 属性为 true 的 promise。但该要求不强制执行。

此外,作为 fulfill 值的 IteratorResult 对象"value" 属性值不应为 promise(或"thenable")。但该要求也不强制执行。

注 1

参数可以传递给 next 函数,但具体解释和有效性取决于目标异步迭代器。for-await-of 语句和其他常见的异步迭代器使用者不会传递任何参数,因此期望以这种方式被使用的异步迭代器对象必须能够处理被无参调用的情况。

表 87:异步 迭代器接口可选属性
属性 要求
"return" 一个返回 IteratorResult 对象 的 Promise 的函数

返回的 promise 被 fulfill 时,必须 fulfill 为一个符合 IteratorResult 接口 的对象。调用此方法通知 异步迭代器对象,调用者不打算再对该对象进行 next 方法调用。返回的 promise fulfill 为一个 IteratorResult 对象,其 "done" 属性值通常为 true"value" 属性为 return 方法参数的值。但该要求不强制执行。

此外,作为 fulfill 值的 IteratorResult 对象"value" 属性值不应为 promise(或"thenable")。如果参数以典型方式使用,则若为拒绝的 promise,应返回一个相同原因拒绝的 promise;若为 fulfill 的 promise,则其 fulfill 值应作为返回 promise 的 IteratorResult 对象"value" 属性值。但这些要求也不强制执行。

"throw" 一个返回 IteratorResult 对象 的 Promise 的函数

返回的 promise 被 fulfill 时,必须 fulfill 为一个符合 IteratorResult 接口 的对象。调用此方法通知 异步迭代器对象,调用者检测到错误条件。参数可用于标识错误,通常是异常对象。典型响应是返回一个拒绝的 promise,拒绝原因为参数值。

如果返回的 promise 被 fulfill,IteratorResult 对象"done" 属性值通常为 true。此外,其 "value" 属性值不应为 promise(或"thenable"),但该要求不强制执行。

注 2

通常调用这些方法前应先检查其是否存在。某些 ECMAScript 语言特性(包括 for-await-ofyield*)在调用这些方法前会做存在性检查。

27.1.1.5 IteratorResult 接口

IteratorResult 接口 包含 表 88 中列出的属性:

表 88:IteratorResult 接口属性
属性 要求
"done" 一个布尔值 这是 迭代器 next 方法调用的结果状态。如果已到达 迭代器 末尾,"done"true。如果未到达末尾,"done"false,且有一个可用的值。如果不存在 "done" 属性(无论是自身还是继承),则视为值为 false
"value" 一个 ECMAScript 语言值 如果 done 为 false,这是当前迭代元素的值。如果 done 为 true,这是 迭代器 的返回值(如果有的话)。如果 迭代器 没有返回值,则 "value"undefined。在这种情况下,如果符合要求的对象没有继承到显式的 "value" 属性,则该属性可不存在。

27.1.2 迭代器辅助对象

迭代器辅助对象是一个普通对象,表示某个特定源迭代器对象的惰性变换。迭代器辅助对象没有命名的构造函数。相反,迭代器辅助对象是通过调用某些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. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[UnderlyingIterator]]).
  3. 断言O 有一个 [[GeneratorState]] 内部槽。
  4. 如果 O.[[GeneratorState]]suspended-start,则
    1. 设置 O.[[GeneratorState]]completed
    2. 注:一旦生成器进入 completed 状态,就不会再离开,并且其相关的执行上下文不会被恢复。此时与 O 关联的所有执行状态都可以被丢弃。
    3. 执行 ? IteratorClose(O.[[UnderlyingIterator]], NormalCompletion(unused)).
    4. 返回 CreateIteratorResultObject(undefined, true).
  5. CReturnCompletion(undefined).
  6. 返回 ? GeneratorResumeAbrupt(O, C, "Iterator Helper").

27.1.2.1.3 %IteratorHelperPrototype% [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值为字符串值 "Iterator Helper"

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

27.1.3 迭代器对象

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.from ( O )

  1. iteratorRecord 为 ? GetIteratorFlattenable(O, 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.1.1 %WrapForValidIteratorPrototype% 对象

%WrapForValidIteratorPrototype% 对象:

27.1.3.2.1.1.1 %WrapForValidIteratorPrototype%.next ( )

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[Iterated]]).
  3. iteratorRecordO.[[Iterated]]
  4. 返回 ? Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]]).

27.1.3.2.1.1.2 %WrapForValidIteratorPrototype%.return ( )

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[Iterated]]).
  3. iteratorO.[[Iterated]].[[Iterator]]
  4. 断言iterator 是对象
  5. returnMethod 为 ? GetMethod(iterator, "return").
  6. 如果 returnMethodundefined,则
    1. 返回 CreateIteratorResultObject(undefined, true).
  7. 返回 ? Call(returnMethod, iterator).

27.1.3.2.2 Iterator.prototype

Iterator.prototype 的初始值是 Iterator 原型对象

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.

27.1.4 Iterator 原型对象的属性

Iterator 原型对象

本规范中所有实现了 迭代器接口 的对象都继承自 %Iterator.prototype%。ECMAScript 代码也可以定义继承自 %Iterator.prototype% 的对象。%Iterator.prototype% 提供了一个可为所有 迭代器对象 添加通用方法的位置。

以下表达式是 ECMAScript 代码访问 %Iterator.prototype% 对象的一种方式:

Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()))

27.1.4.1 Iterator.prototype.constructor

Iterator.prototype.constructor 是一个 访问器属性,属性为 { [[Enumerable]]: false, [[Configurable]]: true }。[[Get]][[Set]] 属性定义如下:

27.1.4.1.1 get Iterator.prototype.constructor

[[Get]] 属性值为一个不带参数的内置函数。被调用时执行以下步骤:

  1. 返回 %Iterator%

27.1.4.1.2 set Iterator.prototype.constructor

[[Set]] 属性值为一个带参数 v 的内置函数。被调用时执行以下步骤:

  1. 执行 ? SetterThatIgnoresPrototypeProperties(this 值, %Iterator.prototype%, "constructor", v).
  2. 返回 undefined

与大多数内置原型上的 "constructor" 属性不同,出于 Web 兼容性原因,该属性必须为访问器属性。

27.1.4.2 Iterator.prototype.drop ( limit )

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. 如果 O 不是对象,抛出 TypeError 异常。
  3. iterated迭代器记录 { [[Iterator]]: O, [[NextMethod]]: undefined, [[Done]]: false }.
  4. numLimitCompletion(ToNumber(limit))。
  5. IfAbruptCloseIterator(numLimit, iterated).
  6. 如果 numLimitNaN,则
    1. errorThrowCompletion(新建的 RangeError 对象)。
    2. 返回 ? IteratorClose(iterated, error).
  7. integerLimit 为 ! ToIntegerOrInfinity(numLimit)。
  8. 如果 integerLimit < 0,则
    1. errorThrowCompletion(新建的 RangeError 对象)。
    2. 返回 ? IteratorClose(iterated, error).
  9. 设置 iterated 为 ? GetIteratorDirect(O)。
  10. closure 为一个新的 抽象闭包,无参数,捕获 iteratedintegerLimit,被调用时执行以下步骤:
    1. remainingintegerLimit
    2. remaining > 0 时重复:
      1. 如果 remaining ≠ +∞,则
        1. 设置 remainingremaining - 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%, « [[UnderlyingIterator]] »)。
  12. 设置 result.[[UnderlyingIterator]]iterated
  13. 返回 result

27.1.4.3 Iterator.prototype.every ( predicate )

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. 如果 O 不是对象,抛出 TypeError 异常。
  3. iterated迭代器记录 { [[Iterator]]: O, [[NextMethod]]: undefined, [[Done]]: false }.
  4. 如果 IsCallable(predicate) 为 false,则
    1. errorThrowCompletion(新建的 TypeError 对象)。
    2. 返回 ? IteratorClose(iterated, error).
  5. 设置 iterated 为 ? GetIteratorDirect(O)。
  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. 设置 countercounter + 1。

27.1.4.4 Iterator.prototype.filter ( predicate )

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. 如果 O 不是对象,抛出 TypeError 异常。
  3. iterated迭代器记录 { [[Iterator]]: O, [[NextMethod]]: undefined, [[Done]]: false }.
  4. 如果 IsCallable(predicate) 为 false,则
    1. errorThrowCompletion(新建的 TypeError 对象)。
    2. 返回 ? IteratorClose(iterated, error).
  5. 设置 iterated 为 ? GetIteratorDirect(O)。
  6. 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. 设置 countercounter + 1。
  7. resultCreateIteratorFromClosure(closure, "Iterator Helper", %IteratorHelperPrototype%, « [[UnderlyingIterator]] »)。
  8. 设置 result.[[UnderlyingIterator]]iterated
  9. 返回 result

27.1.4.5 Iterator.prototype.find ( predicate )

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. 如果 O 不是对象,抛出 TypeError 异常。
  3. iterated迭代器记录 { [[Iterator]]: O, [[NextMethod]]: undefined, [[Done]]: false }.
  4. 如果 IsCallable(predicate) 为 false,则
    1. errorThrowCompletion(新建的 TypeError 对象)。
    2. 返回 ? IteratorClose(iterated, error).
  5. 设置 iterated 为 ? GetIteratorDirect(O)。
  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. 设置 countercounter + 1。

27.1.4.6 Iterator.prototype.flatMap ( mapper )

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. 如果 O 不是对象,抛出 TypeError 异常。
  3. iterated迭代器记录 { [[Iterator]]: O, [[NextMethod]]: undefined, [[Done]]: false }.
  4. 如果 IsCallable(mapper) 为 false,则
    1. errorThrowCompletion(新建的 TypeError 对象)。
    2. 返回 ? IteratorClose(iterated, error).
  5. 设置 iterated 为 ? GetIteratorDirect(O)。
  6. 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. 设置 innerAlivefalse
        4. 否则,
          1. completionCompletion(Yield(innerValue))。
          2. 如果 completionabrupt completion,则
            1. backupCompletionCompletion(IteratorClose(innerIterator, completion))。
            2. IfAbruptCloseIterator(backupCompletion, iterated)。
            3. 返回 ? IteratorClose(iterated, completion)。
      9. 设置 countercounter + 1。
  7. resultCreateIteratorFromClosure(closure, "Iterator Helper", %IteratorHelperPrototype%, « [[UnderlyingIterator]] »)。
  8. 设置 result.[[UnderlyingIterator]]iterated
  9. 返回 result

27.1.4.7 Iterator.prototype.forEach ( procedure )

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. 如果 O 不是对象,抛出 TypeError 异常。
  3. iterated迭代器记录 { [[Iterator]]: O, [[NextMethod]]: undefined, [[Done]]: false }.
  4. 如果 IsCallable(procedure) 为 false,则
    1. errorThrowCompletion(新建的 TypeError 对象)。
    2. 返回 ? IteratorClose(iterated, error).
  5. 设置 iterated 为 ? GetIteratorDirect(O)。
  6. counter 为 0。
  7. 重复:
    1. value 为 ? IteratorStepValue(iterated)。
    2. 如果 valuedone,返回 undefined
    3. resultCompletion(Call(procedure, undefined, « value, 𝔽(counter) »))。
    4. IfAbruptCloseIterator(result, iterated)。
    5. 设置 countercounter + 1。

27.1.4.8 Iterator.prototype.map ( mapper )

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. 如果 O 不是对象,抛出 TypeError 异常。
  3. iterated迭代器记录 { [[Iterator]]: O, [[NextMethod]]: undefined, [[Done]]: false }.
  4. 如果 IsCallable(mapper) 为 false,则
    1. errorThrowCompletion(新建的 TypeError 对象)。
    2. 返回 ? IteratorClose(iterated, error).
  5. 设置 iterated 为 ? GetIteratorDirect(O)。
  6. 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. 设置 countercounter + 1。
  7. resultCreateIteratorFromClosure(closure, "Iterator Helper", %IteratorHelperPrototype%, « [[UnderlyingIterator]] »)。
  8. 设置 result.[[UnderlyingIterator]]iterated
  9. 返回 result

27.1.4.9 Iterator.prototype.reduce ( reducer [ , initialValue ] )

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. 如果 O 不是对象,抛出 TypeError 异常。
  3. iterated迭代器记录 { [[Iterator]]: O, [[NextMethod]]: undefined, [[Done]]: false }.
  4. 如果 IsCallable(reducer) 为 false,则
    1. errorThrowCompletion(新建的 TypeError 对象)。
    2. 返回 ? IteratorClose(iterated, error).
  5. 设置 iterated 为 ? GetIteratorDirect(O)。
  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. 设置 accumulatorresult
    6. 设置 countercounter + 1。

27.1.4.10 Iterator.prototype.some ( predicate )

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. 如果 O 不是对象,抛出 TypeError 异常。
  3. iterated迭代器记录 { [[Iterator]]: O, [[NextMethod]]: undefined, [[Done]]: false }.
  4. 如果 IsCallable(predicate) 为 false,则
    1. errorThrowCompletion(新建的 TypeError 对象)。
    2. 返回 ? IteratorClose(iterated, error).
  5. 设置 iterated 为 ? GetIteratorDirect(O)。
  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. 设置 countercounter + 1。

27.1.4.11 Iterator.prototype.take ( limit )

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. 如果 O 不是对象,抛出 TypeError 异常。
  3. iterated迭代器记录 { [[Iterator]]: O, [[NextMethod]]: undefined, [[Done]]: false }.
  4. numLimitCompletion(ToNumber(limit))。
  5. IfAbruptCloseIterator(numLimit, iterated)。
  6. 如果 numLimitNaN,则
    1. errorThrowCompletion(新建的 RangeError 对象)。
    2. 返回 ? IteratorClose(iterated, error)。
  7. integerLimit 为 ! ToIntegerOrInfinity(numLimit)。
  8. 如果 integerLimit < 0,则
    1. errorThrowCompletion(新建的 RangeError 对象)。
    2. 返回 ? IteratorClose(iterated, error)。
  9. 设置 iterated 为 ? GetIteratorDirect(O)。
  10. closure 为一个新的 抽象闭包,无参数,捕获 iteratedintegerLimit,被调用时执行以下步骤:
    1. remainingintegerLimit
    2. 重复,
      1. 如果 remaining = 0,则
        1. 返回 ? IteratorClose(iterated, ReturnCompletion(undefined))。
      2. 如果 remaining ≠ +∞,则
        1. 设置 remainingremaining - 1。
      3. value 为 ? IteratorStepValue(iterated)。
      4. 如果 valuedone,返回 ReturnCompletion(undefined)。
      5. completionCompletion(Yield(value))。
      6. IfAbruptCloseIterator(completion, iterated)。
  11. resultCreateIteratorFromClosure(closure, "Iterator Helper", %IteratorHelperPrototype%, « [[UnderlyingIterator]] »)。
  12. 设置 result.[[UnderlyingIterator]]iterated
  13. 返回 result

27.1.4.12 Iterator.prototype.toArray ( )

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. 如果 O 不是对象,抛出 TypeError 异常。
  3. iterated 为 ? GetIteratorDirect(O)。
  4. items 为一个新的空 List
  5. 重复,
    1. value 为 ? IteratorStepValue(iterated)。
    2. 如果 valuedone,返回 CreateArrayFromList(items)。
    3. value 添加到 items

27.1.4.13 Iterator.prototype [ %Symbol.iterator% ] ( )

该函数被调用时执行以下步骤:

  1. 返回 this 值。

该函数的 "name" 属性值为 "[Symbol.iterator]"

27.1.4.14 Iterator.prototype [ %Symbol.toStringTag% ]

Iterator.prototype[%Symbol.toStringTag%] 是一个 访问器属性,属性为 { [[Enumerable]]: false, [[Configurable]]: true }。[[Get]][[Set]] 属性定义如下:

27.1.4.14.1 get Iterator.prototype [ %Symbol.toStringTag% ]

[[Get]] 属性值为一个不带参数的内置函数。被调用时执行以下步骤:

  1. 返回 "Iterator"

27.1.4.14.2 set Iterator.prototype [ %Symbol.toStringTag% ]

[[Set]] 属性值为一个带参数 v 的内置函数。被调用时执行以下步骤:

  1. 执行 ? SetterThatIgnoresPrototypeProperties(this 值, %Iterator.prototype%, %Symbol.toStringTag%, v)。
  2. 返回 undefined

与大多数内置原型上的 %Symbol.toStringTag% 属性不同,出于 Web 兼容性原因,该属性必须为访问器属性。

27.1.5 %AsyncIteratorPrototype% 对象

%AsyncIteratorPrototype% 对象:

本规范中所有实现了 异步迭代器接口 的对象也都继承自 %AsyncIteratorPrototype%。ECMAScript 代码也可以定义继承自 %AsyncIteratorPrototype% 的对象。%AsyncIteratorPrototype% 对象为所有 异步迭代器对象 提供一个可添加通用方法的位置。

27.1.5.1 %AsyncIteratorPrototype% [ %Symbol.asyncIterator% ] ( )

该函数被调用时执行以下步骤:

  1. 返回 this 值。

该函数的 "name" 属性值为 "[Symbol.asyncIterator]"

27.1.6 从同步到异步的迭代器对象

从同步到异步的迭代器对象 是一种异步迭代器,用于适配某个特定的同步 迭代器。从同步到异步的迭代器对象永远不会被 ECMAScript 代码直接访问。没有命名的 构造函数用于从同步到异步的迭代器对象。相反,这些对象是通过 CreateAsyncFromSyncIterator 抽象操作在需要时创建的。

27.1.6.1 CreateAsyncFromSyncIterator ( syncIteratorRecord )

抽象操作 CreateAsyncFromSyncIterator 接收参数 syncIteratorRecord(一个 迭代器记录),并返回一个迭代器记录。它用于从同步迭代器记录创建一个异步迭代器记录。调用时执行以下步骤:

  1. asyncIteratorOrdinaryObjectCreate(%AsyncFromSyncIteratorPrototype%, « [[SyncIteratorRecord]] »)。
  2. 设置 asyncIterator.[[SyncIteratorRecord]]syncIteratorRecord
  3. nextMethod 为 ! Get(asyncIterator, "next")。
  4. iteratorRecord迭代器记录 { [[Iterator]]: asyncIterator, [[NextMethod]]: nextMethod, [[Done]]: false }。
  5. 返回 iteratorRecord

27.1.6.2 %AsyncFromSyncIteratorPrototype% 对象

%AsyncFromSyncIteratorPrototype% 对象:

27.1.6.2.1 %AsyncFromSyncIteratorPrototype%.next ( [ value ] )

  1. Othis 值。
  2. 断言O 是一个对象,且有 [[SyncIteratorRecord]] 内部槽。
  3. promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  4. syncIteratorRecordO.[[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.6.2.2 %AsyncFromSyncIteratorPrototype%.return ( [ value ] )

  1. Othis 值。
  2. 断言O 是对象,且有 [[SyncIteratorRecord]] 内部槽。
  3. promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  4. syncIteratorRecordO.[[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 不是对象,则
    1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « 新建的 TypeError 对象 »)。
    2. 返回 promiseCapability.[[Promise]]
  13. 返回 AsyncFromSyncIteratorContinuation(result, promiseCapability, syncIteratorRecord, false)。

27.1.6.2.3 %AsyncFromSyncIteratorPrototype%.throw ( [ value ] )

在本规范中,value 总是会被传入,但为了一致性,仍然标为可选,参见 %AsyncFromSyncIteratorPrototype%.return ( [ value ] )
  1. Othis 值。
  2. 断言O 是对象,且有 [[SyncIteratorRecord]] 内部槽。
  3. promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  4. syncIteratorRecordO.[[SyncIteratorRecord]]
  5. syncIteratorsyncIteratorRecord.[[Iterator]]
  6. throwCompletion(GetMethod(syncIterator, "throw"))。
  7. IfAbruptRejectPromise(throw, promiseCapability)。
  8. 如果 throwundefined,则
    1. 注:如果 syncIterator 没有 throw 方法,需要关闭它以便其有机会清理后再拒绝能力。
    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 不是对象,则
    1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « 新建的 TypeError 对象 »)。
    2. 返回 promiseCapability.[[Promise]]
  13. 返回 AsyncFromSyncIteratorContinuation(result, promiseCapability, syncIteratorRecord, true)。

27.1.6.3 从同步到异步的迭代器实例的属性

从同步到异步的 迭代器 实例是普通对象,继承自 %AsyncFromSyncIteratorPrototype% 本征对象。从同步到异步的 迭代器 实例最初创建时包含 表 89 所列的内部槽。

表 89:从同步到异步 迭代器实例的内部槽
内部槽 类型 描述
[[SyncIteratorRecord]] 一个 迭代器记录 表示被适配的原始同步 迭代器

27.1.6.4 AsyncFromSyncIteratorContinuation ( result, promiseCapability, syncIteratorRecord, closeOnRejection )

抽象操作 AsyncFromSyncIteratorContinuation 接收参数 result (一个对象)、promiseCapability(一个 PromiseCapability 记录,用于本征%Promise%)、syncIteratorRecord(一个迭代器记录)、closeOnRejection(布尔值),并返回一个 Promise。调用时执行以下步骤:

  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异常完成donefalse,且 closeOnRejectiontrue,则
    1. valueWrapper 设为 Completion(IteratorClose(syncIteratorRecord, valueWrapper))。
  8. IfAbruptRejectPromise(valueWrapper, promiseCapability)。
  9. unwrap 为一个新的 抽象闭包,参数为 (v),捕获 done,被调用时执行以下步骤:
    1. 返回 CreateIteratorResultObject(v, done)。
  10. onFulfilledCreateBuiltinFunction(unwrap, 1, "", « »)。
  11. 注:onFulfilled 用于处理 IteratorResult 对象"value" 属性,以便在其为 promise 时等待并重新包装为“解包后”的 IteratorResult 对象
  12. 如果 donetrue,或 closeOnRejectionfalse,则
    1. onRejectedundefined
  13. 否则,
    1. closeIterator 为一个新的 抽象闭包,参数为 (error),捕获 syncIteratorRecord,被调用时执行以下步骤:
      1. 返回 ? IteratorClose(syncIteratorRecord, ThrowCompletion(error))。
    2. onRejectedCreateBuiltinFunction(closeIterator, 1, "", « »)。
    3. 注:onRejected 用于在 IteratorResult 对象"value" 属性为拒绝的 promise 时关闭 迭代器
  14. 执行 PerformPromiseThen(valueWrapper, onFulfilled, onRejected, promiseCapability)。
  15. 返回 promiseCapability.[[Promise]]

27.2 Promise 对象

Promise 是一个用于占位最终延迟(且可能是异步)计算结果的对象。

任何 Promise 都处于三种互斥状态之一:已兑现已拒绝待定

  • 如果 promise p 已兑现,则 p.then(f, r) 会立即入队一个 作业(Job) 调用函数 f
  • 如果 promise p 已拒绝,则 p.then(f, r) 会立即入队一个 作业(Job) 调用函数 r
  • 如果 promise 既未兑现也未拒绝,则为待定状态。

如果 promise 不是待定的,即已兑现或已拒绝,则称其为已定型(settled)

如果 promise 已定型,或已经“锁定”为与另一个 promise 状态一致,则称其为已解决(resolved)。尝试解决或拒绝一个已解决的 promise 无效。未解决(unresolved)的 promise 即为未 resolved 的 promise。未解决的 promise 总是处于待定状态。已解决的 promise 可以是待定、已兑现或已拒绝状态。

27.2.1 Promise 抽象操作

27.2.1.1 PromiseCapability 记录

PromiseCapability 记录是用于封装一个 Promise 或类 Promise 对象及其可解决或拒绝该 promise 的函数的记录(Record)值。PromiseCapability 记录由 NewPromiseCapability 抽象操作生成。

PromiseCapability 记录拥有 表 90 所列字段。

表 90:PromiseCapability 记录字段
字段名 含义
[[Promise]] 一个对象 可用作 promise 的对象。
[[Resolve]] 一个 函数对象 用于解决该 promise 的函数。
[[Reject]] 一个 函数对象 用于拒绝该 promise 的函数。

27.2.1.1.1 IfAbruptRejectPromise ( value, capability )

IfAbruptRejectPromise 是一组使用 PromiseCapability 记录的算法步骤的简写。以下算法步骤:

  1. IfAbruptRejectPromise(value, capability).

等价于:

  1. 断言value 是一个Completion Record
  2. 如果 value异常完成,则
    1. 执行 ? Call(capability.[[Reject]], undefined, « value.[[Value]] »)。
    2. 返回 capability.[[Promise]]
  3. 否则,
    1. value 设为 ! value

27.2.1.2 PromiseReaction 记录

PromiseReaction 记录 是一个 记录(Record)值,用于存储当 promise 被以某个值解决(resolve)或拒绝(reject)时应如何响应的信息。PromiseReaction 记录由 PerformPromiseThen 抽象操作创建,并被 抽象闭包(Abstract Closure)(由 NewPromiseReactionJob 返回)使用。

PromiseReaction 记录具有 表 91 中列出的字段:

表 91:PromiseReaction 记录 字段
字段名 含义
[[Capability]] 一个 PromiseCapability 记录undefined 此记录为其提供响应处理器(reaction handler)的 promise 的能力。
[[Type]] fulfillreject [[Handler]]empty 时,[[Type]] 用于指定与定型类型相关的行为。
[[Handler]] 一个 JobCallback 记录empty 应应用于传入值的函数,其返回值决定派生 promise 的后续处理。如果 [[Handler]]empty,则会根据 [[Type]] 的值采用不同的函数。

27.2.1.3 CreateResolvingFunctions ( promise )

抽象操作 CreateResolvingFunctions 接收参数 promise(一个 Promise),并返回一个包含 [[Resolve]]函数对象) 和 [[Reject]]函数对象)字段的 记录(Record)。调用时执行以下步骤:

  1. alreadyResolved记录 { [[Value]]: false }。
  2. stepsResolvePromise Resolve Functions 中定义的算法步骤。
  3. lengthResolvePromise Resolve Functions 函数定义的非可选参数数量。
  4. resolveCreateBuiltinFunction(stepsResolve, lengthResolve, "", « [[Promise]], [[AlreadyResolved]] »)。
  5. 设置 resolve.[[Promise]]promise
  6. 设置 resolve.[[AlreadyResolved]]alreadyResolved
  7. stepsRejectPromise Reject Functions 中定义的算法步骤。
  8. lengthRejectPromise Reject Functions 函数定义的非可选参数数量。
  9. rejectCreateBuiltinFunction(stepsReject, lengthReject, "", « [[Promise]], [[AlreadyResolved]] »)。
  10. 设置 reject.[[Promise]]promise
  11. 设置 reject.[[AlreadyResolved]]alreadyResolved
  12. 返回 记录 { [[Resolve]]: resolve, [[Reject]]: reject }。

27.2.1.3.1 Promise Reject Functions

promise reject 函数是一个匿名内置函数,具有 [[Promise]][[AlreadyResolved]] 内部槽。

当用参数 reason 调用 promise reject 函数时,执行以下步骤:

  1. F当前函数对象
  2. 断言F 有一个 [[Promise]] 内部槽,且其值 是对象
  3. promiseF.[[Promise]]
  4. alreadyResolvedF.[[AlreadyResolved]]
  5. 如果 alreadyResolved.[[Value]]true,返回 undefined
  6. 设置 alreadyResolved.[[Value]]true
  7. 执行 RejectPromise(promise, reason)。
  8. 返回 undefined

promise reject 函数的 "length" 属性值为 1𝔽

27.2.1.3.2 Promise Resolve Functions

promise resolve 函数是一个匿名内置函数,具有 [[Promise]][[AlreadyResolved]] 内部槽。

当用参数 resolution 调用 promise resolve 函数时,执行以下步骤:

  1. F当前函数对象
  2. 断言F 有一个 [[Promise]] 内部槽,且其值 是对象
  3. promiseF.[[Promise]]
  4. alreadyResolvedF.[[AlreadyResolved]]
  5. 如果 alreadyResolved.[[Value]]true,返回 undefined
  6. 设置 alreadyResolved.[[Value]]true
  7. 如果 SameValue(resolution, promise) 为 true,则
    1. selfResolutionError 为新建的 TypeError 对象。
    2. 执行 RejectPromise(promise, selfResolutionError)。
    3. 返回 undefined
  8. 如果 resolution 不是对象,则
    1. 执行 FulfillPromise(promise, resolution)。
    2. 返回 undefined
  9. thenCompletion(Get(resolution, "then"))。
  10. 如果 then异常完成,则
    1. 执行 RejectPromise(promise, then.[[Value]])。
    2. 返回 undefined
  11. thenActionthen.[[Value]]
  12. 如果 IsCallable(thenAction) 为 false,则
    1. 执行 FulfillPromise(promise, resolution)。
    2. 返回 undefined
  13. thenJobCallbackHostMakeJobCallback(thenAction)。
  14. jobNewPromiseResolveThenableJob(promise, resolution, thenJobCallback)。
  15. 执行 HostEnqueuePromiseJob(job.[[Job]], job.[[Realm]])。
  16. 返回 undefined

promise resolve 函数的 "length" 属性值为 1𝔽

27.2.1.4 FulfillPromise ( promise, value )

抽象操作 FulfillPromise 接收参数 promise(一个 Promise)和 value(一个 ECMAScript 语言值),返回 unused。调用时执行以下步骤:

  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.2.1.5 NewPromiseCapability ( C )

抽象操作 NewPromiseCapability 接收参数 C(一个 ECMAScript 语言值), 返回一个 正常完成(normal completion) 包含PromiseCapability 记录抛出完成(throw completion)。它尝试将 C 作为 构造函数,以内置 Promise 构造函数 的方式,创建一个 promise 并提取其 resolvereject 函数。promise 加上 resolvereject 函数用于初始化一个新的 PromiseCapability 记录。调用时执行以下步骤:

  1. 如果 IsConstructor(C) 为 false,抛出 TypeError 异常。
  2. 注:C 假设为一个 构造函数,且支持 Promise 构造函数 的参数约定(参见 27.2.3.1)。
  3. resolvingFunctions记录 { [[Resolve]]: undefined, [[Reject]]: undefined }。
  4. executorClosure 为一个新的 抽象闭包, 参数为 (resolve, reject),捕获 resolvingFunctions,调用时执行以下步骤:
    1. 如果 resolvingFunctions.[[Resolve]] 不为 undefined,抛出 TypeError 异常。
    2. 如果 resolvingFunctions.[[Reject]] 不为 undefined,抛出 TypeError 异常。
    3. 设置 resolvingFunctions.[[Resolve]]resolve
    4. 设置 resolvingFunctions.[[Reject]]reject
    5. 返回 undefined
  5. executorCreateBuiltinFunction(executorClosure, 2, "", « »)。
  6. promise 为 ? Construct(C, « executor »)。
  7. 如果 IsCallable(resolvingFunctions.[[Resolve]]) 为 false,抛出 TypeError 异常。
  8. 如果 IsCallable(resolvingFunctions.[[Reject]]) 为 false,抛出 TypeError 异常。
  9. 返回 PromiseCapability 记录 { [[Promise]]: promise, [[Resolve]]: resolvingFunctions.[[Resolve]], [[Reject]]: resolvingFunctions.[[Reject]] }.

该抽象操作支持 Promise 子类化,因为它对于任何以与 Promise 构造函数 相同方式调用传入 executor 函数参数的 构造函数 都是通用的。用于将 Promise 构造函数 的静态方法泛化到任何子类。

27.2.1.6 IsPromise ( x )

抽象操作 IsPromise 接收参数 x(一个 ECMAScript 语言值),返回布尔值。该操作检查对象上的 promise 品牌。调用时执行以下步骤:

  1. 如果 x 不是对象,返回 false
  2. 如果 x 没有 [[PromiseState]] 内部槽,返回 false
  3. 返回 true

27.2.1.7 RejectPromise ( promise, reason )

抽象操作 RejectPromise 接收参数 promise(一个 Promise)和 reason(一个 ECMAScript 语言值),返回 unused。调用时执行以下步骤:

  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.2.1.8 TriggerPromiseReactions ( reactions, argument )

抽象操作 TriggerPromiseReactions 接收参数 reactions(一个 List,元素为 PromiseReaction 记录)和 argument(一个 ECMAScript 语言值),返回 unused。它会为 reactions 中的每个记录入队一个新的 作业(Job)。每个这样的 作业 会处理 PromiseReaction 记录[[Type]][[Handler]],如果 [[Handler]] 不为 empty,则调用它并传递参数。如果 [[Handler]]empty,则行为由 [[Type]] 决定。调用时执行以下步骤:

  1. reactions 的每个元素 reaction,执行
    1. jobNewPromiseReactionJob(reaction, argument)。
    2. 执行 HostEnqueuePromiseJob(job.[[Job]], job.[[Realm]])。
  2. 返回 unused

27.2.1.9 HostPromiseRejectionTracker ( promise, operation )

宿主自定义 抽象操作 HostPromiseRejectionTracker 接收参数 promise(一个 Promise) 和 operation"reject""handle"),返回 unused。它允许 宿主环境 跟踪 promise 拒绝。

HostPromiseRejectionTracker 的默认实现是返回 unused

注 1

HostPromiseRejectionTracker 在两种情况下被调用:

  • 当 promise 被拒绝且没有任何处理器时,其 operation 参数为 "reject"
  • 当首次为已拒绝的 promise 添加处理器时,其 operation 参数为 "handle"

典型的 HostPromiseRejectionTracker 实现可能会尝试通知开发者有未处理的拒绝,同时也要注意在新处理器被添加后,如果之前的通知失效要及时通知开发者。

注 2

如果 operation"handle",实现不应以会影响垃圾回收的方式持有 promise 的引用。如果 operation"reject",实现可以持有 promise 引用,因为拒绝情况预计较少且不会出现在热点代码路径上。

27.2.2 Promise 作业(Jobs)

27.2.2.1 NewPromiseReactionJob ( reaction, argument )

抽象操作 NewPromiseReactionJob 接收参数 reaction(一个 PromiseReaction 记录)和 argument(一个 ECMAScript 语言值),返回一个带有字段 [[Job]](一个 作业(Job) 抽象闭包)和 [[Realm]](一个 Realm 记录null)的 记录(Record)。它返回一个新的 作业 抽象闭包,该闭包会对传入值应用合适的处理器,并用处理器的返回值解决或拒绝与该处理器关联的派生 promise。调用时执行以下步骤:

  1. job 为一个新的 作业(Job) 抽象闭包, 无参数,捕获 reactionargument,调用时执行以下步骤:
    1. promiseCapabilityreaction.[[Capability]]
    2. typereaction.[[Type]]
    3. handlerreaction.[[Handler]]
    4. 如果 handlerempty,则
      1. 如果 typefulfill,则
        1. handlerResultNormalCompletion(argument)。
      2. 否则,
        1. 断言typereject
        2. handlerResultThrowCompletion(argument)。
    5. 否则,
      1. handlerResultCompletion(HostCallJobCallback(handler, undefined, « argument »))。
    6. 如果 promiseCapabilityundefined,则
      1. 断言handlerResult 不是 异常完成
      2. 返回 empty
    7. 断言promiseCapabilityPromiseCapability 记录
    8. 如果 handlerResult异常完成,则
      1. 返回 ? Call(promiseCapability.[[Reject]], undefined, « handlerResult.[[Value]] »)。
    9. 否则,
      1. 返回 ? Call(promiseCapability.[[Resolve]], undefined, « handlerResult.[[Value]] »)。
  2. handlerRealmnull
  3. 如果 reaction.[[Handler]] 不为 empty,则
    1. getHandlerRealmResultCompletion(GetFunctionRealm(reaction.[[Handler]].[[Callback]]))。
    2. 如果 getHandlerRealmResult正常完成,则设置 handlerRealmgetHandlerRealmResult.[[Value]]
    3. 否则,设置 handlerRealm当前 Realm 记录
    4. 注:handlerRealm 除非 handler 为 undefined,否则不会为 null。当 handler 是被撤销的 Proxy 且没有 ECMAScript 代码运行时,handlerRealm 用于创建错误对象。
  4. 返回 记录 { [[Job]]: job, [[Realm]]: handlerRealm }。

27.2.2.2 NewPromiseResolveThenableJob ( promiseToResolve, thenable, then )

抽象操作 NewPromiseResolveThenableJob 接收参数 promiseToResolve(一个 Promise)、thenable(一个对象)、then(一个 JobCallback 记录),返回一个带有字段 [[Job]](一个 作业(Job) 抽象闭包)和 [[Realm]](一个 Realm 记录)的 记录(Record)。调用时执行以下步骤:

  1. job 为一个新的 作业(Job) 抽象闭包, 无参数,捕获 promiseToResolvethenablethen,调用时执行以下步骤:
    1. resolvingFunctionsCreateResolvingFunctions(promiseToResolve)。
    2. thenCallResultCompletion(HostCallJobCallback(then, thenable, « resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]] »))。
    3. 如果 thenCallResult异常完成,则
      1. 返回 ? Call(resolvingFunctions.[[Reject]], undefined, « thenCallResult.[[Value]] »)。
    4. 返回 ! thenCallResult
  2. getThenRealmResultCompletion(GetFunctionRealm(then.[[Callback]]))。
  3. 如果 getThenRealmResult正常完成,则令 thenRealmgetThenRealmResult.[[Value]]
  4. 否则,令 thenRealm当前 Realm 记录
  5. 注:thenRealm 永远不会为 null。当 then.[[Callback]] 是被撤销的 Proxy 且没有代码运行时,thenRealm 用于创建错误对象。
  6. 返回 记录 { [[Job]]: job, [[Realm]]: thenRealm }。

作业(Job) 使用提供的 thenable 及其 then 方法来解决给定 promise。该过程必须作为一个 作业(Job) 执行,以保证 then 方法的求值发生在任何外围代码的求值完成之后。

27.2.3 Promise 构造函数

Promise 构造函数

  • %Promise%
  • 全局对象"Promise" 属性的初始值。
  • 作为 构造函数 调用时,会创建并初始化一个新的 Promise。
  • 不应作为普通函数调用,否则会抛出异常。
  • 可以用作类定义的 extends 子句中的值。意图继承指定 Promise 行为的子类 构造函数,必须在内部通过 super 调用 Promise 构造函数,以创建并初始化子类实例,并赋予其支持 PromisePromise.prototype 内置方法所需的内部状态。

27.2.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. resolvingFunctionsCreateResolvingFunctions(promise)。
  10. completionCompletion(Call(executor, undefined, « resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]] »))。
  11. 如果 completion异常完成,则
    1. 执行 ? Call(resolvingFunctions.[[Reject]], undefined, « completion.[[Value]] »)。
  12. 返回 promise

executor 参数必须是 函数对象。它用于启动和报告该 Promise 所表示的(可能是延迟的)操作的完成。executor 会以两个参数 resolvereject 被调用。这两个参数是 executor 可用来报告延迟计算的最终完成或失败的函数。从 executor 返回并不意味着延迟操作已完成,只意味着已接受最终执行该操作的请求。

传递给 executorresolve 函数接受一个参数。executor 代码最终可调用 resolve,表示希望解决关联的 Promise。传递给 resolve 的参数表示延迟操作的最终值,可以是实际的兑现值,也可以是另一个 promise(如果 fulfilled)将提供值。

传递给 executorreject 函数也接受一个参数。executor 代码最终可调用 reject,表示关联的 Promise 被拒绝且永远不会兑现。传递给 reject 的参数用作 promise 的拒绝值。通常应为 Error 对象。

Promise 构造函数 传给 executor 的 resolve 和 reject 函数有能力实际解决和拒绝关联的 promise。子类可有不同的 构造函数 行为,传入自定义的 resolve 和 reject。

27.2.4 Promise 构造函数的属性

Promise 构造函数

27.2.4.1 Promise.all ( iterable )

该函数返回一个新的 promise,当传入的所有 promise 都已兑现时,其值为所有兑现值组成的数组;如果有任意一个 promise 被拒绝,则返回第一个被拒绝的原因。它在运行本算法时,会将传入的 iterable 的所有元素解析为 promise。

  1. Cthis 值。
  2. promiseCapability 为 ? NewPromiseCapability(C)。
  3. promiseResolveCompletion(GetPromiseResolve(C))。
  4. IfAbruptRejectPromise(promiseResolve, promiseCapability)。
  5. iteratorRecordCompletion(GetIterator(iterable, sync))。
  6. IfAbruptRejectPromise(iteratorRecord, promiseCapability)。
  7. resultCompletion(PerformPromiseAll(iteratorRecord, C, promiseCapability, promiseResolve))。
  8. 如果 result异常完成,则
    1. 如果 iteratorRecord.[[Done]]false,则设置 resultCompletion(IteratorClose(iteratorRecord, result))。
    2. IfAbruptRejectPromise(result, promiseCapability)。
  9. 返回 ! result

该函数要求其 this 值为一个支持 Promise 构造函数 参数规范的 构造函数 函数。

27.2.4.1.1 GetPromiseResolve ( promiseConstructor )

抽象操作 GetPromiseResolve 接收参数 promiseConstructor(一个 构造函数),返回一个 正常完成 包含函数对象抛出完成。调用时执行以下步骤:

  1. promiseResolve 为 ? Get(promiseConstructor, "resolve")。
  2. 如果 IsCallable(promiseResolve) 为 false,抛出 TypeError 异常。
  3. 返回 promiseResolve

27.2.4.1.2 PerformPromiseAll ( iteratorRecord, constructor, resultCapability, promiseResolve )

抽象操作 PerformPromiseAll 接收参数 iteratorRecord(一个 迭代器记录), constructor(一个 构造函数), resultCapability(一个 PromiseCapability 记录), promiseResolve(一个 函数对象),返回 正常完成 包含ECMAScript 语言值抛出完成。调用时执行以下步骤:

  1. values 为一个新的空 List
  2. remainingElementsCount记录 { [[Value]]: 1 }。
  3. index 为 0。
  4. 重复,
    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. values 添加 undefined
    4. nextPromise 为 ? Call(promiseResolve, constructor, « next »)。
    5. stepsPromise.all Resolve Element Functions 中定义的算法步骤。
    6. lengthPromise.all Resolve Element Functions 函数定义的非可选参数数量。
    7. onFulfilledCreateBuiltinFunction(steps, length, "", « [[AlreadyCalled]], [[Index]], [[Values]], [[Capability]], [[RemainingElements]] »)。
    8. 设置 onFulfilled.[[AlreadyCalled]]false
    9. 设置 onFulfilled.[[Index]]index
    10. 设置 onFulfilled.[[Values]]values
    11. 设置 onFulfilled.[[Capability]]resultCapability
    12. 设置 onFulfilled.[[RemainingElements]]remainingElementsCount
    13. 设置 remainingElementsCount.[[Value]]remainingElementsCount.[[Value]] + 1。
    14. 执行 ? Invoke(nextPromise, "then", « onFulfilled, resultCapability.[[Reject]] »)。
    15. 设置 indexindex + 1。

27.2.4.1.3 Promise.all 解析元素函数

Promise.all 解析元素函数是一个用于解析特定 Promise.all 元素的匿名内置函数。每个 Promise.all 解析元素函数都有 [[Index]][[Values]][[Capability]][[RemainingElements]][[AlreadyCalled]] 内部槽。

当以参数 x 调用 Promise.all 解析元素函数时,执行以下步骤:

  1. F当前函数对象
  2. 如果 F.[[AlreadyCalled]]true,返回 undefined
  3. 设置 F.[[AlreadyCalled]]true
  4. indexF.[[Index]]
  5. valuesF.[[Values]]
  6. promiseCapabilityF.[[Capability]]
  7. remainingElementsCountF.[[RemainingElements]]
  8. 设置 values[index] 为 x
  9. 设置 remainingElementsCount.[[Value]]remainingElementsCount.[[Value]] - 1。
  10. 如果 remainingElementsCount.[[Value]] = 0, 则
    1. valuesArrayCreateArrayFromList(values)。
    2. 返回 ? Call(promiseCapability.[[Resolve]], undefined, « valuesArray »)。
  11. 返回 undefined

Promise.all 解析元素函数的 "length" 属性值为 1𝔽

27.2.4.2 Promise.allSettled ( iterable )

该函数返回一个 promise,在所有原始 promise 都已定型(即已兑现或已拒绝)后,用 promise 状态快照数组兑现。它在运行本算法时,会将传入的 iterable 的所有元素解析为 promise。

  1. Cthis 值。
  2. promiseCapability 为 ? NewPromiseCapability(C)。
  3. promiseResolveCompletion(GetPromiseResolve(C))。
  4. IfAbruptRejectPromise(promiseResolve, promiseCapability)。
  5. iteratorRecordCompletion(GetIterator(iterable, sync))。
  6. IfAbruptRejectPromise(iteratorRecord, promiseCapability)。
  7. resultCompletion(PerformPromiseAllSettled(iteratorRecord, C, promiseCapability, promiseResolve))。
  8. 如果 result异常完成,则
    1. 如果 iteratorRecord.[[Done]]false,则设置 resultCompletion(IteratorClose(iteratorRecord, result))。
    2. IfAbruptRejectPromise(result, promiseCapability)。
  9. 返回 ! result

该函数要求其 this 值为一个支持 Promise 构造函数 参数规范的 构造函数 函数。

27.2.4.2.1 PerformPromiseAllSettled ( iteratorRecord, constructor, resultCapability, promiseResolve )

抽象操作 PerformPromiseAllSettled 接收参数 iteratorRecord(一个 迭代器记录)、 constructor(一个 构造函数)、 resultCapability(一个 PromiseCapability 记录)和 promiseResolve(一个 函数对象),返回 正常完成 包含ECMAScript 语言值抛出完成。调用时执行以下步骤:

  1. values 为一个新的空 List
  2. remainingElementsCount记录 { [[Value]]: 1 }。
  3. index 为 0。
  4. 重复,
    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. values 添加 undefined
    4. nextPromise 为 ? Call(promiseResolve, constructor, « next »)。
    5. stepsFulfilledPromise.allSettled 解析元素函数 中定义的算法步骤。
    6. lengthFulfilledPromise.allSettled 解析元素函数 函数定义的非可选参数数量。
    7. onFulfilledCreateBuiltinFunction(stepsFulfilled, lengthFulfilled, "", « [[AlreadyCalled]], [[Index]], [[Values]], [[Capability]], [[RemainingElements]] »)。
    8. alreadyCalled记录 { [[Value]]: false }。
    9. 设置 onFulfilled.[[AlreadyCalled]]alreadyCalled
    10. 设置 onFulfilled.[[Index]]index
    11. 设置 onFulfilled.[[Values]]values
    12. 设置 onFulfilled.[[Capability]]resultCapability
    13. 设置 onFulfilled.[[RemainingElements]]remainingElementsCount
    14. stepsRejectedPromise.allSettled 拒绝元素函数 中定义的算法步骤。
    15. lengthRejectedPromise.allSettled 拒绝元素函数 函数定义的非可选参数数量。
    16. onRejectedCreateBuiltinFunction(stepsRejected, lengthRejected, "", « [[AlreadyCalled]], [[Index]], [[Values]], [[Capability]], [[RemainingElements]] »)。
    17. 设置 onRejected.[[AlreadyCalled]]alreadyCalled
    18. 设置 onRejected.[[Index]]index
    19. 设置 onRejected.[[Values]]values
    20. 设置 onRejected.[[Capability]]resultCapability
    21. 设置 onRejected.[[RemainingElements]]remainingElementsCount
    22. 设置 remainingElementsCount.[[Value]]remainingElementsCount.[[Value]] + 1。
    23. 执行 ? Invoke(nextPromise, "then", « onFulfilled, onRejected »)。
    24. 设置 indexindex + 1。

27.2.4.2.2 Promise.allSettled 解析元素函数

Promise.allSettled 解析元素函数是一个匿名内置函数,用于解析特定的 Promise.allSettled 元素。每个 Promise.allSettled 解析元素函数都有 [[Index]][[Values]][[Capability]][[RemainingElements]][[AlreadyCalled]] 内部槽。

当以参数 x 调用 Promise.allSettled 解析元素函数时,执行以下步骤:

  1. F当前函数对象
  2. alreadyCalledF.[[AlreadyCalled]]
  3. 如果 alreadyCalled.[[Value]]true,返回 undefined
  4. 设置 alreadyCalled.[[Value]]true
  5. indexF.[[Index]]
  6. valuesF.[[Values]]
  7. promiseCapabilityF.[[Capability]]
  8. remainingElementsCountF.[[RemainingElements]]
  9. objOrdinaryObjectCreate(%Object.prototype%)。
  10. 执行 ! CreateDataPropertyOrThrow(obj, "status", "fulfilled")。
  11. 执行 ! CreateDataPropertyOrThrow(obj, "value", x)。
  12. 设置 values[index] 为 obj
  13. 设置 remainingElementsCount.[[Value]]remainingElementsCount.[[Value]] - 1。
  14. 如果 remainingElementsCount.[[Value]] = 0, 则
    1. valuesArrayCreateArrayFromList(values)。
    2. 返回 ? Call(promiseCapability.[[Resolve]], undefined, « valuesArray »)。
  15. 返回 undefined

Promise.allSettled 解析元素函数的 "length" 属性值为 1𝔽

27.2.4.2.3 Promise.allSettled 拒绝元素函数

Promise.allSettled 拒绝元素函数是一个匿名内置函数,用于拒绝特定的 Promise.allSettled 元素。每个 Promise.allSettled 拒绝元素函数都有 [[Index]][[Values]][[Capability]][[RemainingElements]][[AlreadyCalled]] 内部槽。

当以参数 x 调用 Promise.allSettled 拒绝元素函数时,执行以下步骤:

  1. F当前函数对象
  2. alreadyCalledF.[[AlreadyCalled]]
  3. 如果 alreadyCalled.[[Value]]true,返回 undefined
  4. 设置 alreadyCalled.[[Value]]true
  5. indexF.[[Index]]
  6. valuesF.[[Values]]
  7. promiseCapabilityF.[[Capability]]
  8. remainingElementsCountF.[[RemainingElements]]
  9. objOrdinaryObjectCreate(%Object.prototype%)。
  10. 执行 ! CreateDataPropertyOrThrow(obj, "status", "rejected")。
  11. 执行 ! CreateDataPropertyOrThrow(obj, "reason", x)。
  12. 设置 values[index] 为 obj
  13. 设置 remainingElementsCount.[[Value]]remainingElementsCount.[[Value]] - 1。
  14. 如果 remainingElementsCount.[[Value]] = 0, 则
    1. valuesArrayCreateArrayFromList(values)。
    2. 返回 ? Call(promiseCapability.[[Resolve]], undefined, « valuesArray »)。
  15. 返回 undefined

Promise.allSettled 拒绝元素函数的 "length" 属性值为 1𝔽

27.2.4.3 Promise.any ( iterable )

该函数返回一个 promise,该 promise 会被第一个兑现的输入 promise 兑现,或者如果所有输入 promise 都被拒绝,则以包含所有拒绝原因的 AggregateError 拒绝。在执行本算法时,会将传入的 iterable 的所有元素解析为 promise。

  1. Cthis 值。
  2. promiseCapability 为 ? NewPromiseCapability(C)。
  3. promiseResolveCompletion(GetPromiseResolve(C))。
  4. IfAbruptRejectPromise(promiseResolve, promiseCapability)。
  5. iteratorRecordCompletion(GetIterator(iterable, sync))。
  6. IfAbruptRejectPromise(iteratorRecord, promiseCapability)。
  7. resultCompletion(PerformPromiseAny(iteratorRecord, C, promiseCapability, promiseResolve))。
  8. 如果 result异常完成,则
    1. 如果 iteratorRecord.[[Done]]false,则设置 resultCompletion(IteratorClose(iteratorRecord, result))。
    2. IfAbruptRejectPromise(result, promiseCapability)。
  9. 返回 ! result

该函数要求其 this 值为支持 Promise 构造函数 参数规范的 构造函数 函数。

27.2.4.3.1 PerformPromiseAny ( iteratorRecord, constructor, resultCapability, promiseResolve )

抽象操作 PerformPromiseAny 接收参数 iteratorRecord(一个 迭代器记录)、 constructor(一个 构造函数)、resultCapability(一个 PromiseCapability 记录)和 promiseResolve(一个 函数对象),返回 正常完成 包含ECMAScript 语言值抛出完成。调用时执行以下步骤:

  1. errors 为一个新的空 List
  2. remainingElementsCount记录 { [[Value]]: 1 }。
  3. index 为 0。
  4. 重复,
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 nextdone,则
      1. 设置 remainingElementsCount.[[Value]]remainingElementsCount.[[Value]] - 1。
      2. 如果 remainingElementsCount.[[Value]] = 0,则
        1. error 为新建的 AggregateError 对象。
        2. 执行 ! DefinePropertyOrThrow(error, "errors", PropertyDescriptor { [[Configurable]]: true, [[Enumerable]]: false, [[Writable]]: true, [[Value]]: CreateArrayFromList(errors) }).
        3. 返回 ThrowCompletion(error)。
      3. 返回 resultCapability.[[Promise]]
    3. errors 添加 undefined
    4. nextPromise 为 ? Call(promiseResolve, constructor, « next »)。
    5. stepsRejectedPromise.any 拒绝元素函数 中定义的算法步骤。
    6. lengthRejectedPromise.any 拒绝元素函数 函数定义的非可选参数数量。
    7. onRejectedCreateBuiltinFunction(stepsRejected, lengthRejected, "", « [[AlreadyCalled]], [[Index]], [[Errors]], [[Capability]], [[RemainingElements]] »)。
    8. 设置 onRejected.[[AlreadyCalled]]false
    9. 设置 onRejected.[[Index]]index
    10. 设置 onRejected.[[Errors]]errors
    11. 设置 onRejected.[[Capability]]resultCapability
    12. 设置 onRejected.[[RemainingElements]]remainingElementsCount
    13. 设置 remainingElementsCount.[[Value]]remainingElementsCount.[[Value]] + 1。
    14. 执行 ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], onRejected »)。
    15. 设置 indexindex + 1。

27.2.4.3.2 Promise.any 拒绝元素函数

Promise.any 拒绝元素函数是一个匿名内置函数,用于拒绝特定的 Promise.any 元素。每个 Promise.any 拒绝元素函数都有 [[Index]][[Errors]][[Capability]][[RemainingElements]][[AlreadyCalled]] 内部槽。

当以参数 x 调用 Promise.any 拒绝元素函数时,执行以下步骤:

  1. F当前函数对象
  2. 如果 F.[[AlreadyCalled]]true,返回 undefined
  3. 设置 F.[[AlreadyCalled]]true
  4. indexF.[[Index]]
  5. errorsF.[[Errors]]
  6. promiseCapabilityF.[[Capability]]
  7. remainingElementsCountF.[[RemainingElements]]
  8. 设置 errors[index] 为 x
  9. 设置 remainingElementsCount.[[Value]]remainingElementsCount.[[Value]] - 1。
  10. 如果 remainingElementsCount.[[Value]] = 0, 则
    1. error 为新建的 AggregateError 对象。
    2. 执行 ! DefinePropertyOrThrow(error, "errors", PropertyDescriptor { [[Configurable]]: true, [[Enumerable]]: false, [[Writable]]: true, [[Value]]: CreateArrayFromList(errors) }).
    3. 返回 ? Call(promiseCapability.[[Reject]], undefined, « error »)。
  11. 返回 undefined

Promise.any 拒绝元素函数的 "length" 属性值为 1𝔽

27.2.4.4 Promise.prototype

Promise.prototype 的初始值为 Promise 原型对象

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

27.2.4.5 Promise.race ( iterable )

该函数返回一个新的 promise,其定型方式与第一个定型的输入 promise 相同。在运行本算法时会把传入的 iterable 的所有元素解析为 promise。

  1. Cthis 值。
  2. promiseCapability 为 ? NewPromiseCapability(C)。
  3. promiseResolveCompletion(GetPromiseResolve(C))。
  4. IfAbruptRejectPromise(promiseResolve, promiseCapability)。
  5. iteratorRecordCompletion(GetIterator(iterable, sync))。
  6. IfAbruptRejectPromise(iteratorRecord, promiseCapability)。
  7. resultCompletion(PerformPromiseRace(iteratorRecord, C, promiseCapability, promiseResolve))。
  8. 如果 result异常完成,则
    1. 如果 iteratorRecord.[[Done]]false,则设置 resultCompletion(IteratorClose(iteratorRecord, result))。
    2. IfAbruptRejectPromise(result, promiseCapability)。
  9. 返回 ! result
注 1

如果 iterable 参数不产出任何值,或者由 iterable 产出的 promise 都不会定型,则该方法返回的待定 promise 将永远不会定型。

注 2

该函数期望其 this 值为一个支持 Promise 构造函数 参数规范的 构造函数 函数。还期望其 this 值提供一个 resolve 方法。

27.2.4.5.1 PerformPromiseRace ( iteratorRecord, constructor, resultCapability, promiseResolve )

抽象操作 PerformPromiseRace 接收参数 iteratorRecord(一个 迭代器记录)、 constructor(一个 构造函数)、 resultCapability(一个 PromiseCapability 记录)和 promiseResolve(一个 函数对象),返回 正常完成包含ECMAScript 语言值抛出完成。调用时执行以下步骤:

  1. 重复,
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 nextdone,则
      1. 返回 resultCapability.[[Promise]]
    3. nextPromise 为 ? Call(promiseResolve, constructor, « next »)。
    4. 执行 ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], resultCapability.[[Reject]] »)。

27.2.4.6 Promise.reject ( r )

该函数返回一个以传入参数为拒绝原因的新 promise。

  1. Cthis 值。
  2. promiseCapability 为 ? NewPromiseCapability(C)。
  3. 执行 ? Call(promiseCapability.[[Reject]], undefined, « r »)。
  4. 返回 promiseCapability.[[Promise]]

该函数期望其 this 值为一个支持 Promise 构造函数 参数规范的 构造函数

27.2.4.7 Promise.resolve ( x )

该函数返回一个用传入参数解决的新 promise,或者如果参数本身就是由该 构造函数 生成的 promise,则直接返回该参数。

  1. Cthis 值。
  2. 如果 C 不是对象,抛出 TypeError 异常。
  3. 返回 ? PromiseResolve(C, x)。

该函数期望其 this 值为一个支持 Promise 构造函数 参数规范的 构造函数

27.2.4.7.1 PromiseResolve ( C, x )

抽象操作 PromiseResolve 接收参数 C(一个对象)和 x(一个 ECMAScript 语言值),返回 正常完成 包含ECMAScript 语言值抛出完成。它返回一个用 x 解决的新 promise。调用时执行以下步骤:

  1. 如果 IsPromise(x) 为 true,则
    1. xConstructor 为 ? Get(x, "constructor")。
    2. 如果 SameValue(xConstructor, C) 为 true,返回 x
  2. promiseCapability 为 ? NewPromiseCapability(C)。
  3. 执行 ? Call(promiseCapability.[[Resolve]], undefined, « x »)。
  4. 返回 promiseCapability.[[Promise]]

27.2.4.8 Promise.try ( callback, ...args )

该函数被调用时执行以下步骤:

  1. Cthis 值。
  2. 如果 C 不是对象,抛出 TypeError 异常。
  3. promiseCapability 为 ? NewPromiseCapability(C)。
  4. statusCompletion(Call(callback, undefined, args))。
  5. 如果 status异常完成,则
    1. 执行 ? Call(promiseCapability.[[Reject]], undefined, « status.[[Value]] »)。
  6. 否则,
    1. 执行 ? Call(promiseCapability.[[Resolve]], undefined, « status.[[Value]] »)。
  7. 返回 promiseCapability.[[Promise]]

该函数期望其 this 值为一个支持 Promise 构造函数 参数规范的 构造函数

27.2.4.9 Promise.withResolvers ( )

该函数返回一个包含三个属性的对象:一个新的 promise,以及与其关联的 resolvereject 函数。

  1. Cthis 值。
  2. promiseCapability 为 ? NewPromiseCapability(C)。
  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.2.4.10 get Promise [ %Symbol.species% ]

Promise[%Symbol.species%] 是一个 访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数被调用时,执行以下步骤:

  1. 返回 this 值。

该函数的 "name" 属性值为 "get [Symbol.species]"

Promise 原型方法通常使用其 this 值的 构造函数 来创建派生对象。然而,子类 构造函数 可以通过重定义其 %Symbol.species% 属性来覆盖该默认行为。

27.2.5 Promise 原型对象的属性

Promise 原型对象

  • %Promise.prototype%
  • 拥有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%
  • 是一个 普通对象
  • 没有 [[PromiseState]] 内部槽,也没有 Promise 实例的其他内部槽。

27.2.5.1 Promise.prototype.catch ( onRejected )

该方法被调用时执行以下步骤:

  1. promisethis 值。
  2. 返回 ? Invoke(promise, "then", « undefined, onRejected »)。

27.2.5.2 Promise.prototype.constructor

Promise.prototype.constructor 的初始值为 %Promise%

27.2.5.3 Promise.prototype.finally ( onFinally )

该方法被调用时执行以下步骤:

  1. promisethis 值。
  2. 如果 promise 不是对象,抛出 TypeError 异常。
  3. C 为 ? SpeciesConstructor(promise, %Promise%)。
  4. 断言IsConstructor(C) 为 true
  5. 如果 IsCallable(onFinally) 为 false,则
    1. thenFinallyonFinally
    2. catchFinallyonFinally
  6. 否则,
    1. thenFinallyClosure 为一个新的 抽象闭包, 参数为 (value),捕获 onFinallyC,调用时执行以下步骤:
      1. result 为 ? Call(onFinally, undefined)。
      2. p 为 ? PromiseResolve(C, result)。
      3. returnValue 为一个新的 抽象闭包 无参数,捕获 value,调用时执行以下步骤:
        1. 返回 value
      4. valueThunkCreateBuiltinFunction(returnValue, 0, "", « »)。
      5. 返回 ? Invoke(p, "then", « valueThunk »)。
    2. thenFinallyCreateBuiltinFunction(thenFinallyClosure, 1, "", « »)。
    3. catchFinallyClosure 为一个新的 抽象闭包, 参数为 (reason),捕获 onFinallyC,调用时执行以下步骤:
      1. result 为 ? Call(onFinally, undefined)。
      2. p 为 ? PromiseResolve(C, result)。
      3. throwReason 为一个新的 抽象闭包 无参数,捕获 reason,调用时执行以下步骤:
        1. 返回 ThrowCompletion(reason)。
      4. throwerCreateBuiltinFunction(throwReason, 0, "", « »)。
      5. 返回 ? Invoke(p, "then", « thrower »)。
    4. catchFinallyCreateBuiltinFunction(catchFinallyClosure, 1, "", « »)。
  7. 返回 ? Invoke(promise, "then", « thenFinally, catchFinally »)。

27.2.5.4 Promise.prototype.then ( onFulfilled, onRejected )

该方法被调用时执行以下步骤:

  1. promisethis 值。
  2. 如果 IsPromise(promise) 为 false,抛出 TypeError 异常。
  3. C 为 ? SpeciesConstructor(promise, %Promise%)。
  4. resultCapability 为 ? NewPromiseCapability(C)。
  5. 返回 PerformPromiseThen(promise, onFulfilled, onRejected, resultCapability)。

27.2.5.4.1 PerformPromiseThen ( promise, onFulfilled, onRejected [ , resultCapability ] )

抽象操作 PerformPromiseThen 接收参数 promise(一个 Promise), onFulfilled(一个 ECMAScript 语言值), onRejected(一个 ECMAScript 语言值) 以及可选参数 resultCapability(一个 PromiseCapability 记录), 返回一个 ECMAScript 语言值。 它使用 onFulfilledonRejected 作为定型操作,对 promise 执行 “then” 操作。如果传入 resultCapability,则通过更新 resultCapability 的 promise 存储结果;如果未传入,则说明 PerformPromiseThen 被规范内部操作调用,结果无关紧要。调用时执行以下步骤:

  1. 断言IsPromise(promise) 为 true
  2. 如果未传入 resultCapability,则
    1. 设置 resultCapabilityundefined
  3. 如果 IsCallable(onFulfilled) 为 false,则
    1. onFulfilledJobCallbackempty
  4. 否则,
    1. onFulfilledJobCallbackHostMakeJobCallback(onFulfilled)。
  5. 如果 IsCallable(onRejected) 为 false,则
    1. onRejectedJobCallbackempty
  6. 否则,
    1. onRejectedJobCallbackHostMakeJobCallback(onRejected)。
  7. fulfillReactionPromiseReaction 记录 { [[Capability]]: resultCapability, [[Type]]: fulfill, [[Handler]]: onFulfilledJobCallback }。
  8. rejectReactionPromiseReaction 记录 { [[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,则
    1. 返回 undefined
  14. 否则,
    1. 返回 resultCapability.[[Promise]]

27.2.5.5 Promise.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值为字符串 "Promise"

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

27.2.6 Promise 实例的属性

Promise 实例是普通对象,继承自 Promise 原型对象(本征的,%Promise.prototype%)。 Promise 实例最初使用表 92中描述的内部槽创建。

表 92:Promise 实例的内部槽
内部槽 类型 描述
[[PromiseState]] pendingfulfilledrejected 控制 promise 对其 then 方法的调用如何反应。
[[PromiseResult]] 一个 ECMAScript 语言值empty promise 被兑现或拒绝时的值(如果有)。仅当 [[PromiseState]]pending 时为 empty
[[PromiseFulfillReactions]] 一个 List ,元素为 PromiseReaction 记录 记录 ,在 promise 从 pending 状态转换到 fulfilled 状态时处理。
[[PromiseRejectReactions]] 一个 List ,元素为 PromiseReaction 记录 记录 ,在 promise 从 pending 状态转换到 rejected 状态时处理。
[[PromiseIsHandled]] 布尔值 指示 promise 是否曾经有过兑现或拒绝处理器;用于未处理拒绝的追踪。

27.3 GeneratorFunction 对象

GeneratorFunction 通常是通过求值 GeneratorDeclarationGeneratorExpressionGeneratorMethod 创建的函数。也可以通过调用 %GeneratorFunction% 内部对象创建。

图 6(信息性):Generator 对象关系
A staggering variety of boxes and arrows.

27.3.1 GeneratorFunction 构造函数

GeneratorFunction 构造函数

  • %GeneratorFunction%
  • Function 的子类。
  • 被作为函数而不是 构造函数 调用时,会创建并初始化一个新的 GeneratorFunction。因此,函数调用 GeneratorFunction (…) 等价于用相同参数的对象创建表达式 new GeneratorFunction (…)
  • 可以用作类定义的 extends 子句的值。意图继承指定 GeneratorFunction 行为的子类 构造函数,必须通过 super 调用 GeneratorFunction 构造函数 创建并初始化子类实例,并赋予其内置 GeneratorFunction 行为所需的内部槽。所有 ECMAScript 定义 generator 函数对象 的语法形式,都会创建 GeneratorFunction 的直接实例。没有语法手段可以创建 GeneratorFunction 子类的实例。

27.3.1.1 GeneratorFunction ( ...parameterArgs, bodyArg )

最后一个参数(如果有)指定生成器函数的主体(可执行代码);之前的所有参数指定形式参数。

该函数被调用时执行以下步骤:

  1. C当前函数对象
  2. 如果 bodyArg 不存在,则将 bodyArg 设为一个空字符串。
  3. 返回 ? CreateDynamicFunction(C, NewTarget, generator, parameterArgs, bodyArg)。

参见 20.2.1.1 的注。

27.3.2 GeneratorFunction 构造函数的属性

GeneratorFunction 构造函数

  • 是一个标准内置 函数对象,继承自 Function 构造函数
  • 拥有 [[Prototype]] 内部槽,其值为 %Function%
  • 拥有 "length" 属性,其值为 1𝔽
  • 拥有 "name" 属性,其值为 "GeneratorFunction"
  • 拥有以下属性:

27.3.2.1 GeneratorFunction.prototype

GeneratorFunction.prototype 的初始值为 GeneratorFunction 原型对象

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

27.3.3 GeneratorFunction 原型对象的属性

GeneratorFunction 原型对象

27.3.3.1 GeneratorFunction.prototype.constructor

GeneratorFunction.prototype.constructor 的初始值为 %GeneratorFunction%

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

27.3.3.2 GeneratorFunction.prototype.prototype

GeneratorFunction.prototype.prototype 的初始值为 %GeneratorPrototype%

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

27.3.3.3 GeneratorFunction.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值为字符串 "GeneratorFunction"

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

27.3.4 GeneratorFunction 实例

每个 GeneratorFunction 实例都是一个 ECMAScript 函数对象,并拥有 表 30 中列出的内部槽。所有此类实例的 [[IsClassConstructor]] 内部槽的值均为 false

每个 GeneratorFunction 实例拥有以下自有属性:

27.3.4.1 length

Function 实例的 "length" 属性规范,见 20.2.4.1,同样适用于 GeneratorFunction 实例。

27.3.4.2 name

Function 实例的 "name" 属性规范,见 20.2.4.2,同样适用于 GeneratorFunction 实例。

27.3.4.3 prototype

每当创建一个 GeneratorFunction 实例时,还会创建另一个 普通对象,作为生成器函数 "prototype" 属性的初始值。该 prototype 属性的值用于在 generator 函数对象 通过 [[Call]] 被调用时,初始化新创建的 Generator 的 [[Prototype]] 内部槽。

该属性具有属性 { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }。

与 Function 实例不同,GeneratorFunction 的 "prototype" 属性所指向的对象没有 "constructor" 属性,其值为该 GeneratorFunction 实例。

27.4 AsyncGeneratorFunction 对象

AsyncGeneratorFunction 通常是通过求值 AsyncGeneratorDeclarationAsyncGeneratorExpressionAsyncGeneratorMethod 语法产生式创建的函数。也可以通过调用 %AsyncGeneratorFunction% 内部对象创建。

27.4.1 AsyncGeneratorFunction 构造函数

AsyncGeneratorFunction 构造函数

  • %AsyncGeneratorFunction%
  • Function 的子类。
  • 被作为函数而不是 构造函数 调用时,会创建并初始化一个新的 AsyncGeneratorFunction。因此,函数调用 AsyncGeneratorFunction (...) 等价于用相同参数的对象创建表达式 new AsyncGeneratorFunction (...)
  • 可以用作类定义的 extends 子句的值。意图继承指定 AsyncGeneratorFunction 行为的子类 构造函数,必须通过 super 调用 AsyncGeneratorFunction 构造函数 创建并初始化子类实例,并赋予其内置 AsyncGeneratorFunction 行为所需的内部槽。所有 ECMAScript 定义 async generator 函数对象 的语法形式,都会创建 AsyncGeneratorFunction 的直接实例。没有语法手段可以创建 AsyncGeneratorFunction 子类的实例。

27.4.1.1 AsyncGeneratorFunction ( ...parameterArgs, bodyArg )

最后一个参数(如果有)指定异步生成器函数的主体(可执行代码);之前的所有参数指定形式参数。

该函数被调用时执行以下步骤:

  1. C当前函数对象
  2. 如果 bodyArg 不存在,则将 bodyArg 设为一个空字符串。
  3. 返回 ? CreateDynamicFunction(C, NewTarget, async-generator, parameterArgs, bodyArg)。

参见 20.2.1.1 的注。

27.4.2 AsyncGeneratorFunction 构造函数的属性

AsyncGeneratorFunction 构造函数

  • 是一个标准内置 函数对象,继承自 Function 构造函数
  • 拥有 [[Prototype]] 内部槽,其值为 %Function%
  • 拥有 "length" 属性,其值为 1𝔽
  • 拥有 "name" 属性,其值为 "AsyncGeneratorFunction"
  • 拥有以下属性:

27.4.2.1 AsyncGeneratorFunction.prototype

AsyncGeneratorFunction.prototype 的初始值为 AsyncGeneratorFunction 原型对象

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

27.4.3 AsyncGeneratorFunction 原型对象的属性

AsyncGeneratorFunction 原型对象

27.4.3.1 AsyncGeneratorFunction.prototype.constructor

AsyncGeneratorFunction.prototype.constructor 的初始值为 %AsyncGeneratorFunction%

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

27.4.3.2 AsyncGeneratorFunction.prototype.prototype

AsyncGeneratorFunction.prototype.prototype 的初始值为 %AsyncGeneratorPrototype%

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

27.4.3.3 AsyncGeneratorFunction.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值为字符串 "AsyncGeneratorFunction"

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

27.4.4 AsyncGeneratorFunction 实例

每个 AsyncGeneratorFunction 实例都是一个 ECMAScript 函数对象,并拥有 表 30 中列出的内部槽。所有此类实例的 [[IsClassConstructor]] 内部槽的值均为 false

每个 AsyncGeneratorFunction 实例拥有以下自有属性:

27.4.4.1 length

"length" 属性的值是一个 整数 Number,表示异步生成器函数通常期望的参数个数。不过,语言允许使用其他数量的参数调用该函数。调用时参数数量与 "length" 属性值不一致时 AsyncGeneratorFunction 的表现取决于具体函数。

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

27.4.4.2 name

Function 实例的 "name" 属性规范,见 20.2.4.2,同样适用于 AsyncGeneratorFunction 实例。

27.4.4.3 prototype

每当创建一个 AsyncGeneratorFunction 实例时,还会创建另一个 普通对象,作为异步生成器函数 "prototype" 属性的初始值。该 prototype 属性的值用于在 async generator 函数对象 通过 [[Call]] 被调用时,初始化新创建的 AsyncGenerator 的 [[Prototype]] 内部槽。

该属性具有属性 { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }。

与普通 Function 实例不同,AsyncGeneratorFunction 的 "prototype" 属性所指向的对象没有 "constructor" 属性,其值为该 AsyncGeneratorFunction 实例。

27.5 Generator 对象

Generator 是通过调用生成器函数创建的,同时符合 迭代器接口可迭代接口

Generator 实例直接继承自创建该实例的生成器函数的 "prototype" 属性的初始值。Generator 实例间接继承自 %GeneratorPrototype%

27.5.1 %GeneratorPrototype% 对象

%GeneratorPrototype% 对象:

  • %GeneratorFunction.prototype.prototype%
  • 是一个 普通对象
  • 不是 Generator 实例,没有 [[GeneratorState]] 内部槽。
  • 拥有 [[Prototype]] 内部槽,其值为 %Iterator.prototype%
  • 具有所有 Generator 实例间接继承的属性。

27.5.1.1 %GeneratorPrototype%.constructor

%GeneratorPrototype%.constructor 的初始值为 %GeneratorFunction.prototype%

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

27.5.1.2 %GeneratorPrototype%.next ( value )

  1. 返回 ? GeneratorResume(this value, value, empty).

27.5.1.3 %GeneratorPrototype%.return ( value )

该方法被调用时执行以下步骤:

  1. gthis 值。
  2. CReturnCompletion(value)。
  3. 返回 ? GeneratorResumeAbrupt(g, C, empty).

27.5.1.4 %GeneratorPrototype%.throw ( exception )

该方法被调用时执行以下步骤:

  1. gthis 值。
  2. CThrowCompletion(exception)。
  3. 返回 ? GeneratorResumeAbrupt(g, C, empty).

27.5.1.5 %GeneratorPrototype% [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值为字符串 "Generator"

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

27.5.2 Generator 实例的属性

Generator 实例最初使用 表 93 中描述的内部槽创建。

表 93:Generator 实例的内部槽
内部槽 类型 描述
[[GeneratorState]] suspended-startsuspended-yieldexecutingcompleted 当前 generator 的执行状态。
[[GeneratorContext]] 一个 执行上下文 执行该 generator 代码时所用的 执行上下文
[[GeneratorBrand]] 字符串或 empty 用于区分不同类型 generator 的标记。由 ECMAScript 源文本 声明的 generator 的 [[GeneratorBrand]] 总是 empty

27.5.3 Generator 抽象操作

27.5.3.1 GeneratorStart ( generator, generatorBody )

抽象操作 GeneratorStart 接收参数 generator(一个 Generator)和 generatorBodyFunctionBody 解析节点 或无参数的 抽象闭包),返回 unused。调用时执行以下步骤:

  1. 断言generator.[[GeneratorState]] 的值为 suspended-start
  2. genContext当前执行上下文
  3. genContext 的 Generator 组件设为 generator
  4. closure 为一个新的 抽象闭包,无参数,捕获 generatorBody,调用时执行以下步骤:
    1. acGenContext当前执行上下文
    2. acGeneratoracGenContext 的 Generator 组件。
    3. 如果 generatorBody解析节点,则
      1. resultCompletion(Evaluation of generatorBody).
    4. 否则,
      1. 断言generatorBody 是一个无参数的 抽象闭包
      2. resultCompletion(generatorBody())。
    5. 断言:如果执行到这里,generator 要么抛出了异常,要么进行了隐式或显式 return。
    6. 执行上下文栈 移除 acGenContext,并恢复 执行上下文,该上下文现在位于 执行上下文栈 顶部,作为 当前执行上下文
    7. 设置 acGenerator.[[GeneratorState]]completed
    8. 注:一旦 generator 进入 completed 状态,就不会再离开,其关联的 执行上下文 也不会被恢复。此时与 acGenerator 相关的执行状态可以被丢弃。
    9. 如果 result正常完成,则
      1. resultValueundefined
    10. 否则如果 resultreturn 完成,则
      1. resultValueresult.[[Value]]
    11. 否则,
      1. 断言resultthrow 完成
      2. 返回 ? result
    12. 返回 CreateIteratorResultObject(resultValue, true).
  5. 设置 genContext 的代码求值状态,使得该 执行上下文 恢复时会调用 closure,且无参数。
  6. 设置 generator.[[GeneratorContext]]genContext
  7. 返回 unused

27.5.3.2 GeneratorValidate ( generator, generatorBrand )

抽象操作 GeneratorValidate 接收参数 generator(一个 ECMAScript 语言值)和 generatorBrand(字符串或 empty),返回 正常完成包含 suspended-startsuspended-yieldcompleted 之一,或 抛出完成。调用时执行以下步骤:

  1. 执行 ? RequireInternalSlot(generator, [[GeneratorState]]).
  2. 执行 ? RequireInternalSlot(generator, [[GeneratorBrand]]).
  3. 如果 generator.[[GeneratorBrand]] 不等于 generatorBrand,抛出 TypeError 异常。
  4. 断言generator 还有 [[GeneratorContext]] 内部槽。
  5. stategenerator.[[GeneratorState]]
  6. 如果 stateexecuting,抛出 TypeError 异常。
  7. 返回 state

27.5.3.3 GeneratorResume ( generator, value, generatorBrand )

抽象操作 GeneratorResume 接收参数 generator(一个 ECMAScript 语言值)、 value(一个 ECMAScript 语言值empty)、generatorBrand(字符串或 empty),返回 正常完成包含ECMAScript 语言值抛出完成。调用时执行以下步骤:

  1. state 为 ? GeneratorValidate(generator, generatorBrand).
  2. 如果 statecompleted,返回 CreateIteratorResultObject(undefined, true).
  3. 断言statesuspended-startsuspended-yield
  4. genContextgenerator.[[GeneratorContext]]
  5. methodContext当前执行上下文
  6. 挂起 methodContext
  7. 设置 generator.[[GeneratorState]]executing
  8. genContext 压入 执行上下文栈genContext 现在是 当前执行上下文
  9. 恢复 genContext 的挂起执行,以 NormalCompletion(value) 作为挂起操作的结果。令 result 为恢复运算返回的值。
  10. 断言: 执行到这里时,genContext 已从 执行上下文栈 移除,methodContext 是当前 执行上下文
  11. 返回 ? result

27.5.3.4 GeneratorResumeAbrupt ( generator, abruptCompletion, generatorBrand )

抽象操作 GeneratorResumeAbrupt 接收参数 generator(一个 ECMAScript 语言值), abruptCompletion(一个 return 完成throw 完成), 以及 generatorBrand(字符串或 empty),返回 正常完成包含ECMAScript 语言值抛出完成。调用时执行以下步骤:

  1. state 为 ? GeneratorValidate(generator, generatorBrand)。
  2. 如果 statesuspended-start,则
    1. 设置 generator.[[GeneratorState]]completed
    2. 注:一旦 generator 进入 completed 状态,就不会再离开,其关联的 执行上下文 也不会被恢复。此时与 generator 相关的执行状态可以被丢弃。
    3. 设置 statecompleted
  3. 如果 statecompleted,则
    1. 如果 abruptCompletionreturn 完成,则
      1. 返回 CreateIteratorResultObject(abruptCompletion.[[Value]], true)。
    2. 返回 ? abruptCompletion
  4. 断言statesuspended-yield
  5. genContextgenerator.[[GeneratorContext]]
  6. methodContext当前执行上下文
  7. 挂起 methodContext
  8. 设置 generator.[[GeneratorState]]executing
  9. genContext 压入 执行上下文栈genContext 现在是 当前执行上下文
  10. 恢复 genContext 的挂起执行,以 abruptCompletion 作为挂起操作的结果。令 result 为恢复运算返回的 Completion Record
  11. 断言: 执行到这里时,genContext 已从 执行上下文栈 移除,methodContext 是当前 执行上下文
  12. 返回 ? result

27.5.3.5 GetGeneratorKind ( )

抽象操作 GetGeneratorKind 不带参数,返回 non-generatorsyncasync。调用时执行以下步骤:

  1. genContext当前执行上下文
  2. 如果 genContext 没有 Generator 组件,返回 non-generator
  3. generatorgenContext 的 Generator 组件。
  4. 如果 generator[[AsyncGeneratorState]] 内部槽,返回 async
  5. 否则,返回 sync

27.5.3.6 GeneratorYield ( iteratorResult )

抽象操作 GeneratorYield 接收参数 iteratorResult(一个符合 IteratorResult 接口 的对象),返回 正常完成包含ECMAScript 语言值异常完成。调用时执行以下步骤:

  1. genContext当前执行上下文
  2. 断言genContext 是 generator 的 执行上下文
  3. generatorgenContext 的 Generator 组件的值。
  4. 断言GetGeneratorKind() 为 sync
  5. 设置 generator.[[GeneratorState]]suspended-yield
  6. 执行上下文栈 移除 genContext,并恢复 执行上下文,该上下文现在位于 执行上下文栈 顶部,作为 当前执行上下文
  7. callerContext当前执行上下文
  8. 恢复 callerContext,传递 NormalCompletion(iteratorResult)。 如果 genContext 以后再次被恢复,令 resumptionValue 为恢复时携带的 Completion Record
  9. 断言:如果执行到这里,genContext 又成为 当前执行上下文
  10. 返回 resumptionValue

27.5.3.7 Yield ( value )

抽象操作 Yield 接收参数 value(一个 ECMAScript 语言值),返回 正常完成包含ECMAScript 语言值异常完成。调用时执行以下步骤:

  1. generatorKindGetGeneratorKind()。
  2. 如果 generatorKindasync,返回 ? AsyncGeneratorYield(? Await(value))。
  3. 否则,返回 ? GeneratorYield(CreateIteratorResultObject(value, false))。

27.5.3.8 CreateIteratorFromClosure ( closure, generatorBrand, generatorPrototype [ , extraSlots ] )

抽象操作 CreateIteratorFromClosure 接收参数 closure(一个无参数的 抽象闭包), generatorBrand(字符串或 empty), generatorPrototype(一个对象),以及可选参数 extraSlotsList,其元素为内部槽名称),返回一个 Generator。调用时执行以下步骤:

  1. 注:closure 可以包含 Yield 操作,用于 yield 一个 IteratorResult 对象
  2. 如果 extraSlots 不存在,则将 extraSlots 设为一个新的空 List
  3. internalSlotsListlist-concatenation(extraSlots 和 « [[GeneratorState]], [[GeneratorContext]], [[GeneratorBrand]] »)。
  4. generatorOrdinaryObjectCreate(generatorPrototype, internalSlotsList)。
  5. 设置 generator.[[GeneratorBrand]]generatorBrand
  6. 设置 generator.[[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(generator, closure)。
  15. 执行上下文栈 移除 calleeContext,并恢复 callerContext 作为 当前执行上下文
  16. 返回 generator

27.6 AsyncGenerator 对象

AsyncGenerator 是通过调用异步生成器函数创建的,并同时符合 异步迭代器接口异步可迭代接口

AsyncGenerator 实例直接继承自创建该实例的异步生成器函数 "prototype" 属性的初始值。AsyncGenerator 实例间接继承自 %AsyncGeneratorPrototype%

27.6.1 %AsyncGeneratorPrototype% 对象

%AsyncGeneratorPrototype% 对象:

  • %AsyncGeneratorFunction.prototype.prototype%
  • 是一个 普通对象
  • 不是 AsyncGenerator 实例,并且没有 [[AsyncGeneratorState]] 内部槽。
  • 拥有 [[Prototype]] 内部槽,其值为 %AsyncIteratorPrototype%
  • 具有所有 AsyncGenerator 实例间接继承的属性。

27.6.1.1 %AsyncGeneratorPrototype%.constructor

%AsyncGeneratorPrototype%.constructor 的初始值为 %AsyncGeneratorFunction.prototype%

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

27.6.1.2 %AsyncGeneratorPrototype%.next ( value )

  1. generatorthis 值。
  2. promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  3. resultCompletion(AsyncGeneratorValidate(generator, empty))。
  4. IfAbruptRejectPromise(result, promiseCapability)。
  5. stategenerator.[[AsyncGeneratorState]]
  6. 如果 statecompleted,则
    1. iteratorResultCreateIteratorResultObject(undefined, true)。
    2. 执行 ! Call(promiseCapability.[[Resolve]], undefined, « iteratorResult »)。
    3. 返回 promiseCapability.[[Promise]]
  7. completionNormalCompletion(value)。
  8. 执行 AsyncGeneratorEnqueue(generator, completion, promiseCapability)。
  9. 如果 statesuspended-startsuspended-yield,则
    1. 执行 AsyncGeneratorResume(generator, completion)。
  10. 否则,
    1. 断言stateexecutingdraining-queue
  11. 返回 promiseCapability.[[Promise]]

27.6.1.3 %AsyncGeneratorPrototype%.return ( value )

  1. generatorthis 值。
  2. promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  3. resultCompletion(AsyncGeneratorValidate(generator, empty))。
  4. IfAbruptRejectPromise(result, promiseCapability)。
  5. completionReturnCompletion(value)。
  6. 执行 AsyncGeneratorEnqueue(generator, completion, promiseCapability)。
  7. stategenerator.[[AsyncGeneratorState]]
  8. 如果 statesuspended-startcompleted,则
    1. 设置 generator.[[AsyncGeneratorState]]draining-queue
    2. 执行 AsyncGeneratorAwaitReturn(generator)。
  9. 否则如果 statesuspended-yield,则
    1. 执行 AsyncGeneratorResume(generator, completion)。
  10. 否则,
    1. 断言stateexecutingdraining-queue
  11. 返回 promiseCapability.[[Promise]]

27.6.1.4 %AsyncGeneratorPrototype%.throw ( exception )

  1. generatorthis 值。
  2. promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  3. resultCompletion(AsyncGeneratorValidate(generator, empty))。
  4. IfAbruptRejectPromise(result, promiseCapability)。
  5. stategenerator.[[AsyncGeneratorState]]
  6. 如果 statesuspended-start,则
    1. 设置 generator.[[AsyncGeneratorState]]completed
    2. 设置 statecompleted
  7. 如果 statecompleted,则
    1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « exception »)。
    2. 返回 promiseCapability.[[Promise]]
  8. completionThrowCompletion(exception)。
  9. 执行 AsyncGeneratorEnqueue(generator, completion, promiseCapability)。
  10. 如果 statesuspended-yield,则
    1. 执行 AsyncGeneratorResume(generator, completion)。
  11. 否则,
    1. 断言stateexecutingdraining-queue
  12. 返回 promiseCapability.[[Promise]]

27.6.1.5 %AsyncGeneratorPrototype% [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值为字符串 "AsyncGenerator"

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

27.6.2 AsyncGenerator 实例的属性

AsyncGenerator 实例最初使用如下内部槽创建:

表 94:AsyncGenerator 实例的内部槽
内部槽 类型 描述
[[AsyncGeneratorState]] suspended-startsuspended-yieldexecutingdraining-queuecompleted 当前异步生成器的执行状态。
[[AsyncGeneratorContext]] 一个 执行上下文 执行该异步生成器代码时所用的 执行上下文
[[AsyncGeneratorQueue]] 一个 List ,元素为 AsyncGeneratorRequest 记录 记录 ,表示恢复异步生成器的请求。除了状态转换期间,只有当 [[AsyncGeneratorState]]executingdraining-queue 时该队列才非空。
[[GeneratorBrand]] 字符串或 empty 用于区分不同类型异步生成器的标记。由 ECMAScript 源文本 声明的异步生成器的 [[GeneratorBrand]] 总是 empty

27.6.3 AsyncGenerator 抽象操作

27.6.3.1 AsyncGeneratorRequest 记录

AsyncGeneratorRequest 是一个 记录值,用于存储如何恢复异步生成器的信息,并包含兑现或拒绝相应 promise 的能力。

它们具有以下字段:

表 95:AsyncGeneratorRequest 记录 字段
字段名 含义
[[Completion]] 一个 Completion Record 用于恢复异步生成器的 Completion Record
[[Capability]] 一个 PromiseCapability 记录 与该请求关联的 promise 能力。

27.6.3.2 AsyncGeneratorStart ( generator, generatorBody )

抽象操作 AsyncGeneratorStart 接收参数 generator(一个 AsyncGenerator)和 generatorBodyFunctionBody 解析节点 或无参数的 抽象闭包),返回 unused。调用时执行以下步骤:

  1. 断言generator.[[AsyncGeneratorState]]suspended-start
  2. genContext当前执行上下文
  3. genContext 的 Generator 组件设为 generator
  4. closure 为一个新的 抽象闭包,无参数,捕获 generatorBody,调用时执行以下步骤:
    1. acGenContext当前执行上下文
    2. acGeneratoracGenContext 的 Generator 组件。
    3. 如果 generatorBody解析节点,则
      1. resultCompletion(Evaluation of generatorBody)。
    4. 否则,
      1. 断言generatorBody 是一个无参数的 抽象闭包
      2. resultCompletion(generatorBody())。
    5. 断言:如果执行到这里,异步生成器要么抛出了异常,要么进行了隐式或显式 return。
    6. 执行上下文栈 移除 acGenContext,并恢复 执行上下文,该上下文现在位于 执行上下文栈 顶部,作为 当前执行上下文
    7. 设置 acGenerator.[[AsyncGeneratorState]]draining-queue
    8. 如果 result正常完成,则将 result 设为 NormalCompletion(undefined)。
    9. 如果 resultreturn 完成,则将 result 设为 NormalCompletion(result.[[Value]])。
    10. 执行 AsyncGeneratorCompleteStep(acGenerator, result, true)。
    11. 执行 AsyncGeneratorDrainQueue(acGenerator)。
    12. 返回 undefined
  5. 设置 genContext 的代码求值状态,使得该 执行上下文 恢复时会调用 closure,且无参数。
  6. 设置 generator.[[AsyncGeneratorContext]]genContext
  7. 设置 generator.[[AsyncGeneratorQueue]] 为一个新的空 List
  8. 返回 unused

27.6.3.3 AsyncGeneratorValidate ( generator, generatorBrand )

抽象操作 AsyncGeneratorValidate 接收参数 generator(一个 ECMAScript 语言值)和 generatorBrand(字符串或 empty),返回 正常完成包含 unused,或 抛出完成。调用时执行以下步骤:

  1. 执行 ? RequireInternalSlot(generator, [[AsyncGeneratorContext]])。
  2. 执行 ? RequireInternalSlot(generator, [[AsyncGeneratorState]])。
  3. 执行 ? RequireInternalSlot(generator, [[AsyncGeneratorQueue]])。
  4. 如果 generator.[[GeneratorBrand]] 不等于 generatorBrand,抛出 TypeError 异常。
  5. 返回 unused

27.6.3.4 AsyncGeneratorEnqueue ( generator, completion, promiseCapability )

抽象操作 AsyncGeneratorEnqueue 接收参数 generator(一个 AsyncGenerator)、completion(一个 Completion Record)和 promiseCapability(一个 PromiseCapability 记录),返回 unused。调用时执行以下步骤:

  1. requestAsyncGeneratorRequest { [[Completion]]: completion, [[Capability]]: promiseCapability }。
  2. request 添加到 generator.[[AsyncGeneratorQueue]] 末尾。
  3. 返回 unused

27.6.3.5 AsyncGeneratorCompleteStep ( generator, completion, done [ , realm ] )

抽象操作 AsyncGeneratorCompleteStep 接收参数 generator(一个 AsyncGenerator)、completion(一个 Completion Record)、done(一个布尔值),以及可选参数 realm(一个 Realm Record),返回 unused。调用时执行以下步骤:

  1. 断言generator.[[AsyncGeneratorQueue]] 不为空。
  2. nextgenerator.[[AsyncGeneratorQueue]] 的第一个元素。
  3. generator.[[AsyncGeneratorQueue]] 中移除第一个元素。
  4. promiseCapabilitynext.[[Capability]]
  5. valuecompletion.[[Value]]
  6. 如果 completionthrow 完成,则
    1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « value »)。
  7. 否则,
    1. 断言completion正常完成
    2. 如果 realm 存在,则
      1. oldRealm当前执行上下文Realm
      2. 设置 当前执行上下文Realmrealm
      3. iteratorResultCreateIteratorResultObject(value, done)。
      4. 设置 当前执行上下文RealmoldRealm
    3. 否则,
      1. iteratorResultCreateIteratorResultObject(value, done)。
    4. 执行 ! Call(promiseCapability.[[Resolve]], undefined, « iteratorResult »)。
  8. 返回 unused

27.6.3.6 AsyncGeneratorResume ( generator, completion )

抽象操作 AsyncGeneratorResume 接收参数 generator(一个 AsyncGenerator)和 completion(一个 Completion Record),返回 unused。调用时执行以下步骤:

  1. 断言generator.[[AsyncGeneratorState]]suspended-startsuspended-yield
  2. genContextgenerator.[[AsyncGeneratorContext]]
  3. callerContext当前执行上下文
  4. 挂起 callerContext
  5. 设置 generator.[[AsyncGeneratorState]]executing
  6. genContext 压入 执行上下文栈genContext 现在为 当前执行上下文
  7. 恢复 genContext 的挂起执行,以 completion 作为挂起操作的结果。令 result 为恢复运算返回的 Completion Record
  8. 断言result 绝不会是 异常完成
  9. 断言: 执行到这里时,genContext 已从 执行上下文栈 移除,callerContext 是当前 执行上下文
  10. 返回 unused

27.6.3.7 AsyncGeneratorUnwrapYieldResumption ( resumptionValue )

抽象操作 AsyncGeneratorUnwrapYieldResumption 接收参数 resumptionValue(一个 Completion Record),返回 正常完成包含ECMAScript 语言值异常完成。调用时执行以下步骤:

  1. 如果 resumptionValue 不是 return 完成,返回 ? resumptionValue
  2. awaitedCompletion(Await(resumptionValue.[[Value]]))。
  3. 如果 awaitedthrow 完成,返回 ? awaited
  4. 断言awaited正常完成
  5. 返回 ReturnCompletion(awaited.[[Value]])。

27.6.3.8 AsyncGeneratorYield ( value )

抽象操作 AsyncGeneratorYield 接收参数 value(一个 ECMAScript 语言值),返回 正常完成包含ECMAScript 语言值异常完成。调用时执行以下步骤:

  1. genContext当前执行上下文
  2. 断言genContext 是 generator 的 执行上下文
  3. generatorgenContext 的 Generator 组件的值。
  4. 断言GetGeneratorKind() 为 async
  5. completionNormalCompletion(value)。
  6. 断言执行上下文栈 至少有两个元素。
  7. previousContext执行上下文栈 的倒数第二个元素。
  8. previousRealmpreviousContextRealm
  9. 执行 AsyncGeneratorCompleteStep(generator, completion, false, previousRealm)。
  10. queuegenerator.[[AsyncGeneratorQueue]]
  11. 如果 queue 不为空,则
    1. 注:执行继续,不会挂起 generator。
    2. toYieldqueue 的第一个元素。
    3. resumptionValueCompletion(toYield.[[Completion]])。
    4. 返回 ? AsyncGeneratorUnwrapYieldResumption(resumptionValue)。
  12. 否则,
    1. 设置 generator.[[AsyncGeneratorState]]suspended-yield
    2. 执行上下文栈 移除 genContext,并恢复 执行上下文,该上下文现在位于 执行上下文栈 顶部,作为 当前执行上下文
    3. callerContext当前执行上下文
    4. 恢复 callerContext,传递 undefined。如果 genContext 以后再次被恢复,令 resumptionValue 为恢复时携带的 Completion Record
    5. 断言:如果执行到这里,genContext 又成为 当前执行上下文
    6. 返回 ? AsyncGeneratorUnwrapYieldResumption(resumptionValue)。

27.6.3.9 AsyncGeneratorAwaitReturn ( generator )

抽象操作 AsyncGeneratorAwaitReturn 接收参数 generator(一个 AsyncGenerator),返回 unused。调用时执行以下步骤:

  1. 断言generator.[[AsyncGeneratorState]]draining-queue
  2. queuegenerator.[[AsyncGeneratorQueue]]
  3. 断言queue 不为空。
  4. nextqueue 的第一个元素。
  5. completionCompletion(next.[[Completion]])。
  6. 断言completionreturn 完成
  7. promiseCompletionCompletion(PromiseResolve(%Promise%, completion.[[Value]]))。
  8. 如果 promiseCompletion异常完成,则
    1. 执行 AsyncGeneratorCompleteStep(generator, promiseCompletion, true)。
    2. 执行 AsyncGeneratorDrainQueue(generator)。
    3. 返回 unused
  9. 断言promiseCompletion正常完成
  10. promisepromiseCompletion.[[Value]]
  11. fulfilledClosure 为一个新的 抽象闭包,参数为 (value),捕获 generator,调用时执行以下步骤:
    1. 断言generator.[[AsyncGeneratorState]]draining-queue
    2. resultNormalCompletion(value)。
    3. 执行 AsyncGeneratorCompleteStep(generator, result, true)。
    4. 执行 AsyncGeneratorDrainQueue(generator)。
    5. 返回 undefined
  12. onFulfilledCreateBuiltinFunction(fulfilledClosure, 1, "", « »)。
  13. rejectedClosure 为一个新的 抽象闭包,参数为 (reason),捕获 generator,调用时执行以下步骤:
    1. 断言generator.[[AsyncGeneratorState]]draining-queue
    2. resultThrowCompletion(reason)。
    3. 执行 AsyncGeneratorCompleteStep(generator, result, true)。
    4. 执行 AsyncGeneratorDrainQueue(generator)。
    5. 返回 undefined
  14. onRejectedCreateBuiltinFunction(rejectedClosure, 1, "", « »)。
  15. 执行 PerformPromiseThen(promise, onFulfilled, onRejected)。
  16. 返回 unused

27.6.3.10 AsyncGeneratorDrainQueue ( generator )

抽象操作 AsyncGeneratorDrainQueue 接收参数 generator(一个 AsyncGenerator),返回 unused。它会持续清空 generator 的 AsyncGeneratorQueue,直到遇到一个持有 AsyncGeneratorRequest,并包含 return 完成 的请求。调用时执行以下步骤:

  1. 断言generator.[[AsyncGeneratorState]]draining-queue
  2. queuegenerator.[[AsyncGeneratorQueue]]
  3. 重复,条件是 queue 不为空,
    1. nextqueue 的第一个元素。
    2. completionCompletion(next.[[Completion]])。
    3. 如果 completionreturn 完成,则
      1. 执行 AsyncGeneratorAwaitReturn(generator)。
      2. 返回 unused
    4. 否则,
      1. 如果 completion正常完成,则
        1. completion 设为 NormalCompletion(undefined)。
      2. 执行 AsyncGeneratorCompleteStep(generator, completion, true)。
  4. 设置 generator.[[AsyncGeneratorState]]completed
  5. 返回 unused

27.6.3.11 CreateAsyncIteratorFromClosure ( closure, generatorBrand, generatorPrototype )

抽象操作 CreateAsyncIteratorFromClosure 接收参数 closure(一个无参数的 抽象闭包)、 generatorBrand(字符串或 empty)、generatorPrototype(一个对象),返回一个 AsyncGenerator。调用时执行以下步骤:

  1. 注:closure 可以包含 Await 操作和 Yield 操作用于 yield 一个 IteratorResult 对象
  2. internalSlotsList 为 « [[AsyncGeneratorState]], [[AsyncGeneratorContext]], [[AsyncGeneratorQueue]], [[GeneratorBrand]] »。
  3. generatorOrdinaryObjectCreate(generatorPrototype, internalSlotsList)。
  4. 设置 generator.[[GeneratorBrand]]generatorBrand
  5. 设置 generator.[[AsyncGeneratorState]]suspended-start
  6. callerContext当前执行上下文
  7. calleeContext 为一个新的 执行上下文
  8. 设置 calleeContext 的 Function 为 null
  9. 设置 calleeContextRealm当前 Realm Record
  10. 设置 calleeContext 的 ScriptOrModule 为 callerContext 的 ScriptOrModule。
  11. 如果 callerContext 尚未挂起,则挂起 callerContext
  12. calleeContext 压入 执行上下文栈calleeContext 现在为 当前执行上下文
  13. 执行 AsyncGeneratorStart(generator, closure)。
  14. 执行上下文栈 移除 calleeContext,并恢复 callerContext 作为 当前执行上下文
  15. 返回 generator

27.7 AsyncFunction 对象

AsyncFunction 通常是通过求值 AsyncFunctionDeclarationAsyncFunctionExpressionAsyncMethodAsyncArrowFunction 创建的函数。也可以通过调用 %AsyncFunction% 内部对象创建。

27.7.1 AsyncFunction 构造函数

AsyncFunction 构造函数

  • %AsyncFunction%
  • Function 的子类。
  • 被作为函数而不是 构造函数 调用时,会创建并初始化一个新的 AsyncFunction。因此,函数调用 AsyncFunction(…) 等价于用相同参数的对象创建表达式 new AsyncFunction(…)
  • 可以用作类定义的 extends 子句的值。意图继承指定 AsyncFunction 行为的子类 构造函数,必须通过 super 调用 AsyncFunction 构造函数 创建并初始化子类实例,并赋予其内置 async function 行为所需的内部槽。所有 ECMAScript 定义 async 函数对象 的语法形式,都会创建 AsyncFunction 的直接实例。没有语法手段可以创建 AsyncFunction 子类的实例。

27.7.1.1 AsyncFunction ( ...parameterArgs, bodyArg )

最后一个参数(如果有)指定异步函数的函数体(可执行代码);之前的所有参数指定形式参数。

该函数被调用时执行以下步骤:

  1. C当前函数对象
  2. 如果 bodyArg 未传入,则将 bodyArg 设为空字符串。
  3. 返回 ? CreateDynamicFunction(C, NewTarget, async, parameterArgs, bodyArg)。
参见 20.2.1.1 的注。

27.7.2 AsyncFunction 构造函数的属性

AsyncFunction 构造函数

  • 是一个标准内置 函数对象,继承自 Function 构造函数
  • 拥有 [[Prototype]] 内部槽,其值为 %Function%
  • 拥有 "length" 属性,其值为 1𝔽
  • 拥有 "name" 属性,其值为 "AsyncFunction"
  • 拥有以下属性:

27.7.2.1 AsyncFunction.prototype

AsyncFunction.prototype 的初始值为 AsyncFunction 原型对象

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

27.7.3 AsyncFunction 原型对象的属性

AsyncFunction 原型对象

27.7.3.1 AsyncFunction.prototype.constructor

AsyncFunction.prototype.constructor 的初始值为 %AsyncFunction%

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

27.7.3.2 AsyncFunction.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值为字符串 "AsyncFunction"

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

27.7.4 AsyncFunction 实例

每个 AsyncFunction 实例都是一个 ECMAScript 函数对象,并拥有 表 30 中列出的内部槽。所有此类实例的 [[IsClassConstructor]] 内部槽的值均为 false。AsyncFunction 实例不是 构造函数,没有 [[Construct]] 内部方法。AsyncFunction 实例没有 prototype 属性,因为它们不可构造。

每个 AsyncFunction 实例拥有以下自有属性:

27.7.4.1 length

Function 实例的 "length" 属性规范,见 20.2.4.1,同样适用于 AsyncFunction 实例。

27.7.4.2 name

Function 实例的 "name" 属性规范,见 20.2.4.2,同样适用于 AsyncFunction 实例。

27.7.5 异步函数的抽象操作

27.7.5.1 AsyncFunctionStart ( promiseCapability, asyncFunctionBody )

抽象操作 AsyncFunctionStart 接收参数 promiseCapability(一个 PromiseCapability 记录)和 asyncFunctionBody(一个 FunctionBody 解析节点ExpressionBody 解析节点 或无参数的 抽象闭包),返回 unused。调用时执行以下步骤:

  1. runningContext当前执行上下文
  2. asyncContextrunningContext 的一个副本。
  3. 注:复制执行状态是为了 AsyncBlockStart 能恢复其执行。如果恢复当前正在执行的上下文是未定义的行为。
  4. 执行 AsyncBlockStart(promiseCapability, asyncFunctionBody, asyncContext)。
  5. 返回 unused

27.7.5.2 AsyncBlockStart ( promiseCapability, asyncBody, asyncContext )

抽象操作 AsyncBlockStart 接收参数 promiseCapability(一个 PromiseCapability 记录), asyncBody(一个 解析节点 或无参数的 抽象闭包), asyncContext(一个 执行上下文),返回 unused。调用时执行以下步骤:

  1. runningContext当前执行上下文
  2. closure 为一个新的 抽象闭包,无参数,捕获 promiseCapabilityasyncBody,调用时执行以下步骤:
    1. acAsyncContext当前执行上下文
    2. 如果 asyncBody解析节点,则
      1. resultCompletion(Evaluation of asyncBody)。
    3. 否则,
      1. 断言asyncBody 是一个无参数的 抽象闭包
      2. resultCompletion(asyncBody())。
    4. 断言:如果执行到这里,async function 要么抛出了异常,要么进行了隐式或显式 return;所有 await 已完成。
    5. 执行上下文栈 移除 acAsyncContext,并恢复 执行上下文,该上下文现在位于 执行上下文栈 顶部,作为 当前执行上下文
    6. 如果 result正常完成,则
      1. 执行 ! Call(promiseCapability.[[Resolve]], undefined, « undefined »)。
    7. 否则如果 resultreturn 完成,则
      1. 执行 ! Call(promiseCapability.[[Resolve]], undefined, « result.[[Value]] »)。
    8. 否则,
      1. 断言resultthrow 完成
      2. 执行 ! Call(promiseCapability.[[Reject]], undefined, « result.[[Value]] »)。
    9. 返回 unused
  3. 设置 asyncContext 的代码求值状态,使得该 执行上下文 恢复时会调用 closure,且无参数。
  4. asyncContext 压入 执行上下文栈asyncContext 现在为 当前执行上下文
  5. 恢复 asyncContext 的挂起执行。令 result 为恢复运算返回的值。
  6. 断言: 执行到这里时,asyncContext 已从 执行上下文栈 移除,runningContext 是当前 执行上下文
  7. 断言result 是一个值为 unused正常完成。该值的来源可能为 Await,或者如果 async function 没有 await,则为上面 2.i 步。
  8. 返回 unused

27.7.5.3 Await ( value )

抽象操作 Await 接收参数 value(一个 ECMAScript 语言值),返回 正常完成包含ECMAScript 语言值empty,或 抛出完成。调用时执行以下步骤:

  1. asyncContext当前执行上下文
  2. promise 为 ? PromiseResolve(%Promise%, value)。
  3. fulfilledClosure 为一个新的 抽象闭包,参数为 (v),捕获 asyncContext,调用时执行以下步骤:
    1. prevContext当前执行上下文
    2. 挂起 prevContext
    3. asyncContext 压入 执行上下文栈asyncContext 现在为 当前执行上下文
    4. 恢复 asyncContext 的挂起执行,以 NormalCompletion(v) 作为挂起操作的结果。
    5. 断言:执行到这里时,asyncContext 已从 执行上下文栈 移除,prevContext 是当前 执行上下文
    6. 返回 undefined
  4. onFulfilledCreateBuiltinFunction(fulfilledClosure, 1, "", « »)。
  5. rejectedClosure 为一个新的 抽象闭包,参数为 (reason),捕获 asyncContext,调用时执行以下步骤:
    1. prevContext当前执行上下文
    2. 挂起 prevContext
    3. asyncContext 压入 执行上下文栈asyncContext 现在为 当前执行上下文
    4. 恢复 asyncContext 的挂起执行,以 ThrowCompletion(reason) 作为挂起操作的结果。
    5. 断言:执行到这里时,asyncContext 已从 执行上下文栈 移除,prevContext 是当前 执行上下文
    6. 返回 undefined
  6. onRejectedCreateBuiltinFunction(rejectedClosure, 1, "", « »)。
  7. 执行 PerformPromiseThen(promise, onFulfilled, onRejected)。
  8. asyncContext 中移除 执行上下文栈,并恢复 执行上下文,该上下文现在位于 执行上下文栈 顶部,作为 当前执行上下文
  9. callerContext当前执行上下文
  10. 恢复 callerContext,传递 empty。如果 asyncContext 以后再次被恢复,令 completion 为恢复时携带的 Completion Record
  11. 断言:如果执行到这里,asyncContext 又成为 当前执行上下文
  12. 返回 completion

28 反射

28.1 Reflect 对象

Reflect 对象:

  • %Reflect%
  • 全局对象"Reflect" 属性的初始值。
  • 是一个 普通对象
  • 有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%
  • 不是 函数对象
  • 没有 [[Construct]] 内部方法;不能作为 构造函数new 操作符一起使用。
  • 没有 [[Call]] 内部方法;不能作为函数调用。

28.1.1 Reflect.apply ( target, thisArgument, argumentsList )

该函数被调用时执行以下步骤:

  1. 如果 IsCallable(target) 为 false,抛出 TypeError 异常。
  2. args 为 ? CreateListFromArrayLike(argumentsList)。
  3. 执行 PrepareForTailCall()。
  4. 返回 ? Call(target, thisArgument, args)。

28.1.2 Reflect.construct ( target, argumentsList [ , newTarget ] )

该函数被调用时执行以下步骤:

  1. 如果 IsConstructor(target) 为 false,抛出 TypeError 异常。
  2. 如果 newTarget 未传入,则将 newTarget 设为 target
  3. 否则如果 IsConstructor(newTarget) 为 false,抛出 TypeError 异常。
  4. args 为 ? CreateListFromArrayLike(argumentsList)。
  5. 返回 ? Construct(target, args, newTarget)。

28.1.3 Reflect.defineProperty ( target, propertyKey, attributes )

该函数被调用时执行以下步骤:

  1. 如果 target 不是对象,抛出 TypeError 异常。
  2. key 为 ? ToPropertyKey(propertyKey)。
  3. desc 为 ? ToPropertyDescriptor(attributes)。
  4. 返回 ? target.[[DefineOwnProperty]](key, desc)。

28.1.4 Reflect.deleteProperty ( target, propertyKey )

该函数被调用时执行以下步骤:

  1. 如果 target 不是对象,抛出 TypeError 异常。
  2. key 为 ? ToPropertyKey(propertyKey)。
  3. 返回 ? target.[[Delete]](key)。

28.1.5 Reflect.get ( target, propertyKey [ , receiver ] )

该函数被调用时执行以下步骤:

  1. 如果 target 不是对象,抛出 TypeError 异常。
  2. key 为 ? ToPropertyKey(propertyKey)。
  3. 如果 receiver 未传入,则
    1. receiver 设为 target
  4. 返回 ? target.[[Get]](key, receiver)。

28.1.6 Reflect.getOwnPropertyDescriptor ( target, propertyKey )

该函数被调用时执行以下步骤:

  1. 如果 target 不是对象,抛出 TypeError 异常。
  2. key 为 ? ToPropertyKey(propertyKey)。
  3. desc 为 ? target.[[GetOwnProperty]](key)。
  4. 返回 FromPropertyDescriptor(desc)。

28.1.7 Reflect.getPrototypeOf ( target )

该函数被调用时执行以下步骤:

  1. 如果 target 不是对象,抛出 TypeError 异常。
  2. 返回 ? target.[[GetPrototypeOf]]()

28.1.8 Reflect.has ( target, propertyKey )

该函数被调用时执行以下步骤:

  1. 如果 target 不是对象,抛出 TypeError 异常。
  2. key 为 ? ToPropertyKey(propertyKey)。
  3. 返回 ? target.[[HasProperty]](key)。

28.1.9 Reflect.isExtensible ( target )

该函数被调用时执行以下步骤:

  1. 如果 target 不是对象,抛出 TypeError 异常。
  2. 返回 ? target.[[IsExtensible]]()

28.1.10 Reflect.ownKeys ( target )

该函数被调用时执行以下步骤:

  1. 如果 target 不是对象,抛出 TypeError 异常。
  2. keys 为 ? target.[[OwnPropertyKeys]]()
  3. 返回 CreateArrayFromList(keys)。

28.1.11 Reflect.preventExtensions ( target )

该函数被调用时执行以下步骤:

  1. 如果 target 不是对象,抛出 TypeError 异常。
  2. 返回 ? target.[[PreventExtensions]]()

28.1.12 Reflect.set ( target, propertyKey, V [ , receiver ] )

该函数被调用时执行以下步骤:

  1. 如果 target 不是对象,抛出 TypeError 异常。
  2. key 为 ? ToPropertyKey(propertyKey)。
  3. 如果 receiver 未传入,则
    1. receiver 设为 target
  4. 返回 ? target.[[Set]](key, V, receiver)。

28.1.13 Reflect.setPrototypeOf ( target, proto )

该函数被调用时执行以下步骤:

  1. 如果 target 不是对象,抛出 TypeError 异常。
  2. 如果 proto 不是对象proto 也不是 null,抛出 TypeError 异常。
  3. 返回 ? target.[[SetPrototypeOf]](proto)。

28.1.14 Reflect [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值为字符串 "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 为一个新的 抽象闭包,无参数,不捕获任何变量,调用时执行以下步骤:
    1. F当前函数对象
    2. pF.[[RevocableProxy]]
    3. 如果 pnull,返回 undefined
    4. 设置 F.[[RevocableProxy]]null
    5. 断言pProxy 异常对象
    6. 设置 p.[[ProxyTarget]]null
    7. 设置 p.[[ProxyHandler]]null
    8. 返回 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 模块命名空间对象

模块命名空间对象是一个 模块命名空间异常对象,用于基于属性的运行时访问某个模块的导出绑定。模块命名空间对象没有 构造函数。而是对每个由包含 ImportDeclaration、且带有 NameSpaceImport 的模块都会创建这样一个对象。

除了 10.4.6 中指定的属性外,每个模块命名空间对象还具有以下自有属性:

28.3.1 %Symbol.toStringTag%

%Symbol.toStringTag% 属性的初始值为字符串 "Module"

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

29 内存模型

内存一致性模型,或称内存模型,规定了通过访问由 SharedArrayBuffer 支持的 TypedArray 实例和对 Atomics 对象的方法,所引发的共享数据块事件的可能顺序。当程序没有数据竞争(定义见下文)时,事件的顺序表现为顺序一致性,即,每个 agent 的动作交错执行。当程序存在数据竞争时,共享内存操作可能表现为非顺序一致性。例如,程序可能表现出违反因果关系的行为和其它令人惊讶的现象。这些现象来源于编译器的变换和 CPU 的设计(例如乱序执行和推测执行)。内存模型定义了程序何时表现为顺序一致的精确条件,以及数据竞争下可能读取的值。也就是说,不存在未定义行为。

内存模型被定义为对由 抽象操作或 Atomics 对象上的方法在一次求值过程中引入的事件的关系约束。

本节为 SharedArrayBuffer 上 抽象操作引入的事件提供了公理化模型。需要强调的是,与本规范其余部分不同,该模型不能用算法表达。抽象操作 非确定性地引入事件,是 ECMAScript 求值操作语义和内存模型公理化语义之间的接口。这些事件的语义通过考虑一次求值中的所有事件图来定义。它们既不是静态语义,也不是运行时语义。没有可行的算法实现,而是通过一组约束来决定某个事件图是否被允许。

29.1 内存模型基础

共享内存的访问(读和写)分为两组,原子访问和数据访问,定义见下。原子访问是顺序一致的,即,在一个 agent 集群 中,所有 agent 都同意一个严格的全序。非原子访问在所有 agent 间没有严格的全序,即无序。

注 1

不支持比顺序一致更弱、比无序更强的顺序(如 release-acquire)。

共享数据块事件ReadSharedMemoryWriteSharedMemoryReadModifyWriteSharedMemory 记录之一。

表 96:ReadSharedMemory 事件字段
字段名 含义
[[Order]] seq-cstunordered 内存模型为该事件保证的最弱顺序。
[[NoTear]] 布尔值 该事件是否允许从与本事件范围相等的多个写事件中读取。
[[Block]] 一个 共享数据块 事件所操作的块。
[[ByteIndex]] 非负 整数 [[Block]] 中读操作的字节地址。
[[ElementSize]] 非负 整数 读操作的大小。
表 97:WriteSharedMemory 事件字段
字段名 含义
[[Order]] seq-cstunorderedinit 内存模型为该事件保证的最弱顺序。
[[NoTear]] 布尔值 该事件是否允许被与本事件范围相等的多个读事件读取。
[[Block]] 一个 共享数据块 事件所操作的块。
[[ByteIndex]] 非负 整数 [[Block]] 中写操作的字节地址。
[[ElementSize]] 非负 整数 写操作的大小。
[[Payload]] 一个 List,其元素为 字节值 其他事件将要读取的 List字节值
表 98:ReadModifyWriteSharedMemory 事件字段
字段名 含义
[[Order]] seq-cst 读-改-写事件总是顺序一致的。
[[NoTear]] true 读-改-写事件不允许撕裂。
[[Block]] 一个 共享数据块 事件所操作的块。
[[ByteIndex]] 非负 整数 [[Block]] 中读-改-写操作的字节地址。
[[ElementSize]] 非负 整数 读-改-写操作的大小。
[[Payload]] 一个 List,其元素为 字节值 将被传递给 [[ModifyOp]]List字节值
[[ModifyOp]] 一个 读-改-写修改函数 一个抽象闭包,接收读到的 List字节值[[Payload]],返回修改后的 List字节值

这些事件由 抽象操作 或 Atomics 对象上的方法引入。

某些操作还可能引入 Synchronize 事件。Synchronize 事件 没有字段,仅用于直接约束其它事件允许的顺序。

除了 共享数据块 和 Synchronize 事件外,还有 宿主特定的事件。

设 ReadSharedMemory、WriteSharedMemory 或 ReadModifyWriteSharedMemory 事件的范围为其 [[ByteIndex]][[ByteIndex]] + [[ElementSize]] - 1 的连续 整数集合。两个事件的范围相等当且仅当事件拥有相同的 [[Block]],且范围元素一一相等。两个事件的范围重叠当且仅当事件拥有相同的 [[Block]],且范围不等、交集非空。两个事件的范围不相交当且仅当事件没有相同的 [[Block]] 或范围既不等也不重叠。

注 2

应考虑的 宿主特定同步事件示例包括:将 SharedArrayBuffer 从一个 agent 发送到另一个(如浏览器中的 postMessage),启动和停止 agent,以及通过除共享内存外的通道在 agent 集群 内通信。对于某个具体执行 execution,这些事件由 宿主通过 host-synchronizes-with 严格偏序提供。此外,宿主可向 execution.[[EventList]] 添加 宿主特定同步事件,以参与 is-agent-order-before 关系

事件在 候选执行中由下文定义的关系排序。

29.2 Agent 事件记录

Agent 事件记录是一个带有以下字段的 记录

表 99:Agent 事件记录 字段
字段名 含义
[[AgentSignifier]] 一个 agent 标识 进行该排序的 agent
[[EventList]] 一个事件 List 事件在求值期间被添加到该列表。
[[AgentSynchronizesWith]] 一个 List,其元素为Synchronize 事件的对 操作语义引入的 Synchronize 关系。

29.3 选定值记录

选定值记录是一个带有以下字段的 记录

表 100:选定值记录 字段
字段名 含义
[[Event]] 一个 共享数据块事件 为该选定值引入的 ReadSharedMemoryReadModifyWriteSharedMemory 事件。
[[ChosenValue]] 一个 List,其元素为 字节值 在求值期间非确定性选定的字节。

29.4 候选执行

候选执行是对 agent 集群 求值的一个 记录,包含以下字段。

表 101:候选执行 记录 字段
字段名 含义
[[EventsRecords]] 一个 List,其元素为 Agent 事件记录 将一个 agent 映射到求值过程中追加的事件 List
[[ChosenValues]] 一个 List,其元素为 选定值记录 ReadSharedMemoryReadModifyWriteSharedMemory 事件映射到求值过程中选择的 字节值列表

空候选执行是字段皆为空 List 的候选执行 记录

29.5 内存模型的抽象操作

29.5.1 EventSet ( execution )

抽象操作 EventSet 接收参数 execution(一个 候选执行),返回事件集合。调用时执行以下步骤:

  1. events 为一个空集合。
  2. 对于 execution.[[EventsRecords]] 中的每个 Agent 事件记录 aer,执行
    1. 对于 aer.[[EventList]] 中的每个事件 E,执行
      1. E 添加到 events
  3. 返回 events

29.5.2 SharedDataBlockEventSet ( execution )

抽象操作 SharedDataBlockEventSet 接收参数 execution(一个 候选执行),返回事件集合。调用时执行以下步骤:

  1. events 为一个空集合。
  2. 对于 EventSet(execution) 中的每个事件 E,执行
    1. 如果 EReadSharedMemoryWriteSharedMemoryReadModifyWriteSharedMemory 事件,则将 E 添加到 events
  3. 返回 events

29.5.3 HostEventSet ( execution )

抽象操作 HostEventSet 接收参数 execution(一个 候选执行),返回事件集合。调用时执行以下步骤:

  1. events 为一个空集合。
  2. 对于 EventSet(execution) 中的每个事件 E,执行
    1. 如果 E 不在 SharedDataBlockEventSet(execution) 中,则将 E 添加到 events
  3. 返回 events

29.5.4 ComposeWriteEventBytes ( execution, byteIndex, Ws )

抽象操作 ComposeWriteEventBytes 接收参数 execution(一个 候选执行)、byteIndex(非负 整数)、WsList,元素为 WriteSharedMemoryReadModifyWriteSharedMemory 事件),返回 字节值列表。调用时执行以下步骤:

  1. byteLocationbyteIndex
  2. bytesRead 为一个新的空 List
  3. 对于 Ws 中的每个元素 W,执行
    1. 断言W 的范围包含 byteLocation
    2. payloadIndexbyteLocation - W.[[ByteIndex]]
    3. 如果 WWriteSharedMemory 事件,则
      1. byteW.[[Payload]][payloadIndex]。
    4. 否则,
      1. 断言WReadModifyWriteSharedMemory 事件。
      2. bytesValueOfReadEvent(execution, W)。
      3. bytesModifiedW.[[ModifyOp]](bytes, W.[[Payload]])。
      4. bytebytesModified[payloadIndex]。
    5. byte 添加到 bytesRead
    6. byteLocation 设为 byteLocation + 1。
  4. 返回 bytesRead
注 1

读-改-写的修改 [[ModifyOp]] 由 Atomics 对象上的相应函数属性决定,这些属性会引入 ReadModifyWriteSharedMemory 事件。

注 2

该抽象操作将若干写事件合成为一个 字节值列表。它用于 ReadSharedMemoryReadModifyWriteSharedMemory 事件的事件语义中。

29.5.5 ValueOfReadEvent ( execution, R )

抽象操作 ValueOfReadEvent 接收参数 execution(一个 候选执行)和 R(一个 ReadSharedMemoryReadModifyWriteSharedMemory 事件),返回 字节值列表。调用时执行以下步骤:

  1. Wsreads-bytes-from(R) in execution
  2. 断言Ws 是一个长度等于 R.[[ElementSize]]WriteSharedMemoryReadModifyWriteSharedMemory 事件的 List
  3. 返回 ComposeWriteEventBytes(execution, R.[[ByteIndex]], Ws)。

29.6 候选执行的关系

以下关系和数学函数以某个 候选执行 为参数,对其事件进行排序。

29.6.1 is-agent-order-before

对于一个 候选执行 execution,其 is-agent-order-before 关系 是满足以下条件的事件上的 最小关系

  • 对于事件 ED,如果存在 Agent 事件记录 aerexecution.[[EventsRecords]] 中,使得 aer.[[EventList]] 同时包含 EDEaer.[[EventList]]List 顺序中位于 D 前,则 E is-agent-order-before D

每个 agent 在求值期间均以每-agent 严格全序 引入事件。这里是这些 严格全序 的并集。

29.6.2 reads-bytes-from

对于一个 候选执行 execution,其 reads-bytes-from 函数是将 SharedDataBlockEventSet(execution) 中的事件映射为 List,其元素为 SharedDataBlockEventSet(execution) 中的事件的数学函数,满足以下条件。

每个 候选执行 总是存在 reads-bytes-from 函数。

29.6.3 reads-from

对于一个 候选执行 execution,其 reads-from 关系 是满足以下条件的事件上的 最小关系

29.6.4 host-synchronizes-with

对于一个 候选执行 execution,其 host-synchronizes-with 关系宿主提供的、满足以下条件的 严格偏序,其作用于 宿主特定事件。

  • E host-synchronizes-with D in execution,则 HostEventSet(execution) 包含 ED
  • host-synchronizes-with 和 is-agent-order-beforeexecution 的并集不含有环。
注 1

对于 宿主特定事件 ED,若 E host-synchronizes-with D,则 E happens-before D 也成立。

注 2

关系 允许 宿主 提供额外的同步机制,比如 HTML worker 之间的 postMessage

29.6.5 synchronizes-with

对于一个 候选执行 execution,其 synchronizes-with 关系 是满足以下条件的事件上的 最小关系

  • 对于事件 RW,如果 R reads-from W,且 R.[[Order]]seq-cstW.[[Order]] 也为 seq-cst,且 RW 范围相等,则 W synchronizes-with R
  • 对于 execution.[[EventsRecords]] 中的每个 eventsRecord,有:
    • eventsRecord.[[AgentSynchronizesWith]] 包含 (S, Sw),则 S synchronizes-with Sw
  • execution.[[HostSynchronizesWith]] 包含 (E, D),则 E synchronizes-with D
注 1

根据内存模型文献的惯例,在 候选执行 execution 中,是写事件 synchronizes-with 读事件,而不是读 synchronizes-with 写。

注 2

候选执行 execution 中,init 事件不参与此 关系,而是直接被 happens-before 约束。

注 3

候选执行 execution 中,并非所有通过 reads-from 关联的 seq-cst 事件都通过 synchronizes-with 关联。只有范围相等的事件才会通过 synchronizes-with 关联。

注 4

对于 共享数据块事件 RW,若 W synchronizes-with R,则 R 可能 reads-from 其他写事件。

29.6.6 happens-before

对于一个 候选执行 execution,其 happens-before 关系 是满足以下条件的事件上的 最小关系

  • 对于事件 ED,如果以下任一条件成立,则 E happens-before D

由于 happens-before 是 agent-order 的超集,候选执行 与 ECMAScript 的单线程求值语义是一致的。

29.7 有效执行的属性

29.7.1 有效选定读取

候选执行 execution 具有有效选定读取,当且仅当下列算法返回 true

  1. 对于 ReadSharedMemoryReadModifyWriteSharedMemory 事件 R,属于 SharedDataBlockEventSet(execution),执行
    1. chosenValueRecordexecution.[[ChosenValues]][[Event]] 字段为 R 的元素。
    2. chosenValuechosenValueRecord.[[ChosenValue]]
    3. readValueValueOfReadEvent(execution, R)。
    4. chosenLenchosenValue 的元素个数。
    5. readLenreadValue 的元素个数。
    6. 如果 chosenLenreadLen,则
      1. 返回 false
    7. 如果存在某个 整数 i,在 区间 [0, chosenLen) 内,使得 chosenValue[i] ≠ readValue[i],则
      1. 返回 false
  2. 返回 true

29.7.2 一致性读取

候选执行 execution 具有一致性读取,当且仅当下列算法返回 true

  1. 对于 ReadSharedMemoryReadModifyWriteSharedMemory 事件 R,属于 SharedDataBlockEventSet(execution),执行
    1. Wsreads-bytes-from(R) in execution
    2. byteLocationR.[[ByteIndex]]
    3. 对于 Ws 中的每个事件 W,执行
      1. 如果 R happens-before W,则
        1. 返回 false
      2. 如果存在 WriteSharedMemoryReadModifyWriteSharedMemory 事件 V,其范围含有 byteLocation,且 W happens-before V,且 V happens-before R,则
        1. 返回 false
      3. byteLocation 设为 byteLocation + 1。
  2. 返回 true

29.7.3 无撕裂读取

候选执行 execution 具有无撕裂读取,当且仅当下列算法返回 true

  1. 对于 ReadSharedMemoryReadModifyWriteSharedMemory 事件 R,属于 SharedDataBlockEventSet(execution),执行
    1. 如果 R.[[NoTear]]true,则
      1. 断言R.[[ByteIndex]] 除以 R.[[ElementSize]] 的余数为 0。
      2. 对于每个事件 W,满足 R reads-from WW.[[NoTear]]true,执行
        1. 如果 RW 范围相等,且存在事件 V,使得 VW 范围相等,V.[[NoTear]]trueWV 不是同一个 共享数据块事件,且 R reads-from V,则
          1. 返回 false
  2. 返回 true

当事件通过访问 整数 TypedArray 引入时,其 [[NoTear]] 字段为 true;若通过访问浮点 TypedArray 或 DataView 引入,则为 false

直观上,这一要求意味着当通过 整数 TypedArray 以对齐方式访问某内存范围时,在与其他范围相等的写事件发生 数据竞争 时,只有一个写事件可以“胜出”。更精确地说,对齐的读事件不能读取由多个、不同但范围相等的写事件拼凑出来的值。但对齐的读事件可以读取来自多个范围重叠写事件的字节。

29.7.4 顺序一致原子

对于 候选执行 executionis-memory-order-before严格全序,作用于 EventSet(execution) 的所有事件,并满足以下条件。

候选执行 拥有顺序一致原子性,当且仅当它存在 is-memory-order-before 关系

注 3

虽然 is-memory-order-before 覆盖 EventSet(execution) 中所有事件,但那些未被 happens-beforesynchronizes-with 约束的事件可以在该序列中的任意位置出现。

29.7.5 有效执行

候选执行 execution 是有效执行(或简称执行),当且仅当以下条件均为真:

所有程序至少有一个有效执行。

29.8 竞争

对于执行 execution 以及其中 SharedDataBlockEventSet(execution) 的事件 ED,如果下列算法返回 true,则称 ED 处于竞争关系。

  1. 如果 ED 不是同一个 共享数据块事件,则
    1. 如果不存在 E happens-before DD happens-before E,则
      1. 如果 ED 都是 WriteSharedMemoryReadModifyWriteSharedMemory 事件,且 ED 的范围不互不相交,则
        1. 返回 true
      2. 如果 E reads-from DD reads-from E,则
        1. 返回 true
  2. 返回 false

29.9 数据竞争

对于执行 execution 以及其中 SharedDataBlockEventSet(execution) 的事件 ED,如果下列算法返回 true,则称 ED 处于数据竞争关系。

  1. 如果 ED竞争中,则
    1. 如果 E.[[Order]] 不是 seq-cstD.[[Order]] 不是 seq-cst,则
      1. 返回 true
    2. 如果 ED 的范围重叠,则
      1. 返回 true
  2. 返回 false

29.10 数据竞争自由

SharedDataBlockEventSet(execution) 中不存在两个事件处于 数据竞争,则执行 execution数据竞争自由的。

若程序的所有执行均为数据竞争自由,则称该程序为数据竞争自由程序。

内存模型保证数据竞争自由程序的所有事件顺序一致。

29.11 共享内存指南

注 1

以下是 ECMAScript 程序员使用共享内存的指南。

我们建议程序保持 数据竞争自由,即确保不会在同一内存位置上发生并发的非原子操作。数据竞争自由的程序具有交错语义,即每个 agent 求值语义中的每一步都与其他 agent 交错。对于 数据竞争自由的程序,不必理解 内存模型 的细节。这些细节不太可能帮助更好地编写 ECMAScript。

更一般地说,即使程序不是数据竞争自由,只要原子操作未参与任何数据竞争,且竞争的所有操作访问大小相同,程序也可能表现为可预测。安排原子操作不参与竞争的最简单方法是确保原子操作和非原子操作使用不同的内存单元,并且不同大小的原子访问不同时访问同一单元。实际上,程序应尽可能将共享内存视为强类型内存。尽管如此,依赖于竞争的非原子访问的顺序和时序仍不可取,但如果内存被视为强类型,则竞争访问不会“撕裂”(值的各比特不会混合)。

注 2

以下是 ECMAScript 实现者为使用共享内存的程序编写编译器转换的指南。

建议在多 agent 环境中允许大多数在单 agent 环境下有效的程序转换,以保证多 agent 程序中每个 agent 的性能与单 agent 程序一样好。通常这些转换难以判断。这里概述了一些关于程序转换的规则,这些规则旨在具有规范性(即被 内存模型隐含,或者比内存模型更强),但可能并不详尽。这些规则旨在适用于在引入 is-agent-order-before 关系 的事件之前的程序转换。

agent-order 片段is-agent-order-before 关系中属于同一个 agent 的子集。

设一次读事件的可能读取值为该事件在所有有效执行中 ValueOfReadEvent 的所有值的集合。

任何在无共享内存时有效的 agent-order 片段转换,在有共享内存时也是有效的,但有如下例外:

  • 原子操作不可变:程序转换不得导致 agent-order 片段内 seq-cst 事件与其 unordered 操作重排序,也不得使 seq-cst 操作彼此重排序,亦不得将 seq-cst 操作从 is-agent-order-before 关系中移除。

    (实际上,对重排序的禁止要求编译器假定每个 seq-cst 操作是一个同步,并会包含在最终 is-memory-order-before 关系 中,这在无跨 agent 程序分析时本来也应假定。同时也要求编译器假定所有调用其内存序未知的函数都可能包含 seq-cst 操作。)

  • 读取必须稳定:每个共享内存读取在一次执行中只能观察到一个值。

    (例如,若程序语义上某次读取被多次执行,则程序只能观察到这些读取值中的一个。rematerialization 转换可能违反此规则。)

  • 写入必须稳定:所有可观察到的共享内存写入都必须由程序语义产生。

    (例如,转换不能引入某些可观察写,如对更大位置的读-改-写操作来写入较小数据,写入程序本不可写的值,或对刚读取的位置写回刚读取的值,如果该位置在读取后可能被其他 agent 覆盖。)

  • 可能读取值非空:程序转换不能导致共享内存读取的可能读取值集合为空。

    (反直觉地,本规则实际上限制了写入的变换,因为写入只有被读取事件读取时才有意义。例如,写入可以移动、合并,有时可在两个 seq-cst 操作间重排序,但不能删除所有更新某位置的写入;必须保留至少一个写。)

以下转换仍然有效:合并同一位置的多个非原子读取、重排序非原子读取、引入推测性非原子读取、合并同一位置的多个非原子写、重排序对不同位置的非原子写、将非原子读取抽出循环(即使影响终止)。注意,别名 TypedArrays 一般使证明位置不同变得困难。

注 3

以下是 ECMAScript 实现者为共享内存访问生成机器码的指南。

对于内存模型不弱于 ARM 或 Power 的体系结构,非原子存储和加载可直接编译为目标架构上的存储和加载指令。原子存储和加载可编译为保证顺序一致性的指令。如果没有这样的指令,则应使用内存屏障,例如在存储或加载两侧加屏障。读-改-写操作可编译为目标架构上的原子读-改-写指令,如 x86 的 LOCK 前缀指令、ARM 的 load-exclusive/store-exclusive、Power 的 load-link/store-conditional。

具体而言,内存模型旨在允许如下代码生成:

  • 假定程序中的每个原子操作都是必要的。
  • 原子操作之间及与非原子操作之间绝不重排。
  • 假定函数总是执行原子操作。
  • 原子操作永远不会实现为更大数据的读-改-写,只能用非 lock-free 的原子操作(如果平台不支持相应大小的原子操作)。(假定每个平台都支持每种有意义大小的正常内存访问操作。)

朴素的代码生成模式如下:

  • 常规加载和存储编译为单条加载或存储指令。
  • lock-free 原子加载与存储编译为完整(顺序一致性)屏障、常规加载或存储、再加完整屏障。
  • lock-free 原子读-改-写编译为完整屏障、原子读-改-写指令序列、再加完整屏障。
  • 非 lock-free 原子操作编译为自旋锁获取、完整屏障、一系列非原子加载和存储指令、完整屏障、自旋锁释放。

只要某地址范围上的原子操作不与非原子写或不同尺寸的原子操作竞争,上述映射就是正确的。这已足够:内存模型等同于将参与竞争的原子操作降级为非原子。另一方面,朴素映射很强:允许原子操作用作顺序一致性屏障,但内存模型并不保证这一点。

在遵守内存模型约束的前提下,也允许对这些基本模式进行本地优化。例如:

  • 平台相关的明显改进可去除冗余屏障。例如,在 x86 上,lock-free 原子加载和存储两边的屏障可省略,除了存储后的屏障;lock-free 原子读-改-写指令无需屏障,因为它们都用 LOCK 前缀。在许多平台,存在多种强度的屏障,在某些情况下可用弱屏障而不破坏顺序一致性。
  • 大多数现代平台支持 ECMAScript 所需全部数据尺寸的 lock-free 原子。若需非 lock-free 原子,原子操作体前后的屏障通常可合并到锁和解锁步骤。最简单方案是每个 SharedArrayBuffer 一个锁字。
  • 还可有更复杂的本地优化,需要一些代码分析。例如,两个连续的屏障通常等价于单个屏障,因此两次原子操作生成的代码只需一个屏障隔开。在 x86 上,甚至可以省略原子存储后的屏障,因为该屏障只需用于分隔存储和后续加载。

附录 A (资料性附录) 语法摘要

A.1 词法语法

SourceCharacter :: any Unicode code point InputElementDiv :: WhiteSpace LineTerminator Comment CommonToken DivPunctuator RightBracePunctuator InputElementRegExp :: WhiteSpace LineTerminator Comment CommonToken RightBracePunctuator RegularExpressionLiteral InputElementRegExpOrTemplateTail :: WhiteSpace LineTerminator Comment CommonToken RegularExpressionLiteral TemplateSubstitutionTail InputElementTemplateTail :: WhiteSpace LineTerminator Comment CommonToken DivPunctuator TemplateSubstitutionTail InputElementHashbangOrRegExp :: WhiteSpace LineTerminator Comment CommonToken HashbangComment RegularExpressionLiteral WhiteSpace :: <TAB> <VT> <FF> <ZWNBSP> <USP> LineTerminator :: <LF> <CR> <LS> <PS> LineTerminatorSequence :: <LF> <CR> [lookahead ≠ <LF>] <LS> <PS> <CR> <LF> Comment :: MultiLineComment SingleLineComment MultiLineComment :: /* MultiLineCommentCharsopt */ MultiLineCommentChars :: MultiLineNotAsteriskChar MultiLineCommentCharsopt * PostAsteriskCommentCharsopt PostAsteriskCommentChars :: MultiLineNotForwardSlashOrAsteriskChar MultiLineCommentCharsopt * PostAsteriskCommentCharsopt MultiLineNotAsteriskChar :: SourceCharacter but not * MultiLineNotForwardSlashOrAsteriskChar :: SourceCharacter but not one of / or * SingleLineComment :: // SingleLineCommentCharsopt SingleLineCommentChars :: SingleLineCommentChar SingleLineCommentCharsopt SingleLineCommentChar :: SourceCharacter but not LineTerminator HashbangComment :: #! SingleLineCommentCharsopt CommonToken :: IdentifierName PrivateIdentifier Punctuator NumericLiteral StringLiteral Template PrivateIdentifier :: # IdentifierName IdentifierName :: IdentifierStart IdentifierName IdentifierPart IdentifierStart :: IdentifierStartChar \ UnicodeEscapeSequence IdentifierPart :: IdentifierPartChar \ UnicodeEscapeSequence IdentifierStartChar :: UnicodeIDStart $ _ IdentifierPartChar :: UnicodeIDContinue $ AsciiLetter :: one of a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z UnicodeIDStart :: any Unicode code point with the Unicode property “ID_Start” UnicodeIDContinue :: any Unicode code point with the Unicode property “ID_Continue” ReservedWord :: one of await break case catch class const continue debugger default delete do else enum export extends false finally for function if import in instanceof new null return super switch this throw true try typeof var void while with yield Punctuator :: OptionalChainingPunctuator OtherPunctuator OptionalChainingPunctuator :: ?. [lookahead ∉ DecimalDigit] OtherPunctuator :: one of { ( ) [ ] . ... ; , < > <= >= == != === !== + - * % ** ++ -- << >> >>> & | ^ ! ~ && || ?? ? : = += -= *= %= **= <<= >>= >>>= &= |= ^= &&= ||= ??= => DivPunctuator :: / /= RightBracePunctuator :: } NullLiteral :: null BooleanLiteral :: true false NumericLiteralSeparator :: _ NumericLiteral :: DecimalLiteral DecimalBigIntegerLiteral NonDecimalIntegerLiteral[+Sep] NonDecimalIntegerLiteral[+Sep] BigIntLiteralSuffix LegacyOctalIntegerLiteral DecimalBigIntegerLiteral :: 0 BigIntLiteralSuffix NonZeroDigit DecimalDigits[+Sep]opt BigIntLiteralSuffix NonZeroDigit NumericLiteralSeparator DecimalDigits[+Sep] BigIntLiteralSuffix NonDecimalIntegerLiteral[Sep] :: BinaryIntegerLiteral[?Sep] OctalIntegerLiteral[?Sep] HexIntegerLiteral[?Sep] BigIntLiteralSuffix :: n DecimalLiteral :: DecimalIntegerLiteral . DecimalDigits[+Sep]opt ExponentPart[+Sep]opt . DecimalDigits[+Sep] ExponentPart[+Sep]opt DecimalIntegerLiteral ExponentPart[+Sep]opt DecimalIntegerLiteral :: 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] AwaitExpression[?Yield] 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] ; LetOrConst : let const BindingList[In, Yield, Await] : LexicalBinding[?In, ?Yield, ?Await] BindingList[?In, ?Yield, ?Await] , LexicalBinding[?In, ?Yield, ?Await] LexicalBinding[In, Yield, Await] : BindingIdentifier[?Yield, ?Await] Initializer[?In, ?Yield, ?Await]opt BindingPattern[?Yield, ?Await] Initializer[?In, ?Yield, ?Await] 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] in Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] for ( ForDeclaration[?Yield, ?Await] 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] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] for ( ForDeclaration[?Yield, ?Await] 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] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] [+Await] for await ( ForDeclaration[?Yield, ?Await] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] ForDeclaration[Yield, Await] : LetOrConst ForBinding[?Yield, ?Await] ForBinding[Yield, Await] : BindingIdentifier[?Yield, ?Await] 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] [此处不能有 LineTerminator ] => 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 Scripts and Modules

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 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 数值转换

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 HexTrailSurrogateu HexLeadSurrogate

 

HexLeadSurrogate :: Hex4Digits but only if the MV of Hex4Digits is in the inclusive interval from 0xD800 to 0xDBFF HexTrailSurrogate :: Hex4Digits but only if the MV of Hex4Digits is in the inclusive interval from 0xDC00 to 0xDFFF HexNonSurrogate :: Hex4Digits but only if the MV of Hex4Digits is not in the inclusive interval from 0xD800 to 0xDFFF IdentityEscape[UnicodeMode] :: [+UnicodeMode] SyntaxCharacter [+UnicodeMode] / [~UnicodeMode] SourceCharacter but not UnicodeIDContinue DecimalEscape :: NonZeroDigit DecimalDigits[~Sep]opt [lookahead ∉ DecimalDigit] CharacterClassEscape[UnicodeMode] :: d D s S w W [+UnicodeMode] p{ UnicodePropertyValueExpression } [+UnicodeMode] P{ UnicodePropertyValueExpression } UnicodePropertyValueExpression :: UnicodePropertyName = UnicodePropertyValue LoneUnicodePropertyNameOrValue UnicodePropertyName :: UnicodePropertyNameCharacters UnicodePropertyNameCharacters :: UnicodePropertyNameCharacter UnicodePropertyNameCharactersopt UnicodePropertyValue :: UnicodePropertyValueCharacters LoneUnicodePropertyNameOrValue :: UnicodePropertyValueCharacters UnicodePropertyValueCharacters :: UnicodePropertyValueCharacter UnicodePropertyValueCharactersopt UnicodePropertyValueCharacter :: UnicodePropertyNameCharacter DecimalDigit UnicodePropertyNameCharacter :: AsciiLetter _ CharacterClass[UnicodeMode, UnicodeSetsMode] :: [ [lookahead ≠ ^] ClassContents[?UnicodeMode, ?UnicodeSetsMode] ] [^ ClassContents[?UnicodeMode, ?UnicodeSetsMode] ] ClassContents[UnicodeMode, UnicodeSetsMode] :: [empty] [~UnicodeSetsMode] NonemptyClassRanges[?UnicodeMode] [+UnicodeSetsMode] ClassSetExpression NonemptyClassRanges[UnicodeMode] :: ClassAtom[?UnicodeMode] ClassAtom[?UnicodeMode] NonemptyClassRangesNoDash[?UnicodeMode] ClassAtom[?UnicodeMode] - ClassAtom[?UnicodeMode] ClassContents[?UnicodeMode, ~UnicodeSetsMode] NonemptyClassRangesNoDash[UnicodeMode] :: ClassAtom[?UnicodeMode] ClassAtomNoDash[?UnicodeMode] NonemptyClassRangesNoDash[?UnicodeMode] ClassAtomNoDash[?UnicodeMode] - ClassAtom[?UnicodeMode] ClassContents[?UnicodeMode, ~UnicodeSetsMode] ClassAtom[UnicodeMode] :: - ClassAtomNoDash[?UnicodeMode] ClassAtomNoDash[UnicodeMode] :: SourceCharacter but not one of \ or ] or - \ ClassEscape[?UnicodeMode] ClassEscape[UnicodeMode] :: b [+UnicodeMode] - CharacterClassEscape[?UnicodeMode] CharacterEscape[?UnicodeMode] ClassSetExpression :: ClassUnion ClassIntersection ClassSubtraction ClassUnion :: ClassSetRange ClassUnionopt ClassSetOperand ClassUnionopt ClassIntersection :: ClassSetOperand && [lookahead ≠ &] ClassSetOperand ClassIntersection && [lookahead ≠ &] ClassSetOperand ClassSubtraction :: ClassSetOperand -- ClassSetOperand ClassSubtraction -- ClassSetOperand ClassSetRange :: ClassSetCharacter - ClassSetCharacter ClassSetOperand :: NestedClass ClassStringDisjunction ClassSetCharacter NestedClass :: [ [lookahead ≠ ^] ClassContents[+UnicodeMode, +UnicodeSetsMode] ] [^ ClassContents[+UnicodeMode, +UnicodeSetsMode] ] \ CharacterClassEscape[+UnicodeMode] ClassStringDisjunction :: \q{ ClassStringDisjunctionContents } ClassStringDisjunctionContents :: ClassString ClassString | ClassStringDisjunctionContents ClassString :: [empty] NonEmptyClassString NonEmptyClassString :: ClassSetCharacter NonEmptyClassStringopt ClassSetCharacter :: [lookahead ∉ ClassSetReservedDoublePunctuator] SourceCharacter but not ClassSetSyntaxCharacter \ CharacterEscape[+UnicodeMode] \ ClassSetReservedPunctuator \b ClassSetReservedDoublePunctuator :: one of && !! ## $$ %% ** ++ ,, .. :: ;; << == >> ?? @@ ^^ `` ~~ ClassSetSyntaxCharacter :: one of ( ) [ ] { } / - \ | ClassSetReservedPunctuator :: one of & - ! # % , : ; < = > @ ` ~

附录 B (规范性) 针对 Web 浏览器的 ECMAScript 额外特性

当 ECMAScript 宿主 是 Web 浏览器时,本附录中定义的 ECMAScript 语言语法和语义是必需的。如果 ECMAScript 宿主 不是 Web 浏览器,则本附录内容为规范性但可选项。

注意

本附录描述了 Web 浏览器 ECMAScript 宿主 的各种遗留特性和其他特性。本附录中指定的所有语言特性和行为都存在一个或多个不理想的特性,如果没有遗留使用,这些内容会从本规范中移除。然而,由于大量现有网页使用了这些特性,Web 浏览器必须继续支持它们。本附录中的规范定义了这些遗留特性的可互操作实现的要求。

这些特性不被认为是 ECMAScript 核心语言的一部分。编写新的 ECMAScript 代码时,程序员不应使用或假定这些特性和行为的存在。除非实现是 Web 浏览器的一部分,或需要运行 Web 浏览器所遇到的相同遗留 ECMAScript 代码,否则不建议 ECMAScript 实现实现这些特性。

B.1 额外语法

B.1.1 类 HTML 注释

12.4 的语法和语义扩展如下,但当使用 目标符号 Module 解析源文本时,不允许进行此扩展:

语法

InputElementHashbangOrRegExp :: WhiteSpace LineTerminator Comment CommonToken HashbangComment RegularExpressionLiteral HTMLCloseComment Comment :: MultiLineComment SingleLineComment SingleLineHTMLOpenComment SingleLineHTMLCloseComment SingleLineDelimitedComment MultiLineComment :: /* FirstCommentLineopt LineTerminator MultiLineCommentCharsopt */ HTMLCloseCommentopt FirstCommentLine :: SingleLineDelimitedCommentChars SingleLineHTMLOpenComment :: <!-- SingleLineCommentCharsopt SingleLineHTMLCloseComment :: LineTerminatorSequence HTMLCloseComment SingleLineDelimitedComment :: /* SingleLineDelimitedCommentCharsopt */ HTMLCloseComment :: WhiteSpaceSequenceopt SingleLineDelimitedCommentSequenceopt --> SingleLineCommentCharsopt SingleLineDelimitedCommentChars :: SingleLineNotAsteriskChar SingleLineDelimitedCommentCharsopt * SingleLinePostAsteriskCommentCharsopt SingleLineNotAsteriskChar :: SourceCharacter but not one of * or LineTerminator SingleLinePostAsteriskCommentChars :: SingleLineNotForwardSlashOrAsteriskChar SingleLineDelimitedCommentCharsopt * SingleLinePostAsteriskCommentCharsopt SingleLineNotForwardSlashOrAsteriskChar :: SourceCharacter but not one of / or * or LineTerminator WhiteSpaceSequence :: WhiteSpace WhiteSpaceSequenceopt SingleLineDelimitedCommentSequence :: SingleLineDelimitedComment WhiteSpaceSequenceopt SingleLineDelimitedCommentSequenceopt

类似于包含行终止符代码点的多行注释(MultiLineComment)单行 HTML 结束注释(SingleLineHTMLCloseComment) 也被视为行终止符(LineTerminator),用于语法解析时的语法文法处理。

B.1.2 正则表达式模式

22.2.1 的语法进行了如下修改和扩展。这些更改引入了歧义,可以通过文法产生式的顺序和上下文信息来消除。在使用下述文法进行解析时,仅当前面的产生式备选项不匹配时,才会考虑每一个备选项。

这种可选的模式文法和语义仅更改了 BMP 模式的语法和语义。下列文法扩展包含带有 [UnicodeMode] 参数的产生式。然而,这些扩展并不会更改在 目标符号 上带有 [UnicodeMode] 参数时解析所识别的 Unicode 模式的语法。

语法

Term[UnicodeMode, UnicodeSetsMode, NamedCaptureGroups] :: [+UnicodeMode] Assertion[+UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] [+UnicodeMode] Atom[+UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Quantifier [+UnicodeMode] Atom[+UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] [~UnicodeMode] QuantifiableAssertion[?NamedCaptureGroups] Quantifier [~UnicodeMode] Assertion[~UnicodeMode, ~UnicodeSetsMode, ?NamedCaptureGroups] [~UnicodeMode] ExtendedAtom[?NamedCaptureGroups] Quantifier [~UnicodeMode] ExtendedAtom[?NamedCaptureGroups] Assertion[UnicodeMode, UnicodeSetsMode, NamedCaptureGroups] :: ^ $ \b \B [+UnicodeMode] (?= Disjunction[+UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) [+UnicodeMode] (?! Disjunction[+UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) [~UnicodeMode] QuantifiableAssertion[?NamedCaptureGroups] (?<= Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) (?<! Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) QuantifiableAssertion[NamedCaptureGroups] :: (?= Disjunction[~UnicodeMode, ~UnicodeSetsMode, ?NamedCaptureGroups] ) (?! Disjunction[~UnicodeMode, ~UnicodeSetsMode, ?NamedCaptureGroups] ) ExtendedAtom[NamedCaptureGroups] :: . \ AtomEscape[~UnicodeMode, ?NamedCaptureGroups] \ [lookahead = c] CharacterClass[~UnicodeMode, ~UnicodeSetsMode] ( GroupSpecifier[~UnicodeMode]opt Disjunction[~UnicodeMode, ~UnicodeSetsMode, ?NamedCaptureGroups] ) (? RegularExpressionModifiers : Disjunction[~UnicodeMode, ~UnicodeSetsMode, ?NamedCaptureGroups] ) (? RegularExpressionModifiers - RegularExpressionModifiers : Disjunction[~UnicodeMode, ~UnicodeSetsMode, ?NamedCaptureGroups] ) InvalidBracedQuantifier ExtendedPatternCharacter InvalidBracedQuantifier :: { DecimalDigits[~Sep] } { DecimalDigits[~Sep] ,} { DecimalDigits[~Sep] , DecimalDigits[~Sep] } ExtendedPatternCharacter :: SourceCharacter but not one of ^ $ \ . * + ? ( ) [ | AtomEscape[UnicodeMode, NamedCaptureGroups] :: [+UnicodeMode] DecimalEscape [~UnicodeMode] DecimalEscape but only if the CapturingGroupNumber of DecimalEscape is ≤ CountLeftCapturingParensWithin(the Pattern containing DecimalEscape) CharacterClassEscape[?UnicodeMode] CharacterEscape[?UnicodeMode, ?NamedCaptureGroups] [+NamedCaptureGroups] k GroupName[?UnicodeMode] CharacterEscape[UnicodeMode, NamedCaptureGroups] :: ControlEscape c AsciiLetter 0 [lookahead ∉ DecimalDigit] HexEscapeSequence RegExpUnicodeEscapeSequence[?UnicodeMode] [~UnicodeMode] LegacyOctalEscapeSequence IdentityEscape[?UnicodeMode, ?NamedCaptureGroups] IdentityEscape[UnicodeMode, NamedCaptureGroups] :: [+UnicodeMode] SyntaxCharacter [+UnicodeMode] / [~UnicodeMode] SourceCharacterIdentityEscape[?NamedCaptureGroups] SourceCharacterIdentityEscape[NamedCaptureGroups] :: [~NamedCaptureGroups] SourceCharacter but not c [+NamedCaptureGroups] SourceCharacter but not one of c or k ClassAtomNoDash[UnicodeMode, NamedCaptureGroups] :: SourceCharacter but not one of \ or ] or - \ ClassEscape[?UnicodeMode, ?NamedCaptureGroups] \ [lookahead = c] ClassEscape[UnicodeMode, NamedCaptureGroups] :: b [+UnicodeMode] - [~UnicodeMode] c ClassControlLetter CharacterClassEscape[?UnicodeMode] CharacterEscape[?UnicodeMode, ?NamedCaptureGroups] ClassControlLetter :: DecimalDigit _

当同一个左侧出现了带有 [+UnicodeMode] 和 [~UnicodeMode] 条件时,这是用于控制消歧优先级。

B.1.2.1 静态语义:早期错误

22.2.1.1 的语义扩展如下:

ExtendedAtom :: InvalidBracedQuantifier
  • 如果任何源码文本被该产生式匹配,则为语法错误。

此外,以下产生式的规则通过添加高亮文本被修改:

NonemptyClassRanges :: ClassAtom - ClassAtom ClassContents NonemptyClassRangesNoDash :: ClassAtomNoDash - ClassAtom ClassContents

B.1.2.2 静态语义:CountLeftCapturingParensWithin 和 CountLeftCapturingParensBefore

CountLeftCapturingParensWithinCountLeftCapturingParensBefore 的定义中,对 “ Atom :: ( GroupSpecifieropt Disjunction ) ” 的引用应被解释为 “ Atom :: ( GroupSpecifieropt Disjunction ) ” 或 “ ExtendedAtom :: ( GroupSpecifieropt Disjunction ) ”。

B.1.2.3 静态语义:IsCharacterClass

22.2.1.6 的语义扩展如下:

ClassAtomNoDash :: \ [lookahead = c]
  1. 返回 false

B.1.2.4 静态语义:CharacterValue

22.2.1.7 的语义扩展如下:

ClassAtomNoDash :: \ [lookahead = c]
  1. 返回 U+005C(反斜杠)的数值。
ClassEscape :: c ClassControlLetter
  1. chClassControlLetter 匹配的代码点。
  2. ich 的数值。
  3. 返回 i 除以 32 的余数。
CharacterEscape :: LegacyOctalEscapeSequence
  1. 返回 LegacyOctalEscapeSequence 的 MV(见 12.9.4.3)。

B.1.2.5 运行时语义: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 运行时语义:CompileAssertion

CompileAssertion 对于 Assertion :: (?= Disjunction ) Assertion :: (?! Disjunction ) 产生式的规则也适用于 QuantifiableAssertion 产生式,但用 QuantifiableAssertion 替换 Assertion

B.1.2.7 运行时语义:CompileAtom

CompileAtomAtom 产生式(除了 Atom :: PatternCharacter )的规则同样适用于 ExtendedAtom 产生式,但用 ExtendedAtom 替换 Atom。同时也新增了如下带参数 direction 的规则:

ExtendedAtom :: \ [lookahead = c]
  1. A 为包含单个字符 \(U+005C,反斜杠)的 CharSet
  2. 返回 CharacterSetMatcher(rer, A, false, direction)。
ExtendedAtom :: ExtendedPatternCharacter
  1. chExtendedPatternCharacter 所代表的字符。
  2. A 为包含字符 ch 的单元素 CharSet
  3. 返回 CharacterSetMatcher(rer, A, false, direction)。

B.1.2.8 运行时语义:CompileToCharSet

22.2.2.9 的语义扩展如下:

以下两条规则替换了 CompileToCharSet 的对应规则。

NonemptyClassRanges :: ClassAtom - ClassAtom ClassContents
  1. A 为第一个 ClassAtomrer 作为参数调用 CompileToCharSet 的结果。
  2. B 为第二个 ClassAtomrer 作为参数调用 CompileToCharSet 的结果。
  3. CClassContentsrer 作为参数调用 CompileToCharSet 的结果。
  4. DCharacterRangeOrUnion(rer, A, B)。
  5. 返回 DC 的并集。
NonemptyClassRangesNoDash :: ClassAtomNoDash - ClassAtom ClassContents
  1. AClassAtomNoDashrer 作为参数调用 CompileToCharSet 的结果。
  2. BClassAtomrer 作为参数调用 CompileToCharSet 的结果。
  3. CClassContentsrer 作为参数调用 CompileToCharSet 的结果。
  4. DCharacterRangeOrUnion(rer, A, B)。
  5. 返回 DC 的并集。

此外,以下规则被添加到 CompileToCharSet

ClassEscape :: c ClassControlLetter
  1. cv 为该 ClassEscapeCharacterValue
  2. c 为字符值为 cv 的字符。
  3. 返回包含单个字符 cCharSet
ClassAtomNoDash :: \ [lookahead = c]
  1. 返回包含单个字符 \(U+005C,反斜杠)的 CharSet
注意
该产生式只会在字符类内的 \c 序列且其后不跟可接受的控制字符时被匹配到。

B.1.2.8.1 CharacterRangeOrUnion ( rer, A, B )

抽象操作 CharacterRangeOrUnion 接收参数 rer(一个 RegExp Record)、A(一个 CharSet)与 B (一个 CharSet),并返回一个 CharSet。调用时执行以下步骤:

  1. 如果 HasEitherUnicodeFlag(rer) 为 false,则
    1. 如果 A 不正好包含一个字符或 B 不正好包含一个字符,则
      1. C 为仅包含字符 -(U+002D,连字符)的 CharSet
      2. 返回 CharSets ABC 的并集。
  2. 返回 CharacterRange(A, B)。

B.1.2.9 静态语义:ParsePattern ( patternText, u, v )

22.2.3.4 的语义扩展如下:

抽象操作 ParsePattern 接收参数 patternText(一组 Unicode 码点序列)、u(布尔值)和 v(布尔值)。调用时执行以下步骤:

  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. 如果 parseResult语法解析节点(Parse Node),且 parseResult 包含 GroupName,则
      1. parseResult 设置为 ParseText(patternText, Pattern[~UnicodeMode, ~UnicodeSetsMode, +NamedCaptureGroups])。
  5. 返回 parseResult

B.2 补充内置属性

当 ECMAScript 宿主 是网页浏览器时,标准内置对象会定义以下附加属性。

B.2.1 全局对象的附加属性

表102 中的条目被添加到 表6 中。

表102:附加知名内在对象
内在名称 全局名称 ECMAScript 语言关联
%escape% escape escape 函数 (B.2.1.1)
%unescape% unescape unescape 函数 (B.2.1.2)

B.2.1.1 escape ( string )

此函数是 全局对象 的一个属性。它会计算一个新的字符串值,其中部分码元被十六进制转义序列替换。

当替换数值小于等于 0x00FF 的码元时,使用形如 %xx 的两位转义序列。当替换数值严格大于 0x00FF 的码元时,使用形如 %uxxxx 的四位转义序列。

它是 %escape% 内在对象。

调用时执行以下步骤:

  1. string 设为 ? ToString(string).
  2. lenstring 的长度。
  3. R 为一个空字符串。
  4. unescapedSet字符串拼接 ASCII 单词字符"@*+-./" 的结果。
  5. k 为 0。
  6. 重复,条件为 k < len,
    1. Cstring 中索引 k 处的码元。
    2. 如果 unescapedSet 包含 C,则
      1. SC
    3. 否则,
      1. nC 的数值。
      2. 如果 n < 256,则
        1. hexn 的字符串表示,按大写十六进制格式。
        2. S字符串拼接 "%"StringPad(hex, 2, "0", start) 的结果。
      3. 否则,
        1. hexn 的字符串表示,按大写十六进制格式。
        2. S字符串拼接 "%u"StringPad(hex, 4, "0", start) 的结果。
    4. R 设为 字符串拼接 RS 的结果。
    5. k 设为 k + 1。
  7. 返回 R
注意

该编码部分基于 RFC 1738 中描述的编码,但本标准中描述的完整编码如上所述,不考虑 RFC 1738 的内容。此编码未反映 RFC 3986 对 RFC 1738 的更改。

B.2.1.2 unescape ( string )

此函数是 全局对象 的一个属性。它会计算一个新的字符串值,将每个可能由 escape 函数引入的转义序列替换为其所代表的码元。

它是 %unescape% 内在对象。

调用时执行以下步骤:

  1. string 设为 ? ToString(string).
  2. lenstring 的长度。
  3. R 为一个空字符串。
  4. k 为 0。
  5. 重复,条件为 k < len,
    1. Cstring 中索引 k 处的码元。
    2. 如果 C 是码元 0x0025(百分号),则
      1. hexDigits 为一个空字符串。
      2. optionalAdvance 为 0。
      3. 如果 k + 5 < lenstring 中索引 k + 1 处的码元是 0x0075(小写字母 u),则
        1. hexDigits 设为 子字符串 stringk + 2 到 k + 6。
        2. optionalAdvance 设为 5。
      4. 否则如果 k + 3 ≤ len,则
        1. hexDigits 设为 子字符串 stringk + 1 到 k + 3。
        2. optionalAdvance 设为 2。
      5. parseResultParseText(hexDigits, HexDigits[~Sep])。
      6. 如果 parseResult解析节点,则
        1. nparseResult 的 MV。
        2. C 设为数值为 n 的码元。
        3. k 设为 k + optionalAdvance
    3. R 设为 字符串拼接 RC 的结果。
    4. k 设为 k + 1。
  6. 返回 R

B.2.2 String.prototype 对象的附加属性

B.2.2.1 String.prototype.substr ( start, length )

该方法返回将 this 的值转换为字符串后的一个 子字符串,从索引 start 开始,长度为 length 个码元(如果 lengthundefined,则到字符串末尾为止)。如果 start 为负值,则视为 sourceLength + start,其中 sourceLength 是字符串的长度。结果 是一个字符串 值,而不是字符串对象。

调用时执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 的值)。
  2. S 为 ? ToString(O).
  3. sizeS 的长度。
  4. intStart 为 ? ToIntegerOrInfinity(start)。
  5. 如果 intStart = -∞,则将 intStart 设为 0。
  6. 否则如果 intStart < 0,则将 intStart 设为 max(size + intStart, 0)。
  7. 否则,将 intStart 设为 min(intStart, size)。
  8. 如果 lengthundefined,则令 intLengthsize;否则令 intLength 为 ? ToIntegerOrInfinity(length)。
  9. intLength 限制在 0 到 size 之间,结果赋值给 intLength
  10. intEndmin(intStart + intLength, size)。
  11. 返回 子字符串 SintStartintEnd 的结果。
注意

该方法本身是通用的;它不要求 this 是字符串对象。因此它可以被转移到其他类型的对象用作方法。

B.2.2.2 String.prototype.anchor ( name )

此方法被调用时执行以下步骤:

  1. Sthis 的值。
  2. 返回 ? CreateHTML(S, "a", "name", name)。

B.2.2.2.1 CreateHTML ( string, tag, attribute, value )

抽象操作 CreateHTML 接收参数 stringECMAScript 语言值), tag(字符串),attribute(字符串),和 valueECMAScript 语言值),返回一个包含字符串的 正常完成抛出完成。调用时执行以下步骤:

  1. str 为 ? RequireObjectCoercible(string)。
  2. S 为 ? ToString(str)。
  3. p1字符串拼接 "<"tag
  4. 如果 attribute 不是空字符串,则
    1. V 为 ? ToString(value)。
    2. escapedVV 的字符串值,除了每个 0x0022(引号)都被 "&quot;" 替换。
    3. p1 设为 字符串拼接
      • p1
      • 码元 0x0020(空格)
      • attribute
      • 码元 0x003D(等号)
      • 码元 0x0022(引号)
      • escapedV
      • 码元 0x0022(引号)
  5. p2字符串拼接 p1">"
  6. p3字符串拼接 p2S
  7. p4字符串拼接 p3"</"tag">"
  8. 返回 p4

B.2.2.3 String.prototype.big ( )

此方法被调用时执行以下步骤:

  1. Sthis 的值。
  2. 返回 ? CreateHTML(S, "big", "", "")。

B.2.2.4 String.prototype.blink ( )

此方法被调用时执行以下步骤:

  1. Sthis 的值。
  2. 返回 ? CreateHTML(S, "blink", "", "")。

B.2.2.5 String.prototype.bold ( )

此方法被调用时执行以下步骤:

  1. Sthis 的值。
  2. 返回 ? CreateHTML(S, "b", "", "")。

B.2.2.6 String.prototype.fixed ( )

此方法被调用时执行以下步骤:

  1. Sthis 的值。
  2. 返回 ? CreateHTML(S, "tt", "", "")。

B.2.2.7 String.prototype.fontcolor ( colour )

此方法被调用时执行以下步骤:

  1. Sthis 的值。
  2. 返回 ? CreateHTML(S, "font", "color", colour)。

B.2.2.8 String.prototype.fontsize ( size )

此方法被调用时执行以下步骤:

  1. Sthis 的值。
  2. 返回 ? CreateHTML(S, "font", "size", size)。

B.2.2.9 String.prototype.italics ( )

此方法被调用时执行以下步骤:

  1. Sthis 的值。
  2. 返回 ? CreateHTML(S, "i", "", "")。

B.2.2.10 String.prototype.link ( url )

此方法被调用时执行以下步骤:

  1. Sthis 的值。
  2. 返回 ? CreateHTML(S, "a", "href", url)。

B.2.2.11 String.prototype.small ( )

此方法被调用时执行以下步骤:

  1. Sthis 的值。
  2. 返回 ? CreateHTML(S, "small", "", "")。

B.2.2.12 String.prototype.strike ( )

此方法被调用时执行以下步骤:

  1. Sthis 的值。
  2. 返回 ? CreateHTML(S, "strike", "", "")。

B.2.2.13 String.prototype.sub ( )

此方法被调用时执行以下步骤:

  1. Sthis 的值。
  2. 返回 ? CreateHTML(S, "sub", "", "")。

B.2.2.14 String.prototype.sup ( )

此方法被调用时执行以下步骤:

  1. Sthis 的值。
  2. 返回 ? CreateHTML(S, "sup", "", "")。

B.2.2.15 String.prototype.trimLeft ( )

注意

推荐使用 "trimStart" 属性。"trimLeft" 属性主要为了兼容旧代码而保留。建议新 ECMAScript 代码使用 "trimStart" 属性。

"trimLeft" 属性的初始值为 %String.prototype.trimStart%,定义见 22.1.3.34

B.2.2.16 String.prototype.trimRight ( )

注意

推荐使用 "trimEnd" 属性。"trimRight" 属性主要为了兼容旧代码而保留。建议新 ECMAScript 代码使用 "trimEnd" 属性。

"trimRight" 属性的初始值为 %String.prototype.trimEnd%,定义见 22.1.3.33

B.2.3 Date.prototype 对象的附加属性

B.2.3.1 Date.prototype.getYear ( )

注意

在几乎所有场合都推荐使用 getFullYear 方法,因为它避免了“千年虫问题”。

该方法被调用时执行以下步骤:

  1. dateObjectthis 的值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,返回 NaN
  5. 返回 YearFromTime(LocalTime(t)) - 1900𝔽

B.2.3.2 Date.prototype.setYear ( year )

注意

在几乎所有场合都推荐使用 setFullYear 方法,因为它避免了“千年虫问题”。

该方法被调用时执行以下步骤:

  1. dateObjectthis 的值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. y 为 ? ToNumber(year)。
  5. 如果 tNaN,则将 t 设为 +0𝔽;否则将 t 设为 LocalTime(t)。
  6. yyyyMakeFullYear(y)。
  7. dMakeDay(yyyy, MonthFromTime(t), DateFromTime(t))。
  8. dateMakeDate(d, TimeWithinDay(t))。
  9. uTimeClip(UTC(date))。
  10. dateObject.[[DateValue]] 设为 u
  11. 返回 u

B.2.3.3 Date.prototype.toGMTString ( )

注意

推荐使用 toUTCString 方法。本方法主要为了兼容旧代码而保留。

"toGMTString" 属性的初始值为 %Date.prototype.toUTCString%,定义见 21.4.4.43

B.2.4 RegExp.prototype 对象的附加属性

B.2.4.1 RegExp.prototype.compile ( pattern, flags )

此方法被调用时执行以下步骤:

  1. Othis 的值。
  2. 执行 ? RequireInternalSlot(O, [[RegExpMatcher]])。
  3. 如果 pattern 是一个对象pattern[[RegExpMatcher]] 内部槽,则
    1. 如果 flags 不是 undefined,抛出 TypeError 异常。
    2. Ppattern.[[OriginalSource]]
    3. Fpattern.[[OriginalFlags]]
  4. 否则,
    1. Ppattern
    2. Fflags
  5. 返回 ? RegExpInitialize(O, P, F)。
注意

该方法会完全重新初始化 this 的 RegExp 对象,使用新的模式和标志。实现可能会把该方法的使用解释为表示结果 RegExp 对象将被多次使用,因此可以额外优化。

B.3 其他附加特性

B.3.1 带标签的函数声明

在 ECMAScript 2015 之前,LabelledStatement 的规范不允许将语句标签与 FunctionDeclaration 关联。然而,带标签的 FunctionDeclaration非严格代码 的一个允许扩展,且大多数浏览器宿主的 ECMAScript 实现都支持该扩展。在 ECMAScript 2015 及以后,LabelledStatement 的语法产生式允许将 FunctionDeclaration 作为 LabelledItem 使用,但 14.13.1 包含一条早期错误规则,如果发生这种情况会产生语法错误。该规则通过添加高亮文本进行了修改:

LabelledItem : FunctionDeclaration
  • 如果该产生式匹配到的源码文本严格模式代码,则为语法错误。
注意

早期错误规则针对 WithStatementIfStatementIterationStatement,在非严格代码下,阻止这些语句包含带标签的 FunctionDeclaration

B.3.2 块级函数声明的 Web 兼容性语义

在 ECMAScript 2015 之前,ECMAScript 规范没有定义 FunctionDeclaration 作为 Block 语句的 StatementList 元素的情况。然而,这种形式的 FunctionDeclaration 是允许的扩展,大多数浏览器宿主的 ECMAScript 实现都允许它们。不幸的是,这种声明的语义在那些实现间有所不同。由于这些语义差异,现有使用 Block 级函数声明的 web ECMAScript 源文本,只有当用法仅依赖于所有这些实现的语义交集时,才能在各浏览器实现间移植。以下用例属于该语义交集:

  1. 函数在单个块内声明且仅在该块内被引用。

  2. 函数在单个 Block 内声明并可能被使用,但也被该 Block 之外的内部函数定义引用。

    • 在外部函数 g 的函数代码体内,出现一个或多个 FunctionDeclaration,其 BindingIdentifier 是名字 f,且声明嵌套在 Block 内。
    • g 的函数代码体内,未出现其他非 var 声明的 f
    • 在包含 f 声明的 StatementListBlock 内,可能出现 IdentifierReferencef
    • 至少有一次 IdentifierReference 形式的 f 出现在嵌套于 g 内的另一个函数 h 中,且不存在其他声明遮蔽 h 内对 f 的引用。
    • 所有对 h 的调用都发生在 f 声明已被求值之后。
  3. 函数在单个块内声明并可能被使用,但也在后续块内被引用。

第一个用例与 ECMAScript 2015 提供的块级函数声明语义兼容。任何采用该用例的现有 ECMAScript 源文本 都将按照 第10章第14章第15章 所定义的块级函数声明语义运行。

第二和第三个用例的 ECMAScript 2015 兼容性需要对 第10章第15章19.2.116.1.7 语义进行如下扩展。

如果 ECMAScript 实现有报告诊断警告信息的机制,当代码包含应用了这些兼容性语义且与非兼容性语义产生可观察差异的 FunctionDeclaration 时,应当产生警告。例如,如果未引入 var 绑定是因为其引入会导致 早期错误,则不应产生警告信息。

B.3.2.1 FunctionDeclarationInstantiation 的变更

FunctionDeclarationInstantiation 过程中,以下步骤替换 第29步

  1. 如果 strictfalse,则
    1. 对每个直接包含在任意 StatementListFunctionDeclaration f,该 StatementList 又属于某个 BlockCaseClauseDefaultClause x,且 code Contains xtrue,执行:
      1. FfBindingIdentifierStringValue
      2. 如果用 F 作为 BindingIdentifierVariableStatement 替换 f,不会为 func 产生任何早期错误,且 parameterNames 不包含 F,则:
        1. 注意:仅当 F 既不是 VarDeclaredName,也不是形参名,也不是另一个 FunctionDeclaration 时,才在此实例化 var 绑定。
        2. 如果 instantiatedVarNames 不包含 FF 不是 "arguments",则:
          1. 执行 ! varEnv.CreateMutableBinding(F, false)。
          2. 执行 ! varEnv.InitializeBinding(F, undefined)。
          3. F 添加到 instantiatedVarNames
        3. 当对 FunctionDeclaration f 求值时,执行以下步骤替换 FunctionDeclarationEvaluation 算法(见 15.2.6):
          1. fEnv 为当前执行上下文的 VariableEnvironment。
          2. bEnv 为当前执行上下文的 LexicalEnvironment。
          3. fObj 为 ! bEnv.GetBindingValue(F, false)。
          4. 执行 ! fEnv.SetMutableBinding(F, fObj, false)。
          5. 返回 unused

B.3.2.2 全局声明实例化的变更

GlobalDeclarationInstantiation 过程中,以下步骤替换 第12步

  1. 执行以下步骤:
    1. strictScriptIsStrictscript)。
    2. 如果 strictfalse,则
      1. declaredFunctionOrVarNamesdeclaredFunctionNamesdeclaredVarNames列表拼接
      2. 对每个直接包含在任意 StatementListFunctionDeclaration f,该 StatementList 又属于某个 BlockCaseClauseDefaultClause x,且 script Contains xtrue,执行:
        1. FfBindingIdentifierStringValue
        2. 如果用 F 作为 BindingIdentifierVariableStatement 替换 f,不会为 script 产生任何早期错误,则
          1. 如果 HasLexicalDeclaration(env, F) 为 false,则
            1. fnDefinable 为 ? CanDeclareGlobalVar(env, F)。
            2. 如果 fnDefinabletrue,则
              1. 注意:仅当 F 既不是 VarDeclaredName,也不是另一个 FunctionDeclaration 的名字时,这里才会实例化 var 绑定。
              2. 如果 declaredFunctionOrVarNames 不包含 F,则
                1. 执行 ? CreateGlobalVarBinding(env, F, false)。
                2. F 添加到 declaredFunctionOrVarNames
              3. 当对 FunctionDeclaration f 求值时,执行以下步骤来替换 FunctionDeclarationEvaluation 算法(见 15.2.6):
                1. gEnv 为当前执行上下文的 VariableEnvironment。
                2. bEnv 为当前执行上下文的 LexicalEnvironment。
                3. fObj 为 ! bEnv.GetBindingValue(F, false)。
                4. 执行 ? gEnv.SetMutableBinding(F, fObj, false)。
                5. 返回 unused

B.3.2.3 EvalDeclarationInstantiation 的变更

EvalDeclarationInstantiation 过程中,以下步骤替换 第13步

  1. 如果 strictfalse,则
    1. declaredFunctionOrVarNamesdeclaredFunctionNamesdeclaredVarNames列表拼接
    2. 对每个直接包含在任意 StatementListFunctionDeclaration f,该 StatementList 又属于某个 BlockCaseClauseDefaultClause x,且 body Contains xtrue,执行:
      1. FfBindingIdentifierStringValue
      2. 如果用 F 作为 BindingIdentifierVariableStatement 替换 f,不会为 body 产生任何早期错误,则
        1. bindingExistsfalse
        2. thisEnvlexEnv
        3. 断言:以下循环将终止。
        4. 重复,条件为 thisEnv 不等于 varEnv
          1. 如果 thisEnv 不是对象 环境记录,则
            1. 如果 ! thisEnv.HasBinding(F) 为 true,则
              1. bindingExiststrue
          2. thisEnv 设为 thisEnv.[[OuterEnv]]
        5. 如果 bindingExistsfalsevarEnv全局环境记录,则
          1. 如果 HasLexicalDeclaration(varEnv, F) 为 false,则
            1. fnDefinable 为 ? CanDeclareGlobalVar(varEnv, F)。
          2. 否则,
            1. fnDefinablefalse
        6. 否则,
          1. fnDefinabletrue
        7. 如果 bindingExistsfalsefnDefinabletrue,则
          1. 如果 declaredFunctionOrVarNames 不包含 F,则
            1. 如果 varEnv全局环境记录,则
              1. 执行 ? CreateGlobalVarBinding(varEnv, F, true)。
            2. 否则,
              1. bindingExists 为 ! varEnv.HasBinding(F)。
              2. 如果 bindingExistsfalse,则
                1. 执行 ! varEnv.CreateMutableBinding(F, true)。
                2. 执行 ! varEnv.InitializeBinding(F, undefined)。
            3. F 添加到 declaredFunctionOrVarNames
          2. 当对 FunctionDeclaration f 求值时,执行以下步骤来替换 FunctionDeclarationEvaluation 算法(见 15.2.6):
            1. gEnv 为当前执行上下文的 VariableEnvironment。
            2. bEnv 为当前执行上下文的 LexicalEnvironment。
            3. fObj 为 ! bEnv.GetBindingValue(F, false)。
            4. 执行 ? gEnv.SetMutableBinding(F, fObj, false)。
            5. 返回 unused

B.3.2.4 块静态语义:早期错误的变更

14.2.1 中,下列产生式的规则通过添加高亮文本进行了修改:

Block : { StatementList }

B.3.2.5 switch 语句静态语义:早期错误的变更

14.12.1 中,下列产生式规则通过添加高亮文本进行了修改:

SwitchStatement : switch ( Expression ) CaseBlock

B.3.2.6 BlockDeclarationInstantiation 的变更

BlockDeclarationInstantiation 过程中,以下步骤替换 3.a.ii.1

  1. 如果 ! env.HasBinding(dn) 为 false,则
    1. 执行 ! env.CreateMutableBinding(dn, false)。

BlockDeclarationInstantiation 过程中,以下步骤替换 3.b.iii

  1. 执行以下步骤:
    1. 如果 envfn 的绑定是未初始化绑定,则
      1. 执行 ! env.InitializeBinding(fn, fo)。
    2. 否则,
      1. 断言d 是一个 FunctionDeclaration
      2. 执行 ! env.SetMutableBinding(fn, fo, false)。

B.3.3 IfStatement 语句子句中的 FunctionDeclarations

下述内容对 IfStatement 产生式进行了补充,详见 14.6

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]都被视为占据该位置的StatementListItem中的唯一一个,并包含在一个BlockStatement中。此类合成的BlockStatement的语义包括在B.3.2中指定的 Web 兼容性旧版语义。

B.3.4 Catch 代码块中的 VariableStatements

子条款 14.15.1 的内容被替换为以下内容:

Catch : catch ( CatchParameter ) Block

Block 中的 Catch 子句可以包含与 CatchParameter 所绑定名称相同的 var 声明。在运行时,这些绑定会在 VariableDeclarationEnvironment 中实例化。它们不会遮蔽由 CatchParameter 引入的同名绑定,因此这些 var 声明的 Initializer 将会赋值给对应的 catch 参数,而不是 var 绑定。

这种修改后的行为也适用于 Block 中包含的通过 直接调用 eval 引入的 varfunction 声明。这一更改是通过如下方式修改 19.2.1.3 的算法来实现的:

3.d.i.2.a.i 步被替换为:

  1. 如果 thisEnv 不是某个 Catch 子句的 环境记录,则抛出 SyntaxError 异常。

13.b.ii.4.a.i.i 步被替换为:

  1. 如果 thisEnv 不是某个 Catch 子句的 环境记录,则设 bindingExiststrue

B.3.5 ForIn 语句头中的初始化器

下列内容补充了 ForInOfStatement 的产生式定义,详见 14.7.5

ForInOfStatement[Yield, Await, Return] : for ( var BindingIdentifier[?Yield, ?Await] Initializer[~In, ?Yield, ?Await] in Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return]

该产生式仅在解析 非严格模式代码 时适用。

静态语义中,ContainsDuplicateLabels 的定义在 8.3.1 中被如下内容扩充:

ForInOfStatement : for ( var BindingIdentifier Initializer in Expression ) Statement
  1. 返回 ContainsDuplicateLabels(参数为 labelSet)应用于 Statement 的结果。

静态语义中,ContainsUndefinedBreakTarget 的定义在 8.3.2 中被如下内容扩充:

ForInOfStatement : for ( var BindingIdentifier Initializer in Expression ) Statement
  1. 返回 ContainsUndefinedBreakTarget(参数为 labelSet)应用于 Statement 的结果。

静态语义中的ContainsUndefinedContinueTarget8.3.3节被增强如下:

ForInOfStatement : for ( var BindingIdentifier Initializer in Expression ) Statement
  1. 返回 ContainsUndefinedContinueTargetStatement 中,使用参数 iterationSet 和 « » 的结果。

静态语义 中的 IsDestructuring14.7.5.2 中被增强如下:

BindingIdentifier : Identifier yield await
  1. 返回 false

静态语义 中,关于 VarDeclaredNames 的定义(位于 8.2.6)被以下内容所扩展:

ForInOfStatement : for ( var BindingIdentifier Initializer in Expression ) Statement
  1. names1绑定名,来源于 BindingIdentifier
  2. names2变量声明名,来源于 语句
  3. 返回 列表连接,将 names1names2 合并。

静态语义 中,关于 变量作用域声明 的定义(位于 8.2.7)被以下内容所扩展:

ForInOfStatement : for ( var BindingIdentifier Initializer in Expression ) Statement
  1. declarations1 为 « 绑定标识符 »。
  2. declarations2变量作用域声明 ,来源于 语句
  3. 返回 列表连接,合并 declarations1declarations2

运行时语义 中,关于 ForInOfLoopEvaluation 的定义(位于 14.7.5.5)被以下内容所扩展:

ForInOfStatement : for ( var BindingIdentifier Initializer in Expression ) Statement
  1. bindingId字符串值,来源于 绑定标识符
  2. lhs 为 ? 解析绑定(bindingId)。
  3. 如果 是否匿名函数定义(初始化器) 为 true,则
    1. value 为 ? 命名求值,对 初始化器bindingId 作为参数。
  4. 否则,
    1. rhs 为 ? 求值,对 初始化器
    2. value 为 ? 取值(rhs)。
  5. 执行 ? 赋值(lhs, value)。
  6. keyResult 为 ? ForIn/Of 头部求值(« », 表达式, enumerate)。
  7. 返回 ? ForIn/Of 主体求值(绑定标识符, 语句, keyResult, enumerate, var-binding, labelSet)。

B.3.6 [[IsHTMLDDA]] 内部槽

[[IsHTMLDDA]] 内部槽 可能存在于 宿主定义对象上。具有 [[IsHTMLDDA]] 内部槽的对象,在 ToBooleanIsLooselyEqual 抽象操作中,以及作为 typeof 运算符的操作数时,表现得如同 undefined

具有 [[IsHTMLDDA]] 内部槽的对象不会由本规范创建。但 Web 浏览器中的 document.all 对象 是一个带有此槽的 宿主定义 特殊对象,用于 Web 兼容性。除此之外,没有其他已知的此类对象,除 document.all 外,实现不应创建任何此类对象。

B.3.6.1 对 ToBoolean 的更改

以下步骤替换 3 步骤,见 ToBoolean

  1. 如果 argument 是对象argument[[IsHTMLDDA]] 内部槽,则返回 false

B.3.6.2 对 IsLooselyEqual 的更改

以下步骤替换 4 步骤,见 IsLooselyEqual

  1. 执行以下步骤:
    1. 如果 x 是对象x[[IsHTMLDDA]] 内部槽,且 yundefinednull,则返回 true
    2. 如果 xundefinednully 是对象,且 y[[IsHTMLDDA]] 内部槽,则返回 true

B.3.6.3typeof 运算符的更改

以下步骤替换 12 步骤,见 typeof 运算符的求值语义

  1. 如果 val[[IsHTMLDDA]] 内部槽,则返回 "undefined"

B.3.7 HostMakeJobCallback 的非默认行为

HostMakeJobCallback 抽象操作允许作为 Web 浏览器的 宿主 指定非默认行为。

B.3.8 HostEnsureCanAddPrivateElement 的非默认行为

HostEnsureCanAddPrivateElement 抽象操作允许作为 Web 浏览器的 宿主 指定非默认行为。

附录 C (资料性) ECMAScript 的严格模式

严格模式的限制与例外

附录 D (说明性) 主机分层点

有关 4.2主机 的定义,请参见该节。

D.1 主机钩子

HostCallJobCallback(...)

HostEnqueueFinalizationRegistryCleanupJob(...)

HostEnqueueGenericJob(...)

HostEnqueuePromiseJob(...)

HostEnqueueTimeoutJob(...)

HostEnsureCanCompileStrings(...)

HostFinalizeImportMeta(...)

HostGetImportMetaProperties(...)

HostGrowSharedArrayBuffer(...)

HostHasSourceTextAvailable(...)

HostLoadImportedModule(...)

HostGetSupportedImportAttributes(...)

HostMakeJobCallback(...)

HostPromiseRejectionTracker(...)

HostResizeArrayBuffer(...)

InitializeHostDefinedRealm(...)

D.2 主机定义字段

[[HostDefined]]Realm 记录 上:见 表 24

[[HostDefined]]Script 记录 上:见 表 39

[[HostDefined]]模块记录 上:见 表 43

[[HostDefined]]JobCallback 记录 上:见 表 28

[[HostSynchronizesWith]] 在候选执行上:见 表 101

[[IsHTMLDDA]]:见 B.3.6

D.3 主机定义对象

全局对象:见第 19 节。

D.4 运行中的作业

在调用 作业 抽象闭包 之前的准备步骤,以及之后的清理步骤。参见 9.5

D.5 异常对象的内部方法

本规范未指定的任何 表 4 中的必要内部方法,适用于任何 异类对象,且其语义由主机环境定义。

D.6 内建对象与方法

本规范未定义的任何内建对象与方法,除非在 17.1 中有限制。

附录 E (说明性) ECMAScript 2015 中可能影响兼容性的修正和澄清

9.1.1.4.14-9.1.1.4.17 第五版和5.1版使用属性存在性测试来确定对应新全局声明的 全局对象 属性是否已存在。ECMAScript 2015 采用自有属性存在性测试。这与大多数网页浏览器的实现方式一致。

10.4.2.1:第五版将当前数组长度的捕获移到了对 整数 转换 数组索引 或新长度值之前。然而,如果转换过程存在副作用更改了数组长度,捕获的长度值可能会变得无效。ECMAScript 2015 规定必须在可能发生此类副作用之后捕获当前数组长度。

21.4.1.31:之前的版本允许 TimeClip 抽象操作返回 +0𝔽-0𝔽 作为 0 时间值 的表示。ECMAScript 2015 规定始终返回 +0𝔽。这意味着在 ECMAScript 2015 中,Date 的 时间值 永远不会被观察为 -0𝔽,且返回时间值的方法也永远不会返回 -0𝔽

21.4.1.32:如果不存在 UTC 偏移表示,则使用本地时区。第五版错误地声明缺少时区应解释为 "z"

21.4.4.36:如果年份无法用 21.4.1.32 指定的日期时间字符串格式表示,则抛出 RangeError 异常。之前版本未指定该情况的行为。

21.4.4.41:之前版本未指定当 时间值NaNDate.prototype.toString 返回的值。ECMAScript 2015 指定返回字符串值 "Invalid Date"

22.2.4.1, 22.2.6.13.1:RegExp 实例的 "source" 属性值中的任何换行符代码点必须使用转义序列表示。5.1版仅要求转义 /

22.2.6.8, 22.2.6.11:在之前版本中,String.prototype.matchString.prototype.replace 的规范对于参数为带有 global 标志的 RegExp 情况是不正确的。之前规范声明每次尝试匹配时,如果 lastIndex 未改变,则应将其加1。正确行为是仅当模式匹配空字符串时才将 lastIndex 加1。

23.1.3.30:之前版本未指定当 比较器 返回 NaN 时,Array.prototype.sort 如何处理。ECMAScript 2015 指定该值视作从比较器返回了 +0𝔽。ECMAScript 2015 还规定对比较器返回的结果应用 ToNumber。之前版本对于非数值的比较器返回值的效果是 由实现决定。实际上,大多数实现都会调用 ToNumber

附录 F (说明性) 与先前版本不兼容的新增内容和更改

6.2.5:在 ECMAScript 2015 中,函数调用不允许返回 引用记录

7.1.4.1:在 ECMAScript 2015 中,应用于字符串值的 ToNumber 现在可以识别并转换 BinaryIntegerLiteralOctalIntegerLiteral 数字字符串。在先前的版本中,此类字符串会被转换为 NaN

9.3:在 ECMAScript 2018 中,模板对象的规范化基于 解析节点(源位置),而不是像先前版本中那样,在 Realm 中跨越该模板字面量或带标签模板的所有出现。

12.2:在 ECMAScript 2016 中,强制使用 Unicode 8.0.0 或更高版本,而 ECMAScript 2015 强制使用 Unicode 5.1。特别地,这导致 U+180E MONGOLIAN VOWEL SEPARATOR(蒙古文元音分隔符),在 ECMAScript 2015 中属于 Space_Separator (Zs) 类别并因此被视为空白,被移至 Format (Cf) 类别(自 Unicode 6.3.0 起)。这导致对空白敏感的方法表现不同。例如,在先前的版本中 "\u180E".trim().length0,但在 ECMAScript 2016 及更高版本中为 1。此外,ECMAScript 2017 强制始终使用最新版本的 Unicode 标准。

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正常完成,则 IfStatement 的结果是 undefined

14.7:在 ECMAScript 2015 中,如果 for 语句的 ( 标记紧随 token 序列 let [,则 let 被视为 LexicalDeclaration 的开始。在先前的版本中,这样的 token 序列会是 Expression 的开始。

14.7:在 ECMAScript 2015 中,如果 for-in 语句的 ( 标记紧随 token 序列 let [,则 let 被视为 ForDeclaration 的开始。在先前的版本中,这样的 token 序列会是 LeftHandSideExpression 的开始。

14.7:在 ECMAScript 2015 之前,初始化表达式可以作为 VariableDeclaration 的一部分出现,该声明位于 in 关键字 之前。在 ECMAScript 2015 中,处于相同位置的 ForBinding 不允许出现这样的初始化器。在 ECMAScript 2017 中,这样的初始化器仅在 非严格代码 中被允许。

14.7:在 ECMAScript 2015 中,求值 IterationStatement 的结果永远不会是其 [[Value]]empty正常完成。如果 IterationStatementStatement 部分未被求值,或者 Statement 部分的最终求值产生其 [[Value]]empty正常完成,则求值 IterationStatement 的结果是其 [[Value]]undefined正常完成

14.11.2:在 ECMAScript 2015 中,求值 WithStatement 的结果永远不会是其 [[Value]]empty正常完成。如果 WithStatementStatement 部分的求值产生其 [[Value]]empty正常完成,则求值 WithStatement 的结果是其 [[Value]]undefined正常完成

14.12.4:在 ECMAScript 2015 中,求值 SwitchStatement 的结果永远不会是其 [[Value]]empty正常完成。如果 SwitchStatementCaseBlock 部分的求值产生其 [[Value]]empty正常完成,则求值 SwitchStatement 的结果是其 [[Value]]undefined正常完成

14.15:在 ECMAScript 2015 中,如果 Catch 子句包含一个 var 声明,其 Identifier 与作为 Catch 子句参数的 Identifier 相同,则这是一个 早期错误。在先前的版本中,这样的变量声明会在封闭的变量环境中实例化,但声明的 Initializer 值会赋给 Catch 参数。

14.1519.2.1.3:在 ECMAScript 2015 中,如果 Catch 子句对一个非严格的直接 eval 求值,其 eval 代码包含一个 varFunctionDeclaration 声明,该声明绑定了与作为 Catch 子句参数的 Identifier 相同的 Identifier,则会抛出一个运行时 SyntaxError

14.15.3:在 ECMAScript 2015 中,TryStatement 的结果永远不会是 empty。如果 TryStatementBlock 部分求值为包含 empty正常完成,则 TryStatement 的结果是 undefined。如果 TryStatementBlock 部分求值为 throw 完成,并且它有一个 Catch 部分,该部分求值为包含 empty正常完成,那么如果不存在 Finally 子句,或者其 Finally 子句求值为一个 empty正常完成,则 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 中,绑定函数的 [[Prototype]] 内部插槽设置为其目标函数的 [[GetPrototypeOf]] 值。在先前的版本中,[[Prototype]] 总是设置为 %Function.prototype%

20.2.4.1:在 ECMAScript 2015 中,函数实例的 "length" 属性是可配置的。在先前的版本中,它是不可配置的。

20.5.6.2:在 ECMAScript 2015 中,NativeError 构造函数[[Prototype]] 内部插槽是 Error 构造函数。在先前的版本中,它是 函数原型对象

21.4.4 在 ECMAScript 2015 中,Date 原型对象 不是 Date 实例。在先前的版本中,它是一个 TimeValue 为 NaN 的 Date 实例。

22.1.3.12 在 ECMAScript 2015 中,String.prototype.localeCompare 函数必须将根据 Unicode 标准在规范上等效的字符串视为相同。在先前的版本中,实现被允许忽略规范等效性,而可以使用逐位比较。

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 实例。在先前的版本中,它是一个模式为空字符串的 RegExp 实例。

22.2.6 在 ECMAScript 2015 中,"source""global""ignoreCase""multiline" 是在 RegExp 原型对象 上定义的 访问器属性。在先前的版本中,它们是在 RegExp 实例上定义的 数据属性

25.4.15: 在 ECMAScript 2019 中,Atomics.wake 已重命名为 Atomics.notify,以防止与 Atomics.wait 混淆。

27.1.6.4, 27.6.3.6: 在 ECMAScript 2019 中,由 await 入队的 作业 数量减少了,这可能导致在 then() 调用和 await 表达式之间的解析顺序出现可观察的差异。

参考文献

  1. IEEE 754-2019: IEEE 浮点数算术标准。电气和电子工程师协会,纽约 (2019) 注意

    IEEE 754-2008 和 IEEE 754-2019 之间没有影响 ECMA-262 规范的规范性变更。

  2. Unicode 标准, 参见 <https://unicode.org/versions/latest>
  3. Unicode 技术说明 #5:应用程序中的规范等价, 参见 <https://unicode.org/notes/tn5/>
  4. Unicode 技术标准 #10:Unicode 排序算法, 参见 <https://unicode.org/reports/tr10/>
  5. Unicode 标准附录 #15, Unicode 规范化形式, 参见 <https://unicode.org/reports/tr15/>
  6. Unicode 标准附录 #18: Unicode 正则表达式, 参见 <https://unicode.org/reports/tr18/>
  7. Unicode 标准附录 #24: Unicode Script 属性, 参见 <https://unicode.org/reports/tr24/>
  8. Unicode 标准附录 #31, Unicode 标识符和模式语法, 参见 <https://unicode.org/reports/tr31/>
  9. Unicode 标准附录 #44: Unicode 字符数据库, 参见 <https://unicode.org/reports/tr44/>
  10. Unicode 技术标准 #51: Unicode Emoji, 参见 <https://unicode.org/reports/tr51/>
  11. IANA 时区数据库, 参见 <https://www.iana.org/time-zones>
  12. ISO 8601: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 方言,它提供了一个框架和工具集,用于以纯文本编写 ECMAScript 规范,并将规范处理成功能齐全的 HTML 渲染,该渲染遵循本文档的编辑约定。Ecmarkup 构建并集成了许多其他格式和技术,包括用于定义语法的 Grammarkdown 和用于编写算法步骤的 Ecmarkdown。本规范的 PDF 渲染是使用打印样式表制作的,该样式表利用了 CSS 分页媒体规范,并使用 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.