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