Draft ECMA-262 / May 7, 2026

ECMAScript® 2027 Language Specification

关于本规范

https://tc39.es/ecma262/上的文档是最准确且最新的 ECMAScript 规范。 它包含最近年份快照的内容以及任何已完成的提案 —— 这些提案已在提案流程中达到第 4 阶段,已在多个实现中落地, 并将被收录进下一个年度快照。历史快照可在 https://ecma-international.org/publications-and-standards/standards/ecma-262/ 获得。

本文件可作为单页面多页面形式获取。

参与本规范的贡献

本规范在 GitHub 上由 ECMAScript 社区共同开发。你可以通过以下多种方式参与规范的开发:

更多关于本文件的生成方式,请参考后记

简介

本 Ecma 标准定义了 ECMAScript 2027 语言。这是 ECMAScript 语言规范的第十八版。 ECMAScript 源自多项技术,最著名的是 JavaScript(Netscape)和 JScript(Microsoft)。 该语言由 Brendan Eich 在网景公司发明,首次出现在该公司发布的 Navigator 2.0 浏览器中。 虽然 ECMAScript 最为人知的是作为网页浏览器内嵌语言,但也被广泛用于浏览器之外的场景,包括服务器和嵌入式应用,现已成长为世界上应用最广泛的通用型编程语言之一。

ECMAScript 语言规范的制定工作始于 1996 年 11 月。第一版 Ecma 标准于 1997 年 6 月在 Ecma 大会通过。

该 Ecma 标准随后提交至 ISO/IEC JTC 1,采用快速通道(fast-track)程序,并于 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 配合万维网取得了巨大成功,成为几乎所有网页浏览器支持的编程语言。曾进行过大量工作以制定第四版规范,但该工作未能完成并发表为 ECMAScript 第四版,其部分成果被吸收进第六版的开发中。

ECMAScript 第五版(作为 ECMA-262 第五版发布)规范化了在浏览器实现中已普遍采用的语言解释方式,并增加了自第三版发布以来出现的新特性,包括访问器属性,对象的反射式创建和检查、属性特性的程序化控制,更多的数组操作函数,对 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、解构模式、正确的尾调用等。内建库扩展,支持新的数据抽象如映射(Map)、集合(Set)、二进制数值数组,并对字符串、正则表达式增强了 Unicode 补充字符支持。内建对象亦可通过子类化扩展。 第六版为语言和库实现定期、渐进增强打下基础。第六版于 2015 年 6 月被大会通过。

ECMAScript 2016 是在 Ecma TC39 全新年度发布节奏和开放开发流程下发布的首个 ECMAScript 版本。从 ECMAScript 2015 源文档构建的纯文本文档,成为后续开发的基础并完全在 GitHub 协作。一年内,有上百次拉取请求与问题提交,修复了数千项错误、编辑及改进。另外,开发了 Ecmarkup、Ecmarkdown、Grammarkdown 等工具,助力标准制定。ES2016 还引入了新的指数运算符和 Array.prototype.includes 方法。

ECMAScript 2017 引入了异步函数、共享内存和原子操作,并带来了更小幅的语言与库增强、漏洞修复和编辑更新。异步函数改善了异步编程体验,为返回 Promise 的函数提供了新语法。共享内存和原子操作引入了一种新内存模型,使多 Agent 程序通过原子操作通信,确保即便在多核并行下也有明确定义的执行顺序。此外,还为 Object 提供了新静态方法:Object.valuesObject.entriesObject.getOwnPropertyDescriptors

ECMAScript 2018 通过异步迭代器协议和异步生成器实现了异步迭代支持。同时还包括四项正则扩展特性:dotAll 标志、具名捕获组、Unicode 属性转义以及后行断言。最后,还加入了对象的剩余与扩展属性。

ECMAScript 2019 新增了若干内建函数:Array.prototype 上的 flatflatMap 用于扁平化数组,Object.fromEntries 可直接将 Object.entries 的返回值转为新对象,String.prototype 上的 trimStarttrimEnd 是更佳命名的 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 组合器不会因某单 Promise 拒绝而短路;globalThis 通用全局对象访问方式;export * as ns from 'module' 专用语法用于模块内命名空间导出;for-in 枚举顺序更趋规范;import.meta 支持模块上下文相关信息;新增“空值”处理语法特性 Nullish 合并(??)和可选链接(?.)。

ECMAScript 2021(第 12 版)引入了字符串的 replaceAll 方法;Promise.any 是会在任一输入完成时即返回的 Promise 组合器;AggregateError 新错误类型可表示多个错误;逻辑赋值操作符(??=&&=||=);WeakRef 支持弱引用对象不影响垃圾回收,FinalizationRegistry 用于对象回收后注册清理回调;数字分隔符(如 1_000);Array.prototype.sort 更精确定义,减少实现相关的不确定顺序。

ECMAScript 2022(第 13 版)增加了顶层 await,允许模块顶层使用关键字 await;新增类元素:公有/私有实例字段,公有/私有静态字段,私有实例方法和访问器,私有静态方法和访问器;类内静态代码块可供每类初始化;#x in obj 语法可检测对象私有字段;正则表达式 /d 标志用于获取子串的起止位置;Error 对象的 cause 属性可记录错误因果链;字符串、数组和 TypedArrayat 方法支持相对索引;Object.hasOwnObject.prototype.hasOwnProperty 提供简化替代。

ECMAScript 2023(第 14 版)针对 Array.prototypeTypedArray.prototype 增加了 toSortedtoReversedwithfindLastfindLastIndex 等方法,Array.prototype 还新增 toSpliced 方法;支持在文件开头添加 #! 注释以增强可执行性;允许大部分 Symbol 作为弱集合键使用。

ECMAScript 2024(第 15 版)引入了调整和转移 ArrayBuffer 与 SharedArrayBuffer 的能力;新增 RegExp /v 标志,可针对字符串集合创建功能更强的正则表达式;加入了 Promise.withResolvers 快捷方法以构造 Promise,Object.groupByMap.groupBy 对数据聚合,Atomics.waitAsync 支持异步等待共享内存变化,以及 String.prototype.isWellFormedString.prototype.toWellFormed 方法用于检查并保证字符串仅包含规范 Unicode 字符。

ECMAScript 2025(第 16 版)引入了全局 Iterator,以及用于操作迭代器的静态和原型方法;为 Set.prototype 新增常用集合操作方法;支持导入 JSON 模块及声明导入模块属性的语法;RegExp.escape 方法可安全转义字符串供正则使用;支持正则内联启用/禁用修饰符标志语法;Promise.try 方法保证无论目标函数是否返回 Promise 都总返回 Promise;新增 Float16Array TypedArray 类型及相关的 DataView.prototype.getFloat16DataView.prototype.setFloat16Math.f16round 方法。

ECMAScript 2026(第 17 版)引入了 Math.sumPrecise,可对不同数量级的数值集合高精度求和,减少误差;Iterator.concat 合并迭代器序列;Array.fromAsync 可从异步可迭代对象等异步来源构建数组;Error.isError 用于识别错误对象;Map.prototypeWeakMap.prototype 可检索默认值键方法(当键不存在时可指定默认返回);Uint8Array 新增方法实现与 16 进制及 base64 编码二进制字符串的相互转换;JSON.parse 的 reviver 可访问 JSON 源片段;JSON.rawJSON 用于对原始值执行更细粒度的 stringify 输出控制。

有数十位、代表众多组织的专家在 Ecma TC39 对本版及以往多版标准做出了极其重要的贡献。 此外,支持 TC39 ECMAScript 工作的社区正在蓬勃发展。 他们审查了大量草案,提交了数千个错误报告,开展实现实验,贡献测试套件,推广 ECMAScript 至全球开发者社群。 遗憾的是,无法一一列出和感谢所有为此做出贡献的个人和组织。

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

Brian Terlson
ECMA-262,第七至第十版项目编辑

Jordan Harband
ECMA-262,第十至第十二版项目编辑

Kevin Gibbons
ECMA-262,第十二至第十七版项目编辑

Shu-yu Guo
ECMA-262,第十二至第十八版项目编辑

Michael Ficarra
ECMA-262,第十二至第十八版项目编辑

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

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

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

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

1 范围

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

2 一致性

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

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

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

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

符合规范的 ECMAScript 实现可以支持本规范未描述的程序语法和正则表达式语法。特别地,符合规范的 ECMAScript 实现可以支持使用本规范子条款 12.7.2 中提到的任意“未来保留字”的程序语法。

符合规范的 ECMAScript 实现不得实现任何在子条款 17.1 中被列为禁止扩展(Forbidden Extension)的扩展。

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

除非另有说明,符合规范的 ECMAScript 实现可以选择实现或不实现规范性可选子条款。Web 浏览器通常需要实现所有规范性可选子条款。(参见附录 B。)如果实现了任何规范性可选行为,则其所在规范性可选条款中的全部行为都必须实现。本规范中,规范性可选条款会以带有“Normative Optional”字样的彩色框标出,如下所示。

Normative Optional

2.1 规范性可选条款标题示例

条款内容示例。

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

Legacy

2.2 遗留条款标题示例

条款内容示例。

Normative Optional, Legacy

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 中列举的设施,或者那些被标记为实现定义(implementation-defined)或实现近似定义(implementation-approximated)的设施。在非正式用法中,实现指的是具体制品,例如某个特定的 Web 浏览器。

实现定义设施,是指其定义被无进一步限定地延后到外部来源的设施。本规范不对具体行为提出任何建议,符合规范的实现可以在本规范施加的约束内自由选择任意行为。

实现近似定义设施,是指其定义被延后到外部来源,但同时推荐一种理想行为。尽管符合规范的实现可以在本规范施加的约束内自由选择任意行为,但仍鼓励其尽量逼近该理想行为。某些数学运算,例如 Math.exp,属于实现近似定义

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

宿主钩子是一个抽象操作,其定义全部或部分由外部来源给出。所有宿主钩子都必须列在附录 D 中。宿主钩子至少必须符合以下要求:

宿主定义设施,是指其定义被无进一步限定地延后到外部来源,且列在附录 D 中。不是宿主的实现也可以为宿主定义设施提供定义。

宿主环境是对所有宿主定义设施的一组特定定义选择。宿主环境通常包括一些对象或函数,它们允许作为全局对象宿主定义属性来获取输入和提供输出。

本规范遵循一种编辑约定,即始终使用最具体的术语。例如,如果某项设施是宿主定义的,则不应称其为实现定义

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

4.3 ECMAScript 概览

以下是对 ECMAScript 的非正式概览——并未描述语言的所有部分。此概览不属于标准正文的一部分。

ECMAScript 是基于对象的:基础语言设施和宿主设施都由对象提供,而 ECMAScript 程序则是一组相互通信的对象。在 ECMAScript 中,对象是由零个或多个属性组成的集合,每个属性带有决定该属性如何被使用的特性——例如,当某个属性的 Writable 特性被设为 false 时,任何已执行的 ECMAScript 代码试图为该属性赋不同值的操作都会失败。属性是容器,用来保存其他对象、原始值函数。原始值属于以下内建类型之一:UndefinedNullBooleanNumberBigIntStringSymbol; 对象属于内建类型 Object;而函数则是可调用对象。通过属性与对象关联的函数称为方法

ECMAScript 定义了一组内建对象,以补全 ECMAScript 实体的定义。这些内建对象包括:全局对象;对语言运行时语义至关重要的对象,包括 ObjectFunctionBooleanSymbol 以及各种 Error 对象;表示和操作数值的对象,包括 MathNumberDate;文本处理对象 StringRegExp;作为值索引集合的对象,包括 Array 以及九种不同类型的 Typed 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 的隐式引用,如此继续;这被称为原型链。当引用对象中的某个属性时,该引用指向原型链中第一个包含该名称属性的对象中的该属性。换言之,首先检查直接提到的对象是否有该属性;如果该对象包含该命名属性,则引用指向该属性;如果不包含,则继续检查该对象的原型;依此类推。

Figure 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 宿主定义

实现定义相同

Note

在编辑表达上,参见条款 4.2

4.4.4 类型

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

4.4.5 原始值

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

Note

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

4.4.6 对象

Object 类型的成员

Note

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

4.4.7 构造器

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

Note

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

4.4.8 原型

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

Note

构造器创建对象时,该对象会为了解析属性引用而隐式引用构造器"prototype" 属性。构造器"prototype" 属性可以通过程序表达式 constructor.prototype 来引用,而添加到某个对象原型上的属性会通过继承被所有共享该原型的对象共享。另一种方式是,使用内建函数 Object.create 并显式指定原型来创建新对象。

4.4.9 普通对象

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

4.4.10 异质对象

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

Note

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

4.4.11 标准对象

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

4.4.12 内建对象

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

Note

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

4.4.13 undefined 值

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

4.4.14 Undefined 类型

其唯一值为 undefined 值的类型

4.4.15 null 值

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

4.4.16 Null 类型

其唯一值为 null 值的类型

4.4.17 Boolean 值

Boolean 类型的成员

Note

Boolean 值只有两个:truefalse

4.4.18 Boolean 类型

由原始值 truefalse 构成的类型

4.4.19 Boolean 对象

Object 类型的成员,且是标准内建 Boolean 构造器的实例

Note

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

4.4.20 String 值

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

Note

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

4.4.21 String 类型

所有可能 String 值的集合

4.4.22 String 对象

Object 类型的成员,且是标准内建 String 构造器的实例

Note

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

4.4.23 Number 值

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

Note

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

4.4.24 Number 类型

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

4.4.25 Number 对象

Object 类型的成员,且是标准内建 Number 构造器的实例

Note

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

4.4.26 Infinity

表示正无穷 Number 值Number 值

4.4.27 NaN

IEEE 754-2019 NaN(“不是数字”)值的 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 类型的成员,可作为子程序被调用

Note

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

4.4.35 内建函数

作为函数的内建对象

Note

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

4.4.36 内建构造器

作为构造器的内建函数

Note

内建构造器的例子包括 ObjectFunction宿主或实现可以提供本规范未描述的额外内建构造器

4.4.37 属性

对象的一部分,它关联一个键(String 值或 Symbol 值之一)和一个值

Note

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

4.4.38 方法

作为属性值的函数

Note

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

4.4.39 内建方法

作为内建函数的方法

Note

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

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.1SourceCharacter 规则的 Unicode 码点作为终结符。它定义了一组产生式,从目标符号 InputElementDivInputElementTemplateTailInputElementRegExpInputElementRegExpOrTemplateTailInputElementHashbangOrRegExp 开始,描述如何将这类码点序列转换为输入元素序列。

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

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

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

5.1.3 数字字符串文法

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

数字字符串文法的产生式通过使用三个冒号“:::”作为标点来区分,并且绝不会用于解析源文本。

5.1.4 语法文法

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

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

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

每次调用解析器时都会实例化新的解析节点,即使源文本完全相同,不同解析之间的解析节点也绝不会复用。只有当两个解析节点表示同一段源文本、是同一个文法符号的实例,并且来自同一次解析器调用时,它们才被认为是同一个解析节点

Note 1

对同一个 String 进行多次解析会得到不同的解析节点。例如,考虑:

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

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

Note 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. 否则(若解析失败),则为早期 Syntax Error。

5.1.5 文法记号

5.1.5.1 终结符

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

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

例如,产生式:

HexIntegerLiteral :: 0x HexDigits

是如下形式的简写:

HexIntegerLiteral :: 0 x HexDigits

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

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

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

5.1.5.2 非终结符与产生式

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

WhileStatement : while ( Expression ) Statement

表示非终结符 WhileStatement 代表词法单元 while,接着一个左括号词法单元,再接着一个 Expression,再接着一个右括号词法单元,最后接着一个 Statement。其中出现的 ExpressionStatement 本身也是非终结符。再例如,语法定义:

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 :: 任意 Unicode 码点

5.2 算法约定

本规范经常使用编号列表来规定算法步骤。这些算法用于精确规定 ECMAScript 语言构造所要求的语义。这些算法并不意味着必须采用任何特定的实现技术。实际上,实现某个给定特性时可能存在更高效的算法。

算法可以显式地带参数,其参数是一个按顺序排列、以逗号分隔的别名序列,这些别名可在算法步骤中用于引用传入对应位置的参数。可选参数用方括号包围表示([ , name]),在算法步骤中与必需参数没有区别。剩余参数可以出现在参数列表末尾,以前导省略号表示(, ...name)。剩余参数将所有位于必需参数和可选参数之后提供的实参收集到一个 List 中。如果没有此类额外参数,该 List 为空。

算法步骤可以再细分为顺序子步骤。子步骤会缩进显示,并且自身也可以继续细分为更深层次的缩进子步骤。为标识子步骤,使用分级编号约定:第一层子步骤使用小写英文字母标记,第二层子步骤使用小写罗马数字标记。如果需要超过三级,则这些规则重复使用,第四层改用数字标记。例如:

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

步骤或子步骤可以写成一个“if”谓词,以条件化其子步骤。在这种情况下,仅当谓词为真时才应用这些子步骤。如果步骤或子步骤以“else”一词开头,则它是与同一层级上前一个“if”谓词步骤相反的谓词。

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

以“Assert:”开头的步骤,用于断言其算法中的某个不变条件。这类断言用于显式表明原本隐含的算法不变式。类似地,以“NOTE:”开头的步骤,为附近步骤提供相关背景。断言步骤和注释步骤都严格属于说明性内容;它们不增加任何额外的语义要求,因此实现不必检查它们。

算法步骤可以使用“Let x be someValue”形式为任意值声明具名别名。这些别名具有类似引用的特性,即 xsomeValue 都引用同一底层数据,对任一者的修改对两者都可见。若算法步骤希望避免这种类似引用的行为,应显式复制右侧值:“Let x be a copy of someValue” 会创建 someValue 的一个浅拷贝。

一旦声明,别名可在其后的任意步骤中被引用,但不得在声明之前的步骤中被引用。别名可以使用“Set x to someOtherValue”形式进行修改。

5.2.1 求值顺序

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

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

等价于

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

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

5.2.2 抽象操作

为便于在本规范多个部分中使用,一些算法被赋予名称,并以带参数的函数形式书写,这些算法称为抽象操作,以便其他算法中可以通过名称引用它们。抽象操作通常通过函数调用风格引用,例如 OperationName(arg1, arg2)。某些抽象操作被视为类式规范抽象上的多态分派方法。这类方法风格的抽象操作通常通过方法调用风格引用,例如 someValue.OperationName(arg1, arg2)。

5.2.3 语法制导操作

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

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

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

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

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

Block : { StatementList }

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

Runtime Semantics: Evaluation

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

5.2.4 运行时语义

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

5.2.4.1 Completion ( completionRecord )

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

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

5.2.4.2 抛出

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

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

等价于

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

当算法步骤说明要抛出某种特定类型的异常时,会构造该类型的异常并将其抛出。例如,

  1. Throw a TypeError exception.

等价于

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

5.2.4.3 用于解包 Completion Record 的简写

前缀 ?! 用作解包 Completion Record 的简写。? 用于将突兀完成传播给调用方,或者在其他情况下解包正常完成! 用于断言某个 Completion Record正常完成并将其解包。形式上,步骤

  1. Let result be ? record.

等价于

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

同样地,步骤

  1. Let result be ! record.

等价于

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

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

  1. Perform AO(? Other()).

可改写为

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

而它进一步展开为

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

5.2.4.4 隐式正常完成

在那些声明返回 Completion Record抽象操作内的算法中,以及在所有内建函数中,返回值会先传给 NormalCompletion,然后使用其结果代替。此规则不适用于 Completion 算法内部,也不适用于该步骤中被明确标记为 Completion Record 的返回值;这些情况包括:

如果在这类抽象操作中通过任何其他方式返回 Completion Record,则属于编辑错误。例如,在这些抽象操作内部,

  1. Return true.

与以下任一形式含义相同:

  1. Return NormalCompletion(true).

或者

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

或者

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

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

  1. Return ? completion.

下面的示例则属于编辑错误,因为某个 Completion Record 在该步骤中未被标注却被返回了。

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

5.2.5 静态语义

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

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

一种特殊的静态语义规则是早期错误规则早期错误规则定义了与特定文法产生式相关联的早期错误条件(见条款 17)。本规范中的大多数早期错误规则的求值,并不会在算法中被显式调用。符合规范的实现必须在首次对某个 ScriptModule 求值之前,验证用于解析该 ScriptModule 的各产生式上的所有早期错误规则。如果任一早期错误规则被违反,则该 ScriptModule 无效,且不能被求值。

5.2.6 数学运算

本规范提及以下几类数值:

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

在本规范的表述中,不同数值种类通过下标后缀加以区分。下标 𝔽 指 Number,下标 指 BigInt。不带下标后缀的数值指数学值。本规范多数数值以十进制表示;它也使用形如 0x 后跟数字 0-9 或 A-F 的数值作为十六进制值。

一般来说,当本规范提及某个数值,比如“y 的长度”或“由四个十六进制数字表示的整数”这类短语,而没有明确指定数值种类时,该短语指的是数学值。凡指代 Number 或 BigInt 值的短语都会显式注明;例如,“……中码点数量对应的 Number 值”或“……对应的 BigInt 值”。

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

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

数学值与 Number 或 BigInt 之间的转换,在本文档中始终是显式的。将数学值扩展数学值 x 转换为 Number,记作“xNumber 值”或 𝔽(x),其定义见 6.1.6.1。将整数 x 转换为 BigInt,记作“xBigInt 值”或 ℤ(x)。将 Number 或 BigInt x 转换为数学值,记作“xmathematical value of”或 ℝ(x)+0𝔽-0𝔽数学值都是数学值 0。非有限值的数学值未定义。xextended mathematical value of,对于有限值而言就是 x数学值,而对于 +∞𝔽-∞𝔽 则分别是 +∞ 和 -∞;对于 NaN 则未定义。

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

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

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

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

短语“将 x 夹取lowerupper 之间的结果”(其中 x扩展数学值,且 lowerupper 是满足 lowerupper数学值)在 x < lower 时产生 lower,在 x > upper 时产生 upper,否则产生 x

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

Note

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

数学函数 truncate(x) 通过朝零方向取整去除 x 的小数部分:若 x < 0,则产生 -floor(-x),否则产生 floor(x)

数学函数 minmaxabsfloortruncate 对 Number 与 BigInt 未定义,任何对这些方法传入非数学值参数的用法,在本规范中都属于编辑错误。

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

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

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

5.2.7 值记号

在本规范中,ECMAScript 语言值粗体 显示。例子包括 nulltrue"hello"。这些值与诸如 Function.prototype.applylet n = 42; 之类的 ECMAScript 源文本是有区别的。

5.2.8 标识

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

从本规范的角度来看,词语 “is” 用于比较两个值是否相等,例如 “If bool is true, then ...”;而词语 “contains” 用于基于相等性比较在列表中查找某个值,例如 "If list contains a Record r such that r.[[Foo]] is true, then ...". 值的规范标识决定了这些比较的结果,并且在本规范中是公理性的。

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

对于规范值,无规范标识的值的例子包括但不限于:数学值扩展数学值ECMAScript 源文本、代理项对、Directive Prologues 等;UTF-16 码元;Unicode 码点;枚举;抽象操作(包括语法制导操作宿主钩子等);以及有序对。有规范标识的规范值的例子包括但不限于:任何种类的 Record,包括 Property DescriptorsPrivateElements 等;解析节点ListSetRelationAbstract ClosuresData BlocksPrivate Names执行上下文执行上下文栈agent 标识符;以及 WaiterList Records

对于所有 ECMAScript 语言值,规范标识都与语言标识一致,唯一例外是由 Symbol.for 产生的 Symbol 值。既无规范标识又无语言标识的 ECMAScript 语言值包括 undefinednullBooleanStringNumberBigInt。具有规范标识且具有语言标识的 ECMAScript 语言值包括不是由 Symbol.for 产生的 Symbol 以及 Object。由 Symbol.for 产生的 Symbol 值具有规范标识,但不具有语言标识。

6 ECMAScript 数据类型和值

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

6.1 ECMAScript 语言类型

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

6.1.1 Undefined 类型

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

6.1.2 Null 类型

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

6.1.3 Boolean 类型

Boolean 类型 表示具有两个值的逻辑实体,这两个值称为 truefalse

6.1.4 String 类型

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

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

函数 String.prototype.normalize(见 22.1.3.15)可用于显式规范化 一个 String 值。String.prototype.localeCompare(见 22.1.3.12)会在内部对 String 值进行规范化,但其他操作在处理其操作对象的字符串时都不会 隐式进行规范化。除非另有说明,操作结果不对语言和/或区域设置敏感。

Note

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

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

短语“strinclusiveStartexclusiveEnd子字符串”(其中 str 是 String 值或码元 序列,inclusiveStartexclusiveEnd整数)表示这样一个 String 值:它由 str 中从索引 inclusiveStart 开始,到索引 exclusiveEnd 之前立即结束的连续码元构成(当 inclusiveStart = exclusiveEnd 时,它就是空 String)。如果省略 “to” 后缀,则使用 str 的长度作为 exclusiveEnd 的值。

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

6.1.4.1 StringIndexOf ( string, searchValue, fromIndex )

The abstract operation StringIndexOf takes arguments string (一个 String,), searchValue (一个 String,), and fromIndex (一个非负整数,) and returns 一个非负整数not-found. It performs the following steps when called:

  1. lenstring 的长度。
  2. searchValue 是空 String 且 fromIndexlen,返回 fromIndex
  3. searchLensearchValue 的长度。
  4. 对每个满足 fromIndexilen - searchLen整数 i,按升序执行
    1. candidatestringii + searchLen子字符串
    2. candidatesearchValue,返回 i
  5. 返回 not-found
Note 1

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

Note 2

fromIndex + searchValue 的长度 > string 的长度, 此算法总是返回 not-found

6.1.4.2 StringLastIndexOf ( string, searchValue, fromIndex )

The abstract operation StringLastIndexOf takes arguments string (一个 String,), searchValue (一个 String,), and fromIndex (一个非负整数,) and returns 一个非负整数not-found. It performs the following steps when called:

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

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

6.1.5 Symbol 类型

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

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

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

6.1.5.1 众所周知的 Symbol

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

在本规范中,众所周知的 symbol 通过标准的 内在记法 来引用,其中该内在值是 Table 1 中列出的某个值。

Note
本规范早期版本使用 @@name 这种形式的记法,而当前版本 会使用 %Symbol.name%。特别地,曾使用过以下名称: @@asyncIterator、@@hasInstance、@@isConcatSpreadable、 @@iterator、@@match、@@matchAll、 @@replace、@@search、@@species、@@split、@@toPrimitive、 @@toStringTag 和 @@unscopables。
Table 1: 众所周知的 Symbol
规范名称 [[Description]] 值与用途
%Symbol.asyncIterator% "Symbol.asyncIterator" 一个方法,返回对象的默认异步迭代器。由 for-await-of 语句的语义调用。
%Symbol.hasInstance% "Symbol.hasInstance" 一个方法,用于确定某个构造器对象是否将某对象识别为该构造器 的一个实例。由 instanceof 运算符的语义调用。
%Symbol.isConcatSpreadable% "Symbol.isConcatSpreadable" 一个 Boolean 值属性,若为 true,则表示对象应当被 Array.prototype.concat 展开为其数组元素。
%Symbol.iterator% "Symbol.iterator" 一个方法,返回对象的默认迭代器。由 for-of 语句的语义 调用。
%Symbol.match% "Symbol.match" 一个正则表达式方法,用于将正则表达式与字符串进行匹配。 由 String.prototype.match 方法调用。
%Symbol.matchAll% "Symbol.matchAll" 一个正则表达式方法,返回一个迭代器,该迭代器会产出正则表达式 对字符串匹配得到的各个结果。由 String.prototype.matchAll 方法调用。
%Symbol.replace% "Symbol.replace" 一个正则表达式方法,用于替换字符串中匹配到的子字符串。 由 String.prototype.replace 方法调用。
%Symbol.search% "Symbol.search" 一个正则表达式方法,返回字符串中匹配该正则表达式的位置索引。 由 String.prototype.search 方法调用。
%Symbol.species% "Symbol.species" 一个函数值属性,它是用于创建派生对象的构造器函数。
%Symbol.split% "Symbol.split" 一个正则表达式方法,用于在字符串中按匹配该正则表达式的索引 进行分割。由 String.prototype.split 方法调用。
%Symbol.toPrimitive% "Symbol.toPrimitive" 一个方法,将对象转换为对应的原始值。由 ToPrimitive 抽象 操作调用。
%Symbol.toStringTag% "Symbol.toStringTag" 一个 String 值属性,用于创建对象的默认字符串描述。由内建 方法 Object.prototype.toString 访问。
%Symbol.unscopables% "Symbol.unscopables" 一个对象值属性,其自有和继承属性名,都是从关联对象的 with 环境绑定中排除的属性名

6.1.6 数值类型

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

Table 2: 数值类型操作
操作 示例源码 由……的 Evaluation 语义调用 结果
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) Object 内部方法, 通过 SameValue ( x, y ), 用于测试精确值相等 Boolean
Number::sameValueZero [x].includes(y) 通过 SameValueZero ( x, y ), 用于测试值相等,并忽略 +0𝔽-0𝔽 之间的差异,如 Array、Map 和 Set 方法中那样 Boolean
Number::bitwiseAND x & y 二元按位运算符 Number
BigInt::bitwiseAND BigInt
Number::bitwiseXOR x ^ y Number
BigInt::bitwiseXOR BigInt
Number::bitwiseOR x | y Number
BigInt::bitwiseOR BigInt
Number::toString String(x) 许多表达式和内建函数,通过 ToString ( argument ) String
BigInt::toString

由于数值类型一般无法在不丢失精度或不截断的情况下互相转换, ECMAScript 语言不提供这些类型之间的隐式转换。当调用要求另一种类型 的函数时,程序员必须显式调用 NumberBigInt 函数来进行类型 转换。

Note

ECMAScript 的第一版及后续版本,对某些运算符提供了可能丢失 精度或发生截断的隐式数值转换。出于向后兼容的考虑,这些遗留的隐式 转换被保留下来;但为了尽量减少程序员出错的机会,并为未来版本中的 广义值类型保留可能性,BigInt 不提供此类隐式转换。

6.1.6.1 Number 类型

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

Note

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

还有另外两个特殊值,称为 positive Infinitynegative Infinity。为简洁起见,在说明中也分别用符号 +∞𝔽-∞𝔽 来表示它们。(注意,这两个 无穷 Number 值由程序表达式 +Infinity(或简写为 Infinity)和 -Infinity 产生。)

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

注意,既有 positive zero 也有 negative zero。为简洁 起见,在说明中也分别用符号 +0𝔽-0𝔽 来表示它们。(注意,这两个不同的零 Number 值由程序表达式 +0 (或简写为 0)和 -0 产生。)

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

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

s × m × 2e

其中 s 为 1 或 -1,m 是位于 252(含)到 253(不含)区间内的整数e 是位于 -1074 到 971 闭区间内的整数

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

s × m × 2e

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

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

若某个有限数非零,且用于表示它的整数 m(以上述两种形式 之一表示)为奇数,则称它具有奇数有效数。否则,它具有 偶数有效数

在本规范中,短语“xNumber 值”,其中 x 表示某个精确的 实数数学量(它甚至可能是像 π 这样的无理数),是指以下方式选择出的 一个 Number 值。考虑由 Number 类型所有有限值构成的集合,去除 -0𝔽,并额外向其中加入两个 Number 类型无法表示的值, 即 21024(即 +1 × 253 × 2971)和 -21024(即 -1 × 253 × 2971)。从该 集合中选择与 x 值最接近的成员。若集合中的两个值与 x 等距接近, 则选择具有偶数有效数的那个;为此目的,额外加入的两个值 21024-21024 被视为 具有偶数有效数。最后,若选中的是 21024,则将其替换为 +∞𝔽;若选中的是 -21024,则将其替换为 -∞𝔽;若选中的是 +0𝔽,则当且仅当 x < 0 时将其替换为 -0𝔽;其他被选中的值则保持不变。结果就是 xNumber 值。(该过程与 IEEE 754-2019 的 roundTiesToEven 模式行为完全一致。)

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

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

6.1.6.1.1 Number::unaryMinus ( x )

The abstract operation Number::unaryMinus takes argument x (一个 Number,) and returns 一个 Number. It performs the following steps when called:

  1. xNaN,返回 NaN
  2. 返回 x 的相反数;即,计算一个大小相同但符号相反的 Number。

6.1.6.1.2 Number::bitwiseNOT ( x )

The abstract operation Number::bitwiseNOT takes argument x (一个 Number,) and returns 一个整数 Number. It performs the following steps when called:

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

6.1.6.1.3 Number::exponentiate ( base, exponent )

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

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

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

6.1.6.1.4 Number::multiply ( x, y )

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

  1. xNaNyNaN,返回 NaN
  2. x+∞𝔽-∞𝔽,则
    1. y+0𝔽-0𝔽,返回 NaN
    2. y > +0𝔽,返回 x
    3. 返回 -x
  3. y+∞𝔽-∞𝔽,则
    1. x+0𝔽-0𝔽,返回 NaN
    2. x > +0𝔽,返回 y
    3. 返回 -y
  4. x-0𝔽,则
    1. y-0𝔽y < -0𝔽, 返回 +0𝔽
    2. 返回 -0𝔽
  5. y-0𝔽,则
    1. x < -0𝔽,返回 +0𝔽
    2. 返回 -0𝔽
  6. 返回 𝔽((x) × (y))。
Note

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

6.1.6.1.5 Number::divide ( x, y )

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

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

6.1.6.1.6 Number::remainder ( n, d )

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

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

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

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

6.1.6.1.7 Number::add ( x, y )

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

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

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

6.1.6.1.8 Number::subtract ( x, y )

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

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

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

6.1.6.1.9 Number::leftShift ( x, y )

The abstract operation Number::leftShift takes arguments x (一个 Number,) and y (一个 Number,) and returns 一个整数 Number. It performs the following steps when called:

  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 )

The abstract operation Number::signedRightShift takes arguments x (一个 Number,) and y (一个 Number,) and returns 一个整数 Number. It performs the following steps when called:

  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 )

The abstract operation Number::unsignedRightShift takes arguments x (一个 Number,) and y (一个 Number,) and returns 一个整数 Number. It performs the following steps when called:

  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 )

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

  1. xNaN,返回 undefined
  2. yNaN,返回 undefined
  3. xy,返回 false
  4. x+0𝔽y-0𝔽, 返回 false
  5. x-0𝔽y+0𝔽, 返回 false
  6. x+∞𝔽,返回 false
  7. y+∞𝔽,返回 true
  8. y-∞𝔽,返回 false
  9. x-∞𝔽,返回 true
  10. 断言:xy有限值。
  11. (x) < (y),返回 true
  12. 返回 false

6.1.6.1.13 Number::equal ( x, y )

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

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

6.1.6.1.14 Number::sameValue ( x, y )

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

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

6.1.6.1.15 Number::sameValueZero ( x, y )

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

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

6.1.6.1.16 NumberBitwiseOp ( op, x, y )

The abstract operation NumberBitwiseOp takes arguments op (&^|,), x (一个 Number,), and y (一个 Number,) and returns 一个整数 Number. It performs the following steps when called:

  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 )

The abstract operation Number::bitwiseAND takes arguments x (一个 Number,) and y (一个 Number,) and returns 一个整数 Number. It performs the following steps when called:

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

6.1.6.1.18 Number::bitwiseXOR ( x, y )

The abstract operation Number::bitwiseXOR takes arguments x (一个 Number,) and y (一个 Number,) and returns 一个整数 Number. It performs the following steps when called:

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

6.1.6.1.19 Number::bitwiseOR ( x, y )

The abstract operation Number::bitwiseOR takes arguments x (一个 Number,) and y (一个 Number,) and returns 一个整数 Number. It performs the following steps when called:

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

6.1.6.1.20 Number::toString ( x, radix )

The abstract operation Number::toString takes arguments x (一个 Number,) and radix (一个位于 2 到 36 闭区间内的整数,) and returns 一个 String. 它使用基数为 radix 的位值计数系统将 x 表示为一个 String。使用基数 r 表示数字时所用的数字字符,按顺序取自 "0123456789abcdefghijklmnopqrstuvwxyz" 的前 r 个码元。对绝对值 大于等于 1𝔽 的数字进行表示时,绝不会包含前导零。 It performs the following steps when called:

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

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

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

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

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

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

Gay, David M. Correctly Rounded Binary-Decimal and Decimal-Binary Conversions. Numerical Analysis, Manuscript 90-10. AT&T Bell Laboratories (Murray Hill, New Jersey). 30 November 1990. Available as
https://ampl.com/_archive/first-website/REFS/rounding.pdf. Associated code available as
http://netlib.sandia.gov/fp/dtoa.c and as
http://netlib.sandia.gov/fp/g_fmt.c and may also be found at the various netlib mirror sites.

6.1.6.2 BigInt 类型

BigInt 类型 表示整数值。该值可以具有任意大小,而不受特定位宽限制。通常,在未另作 说明的情况下,各操作都旨在返回精确的数学结果。对于二元操作,BigInt 表现得如同二进制补码位串,负数被视为在左侧无限延伸且位均已设置。

6.1.6.2.1 BigInt::unaryMinus ( x )

The abstract operation BigInt::unaryMinus takes argument x (一个 BigInt,) and returns 一个 BigInt. It performs the following steps when called:

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

6.1.6.2.2 BigInt::bitwiseNOT ( x )

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

  1. 返回 -x - 1

6.1.6.2.3 BigInt::exponentiate ( base, exponent )

The abstract operation BigInt::exponentiate takes arguments base (一个 BigInt,) and exponent (一个 BigInt,) and returns 要么是包含 BigInt 的正常完成,要么是抛出完成. It performs the following steps when called:

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

6.1.6.2.4 BigInt::multiply ( x, y )

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

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

6.1.6.2.5 BigInt::divide ( x, y )

The abstract operation BigInt::divide takes arguments x (一个 BigInt,) and y (一个 BigInt,) and returns 要么是包含 BigInt 的正常完成,要么是抛出完成. It performs the following steps when called:

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

6.1.6.2.6 BigInt::remainder ( n, d )

The abstract operation BigInt::remainder takes arguments n (一个 BigInt,) and d (一个 BigInt,) and returns 要么是包含 BigInt 的正常完成,要么是抛出完成. It performs the following steps when called:

  1. d = 0,抛出一个 RangeError 异常。
  2. n = 0,返回 0
  3. quotient(n) / (d)。
  4. q(truncate(quotient))。
  5. 返回 n - (d × q)。
Note
结果的符号与被除数的符号相同。

6.1.6.2.7 BigInt::add ( x, y )

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

  1. 返回 x + y

6.1.6.2.8 BigInt::subtract ( x, y )

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

  1. 返回 x - y

6.1.6.2.9 BigInt::leftShift ( x, y )

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

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

6.1.6.2.10 BigInt::signedRightShift ( x, y )

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

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

6.1.6.2.11 BigInt::unsignedRightShift ( x, y )

The abstract operation BigInt::unsignedRightShift takes arguments x (一个 BigInt,) and y (一个 BigInt,) and returns 一个抛出完成. It performs the following steps when called:

  1. 抛出一个 TypeError 异常。

6.1.6.2.12 BigInt::lessThan ( x, y )

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

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

6.1.6.2.13 BigInt::equal ( x, y )

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

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

6.1.6.2.14 BinaryAnd ( x, y )

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

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

6.1.6.2.15 BinaryOr ( x, y )

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

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

6.1.6.2.16 BinaryXor ( x, y )

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

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

6.1.6.2.17 BigIntBitwiseOp ( op, x, y )

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

  1. x 设为 (x)。
  2. y 设为 (y)。
  3. result 为 0。
  4. shift 为 0。
  5. 重复,直到 (x = 0 或 x = -1) 且 (y = 0 或 y = -1),
    1. xDigitx modulo 2。
    2. yDigity modulo 2。
    3. op&,则
      1. result 设为 result + 2shift × BinaryAnd(xDigit, yDigit)。
    4. 否则若 op|,则
      1. result 设为 result + 2shift × BinaryOr(xDigit, yDigit)。
    5. 否则,
      1. 断言:op^
      2. result 设为 result + 2shift × BinaryXor(xDigit, yDigit)。
    6. shift 设为 shift + 1。
    7. x 设为 (x - xDigit) / 2。
    8. y 设为 (y - yDigit) / 2。
  6. op&,则
    1. 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. result 设为 result - 2shift
    2. 注:这会扩展符号位。
  10. 返回 resultBigInt 值

6.1.6.2.18 BigInt::bitwiseAND ( x, y )

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

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

6.1.6.2.19 BigInt::bitwiseXOR ( x, y )

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

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

6.1.6.2.20 BigInt::bitwiseOR ( x, y )

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

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

6.1.6.2.21 BigInt::toString ( x, radix )

The abstract operation BigInt::toString takes arguments x (一个 BigInt,) and radix (一个位于 2 到 36 闭区间内的整数,) and returns 一个 String. 它使用基数为 radix 的位值计数系统将 x 表示为一个 String。使用基数 r 表示 BigInt 时所用的数字字符,按顺序取自 "0123456789abcdefghijklmnopqrstuvwxyz" 的前 r 个码元。除 0 之外的 BigInt 的表示绝不会包含前导零。 It performs the following steps when called:

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

6.1.7 Object 类型

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

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

对象的属性通过属性键被唯一标识。属性键 是 String 或 Symbol 之一。所有 String 和 Symbol,包括空 String, 都可以作为合法的属性键属性名是一个属于 String 的属性键

整数索引 是这样一个属性名 nCanonicalNumericIndexString(n) 返回一个位于 +0𝔽𝔽(253 - 1) 闭区间内的 整数 Number数组索引是这样一个整数索引 nCanonicalNumericIndexString(n) 返回一个位于 +0𝔽𝔽(232 - 2) 闭区间内的 整数 Number

Note

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

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

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

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

6.1.7.1 属性特性

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

Table 3: Object 属性的特性
特性名称 具有该特性的属性类型 值域 默认值 描述
[[Value]] 数据属性 一个 ECMAScript 语言值 undefined 对该属性执行 get 访问时获取到的值。
[[Writable]] 数据属性 一个 Boolean false 若为 false,则 ECMAScript 代码通过 [[Set]] 修改该属性 的 [[Value]] 特性的尝试不会成功。
[[Get]] 访问器属性 一个 Object 或 undefined undefined 若该值是一个 Object,则它必须是函数对象。每次对该属性 执行 get 访问以获取属性值时,都会以空参数列表调用该函数的 [[Call]] 内部方法( Table 5 )。
[[Set]] 访问器属性 一个 Object 或 undefined undefined 若该值是一个 Object,则它必须是函数对象。每次对该属性 执行 set 访问时,都会以仅包含所赋值值作为唯一参数的参数列表 调用该函数的 [[Call]] 内部方法( Table 5 )。属性的 [[Set]] 内部方法的效果可以但不要求影响之后 调用该属性 [[Get]] 内部方法时返回的值。
[[Enumerable]] 数据属性访问器属性 一个 Boolean false 若为 true,则该属性将在 for-in 枚举中被枚举(见 14.7.5 )。否则,该属性被称为不可枚举。
[[Configurable]] 数据属性访问器属性 一个 Boolean false 若为 false,则删除该属性、将其从数据属性改为访问器属性 或从访问器属性改为数据属性,或修改其任何特性(替换现有 [[Value]] 或将 [[Writable]] 设为 false 除外)的尝试 都会失败。

6.1.7.2 对象内部方法和内部槽

在 ECMAScript 中,对象的实际语义是通过称为内部方法 的算法来规定的。ECMAScript 引擎中的每个对象都关联着一组定义其运行时 行为的内部方法。这些内部方法不是 ECMAScript 语言的一部分。它们仅为 说明之用而由本规范定义。然而,ECMAScript 实现中的每个对象都必须按与 其关联的内部方法所规定的方式表现。具体如何做到这一点由实现决定。

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

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

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

本规范中,内部方法和内部槽使用置于双重方括号 [[ ]] 中的名称 标识。

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

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

  • 对于 Table 4 中列出的内部方法,该对象使用 10.1 中定义的方法。
  • 若该对象具有 [[Call]] 内部方法,则它使用 10.2.110.3.1 中定义的方法。
  • 若该对象具有 [[Construct]] 内部方法,则它使用 10.2.210.3.2 中定义的方法。

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

本规范通过对象的内部方法来识别不同种类的异质对象。若某对象在 行为上等价于某种特定异质对象(例如 Array 异质对象绑定函数异质对象), 但并不具备该种类所规定的同样一组内部方法,则不会被识别为那类异质对象

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

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

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

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

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

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

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

6.1.7.3 基本内部方法的不变量

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

实现所提供的任何异质对象也必须为这些对象维持这些不变量。 违反这些不变量可能导致 ECMAScript 代码出现不可预测的行为并引发安全 问题。然而,违反这些不变量绝不能破坏实现的内存安全。

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

定义:

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

返回值:

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

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

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

[[GetPrototypeOf]] ( )

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

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

[[SetPrototypeOf]] ( proto )

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

[[IsExtensible]] ( )

  • 正常返回类型是 Boolean。
  • [[IsExtensible]] 返回 false,则之后对该目标调用 [[IsExtensible]] 必须始终返回 false

[[PreventExtensions]] ( )

  • 正常返回类型是 Boolean。
  • [[PreventExtensions]] 返回 true,则之后对该目标调用 [[IsExtensible]] 必须始终返回 false,并且该目标现在被视为 不可扩展。

[[GetOwnProperty]] ( propertyKey )

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

由第三个不变量可知,若某属性被描述为数据属性,且它可能随时间 返回不同的值,那么即使没有通过其他基本内部方法暴露修改该值的机制, [[Writable]][[Configurable]] 特性中至少有一个必须为 true

[[DefineOwnProperty]] ( propertyKey, desc )

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

[[HasProperty]] ( propertyKey )

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

[[Get]] ( propertyKey, receiver )

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

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

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

[[Delete]] ( propertyKey )

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

[[OwnPropertyKeys]] ( )

  • 正常返回类型是 List
  • 返回的 List 不得包含重复项。
  • 返回的 List 中每个元素都必须是属性键
  • 返回的 List 至少必须包含所有先前已观察到的不可配置自有属性的 键。
  • 若目标不可扩展,则返回的 List 只能包含所有能通过 [[GetOwnProperty]] 观察到的该目标自有属性的键。

[[Call]] ( )

[[Construct]] ( )

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

6.1.7.4 众所周知的内在对象

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

在本规范中,诸如 %name% 这样的引用表示与当前 realm 关联的、 名称对应的那个内在对象。诸如 %name.a.b% 这样的引用表示:仿佛在任何 ECMAScript 代码求值之前,已经访问了内在对象 %name% 的属性 "a" 的 值的属性 "b"。当前 realm 及其内在值的确定见 9.4。众所周知的 内在值列于 Table 6 中。

Table 6: 众所周知的内在对象
内在名称 全局名称 ECMAScript 语言关联
%AggregateError% AggregateError AggregateError 构造器20.5.7.1
%Array% Array Array 构造器23.1.1
%ArrayBuffer% ArrayBuffer ArrayBuffer 构造器25.1.4
%ArrayIteratorPrototype% Array Iterator 对象的原型(23.1.5
%AsyncFromSyncIteratorPrototype% Async-from-Sync Iterator 对象的原型(27.1.5
%AsyncFunction% async function 对象的构造器27.7.1
%AsyncGeneratorFunction% async generator function 对象的构造器27.4.1
%AsyncGeneratorPrototype% async generator 对象的原型(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 Iterator 对象的原型(14.7.5.10
%Function% Function Function 构造器20.2.1
%GeneratorFunction% generator function 对象的构造器27.3.1
%GeneratorPrototype% generator 对象的原型(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% Iterator Helper 对象的原型(27.1.2.1
%JSON% JSON JSON 对象(25.5
%Map% Map Map 构造器24.1.1
%MapIteratorPrototype% Map Iterator 对象的原型(24.1.5
%Math% Math Math 对象(21.3
%Number% Number Number 构造器21.1.1
%Object% Object Object 构造器20.1.1
%parseFloat% parseFloat parseFloat 函数(19.2.4
%parseInt% parseInt parseInt 函数(19.2.5
%Promise% Promise Promise 构造器27.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 String Iterator 对象的原型(22.2.9
%Set% Set Set 构造器24.2.2
%SetIteratorPrototype% Set Iterator 对象的原型(24.2.6
%SharedArrayBuffer% SharedArrayBuffer SharedArrayBuffer 构造器25.2.3
%String% String String 构造器22.1.1
%StringIteratorPrototype% String Iterator 对象的原型(22.1.5
%Symbol% Symbol Symbol 构造器20.4.1
%SyntaxError% SyntaxError SyntaxError 构造器20.5.5.4
%ThrowTypeError% 一个函数对象,它会无条件抛出 %TypeError% 的新实例
%TypedArray% 所有 typed Array 构造器的超类(23.2.1
%TypeError% TypeError TypeError 构造器20.5.5.5
%Uint8Array% Uint8Array Uint8Array 构造器23.2
%Uint8ClampedArray% Uint8ClampedArray Uint8ClampedArray 构造器23.2
%Uint16Array% Uint16Array Uint16Array 构造器23.2
%Uint32Array% Uint32Array Uint32Array 构造器23.2
%URIError% URIError URIError 构造器20.5.5.6
%WeakMap% WeakMap WeakMap 构造器24.3.1
%WeakRef% WeakRef WeakRef 构造器26.1.1
%WeakSet% WeakSet WeakSet 构造器24.4.1
%WrapForValidIteratorPrototype% 由 Iterator.from 返回的包装迭代器对象的原型(27.1.3.2.2.1
Note

Table 98 中还有附加条目。

6.2 ECMAScript 规范类型

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

6.2.1 Enum 规范类型

Enum 是规范内部使用、而不能被 ECMAScript 代码直接观察到的值。Enum 使用全大写 kebab case,并以 sans-serif 字体表示。例如,Completion Record[[Type]] 字段会 取 normalreturnthrow 之类的值。Enum 除其名称外不具有 其他特征。Enum 的名称除了将其与其他 enum 区分开来之外没有别的用途, 也不暗示其在上下文中的用法或含义。

6.2.2 List 和 Record 规范类型

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

当算法遍历 List 的元素而未指定顺序时,所使用的顺序就是 List 中 元素的顺序。

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

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

对于 String 的 List,短语“按码元字典序排序”表示:按每个 码元的数值比较,比较到较短字符串的长度为止;若此前都相等,则较短字符串 排在较长字符串之前,正如抽象操作 IsLessThan 所描述的那样。

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

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

在规范文本和算法中,可使用点记法来引用 Record 值中的某个特定 字段。例如,若 R 是前一段所示的 record,则 R.[[Field2]] 是“R 中名为 [[Field2]] 的字段”的简写。

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

6.2.3 Set 和 Relation 规范类型

Set 类型用于说明内存模型中使用的无序元素集合。它不同于 同名的 ECMAScript 集合类型。为避免歧义,在本规范中,ECMAScript 集合的 实例一律称为 “Set objects”。Set 类型的值是元素的简单集合,其中不会有 元素重复出现。元素可以添加到 Set 中,也可以从 Set 中移除。Set 可以彼此 求并集、交集或差集。

Relation 类型用于说明 Set 上的 约束。Relation 类型的值是由其值域中的值组成的有序对的 Set。例如, 内存事件上的 Relation 是一组内存事件的有序对。对于一个 Relation R 以及 R 值域中的两个值 aba R b 是在说有序对 (a, b) 是 R 的成员的简写。若某个 Relation 在满足某些条件的 情况下是最小 Relation,则意味着它是 满足这些条件的最小的 Relation。

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

  • 对于 R 定义域中的所有 abc

    • 不存在 a R a,并且
    • a R bb R c,则 a R c
Note 1

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

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

  • 对于 R 定义域中的所有 abc

    • ab,或 a R b,或 b R a,并且
    • 不存在 a R a,并且
    • a R bb R c,则 a R c
Note 2

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

6.2.4 Completion Record 规范类型

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

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

Table 7: Completion Record 字段
字段名称 含义
[[Type]] normalbreakcontinuereturnthrow 发生的完成类型。
[[Value]] 任何值,但不能是 Completion Record 所产生的值。
[[Target]] 一个 String 或 empty 定向控制转移的目标标签。

下面这些简写术语有时用于指代 Completion Record。

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

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

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

6.2.4.1 NormalCompletion ( value )

The abstract operation NormalCompletion takes argument value (任何值,但不能是 Completion Record,) and returns 一个正常完成. It performs the following steps when called:

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

6.2.4.2 ThrowCompletion ( value )

The abstract operation ThrowCompletion takes argument value (一个 ECMAScript 语言值,) and returns 一个抛出完成. It performs the following steps when called:

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

6.2.4.3 ReturnCompletion ( value )

The abstract operation ReturnCompletion takes argument value (一个 ECMAScript 语言值,) and returns 一个 return 完成. It performs the following steps when called:

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

6.2.4.4 UpdateEmpty ( completionRecord, value )

The abstract operation UpdateEmpty takes arguments completionRecord (一个 Completion Record,) and value (任何值,但不能是 Completion Record,) and returns 一个 Completion Record. It performs the following steps when called:

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

6.2.5 Reference Record 规范类型

Reference Record 类型 用于说明诸如 deletetypeof、赋值运算符、super 关键字以及其他 语言特性的行为。例如,赋值表达式的左操作数预期会产生一个 Reference Record。

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

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

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

6.2.5.1 IsPropertyReference ( referenceRecord )

The abstract operation IsPropertyReference takes argument referenceRecord (一个 Reference Record,) and returns 一个 Boolean. It performs the following steps when called:

  1. referenceRecord.[[Base]]unresolvable,返回 false
  2. referenceRecord.[[Base]] 是一个 Environment Record, 返回 false
  3. 返回 true

6.2.5.2 IsUnresolvableReference ( referenceRecord )

The abstract operation IsUnresolvableReference takes argument referenceRecord (一个 Reference Record,) and returns 一个 Boolean. It performs the following steps when called:

  1. referenceRecord.[[Base]]unresolvable,返回 true
  2. 返回 false

6.2.5.3 IsSuperReference ( referenceRecord )

The abstract operation IsSuperReference takes argument referenceRecord (一个 Reference Record,) and returns 一个 Boolean. It performs the following steps when called:

  1. referenceRecord.[[ThisValue]]empty,返回 false
  2. 返回 true

6.2.5.4 IsPrivateReference ( referenceRecord )

The abstract operation IsPrivateReference takes argument referenceRecord (一个 Reference Record,) and returns 一个 Boolean. It performs the following steps when called:

  1. referenceRecord.[[ReferencedName]] 是一个 Private Name, 返回 true
  2. 返回 false

6.2.5.5 GetValue ( referenceRecord )

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

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

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

6.2.5.6 PutValue ( referenceRecord, value )

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

  1. referenceRecord 不是 Reference Record,抛出一个 ReferenceError 异常。
  2. IsUnresolvableReference(referenceRecord) 是 true,则
    1. referenceRecord.[[Strict]]true,抛出一个 ReferenceError 异常。
    2. globalObjGetGlobalObject()。
    3. 执行 ? Set(globalObj, referenceRecord.[[ReferencedName]], value, false)。
    4. 返回 unused
  3. IsPropertyReference(referenceRecord) 是 true,则
    1. baseObj 为 ? ToObject(referenceRecord.[[Base]])。
    2. IsPrivateReference(referenceRecord) 是 true,则
      1. 返回 ? PrivateSet(baseObj, referenceRecord.[[ReferencedName]], value)。
    3. referenceRecord.[[ReferencedName]] 不是属性键,则
      1. referenceRecord.[[ReferencedName]] 设为 ? ToPropertyKey(referenceRecord.[[ReferencedName]])。
    4. succeeded 为 ? baseObj.[[Set]](referenceRecord.[[ReferencedName]], value, GetThisValue(referenceRecord))
    5. succeededfalsereferenceRecord.[[Strict]]true,抛出一个 TypeError 异常。
    6. 返回 unused
  4. basereferenceRecord.[[Base]]
  5. 断言:base 是一个 Environment Record
  6. 返回 ? base.SetMutableBinding( referenceRecord.[[ReferencedName]], value, referenceRecord.[[Strict]])(见 9.1)。
Note

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

6.2.5.7 GetThisValue ( referenceRecord )

The abstract operation GetThisValue takes argument referenceRecord (一个 Reference Record,) and returns 一个 ECMAScript 语言值. It performs the following steps when called:

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

6.2.5.8 InitializeReferencedBinding ( referenceRecord, value )

The abstract operation InitializeReferencedBinding takes arguments referenceRecord (一个 Reference Record,) and value (一个 ECMAScript 语言值,) and returns 要么是包含 unused正常完成,要么是突兀完成. It performs the following steps when called:

  1. 断言:IsUnresolvableReference(referenceRecord) 是 false
  2. basereferenceRecord.[[Base]]
  3. 断言:base 是一个 Environment Record
  4. 返回 ? base.InitializeBinding( referenceRecord.[[ReferencedName]], value)。

6.2.5.9 MakePrivateReference ( baseValue, privateIdentifier )

The abstract operation MakePrivateReference takes arguments baseValue (一个 ECMAScript 语言值,) and privateIdentifier (一个 String,) and returns 一个 Reference Record. It performs the following steps when called:

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

6.2.6 Property Descriptor 规范类型

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

Property Descriptor 值还可以根据某些字段的存在或使用进一步分为 数据 Property Descriptor 和访问器 Property Descriptor。数据 Property Descriptor 是包含名为 [[Value]][[Writable]] 的任一字段 的 Property Descriptor。访问器 Property Descriptor 是包含名为 [[Get]][[Set]] 的任一字段的 Property Descriptor。任何 Property Descriptor 都可以包含名为 [[Enumerable]][[Configurable]] 的字段。一个 Property Descriptor 值不能同时既是数据 Property Descriptor 又是访问器 Property Descriptor;不过,它也可以两者都不是 (此时称为通用 Property Descriptor)。完整填充的 Property Descriptor 是指:它要么是访问器 Property Descriptor,要么是 数据 Property Descriptor,并且具有 Table 3 中定义的所有对应字段。

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

6.2.6.1 IsAccessorDescriptor ( desc )

The abstract operation IsAccessorDescriptor takes argument desc (一个 Property Descriptor,) and returns 一个 Boolean. It performs the following steps when called:

  1. desc 具有 [[Get]] 字段,返回 true
  2. desc 具有 [[Set]] 字段,返回 true
  3. 返回 false

6.2.6.2 IsDataDescriptor ( desc )

The abstract operation IsDataDescriptor takes argument desc (一个 Property Descriptor,) and returns 一个 Boolean. It performs the following steps when called:

  1. desc 具有 [[Value]] 字段,返回 true
  2. desc 具有 [[Writable]] 字段,返回 true
  3. 返回 false

6.2.6.3 IsGenericDescriptor ( desc )

The abstract operation IsGenericDescriptor takes argument desc (一个 Property Descriptor,) and returns 一个 Boolean. It performs the following steps when called:

  1. IsAccessorDescriptor(desc) 是 true,返回 false
  2. IsDataDescriptor(desc) 是 true,返回 false
  3. 返回 true

6.2.6.4 FromPropertyDescriptor ( desc )

The abstract operation FromPropertyDescriptor takes argument desc (一个 Property Descriptorundefined,) and returns 一个 Object 或 undefined. It performs the following steps when called:

  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 )

The abstract operation ToPropertyDescriptor takes argument obj (一个 ECMAScript 语言值,) and returns 要么是包含 Property Descriptor正常完成,要么是抛出完成. It performs the following steps when called:

  1. obj 不是 Object,抛出一个 TypeError 异常。
  2. desc 为一个新的 Property Descriptor,初始时没有任何 字段。
  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 )

The abstract operation CompletePropertyDescriptor takes argument desc (一个 Property Descriptor,) and returns unused. It performs the following steps when called:

  1. likeRecord { [[Value]]: undefined, [[Writable]]: false, [[Get]]: undefined, [[Set]]: undefined, [[Enumerable]]: false, [[Configurable]]: false }。
  2. IsGenericDescriptor(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 Environment Record 规范类型

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

6.2.8 Abstract Closure 规范类型

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

在创建 Abstract Closure 的算法步骤中,值通过动词 “capture” 后跟一组别名来捕获。当创建 Abstract Closure 时,它会捕获当时与每个 别名相关联的值。在规定调用 Abstract Closure 时应执行的算法步骤中, 每个被捕获的值都通过用来捕获它的那个别名来引用。

若某个 Abstract Closure 返回 Completion Record,那么该 Completion Record 必须是正常完成或抛出完成之一。

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

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

6.2.9 Data Block

Data Block 规范类型用于描述一段 独立且可变的、由字节大小(8 位)数值构成的序列。字节值是位于 0 到 255 闭区间内的整数。一个 Data Block 值在创建时具有固定数量的字节,这些字节的初始值都为 0。

为便于本规范中的记号表达,可以使用类似数组的语法来访问 Data Block 值中的单个字节。该记法将 Data Block 值表现为一个以 0 为起始索引 的字节序列。比如,若 db 是一个 5 字节的 Data Block 值,则可使用 db[2] 来访问它的第 3 个字节。

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

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

Shared Data Block 事件通过 Record 建模,其定义见内存模型

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

6.2.9.1 CreateByteDataBlock ( size )

The abstract operation CreateByteDataBlock takes argument size (一个非负整数,) and returns 要么是包含 Data Block正常完成,要么是抛出完成. It performs the following steps when called:

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

6.2.9.2 CreateSharedByteDataBlock ( size )

The abstract operation CreateSharedByteDataBlock takes argument size (一个非负整数,) and returns 要么是包含 Shared Data Block正常完成,要么是抛出完成. It performs the following steps when called:

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

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

The abstract operation CopyDataBlockBytes takes arguments toBlock (一个 Data BlockShared Data Block,), toIndex (一个非负整数,), fromBlock (一个 Data BlockShared Data Block,), fromIndex (一个非负整数,), and count (一个非负整数,) and returns unused. It performs the following steps when called:

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

6.2.10 PrivateElement 规范类型

PrivateElement 类型是一个 Record,用于私有类字段、方法和访问器 的规范说明。尽管私有元素不使用 Property Descriptor,但私有字段的行为 类似于不可配置、不可枚举、可写的数据属性,私有方法的行为类似于不可配置、 不可枚举、不可写的数据属性,而私有访问器的行为类似于不可配置、不可枚举 的访问器属性

PrivateElement 类型的值是字段由 Table 9 定义的 Record 值。此类值 被称为 PrivateElements

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

6.2.11 ClassFieldDefinition Record 规范类型

ClassFieldDefinition 类型是一个 Record,用于类字段的规范说明。

ClassFieldDefinition 类型的值是字段由 Table 10 定义的 Record 值。 此类值被称为 ClassFieldDefinition Record

Table 10: ClassFieldDefinition Record 字段
字段名称 含义
[[Name]] 一个 Private Name、一个 String 或一个 Symbol 字段的名称。
[[Initializer]] 一个 ECMAScript 函数对象empty 字段的初始化器(若存在)。

6.2.12 Private Name

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

6.2.13 ClassStaticBlockDefinition Record 规范类型

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

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

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

7 抽象操作

这些操作不是 ECMAScript 语言的一部分;它们在这里只是为了帮助描述 ECMAScript 语言语义的规范而定义的。本规范的其他部分还定义了更多、更专门的抽象操作

7.1 类型转换

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

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

7.1.1 ToPrimitive ( input [ , preferredType ] )

The abstract operation ToPrimitive takes argument input (一个 ECMAScript 语言值,) and optional argument preferredType (stringnumber,) and returns 要么是包含 ECMAScript 语言值正常完成,要么是抛出完成. 它将其参数 input 转换为非 Object 类型。若某个对象能够转换为多种原始类型,则它可以使用可选提示 preferredType 来优先选择该类型。 It performs the following steps when called:

  1. 如果 input 是一个 Object,那么
    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 不是一个 Object,返回 result
      6. 抛出一个 TypeError 异常。
    3. 如果 preferredType 不存在,将 preferredType 设为 number
    4. 返回 ? OrdinaryToPrimitive(input, preferredType)。
  2. 返回 input
Note

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

7.1.1.1 OrdinaryToPrimitive ( obj, hint )

The abstract operation OrdinaryToPrimitive takes arguments obj (一个 Object,) and hint (stringnumber,) and returns 要么是包含 ECMAScript 语言值正常完成,要么是抛出完成. It performs the following steps when called:

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

7.1.2 ToBoolean ( argument )

The abstract operation ToBoolean takes argument argument (一个 ECMAScript 语言值,) and returns 一个 Boolean. 它将 argument 转换为 Boolean 类型的值。 It performs the following steps when called:

  1. 如果 argument 是 Boolean,返回 argument
  2. 如果 argumentundefinednull+0𝔽-0𝔽NaN0 或空 String 之一,返回 false
  3. Normative Optional
    如果宿主是网页浏览器,或以其他方式支持 [[IsHTMLDDA]] 内部槽,那么
    1. 如果 argument 是一个 Object,且 argument 拥有 [[IsHTMLDDA]] 内部槽,返回 false
  4. 返回 true

7.1.3 ToNumeric ( value )

The abstract operation ToNumeric takes argument value (一个 ECMAScript 语言值,) and returns 要么是包含 Number 或 BigInt 的正常完成,要么是抛出完成. 它返回转换为 Number 或 BigInt 的 value。 It performs the following steps when called:

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

7.1.4 ToNumber ( argument )

The abstract operation ToNumber takes argument argument (一个 ECMAScript 语言值,) and returns 要么是包含 Number 的正常完成,要么是抛出完成. 它将 argument 转换为 Number 类型的值。 It performs the following steps when called:

  1. 如果 argument 是 Number,返回 argument
  2. 如果 argument 是 Symbol 或 BigInt 之一,抛出一个 TypeError 异常。
  3. 如果 argumentundefined,返回 NaN
  4. 如果 argumentnullfalse 之一,返回 +0𝔽
  5. 如果 argumenttrue,返回 1𝔽
  6. 如果 argument 是 String,返回 StringToNumber(argument)。
  7. 断言:argument 是一个 Object。
  8. primValue 为 ? ToPrimitive(argument, number)。
  9. 断言:primValue 不是一个 Object。
  10. 返回 ? ToNumber(primValue)。

7.1.4.1 应用于 String 类型的 ToNumber

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

语法

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

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

Note

StringNumericLiteral 的语法与 NumericLiteral 的语法之间有一些差异需要注意:

7.1.4.1.1 StringToNumber ( str )

The abstract operation StringToNumber takes argument str (一个 String,) and returns 一个 Number. It performs the following steps when called:

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

7.1.4.1.2 Runtime Semantics: StringNumericValue

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

Note

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

It is defined piecewise over the following productions:

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

7.1.4.1.3 RoundMVResult ( n )

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

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

7.1.5 ToIntegerOrInfinity ( argument )

The abstract operation ToIntegerOrInfinity takes argument argument (一个 ECMAScript 语言值,) and returns 要么是包含整数、+∞ 或 -∞ 的正常完成,要么是抛出完成. 它将 argument 转换为一个整数,该整数表示其 Number 值去掉小数部分后的结果;如果该 Number 值是无穷大,则转换为 +∞ 或 -∞。 It performs the following steps when called:

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

7.1.6 ToFixedSizeInteger ( int, signed, bitWidth )

The abstract operation ToFixedSizeInteger takes arguments int (一个整数、+∞ 或 -∞), signed (unsignedsigned), and bitWidth (一个正整数) and returns 一个整数. 它将 int 映射到 2bitWidth整数之一;如果 signedunsigned,则该整数位于从 0 到 2bitWidth - 1 的闭区间内;如果 signedsigned,则该整数位于从 -2bitWidth - 1 到 2bitWidth - 1 - 1 的闭区间内。 It performs the following steps when called:

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

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

7.1.7 ToInt32 ( argument )

The abstract operation ToInt32 takes argument argument (一个 ECMAScript 语言值) and returns 要么是一个包含整数 Number正常完成,要么是一个 throw 完成. 它将 argument 转换为 232整数 Number 值之一,该值位于从 𝔽(-231) 到 𝔽(231 - 1) 的闭区间内,不包括 -0𝔽。 It performs the following steps when called:

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

7.1.8 ToUint32 ( argument )

The abstract operation ToUint32 takes argument argument (一个 ECMAScript 语言值) and returns 要么是一个包含整数 Number正常完成,要么是一个 throw 完成. 它将 argument 转换为 232整数 Number 值之一,该值位于从 +0𝔽𝔽(232 - 1) 的闭区间内。 It performs the following steps when called:

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

7.1.9 ToInt16 ( argument )

The abstract operation ToInt16 takes argument argument (一个 ECMAScript 语言值) and returns 要么是一个包含整数 Number正常完成,要么是一个 throw 完成. 它将 argument 转换为 216整数 Number 值之一,该值位于从 𝔽(-215) 到 𝔽(215 - 1) 的闭区间内,不包括 -0𝔽。 It performs the following steps when called:

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

7.1.10 ToUint16 ( argument )

The abstract operation ToUint16 takes argument argument (一个 ECMAScript 语言值) and returns 要么是一个包含整数 Number正常完成,要么是一个 throw 完成. 它将 argument 转换为 216整数 Number 值之一,该值位于从 +0𝔽𝔽(216 - 1) 的闭区间内。 It performs the following steps when called:

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

7.1.11 ToInt8 ( argument )

The abstract operation ToInt8 takes argument argument (一个 ECMAScript 语言值) and returns 要么是一个包含整数 Number正常完成,要么是一个 throw 完成. 它将 argument 转换为 28整数 Number 值之一,该值位于从 -128𝔽127𝔽闭区间内,不包括 -0𝔽。 It performs the following steps when called:

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

7.1.12 ToUint8 ( argument )

The abstract operation ToUint8 takes argument argument (一个 ECMAScript 语言值) and returns 要么是一个包含整数 Number正常完成,要么是一个 throw 完成. 它将 argument 转换为 28整数 Number 值之一,该值位于从 +0𝔽255𝔽闭区间内。 It performs the following steps when called:

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

7.1.13 ToUint8Clamp ( argument )

The abstract operation ToUint8Clamp takes argument argument (一个 ECMAScript 语言值) and returns 要么是一个包含整数 Number正常完成,要么是一个 throw 完成. 它将 argument 钳制并舍入为 28整数 Number 值之一,该值位于从 +0𝔽255𝔽闭区间内。 It performs the following steps when called:

  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)。
  9. 返回 𝔽(f + 1)。
Note

与大多数其他 ECMAScript 整数转换操作不同,ToUint8Clamp 会对非整数值进行舍入,而不是截断。它还使用“向偶数舍入一半”的平局决胜规则,这不同于 Math.round 的“向上舍入一半”平局决胜规则。

7.1.14 ToBigInt ( argument )

The abstract operation ToBigInt takes argument argument (一个 ECMAScript 语言值) and returns 要么是一个包含 BigInt 的正常完成,要么是一个 throw 完成. 它将 argument 转换为 BigInt 值;如果需要从 Number 进行隐式转换,则抛出异常。 It performs the following steps when called:

  1. prim 为 ? ToPrimitive(argument, number)。
  2. 返回 primTable 12 中所对应的值。
Table 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.15 StringToBigInt ( str )

The abstract operation StringToBigInt takes argument str (一个 String) and returns 一个 BigInt 或 undefined. It performs the following steps when called:

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

7.1.15.1 StringIntegerLiteral 文法

StringToBigInt 使用以下文法。

语法

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

7.1.15.2 运行时语义:MV

7.1.16 ToBigInt64 ( argument )

The abstract operation ToBigInt64 takes argument argument (一个 ECMAScript 语言值) and returns 要么是一个包含 BigInt 的正常完成,要么是一个 throw 完成. 它将 argument 转换为 264BigInt 值之一,该值位于从 (-263) 到 (263 - 1) 的闭区间内。 It performs the following steps when called:

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

7.1.17 ToBigUint64 ( argument )

The abstract operation ToBigUint64 takes argument argument (一个 ECMAScript 语言值) and returns 要么是一个包含 BigInt 的正常完成,要么是一个 throw 完成. 它将 argument 转换为 264BigInt 值之一,该值位于从 0(264 - 1) 的闭区间内。 It performs the following steps when called:

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

7.1.18 ToString ( argument )

The abstract operation ToString takes argument argument (一个 ECMAScript 语言值) and returns 要么是一个包含 String 的正常完成,要么是一个 throw 完成. 它将 argument 转换为 String 类型的值。 It performs the following steps when called:

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

7.1.19 ToObject ( argument )

The abstract operation ToObject takes argument argument (一个 ECMAScript 语言值) and returns 要么是一个包含 Object 的正常完成,要么是一个 throw 完成. 它将 argument 转换为 Object 类型的值。 It performs the following steps when called:

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

7.1.20 ToPropertyKey ( argument )

The abstract operation ToPropertyKey takes argument argument (一个 ECMAScript 语言值) and returns 要么是一个包含属性键正常完成,要么是一个 throw 完成. 它将 argument 转换为可用作属性键的值。 It performs the following steps when called:

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

7.1.21 ToLength ( argument )

The abstract operation ToLength takes argument argument (一个 ECMAScript 语言值) and returns 要么是一个包含非负整数 Number正常完成,要么是一个 throw 完成. 它将 argument 钳制并截断为适合用作类数组对象长度的非负整数 Number。 It performs the following steps when called:

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

7.1.22 CanonicalNumericIndexString ( argument )

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

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

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

7.1.23 ToIndex ( value )

The abstract operation ToIndex takes argument value (一个 ECMAScript 语言值,) and returns 要么是包含非负整数正常完成,要么是抛出完成. 它将 value 转换为整数,并且如果该整数是非负且对应于一个整数索引,则返回该整数。否则,抛出异常。 It performs the following steps when called:

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

7.2 测试与比较操作

7.2.1 RequireObjectCoercible ( argument )

The abstract operation RequireObjectCoercible takes argument argument (一个 ECMAScript 语言值,) and returns 要么是包含 unused正常完成,要么是抛出完成. 如果 argument 是一个无法使用 ToObject 转换为 Object 的值,它就抛出错误。 It performs the following steps when called:

  1. 如果 argumentundefinednull 之一,抛出一个 TypeError 异常。
  2. 返回 unused

7.2.2 IsArray ( argument )

The abstract operation IsArray takes argument argument (一个 ECMAScript 语言值,) and returns 要么是包含 Boolean 的正常完成,要么是抛出完成. It performs the following steps when called:

  1. 如果 argument 不是一个 Object,返回 false
  2. 如果 argument 是一个 Array 异质对象,返回 true
  3. 如果 argument 是一个 Proxy 异质对象,那么
    1. 执行 ? ValidateNonRevokedProxy(argument)。
    2. proxyTargetargument.[[ProxyTarget]]
    3. 返回 ? IsArray(proxyTarget)。
  4. 返回 false

7.2.3 IsCallable ( argument )

The abstract operation IsCallable takes argument argument (一个 ECMAScript 语言值,) and returns 一个 Boolean. 它判定 argument 是否为具有 [[Call]] 内部方法的可调用函数。 It performs the following steps when called:

  1. 如果 argument 不是一个 Object,返回 false
  2. 如果 argument 拥有 [[Call]] 内部方法,返回 true
  3. 返回 false

7.2.4 IsConstructor ( argument )

The abstract operation IsConstructor takes argument argument (一个 ECMAScript 语言值,) and returns 一个 Boolean. 它判定 argument 是否为具有 [[Construct]] 内部方法的函数对象。 It performs the following steps when called:

  1. 如果 argument 不是一个 Object,返回 false
  2. 如果 argument 拥有 [[Construct]] 内部方法,返回 true
  3. 返回 false

7.2.5 IsExtensible ( obj )

The abstract operation IsExtensible takes argument obj (一个 Object,) and returns 要么是包含 Boolean 的正常完成,要么是抛出完成. 它用于确定是否可以向 obj 添加额外属性。 It performs the following steps when called:

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

7.2.6 IsRegExp ( argument )

The abstract operation IsRegExp takes argument argument (一个 ECMAScript 语言值,) and returns 要么是包含 Boolean 的正常完成,要么是抛出完成. It performs the following steps when called:

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

7.2.7 Static Semantics: IsStringWellFormedUnicode ( string )

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

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

7.2.8 SameType ( x, y )

The abstract operation SameType takes arguments x (一个 ECMAScript 语言值,) and y (一个 ECMAScript 语言值,) and returns 一个 Boolean. 它判定两个参数是否属于同一类型。 It performs the following steps when called:

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

7.2.9 SameValue ( x, y )

The abstract operation SameValue takes arguments x (一个 ECMAScript 语言值,) and y (一个 ECMAScript 语言值,) and returns 一个 Boolean. 它判定两个参数是否是同一个值。 It performs the following steps when called:

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

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

7.2.10 SameValueZero ( x, y )

The abstract operation SameValueZero takes arguments x (一个 ECMAScript 语言值,) and y (一个 ECMAScript 语言值,) and returns 一个 Boolean. 它判定两个参数是否是同一个值(忽略 +0𝔽-0𝔽 之间的差异)。 It performs the following steps when called:

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

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

7.2.11 SameValueNonNumber ( x, y )

The abstract operation SameValueNonNumber takes arguments x (一个 ECMAScript 语言值,但不是 Number,) and y (一个 ECMAScript 语言值,但不是 Number,) and returns 一个 Boolean. It performs the following steps when called:

  1. 断言:SameType(x, y) 是 true
  2. 如果 xundefinednull 之一,返回 true
  3. 如果 x 是 BigInt,那么
    1. 返回 BigInt::equal(x, y)。
  4. 如果 x 是 String,那么
    1. 如果 xy 长度相同,且在相同位置拥有相同码元,返回 true
    2. 返回 false
  5. 如果 x 是 Boolean,那么
    1. 如果 xtrueytrue,返回 true
    2. 如果 xfalseyfalse,返回 true
    3. 返回 false
  6. 注:所有其他 ECMAScript 语言值都按标识进行比较。
  7. 如果 xy,返回 true
  8. 返回 false
Note 1
出于说明目的,本算法中某些情况被单独处理,即使这样做并非必要。
Note 2
xy” 的具体含义详见 5.2.8

7.2.12 IsLessThan ( x, y, leftFirst )

The abstract operation IsLessThan takes arguments x (一个 ECMAScript 语言值,), y (一个 ECMAScript 语言值,), and leftFirst (一个 Boolean,) and returns 要么是包含 Boolean 或 undefined正常完成,要么是抛出完成. 它为比较 x < y 提供语义,返回 truefalseundefined(表示操作数无法被强制转换为同一数值类型的可比较值)。leftFirst 标志用于控制对 xy 执行具有潜在可见副作用的操作的顺序。这是必要的,因为 ECMAScript 规定表达式从左到右求值。如果 leftFirsttrue,则 x 参数对应于出现在 y 参数对应表达式左侧的表达式。如果 leftFirstfalse,则情况相反,必须先对 y 执行操作,再对 x 执行操作。 It performs the following steps when called:

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

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

Note 2

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

7.2.13 IsLooselyEqual ( x, y )

The abstract operation IsLooselyEqual takes arguments x (一个 ECMAScript 语言值,) and y (一个 ECMAScript 语言值,) and returns 要么是包含 Boolean 的正常完成,要么是抛出完成. 它提供 == 运算符的语义。 It performs the following steps when called:

  1. 如果 SameType(x, y) 是 true,那么
    1. 返回 IsStrictlyEqual(x, y)。
  2. 如果 xnullyundefined,返回 true
  3. 如果 xundefinedynull,返回 true
  4. Normative Optional
    如果宿主是网页浏览器,或以其他方式支持 [[IsHTMLDDA]] 内部槽,那么
    1. 如果 x 是一个 Object,x 拥有 [[IsHTMLDDA]] 内部槽,且 yundefinednull 之一,返回 true
    2. 如果 xundefinednull 之一,y 是一个 Object,且 y 拥有 [[IsHTMLDDA]] 内部槽,返回 true
  5. 如果 x 是 Number 且 y 是 String,返回 ! IsLooselyEqual(x, ! ToNumber(y))。
  6. 如果 x 是 String 且 y 是 Number,返回 ! IsLooselyEqual(! ToNumber(x), y)。
  7. 如果 x 是 BigInt 且 y 是 String,那么
    1. nStringToBigInt(y)。
    2. 如果 nundefined,返回 false
    3. 返回 ! IsLooselyEqual(x, n)。
  8. 如果 x 是 String 且 y 是 BigInt,返回 ! IsLooselyEqual(y, x)。
  9. 如果 x 是 Boolean,返回 ! IsLooselyEqual(! ToNumber(x), y)。
  10. 如果 y 是 Boolean,返回 ! IsLooselyEqual(x, ! ToNumber(y))。
  11. 如果 x 是 String、Number、BigInt 或 Symbol 之一,而 y 是 Object,返回 ! IsLooselyEqual(x, ? ToPrimitive(y))。
  12. 如果 x 是 Object,而 y 是 String、Number、BigInt 或 Symbol 之一,返回 ! IsLooselyEqual(? ToPrimitive(x), y)。
  13. 如果 x 是 BigInt 且 y 是 Number,或 x 是 Number 且 y 是 BigInt,那么
    1. 如果 x 不是有限值或 y 不是有限值,返回 false
    2. 如果 (x) = (y),返回 true
    3. 返回 false
  14. 返回 false

7.2.14 IsStrictlyEqual ( x, y )

The abstract operation IsStrictlyEqual takes arguments x (一个 ECMAScript 语言值,) and y (一个 ECMAScript 语言值,) and returns 一个 Boolean. 它提供 === 运算符的语义。 It performs the following steps when called:

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

该算法与 SameValue 算法的不同之处在于它对有符号零和 NaN 的处理。

7.3 对象上的操作

7.3.1 MakeBasicObject ( internalSlotsList )

The abstract operation MakeBasicObject takes argument internalSlotsList (一个内部槽名称的 List,) and returns 一个 Object. 它是一切通过算法创建的 ECMAScript 对象的来源,包括普通对象异质对象。它提取了创建所有对象时都会用到的共同步骤,并集中处理对象创建。 It performs the following steps when called:

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

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

7.3.2 Get ( obj, propertyKey )

The abstract operation Get takes arguments obj (一个 Object,) and propertyKey (一个属性键,) and returns 要么是包含 ECMAScript 语言值正常完成,要么是抛出完成. 它用于获取对象某个特定属性的值。 It performs the following steps when called:

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

7.3.3 GetV ( value, propertyKey )

The abstract operation GetV takes arguments value (一个 ECMAScript 语言值,) and propertyKey (一个属性键,) and returns 要么是包含 ECMAScript 语言值正常完成,要么是抛出完成. 它用于获取某个 ECMAScript 语言值的特定属性的值。如果该值不是对象,则属性查找会使用适合该值类型的包装对象来执行。 It performs the following steps when called:

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

7.3.4 Set ( obj, propertyKey, value, throw )

The abstract operation Set takes arguments obj (一个 Object,), propertyKey (一个属性键,), value (一个 ECMAScript 语言值,), and throw (一个 Boolean,) and returns 要么是包含 unused正常完成,要么是抛出完成. 它用于设置对象某个特定属性的值。value 是该属性的新值。 It performs the following steps when called:

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

7.3.5 CreateDataProperty ( obj, propertyKey, value )

The abstract operation CreateDataProperty takes arguments obj (一个 Object,), propertyKey (一个属性键,), and value (一个 ECMAScript 语言值,) and returns 要么是包含 Boolean 的正常完成,要么是抛出完成. 它用于创建对象的一个新的自有属性。 It performs the following steps when called:

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

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

7.3.6 CreateDataPropertyOrThrow ( obj, propertyKey, value )

The abstract operation CreateDataPropertyOrThrow takes arguments obj (一个 Object,), propertyKey (一个属性键,), and value (一个 ECMAScript 语言值,) and returns 要么是包含 unused正常完成,要么是抛出完成. 它用于创建对象的一个新的自有属性。如果所请求的属性更新无法执行,它会抛出 TypeError 异常。 It performs the following steps when called:

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

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

7.3.7 CreateNonEnumerableDataPropertyOrThrow ( obj, propertyKey, value )

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

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

抽象操作创建的属性,其特性被设为与 ECMAScript 语言赋值运算符所创建属性相同的默认值,只是它不可枚举。通常,该属性原本并不存在。如果它已存在,DefinePropertyOrThrow 保证会正常完成

7.3.8 DefinePropertyOrThrow ( obj, propertyKey, desc )

The abstract operation DefinePropertyOrThrow takes arguments obj (一个 Object,), propertyKey (一个属性键,), and desc (一个 Property Descriptor,) and returns 要么是包含 unused正常完成,要么是抛出完成. 它用于以一种在所请求的属性更新无法执行时会抛出 TypeError 异常的方式,调用对象的 [[DefineOwnProperty]] 内部方法。 It performs the following steps when called:

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

7.3.9 DeletePropertyOrThrow ( obj, propertyKey )

The abstract operation DeletePropertyOrThrow takes arguments obj (一个 Object,) and propertyKey (一个属性键,) and returns 要么是包含 unused正常完成,要么是抛出完成. 它用于移除对象的一个特定自有属性。如果该属性不可配置,它会抛出异常。 It performs the following steps when called:

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

7.3.10 GetMethod ( value, propertyKey )

The abstract operation GetMethod takes arguments value (一个 ECMAScript 语言值,) and propertyKey (一个属性键,) and returns 要么是包含函数对象undefined正常完成,要么是抛出完成. 它用于在期望属性值为函数时,获取某个 ECMAScript 语言值的特定属性值。 It performs the following steps when called:

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

7.3.11 HasProperty ( obj, propertyKey )

The abstract operation HasProperty takes arguments obj (一个 Object,) and propertyKey (一个属性键,) and returns 要么是包含 Boolean 的正常完成,要么是抛出完成. 它用于判定对象是否具有指定属性键的属性。该属性可以是自有属性,也可以是继承属性。 It performs the following steps when called:

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

7.3.12 HasOwnProperty ( obj, propertyKey )

The abstract operation HasOwnProperty takes arguments obj (一个 Object,) and propertyKey (一个属性键,) and returns 要么是包含 Boolean 的正常完成,要么是抛出完成. 它用于判定对象是否具有指定属性键的自有属性。 It performs the following steps when called:

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

7.3.13 Call ( func, thisValue [ , argumentsList ] )

The abstract operation Call takes arguments func (一个 ECMAScript 语言值,) and thisValue (一个 ECMAScript 语言值,) and optional argument argumentsList (一个 ECMAScript 语言值List,) and returns 要么是包含 ECMAScript 语言值正常完成,要么是抛出完成. 它用于调用函数对象[[Call]] 内部方法。func函数对象thisValue 是一个 ECMAScript 语言值,它是 [[Call]]this 值,而 argumentsList 是传给该内部方法对应参数的值。如果 argumentsList 不存在,则使用一个新的空 List 作为其值。 It performs the following steps when called:

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

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

The abstract operation Construct takes argument constructor (一个构造器,) and optional arguments argumentsList (一个 ECMAScript 语言值List,) and newTarget (一个构造器,) and returns 要么是包含 Object 的正常完成,要么是抛出完成. 它用于调用函数对象[[Construct]] 内部方法。argumentsListnewTarget 是要作为内部方法对应参数传入的值。如果 argumentsList 不存在,则使用一个新的空 List 作为其值。如果 newTarget 不存在,则使用 constructor 作为其值。 It performs the following steps when called:

  1. 如果 newTarget 不存在,将 newTarget 设为 constructor
  2. 如果 argumentsList 不存在,将 argumentsList 设为一个新的空 List
  3. 返回 ? constructor.[[Construct]](argumentsList, newTarget)
Note

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

7.3.15 SetIntegrityLevel ( obj, level )

The abstract operation SetIntegrityLevel takes arguments obj (一个 Object,) and level (sealedfrozen,) and returns 要么是包含 Boolean 的正常完成,要么是抛出完成. 它用于固定一个对象的自有属性集合。 It performs the following steps when called:

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

7.3.16 TestIntegrityLevel ( obj, level )

The abstract operation TestIntegrityLevel takes arguments obj (一个 Object,) and level (sealedfrozen,) and returns 要么是包含 Boolean 的正常完成,要么是抛出完成. 它用于判定对象的自有属性集合是否已经固定。 It performs the following steps when called:

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

7.3.17 CreateArrayFromList ( elements )

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

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

7.3.18 LengthOfArrayLike ( obj )

The abstract operation LengthOfArrayLike takes argument obj (一个 Object,) and returns 要么是包含非负整数正常完成,要么是抛出完成. 它返回类数组对象的 "length" 属性值。 It performs the following steps when called:

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

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

Note 1
通常,类数组对象也会有一些以整数索引名称命名的属性。不过,这不是该定义的要求。
Note 2
Array 和 String 对象都是类数组对象的例子。

7.3.19 CreateListFromArrayLike ( obj [ , validElementTypes ] )

The abstract operation CreateListFromArrayLike takes argument obj (一个 ECMAScript 语言值,) and optional argument validElementTypes (allproperty-key,) and returns 要么是包含 ECMAScript 语言值List正常完成,要么是抛出完成. 它用于创建一个 List,其元素由 obj 的索引属性提供。validElementTypes 指示哪些类型的值允许作为元素。 It performs the following steps when called:

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

7.3.20 Invoke ( value, propertyKey [ , argumentsList ] )

The abstract operation Invoke takes arguments value (一个 ECMAScript 语言值,) and propertyKey (一个属性键,) and optional argument argumentsList (一个 ECMAScript 语言值List,) and returns 要么是包含 ECMAScript 语言值正常完成,要么是抛出完成. 它用于调用某个 ECMAScript 语言值的方法属性。value 同时充当该属性的查找起点和调用时的 this 值。argumentsList 是传给该方法的参数值列表。如果 argumentsList 不存在,则使用一个新的空 List 作为其值。 It performs the following steps when called:

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

7.3.21 OrdinaryHasInstance ( constructor, instance )

The abstract operation OrdinaryHasInstance takes arguments constructor (一个 ECMAScript 语言值,) and instance (一个 ECMAScript 语言值,) and returns 要么是包含 Boolean 的正常完成,要么是抛出完成. 它实现默认算法,用于判定 instance 是否继承自由 constructor 提供的实例对象继承路径。 It performs the following steps when called:

  1. 如果 IsCallable(constructor) 是 false,返回 false
  2. 如果 constructor 拥有 [[BoundTargetFunction]] 内部槽,那么
    1. boundConstructorconstructor.[[BoundTargetFunction]]
    2. 返回 ? InstanceofOperator(instance, boundConstructor)。
  3. 如果 instance 不是一个 Object,返回 false
  4. proto 为 ? Get(constructor, "prototype")。
  5. 如果 proto 不是一个 Object,抛出一个 TypeError 异常。
  6. 重复,
    1. instance 设为 ? instance.[[GetPrototypeOf]]()
    2. 如果 instancenull,返回 false
    3. 如果 SameValue(proto, instance) 是 true,返回 true

7.3.22 SpeciesConstructor ( obj, defaultConstructor )

The abstract operation SpeciesConstructor takes arguments obj (一个 Object,) and defaultConstructor (一个构造器,) and returns 要么是包含构造器正常完成,要么是抛出完成. 它用于获取应当用来创建派生自 obj 的新对象的构造器。如果从 obj 开始无法找到构造器%Symbol.species% 属性,则使用 defaultConstructor 作为构造器。 It performs the following steps when called:

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

7.3.23 EnumerableOwnProperties ( obj, kind )

The abstract operation EnumerableOwnProperties takes arguments obj (一个 Object,) and kind (keyvaluekey+value,) and returns 要么是包含 ECMAScript 语言值List正常完成,要么是抛出完成. It performs the following steps when called:

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

7.3.24 GetFunctionRealm ( func )

The abstract operation GetFunctionRealm takes argument func (一个函数对象,) and returns 要么是包含 Realm Record正常完成,要么是抛出完成. It performs the following steps when called:

  1. 如果 func 拥有 [[Realm]] 内部槽,那么
    1. 返回 func.[[Realm]]
  2. 如果 func 是一个绑定函数异质对象,那么
    1. boundTargetFunctionfunc.[[BoundTargetFunction]]
    2. 返回 ? GetFunctionRealm(boundTargetFunction)。
  3. 如果 func 是一个 Proxy 异质对象,那么
    1. 执行 ? ValidateNonRevokedProxy(func)。
    2. proxyTargetfunc.[[ProxyTarget]]
    3. 断言:proxyTarget 是一个函数对象
    4. 返回 ? GetFunctionRealm(proxyTarget)。
  4. 返回当前 Realm Record
Note

步骤 4 仅会在 func 是不具有 [[Realm]] 内部槽的非标准函数异质对象时被执行到。

7.3.25 CopyDataProperties ( target, source, excludedItems )

The abstract operation CopyDataProperties takes arguments target (一个 Object,), source (一个 ECMAScript 语言值,), and excludedItems (一个属性键List,) and returns 要么是包含 unused正常完成,要么是抛出完成. It performs the following steps when called:

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

这里传入的 target 始终是一个新创建的对象,因此在抛出错误的情况下它不能被直接访问。

7.3.26 PrivateElementFind ( obj, privateName )

The abstract operation PrivateElementFind takes arguments obj (一个 Object,) and privateName (一个 Private Name,) and returns 一个 PrivateElementempty. It performs the following steps when called:

  1. 如果 obj.[[PrivateElements]] 包含某个 PrivateElement pe,且 pe.[[Key]]privateName,那么
    1. 返回 pe
  2. 返回 empty

7.3.27 PrivateFieldAdd ( obj, privateName, value )

The abstract operation PrivateFieldAdd takes arguments obj (一个 Object,), privateName (一个 Private Name,), and value (一个 ECMAScript 语言值,) and returns 要么是包含 unused正常完成,要么是抛出完成. It performs the following steps when called:

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

7.3.28 PrivateMethodOrAccessorAdd ( obj, method )

The abstract operation PrivateMethodOrAccessorAdd takes arguments obj (一个 Object,) and method (一个 PrivateElement,) and returns 要么是包含 unused正常完成,要么是抛出完成. It performs the following steps when called:

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

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

7.3.29 HostEnsureCanAddPrivateElement ( obj )

The host-defined abstract operation HostEnsureCanAddPrivateElement takes argument obj (一个 Object,) and returns 要么是包含 unused正常完成,要么是抛出完成. 它允许宿主环境阻止向特定宿主定义异质对象添加私有元素。

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

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

抽象操作只会被作为网页浏览器的 ECMAScript 宿主调用。

7.3.30 PrivateGet ( obj, privateName )

The abstract operation PrivateGet takes arguments obj (一个 Object,) and privateName (一个 Private Name,) and returns 要么是包含 ECMAScript 语言值正常完成,要么是抛出完成. It performs the following steps when called:

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

7.3.31 PrivateSet ( obj, privateName, value )

The abstract operation PrivateSet takes arguments obj (一个 Object,), privateName (一个 Private Name,), and value (一个 ECMAScript 语言值,) and returns 要么是包含 unused正常完成,要么是抛出完成. It performs the following steps when called:

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

7.3.32 DefineField ( receiver, fieldRecord )

The abstract operation DefineField takes arguments receiver (一个 Object,) and fieldRecord (一个 ClassFieldDefinition Record,) and returns 要么是包含 unused正常完成,要么是抛出完成. It performs the following steps when called:

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

7.3.33 InitializeInstanceElements ( obj, constructor )

The abstract operation InitializeInstanceElements takes arguments obj (一个 Object,) and constructor (一个 ECMAScript 函数对象或内建函数对象,) and returns 要么是包含 unused正常完成,要么是抛出完成. It performs the following steps when called:

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

7.3.34 AddValueToKeyedGroup ( groups, key, value )

The abstract operation AddValueToKeyedGroup takes arguments groups (一个 RecordList,这些 Record 具有 [[Key]](一个 ECMAScript 语言值)和 [[Elements]](一个 ECMAScript 语言值List)字段,), key (一个 ECMAScript 语言值,), and value (一个 ECMAScript 语言值,) and returns unused. It performs the following steps when called:

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

7.3.35 GroupBy ( items, callback, keyCoercion )

The abstract operation GroupBy takes arguments items (一个 ECMAScript 语言值,), callback (一个 ECMAScript 语言值,), and keyCoercion (propertycollection,) and returns 要么是包含 RecordList正常完成,这些 Record 具有 [[Key]](一个 ECMAScript 语言值)和 [[Elements]](一个 ECMAScript 语言值List)字段,要么是抛出完成. It performs the following steps when called:

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

7.3.36 GetOptionsObject ( options )

The abstract operation GetOptionsObject takes argument options (一个 ECMAScript 语言值,) and returns 要么是包含 Object 的正常完成,要么是抛出完成. It performs the following steps when called:

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

7.3.37 SetterThatIgnoresPrototypeProperties ( thisValue, home, propertyKey, value )

The abstract operation SetterThatIgnoresPrototypeProperties takes arguments thisValue (一个 ECMAScript 语言值,), home (一个 Object,), propertyKey (一个属性键,), and value (一个 ECMAScript 语言值,) and returns 要么是包含 unused正常完成,要么是抛出完成. It performs the following steps when called:

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

7.4 迭代器对象上的操作

参见公共迭代接口(27.1)。

7.4.1 Iterator Record

Iterator Record 是一种 Record 值,用于封装一个迭代器或异步迭代器及其 next 方法。

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

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

7.4.2 GetIteratorDirect ( obj )

The abstract operation GetIteratorDirect takes argument obj (一个 Object,) and returns 要么是包含 Iterator Record正常完成,要么是抛出完成. It performs the following steps when called:

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

7.4.3 GetIteratorFromMethod ( obj, method )

The abstract operation GetIteratorFromMethod takes arguments obj (一个 ECMAScript 语言值,) and method (一个函数对象,) and returns 要么是包含 Iterator Record正常完成,要么是抛出完成. It performs the following steps when called:

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

7.4.4 GetIterator ( obj, kind )

The abstract operation GetIterator takes arguments obj (一个 ECMAScript 语言值,) and kind (syncasync,) and returns 要么是包含 Iterator Record正常完成,要么是抛出完成. It performs the following steps when called:

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

7.4.5 GetIteratorFlattenable ( obj, primitiveHandling )

The abstract operation GetIteratorFlattenable takes arguments obj (一个 ECMAScript 语言值,) and primitiveHandling (iterate-string-primitivesreject-primitives,) and returns 要么是包含 Iterator Record正常完成,要么是抛出完成. It performs the following steps when called:

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

7.4.6 IteratorNext ( iteratorRecord [ , value ] )

The abstract operation IteratorNext takes argument iteratorRecord (一个 Iterator Record,) and optional argument value (一个 ECMAScript 语言值,) and returns 要么是包含 Object 的正常完成,要么是抛出完成. It performs the following steps when called:

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

7.4.7 IteratorComplete ( iteratorResult )

The abstract operation IteratorComplete takes argument iteratorResult (一个 Object,) and returns 要么是包含 Boolean 的正常完成,要么是抛出完成. It performs the following steps when called:

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

7.4.8 IteratorValue ( iteratorResult )

The abstract operation IteratorValue takes argument iteratorResult (一个 Object,) and returns 要么是包含 ECMAScript 语言值正常完成,要么是抛出完成. It performs the following steps when called:

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

7.4.9 IteratorStep ( iteratorRecord )

The abstract operation IteratorStep takes argument iteratorRecord (一个 Iterator Record,) and returns 要么是包含 Object 或 done正常完成,要么是抛出完成. 它通过调用 iteratorRecord.[[NextMethod]]iteratorRecord.[[Iterator]] 请求下一个值;如果迭代器已经到达末尾,则返回 done,否则如果存在下一个值,则返回 IteratorResult 对象。 It performs the following steps when called:

  1. result 为 ? IteratorNext(iteratorRecord)。
  2. doneCompletion(IteratorComplete(result))。
  3. 如果 done 是一个抛出完成,那么
    1. iteratorRecord.[[Done]] 设为 true
    2. 返回 ? done
  4. done 设为 ! done
  5. 如果 donetrue,那么
    1. iteratorRecord.[[Done]] 设为 true
    2. 返回 done
  6. 返回 result

7.4.10 IteratorStepValue ( iteratorRecord )

The abstract operation IteratorStepValue takes argument iteratorRecord (一个 Iterator Record,) and returns 要么是包含 ECMAScript 语言值done正常完成,要么是抛出完成. 它通过调用 iteratorRecord.[[NextMethod]]iteratorRecord.[[Iterator]] 请求下一个值;如果迭代器已经到达末尾,则返回 done,否则如果存在下一个值,则返回 IteratorResult 对象中的 value。 It performs the following steps when called:

  1. result 为 ? IteratorStep(iteratorRecord)。
  2. 如果 resultdone,那么
    1. 返回 done
  3. valueCompletion(IteratorValue(result))。
  4. 如果 value 是一个抛出完成,那么
    1. iteratorRecord.[[Done]] 设为 true
  5. 返回 ? value

7.4.11 IteratorClose ( iteratorRecord, completion )

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

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

7.4.12 IteratorCloseAll ( iters, completion )

The abstract operation IteratorCloseAll takes arguments iters (一个 Iterator RecordList,) and completion (一个 Completion Record,) and returns 一个 Completion Record. It performs the following steps when called:

  1. iters 中的每个元素 iter,按 List 的逆序,执行
    1. completion 设为 Completion(IteratorClose(iter, completion))。
  2. 返回 ? completion

7.4.13 IfAbruptCloseIterator ( value, iteratorRecord )

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

  1. IfAbruptCloseIterator(value, iteratorRecord)。

其含义等同于:

  1. 断言:value 是一个 Completion Record
  2. 如果 value 是一个突兀完成,返回 ? IteratorClose(iteratorRecord, value)。
  3. value 设为 ! value

7.4.14 AsyncIteratorClose ( iteratorRecord, completion )

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

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

7.4.15 IfAbruptCloseAsyncIterator ( value, iteratorRecord )

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

  1. IfAbruptCloseAsyncIterator(value, iteratorRecord)。

其含义等同于:

  1. 断言:value 是一个 Completion Record
  2. 如果 value 是一个突兀完成,返回 ? AsyncIteratorClose(iteratorRecord, value)。
  3. value 设为 ! value

7.4.16 CreateIteratorResultObject ( value, done )

The abstract operation CreateIteratorResultObject takes arguments value (一个 ECMAScript 语言值,) and done (一个 Boolean,) and returns 一个符合 IteratorResult 接口的 Object. 它创建一个符合 IteratorResult 接口的对象。 It performs the following steps when called:

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

7.4.17 CreateListIteratorRecord ( list )

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

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

该列表迭代器对象永远不会被 ECMAScript 代码直接访问到。

7.4.18 IteratorToList ( iteratorRecord )

The abstract operation IteratorToList takes argument iteratorRecord (一个 Iterator Record,) and returns 要么是包含 ECMAScript 语言值List正常完成,要么是抛出完成. It performs the following steps when called:

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

8 语法制导操作

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

8.1 Runtime Semantics: Evaluation

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

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

8.2 作用域分析

8.2.1 Static Semantics: BoundNames

The syntax-directed operation BoundNames takes no arguments and returns 一个 String 的 List.

Note

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

It is defined piecewise over the following productions:

BindingIdentifier : Identifier
  1. 返回一个 List,其唯一元素为 IdentifierStringValue
BindingIdentifier : yield
  1. 返回 « "yield" »。
BindingIdentifier : await
  1. 返回 « "await" »。
LexicalDeclaration : LetOrConst BindingList ;
  1. 返回 BindingListBoundNames
BindingList : BindingList , LexicalBinding
  1. names1BindingListBoundNames
  2. names2LexicalBindingBoundNames
  3. 返回 names1names2列表连接
LexicalBinding : BindingIdentifier Initializeropt
  1. 返回 BindingIdentifierBoundNames
LexicalBinding : BindingPattern Initializer
  1. 返回 BindingPatternBoundNames
VariableDeclarationList : VariableDeclarationList , VariableDeclaration
  1. names1VariableDeclarationListBoundNames
  2. names2VariableDeclarationBoundNames
  3. 返回 names1names2列表连接
VariableDeclaration : BindingIdentifier Initializeropt
  1. 返回 BindingIdentifierBoundNames
VariableDeclaration : BindingPattern Initializer
  1. 返回 BindingPatternBoundNames
ObjectBindingPattern : { }
  1. 返回一个新的空 List
ObjectBindingPattern : { BindingPropertyList , BindingRestProperty }
  1. names1BindingPropertyListBoundNames
  2. names2BindingRestPropertyBoundNames
  3. 返回 names1names2列表连接
ArrayBindingPattern : [ Elisionopt ]
  1. 返回一个新的空 List
ArrayBindingPattern : [ Elisionopt BindingRestElement ]
  1. 返回 BindingRestElementBoundNames
ArrayBindingPattern : [ BindingElementList , Elisionopt ]
  1. 返回 BindingElementListBoundNames
ArrayBindingPattern : [ BindingElementList , Elisionopt BindingRestElement ]
  1. names1BindingElementListBoundNames
  2. names2BindingRestElementBoundNames
  3. 返回 names1names2列表连接
BindingPropertyList : BindingPropertyList , BindingProperty
  1. names1BindingPropertyListBoundNames
  2. names2BindingPropertyBoundNames
  3. 返回 names1names2列表连接
BindingElementList : BindingElementList , BindingElisionElement
  1. names1BindingElementListBoundNames
  2. names2BindingElisionElementBoundNames
  3. 返回 names1names2列表连接
BindingElisionElement : Elisionopt BindingElement
  1. 返回 BindingElementBoundNames
BindingProperty : PropertyName : BindingElement
  1. 返回 BindingElementBoundNames
SingleNameBinding : BindingIdentifier Initializeropt
  1. 返回 BindingIdentifierBoundNames
BindingElement : BindingPattern Initializeropt
  1. 返回 BindingPatternBoundNames
ForDeclaration : LetOrConst ForBinding
  1. 返回 ForBindingBoundNames
FunctionDeclaration : function BindingIdentifier ( FormalParameters ) { FunctionBody }
  1. 返回 BindingIdentifierBoundNames
FunctionDeclaration : function ( FormalParameters ) { FunctionBody }
  1. 返回 « "*default*" »。
FormalParameters : [empty]
  1. 返回一个新的空 List
FormalParameters : FormalParameterList , FunctionRestParameter
  1. names1FormalParameterListBoundNames
  2. names2FunctionRestParameterBoundNames
  3. 返回 names1names2列表连接
FormalParameterList : FormalParameterList , FormalParameter
  1. names1FormalParameterListBoundNames
  2. names2FormalParameterBoundNames
  3. 返回 names1names2列表连接
ArrowParameters : CoverParenthesizedExpressionAndArrowParameterList
  1. 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. 返回一个新的空 List
ImportClause : ImportedDefaultBinding , NameSpaceImport
  1. names1ImportedDefaultBindingBoundNames
  2. names2NameSpaceImportBoundNames
  3. 返回 names1names2列表连接
ImportClause : ImportedDefaultBinding , NamedImports
  1. names1ImportedDefaultBindingBoundNames
  2. names2NamedImportsBoundNames
  3. 返回 names1names2列表连接
NamedImports : { }
  1. 返回一个新的空 List
ImportsList : ImportsList , ImportSpecifier
  1. names1ImportsListBoundNames
  2. names2ImportSpecifierBoundNames
  3. 返回 names1names2列表连接
ImportSpecifier : ModuleExportName as ImportedBinding
  1. 返回 ImportedBindingBoundNames
ExportDeclaration : export ExportFromClause FromClause WithClauseopt ; export NamedExports ;
  1. 返回一个新的空 List
ExportDeclaration : export VariableStatement
  1. 返回 VariableStatementBoundNames
ExportDeclaration : export Declaration
  1. 返回 DeclarationBoundNames
ExportDeclaration : export default HoistableDeclaration
  1. 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 Static Semantics: DeclarationPart

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

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

8.2.3 Static Semantics: IsConstantDeclaration

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

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
Note

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

8.2.4 Static Semantics: LexicallyDeclaredNames

The syntax-directed operation LexicallyDeclaredNames takes no arguments and returns 一个 String 的 List. It is defined piecewise over the following productions:

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

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

Note 2

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

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

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

8.2.5 Static Semantics: LexicallyScopedDeclarations

The syntax-directed operation LexicallyScopedDeclarations takes no arguments and returns 一个 Parse Node 的 List. It is defined piecewise over the following productions:

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

8.2.6 Static Semantics: VarDeclaredNames

The syntax-directed operation VarDeclaredNames takes no arguments and returns 一个 String 的 List. It is defined piecewise over the following productions:

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

本节由附录 B.3.5 扩展。

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

8.2.7 Static Semantics: VarScopedDeclarations

The syntax-directed operation VarScopedDeclarations takes no arguments and returns 一个 Parse Node 的 List. It is defined piecewise over the following productions:

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

本节由附录 B.3.5 扩展。

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

8.2.8 Static Semantics: TopLevelLexicallyDeclaredNames

The syntax-directed operation TopLevelLexicallyDeclaredNames takes no arguments and returns 一个 String 的 List. It is defined piecewise over the following productions:

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

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

8.2.9 Static Semantics: TopLevelLexicallyScopedDeclarations

The syntax-directed operation TopLevelLexicallyScopedDeclarations takes no arguments and returns 一个 Parse Node 的 List. It is defined piecewise over the following productions:

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

8.2.10 Static Semantics: TopLevelVarDeclaredNames

The syntax-directed operation TopLevelVarDeclaredNames takes no arguments and returns 一个 String 的 List. It is defined piecewise over the following productions:

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

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

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

8.2.11 Static Semantics: TopLevelVarScopedDeclarations

The syntax-directed operation TopLevelVarScopedDeclarations takes no arguments and returns 一个 Parse Node 的 List. It is defined piecewise over the following productions:

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. 返回一个新的空 List
LabelledStatement : LabelIdentifier : LabelledItem
  1. 返回 LabelledItemTopLevelVarScopedDeclarations
LabelledItem : Statement
  1. 如果 Statement Statement : LabelledStatement ,返回 StatementTopLevelVarScopedDeclarations
  2. 返回 StatementVarScopedDeclarations
LabelledItem : FunctionDeclaration
  1. 返回 « FunctionDeclaration »。

8.3 标签

8.3.1 Static Semantics: ContainsDuplicateLabels

The syntax-directed operation ContainsDuplicateLabels takes argument labelSet (一个 String 的 List,) and returns 一个 Boolean. It is defined piecewise over the following productions:

Statement : VariableStatement EmptyStatement ExpressionStatement ContinueStatement BreakStatement ReturnStatement ThrowStatement DebuggerStatement Block : { } StatementListItem : Declaration
  1. 返回 false
StatementList : StatementList StatementListItem
  1. 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 的结果。
Note

本节由附录 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 作为参数调用第一个 CaseClausesContainsDuplicateLabels 的结果是 true,返回 true
  2. 如果以 labelSet 作为参数调用 DefaultClauseContainsDuplicateLabels 的结果是 true,返回 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 作为参数调用 BlockContainsDuplicateLabels 的结果是 true,返回 true
  2. 如果以 labelSet 作为参数调用 CatchContainsDuplicateLabels 的结果是 true,返回 true
  3. 返回以 labelSet 作为参数调用 FinallyContainsDuplicateLabels 的结果。
Catch : catch ( CatchParameter ) Block
  1. 返回以 labelSet 作为参数调用 BlockContainsDuplicateLabels 的结果。
FunctionStatementList : [empty]
  1. 返回 false
ClassStaticBlockStatementList : [empty]
  1. 返回 false
ModuleItemList : ModuleItemList ModuleItem
  1. hasDuplicates 为以 labelSet 作为参数调用 ModuleItemListContainsDuplicateLabels 的结果。
  2. 如果 hasDuplicatestrue,返回 true
  3. 返回以 labelSet 作为参数调用 ModuleItemContainsDuplicateLabels 的结果。
ModuleItem : ImportDeclaration ExportDeclaration
  1. 返回 false

8.3.2 Static Semantics: ContainsUndefinedBreakTarget

The syntax-directed operation ContainsUndefinedBreakTarget takes argument labelSet (一个 String 的 List,) and returns 一个 Boolean. It is defined piecewise over the following productions:

Statement : VariableStatement EmptyStatement ExpressionStatement ContinueStatement ReturnStatement ThrowStatement DebuggerStatement Block : { } StatementListItem : Declaration
  1. 返回 false
StatementList : StatementList StatementListItem
  1. 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 的结果。
Note

本节由附录 B.3.5 扩展。

BreakStatement : break ;
  1. 返回 false
BreakStatement : break LabelIdentifier ;
  1. 如果 labelSet 包含 LabelIdentifierStringValue,返回 false
  2. 返回 true
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 作为参数调用第一个 CaseClausesContainsUndefinedBreakTarget 的结果是 true,返回 true
  2. 如果以 labelSet 作为参数调用 DefaultClauseContainsUndefinedBreakTarget 的结果是 true,返回 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 作为参数调用 BlockContainsUndefinedBreakTarget 的结果是 true,返回 true
  2. 如果以 labelSet 作为参数调用 CatchContainsUndefinedBreakTarget 的结果是 true,返回 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 Static Semantics: ContainsUndefinedContinueTarget

The syntax-directed operation ContainsUndefinedContinueTarget takes arguments iterationSet (一个 String 的 List,) and labelSet (一个 String 的 List,) and returns 一个 Boolean. It is defined piecewise over the following productions:

Statement : VariableStatement EmptyStatement ExpressionStatement BreakStatement ReturnStatement ThrowStatement DebuggerStatement Block : { } StatementListItem : Declaration
  1. 返回 false
Statement : BlockStatement
  1. 返回以 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 的结果。
Note

本节由附录 B.3.5 扩展。

ContinueStatement : continue ;
  1. 返回 false
ContinueStatement : continue LabelIdentifier ;
  1. 如果 iterationSet 包含 LabelIdentifierStringValue,返回 false
  2. 返回 true
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 和 « » 作为参数调用第一个 CaseClausesContainsUndefinedContinueTarget 的结果是 true,返回 true
  2. 如果以 iterationSet 和 « » 作为参数调用 DefaultClauseContainsUndefinedContinueTarget 的结果是 true,返回 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 和 « » 作为参数调用 BlockContainsUndefinedContinueTarget 的结果是 true,返回 true
  2. 如果以 iterationSet 和 « » 作为参数调用 CatchContainsUndefinedContinueTarget 的结果是 true,返回 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 Static Semantics: HasName

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

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 Static Semantics: IsFunctionDefinition

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

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 Static Semantics: IsAnonymousFunctionDefinition ( expr )

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

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

8.4.4 Static Semantics: IsIdentifierRef

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

PrimaryExpression : IdentifierReference
  1. 返回 true
PrimaryExpression : this Literal ArrayLiteral ObjectLiteral FunctionExpression ClassExpression GeneratorExpression AsyncFunctionExpression AsyncGeneratorExpression RegularExpressionLiteral TemplateLiteral CoverParenthesizedExpressionAndArrowParameterList MemberExpression : MemberExpression [ Expression ] MemberExpression . IdentifierName MemberExpression TemplateLiteral SuperProperty MetaProperty new MemberExpression Arguments MemberExpression . PrivateIdentifier NewExpression : new NewExpression LeftHandSideExpression : CallExpression OptionalExpression
  1. 返回 false

8.4.5 Runtime Semantics: NamedEvaluation

The syntax-directed operation NamedEvaluation takes argument name (一个属性键或一个 Private Name,) and returns 要么是包含函数对象正常完成,要么是突兀完成. It is defined piecewise over the following productions:

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

8.5 Contains

8.5.1 Static Semantics: Contains

The syntax-directed operation Contains takes argument symbol (一个文法符号,) and returns 一个 Boolean.

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

  1. 对该 Parse Node 的每个子节点 child,执行
    1. 如果 childsymbol 的一个实例,返回 true
    2. 如果 child 是一个非终结符的实例,那么
      1. containedchild Contains symbol 的结果。
      2. 如果 containedtrue,返回 true
  2. 返回 false
FunctionDeclaration : function BindingIdentifier ( FormalParameters ) { FunctionBody } function ( FormalParameters ) { FunctionBody } FunctionExpression : function BindingIdentifieropt ( FormalParameters ) { FunctionBody } GeneratorDeclaration : function * BindingIdentifier ( FormalParameters ) { GeneratorBody } function * ( FormalParameters ) { GeneratorBody } GeneratorExpression : function * BindingIdentifieropt ( FormalParameters ) { GeneratorBody } AsyncGeneratorDeclaration : async function * BindingIdentifier ( FormalParameters ) { AsyncGeneratorBody } async function * ( FormalParameters ) { AsyncGeneratorBody } AsyncGeneratorExpression : async function * BindingIdentifieropt ( FormalParameters ) { AsyncGeneratorBody } AsyncFunctionDeclaration : async function BindingIdentifier ( FormalParameters ) { AsyncFunctionBody } async function ( FormalParameters ) { AsyncFunctionBody } AsyncFunctionExpression : async function BindingIdentifieropt ( FormalParameters ) { AsyncFunctionBody }
  1. 返回 false
Note 1

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

ClassTail : ClassHeritageopt { ClassBody }
  1. 如果 symbolClassBody,返回 true
  2. 如果 symbolClassHeritage,那么
    1. 如果 ClassHeritage 存在,返回 true
    2. 返回 false
  3. 如果 ClassHeritage 存在,那么
    1. 如果 ClassHeritage Contains symboltrue,返回 true
  4. 返回以 symbol 作为参数对 ClassBody 进行 ComputedPropertyContains 的结果。
Note 2

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

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

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

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

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

PropertyDefinition : MethodDefinition
  1. 如果 symbolMethodDefinition,返回 true
  2. 返回以 symbol 作为参数对 MethodDefinition 进行 ComputedPropertyContains 的结果。
LiteralPropertyName : IdentifierName
  1. 返回 false
MemberExpression : MemberExpression . IdentifierName
  1. 如果 MemberExpression Contains symboltrue,返回 true
  2. 返回 false
SuperProperty : super . IdentifierName
  1. 如果 symbol保留字 ReservedWord super,返回 true
  2. 返回 false
CallExpression : CallExpression . IdentifierName
  1. 如果 CallExpression Contains symboltrue,返回 true
  2. 返回 false
OptionalChain : ?. IdentifierName
  1. 返回 false
OptionalChain : OptionalChain . IdentifierName
  1. 如果 OptionalChain Contains symboltrue,返回 true
  2. 返回 false

8.5.2 Static Semantics: ComputedPropertyContains

The syntax-directed operation ComputedPropertyContains takes argument symbol (一个文法符号,) and returns 一个 Boolean. It is defined piecewise over the following productions:

ClassElementName : PrivateIdentifier PropertyName : LiteralPropertyName
  1. 返回 false
PropertyName : ComputedPropertyName
  1. 返回 ComputedPropertyName Contains symbol 的结果。
MethodDefinition : ClassElementName ( UniqueFormalParameters ) { FunctionBody } get ClassElementName ( ) { FunctionBody } set ClassElementName ( PropertySetParameterList ) { FunctionBody }
  1. 返回以 symbol 作为参数对 ClassElementName 进行 ComputedPropertyContains 的结果。
GeneratorMethod : * ClassElementName ( UniqueFormalParameters ) { GeneratorBody }
  1. 返回以 symbol 作为参数对 ClassElementName 进行 ComputedPropertyContains 的结果。
AsyncGeneratorMethod : async * ClassElementName ( UniqueFormalParameters ) { AsyncGeneratorBody }
  1. 返回以 symbol 作为参数对 ClassElementName 进行 ComputedPropertyContains 的结果。
ClassElementList : ClassElementList ClassElement
  1. inList 为以 symbol 作为参数对 ClassElementList 进行 ComputedPropertyContains 的结果。
  2. 如果 inListtrue,返回 true
  3. 返回以 symbol 作为参数对 ClassElement 进行 ComputedPropertyContains 的结果。
ClassElement : ClassStaticBlock
  1. 返回 false
ClassElement : ;
  1. 返回 false
AsyncMethod : async ClassElementName ( UniqueFormalParameters ) { AsyncFunctionBody }
  1. 返回以 symbol 作为参数对 ClassElementName 进行 ComputedPropertyContains 的结果。
FieldDefinition : ClassElementName Initializeropt
  1. 返回以 symbol 作为参数对 ClassElementName 进行 ComputedPropertyContains 的结果。

8.6 杂项

这些操作会在本规范的多个位置中使用。

8.6.1 Runtime Semantics: InstantiateFunctionObject

The syntax-directed operation InstantiateFunctionObject takes arguments env (一个 Environment Record,) and privateEnv (一个 PrivateEnvironment Recordnull,) and returns 一个 ECMAScript 函数对象. It is defined piecewise over the following productions:

FunctionDeclaration : function BindingIdentifier ( FormalParameters ) { FunctionBody } function ( FormalParameters ) { FunctionBody }
  1. 返回以 envprivateEnv 作为参数对 FunctionDeclaration 进行 InstantiateOrdinaryFunctionObject 的结果。
GeneratorDeclaration : function * BindingIdentifier ( FormalParameters ) { GeneratorBody } function * ( FormalParameters ) { GeneratorBody }
  1. 返回以 envprivateEnv 作为参数对 GeneratorDeclaration 进行 InstantiateGeneratorFunctionObject 的结果。
AsyncGeneratorDeclaration : async function * BindingIdentifier ( FormalParameters ) { AsyncGeneratorBody } async function * ( FormalParameters ) { AsyncGeneratorBody }
  1. 返回以 envprivateEnv 作为参数对 AsyncGeneratorDeclaration 进行 InstantiateAsyncGeneratorFunctionObject 的结果。
AsyncFunctionDeclaration : async function BindingIdentifier ( FormalParameters ) { AsyncFunctionBody } async function ( FormalParameters ) { AsyncFunctionBody }
  1. 返回以 envprivateEnv 作为参数对 AsyncFunctionDeclaration 进行 InstantiateAsyncFunctionObject 的结果。

8.6.2 Runtime Semantics: BindingInitialization

The syntax-directed operation BindingInitialization takes arguments value (一个 ECMAScript 语言值,) and environment (一个 Environment Recordundefined,) and returns 要么是包含 unused正常完成,要么是突兀完成.

Note

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

It is defined piecewise over the following productions:

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. 返回 ? 以 valueenvironment 作为参数对 ObjectBindingPattern 进行 BindingInitialization 的结果。
BindingPattern : ArrayBindingPattern
  1. iteratorRecord 为 ? GetIterator(value, sync)。
  2. resultCompletion(以 iteratorRecordenvironment 作为参数对 ArrayBindingPattern 进行 IteratorBindingInitialization 的结果)。
  3. 如果 iteratorRecord.[[Done]]false,返回 ? IteratorClose(iteratorRecord, result)。
  4. 返回 ? result
ObjectBindingPattern : { }
  1. 返回 unused
ObjectBindingPattern : { BindingPropertyList } { BindingPropertyList , }
  1. 执行 ? 以 valueenvironment 作为参数对 BindingPropertyList 进行 PropertyBindingInitialization
  2. 返回 unused
ObjectBindingPattern : { BindingRestProperty }
  1. excludedNames 为一个新的空 List
  2. 返回 ? 以 valueenvironmentexcludedNames 作为参数对 BindingRestProperty 进行 RestBindingInitialization 的结果。
ObjectBindingPattern : { BindingPropertyList , BindingRestProperty }
  1. excludedNames 为 ? 以 valueenvironment 作为参数对 BindingPropertyList 进行 PropertyBindingInitialization 的结果。
  2. 返回 ? 以 valueenvironmentexcludedNames 作为参数对 BindingRestProperty 进行 RestBindingInitialization 的结果。

8.6.2.1 InitializeBoundName ( name, value, environment )

The abstract operation InitializeBoundName takes arguments name (一个 String,), value (一个 ECMAScript 语言值,), and environment (一个 Environment Recordundefined,) and returns 要么是包含 unused正常完成,要么是突兀完成. It performs the following steps when called:

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

8.6.3 Runtime Semantics: IteratorBindingInitialization

The syntax-directed operation IteratorBindingInitialization takes arguments iteratorRecord (一个 Iterator Record,) and environment (一个 Environment Recordundefined,) and returns 要么是包含 unused正常完成,要么是突兀完成.

Note

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

It is defined piecewise over the following productions:

ArrayBindingPattern : [ ]
  1. 返回 unused
ArrayBindingPattern : [ Elision ]
  1. 返回 ? 以 iteratorRecord 作为参数对 Elision 进行 IteratorDestructuringAssignmentEvaluation 的结果。
ArrayBindingPattern : [ Elisionopt BindingRestElement ]
  1. 如果 Elision 存在,那么
    1. 执行 ? 以 iteratorRecord 作为参数对 Elision 进行 IteratorDestructuringAssignmentEvaluation
  2. 返回 ? 以 iteratorRecordenvironment 作为参数对 BindingRestElement 进行 IteratorBindingInitialization 的结果。
ArrayBindingPattern : [ BindingElementList , Elision ]
  1. 执行 ? 以 iteratorRecordenvironment 作为参数对 BindingElementList 进行 IteratorBindingInitialization
  2. 返回 ? 以 iteratorRecord 作为参数对 Elision 进行 IteratorDestructuringAssignmentEvaluation 的结果。
ArrayBindingPattern : [ BindingElementList , Elisionopt BindingRestElement ]
  1. 执行 ? 以 iteratorRecordenvironment 作为参数对 BindingElementList 进行 IteratorBindingInitialization
  2. 如果 Elision 存在,那么
    1. 执行 ? 以 iteratorRecord 作为参数对 Elision 进行 IteratorDestructuringAssignmentEvaluation
  3. 返回 ? 以 iteratorRecordenvironment 作为参数对 BindingRestElement 进行 IteratorBindingInitialization 的结果。
BindingElementList : BindingElementList , BindingElisionElement
  1. 执行 ? 以 iteratorRecordenvironment 作为参数对 BindingElementList 进行 IteratorBindingInitialization
  2. 返回 ? 以 iteratorRecordenvironment 作为参数对 BindingElisionElement 进行 IteratorBindingInitialization 的结果。
BindingElisionElement : Elision BindingElement
  1. 执行 ? 以 iteratorRecord 作为参数对 Elision 进行 IteratorDestructuringAssignmentEvaluation
  2. 返回 ? 以 iteratorRecordenvironment 作为参数对 BindingElement 进行 IteratorBindingInitialization 的结果。
SingleNameBinding : BindingIdentifier Initializeropt
  1. bindingIdBindingIdentifierStringValue
  2. lhs 为 ? ResolveBinding(bindingId, environment)。
  3. vundefined
  4. 如果 iteratorRecord.[[Done]]false,那么
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 next 不是 done,那么
      1. v 设为 next
  5. 如果 Initializer 存在且 vundefined,那么
    1. 如果 IsAnonymousFunctionDefinition(Initializer) 是 true,那么
      1. v 设为 ? 以 bindingId 作为参数对 Initializer 进行 NamedEvaluation 的结果。
    2. 否则,
      1. defaultValue 为 ? 对 Initializer 进行 Evaluation 的结果。
      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. v 设为 next
  3. 如果 Initializer 存在且 vundefined,那么
    1. defaultValue 为 ? 对 Initializer 进行 Evaluation 的结果。
    2. v 设为 ? GetValue(defaultValue)。
  4. 返回 ? 以 venvironment 作为参数对 BindingPattern 进行 BindingInitialization 的结果。
BindingRestElement : ... BindingIdentifier
  1. lhs 为 ? ResolveBinding(BindingIdentifierStringValue, environment)。
  2. array 为 ! ArrayCreate(0)。
  3. n 为 0。
  4. 重复,
    1. nextdone
    2. 如果 iteratorRecord.[[Done]]false,那么
      1. next 设为 ? IteratorStepValue(iteratorRecord)。
    3. 如果 nextdone,那么
      1. 如果 environmentundefined,返回 ? PutValue(lhs, array)。
      2. 返回 ? InitializeReferencedBinding(lhs, array)。
    4. 执行 ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(n)), next)。
    5. n 设为 n + 1。
BindingRestElement : ... BindingPattern
  1. array 为 ! ArrayCreate(0)。
  2. n 为 0。
  3. 重复,
    1. nextdone
    2. 如果 iteratorRecord.[[Done]]false,那么
      1. next 设为 ? IteratorStepValue(iteratorRecord)。
    3. 如果 nextdone,那么
      1. 返回 ? 以 arrayenvironment 作为参数对 BindingPattern 进行 BindingInitialization 的结果。
    4. 执行 ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(n)), next)。
    5. n 设为 n + 1。
FormalParameters : [empty]
  1. 返回 unused
FormalParameters : FormalParameterList , FunctionRestParameter
  1. 执行 ? 以 iteratorRecordenvironment 作为参数对 FormalParameterList 进行 IteratorBindingInitialization
  2. 返回 ? 以 iteratorRecordenvironment 作为参数对 FunctionRestParameter 进行 IteratorBindingInitialization 的结果。
FormalParameterList : FormalParameterList , FormalParameter
  1. 执行 ? 以 iteratorRecordenvironment 作为参数对 FormalParameterList 进行 IteratorBindingInitialization
  2. 返回 ? 以 iteratorRecordenvironment 作为参数对 FormalParameter 进行 IteratorBindingInitialization 的结果。
ArrowParameters : BindingIdentifier
  1. vundefined
  2. 断言:iteratorRecord.[[Done]]false
  3. next 为 ? IteratorStepValue(iteratorRecord)。
  4. 如果 next 不是 done,那么
    1. v 设为 next
  5. 返回 ? 以 venvironment 作为参数对 BindingIdentifier 进行 BindingInitialization 的结果。
ArrowParameters : CoverParenthesizedExpressionAndArrowParameterList
  1. formals 为被 CoverParenthesizedExpressionAndArrowParameterList 覆盖ArrowFormalParameters
  2. 返回 ? 以 iteratorRecordenvironment 作为参数对 formals 进行 IteratorBindingInitialization 的结果。
AsyncArrowBindingIdentifier : BindingIdentifier
  1. vundefined
  2. 断言:iteratorRecord.[[Done]]false
  3. next 为 ? IteratorStepValue(iteratorRecord)。
  4. 如果 next 不是 done,那么
    1. v 设为 next
  5. 返回 ? 以 venvironment 作为参数对 BindingIdentifier 进行 BindingInitialization 的结果。

8.6.4 Static Semantics: AssignmentTargetType

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

IdentifierReference : Identifier
  1. 如果 IsStrict(this IdentifierReference) 是 true,且 IdentifierStringValue"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
CallExpression : CoverCallExpressionAndAsyncArrowHead CallExpression Arguments
  1. Normative Optional
    如果宿主是网页浏览器,或以其他方式支持 函数调用作为赋值目标时的运行时错误,并且 IsStrict(this CallExpression) 是 false,那么
    1. 返回 web-compat
  2. 返回 invalid
PrimaryExpression : this Literal ArrayLiteral ObjectLiteral FunctionExpression ClassExpression GeneratorExpression AsyncFunctionExpression AsyncGeneratorExpression RegularExpressionLiteral TemplateLiteral CallExpression : SuperCall ImportCall CallExpression TemplateLiteral NewExpression : new NewExpression MemberExpression : MemberExpression TemplateLiteral new MemberExpression Arguments NewTarget : new . target ImportMeta : import . meta LeftHandSideExpression : OptionalExpression UpdateExpression : LeftHandSideExpression ++ LeftHandSideExpression -- ++ UnaryExpression -- UnaryExpression UnaryExpression : delete UnaryExpression void UnaryExpression typeof UnaryExpression + UnaryExpression - UnaryExpression ~ UnaryExpression ! UnaryExpression 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 Static Semantics: PropName

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

PropertyDefinition : IdentifierReference
  1. 返回 IdentifierReferenceStringValue
PropertyDefinition : ... AssignmentExpression
  1. 返回 empty
PropertyDefinition : PropertyName : AssignmentExpression
  1. 返回 PropertyNamePropName
LiteralPropertyName : IdentifierName AttributeKey : IdentifierName
  1. 返回 IdentifierNameStringValue
LiteralPropertyName : StringLiteral AttributeKey : StringLiteral
  1. 返回 StringLiteralSV
LiteralPropertyName : NumericLiteral
  1. 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 环境记录

Environment Record 是一种规范类型,用于根据 ECMAScript 代码的词法嵌套结构,定义 Identifier 与特定变量和函数之间的关联。通常,一个 Environment Record 会与 ECMAScript 代码中的某个特定语法结构相关联,例如 FunctionDeclarationBlockStatement,或 TryStatement 的某个 Catch 子句。每次对此类代码求值时,都会创建一个新的 Environment Record,用来记录由该代码创建的标识符绑定。

每个 Environment Record 都有一个 [[OuterEnv]] 字段,其值要么是 null,要么是对外层 Environment Record 的引用。它用于表示 Environment Record 值之间的逻辑嵌套关系。某个(内层)Environment Record 的外层引用,是对在逻辑上包围该内层 Environment Record 的那个 Environment Record 的引用。外层 Environment Record 当然也可以有它自己的外层 Environment Record。一个 Environment Record 可以作为多个内层 Environment Record 的外部环境。例如,如果一个 FunctionDeclaration 包含两个嵌套的 FunctionDeclaration,那么这两个嵌套函数各自的 Environment Record,其外层 Environment Record 都将是当前对外围函数进行求值时的那个 Environment Record。

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

9.1.1 Environment Record 类型层级

可以将 Environment Record 视为存在于一个简单的面向对象层级中,其中 Environment Record 是一个抽象类,具有三个具体子类:Declarative Environment RecordObject Environment RecordGlobal Environment RecordFunction Environment RecordModule Environment Record 则是 Declarative Environment Record 的子类。

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

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

The abstract method HasBinding takes argument name (一个 String,) and returns 要么是包含 Boolean 的正常完成,要么是抛出完成.

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

The abstract method CreateMutableBinding takes arguments name (一个 String,) and deletable (一个 Boolean,) and returns 要么是包含 unused正常完成,要么是抛出完成.

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

The abstract method CreateImmutableBinding takes arguments name (一个 String,) and strict (一个 Boolean,) and returns 要么是包含 unused正常完成,要么是抛出完成.

它在 Environment Record 中创建一个新的、但尚未初始化的不可变绑定。name 是被绑定名称的文本。如果 stricttrue,那么在其被初始化之后再尝试设置它时,无论引用该绑定的操作是否处于严格模式,都会始终抛出异常。
它在以下类型中有具体定义:
InitializeBinding ( name, value )

The abstract method InitializeBinding takes arguments name (一个 String,) and value (一个 ECMAScript 语言值,) and returns 要么是包含 unused正常完成,要么是抛出完成.

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

The abstract method SetMutableBinding takes arguments name (一个 String,), value (一个 ECMAScript 语言值,), and strict (一个 Boolean,) and returns 要么是包含 unused正常完成,要么是抛出完成.

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

The abstract method GetBindingValue takes arguments name (一个 String,) and strict (一个 Boolean,) and returns 要么是包含 ECMAScript 语言值正常完成,要么是抛出完成.

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

The abstract method DeleteBinding takes argument name (一个 String,) and returns 要么是包含 Boolean 的正常完成,要么是抛出完成.

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

The abstract method HasThisBinding takes no arguments and returns 一个 Boolean.

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

The abstract method GetThisBinding takes no arguments and returns 要么是包含 ECMAScript 语言值正常完成,要么是抛出完成.

它返回该 Environment Recordthis 绑定值。如果 this 绑定尚未初始化,则抛出 ReferenceError
它在以下类型中有具体定义:
HasSuperBinding ( )

The abstract method HasSuperBinding takes no arguments and returns 一个 Boolean.

它用于判定一个 Environment Record 是否建立了 super 方法绑定。如果有则返回 true,否则返回 false。如果它返回 true,则意味着该 Environment Record 是一个 Function Environment Record,但反过来并不成立。
它在以下类型中有具体定义:
WithBaseObject ( )

The abstract method WithBaseObject takes no arguments and returns 一个 Object 或 undefined.

如果此 Environment Recordwith 语句相关联,则返回该 with 对象。否则返回 undefined
它在以下类型中有具体定义:

9.1.1.1 Declarative Environment Record

每个 Declarative Environment Record 都与一个 ECMAScript 程序作用域相关联,该作用域中包含变量、常量、let、class、module、import 和/或函数声明。Declarative Environment Record 绑定了其作用域内声明所定义的一组标识符。

9.1.1.1.1 HasBinding ( name )

The HasBinding concrete method of a Declarative Environment Record envRec takes argument name (一个 String,) and returns 一个包含 Boolean 的正常完成. 它用于判定参数标识符是否是该记录所绑定的标识符之一。 It performs the following steps when called:

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

9.1.1.1.2 CreateMutableBinding ( name, deletable )

The CreateMutableBinding concrete method of a Declarative Environment Record envRec takes arguments name (一个 String,) and deletable (一个 Boolean,) and returns 一个包含 unused正常完成. 它为名称 name 创建一个新的可变绑定,并且该绑定未初始化。在这个 Environment Record 中,name 的绑定必须尚不存在。如果 deletabletrue,则新绑定会被标记为可删除。 It performs the following steps when called:

  1. 断言:envRec 尚不存在 name 的绑定。
  2. envRec 中为 name 创建一个可变绑定,并记录其尚未初始化。如果 deletabletrue,则记录新创建的绑定可被后续的 DeleteBinding 调用删除。
  3. 返回 unused

9.1.1.1.3 CreateImmutableBinding ( name, strict )

The CreateImmutableBinding concrete method of a Declarative Environment Record envRec takes arguments name (一个 String,) and strict (一个 Boolean,) and returns 一个包含 unused正常完成. 它为名称 name 创建一个新的不可变绑定,并且该绑定未初始化。在这个 Environment Record 中,name 的绑定必须尚不存在。如果 stricttrue,则新绑定会被标记为严格绑定。 It performs the following steps when called:

  1. 断言:envRec 尚不存在 name 的绑定。
  2. envRec 中为 name 创建一个不可变绑定,并记录其尚未初始化。如果 stricttrue,则记录新创建的绑定是严格绑定。
  3. 返回 unused

9.1.1.1.4 InitializeBinding ( name, value )

The InitializeBinding concrete method of a Declarative Environment Record envRec takes arguments name (一个 String,) and value (一个 ECMAScript 语言值,) and returns 一个包含 unused正常完成. 它用于将当前名称为 name 的标识符绑定的绑定值设为 value。必须已经存在一个未初始化的 name 绑定。 It performs the following steps when called:

  1. 断言:envRec 中必须存在一个未初始化的 name 绑定。
  2. envRecname 的绑定值设为 value
  3. 记录 envRecname 的绑定已经完成初始化。
  4. 返回 unused

9.1.1.1.5 SetMutableBinding ( name, value, strict )

The SetMutableBinding concrete method of a Declarative Environment Record envRec takes arguments name (一个 String,), value (一个 ECMAScript 语言值,), and strict (一个 Boolean,) and returns 要么是包含 unused正常完成,要么是抛出完成. 它尝试将当前名称为 name 的标识符绑定的绑定值更改为 value。通常 name 的绑定已经存在,但在极少数情况下可能不存在。如果该绑定是不可变绑定,则当 stricttrue 时会抛出 TypeError。 It performs the following steps when called:

  1. 如果 envRec 没有 name 的绑定,那么
    1. 如果 stricttrue,抛出一个 ReferenceError 异常。
    2. 执行 ! envRec.CreateMutableBinding(name, true)。
    3. 执行 ! envRec.InitializeBinding(name, value)。
    4. 返回 unused
  2. 如果 envRecname 的绑定是一个严格绑定,则将 strict 设为 true
  3. 如果 envRecname 的绑定尚未初始化,那么
    1. 抛出一个 ReferenceError 异常。
  4. 否则如果 envRecname 的绑定是一个可变绑定,那么
    1. 将其绑定值改为 value
  5. 否则,
    1. 断言:这是一次试图更改不可变绑定值的操作。
    2. 如果 stricttrue,抛出一个 TypeError 异常。
  6. 返回 unused
Note

会在步骤 1 处产生缺失绑定的 ECMAScript 代码示例如下:

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

9.1.1.1.6 GetBindingValue ( name, strict )

The GetBindingValue concrete method of a Declarative Environment Record envRec takes arguments name (一个 String,) and strict (一个 Boolean,) and returns 要么是包含 ECMAScript 语言值正常完成,要么是抛出完成. 它返回其所绑定的、名称为 name 的标识符的值。如果该绑定存在但尚未初始化,则无论 strict 的值为何,都会抛出 ReferenceError。 It performs the following steps when called:

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

9.1.1.1.7 DeleteBinding ( name )

The DeleteBinding concrete method of a Declarative Environment Record envRec takes argument name (一个 String,) and returns 一个包含 Boolean 的正常完成. 它只能删除那些被显式指定为可删除的绑定。 It performs the following steps when called:

  1. 断言:envRec 具有 name 的绑定。
  2. 如果 envRecname 的绑定不能被删除,返回 false
  3. envRec 中移除 name 的绑定。
  4. 返回 true

9.1.1.1.8 HasThisBinding ( )

The HasThisBinding concrete method of a Declarative Environment Record envRec takes no arguments and returns false. It performs the following steps when called:

  1. 返回 false
Note

普通的 Declarative Environment Record(即既不是 Function Environment Record 也不是 Module Environment Record 的那种)不提供 this 绑定。

9.1.1.1.9 GetThisBinding ( )

本规范中从不使用 Declarative Environment RecordGetThisBinding 具体方法。

9.1.1.1.10 HasSuperBinding ( )

The HasSuperBinding concrete method of a Declarative Environment Record envRec takes no arguments and returns false. It performs the following steps when called:

  1. 返回 false
Note

普通的 Declarative Environment Record(即既不是 Function Environment Record 也不是 Module Environment Record 的那种)不提供 super 绑定。

9.1.1.1.11 WithBaseObject ( )

The WithBaseObject concrete method of a Declarative Environment Record envRec takes no arguments and returns undefined. It performs the following steps when called:

  1. 返回 undefined

9.1.1.2 Object Environment Record

每个 Object Environment Record 都与一个称为其绑定对象的对象相关联。Object Environment Record 绑定了一组字符串标识符名称,这些名称直接对应于其绑定对象的属性名属性键中那些不是 IdentifierName 形式的字符串的,不包含在绑定标识符集合中。无论是自有属性还是继承属性,都包含在此集合中,而不管它们的 [[Enumerable]] 特性的设置如何。由于对象的属性可以被动态添加和删除,因此 Object Environment Record 所绑定的标识符集合,可能会作为任何添加或删除属性操作的副作用而发生变化。由于这类副作用而创建的任何绑定,即使相应属性的 Writable 特性为 false,也会被视为可变绑定。Object Environment Record 不存在不可变绑定。

with 语句(14.11)创建的 Object Environment Record,可以将其绑定对象作为函数调用中的隐式 this 值提供。该能力由一个 Boolean 类型[[IsWithEnvironment]] 字段控制。

Object Environment Record 具有 Table 15 中列出的附加状态字段。

Table 15: Object Environment Record 的附加字段
字段名称 含义
[[BindingObject]] 一个 Object Environment Record 的绑定对象。
[[IsWithEnvironment]] 一个 Boolean 表示此 Environment Record 是否是为 with 语句创建的。

9.1.1.2.1 HasBinding ( name )

The HasBinding concrete method of a Object Environment Record envRec takes argument name (一个 String,) and returns 要么是包含 Boolean 的正常完成,要么是抛出完成. 它用于判定其关联的绑定对象是否具有名称为 name 的属性。 It performs the following steps when called:

  1. bindingObjectenvRec.[[BindingObject]]
  2. foundBinding 为 ? HasProperty(bindingObject, name)。
  3. 如果 foundBindingfalse,返回 false
  4. 如果 envRec.[[IsWithEnvironment]]false,返回 true
  5. unscopables 为 ? Get(bindingObject, %Symbol.unscopables%)。
  6. 如果 unscopables 是一个 Object,那么
    1. blockedToBoolean(? Get(unscopables, name))。
    2. 如果 blockedtrue,返回 false
  7. 返回 true

9.1.1.2.2 CreateMutableBinding ( name, deletable )

The CreateMutableBinding concrete method of a Object Environment Record envRec takes arguments name (一个 String,) and deletable (一个 Boolean,) and returns 要么是包含 unused正常完成,要么是抛出完成. 它会在 Environment Record 关联的绑定对象中创建一个名为 name 的属性,并将其初始化为值 undefined。如果 deletabletrue,则该新属性的 [[Configurable]] 特性设为 true;否则设为 false。 It performs the following steps when called:

  1. bindingObjectenvRec.[[BindingObject]]
  2. 执行 ? DefinePropertyOrThrow(bindingObject, name, PropertyDescriptor { [[Value]]: undefined, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: deletable })。
  3. 返回 unused
Note

通常 envRec 不会已有 name 的绑定,但如果已有,则 DefinePropertyOrThrow 的语义可能导致现有绑定被替换、被遮蔽,或导致返回突兀完成

9.1.1.2.3 CreateImmutableBinding ( name, strict )

本规范中从不使用 Object Environment RecordCreateImmutableBinding 具体方法。

9.1.1.2.4 InitializeBinding ( name, value )

The InitializeBinding concrete method of a Object Environment Record envRec takes arguments name (一个 String,) and value (一个 ECMAScript 语言值,) and returns 要么是包含 unused正常完成,要么是抛出完成. 它用于将当前名称为 name 的标识符绑定的绑定值设为 value。 It performs the following steps when called:

  1. 执行 ? envRec.SetMutableBinding(name, value, false)
  2. 返回 unused
Note

在本规范中,Object Environment Record 上所有对 CreateMutableBinding 的使用,都会立即紧跟着对同一名称调用 InitializeBinding。因此,本规范不会显式跟踪 Object Environment Record 中绑定的初始化状态。

9.1.1.2.5 SetMutableBinding ( name, value, strict )

The SetMutableBinding concrete method of a Object Environment Record envRec takes arguments name (一个 String,), value (一个 ECMAScript 语言值,), and strict (一个 Boolean,) and returns 要么是包含 unused正常完成,要么是抛出完成. 它尝试将该 Environment Record 关联的绑定对象中名称为 name 的属性值设为 value。通常名称为 name 的属性已存在,但如果不存在,或当前不可写,则错误处理由 strict 决定。 It performs the following steps when called:

  1. bindingObjectenvRec.[[BindingObject]]
  2. stillExists 为 ? HasProperty(bindingObject, name)。
  3. 如果 stillExistsfalsestricttrue,抛出一个 ReferenceError 异常。
  4. 执行 ? Set(bindingObject, name, value, strict)。
  5. 返回 unused

9.1.1.2.6 GetBindingValue ( name, strict )

The GetBindingValue concrete method of a Object Environment Record envRec takes arguments name (一个 String,) and strict (一个 Boolean,) and returns 要么是包含 ECMAScript 语言值正常完成,要么是抛出完成. 它返回其关联的绑定对象中名称为 name 的属性值。该属性应当已经存在,但如果不存在,则结果取决于 strict。 It performs the following steps when called:

  1. bindingObjectenvRec.[[BindingObject]]
  2. value 为 ? HasProperty(bindingObject, name)。
  3. 如果 valuefalse,那么
    1. 如果 strictfalse,返回 undefined
    2. 抛出一个 ReferenceError 异常。
  4. 返回 ? Get(bindingObject, name)。

9.1.1.2.7 DeleteBinding ( name )

The DeleteBinding concrete method of a Object Environment Record envRec takes argument name (一个 String,) and returns 要么是包含 Boolean 的正常完成,要么是抛出完成. 它只能删除那些对应于环境对象属性、且其 [[Configurable]] 特性值为 true 的绑定。 It performs the following steps when called:

  1. bindingObjectenvRec.[[BindingObject]]
  2. 返回 ? bindingObject.[[Delete]](name)

9.1.1.2.8 HasThisBinding ( )

The HasThisBinding concrete method of a Object Environment Record envRec takes no arguments and returns false. It performs the following steps when called:

  1. 返回 false
Note

Object Environment Record 不提供 this 绑定。

9.1.1.2.9 GetThisBinding ( )

本规范中从不使用 Object Environment RecordGetThisBinding 具体方法。

9.1.1.2.10 HasSuperBinding ( )

The HasSuperBinding concrete method of a Object Environment Record envRec takes no arguments and returns false. It performs the following steps when called:

  1. 返回 false
Note

Object Environment Record 不提供 super 绑定。

9.1.1.2.11 WithBaseObject ( )

The WithBaseObject concrete method of a Object Environment Record envRec takes no arguments and returns 一个 Object 或 undefined. It performs the following steps when called:

  1. 如果 envRec.[[IsWithEnvironment]]true,返回 envRec.[[BindingObject]]
  2. 返回 undefined

9.1.1.3 Function Environment Record

Function Environment Record 是一种 Declarative Environment Record,用于表示函数的顶层作用域,并且如果该函数不是 ArrowFunction,则提供 this 绑定。如果函数不是 ArrowFunction 且引用了 super,那么它的 Function Environment Record 还会包含从该函数内部执行 super 方法调用所需的状态。

Function Environment Record 具有 Table 16 中列出的附加状态字段。

Table 16: Function Environment Record 的附加字段
字段名称 含义
[[ThisValue]] 一个 ECMAScript 语言值 这是本次函数调用所使用的 this 值。
[[ThisBindingStatus]] lexicalinitializeduninitialized 如果该值为 lexical,则表示这是一个 ArrowFunction,并且没有局部 this 值。
[[FunctionObject]] 一个 ECMAScript 函数对象 导致创建本 Environment Record 的那个函数对象调用本身。
[[NewTarget]] 一个构造器undefined 如果该 Environment Record 是由 [[Construct]] 内部方法创建的,则 [[NewTarget]] 的值是 [[Construct]]newTarget 参数值。否则,其值为 undefined

Function Environment Record 支持 Table 14 中列出的所有 Declarative Environment Record 方法,并且除 HasThisBindingGetThisBindingHasSuperBinding 之外,其余这些方法的规范都与 Declarative Environment Record 相同。

9.1.1.3.1 BindThisValue ( envRec, value )

The abstract operation BindThisValue takes arguments envRec (一个 Function Environment Record,) and value (一个 ECMAScript 语言值,) and returns 要么是包含 unused正常完成,要么是抛出完成. 它设置 envRec.[[ThisValue]] 并记录其已经初始化。 It performs the following steps when called:

  1. 断言:envRec.[[ThisBindingStatus]] 不是 lexical
  2. 如果 envRec.[[ThisBindingStatus]]initialized,抛出一个 ReferenceError 异常。
  3. envRec.[[ThisValue]] 设为 value
  4. envRec.[[ThisBindingStatus]] 设为 initialized
  5. 返回 unused

9.1.1.3.2 HasThisBinding ( )

The HasThisBinding concrete method of a Function Environment Record envRec takes no arguments and returns 一个 Boolean. It performs the following steps when called:

  1. 如果 envRec.[[ThisBindingStatus]]lexical,返回 false
  2. 返回 true

9.1.1.3.3 GetThisBinding ( )

The GetThisBinding concrete method of a Function Environment Record envRec takes no arguments and returns 要么是包含 ECMAScript 语言值正常完成,要么是抛出完成. It performs the following steps when called:

  1. 断言:envRec.[[ThisBindingStatus]] 不是 lexical
  2. 如果 envRec.[[ThisBindingStatus]]uninitialized,抛出一个 ReferenceError 异常。
  3. 返回 envRec.[[ThisValue]]

9.1.1.3.4 HasSuperBinding ( )

The HasSuperBinding concrete method of a Function Environment Record envRec takes no arguments and returns 一个 Boolean. It performs the following steps when called:

  1. 如果 envRec.[[ThisBindingStatus]]lexical,返回 false
  2. 如果 envRec.[[FunctionObject]].[[HomeObject]]undefined,返回 false
  3. 返回 true

9.1.1.3.5 GetSuperBase ( envRec )

The abstract operation GetSuperBase takes argument envRec (一个 Function Environment Record,) and returns 一个 Object、nullundefined. 它返回作为 envRec 中绑定的 super 属性访问基础对象的那个对象。值 undefined 表示这类访问将产生运行时错误。 It performs the following steps when called:

  1. homeenvRec.[[FunctionObject]].[[HomeObject]]
  2. 如果 homeundefined,返回 undefined
  3. 断言:home 是一个普通对象
  4. 返回 ! home.[[GetPrototypeOf]]()。

9.1.1.4 Global Environment Record

Global Environment Record 用于表示在某个共享 realm 中,由所有被处理的 ECMAScript Script 元素共同共享的最外层作用域。Global Environment Record 为内建全局对象(条款 19)、全局对象的属性,以及 Script 中出现的所有顶层声明(8.2.98.2.11)提供绑定。

从逻辑上说,Global Environment Record 是一个单一记录,但规范中将其描述为一个封装了 Object Environment RecordDeclarative Environment Record 的复合体。其 Object Environment Record 的基础对象是关联 Realm Record全局对象。这个全局对象也是 Global Environment Record 的 GetThisBinding 具体方法返回的值。Global Environment Record 的 Object Environment Record 组件,包含所有内建全局对象(条款 19)的绑定,以及全局代码中由 FunctionDeclarationGeneratorDeclarationAsyncFunctionDeclarationAsyncGeneratorDeclarationVariableStatement 引入的所有绑定。全局代码中所有其他 ECMAScript 声明的绑定,则包含在 Global Environment Record 的 Declarative Environment Record 组件中。

属性可以被直接创建在全局对象上。因此,Global Environment Record 的 Object Environment Record 组件,既可能包含由 FunctionDeclarationGeneratorDeclarationAsyncFunctionDeclarationAsyncGeneratorDeclarationVariableDeclaration 显式创建的绑定,也可能包含作为全局对象属性而隐式创建的绑定。

Global Environment Record 具有 Table 17 中列出的附加字段。

Table 17: Global Environment Record 的附加字段
字段名称 含义
[[ObjectRecord]] 一个 Object Environment Record 其绑定对象是全局对象。它包含关联 realm 的全局内建绑定,以及全局代码中的 FunctionDeclarationGeneratorDeclarationAsyncFunctionDeclarationAsyncGeneratorDeclarationVariableDeclaration 绑定。
[[GlobalThisValue]] 一个 Object 全局作用域中 this 返回的值。宿主可以提供任意 ECMAScript Object 值。
[[DeclarativeRecord]] 一个 Declarative Environment Record 包含关联 realm 代码的全局代码中所有声明的绑定,但不包括 FunctionDeclarationGeneratorDeclarationAsyncFunctionDeclarationAsyncGeneratorDeclarationVariableDeclaration 绑定。

9.1.1.4.1 HasBinding ( name )

The HasBinding concrete method of a Global Environment Record envRec takes argument name (一个 String,) and returns 要么是包含 Boolean 的正常完成,要么是抛出完成. 它用于判定参数标识符是否是该记录所绑定的标识符之一。 It performs the following steps when called:

  1. declarativeRecordenvRec.[[DeclarativeRecord]]
  2. 如果 ! declarativeRecord.HasBinding(name) 是 true,返回 true
  3. objectRecordenvRec.[[ObjectRecord]]
  4. 返回 ? objectRecord.HasBinding(name)

9.1.1.4.2 CreateMutableBinding ( name, deletable )

The CreateMutableBinding concrete method of a Global Environment Record envRec takes arguments name (一个 String,) and deletable (一个 Boolean,) and returns 要么是包含 unused正常完成,要么是抛出完成. 它为名称 name 创建一个新的未初始化可变绑定。该绑定创建于关联的 DeclarativeRecord 中。DeclarativeRecord 中必须还不存在 name 的绑定。如果 deletabletrue,则新绑定会被标记为可删除。 It performs the following steps when called:

  1. declarativeRecordenvRec.[[DeclarativeRecord]]
  2. 如果 ! declarativeRecord.HasBinding(name) 是 true,抛出一个 TypeError 异常。
  3. 返回 ! declarativeRecord.CreateMutableBinding(name, deletable)。

9.1.1.4.3 CreateImmutableBinding ( name, strict )

The CreateImmutableBinding concrete method of a Global Environment Record envRec takes arguments name (一个 String,) and strict (一个 Boolean,) and returns 要么是包含 unused正常完成,要么是抛出完成. 它为名称 name 创建一个新的未初始化不可变绑定。在这个 Environment Record 中,name 的绑定必须尚不存在。如果 stricttrue,则新绑定会被标记为严格绑定。 It performs the following steps when called:

  1. declarativeRecordenvRec.[[DeclarativeRecord]]
  2. 如果 ! declarativeRecord.HasBinding(name) 是 true,抛出一个 TypeError 异常。
  3. 返回 ! declarativeRecord.CreateImmutableBinding(name, strict)。

9.1.1.4.4 InitializeBinding ( name, value )

The InitializeBinding concrete method of a Global Environment Record envRec takes arguments name (一个 String,) and value (一个 ECMAScript 语言值,) and returns 要么是包含 unused正常完成,要么是抛出完成. 它用于将当前名称为 name 的标识符绑定的绑定值设为 value。必须已经存在一个未初始化的 name 绑定。 It performs the following steps when called:

  1. declarativeRecordenvRec.[[DeclarativeRecord]]
  2. 如果 ! declarativeRecord.HasBinding(name) 是 true,那么
    1. 返回 ! declarativeRecord.InitializeBinding(name, value)。
  3. 断言:如果绑定存在,那么它一定在 Object Environment Record 中。
  4. objectRecordenvRec.[[ObjectRecord]]
  5. 返回 ? objectRecord.InitializeBinding(name, value)

9.1.1.4.5 SetMutableBinding ( name, value, strict )

The SetMutableBinding concrete method of a Global Environment Record envRec takes arguments name (一个 String,), value (一个 ECMAScript 语言值,), and strict (一个 Boolean,) and returns 要么是包含 unused正常完成,要么是抛出完成. 它尝试将当前名称为 name 的标识符绑定的绑定值更改为 value。如果该绑定是不可变绑定且 stricttrue,则会抛出一个 TypeError。通常名称为 name 的绑定已经存在,但如果不存在,或当前不可写,则错误处理由 strict 决定。 It performs the following steps when called:

  1. declarativeRecordenvRec.[[DeclarativeRecord]]
  2. 如果 ! declarativeRecord.HasBinding(name) 是 true,那么
    1. 返回 ? declarativeRecord.SetMutableBinding(name, value, strict)。
  3. objectRecordenvRec.[[ObjectRecord]]
  4. 返回 ? objectRecord.SetMutableBinding(name, value, strict)

9.1.1.4.6 GetBindingValue ( name, strict )

The GetBindingValue concrete method of a Global Environment Record envRec takes arguments name (一个 String,) and strict (一个 Boolean,) and returns 要么是包含 ECMAScript 语言值正常完成,要么是抛出完成. 它返回其绑定的、名称为 name 的标识符的值。如果绑定是未初始化绑定,则会抛出一个 ReferenceError 异常。通常名称为 name 的绑定已经存在,但如果不存在,或当前不可写,则错误处理由 strict 决定。 It performs the following steps when called:

  1. declarativeRecordenvRec.[[DeclarativeRecord]]
  2. 如果 ! declarativeRecord.HasBinding(name) 是 true,那么
    1. 返回 ? declarativeRecord.GetBindingValue(name, strict)。
  3. objectRecordenvRec.[[ObjectRecord]]
  4. 返回 ? objectRecord.GetBindingValue(name, strict)

9.1.1.4.7 DeleteBinding ( name )

The DeleteBinding concrete method of a Global Environment Record envRec takes argument name (一个 String,) and returns 要么是包含 Boolean 的正常完成,要么是抛出完成. 它只能删除那些被显式指定为可删除的绑定。 It performs the following steps when called:

  1. declarativeRecordenvRec.[[DeclarativeRecord]]
  2. 如果 ! declarativeRecord.HasBinding(name) 是 true,那么
    1. 返回 ! declarativeRecord.DeleteBinding(name)。
  3. objectRecordenvRec.[[ObjectRecord]]
  4. globalObjectobjectRecord.[[BindingObject]]
  5. existingProp 为 ? HasOwnProperty(globalObject, name)。
  6. 如果 existingProptrue,那么
    1. 返回 ? objectRecord.DeleteBinding(name)
  7. 返回 true

9.1.1.4.8 HasThisBinding ( )

The HasThisBinding concrete method of a Global Environment Record envRec takes no arguments and returns true. It performs the following steps when called:

  1. 返回 true
Note

Global Environment Record 总是提供 this 绑定。

9.1.1.4.9 GetThisBinding ( )

The GetThisBinding concrete method of a Global Environment Record envRec takes no arguments and returns 一个包含 Object 的正常完成. It performs the following steps when called:

  1. 返回 envRec.[[GlobalThisValue]]

9.1.1.4.10 HasSuperBinding ( )

The HasSuperBinding concrete method of a Global Environment Record envRec takes no arguments and returns false. It performs the following steps when called:

  1. 返回 false
Note

Global Environment Record 不提供 super 绑定。

9.1.1.4.11 WithBaseObject ( )

The WithBaseObject concrete method of a Global Environment Record envRec takes no arguments and returns undefined. It performs the following steps when called:

  1. 返回 undefined

9.1.1.4.12 HasLexicalDeclaration ( envRec, name )

The abstract operation HasLexicalDeclaration takes arguments envRec (一个 Global Environment Record,) and name (一个 String,) and returns 一个 Boolean. 它用于判定参数标识符在 envRec 中是否具有一个由词法声明(例如 LexicalDeclarationClassDeclaration)创建的绑定。 It performs the following steps when called:

  1. declarativeRecordenvRec.[[DeclarativeRecord]]
  2. 返回 ! declarativeRecord.HasBinding(name)。

9.1.1.4.13 HasRestrictedGlobalProperty ( envRec, name )

The abstract operation HasRestrictedGlobalProperty takes arguments envRec (一个 Global Environment Record,) and name (一个 String,) and returns 要么是包含 Boolean 的正常完成,要么是抛出完成. 它用于判定参数标识符是否是全局对象上某个属性的名称,并且该属性不能被全局词法绑定遮蔽。 It performs the following steps when called:

  1. objectRecordenvRec.[[ObjectRecord]]
  2. globalObjectobjectRecord.[[BindingObject]]
  3. existingProp 为 ? globalObject.[[GetOwnProperty]](name)
  4. 如果 existingPropundefined,返回 false
  5. 如果 existingProp.[[Configurable]]true,返回 false
  6. 返回 true
Note

全局对象上可能存在某些直接创建出来的属性,而不是通过 var 或 function 声明来声明的。不能创建一个与全局对象的不可配置属性同名的全局词法绑定。全局属性 "undefined" 就是这样一个属性的例子。

9.1.1.4.14 CanDeclareGlobalVar ( envRec, name )

The abstract operation CanDeclareGlobalVar takes arguments envRec (一个 Global Environment Record,) and name (一个 String,) and returns 要么是包含 Boolean 的正常完成,要么是抛出完成. 它用于判定:如果对同一个参数 name 调用对应的 CreateGlobalVarBinding,是否会成功。冗余的 var 声明,以及为已有全局对象属性进行的 var 声明,都是允许的。 It performs the following steps when called:

  1. objectRecordenvRec.[[ObjectRecord]]
  2. globalObjectobjectRecord.[[BindingObject]]
  3. hasProperty 为 ? HasOwnProperty(globalObject, name)。
  4. 如果 hasPropertytrue,返回 true
  5. 返回 ? IsExtensible(globalObject)。

9.1.1.4.15 CanDeclareGlobalFunction ( envRec, name )

The abstract operation CanDeclareGlobalFunction takes arguments envRec (一个 Global Environment Record,) and name (一个 String,) and returns 要么是包含 Boolean 的正常完成,要么是抛出完成. 它用于判定:如果对同一个参数 name 调用对应的 CreateGlobalFunctionBinding,是否会成功。 It performs the following steps when called:

  1. objectRecordenvRec.[[ObjectRecord]]
  2. globalObjectobjectRecord.[[BindingObject]]
  3. existingProp 为 ? globalObject.[[GetOwnProperty]](name)
  4. 如果 existingPropundefined,返回 ? IsExtensible(globalObject)。
  5. 如果 existingProp.[[Configurable]]true,返回 true
  6. 如果 IsDataDescriptor(existingProp) 是 true,并且 existingProp 具有特性值 { [[Writable]]: true, [[Enumerable]]: true },返回 true
  7. 返回 false

9.1.1.4.16 CreateGlobalVarBinding ( envRec, name, deletable )

The abstract operation CreateGlobalVarBinding takes arguments envRec (一个 Global Environment Record,), name (一个 String,), and deletable (一个 Boolean,) and returns 要么是包含 unused正常完成,要么是抛出完成. 它在关联的 Object Environment Record 中创建并初始化一个可变绑定。如果绑定已经存在,则重用它,并假定其已经初始化。 It performs the following steps when called:

  1. objectRecordenvRec.[[ObjectRecord]]
  2. globalObjectobjectRecord.[[BindingObject]]
  3. hasProperty 为 ? HasOwnProperty(globalObject, name)。
  4. extensible 为 ? IsExtensible(globalObject)。
  5. 如果 hasPropertyfalseextensibletrue,那么
    1. 执行 ? objectRecord.CreateMutableBinding(name, deletable)
    2. 执行 ? objectRecord.InitializeBinding(name, undefined)
  6. 返回 unused

9.1.1.4.17 CreateGlobalFunctionBinding ( envRec, name, value, deletable )

The abstract operation CreateGlobalFunctionBinding takes arguments envRec (a Global Environment Record), name (a String), value (an ECMAScript function object), and deletable (a Boolean) and returns 要么是包含 unused正常完成,要么是抛出完成. 它在关联的 Object Environment Record 中创建并初始化一个可变绑定。如果绑定已经存在,则会被替换。 It performs the following steps when called:

  1. objectRecordenvRec.[[ObjectRecord]]
  2. globalObjectobjectRecord.[[BindingObject]]
  3. existingProp 为 ? globalObject.[[GetOwnProperty]](name)
  4. 如果 existingPropundefinedexistingProp.[[Configurable]]true,那么
    1. desc 为 PropertyDescriptor { [[Value]]: value, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: deletable }。
  5. 否则,
    1. desc 为 PropertyDescriptor { [[Value]]: value }。
  6. 执行 ? DefinePropertyOrThrow(globalObject, name, desc)。
  7. 执行 ? Set(globalObject, name, value, false)。
  8. 返回 unused
Note

全局函数声明始终表示为全局对象的自有属性。如果可能,会重新配置已有的自有属性,使其具有一组标准特性值。步骤 7 等价于调用 InitializeBinding 具体方法将执行的操作;如果 globalObject 是一个 Proxy,则会产生相同顺序的 Proxy trap 调用。

9.1.1.5 Module Environment Record

Module Environment Record 是一种 Declarative Environment Record,用于表示 ECMAScript Module 的外层作用域。除了普通的可变绑定和不可变绑定之外,Module Environment Record 还提供不可变的 import 绑定,这类绑定会间接访问存在于另一个 Environment Record 中的目标绑定。

Module Environment Record 支持 Table 14 中列出的所有 Declarative Environment Record 方法,并且除 GetBindingValueDeleteBindingHasThisBindingGetThisBinding 之外,其余这些方法的规范都与 Declarative Environment Record 相同。

9.1.1.5.1 GetBindingValue ( name, strict )

The GetBindingValue concrete method of a Module Environment Record envRec takes arguments name (一个 String,) and strict (一个 Boolean,) and returns 要么是包含 ECMAScript 语言值正常完成,要么是抛出完成. 它返回其绑定的、名称为 name 的标识符的值。不过,如果该绑定是一个间接绑定,则返回目标绑定的值。如果绑定存在但未初始化,则抛出 ReferenceError。 It performs the following steps when called:

  1. 断言:stricttrue
  2. 断言:envRec 具有 name 的绑定。
  3. 如果 name 的绑定是一个间接绑定,那么
    1. moduletargetName 为创建这个 name 绑定时提供的间接引用值。
    2. targetEnvmodule.[[Environment]]
    3. 如果 targetEnvempty,抛出一个 ReferenceError 异常。
    4. 返回 ? targetEnv.GetBindingValue(targetName, true)
  4. 如果 envRecname 的绑定是未初始化绑定,抛出一个 ReferenceError 异常。
  5. 返回 envRec 中当前绑定到 name 的值。
Note

strict 总是 true,因为 Module 始终是严格模式代码

9.1.1.5.2 DeleteBinding ( name )

本规范中从不使用 Module Environment RecordDeleteBinding 具体方法。

Note

Module Environment Record 只会在严格代码中使用,而早期错误规则会阻止在严格代码中将 delete 运算符应用到一个最终会解析为 Module Environment Record 绑定的 Reference Record 上。见 13.5.1.1

9.1.1.5.3 HasThisBinding ( )

The HasThisBinding concrete method of a Module Environment Record envRec takes no arguments and returns true. It performs the following steps when called:

  1. 返回 true
Note

Module Environment Record 总是提供 this 绑定。

9.1.1.5.4 GetThisBinding ( )

The GetThisBinding concrete method of a Module Environment Record envRec takes no arguments and returns 一个包含 undefined正常完成. It performs the following steps when called:

  1. 返回 undefined

9.1.1.5.5 CreateImportBinding ( envRec, name, targetModule, targetName )

The abstract operation CreateImportBinding takes arguments envRec (一个 Module Environment Record,), name (一个 String,), targetModule (一个 Module Record,), and targetName (一个 String,) and returns unused. 它为名称 name 创建一个新的、已初始化的不可变间接绑定。在 envRec 中,name 的绑定必须尚不存在。targetName 是存在于 targetModuleModule Environment Record 中的某个绑定名称。对这个新绑定值的访问将会间接访问目标绑定所绑定的值。 It performs the following steps when called:

  1. 断言:envRec 尚不存在 name 的绑定。
  2. 断言:当 targetModule.[[Environment]] 被实例化时,它将具有 targetName 的直接绑定。
  3. envRec 中为 name 创建一个不可变间接绑定,该绑定引用 targetModuletargetName 作为其目标绑定,并记录该绑定已初始化。
  4. 返回 unused

9.1.2 Environment Record 操作

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

9.1.2.1 GetIdentifierReference ( env, name, strict )

The abstract operation GetIdentifierReference takes arguments env (一个 Environment Recordnull,), name (一个 String,), and strict (一个 Boolean,) and returns 要么是包含 Reference Record正常完成,要么是抛出完成. It performs the following steps when called:

  1. 如果 envnull,那么
    1. 返回 Reference Record { [[Base]]: unresolvable, [[ReferencedName]]: name, [[Strict]]: strict, [[ThisValue]]: empty }。
  2. exists 为 ? env.HasBinding(name)
  3. 如果 existstrue,那么
    1. 返回 Reference Record { [[Base]]: env, [[ReferencedName]]: name, [[Strict]]: strict, [[ThisValue]]: empty }。
  4. outerenv.[[OuterEnv]]
  5. 返回 ? GetIdentifierReference(outer, name, strict)。

9.1.2.2 NewDeclarativeEnvironment ( outerEnv )

The abstract operation NewDeclarativeEnvironment takes argument outerEnv (一个 Environment Recordnull,) and returns 一个 Declarative Environment Record. It performs the following steps when called:

  1. env 为一个新的 Declarative Environment Record,不含任何绑定。
  2. env.[[OuterEnv]] 设为 outerEnv
  3. 返回 env

9.1.2.3 NewObjectEnvironment ( obj, isWithEnvironment, outerEnv )

The abstract operation NewObjectEnvironment takes arguments obj (一个 Object,), isWithEnvironment (一个 Boolean,), and outerEnv (一个 Environment Recordnull,) and returns 一个 Object Environment Record. It performs the following steps when called:

  1. env 为一个新的 Object Environment Record
  2. env.[[BindingObject]] 设为 obj
  3. env.[[IsWithEnvironment]] 设为 isWithEnvironment
  4. env.[[OuterEnv]] 设为 outerEnv
  5. 返回 env

9.1.2.4 NewFunctionEnvironment ( func, newTarget )

The abstract operation NewFunctionEnvironment takes arguments func (一个 ECMAScript 函数对象,) and newTarget (一个 Object 或 undefined,) and returns 一个 Function Environment Record. It performs the following steps when called:

  1. env 为一个新的 Function Environment Record,不含任何绑定。
  2. env.[[FunctionObject]] 设为 func
  3. 如果 func.[[ThisMode]]lexical,将 env.[[ThisBindingStatus]] 设为 lexical
  4. 否则,将 env.[[ThisBindingStatus]] 设为 uninitialized
  5. env.[[NewTarget]] 设为 newTarget
  6. env.[[OuterEnv]] 设为 func.[[Environment]]
  7. 返回 env

9.1.2.5 NewGlobalEnvironment ( obj, thisValue )

The abstract operation NewGlobalEnvironment takes arguments obj (一个 Object,) and thisValue (一个 Object,) and returns 一个 Global Environment Record. It performs the following steps when called:

  1. objRecNewObjectEnvironment(obj, false, null)。
  2. dclRecNewDeclarativeEnvironment(null)。
  3. env 为一个新的 Global Environment Record
  4. env.[[ObjectRecord]] 设为 objRec
  5. env.[[GlobalThisValue]] 设为 thisValue
  6. env.[[DeclarativeRecord]] 设为 dclRec
  7. env.[[OuterEnv]] 设为 null
  8. 返回 env

9.1.2.6 NewModuleEnvironment ( outerEnv )

The abstract operation NewModuleEnvironment takes argument outerEnv (a Global Environment Record) and returns a Module Environment Record. It performs the following steps when called:

  1. env 为一个新的 Module Environment Record,不含任何绑定。
  2. env.[[OuterEnv]] 设为 outerEnv
  3. 返回 env

9.2 PrivateEnvironment Record

PrivateEnvironment Record 是一种规范机制,用于根据 ECMAScript 代码中 ClassDeclarationClassExpression 的词法嵌套结构来追踪 Private Name。它们与 Environment Record 类似,但彼此不同。每个 PrivateEnvironment Record 都与一个 ClassDeclarationClassExpression 相关联。每次对此类类进行求值时,都会创建一个新的 PrivateEnvironment Record,用来记录该类声明的 Private Name

每个 PrivateEnvironment Record 都具有 Table 18 中定义的字段。

Table 18: PrivateEnvironment Record 字段
字段名称 值类型 含义
[[OuterPrivateEnvironment]] 一个 PrivateEnvironment Recordnull 最近的包含类的 PrivateEnvironment Record。如果与此 PrivateEnvironment Record 相关联的类未包含在任何其他类中,则为 null
[[Names]] 一个 Private NameList 由该类声明的 Private Name

9.2.1 PrivateEnvironment Record 操作

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

9.2.1.1 NewPrivateEnvironment ( outerPrivateEnv )

The abstract operation NewPrivateEnvironment takes argument outerPrivateEnv (一个 PrivateEnvironment Recordnull,) and returns 一个 PrivateEnvironment Record. It performs the following steps when called:

  1. names 为一个新的空 List
  2. 返回 PrivateEnvironment Record { [[OuterPrivateEnvironment]]: outerPrivateEnv, [[Names]]: names }。

9.2.1.2 ResolvePrivateIdentifier ( privateEnv, identifier )

The abstract operation ResolvePrivateIdentifier takes arguments privateEnv (一个 PrivateEnvironment Record,) and identifier (一个 String,) and returns 一个 Private Name. It performs the following steps when called:

  1. namesprivateEnv.[[Names]]
  2. names 中的每个 Private Name pn,执行
    1. 如果 pn.[[Description]]identifier,那么
      1. 返回 pn
  3. outerPrivateEnvprivateEnv.[[OuterPrivateEnvironment]]
  4. 断言:outerPrivateEnv 不是 null
  5. 返回 ResolvePrivateIdentifier(outerPrivateEnv, identifier)。

9.3 Realm

在求值之前,所有 ECMAScript 代码都必须与一个 realm 相关联。从概念上说,一个 realm 由一组内在对象、一个 ECMAScript 全局环境、在该全局环境作用域内加载的所有 ECMAScript 代码,以及其他相关状态和资源组成。

在本规范中,realm 表示为一个 Realm Record,其字段规定在 Table 19 中:

Table 19: Realm Record 字段
字段名称 含义
[[AgentSignifier]] 一个 agent 标识符 拥有该 realmagent
[[Intrinsics]] 一个 Record,其字段名为内在键,字段值为对象 与该 realm 关联的代码所使用的内在值
[[GlobalObject]] 一个 Object realm全局对象
[[GlobalEnv]] 一个 Global Environment Record realm 的全局环境
[[TemplateMap]] 一个 RecordList,这些 Record 具有 [[Site]](一个 TemplateLiteral Parse Node)和 [[Array]](一个 Array)字段

模板对象会针对每个 realm 分别使用其 Realm Record[[TemplateMap]] 进行规范化。每个 [[Site]] 值都是一个 Parse Node,并且是一个 TemplateLiteral。关联的 [[Array]] 值是传递给标签函数的对应模板对象。

Note 1
一旦某个 Parse Node 变得不可达,则相应的 [[Array]] 也变得不可达,并且如果某实现将该对从 [[TemplateMap]] 列表中移除,这种行为将不可观察。
[[LoadedModules]] 一个 LoadedModuleRequest RecordList

从该 realm 导入的说明符字符串到已解析 Module Record 的映射。该列表中不会包含两个不同的 Record r1r2,使得 ModuleRequestsEqual(r1, r2) 是 true

Note 2
HostLoadImportedModule16.2.1.10 Note 1)中所述,Realm Record 中的 [[LoadedModules]] 仅在没有活动 script 或 module 的上下文中运行 import() 表达式时使用。
[[HostDefined]] 任意值(默认值为 undefined 为需要将附加信息与 Realm Record 关联起来的宿主保留的字段。

9.3.1 InitializeHostDefinedRealm ( )

The abstract operation InitializeHostDefinedRealm takes no arguments and returns 要么是包含 unused正常完成,要么是抛出完成. It performs the following steps when called:

  1. realm 为一个新的 Realm Record
  2. 执行 CreateIntrinsics(realm)。
  3. realm.[[AgentSignifier]] 设为 AgentSignifier()。
  4. realm.[[TemplateMap]] 设为一个新的空 List
  5. newContext 为一个新的执行上下文
  6. newContext 的 Function 设为 null
  7. newContextRealm 设为 realm
  8. newContext 的 ScriptOrModule 设为 null
  9. newContext 压入执行上下文栈newContext 现在是正在运行的执行上下文
  10. 如果宿主要求使用某个特定对象作为 realm全局对象,那么
    1. global 为以宿主定义方式创建的该对象。
  11. 否则,
    1. globalOrdinaryObjectCreate(realm.[[Intrinsics]].[[%Object.prototype%]])。
  12. 如果宿主要求 realm 的全局作用域中的 this 绑定返回的对象不同于全局对象,那么
    1. thisValue 为以宿主定义方式创建的该对象。
  13. 否则,
    1. thisValueglobal
  14. realm.[[GlobalObject]] 设为 global
  15. realm.[[GlobalEnv]] 设为 NewGlobalEnvironment(global, thisValue)。
  16. 执行 ? SetDefaultGlobalBindings(realm)。
  17. global 上创建任何宿主定义全局对象属性。
  18. 返回 unused

9.3.2 CreateIntrinsics ( realmRec )

The abstract operation CreateIntrinsics takes argument realmRec (一个 Realm Record,) and returns unused. It performs the following steps when called:

  1. realmRec.[[Intrinsics]] 设为一个新的 Record
  2. Table 6 中列出的值设为 realmRec.[[Intrinsics]] 的字段。字段名是表中“Intrinsic Name”列列出的名称。每个字段的值都是一个全新的对象值,并且根据条款 1928 中对每个对象的规范,完整且递归地填充其属性值。所有对象属性值都是新创建的对象值。所有内建函数对象的值都通过执行 CreateBuiltinFunction(steps, length, name, slots, realmRec, prototype, async) 来创建,其中 steps 是本规范提供的该函数定义,name 是函数 "name" 属性的初始值,length 是函数 "length" 属性的初始值,slots 是该函数规定的内部名称列表(如果有),prototype 是该函数 [[Prototype]] 内部槽规定的值,而 async 则在该函数被描述为“async”时为 true,否则为 false。内在对象及其属性的创建顺序必须避免依赖于尚未创建的对象。
  3. 执行 AddRestrictedFunctionProperties(realmRec.[[Intrinsics]].[[%Function.prototype%]], realmRec)。
  4. 返回 unused

9.3.3 SetDefaultGlobalBindings ( realmRec )

The abstract operation SetDefaultGlobalBindings takes argument realmRec (一个 Realm Record,) and returns 要么是包含 unused正常完成,要么是抛出完成. It performs the following steps when called:

  1. globalrealmRec.[[GlobalObject]]
  2. 对条款 19 中规定的 Global Object 的每个属性,执行
    1. name 为该属性名的 String 值。
    2. desc 为该属性的完整填充数据 Property Descriptor,包含该属性规定的特性值。对于列在 19.219.319.4 中的属性,其 [[Value]] 特性的值为来自 realmRec 的相应内在对象。
    3. 执行 ? DefinePropertyOrThrow(global, name, desc)。
  3. 返回 unused

9.4 执行上下文

执行上下文是一种规范装置,用于跟踪 ECMAScript 实现对代码的运行时求值。在任意时刻,每个 agent 最多只有一个实际正在执行代码的执行上下文。这称为该 agent正在运行的执行上下文。本规范中所有对正在运行的执行上下文的引用,都表示外围 agent 的正在运行执行上下文。

执行上下文栈用于跟踪执行上下文。正在运行的执行上下文总是该栈的顶部元素。每当控制从当前正在运行执行上下文关联的可执行代码转移到不与该执行上下文关联的可执行代码时,就会创建一个新的执行上下文。新创建的执行上下文会被压入栈中,并成为正在运行的执行上下文

一个执行上下文包含跟踪其关联代码执行进度所需的任何实现特定状态。每个执行上下文至少具有 Table 20 中列出的状态组成部分。

Table 20: 所有执行上下文的状态组成部分
组成部分 目的
代码求值状态 执行、挂起和恢复与该执行上下文关联代码的求值所需的任何状态。
Function 如果该执行上下文正在求值某个函数对象的代码,则该组成部分的值为该函数对象。如果该上下文正在求值 ScriptModule 的代码,则该值为 null
Realm 与该代码访问 ECMAScript 资源相关联的 Realm Record
ScriptOrModule 与该代码来源相关联的 Module RecordScript Record。如果不存在来源脚本或模块(如在 InitializeHostDefinedRealm 中创建的原始执行上下文的情况),则该值为 null

正在运行的执行上下文对代码的求值,可能会在本规范定义的多个点上被挂起。一旦正在运行的执行上下文被挂起,另一个执行上下文就可能成为正在运行的执行上下文并开始求值其代码。在稍后的某个时间点,一个已挂起的执行上下文可能再次成为正在运行的执行上下文,并从先前挂起的位置继续求值其代码。执行上下文之间正在运行状态的切换,通常以栈式后进先出的方式发生。然而,某些 ECMAScript 特性要求执行上下文的正在运行状态发生非 LIFO 切换。

正在运行的执行上下文Realm 组成部分的值,也称为当前 Realm Record正在运行的执行上下文的 Function 组成部分的值,也称为活动函数对象

ECMAScript 代码执行上下文具有 Table 21 中列出的附加状态组成部分。

Table 21: ECMAScript 代码执行上下文的附加状态组成部分
组成部分 目的
LexicalEnvironment 标识用于解析在该执行上下文中的代码所产生的标识符引用的 Environment Record
VariableEnvironment 标识保存该执行上下文VariableStatement 所创建绑定的 Environment Record
PrivateEnvironment 标识保存最近外围类中由 ClassElement 创建的 Private NamePrivateEnvironment Record。如果不存在外围类,则为 null

执行上下文的 LexicalEnvironment 和 VariableEnvironment 组成部分始终都是 Environment Record

表示 Generator 求值的执行上下文具有 Table 22 中列出的附加状态组成部分。

Table 22: Generator 执行上下文的附加状态组成部分
组成部分 目的
Generator 执行上下文正在求值的 Generator。

在大多数情况下,本规范中的算法只会直接操作正在运行的执行上下文(即执行上下文栈顶)。因此,当术语“LexicalEnvironment”和“VariableEnvironment”在未加限定的情况下使用时,它们指的都是正在运行执行上下文中的相应组成部分。

执行上下文纯粹是一种规范机制,不需要对应于任何 ECMAScript 实现中的特定构件。ECMAScript 代码不可能直接访问或观察执行上下文。

9.4.1 GetActiveScriptOrModule ( )

The abstract operation GetActiveScriptOrModule takes no arguments and returns 一个 Script Record、一个 Module Recordnull. 它用于根据正在运行的执行上下文,确定当前正在运行的脚本或模块。 It performs the following steps when called:

  1. 如果执行上下文栈为空,返回 null
  2. ec执行上下文栈中最顶部的那个执行上下文,且其 ScriptOrModule 组成部分不为 null
  3. 如果不存在这样的执行上下文,返回 null
  4. 返回 ec 的 ScriptOrModule。

9.4.2 ResolveBinding ( name [ , env ] )

The abstract operation ResolveBinding takes argument name (一个 String,) and optional argument env (一个 Environment Recordundefined,) and returns 要么是包含 Reference Record正常完成,要么是抛出完成. 它用于确定 name 的绑定。env 可用于显式提供应当被搜索该绑定的 Environment Record。 It performs the following steps when called:

  1. 如果 env 不存在,或 envundefined,那么
    1. env 设为正在运行执行上下文的 LexicalEnvironment。
  2. 断言:env 是一个 Environment Record
  3. strictIsStrict(当前正在求值的语法产生式)。
  4. 返回 ? GetIdentifierReference(env, name, strict)。
Note

ResolveBinding 的结果始终是一个 Reference Record,其 [[ReferencedName]] 字段为 name

9.4.3 GetThisEnvironment ( )

The abstract operation GetThisEnvironment takes no arguments and returns 一个 Environment Record. 它查找当前提供关键字 this 绑定的那个 Environment Record。 It performs the following steps when called:

  1. env 为正在运行执行上下文的 LexicalEnvironment。
  2. 重复,
    1. existsenv.HasThisBinding()。
    2. 如果 existstrue,返回 env
    3. outerenv.[[OuterEnv]]
    4. 断言:outer 不是 null
    5. env 设为 outer
Note

步骤 2 中的循环总会终止,因为环境列表最终总是以具有 this 绑定的全局环境结束。

9.4.4 ResolveThisBinding ( )

The abstract operation ResolveThisBinding takes no arguments and returns 要么是包含 ECMAScript 语言值正常完成,要么是抛出完成. 它使用正在运行执行上下文的 LexicalEnvironment 来确定关键字 this 的绑定。 It performs the following steps when called:

  1. envRecGetThisEnvironment()。
  2. 返回 ? envRec.GetThisBinding()。

9.4.5 GetNewTarget ( )

The abstract operation GetNewTarget takes no arguments and returns 一个 Object 或 undefined. 它使用正在运行执行上下文的 LexicalEnvironment 来确定 NewTarget 值。 It performs the following steps when called:

  1. envRecGetThisEnvironment()。
  2. 断言:envRec 具有 [[NewTarget]] 字段。
  3. 返回 envRec.[[NewTarget]]

9.4.6 GetGlobalObject ( )

The abstract operation GetGlobalObject takes no arguments and returns 一个 Object. 它返回当前正在运行执行上下文所使用的全局对象。 It performs the following steps when called:

  1. currentRealm当前 Realm Record
  2. 返回 currentRealm.[[GlobalObject]]

9.4.7 RunSuspendedContext ( context, completionRecord )

The abstract operation RunSuspendedContext takes arguments context (一个执行上下文) and completionRecord (一个完成记录) and returns 要么是一个包含 ECMAScript 语言值unused正常完成,要么是一个突然完成. 它恢复 context(将 completionRecord 作为恢复值发送给它),并等待结果。 It performs the following steps when called:

  1. callerContext正在运行的执行上下文
  2. 挂起 callerContext
  3. context 压入执行上下文栈context 现在是正在运行的执行上下文
  4. 恢复 context 的已挂起求值,使用 completionRecord 作为挂起它的操作的结果。令 result 为恢复的计算返回的完成记录。
  5. 断言:当到达此步骤时,context 已经从执行上下文栈中移除,并且 callerContext 再次成为正在运行的执行上下文
  6. 返回 Completion(result)。

9.5 Job 以及将 Job 入队的宿主操作

Job 是一个不带参数的 Abstract Closure,当当前没有其他 ECMAScript 计算正在进行时,它会启动一段 ECMAScript 计算。

Job 由 ECMAScript 宿主环境安排到某个特定 agent 中执行。本规范描述了宿主钩子 HostEnqueueGenericJobHostEnqueueFinalizationRegistryCleanupJobHostEnqueuePromiseJobHostEnqueueTimeoutJob,用于调度 Job。本规范中的宿主钩子是按 Job 调度时施加的附加约束来组织的。宿主还可以定义额外的抽象操作来调度 Job。这类操作接受一个 Job Abstract Closure 和一个 realm(一个 Realm Recordnull)作为参数。如果提供的是一个 Realm Record,那么这些操作会将该 Job 调度到将来某个时间、在提供的 realm 中、由拥有该 realmagent 来执行。如果提供的是 null 而不是 realm,那么该 Job 不会求值 ECMAScript 代码。它们的实现必须符合以下要求:

Note 1
宿主环境不要求在调度上对所有 Job 一视同仁。例如,Web 浏览器和 Node.js 会将 Promise 处理 Job 视为比其他工作更高优先级;未来的特性也可能引入一些不会被赋予如此高优先级的 Job

在任意特定时刻,如果 scriptOrModule(一个 Script Record、一个 Module Recordnull)满足以下所有条件,则它是活动脚本或模块

在任意特定时刻,如果满足以下所有条件,则某次执行是已准备好求值 ECMAScript 代码的:

Note 2

宿主环境可以通过向执行上下文栈压入执行上下文,使某次执行准备好求值代码。具体步骤由实现定义

Realm 的具体选择由宿主环境决定。这个初始执行上下文Realm 只会在任何回调函数被调用之前使用。当与某个 Job 相关的回调函数(例如 Promise 处理器)被调用时,该调用会压入它自己的执行上下文Realm

某些特定种类的 Job 还具有额外的一致性要求。

9.5.1 JobCallback Record

JobCallback Record 是一种 Record 值,用于存储一个函数对象和一个宿主定义值。通过宿主入队的 Job 来调用的函数对象,可能具有额外的宿主定义上下文。为了传播该状态,Job Abstract Closure 不应直接捕获并调用函数对象。相反,应使用 HostMakeJobCallbackHostCallJobCallback

Note

例如,WHATWG HTML 规范(https://html.spec.whatwg.org/)使用该宿主定义值来传播 Promise 回调的 incumbent settings object。

JobCallback Record 具有 Table 23 中列出的字段。

Table 23: JobCallback Record 字段
字段名称 含义
[[Callback]] 一个函数对象 Job 被调用时要调用的函数。
[[HostDefined]] 任意值(默认值为 empty 宿主保留的字段。

9.5.2 HostMakeJobCallback ( callback )

The host-defined abstract operation HostMakeJobCallback takes argument callback (一个函数对象,) and returns 一个 JobCallback Record.

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

HostMakeJobCallback 的默认实现会在被调用时执行以下步骤:

  1. 返回 JobCallback Record { [[Callback]]: callback, [[HostDefined]]: empty }。

不是 Web 浏览器的 ECMAScript 宿主必须使用 HostMakeJobCallback 的默认实现。

Note

这是在回调被传给负责最终调度并运行它的函数时调用的。例如,promise.then(thenAction) 会在调用 Promise.prototype.then 时对 thenAction 调用 MakeJobCallback,而不是在调度 reaction Job 时才调用。

9.5.3 HostCallJobCallback ( jobCallback, value, argumentsList )

The host-defined abstract operation HostCallJobCallback takes arguments jobCallback (一个 JobCallback Record,), value (一个 ECMAScript 语言值,), and argumentsList (一个 ECMAScript 语言值List,) and returns 要么是包含 ECMAScript 语言值正常完成,要么是抛出完成.

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

  • 它必须执行并返回 Call(jobCallback.[[Callback]], value, argumentsList) 的结果。
Note

这一要求意味着宿主不能改变本规范中定义的函数对象[[Call]] 行为。

HostCallJobCallback 的默认实现会在被调用时执行以下步骤:

  1. 断言:IsCallable(jobCallback.[[Callback]]) 是 true
  2. 返回 ? Call(jobCallback.[[Callback]], value, argumentsList)。

不是 Web 浏览器的 ECMAScript 宿主必须使用 HostCallJobCallback 的默认实现。

9.5.4 HostEnqueueGenericJob ( job, realm )

The host-defined abstract operation HostEnqueueGenericJob takes arguments job (一个 Job Abstract Closure,) and realm (一个 Realm Record,) and returns unused. 它会将 job 安排到由 realm.[[AgentSignifier]] 所标识的 agent 中、在 realm realm 内,于将来的某个时间执行。与该算法一起使用的 Abstract Closure 旨在不受诸如优先级与顺序等额外约束地被调度。

HostEnqueueGenericJob 的实现必须符合 9.5 中的要求。

9.5.5 HostEnqueuePromiseJob ( job, realm )

The host-defined abstract operation HostEnqueuePromiseJob takes arguments job (一个 Job Abstract Closure,) and realm (一个 Realm Recordnull,) and returns unused. 它会安排 job 在将来的某个时间执行。与该算法一起使用的 Abstract Closure 旨在与 Promise 的处理相关,或者以与 Promise 处理操作同等优先级的方式进行调度。

HostEnqueuePromiseJob 的实现除了必须符合 9.5 中的要求之外,还必须符合以下要求:

Note

对于由 NewPromiseResolveThenableJob 返回的 Job,其 realm 通常是对 then 函数对象调用 GetFunctionRealm 的结果。对于由 NewPromiseReactionJob 返回的 Job,如果 handler 不是 undefined,则其 realm 通常是对该 handler 调用 GetFunctionRealm 的结果;如果 handler 是 undefined,则 realmnull。对于这两类 Job,当 GetFunctionRealm 异常完成时(即在一个已撤销的 Proxy 上调用),realm 为调用 GetFunctionRealm 时的当前 Realm Record。当 realmnull 时,不会求值任何用户 ECMAScript 代码,也不会创建任何新的 ECMAScript 对象(例如 Error 对象)。例如,WHATWG HTML 规范(https://html.spec.whatwg.org/)会使用 realm 来检查是否有能力运行脚本以及 entry 概念。

9.5.6 HostEnqueueTimeoutJob ( timeoutJob, realm, milliseconds )

The host-defined abstract operation HostEnqueueTimeoutJob takes arguments timeoutJob (一个 Job Abstract Closure,), realm (一个 Realm Record,), and milliseconds (一个非负有限 Number,) and returns unused. 它会将 timeoutJob 安排到由 realm.[[AgentSignifier]] 所标识的 agent 中、在 realm realm 内,至少在 milliseconds 毫秒之后执行。

HostEnqueueTimeoutJob 的实现必须符合 9.5 中的要求。

9.6 Agent

agent 由一组 ECMAScript 执行上下文、一个执行上下文栈、一个正在运行的执行上下文、一个 Agent Record,以及一个执行线程组成。除执行线程外,agent 的这些组成部分都专属于该 agent

一个 agent执行线程会独立于其他 agent,在该 agent执行上下文上执行算法步骤;但一个执行线程也可以同时被多个 agent 作为执行线程使用,只要这些共享该线程的 agent 中,没有任何一个 agentAgent Record[[CanBlock]] 字段为 true

Note 1

例如,一些 Web 浏览器会在一个浏览器窗口中的多个互不相关的标签页之间共享同一个执行线程

当一个 agent执行线程正在执行算法步骤时,该 agent 就是这些步骤的外围 agent。这些步骤通过外围 agent 来访问 agent 内部持有的规范层级执行对象:正在运行的执行上下文执行上下文栈,以及 Agent Record 的字段。

agent 标识符是一个全局唯一的不透明值,用于标识一个 Agent

Table 24: Agent Record 字段
字段名称 含义
[[LittleEndian]] 一个 Boolean 在算法 GetValueFromBufferSetValueInBuffer 需要 isLittleEndian 参数时,作为默认值使用。其选择由实现定义,并且应采用对实现最有效的方案。
[[CanBlock]] 一个 Boolean 决定该 agent 是否可以阻塞。
[[Signifier]] 一个 agent 标识符 在其 agent cluster 内唯一标识该 agent
[[IsLockFree1]] 一个 Boolean 如果对 1 字节值的原子操作是无锁的,则为 true,否则为 false
[[IsLockFree2]] 一个 Boolean 如果对 2 字节值的原子操作是无锁的,则为 true,否则为 false
[[IsLockFree8]] 一个 Boolean 如果对 8 字节值的原子操作是无锁的,则为 true,否则为 false
[[CandidateExecution]] 一个 candidate execution Record 参见内存模型
[[KeptAlive]] 一个由 Object 或 Symbol 组成的 List 初始为一个新的空 List,表示在当前 Job 结束前需要保持存活的对象和/或 symbol 列表
[[ModuleAsyncEvaluationCount]] 一个整数 初始值为 0,用于为异步模块或具有异步依赖的模块的 [[AsyncEvaluationOrder]] 字段分配唯一递增值。

[[LittleEndian]][[Signifier]][[IsLockFree1]][[IsLockFree2]][[IsLockFree8]] 的值都不能改变。

Note 2

[[IsLockFree1]][[IsLockFree2]][[IsLockFree8]] 的值不一定完全由硬件决定,也可能反映实现选择,而这些选择可能随时间变化,并且在不同 ECMAScript 实现之间也可能不同。

不存在 [[IsLockFree4]] 字段:4 字节原子操作始终是无锁的。

在实践中,如果一个原子操作是通过任何类型的锁实现的,那么该操作就不是无锁的。无锁并不意味着无等待:完成一个无锁原子操作所需的机器步骤数没有上界。

大小为 n 的原子访问是无锁的,并不意味着大小为 n 的非原子访问在(感知到的)原子性方面有什么保证;具体来说,非原子访问仍然可能作为多个独立内存访问的序列来执行。详见 ReadSharedMemory 和 WriteSharedMemory。

Note 3

agent 是一种规范机制,不需要对应于任何 ECMAScript 实现中的特定构件。

9.6.1 AgentSignifier ( )

The abstract operation AgentSignifier takes no arguments and returns 一个 agent 标识符. It performs the following steps when called:

  1. agentRecord外围 agentAgent Record
  2. 返回 agentRecord.[[Signifier]]

9.6.2 AgentCanSuspend ( )

The abstract operation AgentCanSuspend takes no arguments and returns 一个 Boolean. It performs the following steps when called:

  1. agentRecord外围 agentAgent Record
  2. 返回 agentRecord.[[CanBlock]]
Note

在某些环境中,允许某个给定 agent 挂起可能并不合理。例如,在 Web 浏览器环境中,禁止挂起文档的主事件处理线程可能是合理的,而仍然允许 worker 的事件处理线程挂起。

9.6.3 IncrementModuleAsyncEvaluationCount ( )

The abstract operation IncrementModuleAsyncEvaluationCount takes no arguments and returns a non-negative integer. It performs the following steps when called:

  1. agentRecord外围 agentAgent Record
  2. countagentRecord.[[ModuleAsyncEvaluationCount]]
  3. agentRecord.[[ModuleAsyncEvaluationCount]] 设为 count + 1。
  4. 返回 count
Note

该值仅用于跟踪待定模块之间的相对求值顺序。当不存在待定模块时,实现可以以不可观察的方式将 [[ModuleAsyncEvaluationCount]] 重置为 0。

9.7 Agent 集群

agent 集群是一个极大 agent 集合,这些 agent 能够通过操作共享内存进行通信。

Note 1

不同 agent 中的程序可以通过未指定的手段共享内存。至少,SharedArrayBuffer 的后备内存可以在该集群中的 agent 之间共享。

可能存在一些 agent,它们可以通过消息传递进行通信,但不能共享内存;它们绝不会处于同一个 agent 集群中。

每个 agent 都且仅属于一个 agent 集群。

Note 2

一个集群中的 agent 不必在某个特定时间点都存活。如果 agent A 创建了另一个 agent B,随后 A 终止,而 B 又创建了 agent C,那么如果 A 能与 B 共享某些内存,且 B 能与 C 共享某些内存,则这三个 agent 处于同一个集群中。

一个集群中的所有 agent,其各自 Agent Record 中的 [[LittleEndian]] 字段必须具有相同的值。

Note 3

如果一个 agent 集群中的不同 agent 具有不同的 [[LittleEndian]] 值,那么在共享内存中使用多字节数据就会变得困难。

一个集群中的所有 agent,其各自 Agent Record 中的 [[IsLockFree1]] 字段必须具有相同的值;[[IsLockFree2]][[IsLockFree8]] 字段也同样如此。

一个集群中的所有 agent,其各自 Agent Record 中的 [[Signifier]] 字段必须具有不同的值。

嵌入环境可以在 agent 不知情或不配合的情况下停用(停止前进进展)或激活(恢复前进进展)一个 agent。如果嵌入环境这样做,它就不得让集群中的某些 agent 保持活动状态,而其他 agent 被无限期停用。

Note 4

上述限制的目的是避免这样一种情况:某个 agent 因为另一个 agent 已被停用而发生死锁或饥饿。例如,如果某个 HTML 共享 worker 的生命周期独立于任何窗口中的文档,并且它被允许与这样一个独立文档的专用 worker 共享内存;而当该专用 worker 持有某个锁时(比如,该文档被推入其窗口历史记录中),该文档及其专用 worker 被停用;然后该共享 worker 又尝试获取这个锁,那么该共享 worker 将一直被阻塞,直到该专用 worker 再次被激活(如果有的话)。与此同时,来自其他窗口、试图通过该共享 worker 进行访问的其他 worker 就会发生饥饿。

这一限制的含义是:不可能在不属于嵌入环境中同一个挂起/唤醒集合的 agent 之间共享内存。

嵌入环境可以在该 agent 集群中的其他 agent 都事先不知情或不配合的情况下终止一个 agent。如果一个 agent 的终止不是由它自己或集群中另一个 agent 的程序动作引起,而是由集群外部的力量导致的,那么嵌入环境必须在两种策略中选择其一:要么终止该集群中的所有 agent,要么提供可靠的 API,使集群中的 agent 能够协调,以便至少有一个剩余成员能够检测到该终止,并且该终止数据中包含足够的信息来识别被终止的那个 agent

Note 5

这种终止的例子包括:操作系统或用户终止运行在独立进程中的 agent;或者当按 agent 的资源记账表明某个 agent 已经失控时,嵌入环境自身终止那个与其他 agent 共同在进程内运行的 agent

以下每一个规范值,以及从它们可传递到达的值,都且仅属于一个 agent 集群。

在一个集群中的任意 agent 开始对任何 ECMAScript 代码求值之前,该集群中所有 agentAgent Record[[CandidateExecution]] 字段都被设为初始 candidate execution。初始 candidate execution 是一个空的 candidate execution,其 [[EventsRecords]] 字段是一个 List;对于每个 agent,其中包含一个 Agent Events Record,该 Record[[AgentSignifier]] 字段为该 agentagent 标识符,而其 [[EventList]][[AgentSynchronizesWith]] 字段均为空 List

Note 6

一个 agent 集群中的所有 agent 在其 Agent Record[[CandidateExecution]] 字段中共享同一个 candidate execution。candidate execution 是内存模型所使用的一种规范机制。

Note 7

agent 集群是一种规范机制,不需要对应于任何 ECMAScript 实现中的特定构件。

9.8 前进进展

一个 agent 取得前进进展,是指它按照本规范执行了一步求值步骤。

当一个 agent 的正在运行执行上下文同步且无限期地等待某个外部事件时,该 agent 就变为阻塞状态。只有其 Agent Record[[CanBlock]] 字段为 trueagent,才能以这种意义进入阻塞状态。未阻塞agent 是指未处于阻塞状态的 agent

实现必须确保:

  • 每个拥有专用执行线程的未阻塞 agent 最终都会取得前进进展
  • 在一组共享同一执行线程agent 中,最终会有一个 agent 取得前进进展
  • 一个 agent 不会使另一个 agent 进入阻塞状态,除非是通过嵌入环境提供阻塞能力的 API。
Note

这一点,加上内存模型中的活性保证,可确保所有 seq-cst 写入最终都会对所有 agent 变得可观察。

9.9 WeakRef 和 FinalizationRegistry 目标的处理模型

9.9.1 目标

本规范不保证任何对象或 symbol 一定会被垃圾回收。那些不再存活的对象或 symbol,可能会在很长时间后才被释放,甚至永远不被释放。出于这个原因,本规范在描述由垃圾回收触发的行为时使用术语“may”。

WeakRefFinalizationRegistry 的语义建立在两个会在特定时间点发生的操作之上:

这两种动作(ClearKeptObjectsCleanupFinalizationRegistry)都不得中断同步 ECMAScript 执行。由于宿主可能会组织出更长的同步 ECMAScript 执行序列,因此本规范将 ClearKeptObjectsCleanupFinalizationRegistry 的调度推迟给宿主环境

某些 ECMAScript 实现包含后台运行的垃圾回收器实现,包括在 ECMAScript 空闲时运行。让宿主环境调度 CleanupFinalizationRegistry,使其能够恢复 ECMAScript 执行以运行终结器工作,而这可能释放 held value,从而减少整体内存使用。

9.9.2 活性

对于某个对象和/或 symbol 的集合 objectSet,相对于 objectSet 的一次假想的 WeakRef-oblivious执行,是指这样一种执行:其中某个 WeakRef 的 abstract operation WeakRefDeref,只要其 referent 是 objectSet 的元素,就总是返回 undefined

Note 1
WeakRef-obliviousness 与活性一起,捕捉了两个概念。其一,WeakRef 本身不会让其 referent 保持存活。其二,活性中的循环并不意味着某个值就是活的。具体来说,如果判定 v 的活性依赖于判定某个 WeakRef referent r 的活性,那么 r 的活性就不能反过来假定 v 的活性,否则会形成循环论证。
Note 2
WeakRef-obliviousness 是对对象或 symbol 的集合而不是单个值定义的,这是为了处理循环。如果它是对单个值定义的,那么处于循环中的某个 WeakRef referent 即使其身份仅通过该循环中的其他 WeakRef referent 才能被观察到,也会被认为是活的。
Note 3
通俗地说,如果每个包含某个单独对象或 symbol 的集合都是活的,那么我们就说这个对象或 symbol 是活的。

在求值期间的任意时刻,一个对象和/或 symbol 的集合 objectSet 被认为是活的,当且仅当满足以下任一条件:

  • objectSet 中的任一元素包含在任意 agent[[KeptAlive]] List 中。
  • 存在一个相对于 objectSet 的有效未来假想 WeakRef-oblivious 执行,并且该执行会观察到 objectSet 中某个值的身份。
Note 4
上述第二个条件意在表达这样一种直觉:如果某个值的身份可以通过非 WeakRef 的方式被观察到,那么该值就是活的。一个值的身份可以通过观察严格相等比较,或者观察该值被用作 Map 的键来观察到。
Note 5

对象或 symbol 出现在某个字段、内部槽或属性中,并不意味着该值就是活的。例如,如果相关值从未被返回给程序,那么它就无法被观察到。

WeakMap 中的键、WeakSet 的成员,以及 FinalizationRegistry Cell record 的 [[WeakRefTarget]][[UnregisterToken]] 字段,就属于这种情况。

上述定义意味着,如果 WeakMap 中的某个键不是活的,那么与之对应的值也不一定是活的。

Note 6
活性是保证哪些 WeakRef 引擎不得清空的下界。这里定义的活性是不可判定的。在实践中,引擎会使用诸如可达性之类的保守近似。预计实现会拥有相当大的自由度。

9.9.3 执行

在任意时刻,如果某个对象和/或 symbol 的集合 objectSet 不是活的,那么 ECMAScript 实现可以原子地执行以下步骤:

  1. objectSet 中的每个元素 value,执行
    1. 对于每个满足 ref.[[WeakRefTarget]]valueWeakRef ref,执行
      1. ref.[[WeakRefTarget]] 设为 empty
    2. 对于每个满足 fg.[[Cells]] 包含某个 Record cellcell.[[WeakRefTarget]]valueFinalizationRegistry fg,执行
      1. cell.[[WeakRefTarget]] 设为 empty
      2. 可选地,执行 HostEnqueueFinalizationRegistryCleanupJob(fg)。
    3. 对于每个满足 map.[[WeakMapData]] 包含某个 Record rr.[[Key]]value 的 WeakMap map,执行
      1. r.[[Key]] 设为 empty
      2. r.[[Value]] 设为 empty
    4. 对于每个满足 set.[[WeakSetData]] 包含 value 的 WeakSet set,执行
      1. set.[[WeakSetData]] 中值为 value 的那个元素替换为值为 empty 的元素。
Note 1

结合活性的定义,本条款规定了实现针对 WeakRef 可以应用的优化。

可以在不观察对象身份的情况下访问对象。诸如死变量消除,以及对那些身份未被观察到的、未逃逸对象属性进行标量替换之类的优化,都是允许的。因此,这些优化允许以可观察的方式清空指向这类对象的 WeakRef

另一方面,如果某个对象的身份是可观察的,并且该对象位于某个 WeakRef[[WeakRefTarget]] 内部槽中,那么像重新实化(rematerialization)这样会以可观察方式清空该 WeakRef 的优化就是被禁止的。

由于调用 HostEnqueueFinalizationRegistryCleanupJob 是可选的,因此注册在某个 FinalizationRegistry 中的对象不一定会使该 FinalizationRegistry 保持活性。实现可以出于任何原因省略 FinalizationRegistry 回调,例如,如果 FinalizationRegistry 本身已经死亡,或者应用程序正在关闭。

Note 2

实现没有义务为极大的非活对象或 symbol 集合清空 WeakRef

如果某个实现选择了一个非活集合 objectSet 来清空 WeakRef,那么本定义要求它同时为 objectSet 中所有值清空 WeakRef。换句话说,如果某实现清空了一个指向值 vWeakRef,却没有同时清空其他那些 WeakRef,而这些未清空的 WeakRef 可能导致某次执行观察到 v 的值,那么这种实现就是不符合规范的。

9.9.4 宿主钩子

9.9.4.1 HostEnqueueFinalizationRegistryCleanupJob ( finalizationRegistry )

The host-defined abstract operation HostEnqueueFinalizationRegistryCleanupJob takes argument finalizationRegistry (一个 FinalizationRegistry,) and returns unused.

cleanupJob 为一个新的无参数 Job Abstract Closure,它捕获 finalizationRegistry,并在被调用时执行以下步骤:

  1. cleanupResultCompletion(CleanupFinalizationRegistry(finalizationRegistry))。
  2. 如果 cleanupResult 是一个突兀完成,执行任何宿主定义的用于报告错误的步骤。
  3. 返回 unused

HostEnqueueFinalizationRegistryCleanupJob 的实现会在将来某个时间(如果可能)安排执行 cleanupJob。它还必须符合 9.5 中的要求。

9.10 ClearKeptObjects ( )

The abstract operation ClearKeptObjects takes no arguments and returns unused. 当一段同步的 ECMAScript 执行序列完成时,ECMAScript 实现预期会调用 ClearKeptObjects。 It performs the following steps when called:

  1. agentRecord外围 agentAgent Record
  2. agentRecord.[[KeptAlive]] 设为一个新的空 List
  3. 返回 unused

9.11 AddToKeptObjects ( value )

The abstract operation AddToKeptObjects takes argument value (一个 Object 或一个 Symbol,) and returns unused. It performs the following steps when called:

  1. agentRecord外围 agentAgent Record
  2. value 追加到 agentRecord.[[KeptAlive]]
  3. 返回 unused
Note
当以某个目标对象或 symbol 调用抽象操作 AddToKeptObjects 时,它会将该目标加入到一个列表中,在调用 ClearKeptObjects 之前,该列表会一直对该目标保持强引用。

9.12 CleanupFinalizationRegistry ( finalizationRegistry )

The abstract operation CleanupFinalizationRegistry takes argument finalizationRegistry (一个 FinalizationRegistry,) and returns 要么是包含 unused正常完成,要么是抛出完成. It performs the following steps when called:

  1. 断言:finalizationRegistry 具有 [[Cells]][[CleanupCallback]] 内部槽。
  2. callbackfinalizationRegistry.[[CleanupCallback]]
  3. finalizationRegistry.[[Cells]] 包含某个 Record cellcell.[[WeakRefTarget]]empty 时,实现可以执行以下步骤:
    1. 任选一个这样的 cell
    2. finalizationRegistry.[[Cells]] 中移除 cell
    3. 执行 ? HostCallJobCallback(callback, undefined, « cell.[[HeldValue]] »)。
  4. 返回 unused

9.13 CanBeHeldWeakly ( v )

The abstract operation CanBeHeldWeakly takes argument v (一个 ECMAScript 语言值,) and returns 一个 Boolean. 当且仅当 v 适合用作弱引用时,它返回 true。只有适合用作弱引用的值,才能作为 WeakMap 的键、WeakSet 的元素、WeakRef 的目标,或 FinalizationRegistry 的某个目标。 It performs the following steps when called:

  1. 如果 v 是一个 Object,返回 true
  2. 如果 v 是一个 Symbol,且 KeyForSymbol(v) 是 undefined,返回 true
  3. 返回 false
Note

没有语言身份的语言值可以在没有先前引用的情况下被显现,因此不适合作为弱引用。由 Symbol.for 产生的 Symbol 值,与其他 Symbol 值不同,它没有语言身份,因此不适合作为弱引用。众所周知的 symbol 很可能永远不会被回收,但它们仍被视为适合作为弱引用,因为它们数量有限,因此可由多种实现方式来管理。然而,在某个存活的 WeakMap 中,与一个众所周知的 symbol 关联的任何值都不太可能被回收,并且在实现中可能会“泄漏”内存资源。

10 普通对象与异质对象行为

10.1 普通对象内部方法和内部槽

所有普通对象都有一个名为 [[Prototype]] 的内部槽。该内部槽的值要么是 null, 要么是一个对象,并用于实现继承。假设一个名为 propertyKey 的属性在普通对象 obj 上不存在,但存在于其 [[Prototype]] 对象上。如果 propertyKey 指的是 [[Prototype]] 对象上的一个数据属性,那么 obj 在获取访问时会继承它,从而表 现得如同 propertyKeyobj 的一个属性一样。如果 propertyKey 指的是 [[Prototype]] 对象上的一个可写数据属性,那么在 obj 上对 propertyKey 的设 值访问会在 obj 上创建一个名为 propertyKey 的新数据属性。如果 propertyKey 指的是 [[Prototype]] 对象上的一个不可写数据属性,那么在 obj 上对 propertyKey 的设置访问会失败。如果 propertyKey 指的是 [[Prototype]] 对象上的一个访问器属 性,那么该访问器会被 obj 同时继承用于获取访问和设置访问。

每个普通对象都有一个布尔值的 [[Extensible]] 内部槽,它用于满足 6.1.7.3 中规定的与可扩展性相关的内部方法不变量。也就是说,一旦对象的 [[Extensible]] 内部槽的值被设为 false,就不再可能向该对象添加属性、修改对象的 [[Prototype]] 内部槽的值,或者随后将 [[Extensible]] 的值再改为 true

在下面的算法描述中,假设 obj 是一个普通对象propertyKey 是一个属性键值, value 是任意 ECMAScript 语言值,而 desc 是一个属性描述符记录。

每个普通对象内部方法都委托给一个名称相近的抽象操作。如果这样的抽象操作依赖于 另一个内部方法,那么该内部方法会在 obj 上被调用,而不是直接调用那个名称相近 的抽象操作。这些语义确保了当普通对象内部方法应用于异质对象时,会调用它们被覆写 的内部方法。

10.1.1 [[GetPrototypeOf]] ( )

The [[GetPrototypeOf]] internal method of 一个普通对象 obj takes no arguments and returns 一个正常完成,包含一个 Object 或 null. It performs the following steps when called:

  1. 返回 OrdinaryGetPrototypeOf(obj)。

10.1.1.1 OrdinaryGetPrototypeOf ( obj )

The abstract operation OrdinaryGetPrototypeOf takes argument obj (一个 Object) and returns 一个 Object 或 null. It performs the following steps when called:

  1. 返回 obj.[[Prototype]]

10.1.2 [[SetPrototypeOf]] ( proto )

The [[SetPrototypeOf]] internal method of 一个普通对象 obj takes argument proto (一个 Object 或 null) and returns 一个正常完成,包含一个 Boolean. It performs the following steps when called:

  1. 返回 OrdinarySetPrototypeOf(obj, proto)。

10.1.2.1 OrdinarySetPrototypeOf ( obj, proto )

The abstract operation OrdinarySetPrototypeOf takes arguments obj (一个 Object) and proto (一个 Object 或 null) and returns 一个 Boolean. It performs the following steps when called:

  1. currentobj.[[Prototype]]
  2. 如果 SameValue(proto, current) 为 true,返回 true
  3. extensibleobj.[[Extensible]]
  4. 如果 extensiblefalse,返回 false
  5. cursorproto
  6. donefalse
  7. 重复,当 donefalse 时,
    1. 如果 cursornull,那么
      1. done 设为 true
    2. 否则如果 SameValue(cursor, obj) 为 true,那么
      1. 返回 false
    3. 否则,
      1. 如果 cursor.[[GetPrototypeOf]] 不是 10.1.1 中定义的普通对象内部方法,则将 done 设为 true
      2. 否则,将 cursor 设为 cursor.[[Prototype]]
  8. obj.[[Prototype]] 设为 proto
  9. 返回 true
Note

步骤 7 中的循环保 证了,在任何仅包含使用普通对象[[GetPrototypeOf]][[SetPrototypeOf]] 定义的对象的原型链中,都不会存在循环。

10.1.3 [[IsExtensible]] ( )

The [[IsExtensible]] internal method of 一个普通对象 obj takes no arguments and returns 一个正常完成,包含一个 Boolean. It performs the following steps when called:

  1. 返回 OrdinaryIsExtensible(obj)。

10.1.3.1 OrdinaryIsExtensible ( obj )

The abstract operation OrdinaryIsExtensible takes argument obj (一个 Object) and returns 一个 Boolean. It performs the following steps when called:

  1. 返回 obj.[[Extensible]]

10.1.4 [[PreventExtensions]] ( )

The [[PreventExtensions]] internal method of 一个普通对象 obj takes no arguments and returns 一个正常完成,包含 true. It performs the following steps when called:

  1. 返回 OrdinaryPreventExtensions(obj)。

10.1.4.1 OrdinaryPreventExtensions ( obj )

The abstract operation OrdinaryPreventExtensions takes argument obj (一个 Object) and returns true. It performs the following steps when called:

  1. obj.[[Extensible]] 设为 false
  2. 返回 true

10.1.5 [[GetOwnProperty]] ( propertyKey )

The [[GetOwnProperty]] internal method of 一个普通对象 obj takes argument propertyKey (一个属性键) and returns 一个正常完成,包含一个属性描述符或 undefined. It performs the following steps when called:

  1. 返回 OrdinaryGetOwnProperty(obj, propertyKey)。

10.1.5.1 OrdinaryGetOwnProperty ( obj, propertyKey )

The abstract operation OrdinaryGetOwnProperty takes arguments obj (一个 Object) and propertyKey (一个属性键) and returns 一个属性描述符或 undefined. It performs the following steps when called:

  1. 如果 obj 没有一个键为 propertyKey 的自有属性,返回 undefined
  2. desc 为一个新创建的、不含任何字段的属性描述符。
  3. ownPropertyobj 的键为 propertyKey 的自有属性。
  4. 如果 ownProperty 是一个数据属性,那么
    1. desc.[[Value]] 设为 ownProperty[[Value]] 特性的值。
    2. desc.[[Writable]] 设为 ownProperty[[Writable]] 特性的值。
  5. 否则,
    1. 断言:ownProperty 是一个访问器属性
    2. desc.[[Get]] 设为 ownProperty[[Get]] 特性的值。
    3. desc.[[Set]] 设为 ownProperty[[Set]] 特性的值。
  6. desc.[[Enumerable]] 设为 ownProperty[[Enumerable]] 特性的值。
  7. desc.[[Configurable]] 设为 ownProperty[[Configurable]] 特性的值。
  8. 返回 desc

10.1.6 [[DefineOwnProperty]] ( propertyKey, desc )

The [[DefineOwnProperty]] internal method of 一个普通对象 obj takes arguments propertyKey (一个属性键) and desc (一个属性描述符) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

  1. 返回 ? OrdinaryDefineOwnProperty(obj, propertyKey, desc)。

10.1.6.1 OrdinaryDefineOwnProperty ( obj, propertyKey, desc )

The abstract operation OrdinaryDefineOwnProperty takes arguments obj (一个 Object), propertyKey (一个属性键), and desc (一个属性描述符) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

  1. current 为 ? obj.[[GetOwnProperty]](propertyKey)
  2. extensible 为 ? IsExtensible(obj)。
  3. 返回 ValidateAndApplyPropertyDescriptor(obj, propertyKey, extensible, desc, current)。

10.1.6.2 IsCompatiblePropertyDescriptor ( extensible, desc, current )

The abstract operation IsCompatiblePropertyDescriptor takes arguments extensible (一个 Boolean), desc (一个属性描述符), and current (一个属性描述符或 undefined) and returns 一个 Boolean. It performs the following steps when called:

  1. 返回 ValidateAndApplyPropertyDescriptor(undefined, "", extensible, desc, current)。

10.1.6.3 ValidateAndApplyPropertyDescriptor ( obj, propertyKey, extensible, desc, current )

The abstract operation ValidateAndApplyPropertyDescriptor takes arguments obj (一个 Object 或 undefined), propertyKey (一个属性键), extensible (一个 Boolean), desc (一个属性描述符), and current (一个属性描述符或 undefined) and returns 一个 Boolean. 当且仅当 desc 能够在维持 不变量 的前提下,被应用为一个具有指定 extensibility 和当前属性 current 的对象的 属性时,它返回 true。当这种应用是可能的且 obj 不是 undefined 时,它会 对名为 propertyKey 的属性执行该应用(必要时会创建该属性)。 It performs the following steps when called:

  1. 断言:propertyKey 是一个属性键
  2. 如果 currentundefined,那么
    1. 如果 extensiblefalse,返回 false
    2. 如果 objundefined,返回 true
    3. 如果 IsAccessorDescriptor(desc) 为 true,那么
      1. 在对象 obj 上创建一个名为 propertyKey 的自有访问器属性,其 [[Get]][[Set]][[Enumerable]][[Configurable]] 特性如果 desc 具有对应字段,则设为对应字段的值,否则设为该特性的 默认值
    4. 否则,
      1. 在对象 obj 上创建一个名为 propertyKey 的自有数据属性,其 [[Value]][[Writable]][[Enumerable]][[Configurable]] 特性如果 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. NOTE: SameValueNaN 值返回 true,而该值可能可以通过其他方式区分。 在这里返回可确保 obj 的任何现有属性保持未被修改。
      3. 如果 desc[[Value]] 字段,返回 SameValue(desc.[[Value]], current.[[Value]])。
  6. 如果 obj 不是 undefined,那么
    1. 如果 IsDataDescriptor(current) 为 trueIsAccessorDescriptor(desc) 为 true,那么
      1. 如果 desc[[Configurable]] 字段,令 configurabledesc.[[Configurable]];否则令 configurablecurrent.[[Configurable]]
      2. 如果 desc[[Enumerable]] 字段,令 enumerabledesc.[[Enumerable]];否则令 enumerablecurrent.[[Enumerable]]
      3. 用一个访问器属性替换对象 obj 中名为 propertyKey 的属性,该访问器属性[[Configurable]][[Enumerable]] 特性分别设为 configurableenumerable,而其 [[Get]][[Set]] 特性如果 desc 具有对应字段,则设为对应字段的值,否则设为该特性的 默认值
    2. 否则如果 IsAccessorDescriptor(current) 为 trueIsDataDescriptor(desc) 为 true,那么
      1. 如果 desc[[Configurable]] 字段,令 configurabledesc.[[Configurable]];否则令 configurablecurrent.[[Configurable]]
      2. 如果 desc[[Enumerable]] 字段,令 enumerabledesc.[[Enumerable]];否则令 enumerablecurrent.[[Enumerable]]
      3. 用一个数据属性替换对象 obj 中名为 propertyKey 的属性,该数据属性[[Configurable]][[Enumerable]] 特性分别设为 configurableenumerable,而其 [[Value]][[Writable]] 特性如果 desc 具有对应字段,则设为对应字段的值,否则设为该特性的 默认值
    3. 否则,
      1. 对于 desc 的每个字段名 fieldName,将对象 obj 中名为 propertyKey 的属性上名为 fieldName 的特性设为 descfieldName 字段的值。
  7. 返回 true

10.1.7 [[HasProperty]] ( propertyKey )

The [[HasProperty]] internal method of 一个普通对象 obj takes argument propertyKey (一个属性键) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

  1. 返回 ? OrdinaryHasProperty(obj, propertyKey)。

10.1.7.1 OrdinaryHasProperty ( obj, propertyKey )

The abstract operation OrdinaryHasProperty takes arguments obj (一个 Object) and propertyKey (一个属性键) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

  1. hasOwn 为 ? obj.[[GetOwnProperty]](propertyKey)
  2. 如果 hasOwn 不是 undefined,返回 true
  3. parent 为 ? obj.[[GetPrototypeOf]]()
  4. 如果 parent 不是 null,那么
    1. 返回 ? parent.[[HasProperty]](propertyKey)
  5. 返回 false

10.1.8 [[Get]] ( propertyKey, receiver )

The [[Get]] internal method of 一个普通对象 obj takes arguments propertyKey (一个属性键) and receiver (一个 ECMAScript 语言值) and returns 要么是一个正常完成,包含一个 ECMAScript 语言值,要么是一个抛出完成. It performs the following steps when called:

  1. 返回 ? OrdinaryGet(obj, propertyKey, receiver)。

10.1.8.1 OrdinaryGet ( obj, propertyKey, receiver )

The abstract operation OrdinaryGet takes arguments obj (一个 Object), propertyKey (一个属性键), and receiver (一个 ECMAScript 语言值) and returns 要么是一个正常完成,包含一个 ECMAScript 语言值,要么是一个抛出完成. It performs the following steps when called:

  1. desc 为 ? obj.[[GetOwnProperty]](propertyKey)
  2. 如果 descundefined,那么
    1. parent 为 ? obj.[[GetPrototypeOf]]()
    2. 如果 parentnull,返回 undefined
    3. 返回 ? parent.[[Get]](propertyKey, 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]] ( propertyKey, value, receiver )

The [[Set]] internal method of 一个普通对象 obj takes arguments propertyKey (一个属性键), value (一个 ECMAScript 语言值), and receiver (一个 ECMAScript 语言值) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

  1. 返回 ? OrdinarySet(obj, propertyKey, value, receiver)。

10.1.9.1 OrdinarySet ( obj, propertyKey, value, receiver )

The abstract operation OrdinarySet takes arguments obj (一个 Object), propertyKey (一个属性键), value (一个 ECMAScript 语言值), and receiver (一个 ECMAScript 语言值) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

  1. ownDesc 为 ? obj.[[GetOwnProperty]](propertyKey)
  2. 返回 ? OrdinarySetWithOwnDescriptor(obj, propertyKey, value, receiver, ownDesc)。

10.1.9.2 OrdinarySetWithOwnDescriptor ( obj, propertyKey, value, receiver, ownDesc )

The abstract operation OrdinarySetWithOwnDescriptor takes arguments obj (一个 Object), propertyKey (一个属性键), value (一个 ECMAScript 语言值), receiver (一个 ECMAScript 语言值), and ownDesc (一个属性描述符或 undefined) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

  1. 如果 ownDescundefined,那么
    1. parent 为 ? obj.[[GetPrototypeOf]]()
    2. 如果 parent 不是 null,返回 ? parent.[[Set]](propertyKey, value, receiver)
    3. ownDesc 设为属性描述符 PropertyDescriptor { [[Value]]: undefined, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true }。
  2. 如果 IsDataDescriptor(ownDesc) 为 true,那么
    1. 如果 ownDesc.[[Writable]]false,返回 false
    2. 如果 receiver 不是一个 Object,返回 false
    3. existingDescriptor 为 ? receiver.[[GetOwnProperty]](propertyKey)
    4. 如果 existingDescriptorundefined,那么
      1. 断言:receiver 当前并不具有属性 propertyKey
      2. 返回 ? CreateDataProperty(receiver, propertyKey, value)。
    5. 如果 IsAccessorDescriptor(existingDescriptor) 为 true,返回 false
    6. 如果 existingDescriptor.[[Writable]]false,返回 false
    7. valueDesc 为属性描述符 PropertyDescriptor { [[Value]]: value }。
    8. 返回 ? receiver.[[DefineOwnProperty]](propertyKey, valueDesc)
  3. 断言:IsAccessorDescriptor(ownDesc) 为 true
  4. setterownDesc.[[Set]]
  5. 如果 setterundefined,返回 false
  6. 执行 ? Call(setter, receiver, « value »)。
  7. 返回 true

10.1.10 [[Delete]] ( propertyKey )

The [[Delete]] internal method of 一个普通对象 obj takes argument propertyKey (一个属性键) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

  1. 返回 ? OrdinaryDelete(obj, propertyKey)。

10.1.10.1 OrdinaryDelete ( obj, propertyKey )

The abstract operation OrdinaryDelete takes arguments obj (一个 Object) and propertyKey (一个属性键) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

  1. desc 为 ? obj.[[GetOwnProperty]](propertyKey)
  2. 如果 descundefined,返回 true
  3. 如果 desc.[[Configurable]]true,那么
    1. obj 中移除名称为 propertyKey 的自有属性。
    2. 返回 true
  4. 返回 false

10.1.11 [[OwnPropertyKeys]] ( )

The [[OwnPropertyKeys]] internal method of 一个普通对象 obj takes no arguments and returns 一个正常完成,包含一个属性键列表. It performs the following steps when called:

  1. 返回 OrdinaryOwnPropertyKeys(obj)。

10.1.11.1 OrdinaryOwnPropertyKeys ( obj )

The abstract operation OrdinaryOwnPropertyKeys takes argument obj (一个 Object) and returns 一个属性键列表. It performs the following steps when called:

  1. keys 为一个新的空列表。
  2. 对于 obj 的每个自有属性键 propertyKey,其中 propertyKey数组索引,按数值索引升序,执行
    1. propertyKey 追加到 keys
  3. 对于 obj 的每个自有属性键 propertyKey,其中 propertyKey 是一个 String 且 propertyKey 不是数组索引,按属性创建时间顺序升序,执行
    1. propertyKey 追加到 keys
  4. 对于 obj 的每个自有属性键 propertyKey,其中 propertyKey 是一个 Symbol,按属性创建时间顺序升序,执行
    1. propertyKey 追加到 keys
  5. 返回 keys

10.1.12 OrdinaryObjectCreate ( proto [ , additionalInternalSlotsList ] )

The abstract operation OrdinaryObjectCreate takes argument proto (一个 Object 或 null) and optional argument additionalInternalSlotsList (一个内部槽名称列表) and returns 一个 Object. 它用于规定新普通对象的运行时创建。additionalInternalSlotsList 包含除了 [[Prototype]][[Extensible]] 之外,必须作为对象一部分定义的额外内部槽 名称。如果未提供 additionalInternalSlotsList,则使用一个新的空列表。 It performs the following steps when called:

  1. internalSlotsList 为 « [[Prototype]], [[Extensible]] »。
  2. 如果 additionalInternalSlotsList 存在,则将 internalSlotsList 设为 internalSlotsListadditionalInternalSlotsList 的列表串接。
  3. objMakeBasicObject(internalSlotsList)。
  4. obj.[[Prototype]] 设为 proto
  5. 返回 obj
Note

尽管 OrdinaryObjectCreate 所做的事情几乎只是调用 MakeBasicObject,但使用它表 达了要创建一个普通对象而不是异质对象的意图。因此,在本规范中,任何随后会以使 结果变为非普通对象的方式修改该对象内部方法的算法都不会调用它。创建异质对象的 操作会直接调用 MakeBasicObject

10.1.13 OrdinaryCreateFromConstructor ( constructor, intrinsicDefaultProto [ , internalSlotsList ] )

The abstract operation OrdinaryCreateFromConstructor takes arguments constructor (一个函数对象) and intrinsicDefaultProto (一个 String) and optional argument internalSlotsList (一个内部槽名称列表) and returns 要么是一个正常完成,包含一个 Object,要么是一个抛出完成. 它创建一个普通对象,其 [[Prototype]] 值会从构造函数的 "prototype" 属 性中获取(如果它存在)。否则,使用由 intrinsicDefaultProto 命名的内在对象 作为 [[Prototype]]internalSlotsList 包含必须作为对象一部分定义的额外内 部槽名称。如果未提供 internalSlotsList,则使用一个新的空列表。 It performs the following steps when called:

  1. 断言:intrinsicDefaultProto 是本规范中某个内在对象的名称。相应的对象必须是一个意图用作对象 [[Prototype]] 值的内在对象。
  2. proto 为 ? GetPrototypeFromConstructor(constructor, intrinsicDefaultProto)。
  3. 如果 internalSlotsList 存在,令 slotsListinternalSlotsList
  4. 否则,令 slotsList 为一个新的空列表。
  5. 返回 OrdinaryObjectCreate(proto, slotsList)。

10.1.14 GetPrototypeFromConstructor ( constructor, intrinsicDefaultProto )

The abstract operation GetPrototypeFromConstructor takes arguments constructor (一个函数对象) and intrinsicDefaultProto (一个 String) and returns 要么是一个正常完成,包含一个 Object,要么是一个抛出完成. 它决定在创建与某个特定构造函数相对应的对象时应使用的 [[Prototype]] 值。 这个值会从构造函数的 "prototype" 属性中获取(如果它存在)。否则,使用由 intrinsicDefaultProto 命名的内在对象作为 [[Prototype]]。 It performs the following steps when called:

  1. 断言:intrinsicDefaultProto 是本规范中某个内在对象的名称。相应的对象必须是一个意图用作对象 [[Prototype]] 值的内在对象。
  2. proto 为 ? Get(constructor, "prototype")。
  3. 如果 proto 不是一个 Object,那么
    1. realm 为 ? GetFunctionRealm(constructor)。
    2. proto 设为 realm 中名为 intrinsicDefaultProto 的内在对象。
  4. 返回 proto
Note

如果 constructor 没有提供 [[Prototype]] 值,则所使用的默认值取自 constructor 函数所属的 realm,而不是取自当前运行的执行上下文

10.1.15 RequireInternalSlot ( obj, internalSlot )

The abstract operation RequireInternalSlot takes arguments obj (一个 ECMAScript 语言值) and internalSlot (一个内部槽名称) and returns 要么是一个正常完成,包含 unused,要么是一个抛出完成. 除非 obj 是一个 Object 且具有给定的内部槽,否则它会抛出一个异常。 It performs the following steps when called:

  1. 如果 obj 不是一个 Object,抛出一个 TypeError 异常。
  2. 如果 obj 不具有 internalSlot 这个内部槽,抛出一个 TypeError 异常。
  3. 返回 unused

10.2 ECMAScript 函数对象

ECMAScript 函数对象封装了闭包于词法环境中的参数化 ECMAScript 代码,并支持 对该代码的动态求值。ECMAScript 函数对象普通对象,并且拥有与其他普通对象相同 的内部槽和相同的内部方法。ECMAScript 函数对象的代码可以是严格模式代码11.2.2)或非严格模式代码。 代码为严格模式代码的 ECMAScript 函数对象称为 严格函数。代码不是严 格模式代码的则称为 非严格函数

除了 [[Extensible]][[Prototype]] 之外,ECMAScript 函数对象还具有列于 Table 25 中的内部槽。

Table 25: ECMAScript 函数对象的内部槽
内部槽 类型 描述
[[Environment]] 一个 Environment Record 该函数闭包捕获的 Environment Record。在对函数代码求值时用作外层环境。
[[PrivateEnvironment]] 一个 PrivateEnvironment Recordnull 该函数闭包捕获的用于 Private NamePrivateEnvironment Record。如果该函 数在语法上不包含于类之中,则为 null。在对函数代码求值时,用作内部类的 外层 PrivateEnvironment。
[[FormalParameters]] 一个 Parse Node 定义该函数形式参数列表的源文本的根解析节点
[[ECMAScriptCode]] 一个 Parse Node 定义该函数体的源文本的根解析节点
[[ConstructorKind]] basederived 该函数是否是派生类构造函数。
[[Realm]] 一个 Realm Record 创建该函数所在的 realm,并提供在对该函数求值时访问的任何内在对象。
[[ScriptOrModule]] 一个 Script Record 或一个 Module Record 创建该函数时所在的脚本或模块。
[[ThisMode]] lexicalstrictglobal 定义如何在函数的形式参数和代码体中解释 this 引用。lexical 表示 this 指向词法外围函数的 this 值。strict 表示 this 值严格按函 数调用时提供的值使用。global 表示如果 this 值是 undefinednull,则将其解释为对全局对象的引用;而其他任何 this 值都会先传给 ToObject
[[Strict]] 一个 Boolean 若这是一个严格函数则为 true,若这是一个非严格函数则为 false
[[HomeObject]] 一个 Object 或 undefined 如果该函数使用 super,那么这是一个对象,其 [[GetPrototypeOf]] 提供了 super 属性查找开始的对象。
[[SourceText]] 一个 Unicode 码点序列 定义该函数的源文本
[[Fields]] 一个 ClassFieldDefinition Record 列表 如果该函数是一个类,那么这是一个记录列表,表示该类的非静态字段及其对应 的初始化器。
[[PrivateMethods]] 一个 PrivateElements 列表 如果该函数是一个类,那么这是一个列表,表示该类的非静态私有方法和访问器。
[[ClassFieldInitializerName]] 一个 String、一个 Symbol、一个 Private Nameempty 如果该函数是作为类字段初始化器创建的,那么这是对该字段执行 NamedEvaluation 时要使用的名称;否则为 empty
[[IsClassConstructor]] 一个 Boolean 表示该函数是否为类构造函数。(如果为 true,调用该函数的 [[Call]] 将立 即抛出一个 TypeError 异常。)

所有 ECMAScript 函数对象都具有这里定义的 [[Call]] 内部方法。除此之外,同时 也是构造器的 ECMAScript 函数还具有 [[Construct]] 内部方法。

10.2.1 [[Call]] ( thisArgument, argumentsList )

The [[Call]] internal method of 一个 ECMAScript 函数对象 func takes arguments thisArgument (一个 ECMAScript 语言值) and argumentsList (一个 ECMAScript 语言值列表) and returns 要么是一个正常完成,包含一个 ECMAScript 语言值,要么是一个抛出完成. It performs the following steps when called:

  1. callerContext 为当前运行的执行上下文
  2. calleeContextPrepareForOrdinaryCall(func, undefined)。
  3. 断言:calleeContext 现在是当前运行的执行上下文
  4. 如果 func.[[IsClassConstructor]]true,那么
    1. error 为一个新创建的 TypeError 对象。
    2. NOTE: errorcalleeContext 中创建,并与 func 关联的 Realm Record 相关联。
    3. 执行上下文栈中移除 calleeContext,并恢复 callerContext 为当前 运行的执行上下文
    4. 抛出 error
  5. 执行 OrdinaryCallBindThis(func, calleeContext, thisArgument)。
  6. resultCompletion(OrdinaryCallEvaluateBody(func, argumentsList))。
  7. 执行上下文栈中移除 calleeContext, 并恢复 callerContext 为当前运行的执行上下文
  8. 如果 result 是一个返回完成,返回 result.[[Value]]
  9. 断言:result 是一个抛出完成。
  10. 返回 ? result
Note

当在步骤 7 中从执 行上下文栈移除 calleeContext 时,如果它已被挂起并被一个可访问的 Generator 保留以供稍后恢复,则不得销毁它。

10.2.1.1 PrepareForOrdinaryCall ( func, newTarget )

The abstract operation PrepareForOrdinaryCall takes arguments func (一个 ECMAScript 函数对象) and newTarget (一个 Object 或 undefined) and returns 一个执行上下文. It performs the following steps when called:

  1. callerContext 为当前运行的执行上下文
  2. calleeContext 为一个新的 ECMAScript 代码执行上下文
  3. calleeContext 的 Function 设为 func
  4. calleeRealmfunc.[[Realm]]
  5. calleeContextRealm 设为 calleeRealm
  6. calleeContext 的 ScriptOrModule 设为 func.[[ScriptOrModule]]
  7. localEnvNewFunctionEnvironment(func, newTarget)。
  8. calleeContext 的 LexicalEnvironment 设为 localEnv
  9. calleeContext 的 VariableEnvironment 设为 localEnv
  10. calleeContext 的 PrivateEnvironment 设为 func.[[PrivateEnvironment]]
  11. 如果 callerContext 尚未挂起,则挂起 callerContext
  12. calleeContext 压入执行上下文栈calleeContext 现在是当前运行的 执行上下文
  13. NOTE: 从此之后产生的任何异常对象都与 calleeRealm 相关联。
  14. 返回 calleeContext

10.2.1.2 OrdinaryCallBindThis ( func, calleeContext, thisArgument )

The abstract operation OrdinaryCallBindThis takes arguments func (一个 ECMAScript 函数对象), calleeContext (一个执行上下文), and thisArgument (一个 ECMAScript 语言值) and returns unused. It performs the following steps when called:

  1. thisModefunc.[[ThisMode]]
  2. 如果 thisModelexical,返回 unused
  3. calleeRealmfunc.[[Realm]]
  4. localEnvcalleeContext 的 LexicalEnvironment。
  5. 如果 thisModestrict,那么
    1. thisValuethisArgument
  6. 否则,
    1. 如果 thisArgumentundefinednull,那么
      1. globalEnvcalleeRealm.[[GlobalEnv]]
      2. 断言:globalEnv 是一个 Global Environment Record
      3. thisValueglobalEnv.[[GlobalThisValue]]
    2. 否则,
      1. thisValue 为 ! ToObject(thisArgument)。
      2. NOTE: ToObject 使用 calleeRealm 产生包装对象。
  7. 断言:localEnv 是一个 Function Environment Record
  8. 断言:下一步绝不会返回一个突然完成,因为 localEnv.[[ThisBindingStatus]] 不是 initialized
  9. 执行 ! BindThisValue(localEnv, thisValue)。
  10. 返回 unused

10.2.1.3 Runtime Semantics: EvaluateBody

The syntax-directed operation EvaluateBody takes arguments func (一个 ECMAScript 函数对象) and argumentsList (一个 ECMAScript 语言值列表) and returns 一个返回完成或一个抛出完成. It is defined piecewise over the following productions:

FunctionBody : FunctionStatementList
  1. 返回 ? 对 FunctionBody 执行 EvaluateFunctionBody,并以 funcargumentsList 为参数。
ConciseBody : ExpressionBody
  1. 返回 ? 对 ConciseBody 执行 EvaluateConciseBody,并以 funcargumentsList 为参数。
GeneratorBody : FunctionBody
  1. 返回 ? 对 GeneratorBody 执行 EvaluateGeneratorBody,并以 funcargumentsList 为参数。
AsyncGeneratorBody : FunctionBody
  1. 返回 ? 对 AsyncGeneratorBody 执行 EvaluateAsyncGeneratorBody,并以 funcargumentsList 为参数。
AsyncFunctionBody : FunctionBody
  1. 返回 ? 对 AsyncFunctionBody 执行 EvaluateAsyncFunctionBody,并以 funcargumentsList 为参数。
AsyncConciseBody : ExpressionBody
  1. 返回 ? 对 AsyncConciseBody 执行 EvaluateAsyncConciseBody,并以 funcargumentsList 为参数。
Initializer : = AssignmentExpression
  1. 断言:argumentsList 为空。
  2. 断言:func.[[ClassFieldInitializerName]] 不为 empty
  3. 如果 IsAnonymousFunctionDefinition(AssignmentExpression) 为 true,那么
    1. value 为 ? 对 Initializer 执行 NamedEvaluation,并以 func.[[ClassFieldInitializerName]] 为参数。
  4. 否则,
    1. rhs 为 ? 对 AssignmentExpression 求值。
    2. value 为 ? GetValue(rhs)。
  5. 返回 ReturnCompletion(value)。
Note

尽管字段初始化器构成了一个函数边界,调用 FunctionDeclarationInstantiation 不会产生任何可观察效果,因此被省略。

ClassStaticBlockBody : ClassStaticBlockStatementList
  1. 断言:argumentsList 为空。
  2. 返回 ? 对 ClassStaticBlockBody 执行 EvaluateClassStaticBlockBody, 并以 func 为参数。

10.2.1.4 OrdinaryCallEvaluateBody ( func, argumentsList )

The abstract operation OrdinaryCallEvaluateBody takes arguments func (一个 ECMAScript 函数对象) and argumentsList (一个 ECMAScript 语言值列表) and returns 一个返回完成或一个抛出完成. It performs the following steps when called:

  1. 返回 ? 对 func.[[ECMAScriptCode]] 执行 EvaluateBody,并以 funcargumentsList 为参数。

10.2.2 [[Construct]] ( argumentsList, newTarget )

The [[Construct]] internal method of 一个 ECMAScript 函数对象 func takes arguments argumentsList (一个 ECMAScript 语言值列表) and newTarget (一个构造器) and returns 要么是一个正常完成,包含一个 Object,要么是一个抛出完成. It performs the following steps when called:

  1. callerContext 为当前运行的执行上下文
  2. kindfunc.[[ConstructorKind]]
  3. 如果 kindbase,那么
    1. thisArgument 为 ? OrdinaryCreateFromConstructor(newTarget, "%Object.prototype%")。
  4. calleeContextPrepareForOrdinaryCall(func, newTarget)。
  5. 断言:calleeContext 现在是当前运行的执行上下文
  6. 如果 kindbase,那么
    1. 执行 OrdinaryCallBindThis(func, calleeContext, thisArgument)。
    2. initializeResultCompletion(InitializeInstanceElements(thisArgument, func))。
    3. 如果 initializeResult 是一个突然完成,那么
      1. 执行上下文栈中移除 calleeContext,并恢复 callerContext 为当前运行的执行上下文
      2. 返回 ? initializeResult
  7. constructorEnvcalleeContext 的 LexicalEnvironment。
  8. resultCompletion(OrdinaryCallEvaluateBody(func, 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 )

The abstract operation OrdinaryFunctionCreate takes arguments functionPrototype (一个 Object), sourceText (一个 Unicode 码点序列), parameterList (一个 Parse Node), body (一个 Parse Node), thisMode (lexical-thisnon-lexical-this), env (一个 Environment Record), and privateEnv (一个 PrivateEnvironment Recordnull) and returns 一个 ECMAScript 函数对象. 它用于规定在运行时创建一个新函数,该函数具有默认的 [[Call]] 内部方法且没 有 [[Construct]] 内部方法(尽管之后可以通过 MakeConstructor 之类的操作添 加)。sourceText 是所创建函数的语法定义的源文本。 It performs the following steps when called:

  1. internalSlotsListTable 25 中列出的内部槽。
  2. funcOrdinaryObjectCreate(functionPrototype, internalSlotsList)。
  3. func.[[Call]] 设为 10.2.1 中规定的定义。
  4. func.[[SourceText]] 设为 sourceText
  5. func.[[FormalParameters]] 设为 parameterList
  6. func.[[ECMAScriptCode]] 设为 body
  7. strictIsStrict(body)。
  8. func.[[Strict]] 设为 strict
  9. 如果 thisModelexical-this,将 func.[[ThisMode]] 设为 lexical
  10. 否则如果 stricttrue,将 func.[[ThisMode]] 设为 strict
  11. 否则,将 func.[[ThisMode]] 设为 global
  12. func.[[IsClassConstructor]] 设为 false
  13. func.[[Environment]] 设为 env
  14. func.[[PrivateEnvironment]] 设为 privateEnv
  15. func.[[ScriptOrModule]] 设为 GetActiveScriptOrModule()。
  16. func.[[Realm]] 设为当前 Realm Record
  17. func.[[HomeObject]] 设为 undefined
  18. func.[[Fields]] 设为一个新的空列表。
  19. func.[[PrivateMethods]] 设为一个新的空列表。
  20. func.[[ClassFieldInitializerName]] 设为 empty
  21. lenparameterListExpectedArgumentCount
  22. 执行 SetFunctionLength(func, len)。
  23. 返回 func

10.2.4 AddRestrictedFunctionProperties ( func, realm )

The abstract operation AddRestrictedFunctionProperties takes arguments func (一个函数对象) and realm (一个 Realm Record) and returns unused. It performs the following steps when called:

  1. 断言:realm.[[Intrinsics]].[[%ThrowTypeError%]] 存在并且已经初始化。
  2. throwerrealm.[[Intrinsics]].[[%ThrowTypeError%]]。
  3. 执行 ! DefinePropertyOrThrow(func, "caller", PropertyDescriptor { [[Get]]: thrower, [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: true })。
  4. 执行 ! DefinePropertyOrThrow(func, "arguments", PropertyDescriptor { [[Get]]: thrower, [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: true })。
  5. 返回 unused

10.2.4.1 %ThrowTypeError% ( )

该函数是内在对象 %ThrowTypeError%

它是一个匿名内建函数对象,并且在每个 realm 中只定义一次。

当被调用时,它执行以下步骤:

  1. 抛出一个 TypeError 异常。

该函数的 [[Extensible]] 内部槽的值为 false

该函数的 "length" 属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

该函数的 "name" 属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

10.2.5 MakeConstructor ( func [ , writablePrototype [ , prototype ] ] )

The abstract operation MakeConstructor takes argument func (一个 ECMAScript 函数对象或一个内建函数对象) and optional arguments writablePrototype (一个 Boolean) and prototype (一个 Object) and returns unused. 它将 func 转换为一个构造器。 It performs the following steps when called:

  1. 如果 func 是一个 ECMAScript 函数对象,那么
    1. 断言:IsConstructor(func) 为 false
    2. 断言:func 是一个可扩展对象,并且没有一个 "prototype" 自有属性。
    3. func.[[Construct]] 设为 10.2.2 中规定的定义。
  2. 否则,
    1. func.[[Construct]] 设为 10.3.2 中规定的定义。
  3. func.[[ConstructorKind]] 设为 base
  4. 如果 writablePrototype 未出现,则将 writablePrototype 设为 true
  5. 如果 prototype 未出现,那么
    1. prototype 设为 OrdinaryObjectCreate(%Object.prototype%)。
    2. 执行 ! DefinePropertyOrThrow(prototype, "constructor", PropertyDescriptor { [[Value]]: func, [[Writable]]: writablePrototype, [[Enumerable]]: false, [[Configurable]]: true })。
  6. 执行 ! DefinePropertyOrThrow(func, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: writablePrototype, [[Enumerable]]: false, [[Configurable]]: false })。
  7. 返回 unused

10.2.6 MakeClassConstructor ( func )

The abstract operation MakeClassConstructor takes argument func (一个 ECMAScript 函数对象) and returns unused. It performs the following steps when called:

  1. 断言:func.[[IsClassConstructor]]false
  2. func.[[IsClassConstructor]] 设为 true
  3. 返回 unused

10.2.7 MakeMethod ( func, homeObject )

The abstract operation MakeMethod takes arguments func (一个 ECMAScript 函数对象) and homeObject (一个 Object) and returns unused. 它将 func 配置为一个方法。 It performs the following steps when called:

  1. 断言:homeObject 是一个普通对象
  2. func.[[HomeObject]] 设为 homeObject
  3. 返回 unused

10.2.8 DefineMethodProperty ( homeObject, key, closure, enumerable )

The abstract operation DefineMethodProperty takes arguments homeObject (一个 Object), key (一个属性键Private Name), closure (一个函数对象), and enumerable (一个 Boolean) and returns 要么是一个正常完成,包含一个 PrivateElementunused,要么是一个突然完成. It performs the following steps when called:

  1. 断言:homeObject 是一个普通的、可扩展的对象。
  2. 如果 key 是一个 Private Name,返回 PrivateElement { [[Key]]: key, [[Kind]]: method, [[Value]]: closure }。
  3. desc 为属性描述符 PropertyDescriptor { [[Value]]: closure, [[Writable]]: true, [[Enumerable]]: enumerable, [[Configurable]]: true }。
  4. 执行 ? DefinePropertyOrThrow(homeObject, key, desc)。
  5. NOTE: DefinePropertyOrThrow 仅在试图定义一个 key"prototype" 的类静态方法时才返回一个突然完成。
  6. 返回 unused

10.2.9 SetFunctionName ( func, name [ , prefix ] )

The abstract operation SetFunctionName takes arguments func (一个函数对象) and name (一个属性键Private Name) and optional argument prefix (一个 String) and returns unused. 它向 func 添加一个 "name" 属性。 It performs the following steps when called:

  1. 断言:func 是一个可扩展对象,并且没有一个 "name" 自有属性。
  2. 如果 name 是一个 Symbol,那么
    1. descriptionname.[[Description]]
    2. 如果 descriptionundefined,将 name 设为空字符串。
    3. 否则,将 name 设为 "["description"]" 的字符串串接结果。
  3. 否则如果 name 是一个 Private Name,那么
    1. name 设为 name.[[Description]]
  4. 如果 func 具有 [[InitialName]] 内部槽,那么
    1. func.[[InitialName]] 设为 name
  5. 如果 prefix 出现,那么
    1. name 设为 prefix、码元 0x0020(SPACE)与 name 的字符串串接结果。
    2. 如果 func 具有 [[InitialName]] 内部槽,那么
      1. NOTE: 以下步骤中的选择在每次调用该抽象操作时都是独立作出的。
      2. 可选地,将 func.[[InitialName]] 设为 name
  6. 执行 ! DefinePropertyOrThrow(func, "name", PropertyDescriptor { [[Value]]: name, [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true })。
  7. 返回 unused

10.2.10 SetFunctionLength ( func, length )

The abstract operation SetFunctionLength takes arguments func (一个函数对象) and length (一个非负整数或 +∞) and returns unused. 它向 func 添加一个 "length" 属性。 It performs the following steps when called:

  1. 断言:func 是一个可扩展对象,并且没有一个 "length" 自有属性。
  2. 执行 ! DefinePropertyOrThrow(func, "length", PropertyDescriptor { [[Value]]: 𝔽(length), [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true })。
  3. 返回 unused

10.2.11 FunctionDeclarationInstantiation ( func, argumentsList )

The abstract operation FunctionDeclarationInstantiation takes arguments func (一个 ECMAScript 函数对象) and argumentsList (一个 ECMAScript 语言值列表) and returns 要么是一个正常完成,包含 unused,要么是一个抛出完成. func 是正在为其建立执行上下文函数对象

Note

当为求值一个 ECMAScript 函数建立执行上下文时,会创建一个新的 Function Environment Record,并在该 Environment Record 中实例化每个形式参数的绑定。 函数体中的每个声明也都会被实例化。如果函数的形式参数不包含任何默认值初始化 器,那么函数体声明会在与参数相同的 Environment Record 中实例化。如果存在默认 值参数初始化器,则会为函数体声明创建第二个 Environment Record。形式参数和函 数会作为 FunctionDeclarationInstantiation 的一部分被初始化。所有其他绑定则 在函数体求值期间初始化。

调用时它执行以下步骤:

  1. calleeContext 为当前运行的执行上下文
  2. codefunc.[[ECMAScriptCode]]
  3. strictfunc.[[Strict]]
  4. formalsfunc.[[FormalParameters]]
  5. parameterNamesformalsBoundNames
  6. 如果 parameterNames 具有任何重复项,令 hasDuplicatestrue;否则令 hasDuplicatesfalse
  7. simpleParameterListformalsIsSimpleParameterList
  8. hasParameterExpressionsformalsContainsExpression
  9. varNamescodeVarDeclaredNames
  10. varDeclarationscodeVarScopedDeclarations
  11. lexicalNamescodeLexicallyDeclaredNames
  12. functionNames 为一个新的空列表。
  13. functionsToInitialize 为一个新的空列表。
  14. 对于 varDeclarations 中的每个元素 varDecl,按列表逆序执行,
    1. 如果 varDecl 既不是 VariableDeclaration,也不是 ForBinding,也不是 BindingIdentifier,那么
      1. 断言:varDecl 要么是 FunctionDeclaration,要么是 GeneratorDeclaration,要么是 AsyncFunctionDeclaration,要么是 AsyncGeneratorDeclaration
      2. fnvarDeclBoundNames 的唯一元素。
      3. 如果 functionNames 不包含 fn,那么
        1. fn 插入到 functionNames 的首部。
        2. NOTE: 如果同一名称有多个函数声明,则使用最后一个声明。
        3. varDecl 插入到 functionsToInitialize 的首部。
  15. argumentsObjectNeededtrue
  16. 如果 func.[[ThisMode]]lexical,那么
    1. NOTE: 箭头函数永远没有 arguments 对象。
    2. argumentsObjectNeeded 设为 false
  17. 否则如果 parameterNames 包含 "arguments",那么
    1. argumentsObjectNeeded 设为 false
  18. 否则如果 hasParameterExpressionsfalse,那么
    1. 如果 functionNames 包含 "arguments"lexicalNames 包含 "arguments",那么
      1. argumentsObjectNeeded 设为 false
  19. 如果 stricttruehasParameterExpressionsfalse,那么
    1. NOTE: 参数只需要一个 Environment Record,因为严格模式代码中的 eval 调用不能创建在 eval 外部可见的新绑定。
    2. envcalleeContext 的 LexicalEnvironment。
  20. 否则,
    1. NOTE: 需要一个单独的 Environment Record,以确保在形式参数列表中的直 接 eval 调用所创建的绑定位于参数声明所在环境之外。
    2. calleeEnvcalleeContext 的 LexicalEnvironment。
    3. envNewDeclarativeEnvironment(calleeEnv)。
    4. 断言:calleeContext 的 VariableEnvironment 与 calleeEnv 是同一个 Environment Record
    5. calleeContext 的 LexicalEnvironment 设为 env
  21. 对于 parameterNames 中的每个字符串 paramName,执行
    1. alreadyDeclared 为 ! env.HasBinding(paramName)。
    2. NOTE: 早期错误保证,重复的参数名只会出现在既非严格、又没有参数默认值、也没有剩余参数的函数中。
    3. 如果 alreadyDeclaredfalse,那么
      1. 执行 ! env.CreateMutableBinding(paramName, false)。
      2. 如果 hasDuplicatestrue,那么
        1. 执行 ! env.InitializeBinding(paramName, undefined)。
  22. 如果 argumentsObjectNeededtrue,那么
    1. 如果 stricttruesimpleParameterListfalse,那么
      1. aoCreateUnmappedArgumentsObject(argumentsList)。
    2. 否则,
      1. NOTE: 映射 arguments 对象只提供给那些非严格函数,并且它们不具有剩余参数、参数默认值初始化器或解构参数。
      2. aoCreateMappedArgumentsObject(func, formals, argumentsList, env)。
    3. 如果 stricttrue,那么
      1. 执行 ! env.CreateImmutableBinding("arguments", false)。
      2. NOTE: 在严格模式代码中,早期错误会阻止尝试给该绑定赋值,因此它的可变性是不可观察的。
    4. 否则,
      1. 执行 ! env.CreateMutableBinding("arguments", false)。
    5. 执行 ! env.InitializeBinding("arguments", ao)。
    6. parameterBindingsparameterNames 与 « "arguments" » 的列表串接。
  23. 否则,
    1. parameterBindingsparameterNames
  24. iteratorRecordCreateListIteratorRecord(argumentsList)。
  25. 如果 hasDuplicatestrue,那么
    1. usedEnvundefined
  26. 否则,
    1. usedEnvenv
  27. NOTE: 以下步骤不可能返回 ReturnCompletion,因为在表达式位置中产生此类完成的唯一方式是使用 YieldExpression,而它在参数列表中被 15.5.115.6.1早期错误规则所禁止。
  28. 执行 ? 对 formals 进行 IteratorBindingInitialization,并以 iteratorRecordusedEnv 为参数。
  29. 如果 hasParameterExpressionsfalse,那么
    1. NOTE: 参数和顶层 var 只需要一个 Environment Record
    2. instantiatedVarNames 为列表 parameterBindings 的一个副本。
    3. 对于 varNames 中的每个元素 n,执行
      1. 如果 instantiatedVarNames 不包含 n,那么
        1. n 追加到 instantiatedVarNames
        2. 执行 ! env.CreateMutableBinding(n, false)。
        3. 执行 ! env.InitializeBinding(n, undefined)。
    4. varEnvenv
  30. 否则,
    1. NOTE: 需要一个单独的 Environment Record,以确保在形式参数列表表达式中创建的闭包无法看到函数体中的声明。
    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 不包含 nfunctionNames 包含 n,那么
          1. initialValueundefined
        4. 否则,
          1. initialValue 为 ! env.GetBindingValue(n, false)。
        5. 执行 ! varEnv.InitializeBinding(n, initialValue)。
        6. NOTE: 一个与形式参数同名的 var,其初始值与相应已初始化参数的值相同。
  31. 如果 stricttrue,那么
    1. lexEnvvarEnv
  32. 否则,
    1. Normative Optional
      如果宿主是 Web 浏览器,或以其他方式支持 块级函数声明的 Web 遗留兼容性语义,那么
      1. 对于任意 BlockCaseClauseDefaultClause x 中直接包含于其 StatementList 的每个 FunctionDeclaration fnDecl,且 code Contains xtrue,执行
        1. funcNamefnDeclBindingIdentifierStringValue
        2. 如果将 FunctionDeclaration fnDecl 替换为一个以 funcName 作为 BindingIdentifierVariableStatement 不会为 funcparameterNames 产生任何早期错误,并且 parameterNames 不包含 funcName,那么
          1. NOTE: 这里仅当 funcName 既不是 VarDeclaredName、也不是形式参数名、也不是另一个 FunctionDeclaration 的名称时,才会为其实例化一个 var 绑定。
          2. 如果 instantiatedVarNames 不包含 funcNamefuncName 不是 "arguments",那么
            1. 执行 ! varEnv.CreateMutableBinding(funcName, false)。
            2. 执行 ! varEnv.InitializeBinding(funcName, undefined)。
            3. funcName 追加到 instantiatedVarNames
          3. 当对 FunctionDeclaration fnDecl 求值时,用以下步骤替代 15.2.6 中给出的 FunctionDeclaration 求值算法:
            1. fEnv 为当前运行执行上下文的 VariableEnvironment。
            2. bEnv 为当前运行执行上下文的 LexicalEnvironment。
            3. fObj 为 ! bEnv.GetBindingValue(funcName, false)。
            4. 执行 ! fEnv.SetMutableBinding(funcName, fObj, false)。
            5. 返回 unused
    2. lexEnvNewDeclarativeEnvironment(varEnv)。
    3. NOTE: 非严格函数对顶层词法声明使用一个单独的 Environment Record,以便直接 eval 能够判断由 eval 代码引入的任何 var 作用域声明是否与预先存在的顶层词法作用域声明冲突。对于严格函数则不需要这样做,因为严格直接 eval 总是将所有声明放入一个新的 Environment Record 中。
  33. calleeContext 的 LexicalEnvironment 设为 lexEnv
  34. lexDeclarationscodeLexicallyScopedDeclarations
  35. 对于 lexDeclarations 中的每个元素 lexDecl,执行
    1. NOTE: 一个词法声明的名称不能与函数/生成器声明、形式参数或 var 名称相同。词法声明的名称只在这里被实例化,而不会被初始化。
    2. 对于 lexDeclBoundNames 中的每个元素 dn,执行
      1. 如果 lexDeclIsConstantDeclarationtrue,那么
        1. 执行 ! lexEnv.CreateImmutableBinding(dn, true)。
      2. 否则,
        1. 执行 ! lexEnv.CreateMutableBinding(dn, false)。
  36. privateEnvcalleeContext 的 PrivateEnvironment。
  37. 对于 functionsToInitialize 中的每个解析节点 fnDecl,执行
    1. fnfnDeclBoundNames 的唯一元素。
    2. fo 为对 fnDecl 执行 InstantiateFunctionObject,并以 lexEnvprivateEnv 为参数所得的结果。
    3. 执行 ! varEnv.SetMutableBinding(fn, fo, false)。
  38. 返回 unused

10.3 内建函数对象

内建函数对象是一种普通对象;它必须满足 10.1 中列出的普通对象要求。

除了每个普通对象都必须具有的内部槽之外(见 10.1), 内建函数对象还必须具有以下内部槽:

  • [[Realm]],一个 Realm Record,表示创建该函数的 realm
  • [[InitialName]],一个 String,是该函数的初始名称。它被 20.2.3.5 使用。
  • [[Async]],一个 Boolean,表示该函数在 BuiltinCallOrConstruct 中是否具有 async 的函数调用和构造行为。

除非另有说明,内建函数对象[[Prototype]] 内部槽的初始值为 %Function.prototype%

内建函数对象必须具有一个 [[Call]] 内部方法,其定义需符合 10.3.1 中的规定。

仅当一个内建函数对象被描述为“构造器”,或者本规范中的某个算法显式设置了它的 [[Construct]] 内部方法时,它才具有 [[Construct]] 内部方法。这样的 [[Construct]] 内部方法必须符合 10.3.2 中的定义。

实现可以提供本规范未定义的其他内建函数对象

10.3.1 [[Call]] ( thisArgument, argumentsList )

The [[Call]] internal method of 一个内建函数对象 func takes arguments thisArgument (一个 ECMAScript 语言值) and argumentsList (一个 ECMAScript 语言值列表) and returns 要么是一个正常完成,包含一个 ECMAScript 语言值,要么是一个抛出完成. It performs the following steps when called:

  1. 返回 ? BuiltinCallOrConstruct(func, thisArgument, argumentsList, undefined)。

10.3.2 [[Construct]] ( argumentsList, newTarget )

The [[Construct]] internal method of 一个内建函数对象 func(当该方法存在时) takes arguments argumentsList (一个 ECMAScript 语言值列表) and newTarget (一个构造器) and returns 要么是一个正常完成,包含一个 Object,要么是一个抛出完成. It performs the following steps when called:

  1. result 为 ? BuiltinCallOrConstruct(func, uninitialized, argumentsList, newTarget)。
  2. 断言:result 是一个 Object。
  3. 返回 result

10.3.3 BuiltinCallOrConstruct ( func, thisArgument, argumentsList, newTarget )

The abstract operation BuiltinCallOrConstruct takes arguments func (一个内建函数对象), thisArgument (一个 ECMAScript 语言值uninitialized), argumentsList (一个 ECMAScript 语言值列表), and newTarget (一个构造器undefined) and returns 要么是一个正常完成,包含一个 ECMAScript 语言值,要么是一个抛出完成. It performs the following steps when called:

  1. callerContext 为当前运行的执行上下文
  2. 如果 callerContext 尚未挂起,则挂起 callerContext
  3. calleeContext 为一个新的执行上下文
  4. calleeContext 的 Function 设为 func
  5. calleeRealmfunc.[[Realm]]
  6. calleeContextRealm 设为 calleeRealm
  7. calleeContext 的 ScriptOrModule 设为 null
  8. calleeContext 执行任何必要的、由实现定义的初始化。
  9. calleeContext 压入执行上下文栈calleeContext 现在是当前运行的执行上下文
  10. 如果 func.[[Async]]true,那么
    1. promiseCapability 为 ! NewPromiseCapability(%Promise%)。
    2. resultsClosure 为一个新的不带参数的抽象闭包,它捕获 functhisArgumentargumentsListnewTarget,并在被调用时执行以下步骤:
      1. result 为一个 Completion Record,它是以符合 func 规范的方式对 func 求值的结果。如果 thisArgumentuninitialized,则 this 值未初始化;否则 thisArgument 提供 this 值。argumentsList 提供具名参数。newTarget 提供 NewTarget 值。
      2. NOTE: 如果 func 定义于本文档中,那么“func 的规范”是指通过算法步骤或其他方式为其规定的行为。
      3. 返回 Completion(result)。
    3. 执行 AsyncFunctionStart(promiseCapability, resultsClosure)。
    4. 执行上下文栈中移除 calleeContext,并恢复 callerContext 为当前运行的执行上下文
    5. 返回 promiseCapability.[[Promise]]
  11. result 为一个 Completion Record,它是以符合 func 规范的方式对 func 求值的结果。如果 thisArgumentuninitialized,则 this 值未初始化;否则 thisArgument 提供 this 值。argumentsList 提供具名参数。newTarget 提供 NewTarget 值。
  12. NOTE: 如果 func 定义于本文档中,那么“func 的规范”是指通过算法步骤或其他方式为其规定的行为。
  13. 执行上下文栈中移除 calleeContext,并恢复 callerContext 为当前运行的执行上下文
  14. 返回 ? result
Note

calleeContext执行上下文栈中移除时,如果它已经被挂起并被一个可访问 的 Generator 保留下来以供稍后恢复,则不得销毁它。

10.3.4 CreateBuiltinFunction ( behaviour, length, name, additionalInternalSlotsList [ , realm [ , prototype [ , prefix [ , async ] ] ] ] )

The abstract operation CreateBuiltinFunction takes arguments behaviour (一个抽象闭包、一组算法步骤,或本规范中提供的某种其他函数行为定义), length (一个非负整数或 +∞), name (一个属性键或一个 Private Name), and additionalInternalSlotsList (一个内部槽名称列表) and optional arguments realm (一个 Realm Record), prototype (一个 Object 或 null), prefix (一个 String), and async (一个 Boolean) and returns 一个内建函数对象. additionalInternalSlotsList 包含必须作为该对象一部分定义的额外内部槽名 称。该操作会创建一个内建函数对象。 It performs the following steps when called:

  1. 如果 realm 未出现,则将 realm 设为当前 Realm Record
  2. 如果 prototype 未出现,则将 prototype 设为 realm.[[Intrinsics]].[[%Function.prototype%]]。
  3. 如果 async 未出现,则将 async 设为 false
  4. internalSlotsList 为一个列表,包含 10.3 要求即将创建的内建函数对象具有的所有内部槽名称。
  5. additionalInternalSlotsList 的元素追加到 internalSlotsList
  6. func 为一个新的内建函数对象,当被调用时,它会使用所提供的实参作为 behaviour 所指定的对应形参的值,执行 behaviour 所描述的动作。这个新函数对象拥有名称为 internalSlotsList 中各元素的内部槽,并且还拥有一个 [[InitialName]] 内部槽。
  7. func.[[Async]] 设为 async
  8. func.[[Prototype]] 设为 prototype
  9. func.[[Extensible]] 设为 true
  10. func.[[Realm]] 设为 realm
  11. func.[[InitialName]] 设为 null
  12. 执行 SetFunctionLength(func, length)。
  13. 如果 prefix 未出现,那么
    1. 执行 SetFunctionName(func, name)。
  14. 否则,
    1. 执行 SetFunctionName(func, name, prefix)。
  15. 返回 func

本规范中定义的每个内建函数都是通过调用抽象操作 CreateBuiltinFunction 创建的。

10.4 内建异质对象的内部方法和内部槽

本规范定义了若干种内建异质对象。这些对象在大多数情况下的行为与普通对象相似, 只有在少数特定情形下例外。以下异质对象除非下文显式另有规定,否则使用普通对象的 内部方法:

10.4.1 绑定函数异质对象

绑定函数异质对象是一种包装了另一个函数对象异质对象绑定函数异质对象是可调 用的(它具有 [[Call]] 内部方法,并且可能具有 [[Construct]] 内部方法)。调用 绑定函数异质对象通常会导致对其所包装函数的调用。

如果一个对象的 [[Call]] 和(如适用)[[Construct]] 内部方法使用以下实现, 且其其他基本内部方法使用 10.1 中给出的定义,则该对象是一个 绑定函数异质对象。 这些方法在 BoundFunctionCreate 中被安装。

绑定函数异质对象不具有 Table 25 中列出的 ECMAScript 函数对象内部槽。相反,它们具有 Table 26 中列出的内部槽,外加 [[Prototype]][[Extensible]]

Table 26: 绑定函数异质对象的内部槽
内部槽 类型 描述
[[BoundTargetFunction]] 一个可调用的 Object 被包装的函数对象
[[BoundThis]] 一个 ECMAScript 语言值 在调用被包装函数时,总是作为 this 值传入的值。
[[BoundArguments]] 一个 ECMAScript 语言值列表 一个值列表,其元素会作为对被包装函数的任何调用的前几个参数使用。

10.4.1.1 [[Call]] ( thisArgument, argumentsList )

The [[Call]] internal method of 一个绑定函数异质对象 func takes arguments thisArgument (一个 ECMAScript 语言值) and argumentsList (一个 ECMAScript 语言值列表) and returns 要么是一个正常完成,包含一个 ECMAScript 语言值,要么是一个抛出完成. It performs the following steps when called:

  1. targetfunc.[[BoundTargetFunction]]
  2. boundThisfunc.[[BoundThis]]
  3. boundArgsfunc.[[BoundArguments]]
  4. argsboundArgsargumentsList 的列表串接。
  5. 返回 ? Call(target, boundThis, args)。

10.4.1.2 [[Construct]] ( argumentsList, newTarget )

The [[Construct]] internal method of 一个绑定函数异质对象 func takes arguments argumentsList (一个 ECMAScript 语言值列表) and newTarget (一个构造器) and returns 要么是一个正常完成,包含一个 Object,要么是一个抛出完成. It performs the following steps when called:

  1. targetfunc.[[BoundTargetFunction]]
  2. 断言:IsConstructor(target) 为 true
  3. boundArgsfunc.[[BoundArguments]]
  4. argsboundArgsargumentsList 的列表串接。
  5. 如果 SameValue(func, newTarget) 为 true,则将 newTarget 设为 target
  6. 返回 ? Construct(target, args, newTarget)。

10.4.1.3 BoundFunctionCreate ( targetFunction, boundThis, boundArgs )

The abstract operation BoundFunctionCreate takes arguments targetFunction (一个函数对象), boundThis (一个 ECMAScript 语言值), and boundArgs (一个 ECMAScript 语言值列表) and returns 要么是一个正常完成,包含一个函数对象,要么是一个抛出完成. 它用于规定新绑定函数异质对象的创建。 It performs the following steps when called:

  1. proto 为 ? targetFunction.[[GetPrototypeOf]]()
  2. internalSlotsList 为 « [[Prototype]], [[Extensible]] » 与 Table 26 中列出的内部槽的列表串接。
  3. objMakeBasicObject(internalSlotsList)。
  4. obj.[[Prototype]] 设为 proto
  5. obj.[[Call]] 设为 10.4.1.1 中规定的内容。
  6. 如果 IsConstructor(targetFunction) 为 true,那么
    1. obj.[[Construct]] 设为 10.4.1.2 中规定的内容。
  7. obj.[[BoundTargetFunction]] 设为 targetFunction
  8. obj.[[BoundThis]] 设为 boundThis
  9. obj.[[BoundArguments]] 设为 boundArgs
  10. 返回 obj

10.4.2 数组异质对象

Array 是一种异质对象,它会对数组索引属性键作特殊处理(见 6.1.7)。属性名数组索引的属性也称 为一个元素。每个 Array 都有一个不可配置的 "length" 属性,它的值始 终是一个非负整数 Number,其数学值严格小于 232"length" 属性的值 在数值上大于每一个属性名数组索引的自有属性的名称;每当 Array 的某个自有属性 被创建或更改时,其他属性都会按需要调整以维持这一不变量。具体来说,每当新增一 个属性名数组索引的自有属性时,"length" 属性的值会在必要时改为该数组索引数 值再加一;而每当 "length" 属性的值被更改时,所有属性名数组索引且其值不小 于新长度的自有属性都会被删除。该约束只适用于 Array 的自有属性,不受其原型继承 而来的 "length"数组索引属性影响。

如果一个对象的 [[DefineOwnProperty]] 内部方法使用以下实现,且其其他基本内 部方法使用 10.1 中给出的定义,则该对象是一个 数组异质对象 (或简称为 Array)。这些方法在 ArrayCreate 中被安装。

10.4.2.1 [[DefineOwnProperty]] ( propertyKey, desc )

The [[DefineOwnProperty]] internal method of 一个数组异质对象 array takes arguments propertyKey (一个属性键) and desc (一个属性描述符) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

  1. 如果 propertyKey"length",返回 ? ArraySetLength(array, desc)。
  2. 如果 propertyKey 是一个数组索引,那么
    1. lengthDescOrdinaryGetOwnProperty(array, "length")。
    2. 断言:lengthDesc 不为 undefined
    3. 断言:IsDataDescriptor(lengthDesc) 为 true
    4. 断言:lengthDesc.[[Configurable]]false
    5. lengthlengthDesc.[[Value]]
    6. 断言:length 是一个非负整数 Number
    7. index 为 ! ToUint32(propertyKey)。
    8. 如果 indexlengthlengthDesc.[[Writable]]false,返回 false
    9. succeeded 为 ! OrdinaryDefineOwnProperty(array, propertyKey, desc)。
    10. 如果 succeededfalse,返回 false
    11. 如果 indexlength,那么
      1. lengthDesc.[[Value]] 设为 index + 1𝔽
      2. succeeded 设为 ! OrdinaryDefineOwnProperty(array, "length", lengthDesc)。
      3. 断言:succeededtrue
    12. 返回 true
  3. 返回 ? OrdinaryDefineOwnProperty(array, propertyKey, desc)。

10.4.2.2 ArrayCreate ( length [ , proto ] )

The abstract operation ArrayCreate takes argument length (一个非负整数) and optional argument proto (一个 Object) and returns 要么是一个正常完成,包含一个数组异质对象,要么是一个抛出完成. 它用于规定新 Array 的创建。 It performs the following steps when called:

  1. 如果 length > 232 - 1,抛出一个 RangeError 异常。
  2. 如果 proto 未出现,则将 proto 设为 %Array.prototype%
  3. arrayMakeBasicObject[[Prototype]], [[Extensible]] »)。
  4. array.[[Prototype]] 设为 proto
  5. array.[[DefineOwnProperty]] 设为 10.4.2.1 中规定的内容。
  6. 执行 ! OrdinaryDefineOwnProperty(array, "length", PropertyDescriptor { [[Value]]: 𝔽(length), [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  7. 返回 array

10.4.2.3 ArraySpeciesCreate ( originalArray, length )

The abstract operation ArraySpeciesCreate takes arguments originalArray (一个 Object) and length (一个非负整数) and returns 要么是一个正常完成,包含一个 Object,要么是一个抛出完成. 它用于规定使用从 originalArray 派生出的构造函数来创建一个新的 Array 或类似对象。它并不强制该构造函数必须返回一个 Array。 It performs the following steps when called:

  1. isArray 为 ? IsArray(originalArray)。
  2. 如果 isArrayfalse,返回 ? ArrayCreate(length)。
  3. constructor 为 ? Get(originalArray, "constructor")。
  4. 如果 IsConstructor(constructor) 为 true,那么
    1. thisRealm当前 Realm Record
    2. constructorRealm 为 ? GetFunctionRealm(constructor)。
    3. 如果 thisRealmconstructorRealm 不是同一个 Realm Record,那么
      1. 如果 SameValue(constructor, constructorRealm.[[Intrinsics]].[[%Array%]]) 为 true,则将 constructor 设为 undefined
  5. 如果 constructor 是一个 Object,那么
    1. constructor 设为 ? Get(constructor, %Symbol.species%)。
    2. 如果 constructornull,将 constructor 设为 undefined
  6. 如果 constructorundefined,返回 ? ArrayCreate(length)。
  7. 如果 IsConstructor(constructor) 为 false,抛出一个 TypeError 异常。
  8. 返回 ? Construct(constructor, « 𝔽(length) »)。
Note

如果 originalArray 是使用某个不等于当前运行执行上下文所属 realm 的标准 内建 Array 构造函数所创建的,那么会使用当前运行执行上下文所属 realm 来创建 一个新的 Array。这保持了与 Web 浏览器历史行为的兼容性,因为那些现如今使用 ArraySpeciesCreate 定义的 Array.prototype 方法在历史上就是如此表现的。

10.4.2.4 ArraySetLength ( array, desc )

The abstract operation ArraySetLength takes arguments array (一个 Array) and desc (一个属性描述符) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

  1. 如果 desc 没有 [[Value]] 字段,那么
    1. 返回 ! OrdinaryDefineOwnProperty(array, "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(array, "length")。
  8. 断言:oldLenDesc 不是 undefined
  9. 断言:IsDataDescriptor(oldLenDesc) 为 true
  10. 断言:oldLenDesc.[[Configurable]]false
  11. oldLenoldLenDesc.[[Value]]
  12. 如果 newLenoldLen,那么
    1. 返回 ! OrdinaryDefineOwnProperty(array, "length", newLenDesc)。
  13. 如果 oldLenDesc.[[Writable]]false,返回 false
  14. 如果 newLenDesc 没有 [[Writable]] 字段或 newLenDesc.[[Writable]]true,那么
    1. newWritabletrue
  15. 否则,
    1. NOTE: 将 [[Writable]] 特性设为 false 会被延后,以防某些元素无法删除。
    2. newWritablefalse
    3. newLenDesc.[[Writable]] 设为 true
  16. succeeded 为 ! OrdinaryDefineOwnProperty(array, "length", newLenDesc)。
  17. 如果 succeededfalse,返回 false
  18. 对于 array 的每个自有属性键 propertyKey,若 propertyKey数组索引且 ! ToUint32(propertyKey) ≥ newLen,按数值索引降序,执行
    1. deleteSucceeded 为 ! array.[[Delete]](propertyKey)。
    2. 如果 deleteSucceededfalse,那么
      1. newLenDesc.[[Value]] 设为 ! ToUint32(propertyKey) + 1𝔽
      2. 如果 newWritablefalse,则将 newLenDesc.[[Writable]] 设为 false
      3. 执行 ! OrdinaryDefineOwnProperty(array, "length", newLenDesc)。
      4. 返回 false
  19. 如果 newWritablefalse,那么
    1. succeeded 设为 ! OrdinaryDefineOwnProperty(array, "length", PropertyDescriptor { [[Writable]]: false })。
    2. 断言:succeededtrue
  20. 返回 true
Note

在步骤 34 中,如果 desc.[[Value]] 是一个对象,则它的 valueOf 方法会被调用两次。这是一种 旧有行为,并且自本规范第 2 版起就以这种效果被规定下来。

10.4.3 字符串异质对象

String 对象是一种异质对象,它封装了一个 String 值,并暴露出与该 String 值各 个码元元素相对应的、虚拟的整数索引数据属性字符串异质对象始终具有一个名为 "length"数据属性,其值为所封装 String 值的长度。码元数据属性以及 "length" 属性都不可写且不可配置。

如果一个对象的 [[GetOwnProperty]][[DefineOwnProperty]][[OwnPropertyKeys]] 内部方法使用以下实现,且其其他基本内部方法使用 10.1 中给出的定义,则该对象是一个 字符串异质对象 (或简称为 String 对象)。这些方法在 StringCreate 中被安装。

字符串异质对象具有与普通对象相同的内部槽。它们还具有一个 [[StringData]] 内部槽。

10.4.3.1 [[GetOwnProperty]] ( propertyKey )

The [[GetOwnProperty]] internal method of 一个字符串异质对象 str takes argument propertyKey (一个属性键) and returns 一个正常完成,包含一个属性描述符或 undefined. It performs the following steps when called:

  1. descOrdinaryGetOwnProperty(str, propertyKey)。
  2. 如果 desc 不是 undefined,返回 desc
  3. 返回 StringGetOwnProperty(str, propertyKey)。

10.4.3.2 [[DefineOwnProperty]] ( propertyKey, desc )

The [[DefineOwnProperty]] internal method of 一个字符串异质对象 str takes arguments propertyKey (一个属性键) and desc (一个属性描述符) and returns 一个正常完成,包含一个 Boolean. It performs the following steps when called:

  1. stringDescStringGetOwnProperty(str, propertyKey)。
  2. 如果 stringDesc 不是 undefined,那么
    1. extensiblestr.[[Extensible]]
    2. 返回 IsCompatiblePropertyDescriptor(extensible, desc, stringDesc)。
  3. 返回 ! OrdinaryDefineOwnProperty(str, propertyKey, desc)。

10.4.3.3 [[OwnPropertyKeys]] ( )

The [[OwnPropertyKeys]] internal method of 一个字符串异质对象 obj takes no arguments and returns 一个正常完成,包含一个属性键列表. It performs the following steps when called:

  1. keys 为一个新的空列表。
  2. strobj.[[StringData]]
  3. 断言:str 是一个 String。
  4. lenstr 的长度。
  5. 对于每个满足 0 ≤ i < len整数 i,按升序,执行
    1. 将 ! ToString(𝔽(i)) 追加到 keys
  6. 对于 obj 的每个自有属性键 propertyKey,若 propertyKey数组索引且 ! ToIntegerOrInfinity(propertyKey) ≥ len,按数值索引升序,执行
    1. propertyKey 追加到 keys
  7. 对于 obj 的每个自有属性键 propertyKey,若 propertyKey 是一个 String 且 propertyKey 不是数组索引,按属性创建时间顺序升序,执行
    1. propertyKey 追加到 keys
  8. 对于 obj 的每个自有属性键 propertyKey,若 propertyKey 是一个 Symbol,按属性创建时间顺序升序,执行
    1. propertyKey 追加到 keys
  9. 返回 keys

10.4.3.4 StringCreate ( value, prototype )

The abstract operation StringCreate takes arguments value (一个 String) and prototype (一个 Object) and returns 一个字符串异质对象. 它用于规定新字符串异质对象的创建。 It performs the following steps when called:

  1. strMakeBasicObject[[Prototype]], [[Extensible]], [[StringData]] »)。
  2. str.[[Prototype]] 设为 prototype
  3. str.[[StringData]] 设为 value
  4. str.[[GetOwnProperty]] 设为 10.4.3.1 中规定的内容。
  5. str.[[DefineOwnProperty]] 设为 10.4.3.2 中规定的内容。
  6. str.[[OwnPropertyKeys]] 设为 10.4.3.3 中规定的内容。
  7. lengthvalue 的长度。
  8. 执行 ! DefinePropertyOrThrow(str, "length", PropertyDescriptor { [[Value]]: 𝔽(length), [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false })。
  9. 返回 str

10.4.3.5 StringGetOwnProperty ( str, propertyKey )

The abstract operation StringGetOwnProperty takes arguments str (一个具有 [[StringData]] 内部槽的 Object) and propertyKey (一个属性键) and returns 一个属性描述符或 undefined. It performs the following steps when called:

  1. 如果 propertyKey 不是一个 String,返回 undefined
  2. indexCanonicalNumericIndexString(propertyKey)。
  3. 如果 index 不是一个整数 Number,返回 undefined
  4. 如果 index-0𝔽index < -0𝔽,返回 undefined
  5. stringDatastr.[[StringData]]
  6. 断言:stringData 是一个 String。
  7. lenstringData 的长度。
  8. 如果 (index) ≥ len,返回 undefined
  9. resultStrstringData 中从 (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 中被安装。

Note 1

虽然 CreateUnmappedArgumentsObject 被归在本条款中,但它创建的是一个普通 对象,而不是 arguments 异质对象

arguments 异质对象具有与普通对象相同的内部槽。它们还具有一个 [[ParameterMap]] 内部槽。普通 arguments 对象也具有一个 [[ParameterMap]] 内部槽,但其值始终为 undefined。对于普通 arguments 对象而言,[[ParameterMap]] 内部槽仅由 Object.prototype.toString20.1.3.6)用来将它们识别 为 arguments 对象。

Note 2

arguments 异质对象中那些其数值名称小于对应函数对象形式参数个数的整数索引 数据属性,初始时会与函数执行上下文中的对应参数绑定共享其值。这意味着更改该 属性会更改对应参数绑定的值,反之亦然。如果这样的属性被删除后又重新定义,或者 被变更为访问器属性,则这种对应关系会被打破。如果 arguments 对象是一个普通对 象,那么其属性值只是对传入函数参数的简单拷贝,属性值与形式参数值之间不存在动 态联动。

Note 3

ParameterMap 对象及其属性值被用作一种装置,用来规定 arguments 对象与参数 绑定之间的对应关系。ParameterMap 对象以及作为其属性值的对象都不能被 ECMAScript 代码直接观察到。ECMAScript 实现并不需要实际创建或使用这类对象来实现所规定的 语义。

Note 4

普通 arguments 对象定义了一个名为 "callee" 的不可配置访问器属性,对其 访问会抛出一个 TypeError 异常。对于 arguments 异质对象来说,"callee" 属性有更具体的含义,因为它们只为某类非严格函数创建。普通变体中该属性的定义 之所以存在,是为了确保符合规范的 ECMAScript 实现不会以任何其他方式定义它。

Note 5

ECMAScript 对 arguments 异质对象的实现曾经在历史上包含一个名为 "caller"访问器属性。在 ECMAScript 2017 之前,本规范还包含对普通 arguments 对象上 一个会抛出的 "caller" 属性的定义。由于实现如今已经不再包含这一扩展, ECMAScript 2017 取消了对会抛出的 "caller" 访问器的要求。

10.4.4.1 [[GetOwnProperty]] ( propertyKey )

The [[GetOwnProperty]] internal method of 一个 arguments 异质对象 args takes argument propertyKey (一个属性键) and returns 一个正常完成,包含一个属性描述符或 undefined. It performs the following steps when called:

  1. descOrdinaryGetOwnProperty(args, propertyKey)。
  2. 如果 descundefined,返回 undefined
  3. mapargs.[[ParameterMap]]
  4. isMapped 为 ! HasOwnProperty(map, propertyKey)。
  5. 如果 isMappedtrue,那么
    1. desc.[[Value]] 设为 ! Get(map, propertyKey)。
  6. 返回 desc

10.4.4.2 [[DefineOwnProperty]] ( propertyKey, desc )

The [[DefineOwnProperty]] internal method of 一个 arguments 异质对象 args takes arguments propertyKey (一个属性键) and desc (一个属性描述符) and returns 一个正常完成,包含一个 Boolean. It performs the following steps when called:

  1. mapargs.[[ParameterMap]]
  2. isMapped 为 ! HasOwnProperty(map, propertyKey)。
  3. newArgDescdesc
  4. 如果 isMappedtrueIsDataDescriptor(desc) 为 true,那么
    1. 如果 desc 不具有 [[Value]] 字段,且 desc 具有 [[Writable]] 字段,并且 desc.[[Writable]]false,那么
      1. newArgDesc 设为 desc 的一个副本。
      2. newArgDesc.[[Value]] 设为 ! Get(map, propertyKey)。
  5. allowed 为 ! OrdinaryDefineOwnProperty(args, propertyKey, newArgDesc)。
  6. 如果 allowedfalse,返回 false
  7. 如果 isMappedtrue,那么
    1. 如果 IsAccessorDescriptor(desc) 为 true,那么
      1. 执行 ! map.[[Delete]](propertyKey)。
    2. 否则,
      1. 如果 desc 具有 [[Value]] 字段,那么
        1. 断言:以下 Set 将会成功,因为由 arguments 对象映射的形式参数始终可写。
        2. 执行 ! Set(map, propertyKey, desc.[[Value]], false)。
      2. 如果 desc 具有 [[Writable]] 字段且 desc.[[Writable]]false,那么
        1. 执行 ! map.[[Delete]](propertyKey)。
  8. 返回 true

10.4.4.3 [[Get]] ( propertyKey, receiver )

The [[Get]] internal method of 一个 arguments 异质对象 args takes arguments propertyKey (一个属性键) and receiver (一个 ECMAScript 语言值) and returns 要么是一个正常完成,包含一个 ECMAScript 语言值,要么是一个抛出完成. It performs the following steps when called:

  1. mapargs.[[ParameterMap]]
  2. isMapped 为 ! HasOwnProperty(map, propertyKey)。
  3. 如果 isMappedfalse,返回 ? OrdinaryGet(args, propertyKey, receiver)。
  4. 断言:map 包含 propertyKey 的一个形式参数映射。
  5. 返回 ! Get(map, propertyKey)。

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

The [[Set]] internal method of 一个 arguments 异质对象 args takes arguments propertyKey (一个属性键), value (一个 ECMAScript 语言值), and receiver (一个 ECMAScript 语言值) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

  1. 如果 SameValue(args, receiver) 为 false,那么
    1. isMappedfalse
  2. 否则,
    1. mapargs.[[ParameterMap]]
    2. isMapped 为 ! HasOwnProperty(map, propertyKey)。
  3. 如果 isMappedtrue,那么
    1. 断言:以下 Set 将会成功,因为由 arguments 对象映射的形式参数始终可写。
    2. 执行 ! Set(map, propertyKey, value, false)。
  4. 返回 ? OrdinarySet(args, propertyKey, value, receiver)。

10.4.4.5 [[Delete]] ( propertyKey )

The [[Delete]] internal method of 一个 arguments 异质对象 args takes argument propertyKey (一个属性键) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

  1. mapargs.[[ParameterMap]]
  2. isMapped 为 ! HasOwnProperty(map, propertyKey)。
  3. result 为 ? OrdinaryDelete(args, propertyKey)。
  4. 如果 resulttrueisMappedtrue,那么
    1. 执行 ! map.[[Delete]](propertyKey)。
  5. 返回 result

10.4.4.6 CreateUnmappedArgumentsObject ( argumentsList )

The abstract operation CreateUnmappedArgumentsObject takes argument argumentsList (一个 ECMAScript 语言值列表) and returns 一个普通对象. It performs the following steps when called:

  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. index 设为 index + 1。
  7. 执行 ! DefinePropertyOrThrow(obj, %Symbol.iterator%, PropertyDescriptor { [[Value]]: %Array.prototype.values%, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true })。
  8. 执行 ! DefinePropertyOrThrow(obj, "callee", PropertyDescriptor { [[Get]]: %ThrowTypeError%, [[Set]]: %ThrowTypeError%, [[Enumerable]]: false, [[Configurable]]: false })。
  9. 返回 obj

10.4.4.7 CreateMappedArgumentsObject ( func, formals, argumentsList, env )

The abstract operation CreateMappedArgumentsObject takes arguments func (an ECMAScript function object), formals (a Parse Node), argumentsList (a List of ECMAScript language values), and env (an Environment Record) and returns an arguments exotic object. It performs the following steps when called:

  1. 断言:formals 不包含剩余参数、任何绑定模式或任何初始化器。它可以包含重复的标识符。
  2. lenargumentsList 中元素的个数。
  3. objMakeBasicObject[[Prototype]], [[Extensible]], [[ParameterMap]] »)。
  4. obj.[[GetOwnProperty]] 设为 10.4.4.1 中规定的内容。
  5. obj.[[DefineOwnProperty]] 设为 10.4.4.2 中规定的内容。
  6. obj.[[Get]] 设为 10.4.4.3 中规定的内容。
  7. obj.[[Set]] 设为 10.4.4.4 中规定的内容。
  8. obj.[[Delete]] 设为 10.4.4.5 中规定的内容。
  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. index 设为 index + 1。
  16. 执行 ! DefinePropertyOrThrow(obj, "length", PropertyDescriptor { [[Value]]: 𝔽(len), [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true })。
  17. mappedNames 为一个新的空列表。
  18. index 设为 numberOfParameters - 1。
  19. 重复,当 index ≥ 0 时,
    1. nameparameterNames[index]。
    2. 如果 mappedNames 不包含 name,那么
      1. name 追加到 mappedNames
      2. 如果 index < len,那么
        1. getterMakeArgGetter(name, env)。
        2. setterMakeArgSetter(name, env)。
        3. 执行 ! map.[[DefineOwnProperty]](! ToString(𝔽(index)), PropertyDescriptor { [[Set]]: setter, [[Get]]: getter, [[Enumerable]]: false, [[Configurable]]: true })。
    3. index 设为 index - 1。
  20. 执行 ! DefinePropertyOrThrow(obj, %Symbol.iterator%, PropertyDescriptor { [[Value]]: %Array.prototype.values%, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true })。
  21. 执行 ! DefinePropertyOrThrow(obj, "callee", PropertyDescriptor { [[Value]]: func, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true })。
  22. 返回 obj

10.4.4.7.1 MakeArgGetter ( name, env )

The abstract operation MakeArgGetter takes arguments name (一个 String) and env (一个 Environment Record) and returns 一个函数对象. 它会创建一个内建函数对象,该对象在执行时返回 env 中绑定到 name 的值。 It performs the following steps when called:

  1. getterClosure 为一个新的不带参数的抽象闭包,它捕获 nameenv,并在被调用时执行以下步骤:
    1. 返回 NormalCompletion(! env.GetBindingValue(name, false))。
  2. getterCreateBuiltinFunction(getterClosure, 0, "", « »)。
  3. NOTE: getter 永远不能被 ECMAScript 代码直接访问。
  4. 返回 getter

10.4.4.7.2 MakeArgSetter ( name, env )

The abstract operation MakeArgSetter takes arguments name (一个 String) and env (一个 Environment Record) and returns 一个函数对象. 它会创建一个内建函数对象,该对象在执行时将 env 中绑定到 name 的值设为给定值。 It performs the following steps when called:

  1. setterClosure 为一个带参数 (value) 的新抽象闭包,它捕获 nameenv,并在被调用时执行以下步骤:
    1. 返回 NormalCompletion(! env.SetMutableBinding(name, value, false))。
  2. setterCreateBuiltinFunction(setterClosure, 1, "", « »)。
  3. NOTE: setter 永远不能被 ECMAScript 代码直接访问。
  4. 返回 setter

10.4.5 TypedArray 异质对象

TypedArray 是一种异质对象,它会对作为规范数值字符串canonical numeric strings) 的属性键进行特殊处理,使用其中属于边界内整数索引的那一部分来索引统一类型的元 素,并强制保证其余那些键不存在,且不会引发原型链遍历。

Note

由于对于任意 Number nToString(n) 都是一个规范数值字符串,因此实现 可以将 Number 当作 TypedArray属性键处理,而不必真的执行字符串转换。

TypedArray 具有与普通对象相同的内部槽,并额外具有 [[ViewedArrayBuffer]][[TypedArrayName]][[ContentType]][[ByteLength]][[ByteOffset]][[ArrayLength]] 内部槽。

如果一个对象的 [[PreventExtensions]][[GetOwnProperty]][[HasProperty]][[DefineOwnProperty]][[Get]][[Set]][[Delete]][[OwnPropertyKeys]] 内部方法使用本节中的定义,而其他基本内部方法使用 10.1 中给出的定义,则该对象是一个 TypedArray。 这些方法由 TypedArrayCreate 安装。

10.4.5.1 [[PreventExtensions]] ( )

The [[PreventExtensions]] internal method of 一个 TypedArray obj takes no arguments and returns 一个正常完成,包含一个 Boolean. It performs the following steps when called:

  1. NOTE: 6.1.7.3 中规定的与可扩展性相关的不变量不允许当 obj 仍可能获得(或失去后再次获 得)属性时该方法返回 true;而这类情况可能会发生在其底层缓冲区被调整大 小时,具有整数索引名称的属性上。
  2. 如果 IsTypedArrayFixedLength(obj) 为 false,返回 false
  3. 返回 OrdinaryPreventExtensions(obj)。

10.4.5.2 [[GetOwnProperty]] ( propertyKey )

The [[GetOwnProperty]] internal method of 一个 TypedArray obj takes argument propertyKey (一个属性键) and returns 一个正常完成,包含一个属性描述符或 undefined. It performs the following steps when called:

  1. 如果 propertyKey 是一个 String,那么
    1. numericIndexCanonicalNumericIndexString(propertyKey)。
    2. 如果 numericIndex 不是 undefined,那么
      1. valueTypedArrayGetElement(obj, numericIndex)。
      2. 如果 valueundefined,返回 undefined
      3. 返回属性描述符 PropertyDescriptor { [[Value]]: value, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true }。
  2. 返回 OrdinaryGetOwnProperty(obj, propertyKey)。

10.4.5.3 [[HasProperty]] ( propertyKey )

The [[HasProperty]] internal method of 一个 TypedArray obj takes argument propertyKey (一个属性键) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

  1. 如果 propertyKey 是一个 String,那么
    1. numericIndexCanonicalNumericIndexString(propertyKey)。
    2. 如果 numericIndex 不是 undefined,返回 IsValidIntegerIndex(obj, numericIndex)。
  2. 返回 ? OrdinaryHasProperty(obj, propertyKey)。

10.4.5.4 [[DefineOwnProperty]] ( propertyKey, desc )

The [[DefineOwnProperty]] internal method of 一个 TypedArray obj takes arguments propertyKey (一个属性键) and desc (一个属性描述符) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

  1. 如果 propertyKey 是一个 String,那么
    1. numericIndexCanonicalNumericIndexString(propertyKey)。
    2. 如果 numericIndex 不是 undefined,那么
      1. 如果 IsValidIntegerIndex(obj, 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(obj, numericIndex, desc.[[Value]])。
      7. 返回 true
  2. 返回 ! OrdinaryDefineOwnProperty(obj, propertyKey, desc)。

10.4.5.5 [[Get]] ( propertyKey, receiver )

The [[Get]] internal method of 一个 TypedArray obj takes arguments propertyKey (一个属性键) and receiver (一个 ECMAScript 语言值) and returns 要么是一个正常完成,包含一个 ECMAScript 语言值,要么是一个抛出完成. It performs the following steps when called:

  1. 如果 propertyKey 是一个 String,那么
    1. numericIndexCanonicalNumericIndexString(propertyKey)。
    2. 如果 numericIndex 不是 undefined,那么
      1. 返回 TypedArrayGetElement(obj, numericIndex)。
  2. 返回 ? OrdinaryGet(obj, propertyKey, receiver)。

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

The [[Set]] internal method of 一个 TypedArray obj takes arguments propertyKey (一个属性键), value (一个 ECMAScript 语言值), and receiver (一个 ECMAScript 语言值) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

  1. 如果 propertyKey 是一个 String,那么
    1. numericIndexCanonicalNumericIndexString(propertyKey)。
    2. 如果 numericIndex 不是 undefined,那么
      1. 如果 SameValue(obj, receiver) 为 true,那么
        1. 执行 ? TypedArraySetElement(obj, numericIndex, value)。
        2. 返回 true
      2. 如果 IsValidIntegerIndex(obj, numericIndex) 为 false,返回 true
  2. 返回 ? OrdinarySet(obj, propertyKey, value, receiver)。

10.4.5.7 [[Delete]] ( propertyKey )

The [[Delete]] internal method of 一个 TypedArray obj takes argument propertyKey (一个属性键) and returns 一个正常完成,包含一个 Boolean. It performs the following steps when called:

  1. 如果 propertyKey 是一个 String,那么
    1. numericIndexCanonicalNumericIndexString(propertyKey)。
    2. 如果 numericIndex 不是 undefined,那么
      1. 如果 IsValidIntegerIndex(obj, numericIndex) 为 false,返回 true
      2. 返回 false
  2. 返回 ! OrdinaryDelete(obj, propertyKey)。

10.4.5.8 [[OwnPropertyKeys]] ( )

The [[OwnPropertyKeys]] internal method of 一个 TypedArray obj takes no arguments and returns 一个正常完成,包含一个属性键列表. It performs the following steps when called:

  1. taRecordMakeTypedArrayWithBufferWitnessRecord(obj, seq-cst)。
  2. keys 为一个新的空列表。
  3. 如果 IsTypedArrayOutOfBounds(taRecord) 为 false,那么
    1. lengthTypedArrayLength(taRecord)。
    2. 对于每个满足 0 ≤ i < length整数 i,按升序,执行
      1. 将 ! ToString(𝔽(i)) 追加到 keys
  4. 对于 obj 的每个自有属性键 propertyKey,若 propertyKey 是一个 String 且 propertyKey 不是整数索引,按属性创建时间顺序升序,执行
    1. propertyKey 追加到 keys
  5. 对于 obj 的每个自有属性键 propertyKey,若 propertyKey 是一个 Symbol,按属性创建时间顺序升序,执行
    1. propertyKey 追加到 keys
  6. 返回 keys

10.4.5.9 带缓冲区见证记录的 TypedArray

带缓冲区见证记录的 TypedArray 是一种记录值,用于封装一个 TypedArray 以及其所查看缓冲区的一个缓存字节长度。 当该查看缓冲区是一个可增长的 SharedArrayBuffer 时,它用于帮助确保字节长度数 据块只有一次 ReadSharedMemory 事件。

带缓冲区见证记录的 TypedArray 具有 Table 27 中列出的字段。

Table 27: 带缓冲区见证记录的 TypedArray 字段
字段名 含义
[[Object]] 一个 TypedArray 其缓冲区字节长度被加载的那个 TypedArray
[[CachedBufferByteLength]] 一个非负整数detached 创建该记录时,对象的 [[ViewedArrayBuffer]] 的字节长度。

10.4.5.10 MakeTypedArrayWithBufferWitnessRecord ( obj, order )

The abstract operation MakeTypedArrayWithBufferWitnessRecord takes arguments obj (一个 TypedArray) and order (seq-cstunordered) and returns 一个带缓冲区见证记录的 TypedArray. It performs the following steps when called:

  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 )

The abstract operation TypedArrayCreate takes argument prototype (一个 Object) and returns 一个 TypedArray. 它用于规定新 TypedArray 的创建。 It performs the following steps when called:

  1. internalSlotsList 为 « [[Prototype]], [[Extensible]], [[ViewedArrayBuffer]], [[TypedArrayName]], [[ContentType]], [[ByteLength]], [[ByteOffset]], [[ArrayLength]] »。
  2. typedArrayMakeBasicObject(internalSlotsList)。
  3. typedArray.[[PreventExtensions]] 设为 10.4.5.1 中规定的内容。
  4. typedArray.[[GetOwnProperty]] 设为 10.4.5.2 中规定的内容。
  5. typedArray.[[HasProperty]] 设为 10.4.5.3 中规定的内容。
  6. typedArray.[[DefineOwnProperty]] 设为 10.4.5.4 中规定的内容。
  7. typedArray.[[Get]] 设为 10.4.5.5 中规定的内容。
  8. typedArray.[[Set]] 设为 10.4.5.6 中规定的内容。
  9. typedArray.[[Delete]] 设为 10.4.5.7 中规定的内容。
  10. typedArray.[[OwnPropertyKeys]] 设为 10.4.5.8 中规定的内容。
  11. typedArray.[[Prototype]] 设为 prototype
  12. 返回 typedArray

10.4.5.12 TypedArrayByteLength ( taRecord )

The abstract operation TypedArrayByteLength takes argument taRecord (一个带缓冲区见证记录的 TypedArray) and returns 一个非负整数. It performs the following steps when called:

  1. 断言:IsTypedArrayOutOfBounds(taRecord) 为 false
  2. objtaRecord.[[Object]]
  3. 如果 obj.[[ByteLength]] 不是 auto,返回 obj.[[ByteLength]]
  4. lengthTypedArrayLength(taRecord)。
  5. elementSizeTypedArrayElementSize(obj)。
  6. NOTE: 返回的字节长度始终是 elementSize整数倍,即便底层缓冲区已被调整为非整数倍长度。
  7. 返回 length × elementSize

10.4.5.13 TypedArrayLength ( taRecord )

The abstract operation TypedArrayLength takes argument taRecord (一个带缓冲区见证记录的 TypedArray) and returns 一个非负整数. It performs the following steps when called:

  1. 断言:IsTypedArrayOutOfBounds(taRecord) 为 false
  2. objtaRecord.[[Object]]
  3. 如果 obj.[[ArrayLength]] 不是 auto,返回 obj.[[ArrayLength]]
  4. 断言:IsFixedLengthArrayBuffer(obj.[[ViewedArrayBuffer]]) 为 false
  5. byteOffsetobj.[[ByteOffset]]
  6. elementSizeTypedArrayElementSize(obj)。
  7. byteLengthtaRecord.[[CachedBufferByteLength]]
  8. 断言:byteLength 不是 detached
  9. 返回 floor((byteLength - byteOffset) / elementSize)。

10.4.5.14 IsTypedArrayOutOfBounds ( taRecord )

The abstract operation IsTypedArrayOutOfBounds takes argument taRecord (一个带缓冲区见证记录的 TypedArray) and returns 一个 Boolean. 它检查对象的任何数值属性是否会引用到底层缓冲区边界之外某个索引处的值。 It performs the following steps when called:

  1. objtaRecord.[[Object]]
  2. bufferByteLengthtaRecord.[[CachedBufferByteLength]]
  3. 如果 IsDetachedBuffer(obj.[[ViewedArrayBuffer]]) 为 true,那么
    1. 断言:bufferByteLengthdetached
    2. 返回 true
  4. 断言:bufferByteLength 是一个非负整数
  5. byteOffsetStartobj.[[ByteOffset]]
  6. 如果 obj.[[ArrayLength]]auto,那么
    1. byteOffsetEndbufferByteLength
  7. 否则,
    1. elementSizeTypedArrayElementSize(obj)。
    2. arrayByteLengthobj.[[ArrayLength]] × elementSize
    3. byteOffsetEndbyteOffsetStart + arrayByteLength
  8. NOTE: 一个长度为 0 且其 [[ByteOffset]] 等于 bufferByteLengthTypedArray 不被视为越界。
  9. 如果 byteOffsetStart > bufferByteLengthbyteOffsetEnd > bufferByteLength,返回 true
  10. 返回 false

10.4.5.15 IsTypedArrayFixedLength ( obj )

The abstract operation IsTypedArrayFixedLength takes argument obj (一个 TypedArray) and returns 一个 Boolean. It performs the following steps when called:

  1. 如果 obj.[[ArrayLength]]auto,返回 false
  2. bufferobj.[[ViewedArrayBuffer]]
  3. 如果 IsFixedLengthArrayBuffer(buffer) 为 falseIsSharedArrayBuffer(buffer) 为 false,返回 false
  4. 返回 true

10.4.5.16 IsValidIntegerIndex ( obj, index )

The abstract operation IsValidIntegerIndex takes arguments obj (一个 TypedArray) and index (一个 Number) and returns 一个 Boolean. It performs the following steps when called:

  1. 如果 IsDetachedBuffer(obj.[[ViewedArrayBuffer]]) 为 true,返回 false
  2. 如果 index 不是一个整数 Number,返回 false
  3. 如果 index-0𝔽index < -0𝔽,返回 false
  4. taRecordMakeTypedArrayWithBufferWitnessRecord(obj, unordered)。
  5. NOTE: 当 obj 的后备缓冲区是一个可增长的 SharedArrayBuffer 时,边界检查不是一个同步操作。
  6. 如果 IsTypedArrayOutOfBounds(taRecord) 为 true,返回 false
  7. lengthTypedArrayLength(taRecord)。
  8. 如果 (index) ≥ length,返回 false
  9. 返回 true

10.4.5.17 TypedArrayGetElement ( obj, index )

The abstract operation TypedArrayGetElement takes arguments obj (一个 TypedArray) and index (一个 Number) and returns 一个 Number、一个 BigInt 或 undefined. It performs the following steps when called:

  1. 如果 IsValidIntegerIndex(obj, index) 为 false,返回 undefined
  2. offsetobj.[[ByteOffset]]
  3. elementSizeTypedArrayElementSize(obj)。
  4. byteIndexInBuffer 为 ((index) × elementSize) + offset
  5. elementTypeTypedArrayElementType(obj)。
  6. 返回 GetValueFromBuffer(obj.[[ViewedArrayBuffer]], byteIndexInBuffer, elementType, true, unordered)。

10.4.5.18 TypedArraySetElement ( obj, index, value )

The abstract operation TypedArraySetElement takes arguments obj (一个 TypedArray), index (一个 Number), and value (一个 ECMAScript 语言值) and returns 要么是一个正常完成,包含 unused,要么是一个抛出完成. It performs the following steps when called:

  1. 如果 obj.[[ContentType]]bigint,令 numValue 为 ? ToBigInt(value)。
  2. 否则,令 numValue 为 ? ToNumber(value)。
  3. 如果 IsValidIntegerIndex(obj, index) 为 true,那么
    1. offsetobj.[[ByteOffset]]
    2. elementSizeTypedArrayElementSize(obj)。
    3. byteIndexInBuffer 为 ((index) × elementSize) + offset
    4. elementTypeTypedArrayElementType(obj)。
    5. 执行 SetValueInBuffer(obj.[[ViewedArrayBuffer]], byteIndexInBuffer, elementType, numValue, true, unordered)。
  4. 返回 unused
Note

该操作总是看起来会成功,但当尝试写入 TypedArray 末尾之外的位置,或写入一 个由已分离的 ArrayBuffer 支持的 TypedArray 时,它实际上不会产生效果。

10.4.5.19 IsArrayBufferViewOutOfBounds ( obj )

The abstract operation IsArrayBufferViewOutOfBounds takes argument obj (一个 TypedArray 或一个 DataView) and returns 一个 Boolean. 它检查 TypedArray 的任何数值属性或 DataView 对象的方法是否能够引用到底 层数据块边界之外某个索引处的值。该抽象操作作为对上游规范的一种便利而存在。 It performs the following steps when called:

  1. 如果 obj 具有 [[DataView]] 内部槽,那么
    1. viewRecordMakeDataViewWithBufferWitnessRecord(obj, seq-cst)。
    2. 返回 IsViewOutOfBounds(viewRecord)。
  2. taRecordMakeTypedArrayWithBufferWitnessRecord(obj, seq-cst)。
  3. 返回 IsTypedArrayOutOfBounds(taRecord)。

10.4.6 模块命名空间异质对象

模块命名空间异质对象是一种异质对象,它暴露来自某个 ECMAScript Module 的导 出绑定(见 16.2.3)。模块命名空间异质对象 的以 String 为键的自有属性,与该 Module 导出的绑定名称之间是一一对应的。这 些导出绑定包括通过 export * 导出项间接导出的任何绑定。每个 String 值的自有 属性键都是相应导出绑定名称的 StringValue。这些就是模块命名空间异质对象唯一的 以 String 为键的属性。每个这样的属性都具有特性 { [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: false }。 模块命名空间异质对象是不可扩展的。

如果一个对象的 [[GetPrototypeOf]][[SetPrototypeOf]][[IsExtensible]][[PreventExtensions]][[GetOwnProperty]][[DefineOwnProperty]][[HasProperty]][[Get]][[Set]][[Delete]][[OwnPropertyKeys]] 内部方法使用本节中的定义,而其他基本内部方法使用 10.1 中给出的定义,则该对象是一个 模块命名空间异质对象。 这些方法在 ModuleNamespaceCreate 中被安装。

模块命名空间异质对象具有 Table 28 中定义的内部槽。

Table 28: 模块命名空间异质对象的内部槽
内部槽 类型 描述
[[Module]] 一个 Module Record 其导出由该命名空间暴露的 Module Record
[[Exports]] 一个 String 列表 一个列表,其元素是作为该对象自有属性暴露的导出名称的 String 值。该列表 按词法码元顺序排序。

10.4.6.1 [[GetPrototypeOf]] ( )

The [[GetPrototypeOf]] internal method of 一个模块命名空间异质对象 takes no arguments and returns 一个正常完成,包含 null. It performs the following steps when called:

  1. 返回 null

10.4.6.2 [[SetPrototypeOf]] ( proto )

The [[SetPrototypeOf]] internal method of 一个模块命名空间异质对象 obj takes argument proto (一个 Object 或 null) and returns 一个正常完成,包含一个 Boolean. It performs the following steps when called:

  1. 返回 ! SetImmutablePrototype(obj, proto)。

10.4.6.3 [[IsExtensible]] ( )

The [[IsExtensible]] internal method of 一个模块命名空间异质对象 takes no arguments and returns 一个正常完成,包含 false. It performs the following steps when called:

  1. 返回 false

10.4.6.4 [[PreventExtensions]] ( )

The [[PreventExtensions]] internal method of 一个模块命名空间异质对象 takes no arguments and returns 一个正常完成,包含 true. It performs the following steps when called:

  1. 返回 true

10.4.6.5 [[GetOwnProperty]] ( propertyKey )

The [[GetOwnProperty]] internal method of 一个模块命名空间异质对象 obj takes argument propertyKey (一个属性键) and returns 要么是一个正常完成,包含一个属性描述符或 undefined,要么是一个抛出完成. It performs the following steps when called:

  1. 如果 propertyKey 是一个 Symbol,返回 OrdinaryGetOwnProperty(obj, propertyKey)。
  2. exportsobj.[[Exports]]
  3. 如果 exports 不包含 propertyKey,返回 undefined
  4. value 为 ? obj.[[Get]](propertyKey, obj)。
  5. 返回 PropertyDescriptor { [[Value]]: value, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: false }。

10.4.6.6 [[DefineOwnProperty]] ( propertyKey, desc )

The [[DefineOwnProperty]] internal method of 一个模块命名空间异质对象 obj takes arguments propertyKey (一个属性键) and desc (一个属性描述符) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

  1. 如果 propertyKey 是一个 Symbol,返回 ! OrdinaryDefineOwnProperty(obj, propertyKey, desc)。
  2. current 为 ? obj.[[GetOwnProperty]](propertyKey)。
  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]] ( propertyKey )

The [[HasProperty]] internal method of 一个模块命名空间异质对象 obj takes argument propertyKey (一个属性键) and returns 一个正常完成,包含一个 Boolean. It performs the following steps when called:

  1. 如果 propertyKey 是一个 Symbol,返回 ! OrdinaryHasProperty(obj, propertyKey)。
  2. exportsobj.[[Exports]]
  3. 如果 exports 包含 propertyKey,返回 true
  4. 返回 false

10.4.6.8 [[Get]] ( propertyKey, receiver )

The [[Get]] internal method of 一个模块命名空间异质对象 obj takes arguments propertyKey (一个属性键) and receiver (一个 ECMAScript 语言值) and returns 要么是一个正常完成,包含一个 ECMAScript 语言值,要么是一个抛出完成. It performs the following steps when called:

  1. 如果 propertyKey 是一个 Symbol,那么
    1. 返回 ! OrdinaryGet(obj, propertyKey, receiver)。
  2. exportsobj.[[Exports]]
  3. 如果 exports 不包含 propertyKey,返回 undefined
  4. moduleobj.[[Module]]
  5. bindingmodule.ResolveExport(propertyKey)。
  6. 断言:binding 是一个 ResolvedBinding Record
  7. targetModulebinding.[[Module]]
  8. 断言:targetModule 不是 undefined
  9. 如果 binding.[[BindingName]]namespace,那么
    1. 返回 GetModuleNamespace(targetModule)。
  10. targetEnvtargetModule.[[Environment]]
  11. 如果 targetEnvempty,抛出一个 ReferenceError 异常。
  12. 返回 ? targetEnv.GetBindingValue(binding.[[BindingName]], true)。
Note

ResolveExport 没有副作用。每次当以某个特定的 exportNameresolveSet 对作为参数调用该操作时,它都必须返回相同的结果。实现可以选择为每个模块命名 空间异质对象[[Exports]] 预先计算或缓存 ResolveExport 的结果。

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

The [[Set]] internal method of 一个模块命名空间异质对象 takes arguments propertyKey (一个属性键), value (一个 ECMAScript 语言值), and receiver (一个 ECMAScript 语言值) and returns 一个正常完成,包含 false. It performs the following steps when called:

  1. 返回 false

10.4.6.10 [[Delete]] ( propertyKey )

The [[Delete]] internal method of 一个模块命名空间异质对象 obj takes argument propertyKey (一个属性键) and returns 一个正常完成,包含一个 Boolean. It performs the following steps when called:

  1. 如果 propertyKey 是一个 Symbol,那么
    1. 返回 ! OrdinaryDelete(obj, propertyKey)。
  2. exportsobj.[[Exports]]
  3. 如果 exports 包含 propertyKey,返回 false
  4. 返回 true

10.4.6.11 [[OwnPropertyKeys]] ( )

The [[OwnPropertyKeys]] internal method of 一个模块命名空间异质对象 obj takes no arguments and returns 一个正常完成,包含一个属性键列表. It performs the following steps when called:

  1. exportsobj.[[Exports]]
  2. symbolKeysOrdinaryOwnPropertyKeys(obj)。
  3. 返回 exportssymbolKeys 的列表串接。

10.4.6.12 ModuleNamespaceCreate ( module, exports )

The abstract operation ModuleNamespaceCreate takes arguments module (一个 Module Record) and exports (一个 String 列表) and returns 一个模块命名空间异质对象. 它用于规定新模块命名空间异质对象的创建。 It performs the following steps when called:

  1. 断言:module.[[Namespace]]empty
  2. internalSlotsListTable 28 中列出的内部槽。
  3. namespaceMakeBasicObject(internalSlotsList)。
  4. namespace 的基本内部方法设为 10.4.6 中规定的定义。
  5. namespace.[[Module]] 设为 module
  6. sortedExports 为一个列表,其元素是 exports 的元素,并按词法码元顺序排序。
  7. namespace.[[Exports]] 设为 sortedExports
  8. 根据 28.3 中的定义在 namespace 上创建自有属性。
  9. module.[[Namespace]] 设为 namespace
  10. 返回 namespace

10.4.7 不可变原型异质对象

不可变原型异质对象是一种异质对象,它具有一个一旦初始化后就不会再改变的 [[Prototype]] 内部槽。

如果一个对象的 [[SetPrototypeOf]] 内部方法使用以下实现,则该对象是一个 不可变原型异质对象。 (至于它的其他基本内部方法可以采用何种实现,则取决于具体的不可变原型异质对象。)

Note

与其他异质对象不同,并没有为不可变原型异质对象提供专门的创建抽象操作。这是 因为它们只被 %Object.prototype%宿主环境使用;而在宿主环境中,相关对象可能 还会以其他方式表现为异质,因此需要它们自己的专门创建操作。

10.4.7.1 [[SetPrototypeOf]] ( proto )

The [[SetPrototypeOf]] internal method of 一个不可变原型异质对象 obj takes argument proto (一个 Object 或 null) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

  1. 返回 ? SetImmutablePrototype(obj, proto)。

10.4.7.2 SetImmutablePrototype ( obj, proto )

The abstract operation SetImmutablePrototype takes arguments obj (一个 Object) and proto (一个 Object 或 null) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

  1. current 为 ? obj.[[GetPrototypeOf]]()
  2. 如果 SameValue(proto, current) 为 true,返回 true
  3. 返回 false

10.5 Proxy 对象内部方法和内部槽

Proxy 对象是一种异质对象,其基本内部方法的一部分使用 ECMAScript 代码实现。 每个 Proxy 对象都有一个名为 [[ProxyHandler]] 的内部槽。[[ProxyHandler]] 的值 是一个对象,称为该 proxy 的处理器对象,或者是 null。处理器对象 的方法(见 Table 29)可 以用来增强 Proxy 对象的一个或多个内部方法的实现。每个 Proxy 对象还有一个名 为 [[ProxyTarget]] 的内部槽,其值要么是一个对象,要么是 null。这个对象 被称为该 proxy 的目标对象

如果一个对象的基本内部方法(包括在适用时的 [[Call]][[Construct]]) 使用本节中的定义,那么它就是一个 Proxy 异质对象。 这些内部方法会在 ProxyCreate 中被安装。

Table 29: Proxy 处理器方法
内部方法 处理器方法
[[GetPrototypeOf]] getPrototypeOf
[[SetPrototypeOf]] setPrototypeOf
[[IsExtensible]] isExtensible
[[PreventExtensions]] preventExtensions
[[GetOwnProperty]] getOwnPropertyDescriptor
[[DefineOwnProperty]] defineProperty
[[HasProperty]] has
[[Get]] get
[[Set]] set
[[Delete]] deleteProperty
[[OwnPropertyKeys]] ownKeys
[[Call]] apply
[[Construct]] construct

当调用某个处理器方法以提供 Proxy 对象某个内部方法的实现时,该处理器方法会 将 proxy 的目标对象作为参数传入。proxy 的处理器对象不一定具有与每个基本内部 方法对应的方法。如果处理器对象没有与该内部陷阱对应的方法,那么在 proxy 上调 用某个内部方法,会导致在 proxy 的目标对象上调用相应的内部方法。

Proxy 对象的 [[ProxyHandler]][[ProxyTarget]] 内部槽在对象创建时总是 被初始化,并且通常不可修改。某些 Proxy 对象会以一种允许其后续被撤销 的方式创建。当一个 proxy 被撤销时,它的 [[ProxyHandler]][[ProxyTarget]] 内部槽都会被设为 null,从而导致之后对该 Proxy 对象内部方法的调用抛出一个 TypeError 异常。

由于 Proxy 对象允许由任意 ECMAScript 代码来提供内部方法的实现,因此有可 能定义一个 Proxy 对象,使其处理器方法违反 6.1.7.3 中定义的不变量。其中一些在 6.1.7.3 中定义的内部方法不变量是基本完整性不变量。这些不变量由本节所规定的 Proxy 对 象内部方法显式强制执行。ECMAScript 实现必须能够稳健地处理所有可能的不变量违 反情况。

在以下算法描述中,假设 obj 是一个 ECMAScript Proxy 对象,propertyKey 是一个属性键值,value 是任意 ECMAScript 语言值desc 是一个属性描述符记 录。

10.5.1 [[GetPrototypeOf]] ( )

The [[GetPrototypeOf]] internal method of 一个 Proxy 异质对象 obj takes no arguments and returns 要么是一个正常完成,包含一个 Object 或 null,要么是一个抛出完成. It performs the following steps when called:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. targetobj.[[ProxyTarget]]
  3. handlerobj.[[ProxyHandler]]
  4. 断言:handler 是一个 Object。
  5. trap 为 ? GetMethod(handler, "getPrototypeOf")。
  6. 如果 trapundefined,那么
    1. 返回 ? target.[[GetPrototypeOf]]()
  7. handlerProto 为 ? Call(trap, handler, « target »)。
  8. 如果 handlerProto 既不是一个 Object 也不是 null,抛出一个 TypeError 异常。
  9. extensibleTarget 为 ? IsExtensible(target)。
  10. 如果 extensibleTargettrue,返回 handlerProto
  11. targetProto 为 ? target.[[GetPrototypeOf]]()
  12. 如果 SameValue(handlerProto, targetProto) 为 false,抛出一个 TypeError 异常。
  13. 返回 handlerProto
Note

Proxy 对象的 [[GetPrototypeOf]] 强制执行以下不变量:

  • [[GetPrototypeOf]] 的结果必须是一个 Object 或 null
  • 如果目标对象不可扩展,则对 Proxy 对象应用 [[GetPrototypeOf]] 必须返回 与对 Proxy 对象的目标对象应用 [[GetPrototypeOf]] 相同的值。

10.5.2 [[SetPrototypeOf]] ( proto )

The [[SetPrototypeOf]] internal method of 一个 Proxy 异质对象 obj takes argument proto (一个 Object 或 null) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. targetobj.[[ProxyTarget]]
  3. handlerobj.[[ProxyHandler]]
  4. 断言:handler 是一个 Object。
  5. trap 为 ? GetMethod(handler, "setPrototypeOf")。
  6. 如果 trapundefined,那么
    1. 返回 ? target.[[SetPrototypeOf]](proto)
  7. booleanTrapResultToBoolean(? Call(trap, handler, « target, proto »))。
  8. 如果 booleanTrapResultfalse,返回 false
  9. extensibleTarget 为 ? IsExtensible(target)。
  10. 如果 extensibleTargettrue,返回 true
  11. targetProto 为 ? target.[[GetPrototypeOf]]()
  12. 如果 SameValue(proto, targetProto) 为 false,抛出一个 TypeError 异常。
  13. 返回 true
Note

Proxy 对象的 [[SetPrototypeOf]] 强制执行以下不变量:

  • [[SetPrototypeOf]] 的结果是一个 Boolean 值。
  • 如果目标对象不可扩展,则参数值必须与对目标对象应用 [[GetPrototypeOf]] 的结果相同。

10.5.3 [[IsExtensible]] ( )

The [[IsExtensible]] internal method of 一个 Proxy 异质对象 obj takes no arguments and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. targetobj.[[ProxyTarget]]
  3. handlerobj.[[ProxyHandler]]
  4. 断言:handler 是一个 Object。
  5. trap 为 ? GetMethod(handler, "isExtensible")。
  6. 如果 trapundefined,那么
    1. 返回 ? IsExtensible(target)。
  7. booleanTrapResultToBoolean(? Call(trap, handler, « target »))。
  8. targetResult 为 ? IsExtensible(target)。
  9. 如果 booleanTrapResult 不等于 targetResult,抛出一个 TypeError 异常。
  10. 返回 booleanTrapResult
Note

Proxy 对象的 [[IsExtensible]] 强制执行以下不变量:

  • [[IsExtensible]] 的结果是一个 Boolean 值。
  • 对 Proxy 对象应用 [[IsExtensible]] 必须返回与对 Proxy 对象目标对象应用 [[IsExtensible]] 且使用同一参数时相同的值。

10.5.4 [[PreventExtensions]] ( )

The [[PreventExtensions]] internal method of 一个 Proxy 异质对象 obj takes no arguments and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. targetobj.[[ProxyTarget]]
  3. handlerobj.[[ProxyHandler]]
  4. 断言:handler 是一个 Object。
  5. trap 为 ? GetMethod(handler, "preventExtensions")。
  6. 如果 trapundefined,那么
    1. 返回 ? target.[[PreventExtensions]]()
  7. booleanTrapResultToBoolean(? Call(trap, handler, « target »))。
  8. 如果 booleanTrapResulttrue,那么
    1. extensibleTarget 为 ? IsExtensible(target)。
    2. 如果 extensibleTargettrue,抛出一个 TypeError 异常。
  9. 返回 booleanTrapResult
Note

Proxy 对象的 [[PreventExtensions]] 强制执行以下不变量:

  • [[PreventExtensions]] 的结果是一个 Boolean 值。
  • 仅当对 Proxy 对象的目标对象应用 [[IsExtensible]] 的结果为 false 时, 对 Proxy 对象应用 [[PreventExtensions]] 才能返回 true

10.5.5 [[GetOwnProperty]] ( propertyKey )

The [[GetOwnProperty]] internal method of 一个 Proxy 异质对象 obj takes argument propertyKey (一个属性键) and returns 要么是一个正常完成,包含一个属性描述符或 undefined,要么是一个抛出完成. It performs the following steps when called:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. targetobj.[[ProxyTarget]]
  3. handlerobj.[[ProxyHandler]]
  4. 断言:handler 是一个 Object。
  5. trap 为 ? GetMethod(handler, "getOwnPropertyDescriptor")。
  6. 如果 trapundefined,那么
    1. 返回 ? target.[[GetOwnProperty]](propertyKey)
  7. trapResultObj 为 ? Call(trap, handler, « target, propertyKey »)。
  8. 如果 trapResultObj 既不是一个 Object 也不是 undefined,抛出一个 TypeError 异常。
  9. targetDesc 为 ? target.[[GetOwnProperty]](propertyKey)
  10. 如果 trapResultObjundefined,那么
    1. 如果 targetDescundefined,返回 undefined
    2. 如果 targetDesc.[[Configurable]]false,抛出一个 TypeError 异常。
    3. extensibleTarget 为 ? IsExtensible(target)。
    4. 如果 extensibleTargetfalse,抛出一个 TypeError 异常。
    5. 返回 undefined
  11. extensibleTarget 为 ? IsExtensible(target)。
  12. resultDesc 为 ? ToPropertyDescriptor(trapResultObj)。
  13. 执行 CompletePropertyDescriptor(resultDesc)。
  14. validIsCompatiblePropertyDescriptor(extensibleTarget, resultDesc, targetDesc)。
  15. 如果 validfalse,抛出一个 TypeError 异常。
  16. 如果 resultDesc.[[Configurable]]false,那么
    1. 如果 targetDescundefinedtargetDesc.[[Configurable]]true,那么
      1. 抛出一个 TypeError 异常。
    2. 如果 resultDesc 具有 [[Writable]] 字段且 resultDesc.[[Writable]]false,那么
      1. 断言:targetDesc 具有 [[Writable]] 字段。
      2. 如果 targetDesc.[[Writable]]true,抛出一个 TypeError 异常。
  17. 返回 resultDesc
Note

Proxy 对象的 [[GetOwnProperty]] 强制执行以下不变量:

  • [[GetOwnProperty]] 的结果必须是一个属性描述符或 undefined
  • 如果某个属性作为目标对象的一个不可配置自有属性存在,则不能将其报告为不存在。
  • 如果某个属性作为不可扩展目标对象的一个自有属性存在,则不能将其报告为不存在。
  • 如果某个属性不是目标对象的自有属性,且目标对象不可扩展,则不能将其报告为存在。
  • 除非目标对象上存在一个对应的不可配置自有属性,否则不能将某个属性报告为不可配置。
  • 除非目标对象上存在一个对应的不可配置且不可写的自有属性,否则不能将某个属性同时报告为不可配置且不可写。

10.5.6 [[DefineOwnProperty]] ( propertyKey, desc )

The [[DefineOwnProperty]] internal method of 一个 Proxy 异质对象 obj takes arguments propertyKey (一个属性键) and desc (一个属性描述符) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. targetobj.[[ProxyTarget]]
  3. handlerobj.[[ProxyHandler]]
  4. 断言:handler 是一个 Object。
  5. trap 为 ? GetMethod(handler, "defineProperty")。
  6. 如果 trapundefined,那么
    1. 返回 ? target.[[DefineOwnProperty]](propertyKey, desc)
  7. descObjFromPropertyDescriptor(desc)。
  8. booleanTrapResultToBoolean(? Call(trap, handler, « target, propertyKey, descObj »))。
  9. 如果 booleanTrapResultfalse,返回 false
  10. targetDesc 为 ? target.[[GetOwnProperty]](propertyKey)
  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
Note

Proxy 对象的 [[DefineOwnProperty]] 强制执行以下不变量:

  • [[DefineOwnProperty]] 的结果是一个 Boolean 值。
  • 如果目标对象不可扩展,则不能添加属性。
  • 除非目标对象上存在一个对应的不可配置自有属性,否则某个属性不能是不可配置的。
  • 除非目标对象上存在一个对应的不可配置且不可写的自有属性,否则不可配置属性不能是不可写的。
  • 如果某个属性在目标对象上有对应属性,那么将该属性的属性描述符应用到目标对象 并使用 [[DefineOwnProperty]] 时,不得抛出异常。

10.5.7 [[HasProperty]] ( propertyKey )

The [[HasProperty]] internal method of 一个 Proxy 异质对象 obj takes argument propertyKey (一个属性键) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. targetobj.[[ProxyTarget]]
  3. handlerobj.[[ProxyHandler]]
  4. 断言:handler 是一个 Object。
  5. trap 为 ? GetMethod(handler, "has")。
  6. 如果 trapundefined,那么
    1. 返回 ? target.[[HasProperty]](propertyKey)
  7. booleanTrapResultToBoolean(? Call(trap, handler, « target, propertyKey »))。
  8. 如果 booleanTrapResultfalse,那么
    1. targetDesc 为 ? target.[[GetOwnProperty]](propertyKey)
    2. 如果 targetDesc 不是 undefined,那么
      1. 如果 targetDesc.[[Configurable]]false,抛出一个 TypeError 异常。
      2. extensibleTarget 为 ? IsExtensible(target)。
      3. 如果 extensibleTargetfalse,抛出一个 TypeError 异常。
  9. 返回 booleanTrapResult
Note

Proxy 对象的 [[HasProperty]] 强制执行以下不变量:

  • [[HasProperty]] 的结果是一个 Boolean 值。
  • 如果某个属性作为目标对象的一个不可配置自有属性存在,则不能将其报告为不存在。
  • 如果某个属性作为目标对象的一个自有属性存在且目标对象不可扩展,则不能将其报告为不存在。

10.5.8 [[Get]] ( propertyKey, receiver )

The [[Get]] internal method of 一个 Proxy 异质对象 obj takes arguments propertyKey (一个属性键) and receiver (一个 ECMAScript 语言值) and returns 要么是一个正常完成,包含一个 ECMAScript 语言值,要么是一个抛出完成. It performs the following steps when called:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. targetobj.[[ProxyTarget]]
  3. handlerobj.[[ProxyHandler]]
  4. 断言:handler 是一个 Object。
  5. trap 为 ? GetMethod(handler, "get")。
  6. 如果 trapundefined,那么
    1. 返回 ? target.[[Get]](propertyKey, receiver)
  7. trapResult 为 ? Call(trap, handler, « target, propertyKey, receiver »)。
  8. targetDesc 为 ? target.[[GetOwnProperty]](propertyKey)
  9. 如果 targetDesc 不是 undefinedtargetDesc.[[Configurable]]false,那么
    1. 如果 IsDataDescriptor(targetDesc) 为 truetargetDesc.[[Writable]]false,那么
      1. 如果 SameValue(trapResult, targetDesc.[[Value]]) 为 false,抛出一个 TypeError 异常。
    2. 如果 IsAccessorDescriptor(targetDesc) 为 truetargetDesc.[[Get]]undefined,那么
      1. 如果 trapResult 不是 undefined,抛出一个 TypeError 异常。
  10. 返回 trapResult
Note

Proxy 对象的 [[Get]] 强制执行以下不变量:

  • 如果目标对象上的对应属性是一个不可写、不可配置的自有数据属性,那么某属性 所报告的值必须与该对应目标对象属性的值相同。
  • 如果目标对象上的对应属性是一个不可配置的自有访问器属性,且其 [[Get]] 特 性为 undefined,那么该属性所报告的值必须是 undefined

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

The [[Set]] internal method of 一个 Proxy 异质对象 obj takes arguments propertyKey (一个属性键), value (一个 ECMAScript 语言值), and receiver (一个 ECMAScript 语言值) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. targetobj.[[ProxyTarget]]
  3. handlerobj.[[ProxyHandler]]
  4. 断言:handler 是一个 Object。
  5. trap 为 ? GetMethod(handler, "set")。
  6. 如果 trapundefined,那么
    1. 返回 ? target.[[Set]](propertyKey, value, receiver)
  7. booleanTrapResultToBoolean(? Call(trap, handler, « target, propertyKey, value, receiver »))。
  8. 如果 booleanTrapResultfalse,返回 false
  9. targetDesc 为 ? target.[[GetOwnProperty]](propertyKey)
  10. 如果 targetDesc 不是 undefinedtargetDesc.[[Configurable]]false,那么
    1. 如果 IsDataDescriptor(targetDesc) 为 truetargetDesc.[[Writable]]false,那么
      1. 如果 SameValue(value, targetDesc.[[Value]]) 为 false,抛出一个 TypeError 异常。
    2. 如果 IsAccessorDescriptor(targetDesc) 为 true,那么
      1. 如果 targetDesc.[[Set]]undefined,抛出一个 TypeError 异常。
  11. 返回 true
Note

Proxy 对象的 [[Set]] 强制执行以下不变量:

  • [[Set]] 的结果是一个 Boolean 值。
  • 如果目标对象上的对应属性是一个不可写、不可配置的自有数据属性,则不能把该 属性的值更改为与目标对象对应属性值不同的值。
  • 如果目标对象上的对应属性是一个不可配置的自有访问器属性,且其 [[Set]] 特 性为 undefined,则不能设置该属性的值。

10.5.10 [[Delete]] ( propertyKey )

The [[Delete]] internal method of 一个 Proxy 异质对象 obj takes argument propertyKey (一个属性键) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. targetobj.[[ProxyTarget]]
  3. handlerobj.[[ProxyHandler]]
  4. 断言:handler 是一个 Object。
  5. trap 为 ? GetMethod(handler, "deleteProperty")。
  6. 如果 trapundefined,那么
    1. 返回 ? target.[[Delete]](propertyKey)
  7. booleanTrapResultToBoolean(? Call(trap, handler, « target, propertyKey »))。
  8. 如果 booleanTrapResultfalse,返回 false
  9. targetDesc 为 ? target.[[GetOwnProperty]](propertyKey)
  10. 如果 targetDescundefined,返回 true
  11. 如果 targetDesc.[[Configurable]]false,抛出一个 TypeError 异常。
  12. extensibleTarget 为 ? IsExtensible(target)。
  13. 如果 extensibleTargetfalse,抛出一个 TypeError 异常。
  14. 返回 true
Note

Proxy 对象的 [[Delete]] 强制执行以下不变量:

  • [[Delete]] 的结果是一个 Boolean 值。
  • 如果某个属性作为目标对象的一个不可配置自有属性存在,则不能将其报告为已删除。
  • 如果某个属性作为目标对象的一个自有属性存在且目标对象不可扩展,则不能将其 报告为已删除。

10.5.11 [[OwnPropertyKeys]] ( )

The [[OwnPropertyKeys]] internal method of 一个 Proxy 异质对象 obj takes no arguments and returns 要么是一个正常完成,包含一个属性键列表,要么是一个抛出完成. It performs the following steps when called:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. targetobj.[[ProxyTarget]]
  3. handlerobj.[[ProxyHandler]]
  4. 断言:handler 是一个 Object。
  5. trap 为 ? GetMethod(handler, "ownKeys")。
  6. 如果 trapundefined,那么
    1. 返回 ? target.[[OwnPropertyKeys]]()
  7. trapResultArray 为 ? Call(trap, handler, « target »)。
  8. trapResult 为 ? CreateListFromArrayLike(trapResultArray, property-key)。
  9. 如果 trapResult 包含任何重复项,抛出一个 TypeError 异常。
  10. extensibleTarget 为 ? IsExtensible(target)。
  11. targetKeys 为 ? target.[[OwnPropertyKeys]]()
  12. 断言:targetKeys 是一个属性键列表。
  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
Note

Proxy 对象的 [[OwnPropertyKeys]] 强制执行以下不变量:

  • [[OwnPropertyKeys]] 的结果是一个 List
  • 返回的 List 不包含重复项。
  • 返回的 List 的每个元素都是一个属性键
  • 结果 List 必须包含目标对象所有不可配置自有属性的键。
  • 如果目标对象不可扩展,则结果 List 必须包含目标对象所有自有属性的键,而且 不能包含任何其他值。

10.5.12 [[Call]] ( thisArgument, argumentsList )

The [[Call]] internal method of 一个 Proxy 异质对象 obj takes arguments thisArgument (一个 ECMAScript 语言值) and argumentsList (一个 ECMAScript 语言值列表) and returns 要么是一个正常完成,包含一个 ECMAScript 语言值,要么是一个抛出完成. It performs the following steps when called:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. targetobj.[[ProxyTarget]]
  3. handlerobj.[[ProxyHandler]]
  4. 断言:handler 是一个 Object。
  5. trap 为 ? GetMethod(handler, "apply")。
  6. 如果 trapundefined,那么
    1. 返回 ? Call(target, thisArgument, argumentsList)。
  7. argArrayCreateArrayFromList(argumentsList)。
  8. 返回 ? Call(trap, handler, « target, thisArgument, argArray »)。
Note

只有当 [[ProxyTarget]] 内部槽的初始值是一个具有 [[Call]] 内部方法的对象 时,Proxy 异质对象才具有 [[Call]] 内部方法。

10.5.13 [[Construct]] ( argumentsList, newTarget )

The [[Construct]] internal method of 一个 Proxy 异质对象 obj takes arguments argumentsList (一个 ECMAScript 语言值列表) and newTarget (一个构造器) and returns 要么是一个正常完成,包含一个 Object,要么是一个抛出完成. It performs the following steps when called:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. targetobj.[[ProxyTarget]]
  3. 断言:IsConstructor(target) 为 true
  4. handlerobj.[[ProxyHandler]]
  5. 断言:handler 是一个 Object。
  6. trap 为 ? GetMethod(handler, "construct")。
  7. 如果 trapundefined,那么
    1. 返回 ? Construct(target, argumentsList, newTarget)。
  8. argArrayCreateArrayFromList(argumentsList)。
  9. newObj 为 ? Call(trap, handler, « target, argArray, newTarget »)。
  10. 如果 newObj 不是一个 Object,抛出一个 TypeError 异常。
  11. 返回 newObj
Note 1

只有当 [[ProxyTarget]] 内部槽的初始值是一个具有 [[Construct]] 内部方法的 对象时,Proxy 异质对象才具有 [[Construct]] 内部方法。

Note 2

Proxy 对象的 [[Construct]] 强制执行以下不变量:

  • [[Construct]] 的结果必须是一个 Object。

10.5.14 ValidateNonRevokedProxy ( proxy )

The abstract operation ValidateNonRevokedProxy takes argument proxy (一个 Proxy 异质对象) and returns 要么是一个正常完成,包含 unused,要么是一个抛出完成. 如果 proxy 已被撤销,则它会抛出一个 TypeError 异常。 It performs the following steps when called:

  1. 如果 proxy.[[ProxyTarget]]null,抛出一个 TypeError 异常。
  2. 断言:proxy.[[ProxyHandler]] 不是 null
  3. 返回 unused

10.5.15 ProxyCreate ( target, handler )

The abstract operation ProxyCreate takes arguments target (一个 ECMAScript 语言值) and handler (一个 ECMAScript 语言值) and returns 要么是一个正常完成,包含一个 Proxy 异质对象,要么是一个抛出完成. 它用于规定新 Proxy 对象的创建。 It performs the following steps when called:

  1. 如果 target 不是一个 Object,抛出一个 TypeError 异常。
  2. 如果 handler 不是一个 Object,抛出一个 TypeError 异常。
  3. proxyMakeBasicObject[[ProxyHandler]], [[ProxyTarget]] »)。
  4. proxy 的基本内部方法(除 [[Call]][[Construct]] 之外)设为 10.5 中规定的定义。
  5. 如果 IsCallable(target) 为 true,那么
    1. proxy.[[Call]] 设为 10.5.12 中规定的内容。
    2. 如果 IsConstructor(target) 为 true,那么
      1. proxy.[[Construct]] 设为 10.5.13 中规定的内容。
  6. proxy.[[ProxyTarget]] 设为 target
  7. proxy.[[ProxyHandler]] 设为 handler
  8. 返回 proxy

11 ECMAScript 语言:源文本

11.1 源文本

语法

SourceCharacter :: 任意 Unicode 码点

ECMAScript 源文本是一个 Unicode 码点序列。所有从 U+0000 到 U+10FFFF 的 Unicode 码点值,包括代理码点,只要被 ECMAScript 文法允许,都可 以出现在 ECMAScript 源文本中。用于存储和交换 ECMAScript 源文本的实际编码方式 与本规范无关。无论外部源文本使用何种编码,符合规范的 ECMAScript 实现都会像处理 一个等价的 SourceCharacter 值序列那样处理源文本,其中每个 SourceCharacter 都是一个 Unicode 码点。符合规范的 ECMAScript 实现不要求对源文本执行任何规范化, 也不要求表现得像它们执行了源文本规范化一样。

组合字符序列的各个组成部分会被视为单独的 Unicode 码点,尽管用户可能会将整 个序列视为一个单一字符。

Note

在字符串字面量、正则表达式字面量、模板字面量和标识符中,任何 Unicode 码点 也都可以使用显式表示码点数值的 Unicode 转义序列来表示。在注释内部,这样的转 义序列会被当作注释的一部分而实际上被忽略。

ECMAScript 在 Unicode 转义序列的行为上不同于 Java 编程语言。例如,在 Java 程序中,如果 Unicode 转义序列 \u000A 出现在单行注释中,它会被解释为一个行 终止符(Unicode 码点 U+000A 是 LINE FEED (LF)),因此下一个码点就不再属于该 注释。类似地,如果 Unicode 转义序列 \u000A 出现在 Java 程序的字符串字面量 中,它同样会被解释为一个行终止符,而行终止符不允许出现在字符串字面量中——必须 写成 \n 而不是 \u000A,才能使 LINE FEED (LF) 成为字符串字面量值的一部 分。在 ECMAScript 程序中,出现在注释中的 Unicode 转义序列永远不会被解释,因此 不可能促成注释的终结。类似地,出现在 ECMAScript 程序字符串字面量中的 Unicode 转义序列总是构成该字面量的一部分,绝不会被解释为行终止符,也不会被解释为可能 终止字符串字面量的码点。

11.1.1 Static Semantics: UTF16EncodeCodePoint ( cp )

The abstract operation UTF16EncodeCodePoint takes argument cp (一个 Unicode 码点) and returns 一个 String. It performs the following steps when called:

  1. 断言:0 ≤ cp ≤ 0x10FFFF。
  2. 如果 cp ≤ 0xFFFF,返回一个 String 值,该值由数值等于 cp 的码元构成。
  3. cu1 为一个码元,其数值为 floor((cp - 0x10000) / 0x400) + 0xD800。
  4. cu2 为一个码元,其数值为 ((cp - 0x10000) modulo 0x400) + 0xDC00。
  5. 返回 cu1cu2 的字符串串接结果。

11.1.2 Static Semantics: CodePointsToString ( text )

The abstract operation CodePointsToString takes argument text (一个 Unicode 码点序列) and returns 一个 String. 它将 text 转换为一个 String 值,如 6.1.4 中所述。 It performs the following steps when called:

  1. result 为空字符串。
  2. 对于 text 中的每个码点 cp,执行
    1. result 设为 resultUTF16EncodeCodePoint(cp) 的字符串串接结果。
  3. 返回 result

11.1.3 Static Semantics: UTF16SurrogatePairToCodePoint ( lead, trail )

The abstract operation UTF16SurrogatePairToCodePoint takes arguments lead (一个码元) and trail (一个码元) and returns 一个码点. 构成一个 UTF-16 代理对的两个码元会被转换为一个码点。 It performs the following steps when called:

  1. 断言:lead 是一个前导代理项,且 trail 是一个尾随代理项。
  2. cp 为 (lead - 0xD800) × 0x400 + (trail - 0xDC00) + 0x10000。
  3. 返回码点 cp

11.1.4 Static Semantics: CodePointAt ( string, position )

The abstract operation CodePointAt takes arguments string (一个 String) and position (一个非负整数) and returns 一个 Record,具有字段 [[CodePoint]](一个码点)、[[CodeUnitCount]](一个正整数)和 [[IsUnpairedSurrogate]](一个 Boolean). 它将 string 解释为一个 UTF-16 编码的码点序列,如 6.1.4 中所述,并从索引为 position 的码元开始读取一个单独的码点。 It performs the following steps when called:

  1. sizestring 的长度。
  2. 断言:position ≥ 0 且 position < size
  3. firststring 中索引为 position 的码元。
  4. cp 为一个码点,其数值等于 first 的数值。
  5. 如果 first 既不是前导代理项也不是尾随代理项,那么
    1. 返回 Record { [[CodePoint]]: cp, [[CodeUnitCount]]: 1, [[IsUnpairedSurrogate]]: false }。
  6. 如果 first 是一个尾随代理项,或者 position + 1 = size,那么
    1. 返回 Record { [[CodePoint]]: cp, [[CodeUnitCount]]: 1, [[IsUnpairedSurrogate]]: true }。
  7. secondstring 中索引为 position + 1 的码元。
  8. 如果 second 不是尾随代理项,那么
    1. 返回 Record { [[CodePoint]]: cp, [[CodeUnitCount]]: 1, [[IsUnpairedSurrogate]]: true }。
  9. cp 设为 UTF16SurrogatePairToCodePoint(first, second)。
  10. 返回 Record { [[CodePoint]]: cp, [[CodeUnitCount]]: 2, [[IsUnpairedSurrogate]]: false }。

11.1.5 Static Semantics: StringToCodePoints ( string )

The abstract operation StringToCodePoints takes argument string (一个 String) and returns 一个码点列表. 它返回将 string 按照 6.1.4 中所述解释为 UTF-16 编码 Unicode 文本后所得的 Unicode 码点序列。 It performs the following steps when called:

  1. codePoints 为一个新的空列表。
  2. sizestring 的长度。
  3. position 为 0。
  4. 重复,当 position < size 时,
    1. cpCodePointAt(string, position)。
    2. cp.[[CodePoint]] 追加到 codePoints
    3. position 设为 position + cp.[[CodeUnitCount]]
  5. 返回 codePoints

11.1.6 Static Semantics: ParseText ( sourceText, goalSymbol )

The abstract operation ParseText takes arguments sourceText (一个 String 或一个 Unicode 码点序列) and goalSymbol (ECMAScript 文法之一中的一个非终结符) and returns 一个 Parse Node 或一个非空的 SyntaxError 对象列表. It performs the following steps when called:

  1. 如果 sourceText 是一个 String,则将 sourceText 设为 StringToCodePoints(sourceText)。
  2. 尝试使用 goalSymbol 作为目标符号来解析 sourceText,并分析解析结果是否存在任何早期错误条件。解析和早期错误检测可以按照实现定义的方式交错进行。
  3. 如果解析成功且未发现早期错误,则返回解析所得语法树根部的 Parse Node(即 goalSymbol 的一个实例)。
  4. 返回一个由一个或多个 SyntaxError 对象构成的列表,用来表示解析错误和/或早期错误。如果存在多个解析错误或早期错误,则列表中错误对象的数量和顺序由实现定义,但至少必须存在一个。
Note 1

设想某段文本在某个位置具有一个早期错误,而在更靠后的某个位置还有一个语法错 误。一个先执行解析遍历、再执行早期错误遍历的实现,可能会报告该语法错误,并且 不再继续到早期错误遍历。一个将这两项活动交错进行的实现,可能会报告该早期错 误,并且不再继续查找语法错误。第三种实现则可能会报告这两种错误。所有这些行为 都是符合规范的。

Note 2

另见 17 条。

11.2 源代码的类型

ECMAScript 代码共有四种类型:

Note 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) 和 AsyncGeneratorFunction 构造器27.4.1.1)的参数。

Note 2

BindingIdentifier 包含在函数代码中的实际效果是:对于函数体中包含 "use strict" 指令的函数,其名称对应的 BindingIdentifier 会应用严格模式代 码的早期错误规则,即使外围代码不是严格模式代码也是如此。

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 指令。不过,如果发生这种情况,实现可以 发出警告。

Note

指令序言中的 ExpressionStatement 会在对其所在产生式求值期间按正常方式 求值。实现可以为那些不是 Use Strict 指令、但出现在指令序言中的 ExpressionStatement 定义特定于实现的含义。如果存在适当的通知机制,那么当 实现遇到一个出现在指令序言中、既不是 Use Strict 指令也没有被实现赋予特定含义 的 ExpressionStatement 时,应当发出警告。

11.2.2 严格模式代码

ECMAScript 语法单元可以使用非受限或严格模式的语法和语义来处理 (4.3.2)。在以下情 况下,代码会被解释为严格模式代码

不是严格模式代码的 ECMAScript 代码称为 非严格代码

11.2.2.1 Static Semantics: IsStrict ( node )

The abstract operation IsStrict takes argument node (一个 Parse Node) and returns 一个 Boolean. It performs the following steps when called:

  1. 如果 node匹配的源文本严格模式代码,返回 true
  2. 返回 false

11.2.3 非 ECMAScript 函数

ECMAScript 实现可以支持对某些函数异质对象进行求值,这些对象的求值行为用宿 主定义的某种可执行代码形式表达,而非 ECMAScript 源文本。从会调用这类函数对象 或被这类函数对象调用的 ECMAScript 代码视角来看,一个函数对象是在 ECMAScript 代码中定义的,还是一个内建函数,是不可观察的。

12 ECMAScript 语言:词法文法

ECMAScript ScriptModule 的源文本首先会被转换为一系列输入元素, 这些输入元素可以是记号、行终止符、注释或空白。源文本从左到右扫描, 每次反复取尽可能长的码点序列作为下一个输入元素。

在若干情形下,词法输入元素的识别会依赖于消费这些输入元素的语法文法上下文。 这就要求词法文法具有多个目标符号InputElementHashbangOrRegExp 目标用 于 ScriptModule 的起始位置。InputElementRegExpOrTemplateTail 目标用于那些允许 RegularExpressionLiteralTemplateMiddleTemplateTail 的语法文法上下文。InputElementRegExp 目标符号用于所有允 许 RegularExpressionLiteral 但既不允许 TemplateMiddle 也不允许 TemplateTail 的语法文法上下文。InputElementTemplateTail 目标用于所 有允许 TemplateMiddleTemplateTail 但不允许 RegularExpressionLiteral 的语法文法上下文。在所有其他上下文中, InputElementDiv 被用作词法目标符号

Note

使用多个词法目标可确保不存在会影响自动分号插入的词法歧义。例如,不存在同 时允许前导除法或除法赋值,以及前导 RegularExpressionLiteral 的语法文法 上下文。这一点不会受分号插入影响(见 12.10);在如 下示例中:

a = b
/hi/g.exec(c).map(d);

其中,在 LineTerminator 之后第一个非空白、非注释的码点是 U+002F (SOLIDUS),并且语法上下文允许除法或除法赋值,因此不会在该 LineTerminator 处插入分号。也就是说,上面的示例会按与下列代码相同的方 式解释:

a = b / hi / g.exec(c).map(d);

语法

InputElementDiv :: WhiteSpace LineTerminator Comment CommonToken DivPunctuator RightBracePunctuator InputElementRegExp :: WhiteSpace LineTerminator Comment CommonToken RightBracePunctuator RegularExpressionLiteral InputElementRegExpOrTemplateTail :: WhiteSpace LineTerminator Comment CommonToken RegularExpressionLiteral TemplateSubstitutionTail InputElementTemplateTail :: WhiteSpace LineTerminator Comment CommonToken DivPunctuator TemplateSubstitutionTail InputElementHashbangOrRegExp :: WhiteSpace LineTerminator Comment CommonToken HashbangComment RegularExpressionLiteral

12.1 Unicode 格式控制字符

Unicode 格式控制字符(即 Unicode 字符数据库中“Cf”类别的字符,例如 LEFT-TO-RIGHT MARK 或 RIGHT-TO-LEFT MARK)是控制码,用于在缺少更高层协 议(如标记语言)时控制一段文本的格式。

允许源文本中出现格式控制字符有助于编辑和显示。所有格式控制字符都可用于注 释内部,以及字符串字面量、模板字面量和正则表达式字面量内部。

U+FEFF(ZERO WIDTH NO-BREAK SPACE)是一种格式控制字符,主要用于文本开 头,将其标记为 Unicode,并允许检测文本的编码和字节序。用于此目的的 <ZWNBSP> 字符有时也可能出现在文本开始之后,例如作为文件拼接的结果。 在 ECMAScript 源文本中,位于注释、字符串字面量、模板字面量和正则表达式字 面量之外的 <ZWNBSP> 码点会被当作空白字符处理(见 12.2)。

12.2 空白

空白码点用于提升源文本可读性,并将记号(不可再分的词法单元)彼此分隔开 来,但除此之外并无意义。空白码点可以出现在任意两个记号之间,也可以出现在输 入的开头或结尾。空白码点可以出现在 StringLiteralRegularExpressionLiteralTemplateTemplateSubstitutionTail 内部,在这些地方它们被视为有意义的码点,并构成字面量值的一部分。它们也可以 出现在 Comment 内部,但不能出现在任何其他种类的记号内部。

ECMAScript 的空白码点列于 Table 30

Table 30: 空白码点
码点 名称 缩写
U+0009 CHARACTER TABULATION <TAB>
U+000B LINE TABULATION <VT>
U+000C FORM FEED (FF) <FF>
U+FEFF ZERO WIDTH NO-BREAK SPACE <ZWNBSP>
“Space_Separator” 一般类别中的任意码点 <USP>
Note 1

U+0020(SPACE)和 U+00A0(NO-BREAK SPACE)码点属于 <USP> 的一部 分。

Note 2

Table 30 中列出的码点之外,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 的行终止符码点列于 Table 31

Table 31: 行终止符码点
码点 Unicode 名称 缩写
U+000A LINE FEED (LF) <LF>
U+000D CARRIAGE RETURN (CR) <CR>
U+2028 LINE SEPARATOR <LS>
U+2029 PARAGRAPH SEPARATOR <PS>

只有 Table 31 中的 Unicode 码点会被视为行终止符。其他换行或断行的 Unicode 码点不会被 视为行终止符;如果它们满足 Table 30 中列出的要求,则会被视为空白。序列 <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 Note

DivPunctuatorRegularExpressionLiteralRightBracePunctuatorTemplateSubstitutionTail 产生式会派生出未包含在 CommonToken 产生式中 的额外记号。

12.7 名称和关键字

IdentifierNameReservedWord 是按照 Unicode Standard Annex #31 《Identifier and Pattern Syntax》中给出的默认标识符语法解释的记号,但做了少 量修改。ReservedWordIdentifierName 的一个枚举子集。语法文法将 Identifier 定义为一个不是 ReservedWordIdentifierName。Unicode 标识符文法基于 Unicode 标准规定的字符属性。Unicode 标准最新版本中指定类别内 的 Unicode 码点,必须被所有符合规范的 ECMAScript 实现按这些类别处理。 ECMAScript 实现也可以识别 Unicode 标准后续版本中定义的标识符码点。

Note 1

本标准规定了特定的码点补充:U+0024(DOLLAR SIGN)和 U+005F (LOW LINE)允许出现在 IdentifierName 的任意位置。

语法

PrivateIdentifier :: # IdentifierName IdentifierName :: IdentifierStart IdentifierName IdentifierPart IdentifierStart :: IdentifierStartChar \ UnicodeEscapeSequence IdentifierPart :: IdentifierPartChar \ UnicodeEscapeSequence IdentifierStartChar :: UnicodeIDStart $ _ IdentifierPartChar :: UnicodeIDContinue $ AsciiLetter :: one of a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z UnicodeIDStart :: 任何具有 Unicode 属性 “ID_Start” 的 Unicode 码点 UnicodeIDContinue :: 任何具有 Unicode 属性 “ID_Continue” 的 Unicode 码点

非终结符 UnicodeEscapeSequence 的定义见 12.9.4

Note 2

非终结符 IdentifierPart 通过 UnicodeIDContinue 派生 _

Note 3

具有 Unicode 属性 “ID_Start” 和 “ID_Continue” 的码点集合,分别包 含具有 Unicode 属性 “Other_ID_Start” 和 “Other_ID_Continue” 的码点。

12.7.1 标识符名称

IdentifierName 中允许使用 Unicode 转义序列,此时它们会贡献一个单独 的 Unicode 码点,其值等于该 UnicodeEscapeSequenceIdentifierCodePoint。位于 UnicodeEscapeSequence 之前的 \ 不贡献任 何码点。UnicodeEscapeSequence 不能用于向一个原本无效的 IdentifierName 贡献码点。换言之,如果将一个 \ UnicodeEscapeSequence 序列替换为它所贡献的 SourceCharacter,结果必 须仍然是一个有效的 IdentifierName,并且它具有与原始 IdentifierName 完全相同的 SourceCharacter 元素序列。本规范中对 IdentifierName 的所有解释都基于其实际码点,而不考虑某个特定码点是否是 通过转义序列贡献的。

根据 Unicode 标准,两个规范等价的 IdentifierName相 等,除非在替换每个 UnicodeEscapeSequence 之后,它们由完全相同的码点序列 表示。

12.7.1.1 Static Semantics: 早期错误

IdentifierStart :: \ UnicodeEscapeSequence IdentifierPart :: \ UnicodeEscapeSequence

12.7.1.2 Static Semantics: IdentifierCodePoints

The syntax-directed operation IdentifierCodePoints takes no arguments and returns 一个码点列表. It is defined piecewise over the following productions:

IdentifierName :: IdentifierStart
  1. cpIdentifierStartIdentifierCodePoint
  2. 返回 « cp »。
IdentifierName :: IdentifierName IdentifierPart
  1. cps 为已派生的 IdentifierNameIdentifierCodePoints
  2. cpIdentifierPartIdentifierCodePoint
  3. 返回 cps 与 « cp » 的列表串接。

12.7.1.3 Static Semantics: IdentifierCodePoint

The syntax-directed operation IdentifierCodePoint takes no arguments and returns 一个码点. It is defined piecewise over the following productions:

IdentifierStart :: IdentifierStartChar
  1. 返回 IdentifierStartChar 所匹配的码点。
IdentifierPart :: IdentifierPartChar
  1. 返回 IdentifierPartChar 所匹配的码点。
UnicodeEscapeSequence :: u Hex4Digits
  1. 返回其数值等于 Hex4Digits 的 MV 的码点。
UnicodeEscapeSequence :: u{ CodePoint }
  1. 返回其数值等于 CodePoint 的 MV 的码点。

12.7.2 关键字和保留字

关键字是一个匹配 IdentifierName 的记 号,但同时还具有语法用途;也就是说,它会以字面形式(使用 fixed width 字体)出现在某个语法产生式中。ECMAScript 的关键字包括 ifwhileasyncawait 以及许多其他关键字。

保留字是一个不能用作标识符的 IdentifierName。许多关键字是保留字,但有些不是,还有些只在特定上下文中 才是保留的。ifwhile 是保留字。await 只在 async 函数和模块内部 保留。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 Note 1

根据 5.1.5,文法中的关 键字匹配特定 SourceCharacter 元素的字面序列。关键字中的码点不能用 \ UnicodeEscapeSequence 来表示。

IdentifierName 可以包含 \ UnicodeEscapeSequence,但不能通过 将变量名 "else" 写成 els\u{65} 来声明变量。位于 13.1.1早期错误规则会排除那些具有与保留字相同 StringValue 的标识符。

Note 2

enum 目前在本规范中并未用作关键字。它是一个未来保留字, 为将来语言扩展中作为关键字使用而预留。

同样地,implementsinterfacepackageprivateprotectedpublic严格模式代码中也是未来保留字。

Note 3

argumentseval 这两个名称不是关键字,但它们在严格模式代码中 受到某些限制。见 13.1.18.6.415.2.115.5.115.6.115.8.1

12.8 标点符

语法

Punctuator :: OptionalChainingPunctuator OtherPunctuator OptionalChainingPunctuator :: ?. [lookahead ∉ DecimalDigit] OtherPunctuator :: one of { ( ) [ ] . ... ; , < > <= >= == != === !== + - * % ** ++ -- << >> >>> & | ^ ! ~ && || ?? ? : = += -= *= %= **= <<= >>= >>>= &= |= ^= &&= ||= ??= => DivPunctuator :: / /= RightBracePunctuator :: }

12.9 字面量

12.9.1 空字面量

语法

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

Note

例如:3in 是错误,而不是两个输入元素 3in

12.9.3.1 Static Semantics: 早期错误

NumericLiteral :: LegacyOctalIntegerLiteral DecimalIntegerLiteral :: NonOctalDecimalIntegerLiteral
  • 如果 IsStrict(this production) 为 true,则是语法错误。
Note
非严格代码中,此语法属于遗留语法。

12.9.3.2 Static Semantics: MV

数值字面量表示一个 Number 类型BigInt 类型的值。

12.9.3.3 Static Semantics: NumericValue

The syntax-directed operation NumericValue takes no arguments and returns 一个 Number 或一个 BigInt. It is defined piecewise over the following productions:

NumericLiteral :: DecimalLiteral
  1. 返回 RoundMVResult(MV of DecimalLiteral)。
NumericLiteral :: NonDecimalIntegerLiteral
  1. 返回 𝔽(MV of NonDecimalIntegerLiteral)。
NumericLiteral :: LegacyOctalIntegerLiteral
  1. 返回 𝔽(MV of LegacyOctalIntegerLiteral)。
NumericLiteral :: NonDecimalIntegerLiteral BigIntLiteralSuffix
  1. 返回 NonDecimalIntegerLiteral 的 MV 所对应的 BigInt 值
DecimalBigIntegerLiteral :: 0 BigIntLiteralSuffix
  1. 返回 0
DecimalBigIntegerLiteral :: NonZeroDigit BigIntLiteralSuffix
  1. 返回 NonZeroDigit 的 MV 所对应的 BigInt 值
DecimalBigIntegerLiteral :: NonZeroDigit DecimalDigits BigIntLiteralSuffix NonZeroDigit NumericLiteralSeparator DecimalDigits BigIntLiteralSuffix
  1. nDecimalDigits 中码点的个数,不包括所有 NumericLiteralSeparator 的出现。
  2. mv 为(NonZeroDigit 的 MV × 10n)加上 DecimalDigits 的 MV。
  3. 返回 (mv)。

12.9.4 字符串字面量

Note 1

字符串字面量是由单引号或双引号包围的 0 个或多个 Unicode 码点。Unicode 码点也可以由转义序列表示。除闭合引号码点、U+005C(REVERSE SOLIDUS)、 U+000D(CARRIAGE RETURN)和 U+000A(LINE FEED)之外,所有码点都可以在 字符串字面量中直接出现。任意码点都可以以转义序列形式出现。字符串字面量求 值为 ECMAScript String 值。在生成这些 String 值时,Unicode 码点会按照 11.1.1 中定义的方式进行 UTF-16 编码。属于基本多文种平面的码点被编码为字符串的一 个码元元素。所有其他码点被编码为字符串的两个码元元素。

语法

StringLiteral :: " DoubleStringCharactersopt " ' SingleStringCharactersopt ' DoubleStringCharacters :: DoubleStringCharacter DoubleStringCharactersopt SingleStringCharacters :: SingleStringCharacter SingleStringCharactersopt DoubleStringCharacter :: SourceCharacter but not one of " or \ or LineTerminator <LS> <PS> \ EscapeSequence LineContinuation SingleStringCharacter :: SourceCharacter but not one of ' or \ or LineTerminator <LS> <PS> \ EscapeSequence LineContinuation LineContinuation :: \ LineTerminatorSequence EscapeSequence :: CharacterEscapeSequence 0 [lookahead ∉ DecimalDigit] LegacyOctalEscapeSequence NonOctalDecimalEscapeSequence HexEscapeSequence UnicodeEscapeSequence CharacterEscapeSequence :: SingleEscapeCharacter NonEscapeCharacter SingleEscapeCharacter :: one of ' " \ b f n r t v NonEscapeCharacter :: SourceCharacter but not one of EscapeCharacter or LineTerminator EscapeCharacter :: SingleEscapeCharacter DecimalDigit x u LegacyOctalEscapeSequence :: 0 [lookahead ∈ { 8, 9 }] NonZeroOctalDigit [lookahead ∉ OctalDigit] ZeroToThree OctalDigit [lookahead ∉ OctalDigit] FourToSeven OctalDigit ZeroToThree OctalDigit OctalDigit NonZeroOctalDigit :: OctalDigit but not 0 ZeroToThree :: one of 0 1 2 3 FourToSeven :: one of 4 5 6 7 NonOctalDecimalEscapeSequence :: one of 8 9 HexEscapeSequence :: x HexDigit HexDigit UnicodeEscapeSequence :: u Hex4Digits u{ CodePoint } Hex4Digits :: HexDigit HexDigit HexDigit HexDigit

非终结符 HexDigit 的定义见 12.9.3SourceCharacter 定义见 11.1

Note 2

<LF> 和 <CR> 不能出现在字符串字面量中,除非它们作为 LineContinuation 的一部分,以产生空码点序列。要将其中任意一个包含进字 符串字面量的 String 值中,正确做法是使用诸如 \n\u000A 这样的 转义序列。

12.9.4.1 Static Semantics: 早期错误

EscapeSequence :: LegacyOctalEscapeSequence NonOctalDecimalEscapeSequence
  • 如果 IsStrict(this production) 为 true,则是语法错误。
Note 1
非严格代码中,此语法属于遗留语法。
Note 2

字符串字面量有可能出现在 Use Strict Directive 之前,而该指令会使外 层代码进入 严格模式, 实现必须注意对这类字面量执行上述规则。例如,以下源文本包含一个语法错误:

function invalid() { "\7"; "use strict"; }

12.9.4.2 Static Semantics: SV

The syntax-directed operation SV takes no arguments and returns 一个 String.

字符串字面量表示一个 String 类型的值。SV 通过对字符串字面量的各个部 分递归应用,来为字符串字面量生成 String 值。在这一过程中,字符串字面量中 的某些 Unicode 码点会被解释为具有数学值,如下文或 12.9.3 中所描述。

Table 32: 字符串单字符转义序列
转义序列 码元值 Unicode 字符名称 符号
\b 0x0008 BACKSPACE <BS>
\t 0x0009 CHARACTER TABULATION <HT>
\n 0x000A LINE FEED (LF) <LF>
\v 0x000B LINE TABULATION <VT>
\f 0x000C FORM FEED (FF) <FF>
\r 0x000D CARRIAGE RETURN (CR) <CR>
\" 0x0022 QUOTATION MARK "
\' 0x0027 APOSTROPHE '
\\ 0x005C REVERSE SOLIDUS \

12.9.4.3 Static Semantics: MV

12.9.5 正则表达式字面量

Note 1

正则表达式字面量是一种输入元素,每次对该字面量求值时,都会将其转换为一 个 RegExp 对象(见 22.2)。 程序中的两个正则表达式字面量即使内容完全相同,求值所得的正则表达式对象也永 远不会彼此 === 相等。RegExp 对象也可以在运行时通过 new RegExp 或以函 数方式调用 RegExp 构造器来创建(见 22.2.4)。

下面的产生式描述了正则表达式字面量的语法,并被输入元素扫描器用来查找正则 表达式字面量的结束位置。构成 RegularExpressionBodyRegularExpressionFlags 的源文本随后会再使用更严格的 ECMAScript 正则表 达式文法(22.2.1)重新解析。

实现可以扩展 22.2.1 中定义的 ECMAScript 正则表达式文法,但不得扩展下面定义的 RegularExpressionBodyRegularExpressionFlags 产生式,也不得扩展 这些产生式所使用的产生式。

语法

RegularExpressionLiteral :: / RegularExpressionBody / RegularExpressionFlags RegularExpressionBody :: RegularExpressionFirstChar RegularExpressionChars RegularExpressionChars :: [empty] RegularExpressionChars RegularExpressionChar RegularExpressionFirstChar :: RegularExpressionNonTerminator but not one of * or \ or / or [ RegularExpressionBackslashSequence RegularExpressionClass RegularExpressionChar :: RegularExpressionNonTerminator but not one of \ or / or [ RegularExpressionBackslashSequence RegularExpressionClass RegularExpressionBackslashSequence :: \ RegularExpressionNonTerminator RegularExpressionNonTerminator :: SourceCharacter but not LineTerminator RegularExpressionClass :: [ RegularExpressionClassChars ] RegularExpressionClassChars :: [empty] RegularExpressionClassChars RegularExpressionClassChar RegularExpressionClassChar :: RegularExpressionNonTerminator but not one of ] or \ RegularExpressionBackslashSequence RegularExpressionFlags :: [empty] RegularExpressionFlags IdentifierPartChar Note 2

正则表达式字面量不能为空;表示为空正则表达式字面量的码元序列 // 会启 动一个单行注释。要指定一个空正则表达式,请使用:/(?:)/

12.9.5.1 Static Semantics: BodyText

The syntax-directed operation BodyText takes no arguments and returns 源文本. It is defined piecewise over the following productions:

RegularExpressionLiteral :: / RegularExpressionBody / RegularExpressionFlags
  1. 返回被识别为 RegularExpressionBody 的源文本。

12.9.5.2 Static Semantics: FlagText

The syntax-directed operation FlagText takes no arguments and returns 源文本. It is defined piecewise over the following productions:

RegularExpressionLiteral :: / RegularExpressionBody / RegularExpressionFlags
  1. 返回被识别为 RegularExpressionFlags 的源文本。

12.9.6 模板字面量词法组成部分

语法

Template :: NoSubstitutionTemplate TemplateHead NoSubstitutionTemplate :: ` TemplateCharactersopt ` TemplateHead :: ` TemplateCharactersopt ${ TemplateSubstitutionTail :: TemplateMiddle TemplateTail TemplateMiddle :: } TemplateCharactersopt ${ TemplateTail :: } TemplateCharactersopt ` TemplateCharacters :: TemplateCharacter TemplateCharactersopt TemplateCharacter :: $ [lookahead ≠ {] \ TemplateEscapeSequence \ NotEscapeSequence LineContinuation LineTerminatorSequence SourceCharacter but not one of ` or \ or $ or LineTerminator TemplateEscapeSequence :: CharacterEscapeSequence 0 [lookahead ∉ DecimalDigit] HexEscapeSequence UnicodeEscapeSequence NotEscapeSequence :: 0 DecimalDigit DecimalDigit but not 0 x [lookahead ∉ HexDigit] x HexDigit [lookahead ∉ HexDigit] u [lookahead ∉ HexDigit] [lookahead ≠ {] u HexDigit [lookahead ∉ HexDigit] u HexDigit HexDigit [lookahead ∉ HexDigit] u HexDigit HexDigit HexDigit [lookahead ∉ HexDigit] u { [lookahead ∉ HexDigit] u { NotCodePoint [lookahead ∉ HexDigit] u { CodePoint [lookahead ∉ HexDigit] [lookahead ≠ }] NotCodePoint :: HexDigits[~Sep] but only if the MV of HexDigits > 0x10FFFF CodePoint :: HexDigits[~Sep] but only if the MV of HexDigits ≤ 0x10FFFF Note

TemplateSubstitutionTailInputElementTemplateTail 这一备选词法 目标使用。

12.9.6.1 Static Semantics: TV

The syntax-directed operation TV takes no arguments and returns 一个 String 或 undefined. 模板字面量组成部分会被 TV 解释为一个 String 类型的值。TV 用于构造模 板对象的带索引组成部分(通俗地说,就是模板值)。在 TV 中,转义序列会被替 换为该转义序列所表示的 Unicode 码点的 UTF-16 码元。

12.9.6.2 Static Semantics: TRV

The syntax-directed operation TRV takes no arguments and returns 一个 String. 模板字面量组成部分会被 TRV 解释为一个 String 类型的值。TRV 用于构造 模板对象的原始组成部分(通俗地说,就是模板原始值)。TRV 与 TV 类似,区别 在于,在 TRV 中,转义序列会按其在字面量中出现的形式解释。

Note

TV 排除了 LineContinuation 的码元,而 TRV 包含这些码元。 <CR><LF> 和 <CR> LineTerminatorSequence 都会被规范化为 <LF>,无论对 TV 还是 TRV 都如此。若要包含一个 <CR> 或 <CR><LF> 序列,则需要显式使用 TemplateEscapeSequence

12.10 自动分号插入

大多数 ECMAScript 语句和声明都必须以分号终止。这类分号总是可以显式写在 源文本中。不过,为了方便,在某些情况下,这类分号可以从源文本中省略。这些情 况通过以下方式描述:在这些情况下,分号会被自动插入源代码记号流中。

12.10.1 自动分号插入规则

在以下规则中,“token” 指的是使用当前词法目标符号、按照 12 中所述确定出的实际识别词法记号。

分号插入有三条基本规则:

  1. 当从左到右解析源文本时,遇到一个任何文法产生式都不允许的记号(称为 违规记号)时,如果满足下列一个或多个条件,则会在该违规记号之前 自动插入一个分号:

    • 该违规记号与前一个记号之间至少被一个 LineTerminator 分隔。
    • 该违规记号是 }
    • 前一个记号是 ),并且插入的分号会被解析为 do-while 语句 (14.7.2)的终止分号。
  2. 当从左到右解析源文本时,遇到记号输入流的结尾,并且解析器无法将输入记号流 解析为目标非终结符的单个实例时,则会在输入流末尾自动插入一个分号。
  3. 当从左到右解析源文本时,遇到一个被某个文法产生式允许的记号,但该产生式是 一个受限产生式,并且该记号将会成为该受限产生式中紧跟在标注 “[no LineTerminator here]” 之后的终结符或非终结符的第一个记号 (因此这样的记号被称为受限记号),而且该受限记号与前一个记号之间至少被一 个 LineTerminator 分隔,那么就会在该受限记号之前自动插入一个分号。

不过,对上述规则还有一个额外的优先条件:如果该分号插入后会被解析为空语 句,或者该分号会成为 for 语句头部中的两个分号之一(见 14.7.4),那么绝不会自动插入分号。

Note

文法中唯一的受限产生式如下:

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 语句中的 Expression,或 yield 表达式中的 AssignmentExpression,应与 returnthrowyield 记号位于 同一行起始。
  • breakcontinue 语句中的 LabelIdentifier 应与 breakcontinue 记号位于同一行。
  • 箭头函数参数的结尾与其 => 应位于同一行。
  • 位于异步函数或方法之前的 async 记号应与其后紧跟的记号位于同一行。

12.10.2 自动分号插入示例

本节为非规范性内容。

以下源代码

{ 1 2 } 3

不是一个有效的 ECMAScript 文法句子,即使应用自动分号插入规则也是如此。 相比之下,以下源代码

{ 1
2 } 3

同样不是一个有效的 ECMAScript 句子,但它会被自动分号插入转换为以下形 式:

{ 1
;2 ;} 3;

这就是一个有效的 ECMAScript 句子。

以下源代码

for (a; b
)

不是一个有效的 ECMAScript 句子,并且不会被自动分号插入修改,因为该分号 是 for 语句头部所必需的。自动分号插入绝不会插入 for 语句头部中的两个分 号之一。

以下源代码

return
a + b

会被自动分号插入转换为以下形式:

return;
a + b;
Note 1

表达式 a + b 不会被当作 return 语句要返回的值,因为一个 LineTerminator 将它与记号 return 分隔开了。

以下源代码

a = b
++c

会被自动分号插入转换为以下形式:

a = b;
++c;
Note 2

记号 ++ 不会被当作施加于变量 b 的后缀运算符,因为 b++ 之间出现了一个 LineTerminator

以下源代码

if (a > b)
else c = d

不是一个有效的 ECMAScript 句子,并且不会在 else 记号之前通过自动分号 插入进行修改,即使此处没有任何文法产生式适用,因为自动插入的分号将会被解析 为空语句。

以下源代码

a = b + c
(d + e).print()

不会被自动分号插入转换,因为第二行开始的带括号表达式可以被解释 为函数调用的参数列表:

a = b + c(d + e).print()

在赋值语句必须以左圆括号开头的情况下,程序员最好在前一条语句的末尾显式写 出分号,而不要依赖自动分号插入。

12.10.3 自动分号插入的有趣情形

本节为非规范性内容。

ECMAScript 程序可以通过依赖自动分号插入而采用一种几乎不写分号的风格。 正如上文所述,分号并不会在每一个换行处插入,自动分号插入还可能依赖跨越行终 止符的多个记号。

随着新的语法特性被加入 ECMAScript,可能还会增加新的文法产生式,从而导致 那些依赖于其前方自动分号插入的代码行在解析时落入不同的文法产生式。

就本节而言,如果一个自动分号插入案例中,分号是否会被插入取决于其前面的源 文本,那么该案例就被认为是有趣的。本节剩余部分描述了本版 ECMAScript 中若干 自动分号插入的有趣情形。

12.10.3.1 语句列表中的自动分号插入有趣情形

StatementList 中,许多 StatementListItem 都以分号结尾,而这些 分号可通过自动分号插入来省略。根据上述规则,在以表达式结尾的一行末尾,如果 下一行以下列任何一种内容开头,则需要一个分号:

  • 左圆括号((。如果没有分号,这两行会 一起被当作一个 CallExpression
  • 左方括号([。如果没有分号,这两行 会一起被当作属性访问,而不是 ArrayLiteralArrayAssignmentPattern
  • 模板字面量(`。如果没有分号,这两 行会一起被解释为一个带标签的 Template (13.3.11),其中前一个表 达式充当 MemberExpression
  • 一元 +-。如果没有分 号,这两行会一起被解释为相应二元运算符的一次使用。
  • RegExp 字面量。如果没有分号,这两行可能会被解析为 / MultiplicativeOperator,例如当该 RegExp 带有 flags 时。

12.10.3.2 自动分号插入与 “[no LineTerminator here]” 的情形

本节为非规范性内容。

ECMAScript 包含若干文法产生式,其中带有 “[no LineTerminator here]”。 这些产生式有时是用来在文法中实现可选操作数的一种方式。在这些位置引入一个 LineTerminator,将会通过使用不带该可选操作数的文法产生式,从而改变某段 源文本所对应的文法产生式。

本节剩余部分描述了本版 ECMAScript 中若干使用 “[no LineTerminator here]” 的产生式。

12.10.3.2.1 带有可选操作数且使用 “[no LineTerminator here]” 的文法产生式列表

13 ECMAScript 语言:表达式

13.1 标识符

语法

IdentifierReference[Yield, Await] : Identifier [~Yield] yield [~Await] await BindingIdentifier[Yield, Await] : Identifier yield await LabelIdentifier[Yield, Await] : Identifier [~Yield] yield [~Await] await Identifier : IdentifierName but not ReservedWord Note

在文法中,yieldawait 被允许作为 BindingIdentifier, 并在下方通过静态语义禁止,以避免在如下情形中发生自动分号插入

let
await 0;

13.1.1 Static Semantics: 早期错误

BindingIdentifier : Identifier IdentifierReference : yield BindingIdentifier : yield LabelIdentifier : yield
  • 如果 IsStrict(this production) 为 true,则是语法错误。
IdentifierReference : await BindingIdentifier : await LabelIdentifier : await BindingIdentifier[Yield, Await] : yield
  • 如果该产生式具有一个 [Yield] 参数,则是语法错误。
BindingIdentifier[Yield, Await] : await
  • 如果该产生式具有一个 [Await] 参数,则是语法错误。
IdentifierReference[Yield, Await] : Identifier BindingIdentifier[Yield, Await] : Identifier LabelIdentifier[Yield, Await] : Identifier
  • 如果该产生式具有一个 [Yield] 参数,并且 IdentifierStringValue"yield",则是语法错误。
  • 如果该产生式具有一个 [Await] 参数,并且 IdentifierStringValue"await",则是语法错误。
Identifier : IdentifierName but not ReservedWord Note

IdentifierNameStringValue 会将 IdentifierName 中的任意 Unicode 转义序列规范化,因此不能使用这类转义来书写一个码点序列与某个 ReservedWord 相同的 Identifier

13.1.2 Static Semantics: StringValue

The syntax-directed operation StringValue takes no arguments and returns 一个 String. It is defined piecewise over the following productions:

IdentifierName :: IdentifierStart IdentifierName IdentifierPart
  1. idTextUnescapedIdentifierNameIdentifierCodePoints
  2. 返回 CodePointsToString(idTextUnescaped)。
IdentifierReference : yield BindingIdentifier : yield LabelIdentifier : yield
  1. 返回 "yield"
IdentifierReference : await BindingIdentifier : await LabelIdentifier : await
  1. 返回 "await"
Identifier : IdentifierName but not ReservedWord
  1. 返回 IdentifierNameStringValue
PrivateIdentifier :: # IdentifierName
  1. 返回 0x0023(NUMBER SIGN)与 IdentifierNameStringValue 的字符串串接结果。
ModuleExportName : StringLiteral
  1. 返回 StringLiteralSV

13.1.3 Runtime Semantics: 求值

IdentifierReference : Identifier
  1. 返回 ? ResolveBinding(StringValue of Identifier)。
IdentifierReference : yield
  1. 返回 ? ResolveBinding("yield")。
IdentifierReference : await
  1. 返回 ? ResolveBinding("await")。
Note 1

IdentifierReference 求值的结果总是一个 Reference 类型的值。

Note 2

非严格代码中,关键字 yield 可以被用作标识符。对该 IdentifierReference 的求值会像它是一个 Identifier 一样解析 yield 的绑定。早期错误限制确保这类求值只会出现在非严格代码中。

13.2 主表达式

语法

PrimaryExpression[Yield, Await] : this IdentifierReference[?Yield, ?Await] Literal ArrayLiteral[?Yield, ?Await] ObjectLiteral[?Yield, ?Await] FunctionExpression ClassExpression[?Yield, ?Await] GeneratorExpression AsyncFunctionExpression AsyncGeneratorExpression RegularExpressionLiteral TemplateLiteral[?Yield, ?Await, ~Tagged] CoverParenthesizedExpressionAndArrowParameterList[?Yield, ?Await] CoverParenthesizedExpressionAndArrowParameterList[Yield, Await] : ( Expression[+In, ?Yield, ?Await] ) ( Expression[+In, ?Yield, ?Await] , ) ( ) ( ... BindingIdentifier[?Yield, ?Await] ) ( ... BindingPattern[?Yield, ?Await] ) ( Expression[+In, ?Yield, ?Await] , ... BindingIdentifier[?Yield, ?Await] ) ( Expression[+In, ?Yield, ?Await] , ... BindingPattern[?Yield, ?Await] )

补充语法

在处理如下产生式的一个实例时
PrimaryExpression[Yield, Await] : CoverParenthesizedExpressionAndArrowParameterList[?Yield, ?Await]
CoverParenthesizedExpressionAndArrowParameterList 的解释会使用如下文法加以细化:

ParenthesizedExpression[Yield, Await] : ( Expression[+In, ?Yield, ?Await] )

13.2.1 this 关键字

13.2.1.1 Runtime Semantics: 求值

PrimaryExpression : this
  1. 返回 ? ResolveThisBinding()。

13.2.2 标识符引用

有关 IdentifierReference,见 13.1

13.2.3 字面量

语法

Literal : NullLiteral BooleanLiteral NumericLiteral StringLiteral

13.2.3.1 Runtime Semantics: 求值

Literal : NullLiteral
  1. 返回 null
Literal : BooleanLiteral
  1. 如果 BooleanLiteral 是记号 false,返回 false
  2. 如果 BooleanLiteral 是记号 true,返回 true
Literal : NumericLiteral
  1. 返回按 12.9.3 中定义的 NumericLiteralNumericValue
Literal : StringLiteral
  1. 返回按 12.9.4.2 中定义的 StringLiteralSV

13.2.4 数组初始化器

Note

ArrayLiteral 是一种描述 Array 初始化的表达式,它使用方括号括起来的 0 个或多个表达式的列表来表示,其中每个表达式代表一个数组元素。这些元素不必 是字面量;每次对该数组初始化器求值时,它们都会被求值。

数组元素可以在元素列表的开头、中间或结尾被省略。每当元素列表中的一个逗号 前面没有 AssignmentExpression(即,位于开头的逗号,或者位于另一个逗号 之后的逗号),这个缺失的数组元素就会对 Array 的长度作出贡献,并增加后续元 素的索引。被省略的数组元素不会被定义。如果一个元素在数组末尾被省略,该元素 不会对 Array 的长度作出贡献。

语法

ArrayLiteral[Yield, Await] : [ Elisionopt ] [ ElementList[?Yield, ?Await] ] [ ElementList[?Yield, ?Await] , Elisionopt ] ElementList[Yield, Await] : Elisionopt AssignmentExpression[+In, ?Yield, ?Await] Elisionopt SpreadElement[?Yield, ?Await] ElementList[?Yield, ?Await] , Elisionopt AssignmentExpression[+In, ?Yield, ?Await] ElementList[?Yield, ?Await] , Elisionopt SpreadElement[?Yield, ?Await] Elision : , Elision , SpreadElement[Yield, Await] : ... AssignmentExpression[+In, ?Yield, ?Await]

13.2.4.1 Runtime Semantics: ArrayAccumulation

The syntax-directed operation ArrayAccumulation takes arguments array (一个 Array) and nextIndex (一个整数) and returns 要么是一个正常完成,包含一个整数,要么是一个突然完成. It is defined piecewise over the following productions:

Elision : ,
  1. lennextIndex + 1。
  2. 执行 ? Set(array, "length", 𝔽(len), true)。
  3. NOTE: 如果 len 超过 232 - 1,上一步会抛出异常。
  4. 返回 len
Elision : Elision ,
  1. 返回 ? 对 Elision 执行 ArrayAccumulation,并以 array 和 (nextIndex + 1) 为参数。
ElementList : Elisionopt AssignmentExpression
  1. 如果 Elision 存在,那么
    1. nextIndex 设为 ? 对 Elision 执行 ArrayAccumulation,并以 arraynextIndex 为参数。
  2. initResult 为 ? 对 AssignmentExpression 求值。
  3. initValue 为 ? GetValue(initResult)。
  4. 执行 ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(nextIndex)), initValue)。
  5. 返回 nextIndex + 1。
ElementList : Elisionopt SpreadElement
  1. 如果 Elision 存在,那么
    1. nextIndex 设为 ? 对 Elision 执行 ArrayAccumulation,并以 arraynextIndex 为参数。
  2. 返回 ? 对 SpreadElement 执行 ArrayAccumulation,并以 arraynextIndex 为参数。
ElementList : ElementList , Elisionopt AssignmentExpression
  1. nextIndex 设为 ? 对已派生的 ElementList 执行 ArrayAccumulation,并以 arraynextIndex 为参数。
  2. 如果 Elision 存在,那么
    1. nextIndex 设为 ? 对 Elision 执行 ArrayAccumulation,并以 arraynextIndex 为参数。
  3. initResult 为 ? 对 AssignmentExpression 求值。
  4. initValue 为 ? GetValue(initResult)。
  5. 执行 ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(nextIndex)), initValue)。
  6. 返回 nextIndex + 1。
ElementList : ElementList , Elisionopt SpreadElement
  1. nextIndex 设为 ? 对已派生的 ElementList 执行 ArrayAccumulation,并以 arraynextIndex 为参数。
  2. 如果 Elision 存在,那么
    1. nextIndex 设为 ? 对 Elision 执行 ArrayAccumulation,并以 arraynextIndex 为参数。
  3. 返回 ? 对 SpreadElement 执行 ArrayAccumulation,并以 arraynextIndex 为参数。
SpreadElement : ... AssignmentExpression
  1. spreadRef 为 ? 对 AssignmentExpression 求值。
  2. spreadObj 为 ? GetValue(spreadRef)。
  3. iteratorRecord 为 ? GetIterator(spreadObj, sync)。
  4. 重复,
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 nextdone,返回 nextIndex
    3. 执行 ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(nextIndex)), next)。
    4. nextIndex 设为 nextIndex + 1。
Note

使用 CreateDataPropertyOrThrow 是为了确保即使标准内建 Array 原型对象 已经被修改得无法通过 [[Set]] 创建新的自有属性,数组上仍然会定义自有属性。

13.2.4.2 Runtime Semantics: 求值

ArrayLiteral : [ Elisionopt ]
  1. array 为 ! ArrayCreate(0)。
  2. 如果 Elision 存在,那么
    1. 执行 ? 对 Elision 执行 ArrayAccumulation,并以 array 和 0 为参数。
  3. 返回 array
ArrayLiteral : [ ElementList ]
  1. array 为 ! ArrayCreate(0)。
  2. 执行 ? 对 ElementList 执行 ArrayAccumulation,并以 array 和 0 为参数。
  3. 返回 array
ArrayLiteral : [ ElementList , Elisionopt ]
  1. array 为 ! ArrayCreate(0)。
  2. nextIndex 为 ? 对 ElementList 执行 ArrayAccumulation,并以 array 和 0 为参数。
  3. 如果 Elision 存在,那么
    1. 执行 ? 对 Elision 执行 ArrayAccumulation,并以 arraynextIndex 为参数。
  4. 返回 array

13.2.5 对象初始化器

Note 1

对象初始化器是一种描述 Object 初始化的表达式,其书写形式类似字面量。它 是一个由 0 个或多个属性键及其相关联值所组成的列表,且被花括号包围。这些值 不必是字面量;每次对该对象初始化器求值时,它们都会被求值。

语法

ObjectLiteral[Yield, Await] : { } { PropertyDefinitionList[?Yield, ?Await] } { PropertyDefinitionList[?Yield, ?Await] , } PropertyDefinitionList[Yield, Await] : PropertyDefinition[?Yield, ?Await] PropertyDefinitionList[?Yield, ?Await] , PropertyDefinition[?Yield, ?Await] PropertyDefinition[Yield, Await] : IdentifierReference[?Yield, ?Await] CoverInitializedName[?Yield, ?Await] PropertyName[?Yield, ?Await] : AssignmentExpression[+In, ?Yield, ?Await] MethodDefinition[?Yield, ?Await] ... AssignmentExpression[+In, ?Yield, ?Await] PropertyName[Yield, Await] : LiteralPropertyName ComputedPropertyName[?Yield, ?Await] LiteralPropertyName : IdentifierName StringLiteral NumericLiteral ComputedPropertyName[Yield, Await] : [ AssignmentExpression[+In, ?Yield, ?Await] ] CoverInitializedName[Yield, Await] : IdentifierReference[?Yield, ?Await] Initializer[+In, ?Yield, ?Await] Initializer[In, Yield, Await] : = AssignmentExpression[?In, ?Yield, ?Await] Note 2

MethodDefinition 定义于 15.4

Note 3

在某些上下文中,ObjectLiteral 被用作更受限的次级文法的覆盖文法。 CoverInitializedName 产生式对于完整覆盖这些次级文法是必要的。然而, 使用这个产生式会在那些期望出现实际 ObjectLiteral 的普通上下文中导致一 个早期语法错误。

13.2.5.1 Static Semantics: 早期错误

PropertyDefinition : MethodDefinition

ObjectLiteral 产生式除了描述实际对象初始化器之外,还被用作 ObjectAssignmentPattern覆盖文法,并且可能会被识别为 CoverParenthesizedExpressionAndArrowParameterList 的一部分。当 ObjectLiteral 出现在要求 ObjectAssignmentPattern 的上下文中时,下 述早期错误规则不会被应用。此外,在初始解析 CoverParenthesizedExpressionAndArrowParameterListCoverCallExpressionAndAsyncArrowHead 时,也不会应用这些规则。

PropertyDefinition : CoverInitializedName
  • 如果有任何源文本被该产生式匹配,则是语法错误。
Note 1

该产生式存在是为了让 ObjectLiteral 能作为 ObjectAssignmentPattern覆盖文法。它不能出现在实际对象初始化器中。

ObjectLiteral : { PropertyDefinitionList } { PropertyDefinitionList , } Note 2

PropertyNameList 返回的列表不包括使用 ComputedPropertyName 定义的属性名

13.2.5.2 Static Semantics: IsComputedPropertyKey

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

PropertyName : LiteralPropertyName
  1. 返回 false
PropertyName : ComputedPropertyName
  1. 返回 true

13.2.5.3 Static Semantics: PropertyDefinitionNodes

The syntax-directed operation PropertyDefinitionNodes takes no arguments and returns 一个 Parse Node 列表. It is defined piecewise over the following productions:

ObjectLiteral : { }
  1. 返回一个新的空列表。
PropertyDefinitionList : PropertyDefinition
  1. 返回 « PropertyDefinition »。
PropertyDefinitionList : PropertyDefinitionList , PropertyDefinition
  1. head 为已派生的 PropertyDefinitionListPropertyDefinitionNodes
  2. 返回 head 与 « PropertyDefinition » 的列表串接。

13.2.5.4 Static Semantics: PropertyNameList

The syntax-directed operation PropertyNameList takes no arguments and returns 一个 String 列表. It is defined piecewise over the following productions:

PropertyDefinitionList : PropertyDefinition
  1. propNamePropertyDefinitionPropName
  2. 如果 propNameempty,返回一个新的空列表。
  3. 返回 « propName »。
PropertyDefinitionList : PropertyDefinitionList , PropertyDefinition
  1. listPropertyDefinitionListPropertyNameList
  2. propNamePropertyDefinitionPropName
  3. 如果 propNameempty,返回 list
  4. 返回 list 与 « propName » 的列表串接。

13.2.5.5 Runtime Semantics: 求值

ObjectLiteral : { }
  1. 返回 OrdinaryObjectCreate(%Object.prototype%)。
ObjectLiteral : { PropertyDefinitionList } { PropertyDefinitionList , }
  1. objOrdinaryObjectCreate(%Object.prototype%)。
  2. 执行 ? 对 PropertyDefinitionList 执行 PropertyDefinitionEvaluation,并以 obj 为参数。
  3. 返回 obj
LiteralPropertyName : IdentifierName
  1. 返回 IdentifierNameStringValue
LiteralPropertyName : StringLiteral
  1. 返回 StringLiteralSV
LiteralPropertyName : NumericLiteral
  1. nbrNumericLiteralNumericValue
  2. 返回 ! ToString(nbr)。
ComputedPropertyName : [ AssignmentExpression ]
  1. exprValue 为 ? 对 AssignmentExpression 求值。
  2. propName 为 ? GetValue(exprValue)。
  3. 返回 ? ToPropertyKey(propName)。

13.2.5.6 Runtime Semantics: PropertyDefinitionEvaluation

The syntax-directed operation PropertyDefinitionEvaluation takes argument object (一个 Object) and returns 要么是一个正常完成,包含 unused,要么是一个突然完成. It is defined piecewise over the following productions:

PropertyDefinitionList : PropertyDefinitionList , PropertyDefinition
  1. 执行 ? 对 PropertyDefinitionList 执行 PropertyDefinitionEvaluation,并以 object 为参数。
  2. 执行 ? 对 PropertyDefinition 执行 PropertyDefinitionEvaluation,并以 object 为参数。
  3. 返回 unused
PropertyDefinition : ... AssignmentExpression
  1. exprValue 为 ? 对 AssignmentExpression 求值。
  2. fromValue 为 ? GetValue(exprValue)。
  3. excludedNames 为一个新的空列表。
  4. 执行 ? CopyDataProperties(object, fromValue, excludedNames)。
  5. 返回 unused
PropertyDefinition : IdentifierReference
  1. propNameIdentifierReferenceStringValue
  2. exprValue 为 ? 对 IdentifierReference 求值。
  3. propValue 为 ? GetValue(exprValue)。
  4. 断言:object 是一个普通的、可扩展的对象,并且不具有不可配置属性。
  5. 执行 ! CreateDataPropertyOrThrow(object, propName, propValue)。
  6. 返回 unused
PropertyDefinition : PropertyName : AssignmentExpression
  1. propertyKey 为 ? 对 PropertyName 求值。
  2. 如果该 PropertyDefinition 包含于一个正为 ParseJSON 求值的 Script 中(见 ParseJSON 的步骤 6),那么
    1. isProtoSetterfalse
  3. 否则如果 propertyKey"__proto__",并且 PropertyNameIsComputedPropertyKeyfalse,那么
    1. isProtoSettertrue
  4. 否则,
    1. isProtoSetterfalse
  5. 如果 IsAnonymousFunctionDefinition(AssignmentExpression) 为 trueisProtoSetterfalse,那么
    1. propValue 为 ? 对 AssignmentExpression 执行 NamedEvaluation,并以 propertyKey 为参数。
  6. 否则,
    1. exprValueRef 为 ? 对 AssignmentExpression 求值。
    2. propValue 为 ? GetValue(exprValueRef)。
  7. 如果 isProtoSettertrue,那么
    1. 如果 propValue 是一个 Object 或 propValuenull,那么
      1. 执行 ! object.[[SetPrototypeOf]](propValue)
    2. 返回 unused
  8. 断言:object 是一个普通的、可扩展的对象,并且不具有不可配置属性。
  9. 执行 ! CreateDataPropertyOrThrow(object, propertyKey, propValue)。
  10. 返回 unused
PropertyDefinition : MethodDefinition
  1. 执行 ? 对 MethodDefinition 执行 MethodDefinitionEvaluation,并以 objecttrue 为参数。
  2. 返回 unused

13.2.6 函数定义表达式

有关 PrimaryExpression : FunctionExpression , 见 15.2

有关 PrimaryExpression : GeneratorExpression , 见 15.5

有关 PrimaryExpression : ClassExpression , 见 15.7

有关 PrimaryExpression : AsyncFunctionExpression , 见 15.8

有关 PrimaryExpression : AsyncGeneratorExpression , 见 15.6

13.2.7 正则表达式字面量

语法

12.9.5

13.2.7.1 Static Semantics: 早期错误

PrimaryExpression : RegularExpressionLiteral

13.2.7.2 Static Semantics: IsValidRegularExpressionLiteral ( literal )

The abstract operation IsValidRegularExpressionLiteral takes argument literal (一个 RegularExpressionLiteral Parse Node) and returns 一个 Boolean. 它判定其参数是否为一个有效的正则表达式字面量。 It performs the following steps when called:

  1. flagsliteralFlagText
  2. 如果 flags 包含除 dgimsuvy 之外的任何码点,返回 false
  3. 如果 flags 中有任何码点出现多于一次,返回 false
  4. 如果 flags 包含 u,令 utrue;否则令 ufalse
  5. 如果 flags 包含 v,令 vtrue;否则令 vfalse
  6. patternTextliteralBodyText
  7. 如果 ufalsevfalse,那么
    1. stringValueCodePointsToString(patternText)。
    2. patternText 设为如下得到的码点序列:把 stringValue 的每个 16 位元素解释为一个 Unicode BMP 码点。不会对这些元素应用 UTF-16 解码。
  8. parseResultParsePattern(patternText, u, v)。
  9. 如果 parseResult 是一个 Parse Node,返回 true
  10. 返回 false

13.2.7.3 Runtime Semantics: 求值

PrimaryExpression : RegularExpressionLiteral
  1. patternCodePointsToString(BodyText of RegularExpressionLiteral)。
  2. flagsCodePointsToString(FlagText of RegularExpressionLiteral)。
  3. 返回 ! RegExpCreate(pattern, flags)。

13.2.8 模板字面量

语法

TemplateLiteral[Yield, Await, Tagged] : NoSubstitutionTemplate SubstitutionTemplate[?Yield, ?Await, ?Tagged] SubstitutionTemplate[Yield, Await, Tagged] : TemplateHead Expression[+In, ?Yield, ?Await] TemplateSpans[?Yield, ?Await, ?Tagged] TemplateSpans[Yield, Await, Tagged] : TemplateTail TemplateMiddleList[?Yield, ?Await, ?Tagged] TemplateTail TemplateMiddleList[Yield, Await, Tagged] : TemplateMiddle Expression[+In, ?Yield, ?Await] TemplateMiddleList[?Yield, ?Await, ?Tagged] TemplateMiddle Expression[+In, ?Yield, ?Await]

13.2.8.1 Static Semantics: 早期错误

TemplateLiteral[Yield, Await, Tagged] : NoSubstitutionTemplate TemplateLiteral[Yield, Await, Tagged] : SubstitutionTemplate[?Yield, ?Await, ?Tagged] SubstitutionTemplate[Yield, Await, Tagged] : TemplateHead Expression[+In, ?Yield, ?Await] TemplateSpans[?Yield, ?Await, ?Tagged] TemplateSpans[Yield, Await, Tagged] : TemplateTail TemplateMiddleList[Yield, Await, Tagged] : TemplateMiddle Expression[+In, ?Yield, ?Await] TemplateMiddleList[?Yield, ?Await, ?Tagged] TemplateMiddle Expression[+In, ?Yield, ?Await]

13.2.8.2 Static Semantics: TemplateStrings

The syntax-directed operation TemplateStrings takes argument raw (一个 Boolean) and returns 一个由 String 或 undefined 构成的列表. It is defined piecewise over the following productions:

TemplateLiteral : NoSubstitutionTemplate
  1. 返回 « TemplateString(NoSubstitutionTemplate, raw) »。
SubstitutionTemplate : TemplateHead Expression TemplateSpans
  1. head 为 « TemplateString(TemplateHead, raw) »。
  2. tail 为以 raw 为参数调用 TemplateSpansTemplateStrings
  3. 返回 headtail 的列表串接。
TemplateSpans : TemplateTail
  1. 返回 « TemplateString(TemplateTail, raw) »。
TemplateSpans : TemplateMiddleList TemplateTail
  1. middle 为以 raw 为参数调用 TemplateMiddleListTemplateStrings
  2. tail 为 « TemplateString(TemplateTail, raw) »。
  3. 返回 middletail 的列表串接。
TemplateMiddleList : TemplateMiddle Expression
  1. 返回 « TemplateString(TemplateMiddle, raw) »。
TemplateMiddleList : TemplateMiddleList TemplateMiddle Expression
  1. front 为以 raw 为参数调用 TemplateMiddleListTemplateStrings
  2. last 为 « TemplateString(TemplateMiddle, raw) »。
  3. 返回 frontlast 的列表串接。

13.2.8.3 Static Semantics: TemplateString ( templateToken, raw )

The abstract operation TemplateString takes arguments templateToken (一个 NoSubstitutionTemplate Parse Node、一个 TemplateHead Parse Node、一个 TemplateMiddle Parse Node 或一个 TemplateTail Parse Node) and raw (一个 Boolean) and returns 一个 String 或 undefined. It performs the following steps when called:

  1. 如果 rawtrue,那么
    1. stringtemplateTokenTRV
  2. 否则,
    1. stringtemplateTokenTV
  3. 返回 string
Note

如果 rawfalsetemplateToken 包含一个 NotEscapeSequence,则该操作返回 undefined。在所有其他情况下, 它返回一个 String。

13.2.8.4 GetTemplateObject ( templateLiteral )

The abstract operation GetTemplateObject takes argument templateLiteral (一个 Parse Node) and returns 一个 Array. It performs the following steps when called:

  1. realm当前 Realm Record
  2. templateRegistryrealm.[[TemplateMap]]
  3. 对于 templateRegistry 中的每个元素 e,执行
    1. 如果 e.[[Site]]templateLiteral 是同一个 Parse Node,那么
      1. 返回 e.[[Array]]
  4. rawStrings 为以 true 为参数调用 templateLiteralTemplateStrings
  5. 断言:rawStrings 是一个 String 列表。
  6. cookedStrings 为以 false 为参数调用 templateLiteralTemplateStrings
  7. count 为列表 cookedStrings 中元素的个数。
  8. 断言:count ≤ 232 - 1。
  9. template 为 ! ArrayCreate(count)。
  10. rawObj 为 ! ArrayCreate(count)。
  11. index 为 0。
  12. 重复,当 index < count 时,
    1. propertyKey 为 ! ToString(𝔽(index))。
    2. cookedValuecookedStrings[index]。
    3. 执行 ! DefinePropertyOrThrow(template, propertyKey, PropertyDescriptor { [[Value]]: cookedValue, [[Writable]]: false, [[Enumerable]]: true, [[Configurable]]: false })。
    4. rawValue 为 String 值 rawStrings[index]。
    5. 执行 ! DefinePropertyOrThrow(rawObj, propertyKey, PropertyDescriptor { [[Value]]: rawValue, [[Writable]]: false, [[Enumerable]]: true, [[Configurable]]: false })。
    6. index 设为 index + 1。
  13. 执行 ! SetIntegrityLevel(rawObj, frozen)。
  14. 执行 ! DefinePropertyOrThrow(template, "raw", PropertyDescriptor { [[Value]]: rawObj, [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false })。
  15. 执行 ! SetIntegrityLevel(template, frozen)。
  16. Record { [[Site]]: templateLiteral, [[Array]]: template } 追加到 realm.[[TemplateMap]]
  17. 返回 template
Note 1

模板对象的创建不可能导致一个突然完成。

Note 2

一个 realm 的程序代码中的每个 TemplateLiteral 都关联着一个唯一的模 板对象,该对象用于带标签模板的求值 (13.2.8.6)。 模板对象是被冻结的,并且每次对某个特定带标签模板求值时都会使用同一个模板对 象。模板对象是在首次对该 TemplateLiteral 求值时惰性创建,还是在首次求值 之前急切创建,是一个实现选择,ECMAScript 代码无法观察到。

Note 3

本规范未来版本可能会定义模板对象的额外不可枚举属性。

13.2.8.5 Runtime Semantics: SubstitutionEvaluation

The syntax-directed operation SubstitutionEvaluation takes no arguments and returns 要么是一个正常完成,包含一个 ECMAScript 语言值列表,要么是一个突然完成. It is defined piecewise over the following productions:

TemplateSpans : TemplateTail
  1. 返回一个新的空列表。
TemplateSpans : TemplateMiddleList TemplateTail
  1. 返回 ? 对 TemplateMiddleList 执行 SubstitutionEvaluation
TemplateMiddleList : TemplateMiddle Expression
  1. subRef 为 ? 对 Expression 求值。
  2. sub 为 ? GetValue(subRef)。
  3. 返回 « sub »。
TemplateMiddleList : TemplateMiddleList TemplateMiddle Expression
  1. preceding 为 ? 对 TemplateMiddleList 执行 SubstitutionEvaluation
  2. nextRef 为 ? 对 Expression 求值。
  3. next 为 ? GetValue(nextRef)。
  4. 返回 preceding 与 « next » 的列表串接。

13.2.8.6 Runtime Semantics: 求值

TemplateLiteral : NoSubstitutionTemplate
  1. 返回按 12.9.6 中定义的 NoSubstitutionTemplateTV
SubstitutionTemplate : TemplateHead Expression TemplateSpans
  1. head 为按 12.9.6 中定义的 TemplateHeadTV
  2. subRef 为 ? 对 Expression 求值。
  3. sub 为 ? GetValue(subRef)。
  4. middle 为 ? ToString(sub)。
  5. tail 为 ? 对 TemplateSpans 求值。
  6. 返回 headmiddletail 的字符串串接结果。
Note 1

应用于 Expression 值的字符串转换语义类似 String.prototype.concat, 而不是 + 运算符。

TemplateSpans : TemplateTail
  1. 返回按 12.9.6 中定义的 TemplateTailTV
TemplateSpans : TemplateMiddleList TemplateTail
  1. head 为 ? 对 TemplateMiddleList 求值。
  2. tail 为按 12.9.6 中定义的 TemplateTailTV
  3. 返回 headtail 的字符串串接结果。
TemplateMiddleList : TemplateMiddle Expression
  1. head 为按 12.9.6 中定义的 TemplateMiddleTV
  2. subRef 为 ? 对 Expression 求值。
  3. sub 为 ? GetValue(subRef)。
  4. middle 为 ? ToString(sub)。
  5. 返回 headmiddle 的字符串串接结果。
Note 2

应用于 Expression 值的字符串转换语义类似 String.prototype.concat, 而不是 + 运算符。

TemplateMiddleList : TemplateMiddleList TemplateMiddle Expression
  1. rest 为 ? 对 TemplateMiddleList 求值。
  2. middle 为按 12.9.6 中定义的 TemplateMiddleTV
  3. subRef 为 ? 对 Expression 求值。
  4. sub 为 ? GetValue(subRef)。
  5. last 为 ? ToString(sub)。
  6. 返回 restmiddlelast 的字符串串接结果。
Note 3

应用于 Expression 值的字符串转换语义类似 String.prototype.concat, 而不是 + 运算符。

13.2.9 分组运算符

13.2.9.1 Static Semantics: 早期错误

PrimaryExpression : CoverParenthesizedExpressionAndArrowParameterList

13.2.9.2 Runtime Semantics: 求值

PrimaryExpression : CoverParenthesizedExpressionAndArrowParameterList
  1. expr 为被 CoverParenthesizedExpressionAndArrowParameterList覆盖ParenthesizedExpression
  2. 返回 ? 对 expr 求值。
ParenthesizedExpression : ( Expression )
  1. 返回 ? 对 Expression 求值。该结果可能是 Reference 类型。
Note

该算法不会对 Expression 的求值结果应用 GetValue。其主要动机在于使 得 deletetypeof 这样的运算符可以应用于带括号的表达式。

13.3 左侧表达式

语法

MemberExpression[Yield, Await] : PrimaryExpression[?Yield, ?Await] MemberExpression[?Yield, ?Await] [ Expression[+In, ?Yield, ?Await] ] MemberExpression[?Yield, ?Await] . IdentifierName MemberExpression[?Yield, ?Await] TemplateLiteral[?Yield, ?Await, +Tagged] SuperProperty[?Yield, ?Await] MetaProperty new MemberExpression[?Yield, ?Await] Arguments[?Yield, ?Await] MemberExpression[?Yield, ?Await] . PrivateIdentifier SuperProperty[Yield, Await] : super [ Expression[+In, ?Yield, ?Await] ] super . IdentifierName MetaProperty : NewTarget ImportMeta NewTarget : new . target ImportMeta : import . meta NewExpression[Yield, Await] : MemberExpression[?Yield, ?Await] new NewExpression[?Yield, ?Await] CallExpression[Yield, Await] : CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await] SuperCall[?Yield, ?Await] ImportCall[?Yield, ?Await] CallExpression[?Yield, ?Await] Arguments[?Yield, ?Await] CallExpression[?Yield, ?Await] [ Expression[+In, ?Yield, ?Await] ] CallExpression[?Yield, ?Await] . IdentifierName CallExpression[?Yield, ?Await] TemplateLiteral[?Yield, ?Await, +Tagged] CallExpression[?Yield, ?Await] . PrivateIdentifier SuperCall[Yield, Await] : super Arguments[?Yield, ?Await] ImportCall[Yield, Await] : import ( AssignmentExpression[+In, ?Yield, ?Await] ,opt ) import ( AssignmentExpression[+In, ?Yield, ?Await] , AssignmentExpression[+In, ?Yield, ?Await] ,opt ) Arguments[Yield, Await] : ( ) ( ArgumentList[?Yield, ?Await] ) ( ArgumentList[?Yield, ?Await] , ) ArgumentList[Yield, Await] : AssignmentExpression[+In, ?Yield, ?Await] ... AssignmentExpression[+In, ?Yield, ?Await] ArgumentList[?Yield, ?Await] , AssignmentExpression[+In, ?Yield, ?Await] ArgumentList[?Yield, ?Await] , ... AssignmentExpression[+In, ?Yield, ?Await] OptionalExpression[Yield, Await] : MemberExpression[?Yield, ?Await] OptionalChain[?Yield, ?Await] CallExpression[?Yield, ?Await] OptionalChain[?Yield, ?Await] OptionalExpression[?Yield, ?Await] OptionalChain[?Yield, ?Await] OptionalChain[Yield, Await] : ?. Arguments[?Yield, ?Await] ?. [ Expression[+In, ?Yield, ?Await] ] ?. IdentifierName ?. TemplateLiteral[?Yield, ?Await, +Tagged] ?. PrivateIdentifier OptionalChain[?Yield, ?Await] Arguments[?Yield, ?Await] OptionalChain[?Yield, ?Await] [ Expression[+In, ?Yield, ?Await] ] OptionalChain[?Yield, ?Await] . IdentifierName OptionalChain[?Yield, ?Await] TemplateLiteral[?Yield, ?Await, +Tagged] OptionalChain[?Yield, ?Await] . PrivateIdentifier LeftHandSideExpression[Yield, Await] : NewExpression[?Yield, ?Await] CallExpression[?Yield, ?Await] OptionalExpression[?Yield, ?Await]

补充语法

在处理如下产生式的一个实例时
CallExpression : CoverCallExpressionAndAsyncArrowHead
CoverCallExpressionAndAsyncArrowHead 的解释会使用如下文法加以细化:

CallMemberExpression[Yield, Await] : MemberExpression[?Yield, ?Await] Arguments[?Yield, ?Await]

13.3.1 静态语义

13.3.1.1 Static Semantics: 早期错误

OptionalChain : ?. TemplateLiteral OptionalChain TemplateLiteral
  • 如果有任何源文本被该产生式匹配,则是语法错误。
Note

该产生式存在是为了防止自动分号插入规则 (12.10) 被应用到如下代码:

a?.b
`c`

否则它会被解释为两条有效语句。其目的是与不使用可选链的类似代码保持一 致:

a.b
`c`

后者是一条有效语句,并且不会应用自动分号插入。

ImportMeta : import . meta

13.3.2 属性访问器

Note

属性通过名称进行访问,使用点记法:

或方括号记法:

点记法可由如下语法转换解释:

其行为与下式完全相同

MemberExpression [ <identifier-name-string> ]

类似地

其行为与下式完全相同

CallExpression [ <identifier-name-string> ]

其中 <identifier-name-string> 是 IdentifierNameStringValue

13.3.2.1 Runtime Semantics: 求值

MemberExpression : MemberExpression [ Expression ]
  1. baseReference 为 ? 对 MemberExpression 求值。
  2. baseValue 为 ? GetValue(baseReference)。
  3. strictIsStrict(this MemberExpression)。
  4. 返回 ? EvaluatePropertyAccessWithExpressionKey(baseValue, Expression, strict)。
MemberExpression : MemberExpression . IdentifierName
  1. baseReference 为 ? 对 MemberExpression 求值。
  2. baseValue 为 ? GetValue(baseReference)。
  3. strictIsStrict(this MemberExpression)。
  4. 返回 EvaluatePropertyAccessWithIdentifierKey(baseValue, IdentifierName, strict)。
MemberExpression : MemberExpression . PrivateIdentifier
  1. baseReference 为 ? 对 MemberExpression 求值。
  2. baseValue 为 ? GetValue(baseReference)。
  3. fieldNameStringPrivateIdentifierStringValue
  4. 返回 MakePrivateReference(baseValue, fieldNameString)。
CallExpression : CallExpression [ Expression ]
  1. baseReference 为 ? 对 CallExpression 求值。
  2. baseValue 为 ? GetValue(baseReference)。
  3. strictIsStrict(this CallExpression)。
  4. 返回 ? EvaluatePropertyAccessWithExpressionKey(baseValue, Expression, strict)。
CallExpression : CallExpression . IdentifierName
  1. baseReference 为 ? 对 CallExpression 求值。
  2. baseValue 为 ? GetValue(baseReference)。
  3. strictIsStrict(this CallExpression)。
  4. 返回 EvaluatePropertyAccessWithIdentifierKey(baseValue, IdentifierName, strict)。
CallExpression : CallExpression . PrivateIdentifier
  1. baseReference 为 ? 对 CallExpression 求值。
  2. baseValue 为 ? GetValue(baseReference)。
  3. fieldNameStringPrivateIdentifierStringValue
  4. 返回 MakePrivateReference(baseValue, fieldNameString)。

13.3.3 EvaluatePropertyAccessWithExpressionKey ( baseValue, expression, strict )

The abstract operation EvaluatePropertyAccessWithExpressionKey takes arguments baseValue (一个 ECMAScript 语言值), expression (一个 Expression Parse Node), and strict (一个 Boolean) and returns 要么是一个正常完成,包含一个 Reference Record,要么是一个突然完成. It performs the following steps when called:

  1. propertyNameReference 为 ? 对 expression 求值。
  2. propertyNameValue 为 ? GetValue(propertyNameReference)。
  3. NOTE: 在大多数情况下,ToPropertyKey 会在此步骤之后立即作用于 propertyNameValue。但是,在 a[b] = c 的情形下,它要等到对 c 求值之后才会执行。
  4. 返回 Reference Record { [[Base]]: baseValue, [[ReferencedName]]: propertyNameValue, [[Strict]]: strict, [[ThisValue]]: empty }。

13.3.4 EvaluatePropertyAccessWithIdentifierKey ( baseValue, identifierName, strict )

The abstract operation EvaluatePropertyAccessWithIdentifierKey takes arguments baseValue (一个 ECMAScript 语言值), identifierName (一个 IdentifierName Parse Node), and strict (一个 Boolean) and returns 一个 Reference Record. It performs the following steps when called:

  1. propertyNameStringidentifierNameStringValue
  2. 返回 Reference Record { [[Base]]: baseValue, [[ReferencedName]]: propertyNameString, [[Strict]]: strict, [[ThisValue]]: empty }。

13.3.5 new 运算符

13.3.5.1 Runtime Semantics: 求值

NewExpression : new NewExpression
  1. 返回 ? EvaluateNew(NewExpression, empty)。
MemberExpression : new MemberExpression Arguments
  1. 返回 ? EvaluateNew(MemberExpression, Arguments)。

13.3.5.1.1 EvaluateNew ( constructExpr, arguments )

The abstract operation EvaluateNew takes arguments constructExpr (a NewExpression Parse Node or a MemberExpression Parse Node) and arguments (empty or an Arguments Parse Node) and returns either a normal completion containing an Object or an abrupt completion. It performs the following steps when called:

  1. ref 为 ? 对 constructExpr 求值。
  2. constructor 为 ? GetValue(ref)。
  3. 如果 argumentsempty,那么
    1. argList 为一个新的空列表。
  4. 否则,
    1. argList 为 ? 对 arguments 执行 ArgumentListEvaluation
  5. 如果 IsConstructor(constructor) 为 false,抛出一个 TypeError 异常。
  6. 返回 ? Construct(constructor, argList)。

13.3.6 函数调用

13.3.6.1 Runtime Semantics: 求值

CallExpression : CoverCallExpressionAndAsyncArrowHead
  1. expr 为被 CoverCallExpressionAndAsyncArrowHead 覆盖CallMemberExpression
  2. memberExprexprMemberExpression
  3. argumentsexprArguments
  4. ref 为 ? 对 memberExpr 求值。
  5. func 为 ? GetValue(ref)。
  6. 如果 ref 是一个 Reference RecordIsPropertyReference(ref) 为 false,并且 ref.[[ReferencedName]]"eval",那么
    1. 如果 SameValue(func, %eval%) 为 true,那么
      1. argList 为 ? 对 arguments 执行 ArgumentListEvaluation
      2. 如果 argList 不含任何元素,返回 undefined
      3. evalArgargList 的第一个元素。
      4. 如果 IsStrict(this CallExpression) 为 true,令 strictCallertrue;否则令 strictCallerfalse
      5. 返回 ? PerformEval(evalArg, strictCaller, true)。
  7. thisCall 为该 CallExpression
  8. tailCallIsInTailPosition(thisCall)。
  9. 返回 ? EvaluateCall(func, ref, arguments, tailCall)。

执行步骤 6.a.vCallExpression 求值称为一个 直接 eval

CallExpression : CallExpression Arguments
  1. ref 为 ? 对 CallExpression 求值。
  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 )

The abstract operation EvaluateCall takes arguments func (一个 ECMAScript 语言值), ref (一个 ECMAScript 语言值或一个 Reference Record), arguments (一个 Parse Node), and tailPosition (一个 Boolean) and returns 要么是一个正常完成,包含一个 ECMAScript 语言值,要么是一个突然完成. It performs the following steps when called:

  1. 如果 ref 是一个 Reference Record,那么
    1. 如果 IsPropertyReference(ref) 为 true,那么
      1. thisValueGetThisValue(ref)。
    2. 否则,
      1. refEnvref.[[Base]]
      2. 断言:refEnv 是一个 Environment Record
      3. thisValuerefEnv.WithBaseObject()。
  2. 否则,
    1. thisValueundefined
  3. argList 为 ? 对 arguments 执行 ArgumentListEvaluation
  4. 如果 func 不是一个 Object,抛出一个 TypeError 异常。
  5. 如果 IsCallable(func) 为 false,抛出一个 TypeError 异常。
  6. 如果 tailPositiontrue,执行 PrepareForTailCall()。
  7. 返回 ? Call(func, thisValue, argList)。

13.3.7 super 关键字

13.3.7.1 Runtime Semantics: 求值

SuperProperty : super [ Expression ]
  1. envGetThisEnvironment()。
  2. actualThis 为 ? env.GetThisBinding()。
  3. propertyNameReference 为 ? 对 Expression 求值。
  4. propertyNameValue 为 ? GetValue(propertyNameReference)。
  5. strictIsStrict(this SuperProperty)。
  6. NOTE: 在大多数情况下,ToPropertyKey 会在此步骤之后立即作用于 propertyNameValue。但是,在 super[b] = c 的情形下,它要等到对 c 求值之后才会执行。
  7. 返回 MakeSuperPropertyReference(actualThis, propertyNameValue, strict)。
SuperProperty : super . IdentifierName
  1. envGetThisEnvironment()。
  2. actualThis 为 ? env.GetThisBinding()。
  3. propertyKeyIdentifierNameStringValue
  4. strictIsStrict(this SuperProperty)。
  5. 返回 MakeSuperPropertyReference(actualThis, propertyKey, strict)。
SuperCall : super Arguments
  1. newTargetGetNewTarget()。
  2. 断言:newTarget 是一个构造器
  3. superConstructorGetSuperConstructor()。
  4. argList 为 ? 对 Arguments 执行 ArgumentListEvaluation
  5. 如果 IsConstructor(superConstructor) 为 false,抛出一个 TypeError 异常。
  6. result 为 ? Construct(superConstructor, argList, newTarget)。
  7. thisERGetThisEnvironment()。
  8. 断言:thisER 是一个 Function Environment Record
  9. 执行 ? BindThisValue(thisER, result)。
  10. funcObjthisER.[[FunctionObject]]
  11. 断言:funcObj 是一个 ECMAScript 函数对象
  12. 执行 ? InitializeInstanceElements(result, funcObj)。
  13. 返回 result

13.3.7.2 GetSuperConstructor ( )

The abstract operation GetSuperConstructor takes no arguments and returns an Object or null. It performs the following steps when called:

  1. envRecGetThisEnvironment()。
  2. 断言:envRec 是一个 Function Environment Record
  3. activeFunctionenvRec.[[FunctionObject]]
  4. 断言:activeFunction 是一个 ECMAScript 函数对象
  5. superConstructor 为 ! activeFunction.[[GetPrototypeOf]]()。
  6. 返回 superConstructor

13.3.7.3 MakeSuperPropertyReference ( actualThis, propertyKey, strict )

The abstract operation MakeSuperPropertyReference takes arguments actualThis (一个 ECMAScript 语言值), propertyKey (一个 ECMAScript 语言值), and strict (一个 Boolean) and returns 一个 Super Reference Record. It performs the following steps when called:

  1. envGetThisEnvironment()。
  2. 断言:env.HasSuperBinding() 为 true
  3. 断言:env 是一个 Function Environment Record
  4. baseValueGetSuperBase(env)。
  5. 返回 Reference Record { [[Base]]: baseValue, [[ReferencedName]]: propertyKey, [[Strict]]: strict, [[ThisValue]]: actualThis }。

13.3.8 实参列表

Note

对实参列表求值会产生一个值列表。

13.3.8.1 Runtime Semantics: ArgumentListEvaluation

The syntax-directed operation ArgumentListEvaluation takes no arguments and returns 要么是一个正常完成,包含一个 ECMAScript 语言值列表,要么是一个突然完成. It is defined piecewise over the following productions:

Arguments : ( )
  1. 返回一个新的空列表。
ArgumentList : AssignmentExpression
  1. ref 为 ? 对 AssignmentExpression 求值。
  2. arg 为 ? GetValue(ref)。
  3. 返回 « arg »。
ArgumentList : ... AssignmentExpression
  1. list 为一个新的空列表。
  2. spreadRef 为 ? 对 AssignmentExpression 求值。
  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 为 ? 对 ArgumentList 执行 ArgumentListEvaluation
  2. ref 为 ? 对 AssignmentExpression 求值。
  3. arg 为 ? GetValue(ref)。
  4. 返回 precedingArgs 与 « arg » 的列表串接。
ArgumentList : ArgumentList , ... AssignmentExpression
  1. precedingArgs 为 ? 对 ArgumentList 执行 ArgumentListEvaluation
  2. spreadRef 为 ? 对 AssignmentExpression 求值。
  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 为 ? 对 SubstitutionTemplate 执行 ArgumentListEvaluation
  4. 返回 « siteObj » 与 remaining 的列表串接。
SubstitutionTemplate : TemplateHead Expression TemplateSpans
  1. firstSubRef 为 ? 对 Expression 求值。
  2. firstSub 为 ? GetValue(firstSubRef)。
  3. restSub 为 ? 对 TemplateSpans 执行 SubstitutionEvaluation
  4. 断言:restSub 是一个可能为空的列表。
  5. 返回 « firstSub » 与 restSub 的列表串接。

13.3.9 可选链

Note
可选链是由一个或多个属性访问和函数调用组成的链,其中第一个以记号 ?. 开始。

13.3.9.1 Runtime Semantics: 求值

OptionalExpression : MemberExpression OptionalChain
  1. baseReference 为 ? 对 MemberExpression 求值。
  2. baseValue 为 ? GetValue(baseReference)。
  3. 如果 baseValueundefinednull,那么
    1. 返回 undefined
  4. 返回 ? 对 OptionalChain 执行 ChainEvaluation,并以 baseValuebaseReference 为参数。
OptionalExpression : CallExpression OptionalChain
  1. baseReference 为 ? 对 CallExpression 求值。
  2. baseValue 为 ? GetValue(baseReference)。
  3. 如果 baseValueundefinednull,那么
    1. 返回 undefined
  4. 返回 ? 对 OptionalChain 执行 ChainEvaluation,并以 baseValuebaseReference 为参数。
OptionalExpression : OptionalExpression OptionalChain
  1. baseReference 为 ? 对 OptionalExpression 求值。
  2. baseValue 为 ? GetValue(baseReference)。
  3. 如果 baseValueundefinednull,那么
    1. 返回 undefined
  4. 返回 ? 对 OptionalChain 执行 ChainEvaluation,并以 baseValuebaseReference 为参数。

13.3.9.2 Runtime Semantics: ChainEvaluation

The syntax-directed operation ChainEvaluation takes arguments baseValue (一个 ECMAScript 语言值) and baseReference (一个 ECMAScript 语言值或一个 Reference Record) and returns 要么是一个正常完成,包含一个 ECMAScript 语言值或一个 Reference Record,要么是一个突然完成. It is defined piecewise over the following productions:

OptionalChain : ?. Arguments
  1. thisChain 为该 OptionalChain
  2. tailCallIsInTailPosition(thisChain)。
  3. 返回 ? EvaluateCall(baseValue, baseReference, Arguments, tailCall)。
OptionalChain : ?. [ Expression ]
  1. strictIsStrict(this OptionalChain)。
  2. 返回 ? EvaluatePropertyAccessWithExpressionKey(baseValue, Expression, strict)。
OptionalChain : ?. IdentifierName
  1. strictIsStrict(this OptionalChain)。
  2. 返回 EvaluatePropertyAccessWithIdentifierKey(baseValue, IdentifierName, strict)。
OptionalChain : ?. PrivateIdentifier
  1. fieldNameStringPrivateIdentifierStringValue
  2. 返回 MakePrivateReference(baseValue, fieldNameString)。
OptionalChain : OptionalChain Arguments
  1. optionalChainOptionalChain
  2. newReference 为 ? 对 optionalChain 执行 ChainEvaluation,并以 baseValuebaseReference 为参数。
  3. newValue 为 ? GetValue(newReference)。
  4. thisChain 为该 OptionalChain
  5. tailCallIsInTailPosition(thisChain)。
  6. 返回 ? EvaluateCall(newValue, newReference, Arguments, tailCall)。
OptionalChain : OptionalChain [ Expression ]
  1. optionalChainOptionalChain
  2. newReference 为 ? 对 optionalChain 执行 ChainEvaluation,并以 baseValuebaseReference 为参数。
  3. newValue 为 ? GetValue(newReference)。
  4. strictIsStrict(this OptionalChain)。
  5. 返回 ? EvaluatePropertyAccessWithExpressionKey(newValue, Expression, strict)。
OptionalChain : OptionalChain . IdentifierName
  1. optionalChainOptionalChain
  2. newReference 为 ? 对 optionalChain 执行 ChainEvaluation,并以 baseValuebaseReference 为参数。
  3. newValue 为 ? GetValue(newReference)。
  4. strictIsStrict(this OptionalChain)。
  5. 返回 EvaluatePropertyAccessWithIdentifierKey(newValue, IdentifierName, strict)。
OptionalChain : OptionalChain . PrivateIdentifier
  1. optionalChainOptionalChain
  2. newReference 为 ? 对 optionalChain 执行 ChainEvaluation,并以 baseValuebaseReference 为参数。
  3. newValue 为 ? GetValue(newReference)。
  4. fieldNameStringPrivateIdentifierStringValue
  5. 返回 MakePrivateReference(newValue, fieldNameString)。

13.3.10 Import 调用

13.3.10.1 Runtime Semantics: 求值

ImportCall : import ( AssignmentExpression ,opt )
  1. 返回 ? EvaluateImportCall(AssignmentExpression)。
ImportCall : import ( AssignmentExpression , AssignmentExpression ,opt )
  1. 返回 ? EvaluateImportCall(第一个 AssignmentExpression, 第二个 AssignmentExpression)。

13.3.10.2 EvaluateImportCall ( specifierExpression [ , optionsExpression ] )

The abstract operation EvaluateImportCall takes argument specifierExpression (一个 Parse Node) and optional argument optionsExpression (一个 Parse Node) and returns 要么是一个正常完成,包含一个 Promise,要么是一个突然完成. It performs the following steps when called:

  1. referrerGetActiveScriptOrModule()。
  2. 如果 referrernull,将 referrer 设为当前 Realm Record
  3. specifierRef 为 ? 对 specifierExpression 求值。
  4. specifier 为 ? GetValue(specifierRef)。
  5. 如果 optionsExpression 存在,那么
    1. optionsRef 为 ? 对 optionsExpression 求值。
    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 不是一个 Object,那么
      1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « 一个新创建的 TypeError 对象 »)。
      2. 返回 promiseCapability.[[Promise]]
    2. attributesObjCompletion(Get(options, "with")).
    3. IfAbruptRejectPromise(attributesObj, promiseCapability)。
    4. 如果 attributesObj 不为 undefined,那么
      1. 如果 attributesObj 不是一个 Object,那么
        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 是一个 String,那么
          1. 如果 value 不是一个 String,那么
            1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « 一个新创建的 TypeError 对象 »)。
            2. 返回 promiseCapability.[[Promise]]
          2. ImportAttribute Record { [[Key]]: key, [[Value]]: value } 追加到 attributes
    5. 如果 AllImportAttributesSupported(attributes) 为 false,那么
      1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « 一个新创建的 TypeError 对象 »)。
      2. 返回 promiseCapability.[[Promise]]
    6. 按照 [[Key]] 字段的词法顺序对 attributes 排序,将每个此类字段的值视为 UTF-16 码元值序列。NOTE: 这种排序只在如下意义上可观察:宿主被禁止根据枚举属性的顺序来改变行为。
  12. moduleRequest 为一个新的 ModuleRequest Record { [[Specifier]]: specifierString, [[Attributes]]: attributes }。
  13. 执行 HostLoadImportedModule(referrer, moduleRequest, empty, promiseCapability)。
  14. 返回 promiseCapability.[[Promise]]

13.3.10.3 ContinueDynamicImport ( promiseCapability, moduleCompletion )

The abstract operation ContinueDynamicImport takes arguments promiseCapability (一个 PromiseCapability Record) and moduleCompletion (要么是一个正常完成,包含一个 Module Record,要么是一个抛出完成) and returns unused. 它完成最初由一次 import() 调用发起的动态导入过程,并视情况解析或拒绝该调用返回的 promise。 It performs the following steps when called:

  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. 返回 NormalCompletion(undefined)。
  5. onRejectedCreateBuiltinFunction(rejectedClosure, 1, "", « »)。
  6. linkAndEvaluateClosure 为一个新的不带参数的抽象闭包,它捕获 modulepromiseCapabilityonRejected,并在被调用时执行以下步骤:
    1. linkCompletion(module.Link())。
    2. 如果 link 是一个突然完成,那么
      1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « link.[[Value]] »)。
      2. 返回 NormalCompletion(undefined)。
    3. evaluatePromisemodule.Evaluate()。
    4. fulfilledClosure 为一个新的不带参数的抽象闭包,它捕获 modulepromiseCapability,并在被调用时执行以下步骤:
      1. namespaceGetModuleNamespace(module)。
      2. 执行 ! Call(promiseCapability.[[Resolve]], undefined, « namespace »)。
      3. 返回 NormalCompletion(undefined)。
    5. onFulfilledCreateBuiltinFunction(fulfilledClosure, 0, "", « »)。
    6. 执行 PerformPromiseThen(evaluatePromise, onFulfilled, onRejected)。
    7. 返回 unused
  7. linkAndEvaluateCreateBuiltinFunction(linkAndEvaluateClosure, 0, "", « »)。
  8. 执行 PerformPromiseThen(loadPromise, linkAndEvaluate, onRejected)。
  9. 返回 unused

13.3.11 带标签模板

Note

带标签模板是一种函数调用,其中调用的参数来自一个 TemplateLiteral13.2.8)。实际参数包括一 个模板对象(13.2.8.4)以及 对嵌入在 TemplateLiteral 中的表达式求值所产生的值。

13.3.11.1 Runtime Semantics: 求值

MemberExpression : MemberExpression TemplateLiteral
  1. tagRef 为 ? 对 MemberExpression 求值。
  2. tagFunc 为 ? GetValue(tagRef)。
  3. thisCall 为该 MemberExpression
  4. tailCallIsInTailPosition(thisCall)。
  5. 返回 ? EvaluateCall(tagFunc, tagRef, TemplateLiteral, tailCall)。
CallExpression : CallExpression TemplateLiteral
  1. tagRef 为 ? 对 CallExpression 求值。
  2. tagFunc 为 ? GetValue(tagRef)。
  3. thisCall 为该 CallExpression
  4. tailCallIsInTailPosition(thisCall)。
  5. 返回 ? EvaluateCall(tagFunc, tagRef, TemplateLiteral, tailCall)。

13.3.12 元属性

13.3.12.1 Runtime Semantics: 求值

NewTarget : new . target
  1. 返回 GetNewTarget()。
ImportMeta : import . meta
  1. moduleGetActiveScriptOrModule()。
  2. 断言:module 是一个 Source Text Module Record
  3. importMetamodule.[[ImportMeta]]
  4. 如果 importMetaempty,那么
    1. importMeta 设为 OrdinaryObjectCreate(null)。
    2. importMetaValuesHostGetImportMetaProperties(module)。
    3. 对于 importMetaValues 中的每个 Record { [[Key]], [[Value]] } p,执行
      1. 执行 ! CreateDataPropertyOrThrow(importMeta, p.[[Key]], p.[[Value]])。
    4. 执行 HostFinalizeImportMeta(importMeta, module)。
    5. module.[[ImportMeta]] 设为 importMeta
    6. 返回 importMeta
  5. 断言:importMeta 是一个 Object。
  6. 返回 importMeta

13.3.12.1.1 HostGetImportMetaProperties ( moduleRecord )

The host-defined abstract operation HostGetImportMetaProperties takes argument moduleRecord (一个 Module Record) and returns 一个列表,其元素为具有字段 [[Key]](一个属性键)和 [[Value]](一个 ECMAScript 语言值)的 Record. 它允许宿主import.meta 返回的对象提供属性键和值。

HostGetImportMetaProperties 的默认实现是返回一个新的空列表。

13.3.12.1.2 HostFinalizeImportMeta ( importMeta, moduleRecord )

The host-defined abstract operation HostFinalizeImportMeta takes arguments importMeta (一个 Object) and moduleRecord (一个 Module Record) and returns unused. 它允许宿主执行任意非常规操作,以准备 import.meta 返回的对象。

大多数宿主只需定义 HostGetImportMetaProperties,并保留 HostFinalizeImportMeta 的默认行为即可。不过,HostFinalizeImportMeta 为那些在将对象暴露给 ECMAScript 代码之前需要直接操纵它的宿主提供了一个 “逃生口”。

HostFinalizeImportMeta 的默认实现是返回 unused

13.4 更新表达式

语法

UpdateExpression[Yield, Await] : LeftHandSideExpression[?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] [no LineTerminator here] ++ LeftHandSideExpression[?Yield, ?Await] [no LineTerminator here] -- ++ UnaryExpression[?Yield, ?Await] -- UnaryExpression[?Yield, ?Await]

13.4.1 Static Semantics: 早期错误

UpdateExpression : LeftHandSideExpression ++ LeftHandSideExpression -- UpdateExpression : ++ UnaryExpression -- UnaryExpression

13.4.2 后缀递增运算符

13.4.2.1 Runtime Semantics: 求值

UpdateExpression : LeftHandSideExpression ++
  1. lhs 为 ? 对 LeftHandSideExpression 求值。
  2. 如果 LeftHandSideExpressionAssignmentTargetTypeweb-compat,抛出一个 ReferenceError 异常。
  3. oldValue 为 ? ToNumeric(? GetValue(lhs))。
  4. 如果 oldValue 是一个 Number,那么
    1. newValueNumber::add(oldValue, 1𝔽)。
  5. 否则,
    1. 断言:oldValue 是一个 BigInt。
    2. newValueBigInt::add(oldValue, 1)。
  6. 执行 ? PutValue(lhs, newValue)。
  7. 返回 oldValue

13.4.3 后缀递减运算符

13.4.3.1 Runtime Semantics: 求值

UpdateExpression : LeftHandSideExpression --
  1. lhs 为 ? 对 LeftHandSideExpression 求值。
  2. 如果 LeftHandSideExpressionAssignmentTargetTypeweb-compat,抛出一个 ReferenceError 异常。
  3. oldValue 为 ? ToNumeric(? GetValue(lhs))。
  4. 如果 oldValue 是一个 Number,那么
    1. newValueNumber::subtract(oldValue, 1𝔽)。
  5. 否则,
    1. 断言:oldValue 是一个 BigInt。
    2. newValueBigInt::subtract(oldValue, 1)。
  6. 执行 ? PutValue(lhs, newValue)。
  7. 返回 oldValue

13.4.4 前缀递增运算符

13.4.4.1 Runtime Semantics: 求值

UpdateExpression : ++ UnaryExpression
  1. expr 为 ? 对 UnaryExpression 求值。
  2. 如果 UnaryExpressionAssignmentTargetTypeweb-compat,抛出一个 ReferenceError 异常。
  3. oldValue 为 ? ToNumeric(? GetValue(expr))。
  4. 如果 oldValue 是一个 Number,那么
    1. newValueNumber::add(oldValue, 1𝔽)。
  5. 否则,
    1. 断言:oldValue 是一个 BigInt。
    2. newValueBigInt::add(oldValue, 1)。
  6. 执行 ? PutValue(expr, newValue)。
  7. 返回 newValue

13.4.5 前缀递减运算符

13.4.5.1 Runtime Semantics: 求值

UpdateExpression : -- UnaryExpression
  1. expr 为 ? 对 UnaryExpression 求值。
  2. 如果 UnaryExpressionAssignmentTargetTypeweb-compat,抛出一个 ReferenceError 异常。
  3. oldValue 为 ? ToNumeric(? GetValue(expr))。
  4. 如果 oldValue 是一个 Number,那么
    1. newValueNumber::subtract(oldValue, 1𝔽)。
  5. 否则,
    1. 断言:oldValue 是一个 BigInt。
    2. newValueBigInt::subtract(oldValue, 1)。
  6. 执行 ? PutValue(expr, newValue)。
  7. 返回 newValue

13.5 一元运算符

语法

UnaryExpression[Yield, Await] : UpdateExpression[?Yield, ?Await] delete UnaryExpression[?Yield, ?Await] void UnaryExpression[?Yield, ?Await] typeof UnaryExpression[?Yield, ?Await] + UnaryExpression[?Yield, ?Await] - UnaryExpression[?Yield, ?Await] ~ UnaryExpression[?Yield, ?Await] ! UnaryExpression[?Yield, ?Await] [+Await] AwaitExpression[?Yield]

13.5.1 delete 运算符

13.5.1.1 Static Semantics: 早期错误

UnaryExpression : delete UnaryExpression Note

最后一条规则意味着,像 delete (((foo))) 这样的表达式会由于递归应 用第一条规则而产生早期错误

13.5.1.2 Runtime Semantics: 求值

UnaryExpression : delete UnaryExpression
  1. ref 为 ? 对 UnaryExpression 求值。
  2. 如果 ref 不是一个 Reference Record,返回 true
  3. 如果 IsUnresolvableReference(ref) 为 true,那么
    1. 断言:ref.[[Strict]]false
    2. 返回 true
  4. 如果 IsPropertyReference(ref) 为 true,那么
    1. 断言:IsPrivateReference(ref) 为 false
    2. 如果 IsSuperReference(ref) 为 true,抛出一个 ReferenceError 异常。
    3. baseObj 为 ? ToObject(ref.[[Base]])。
    4. 如果 ref.[[ReferencedName]] 不是一个属性键,那么
      1. ref.[[ReferencedName]] 设为 ? ToPropertyKey(ref.[[ReferencedName]])。
    5. deleteStatus 为 ? baseObj.[[Delete]](ref.[[ReferencedName]])
    6. 如果 deleteStatusfalseref.[[Strict]]true,抛出一个 TypeError 异常。
    7. 返回 deleteStatus
  5. baseref.[[Base]]
  6. 断言:base 是一个 Environment Record
  7. 返回 ? base.DeleteBinding(ref.[[ReferencedName]])
Note 1

当一个 delete 运算符出现在严格模式代码中时,如果它的 UnaryExpression 是对变量、函数参数或函数名的直接引用,则会抛出一个 SyntaxError 异常。此外,如果 delete 运算符出现在严格模式代码中, 并且要删除的属性具有特性 { [[Configurable]]: false }(或者因其他原 因不可删除),则会抛出一个 TypeError 异常。

Note 2

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

13.5.2 void 运算符

13.5.2.1 Runtime Semantics: 求值

UnaryExpression : void UnaryExpression
  1. expr 为 ? 对 UnaryExpression 求值。
  2. 执行 ? GetValue(expr)。
  3. 返回 undefined
Note

即使不会使用其值,也必须调用 GetValue,因为它可能具有可观察的副作用。

13.5.3 typeof 运算符

13.5.3.1 Runtime Semantics: 求值

UnaryExpression : typeof UnaryExpression
  1. val 为 ? 对 UnaryExpression 求值。
  2. 如果 val 是一个 Reference Record,那么
    1. 如果 IsUnresolvableReference(val) 为 true,返回 "undefined"
  3. val 设为 ? GetValue(val)。
  4. 如果 valundefined,返回 "undefined"
  5. 如果 valnull,返回 "object"
  6. 如果 val 是一个 String,返回 "string"
  7. 如果 val 是一个 Symbol,返回 "symbol"
  8. 如果 val 是一个 Boolean,返回 "boolean"
  9. 如果 val 是一个 Number,返回 "number"
  10. 如果 val 是一个 BigInt,返回 "bigint"
  11. 断言:val 是一个 Object。
  12. Normative Optional
    如果宿主是 Web 浏览器,或以其他方式支持 [[IsHTMLDDA]] 内部槽,那么
    1. 如果 val 具有 [[IsHTMLDDA]] 内部槽,返回 "undefined"
  13. 如果 val 具有 [[Call]] 内部方法,返回 "function"
  14. 返回 "object"

13.5.4 一元 + 运算符

Note

一元 + 运算符会将其操作数转换为 Number 类型

13.5.4.1 Runtime Semantics: 求值

UnaryExpression : + UnaryExpression
  1. expr 为 ? 对 UnaryExpression 求值。
  2. 返回 ? ToNumber(? GetValue(expr))。

13.5.5 一元 - 运算符

Note

一元 - 运算符会将其操作数转换为一个数值,然后对其取反。对 +0𝔽 取反会得到 -0𝔽,而对 -0𝔽 取反会得到 +0𝔽

13.5.5.1 Runtime Semantics: 求值

UnaryExpression : - UnaryExpression
  1. expr 为 ? 对 UnaryExpression 求值。
  2. oldValue 为 ? ToNumeric(? GetValue(expr))。
  3. 如果 oldValue 是一个 Number,返回 Number::unaryMinus(oldValue)。
  4. 断言:oldValue 是一个 BigInt。
  5. 返回 BigInt::unaryMinus(oldValue)。

13.5.6 按位非运算符 ( ~ )

13.5.6.1 Runtime Semantics: 求值

UnaryExpression : ~ UnaryExpression
  1. expr 为 ? 对 UnaryExpression 求值。
  2. oldValue 为 ? ToNumeric(? GetValue(expr))。
  3. 如果 oldValue 是一个 Number,返回 Number::bitwiseNOT(oldValue)。
  4. 断言:oldValue 是一个 BigInt。
  5. 返回 BigInt::bitwiseNOT(oldValue)。

13.5.7 逻辑非运算符 ( ! )

13.5.7.1 Runtime Semantics: 求值

UnaryExpression : ! UnaryExpression
  1. expr 为 ? 对 UnaryExpression 求值。
  2. oldValueToBoolean(? GetValue(expr))。
  3. 如果 oldValuetrue,返回 false
  4. 返回 true

13.6 指数运算符

语法

ExponentiationExpression[Yield, Await] : UnaryExpression[?Yield, ?Await] UpdateExpression[?Yield, ?Await] ** ExponentiationExpression[?Yield, ?Await]

13.6.1 Runtime Semantics: 求值

ExponentiationExpression : UpdateExpression ** ExponentiationExpression
  1. 返回 ? EvaluateStringOrNumericBinaryExpression(UpdateExpression, **, ExponentiationExpression)。

13.7 乘法运算符

语法

MultiplicativeExpression[Yield, Await] : ExponentiationExpression[?Yield, ?Await] MultiplicativeExpression[?Yield, ?Await] MultiplicativeOperator ExponentiationExpression[?Yield, ?Await] MultiplicativeOperator : one of * / % Note
  • * 运算符执行乘法,产生其操作数的乘积。
  • / 运算符执行除法,产生其操作数的商。
  • % 运算符产生其操作数在一个隐含除法中的余数。

13.7.1 Runtime Semantics: 求值

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 加法运算符 ( + )

Note

加法运算符要么执行字符串串接,要么执行数值加法。

13.8.1.1 Runtime Semantics: 求值

AdditiveExpression : AdditiveExpression + MultiplicativeExpression
  1. 返回 ? EvaluateStringOrNumericBinaryExpression(AdditiveExpression, +, MultiplicativeExpression)。

13.8.2 减法运算符 ( - )

Note

- 运算符执行减法,产生其操作数的差。

13.8.2.1 Runtime Semantics: 求值

AdditiveExpression : AdditiveExpression - MultiplicativeExpression
  1. 返回 ? EvaluateStringOrNumericBinaryExpression(AdditiveExpression, -, MultiplicativeExpression)。

13.9 按位移位运算符

语法

ShiftExpression[Yield, Await] : AdditiveExpression[?Yield, ?Await] ShiftExpression[?Yield, ?Await] << AdditiveExpression[?Yield, ?Await] ShiftExpression[?Yield, ?Await] >> AdditiveExpression[?Yield, ?Await] ShiftExpression[?Yield, ?Await] >>> AdditiveExpression[?Yield, ?Await]

13.9.1 左移运算符 ( << )

Note

对左操作数执行按位左移,移位的位数由右操作数指定。

13.9.1.1 Runtime Semantics: 求值

ShiftExpression : ShiftExpression << AdditiveExpression
  1. 返回 ? EvaluateStringOrNumericBinaryExpression(ShiftExpression, <<, AdditiveExpression)。

13.9.2 有符号右移运算符 ( >> )

Note

对左操作数执行符号扩展的按位右移,移位的位数由右操作数指定。

13.9.2.1 Runtime Semantics: 求值

ShiftExpression : ShiftExpression >> AdditiveExpression
  1. 返回 ? EvaluateStringOrNumericBinaryExpression(ShiftExpression, >>, AdditiveExpression)。

13.9.3 无符号右移运算符 ( >>> )

Note

对左操作数执行零扩展的按位右移,移位的位数由右操作数指定。

13.9.3.1 Runtime Semantics: 求值

ShiftExpression : ShiftExpression >>> AdditiveExpression
  1. 返回 ? EvaluateStringOrNumericBinaryExpression(ShiftExpression, >>>, AdditiveExpression)。

13.10 关系运算符

Note 1

对关系运算符求值的结果总是 Boolean 类型,反映该运算符所命名的关系是否在 其两个操作数之间成立。

语法

RelationalExpression[In, Yield, Await] : ShiftExpression[?Yield, ?Await] RelationalExpression[?In, ?Yield, ?Await] < ShiftExpression[?Yield, ?Await] RelationalExpression[?In, ?Yield, ?Await] > ShiftExpression[?Yield, ?Await] RelationalExpression[?In, ?Yield, ?Await] <= ShiftExpression[?Yield, ?Await] RelationalExpression[?In, ?Yield, ?Await] >= ShiftExpression[?Yield, ?Await] RelationalExpression[?In, ?Yield, ?Await] instanceof ShiftExpression[?Yield, ?Await] [+In] RelationalExpression[+In, ?Yield, ?Await] in ShiftExpression[?Yield, ?Await] [+In] PrivateIdentifier in ShiftExpression[?Yield, ?Await] Note 2

[In] 文法参数是必需的,以避免将关系表达式中的 in 运算符与 for 语句中的 in 运算符混淆。

13.10.1 Runtime Semantics: 求值

RelationalExpression : RelationalExpression < ShiftExpression
  1. lRef 为 ? 对 RelationalExpression 求值。
  2. lVal 为 ? GetValue(lRef)。
  3. rRef 为 ? 对 ShiftExpression 求值。
  4. rVal 为 ? GetValue(rRef)。
  5. result 为 ? IsLessThan(lVal, rVal, true)。
  6. 如果 resultundefined,返回 false
  7. 返回 result
RelationalExpression : RelationalExpression > ShiftExpression
  1. lRef 为 ? 对 RelationalExpression 求值。
  2. lVal 为 ? GetValue(lRef)。
  3. rRef 为 ? 对 ShiftExpression 求值。
  4. rVal 为 ? GetValue(rRef)。
  5. result 为 ? IsLessThan(rVal, lVal, false)。
  6. 如果 resultundefined,返回 false
  7. 返回 result
RelationalExpression : RelationalExpression <= ShiftExpression
  1. lRef 为 ? 对 RelationalExpression 求值。
  2. lVal 为 ? GetValue(lRef)。
  3. rRef 为 ? 对 ShiftExpression 求值。
  4. rVal 为 ? GetValue(rRef)。
  5. result 为 ? IsLessThan(rVal, lVal, false)。
  6. 如果 resulttrueundefined,返回 false
  7. 返回 true
RelationalExpression : RelationalExpression >= ShiftExpression
  1. lRef 为 ? 对 RelationalExpression 求值。
  2. lVal 为 ? GetValue(lRef)。
  3. rRef 为 ? 对 ShiftExpression 求值。
  4. rVal 为 ? GetValue(rRef)。
  5. result 为 ? IsLessThan(lVal, rVal, true)。
  6. 如果 resulttrueundefined,返回 false
  7. 返回 true
RelationalExpression : RelationalExpression instanceof ShiftExpression
  1. lRef 为 ? 对 RelationalExpression 求值。
  2. lVal 为 ? GetValue(lRef)。
  3. rRef 为 ? 对 ShiftExpression 求值。
  4. rVal 为 ? GetValue(rRef)。
  5. 返回 ? InstanceofOperator(lVal, rVal)。
RelationalExpression : RelationalExpression in ShiftExpression
  1. lRef 为 ? 对 RelationalExpression 求值。
  2. lVal 为 ? GetValue(lRef)。
  3. rRef 为 ? 对 ShiftExpression 求值。
  4. rVal 为 ? GetValue(rRef)。
  5. 如果 rVal 不是一个 Object,抛出一个 TypeError 异常。
  6. 返回 ? HasProperty(rVal, ? ToPropertyKey(lVal))。
RelationalExpression : PrivateIdentifier in ShiftExpression
  1. privateIdentifierPrivateIdentifierStringValue
  2. rRef 为 ? 对 ShiftExpression 求值。
  3. rVal 为 ? GetValue(rRef)。
  4. 如果 rVal 不是一个 Object,抛出一个 TypeError 异常。
  5. privateEnv 为当前运行执行上下文的 PrivateEnvironment。
  6. 断言:privateEnv 不为 null
  7. privateNameResolvePrivateIdentifier(privateEnv, privateIdentifier)。
  8. 如果 PrivateElementFind(rVal, privateName) 为 empty,返回 false
  9. 返回 true

13.10.2 InstanceofOperator ( value, target )

The abstract operation InstanceofOperator takes arguments value (一个 ECMAScript 语言值) and target (一个 ECMAScript 语言值) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. 它实现了用于判定 value 是否是 target 的实例的通用算法:要么查阅 target%Symbol.hasInstance% 方法,要么(如果该方法不存在)通过判定 target"prototype" 属性值是否出现在 value 的原型链中来完成。 It performs the following steps when called:

  1. 如果 target 不是一个 Object,抛出一个 TypeError 异常。
  2. instOfHandler 为 ? GetMethod(target, %Symbol.hasInstance%)。
  3. 如果 instOfHandler 不为 undefined,那么
    1. 返回 ToBoolean(? Call(instOfHandler, target, « value »))。
  4. 如果 IsCallable(target) 为 false,抛出一个 TypeError 异常。
  5. 返回 ? OrdinaryHasInstance(target, value)。
Note

步骤 45 提供了与 ECMAScript 先前版本的兼容性;那些版本并未使用 %Symbol.hasInstance% 方法来定义 instanceof 运算符的语义。如果一个对象没有定义或继承 %Symbol.hasInstance%,则会使用默认的 instanceof 语义。

13.11 相等运算符

Note

对相等运算符求值的结果总是 Boolean 类型,反映该运算符所命名的关系是否在 其两个操作数之间成立。

语法

EqualityExpression[In, Yield, Await] : RelationalExpression[?In, ?Yield, ?Await] EqualityExpression[?In, ?Yield, ?Await] == RelationalExpression[?In, ?Yield, ?Await] EqualityExpression[?In, ?Yield, ?Await] != RelationalExpression[?In, ?Yield, ?Await] EqualityExpression[?In, ?Yield, ?Await] === RelationalExpression[?In, ?Yield, ?Await] EqualityExpression[?In, ?Yield, ?Await] !== RelationalExpression[?In, ?Yield, ?Await]

13.11.1 Runtime Semantics: 求值

EqualityExpression : EqualityExpression == RelationalExpression
  1. lRef 为 ? 对 EqualityExpression 求值。
  2. lVal 为 ? GetValue(lRef)。
  3. rRef 为 ? 对 RelationalExpression 求值。
  4. rVal 为 ? GetValue(rRef)。
  5. 返回 ? IsLooselyEqual(rVal, lVal)。
EqualityExpression : EqualityExpression != RelationalExpression
  1. lRef 为 ? 对 EqualityExpression 求值。
  2. lVal 为 ? GetValue(lRef)。
  3. rRef 为 ? 对 RelationalExpression 求值。
  4. rVal 为 ? GetValue(rRef)。
  5. r 为 ? IsLooselyEqual(rVal, lVal)。
  6. 如果 rtrue,返回 false
  7. 返回 true
EqualityExpression : EqualityExpression === RelationalExpression
  1. lRef 为 ? 对 EqualityExpression 求值。
  2. lVal 为 ? GetValue(lRef)。
  3. rRef 为 ? 对 RelationalExpression 求值。
  4. rVal 为 ? GetValue(rRef)。
  5. 返回 IsStrictlyEqual(rVal, lVal)。
EqualityExpression : EqualityExpression !== RelationalExpression
  1. lRef 为 ? 对 EqualityExpression 求值。
  2. lVal 为 ? GetValue(lRef)。
  3. rRef 为 ? 对 RelationalExpression 求值。
  4. rVal 为 ? GetValue(rRef)。
  5. rIsStrictlyEqual(rVal, lVal)。
  6. 如果 rtrue,返回 false
  7. 返回 true
Note 1

相等运算符保持以下不变量:

  • A != B 等价于 !(A == B)
  • A == B 等价于 B == A,除了 AB 的求值顺序不同之外。
Note 2

相等运算符并不总是具有传递性。例如,可能存在两个不同的 String 对象, 它们都表示相同的 String 值;每个 String 对象都会被 == 运算符视为与该 String 值相等,但这两个 String 对象彼此并不相等。例如:

  • new String("a") == "a""a" == new String("a") 都为 true
  • new String("a") == new String("a")false
Note 3

String 的比较使用的是对码元值序列的简单相等测试。不会尝试使用 Unicode 规范中定义的、更复杂且更偏语义化的字符或字符串相等与排序定义。因此,根据 Unicode 标准属于规范相等的 String 值,测试结果可能并不相等。实际上,该算 法假定两个 String 都已经处于规范化形式。

13.12 二元按位运算符

语法

BitwiseANDExpression[In, Yield, Await] : EqualityExpression[?In, ?Yield, ?Await] BitwiseANDExpression[?In, ?Yield, ?Await] & EqualityExpression[?In, ?Yield, ?Await] BitwiseXORExpression[In, Yield, Await] : BitwiseANDExpression[?In, ?Yield, ?Await] BitwiseXORExpression[?In, ?Yield, ?Await] ^ BitwiseANDExpression[?In, ?Yield, ?Await] BitwiseORExpression[In, Yield, Await] : BitwiseXORExpression[?In, ?Yield, ?Await] BitwiseORExpression[?In, ?Yield, ?Await] | BitwiseXORExpression[?In, ?Yield, ?Await]

13.12.1 Runtime Semantics: 求值

BitwiseANDExpression : BitwiseANDExpression & EqualityExpression
  1. 返回 ? EvaluateStringOrNumericBinaryExpression(BitwiseANDExpression, &, EqualityExpression)。
BitwiseXORExpression : BitwiseXORExpression ^ BitwiseANDExpression
  1. 返回 ? EvaluateStringOrNumericBinaryExpression(BitwiseXORExpression, ^, BitwiseANDExpression)。
BitwiseORExpression : BitwiseORExpression | BitwiseXORExpression
  1. 返回 ? EvaluateStringOrNumericBinaryExpression(BitwiseORExpression, |, BitwiseXORExpression)。

13.13 二元逻辑运算符

语法

LogicalANDExpression[In, Yield, Await] : BitwiseORExpression[?In, ?Yield, ?Await] LogicalANDExpression[?In, ?Yield, ?Await] && BitwiseORExpression[?In, ?Yield, ?Await] LogicalORExpression[In, Yield, Await] : LogicalANDExpression[?In, ?Yield, ?Await] LogicalORExpression[?In, ?Yield, ?Await] || LogicalANDExpression[?In, ?Yield, ?Await] CoalesceExpression[In, Yield, Await] : CoalesceExpressionHead[?In, ?Yield, ?Await] ?? BitwiseORExpression[?In, ?Yield, ?Await] CoalesceExpressionHead[In, Yield, Await] : CoalesceExpression[?In, ?Yield, ?Await] BitwiseORExpression[?In, ?Yield, ?Await] ShortCircuitExpression[In, Yield, Await] : LogicalORExpression[?In, ?Yield, ?Await] CoalesceExpression[?In, ?Yield, ?Await] Note

&&|| 运算符所产生的值不一定是 Boolean 类型。产生的值总是两个操作数表达式之一的值。

13.13.1 Runtime Semantics: 求值

LogicalANDExpression : LogicalANDExpression && BitwiseORExpression
  1. lRef 为 ? 对 LogicalANDExpression 求值。
  2. lVal 为 ? GetValue(lRef)。
  3. 如果 ToBoolean(lVal) 为 false,返回 lVal
  4. rRef 为 ? 对 BitwiseORExpression 求值。
  5. 返回 ? GetValue(rRef)。
LogicalORExpression : LogicalORExpression || LogicalANDExpression
  1. lRef 为 ? 对 LogicalORExpression 求值。
  2. lVal 为 ? GetValue(lRef)。
  3. 如果 ToBoolean(lVal) 为 true,返回 lVal
  4. rRef 为 ? 对 LogicalANDExpression 求值。
  5. 返回 ? GetValue(rRef)。
CoalesceExpression : CoalesceExpressionHead ?? BitwiseORExpression
  1. lRef 为 ? 对 CoalesceExpressionHead 求值。
  2. lVal 为 ? GetValue(lRef)。
  3. 如果 lVal 既不是 undefined 也不是 null,返回 lVal
  4. rRef 为 ? 对 BitwiseORExpression 求值。
  5. 返回 ? GetValue(rRef)。

13.14 条件运算符 ( ? : )

语法

ConditionalExpression[In, Yield, Await] : ShortCircuitExpression[?In, ?Yield, ?Await] ShortCircuitExpression[?In, ?Yield, ?Await] ? AssignmentExpression[+In, ?Yield, ?Await] : AssignmentExpression[?In, ?Yield, ?Await] Note

ECMAScript 中 ConditionalExpression 的文法与 C 和 Java 稍有不同;后 两者都允许第二个子表达式是一个 Expression,但将第三个表达式限制为一个 ConditionalExpression。ECMAScript 采用这种差异化设计的动机,是为了允 许赋值表达式受条件两支中的任一支控制,并消除将逗号表达式作为中间表达式这一 令人困惑且几乎无用的情形。

13.14.1 Runtime Semantics: 求值

ConditionalExpression : ShortCircuitExpression ? AssignmentExpression : AssignmentExpression
  1. lRef 为 ? 对 ShortCircuitExpression 求值。
  2. lValToBoolean(? GetValue(lRef))。
  3. 如果 lValtrue,那么
    1. trueRef 为 ? 对第一个 AssignmentExpression 求值。
    2. 返回 ? GetValue(trueRef)。
  4. falseRef 为 ? 对第二个 AssignmentExpression 求值。
  5. 返回 ? GetValue(falseRef)。

13.15 赋值运算符

语法

AssignmentExpression[In, Yield, Await] : ConditionalExpression[?In, ?Yield, ?Await] [+Yield] YieldExpression[?In, ?Await] ArrowFunction[?In, ?Yield, ?Await] AsyncArrowFunction[?In, ?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] = AssignmentExpression[?In, ?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] AssignmentOperator AssignmentExpression[?In, ?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] &&= AssignmentExpression[?In, ?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] ||= AssignmentExpression[?In, ?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] ??= AssignmentExpression[?In, ?Yield, ?Await] AssignmentOperator : one of *= /= %= += -= <<= >>= >>>= &= ^= |= **=

13.15.1 Static Semantics: 早期错误

AssignmentExpression : LeftHandSideExpression = AssignmentExpression AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression AssignmentExpression : LeftHandSideExpression &&= AssignmentExpression LeftHandSideExpression ||= AssignmentExpression LeftHandSideExpression ??= AssignmentExpression

13.15.2 Runtime Semantics: 求值

AssignmentExpression : LeftHandSideExpression = AssignmentExpression
  1. 如果 LeftHandSideExpression 既不是 ObjectLiteral 也不是 ArrayLiteral,那么
    1. lRef 为 ? 对 LeftHandSideExpression 求值。
    2. 如果 LeftHandSideExpressionAssignmentTargetTypeweb-compat,抛出一个 ReferenceError 异常。
    3. 如果 IsAnonymousFunctionDefinition(AssignmentExpression) 为 trueIsIdentifierRef of LeftHandSideExpressiontrue,那么
      1. lhsLeftHandSideExpressionStringValue
      2. rVal 为 ? 对 AssignmentExpression 执行 NamedEvaluation,并以 lhs 为参数。
    4. 否则,
      1. rRef 为 ? 对 AssignmentExpression 求值。
      2. rVal 为 ? GetValue(rRef)。
    5. 执行 ? PutValue(lRef, rVal)。
    6. 返回 rVal
  2. assignmentPattern 为被 LeftHandSideExpression 覆盖AssignmentPattern
  3. rRef 为 ? 对 AssignmentExpression 求值。
  4. rVal 为 ? GetValue(rRef)。
  5. 执行 ? 对 assignmentPattern 执行 DestructuringAssignmentEvaluation,并以 rVal 为参数。
  6. 返回 rVal
AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression
  1. lRef 为 ? 对 LeftHandSideExpression 求值。
  2. 如果 LeftHandSideExpressionAssignmentTargetTypeweb-compat,抛出一个 ReferenceError 异常。
  3. lVal 为 ? GetValue(lRef)。
  4. rRef 为 ? 对 AssignmentExpression 求值。
  5. rVal 为 ? GetValue(rRef)。
  6. assignmentOpTextAssignmentOperator匹配的源文本
  7. opText 为与 assignmentOpText 在下表中对应的 Unicode 码点序列:
    assignmentOpText opText
    **= **
    *= *
    /= /
    %= %
    += +
    -= -
    <<= <<
    >>= >>
    >>>= >>>
    &= &
    ^= ^
    |= |
  8. r 为 ? ApplyStringOrNumericBinaryOperator(lVal, opText, rVal)。
  9. 执行 ? PutValue(lRef, r)。
  10. 返回 r
AssignmentExpression : LeftHandSideExpression &&= AssignmentExpression
  1. lRef 为 ? 对 LeftHandSideExpression 求值。
  2. lVal 为 ? GetValue(lRef)。
  3. 如果 ToBoolean(lVal) 为 false,返回 lVal
  4. 如果 IsAnonymousFunctionDefinition(AssignmentExpression) 为 trueIsIdentifierRef of LeftHandSideExpressiontrue,那么
    1. lhsLeftHandSideExpressionStringValue
    2. rVal 为 ? 对 AssignmentExpression 执行 NamedEvaluation,并以 lhs 为参数。
  5. 否则,
    1. rRef 为 ? 对 AssignmentExpression 求值。
    2. rVal 为 ? GetValue(rRef)。
  6. 执行 ? PutValue(lRef, rVal)。
  7. 返回 rVal
AssignmentExpression : LeftHandSideExpression ||= AssignmentExpression
  1. lRef 为 ? 对 LeftHandSideExpression 求值。
  2. lVal 为 ? GetValue(lRef)。
  3. 如果 ToBoolean(lVal) 为 true,返回 lVal
  4. 如果 IsAnonymousFunctionDefinition(AssignmentExpression) 为 trueIsIdentifierRef of LeftHandSideExpressiontrue,那么
    1. lhsLeftHandSideExpressionStringValue
    2. rVal 为 ? 对 AssignmentExpression 执行 NamedEvaluation,并以 lhs 为参数。
  5. 否则,
    1. rRef 为 ? 对 AssignmentExpression 求值。
    2. rVal 为 ? GetValue(rRef)。
  6. 执行 ? PutValue(lRef, rVal)。
  7. 返回 rVal
AssignmentExpression : LeftHandSideExpression ??= AssignmentExpression
  1. lRef 为 ? 对 LeftHandSideExpression 求值。
  2. lVal 为 ? GetValue(lRef)。
  3. 如果 lVal 既不是 undefined 也不是 null,返回 lVal
  4. 如果 IsAnonymousFunctionDefinition(AssignmentExpression) 为 trueIsIdentifierRef of LeftHandSideExpressiontrue,那么
    1. lhsLeftHandSideExpressionStringValue
    2. rVal 为 ? 对 AssignmentExpression 执行 NamedEvaluation,并以 lhs 为参数。
  5. 否则,
    1. rRef 为 ? 对 AssignmentExpression 求值。
    2. rVal 为 ? GetValue(rRef)。
  6. 执行 ? PutValue(lRef, rVal)。
  7. 返回 rVal
Note

当该表达式出现在严格模式代码中时,如果步骤 1.e3222 中的 lRef 是一个不可解析引用,则会发生运行时错误。如果是这种情况,会抛出 一个 ReferenceError 异常。此外,如果步骤 9666 中的 lRef 是对某个数据属性的引用,而该属性具有特性值 { [[Writable]]: false },或者是对某个访问器属性的引用,而该属性具有特 性值 { [[Set]]: undefined },或者是对某个不可扩展对象上不存在属性的引 用,则也会发生运行时错误。在这些情况下会抛出一个 TypeError 异常。

13.15.3 ApplyStringOrNumericBinaryOperator ( lVal, opText, rVal )

The abstract operation ApplyStringOrNumericBinaryOperator takes arguments lVal (一个 ECMAScript 语言值), opText (***/%+-<<>>>>>&^|), and rVal (一个 ECMAScript 语言值) and returns 要么是一个正常完成,包含一个 String、一个 BigInt 或一个 Number,要么是一个抛出完成. It performs the following steps when called:

  1. 如果 opText+,那么
    1. lPrim 为 ? ToPrimitive(lVal)。
    2. rPrim 为 ? ToPrimitive(rVal)。
    3. 如果 lPrim 是一个 String 或 rPrim 是一个 String,那么
      1. lStr 为 ? ToString(lPrim)。
      2. rStr 为 ? ToString(rPrim)。
      3. 返回 lStrrStr 的字符串串接结果。
    4. lVal 设为 lPrim
    5. rVal 设为 rPrim
  2. NOTE: 到此为止,它必须是一个数值运算。
  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)。
Note 1

在步骤 1.a1.b 中对 ToPrimitive 的调用没有提供 hint。除 Date 外,所有标准对象在缺少 hint 时都按给出 number 的方式处理;Date 在缺少 hint 时则按给出 string 的方式处理。异质对象可能会以其他方式处理缺少 hint 的情况。

Note 2

步骤 1.cIsLessThan 算法的步骤 3 不同, 这里使用逻辑或运算,而不是逻辑与运算。

13.15.4 EvaluateStringOrNumericBinaryExpression ( leftOperand, opText, rightOperand )

The abstract operation EvaluateStringOrNumericBinaryExpression takes arguments leftOperand (a Parse Node), opText (**, *, /, %, +, -, <<, >>, >>>, &, ^, or |), and rightOperand (a Parse Node) and returns either a normal completion containing either a String, a BigInt, or a Number, or an abrupt completion. It performs the following steps when called:

  1. lRef 为 ? 对 leftOperand 求值。
  2. lVal 为 ? GetValue(lRef)。
  3. rRef 为 ? 对 rightOperand 求值。
  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 Static Semantics: 早期错误

AssignmentProperty : IdentifierReference Initializeropt AssignmentRestProperty : ... DestructuringAssignmentTarget DestructuringAssignmentTarget : LeftHandSideExpression

13.15.5.2 Runtime Semantics: DestructuringAssignmentEvaluation

The syntax-directed operation DestructuringAssignmentEvaluation takes argument value (一个 ECMAScript 语言值) and returns 要么是一个正常完成,包含 unused,要么是一个突然完成. It is defined piecewise over the following productions:

ObjectAssignmentPattern : { }
  1. 执行 ? RequireObjectCoercible(value)。
  2. 返回 unused
ObjectAssignmentPattern : { AssignmentPropertyList } { AssignmentPropertyList , }
  1. 执行 ? RequireObjectCoercible(value)。
  2. 执行 ? 对 AssignmentPropertyList 执行 PropertyDestructuringAssignmentEvaluation,并以 value 为参数。
  3. 返回 unused
ObjectAssignmentPattern : { AssignmentRestProperty }
  1. 执行 ? RequireObjectCoercible(value)。
  2. excludedNames 为一个新的空列表。
  3. 返回 ? 对 AssignmentRestProperty 执行 RestDestructuringAssignmentEvaluation,并以 valueexcludedNames 为参数。
ObjectAssignmentPattern : { AssignmentPropertyList , AssignmentRestProperty }
  1. 执行 ? RequireObjectCoercible(value)。
  2. excludedNames 为 ? 对 AssignmentPropertyList 执行 PropertyDestructuringAssignmentEvaluation,并以 value 为参数。
  3. 返回 ? 对 AssignmentRestProperty 执行 RestDestructuringAssignmentEvaluation,并以 valueexcludedNames 为参数。
ArrayAssignmentPattern : [ ]
  1. iteratorRecord 为 ? GetIterator(value, sync)。
  2. 返回 ? IteratorClose(iteratorRecord, NormalCompletion(unused))。
ArrayAssignmentPattern : [ Elision ]
  1. iteratorRecord 为 ? GetIterator(value, sync)。
  2. resultCompletion(对 Elision 执行 IteratorDestructuringAssignmentEvaluation,并以 iteratorRecord 为参数)。
  3. 如果 iteratorRecord.[[Done]]false,返回 ? IteratorClose(iteratorRecord, result)。
  4. 返回 result
ArrayAssignmentPattern : [ Elisionopt AssignmentRestElement ]
  1. iteratorRecord 为 ? GetIterator(value, sync)。
  2. 如果 Elision 存在,那么
    1. statusCompletion(对 Elision 执行 IteratorDestructuringAssignmentEvaluation,并以 iteratorRecord 为参数)。
    2. 如果 status 是一个突然完成,那么
      1. 断言:iteratorRecord.[[Done]]true
      2. 返回 ? status
  3. resultCompletion(对 AssignmentRestElement 执行 IteratorDestructuringAssignmentEvaluation,并以 iteratorRecord 为参数)。
  4. 如果 iteratorRecord.[[Done]]false,返回 ? IteratorClose(iteratorRecord, result)。
  5. 返回 result
ArrayAssignmentPattern : [ AssignmentElementList ]
  1. iteratorRecord 为 ? GetIterator(value, sync)。
  2. resultCompletion(对 AssignmentElementList 执行 IteratorDestructuringAssignmentEvaluation,并以 iteratorRecord 为参数)。
  3. 如果 iteratorRecord.[[Done]]false,返回 ? IteratorClose(iteratorRecord, result)。
  4. 返回 result
ArrayAssignmentPattern : [ AssignmentElementList , Elisionopt AssignmentRestElementopt ]
  1. iteratorRecord 为 ? GetIterator(value, sync)。
  2. statusCompletion(对 AssignmentElementList 执行 IteratorDestructuringAssignmentEvaluation,并以 iteratorRecord 为参数)。
  3. 如果 status 是一个突然完成,那么
    1. 如果 iteratorRecord.[[Done]]false,返回 ? IteratorClose(iteratorRecord, status)。
    2. 返回 ? status
  4. 如果 Elision 存在,那么
    1. status 设为 Completion(对 Elision 执行 IteratorDestructuringAssignmentEvaluation,并以 iteratorRecord 为参数)。
    2. 如果 status 是一个突然完成,那么
      1. 断言:iteratorRecord.[[Done]]true
      2. 返回 ? status
  5. 如果 AssignmentRestElement 存在,那么
    1. status 设为 Completion(对 AssignmentRestElement 执行 IteratorDestructuringAssignmentEvaluation,并以 iteratorRecord 为参数)。
  6. 如果 iteratorRecord.[[Done]]false,返回 ? IteratorClose(iteratorRecord, status)。
  7. 返回 ? status

13.15.5.3 Runtime Semantics: PropertyDestructuringAssignmentEvaluation

The syntax-directed operation PropertyDestructuringAssignmentEvaluation takes argument value (一个 ECMAScript 语言值) and returns 要么是一个正常完成,包含一个属性键列表,要么是一个突然完成. 它收集所有被解构属性键的列表。 It is defined piecewise over the following productions:

AssignmentPropertyList : AssignmentPropertyList , AssignmentProperty
  1. propertyNames 为 ? 对 AssignmentPropertyList 执行 PropertyDestructuringAssignmentEvaluation,并以 value 为参数。
  2. nextNames 为 ? 对 AssignmentProperty 执行 PropertyDestructuringAssignmentEvaluation,并以 value 为参数。
  3. 返回 propertyNamesnextNames 的列表串接。
AssignmentProperty : IdentifierReference Initializeropt
  1. propertyNameIdentifierReferenceStringValue
  2. lRef 为 ? ResolveBinding(propertyName)。
  3. v 为 ? GetV(value, propertyName)。
  4. 如果 Initializer 存在且 vundefined,那么
    1. 如果 IsAnonymousFunctionDefinition(Initializer) 为 true,那么
      1. v 设为 ? 对 Initializer 执行 NamedEvaluation,并以 propertyName 为参数。
    2. 否则,
      1. defaultValue 为 ? 对 Initializer 求值。
      2. v 设为 ? GetValue(defaultValue)。
  5. 执行 ? PutValue(lRef, v)。
  6. 返回 « propertyName »。
AssignmentProperty : PropertyName : AssignmentElement
  1. name 为 ? 对 PropertyName 求值。
  2. 执行 ? 对 AssignmentElement 执行 KeyedDestructuringAssignmentEvaluation,并以 valuename 为参数。
  3. 返回 « name »。

13.15.5.4 Runtime Semantics: RestDestructuringAssignmentEvaluation

The syntax-directed operation RestDestructuringAssignmentEvaluation takes arguments value (一个 ECMAScript 语言值) and excludedNames (一个属性键列表) and returns 要么是一个正常完成,包含 unused,要么是一个突然完成. It is defined piecewise over the following productions:

AssignmentRestProperty : ... DestructuringAssignmentTarget
  1. lRef 为 ? 对 DestructuringAssignmentTarget 求值。
  2. restObjOrdinaryObjectCreate(%Object.prototype%)。
  3. 执行 ? CopyDataProperties(restObj, value, excludedNames)。
  4. 返回 ? PutValue(lRef, restObj)。

13.15.5.5 Runtime Semantics: IteratorDestructuringAssignmentEvaluation

The syntax-directed operation IteratorDestructuringAssignmentEvaluation takes argument iteratorRecord (一个 Iterator Record) and returns 要么是一个正常完成,包含 unused,要么是一个突然完成. It is defined piecewise over the following productions:

AssignmentElementList : AssignmentElisionElement
  1. 返回 ? 对 AssignmentElisionElement 执行 IteratorDestructuringAssignmentEvaluation,并以 iteratorRecord 为参数。
AssignmentElementList : AssignmentElementList , AssignmentElisionElement
  1. 执行 ? 对 AssignmentElementList 执行 IteratorDestructuringAssignmentEvaluation,并以 iteratorRecord 为参数。
  2. 返回 ? 对 AssignmentElisionElement 执行 IteratorDestructuringAssignmentEvaluation,并以 iteratorRecord 为参数。
AssignmentElisionElement : AssignmentElement
  1. 返回 ? 对 AssignmentElement 执行 IteratorDestructuringAssignmentEvaluation,并以 iteratorRecord 为参数。
AssignmentElisionElement : Elision AssignmentElement
  1. 执行 ? 对 Elision 执行 IteratorDestructuringAssignmentEvaluation,并以 iteratorRecord 为参数。
  2. 返回 ? 对 AssignmentElement 执行 IteratorDestructuringAssignmentEvaluation,并以 iteratorRecord 为参数。
Elision : ,
  1. 如果 iteratorRecord.[[Done]]false,那么
    1. 执行 ? IteratorStep(iteratorRecord)。
  2. 返回 unused
Elision : Elision ,
  1. 执行 ? 对 Elision 执行 IteratorDestructuringAssignmentEvaluation,并以 iteratorRecord 为参数。
  2. 如果 iteratorRecord.[[Done]]false,那么
    1. 执行 ? IteratorStep(iteratorRecord)。
  3. 返回 unused
AssignmentElement : DestructuringAssignmentTarget Initializeropt
  1. 如果 DestructuringAssignmentTarget 既不是 ObjectLiteral 也不是 ArrayLiteral,那么
    1. lRef 为 ? 对 DestructuringAssignmentTarget 求值。
  2. valueundefined
  3. 如果 iteratorRecord.[[Done]]false,那么
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 next 不为 done,那么
      1. value 设为 next
  4. 如果 Initializer 存在且 valueundefined,那么
    1. 如果 IsAnonymousFunctionDefinition(Initializer) 为 trueIsIdentifierRef of DestructuringAssignmentTargettrue,那么
      1. targetDestructuringAssignmentTargetStringValue
      2. v 为 ? 对 Initializer 执行 NamedEvaluation,并以 target 为参数。
    2. 否则,
      1. defaultValue 为 ? 对 Initializer 求值。
      2. v 为 ? GetValue(defaultValue)。
  5. 否则,
    1. vvalue
  6. 如果 DestructuringAssignmentTarget 是一个 ObjectLiteral 或一个 ArrayLiteral,那么
    1. nestedAssignmentPattern 为被 DestructuringAssignmentTarget 覆盖AssignmentPattern
    2. 返回 ? 对 nestedAssignmentPattern 执行 DestructuringAssignmentEvaluation,并以 v 为参数。
  7. 返回 ? PutValue(lRef, v)。
Note

从左到右的求值顺序通过如下方式得到保持:对于不是解构模式的 DestructuringAssignmentTarget,会在访问迭代器或对 Initializer 求值之前先对其求值。

AssignmentRestElement : ... DestructuringAssignmentTarget
  1. 如果 DestructuringAssignmentTarget 既不是 ObjectLiteral 也不是 ArrayLiteral,那么
    1. lRef 为 ? 对 DestructuringAssignmentTarget 求值。
  2. array 为 ! ArrayCreate(0)。
  3. n 为 0。
  4. 重复,当 iteratorRecord.[[Done]]false 时,
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 next 不为 done,那么
      1. 执行 ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(n)), next)。
      2. n 设为 n + 1。
  5. 如果 DestructuringAssignmentTarget 既不是 ObjectLiteral 也不是 ArrayLiteral,那么
    1. 返回 ? PutValue(lRef, array)。
  6. nestedAssignmentPattern 为被 DestructuringAssignmentTarget 覆盖AssignmentPattern
  7. 返回 ? 对 nestedAssignmentPattern 执行 DestructuringAssignmentEvaluation,并以 array 为参数。

13.15.5.6 Runtime Semantics: KeyedDestructuringAssignmentEvaluation

The syntax-directed operation KeyedDestructuringAssignmentEvaluation takes arguments value (一个 ECMAScript 语言值) and propertyName (一个属性键) and returns 要么是一个正常完成,包含 unused,要么是一个突然完成. It is defined piecewise over the following productions:

AssignmentElement : DestructuringAssignmentTarget Initializeropt
  1. 如果 DestructuringAssignmentTarget 既不是 ObjectLiteral 也不是 ArrayLiteral,那么
    1. lRef 为 ? 对 DestructuringAssignmentTarget 求值。
  2. v 为 ? GetV(value, propertyName)。
  3. 如果 Initializer 存在且 vundefined,那么
    1. 如果 IsAnonymousFunctionDefinition(Initializer) 为 trueIsIdentifierRef of DestructuringAssignmentTargettrue,那么
      1. targetDestructuringAssignmentTargetStringValue
      2. rhsValue 为 ? 对 Initializer 执行 NamedEvaluation,并以 target 为参数。
    2. 否则,
      1. defaultValue 为 ? 对 Initializer 求值。
      2. rhsValue 为 ? GetValue(defaultValue)。
  4. 否则,
    1. rhsValuev
  5. 如果 DestructuringAssignmentTarget 是一个 ObjectLiteral 或一个 ArrayLiteral,那么
    1. assignmentPattern 为被 DestructuringAssignmentTarget 覆盖AssignmentPattern
    2. 返回 ? 对 assignmentPattern 执行 DestructuringAssignmentEvaluation,并以 rhsValue 为参数。
  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 Runtime Semantics: 求值

Expression : Expression , AssignmentExpression
  1. lRef 为 ? 对 Expression 求值。
  2. 执行 ? GetValue(lRef)。
  3. rRef 为 ? 对 AssignmentExpression 求值。
  4. 返回 ? GetValue(rRef)。
Note

即使不会使用其值,也必须调用 GetValue,因为它可能具有可观察的副作用。

14 ECMAScript 语言:语句和声明

语法

Statement[Yield, Await, Return] : BlockStatement[?Yield, ?Await, ?Return] VariableStatement[?Yield, ?Await] EmptyStatement ExpressionStatement[?Yield, ?Await] IfStatement[?Yield, ?Await, ?Return] BreakableStatement[?Yield, ?Await, ?Return] ContinueStatement[?Yield, ?Await] BreakStatement[?Yield, ?Await] [+Return] ReturnStatement[?Yield, ?Await] WithStatement[?Yield, ?Await, ?Return] LabelledStatement[?Yield, ?Await, ?Return] ThrowStatement[?Yield, ?Await] TryStatement[?Yield, ?Await, ?Return] DebuggerStatement Declaration[Yield, Await] : HoistableDeclaration[?Yield, ?Await, ~Default] ClassDeclaration[?Yield, ?Await, ~Default] LexicalDeclaration[+In, ?Yield, ?Await] HoistableDeclaration[Yield, Await, Default] : FunctionDeclaration[?Yield, ?Await, ?Default] GeneratorDeclaration[?Yield, ?Await, ?Default] AsyncFunctionDeclaration[?Yield, ?Await, ?Default] AsyncGeneratorDeclaration[?Yield, ?Await, ?Default] BreakableStatement[Yield, Await, Return] : IterationStatement[?Yield, ?Await, ?Return] SwitchStatement[?Yield, ?Await, ?Return]

14.1 语句语义

14.1.1 Runtime Semantics: 求值

HoistableDeclaration : GeneratorDeclaration AsyncFunctionDeclaration AsyncGeneratorDeclaration
  1. 返回 empty
HoistableDeclaration : FunctionDeclaration
  1. 返回 ? 对 FunctionDeclaration 求值。
BreakableStatement : IterationStatement SwitchStatement
  1. newLabelSet 为一个新的空列表。
  2. 返回 ? 对该 BreakableStatement 执行 LabelledEvaluation,并以 newLabelSet 为参数。

14.2

语法

BlockStatement[Yield, Await, Return] : Block[?Yield, ?Await, ?Return] Block[Yield, Await, Return] : { StatementList[?Yield, ?Await, ?Return]opt } StatementList[Yield, Await, Return] : StatementListItem[?Yield, ?Await, ?Return] StatementList[?Yield, ?Await, ?Return] StatementListItem[?Yield, ?Await, ?Return] StatementListItem[Yield, Await, Return] : Statement[?Yield, ?Await, ?Return] Declaration[?Yield, ?Await]

14.2.1 Static Semantics: 早期错误

Block : { StatementList }

14.2.2 Runtime Semantics: 求值

Block : { }
  1. 返回 empty
Block : { StatementList }
  1. oldEnv 为当前运行执行上下文的 LexicalEnvironment。
  2. blockEnvNewDeclarativeEnvironment(oldEnv)。
  3. 执行 BlockDeclarationInstantiation(StatementList, blockEnv)。
  4. 将当前运行执行上下文的 LexicalEnvironment 设为 blockEnv
  5. blockValueCompletion(对 StatementList 求值)。
  6. 将当前运行执行上下文的 LexicalEnvironment 设为 oldEnv
  7. 返回 ? blockValue
Note 1

无论控制以何种方式离开 Block,LexicalEnvironment 总是会恢复到其原先状态。

StatementList : StatementList StatementListItem
  1. sl 为 ? 对 StatementList 求值。
  2. sCompletion(对 StatementListItem 求值)。
  3. 返回 ? UpdateEmpty(s, sl)。
Note 2

StatementList 的值是该 StatementList 中最后一个产生值的项的值。 例如,以下对 eval 函数的调用都返回值 1:

eval("1;;;;;")
eval("1;{}")
eval("1;var a;")

14.2.3 BlockDeclarationInstantiation ( code, env )

The abstract operation BlockDeclarationInstantiation takes arguments code (一个 Parse Node) and env (一个 Declarative Environment Record) and returns unused. code 是对应于块体的 Parse Node。env 是要在其中创建绑定的 Environment Record

Note

当对一个 BlockCaseBlock 求值时,会创建一个新的 Declarative Environment Record,并且块中声明的每个块作用域变量、常量、函数或类的绑 定都会在该 Environment Record 中实例化。

被调用时它执行以下步骤:

  1. declarationscodeLexicallyScopedDeclarations
  2. privateEnv 为当前运行执行上下文的 PrivateEnvironment。
  3. 对于 declarations 中的每个元素 decl,执行
    1. 对于 declBoundNames 中的每个元素 dn,执行
      1. 如果 declIsConstantDeclarationtrue,那么
        1. 执行 ! env.CreateImmutableBinding(dn, true)。
      2. 否则,
        1. Normative Optional
          如果宿主是 Web 浏览器或以其他方式支持 块级函数声明的 Web 遗留兼容性语义,那么
          1. 如果 ! env.HasBinding(dn) 为 false,那么
            1. 执行 ! env.CreateMutableBinding(dn, false)。
        2. 否则,
          1. 执行 ! env.CreateMutableBinding(dn, false)。
    2. 如果 declFunctionDeclarationGeneratorDeclarationAsyncFunctionDeclarationAsyncGeneratorDeclaration 之一,那么
      1. fndeclBoundNames 的唯一元素。
      2. fo 为对 decl 执行 InstantiateFunctionObject,并以 envprivateEnv 为参数。
      3. Normative Optional
        如果宿主是 Web 浏览器或以其他方式支持 块级函数声明的 Web 遗留兼容性语义,那么
        1. 如果 envfn 的绑定是一个未初始化绑定,那么
          1. 执行 ! env.InitializeBinding(fn, fo)。
        2. 否则,
          1. 断言:decl 是一个 FunctionDeclaration
          2. 执行 ! env.SetMutableBinding(fn, fo, false)。
      4. 否则,
        1. 执行 ! env.InitializeBinding(fn, fo)。
  4. 返回 unused

14.3 声明与变量语句

14.3.1 Let 和 Const 声明

Note

letconst 声明定义的是作用域限于当前运行执行上下文的 LexicalEnvironment 的变量。这些变量在其所在的 Environment Record 实例 化时被创建,但在该变量的 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 Static Semantics: 早期错误

LexicalDeclaration : LetOrConst BindingList ; LexicalBinding : BindingIdentifier Initializeropt

14.3.1.2 Runtime Semantics: 求值

LexicalDeclaration : LetOrConst BindingList ;
  1. 执行 ? 对 BindingList 求值。
  2. 返回 empty
BindingList : BindingList , LexicalBinding
  1. 执行 ? 对 BindingList 求值。
  2. 返回 ? 对 LexicalBinding 求值。
LexicalBinding : BindingIdentifier
  1. lhs 为 ! ResolveBinding(StringValue of BindingIdentifier)。
  2. 执行 ! InitializeReferencedBinding(lhs, undefined)。
  3. 返回 empty
Note

一条静态语义规则保证这种形式的 LexicalBinding 永远不会出现在 const 声明中。

LexicalBinding : BindingIdentifier Initializer
  1. bindingIdBindingIdentifierStringValue
  2. lhs 为 ! ResolveBinding(bindingId)。
  3. 如果 IsAnonymousFunctionDefinition(Initializer) 为 true,那么
    1. value 为 ? 对 Initializer 执行 NamedEvaluation,并以 bindingId 为参数。
  4. 否则,
    1. rhs 为 ? 对 Initializer 求值。
    2. value 为 ? GetValue(rhs)。
  5. 执行 ! InitializeReferencedBinding(lhs, value)。
  6. 返回 empty
LexicalBinding : BindingPattern Initializer
  1. rhs 为 ? 对 Initializer 求值。
  2. value 为 ? GetValue(rhs)。
  3. env 为当前运行执行上下文的 LexicalEnvironment。
  4. 返回 ? 对 BindingPattern 执行 BindingInitialization,并以 valueenv 为参数。

14.3.2 变量语句

Note

var 语句声明的是作用域限于当前运行执行上下文的 VariableEnvironment 的变量。var 变量在其所在的 Environment Record 实例 化时被创建,并在创建时初始化为 undefined。在任意 VariableEnvironment 的作用域内,同一个 BindingIdentifier 可以出现在 多个 VariableDeclaration 中,但这些声明共同只定义一个变量。由带有 InitializerVariableDeclaration 所定义的变量,会在该 VariableDeclaration 执行时被赋予其 InitializerAssignmentExpression 的值,而不是在变量创建时赋值。

语法

VariableStatement[Yield, Await] : var VariableDeclarationList[+In, ?Yield, ?Await] ; VariableDeclarationList[In, Yield, Await] : VariableDeclaration[?In, ?Yield, ?Await] VariableDeclarationList[?In, ?Yield, ?Await] , VariableDeclaration[?In, ?Yield, ?Await] VariableDeclaration[In, Yield, Await] : BindingIdentifier[?Yield, ?Await] Initializer[?In, ?Yield, ?Await]opt BindingPattern[?Yield, ?Await] Initializer[?In, ?Yield, ?Await]

14.3.2.1 Runtime Semantics: 求值

VariableStatement : var VariableDeclarationList ;
  1. 执行 ? 对 VariableDeclarationList 求值。
  2. 返回 empty
VariableDeclarationList : VariableDeclarationList , VariableDeclaration
  1. 执行 ? 对 VariableDeclarationList 求值。
  2. 返回 ? 对 VariableDeclaration 求值。
VariableDeclaration : BindingIdentifier
  1. 返回 empty
VariableDeclaration : BindingIdentifier Initializer
  1. bindingIdBindingIdentifierStringValue
  2. lhs 为 ? ResolveBinding(bindingId)。
  3. 如果 IsAnonymousFunctionDefinition(Initializer) 为 true,那么
    1. value 为 ? 对 Initializer 执行 NamedEvaluation,并以 bindingId 为参数。
  4. 否则,
    1. rhs 为 ? 对 Initializer 求值。
    2. value 为 ? GetValue(rhs)。
  5. 执行 ? PutValue(lhs, value)。
  6. 返回 empty
Note

如果某个 VariableDeclaration 嵌套在一个 with 语句内部,并且该 VariableDeclaration 中的 BindingIdentifier 与该 with 语句的对象 环境记录的绑定对象的某个属性名相同,那么步骤 5 会将 value 赋给该属性,而不是赋给 Identifier 的 VariableEnvironment 绑定。

VariableDeclaration : BindingPattern Initializer
  1. rhs 为 ? 对 Initializer 求值。
  2. rVal 为 ? GetValue(rhs)。
  3. 返回 ? 对 BindingPattern 执行 BindingInitialization,并以 rValundefined 为参数。

14.3.3 解构绑定模式

语法

BindingPattern[Yield, Await] : ObjectBindingPattern[?Yield, ?Await] ArrayBindingPattern[?Yield, ?Await] ObjectBindingPattern[Yield, Await] : { } { BindingRestProperty[?Yield, ?Await] } { BindingPropertyList[?Yield, ?Await] } { BindingPropertyList[?Yield, ?Await] , BindingRestProperty[?Yield, ?Await]opt } ArrayBindingPattern[Yield, Await] : [ Elisionopt BindingRestElement[?Yield, ?Await]opt ] [ BindingElementList[?Yield, ?Await] ] [ BindingElementList[?Yield, ?Await] , Elisionopt BindingRestElement[?Yield, ?Await]opt ] BindingRestProperty[Yield, Await] : ... BindingIdentifier[?Yield, ?Await] BindingPropertyList[Yield, Await] : BindingProperty[?Yield, ?Await] BindingPropertyList[?Yield, ?Await] , BindingProperty[?Yield, ?Await] BindingElementList[Yield, Await] : BindingElisionElement[?Yield, ?Await] BindingElementList[?Yield, ?Await] , BindingElisionElement[?Yield, ?Await] BindingElisionElement[Yield, Await] : Elisionopt BindingElement[?Yield, ?Await] BindingProperty[Yield, Await] : SingleNameBinding[?Yield, ?Await] PropertyName[?Yield, ?Await] : BindingElement[?Yield, ?Await] BindingElement[Yield, Await] : SingleNameBinding[?Yield, ?Await] BindingPattern[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]opt SingleNameBinding[Yield, Await] : BindingIdentifier[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]opt BindingRestElement[Yield, Await] : ... BindingIdentifier[?Yield, ?Await] ... BindingPattern[?Yield, ?Await]

14.3.3.1 Runtime Semantics: PropertyBindingInitialization

The syntax-directed operation PropertyBindingInitialization takes arguments value (一个 ECMAScript 语言值) and environment (一个 Environment Recordundefined) and returns 要么是一个正常完成,包含一个属性键列表,要么是一个突然完成. 它收集所有被绑定的属性名的列表。 It is defined piecewise over the following productions:

BindingPropertyList : BindingPropertyList , BindingProperty
  1. boundNames 为 ? 对 BindingPropertyList 执行 PropertyBindingInitialization,并以 valueenvironment 为参 数。
  2. nextNames 为 ? 对 BindingProperty 执行 PropertyBindingInitialization,并以 valueenvironment 为参 数。
  3. 返回 boundNamesnextNames 的列表串接。
BindingProperty : SingleNameBinding
  1. nameSingleNameBindingBoundNames 的唯一元素。
  2. 执行 ? 对 SingleNameBinding 执行 KeyedBindingInitialization, 并以 valueenvironmentname 为参数。
  3. 返回 « name »。
BindingProperty : PropertyName : BindingElement
  1. propertyKey 为 ? 对 PropertyName 求值。
  2. 执行 ? 对 BindingElement 执行 KeyedBindingInitialization,并以 valueenvironmentpropertyKey 为参数。
  3. 返回 « propertyKey »。

14.3.3.2 Runtime Semantics: RestBindingInitialization

The syntax-directed operation RestBindingInitialization takes arguments value (一个 ECMAScript 语言值), environment (一个 Environment Recordundefined), and excludedNames (一个属性键列表) and returns 要么是一个正常完成,包含 unused,要么是一个突然完成. It is defined piecewise over the following productions:

BindingRestProperty : ... BindingIdentifier
  1. lhs 为 ? ResolveBinding(StringValue of BindingIdentifier, environment)。
  2. restObjOrdinaryObjectCreate(%Object.prototype%)。
  3. 执行 ? CopyDataProperties(restObj, value, excludedNames)。
  4. 如果 environmentundefined,返回 ? PutValue(lhs, restObj)。
  5. 返回 ? InitializeReferencedBinding(lhs, restObj)。

14.3.3.3 Runtime Semantics: KeyedBindingInitialization

The syntax-directed operation KeyedBindingInitialization takes arguments value (一个 ECMAScript 语言值), environment (一个 Environment Recordundefined), and propertyName (一个属性键) and returns 要么是一个正常完成,包含 unused,要么是一个突然完成.

Note

environment 传入 undefined 时,表示应当使用 PutValue 操作 来赋予初始化值。这种情况出现在非严格函数的形式参数列表中。在那种情况下, 形式参数绑定会被预初始化,以处理多个参数具有相同名称的可能性。

It is defined piecewise over the following productions:

BindingElement : BindingPattern Initializeropt
  1. v 为 ? GetV(value, propertyName)。
  2. 如果 Initializer 存在且 vundefined,那么
    1. defaultValue 为 ? 对 Initializer 求值。
    2. v 设为 ? GetValue(defaultValue)。
  3. 返回 ? 对 BindingPattern 执行 BindingInitialization,并以 venvironment 为参数。
SingleNameBinding : BindingIdentifier Initializeropt
  1. bindingIdBindingIdentifierStringValue
  2. lhs 为 ? ResolveBinding(bindingId, environment)。
  3. v 为 ? GetV(value, propertyName)。
  4. 如果 Initializer 存在且 vundefined,那么
    1. 如果 IsAnonymousFunctionDefinition(Initializer) 为 true,那么
      1. v 设为 ? 对 Initializer 执行 NamedEvaluation,并以 bindingId 为参数。
    2. 否则,
      1. defaultValue 为 ? 对 Initializer 求值。
      2. v 设为 ? GetValue(defaultValue)。
  5. 如果 environmentundefined,返回 ? PutValue(lhs, v)。
  6. 返回 ? InitializeReferencedBinding(lhs, v)。

14.4 空语句

语法

EmptyStatement : ;

14.4.1 Runtime Semantics: 求值

EmptyStatement : ;
  1. 返回 empty

14.5 表达式语句

语法

ExpressionStatement[Yield, Await] : [lookahead ∉ { {, function, async [no LineTerminator here] function, class, let [ }] Expression[+In, ?Yield, ?Await] ; Note

ExpressionStatement 不能以 U+007B(LEFT CURLY BRACKET)开头, 因为那会使它与 Block 产生歧义。ExpressionStatement 不能以关键字 functionclass 开头,因为那会使它与 FunctionDeclarationGeneratorDeclarationClassDeclaration 产生歧义。 ExpressionStatement 不能以 async function 开头,因为那会使它与 AsyncFunctionDeclarationAsyncGeneratorDeclaration 产生歧义。 ExpressionStatement 不能以两个记号序列 let [ 开头,因为那会使它与一 个 let LexicalDeclaration 产生歧义,而该声明的第一个 LexicalBinding 是一个 ArrayBindingPattern

14.5.1 Runtime Semantics: 求值

ExpressionStatement : Expression ;
  1. exprRef 为 ? 对 Expression 求值。
  2. 返回 ? GetValue(exprRef)。

14.6 if 语句

语法

IfStatement[Yield, Await, Return] : if ( Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] else Statement[?Yield, ?Await, ?Return] if ( Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] [lookahead ≠ else] Note
[lookahead ≠ else] 这一前瞻限制以通常方式解决了经典的“悬空 else”问题。也就是说,当关联哪个 if 在其他方面仍然有歧义时,else 会与候选 if 中最近的(最内层的)那个相关联。

14.6.1 Static Semantics: 早期错误

IfStatement : if ( Expression ) Statement else Statement IfStatement : if ( Expression ) Statement Note

仅在实现了 B.3.1 中规定的扩展时,才有必要应用此规则。

14.6.2 Runtime Semantics: 求值

IfStatement : if ( Expression ) Statement else Statement
  1. exprRef 为 ? 对 Expression 求值。
  2. exprValueToBoolean(? GetValue(exprRef))。
  3. 如果 exprValuetrue,那么
    1. stmtCompletionCompletion(对第一个 Statement 求值)。
  4. 否则,
    1. stmtCompletionCompletion(对第二个 Statement 求值)。
  5. 返回 ? UpdateEmpty(stmtCompletion, undefined)。
IfStatement : if ( Expression ) Statement
  1. exprRef 为 ? 对 Expression 求值。
  2. exprValueToBoolean(? GetValue(exprRef))。
  3. 如果 exprValuefalse,返回 undefined
  4. stmtCompletionCompletion(对 Statement 求值)。
  5. 返回 ? UpdateEmpty(stmtCompletion, undefined)。

14.7 迭代语句

语法

IterationStatement[Yield, Await, Return] : DoWhileStatement[?Yield, ?Await, ?Return] WhileStatement[?Yield, ?Await, ?Return] ForStatement[?Yield, ?Await, ?Return] ForInOfStatement[?Yield, ?Await, ?Return]

14.7.1 语义

14.7.1.1 LoopContinues ( completion, labelSet )

The abstract operation LoopContinues takes arguments completion (一个 Completion Record) and labelSet (一个 String 列表) and returns 一个 Boolean. It performs the following steps when called:

  1. 如果 completion 是一个正常完成,返回 true
  2. 如果 completion 不是一个 continue 完成,返回 false
  3. 如果 completion.[[Target]]empty,返回 true
  4. 如果 labelSet 包含 completion.[[Target]],返回 true
  5. 返回 false
Note

IterationStatementStatement 部分内部,可以使用 ContinueStatement 来开始一次新的迭代。

14.7.1.2 Runtime Semantics: LoopEvaluation

The syntax-directed operation LoopEvaluation takes argument labelSet (一个 String 列表) and returns 要么是一个正常完成,包含一个 ECMAScript 语言值,要么是一个突然完成. It is defined piecewise over the following productions:

IterationStatement : DoWhileStatement
  1. 返回 ? 对 DoWhileStatement 执行 DoWhileLoopEvaluation,并以 labelSet 为参数。
IterationStatement : WhileStatement
  1. 返回 ? 对 WhileStatement 执行 WhileLoopEvaluation,并以 labelSet 为参数。
IterationStatement : ForStatement
  1. 返回 ? 对 ForStatement 执行 ForLoopEvaluation,并以 labelSet 为参数。
IterationStatement : ForInOfStatement
  1. 返回 ? 对 ForInOfStatement 执行 ForInOfLoopEvaluation,并以 labelSet 为参数。

14.7.2 do-while 语句

语法

DoWhileStatement[Yield, Await, Return] : do Statement[?Yield, ?Await, ?Return] while ( Expression[+In, ?Yield, ?Await] ) ;

14.7.2.1 Static Semantics: 早期错误

DoWhileStatement : do Statement while ( Expression ) ; Note

仅在实现了 B.3.1 中规定的扩展时,才有必要应用此规则。

14.7.2.2 Runtime Semantics: DoWhileLoopEvaluation

The syntax-directed operation DoWhileLoopEvaluation takes argument labelSet (一个 String 列表) and returns 要么是一个正常完成,包含一个 ECMAScript 语言值,要么是一个突然完成. It is defined piecewise over the following productions:

DoWhileStatement : do Statement while ( Expression ) ;
  1. iterationResultundefined
  2. 重复,
    1. stmtResultCompletion(对 Statement 求值)。
    2. 如果 LoopContinues(stmtResult, labelSet) 为 false,返回 ? UpdateEmpty(stmtResult, iterationResult)。
    3. 如果 stmtResult.[[Value]] 不为 empty,将 iterationResult 设为 stmtResult.[[Value]]
    4. exprRef 为 ? 对 Expression 求值。
    5. exprValue 为 ? GetValue(exprRef)。
    6. 如果 ToBoolean(exprValue) 为 false,返回 iterationResult

14.7.3 while 语句

语法

WhileStatement[Yield, Await, Return] : while ( Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return]

14.7.3.1 Static Semantics: 早期错误

WhileStatement : while ( Expression ) Statement Note

仅在实现了 B.3.1 中规定的扩展时,才有必要应用此规则。

14.7.3.2 Runtime Semantics: WhileLoopEvaluation

The syntax-directed operation WhileLoopEvaluation takes argument labelSet (一个 String 列表) and returns 要么是一个正常完成,包含一个 ECMAScript 语言值,要么是一个突然完成. It is defined piecewise over the following productions:

WhileStatement : while ( Expression ) Statement
  1. iterationResultundefined
  2. 重复,
    1. exprRef 为 ? 对 Expression 求值。
    2. exprValue 为 ? GetValue(exprRef)。
    3. 如果 ToBoolean(exprValue) 为 false,返回 iterationResult
    4. stmtResultCompletion(对 Statement 求值)。
    5. 如果 LoopContinues(stmtResult, labelSet) 为 false,返回 ? UpdateEmpty(stmtResult, iterationResult)。
    6. 如果 stmtResult.[[Value]] 不为 empty,将 iterationResult 设为 stmtResult.[[Value]]

14.7.4 for 语句

语法

ForStatement[Yield, Await, Return] : for ( [lookahead ≠ let [] Expression[~In, ?Yield, ?Await]opt ; Expression[+In, ?Yield, ?Await]opt ; Expression[+In, ?Yield, ?Await]opt ) Statement[?Yield, ?Await, ?Return] for ( var VariableDeclarationList[~In, ?Yield, ?Await] ; Expression[+In, ?Yield, ?Await]opt ; Expression[+In, ?Yield, ?Await]opt ) Statement[?Yield, ?Await, ?Return] for ( LexicalDeclaration[~In, ?Yield, ?Await] Expression[+In, ?Yield, ?Await]opt ; Expression[+In, ?Yield, ?Await]opt ) Statement[?Yield, ?Await, ?Return]

14.7.4.1 Static Semantics: 早期错误

ForStatement : for ( Expressionopt ; Expressionopt ; Expressionopt ) Statement for ( var VariableDeclarationList ; Expressionopt ; Expressionopt ) Statement for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement Note

仅在实现了 B.3.1 中规定的扩展时,才有必要应用此规则。

ForStatement : for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement

14.7.4.2 Runtime Semantics: ForLoopEvaluation

The syntax-directed operation ForLoopEvaluation takes argument labelSet (一个 String 列表) and returns 要么是一个正常完成,包含一个 ECMAScript 语言值,要么是一个突然完成. It is defined piecewise over the following productions:

ForStatement : for ( Expressionopt ; Expressionopt ; Expressionopt ) Statement
  1. 如果第一个 Expression 存在,那么
    1. exprRef 为 ? 对第一个 Expression 求值。
    2. 执行 ? GetValue(exprRef)。
  2. 如果第二个 Expression 存在,令 test 为第二个 Expression; 否则令 testempty
  3. 如果第三个 Expression 存在,令 increment 为第三个 Expression;否则令 incrementempty
  4. 返回 ? ForBodyEvaluation(test, increment, Statement, « », labelSet)。
ForStatement : for ( var VariableDeclarationList ; Expressionopt ; Expressionopt ) Statement
  1. 执行 ? 对 VariableDeclarationList 求值。
  2. 如果第一个 Expression 存在,令 test 为第一个 Expression; 否则令 testempty
  3. 如果第二个 Expression 存在,令 increment 为第二个 Expression;否则令 incrementempty
  4. 返回 ? ForBodyEvaluation(test, increment, Statement, « », labelSet)。
ForStatement : for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement
  1. oldEnv 为当前运行执行上下文的 LexicalEnvironment。
  2. loopEnvNewDeclarativeEnvironment(oldEnv)。
  3. isConstLexicalDeclarationIsConstantDeclaration
  4. boundNamesLexicalDeclarationBoundNames
  5. 对于 boundNames 中的每个元素 dn,执行
    1. 如果 isConsttrue,那么
      1. 执行 ! loopEnv.CreateImmutableBinding(dn, true)。
    2. 否则,
      1. 执行 ! loopEnv.CreateMutableBinding(dn, false)。
  6. 将当前运行执行上下文的 LexicalEnvironment 设为 loopEnv
  7. forDclCompletion(对 LexicalDeclaration 求值)。
  8. 如果 forDcl 是一个突然完成,那么
    1. 将当前运行执行上下文的 LexicalEnvironment 设为 oldEnv
    2. 返回 ? forDcl
  9. 如果 isConstfalse,令 perIterationLetsboundNames; 否则令 perIterationLets 为一个新的空列表。
  10. 如果第一个 Expression 存在,令 test 为第一个 Expression; 否则令 testempty
  11. 如果第二个 Expression 存在,令 increment 为第二个 Expression;否则令 incrementempty
  12. bodyResultCompletion(ForBodyEvaluation(test, increment, Statement, perIterationLets, labelSet))。
  13. 将当前运行执行上下文的 LexicalEnvironment 设为 oldEnv
  14. 返回 ? bodyResult

14.7.4.3 ForBodyEvaluation ( test, increment, stmt, perIterationBindings, labelSet )

The abstract operation ForBodyEvaluation takes arguments test (一个 Expression Parse Node 或 empty), increment (一个 Expression Parse Node 或 empty), stmt (一个 Statement Parse Node), perIterationBindings (一个 String 列表), and labelSet (一个 String 列表) and returns 要么是一个正常完成,包含一个 ECMAScript 语言值,要么是一个突然完成. It performs the following steps when called:

  1. iterationResultundefined
  2. 执行 ? CreatePerIterationEnvironment(perIterationBindings)。
  3. 重复,
    1. 如果 test 不为 empty,那么
      1. testRef 为 ? 对 test 求值。
      2. testValue 为 ? GetValue(testRef)。
      3. 如果 ToBoolean(testValue) 为 false,返回 iterationResult
    2. resultCompletion(对 stmt 求值)。
    3. 如果 LoopContinues(result, labelSet) 为 false,返回 ? UpdateEmpty(result, iterationResult)。
    4. 如果 result.[[Value]] 不为 empty,将 iterationResult 设为 result.[[Value]]
    5. 执行 ? CreatePerIterationEnvironment(perIterationBindings)。
    6. 如果 increment 不为 empty,那么
      1. incRef 为 ? 对 increment 求值。
      2. 执行 ? GetValue(incRef)。

14.7.4.4 CreatePerIterationEnvironment ( perIterationBindings )

The abstract operation CreatePerIterationEnvironment takes argument perIterationBindings (一个 String 列表) and returns 要么是一个正常完成,包含 unused,要么是一个抛出完成. It performs the following steps when called:

  1. 如果 perIterationBindings 含有任何元素,那么
    1. lastIterationEnv 为当前运行执行上下文的 LexicalEnvironment。
    2. outerlastIterationEnv.[[OuterEnv]]
    3. 断言:outer 不为 null
    4. thisIterationEnvNewDeclarativeEnvironment(outer)。
    5. 对于 perIterationBindings 中的每个元素 bn,执行
      1. 执行 ! thisIterationEnv.CreateMutableBinding(bn, false)。
      2. lastValue 为 ? lastIterationEnv.GetBindingValue(bn, true)。
      3. 执行 ! thisIterationEnv.InitializeBinding(bn, lastValue)。
    6. 将当前运行执行上下文的 LexicalEnvironment 设为 thisIterationEnv
  2. 返回 unused

14.7.5 for-infor-offor-await-of 语句

语法

ForInOfStatement[Yield, Await, Return] : for ( [lookahead ≠ let [] LeftHandSideExpression[?Yield, ?Await] in Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] for ( var ForBinding[?Yield, ?Await] in Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] for ( ForDeclaration[?Yield, ?Await] in Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] for ( [lookahead ∉ { let, async of }] LeftHandSideExpression[?Yield, ?Await] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] for ( var ForBinding[?Yield, ?Await] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] for ( ForDeclaration[?Yield, ?Await] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] [+Await] for await ( [lookahead ≠ let] LeftHandSideExpression[?Yield, ?Await] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] [+Await] for await ( var ForBinding[?Yield, ?Await] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] [+Await] for await ( ForDeclaration[?Yield, ?Await] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] ForDeclaration[Yield, Await] : LetOrConst ForBinding[?Yield, ?Await] ForBinding[Yield, Await] : BindingIdentifier[?Yield, ?Await] BindingPattern[?Yield, ?Await] Note

本节由附录 B.3.5 扩展。

14.7.5.1 Static Semantics: 早期错误

ForInOfStatement : for ( LeftHandSideExpression in Expression ) Statement for ( var ForBinding in Expression ) Statement for ( ForDeclaration in Expression ) Statement for ( LeftHandSideExpression of AssignmentExpression ) Statement for ( var ForBinding of AssignmentExpression ) Statement for ( ForDeclaration of AssignmentExpression ) Statement for await ( LeftHandSideExpression of AssignmentExpression ) Statement for await ( var ForBinding of AssignmentExpression ) Statement for await ( ForDeclaration of AssignmentExpression ) Statement Note

仅在实现了 B.3.1 中规定的扩展时,才有必要应用此规则。

ForInOfStatement : for ( LeftHandSideExpression in Expression ) Statement for ( LeftHandSideExpression of AssignmentExpression ) Statement for await ( LeftHandSideExpression of AssignmentExpression ) Statement ForInOfStatement : for ( ForDeclaration in Expression ) Statement for ( ForDeclaration of AssignmentExpression ) Statement for await ( ForDeclaration of AssignmentExpression ) Statement

14.7.5.2 Static Semantics: IsDestructuring

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

MemberExpression : PrimaryExpression
  1. 如果 PrimaryExpression 是一个 ObjectLiteral 或一个 ArrayLiteral,返回 true
  2. 返回 false
MemberExpression : MemberExpression [ Expression ] MemberExpression . IdentifierName MemberExpression TemplateLiteral SuperProperty MetaProperty new MemberExpression Arguments MemberExpression . PrivateIdentifier NewExpression : new NewExpression LeftHandSideExpression : CallExpression OptionalExpression
  1. 返回 false
ForDeclaration : LetOrConst ForBinding
  1. 返回 ForBindingIsDestructuring
ForBinding : BindingIdentifier
  1. 返回 false
ForBinding : BindingPattern
  1. 返回 true
Note

本节由附录 B.3.5 扩展。

14.7.5.3 Runtime Semantics: ForDeclarationBindingInitialization

The syntax-directed operation ForDeclarationBindingInitialization takes arguments value (一个 ECMAScript 语言值) and environment (一个 Environment Record) and returns 要么是一个正常完成,包含 unused,要么是一个突然完成. It is defined piecewise over the following productions:

ForDeclaration : LetOrConst ForBinding
  1. 返回 ? 对 ForBinding 执行 BindingInitialization,并以 valueenvironment 为参数。

14.7.5.4 Runtime Semantics: ForDeclarationBindingInstantiation

The syntax-directed operation ForDeclarationBindingInstantiation takes argument environment (一个 Declarative Environment Record) and returns unused. It is defined piecewise over the following productions:

ForDeclaration : LetOrConst ForBinding
  1. 对于 ForBindingBoundNames 中的每个元素 name,执行
    1. 如果 LetOrConstIsConstantDeclarationtrue,那么
      1. 执行 ! environment.CreateImmutableBinding(name, true)。
    2. 否则,
      1. 执行 ! environment.CreateMutableBinding(name, false)。
  2. 返回 unused

14.7.5.5 Runtime Semantics: ForInOfLoopEvaluation

The syntax-directed operation ForInOfLoopEvaluation takes argument labelSet (一个 String 列表) and returns 要么是一个正常完成,包含一个 ECMAScript 语言值,要么是一个突然完成. It is defined piecewise over the following productions:

ForInOfStatement : for ( LeftHandSideExpression in Expression ) Statement
  1. keyResult 为 ? ForIn/OfHeadEvaluation(« », Expression, enumerate)。
  2. 返回 ? ForIn/OfBodyEvaluation(LeftHandSideExpression, Statement, keyResult, enumerate, assignment, labelSet)。
ForInOfStatement : for ( var ForBinding in Expression ) Statement
  1. keyResult 为 ? ForIn/OfHeadEvaluation(« », Expression, enumerate)。
  2. 返回 ? ForIn/OfBodyEvaluation(ForBinding, Statement, keyResult, enumerate, var-binding, labelSet)。
ForInOfStatement : for ( ForDeclaration in Expression ) Statement
  1. keyResult 为 ? ForIn/OfHeadEvaluation(BoundNames of ForDeclaration, Expression, enumerate)。
  2. 返回 ? ForIn/OfBodyEvaluation(ForDeclaration, Statement, keyResult, enumerate, lexical-binding, labelSet)。
ForInOfStatement : for ( LeftHandSideExpression of AssignmentExpression ) Statement
  1. keyResult 为 ? ForIn/OfHeadEvaluation(« », AssignmentExpression, iterate)。
  2. 返回 ? ForIn/OfBodyEvaluation(LeftHandSideExpression, Statement, keyResult, iterate, assignment, labelSet)。
ForInOfStatement : for ( var ForBinding of AssignmentExpression ) Statement
  1. keyResult 为 ? ForIn/OfHeadEvaluation(« », AssignmentExpression, iterate)。
  2. 返回 ? ForIn/OfBodyEvaluation(ForBinding, Statement, keyResult, iterate, var-binding, labelSet)。
ForInOfStatement : for ( ForDeclaration of AssignmentExpression ) Statement
  1. keyResult 为 ? ForIn/OfHeadEvaluation(BoundNames of ForDeclaration, AssignmentExpression, iterate)。
  2. 返回 ? ForIn/OfBodyEvaluation(ForDeclaration, Statement, keyResult, iterate, lexical-binding, labelSet)。
ForInOfStatement : for await ( LeftHandSideExpression of AssignmentExpression ) Statement
  1. keyResult 为 ? ForIn/OfHeadEvaluation(« », AssignmentExpression, async-iterate)。
  2. 返回 ? ForIn/OfBodyEvaluation(LeftHandSideExpression, Statement, keyResult, iterate, assignment, labelSet, async)。
ForInOfStatement : for await ( var ForBinding of AssignmentExpression ) Statement
  1. keyResult 为 ? ForIn/OfHeadEvaluation(« », AssignmentExpression, async-iterate)。
  2. 返回 ? ForIn/OfBodyEvaluation(ForBinding, Statement, keyResult, iterate, var-binding, labelSet, async)。
ForInOfStatement : for await ( ForDeclaration of AssignmentExpression ) Statement
  1. keyResult 为 ? ForIn/OfHeadEvaluation(BoundNames of ForDeclaration, AssignmentExpression, async-iterate)。
  2. 返回 ? ForIn/OfBodyEvaluation(ForDeclaration, Statement, keyResult, iterate, lexical-binding, labelSet, async)。
Note

本节由附录 B.3.5 扩展。

14.7.5.6 ForIn/OfHeadEvaluation ( uninitializedBoundNames, expr, iterationKind )

The abstract operation ForIn/OfHeadEvaluation takes arguments uninitializedBoundNames (一个 String 列表), expr (一个 Expression Parse Node 或一个 AssignmentExpression Parse Node), and iterationKind (enumerateiterateasync-iterate) and returns 要么是一个正常完成,包含一个 Iterator Record,要么是一个突然完成. It performs the following steps when called:

  1. oldEnv 为当前运行执行上下文的 LexicalEnvironment。
  2. 如果 uninitializedBoundNames 非空,那么
    1. 断言:uninitializedBoundNames 不含重复条目。
    2. newEnvNewDeclarativeEnvironment(oldEnv)。
    3. 对于 uninitializedBoundNames 中的每个 String name,执行
      1. 执行 ! newEnv.CreateMutableBinding(name, false)。
    4. 将当前运行执行上下文的 LexicalEnvironment 设为 newEnv
  3. exprRefCompletion(对 expr 求值)。
  4. 将当前运行执行上下文的 LexicalEnvironment 设回 oldEnv
  5. exprValue 为 ? GetValue(? exprRef)。
  6. 如果 iterationKindenumerate,那么
    1. 如果 exprValueundefinednull,那么
      1. 返回 Completion Record { [[Type]]: break, [[Value]]: empty, [[Target]]: empty }。
    2. obj 为 ! ToObject(exprValue)。
    3. iteratorEnumerateObjectProperties(obj)。
    4. nextMethod 为 ! GetV(iterator, "next")。
    5. 返回 Iterator Record { [[Iterator]]: iterator, [[NextMethod]]: nextMethod, [[Done]]: false }。
  7. 断言:iterationKinditerateasync-iterate 之一。
  8. 如果 iterationKindasync-iterate,令 iteratorKindasync
  9. 否则,令 iteratorKindsync
  10. 返回 ? GetIterator(exprValue, iteratorKind)。

14.7.5.7 ForIn/OfBodyEvaluation ( lhs, stmt, iteratorRecord, iterationKind, lhsKind, labelSet [ , iteratorKind ] )

The abstract operation ForIn/OfBodyEvaluation takes arguments lhs (一个 Parse Node), stmt (一个 Statement Parse Node), iteratorRecord (一个 Iterator Record), iterationKind (enumerateiterate), lhsKind (assignmentvar-bindinglexical-binding), and labelSet (一个 String 列表) and optional argument iteratorKind (syncasync) and returns 要么是一个正常完成,包含一个 ECMAScript 语言值,要么是一个突然完成. It performs the following steps when called:

  1. 如果 iteratorKind 未出现,将 iteratorKind 设为 sync
  2. oldEnv 为当前运行执行上下文的 LexicalEnvironment。
  3. iterationResultundefined
  4. destructuringlhsIsDestructuring
  5. 如果 destructuringtruelhsKindassignment,那么
    1. 断言:lhs 是一个 LeftHandSideExpression
    2. assignmentPatternlhs覆盖AssignmentPattern
  6. 重复,
    1. nextResult 为 ? Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]])。
    2. 如果 iteratorKindasync,将 nextResult 设为 ? Await(nextResult)。
    3. 如果 nextResult 不是一个 Object,抛出一个 TypeError 异常。
    4. done 为 ? IteratorComplete(nextResult)。
    5. 如果 donetrue,返回 iterationResult
    6. nextValue 为 ? IteratorValue(nextResult)。
    7. 如果 lhsKindassignmentvar-binding 之一,那么
      1. 如果 destructuringtrue,那么
        1. 如果 lhsKindassignment,那么
          1. statusCompletion(对 assignmentPattern 执行 DestructuringAssignmentEvaluation,并以 nextValue 为参数)。
        2. 否则,
          1. 断言:lhsKindvar-binding
          2. 断言:lhs 是一个 ForBinding
          3. statusCompletion(对 lhs 执行 BindingInitialization,并以 nextValueundefined 为参数)。
      2. 否则,
        1. lhsRefCompletion(对 lhs 求值)。(它可能会被重复求值。)
        2. 如果 lhsKindassignmentlhsAssignmentTargetTypeweb-compat,抛出一个 ReferenceError 异常。
        3. 如果 lhsRef 是一个突然完成,那么
          1. statuslhsRef
        4. 否则,
          1. statusCompletion(PutValue(lhsRef.[[Value]], nextValue))。
    8. 否则,
      1. 断言:lhsKindlexical-binding
      2. 断言:lhs 是一个 ForDeclaration
      3. iterationEnvNewDeclarativeEnvironment(oldEnv)。
      4. 执行 ForDeclarationBindingInstantiation of lhs,并以 iterationEnv 为参数。
      5. 将当前运行执行上下文的 LexicalEnvironment 设为 iterationEnv
      6. 如果 destructuringtrue,那么
        1. statusCompletion(对 lhs 执行 ForDeclarationBindingInitialization,并以 nextValueiterationEnv 为参数)。
      7. 否则,
        1. 断言:lhs 绑定单个名称。
        2. lhsNamelhsBoundNames 的唯一元素。
        3. lhsRef 为 ! ResolveBinding(lhsName)。
        4. statusCompletion(InitializeReferencedBinding(lhsRef, nextValue))。
    9. 如果 status 是一个突然完成,那么
      1. 将当前运行执行上下文的 LexicalEnvironment 设为 oldEnv
      2. 如果 iterationKindenumerate,返回 ? status
      3. 断言:iterationKinditerate
      4. 如果 iteratorKindasync,返回 ? AsyncIteratorClose(iteratorRecord, status)。
      5. 返回 ? IteratorClose(iteratorRecord, status)。
    10. resultCompletion(对 stmt 求值)。
    11. 将当前运行执行上下文的 LexicalEnvironment 设为 oldEnv
    12. 如果 LoopContinues(result, labelSet) 为 false,那么
      1. status 设为 Completion(UpdateEmpty(result, iterationResult))。
      2. 如果 iterationKindenumerate,返回 ? status
      3. 断言:iterationKinditerate
      4. 如果 iteratorKindasync,返回 ? AsyncIteratorClose(iteratorRecord, status)。
      5. 返回 ? IteratorClose(iteratorRecord, status)。
    13. 如果 result.[[Value]] 不为 empty,将 iterationResult 设为 result.[[Value]]

14.7.5.8 Runtime Semantics: 求值

BindingIdentifier : Identifier yield await
  1. bindingIdBindingIdentifierStringValue
  2. 返回 ? ResolveBinding(bindingId)。

14.7.5.9 EnumerateObjectProperties ( obj )

The abstract operation EnumerateObjectProperties takes argument obj (一个 Object) and returns 一个迭代器对象. It performs the following steps when called:

  1. 返回一个迭代器对象,其 next 方法会遍历 obj 的所有可枚举属性中值为 String 的键。该迭代器对象永远不能被 ECMAScript 代码直接访问。枚举属性的机制与顺序未被规定,但必须符合下方规定的规则。

该迭代器的 throwreturn 方法为 null,并且永远不会被调用。该 迭代器的 next 方法会处理对象属性,以判定该属性键是否应作为迭代器值返回。 返回的属性键不包括 Symbol 键。在枚举期间,目标对象的属性可能会被删除。在 被迭代器的 next 方法处理之前就已被删除的属性会被忽略。如果在枚举期间向 目标对象新增属性,则不能保证这些新加属性会在当前激活的枚举中被处理。某个属 性名在任何一次枚举中,最多只会由迭代器的 next 方法返回一次。

对目标对象属性的枚举还包括递归枚举其原型、原型的原型,以此类推;但如果某 个原型上的属性与已被迭代器 next 方法处理过的某个属性同名,则不会处理该原 型属性。在判断某个原型对象的属性是否已被处理时,不考虑 [[Enumerable]] 特 性的值。原型对象的可枚举属性名必须通过调用 EnumerateObjectProperties 并将 该原型对象作为参数来获得。EnumerateObjectProperties 必须通过调用目标对象 的 [[OwnPropertyKeys]] 内部方法来获得其自有属性键。目标对象的属性特性必须 通过调用其 [[GetOwnProperty]] 内部方法来获得。

此外,如果 obj 及其原型链上的任何对象都不是 Proxy 异质对象TypedArray模块命名空间异质对象或实现提供的异质对象,那么该迭代器就必须 表现得像由 CreateForInIterator(obj) 所给出的迭代器一样,直到发生以下任 一情况为止:

  • obj 或其原型链中某个对象的 [[Prototype]] 内部槽的值发生变化,
  • obj 或其原型链中某个对象上移除了某个属性,
  • obj 的原型链中的某个对象添加了某个属性,或
  • obj 或其原型链中某个对象的某个属性的 [[Enumerable]] 特性的值发生变化。
Note 1

ECMAScript 实现不要求直接实现 14.7.5.10.2.1 中的算法。它们可以选择任何一种实现,只要其行为不会偏离该算法,除非违反了 前一段中的某项约束。

以下是一个符合这些规则的 ECMAScript 生成器函数的信息性定义:

function* EnumerateObjectProperties(obj) {
  const visited = new Set();
  for (const key of Reflect.ownKeys(obj)) {
    if (typeof key === "symbol") continue;
    const desc = Reflect.getOwnPropertyDescriptor(obj, key);
    if (desc) {
      visited.add(key);
      if (desc.enumerable) yield key;
    }
  }
  const proto = Reflect.getPrototypeOf(obj);
  if (proto === null) return;
  for (const protoKey of EnumerateObjectProperties(proto)) {
    if (!visited.has(protoKey)) yield protoKey;
  }
}
Note 2
实现不要求与 CreateForInIterator 保持一致的异质对象列表之所以如此选取, 是因为实现历史上在这些情形下的行为有所不同,而在其他所有情形下都一致。

14.7.5.10 For-In 迭代器对象

For-In 迭代器 是一种对象,它表示对某个特定对象进行的一次特定迭代。For-In 迭代器对象永远 不能被 ECMAScript 代码直接访问;它们的存在仅用于说明 EnumerateObjectProperties 的行为。

14.7.5.10.1 CreateForInIterator ( object )

The abstract operation CreateForInIterator takes argument object (一个 Object) and returns 一个 For-In 迭代器. 它用于创建一个 For-In 迭代器对象,该对象以特定顺序遍历 object 自有及继承的可枚举字符串属性。 It performs the following steps when called:

  1. iteratorOrdinaryObjectCreate(%ForInIteratorPrototype%, « [[Object]], [[ObjectWasVisited]], [[VisitedKeys]], [[RemainingKeys]] »)。
  2. iterator.[[Object]] 设为 object
  3. iterator.[[ObjectWasVisited]] 设为 false
  4. iterator.[[VisitedKeys]] 设为一个新的空列表。
  5. iterator.[[RemainingKeys]] 设为一个新的空列表。
  6. 返回 iterator

14.7.5.10.2 %ForInIteratorPrototype% 对象

%ForInIteratorPrototype% 对象:

14.7.5.10.2.1 %ForInIteratorPrototype%.next ( )

  1. iterthis 值。
  2. 断言:iter 是一个 Object。
  3. 断言:iter 具有 For-In 迭代器实例的全部内部槽(14.7.5.10.3)。
  4. objectiter.[[Object]]
  5. 重复,
    1. 如果 iter.[[ObjectWasVisited]]false,那么
      1. keys 为 ? object.[[OwnPropertyKeys]]()
      2. 对于 keys 中的每个元素 key,执行
        1. 如果 key 是一个 String,那么
          1. key 追加到 iter.[[RemainingKeys]]
      3. iter.[[ObjectWasVisited]] 设为 true
    2. 重复,当 iter.[[RemainingKeys]] 非空时,
      1. keyiter.[[RemainingKeys]] 的第一个元素。
      2. iter.[[RemainingKeys]] 中移除第一个元素。
      3. 如果 iter.[[VisitedKeys]] 不包含 key,那么
        1. desc 为 ? object.[[GetOwnProperty]](key)
        2. 如果 desc 不为 undefined,那么
          1. key 追加到 iter.[[VisitedKeys]]
          2. 如果 desc.[[Enumerable]]true,返回 CreateIteratorResultObject(key, false)。
    3. object 设为 ? object.[[GetPrototypeOf]]()
    4. iter.[[Object]] 设为 object
    5. iter.[[ObjectWasVisited]] 设为 false
    6. 如果 objectnull,返回 CreateIteratorResultObject(undefined, true)。

14.7.5.10.3 For-In 迭代器实例的属性

For-In 迭代器实例是普通对象,它们从内在对象 %ForInIteratorPrototype% 继承属性。For-In 迭代器实例在初始创建时具有 Table 33 中列出的内部槽。

Table 33: For-In 迭代器实例的内部槽
内部槽 类型 描述
[[Object]] 一个 Object 其属性正在被迭代的 Object 值。
[[ObjectWasVisited]] 一个 Boolean 如果迭代器已经对 [[Object]] 调用了 [[OwnPropertyKeys]], 则为 true;否则为 false
[[VisitedKeys]] 一个 String 列表 到目前为止该迭代器已经发出的值。
[[RemainingKeys]] 一个 String 列表 在开始迭代其原型的属性之前(如果其原型不为 null),当前对象还剩余待发出的值。

14.8 continue 语句

语法

ContinueStatement[Yield, Await] : continue ; continue [no LineTerminator here] LabelIdentifier[?Yield, ?Await] ;

14.8.1 Static Semantics: 早期错误

ContinueStatement : continue ; continue LabelIdentifier ;

14.8.2 Runtime Semantics: 求值

ContinueStatement : continue ;
  1. 返回 Completion Record { [[Type]]: continue, [[Value]]: empty, [[Target]]: empty }。
ContinueStatement : continue LabelIdentifier ;
  1. labelLabelIdentifierStringValue
  2. 返回 Completion Record { [[Type]]: continue, [[Value]]: empty, [[Target]]: label }。

14.9 break 语句

语法

BreakStatement[Yield, Await] : break ; break [no LineTerminator here] LabelIdentifier[?Yield, ?Await] ;

14.9.1 Static Semantics: 早期错误

BreakStatement : break ;

14.9.2 Runtime Semantics: 求值

BreakStatement : break ;
  1. 返回 Completion Record { [[Type]]: break, [[Value]]: empty, [[Target]]: empty }。
BreakStatement : break LabelIdentifier ;
  1. labelLabelIdentifierStringValue
  2. 返回 Completion Record { [[Type]]: break, [[Value]]: empty, [[Target]]: label }。

14.10 return 语句

语法

ReturnStatement[Yield, Await] : return ; return [no LineTerminator here] Expression[+In, ?Yield, ?Await] ; Note

return 语句会使函数停止执行,并且在大多数情况下会向调用者返回一个值。 如果省略 Expression,返回值是 undefined。否则,返回值就是 Expression 的值。根据外围上下文不同,return 语句实际上不一定真的向 调用者返回一个值。例如,在 try 块中,return 语句的 Completion Record 可能在 finally 块求值期间被另一个 Completion Record 替换。

14.10.1 Runtime Semantics: 求值

ReturnStatement : return ;
  1. 返回 ReturnCompletion(undefined)。
ReturnStatement : return Expression ;
  1. exprRef 为 ? 对 Expression 求值。
  2. exprValue 为 ? GetValue(exprRef)。
  3. 如果 GetGeneratorKind() 为 async,将 exprValue 设为 ? Await(exprValue)。
  4. 返回 ReturnCompletion(exprValue)。
Legacy

14.11 with 语句

Note 1

不鼓励在新的 ECMAScript 代码中使用这种遗留with 语句。请考虑在严 格模式代码和非严格代码中都允许的替代方案,例如 解构赋值

语法

WithStatement[Yield, Await, Return] : with ( Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] Note 2

with 语句会为一个计算得出的对象向当前运行执行上下文的词法环境中添加 一个对象环境记录。然后它使用这个增强后的词法环境执行一条语句。最后,它恢复 原始词法环境。

14.11.1 Static Semantics: 早期错误

WithStatement : with ( Expression ) Statement Note

仅在实现了 B.3.1 中规定的扩展时,才有必要应用第二条规则。

14.11.2 Runtime Semantics: 求值

WithStatement : with ( Expression ) Statement
  1. val 为 ? 对 Expression 求值。
  2. obj 为 ? ToObject(? GetValue(val))。
  3. oldEnv 为当前运行执行上下文的 LexicalEnvironment。
  4. newEnvNewObjectEnvironment(obj, true, oldEnv)。
  5. 将当前运行执行上下文的 LexicalEnvironment 设为 newEnv
  6. stmtCompletionCompletion(对 Statement 求值)。
  7. 将当前运行执行上下文的 LexicalEnvironment 设为 oldEnv
  8. 返回 ? UpdateEmpty(stmtCompletion, undefined)。
Note

无论控制如何离开所嵌入的 Statement,无论是正常完成、某种突然完成还 是异常,LexicalEnvironment 总是会恢复到其原先状态。

14.12 switch 语句

语法

SwitchStatement[Yield, Await, Return] : switch ( Expression[+In, ?Yield, ?Await] ) CaseBlock[?Yield, ?Await, ?Return] CaseBlock[Yield, Await, Return] : { CaseClauses[?Yield, ?Await, ?Return]opt } { CaseClauses[?Yield, ?Await, ?Return]opt DefaultClause[?Yield, ?Await, ?Return] CaseClauses[?Yield, ?Await, ?Return]opt } CaseClauses[Yield, Await, Return] : CaseClause[?Yield, ?Await, ?Return] CaseClauses[?Yield, ?Await, ?Return] CaseClause[?Yield, ?Await, ?Return] CaseClause[Yield, Await, Return] : case Expression[+In, ?Yield, ?Await] : StatementList[?Yield, ?Await, ?Return]opt DefaultClause[Yield, Await, Return] : default : StatementList[?Yield, ?Await, ?Return]opt

14.12.1 Static Semantics: 早期错误

SwitchStatement : switch ( Expression ) CaseBlock

14.12.2 Runtime Semantics: CaseBlockEvaluation

The syntax-directed operation CaseBlockEvaluation takes argument input (一个 ECMAScript 语言值) and returns 要么是一个正常完成,包含一个 ECMAScript 语言值,要么是一个突然完成. It is defined piecewise over the following productions:

CaseBlock : { }
  1. 返回 undefined
CaseBlock : { CaseClauses }
  1. resultValueundefined
  2. caseClausesCaseClausesCaseClause 项构成的列表, 按源文本顺序排列。
  3. foundfalse
  4. 对于 caseClauses 中的每个 CaseClause clause,执行
    1. 如果 foundfalse,那么
      1. found 设为 ? CaseClauseIsSelected(clause, input)。
    2. 如果 foundtrue,那么
      1. completionCompletion(对 clause 求值)。
      2. 如果 completion.[[Value]] 不为 empty,将 resultValue 设为 completion.[[Value]]
      3. 如果 completion 是一个突然完成,返回 ? UpdateEmpty(completion, resultValue)。
  5. 返回 resultValue
CaseBlock : { CaseClausesopt DefaultClause CaseClausesopt }
  1. resultValueundefined
  2. 如果第一个 CaseClauses 存在,那么
    1. caseClauses 为第一个 CaseClausesCaseClause 项构成 的列表,按源文本顺序排列。
  3. 否则,
    1. caseClauses 为一个新的空列表。
  4. foundfalse
  5. 对于 caseClauses 中的每个 CaseClause clause,执行
    1. 如果 foundfalse,那么
      1. found 设为 ? CaseClauseIsSelected(clause, input)。
    2. 如果 foundtrue,那么
      1. completionCompletion(对 clause 求值)。
      2. 如果 completion.[[Value]] 不为 empty,将 resultValue 设为 completion.[[Value]]
      3. 如果 completion 是一个突然完成,返回 ? UpdateEmpty(completion, resultValue)。
  6. foundInBfalse
  7. 如果第二个 CaseClauses 存在,那么
    1. secondCaseClauses 为第二个 CaseClausesCaseClause 项构成的列表,按源文本顺序排列。
  8. 否则,
    1. secondCaseClauses 为一个新的空列表。
  9. 如果 foundfalse,那么
    1. 对于 secondCaseClauses 中的每个 CaseClause clause,执行
      1. 如果 foundInBfalse,那么
        1. foundInB 设为 ? CaseClauseIsSelected(clause, input)。
      2. 如果 foundInBtrue,那么
        1. completionCompletion(对 CaseClause clause 求值)。
        2. 如果 completion.[[Value]] 不为 empty,将 resultValue 设为 completion.[[Value]]
        3. 如果 completion 是一个突然完成,返回 ? UpdateEmpty(completion, resultValue)。
  10. 如果 foundInBtrue,返回 resultValue
  11. defaultRCompletion(对 DefaultClause 求值)。
  12. 如果 defaultR.[[Value]] 不为 empty,将 resultValue 设为 defaultR.[[Value]]
  13. 如果 defaultR 是一个突然完成,返回 ? UpdateEmpty(defaultR, resultValue)。
  14. NOTE: 以下是对第二个 CaseClauses 的又一次完整迭代。
  15. 对于 secondCaseClauses 中的每个 CaseClause clause,执行
    1. completionCompletion(对 CaseClause clause 求值)。
    2. 如果 completion.[[Value]] 不为 empty,将 resultValue 设为 completion.[[Value]]
    3. 如果 completion 是一个突然完成,返回 ? UpdateEmpty(completion, resultValue)。
  16. 返回 resultValue

14.12.3 Runtime Semantics: CaseClauseIsSelected ( constructor, input )

The abstract operation CaseClauseIsSelected takes arguments constructor (一个 CaseClause Parse Node) and input (一个 ECMAScript 语言值) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个突然完成. 它判定 constructor 是否匹配 input。 It performs the following steps when called:

  1. 断言:constructor 是产生式 CaseClause : case Expression : StatementListopt 的一个实例。
  2. exprRef 为 ? 对 constructorExpression 求值。
  3. clauseSelector 为 ? GetValue(exprRef)。
  4. 返回 IsStrictlyEqual(input, clauseSelector)。
Note

该操作不会执行 constructorStatementList(如果有)。 CaseBlock 算法使用它的返回值来决定从哪个 StatementList 开始执行。

14.12.4 Runtime Semantics: 求值

SwitchStatement : switch ( Expression ) CaseBlock
  1. exprRef 为 ? 对 Expression 求值。
  2. switchValue 为 ? GetValue(exprRef)。
  3. oldEnv 为当前运行执行上下文的 LexicalEnvironment。
  4. blockEnvNewDeclarativeEnvironment(oldEnv)。
  5. 执行 BlockDeclarationInstantiation(CaseBlock, blockEnv)。
  6. 将当前运行执行上下文的 LexicalEnvironment 设为 blockEnv
  7. blockResultCompletion(对 CaseBlock 执行 CaseBlockEvaluation,并以 switchValue 为参数)。
  8. 将当前运行执行上下文的 LexicalEnvironment 设为 oldEnv
  9. 返回 blockResult
Note

无论控制如何离开 SwitchStatement,LexicalEnvironment 总是会恢复到其原先状态。

CaseClause : case Expression :
  1. 返回 empty
CaseClause : case Expression : StatementList
  1. 返回 ? 对 StatementList 求值。
DefaultClause : default :
  1. 返回 empty
DefaultClause : default : StatementList
  1. 返回 ? 对 StatementList 求值。

14.13 带标签语句

语法

LabelledStatement[Yield, Await, Return] : LabelIdentifier[?Yield, ?Await] : LabelledItem[?Yield, ?Await, ?Return] LabelledItem[Yield, Await, Return] : Statement[?Yield, ?Await, ?Return] FunctionDeclaration[?Yield, ?Await, ~Default] Note

Statement 可以带有一个前缀标签。带标签语句仅与带标签的 breakcontinue 语句一起使用。ECMAScript 没有 goto 语句。一个 Statement 可以是某个 LabelledStatement 的一部分,而该 LabelledStatement 本身又 可以是另一个 LabelledStatement 的一部分,以此类推。以这种方式引入的标签 在描述各个语句语义时统称为“当前标签集”。

14.13.1 Static Semantics: 早期错误

LabelledItem : FunctionDeclaration

14.13.2 Static Semantics: IsLabelledFunction ( stmt )

The abstract operation IsLabelledFunction takes argument stmt (一个 Statement Parse Node) and returns 一个 Boolean. It performs the following steps when called:

  1. 如果 stmt 不是一个 LabelledStatement,返回 false
  2. itemstmtLabelledItem
  3. 如果 item LabelledItem : FunctionDeclaration ,返回 true
  4. subStmtitemStatement
  5. 返回 IsLabelledFunction(subStmt)。

14.13.3 Runtime Semantics: 求值

LabelledStatement : LabelIdentifier : LabelledItem
  1. 返回 ? 对该 LabelledStatement 执行 LabelledEvaluation,并以 « » 为参数。

14.13.4 Runtime Semantics: LabelledEvaluation

The syntax-directed operation LabelledEvaluation takes argument labelSet (一个 String 列表) and returns 要么是一个正常完成,包含一个 ECMAScript 语言值empty,要么是一个突然完成. It is defined piecewise over the following productions:

BreakableStatement : IterationStatement
  1. stmtResultCompletion(对 IterationStatement 执行 LoopEvaluation,并以 labelSet 为参数)。
  2. 如果 stmtResult 是一个 break 完成,那么
    1. 如果 stmtResult.[[Target]]empty,那么
      1. 如果 stmtResult.[[Value]]empty,将 stmtResult 设为 NormalCompletion(undefined)。
      2. 否则,将 stmtResult 设为 NormalCompletion(stmtResult.[[Value]])。
  3. 返回 ? stmtResult
BreakableStatement : SwitchStatement
  1. stmtResultCompletion(对 SwitchStatement 求值)。
  2. 如果 stmtResult 是一个 break 完成,那么
    1. 如果 stmtResult.[[Target]]empty,那么
      1. 如果 stmtResult.[[Value]]empty,将 stmtResult 设为 NormalCompletion(undefined)。
      2. 否则,将 stmtResult 设为 NormalCompletion(stmtResult.[[Value]])。
  3. 返回 ? stmtResult
Note 1

BreakableStatement 是指可以通过一个不带标签的 BreakStatement 退出的语句。

LabelledStatement : LabelIdentifier : LabelledItem
  1. labelLabelIdentifierStringValue
  2. newLabelSetlabelSet 与 « label » 的列表串接。
  3. stmtResultCompletion(对 LabelledItem 执行 LabelledEvaluation,并以 newLabelSet 为参数)。
  4. 如果 stmtResult 是一个 break 完成stmtResult.[[Target]]label,那么
    1. stmtResult 设为 NormalCompletion(stmtResult.[[Value]])。
  5. 返回 ? stmtResult
LabelledItem : FunctionDeclaration
  1. 返回 ? 对 FunctionDeclaration 求值。
Statement : BlockStatement VariableStatement EmptyStatement ExpressionStatement IfStatement ContinueStatement BreakStatement ReturnStatement WithStatement ThrowStatement TryStatement DebuggerStatement
  1. 返回 ? 对 Statement 求值。
Note 2

Statement 中仅有两个产生式在 LabelledEvaluation 上具有特殊语义: BreakableStatementLabelledStatement

14.14 throw 语句

语法

ThrowStatement[Yield, Await] : throw [no LineTerminator here] Expression[+In, ?Yield, ?Await] ;

14.14.1 Runtime Semantics: 求值

ThrowStatement : throw Expression ;
  1. exprRef 为 ? 对 Expression 求值。
  2. exprValue 为 ? GetValue(exprRef)。
  3. 抛出 exprValue

14.15 try 语句

语法

TryStatement[Yield, Await, Return] : try Block[?Yield, ?Await, ?Return] Catch[?Yield, ?Await, ?Return] try Block[?Yield, ?Await, ?Return] Finally[?Yield, ?Await, ?Return] try Block[?Yield, ?Await, ?Return] Catch[?Yield, ?Await, ?Return] Finally[?Yield, ?Await, ?Return] Catch[Yield, Await, Return] : catch ( CatchParameter[?Yield, ?Await] ) Block[?Yield, ?Await, ?Return] catch Block[?Yield, ?Await, ?Return] Finally[Yield, Await, Return] : finally Block[?Yield, ?Await, ?Return] CatchParameter[Yield, Await] : BindingIdentifier[?Yield, ?Await] BindingPattern[?Yield, ?Await] Note

try 语句包围了一段可能发生异常情况的代码块,例如运行时错误或一条 throw 语句。catch 子句提供异常处理代码。当 catch 子句捕获一个异常时, 它的 CatchParameter 会绑定到该异常。

14.15.1 Static Semantics: 早期错误

Catch : catch ( CatchParameter ) Block

14.15.2 Runtime Semantics: CatchClauseEvaluation

The syntax-directed operation CatchClauseEvaluation takes argument thrownValue (一个 ECMAScript 语言值) and returns 要么是一个正常完成,包含一个 ECMAScript 语言值empty,要么是一个突然完成. It is defined piecewise over the following productions:

Catch : catch ( CatchParameter ) Block
  1. oldEnv 为当前运行执行上下文的 LexicalEnvironment。
  2. catchEnvNewDeclarativeEnvironment(oldEnv)。
  3. 对于 CatchParameterBoundNames 中的每个元素 argName,执行
    1. 执行 ! catchEnv.CreateMutableBinding(argName, false)。
  4. 将当前运行执行上下文的 LexicalEnvironment 设为 catchEnv
  5. statusCompletion(对 CatchParameter 执行 BindingInitialization,并以 thrownValuecatchEnv 为参数)。
  6. 如果 status 是一个突然完成,那么
    1. 将当前运行执行上下文的 LexicalEnvironment 设为 oldEnv
    2. 返回 ? status
  7. blockCompletionCompletion(对 Block 求值)。
  8. 将当前运行执行上下文的 LexicalEnvironment 设为 oldEnv
  9. 返回 ? blockCompletion
Catch : catch Block
  1. 返回 ? 对 Block 求值。
Note

无论控制如何离开 Block,LexicalEnvironment 总是会恢复到其原先状态。

14.15.3 Runtime Semantics: 求值

TryStatement : try Block Catch
  1. blockResultCompletion(对 Block 求值)。
  2. 如果 blockResult 是一个 throw 完成,令 catchResultCompletion(对 Catch 执行 CatchClauseEvaluation,并以 blockResult.[[Value]] 为参数)。
  3. 否则,令 catchResultblockResult
  4. 返回 ? UpdateEmpty(catchResult, undefined)。
TryStatement : try Block Finally
  1. blockResultCompletion(对 Block 求值)。
  2. finallyResultCompletion(对 Finally 求值)。
  3. 如果 finallyResult 是一个正常完成,将 finallyResult 设为 blockResult
  4. 返回 ? UpdateEmpty(finallyResult, undefined)。
TryStatement : try Block Catch Finally
  1. blockResultCompletion(对 Block 求值)。
  2. 如果 blockResult 是一个 throw 完成,令 catchResultCompletion(对 Catch 执行 CatchClauseEvaluation,并以 blockResult.[[Value]] 为参数)。
  3. 否则,令 catchResultblockResult
  4. finallyResultCompletion(对 Finally 求值)。
  5. 如果 finallyResult 是一个正常完成,将 finallyResult 设为 catchResult
  6. 返回 ? UpdateEmpty(finallyResult, undefined)。

14.16 debugger 语句

语法

DebuggerStatement : debugger ;

14.16.1 Runtime Semantics: 求值

Note

DebuggerStatement 求值时,实现可以在调试器环境下触发断点。如 果调试器不存在或未启用,该语句没有可观察效果。

DebuggerStatement : debugger ;
  1. 如果存在并启用了某种实现定义的调试设施,那么
    1. 执行一个实现定义的调试动作。
    2. 返回一个新的实现定义Completion Record
  2. 返回 empty

15 ECMAScript 语言:函数与类

Note

各种 ECMAScript 语言元素会导致创建 ECMAScript 函数对象10.2)。对此类函数的求值从执行其 [[Call]] 内部方法开始(10.2.1)。

15.1 参数列表

语法

UniqueFormalParameters[Yield, Await] : FormalParameters[?Yield, ?Await] FormalParameters[Yield, Await] : [empty] FunctionRestParameter[?Yield, ?Await] FormalParameterList[?Yield, ?Await] FormalParameterList[?Yield, ?Await] , FormalParameterList[?Yield, ?Await] , FunctionRestParameter[?Yield, ?Await] FormalParameterList[Yield, Await] : FormalParameter[?Yield, ?Await] FormalParameterList[?Yield, ?Await] , FormalParameter[?Yield, ?Await] FunctionRestParameter[Yield, Await] : BindingRestElement[?Yield, ?Await] FormalParameter[Yield, Await] : BindingElement[?Yield, ?Await]

15.1.1 Static Semantics: 早期错误

UniqueFormalParameters : FormalParameters FormalParameters : FormalParameterList Note

FormalParameterList 中,同一个 BindingIdentifier 出现多次,仅在函数具有简单参数列表且未在严格模式代码中定义时才被允许。

15.1.2 Static Semantics: ContainsExpression

The syntax-directed operation ContainsExpression takes no arguments and returns 一个布尔值. It is defined piecewise over the following productions:

ObjectBindingPattern : { } { BindingRestProperty }
  1. 返回 false
ObjectBindingPattern : { BindingPropertyList , BindingRestProperty }
  1. 返回 BindingPropertyListContainsExpression
ArrayBindingPattern : [ Elisionopt ]
  1. 返回 false
ArrayBindingPattern : [ Elisionopt BindingRestElement ]
  1. 返回 BindingRestElementContainsExpression
ArrayBindingPattern : [ BindingElementList , Elisionopt ]
  1. 返回 BindingElementListContainsExpression
ArrayBindingPattern : [ BindingElementList , Elisionopt BindingRestElement ]
  1. hasBindingElementListContainsExpression
  2. 如果 hastrue,返回 true
  3. 返回 BindingRestElementContainsExpression
BindingPropertyList : BindingPropertyList , BindingProperty
  1. hasBindingPropertyListContainsExpression
  2. 如果 hastrue,返回 true
  3. 返回 BindingPropertyContainsExpression
BindingElementList : BindingElementList , BindingElisionElement
  1. hasBindingElementListContainsExpression
  2. 如果 hastrue,返回 true
  3. 返回 BindingElisionElementContainsExpression
BindingElisionElement : Elisionopt BindingElement
  1. 返回 BindingElementContainsExpression
BindingProperty : PropertyName : BindingElement
  1. hasPropertyNameIsComputedPropertyKey
  2. 如果 hastrue,返回 true
  3. 返回 BindingElementContainsExpression
BindingElement : BindingPattern Initializer
  1. 返回 true
SingleNameBinding : BindingIdentifier
  1. 返回 false
SingleNameBinding : BindingIdentifier Initializer
  1. 返回 true
BindingRestElement : ... BindingIdentifier
  1. 返回 false
BindingRestElement : ... BindingPattern
  1. 返回 BindingPatternContainsExpression
FormalParameters : [empty]
  1. 返回 false
FormalParameters : FormalParameterList , FunctionRestParameter
  1. 如果 FormalParameterListContainsExpressiontrue,返回 true
  2. 返回 FunctionRestParameterContainsExpression
FormalParameterList : FormalParameterList , FormalParameter
  1. 如果 FormalParameterListContainsExpressiontrue,返回 true
  2. 返回 FormalParameterContainsExpression
ArrowParameters : BindingIdentifier
  1. 返回 false
ArrowParameters : CoverParenthesizedExpressionAndArrowParameterList
  1. formals 为被 CoverParenthesizedExpressionAndArrowParameterList 覆盖ArrowFormalParameters
  2. 返回 formalsContainsExpression
AsyncArrowBindingIdentifier : BindingIdentifier
  1. 返回 false

15.1.3 Static Semantics: IsSimpleParameterList

The syntax-directed operation IsSimpleParameterList takes no arguments and returns 一个布尔值. It is defined piecewise over the following productions:

BindingElement : BindingPattern
  1. 返回 false
BindingElement : BindingPattern Initializer
  1. 返回 false
SingleNameBinding : BindingIdentifier
  1. 返回 true
SingleNameBinding : BindingIdentifier Initializer
  1. 返回 false
FormalParameters : [empty]
  1. 返回 true
FormalParameters : FunctionRestParameter
  1. 返回 false
FormalParameters : FormalParameterList , FunctionRestParameter
  1. 返回 false
FormalParameterList : FormalParameterList , FormalParameter
  1. 如果 FormalParameterListIsSimpleParameterListfalse,返回 false
  2. 返回 FormalParameterIsSimpleParameterList
FormalParameter : BindingElement
  1. 返回 BindingElementIsSimpleParameterList
ArrowParameters : BindingIdentifier
  1. 返回 true
ArrowParameters : CoverParenthesizedExpressionAndArrowParameterList
  1. formals 为被 CoverParenthesizedExpressionAndArrowParameterList 覆盖ArrowFormalParameters
  2. 返回 formalsIsSimpleParameterList
AsyncArrowBindingIdentifier : BindingIdentifier
  1. 返回 true
CoverCallExpressionAndAsyncArrowHead : MemberExpression Arguments
  1. head 为被 CoverCallExpressionAndAsyncArrowHead 覆盖AsyncArrowHead
  2. 返回 headIsSimpleParameterList

15.1.4 Static Semantics: HasInitializer

The syntax-directed operation HasInitializer takes no arguments and returns 一个布尔值. It is defined piecewise over the following productions:

BindingElement : BindingPattern
  1. 返回 false
BindingElement : BindingPattern Initializer
  1. 返回 true
SingleNameBinding : BindingIdentifier
  1. 返回 false
SingleNameBinding : BindingIdentifier Initializer
  1. 返回 true
FormalParameterList : FormalParameterList , FormalParameter
  1. 如果 FormalParameterListHasInitializertrue,返回 true
  2. 返回 FormalParameterHasInitializer

15.1.5 Static Semantics: ExpectedArgumentCount

The syntax-directed operation ExpectedArgumentCount takes no arguments and returns 一个非负整数. It is defined piecewise over the following productions:

FormalParameters : [empty] FunctionRestParameter
  1. 返回 0。
FormalParameters : FormalParameterList , FunctionRestParameter
  1. 返回 FormalParameterListExpectedArgumentCount
Note

FormalParameterList 的 ExpectedArgumentCount 是位于 rest 参数或第一个带有 Initializer 的 FormalParameter 左侧的 FormalParameters 的数量。允许在第一个带有初始化器的参数之后再出现没有初始化器的 FormalParameter,但此类参数被视为可选参数,其默认值为 undefined

FormalParameterList : FormalParameter
  1. 如果 FormalParameterHasInitializertrue,返回 0。
  2. 返回 1。
FormalParameterList : FormalParameterList , FormalParameter
  1. countFormalParameterListExpectedArgumentCount
  2. 如果 FormalParameterListHasInitializertrueFormalParameterHasInitializertrue,返回 count
  3. 返回 count + 1。
ArrowParameters : BindingIdentifier
  1. 返回 1。
ArrowParameters : CoverParenthesizedExpressionAndArrowParameterList
  1. formals 为被 CoverParenthesizedExpressionAndArrowParameterList 覆盖ArrowFormalParameters
  2. 返回 formalsExpectedArgumentCount
PropertySetParameterList : FormalParameter
  1. 如果 FormalParameterHasInitializertrue,返回 0。
  2. 返回 1。
AsyncArrowBindingIdentifier : BindingIdentifier
  1. 返回 1。

15.2 函数定义

语法

FunctionDeclaration[Yield, Await, Default] : function BindingIdentifier[?Yield, ?Await] ( FormalParameters[~Yield, ~Await] ) { FunctionBody[~Yield, ~Await] } [+Default] function ( FormalParameters[~Yield, ~Await] ) { FunctionBody[~Yield, ~Await] } FunctionExpression : function BindingIdentifier[~Yield, ~Await]opt ( FormalParameters[~Yield, ~Await] ) { FunctionBody[~Yield, ~Await] } FunctionBody[Yield, Await] : FunctionStatementList[?Yield, ?Await] FunctionStatementList[Yield, Await] : StatementList[?Yield, ?Await, +Return]opt

15.2.1 Static Semantics: 早期错误

FunctionDeclaration : function BindingIdentifier ( FormalParameters ) { FunctionBody } function ( FormalParameters ) { FunctionBody } FunctionExpression : function BindingIdentifieropt ( FormalParameters ) { FunctionBody } Note

FunctionBodyLexicallyDeclaredNames 不包含使用 var 或 function 声明绑定的标识符。

FunctionBody : FunctionStatementList

15.2.2 Static Semantics: FunctionBodyContainsUseStrict

The syntax-directed operation FunctionBodyContainsUseStrict takes no arguments and returns 布尔值. It is defined piecewise over the following productions:

FunctionBody : FunctionStatementList
  1. 如果 FunctionBody指令序言包含 Use Strict 指令,返回 true
  2. 返回 false

15.2.3 Runtime Semantics: EvaluateFunctionBody

The syntax-directed operation EvaluateFunctionBody takes arguments functionObject (ECMAScript 函数对象) and argumentsList (ECMAScript 语言值列表) and returns 返回补全或抛出补全. It is defined piecewise over the following productions:

FunctionBody : FunctionStatementList
  1. 执行 ? FunctionDeclarationInstantiation(functionObject, argumentsList)。
  2. 执行 FunctionStatementList 的 ? Evaluation
  3. 注:如果上一步产生了正常补全,则求值是通过越过 FunctionStatementList 的末尾而完成的。
  4. 返回 ReturnCompletion(undefined)。

15.2.4 Runtime Semantics: InstantiateOrdinaryFunctionObject

The syntax-directed operation InstantiateOrdinaryFunctionObject takes arguments env (Environment Record) and privateEnv (PrivateEnvironment Recordnull) and returns ECMAScript 函数对象. It is defined piecewise over the following productions:

FunctionDeclaration : function BindingIdentifier ( FormalParameters ) { FunctionBody }
  1. nameBindingIdentifierStringValue
  2. sourceTextFunctionDeclaration 匹配的源文本
  3. closureOrdinaryFunctionCreate(%Function.prototype%, sourceText, FormalParameters, FunctionBody, non-lexical-this, env, privateEnv)。
  4. 执行 SetFunctionName(closure, name)。
  5. 执行 MakeConstructor(closure)。
  6. 返回 closure
FunctionDeclaration : function ( FormalParameters ) { FunctionBody }
  1. sourceTextFunctionDeclaration 匹配的源文本
  2. closureOrdinaryFunctionCreate(%Function.prototype%, sourceText, FormalParameters, FunctionBody, non-lexical-this, env, privateEnv)。
  3. 执行 SetFunctionName(closure, "default")。
  4. 执行 MakeConstructor(closure)。
  5. 返回 closure
Note

匿名 FunctionDeclaration 只能作为 export default 声明的一部分出现,因此它的函数代码始终是严格模式代码

15.2.5 Runtime Semantics: InstantiateOrdinaryFunctionExpression

The syntax-directed operation InstantiateOrdinaryFunctionExpression takes optional argument name (属性键Private Name) and returns ECMAScript 函数对象. It is defined piecewise over the following productions:

FunctionExpression : function ( FormalParameters ) { FunctionBody }
  1. 如果 name 不存在,则将 name 设为空 String。
  2. env 为运行中的执行上下文的 LexicalEnvironment。
  3. privateEnv 为运行中的执行上下文的 PrivateEnvironment。
  4. sourceTextFunctionExpression 匹配的源文本
  5. closureOrdinaryFunctionCreate(%Function.prototype%, sourceText, FormalParameters, FunctionBody, non-lexical-this, env, privateEnv)。
  6. 执行 SetFunctionName(closure, name)。
  7. 执行 MakeConstructor(closure)。
  8. 返回 closure
FunctionExpression : function BindingIdentifier ( FormalParameters ) { FunctionBody }
  1. 断言:name 不存在。
  2. name 设为 BindingIdentifierStringValue
  3. outerEnv 为运行中的执行上下文的 LexicalEnvironment。
  4. funcEnvNewDeclarativeEnvironment(outerEnv)。
  5. 执行 ! funcEnv.CreateImmutableBinding(name, false)。
  6. privateEnv 为运行中的执行上下文的 PrivateEnvironment。
  7. sourceTextFunctionExpression 匹配的源文本
  8. closureOrdinaryFunctionCreate(%Function.prototype%, sourceText, FormalParameters, FunctionBody, non-lexical-this, funcEnv, privateEnv)。
  9. 执行 SetFunctionName(closure, name)。
  10. 执行 MakeConstructor(closure)。
  11. 执行 ! funcEnv.InitializeBinding(name, closure)。
  12. 返回 closure
Note

FunctionExpression 中的 BindingIdentifier 可以从 FunctionExpressionFunctionBody 内部引用,以允许函数递归调用自身。但是,与 FunctionDeclaration 不同,FunctionExpression 中的 BindingIdentifier 不能从包围该 FunctionExpression 的作用域中引用,也不会影响该作用域。

15.2.6 Runtime Semantics: Evaluation

FunctionDeclaration : function BindingIdentifier ( FormalParameters ) { FunctionBody }
  1. 返回 empty
Note 1 FunctionDeclaration : function ( FormalParameters ) { FunctionBody }
  1. 返回 empty
FunctionExpression : function BindingIdentifieropt ( FormalParameters ) { FunctionBody }
  1. 返回 FunctionExpressionInstantiateOrdinaryFunctionExpression
Note 2

对于每个使用 FunctionDeclarationFunctionExpression 定义的函数,都会自动创建一个 "prototype" 属性,以允许该函数可能被用作构造函数。

FunctionStatementList : [empty]
  1. 返回 undefined

15.3 箭头函数定义

语法

ArrowFunction[In, Yield, Await] : ArrowParameters[?Yield, ?Await] [no LineTerminator here] => ConciseBody[?In] ArrowParameters[Yield, Await] : BindingIdentifier[?Yield, ?Await] CoverParenthesizedExpressionAndArrowParameterList[?Yield, ?Await] ConciseBody[In] : [lookahead ≠ {] ExpressionBody[?In, ~Await] { FunctionBody[~Yield, ~Await] } ExpressionBody[In, Await] : AssignmentExpression[?In, ~Yield, ?Await]

补充语法

当处理产生式的一个实例
ArrowParameters[Yield, Await] : CoverParenthesizedExpressionAndArrowParameterList[?Yield, ?Await]
时,使用以下文法来细化对 CoverParenthesizedExpressionAndArrowParameterList 的解释:

ArrowFormalParameters[Yield, Await] : ( UniqueFormalParameters[?Yield, ?Await] )

15.3.1 Static Semantics: 早期错误

ArrowFunction : ArrowParameters => ConciseBody ArrowParameters : CoverParenthesizedExpressionAndArrowParameterList

15.3.2 Static Semantics: ConciseBodyContainsUseStrict

The syntax-directed operation ConciseBodyContainsUseStrict takes no arguments and returns 一个布尔值. It is defined piecewise over the following productions:

ConciseBody : ExpressionBody
  1. 返回 false
ConciseBody : { FunctionBody }
  1. 返回 FunctionBodyFunctionBodyContainsUseStrict

15.3.3 Runtime Semantics: EvaluateConciseBody

The syntax-directed operation EvaluateConciseBody takes arguments functionObject (一个 ECMAScript 函数对象) and argumentsList (ECMAScript 语言值List) and returns 一个返回完成或抛出完成. It is defined piecewise over the following productions:

ConciseBody : ExpressionBody
  1. 执行 ? FunctionDeclarationInstantiation(functionObject, argumentsList)。
  2. 返回 ? ExpressionBodyEvaluation

15.3.4 Runtime Semantics: InstantiateArrowFunctionExpression

The syntax-directed operation InstantiateArrowFunctionExpression takes optional argument name (一个属性键Private Name) and returns 一个 ECMAScript 函数对象. It is defined piecewise over the following productions:

ArrowFunction : ArrowParameters => ConciseBody
  1. 如果 name 不存在,则将 name 设为空 String。
  2. env 为运行中执行上下文的 LexicalEnvironment。
  3. privateEnv 为运行中执行上下文的 PrivateEnvironment。
  4. sourceTextArrowFunction匹配的源文本
  5. closureOrdinaryFunctionCreate(%Function.prototype%, sourceText, ArrowParameters, ConciseBody, lexical-this, env, privateEnv)。
  6. 执行 SetFunctionName(closure, name)。
  7. 返回 closure
Note

ArrowFunction 不会为 argumentssuperthisnew.target 定义局部绑定。ArrowFunction 内部对 argumentssuperthisnew.target 的任何引用都必须解析到词法外围环境中的绑定。通常这会是紧邻外围函数的 Function Environment。即使 ArrowFunction 可以包含对 super 的引用,在步骤 5 中创建的函数对象也不会通过执行 MakeMethod 而成为方法。引用 superArrowFunction 总是包含在非 ArrowFunction 内,实现 super 所需的状态可通过 ArrowFunction函数对象所捕获的 env 访问。

15.3.5 Runtime Semantics: Evaluation

ArrowFunction : ArrowParameters => ConciseBody
  1. 返回 ArrowFunctionInstantiateArrowFunctionExpression
ExpressionBody : AssignmentExpression
  1. exprRef 为 ? AssignmentExpressionEvaluation
  2. exprValue 为 ? GetValue(exprRef)。
  3. 返回 ReturnCompletion(exprValue)。

15.4 方法定义

语法

MethodDefinition[Yield, Await] : ClassElementName[?Yield, ?Await] ( UniqueFormalParameters[~Yield, ~Await] ) { FunctionBody[~Yield, ~Await] } GeneratorMethod[?Yield, ?Await] AsyncMethod[?Yield, ?Await] AsyncGeneratorMethod[?Yield, ?Await] get ClassElementName[?Yield, ?Await] ( ) { FunctionBody[~Yield, ~Await] } set ClassElementName[?Yield, ?Await] ( PropertySetParameterList ) { FunctionBody[~Yield, ~Await] } PropertySetParameterList : FormalParameter[~Yield, ~Await]

15.4.1 Static Semantics: 早期错误

MethodDefinition : ClassElementName ( UniqueFormalParameters ) { FunctionBody } MethodDefinition : set ClassElementName ( PropertySetParameterList ) { FunctionBody }

15.4.2 Static Semantics: HasDirectSuper

The syntax-directed operation HasDirectSuper takes no arguments and returns 一个布尔值. It is defined piecewise over the following productions:

MethodDefinition : ClassElementName ( UniqueFormalParameters ) { FunctionBody }
  1. 如果 UniqueFormalParameters Contains SuperCalltrue,返回 true
  2. 返回 FunctionBody Contains SuperCall
MethodDefinition : get ClassElementName ( ) { FunctionBody }
  1. 返回 FunctionBody Contains SuperCall
MethodDefinition : set ClassElementName ( PropertySetParameterList ) { FunctionBody }
  1. 如果 PropertySetParameterList Contains SuperCalltrue,返回 true
  2. 返回 FunctionBody Contains SuperCall
GeneratorMethod : * ClassElementName ( UniqueFormalParameters ) { GeneratorBody }
  1. 如果 UniqueFormalParameters Contains SuperCalltrue,返回 true
  2. 返回 GeneratorBody Contains SuperCall
AsyncGeneratorMethod : async * ClassElementName ( UniqueFormalParameters ) { AsyncGeneratorBody }
  1. 如果 UniqueFormalParameters Contains SuperCalltrue,返回 true
  2. 返回 AsyncGeneratorBody Contains SuperCall
AsyncMethod : async ClassElementName ( UniqueFormalParameters ) { AsyncFunctionBody }
  1. 如果 UniqueFormalParameters Contains SuperCalltrue,返回 true
  2. 返回 AsyncFunctionBody Contains SuperCall

15.4.3 Static Semantics: SpecialMethod

The syntax-directed operation SpecialMethod takes no arguments and returns 一个布尔值. It is defined piecewise over the following productions:

MethodDefinition : ClassElementName ( UniqueFormalParameters ) { FunctionBody }
  1. 返回 false
MethodDefinition : GeneratorMethod AsyncMethod AsyncGeneratorMethod get ClassElementName ( ) { FunctionBody } set ClassElementName ( PropertySetParameterList ) { FunctionBody }
  1. 返回 true

15.4.4 Runtime Semantics: DefineMethod

The syntax-directed operation DefineMethod takes argument object (一个 Object) and optional argument functionPrototype (一个 Object) and returns 要么是一个正常完成,其中包含带有字段 [[Key]](一个属性键)和 [[Closure]](一个 ECMAScript 函数对象)的 Record;要么是一个突然完成. It is defined piecewise over the following productions:

MethodDefinition : ClassElementName ( UniqueFormalParameters ) { FunctionBody }
  1. propertyKey 为 ? ClassElementNameEvaluation
  2. env 为运行中执行上下文的 LexicalEnvironment。
  3. privateEnv 为运行中执行上下文的 PrivateEnvironment。
  4. 如果 functionPrototype 存在,则
    1. prototypefunctionPrototype
  5. 否则,
    1. prototype%Function.prototype%
  6. sourceTextMethodDefinition匹配的源文本
  7. closureOrdinaryFunctionCreate(prototype, sourceText, UniqueFormalParameters, FunctionBody, non-lexical-this, env, privateEnv)。
  8. 执行 MakeMethod(closure, object)。
  9. 返回 Record { [[Key]]: propertyKey, [[Closure]]: closure }。

15.4.5 Runtime Semantics: MethodDefinitionEvaluation

The syntax-directed operation MethodDefinitionEvaluation takes arguments object (一个 Object) and enumerable (一个布尔值) and returns 要么是一个正常完成,其中包含一个 PrivateElementunused;要么是一个突然完成. It is defined piecewise over the following productions:

MethodDefinition : ClassElementName ( UniqueFormalParameters ) { FunctionBody }
  1. methodDef 为以 object 为参数的 MethodDefinition 的 ? DefineMethod
  2. 执行 SetFunctionName(methodDef.[[Closure]], methodDef.[[Key]])。
  3. 返回 ? DefineMethodProperty(object, methodDef.[[Key]], methodDef.[[Closure]], enumerable)。
MethodDefinition : get ClassElementName ( ) { FunctionBody }
  1. propertyKey 为 ? ClassElementNameEvaluation
  2. env 为运行中执行上下文的 LexicalEnvironment。
  3. privateEnv 为运行中执行上下文的 PrivateEnvironment。
  4. sourceTextMethodDefinition匹配的源文本
  5. formalParameterList 为产生式 FormalParameters : [empty] 的一个实例。
  6. closureOrdinaryFunctionCreate(%Function.prototype%, sourceText, formalParameterList, FunctionBody, non-lexical-this, env, privateEnv)。
  7. 执行 MakeMethod(closure, object)。
  8. 执行 SetFunctionName(closure, propertyKey, "get")。
  9. 如果 propertyKeyPrivate Name,则
    1. 返回 PrivateElement { [[Key]]: propertyKey, [[Kind]]: accessor, [[Get]]: closure, [[Set]]: undefined }。
  10. desc 为 PropertyDescriptor { [[Get]]: closure, [[Enumerable]]: enumerable, [[Configurable]]: true }。
  11. 执行 ? DefinePropertyOrThrow(object, propertyKey, desc)。
  12. 返回 unused
MethodDefinition : set ClassElementName ( PropertySetParameterList ) { FunctionBody }
  1. propertyKey 为 ? ClassElementNameEvaluation
  2. env 为运行中执行上下文的 LexicalEnvironment。
  3. privateEnv 为运行中执行上下文的 PrivateEnvironment。
  4. sourceTextMethodDefinition匹配的源文本
  5. closureOrdinaryFunctionCreate(%Function.prototype%, sourceText, PropertySetParameterList, FunctionBody, non-lexical-this, env, privateEnv)。
  6. 执行 MakeMethod(closure, object)。
  7. 执行 SetFunctionName(closure, propertyKey, "set")。
  8. 如果 propertyKeyPrivate Name,则
    1. 返回 PrivateElement { [[Key]]: propertyKey, [[Kind]]: accessor, [[Get]]: undefined, [[Set]]: closure }。
  9. desc 为 PropertyDescriptor { [[Set]]: closure, [[Enumerable]]: enumerable, [[Configurable]]: true }。
  10. 执行 ? DefinePropertyOrThrow(object, propertyKey, desc)。
  11. 返回 unused
GeneratorMethod : * ClassElementName ( UniqueFormalParameters ) { GeneratorBody }
  1. propertyKey 为 ? ClassElementNameEvaluation
  2. env 为运行中执行上下文的 LexicalEnvironment。
  3. privateEnv 为运行中执行上下文的 PrivateEnvironment。
  4. sourceTextGeneratorMethod匹配的源文本
  5. closureOrdinaryFunctionCreate(%GeneratorFunction.prototype%, sourceText, UniqueFormalParameters, GeneratorBody, non-lexical-this, env, privateEnv)。
  6. 执行 MakeMethod(closure, object)。
  7. 执行 SetFunctionName(closure, propertyKey)。
  8. prototypeOrdinaryObjectCreate(%GeneratorPrototype%)。
  9. 执行 ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  10. 返回 ? DefineMethodProperty(object, propertyKey, closure, enumerable)。
AsyncGeneratorMethod : async * ClassElementName ( UniqueFormalParameters ) { AsyncGeneratorBody }
  1. propertyKey 为 ? ClassElementNameEvaluation
  2. env 为运行中执行上下文的 LexicalEnvironment。
  3. privateEnv 为运行中执行上下文的 PrivateEnvironment。
  4. sourceTextAsyncGeneratorMethod匹配的源文本
  5. closureOrdinaryFunctionCreate(%AsyncGeneratorFunction.prototype%, sourceText, UniqueFormalParameters, AsyncGeneratorBody, non-lexical-this, env, privateEnv)。
  6. 执行 MakeMethod(closure, object)。
  7. 执行 SetFunctionName(closure, propertyKey)。
  8. prototypeOrdinaryObjectCreate(%AsyncGeneratorPrototype%)。
  9. 执行 ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  10. 返回 ? DefineMethodProperty(object, propertyKey, closure, enumerable)。
AsyncMethod : async ClassElementName ( UniqueFormalParameters ) { AsyncFunctionBody }
  1. propertyKey 为 ? ClassElementNameEvaluation
  2. env 为运行中执行上下文的 LexicalEnvironment。
  3. privateEnv 为运行中执行上下文的 PrivateEnvironment。
  4. sourceTextAsyncMethod匹配的源文本
  5. closureOrdinaryFunctionCreate(%AsyncFunction.prototype%, sourceText, UniqueFormalParameters, AsyncFunctionBody, non-lexical-this, env, privateEnv)。
  6. 执行 MakeMethod(closure, object)。
  7. 执行 SetFunctionName(closure, propertyKey)。
  8. 返回 ? DefineMethodProperty(object, propertyKey, closure, enumerable)。

15.5 生成器函数定义

语法

GeneratorDeclaration[Yield, Await, Default] : function * BindingIdentifier[?Yield, ?Await] ( FormalParameters[+Yield, ~Await] ) { GeneratorBody } [+Default] function * ( FormalParameters[+Yield, ~Await] ) { GeneratorBody } GeneratorExpression : function * BindingIdentifier[+Yield, ~Await]opt ( FormalParameters[+Yield, ~Await] ) { GeneratorBody } GeneratorMethod[Yield, Await] : * ClassElementName[?Yield, ?Await] ( UniqueFormalParameters[+Yield, ~Await] ) { GeneratorBody } GeneratorBody : FunctionBody[+Yield, ~Await] YieldExpression[In, Await] : yield yield [no LineTerminator here] AssignmentExpression[?In, +Yield, ?Await] yield [no LineTerminator here] * AssignmentExpression[?In, +Yield, ?Await] Note 1

紧跟在 yield 之后的语法上下文要求使用 InputElementRegExpOrTemplateTail 词法目标。

Note 2

YieldExpression 不能在生成器函数的 FormalParameters 内使用,因为作为 FormalParameters 一部分的任何表达式都会在生成的 Generator 进入可恢复状态之前求值。

Note 3

与 Generator 相关的抽象操作定义于 27.5.3

15.5.1 Static Semantics: 早期错误

GeneratorMethod : * ClassElementName ( UniqueFormalParameters ) { GeneratorBody } GeneratorDeclaration : function * BindingIdentifier ( FormalParameters ) { GeneratorBody } function * ( FormalParameters ) { GeneratorBody } GeneratorExpression : function * BindingIdentifieropt ( FormalParameters ) { GeneratorBody }

15.5.2 Runtime Semantics: EvaluateGeneratorBody

The syntax-directed operation EvaluateGeneratorBody takes arguments functionObject (一个 ECMAScript 函数对象) and argumentsList (ECMAScript 语言值List) and returns 一个抛出完成或返回完成. It is defined piecewise over the following productions:

GeneratorBody : FunctionBody
  1. 执行 ? FunctionDeclarationInstantiation(functionObject, argumentsList)。
  2. generator 为 ? OrdinaryCreateFromConstructor(functionObject, "%GeneratorPrototype%", « [[GeneratorState]], [[GeneratorContext]], [[GeneratorBrand]] »)。
  3. generator.[[GeneratorBrand]] 设为 empty
  4. generator.[[GeneratorState]] 设为 suspended-start
  5. 执行 GeneratorStart(generator, FunctionBody)。
  6. 返回 ReturnCompletion(generator)。

15.5.3 Runtime Semantics: InstantiateGeneratorFunctionObject

The syntax-directed operation InstantiateGeneratorFunctionObject takes arguments env (一个 Environment Record) and privateEnv (一个 PrivateEnvironment Recordnull) and returns 一个 ECMAScript 函数对象. It is defined piecewise over the following productions:

GeneratorDeclaration : function * BindingIdentifier ( FormalParameters ) { GeneratorBody }
  1. nameBindingIdentifierStringValue
  2. sourceTextGeneratorDeclaration匹配的源文本
  3. closureOrdinaryFunctionCreate(%GeneratorFunction.prototype%, sourceText, FormalParameters, GeneratorBody, non-lexical-this, env, privateEnv)。
  4. 执行 SetFunctionName(closure, name)。
  5. prototypeOrdinaryObjectCreate(%GeneratorPrototype%)。
  6. 执行 ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  7. 返回 closure
GeneratorDeclaration : function * ( FormalParameters ) { GeneratorBody }
  1. sourceTextGeneratorDeclaration匹配的源文本
  2. closureOrdinaryFunctionCreate(%GeneratorFunction.prototype%, sourceText, FormalParameters, GeneratorBody, non-lexical-this, env, privateEnv)。
  3. 执行 SetFunctionName(closure, "default")。
  4. prototypeOrdinaryObjectCreate(%GeneratorPrototype%)。
  5. 执行 ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  6. 返回 closure
Note

匿名 GeneratorDeclaration 只能作为 export default 声明的一部分出现,因此其函数代码总是严格模式代码

15.5.4 Runtime Semantics: InstantiateGeneratorFunctionExpression

The syntax-directed operation InstantiateGeneratorFunctionExpression takes optional argument name (一个属性键Private Name) and returns 一个 ECMAScript 函数对象. It is defined piecewise over the following productions:

GeneratorExpression : function * ( FormalParameters ) { GeneratorBody }
  1. 如果 name 不存在,则将 name 设为空 String。
  2. env 为运行中执行上下文的 LexicalEnvironment。
  3. privateEnv 为运行中执行上下文的 PrivateEnvironment。
  4. sourceTextGeneratorExpression匹配的源文本
  5. closureOrdinaryFunctionCreate(%GeneratorFunction.prototype%, sourceText, FormalParameters, GeneratorBody, non-lexical-this, env, privateEnv)。
  6. 执行 SetFunctionName(closure, name)。
  7. prototypeOrdinaryObjectCreate(%GeneratorPrototype%)。
  8. 执行 ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  9. 返回 closure
GeneratorExpression : function * BindingIdentifier ( FormalParameters ) { GeneratorBody }
  1. 断言:name 不存在。
  2. name 设为 BindingIdentifierStringValue
  3. outerEnv 为运行中执行上下文的 LexicalEnvironment。
  4. funcEnvNewDeclarativeEnvironment(outerEnv)。
  5. 执行 ! funcEnv.CreateImmutableBinding(name, false)。
  6. privateEnv 为运行中执行上下文的 PrivateEnvironment。
  7. sourceTextGeneratorExpression匹配的源文本
  8. closureOrdinaryFunctionCreate(%GeneratorFunction.prototype%, sourceText, FormalParameters, GeneratorBody, non-lexical-this, funcEnv, privateEnv)。
  9. 执行 SetFunctionName(closure, name)。
  10. prototypeOrdinaryObjectCreate(%GeneratorPrototype%)。
  11. 执行 ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  12. 执行 ! funcEnv.InitializeBinding(name, closure)。
  13. 返回 closure
Note

GeneratorExpression 中的 BindingIdentifier 可在 GeneratorExpressionFunctionBody 内被引用,以允许生成器代码递归调用自身。然而,与 GeneratorDeclaration 中不同,GeneratorExpression 中的 BindingIdentifier 不能从外围作用域引用,也不会影响包围 GeneratorExpression 的作用域。

15.5.5 Runtime Semantics: Evaluation

GeneratorExpression : function * BindingIdentifieropt ( FormalParameters ) { GeneratorBody }
  1. 返回 GeneratorExpressionInstantiateGeneratorFunctionExpression
YieldExpression : yield
  1. 返回 ? Yield(undefined)。
YieldExpression : yield AssignmentExpression
  1. exprRef 为 ? AssignmentExpressionEvaluation
  2. value 为 ? GetValue(exprRef)。
  3. 返回 ? Yield(value)。
YieldExpression : yield * AssignmentExpression
  1. generatorKindGetGeneratorKind()。
  2. 断言:generatorKindsyncasync
  3. exprRef 为 ? AssignmentExpressionEvaluation
  4. value 为 ? GetValue(exprRef)。
  5. iteratorRecord 为 ? GetIterator(value, generatorKind)。
  6. iteratoriteratorRecord.[[Iterator]]
  7. receivedNormalCompletion(undefined)。
  8. 重复,
    1. 如果 received正常完成,则
      1. innerResult 为 ? Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]], « received.[[Value]] »)。
      2. 如果 generatorKindasync,则将 innerResult 设为 ? Await(innerResult)。
      3. 如果 innerResult 不是 Object,则抛出 TypeError 异常。
      4. done 为 ? IteratorComplete(innerResult)。
      5. 如果 donetrue,则
        1. 返回 ? IteratorValue(innerResult)。
      6. 如果 generatorKindasync,则将 received 设为 Completion(AsyncGeneratorYield(? IteratorValue(innerResult)))。
      7. 否则,将 received 设为 Completion(GeneratorYield(innerResult))。
    2. 否则如果 received 是抛出完成,则
      1. throw 为 ? GetMethod(iterator, "throw")。
      2. 如果 throw 不是 undefined,则
        1. innerResult 为 ? Call(throw, iterator, « received.[[Value]] »)。
        2. 如果 generatorKindasync,则将 innerResult 设为 ? Await(innerResult)。
        3. 注:来自内部迭代器 throw 方法的异常会被传播。来自内部 throw 方法的正常完成会以类似于内部 next 的方式处理。
        4. 如果 innerResult 不是 Object,则抛出 TypeError 异常。
        5. done 为 ? IteratorComplete(innerResult)。
        6. 如果 donetrue,则
          1. 返回 ? IteratorValue(innerResult)。
        7. 如果 generatorKindasync,则将 received 设为 Completion(AsyncGeneratorYield(? IteratorValue(innerResult)))。
        8. 否则,将 received 设为 Completion(GeneratorYield(innerResult))。
      3. 否则,
        1. 注:如果 iterator 没有 throw 方法,此抛出将终止 yield* 循环。但首先需要给 iterator 一个清理的机会。
        2. closeCompletionNormalCompletion(empty)。
        3. 如果 generatorKindasync,执行 ? AsyncIteratorClose(iteratorRecord, closeCompletion)。
        4. 否则,执行 ? IteratorClose(iteratorRecord, closeCompletion)。
        5. 注:下一步抛出 TypeError,用于表明存在 yield* 协议违例:iterator 没有 throw 方法。
        6. 抛出 TypeError 异常。
    3. 否则,
      1. 断言:received 是返回完成。
      2. return 为 ? GetMethod(iterator, "return")。
      3. 如果 returnundefined,则
        1. receivedValuereceived.[[Value]]
        2. 如果 generatorKindasync,则
          1. receivedValue 设为 ? Await(receivedValue)。
        3. 返回 ReturnCompletion(receivedValue)。
      4. innerReturnResult 为 ? Call(return, iterator, « received.[[Value]] »)。
      5. 如果 generatorKindasync,则将 innerReturnResult 设为 ? Await(innerReturnResult)。
      6. 如果 innerReturnResult 不是 Object,则抛出 TypeError 异常。
      7. done 为 ? IteratorComplete(innerReturnResult)。
      8. 如果 donetrue,则
        1. returnedValue 为 ? IteratorValue(innerReturnResult)。
        2. 返回 ReturnCompletion(returnedValue)。
      9. 如果 generatorKindasync,则将 received 设为 Completion(AsyncGeneratorYield(? IteratorValue(innerReturnResult)))。
      10. 否则,将 received 设为 Completion(GeneratorYield(innerReturnResult))。

15.6 异步生成器函数定义

语法

AsyncGeneratorDeclaration[Yield, Await, Default] : async [no LineTerminator here] function * BindingIdentifier[?Yield, ?Await] ( FormalParameters[+Yield, +Await] ) { AsyncGeneratorBody } [+Default] async [no LineTerminator here] function * ( FormalParameters[+Yield, +Await] ) { AsyncGeneratorBody } AsyncGeneratorExpression : async [no LineTerminator here] function * BindingIdentifier[+Yield, +Await]opt ( FormalParameters[+Yield, +Await] ) { AsyncGeneratorBody } AsyncGeneratorMethod[Yield, Await] : async [no LineTerminator here] * ClassElementName[?Yield, ?Await] ( UniqueFormalParameters[+Yield, +Await] ) { AsyncGeneratorBody } AsyncGeneratorBody : FunctionBody[+Yield, +Await] Note 1

YieldExpressionAwaitExpression 不能在异步生成器函数的 FormalParameters 内使用,因为作为 FormalParameters 一部分的任何表达式都会在生成的 AsyncGenerator 进入可恢复状态之前求值。

Note 2

与 AsyncGenerator 相关的抽象操作定义于 27.6.3

15.6.1 Static Semantics: 早期错误

AsyncGeneratorMethod : async * ClassElementName ( UniqueFormalParameters ) { AsyncGeneratorBody } AsyncGeneratorDeclaration : async function * BindingIdentifier ( FormalParameters ) { AsyncGeneratorBody } async function * ( FormalParameters ) { AsyncGeneratorBody } AsyncGeneratorExpression : async function * BindingIdentifieropt ( FormalParameters ) { AsyncGeneratorBody }

15.6.2 Runtime Semantics: EvaluateAsyncGeneratorBody

The syntax-directed operation EvaluateAsyncGeneratorBody takes arguments functionObject (一个 ECMAScript 函数对象) and argumentsList (ECMAScript 语言值List) and returns 一个抛出完成或返回完成. It is defined piecewise over the following productions:

AsyncGeneratorBody : FunctionBody
  1. 执行 ? FunctionDeclarationInstantiation(functionObject, argumentsList)。
  2. generator 为 ? OrdinaryCreateFromConstructor(functionObject, "%AsyncGeneratorPrototype%", « [[AsyncGeneratorState]], [[AsyncGeneratorContext]], [[AsyncGeneratorQueue]], [[GeneratorBrand]] »)。
  3. generator.[[GeneratorBrand]] 设为 empty
  4. generator.[[AsyncGeneratorState]] 设为 suspended-start
  5. 执行 AsyncGeneratorStart(generator, FunctionBody)。
  6. 返回 ReturnCompletion(generator)。

15.6.3 Runtime Semantics: InstantiateAsyncGeneratorFunctionObject

The syntax-directed operation InstantiateAsyncGeneratorFunctionObject takes arguments env (一个 Environment Record) and privateEnv (一个 PrivateEnvironment Recordnull) and returns 一个 ECMAScript 函数对象. It is defined piecewise over the following productions:

AsyncGeneratorDeclaration : async function * BindingIdentifier ( FormalParameters ) { AsyncGeneratorBody }
  1. nameBindingIdentifierStringValue
  2. sourceTextAsyncGeneratorDeclaration匹配的源文本
  3. closureOrdinaryFunctionCreate(%AsyncGeneratorFunction.prototype%, sourceText, FormalParameters, AsyncGeneratorBody, non-lexical-this, env, privateEnv)。
  4. 执行 SetFunctionName(closure, name)。
  5. prototypeOrdinaryObjectCreate(%AsyncGeneratorPrototype%)。
  6. 执行 ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  7. 返回 closure
AsyncGeneratorDeclaration : async function * ( FormalParameters ) { AsyncGeneratorBody }
  1. sourceTextAsyncGeneratorDeclaration匹配的源文本
  2. closureOrdinaryFunctionCreate(%AsyncGeneratorFunction.prototype%, sourceText, FormalParameters, AsyncGeneratorBody, non-lexical-this, env, privateEnv)。
  3. 执行 SetFunctionName(closure, "default")。
  4. prototypeOrdinaryObjectCreate(%AsyncGeneratorPrototype%)。
  5. 执行 ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  6. 返回 closure
Note

匿名 AsyncGeneratorDeclaration 只能作为 export default 声明的一部分出现。

15.6.4 Runtime Semantics: InstantiateAsyncGeneratorFunctionExpression

The syntax-directed operation InstantiateAsyncGeneratorFunctionExpression takes optional argument name (一个属性键Private Name) and returns 一个 ECMAScript 函数对象. It is defined piecewise over the following productions:

AsyncGeneratorExpression : async function * ( FormalParameters ) { AsyncGeneratorBody }
  1. 如果 name 不存在,则将 name 设为空 String。
  2. env 为运行中执行上下文的 LexicalEnvironment。
  3. privateEnv 为运行中执行上下文的 PrivateEnvironment。
  4. sourceTextAsyncGeneratorExpression匹配的源文本
  5. closureOrdinaryFunctionCreate(%AsyncGeneratorFunction.prototype%, sourceText, FormalParameters, AsyncGeneratorBody, non-lexical-this, env, privateEnv)。
  6. 执行 SetFunctionName(closure, name)。
  7. prototypeOrdinaryObjectCreate(%AsyncGeneratorPrototype%)。
  8. 执行 ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  9. 返回 closure
AsyncGeneratorExpression : async function * BindingIdentifier ( FormalParameters ) { AsyncGeneratorBody }
  1. 断言:name 不存在。
  2. name 设为 BindingIdentifierStringValue
  3. outerEnv 为运行中执行上下文的 LexicalEnvironment。
  4. funcEnvNewDeclarativeEnvironment(outerEnv)。
  5. 执行 ! funcEnv.CreateImmutableBinding(name, false)。
  6. privateEnv 为运行中执行上下文的 PrivateEnvironment。
  7. sourceTextAsyncGeneratorExpression匹配的源文本
  8. closureOrdinaryFunctionCreate(%AsyncGeneratorFunction.prototype%, sourceText, FormalParameters, AsyncGeneratorBody, non-lexical-this, funcEnv, privateEnv)。
  9. 执行 SetFunctionName(closure, name)。
  10. prototypeOrdinaryObjectCreate(%AsyncGeneratorPrototype%)。
  11. 执行 ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  12. 执行 ! funcEnv.InitializeBinding(name, closure)。
  13. 返回 closure
Note

AsyncGeneratorExpression 中的 BindingIdentifier 可在 AsyncGeneratorExpressionAsyncGeneratorBody 内被引用,以允许生成器代码递归调用自身。然而,与 AsyncGeneratorDeclaration 中不同,AsyncGeneratorExpression 中的 BindingIdentifier 不能从外围作用域引用,也不会影响包围 AsyncGeneratorExpression 的作用域。

15.6.5 Runtime Semantics: Evaluation

AsyncGeneratorExpression : async function * BindingIdentifieropt ( FormalParameters ) { AsyncGeneratorBody }
  1. 返回 AsyncGeneratorExpressionInstantiateAsyncGeneratorFunctionExpression

15.7 类定义

语法

ClassDeclaration[Yield, Await, Default] : class BindingIdentifier[?Yield, ?Await] ClassTail[?Yield, ?Await] [+Default] class ClassTail[?Yield, ?Await] ClassExpression[Yield, Await] : class BindingIdentifier[?Yield, ?Await]opt ClassTail[?Yield, ?Await] ClassTail[Yield, Await] : ClassHeritage[?Yield, ?Await]opt { ClassBody[?Yield, ?Await]opt } ClassHeritage[Yield, Await] : extends LeftHandSideExpression[?Yield, ?Await] ClassBody[Yield, Await] : ClassElementList[?Yield, ?Await] ClassElementList[Yield, Await] : ClassElement[?Yield, ?Await] ClassElementList[?Yield, ?Await] ClassElement[?Yield, ?Await] ClassElement[Yield, Await] : MethodDefinition[?Yield, ?Await] static MethodDefinition[?Yield, ?Await] FieldDefinition[?Yield, ?Await] ; static FieldDefinition[?Yield, ?Await] ; ClassStaticBlock ; FieldDefinition[Yield, Await] : ClassElementName[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]opt ClassElementName[Yield, Await] : PropertyName[?Yield, ?Await] PrivateIdentifier ClassStaticBlock : static { ClassStaticBlockBody } ClassStaticBlockBody : ClassStaticBlockStatementList ClassStaticBlockStatementList : StatementList[~Yield, +Await, ~Return]opt Note

类定义始终是严格模式代码

15.7.1 Static Semantics: 早期错误

ClassTail : ClassHeritageopt { ClassBody } ClassBody : ClassElementList ClassElement : MethodDefinition ClassElement : static MethodDefinition ClassElement : FieldDefinition ; ClassElement : static FieldDefinition ; FieldDefinition : ClassElementName Initializeropt ClassElementName : PrivateIdentifier ClassStaticBlockBody : ClassStaticBlockStatementList

15.7.2 Static Semantics: ClassElementKind

The syntax-directed operation ClassElementKind takes no arguments and returns constructor-methodnon-constructor-methodempty. It is defined piecewise over the following productions:

ClassElement : MethodDefinition
  1. 如果 MethodDefinitionPropName"constructor",返回 constructor-method
  2. 返回 non-constructor-method
ClassElement : static MethodDefinition FieldDefinition ; static FieldDefinition ;
  1. 返回 non-constructor-method
ClassElement : ClassStaticBlock
  1. 返回 non-constructor-method
ClassElement : ;
  1. 返回 empty

15.7.3 Static Semantics: ConstructorMethod

The syntax-directed operation ConstructorMethod takes no arguments and returns 一个 ClassElement 解析节点empty. It is defined piecewise over the following productions:

ClassElementList : ClassElement
  1. 如果 ClassElementClassElementKindconstructor-method,返回 ClassElement
  2. 返回 empty
ClassElementList : ClassElementList ClassElement
  1. headClassElementListConstructorMethod
  2. 如果 head 不是 empty,返回 head
  3. 如果 ClassElementClassElementKindconstructor-method,返回 ClassElement
  4. 返回 empty
Note

早期错误规则确保只有一个名为 "constructor" 的方法定义,并且它不是访问器属性或生成器定义。

15.7.4 Static Semantics: IsStatic

The syntax-directed operation IsStatic takes no arguments and returns 一个布尔值. It is defined piecewise over the following productions:

ClassElement : MethodDefinition
  1. 返回 false
ClassElement : static MethodDefinition
  1. 返回 true
ClassElement : FieldDefinition ;
  1. 返回 false
ClassElement : static FieldDefinition ;
  1. 返回 true
ClassElement : ClassStaticBlock
  1. 返回 true
ClassElement : ;
  1. 返回 false

15.7.5 Static Semantics: NonConstructorElements

The syntax-directed operation NonConstructorElements takes no arguments and returns 一个 ClassElement 解析节点List. It is defined piecewise over the following productions:

ClassElementList : ClassElement
  1. 如果 ClassElementClassElementKindnon-constructor-method,则
    1. 返回 « ClassElement »。
  2. 返回一个新的空 List
ClassElementList : ClassElementList ClassElement
  1. listClassElementListNonConstructorElements
  2. 如果 ClassElementClassElementKindnon-constructor-method,则
    1. ClassElement 追加到 list
  3. 返回 list

15.7.6 Static Semantics: PrototypePropertyNameList

The syntax-directed operation PrototypePropertyNameList takes no arguments and returns 一个属性键List. It is defined piecewise over the following productions:

ClassElementList : ClassElement
  1. propNameClassElementPropName
  2. 如果 propNameempty,返回一个新的空 List
  3. 如果 ClassElementIsStatictrue,返回一个新的空 List
  4. 返回 « propName »。
ClassElementList : ClassElementList ClassElement
  1. listClassElementListPrototypePropertyNameList
  2. propNameClassElementPropName
  3. 如果 propNameempty,返回 list
  4. 如果 ClassElementIsStatictrue,返回 list
  5. 返回 list 与 « propName » 的列表拼接。

15.7.7 Static Semantics: AllPrivateIdentifiersValid

The syntax-directed operation AllPrivateIdentifiersValid takes argument names (一个字符串的 List) and returns 一个布尔值.

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

  1. 对此解析节点的每个子节点 child,执行
    1. 如果 child 是非终结符的一个实例,则
      1. 如果以参数 names 调用 childAllPrivateIdentifiersValidfalse,返回 false
  2. 返回 true
MemberExpression : MemberExpression . PrivateIdentifier
  1. 如果 names 包含 PrivateIdentifierStringValue,则
    1. 返回以参数 names 调用 MemberExpressionAllPrivateIdentifiersValid
  2. 返回 false
CallExpression : CallExpression . PrivateIdentifier
  1. 如果 names 包含 PrivateIdentifierStringValue,则
    1. 返回以参数 names 调用 CallExpressionAllPrivateIdentifiersValid
  2. 返回 false
OptionalChain : ?. PrivateIdentifier
  1. 如果 names 包含 PrivateIdentifierStringValue,返回 true
  2. 返回 false
OptionalChain : OptionalChain . PrivateIdentifier
  1. 如果 names 包含 PrivateIdentifierStringValue,则
    1. 返回以参数 names 调用 OptionalChainAllPrivateIdentifiersValid
  2. 返回 false
ClassBody : ClassElementList
  1. newNamesnamesClassBodyPrivateBoundIdentifiers 的列表拼接。
  2. 返回以参数 newNames 调用 ClassElementListAllPrivateIdentifiersValid
RelationalExpression : PrivateIdentifier in ShiftExpression
  1. 如果 names 包含 PrivateIdentifierStringValue,则
    1. 返回以参数 names 调用 ShiftExpressionAllPrivateIdentifiersValid
  2. 返回 false

15.7.8 Static Semantics: PrivateBoundIdentifiers

The syntax-directed operation PrivateBoundIdentifiers takes no arguments and returns 一个字符串的 List. It is defined piecewise over the following productions:

FieldDefinition : ClassElementName Initializeropt
  1. 返回 ClassElementNamePrivateBoundIdentifiers
ClassElementName : PrivateIdentifier
  1. 返回一个 List,其唯一元素为 PrivateIdentifierStringValue
ClassElementName : PropertyName ClassElement : ClassStaticBlock ;
  1. 返回一个新的空 List
ClassElementList : ClassElementList ClassElement
  1. names1ClassElementListPrivateBoundIdentifiers
  2. names2ClassElementPrivateBoundIdentifiers
  3. 返回 names1names2 的列表拼接。
MethodDefinition : ClassElementName ( UniqueFormalParameters ) { FunctionBody } get ClassElementName ( ) { FunctionBody } set ClassElementName ( PropertySetParameterList ) { FunctionBody } GeneratorMethod : * ClassElementName ( UniqueFormalParameters ) { GeneratorBody } AsyncMethod : async ClassElementName ( UniqueFormalParameters ) { AsyncFunctionBody } AsyncGeneratorMethod : async * ClassElementName ( UniqueFormalParameters ) { AsyncGeneratorBody }
  1. 返回 ClassElementNamePrivateBoundIdentifiers

15.7.9 Static Semantics: ContainsArguments

The syntax-directed operation ContainsArguments takes no arguments and returns 一个布尔值.

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

  1. 对此解析节点的每个子节点 child,执行
    1. 如果 child 是非终结符的一个实例,则
      1. 如果 childContainsArgumentstrue,返回 true
  2. 返回 false
IdentifierReference : Identifier
  1. 如果 IdentifierStringValue"arguments",返回 true
  2. 返回 false
FunctionDeclaration : function BindingIdentifier ( FormalParameters ) { FunctionBody } function ( FormalParameters ) { FunctionBody } FunctionExpression : function BindingIdentifieropt ( FormalParameters ) { FunctionBody } GeneratorDeclaration : function * BindingIdentifier ( FormalParameters ) { GeneratorBody } function * ( FormalParameters ) { GeneratorBody } GeneratorExpression : function * BindingIdentifieropt ( FormalParameters ) { GeneratorBody } AsyncGeneratorDeclaration : async function * BindingIdentifier ( FormalParameters ) { AsyncGeneratorBody } async function * ( FormalParameters ) { AsyncGeneratorBody } AsyncGeneratorExpression : async function * BindingIdentifieropt ( FormalParameters ) { AsyncGeneratorBody } AsyncFunctionDeclaration : async function BindingIdentifier ( FormalParameters ) { AsyncFunctionBody } async function ( FormalParameters ) { AsyncFunctionBody } AsyncFunctionExpression : async function BindingIdentifieropt ( FormalParameters ) { AsyncFunctionBody }
  1. 返回 false
MethodDefinition : ClassElementName ( UniqueFormalParameters ) { FunctionBody } get ClassElementName ( ) { FunctionBody } set ClassElementName ( PropertySetParameterList ) { FunctionBody } GeneratorMethod : * ClassElementName ( UniqueFormalParameters ) { GeneratorBody } AsyncGeneratorMethod : async * ClassElementName ( UniqueFormalParameters ) { AsyncGeneratorBody } AsyncMethod : async ClassElementName ( UniqueFormalParameters ) { AsyncFunctionBody }
  1. 返回 ClassElementNameContainsArguments

15.7.10 Runtime Semantics: ClassFieldDefinitionEvaluation

The syntax-directed operation ClassFieldDefinitionEvaluation takes argument homeObject (一个 Object) and returns 要么是一个正常完成,其中包含一个 ClassFieldDefinition Record;要么是一个突然完成. It is defined piecewise over the following productions:

FieldDefinition : ClassElementName Initializeropt
  1. name 为 ? ClassElementNameEvaluation
  2. 如果 Initializer 存在,则
    1. formalParameterList 为产生式 FormalParameters : [empty] 的一个实例。
    2. env 为运行中执行上下文的 LexicalEnvironment。
    3. privateEnv 为运行中执行上下文的 PrivateEnvironment。
    4. sourceText 为空 Unicode 码点序列。
    5. initializerOrdinaryFunctionCreate(%Function.prototype%, sourceText, formalParameterList, Initializer, non-lexical-this, env, privateEnv)。
    6. 执行 MakeMethod(initializer, homeObject)。
    7. initializer.[[ClassFieldInitializerName]] 设为 name
  3. 否则,
    1. initializerempty
  4. 返回 ClassFieldDefinition Record { [[Name]]: name, [[Initializer]]: initializer }。
Note
initializer 创建的函数永远不能由 ECMAScript 代码直接访问。

15.7.11 Runtime Semantics: ClassStaticBlockDefinitionEvaluation

The syntax-directed operation ClassStaticBlockDefinitionEvaluation takes argument homeObject (一个 Object) and returns 一个 ClassStaticBlockDefinition Record. It is defined piecewise over the following productions:

ClassStaticBlock : static { ClassStaticBlockBody }
  1. lex 为运行中执行上下文的 LexicalEnvironment。
  2. privateEnv 为运行中执行上下文的 PrivateEnvironment。
  3. sourceText 为空 Unicode 码点序列。
  4. formalParameters 为产生式 FormalParameters : [empty] 的一个实例。
  5. bodyFunctionOrdinaryFunctionCreate(%Function.prototype%, sourceText, formalParameters, ClassStaticBlockBody, non-lexical-this, lex, privateEnv)。
  6. 执行 MakeMethod(bodyFunction, homeObject)。
  7. 返回 ClassStaticBlockDefinition Record { [[BodyFunction]]: bodyFunction }。
Note
函数 bodyFunction 永远不能由 ECMAScript 代码直接访问。

15.7.12 Runtime Semantics: EvaluateClassStaticBlockBody

The syntax-directed operation EvaluateClassStaticBlockBody takes argument functionObject (一个 ECMAScript 函数对象) and returns 一个返回完成或抛出完成. It is defined piecewise over the following productions:

ClassStaticBlockBody : ClassStaticBlockStatementList
  1. 断言:functionObject 是由 ClassStaticBlockDefinitionEvaluation 步骤 5 创建的合成函数。
  2. 执行 ! FunctionDeclarationInstantiation(functionObject, « »)。
  3. 执行 ? ClassStaticBlockStatementListEvaluation
  4. 返回 ReturnCompletion(undefined)。

15.7.13 Runtime Semantics: ClassElementEvaluation

The syntax-directed operation ClassElementEvaluation takes argument object (一个 Object) and returns 要么是一个正常完成,其中包含一个 ClassFieldDefinition Record、一个 ClassStaticBlockDefinition Record、一个 PrivateElementunused;要么是一个突然完成. It is defined piecewise over the following productions:

ClassElement : FieldDefinition ; static FieldDefinition ;
  1. 返回以 object 为参数的 FieldDefinition 的 ? ClassFieldDefinitionEvaluation
ClassElement : MethodDefinition static MethodDefinition
  1. 返回以 objectfalse 为参数的 MethodDefinition 的 ? MethodDefinitionEvaluation
ClassElement : ClassStaticBlock
  1. 返回以 object 为参数的 ClassStaticBlockClassStaticBlockDefinitionEvaluation
ClassElement : ;
  1. 返回 unused

15.7.14 Runtime Semantics: ClassDefinitionEvaluation

The syntax-directed operation ClassDefinitionEvaluation takes arguments classBinding (一个 String 或 undefined), className (一个属性键Private Name), and sourceText (ECMAScript 源文本) and returns 要么是一个正常完成,其中包含一个函数对象;要么是一个突然完成.

Note

为便于规范说明,私有方法和访问器与私有字段一起包含在类实例的 [[PrivateElements]] 槽中。然而,对于任一给定对象,要么具有由给定类定义的所有私有方法和访问器,要么一个也没有。此特性经过设计,使实现可以选择使用一种不需要单独跟踪每个方法或访问器的策略来实现私有方法和访问器。

例如,实现可以将实例私有方法直接与其对应的 Private Name 关联,并针对每个对象跟踪哪些类构造函数曾以该对象作为其 this 值运行。随后,在对象上查找实例私有方法就包括检查定义该方法的类构造函数是否已用于初始化该对象,然后返回与该 Private Name 关联的方法。

这不同于私有字段:由于字段初始化器可能在类实例化期间抛出,单个对象可能只具有给定类的私有字段的某个真子集,因此私有字段通常必须单独跟踪。

It is defined piecewise over the following productions:

ClassTail : ClassHeritageopt { ClassBodyopt }
  1. env 为运行中执行上下文的 LexicalEnvironment。
  2. classEnvNewDeclarativeEnvironment(env)。
  3. 如果 classBinding 不是 undefined,则
    1. 执行 ! classEnv.CreateImmutableBinding(classBinding, true)。
  4. outerPrivateEnvironment 为运行中执行上下文的 PrivateEnvironment。
  5. classPrivateEnvironmentNewPrivateEnvironment(outerPrivateEnvironment)。
  6. 如果 ClassBody 存在,则
    1. ClassBodyPrivateBoundIdentifiers 中的每个 String dn,执行
      1. 如果 classPrivateEnvironment.[[Names]] 包含一个 Private Name pn,使得 pn.[[Description]]dn,则
        1. 断言:这只可能发生于 getter/setter 对。
      2. 否则,
        1. name 为一个新的 Private Name,其 [[Description]]dn
        2. name 追加到 classPrivateEnvironment.[[Names]]
  7. 如果 ClassHeritage 不存在,则
    1. protoParent%Object.prototype%
    2. constructorParent%Function.prototype%
  8. 否则,
    1. 将运行中执行上下文的 LexicalEnvironment 设为 classEnv
    2. 注:在求值 ClassHeritage 时,运行中执行上下文的 PrivateEnvironment 为 outerPrivateEnvironment
    3. superclassRefCompletion(ClassHeritageEvaluation)。
    4. 将运行中执行上下文的 LexicalEnvironment 设为 env
    5. superclass 为 ? GetValue(? superclassRef)。
    6. 如果 superclassnull,则
      1. protoParentnull
      2. constructorParent%Function.prototype%
    7. 否则如果 IsConstructor(superclass) 为 false,则
      1. 抛出 TypeError 异常。
    8. 否则,
      1. protoParent 为 ? Get(superclass, "prototype")。
      2. 如果 protoParent 不是 Object 且 protoParent 不是 null,抛出 TypeError 异常。
      3. constructorParentsuperclass
  9. protoOrdinaryObjectCreate(protoParent)。
  10. 如果 ClassBody 不存在,令 constructorempty
  11. 否则,令 constructorClassBodyConstructorMethod
  12. 将运行中执行上下文的 LexicalEnvironment 设为 classEnv
  13. 将运行中执行上下文的 PrivateEnvironment 设为 classPrivateEnvironment
  14. 如果 constructorempty,则
    1. defaultConstructor 为一个新的 Abstract Closure,它没有参数,不捕获任何内容,并在被调用时执行以下步骤:
      1. args 为通过 [[Call]][[Construct]] 传递给此函数的参数 List
      2. 如果 NewTarget 为 undefined,抛出 TypeError 异常。
      3. constructorFunction活动函数对象
      4. 如果 constructorFunction.[[ConstructorKind]]derived,则
        1. 注:此分支的行为类似于 constructor(...args) { super(...args); }。最显著的区别是,前述 ECMAScript 源文本会可观察地调用 %Array.prototype% 上的 %Symbol.iterator% 方法,而此函数不会。
        2. func 为 ! constructorFunction.[[GetPrototypeOf]]()。
        3. 如果 IsConstructor(func) 为 false,抛出 TypeError 异常。
        4. result 为 ? Construct(func, args, NewTarget)。
      5. 否则,
        1. 注:此分支的行为类似于 constructor() {}
        2. result 为 ? OrdinaryCreateFromConstructor(NewTarget, "%Object.prototype%")。
      6. 执行 ? InitializeInstanceElements(result, constructorFunction)。
      7. 返回 NormalCompletion(result)。
    2. constructorFunctionCreateBuiltinFunction(defaultConstructor, 0, className, « [[ConstructorKind]], [[SourceText]], [[PrivateMethods]], [[Fields]] », 当前 Realm Record, constructorParent)。
  15. 否则,
    1. constructorInfo 为以 protoconstructorParent 为参数的 constructor 的 ! DefineMethod
    2. constructorFunctionconstructorInfo.[[Closure]]
    3. 执行 MakeClassConstructor(constructorFunction)。
    4. 执行 SetFunctionName(constructorFunction, className)。
  16. constructorFunction.[[SourceText]] 设为 sourceText
  17. 执行 MakeConstructor(constructorFunction, false, proto)。
  18. 如果 ClassHeritage 存在,将 constructorFunction.[[ConstructorKind]] 设为 derived
  19. 执行 ! DefineMethodProperty(proto, "constructor", constructorFunction, false)。
  20. 如果 ClassBody 不存在,令 elements 为一个新的空 List
  21. 否则,令 elementsClassBodyNonConstructorElements
  22. instancePrivateMethods 为一个新的空 List
  23. staticPrivateMethods 为一个新的空 List
  24. instanceFields 为一个新的空 List
  25. staticElements 为一个新的空 List
  26. elements 的每个 ClassElement e,执行
    1. 如果 eIsStaticfalse,则
      1. elementCompletion(以 proto 为参数的 eClassElementEvaluation)。
    2. 否则,
      1. elementCompletion(以 constructorFunction 为参数的 eClassElementEvaluation)。
    3. 如果 element 是突然完成,则
      1. 将运行中执行上下文的 LexicalEnvironment 设为 env
      2. 将运行中执行上下文的 PrivateEnvironment 设为 outerPrivateEnvironment
      3. 返回 ? element
    4. element 设为 ! element
    5. 如果 elementPrivateElement,则
      1. 断言:element.[[Kind]]methodaccessor
      2. 如果 eIsStaticfalse,令 containerinstancePrivateMethods
      3. 否则,令 containerstaticPrivateMethods
      4. 如果 container 包含一个 PrivateElement pe,使得 pe.[[Key]]element.[[Key]],则
        1. 断言:element.[[Kind]]pe.[[Kind]] 都是 accessor
        2. 如果 element.[[Get]]undefined,则
          1. combinedPrivateElement { [[Key]]: element.[[Key]], [[Kind]]: accessor, [[Get]]: pe.[[Get]], [[Set]]: element.[[Set]] }。
        3. 否则,
          1. combinedPrivateElement { [[Key]]: element.[[Key]], [[Kind]]: accessor, [[Get]]: element.[[Get]], [[Set]]: pe.[[Set]] }。
        4. combined 替换 container 中的 pe
      5. 否则,
        1. element 追加到 container
    6. 否则如果 elementClassFieldDefinition Record,则
      1. 如果 eIsStaticfalse,将 element 追加到 instanceFields
      2. 否则,将 element 追加到 staticElements
    7. 否则如果 element 是 ClassStaticBlockDefinition Record,则
      1. element 追加到 staticElements
  27. 将运行中执行上下文的 LexicalEnvironment 设为 env
  28. 如果 classBinding 不是 undefined,则
    1. 执行 ! classEnv.InitializeBinding(classBinding, constructorFunction)。
  29. constructorFunction.[[PrivateMethods]] 设为 instancePrivateMethods
  30. constructorFunction.[[Fields]] 设为 instanceFields
  31. staticPrivateMethods 的每个 PrivateElement method,执行
    1. 执行 ! PrivateMethodOrAccessorAdd(constructorFunction, method)。
  32. staticElements 的每个元素 elementRecord,执行
    1. 如果 elementRecordClassFieldDefinition Record,则
      1. resultCompletion(DefineField(constructorFunction, elementRecord))。
    2. 否则,
      1. 断言:elementRecord 是 ClassStaticBlockDefinition Record
      2. resultCompletion(Call(elementRecord.[[BodyFunction]], constructorFunction))。
    3. 如果 result 是突然完成,则
      1. 将运行中执行上下文的 PrivateEnvironment 设为 outerPrivateEnvironment
      2. 返回 ? result
  33. 将运行中执行上下文的 PrivateEnvironment 设为 outerPrivateEnvironment
  34. 返回 constructorFunction

15.7.15 Runtime Semantics: BindingClassDeclarationEvaluation

The syntax-directed operation BindingClassDeclarationEvaluation takes no arguments and returns 要么是一个正常完成,其中包含一个函数对象;要么是一个突然完成. It is defined piecewise over the following productions:

ClassDeclaration : class BindingIdentifier ClassTail
  1. classNameBindingIdentifierStringValue
  2. sourceTextClassDeclaration匹配的源文本
  3. value 为以 classNameclassNamesourceText 为参数的 ClassTail 的 ? ClassDefinitionEvaluation
  4. env 为运行中执行上下文的 LexicalEnvironment。
  5. 执行 ? InitializeBoundName(className, value, env)。
  6. 返回 value
ClassDeclaration : class ClassTail
  1. sourceTextClassDeclaration匹配的源文本
  2. 返回以 undefined"default"sourceText 为参数的 ClassTail 的 ? ClassDefinitionEvaluation
Note

ClassDeclaration : class ClassTail 只作为 ExportDeclaration 的一部分出现,其绑定的建立作为该产生式求值动作的一部分处理。参见 16.2.3.7

15.7.16 Runtime Semantics: Evaluation

ClassDeclaration : class BindingIdentifier ClassTail
  1. 执行此 ClassDeclaration 的 ? BindingClassDeclarationEvaluation
  2. 返回 empty
Note

ClassDeclaration : class ClassTail 只作为 ExportDeclaration 的一部分出现,并且从不被直接求值。

ClassExpression : class ClassTail
  1. sourceTextClassExpression匹配的源文本
  2. 返回以 undefined、空 String 和 sourceText 为参数的 ClassTail 的 ? ClassDefinitionEvaluation
ClassExpression : class BindingIdentifier ClassTail
  1. classNameBindingIdentifierStringValue
  2. sourceTextClassExpression匹配的源文本
  3. 返回以 classNameclassNamesourceText 为参数的 ClassTail 的 ? ClassDefinitionEvaluation
ClassElementName : PrivateIdentifier
  1. privateIdentifierPrivateIdentifierStringValue
  2. privateEnvRec 为运行中执行上下文的 PrivateEnvironment。
  3. namesprivateEnvRec.[[Names]]
  4. 断言:names 中恰有一个元素是 [[Description]]privateIdentifierPrivate Name
  5. privateNamenames[[Description]]privateIdentifierPrivate Name
  6. 返回 privateName
ClassStaticBlockStatementList : [empty]
  1. 返回 undefined

15.8 异步函数定义

语法

AsyncFunctionDeclaration[Yield, Await, Default] : async [no LineTerminator here] function BindingIdentifier[?Yield, ?Await] ( FormalParameters[~Yield, +Await] ) { AsyncFunctionBody } [+Default] async [no LineTerminator here] function ( FormalParameters[~Yield, +Await] ) { AsyncFunctionBody } AsyncFunctionExpression : async [no LineTerminator here] function BindingIdentifier[~Yield, +Await]opt ( FormalParameters[~Yield, +Await] ) { AsyncFunctionBody } AsyncMethod[Yield, Await] : async [no LineTerminator here] ClassElementName[?Yield, ?Await] ( UniqueFormalParameters[~Yield, +Await] ) { AsyncFunctionBody } AsyncFunctionBody : FunctionBody[~Yield, +Await] AwaitExpression[Yield] : await UnaryExpression[?Yield, +Await] Note 1

[Await] 参数存在时,await 被解析为 AwaitExpression关键字[Await] 参数存在于以下上下文的顶层,尽管根据非终结符(例如 FunctionBody)不同,该参数在某些上下文中可能不存在:

Script 是语法目标符号时,若 [Await] 参数不存在,await 可以被解析为标识符。这包括以下上下文:

Note 2

YieldExpression 不同,省略 AwaitExpression 的操作数是语法错误。必须 await 某个东西。

15.8.1 Static Semantics: 早期错误

AsyncMethod : async ClassElementName ( UniqueFormalParameters ) { AsyncFunctionBody } AsyncFunctionDeclaration : async function BindingIdentifier ( FormalParameters ) { AsyncFunctionBody } async function ( FormalParameters ) { AsyncFunctionBody } AsyncFunctionExpression : async function BindingIdentifieropt ( FormalParameters ) { AsyncFunctionBody }

15.8.2 Runtime Semantics: InstantiateAsyncFunctionObject

The syntax-directed operation InstantiateAsyncFunctionObject takes arguments env (一个 Environment Record) and privateEnv (一个 PrivateEnvironment Recordnull) and returns 一个 ECMAScript 函数对象. It is defined piecewise over the following productions:

AsyncFunctionDeclaration : async function BindingIdentifier ( FormalParameters ) { AsyncFunctionBody }
  1. nameBindingIdentifierStringValue
  2. sourceTextAsyncFunctionDeclaration匹配的源文本
  3. closureOrdinaryFunctionCreate(%AsyncFunction.prototype%, sourceText, FormalParameters, AsyncFunctionBody, non-lexical-this, env, privateEnv)。
  4. 执行 SetFunctionName(closure, name)。
  5. 返回 closure
AsyncFunctionDeclaration : async function ( FormalParameters ) { AsyncFunctionBody }
  1. sourceTextAsyncFunctionDeclaration匹配的源文本
  2. closureOrdinaryFunctionCreate(%AsyncFunction.prototype%, sourceText, FormalParameters, AsyncFunctionBody, non-lexical-this, env, privateEnv)。
  3. 执行 SetFunctionName(closure, "default")。
  4. 返回 closure

15.8.3 Runtime Semantics: InstantiateAsyncFunctionExpression

The syntax-directed operation InstantiateAsyncFunctionExpression takes optional argument name (一个属性键Private Name) and returns 一个 ECMAScript 函数对象. It is defined piecewise over the following productions:

AsyncFunctionExpression : async function ( FormalParameters ) { AsyncFunctionBody }
  1. 如果 name 不存在,则将 name 设为空 String。
  2. env 为运行中执行上下文的 LexicalEnvironment。
  3. privateEnv 为运行中执行上下文的 PrivateEnvironment。
  4. sourceTextAsyncFunctionExpression匹配的源文本
  5. closureOrdinaryFunctionCreate(%AsyncFunction.prototype%, sourceText, FormalParameters, AsyncFunctionBody, non-lexical-this, env, privateEnv)。
  6. 执行 SetFunctionName(closure, name)。
  7. 返回 closure
AsyncFunctionExpression : async function BindingIdentifier ( FormalParameters ) { AsyncFunctionBody }
  1. 断言:name 不存在。
  2. name 设为 BindingIdentifierStringValue
  3. outerEnv 为运行中执行上下文的 LexicalEnvironment。
  4. funcEnvNewDeclarativeEnvironment(outerEnv)。
  5. 执行 ! funcEnv.CreateImmutableBinding(name, false)。
  6. privateEnv 为运行中执行上下文的 PrivateEnvironment。
  7. sourceTextAsyncFunctionExpression匹配的源文本
  8. closureOrdinaryFunctionCreate(%AsyncFunction.prototype%, sourceText, FormalParameters, AsyncFunctionBody, non-lexical-this, funcEnv, privateEnv)。
  9. 执行 SetFunctionName(closure, name)。
  10. 执行 ! funcEnv.InitializeBinding(name, closure)。
  11. 返回 closure
Note

AsyncFunctionExpression 中的 BindingIdentifier 可在 AsyncFunctionExpressionAsyncFunctionBody 内被引用,以允许函数递归调用自身。然而,与 FunctionDeclaration 中不同,AsyncFunctionExpression 中的 BindingIdentifier 不能从外围作用域引用,也不会影响包围 AsyncFunctionExpression 的作用域。

15.8.4 Runtime Semantics: EvaluateAsyncFunctionBody

The syntax-directed operation EvaluateAsyncFunctionBody takes arguments functionObject (一个 ECMAScript 函数对象) and argumentsList (ECMAScript 语言值List) and returns 一个返回完成. It is defined piecewise over the following productions:

AsyncFunctionBody : FunctionBody
  1. promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  2. completionCompletion(FunctionDeclarationInstantiation(functionObject, argumentsList))。
  3. 如果 completion 是突然完成,则
    1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « completion.[[Value]] »)。
  4. 否则,
    1. 执行 AsyncFunctionStart(promiseCapability, FunctionBody)。
  5. 返回 ReturnCompletion(promiseCapability.[[Promise]])。

15.8.5 Runtime Semantics: Evaluation

AsyncFunctionExpression : async function BindingIdentifieropt ( FormalParameters ) { AsyncFunctionBody }
  1. 返回 AsyncFunctionExpressionInstantiateAsyncFunctionExpression
AwaitExpression : await UnaryExpression
  1. exprRef 为 ? UnaryExpressionEvaluation
  2. value 为 ? GetValue(exprRef)。
  3. 返回 ? Await(value)。

15.9 异步箭头函数定义

语法

AsyncArrowFunction[In, Yield, Await] : async [no LineTerminator here] AsyncArrowBindingIdentifier[?Yield] [no LineTerminator here] => AsyncConciseBody[?In] CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await] [no LineTerminator here] => AsyncConciseBody[?In] AsyncConciseBody[In] : [lookahead ≠ {] ExpressionBody[?In, +Await] { AsyncFunctionBody } AsyncArrowBindingIdentifier[Yield] : BindingIdentifier[?Yield, +Await] CoverCallExpressionAndAsyncArrowHead[Yield, Await] : MemberExpression[?Yield, ?Await] Arguments[?Yield, ?Await]

补充语法

当处理产生式的一个实例
AsyncArrowFunction : CoverCallExpressionAndAsyncArrowHead => AsyncConciseBody
时,使用以下文法来细化对 CoverCallExpressionAndAsyncArrowHead 的解释:

AsyncArrowHead : async [no LineTerminator here] ArrowFormalParameters[~Yield, +Await]

15.9.1 Static Semantics: 早期错误

AsyncArrowFunction : async AsyncArrowBindingIdentifier => AsyncConciseBody AsyncArrowFunction : CoverCallExpressionAndAsyncArrowHead => AsyncConciseBody

15.9.2 Static Semantics: AsyncConciseBodyContainsUseStrict

The syntax-directed operation AsyncConciseBodyContainsUseStrict takes no arguments and returns 一个布尔值. It is defined piecewise over the following productions:

AsyncConciseBody : ExpressionBody
  1. 返回 false
AsyncConciseBody : { AsyncFunctionBody }
  1. 返回 AsyncFunctionBodyFunctionBodyContainsUseStrict

15.9.3 Runtime Semantics: EvaluateAsyncConciseBody

The syntax-directed operation EvaluateAsyncConciseBody takes arguments functionObject (一个 ECMAScript 函数对象) and argumentsList (ECMAScript 语言值List) and returns 一个返回完成. It is defined piecewise over the following productions:

AsyncConciseBody : ExpressionBody
  1. promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  2. completionCompletion(FunctionDeclarationInstantiation(functionObject, argumentsList))。
  3. 如果 completion 是突然完成,则
    1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « completion.[[Value]] »)。
  4. 否则,
    1. 执行 AsyncFunctionStart(promiseCapability, ExpressionBody)。
  5. 返回 ReturnCompletion(promiseCapability.[[Promise]])。

15.9.4 Runtime Semantics: InstantiateAsyncArrowFunctionExpression

The syntax-directed operation InstantiateAsyncArrowFunctionExpression takes optional argument name (一个属性键Private Name) and returns 一个 ECMAScript 函数对象. It is defined piecewise over the following productions:

AsyncArrowFunction : async AsyncArrowBindingIdentifier => AsyncConciseBody
  1. 如果 name 不存在,则将 name 设为空 String。
  2. env 为运行中执行上下文的 LexicalEnvironment。
  3. privateEnv 为运行中执行上下文的 PrivateEnvironment。
  4. sourceTextAsyncArrowFunction匹配的源文本
  5. parametersAsyncArrowBindingIdentifier
  6. closureOrdinaryFunctionCreate(%AsyncFunction.prototype%, sourceText, parameters, AsyncConciseBody, lexical-this, env, privateEnv)。
  7. 执行 SetFunctionName(closure, name)。
  8. 返回 closure
AsyncArrowFunction : CoverCallExpressionAndAsyncArrowHead => AsyncConciseBody
  1. 如果 name 不存在,则将 name 设为空 String。
  2. env 为运行中执行上下文的 LexicalEnvironment。
  3. privateEnv 为运行中执行上下文的 PrivateEnvironment。
  4. sourceTextAsyncArrowFunction匹配的源文本
  5. headCoverCallExpressionAndAsyncArrowHead覆盖AsyncArrowHead
  6. parametersheadArrowFormalParameters
  7. closureOrdinaryFunctionCreate(%AsyncFunction.prototype%, sourceText, parameters, AsyncConciseBody, lexical-this, env, privateEnv)。
  8. 执行 SetFunctionName(closure, name)。
  9. 返回 closure

15.9.5 Runtime Semantics: Evaluation

AsyncArrowFunction : async AsyncArrowBindingIdentifier => AsyncConciseBody CoverCallExpressionAndAsyncArrowHead => AsyncConciseBody
  1. 返回 AsyncArrowFunctionInstantiateAsyncArrowFunctionExpression

15.10 尾位置调用

15.10.1 Static Semantics: IsInTailPosition ( call )

The abstract operation IsInTailPosition takes argument call (一个 CallExpression 解析节点、一个 MemberExpression 解析节点或一个 OptionalChain 解析节点) and returns 一个布尔值. It performs the following steps when called:

  1. 如果 IsStrict(call) 为 false,返回 false
  2. 如果 call 未包含在 FunctionBodyConciseBodyAsyncConciseBody 内,返回 false
  3. body 为最紧密包含 callFunctionBodyConciseBodyAsyncConciseBody
  4. 如果 bodyGeneratorBodyFunctionBody,返回 false
  5. 如果 bodyAsyncFunctionBodyFunctionBody,返回 false
  6. 如果 bodyAsyncGeneratorBodyFunctionBody,返回 false
  7. 如果 bodyAsyncConciseBody,返回 false
  8. 返回以 call 为参数的 bodyHasCallInTailPosition 的结果。
Note

尾位置调用只在严格模式代码中定义,因为存在一种常见的非标准语言扩展(参见 10.2.4),该扩展允许观察调用者上下文链。

15.10.2 Static Semantics: HasCallInTailPosition

The syntax-directed operation HasCallInTailPosition takes argument call (一个 CallExpression 解析节点、一个 MemberExpression 解析节点或一个 OptionalChain 解析节点) and returns 一个布尔值.

Note 1

call 是表示特定源文本范围的解析节点。当以下算法将 call 与另一个解析节点比较时,这是在测试它们是否表示同一段源文本。

Note 2

紧随其后返回调用结果的 GetValue 的潜在尾位置调用,也是一种可能的尾位置调用。函数调用不能返回 Reference Record,因此这样的 GetValue 操作总是会返回与实际函数调用结果相同的值。

It is defined piecewise over the following productions:

StatementList : StatementList StatementListItem
  1. has 为以 call 为参数的 StatementListHasCallInTailPosition
  2. 如果 hastrue,返回 true
  3. 返回以 call 为参数的 StatementListItemHasCallInTailPosition
FunctionStatementList : [empty] StatementListItem : Declaration Statement : VariableStatement EmptyStatement ExpressionStatement ContinueStatement BreakStatement ThrowStatement DebuggerStatement Block : { } ReturnStatement : return ; LabelledItem : FunctionDeclaration ForInOfStatement : for ( LeftHandSideExpression of AssignmentExpression ) Statement for ( var ForBinding of AssignmentExpression ) Statement for ( ForDeclaration of AssignmentExpression ) Statement CaseBlock : { }
  1. 返回 false
IfStatement : if ( Expression ) Statement else Statement
  1. has 为以 call 为参数的第一个 StatementHasCallInTailPosition
  2. 如果 hastrue,返回 true
  3. 返回以 call 为参数的第二个 StatementHasCallInTailPosition
IfStatement : if ( Expression ) Statement DoWhileStatement : do Statement while ( Expression ) ; WhileStatement : while ( Expression ) Statement ForStatement : for ( Expressionopt ; Expressionopt ; Expressionopt ) Statement for ( var VariableDeclarationList ; Expressionopt ; Expressionopt ) Statement for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement ForInOfStatement : for ( LeftHandSideExpression in Expression ) Statement for ( var ForBinding in Expression ) Statement for ( ForDeclaration in Expression ) Statement WithStatement : with ( Expression ) Statement
  1. 返回以 call 为参数的 StatementHasCallInTailPosition
LabelledStatement : LabelIdentifier : LabelledItem
  1. 返回以 call 为参数的 LabelledItemHasCallInTailPosition
ReturnStatement : return Expression ;
  1. 返回以 call 为参数的 ExpressionHasCallInTailPosition
SwitchStatement : switch ( Expression ) CaseBlock
  1. 返回以 call 为参数的 CaseBlockHasCallInTailPosition
CaseBlock : { CaseClausesopt DefaultClause CaseClausesopt }
  1. hasfalse
  2. 如果第一个 CaseClauses 存在,将 has 设为以 call 为参数的第一个 CaseClausesHasCallInTailPosition
  3. 如果 hastrue,返回 true
  4. has 设为以 call 为参数的 DefaultClauseHasCallInTailPosition
  5. 如果 hastrue,返回 true
  6. 如果第二个 CaseClauses 存在,将 has 设为以 call 为参数的第二个 CaseClausesHasCallInTailPosition
  7. 返回 has
CaseClauses : CaseClauses CaseClause
  1. has 为以 call 为参数的 CaseClausesHasCallInTailPosition
  2. 如果 hastrue,返回 true
  3. 返回以 call 为参数的 CaseClauseHasCallInTailPosition
CaseClause : case Expression : StatementListopt DefaultClause : default : StatementListopt
  1. 如果 StatementList 存在,返回以 call 为参数的 StatementListHasCallInTailPosition
  2. 返回 false
TryStatement : try Block Catch
  1. 返回以 call 为参数的 CatchHasCallInTailPosition
TryStatement : try Block Finally try Block Catch Finally
  1. 返回以 call 为参数的 FinallyHasCallInTailPosition
Catch : catch ( CatchParameter ) Block
  1. 返回以 call 为参数的 BlockHasCallInTailPosition
AssignmentExpression : YieldExpression ArrowFunction AsyncArrowFunction LeftHandSideExpression = AssignmentExpression LeftHandSideExpression AssignmentOperator AssignmentExpression LeftHandSideExpression &&= AssignmentExpression LeftHandSideExpression ||= AssignmentExpression LeftHandSideExpression ??= AssignmentExpression BitwiseANDExpression : BitwiseANDExpression & EqualityExpression BitwiseXORExpression : BitwiseXORExpression ^ BitwiseANDExpression BitwiseORExpression : BitwiseORExpression | BitwiseXORExpression EqualityExpression : EqualityExpression == RelationalExpression EqualityExpression != RelationalExpression EqualityExpression === RelationalExpression EqualityExpression !== RelationalExpression RelationalExpression : RelationalExpression < ShiftExpression RelationalExpression > ShiftExpression RelationalExpression <= ShiftExpression RelationalExpression >= ShiftExpression RelationalExpression instanceof ShiftExpression RelationalExpression in ShiftExpression PrivateIdentifier in ShiftExpression ShiftExpression : ShiftExpression << AdditiveExpression ShiftExpression >> AdditiveExpression ShiftExpression >>> AdditiveExpression AdditiveExpression : AdditiveExpression + MultiplicativeExpression AdditiveExpression - MultiplicativeExpression MultiplicativeExpression : MultiplicativeExpression MultiplicativeOperator ExponentiationExpression ExponentiationExpression : UpdateExpression ** ExponentiationExpression UpdateExpression : LeftHandSideExpression ++ LeftHandSideExpression -- ++ UnaryExpression -- UnaryExpression UnaryExpression : delete UnaryExpression void UnaryExpression typeof UnaryExpression + UnaryExpression - UnaryExpression ~ UnaryExpression ! UnaryExpression AwaitExpression CallExpression : SuperCall ImportCall CallExpression [ Expression ] CallExpression . IdentifierName CallExpression . PrivateIdentifier NewExpression : new NewExpression MemberExpression : MemberExpression [ Expression ] MemberExpression . IdentifierName SuperProperty MetaProperty new MemberExpression Arguments MemberExpression . PrivateIdentifier PrimaryExpression : this IdentifierReference Literal ArrayLiteral ObjectLiteral FunctionExpression ClassExpression GeneratorExpression AsyncFunctionExpression AsyncGeneratorExpression RegularExpressionLiteral TemplateLiteral
  1. 返回 false
Expression : AssignmentExpression Expression , AssignmentExpression
  1. 返回以 call 为参数的 AssignmentExpressionHasCallInTailPosition
ConditionalExpression : ShortCircuitExpression ? AssignmentExpression : AssignmentExpression
  1. has 为以 call 为参数的第一个 AssignmentExpressionHasCallInTailPosition
  2. 如果 hastrue,返回 true
  3. 返回以 call 为参数的第二个 AssignmentExpressionHasCallInTailPosition
LogicalANDExpression : LogicalANDExpression && BitwiseORExpression
  1. 返回以 call 为参数的 BitwiseORExpressionHasCallInTailPosition
LogicalORExpression : LogicalORExpression || LogicalANDExpression
  1. 返回以 call 为参数的 LogicalANDExpressionHasCallInTailPosition
CoalesceExpression : CoalesceExpressionHead ?? BitwiseORExpression
  1. 返回以 call 为参数的 BitwiseORExpressionHasCallInTailPosition
CallExpression : CoverCallExpressionAndAsyncArrowHead CallExpression Arguments CallExpression TemplateLiteral
  1. 如果此 CallExpressioncall,返回 true
  2. 返回 false
OptionalExpression : MemberExpression OptionalChain CallExpression OptionalChain OptionalExpression OptionalChain
  1. 返回以 call 为参数的 OptionalChainHasCallInTailPosition
OptionalChain : ?. [ Expression ] ?. IdentifierName ?. PrivateIdentifier OptionalChain [ Expression ] OptionalChain . IdentifierName OptionalChain . PrivateIdentifier
  1. 返回 false
OptionalChain : ?. Arguments OptionalChain Arguments
  1. 如果此 OptionalChaincall,返回 true
  2. 返回 false
MemberExpression : MemberExpression TemplateLiteral
  1. 如果此 MemberExpressioncall,返回 true
  2. 返回 false
PrimaryExpression : CoverParenthesizedExpressionAndArrowParameterList
  1. exprCoverParenthesizedExpressionAndArrowParameterList覆盖ParenthesizedExpression
  2. 返回以 call 为参数的 exprHasCallInTailPosition
ParenthesizedExpression : ( Expression )
  1. 返回以 call 为参数的 ExpressionHasCallInTailPosition

15.10.3 PrepareForTailCall ( )

The abstract operation PrepareForTailCall takes no arguments and returns unused. It performs the following steps when called:

  1. 断言:当前执行上下文随后不会再用于求值任何 ECMAScript 代码或内置函数。在调用此抽象操作之后对 Call 的调用,会在执行任何此类求值之前创建并推入一个新的执行上下文
  2. 丢弃与当前执行上下文关联的所有资源。
  3. 返回 unused

尾位置调用必须在调用目标函数之前释放与当前正在执行的函数执行上下文关联的任何瞬时内部资源,或者重用这些资源以支持目标函数。

Note

例如,尾位置调用应当只让实现的活动记录栈增长目标函数活动记录大小超出调用函数活动记录大小的那部分。如果目标函数的活动记录更小,则栈的总大小应当减少。

16 ECMAScript 语言:脚本和模块

16.1 脚本

语法

Script : ScriptBodyopt ScriptBody : StatementList[~Yield, ~Await, ~Return]

16.1.1 Static Semantics: 早期错误

Script : ScriptBody ScriptBody : StatementList

16.1.2 Static Semantics: ScriptIsStrict

The syntax-directed operation ScriptIsStrict takes no arguments and returns 一个布尔值. It is defined piecewise over the following productions:

Script : ScriptBodyopt
  1. 如果 ScriptBody 存在,且 ScriptBody 的 Directive Prologue 包含 Use Strict Directive,返回 true
  2. 返回 false

16.1.3 Runtime Semantics: Evaluation

Script : [empty]
  1. 返回 undefined

16.1.4 Script Record

Script Record 封装正在求值的脚本相关信息。每个 script record 包含 Table 34 中列出的字段。

Table 34: Script Record Fields
字段名 值类型 含义
[[Realm]] 一个 Realm Record 创建此脚本所在的 realm
[[ECMAScriptCode]] 一个 Script 解析节点 解析此脚本源文本的结果。
[[LoadedModules]] LoadedModuleRequest RecordList 从此脚本导入的说明符字符串到已解析 Module Record 的映射。该列表不包含两个不同的 Record r1r2,使得 ModuleRequestsEqual(r1, r2) 为 true
[[HostDefined]] 任何值(默认值为 empty 保留给需要将额外信息与脚本关联的宿主环境使用的字段。

16.1.5 ParseScript ( sourceText, realm, hostDefined )

The abstract operation ParseScript takes arguments sourceText (ECMAScript 源文本), realm (一个 Realm Record), and hostDefined (任何值) and returns 一个 Script RecordSyntaxError 对象的非空 List. 它基于将 sourceText 解析为 Script 的结果创建一个 Script Record。 It performs the following steps when called:

  1. scriptParseText(sourceText, Script)。
  2. 如果 script 是一个错误 List,返回 script
  3. 返回 Script Record { [[Realm]]: realm, [[ECMAScriptCode]]: script, [[LoadedModules]]: « », [[HostDefined]]: hostDefined }。
Note

实现在对该脚本源文本求值 ParseScript 之前,可以解析脚本源文本并分析其 Early Error 条件。然而,任何错误的报告都必须推迟到本规范实际对该源文本执行 ParseScript 的时刻。

16.1.6 ScriptEvaluation ( scriptRecord )

The abstract operation ScriptEvaluation takes argument scriptRecord (一个 Script Record) and returns 要么是包含一个 ECMAScript 语言值正常完成,要么是突然完成. It performs the following steps when called:

  1. globalEnvscriptRecord.[[Realm]].[[GlobalEnv]]
  2. scriptContext 为一个新的 ECMAScript 代码执行上下文
  3. scriptContext 的 Function 设为 null
  4. scriptContextRealm 设为 scriptRecord.[[Realm]]
  5. scriptContext 的 ScriptOrModule 设为 scriptRecord
  6. scriptContext 的 VariableEnvironment 设为 globalEnv
  7. scriptContext 的 LexicalEnvironment 设为 globalEnv
  8. scriptContext 的 PrivateEnvironment 设为 null
  9. 挂起运行中执行上下文
  10. scriptContext 推入执行上下文栈scriptContext 现在是运行中执行上下文
  11. scriptscriptRecord.[[ECMAScriptCode]]
  12. resultCompletion(GlobalDeclarationInstantiation(script, globalEnv))。
  13. 如果 result正常完成,则
    1. result 设为 Completion(scriptEvaluation)。
    2. 如果 result正常完成result.[[Value]]empty,则
      1. result 设为 NormalCompletion(undefined)。
  14. 挂起 scriptContext 并将其从执行上下文栈中移除。
  15. 断言:执行上下文栈不为空。
  16. 恢复现在位于执行上下文栈顶部的上下文作为运行中执行上下文
  17. 返回 ? result

16.1.7 GlobalDeclarationInstantiation ( script, env )

The abstract operation GlobalDeclarationInstantiation takes arguments script (一个 Script 解析节点) and env (一个 Global Environment Record) and returns 要么是包含 unused正常完成,要么是抛出完成. script 是正在为其建立执行上下文Scriptenv 是将在其中创建绑定的全局环境。

Note 1

当为求值脚本建立执行上下文时,声明会在当前全局环境中实例化。代码中声明的每个全局绑定都会被实例化。

调用时执行以下步骤:

  1. lexNamesscriptLexicallyDeclaredNames
  2. varNamesscriptVarDeclaredNames
  3. lexNames 的每个元素 name,执行
    1. 如果 HasLexicalDeclaration(env, name) 为 true,抛出 SyntaxError 异常。
    2. hasRestrictedGlobal 为 ? HasRestrictedGlobalProperty(env, name)。
    3. 注:全局 varfunction 绑定(由非严格直接 eval 引入的除外)是不可配置的,因此是受限制的全局属性。
    4. 如果 hasRestrictedGlobaltrue,抛出 SyntaxError 异常。
  4. varNames 的每个元素 name,执行
    1. 如果 HasLexicalDeclaration(env, name) 为 true,抛出 SyntaxError 异常。
  5. varDeclarationsscriptVarScopedDeclarations
  6. functionsToInitialize 为一个新的空 List
  7. declaredFunctionNames 为一个新的空 List
  8. varDeclarations 的每个元素 varDecl,按 List 逆序执行
    1. 如果 varDecl 不是 VariableDeclarationForBindingBindingIdentifier 中的任一者,则
      1. 断言:varDeclFunctionDeclarationGeneratorDeclarationAsyncFunctionDeclarationAsyncGeneratorDeclaration 中的任一者。
      2. 注:如果同一名称有多个函数声明,则使用最后一个声明。
      3. fnvarDeclBoundNames 的唯一元素。
      4. 如果 declaredFunctionNames 不包含 fn,则
        1. fnDefinable 为 ? CanDeclareGlobalFunction(env, fn)。
        2. 如果 fnDefinablefalse,抛出 TypeError 异常。
        3. fn 追加到 declaredFunctionNames
        4. varDecl 插入为 functionsToInitialize 的第一个元素。
  9. declaredVarNames 为一个新的空 List
  10. varDeclarations 的每个元素 varDecl,执行
    1. 如果 varDeclVariableDeclarationForBindingBindingIdentifier 中的任一者,则
      1. varDeclBoundNames 的每个 String vn,执行
        1. 如果 declaredFunctionNames 不包含 vn,则
          1. vnDefinable 为 ? CanDeclareGlobalVar(env, vn)。
          2. 如果 vnDefinablefalse,抛出 TypeError 异常。
          3. 如果 declaredVarNames 不包含 vn,则
            1. vn 追加到 declaredVarNames
  11. 注:如果全局对象普通对象,则此算法步骤之后不会发生异常终止。然而,如果全局对象Proxy 异质对象,它可能表现出在以下某些步骤中导致异常终止的行为。
  12. Normative Optional
    如果宿主是 Web 浏览器或以其他方式支持 块级函数声明的 Web 遗留兼容性语义,则
    1. strictscriptScriptIsStrict
    2. 如果 strictfalse,则
      1. declaredFunctionOrVarNamesdeclaredFunctionNamesdeclaredVarNames 的列表拼接。
      2. 对直接包含于任何 BlockCaseClauseDefaultClause xStatementList 中,且 script Contains xtrue 的每个 FunctionDeclaration f,执行
        1. funcNamefBindingIdentifierStringValue
        2. 如果将 FunctionDeclaration f 替换为以 funcName 作为 BindingIdentifierVariableStatement 不会为 script 产生任何 Early Errors,则
          1. 如果 HasLexicalDeclaration(env, funcName) 为 false,则
            1. fnDefinable 为 ? CanDeclareGlobalVar(env, funcName)。
            2. 如果 fnDefinabletrue,则
              1. 注:只有当 funcName 既不是 VarDeclaredName 也不是另一个 FunctionDeclaration 的名称时,才在此实例化它的 var 绑定。
              2. 如果 declaredFunctionOrVarNames 不包含 funcName,则
                1. 执行 ? CreateGlobalVarBinding(env, funcName, false)。
                2. funcName 追加到 declaredFunctionOrVarNames
              3. FunctionDeclaration f 被求值时,执行以下步骤来替代 15.2.6 中提供的 FunctionDeclaration Evaluation 算法:
                1. gEnv 为运行中执行上下文的 VariableEnvironment。
                2. bEnv 为运行中执行上下文的 LexicalEnvironment。
                3. fObj 为 ! bEnv.GetBindingValue(funcName, false)。
                4. 执行 ? gEnv.SetMutableBinding(funcName, fObj, false)
                5. 返回 unused
  13. lexDeclarationsscriptLexicallyScopedDeclarations
  14. privateEnvnull
  15. lexDeclarations 的每个元素 lexDecl,执行
    1. 注:词法声明名称只在此实例化,而不初始化。
    2. lexDeclBoundNames 的每个元素 dn,执行
      1. 如果 lexDeclIsConstantDeclarationtrue,则
        1. 执行 ? env.CreateImmutableBinding(dn, true)
      2. 否则,
        1. 执行 ? env.CreateMutableBinding(dn, false)
  16. functionsToInitialize 的每个解析节点 f,执行
    1. fnfBoundNames 的唯一元素。
    2. fo 为以 envprivateEnv 为参数的 fInstantiateFunctionObject
    3. 执行 ? CreateGlobalFunctionBinding(env, fn, fo, false)。
  17. declaredVarNames 的每个 String vn,执行
    1. 执行 ? CreateGlobalVarBinding(env, vn, false)。
  18. 返回 unused
Note 2

16.1.1 中指定的早期错误,会防止 function/var 声明与 let/const/class 声明之间的名称冲突,也会防止单个 Script 中包含的声明对 let/const/class 绑定进行重声明。然而,跨越多个 Script 的此类冲突和重声明会在 GlobalDeclarationInstantiation 期间作为运行时错误被检测。如果检测到任何此类错误,则不会为该脚本实例化任何绑定。然而,如果全局对象使用 Proxy 异质对象定义,则用于冲突声明的运行时测试可能不可靠,从而导致突然完成,并且某些全局声明不会被实例化。如果发生这种情况,则不会求值 Script 的代码。

与显式 var 或 function 声明不同,直接在全局对象上创建的属性会产生可被 let/const/class 声明遮蔽的全局绑定。

16.2 模块

语法

Module : ModuleBodyopt ModuleBody : ModuleItemList ModuleItemList : ModuleItem ModuleItemList ModuleItem ModuleItem : ImportDeclaration ExportDeclaration StatementListItem[~Yield, +Await, ~Return] ModuleExportName : IdentifierName StringLiteral

16.2.1 模块语义

16.2.1.1 Static Semantics: 早期错误

ModuleBody : ModuleItemList Note

重复的 ExportedNames 规则意味着在一个 ModuleBody 中存在多个 export default ExportDeclaration 项会导致语法错误。与冲突或重复声明相关的其他错误条件会在模块链接期间(即 Module 求值之前)进行检查。如果检测到任何此类错误,则该 Module 不会被求值。

ModuleExportName : StringLiteral

16.2.1.2 Static Semantics: ImportedLocalNames ( importEntries )

The abstract operation ImportedLocalNames takes argument importEntries (ImportEntry RecordList) and returns String 的 List. 它创建一个由 importEntries 定义的所有本地名称绑定组成的 List。 It performs the following steps when called:

  1. localNames 为一个新的空 List
  2. importEntries 的每个 ImportEntry Record i,执行
    1. i.[[LocalName]] 追加到 localNames
  3. 返回 localNames

16.2.1.3 ModuleRequest Records

ModuleRequest Record 表示带有给定导入属性的模块导入请求。它由以下字段组成:

Table 35: ModuleRequest Record Fields
字段名 值类型 含义
[[Specifier]] 一个 String 模块说明符
[[Attributes]] ImportAttribute RecordList 导入属性

LoadedModuleRequest Record 表示导入模块的请求以及产生的 Module Record。它由表 Table 35 中定义的相同字段组成,并额外包含 [[Module]]

Table 36: LoadedModuleRequest Record Fields
字段名 值类型 含义
[[Specifier]] 一个 String 模块说明符
[[Attributes]] ImportAttribute RecordList 导入属性
[[Module]] 一个 Module Record 与此模块请求对应的已加载模块

ImportAttribute Record 由以下字段组成:

Table 37: ImportAttribute Record Fields
字段名 值类型 含义
[[Key]] 一个 String 属性键
[[Value]] 一个 String 属性值

16.2.1.3.1 ModuleRequestsEqual ( left, right )

The abstract operation ModuleRequestsEqual takes arguments left (一个 ModuleRequest RecordLoadedModuleRequest Record) and right (一个 ModuleRequest RecordLoadedModuleRequest Record) and returns 一个布尔值. It performs the following steps when called:

  1. 如果 left.[[Specifier]] 不是 right.[[Specifier]],返回 false
  2. leftAttrsleft.[[Attributes]]
  3. rightAttrsright.[[Attributes]]
  4. leftAttrsCountleftAttrs 中的元素数量。
  5. rightAttrsCountrightAttrs 中的元素数量。
  6. 如果 leftAttrsCountrightAttrsCount,返回 false
  7. leftAttrs 的每个 ImportAttribute Record l,执行
    1. 如果 rightAttrs 不包含一个 ImportAttribute Record r,使得 l.[[Key]] 等于 r.[[Key]]l.[[Value]] 等于 r.[[Value]],返回 false
  8. 返回 true

16.2.1.4 Static Semantics: ModuleRequests

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

Module : [empty]
  1. 返回一个新的空 List
ModuleItemList : ModuleItem
  1. 返回 ModuleItemModuleRequests
ModuleItemList : ModuleItemList ModuleItem
  1. requestsModuleItemListModuleRequests
  2. additionalRequestsModuleItemModuleRequests
  3. additionalRequests 的每个 ModuleRequest Record mr,执行
    1. 如果 requests 不包含一个 ModuleRequest Record mr2,使得 ModuleRequestsEqual(mr, mr2) 为 true,则
      1. mr 追加到 requests
  4. 返回 requests
ModuleItem : StatementListItem
  1. 返回一个新的空 List
ImportDeclaration : import ImportClause FromClause ;
  1. specifierFromClauseSV
  2. 返回一个 List,其唯一元素为 ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: « » }。
ImportDeclaration : import ImportClause FromClause WithClause ;
  1. specifierFromClauseSV
  2. attributesWithClauseWithClauseToAttributes
  3. 返回一个 List,其唯一元素为 ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: attributes }。
ImportDeclaration : import ModuleSpecifier ;
  1. specifierModuleSpecifierSV
  2. 返回一个 List,其唯一元素为 ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: « » }。
ImportDeclaration : import ModuleSpecifier WithClause ;
  1. specifierModuleSpecifierSV
  2. attributesWithClauseWithClauseToAttributes
  3. 返回一个 List,其唯一元素为 ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: attributes }。
ExportDeclaration : export ExportFromClause FromClause ;
  1. specifierFromClauseSV
  2. 返回一个 List,其唯一元素为 ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: « » }。
ExportDeclaration : export ExportFromClause FromClause WithClause ;
  1. specifierFromClauseSV
  2. attributesWithClauseWithClauseToAttributes
  3. 返回一个 List,其唯一元素为 ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: attributes }。
ExportDeclaration : export NamedExports ; export VariableStatement export Declaration export default HoistableDeclaration export default ClassDeclaration export default AssignmentExpression ;
  1. 返回一个新的空 List

16.2.1.5 抽象模块记录

模块记录 封装了关于单个模块导入和导出的结构信息。 这些信息用于链接一组关联模块的导入与导出。 模块记录包含四个仅在评估模块时使用的字段。

从规范角度看,模块记录的值是 Record 规范类型的值, 可以认为处于一个简单的面向对象的类层次中, 其中模块记录是一个抽象类,拥有抽象子类和具体子类。 本规范定义了一个名为循环模块记录的抽象子类, 以及其具体子类源文本模块记录。 其他规范和实现可以定义额外的模块记录子类, 对应于它们定义的其他模块定义机制。

模块记录定义了 Table 38 中列出的字段。 所有模块定义的子类至少都包含这些字段。 模块记录还定义了 Table 39 中的抽象方法列表。 所有模块定义子类必须为这些抽象方法提供具体实现。

Table 38: 模块记录字段
字段名 值类型 含义
[[Realm]] 一个 Realm 记录 创建此模块的 Realm
[[Environment]] 一个模块环境记录或 empty 包含该模块顶层绑定的环境记录。此字段在模块被链接时设置。
[[Namespace]] 一个对象或 empty 如果已为该模块创建了模块命名空间对象(28.3),则为该对象。
[[HostDefined]] 任意值(默认值为 undefined 保留给需要将附加信息与模块关联的宿主环境使用的字段。
Table 39: Abstract Methods of Module Records
方法 目的 定义
LoadRequestedModules ( [ hostDefined ] )

The abstract method LoadRequestedModules takes optional argument hostDefined (任意值) and returns 一个 Promise.

递归加载所有依赖,为模块链接做准备。

在本规范内,此方法在以下类型中有定义;宿主可提供带有自定义定义的其他类型:
GetExportedNames ( [ exportStarSet ] )

The abstract method GetExportedNames takes optional argument exportStarSet (源文本模块记录的列表) and returns 字符串列表.

返回从该模块直接或间接导出的所有名称的列表。

在调用本方法前,必须已经调用并成功完成 LoadRequestedModules

在本规范内,此方法在以下类型中有定义;宿主可提供带有自定义定义的其他类型:
ResolveExport ( exportName [ , resolveSet ] )

The abstract method ResolveExport takes argument exportName (字符串) and optional argument resolveSet (具有字段 [[Module]]模块记录)和 [[ExportName]](字符串)的记录列表) and returns ResolvedBinding 记录nullambiguous.

返回该模块导出的某个名称的绑定。绑定由 ResolvedBinding 记录 表示, 形式为 { [[Module]]: 模块记录, [[BindingName]]: 字符串 | namespace }。 如果导出是没有任何模块直接绑定的模块命名空间对象,[[BindingName]]namespace。 如果名称无法解析,返回 null;如发现多个绑定,返回 ambiguous

每次使用特定 exportNameresolveSet 调用本操作时,必须返回相同结果。

在调用本方法前,必须已成功完成 LoadRequestedModules

在本规范内,此方法在以下类型中有定义;宿主可提供带有自定义定义的其他类型:
Evaluate ( )

The abstract method Evaluate takes no arguments and returns 一个 Promise.

返回一个 promise,其结果为评估该模块及其依赖的过程。 若评估成功或已经成功则 resolve,若失败或之前已失败则 reject。 若 promise 被拒绝,宿主应处理 promise 拒绝并重新抛出评估错误。 除非该模块是循环模块记录,否则返回的 promise 必须已结算。

在调用本方法前,必须已成功完成 Link

在本规范内,此方法在以下类型中有定义;宿主可提供带有自定义定义的其他类型:

16.2.1.5.1 EvaluateModuleSync ( module )

The abstract operation EvaluateModuleSync takes argument module (一个模块记录) and returns 返回包含 unused正常完成或 throw completion. 同步地对 module 求值,前提是调用方保证 module 的求值将返回一个已经 settled 的 promise。 It performs the following steps when called:

  1. 断言:module 不是循环模块记录
  2. promisemodule.Evaluate()。
  3. 断言:promise.[[PromiseState]]fulfilledrejected
  4. 如果 promise.[[PromiseState]]rejected,则
    1. 如果 promise.[[PromiseIsHandled]]false,执行 HostPromiseRejectionTracker(promise, "handle")。
    2. promise.[[PromiseIsHandled]] 设置为 true
    3. 抛出 promise.[[PromiseResult]]
  5. 返回 unused

16.2.1.6 循环模块记录

循环模块记录用于表示可以与其他循环模块记录类型的子类模块参与依赖循环的模块信息。不属于循环模块记录类型子类的模块记录不得与源文本模块记录参与依赖循环。

除了在Table 38中定义的字段外,循环模块记录还具有在Table 40中列出的附加字段

Table 40: 循环模块记录的附加字段
字段名 值类型 含义
[[Status]] newunlinkedlinkinglinkedevaluatingevaluating-asyncevaluated 初始为 new。随着模块在其生命周期中的推进,依次转换为 unlinkedlinkinglinkedevaluating,可能为 evaluating-async,最终为 evaluatedevaluating-async 表示该模块被排队等待其异步依赖完成后执行,或该模块的 [[HasTLA]] 字段为 true 且已执行并等待顶层完成。
[[EvaluationError]] 一个 throw completion 或 empty 表示在求值过程中发生的异常的 throw completion。如果未发生异常或 [[Status]] 不是 evaluated,则为 empty
[[DFSAncestorIndex]] 一个整数empty 仅在 LinkEvaluate 期间使用的辅助字段。如果 [[Status]]linkingevaluating,该值为模块的深度优先遍历索引,或同一强连通分量中“更早”的模块的索引。
[[RequestedModules]] ModuleRequest Record 的列表 与该模块中 import 相关联的 ModuleRequest Record 列表。该列表按源代码中 import 出现的顺序排列。
[[LoadedModules]] LoadedModuleRequest Record 的列表 一个从该模块使用的说明符字符串(用于请求导入模块,并带有相对导入属性)映射到已解析的模块记录的映射。该列表中不存在两个不同记录 r1r2 使得 ModuleRequestsEqual(r1, r2) 为 true
[[CycleRoot]] 一个循环模块记录empty 循环中首次访问的模块,即该强连通分量的 DFS 根祖先。对于不在循环中的模块,该值为模块自身。在 Evaluate 完成后,模块的 [[DFSAncestorIndex]] 是其 [[CycleRoot]] 的深度优先遍历索引。
[[HasTLA]] 一个布尔值 指示该模块是否本身是异步的(例如,包含顶层 await 的源文本模块记录)。拥有异步依赖并不意味着该字段为 true。该字段在模块解析后不得更改。
[[AsyncEvaluationOrder]] unset、一个整数done 该字段初始为 unset,对于完全同步的模块保持为 unset。对于自身为异步或具有异步依赖的模块,该字段被设置为一个整数,用于确定在16.2.1.6.1.3.4中排队执行待处理模块的顺序。一旦模块成功执行,该字段设置为 done
[[TopLevelCapability]] 一个 PromiseCapability Recordempty 如果该模块是某个循环的 [[CycleRoot]],且对该循环中的某个模块调用了 Evaluate(),则该字段包含整个求值过程的 PromiseCapability Record。它用于兑现 Evaluate() 抽象方法返回的 Promise 对象。对于该模块的依赖,该字段为 empty,除非对这些依赖中的某些模块启动了顶层 Evaluate()。
[[AsyncParentModules]] 循环模块记录的列表 如果该模块或其依赖的 [[HasTLA]]true,且执行正在进行中,则该字段跟踪该模块在顶层执行任务中的父导入模块。这些父模块在该模块成功完成执行之前不会开始执行。
[[PendingAsyncDependencies]] 一个整数empty 如果该模块具有异步依赖,该字段用于跟踪该模块剩余待执行的异步依赖模块数量。当该字段为 0 且没有执行错误时,该模块将被执行。

除了在Table 39中定义的方法外,循环模块记录还具有在Table 41中列出的附加方法:

Table 41: 循环模块记录的附加抽象方法
方法 目的 定义
InitializeEnvironment ( )

The abstract method InitializeEnvironment takes no arguments and returns 返回包含 unused正常完成或 throw completion.

初始化模块的环境记录,包括解析所有导入绑定,并创建模块的执行上下文
在本规范中,它在以下类型中具有定义;宿主可以提供具有其自身定义的其他类型:
ExecuteModule ( [ capability ] )

The abstract method ExecuteModule takes optional argument capability (一个 PromiseCapability Record,) and returns 返回包含 unused正常完成或 throw completion.

在其执行上下文中对模块代码进行求值。如果该模块的 [[HasTLA]]true,则会传入一个 PromiseCapability Record 作为参数,并期望该方法解析或拒绝该 capability。在这种情况下,该方法不得抛出异常,而是应在必要时拒绝该 PromiseCapability Record
在本规范中,它在以下类型中具有定义;宿主可以提供具有其自身定义的其他类型:

GraphLoadingState 记录是一个记录,用于包含模块图加载过程的信息。它用于在调用 HostLoadImportedModule 后继续加载。每个 GraphLoadingState 记录具有在Table 42中定义的字段:

Table 42: GraphLoadingState 记录字段
字段名 值类型 含义
[[PromiseCapability]] 一个 PromiseCapability Record 在加载过程完成时需要解析的 promise。
[[IsLoading]] 一个布尔值 如果加载过程尚未结束(既未成功也未出错),则为 true。
[[PendingModulesCount]] 一个非负整数 用于跟踪待处理的 HostLoadImportedModule 调用数量。
[[Visited]] 循环模块记录的列表 当前加载过程中已经加载的循环模块记录列表,用于避免循环依赖导致的无限循环。
[[HostDefined]] 任意值(默认值为 empty 包含由宿主定义的数据,用于从 LoadRequestedModules 调用方传递到 HostLoadImportedModule

16.2.1.6.1 模块记录抽象方法的实现

以下是循环模块记录的具体方法,用于实现Table 39中定义的对应模块记录抽象方法。

16.2.1.6.1.1 LoadRequestedModules ( [ hostDefined ] )

The LoadRequestedModules concrete method of a Cyclic Module Record module takes optional argument hostDefined (任意值) and returns 一个 Promise. 为 module 的依赖图中所有模块记录填充 [[LoadedModules]](大部分工作由辅助函数 InnerModuleLoading 完成)。它接受一个可选的 hostDefined 参数,并将其传递给 HostLoadImportedModule 钩子。 It performs the following steps when called:

  1. 如果 hostDefined 未提供,则将 hostDefined 设为 empty
  2. pc 为 ! NewPromiseCapability(%Promise%)。
  3. stateGraphLoadingState 记录 { [[IsLoading]]: true, [[PendingModulesCount]]: 1, [[Visited]]: « », [[PromiseCapability]]: pc, [[HostDefined]]: hostDefined }。
  4. 执行 InnerModuleLoading(state, module)。
  5. 返回 pc.[[Promise]]
Note
hostDefined 参数可用于传递获取导入模块所需的附加信息。例如,HTML 使用它来为 <link rel="preload" as="..."> 标签设置正确的 fetch 目标。 import() 表达式从不会设置 hostDefined 参数。

16.2.1.6.1.1.1 InnerModuleLoading ( state, module )

The abstract operation InnerModuleLoading takes arguments state (一个 GraphLoadingState 记录) and module (一个模块记录) and returns unused. 被 LoadRequestedModules 使用,用于递归执行 module 依赖图的实际加载过程。 It performs the following steps when called:

  1. 断言:state.[[IsLoading]]true
  2. 如果 module循环模块记录,且 module.[[Status]]new,并且 state.[[Visited]] 不包含 module,则
    1. module 追加到 state.[[Visited]]
    2. requestedModulesCountmodule.[[RequestedModules]] 中元素的数量。
    3. state.[[PendingModulesCount]] 设为 state.[[PendingModulesCount]] + requestedModulesCount
    4. 对于 module.[[RequestedModules]] 中的每个 ModuleRequest Record request,执行
      1. 如果 AllImportAttributesSupported(request.[[Attributes]]) 为 false,则
        1. errorThrowCompletion(一个新创建的 SyntaxError 对象)。
        2. 执行 ContinueModuleLoading(state, error)。
      2. 否则如果 module.[[LoadedModules]] 包含一个 LoadedModuleRequest Record record,使得 ModuleRequestsEqual(record, request) 为 true,则
        1. 执行 InnerModuleLoading(state, record.[[Module]])。
      3. 否则,
        1. 执行 HostLoadImportedModule(module, request, state.[[HostDefined]], state)。
        2. 注意:HostLoadImportedModule 将调用 FinishLoadingImportedModule,该调用会通过 ContinueModuleLoading 重新进入图加载过程。
      4. 如果 state.[[IsLoading]]false,返回 unused
  3. 断言:state.[[PendingModulesCount]] ≥ 1。
  4. state.[[PendingModulesCount]] 设为 state.[[PendingModulesCount]] - 1。
  5. 如果 state.[[PendingModulesCount]] = 0,则
    1. state.[[IsLoading]] 设为 false
    2. 对于 state.[[Visited]] 中的每个循环模块记录 loaded,执行
      1. 如果 loaded.[[Status]]new,则将其设为 unlinked
    3. 执行 ! Call(state.[[PromiseCapability]].[[Resolve]], undefined, « undefined »)。
  6. 返回 unused

16.2.1.6.1.1.2 ContinueModuleLoading ( state, moduleCompletion )

The abstract operation ContinueModuleLoading takes arguments state (一个 GraphLoadingState 记录) and moduleCompletion (一个包含模块记录正常完成或 throw completion) and returns unused. 用于在调用 HostLoadImportedModule 之后重新进入加载过程。 It performs the following steps when called:

  1. 如果 state.[[IsLoading]]false,返回 unused
  2. 如果 moduleCompletion正常完成,则
    1. 执行 InnerModuleLoading(state, moduleCompletion.[[Value]])。
  3. 否则,
    1. state.[[IsLoading]] 设为 false
    2. 执行 ! Call(state.[[PromiseCapability]].[[Reject]], undefined, « moduleCompletion.[[Value]] »)。
  4. 返回 unused

16.2.1.6.1.2 Link ( )

The Link concrete method of a Cyclic Module Record module takes no arguments and returns 返回包含 unused正常完成或 throw completion. 成功时,Link 将该模块的 [[Status]]unlinked 转换为 linked。失败时,将抛出异常并且该模块的 [[Status]] 保持为 unlinked。(大部分工作由辅助函数 InnerModuleLinking 完成。) It performs the following steps when called:

  1. 断言:module.[[Status]]unlinkedlinkedevaluating-asyncevaluated 之一。
  2. stack 为一个新的空列表。
  3. resultCompletion(InnerModuleLinking(module, stack, 0))。
  4. 如果 result 是异常完成,则
    1. 对于 stack 中的每个循环模块记录 m,执行
      1. 断言:m.[[Status]]linking
      2. m.[[Status]] 设为 unlinked
    2. 断言:module.[[Status]]unlinked
    3. 返回 ? result
  5. 断言:module.[[Status]]linkedevaluating-asyncevaluated 之一。
  6. 断言:stack 为空。
  7. 返回 unused

16.2.1.6.1.2.1 InnerModuleLinking ( module, stack, index )

The abstract operation InnerModuleLinking takes arguments module (一个模块记录), stack (循环模块记录的列表), and index (一个非负整数) and returns 返回包含一个非负整数正常完成或 throw completion. 被 Link 使用,用于执行 module 的实际链接过程,并递归处理依赖图中的所有其他模块。stackindex 参数,以及模块的 [[DFSAncestorIndex]] 字段,用于跟踪深度优先搜索(DFS)遍历。特别是,[[DFSAncestorIndex]] 用于发现强连通分量(SCC),使得同一 SCC 中的所有模块一起转换为 linked。 It performs the following steps when called:

  1. 如果 module 不是循环模块记录,则
    1. 执行 ? module.Link()。
    2. 返回 index
  2. 如果 module.[[Status]]linkinglinkedevaluating-asyncevaluated 之一,则
    1. 返回 index
  3. 断言:module.[[Status]]unlinked
  4. module.[[Status]] 设为 linking
  5. moduleIndexindex
  6. module.[[DFSAncestorIndex]] 设为 index
  7. index 设为 index + 1。
  8. module 追加到 stack
  9. 对于 module.[[RequestedModules]] 中的每个 ModuleRequest Record request,执行
    1. requiredModuleGetImportedModule(module, request)。
    2. index 设为 ? InnerModuleLinking(requiredModule, stack, index)。
    3. 如果 requiredModule循环模块记录,则
      1. 断言:requiredModule.[[Status]]linkinglinkedevaluating-asyncevaluated 之一。
      2. 断言:当且仅当 stack 包含 requiredModule 时,requiredModule.[[Status]]linking
      3. 如果 requiredModule.[[Status]]linking,则
        1. module.[[DFSAncestorIndex]] 设为 min(module.[[DFSAncestorIndex]], requiredModule.[[DFSAncestorIndex]])。
  10. 执行 ? module.InitializeEnvironment()。
  11. 断言:modulestack 中恰好出现一次。
  12. 断言:module.[[DFSAncestorIndex]]moduleIndex
  13. 如果 module.[[DFSAncestorIndex]] = moduleIndex,则
    1. donefalse
    2. 重复执行,直到 donetrue
      1. requiredModulestack 的最后一个元素。
      2. stack 中移除最后一个元素。
      3. 断言:requiredModule循环模块记录
      4. requiredModule.[[Status]] 设为 linked
      5. 如果 requiredModulemodule 是同一个模块记录,则将 done 设为 true
  14. 返回 index

16.2.1.6.1.3 Evaluate ( )

The Evaluate concrete method of a Cyclic Module Record module takes no arguments and returns 一个 Promise. Evaluate 将该模块的 [[Status]]linked 转换为 evaluating-asyncevaluated。在某个强连通分量中第一次调用时,Evaluate 会创建并返回一个 Promise,该 Promise 在模块完成求值时被解析。该 Promise 存储在该分量的 [[CycleRoot]][[TopLevelCapability]] 字段中。之后在该分量中任意模块上调用 Evaluate 都会返回同一个 Promise。(大部分工作由辅助函数 InnerModuleEvaluation 完成。) It performs the following steps when called:

  1. 断言:在同一代理中,对 Evaluate 的此调用不会与另一个 Evaluate 调用同时发生。
  2. 断言:module.[[Status]]linkedevaluating-asyncevaluated 之一。
  3. 如果 module.[[Status]]evaluating-asyncevaluated,则
    1. 如果 module.[[CycleRoot]] 不为 empty,则
      1. module 设为 module.[[CycleRoot]]
    2. 否则,
      1. 断言:module.[[Status]]evaluatedmodule.[[EvaluationError]] 为 throw completion。
  4. 如果 module.[[TopLevelCapability]] 不为 empty,则
    1. 返回 module.[[TopLevelCapability]].[[Promise]]
  5. stack 为一个新的空列表。
  6. capability 为 ! NewPromiseCapability(%Promise%)。
  7. module.[[TopLevelCapability]] 设为 capability
  8. resultCompletion(InnerModuleEvaluation(module, stack, 0))。
  9. 如果 result 是异常完成,则
    1. 对于 stack 中的每个循环模块记录 m,执行
      1. 断言:m.[[Status]]evaluating
      2. m.[[Status]] 设为 evaluated
      3. m.[[EvaluationError]] 设为 result
    2. 断言:module.[[Status]]evaluated
    3. 断言:module.[[EvaluationError]]result 是同一个 Completion Record
    4. 执行 ! Call(capability.[[Reject]], undefined, « result.[[Value]] »)。
  10. 否则,
    1. 断言:module.[[Status]]evaluating-asyncevaluated
    2. 断言:module.[[EvaluationError]]empty
    3. 如果 module.[[Status]]evaluated,则
      1. 断言:module.[[AsyncEvaluationOrder]]unsetdone
      2. 注意:当且仅当该模块之前已经被异步求值时,module.[[AsyncEvaluationOrder]]done
      3. 执行 ! Call(capability.[[Resolve]], undefined, « undefined »)。
    4. 断言:stack 为空。
  11. 返回 capability.[[Promise]]

16.2.1.6.1.3.1 InnerModuleEvaluation ( module, stack, index )

The abstract operation InnerModuleEvaluation takes arguments module (一个模块记录), stack (循环模块记录的列表), and index (一个非负整数) and returns 返回包含一个非负整数正常完成或 throw completion. 被 Evaluate 使用,用于执行 module 的实际求值过程,并递归处理依赖图中的所有其他模块。stackindex 参数,以及 module[[DFSAncestorIndex]] 字段,与 InnerModuleLinking 中的使用方式相同。 It performs the following steps when called:

  1. 如果 module 不是循环模块记录,则
    1. 执行 ? EvaluateModuleSync(module)。
    2. 返回 index
  2. 如果 module.[[Status]]evaluating-asyncevaluated,则
    1. 如果 module.[[EvaluationError]]empty,返回 index
    2. 返回 ? module.[[EvaluationError]]
  3. 如果 module.[[Status]]evaluating,返回 index
  4. 断言:module.[[Status]]linked
  5. module.[[Status]] 设为 evaluating
  6. moduleIndexindex
  7. module.[[DFSAncestorIndex]] 设为 index
  8. module.[[PendingAsyncDependencies]] 设为 0。
  9. index 设为 index + 1。
  10. module 追加到 stack
  11. 对于 module.[[RequestedModules]] 中的每个 ModuleRequest Record request,执行
    1. requiredModuleGetImportedModule(module, request)。
    2. index 设为 ? InnerModuleEvaluation(requiredModule, stack, index)。
    3. 如果 requiredModule循环模块记录,则
      1. 断言:requiredModule.[[Status]]evaluatingevaluating-asyncevaluated 之一。
      2. 断言:当且仅当 stack 包含 requiredModule 时,requiredModule.[[Status]]evaluating
      3. 如果 requiredModule.[[Status]]evaluating,则
        1. module.[[DFSAncestorIndex]] 设为 min(module.[[DFSAncestorIndex]], requiredModule.[[DFSAncestorIndex]])。
      4. 否则,
        1. requiredModule 设为 requiredModule.[[CycleRoot]]
        2. 断言:requiredModule.[[Status]]evaluating-asyncevaluated
        3. 如果 requiredModule.[[EvaluationError]] 不为 empty,返回 ? requiredModule.[[EvaluationError]]
      5. 如果 requiredModule.[[AsyncEvaluationOrder]]整数,则
        1. module.[[PendingAsyncDependencies]] 设为 module.[[PendingAsyncDependencies]] + 1。
        2. module 追加到 requiredModule.[[AsyncParentModules]]
  12. 如果 module.[[PendingAsyncDependencies]] > 0 或 module.[[HasTLA]]true,则
    1. 断言:module.[[AsyncEvaluationOrder]]unset
    2. module.[[AsyncEvaluationOrder]] 设为 IncrementModuleAsyncEvaluationCount()。
    3. 如果 module.[[PendingAsyncDependencies]] = 0,则执行 ExecuteAsyncModule(module)。
  13. 否则,
    1. 执行 ? module.ExecuteModule()
  14. 断言:modulestack 中恰好出现一次。
  15. 断言:module.[[DFSAncestorIndex]]moduleIndex
  16. 如果 module.[[DFSAncestorIndex]] = moduleIndex,则
    1. donefalse
    2. 重复执行,直到 donetrue
      1. requiredModulestack 的最后一个元素。
      2. stack 中移除最后一个元素。
      3. 断言:requiredModule循环模块记录
      4. 断言:requiredModule.[[AsyncEvaluationOrder]]整数unset
      5. 如果 requiredModule.[[AsyncEvaluationOrder]]unset,则将 requiredModule.[[Status]] 设为 evaluated
      6. 否则,将 requiredModule.[[Status]] 设为 evaluating-async
      7. 如果 requiredModulemodule 是同一个模块记录,则将 done 设为 true
      8. requiredModule.[[CycleRoot]] 设为 module
  17. 返回 index
Note 1

当模块正在被 InnerModuleEvaluation 遍历时,其状态为 evaluating。当执行完成时,模块状态为 evaluated;如果其 [[HasTLA]]true 或存在异步依赖,则在执行期间为 evaluating-async

Note 2

当某个异步循环中的模块不处于 evaluating 状态时,任何依赖该循环模块的模块将通过 [[CycleRoot]] 依赖该循环的根模块的执行。这确保循环状态可以通过其根模块状态作为一个单一的强连通分量来处理。

16.2.1.6.1.3.2 ExecuteAsyncModule ( module )

The abstract operation ExecuteAsyncModule takes argument module (一个循环模块记录) and returns unused. It performs the following steps when called:

  1. 断言:module.[[Status]]evaluatingevaluating-async
  2. 断言:module.[[HasTLA]]true
  3. capability 为 ! NewPromiseCapability(%Promise%)。
  4. fulfilledClosure 为一个新的无参数抽象闭包,它捕获 module,并在调用时执行以下步骤:
    1. 执行 AsyncModuleExecutionFulfilled(module)。
    2. 返回 NormalCompletion(undefined)。
  5. onFulfilledCreateBuiltinFunction(fulfilledClosure, 0, "", « »)。
  6. rejectedClosure 为一个新的抽象闭包,参数为 (error),它捕获 module,并在调用时执行以下步骤:
    1. 执行 AsyncModuleExecutionRejected(module, error)。
    2. 返回 NormalCompletion(undefined)。
  7. onRejectedCreateBuiltinFunction(rejectedClosure, 0, "", « »)。
  8. 执行 PerformPromiseThen(capability.[[Promise]], onFulfilled, onRejected)。
  9. 执行 ! module.ExecuteModule(capability)
  10. 返回 unused

16.2.1.6.1.3.3 GatherAvailableAncestors ( module, execList )

The abstract operation GatherAvailableAncestors takes arguments module (一个循环模块记录) and execList (循环模块记录的列表) and returns unused. It performs the following steps when called:

  1. 对于 module.[[AsyncParentModules]] 中的每个循环模块记录 m,执行
    1. 如果 execList 不包含 mm.[[CycleRoot]].[[EvaluationError]]empty,则
      1. 断言:m.[[Status]]evaluating-async
      2. 断言:m.[[EvaluationError]]empty
      3. 断言:m.[[AsyncEvaluationOrder]]整数
      4. 断言:m.[[PendingAsyncDependencies]] > 0。
      5. m.[[PendingAsyncDependencies]] 设为 m.[[PendingAsyncDependencies]] - 1。
      6. 如果 m.[[PendingAsyncDependencies]] = 0,则
        1. m 追加到 execList
        2. 如果 m.[[HasTLA]]false,则执行 GatherAvailableAncestors(m, execList)。
  2. 返回 unused
Note

当某个根模块 module 的异步执行完成时,此函数用于确定可以在该完成点同步执行的一组模块,并将它们填充到 execList 中。

16.2.1.6.1.3.4 AsyncModuleExecutionFulfilled ( module )

The abstract operation AsyncModuleExecutionFulfilled takes argument module (一个循环模块记录) and returns unused. It performs the following steps when called:

  1. 如果 module.[[Status]]evaluated,则
    1. 断言:module.[[EvaluationError]] 不为 empty
    2. 返回 unused
  2. 断言:module.[[Status]]evaluating-async
  3. 断言:module.[[AsyncEvaluationOrder]]整数
  4. 断言:module.[[EvaluationError]]empty
  5. module.[[AsyncEvaluationOrder]] 设为 done
  6. module.[[Status]] 设为 evaluated
  7. 如果 module.[[TopLevelCapability]] 不为 empty,则
    1. 断言:module.[[CycleRoot]]module 是同一个模块记录
    2. 执行 ! Call(module.[[TopLevelCapability]].[[Resolve]], undefined, « undefined »)。
  8. execList 为一个新的空列表。
  9. 执行 GatherAvailableAncestors(module, execList)。
  10. 断言:execList 中所有元素的 [[AsyncEvaluationOrder]] 字段为整数[[PendingAsyncDependencies]] 字段为 0,且 [[EvaluationError]] 字段为 empty
  11. sortedExecList 为一个列表,其元素为 execList 的元素,并按其 [[AsyncEvaluationOrder]] 字段升序排序。
  12. 对于 sortedExecList 中的每个循环模块记录 m,执行
    1. 如果 m.[[Status]]evaluated,则
      1. 断言:m.[[EvaluationError]] 不为 empty
    2. 否则如果 m.[[HasTLA]]true,则
      1. 执行 ExecuteAsyncModule(m)。
    3. 否则,
      1. resultCompletion(m.ExecuteModule())。
      2. 如果 result 是异常完成,则
        1. 执行 AsyncModuleExecutionRejected(m, result.[[Value]])。
      3. 否则,
        1. m.[[AsyncEvaluationOrder]] 设为 done
        2. m.[[Status]] 设为 evaluated
        3. 如果 m.[[TopLevelCapability]] 不为 empty,则
          1. 断言:m.[[CycleRoot]]m 是同一个模块记录
          2. 执行 ! Call(m.[[TopLevelCapability]].[[Resolve]], undefined, « undefined »)。
  13. 返回 unused

16.2.1.6.1.3.5 AsyncModuleExecutionRejected ( module, error )

The abstract operation AsyncModuleExecutionRejected takes arguments module (一个循环模块记录) and error (一个 ECMAScript 语言值) and returns unused. It performs the following steps when called:

  1. 如果 module.[[Status]]evaluated,则
    1. 断言:module.[[EvaluationError]] 不为 empty
    2. 返回 unused
  2. 断言:module.[[Status]]evaluating-async
  3. 断言:module.[[AsyncEvaluationOrder]]整数
  4. 断言:module.[[EvaluationError]]empty
  5. module.[[EvaluationError]] 设为 ThrowCompletion(error)。
  6. module.[[Status]] 设为 evaluated
  7. module.[[AsyncEvaluationOrder]] 设为 done
  8. 注意:为了与 AsyncModuleExecutionFulfilled 对称,module.[[AsyncEvaluationOrder]] 被设为 done。在 InnerModuleEvaluation 中,当模块的 [[EvaluationError]] 不为 empty 时,其 [[AsyncEvaluationOrder]] 内部槽的值不会被使用。
  9. 如果 module.[[TopLevelCapability]] 不为 empty,则
    1. 断言:module.[[CycleRoot]]module 是同一个模块记录
    2. 执行 ! Call(module.[[TopLevelCapability]].[[Reject]], undefined, « error »)。
  10. 对于 module.[[AsyncParentModules]] 中的每个循环模块记录 m,执行
    1. 执行 AsyncModuleExecutionRejected(m, error)。
  11. 返回 unused

16.2.1.6.2 循环模块记录图示例

本非规范性章节给出一系列常见模块图的链接和求值示例,并特别关注错误可能如何发生。

首先考虑以下简单模块图:

Figure 2: 一个简单模块图
模块 A 依赖模块 B,模块 B 依赖模块 C 的模块图

我们先假设不存在错误条件。当宿主首次调用 A.LoadRequestedModules() 时,根据假设它会成功完成,并递归加载 BC 的依赖(分别是 C 和无),然后设置 A.[[Status]] = B.[[Status]] = C.[[Status]] = unlinked。随后,当宿主调用 A.Link() 时,它会成功完成(同样根据假设),使得 A.[[Status]] = B.[[Status]] = C.[[Status]] = linked。这些准备步骤可以在任何时候执行。之后,当宿主准备好承受模块可能产生的任何副作用时,它可以调用 A.Evaluate(),该调用会成功完成,返回一个解析为 undefined 的 Promise(同样根据假设),并且递归地先对 C 求值,再对 B 求值。此时每个模块的 [[Status]] 都将为 evaluated

接着考虑在成功调用 A.LoadRequestedModules() 之后涉及链接错误的情况。如果 CInnerModuleLinking 成功,但随后 B 失败,例如因为它导入了 C 不提供的某个内容,那么原始的 A.Link() 将失败,并且 AB[[Status]] 都保持为 unlinked。不过,C[[Status]] 已变为 linked

最后,考虑在成功调用 Link() 之后涉及求值错误的情况。如果 CInnerModuleEvaluation 成功,但随后 B 失败,例如因为 B 包含会抛出异常的代码,那么原始的 A.Evaluate() 将失败,返回一个 rejected Promise。产生的异常会记录在 AB[[EvaluationError]] 字段中,并且它们的 [[Status]] 将变为 evaluatedC 也会变为 evaluated,但与 AB 不同,它不会有 [[EvaluationError]],因为它已成功完成求值。存储该异常可确保宿主日后任何时候尝试通过调用 ABEvaluate() 方法来复用它们时,都会遇到同一个异常。(宿主不要求复用循环模块记录;类似地,宿主也不要求暴露这些方法抛出的异常对象。不过,本规范允许此类用途。)

现在考虑一种不同类型的错误条件:

Figure 3: 包含无法解析模块的模块图
模块 A 依赖一个缺失(无法解析)的模块,该模块用 ??? 表示的模块图

在此场景中,模块 A 声明依赖另一个模块,但该模块不存在 Module Record,也就是说,当请求该模块时,HostLoadImportedModule 会带着异常调用 FinishLoadingImportedModule。这可能由多种原因导致,例如对应资源不存在,或资源存在但 ParseModule 在尝试解析得到的源文本时返回错误。宿主可以选择通过传递给 FinishLoadingImportedModule 的完成记录暴露失败原因。无论如何,该异常会导致加载失败,从而使 A[[Status]] 保持为 new

这里加载、链接和求值错误之间的差异源于以下特性:

  • 求值必须只执行一次,因为它可能产生副作用;因此,即使求值未成功,记住求值是否已经执行过也很重要。(在错误情况下,也有必要记住异常,否则后续 Evaluate() 调用将不得不合成一个新的异常。)
  • 另一方面,链接没有副作用,因此即使链接失败,也可以在之后无问题地重试。
  • 加载与宿主紧密交互,对某些宿主而言,允许用户重试失败的加载可能是可取的(例如,当失败由暂时不佳的网络条件导致时)。

现在,考虑一个带有循环的模块图:

Figure 4: 一个循环模块图
模块 A 依赖模块 B 和 C,但模块 B 也依赖模块 A 的模块图

这里我们假设入口点是模块 A,因此宿主通过调用 A.LoadRequestedModules() 开始,它会在 A 上执行 InnerModuleLoading。这又会在 BC 上调用 InnerModuleLoading。由于存在循环,这再次触发在 A 上调用 InnerModuleLoading,但此时它是无操作,因为在此 LoadRequestedModules 过程中 A 的依赖加载已经被触发。当图中的所有模块都成功加载后,它们的 [[Status]] 会同时从 new 转换为 unlinked

随后宿主调用 A.Link(),它会在 A 上执行 InnerModuleLinking。这又会在 B 上调用 InnerModuleLinking。由于存在循环,这再次触发在 A 上调用 InnerModuleLinking,但此时它是无操作,因为 A.[[Status]] 已经是 linking。当控制返回 A 并在 C 上触发 InnerModuleLinking 时,B.[[Status]] 自身仍保持为 linking。在该调用返回并且 C.[[Status]]linked 之后,AB 一起从 linking 转换为 linked;这是有意设计的,因为它们构成一个强连通分量。之所以可以同时转换同一 SCC 中模块的状态,是因为在此阶段模块图是通过深度优先搜索遍历的。

在循环模块图的求值阶段,在成功情况下也会发生类似过程。

现在考虑 A 存在链接错误的情况;例如,它试图从 C 导入一个不存在的绑定。在这种情况下,上述步骤仍然发生,包括第二次在 A 上调用 InnerModuleLinking 时的提前返回。然而,一旦回退到原始的 A 上的 InnerModuleLinking,它会在 InitializeEnvironment 期间失败,即紧接在 C.ResolveExport() 之后。抛出的 SyntaxError 异常传播到 A.Link,它会重置当前位于其 stack 上的所有模块(这些模块始终恰好是仍处于 linking 的模块)。因此 AB 都变为 unlinked。注意 C 保持为 linked

或者,考虑 A 存在求值错误的情况;例如,其源代码抛出异常。在这种情况下,上述步骤在求值时的对应过程仍然发生,包括第二次在 A 上调用 InnerModuleEvaluation 时的提前返回。然而,一旦回退到原始的 A 上的 InnerModuleEvaluation,它按假设失败。抛出的异常传播到 A.Evaluate(),该方法会在所有当前位于其 stack 上的模块(即仍处于 evaluating 的模块)中记录该错误,并且还会通过 [[AsyncParentModules]] 传播,该字段为包含或依赖顶层 await 的模块形成一条贯穿整个依赖图的链,并通过 AsyncModuleExecutionRejected 算法传播。因此 AB 都变为 evaluated,且异常记录在 AB[[EvaluationError]] 字段中,而 C 保持为 evaluated 且没有 [[EvaluationError]]

最后,考虑一个带有循环的模块图,其中所有模块都异步完成:

Figure 5: 一个异步循环模块图
模块 A 依赖模块 B 和 C,模块 B 依赖模块 D,模块 C 依赖模块 D 和 E,模块 D 依赖模块 A 的模块图

加载和链接照常发生,所有模块最终的 [[Status]] 都设置为 linked

调用 A.Evaluate() 会在 ABD 上调用 InnerModuleEvaluation,它们都转换为 evaluating。然后再次在 A 上调用 InnerModuleEvaluation,由于它已经是 evaluating,所以这是无操作。此时,D.[[PendingAsyncDependencies]] 为 0,因此调用 ExecuteAsyncModule(D),并使用一个新的 PromiseCapability 调用 D.ExecuteModule 来跟踪 D 的异步执行。我们回退到 B 上的 InnerModuleEvaluation,将 B.[[PendingAsyncDependencies]] 设为 1,并将 B.[[AsyncEvaluationOrder]] 设为 1。我们再回退到原始的 A 上的 InnerModuleEvaluation,将 A.[[PendingAsyncDependencies]] 设为 1。在遍历 A 的依赖的下一次循环中,我们在 C 上调用 InnerModuleEvaluation,并因此在 D(再次为无操作)和 E 上调用它。由于 E 没有依赖且不是循环的一部分,我们以与 D 相同的方式调用 ExecuteAsyncModule(E),并立即将 E 从栈中移除。我们再次回退到 C 上的 InnerModuleEvaluation,将 C.[[AsyncEvaluationOrder]] 设为 3。现在我们完成对 A 依赖的循环,将 A.[[AsyncEvaluationOrder]] 设为 4,并从栈中移除整个强连通分量,使所有这些模块一次性转换为 evaluating-async。此时,各模块的字段如Table 43所示。

Table 43: 初始 Evaluate() 调用后的模块字段
字段
模块
A B C D E
[[DFSAncestorIndex]] 0 0 0 0 4
[[Status]] evaluating-async evaluating-async evaluating-async evaluating-async evaluating-async
[[AsyncEvaluationOrder]] 4 1 3 0 2
[[AsyncParentModules]] « » « A » « A » « B, C » « C »
[[PendingAsyncDependencies]] 2(BC 1(D 2(DE 0 0

我们假设 E 最先完成执行。当这发生时,调用 AsyncModuleExecutionFulfilledE.[[Status]] 被设置为 evaluated,并且 C.[[PendingAsyncDependencies]] 递减为 1。更新后的模块字段如Table 44所示。

Table 44: 模块 E 完成执行后的模块字段
字段
模块
C E
[[DFSAncestorIndex]] 0 4
[[Status]] evaluating-async evaluated
[[AsyncEvaluationOrder]] 3 done
[[AsyncParentModules]] « A » « C »
[[PendingAsyncDependencies]] 1(D 0

接下来 D 完成(因为它是唯一仍在执行的模块)。当这发生时,再次调用 AsyncModuleExecutionFulfilled,并将 D.[[Status]] 设置为 evaluated。其可供执行的祖先是 B(其 [[AsyncEvaluationOrder]] 为 1)和 C(其 [[AsyncEvaluationOrder]] 为 3),因此会先处理 BB.[[PendingAsyncDependencies]] 递减为 0,在 B 上调用 ExecuteAsyncModule,并开始执行。C.[[PendingAsyncDependencies]] 也递减为 0,C 开始执行(如果 B 包含 await,则可能与 B 并行执行)。更新后的模块字段如Table 45所示。

Table 45: 模块 D 完成执行后的模块字段
字段
模块
B C D
[[DFSAncestorIndex]] 0 0 0
[[Status]] evaluating-async evaluating-async evaluated
[[AsyncEvaluationOrder]] 1 3 done
[[AsyncParentModules]] « A » « A » « B, C »
[[PendingAsyncDependencies]] 0 0 0

我们假设 C 接下来完成执行。当这发生时,再次调用 AsyncModuleExecutionFulfilledC.[[Status]] 被设置为 evaluated,并且 A.[[PendingAsyncDependencies]] 递减为 1。更新后的模块字段如Table 46所示。

Table 46: 模块 C 完成执行后的模块字段
字段
模块
A C
[[DFSAncestorIndex]] 0 0
[[Status]] evaluating-async evaluated
[[AsyncEvaluationOrder]] 4 done
[[AsyncParentModules]] « » « A »
[[PendingAsyncDependencies]] 1(B 0

然后,B 完成执行。当这发生时,再次调用 AsyncModuleExecutionFulfilled,并将 B.[[Status]] 设置为 evaluatedA.[[PendingAsyncDependencies]] 递减为 0,因此调用 ExecuteAsyncModule 并开始执行。更新后的模块字段如Table 47所示。

Table 47: 模块 B 完成执行后的模块字段
字段
模块
A B
[[DFSAncestorIndex]] 0 0
[[Status]] evaluating-async evaluated
[[AsyncEvaluationOrder]] 4 done
[[AsyncParentModules]] « » « A »
[[PendingAsyncDependencies]] 0 0

最后,A 完成执行。当这发生时,再次调用 AsyncModuleExecutionFulfilled,并将 A.[[Status]] 设置为 evaluated。此时,A.[[TopLevelCapability]] 中的 Promise(即从 A.Evaluate() 返回的 Promise)被解析,这就完成了此模块图的处理。更新后的模块字段如Table 48所示。

Table 48: 模块 A 完成执行后的模块字段
字段
模块
A
[[DFSAncestorIndex]] 0
[[Status]] evaluated
[[AsyncEvaluationOrder]] done
[[AsyncParentModules]] « »
[[PendingAsyncDependencies]] 0

或者,考虑一种失败情况:CB 完成执行之前执行失败并返回错误。当这发生时,调用 AsyncModuleExecutionRejected,它将 C.[[Status]] 设置为 evaluated,并将 C.[[EvaluationError]] 设置为该错误。然后它通过对每个 AsyncParentModules 执行 AsyncModuleExecutionRejected,将该错误传播给所有 AsyncParentModules。更新后的模块字段如Table 49所示。

Table 49: 模块 C 以错误完成后的模块字段
字段
模块
A C
[[DFSAncestorIndex]] 0 0
[[Status]] evaluated evaluated
[[AsyncEvaluationOrder]] done done
[[AsyncParentModules]] « » « A »
[[PendingAsyncDependencies]] 1(B 0
[[EvaluationError]] empty C 的求值错误

A 将以与 C 相同的错误被拒绝,因为 C 会使用 C 的错误在 A 上调用 AsyncModuleExecutionRejectedA.[[Status]] 被设置为 evaluated。此时,A.[[TopLevelCapability]] 中的 Promise(即从 A.Evaluate() 返回的 Promise)被拒绝。更新后的模块字段如Table 50所示。

Table 50: 模块 A 被拒绝后的模块字段
字段
模块
A
[[DFSAncestorIndex]] 0
[[Status]] evaluated
[[AsyncEvaluationOrder]] done
[[AsyncParentModules]] « »
[[PendingAsyncDependencies]] 0
[[EvaluationError]] C 的求值错误

然后,B 无错误地完成执行。当这发生时,再次调用 AsyncModuleExecutionFulfilled,并将 B.[[Status]] 设置为 evaluated。在 B 上调用 GatherAvailableAncestors。然而,A.[[CycleRoot]]A,而它有求值错误,因此它不会被添加到返回的 sortedExecList 中,AsyncModuleExecutionFulfilled 将不再进一步处理而返回。B 的任何未来导入方都会解析 B.[[CycleRoot]].[[EvaluationError]] 的拒绝,该错误来自 C 的求值错误,并且已设置在循环根 A 上。更新后的模块字段如Table 51所示。

Table 51: 错误图中模块 B 完成执行后的模块字段
字段
模块
A B
[[DFSAncestorIndex]] 0 0
[[Status]] evaluated evaluated
[[AsyncEvaluationOrder]] 4 1
[[AsyncParentModules]] « » « A »
[[PendingAsyncDependencies]] 0 0
[[EvaluationError]] C 的求值错误 empty

16.2.1.7 源文本模块记录

源文本模块记录用于表示从 ECMAScript 源文本11)定义的模块的信息,该源文本使用目标符号 Module 进行解析。其字段包含关于该模块导入和导出的名称的摘要信息,其具体方法使用这些摘要来链接和求值该模块。

源文本模块记录可以与抽象模块记录类型的其他子类共存于一个模块图中,并且可以与循环模块记录类型的其他子类参与循环。

除了在Table 40中定义的字段外,源文本模块记录还具有在Table 52中列出的附加字段。这些字段中的每一个最初都在 ParseModule 中设置。

Table 52: 源文本模块记录的附加字段
字段名 值类型 含义
[[ECMAScriptCode]] 一个解析节点 使用 Module 作为目标符号解析该模块源文本的结果。
[[Context]] 一个 ECMAScript 代码执行上下文empty 与该模块关联的执行上下文。在模块的环境被初始化之前,它为 empty
[[ImportMeta]] 一个对象或 empty 通过 import.meta 元属性暴露的对象。在 ECMAScript 代码访问它之前,它为 empty
[[ImportEntries]] ImportEntry 记录的列表 从该模块代码派生出的 ImportEntry 记录列表。
[[LocalExportEntries]] ExportEntry 记录的列表 从该模块代码派生出的 ExportEntry 记录列表,对应于模块内部出现的声明。
[[IndirectExportEntries]] ExportEntry 记录的列表 从该模块代码派生出的 ExportEntry 记录列表,对应于模块内部出现的重导出导入,或来自 export * as namespace 声明的导出。
[[StarExportEntries]] ExportEntry 记录的列表 从该模块代码派生出的 ExportEntry 记录列表,对应于模块内部出现的 export * 声明,不包括 export * as namespace 声明。

ImportEntry 记录是一个记录,用于摘要关于单个声明式导入的信息。每个 ImportEntry 记录具有在Table 53中定义的字段:

Table 53: ImportEntry 记录字段
字段名 值类型 含义
[[ModuleRequest]] 一个 ModuleRequest 记录 表示 ImportDeclarationModuleSpecifier 和导入属性的 ModuleRequest 记录。
[[ImportName]] 一个字符串或 namespace [[ModuleRequest]] 标识的模块导出所需绑定所使用的名称。值 namespace 表示导入请求针对目标模块的命名空间对象。
[[LocalName]] 一个字符串 在导入模块内部用于本地访问导入值的名称。
Note 1

Table 54给出了用于表示语法导入形式的 ImportEntry 记录字段示例:

Table 54 (Informative): 导入形式到 ImportEntry 记录的映射
导入语句形式 [[ModuleRequest]] [[ImportName]] [[LocalName]]
import v from "mod"; "mod" "default" "v"
import * as ns from "mod"; "mod" namespace "ns"
import {x} from "mod"; "mod" "x" "x"
import {x as v} from "mod"; "mod" "x" "v"
import "mod"; 不会创建 ImportEntry 记录

ExportEntry 记录是一个记录,用于摘要关于单个声明式导出的信息。每个 ExportEntry 记录具有在Table 55中定义的字段:

Table 55: ExportEntry 记录字段
字段名 值类型 含义
[[ExportName]] 一个字符串或 null 此模块用于导出该绑定的名称。
[[ModuleRequest]] 一个 ModuleRequest 记录或 null 表示 ExportDeclarationModuleSpecifier 和导入属性的 ModuleRequest 记录。如果 ExportDeclaration 没有 ModuleSpecifier,则为 null
[[ImportName]] 一个字符串、nullnamespaceall-but-default [[ModuleRequest]] 标识的模块导出所需绑定所使用的名称。如果 ExportDeclaration 没有 ModuleSpecifier,则为 nullnamespace 用于 export * as ns from "mod" 声明。all-but-default 用于 export * from "mod" 声明。
[[LocalName]] 一个字符串或 null 在导入模块内部用于本地访问导出值的名称。如果导出的值在模块内部无法本地访问,则为 null
Note 2

Table 56给出了用于表示语法导出形式的 ExportEntry 记录字段示例:

Table 56 (Informative): 导出形式到 ExportEntry 记录的映射
导出语句形式 [[ExportName]] [[ModuleRequest]] [[ImportName]] [[LocalName]]
export var v; "v" null null "v"
export default function f() {} "default" null null "f"
export default function () {} "default" null null "*default*"
export default 42; "default" null null "*default*"
export {x}; "x" null null "x"
export {v as x}; "x" null null "v"
export {x} from "mod"; "x" "mod" "x" null
export {v as x} from "mod"; "x" "mod" "v" null
export * from "mod"; null "mod" all-but-default null
export * as ns from "mod"; "ns" "mod" namespace null

以下定义指定源文本模块记录所需的具体方法和其他抽象操作

16.2.1.7.1 ParseModule ( sourceText, realm, hostDefined )

The abstract operation ParseModule takes arguments sourceText (ECMAScript 源文本), realm (一个 Realm 记录), and hostDefined (任意值) and returns 一个源文本模块记录或一个非空 SyntaxError 对象列表. 基于将 sourceText 解析为 Module 的结果创建一个源文本模块记录。 It performs the following steps when called:

  1. bodyParseText(sourceText, Module)。
  2. 如果 body 是错误列表,则返回 body
  3. requestedModulesbodyModuleRequests
  4. importEntriesbodyImportEntries
  5. importedBoundNamesImportedLocalNames(importEntries)。
  6. indirectExportEntries 为一个新的空列表。
  7. localExportEntries 为一个新的空列表。
  8. starExportEntries 为一个新的空列表。
  9. exportEntriesbodyExportEntries
  10. 对于 exportEntries 中的每个 ExportEntry 记录 ee,执行
    1. 如果 ee.[[ModuleRequest]]null,则
      1. 如果 importedBoundNames 不包含 ee.[[LocalName]],则
        1. ee 追加到 localExportEntries
      2. 否则,
        1. 注意:当导出最初从另一个模块导入的绑定或命名空间对象时,ExportEntry 记录会被重写为与该绑定或命名空间对象直接从原始模块重导出时所具有的形式相匹配,而不是先导入再导出。这允许通过 export * from 以相同名称导出同一绑定或命名空间两次所产生的冲突被忽略,而不是在源文本模块记录的 ResolveExport 具体方法的步骤9.e.iii中被视为歧义。
        2. ieimportEntries[[LocalName]]ee.[[LocalName]] 的元素。
        3. ExportEntry 记录 { [[ModuleRequest]]: ie.[[ModuleRequest]], [[ImportName]]: ie.[[ImportName]], [[LocalName]]: null, [[ExportName]]: ee.[[ExportName]] } 追加到 indirectExportEntries
    2. 否则如果 ee.[[ImportName]]all-but-default,则
      1. 断言:ee.[[ExportName]]null
      2. ee 追加到 starExportEntries
    3. 否则,
      1. ee 追加到 indirectExportEntries
  11. asyncbody Contains await
  12. 返回源文本模块记录 { [[Realm]]: realm, [[Environment]]: empty, [[Namespace]]: empty, [[CycleRoot]]: empty, [[HasTLA]]: async, [[AsyncEvaluationOrder]]: unset, [[TopLevelCapability]]: empty, [[AsyncParentModules]]: « », [[PendingAsyncDependencies]]: empty, [[Status]]: new, [[EvaluationError]]: empty, [[HostDefined]]: hostDefined, [[ECMAScriptCode]]: body, [[Context]]: empty, [[ImportMeta]]: empty, [[RequestedModules]]: requestedModules, [[LoadedModules]]: « », [[ImportEntries]]: importEntries, [[LocalExportEntries]]: localExportEntries, [[IndirectExportEntries]]: indirectExportEntries, [[StarExportEntries]]: starExportEntries, [[DFSAncestorIndex]]: empty }。
Note

实现可以在对该模块源文本求值 ParseModule 之前解析模块源文本并分析其 Early Error 条件。然而,任何错误的报告都必须推迟到本规范实际对该源文本执行 ParseModule 的时刻。

16.2.1.7.2 模块记录抽象方法的实现

以下是源文本模块记录的具体方法,用于实现Table 39中定义的对应模块记录抽象方法。

16.2.1.7.2.1 GetExportedNames ( [ exportStarSet ] )

The GetExportedNames concrete method of a Source Text Module Record module takes optional argument exportStarSet (源文本模块记录的列表) and returns 字符串列表. It performs the following steps when called:

  1. 断言:module.[[Status]] 不是 new
  2. 如果 exportStarSet 未提供,则将 exportStarSet 设为一个新的空列表。
  3. 如果 exportStarSet 包含 module,则
    1. 断言:我们已经到达 export * 循环的起点。
    2. 返回一个新的空列表。
  4. module 追加到 exportStarSet
  5. exportedNames 为一个新的空列表。
  6. 对于 module.[[LocalExportEntries]] 中的每个 ExportEntry 记录 e,执行
    1. 断言:module 为此导出提供直接绑定。
    2. 断言:e.[[ExportName]] 不是 null
    3. e.[[ExportName]] 追加到 exportedNames
  7. 对于 module.[[IndirectExportEntries]] 中的每个 ExportEntry 记录 e,执行
    1. 断言:module 为此导出导入一个特定绑定。
    2. 断言:e.[[ExportName]] 不是 null
    3. e.[[ExportName]] 追加到 exportedNames
  8. 对于 module.[[StarExportEntries]] 中的每个 ExportEntry 记录 e,执行
    1. 断言:e.[[ModuleRequest]] 不是 null
    2. requestedModuleGetImportedModule(module, e.[[ModuleRequest]])。
    3. starNamesrequestedModule.GetExportedNames(exportStarSet)。
    4. 对于 starNames 中的每个元素 n,执行
      1. 如果 n 不是 "default",则
        1. 如果 exportedNames 不包含 n,则
          1. n 追加到 exportedNames
  9. 返回 exportedNames
Note

GetExportedNames 不会过滤掉具有歧义星号导出绑定的名称,也不会为这些名称抛出异常。

16.2.1.7.2.2 ResolveExport ( exportName [ , resolveSet ] )

The ResolveExport concrete method of a Source Text Module Record module takes argument exportName (一个字符串) and optional argument resolveSet (具有字段 [[Module]](一个模块记录)和 [[ExportName]](一个字符串)的记录列表) and returns 一个 ResolvedBinding 记录nullambiguous.

ResolveExport 尝试将导入的绑定解析到实际的定义模块和本地绑定名称。定义模块可以是调用此方法的模块记录所表示的模块,也可以是该模块导入的其他模块。参数 resolveSet 用于检测未解析的循环导入/导出路径。如果到达一个由特定模块记录exportName 组成的对,而该对已经在 resolveSet 中,则遇到了导入循环。在递归调用 ResolveExport 之前,会将由 moduleexportName 组成的对添加到 resolveSet

如果找到定义模块,则返回 ResolvedBinding 记录 { [[Module]], [[BindingName]] }。该记录标识最初请求的导出的已解析绑定,除非这是一个没有本地绑定的命名空间导出。在这种情况下,[[BindingName]] 将被设置为 namespace。如果未找到定义或请求被发现是循环的,则返回 null。如果请求被发现有歧义,则返回 ambiguous

It performs the following steps when called:

  1. 断言:module.[[Status]] 不是 new
  2. 如果 resolveSet 未提供,则将 resolveSet 设为一个新的空列表。
  3. 对于 resolveSet 中的每个记录 { [[Module]], [[ExportName]] } r,执行
    1. 如果 moduler.[[Module]] 是同一个模块记录,且 exportNamer.[[ExportName]],则
      1. 断言:这是一个循环导入请求。
      2. 返回 null
  4. 将记录 { [[Module]]: module, [[ExportName]]: exportName } 追加到 resolveSet
  5. 对于 module.[[LocalExportEntries]] 中的每个 ExportEntry 记录 e,执行
    1. 如果 e.[[ExportName]]exportName,则
      1. 断言:module 为此导出提供直接绑定。
      2. 返回 ResolvedBinding 记录 { [[Module]]: module, [[BindingName]]: e.[[LocalName]] }。
  6. 对于 module.[[IndirectExportEntries]] 中的每个 ExportEntry 记录 e,执行
    1. 如果 e.[[ExportName]]exportName,则
      1. 断言:e.[[ModuleRequest]] 不是 null
      2. importedModuleGetImportedModule(module, e.[[ModuleRequest]])。
      3. 如果 e.[[ImportName]]namespace,则
        1. 断言:module 不为此导出提供直接绑定。
        2. 返回 ResolvedBinding 记录 { [[Module]]: importedModule, [[BindingName]]: namespace }。
      4. 断言:module 为此导出导入一个特定绑定。
      5. 断言:e.[[ImportName]] 是一个字符串。
      6. 返回 importedModule.ResolveExport(e.[[ImportName]], resolveSet)。
  7. 如果 exportName"default",则
    1. 断言:此模块未显式定义 default 导出。
    2. 返回 null
    3. 注意:default 导出不能由 export * from "mod" 声明提供。
  8. starResolutionnull
  9. 对于 module.[[StarExportEntries]] 中的每个 ExportEntry 记录 e,执行
    1. 断言:e.[[ModuleRequest]] 不是 null
    2. importedModuleGetImportedModule(module, e.[[ModuleRequest]])。
    3. resolutionimportedModule.ResolveExport(exportName, resolveSet)。
    4. 如果 resolutionambiguous,返回 ambiguous
    5. 如果 resolution 不是 null,则
      1. 断言:resolution 是一个 ResolvedBinding 记录
      2. 如果 starResolutionnull,则
        1. starResolution 设为 resolution
      3. 否则,
        1. 断言:存在多个包含所请求名称的 * 导出。
        2. 如果 resolution.[[Module]]starResolution.[[Module]] 不是同一个模块记录,返回 ambiguous
        3. 如果 resolution.[[BindingName]] 不是 starResolution.[[BindingName]],返回 ambiguous
  10. 返回 starResolution

16.2.1.7.3 循环模块记录抽象方法的实现

以下是源文本模块记录的具体方法,用于实现Table 41中定义的对应循环模块记录抽象方法。

16.2.1.7.3.1 InitializeEnvironment ( )

The InitializeEnvironment concrete method of a Source Text Module Record module takes no arguments and returns 返回包含 unused正常完成或 throw completion. It performs the following steps when called:

  1. 对于 module.[[IndirectExportEntries]] 中的每个 ExportEntry 记录 e,执行
    1. 断言:e.[[ExportName]] 不是 null
    2. resolutionmodule.ResolveExport(e.[[ExportName]])。
    3. 如果 resolutionnullambiguous,则抛出一个 SyntaxError 异常。
    4. 断言:resolution 是一个 ResolvedBinding 记录
  2. 断言:来自 module 的所有命名导出都是可解析的。
  3. realmmodule.[[Realm]]
  4. 断言:realm 不是 undefined
  5. envNewModuleEnvironment(realm.[[GlobalEnv]])。
  6. module.[[Environment]] 设为 env
  7. 对于 module.[[ImportEntries]] 中的每个 ImportEntry 记录 in,执行
    1. importedModuleGetImportedModule(module, in.[[ModuleRequest]])。
    2. 如果 in.[[ImportName]]namespace,则
      1. namespaceGetModuleNamespace(importedModule)。
      2. 执行 ! env.CreateImmutableBinding(in.[[LocalName]], true)。
      3. 执行 ! env.InitializeBinding(in.[[LocalName]], namespace)。
    3. 否则,
      1. 断言:in.[[ImportName]] 是一个字符串。
      2. resolutionimportedModule.ResolveExport(in.[[ImportName]])。
      3. 如果 resolutionnullambiguous,则抛出一个 SyntaxError 异常。
      4. 如果 resolution.[[BindingName]]namespace,则
        1. namespaceGetModuleNamespace(resolution.[[Module]])。
        2. 执行 ! env.CreateImmutableBinding(in.[[LocalName]], true)。
        3. 执行 ! env.InitializeBinding(in.[[LocalName]], namespace)。
      5. 否则,
        1. 执行 CreateImportBinding(env, in.[[LocalName]], resolution.[[Module]], resolution.[[BindingName]])。
  8. moduleContext 为一个新的 ECMAScript 代码执行上下文
  9. moduleContext 的 Function 设为 null
  10. 断言:module.[[Realm]] 不是 undefined
  11. moduleContextRealm 设为 module.[[Realm]]
  12. moduleContext 的 ScriptOrModule 设为 module
  13. moduleContext 的 VariableEnvironment 设为 module.[[Environment]]
  14. moduleContext 的 LexicalEnvironment 设为 module.[[Environment]]
  15. moduleContext 的 PrivateEnvironment 设为 null
  16. module.[[Context]] 设为 moduleContext
  17. moduleContext 压入执行上下文栈moduleContext 现在是运行中的执行上下文
  18. codemodule.[[ECMAScriptCode]]
  19. varDeclarationscodeVarScopedDeclarations
  20. declaredVarNames 为一个新的空列表。
  21. 对于 varDeclarations 中的每个元素 d,执行
    1. 对于 dBoundNames 中的每个元素 dn,执行
      1. 如果 declaredVarNames 不包含 dn,则
        1. 执行 ! env.CreateMutableBinding(dn, false)。
        2. 执行 ! env.InitializeBinding(dn, undefined)。
        3. dn 追加到 declaredVarNames
  22. lexDeclarationscodeLexicallyScopedDeclarations
  23. privateEnvnull
  24. 对于 lexDeclarations 中的每个元素 d,执行
    1. 对于 dBoundNames 中的每个元素 dn,执行
      1. 如果 dIsConstantDeclarationtrue,则
        1. 执行 ! env.CreateImmutableBinding(dn, true)。
      2. 否则,
        1. 执行 ! env.CreateMutableBinding(dn, false)。
      3. 如果 dFunctionDeclarationGeneratorDeclarationAsyncFunctionDeclarationAsyncGeneratorDeclaration,则
        1. fo 为以 envprivateEnv 为参数对 d 执行 InstantiateFunctionObject 的结果。
        2. 执行 ! env.InitializeBinding(dn, fo)。
  25. 执行上下文栈中移除 moduleContext
  26. 返回 unused

16.2.1.7.3.2 ExecuteModule ( [ capability ] )

The ExecuteModule concrete method of a Source Text Module Record module takes optional argument capability (一个 PromiseCapability 记录) and returns 返回包含 unused正常完成或 throw completion. It performs the following steps when called:

  1. 断言:module 已被链接,且其模块环境中的声明已被实例化。
  2. moduleContextmodule.[[Context]]
  3. 如果 module.[[HasTLA]]false,则
    1. 断言:capability 未提供。
    2. 挂起运行中的执行上下文
    3. moduleContext 压入执行上下文栈moduleContext 现在是运行中的执行上下文
    4. resultCompletion(对 module.[[ECMAScriptCode]] 求值)。
    5. 挂起 moduleContext 并将其从执行上下文栈中移除。
    6. 恢复现在位于执行上下文栈顶部的上下文作为运行中的执行上下文
    7. 如果 result 是异常完成,则
      1. 返回 ? result
  4. 否则,
    1. 断言:capability 是一个 PromiseCapability 记录。
    2. 执行 AsyncBlockStart(capability, module.[[ECMAScriptCode]], moduleContext)。
  5. 返回 unused

16.2.1.8 合成模块记录

合成模块记录用于表示由规范定义的模块的信息。其导出名称在创建时静态定义,而其对应值可以随时间通过 SetSyntheticModuleExport 改变。它没有导入或依赖。

Note
合成模块记录可用于定义各种模块类型:例如 JSON 模块或 CSS 模块。

除了在Table 38中定义的字段外,合成模块记录还具有在Table 57中列出的附加字段。

Table 57: 合成模块记录的附加字段
字段名 值类型 含义
[[ExportNames]] 字符串列表 该模块的导出名称。此列表不包含重复项。
[[EvaluationSteps]] 一个抽象闭包 在模块求值时执行的初始化逻辑,以该合成模块记录作为其唯一参数。它不得修改 [[ExportNames]]。它可以返回一个异常完成。

16.2.1.8.1 CreateDefaultExportSyntheticModule ( defaultExport )

The abstract operation CreateDefaultExportSyntheticModule takes argument defaultExport (一个 ECMAScript 语言值) and returns 一个合成模块记录. 创建一个默认导出为 defaultExport合成模块记录。 It performs the following steps when called:

  1. realm 为当前 Realm 记录。
  2. setDefaultExport 为一个新的抽象闭包,其参数为 (module),捕获 defaultExport,并在调用时执行以下步骤:
    1. 执行 SetSyntheticModuleExport(module, "default", defaultExport)。
    2. 返回 NormalCompletion(unused)。
  3. 返回合成模块记录 { [[Realm]]: realm, [[Environment]]: empty, [[Namespace]]: empty, [[HostDefined]]: undefined, [[ExportNames]]: « "default" », [[EvaluationSteps]]: setDefaultExport }。

16.2.1.8.2 ParseJSONModule ( source )

The abstract operation ParseJSONModule takes argument source (一个字符串) and returns 返回包含合成模块记录正常完成,或 throw completion. It performs the following steps when called:

  1. parseResult 为 ? ParseJSON(source)。
  2. 返回 CreateDefaultExportSyntheticModule(parseResult.[[Value]])。

16.2.1.8.3 SetSyntheticModuleExport ( module, exportName, exportValue )

The abstract operation SetSyntheticModuleExport takes arguments module (一个合成模块记录), exportName (一个字符串), and exportValue (一个 ECMAScript 语言值) and returns unused. 可用于设置或更改合成模块记录现有导出的导出值。 It performs the following steps when called:

  1. 断言:module.[[ExportNames]] 包含 exportName
  2. envRecmodule.[[Environment]]
  3. 断言:envRec 不是 empty
  4. 执行 ! envRec.SetMutableBinding(exportName, exportValue, true)。
  5. 返回 unused

16.2.1.8.4 模块记录抽象方法的实现

以下是合成模块记录的具体方法,用于实现Table 39中定义的对应模块记录抽象方法。

16.2.1.8.4.1 LoadRequestedModules ( [ hostDefined ] )

The LoadRequestedModules concrete method of a Synthetic Module Record module takes optional argument hostDefined (任意值) and returns 一个 Promise. It performs the following steps when called:

  1. 注意:LoadRequestedModules 的此实现不使用 hostDefined
  2. 返回 ! PromiseResolve(%Promise%, undefined)。
Note
合成模块记录没有依赖。

16.2.1.8.4.2 GetExportedNames ( [ exportStarSet ] )

The GetExportedNames concrete method of a Synthetic Module Record module takes optional argument exportStarSet (源文本模块记录的列表) and returns 字符串列表. It performs the following steps when called:

  1. 注意:GetExportedNames 的此实现不使用 exportStarSet
  2. 返回 module.[[ExportNames]]

16.2.1.8.4.3 ResolveExport ( exportName [ , resolveSet ] )

The ResolveExport concrete method of a Synthetic Module Record module takes argument exportName (一个字符串) and optional argument resolveSet (具有字段 [[Module]](一个模块记录)和 [[ExportName]](一个字符串)的记录列表) and returns 一个 ResolvedBinding 记录nullambiguous. It performs the following steps when called:

  1. 注意:ResolveExport 的此实现不使用 resolveSet
  2. 如果 module.[[ExportNames]] 不包含 exportName,返回 null
  3. 返回 ResolvedBinding 记录 { [[Module]]: module, [[BindingName]]: exportName }。

16.2.1.8.4.4 Link ( )

The Link concrete method of a Synthetic Module Record module takes no arguments and returns 包含 unused正常完成. It performs the following steps when called:

  1. realmmodule.[[Realm]]
  2. envNewModuleEnvironment(realm.[[GlobalEnv]])。
  3. module.[[Environment]] 设为 env
  4. 对于 module.[[ExportNames]] 中的每个字符串 exportName,执行
    1. 执行 ! env.CreateMutableBinding(exportName, false)。
    2. 执行 ! env.InitializeBinding(exportName, undefined)。
  5. 返回 NormalCompletion(unused)。

16.2.1.8.4.5 Evaluate ( )

The Evaluate concrete method of a Synthetic Module Record module takes no arguments and returns 一个 Promise. It performs the following steps when called:

  1. moduleContext 为一个新的 ECMAScript 代码执行上下文
  2. moduleContext 的 Function 设为 null
  3. moduleContextRealm 设为 module.[[Realm]]
  4. moduleContext 的 ScriptOrModule 设为 module
  5. moduleContext 的 VariableEnvironment 设为 module.[[Environment]]
  6. moduleContext 的 LexicalEnvironment 设为 module.[[Environment]]
  7. 挂起运行中的执行上下文
  8. moduleContext 压入执行上下文栈moduleContext 现在是运行中的执行上下文
  9. stepsmodule.[[EvaluationSteps]]
  10. resultCompletion(steps(module))。
  11. 挂起 moduleContext 并将其从执行上下文栈中移除。
  12. 恢复现在位于执行上下文栈顶部的上下文作为运行中的执行上下文
  13. pc 为 ! NewPromiseCapability(%Promise%)。
  14. IfAbruptRejectPromise(result, pc)。
  15. 执行 ! Call(pc.[[Resolve]], undefined, « undefined »)。
  16. 返回 pc.[[Promise]]

16.2.1.9 GetImportedModule ( referrer, request )

The abstract operation GetImportedModule takes arguments referrer (一个循环模块记录) and request (一个 ModuleRequest 记录) and returns 一个模块记录. It performs the following steps when called:

  1. records 为一个列表,由 referrer.[[LoadedModules]] 中满足 ModuleRequestsEqual(r, request) 为 true 的每个 LoadedModuleRequest 记录 r 组成。
  2. 断言:records 恰好有一个元素,因为在调用此抽象操作之前,LoadRequestedModules 已在 referrer 上成功完成。
  3. recordrecords 的唯一元素。
  4. 返回 record.[[Module]]

16.2.1.10 HostLoadImportedModule ( referrer, moduleRequest, hostDefined, payload )

The host-defined abstract operation HostLoadImportedModule takes arguments referrer (一个 Script 记录、一个循环模块记录或一个 Realm 记录), moduleRequest (一个 ModuleRequest 记录), hostDefined (任意值), and payload (一个 GraphLoadingState 记录或一个 PromiseCapability 记录) and returns unused.

Note 1

在 Web 浏览器宿主中,referrer 可以是 Realm 记录的一个示例是:如果用户点击由以下代码给出的控件

<button type="button" onclick="import('./foo.mjs')">点击我</button>

那么在import()表达式运行时,将不存在活动的脚本或模块。更一般地,这可能发生在宿主将 ScriptOrModule 组件为 null执行上下文压入执行上下文栈的任何情况中。

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

实际执行的过程由宿主定义,但通常包括执行加载适当模块记录所需的任何 I/O 操作。多个不同的 (referrer, moduleRequest.[[Specifier]], moduleRequest.[[Attributes]]) 三元组可以映射到同一个模块记录实例。实际的映射语义由宿主定义,但通常会在映射过程中对 specifier 应用规范化过程。典型的规范化过程会包括诸如展开相对路径和缩写路径说明符之类的操作。

Note 2

上述文本要求宿主在使用 type: "json" 导入 JSON 模块时支持 JSON 模块(且 HostLoadImportedModule 正常完成),但并不禁止宿主在不使用 type: "json" 导入时支持 JSON 模块。

16.2.1.11 FinishLoadingImportedModule ( referrer, moduleRequest, payload, result )

The abstract operation FinishLoadingImportedModule takes arguments referrer (一个 Script 记录、一个循环模块记录或一个 Realm 记录), moduleRequest (一个 ModuleRequest 记录), payload (一个 GraphLoadingState 记录或一个 PromiseCapability 记录), and result (包含模块记录正常完成或 throw completion) and returns unused. It performs the following steps when called:

  1. 如果 result正常完成,则
    1. 如果 referrer.[[LoadedModules]] 包含一个 LoadedModuleRequest 记录 record,使得 ModuleRequestsEqual(record, moduleRequest) 为 true,则
      1. 断言:record.[[Module]]result.[[Value]] 是同一个模块记录
    2. 否则,
      1. 将 LoadedModuleRequest 记录 { [[Specifier]]: moduleRequest.[[Specifier]], [[Attributes]]: moduleRequest.[[Attributes]], [[Module]]: result.[[Value]] } 追加到 referrer.[[LoadedModules]]
  2. 如果 payloadGraphLoadingState 记录,则
    1. 执行 ContinueModuleLoading(payload, result)。
  3. 否则,
    1. 执行 ContinueDynamicImport(payload, result)。
  4. 返回 unused

16.2.1.12 AllImportAttributesSupported ( attributes )

The abstract operation AllImportAttributesSupported takes argument attributes (ImportAttribute 记录的列表) and returns 一个布尔值. It performs the following steps when called:

  1. supportedHostGetSupportedImportAttributes()。
  2. 对于 attributes 中的每个 ImportAttribute 记录 attribute,执行
    1. 如果 supported 不包含 attribute.[[Key]],返回 false
  3. 返回 true

16.2.1.12.1 HostGetSupportedImportAttributes ( )

The host-defined abstract operation HostGetSupportedImportAttributes takes no arguments and returns 字符串列表. 允许宿主环境指定它们支持哪些导入属性。只有具有受支持键的属性才会提供给宿主

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

  • 它必须返回一个字符串列表,每个字符串表示一个受支持的属性。
  • 每次调用此操作时,它都必须返回内容相同且顺序相同的同一个列表。

HostGetSupportedImportAttributes 的默认实现是返回一个新的空列表。

Note
要求宿主指定其支持的导入属性,而不是将所有属性都传递给宿主再让宿主选择想处理哪些属性,其目的是确保不同宿主以一致的方式处理不受支持的属性。

16.2.1.13 GetModuleNamespace ( module )

The abstract operation GetModuleNamespace takes argument module (模块记录的某个具体子类实例) and returns 一个模块命名空间对象. 检索表示 module 导出的模块命名空间对象,在第一次请求时惰性创建它,并将其存储在 module.[[Namespace]] 中以便将来检索。 It performs the following steps when called:

  1. 断言:如果 module循环模块记录,则 module.[[Status]] 不是 newunlinked
  2. namespacemodule.[[Namespace]]
  3. 如果 namespaceempty,则
    1. exportedNamesmodule.GetExportedNames()。
    2. unambiguousNames 为一个新的空列表。
    3. 对于 exportedNames 中的每个元素 name,执行
      1. resolutionmodule.ResolveExport(name)。
      2. 如果 resolutionResolvedBinding 记录,则将 name 追加到 unambiguousNames
    4. namespace 设为 ModuleNamespaceCreate(module, unambiguousNames)。
  4. 返回 namespace
Note

GetModuleNamespace 从不抛出异常。相反,无法解析的名称此时会被简单地从命名空间中排除。它们稍后会导致真正的链接错误,除非它们全都是没有在任何地方被显式请求的歧义星号导出。

16.2.1.14 Runtime Semantics: 求值

Module : [empty]
  1. 返回 undefined
ModuleBody : ModuleItemList
  1. resultCompletion(对 ModuleItemList 求值)。
  2. 如果 result正常完成result.[[Value]]empty,则
    1. 返回 undefined
  3. 返回 ? result
ModuleItemList : ModuleItemList ModuleItem
  1. sl 为 ? 对 ModuleItemList 求值。
  2. sCompletion(对 ModuleItem 求值)。
  3. 返回 ? UpdateEmpty(s, sl)。
Note

ModuleItemList 的值是 ModuleItemList 中最后一个产生值的项的值。

ModuleItem : ImportDeclaration
  1. 返回 empty

16.2.2 导入

语法

ImportDeclaration : import ImportClause FromClause WithClauseopt ; import ModuleSpecifier WithClauseopt ; ImportClause : ImportedDefaultBinding NameSpaceImport NamedImports ImportedDefaultBinding , NameSpaceImport ImportedDefaultBinding , NamedImports ImportedDefaultBinding : ImportedBinding NameSpaceImport : * as ImportedBinding NamedImports : { } { ImportsList } { ImportsList , } FromClause : from ModuleSpecifier ImportsList : ImportSpecifier ImportsList , ImportSpecifier ImportSpecifier : ImportedBinding ModuleExportName as ImportedBinding ModuleSpecifier : StringLiteral ImportedBinding : BindingIdentifier[~Yield, +Await] WithClause : with { } with { WithEntries ,opt } WithEntries : AttributeKey : StringLiteral AttributeKey : StringLiteral , WithEntries AttributeKey : IdentifierName StringLiteral

16.2.2.1 Static Semantics: 早期错误

ModuleItem : ImportDeclaration WithClause : with { WithEntries ,opt }

16.2.2.2 Static Semantics: ImportEntries

The syntax-directed operation ImportEntries takes no arguments and returns ImportEntry 记录的列表. It is defined piecewise over the following productions:

Module : [empty]
  1. 返回一个新的空列表。
ModuleItemList : ModuleItemList ModuleItem
  1. entries1ModuleItemListImportEntries
  2. entries2ModuleItemImportEntries
  3. 返回 entries1entries2 的列表拼接结果。
ModuleItem : ExportDeclaration StatementListItem
  1. 返回一个新的空列表。
ImportDeclaration : import ImportClause FromClause WithClauseopt ;
  1. moduleImportDeclarationModuleRequests 的唯一元素。
  2. 返回以 module 为参数的 ImportClauseImportEntriesForModule
ImportDeclaration : import ModuleSpecifier WithClauseopt ;
  1. 返回一个新的空列表。

16.2.2.3 Static Semantics: ImportEntriesForModule

The syntax-directed operation ImportEntriesForModule takes argument module (ModuleRequest 记录) and returns ImportEntry 记录的列表. It is defined piecewise over the following productions:

ImportClause : ImportedDefaultBinding , NameSpaceImport
  1. entries1 为以 module 为参数的 ImportedDefaultBindingImportEntriesForModule
  2. entries2 为以 module 为参数的 NameSpaceImportImportEntriesForModule
  3. 返回 entries1entries2 的列表拼接结果。
ImportClause : ImportedDefaultBinding , NamedImports
  1. entries1 为以 module 为参数的 ImportedDefaultBindingImportEntriesForModule
  2. entries2 为以 module 为参数的 NamedImportsImportEntriesForModule
  3. 返回 entries1entries2 的列表拼接结果。
ImportedDefaultBinding : ImportedBinding
  1. localNameImportedBindingBoundNames 的唯一元素。
  2. defaultEntryImportEntry 记录 { [[ModuleRequest]]: module, [[ImportName]]: "default", [[LocalName]]: localName }。
  3. 返回 « defaultEntry »。
NameSpaceImport : * as ImportedBinding
  1. localNameImportedBindingStringValue
  2. entryImportEntry 记录 { [[ModuleRequest]]: module, [[ImportName]]: namespace, [[LocalName]]: localName }。
  3. 返回 « entry »。
NamedImports : { }
  1. 返回一个新的空列表。
ImportsList : ImportsList , ImportSpecifier
  1. specs1 为以 module 为参数的 ImportsListImportEntriesForModule
  2. specs2 为以 module 为参数的 ImportSpecifierImportEntriesForModule
  3. 返回 specs1specs2 的列表拼接结果。
ImportSpecifier : ImportedBinding
  1. localNameImportedBindingBoundNames 的唯一元素。
  2. entryImportEntry 记录 { [[ModuleRequest]]: module, [[ImportName]]: localName, [[LocalName]]: localName }。
  3. 返回 « entry »。
ImportSpecifier : ModuleExportName as ImportedBinding
  1. importNameModuleExportNameStringValue
  2. localNameImportedBindingStringValue
  3. entryImportEntry 记录 { [[ModuleRequest]]: module, [[ImportName]]: importName, [[LocalName]]: localName }。
  4. 返回 « entry »。

16.2.2.4 Static Semantics: WithClauseToAttributes

The syntax-directed operation WithClauseToAttributes takes no arguments and returns ImportAttribute 记录的列表. It is defined piecewise over the following productions:

WithClause : with { }
  1. 返回一个新的空列表。
WithClause : with { WithEntries ,opt }
  1. attributesWithEntriesWithClauseToAttributes
  2. 按照其 [[Key]] 字段的字典序对 attributes 排序,并将每个此类字段的值视为 UTF-16 代码单元值序列。注:这种排序唯一可观察之处在于,宿主被禁止基于属性枚举的顺序改变行为。
  3. 返回 attributes
WithEntries : AttributeKey : StringLiteral
  1. keyAttributeKeyPropName
  2. entry 为 ImportAttribute 记录 { [[Key]]: key, [[Value]]: StringLiteralSV }。
  3. 返回 « entry »。
WithEntries : AttributeKey : StringLiteral , WithEntries
  1. keyAttributeKeyPropName
  2. entry 为 ImportAttribute 记录 { [[Key]]: key, [[Value]]: StringLiteralSV }。
  3. restWithEntriesWithClauseToAttributes
  4. 返回 « entry » 和 rest 的列表拼接结果。

16.2.3 导出

语法

ExportDeclaration : export ExportFromClause FromClause WithClauseopt ; export NamedExports ; export VariableStatement[~Yield, +Await] export Declaration[~Yield, +Await] export default HoistableDeclaration[~Yield, +Await, +Default] export default ClassDeclaration[~Yield, +Await, +Default] export default [lookahead ∉ { function, async [no LineTerminator here] function, class }] AssignmentExpression[+In, ~Yield, +Await] ; ExportFromClause : * * as ModuleExportName NamedExports NamedExports : { } { ExportsList } { ExportsList , } ExportsList : ExportSpecifier ExportsList , ExportSpecifier ExportSpecifier : ModuleExportName ModuleExportName as ModuleExportName

16.2.3.1 Static Semantics: 早期错误

ExportDeclaration : export NamedExports ; Note

上述规则意味着 NamedExports 的每个 ReferencedBindings 都被视为 IdentifierReference

16.2.3.2 Static Semantics: ExportedBindings

The syntax-directed operation ExportedBindings takes no arguments and returns 字符串列表.

Note

ExportedBindings 是与 ModuleExportedNames 显式关联的本地绑定名称。

It is defined piecewise over the following productions:

ModuleItemList : ModuleItemList ModuleItem
  1. names1ModuleItemListExportedBindings
  2. names2ModuleItemExportedBindings
  3. 返回 names1names2 的列表拼接结果。
ModuleItem : ImportDeclaration StatementListItem
  1. 返回一个新的空列表。
ExportDeclaration : export ExportFromClause FromClause WithClauseopt ;
  1. 返回一个新的空列表。
ExportDeclaration : export NamedExports ;
  1. 返回 NamedExportsExportedBindings
ExportDeclaration : export VariableStatement
  1. 返回 VariableStatementBoundNames
ExportDeclaration : export Declaration
  1. 返回 DeclarationBoundNames
ExportDeclaration : export default HoistableDeclaration export default ClassDeclaration export default AssignmentExpression ;
  1. 返回此 ExportDeclarationBoundNames
NamedExports : { }
  1. 返回一个新的空列表。
ExportsList : ExportsList , ExportSpecifier
  1. names1ExportsListExportedBindings
  2. names2ExportSpecifierExportedBindings
  3. 返回 names1names2 的列表拼接结果。
ExportSpecifier : ModuleExportName
  1. 返回一个列表,其唯一元素为 ModuleExportNameStringValue
ExportSpecifier : ModuleExportName as ModuleExportName
  1. 返回一个列表,其唯一元素为第一个 ModuleExportNameStringValue

16.2.3.3 Static Semantics: ExportedNames

The syntax-directed operation ExportedNames takes no arguments and returns 字符串列表.

Note

ExportedNames 是 Module 显式映射到其本地名称绑定之一的外部可见名称。

It is defined piecewise over the following productions:

ModuleItemList : ModuleItemList ModuleItem
  1. names1ModuleItemListExportedNames
  2. names2ModuleItemExportedNames
  3. 返回 names1names2 的列表拼接结果。
ModuleItem : ExportDeclaration
  1. 返回 ExportDeclarationExportedNames
ModuleItem : ImportDeclaration StatementListItem
  1. 返回一个新的空列表。
ExportDeclaration : export ExportFromClause FromClause WithClauseopt ;
  1. 返回 ExportFromClauseExportedNames
ExportFromClause : *
  1. 返回一个新的空列表。
ExportFromClause : * as ModuleExportName
  1. 返回一个列表,其唯一元素为 ModuleExportNameStringValue
ExportFromClause : NamedExports
  1. 返回 NamedExportsExportedNames
ExportDeclaration : export VariableStatement
  1. 返回 VariableStatementBoundNames
ExportDeclaration : export Declaration
  1. 返回 DeclarationBoundNames
ExportDeclaration : export default HoistableDeclaration export default ClassDeclaration export default AssignmentExpression ;
  1. 返回 « "default" »。
NamedExports : { }
  1. 返回一个新的空列表。
ExportsList : ExportsList , ExportSpecifier
  1. names1ExportsListExportedNames
  2. names2ExportSpecifierExportedNames
  3. 返回 names1names2 的列表拼接结果。
ExportSpecifier : ModuleExportName
  1. 返回一个列表,其唯一元素为 ModuleExportNameStringValue
ExportSpecifier : ModuleExportName as ModuleExportName
  1. 返回一个列表,其唯一元素为第二个 ModuleExportNameStringValue

16.2.3.4 Static Semantics: ExportEntries

The syntax-directed operation ExportEntries takes no arguments and returns ExportEntry 记录的列表. It is defined piecewise over the following productions:

Module : [empty]
  1. 返回一个新的空列表。
ModuleItemList : ModuleItemList ModuleItem
  1. entries1ModuleItemListExportEntries
  2. entries2ModuleItemExportEntries
  3. 返回 entries1entries2 的列表拼接结果。
ModuleItem : ImportDeclaration StatementListItem
  1. 返回一个新的空列表。
ExportDeclaration : export ExportFromClause FromClause WithClauseopt ;
  1. moduleExportDeclarationModuleRequests 的唯一元素。
  2. 返回以 module 为参数的 ExportFromClauseExportEntriesForModule
ExportDeclaration : export NamedExports ;
  1. 返回以 null 为参数的 NamedExportsExportEntriesForModule
ExportDeclaration : export VariableStatement
  1. entries 为一个新的空列表。
  2. namesVariableStatementBoundNames
  3. names 的每个元素 name,执行
    1. ExportEntry 记录 { [[ModuleRequest]]: null, [[ImportName]]: null, [[LocalName]]: name, [[ExportName]]: name } 追加到 entries
  4. 返回 entries
ExportDeclaration : export Declaration
  1. entries 为一个新的空列表。
  2. namesDeclarationBoundNames
  3. names 的每个元素 name,执行
    1. ExportEntry 记录 { [[ModuleRequest]]: null, [[ImportName]]: null, [[LocalName]]: name, [[ExportName]]: name } 追加到 entries
  4. 返回 entries
ExportDeclaration : export default HoistableDeclaration
  1. namesHoistableDeclarationBoundNames
  2. localNamenames 的唯一元素。
  3. 返回一个列表,其唯一元素为新的 ExportEntry 记录 { [[ModuleRequest]]: null, [[ImportName]]: null, [[LocalName]]: localName, [[ExportName]]: "default" }。
ExportDeclaration : export default ClassDeclaration
  1. namesClassDeclarationBoundNames
  2. localNamenames 的唯一元素。
  3. 返回一个列表,其唯一元素为新的 ExportEntry 记录 { [[ModuleRequest]]: null, [[ImportName]]: null, [[LocalName]]: localName, [[ExportName]]: "default" }。
ExportDeclaration : export default AssignmentExpression ;
  1. entryExportEntry 记录 { [[ModuleRequest]]: null, [[ImportName]]: null, [[LocalName]]: "*default*", [[ExportName]]: "default" }。
  2. 返回 « entry »。
Note

"*default*" 在本规范中用作匿名默认导出值的合成名称。更多细节见此注释

16.2.3.5 Static Semantics: ExportEntriesForModule

The syntax-directed operation ExportEntriesForModule takes argument module (ModuleRequest 记录或 null) and returns ExportEntry 记录的列表. It is defined piecewise over the following productions:

ExportFromClause : *
  1. entryExportEntry 记录 { [[ModuleRequest]]: module, [[ImportName]]: all-but-default, [[LocalName]]: null, [[ExportName]]: null }。
  2. 返回 « entry »。
ExportFromClause : * as ModuleExportName
  1. exportNameModuleExportNameStringValue
  2. entryExportEntry 记录 { [[ModuleRequest]]: module, [[ImportName]]: namespace, [[LocalName]]: null, [[ExportName]]: exportName }。
  3. 返回 « entry »。
NamedExports : { }
  1. 返回一个新的空列表。
ExportsList : ExportsList , ExportSpecifier
  1. specs1 为以 module 为参数的 ExportsListExportEntriesForModule
  2. specs2 为以 module 为参数的 ExportSpecifierExportEntriesForModule
  3. 返回 specs1specs2 的列表拼接结果。
ExportSpecifier : ModuleExportName
  1. sourceNameModuleExportNameStringValue
  2. 如果 modulenull,则
    1. localNamesourceName
    2. importNamenull
  3. 否则,
    1. localNamenull
    2. importNamesourceName
  4. 返回一个列表,其唯一元素为新的 ExportEntry 记录 { [[ModuleRequest]]: module, [[ImportName]]: importName, [[LocalName]]: localName, [[ExportName]]: sourceName }。
ExportSpecifier : ModuleExportName as ModuleExportName
  1. sourceName 为第一个 ModuleExportNameStringValue
  2. exportName 为第二个 ModuleExportNameStringValue
  3. 如果 modulenull,则
    1. localNamesourceName
    2. importNamenull
  4. 否则,
    1. localNamenull
    2. importNamesourceName
  5. 返回一个列表,其唯一元素为新的 ExportEntry 记录 { [[ModuleRequest]]: module, [[ImportName]]: importName, [[LocalName]]: localName, [[ExportName]]: exportName }。

16.2.3.6 Static Semantics: ReferencedBindings

The syntax-directed operation ReferencedBindings takes no arguments and returns 解析节点列表. It is defined piecewise over the following productions:

NamedExports : { }
  1. 返回一个新的空列表。
ExportsList : ExportsList , ExportSpecifier
  1. names1ExportsListReferencedBindings
  2. names2ExportSpecifierReferencedBindings
  3. 返回 names1names2 的列表拼接结果。
ExportSpecifier : ModuleExportName as ModuleExportName
  1. 返回第一个 ModuleExportNameReferencedBindings
ModuleExportName : IdentifierName
  1. 返回一个列表,其唯一元素为该 IdentifierName
ModuleExportName : StringLiteral
  1. 返回一个列表,其唯一元素为该 StringLiteral

16.2.3.7 Runtime Semantics: Evaluation

ExportDeclaration : export ExportFromClause FromClause WithClauseopt ; export NamedExports ;
  1. 返回 empty
ExportDeclaration : export VariableStatement
  1. 返回 ? VariableStatementEvaluation
ExportDeclaration : export Declaration
  1. 返回 ? DeclarationEvaluation
ExportDeclaration : export default HoistableDeclaration
  1. 返回 ? HoistableDeclarationEvaluation
ExportDeclaration : export default ClassDeclaration
  1. value 为 ? ClassDeclarationBindingClassDeclarationEvaluation
  2. classNameClassDeclarationBoundNames 的唯一元素。
  3. 如果 className"*default*",则
    1. env正在运行的执行上下文的 LexicalEnvironment。
    2. 执行 ? InitializeBoundName("*default*", value, env)。
  4. 返回 empty
ExportDeclaration : export default AssignmentExpression ;
  1. 如果 IsAnonymousFunctionDefinition(AssignmentExpression) 是 true,则
    1. value 为以 "default" 为参数的 AssignmentExpression 的 ? NamedEvaluation
  2. 否则,
    1. rhs 为 ? AssignmentExpressionEvaluation
    2. value 为 ? GetValue(rhs)。
  3. env正在运行的执行上下文的 LexicalEnvironment。
  4. 执行 ? InitializeBoundName("*default*", value, env)。
  5. 返回 empty

17 错误处理与语言扩展

实现必须在相关 ECMAScript 语言构造被求值时报告大多数错误。早期错误是指在包含该错误的 Script 中任何构造被求值之前即可检测并报告的错误。出现早期错误会阻止该构造的求值。实现必须在 ParseScript 解析该 Script 时报告其中的早期错误Module 中的早期错误在该 Module 将被求值时报告,并且该 Module 永远不会被初始化。eval 代码中的早期错误在调用 eval 时报告,并阻止 eval 代码的求值。所有非早期错误的错误都是运行时错误。

实现必须将本规范中“Static Semantics: 早期错误”子条款列出的任何条件的出现报告为早期错误

即使编译器可以证明某个构造在任何情况下都无法无错误地执行,实现也不得将其他类型的错误视为早期错误。在这种情况下,实现可以发出早期警告,但不应在相关构造真正执行之前报告该错误。

实现应按规范报告所有错误,但以下情况除外:

17.1 禁止的扩展

实现不得以以下方式扩展本规范:

18 ECMAScript 标准内建对象

在任何 ECMAScript ScriptModule 开始执行时,都存在某些内建对象。其中之一是全局对象,它是执行程序的全局环境的一部分。其他对象可以作为全局对象的初始属性访问,或作为可访问的内建对象的属性间接访问。

除非另有说明,可作为函数调用的内建对象都是具有 10.3 中描述特性的内建函数对象。除非另有说明,内建对象的 [[Extensible]] 内部槽初始值为 true。每个内建函数对象都有一个 [[Realm]] 内部槽,其值为创建该对象时所属的 Realm Record

许多内建对象是函数:它们可以带参数调用。其中一些还是构造函数:它们是用于与 new 运算符一起使用的函数。对于每个内建函数,本规范描述了该函数所需的参数以及该函数对象的属性。对于每个内建构造函数,本规范还描述了该构造函数的原型对象的属性,以及通过 new 表达式调用该构造函数所返回的具体对象实例的属性。

除非在特定函数的描述中另有说明,如果内建函数或构造函数接收到的参数少于其规定所需的参数,则其行为应与接收到足够数量的额外参数完全相同,每个额外参数的值均为 undefined。这些缺失参数被视为“未提供”,规范算法可以以此方式识别。在特定函数的描述中,“this 值”和“NewTarget”术语的含义见 10.3

除非在特定函数的描述中另有说明,如果内建函数或构造函数接收到的参数多于其允许的数量,则这些额外参数会被调用过程求值,但随后被函数忽略。不过,只要行为不是仅因为存在额外参数而抛出 TypeError 异常,实现可以定义与这些参数相关的特定实现行为。

Note 1

鼓励实现通过添加新函数来扩展内建函数集合,而不是向现有函数添加新参数。

除非另有说明,每个内建函数和内建构造函数的 [[Prototype]] 内部槽值都是函数原型对象,即表达式 Function.prototype 的初始值(20.2.3)。

除非另有说明,每个内建原型对象的 [[Prototype]] 内部槽值都是对象原型对象,即表达式 Object.prototype 的初始值(20.1.3),但对象原型对象本身除外。

如果本规范通过算法步骤定义了某个内建构造函数的行为,则该行为同时适用于 [[Call]][[Construct]]。如果需要区分这两种情况,则通过检查 NewTarget 是否为 undefined 来实现,若为 undefined 则表示 [[Call]] 调用。

未被标识为构造函数的内建函数对象不实现 [[Construct]] 内部方法,除非在特定函数的描述中另有说明。

未被标识为构造函数的内建函数对象没有 "prototype" 属性,除非在特定函数的描述中另有说明。

本规范中定义的每个内建函数都是通过调用 CreateBuiltinFunction 抽象操作创建的(10.3.4)。参数 lengthname 的值分别是 "length""name" 属性的初始值,如下文所述。参数 prefix 的值也在下文中说明。

每个内建函数对象(包括构造函数)都有一个 "length" 属性,其值为非负整数 Number。除非另有说明,该值等于函数描述子条款标题中显示的必需参数数量。可选参数和剩余参数不计入该数量。

Note 2

例如,Array 原型对象"map" 属性的初始值对应的函数对象,在子条款标题 «Array.prototype.map (callback [ , thisArg])» 中描述,其中包含两个命名参数 callback 和 thisArg,后者为可选参数;因此该函数对象"length" 属性值为 1𝔽

除非另有说明,内建函数对象"length" 属性具有 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true } 特性。

每个内建函数对象(包括构造函数)都有一个 "name" 属性,其值为字符串。除非另有说明,该值为本规范中赋予该函数的名称。被标识为匿名函数的函数使用空字符串作为 "name" 属性的值。对于被指定为对象属性的函数,其名称值为用于访问该函数的属性名字符串。对于作为内建属性的 getter 或 setter 访问器函数,其在调用 CreateBuiltinFunction 时会将 "get""set"(分别)传递给参数 prefix

对于其属性键为 Symbol 值的内建函数,其 "name" 属性的值会被显式指定。如果该值以前缀 "get ""set " 开头,并且该函数是某个内建属性的 getter 或 setter 访问器函数,则去掉前缀后的值传递给参数 name,而 "get""set"(分别)传递给参数 prefix,用于调用 CreateBuiltinFunction

除非另有说明,内建函数对象"name" 属性具有 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true } 特性。

在条款 1928 以及附录 B.2 中描述的所有其他数据属性,除非另有说明,其特性为 { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }。

在条款 1928 以及附录 B.2 中描述的所有访问器属性,除非另有说明,其特性为 { [[Enumerable]]: false, [[Configurable]]: true }。如果仅描述了 getter 访问器函数,则 setter 访问器函数的默认值为 undefined。如果仅描述了 setter 访问器,则 getter 访问器的默认值为 undefined

19 全局对象

下列为 全局对象

19.1 全局对象的值属性

19.1.1 globalThis

Realm 记录 realm全局对象"globalThis" 属性的初始值为 realm.[[GlobalEnv]].[[GlobalThisValue]].

该属性具有属性 { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }。

19.1.2 Infinity

Infinity 的值为 +∞𝔽(参见 6.1.6.1)。该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

19.1.3 NaN

NaN 的值为 NaN(参见 6.1.6.1)。该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

19.1.4 undefined

undefined 的值为 undefined(参见 6.1.1)。该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

19.2 全局对象的函数属性

19.2.1 eval ( source )

该函数为 %eval% 内在对象。

调用时执行下列步骤:

  1. 返回 ? PerformEval(source, false, false)。

19.2.1.1 PerformEval ( source, strictCaller, direct )

The abstract operation PerformEval takes arguments source (an ECMAScript language value), strictCaller (a Boolean), and direct (a Boolean) and returns either a normal completion containing an ECMAScript language value or a throw completion. It performs the following steps when called:

  1. 断言:如果 directfalse,则 strictCaller 也为 false
  2. 如果 source 不是一个 String,返回 source
  3. evalRealm 为当前的 Realm 记录。
  4. 注意:在直接 eval 的情况下,evalRealm 是 eval 函数的调用者和 eval 函数本身的 realm
  5. 执行 ? HostEnsureCanCompileStrings(evalRealm, « », source, direct)。
  6. inFunctionfalse
  7. inMethodfalse
  8. inDerivedConstructorfalse
  9. inClassFieldInitializerfalse
  10. 如果 directtrue,则
    1. thisEnvRecGetThisEnvironment()。
    2. 如果 thisEnvRec 是一个 Function Environment Record,则
      1. functhisEnvRec.[[FunctionObject]]
      2. inFunction 设为 true
      3. inMethod 设为 thisEnvRec.HasSuperBinding()。
      4. 如果 func.[[ConstructorKind]]derived,将 inDerivedConstructor 设为 true
      5. classFieldInitializerNamefunc.[[ClassFieldInitializerName]]
      6. 如果 classFieldInitializerNameempty,将 inClassFieldInitializer 设为 true
  11. 实现定义的顺序执行下列子步骤,可能交错进行解析与错误检测:
    1. scriptParseText(source, Script)。
    2. 如果 script 是一个错误列表,则抛出 SyntaxError 异常。
    3. 如果 script.Contains ScriptBodyfalse,返回 undefined
    4. bodyscriptScriptBody
    5. 如果 inFunctionfalsebody.Contains NewTarget,抛出 SyntaxError 异常。
    6. 如果 inMethodfalsebody.Contains SuperProperty,抛出 SyntaxError 异常。
    7. 如果 inDerivedConstructorfalsebody.Contains SuperCall,抛出 SyntaxError 异常。
    8. 如果 inClassFieldInitializertrueContainsArguments(body) 为 true,抛出 SyntaxError 异常。
  12. 如果 strictCallertrue,令 strictEvaltrue
  13. 否则,令 strictEvalScriptIsStrict(script)。
  14. runningContext正在运行的执行上下文
  15. 注意:如果 directtruerunningContext 将是执行直接 eval执行上下文。如果 directfalserunningContext 将是调用 eval 函数的执行上下文
  16. 如果 directtrue,则
    1. lexEnvNewDeclarativeEnvironment(runningContext's LexicalEnvironment)。
    2. varEnvrunningContext 的 VariableEnvironment。
    3. privateEnvrunningContext 的 PrivateEnvironment。
  17. 否则,
    1. lexEnvNewDeclarativeEnvironment(evalRealm.[[GlobalEnv]])。
    2. varEnvevalRealm.[[GlobalEnv]]
    3. privateEnvnull
  18. 如果 strictEvaltrue,将 varEnv 设为 lexEnv
  19. 如果 runningContext 尚未被挂起,则挂起 runningContext
  20. evalContext 为新的 ECMAScript 代码执行上下文
  21. evalContext 的 Function 设为 null
  22. evalContextRealm 设为 evalRealm
  23. evalContext 的 ScriptOrModule 设为 runningContext 的 ScriptOrModule。
  24. evalContext 的 VariableEnvironment 设为 varEnv
  25. evalContext 的 LexicalEnvironment 设为 lexEnv
  26. evalContext 的 PrivateEnvironment 设为 privateEnv
  27. evalContext 推入执行上下文栈evalContext 现在为正在运行的执行上下文
  28. resultCompletion(EvalDeclarationInstantiation(body, varEnv, lexEnv, privateEnv, strictEval)) 的结果。
  29. 如果 result 为普通完成,则
    1. result 设为 Completion(Evaluation of body) 的结果。
  30. 如果 result 为普通完成且 result.[[Value]]empty,则
    1. result 设为 NormalCompletion(undefined)。
  31. 挂起 evalContext 并将其从执行上下文栈中移除。
  32. 恢复当前栈顶的上下文为正在运行的执行上下文
  33. 返回 ? result
Note

如果调用 eval 的上下文代码或 eval 代码为严格模式代码,eval 代码不能在调用上下文的变量环境中实例化变量或函数绑定。相反,这些绑定在仅对 eval 代码可见的新 VariableEnvironment 中实例化。由 letconstclass 声明引入的绑定总是实例化在新的 LexicalEnvironment 中。

19.2.1.2 HostEnsureCanCompileStrings ( calleeRealm, parameterStrings, bodyString, direct )

The host-defined abstract operation HostEnsureCanCompileStrings takes arguments calleeRealm (a Realm Record), parameterStrings (a List of Strings), bodyString (a String), and direct (a Boolean) and returns either a normal completion containing unused or a throw completion. 允许宿主环境阻止某些 ECMAScript 函数,这些函数允许开发者将字符串解释并作为 ECMAScript 代码求值。

parameterStrings 表示在使用函数构造器时会被串联以构建参数列表的字符串。bodyString 表示函数体或传递给 eval 调用的字符串。 direct 表示该求值是否为直接 eval

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

19.2.1.3 EvalDeclarationInstantiation ( body, varEnv, lexEnv, privateEnv, strict )

The abstract operation EvalDeclarationInstantiation takes arguments body (a ScriptBody Parse Node), varEnv (an Environment Record), lexEnv (a Declarative Environment Record), privateEnv (a PrivateEnvironment Record or null), and strict (a Boolean) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

  1. varNamesbodyVarDeclaredNames
  2. varDeclarationsbodyVarScopedDeclarations
  3. 如果 strictfalse,则
    1. 如果 varEnvGlobal Environment Record,则
      1. varNames 的每个元素 name 执行
        1. 如果 HasLexicalDeclaration(varEnv, name) 为 true,抛出 SyntaxError 异常。
        2. 注:如果有全局词法声明,eval 将不会创建会被该全局词法声明遮蔽的全局 var 声明。
    2. thisEnvlexEnv
    3. 断言:以下循环将终止。
    4. 重复,当 thisEnvvarEnv 不是同一 Environment Record 时,
      1. 如果 thisEnv 不是 Object Environment Record,则
        1. 注:with 语句的环境不能包含任何词法声明,因此不需要检查 var/let 抛出冲突。
        2. varNames 的每个元素 name 执行
          1. 如果 ! thisEnv.HasBinding(name) 为 true,则
            1. Normative Optional
              如果宿主为 Web 浏览器或以其他方式支持 Catch 块中的 VariableStatement,则
              1. 如果 thisEnv 不是 Catch 子句的 Environment Record,抛出 SyntaxError 异常。
            2. 否则,
              1. 抛出 SyntaxError 异常。
          2. 注:直接 eval 不会将 var 声明提升至同名的词法声明之上。
      2. thisEnv 设为 thisEnv.[[OuterEnv]]
  4. privateIdentifiers 为新的空列表。
  5. pointerprivateEnv
  6. 重复,直到 pointernull
    1. pointer.[[Names]] 的每个 Private Name binding 执行
      1. 如果 privateIdentifiers 不包含 binding.[[Description]],则将 binding.[[Description]] 附加到 privateIdentifiers
    2. pointer 设为 pointer.[[OuterPrivateEnvironment]]
  7. 如果 AllPrivateIdentifiersValid of body 以参数 privateIdentifiers 为假,抛出 SyntaxError 异常。
  8. functionsToInitialize 为新的空列表。
  9. declaredFunctionNames 为新的空列表。
  10. 以逆序对 varDeclarations 的每个元素 d 执行
    1. 如果 d 既不是 VariableDeclaration、也不是 ForBinding、也不是 BindingIdentifier,则
      1. 断言:dFunctionDeclarationGeneratorDeclarationAsyncFunctionDeclarationAsyncGeneratorDeclaration 之一。
      2. 注:如果存在同名的多个函数声明,使用最后一个声明。
      3. fndBoundNames 的唯一元素。
      4. 如果 declaredFunctionNames 不包含 fn,则
        1. 如果 varEnvGlobal Environment Record,则
          1. fnDefinable 为 ? CanDeclareGlobalFunction(varEnv, fn)。
          2. 如果 fnDefinablefalse,抛出 TypeError 异常。
        2. fn 附加到 declaredFunctionNames
        3. d 插入为 functionsToInitialize 的第一个元素。
  11. declaredVarNames 为新的空列表。
  12. varDeclarations 的每个元素 d 执行
    1. 如果 dVariableDeclarationForBindingBindingIdentifier 之一,则
      1. dBoundNames 的每个字符串 vn 执行
        1. 如果 declaredFunctionNames 不包含 vn,则
          1. 如果 varEnvGlobal Environment Record,则
            1. vnDefinable 为 ? CanDeclareGlobalVar(varEnv, vn)。
            2. 如果 vnDefinablefalse,抛出 TypeError 异常。
          2. 如果 declaredVarNames 不包含 vn,则
            1. vn 附加到 declaredVarNames
  13. Normative Optional
    如果 strictfalse宿主为 Web 浏览器或以其他方式支持 块级函数声明的 Web 遗留兼容性语义,则
    1. declaredFunctionOrVarNamesdeclaredFunctionNamesdeclaredVarNames 的串联列表。
    2. 对任意 BlockCaseClauseDefaultClause x 中直接包含于其 StatementListbody.Contains xtrue 的每个 FunctionDeclaration f 执行
      1. funcNamefBindingIdentifierStringValue
      2. 如果将 FunctionDeclaration f 替换为一个具有 funcName 作为 BindingIdentifierVariableStatement 不会为 body 产生任何早期错误,则
        1. bindingExistsfalse
        2. thisEnv 设为 lexEnv
        3. 断言:以下循环将终止。
        4. 重复,直到 thisEnvvarEnv,
          1. 如果 thisEnv 不是 Object Environment Record,则
            1. 如果 ! thisEnv.HasBinding(funcName) 为 true,则
              1. Normative Optional
                如果宿主为 Web 浏览器或以其他方式支持 Catch 块中的 VariableStatement,则
                1. 如果 thisEnv 不是 Catch 子句的 Environment Record,设 bindingExiststrue
              2. 否则,
                1. bindingExiststrue
          2. thisEnv 设为 thisEnv.[[OuterEnv]]
        5. 如果 bindingExistsfalsevarEnvGlobal Environment Record,则
          1. 如果 HasLexicalDeclaration(varEnv, funcName) 为 false,则
            1. fnDefinable 为 ? CanDeclareGlobalVar(varEnv, funcName)。
          2. 否则,
            1. fnDefinablefalse
        6. 否则,
          1. fnDefinabletrue
        7. 如果 bindingExistsfalsefnDefinabletrue,则
          1. 如果 declaredFunctionOrVarNames 不包含 funcName,则
            1. 如果 varEnvGlobal Environment Record,则
              1. 执行 ? CreateGlobalVarBinding(varEnv, funcName, true)。
            2. 否则,
              1. bindingExists 为 ! varEnv.HasBinding(funcName)。
              2. 如果 bindingExistsfalse,则
                1. 执行 ! varEnv.CreateMutableBinding(funcName, true)。
                2. 执行 ! varEnv.InitializeBinding(funcName, undefined)。
            3. funcName 附加到 declaredFunctionOrVarNames
          2. FunctionDeclaration f 被求值时,替代 15.2.6 中提供的 FunctionDeclaration 求值算法执行下列步骤:
            1. gEnv正在运行的执行上下文的 VariableEnvironment。
            2. bEnv正在运行的执行上下文的 LexicalEnvironment。
            3. fObj 为 ! bEnv.GetBindingValue(funcName, false)。
            4. 执行 ? gEnv.SetMutableBinding(funcName, fObj, false)
            5. 返回 unused
  14. 注:除非 varEnvGlobal Environment Record全局对象为 Proxy 异常对象,否则在本算法步骤后不会发生异常终止。
  15. lexDeclarationsbodyLexicallyScopedDeclarations
  16. lexDeclarations 的每个元素 d 执行
    1. 注:词法声明的名字仅在此处被实例化但不被初始化。
    2. dBoundNames 的每个元素 dn 执行
      1. 如果 IsConstantDeclaration(d) 为 true,则
        1. 执行 ? lexEnv.CreateImmutableBinding(dn, true)。
      2. 否则,
        1. 执行 ? lexEnv.CreateMutableBinding(dn, false)。
  17. functionsToInitialize 的每个 Parse Node f 执行
    1. fnfBoundNames 的唯一元素。
    2. foInstantiateFunctionObject(f, lexEnv, privateEnv)。
    3. 如果 varEnvGlobal Environment Record,则
      1. 执行 ? CreateGlobalFunctionBinding(varEnv, fn, fo, true)。
    4. 否则,
      1. bindingExists 为 ! varEnv.HasBinding(fn)。
      2. 如果 bindingExistsfalse,则
        1. 注:由于在 14 之前已进行验证,因此以下调用不会返回异常完成。
        2. 执行 ! varEnv.CreateMutableBinding(fn, true)。
        3. 执行 ! varEnv.InitializeBinding(fn, fo)。
      3. 否则,
        1. 执行 ! varEnv.SetMutableBinding(fn, fo, false)。
  18. declaredVarNames 的每个字符串 vn 执行
    1. 如果 varEnvGlobal Environment Record,则
      1. 执行 ? CreateGlobalVarBinding(varEnv, vn, true)。
    2. 否则,
      1. bindingExists 为 ! varEnv.HasBinding(vn)。
      2. 如果 bindingExistsfalse,则
        1. 注:由于在 14 之前已进行验证,因此以下调用不会返回异常完成。
        2. 执行 ! varEnv.CreateMutableBinding(vn, true)。
        3. 执行 ! varEnv.InitializeBinding(vn, undefined)。
  19. 返回 unused

19.2.2 isFinite ( number )

该函数为 %isFinite% 内在对象。

调用时执行下列步骤:

  1. num 为 ? ToNumber(number)。
  2. 如果 num有限值,返回 true
  3. 返回 false

19.2.3 isNaN ( number )

该函数为 %isNaN% 内在对象。

调用时执行下列步骤:

  1. num 为 ? ToNumber(number)。
  2. 如果 numNaN,返回 true
  3. 返回 false
Note

在 ECMAScript 代码中检测值 X 是否为 NaN 的一种可靠方法是使用表达式 X !== X。当且仅当 XNaN 时,该表达式结果为 true

19.2.4 parseFloat ( string )

该函数根据将 string 参数的内容解释为十进制字面量来产生一个 Number 值

它是 %parseFloat% 内在对象。

调用时执行下列步骤:

  1. inputString 为 ? ToString(string)。
  2. trimmedString 为 ! TrimString(inputString, start)。
  3. trimmedStringToCodePoints(trimmedString)。
  4. trimmedPrefix 为满足 StrDecimalLiteral 语法的 trimmed 的最长前缀,该前缀可能就是 trimmed 本身。如果没有这样的前缀,返回 NaN
  5. parsedNumberParseText(trimmedPrefix, StrDecimalLiteral)。
  6. 断言:parsedNumber 为一个 Parse Node。
  7. 返回 parsedNumberStringNumericValue
Note

该函数可能仅将 string 的前导部分解释为 Number 值;它忽略任何不能被解释为十进制字面量记法部分的代码单元,且不提示任何此类代码单元被忽略。

19.2.5 parseInt ( string, radix )

该函数根据指定的 radix 解释 string 的内容来产生一个整数 Number。忽略 string 的前导空白。如果 radix 被强制转换为 0(例如当其为 undefined 时),则假定为 10,除非数字表示以 "0x""0X" 开头,在这种情况下假定为 16。如果 radix 为 16,则数字表示可以可选地以 "0x""0X" 开头。

它是 %parseInt% 内在对象。

调用时执行下列步骤:

  1. inputString 为 ? ToString(string)。
  2. trimmedString 为 ! TrimString(inputString, start)。
  3. sign 为 1。
  4. 如果 trimmedString 非空且其第一个代码单元为代码单元 0x002D (HYPHEN-MINUS),将 sign 设为 -1。
  5. 如果 trimmedString 非空且其第一个代码单元为代码单元 0x002B (PLUS SIGN) 或代码单元 0x002D (HYPHEN-MINUS),将 trimmedString 设为从索引 1 开始的子字符串
  6. radixMV(? ToInt32(radix))。
  7. stripPrefixtrue
  8. 如果 radixMV ≠ 0,则
    1. 如果 radixMV < 2 或 radixMV > 36,返回 NaN
    2. 如果 radixMV ≠ 16,将 stripPrefix 设为 false
  9. 否则,
    1. radixMV 设为 10。
  10. 如果 stripPrefixtrue,则
    1. 如果 trimmedString 的长度 ≥ 2 且其前两个代码单元为 "0x""0X",则
      1. trimmedString 设为从索引 2 开始的子字符串
      2. radixMV 设为 16。
  11. 如果 trimmedString 包含非 radix-radixMV 的代码单元,则令 endtrimmedString 中第一个此类代码单元的索引;否则令 endtrimmedString 的长度。
  12. numberStringtrimmedString 从 0 到 end子字符串
  13. 如果 numberString 为空,返回 NaN
  14. mathInt 为以 radix-radixMV 表示法由 numberString 表示的整数值,使用字母 AZaz 表示值为 10 到 35 的数字。(不过,如果 radixMV = 10 且 numberString 包含超过 20 个有效数字,则实现可以选择在第 20 位之后将每个有效数字替换为 0;并且如果 radixMV 不是 2、4、8、10、16 或 32 之一,则 mathInt 可以是对由 numberString 在 radix-radixMV 表示法所表示整数值的实现近似。)
  15. 如果 mathInt = 0,则
    1. 如果 sign = -1,返回 -0𝔽
    2. 返回 +0𝔽
  16. 返回 𝔽(sign × mathInt)。
Note

该函数可能仅将 string 的前导部分解释为整数值;它忽略任何不能被解释为整数记法部分的代码单元,且不提示任何此类代码单元被忽略。

19.2.6 URI 处理函数

统一资源标识符(URI)是标识资源(例如网页或文件)以及访问这些资源的传输协议(例如 HTTP 或 FTP)的字符串。ECMAScript 语言本身除了本节所述用于编码和解码 URI 的函数之外,不提供任何用于使用 URI 的支持。encodeURIdecodeURI 旨在用于完整的 URI;它们假定任何保留字符具有特殊含义(例如作为分隔符),因此不被编码。encodeURIComponentdecodeURIComponent 旨在用于 URI 的单个组件;它们假定任何保留字符表示文本并且必须被编码,以避免在组件成为完整 URI 的一部分时具有特殊含义。

Note 1

保留字符集合基于 RFC 2396,并未反映更新的 RFC 3986 引入的更改。

Note 2

许多 ECMAScript 实现提供额外的函数和方法来操作网页;这些函数超出本标准的范围。

19.2.6.1 decodeURI ( encodedURI )

该函数计算 URI 的新版本,其中 encodeURI 可能引入的每个转义序列和 UTF-8 编码都被替换为其所表示的代码点的 UTF-16 编码。那些不可能由 encodeURI 引入的转义序列不被替换。

它是 %decodeURI% 内在对象。

调用时执行下列步骤:

  1. uriString 为 ? ToString(encodedURI)。
  2. preserveEscapeSet";/?:@&=+$,#"
  3. 返回 ? Decode(uriString, preserveEscapeSet)。

19.2.6.2 decodeURIComponent ( encodedURIComponent )

该函数计算 URI 的新版本,其中 encodeURIComponent 可能引入的每个转义序列和 UTF-8 编码都被替换为其所表示的代码点的 UTF-16 编码。

它是 %decodeURIComponent% 内在对象。

调用时执行下列步骤:

  1. componentString 为 ? ToString(encodedURIComponent)。
  2. preserveEscapeSet 为空字符串。
  3. 返回 ? Decode(componentString, preserveEscapeSet)。

19.2.6.3 encodeURI ( uri )

该函数计算一个 UTF-16 编码(参见 6.1.4)的 URI 的新版本,其中某些代码点的每个出现都被替换为表示该代码点 UTF-8 编码的一个、两个、三个或四个转义序列。

它是 %encodeURI% 内在对象。

调用时执行下列步骤:

  1. uriString 为 ? ToString(uri)。
  2. extraUnescaped";/?:@&=+$,#"
  3. 返回 ? Encode(uriString, extraUnescaped)。

19.2.6.4 encodeURIComponent ( uriComponent )

该函数计算一个 UTF-16 编码(参见 6.1.4)的 URI 组件的新版本,其中某些代码点的每个出现都被替换为表示该代码点 UTF-8 编码的一个、两个、三个或四个转义序列。

它是 %encodeURIComponent% 内在对象。

调用时执行下列步骤:

  1. componentString 为 ? ToString(uriComponent)。
  2. extraUnescaped 为空字符串。
  3. 返回 ? Encode(componentString, extraUnescaped)。

19.2.6.5 Encode ( string, extraUnescaped )

The abstract operation Encode takes arguments string (a String) and extraUnescaped (a String) and returns either a normal completion containing a String or a throw completion. 对 string 执行 URI 编码与转义,将其视为如 6.1.4 所述的一系列 UTF-16 编码的码点。如果某字符在 RFC 2396 中被识别为未保留字符或出现在 extraUnescaped 中,则不对其转义。 It performs the following steps when called:

  1. lenstring 的长度。
  2. result 为空字符串。
  3. alwaysUnescapedASCII 单词字符"-.!~*'()" 的字符串拼接。
  4. unescapedSetalwaysUnescapedextraUnescaped 的字符串拼接。
  5. k 为 0。
  6. 重复,当 k < len 时,
    1. codeUnitstring 中索引 k 的代码单元。
    2. 如果 unescapedSet 包含 codeUnit,则
      1. k 设为 k + 1。
      2. result 设为 resultcodeUnit 的字符串拼接。
    3. 否则,
      1. cpCodePointAt(string, k)。
      2. 如果 cp.[[IsUnpairedSurrogate]]true,抛出 URIError 异常。
      3. k 设为 k + cp.[[CodeUnitCount]]
      4. octets 为对 cp.[[CodePoint]] 应用 UTF-8 转换所得到的八位元组列表。
      5. octets 的每个元素 octet 执行
        1. hex 为格式为大写十六进制数的 octet 的字符串表示。
        2. result 设为 result"%"StringPad(hex, 2, "0", start) 的字符串拼接。
  7. 返回 result
Note

因为百分号编码用于表示单个八位元组,单个代码点可能被表示为多个连续的转义序列(每个 8 位 UTF-8 代码单元一个)。

19.2.6.6 Decode ( string, preserveEscapeSet )

The abstract operation Decode takes arguments string (a String) and preserveEscapeSet (a String) and returns either a normal completion containing a String or a throw completion. 执行 URI 取消转义与解码,同时保留任何对应于 preserveEscapeSet 中基本拉丁字符的转义序列。 It performs the following steps when called:

  1. lenstring 的长度。
  2. result 为空字符串。
  3. k 为 0。
  4. 重复,当 k < len 时,
    1. codeUnitstring 中索引 k 的代码单元。
    2. segmentcodeUnit
    3. 如果 codeUnit 为代码单元 0x0025 (PERCENT SIGN),则
      1. 如果 k + 3 > len,抛出 URIError 异常。
      2. escapestringkk + 3 的子字符串
      3. firstOctetParseHexOctet(string, k + 1)。
      4. 如果 firstOctet 不是整数,抛出 URIError 异常。
      5. k 设为 k + 2。
      6. nfirstOctet 中领先 1 位的个数。
      7. 如果 n = 0,则
        1. asciiChar 为其数值为 firstOctet 的代码单元。
        2. 如果 preserveEscapeSet 包含 asciiChar,将 segment 设为 escape;否则将 segment 设为 asciiChar
      8. 否则,
        1. 如果 n = 1 或 n > 4,抛出 URIError 异常。
        2. octets 为 « firstOctet »。
        3. j 为 1。
        4. 重复,当 j < n 时,
          1. k 设为 k + 1。
          2. 如果 k + 3 > len,抛出 URIError 异常。
          3. 如果 string 在索引 k 处的代码单元不是代码单元 0x0025 (PERCENT SIGN),抛出 URIError 异常。
          4. continuationByteParseHexOctet(string, k + 1)。
          5. 如果 continuationByte 不是整数,抛出 URIError 异常。
          6. continuationByte 附加到 octets
          7. k 设为 k + 2。
          8. j 设为 j + 1。
        5. 断言:octets 的长度为 n
        6. 如果 octets 不包含有效的 UTF-8 编码的 Unicode 代码点,抛出 URIError 异常。
        7. codePoint 为通过对 octets 应用 UTF-8 变换得到的代码点(即从八位元组列表到 21 位值)。
        8. segment 设为 UTF16EncodeCodePoint(codePoint)。
    4. result 设为 resultsegment 的字符串拼接。
    5. k 设为 k + 1。
  5. 返回 result
Note

RFC 3629 禁止对无效的 UTF-8 八位元组序列进行解码。例如,无效序列 0xC0 0x80 不得解码为代码单元 0x0000。Decode 算法的实现遇到此类无效序列时必须抛出 URIError

19.2.6.7 ParseHexOctet ( string, position )

The abstract operation ParseHexOctet takes arguments string (a String) and position (a non-negative integer) and returns either a non-negative integer or a non-empty List of SyntaxError objects. 解析 string 在指定 position 处的一段两个十六进制字符为无符号 8 位整数。 It performs the following steps when called:

  1. lenstring 的长度。
  2. 断言:position + 2 ≤ len
  3. hexDigitsstringpositionposition + 2 的子字符串
  4. parseResultParseText(hexDigits, HexDigits[~Sep])。
  5. 如果 parseResult 不是 Parse Node,返回 parseResult
  6. nparseResult 的 MV。
  7. 断言:n 在 0 到 255 的包含区间内。
  8. 返回 n

19.3 全局对象的构造器属性

19.3.1 AggregateError ( . . . )

参见 20.5.7.1

19.3.2 Array ( . . . )

参见 23.1.1

19.3.3 ArrayBuffer ( . . . )

参见 25.1.4

19.3.4 BigInt ( . . . )

参见 21.2.1

19.3.5 BigInt64Array ( . . . )

参见 23.2.5

19.3.6 BigUint64Array ( . . . )

参见 23.2.5

19.3.7 Boolean ( . . . )

参见 20.3.1

19.3.8 DataView ( . . . )

参见 25.3.2

19.3.9 Date ( . . . )

参见 21.4.2

19.3.10 Error ( . . . )

参见 20.5.1

19.3.11 EvalError ( . . . )

参见 20.5.5.1

19.3.12 FinalizationRegistry ( . . . )

参见 26.2.1

19.3.13 Float16Array ( . . . )

参见 23.2.5

19.3.14 Float32Array ( . . . )

参见 23.2.5

19.3.15 Float64Array ( . . . )

参见 23.2.5

19.3.16 Function ( . . . )

参见 20.2.1

19.3.17 Int8Array ( . . . )

参见 23.2.5

19.3.18 Int16Array ( . . . )

参见 23.2.5

19.3.19 Int32Array ( . . . )

参见 23.2.5

19.3.20 Iterator ( . . . )

参见 27.1.3.1

19.3.21 Map ( . . . )

参见 24.1.1

19.3.22 Number ( . . . )

参见 21.1.1

19.3.23 Object ( . . . )

参见 20.1.1

19.3.24 Promise ( . . . )

参见 27.2.3

19.3.25 Proxy ( . . . )

参见 28.2.1

19.3.26 RangeError ( . . . )

参见 20.5.5.2

19.3.27 ReferenceError ( . . . )

参见 20.5.5.3

19.3.28 RegExp ( . . . )

参见 22.2.4

19.3.29 Set ( . . . )

参见 24.2.2

19.3.30 SharedArrayBuffer ( . . . )

参见 25.2.3

19.3.31 String ( . . . )

参见 22.1.1

19.3.32 Symbol ( . . . )

参见 20.4.1

19.3.33 SyntaxError ( . . . )

参见 20.5.5.4

19.3.34 TypeError ( . . . )

参见 20.5.5.5

19.3.35 Uint8Array ( . . . )

参见 23.2.5

19.3.36 Uint8ClampedArray ( . . . )

参见 23.2.5

19.3.37 Uint16Array ( . . . )

参见 23.2.5

19.3.38 Uint32Array ( . . . )

参见 23.2.5

19.3.39 URIError ( . . . )

参见 20.5.5.6

19.3.40 WeakMap ( . . . )

参见 24.3.1

19.3.41 WeakRef ( . . . )

参见 26.1.1

19.3.42 WeakSet ( . . . )

参见 24.4

19.4 全局对象的其他属性

19.4.1 Atomics

参见 25.4

19.4.2 JSON

参见 25.5

19.4.3 Math

参见 21.3

19.4.4 Reflect

参见 28.1

20 基本对象

20.1 Object 对象

20.1.1 Object 构造函数

Object 构造函数:

  • %Object%
  • 全局对象"Object" 属性的初始值。
  • 当作为构造函数调用时会创建一个新的普通对象
  • 当作为函数而非构造函数调用时会执行类型转换。
  • 可用作类定义的 extends 子句的值。

20.1.1.1 Object ( value )

调用此函数时执行下列步骤:

  1. 如果 NewTarget 既不是 undefined 也不是活动函数对象,则
    1. 返回 ? OrdinaryCreateFromConstructor(NewTarget, "%Object.prototype%")。
  2. 如果 valueundefinednull,返回 OrdinaryObjectCreate(%Object.prototype%)。
  3. 返回 ! ToObject(value)。

20.1.2 Object 构造函数的属性

Object 构造函数:

20.1.2.1 Object.assign ( target, ...sources )

此函数将一个或多个源对象的所有可枚举自有属性的值复制到目标对象 target

调用时执行下列步骤:

  1. to 为 ? ToObject(target)。
  2. 如果只传入了一个参数,返回 to
  3. sources 的每个元素 nextSource 执行
    1. 如果 nextSource 既不是 undefined 也不是 null,则
      1. from 为 ! ToObject(nextSource)。
      2. keys 为 ? from.[[OwnPropertyKeys]]()
      3. keys 的每个元素 nextKey 执行
        1. desc 为 ? from.[[GetOwnProperty]](nextKey)
        2. 如果 desc 不是 undefineddesc.[[Enumerable]]true,则
          1. propValue 为 ? Get(from, nextKey)。
          2. 执行 ? Set(to, nextKey, propValue, true)。
  4. 返回 to

此函数的 "length" 属性为 2𝔽

20.1.2.2 Object.create ( proto, properties )

此函数创建一个具有指定原型的新对象。

调用时执行下列步骤:

  1. 如果 proto 既不是一个 Object 也不是 null,抛出 TypeError 异常。
  2. objOrdinaryObjectCreate(proto)。
  3. 如果 properties 不是 undefined,则
    1. 返回 ? ObjectDefineProperties(obj, properties)。
  4. 返回 obj

20.1.2.3 Object.defineProperties ( obj, properties )

此函数向对象添加自有属性和/或更新现有自有属性的属性描述。

调用时执行下列步骤:

  1. 如果 obj 不是一个 Object,抛出 TypeError 异常。
  2. 返回 ? ObjectDefineProperties(obj, properties)。

20.1.2.3.1 ObjectDefineProperties ( obj, properties )

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

  1. props 为 ? ToObject(properties)。
  2. keys 为 ? props.[[OwnPropertyKeys]]()
  3. descriptors 为新的空列表。
  4. keys 的每个元素 nextKey 执行
    1. propDesc 为 ? props.[[GetOwnProperty]](nextKey)
    2. 如果 propDesc 不是 undefinedpropDesc.[[Enumerable]]true,则
      1. descObj 为 ? Get(props, nextKey)。
      2. desc 为 ? ToPropertyDescriptor(descObj)。
      3. 将记录 { [[Key]]: nextKey, [[Descriptor]]: desc } 附加到 descriptors
  5. descriptors 的每个元素 property 执行
    1. 执行 ? DefinePropertyOrThrow(obj, property.[[Key]], property.[[Descriptor]])。
  6. 返回 obj

20.1.2.4 Object.defineProperty ( obj, propertyKey, attributes )

此函数向对象添加自有属性和/或更新现有自有属性的属性描述。

调用时执行下列步骤:

  1. 如果 obj 不是一个 Object,抛出 TypeError 异常。
  2. key 为 ? ToPropertyKey(propertyKey)。
  3. desc 为 ? ToPropertyDescriptor(attributes)。
  4. 执行 ? DefinePropertyOrThrow(obj, key, desc)。
  5. 返回 obj

20.1.2.5 Object.entries ( obj )

调用此函数时执行下列步骤:

  1. coerced 为 ? ToObject(obj)。
  2. entryList 为 ? EnumerableOwnProperties(coerced, key+value)。
  3. 返回 CreateArrayFromList(entryList)。

20.1.2.6 Object.freeze ( obj )

调用此函数时执行下列步骤:

  1. 如果 obj 不是一个 Object,返回 obj
  2. status 为 ? SetIntegrityLevel(obj, frozen)。
  3. 如果 statusfalse,抛出 TypeError 异常。
  4. 返回 obj

20.1.2.7 Object.fromEntries ( iterable )

调用此函数时执行下列步骤:

  1. 执行 ? RequireObjectCoercible(iterable)。
  2. objOrdinaryObjectCreate(%Object.prototype%)。
  3. 断言:obj 是一个不可枚举自有属性的可扩展普通对象
  4. closure 为一个新的抽象闭包,参数为 (key, value),该闭包捕获 obj 并在调用时执行下列步骤:
    1. propertyKey 为 ? ToPropertyKey(key)。
    2. 执行 ! CreateDataPropertyOrThrow(obj, propertyKey, value)。
    3. 返回 NormalCompletion(undefined)。
  5. adderCreateBuiltinFunction(closure, 2, "", « »)。
  6. 返回 ? AddEntriesFromIterable(obj, iterable, adder)。
Note
The function created for adder is never directly accessible to ECMAScript code.

20.1.2.8 Object.getOwnPropertyDescriptor ( obj, propertyKey )

调用此函数时执行下列步骤:

  1. coerced 为 ? ToObject(obj)。
  2. key 为 ? ToPropertyKey(propertyKey)。
  3. desc 为 ? coerced.[[GetOwnProperty]](key)
  4. 返回 FromPropertyDescriptor(desc)。

20.1.2.9 Object.getOwnPropertyDescriptors ( obj )

调用此函数时执行下列步骤:

  1. coerced 为 ? ToObject(obj)。
  2. ownKeys 为 ? coerced.[[OwnPropertyKeys]]()
  3. descriptorsOrdinaryObjectCreate(%Object.prototype%)。
  4. ownKeys 的每个元素 key 执行
    1. desc 为 ? coerced.[[GetOwnProperty]](key)
    2. descriptorFromPropertyDescriptor(desc)。
    3. 如果 descriptor 不是 undefined,执行 ! CreateDataPropertyOrThrow(descriptors, key, descriptor)。
  5. 返回 descriptors

20.1.2.10 Object.getOwnPropertyNames ( obj )

调用此函数时执行下列步骤:

  1. 返回 CreateArrayFromList(? GetOwnPropertyKeys(obj, string))。

20.1.2.11 Object.getOwnPropertySymbols ( obj )

调用此函数时执行下列步骤:

  1. 返回 CreateArrayFromList(? GetOwnPropertyKeys(obj, symbol))。

20.1.2.11.1 GetOwnPropertyKeys ( value, type )

The abstract operation GetOwnPropertyKeys takes arguments value (an ECMAScript language value) and type (string or symbol) and returns either a normal completion containing a List of property keys or a throw completion. It performs the following steps when called:

  1. obj 为 ? ToObject(value)。
  2. keys 为 ? obj.[[OwnPropertyKeys]]()
  3. nameList 为新的空列表。
  4. keys 的每个元素 nextKey 执行
    1. 如果 nextKey 是一个 Symbol 且 typesymbol,或者 nextKey 是一个 String 且 typestring,则
      1. nextKey 附加到 nameList
  5. 返回 nameList

20.1.2.12 Object.getPrototypeOf ( obj )

调用此函数时执行下列步骤:

  1. coerced 为 ? ToObject(obj)。
  2. 返回 ? coerced.[[GetPrototypeOf]]()

20.1.2.13 Object.groupBy ( items, callback )

Note

callback 应为接受两个参数的函数。groupBy 以升序顺序对 items 的每个元素调用 callback 并构造一个新对象。callback 返回的每个值都会被强制转换为属性键。对于每个此类属性键,结果对象拥有一个以该属性键为键、其值为包含所有使得 callback 返回值强制为该键的元素的数组的属性。

callback 以两个参数调用:元素的值和元素的索引。

groupBy 的返回值是一个不从 %Object.prototype% 继承的对象。

调用此函数时执行下列步骤:

  1. groups 为 ? GroupBy(items, callback, property)。
  2. objOrdinaryObjectCreate(null)。
  3. groups 的每个记录 { [[Key]], [[Elements]] } g 执行
    1. elementsCreateArrayFromList(g.[[Elements]])。
    2. 执行 ! CreateDataPropertyOrThrow(obj, g.[[Key]], elements)。
  4. 返回 obj

20.1.2.14 Object.hasOwn ( obj, propertyKey )

调用此函数时执行下列步骤:

  1. coerced 为 ? ToObject(obj)。
  2. key 为 ? ToPropertyKey(propertyKey)。
  3. 返回 ? HasOwnProperty(coerced, key)。

20.1.2.15 Object.is ( value1, value2 )

调用此函数时执行下列步骤:

  1. 返回 SameValue(value1, value2)。

20.1.2.16 Object.isExtensible ( obj )

调用此函数时执行下列步骤:

  1. 如果 obj 不是一个 Object,返回 false
  2. 返回 ? IsExtensible(obj)。

20.1.2.17 Object.isFrozen ( obj )

调用此函数时执行下列步骤:

  1. 如果 obj 不是一个 Object,返回 true
  2. 返回 ? TestIntegrityLevel(obj, frozen)。

20.1.2.18 Object.isSealed ( obj )

调用此函数时执行下列步骤:

  1. 如果 obj 不是一个 Object,返回 true
  2. 返回 ? TestIntegrityLevel(obj, sealed)。

20.1.2.19 Object.keys ( obj )

调用此函数时执行下列步骤:

  1. coerced 为 ? ToObject(obj)。
  2. keyList 为 ? EnumerableOwnProperties(coerced, key)。
  3. 返回 CreateArrayFromList(keyList)。

20.1.2.20 Object.preventExtensions ( obj )

调用此函数时执行下列步骤:

  1. 如果 obj 不是一个 Object,返回 obj
  2. status 为 ? obj.[[PreventExtensions]]()
  3. 如果 statusfalse,抛出 TypeError 异常。
  4. 返回 obj

20.1.2.21 Object.prototype

Object.prototype 的初始值是 Object 原型对象

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.1.2.22 Object.seal ( obj )

调用此函数时执行下列步骤:

  1. 如果 obj 不是一个 Object,返回 obj
  2. status 为 ? SetIntegrityLevel(obj, sealed)。
  3. 如果 statusfalse,抛出 TypeError 异常。
  4. 返回 obj

20.1.2.23 Object.setPrototypeOf ( obj, proto )

调用此函数时执行下列步骤:

  1. 执行 ? RequireObjectCoercible(obj)。
  2. 如果 proto 既不是一个 Object 也不是 null,抛出 TypeError 异常。
  3. 如果 obj 不是一个 Object,返回 obj
  4. status 为 ? obj.[[SetPrototypeOf]](proto)
  5. 如果 statusfalse,抛出 TypeError 异常。
  6. 返回 obj

20.1.2.24 Object.values ( obj )

调用此函数时执行下列步骤:

  1. coerced 为 ? ToObject(obj)。
  2. valueList 为 ? EnumerableOwnProperties(coerced, value)。
  3. 返回 CreateArrayFromList(valueList)。

20.1.3 Object 原型对象的属性

Object 原型对象

  • %Object.prototype%
  • 有一个 [[Extensible]] 内部槽,其值为 true
  • 具有普通对象定义的内部方法,除了 [[SetPrototypeOf]] 方法外,该方法按 10.4.7.1 中的定义。(因此,它是一个不可变原型的特殊对象。)
  • 有一个 [[Prototype]] 内部槽,其值为 null

20.1.3.1 Object.prototype.constructor

Object.prototype.constructor 的初始值为 %Object%

20.1.3.2 Object.prototype.hasOwnProperty ( value )

调用此方法时执行下列步骤:

  1. propertyKey 为 ? ToPropertyKey(value)。
  2. obj 为 ? ToObject(this value)。
  3. 返回 ? HasOwnProperty(obj, propertyKey)。
Note

选择步骤 12 的执行顺序,是为了确保在本规范早期版本中会被步骤 1 抛出的任何异常,即便 this 值为 undefinednull,仍会继续被抛出。

20.1.3.3 Object.prototype.isPrototypeOf ( value )

调用此方法时执行下列步骤:

  1. 如果 value 不是一个 Object,返回 false
  2. obj 为 ? ToObject(this value)。
  3. 重复,
    1. value 设为 ? value.[[GetPrototypeOf]]()
    2. 如果 valuenull,返回 false
    3. 如果 SameValue(obj, value) 为 true,返回 true
Note

选择步骤 12 的执行顺序,使得在先前版本规范中对当 value 不是对象且 this 值为 undefinednull 的情况所指定的行为得以保留。

20.1.3.4 Object.prototype.propertyIsEnumerable ( value )

调用此方法时执行下列步骤:

  1. propertyKey 为 ? ToPropertyKey(value)。
  2. obj 为 ? ToObject(this value)。
  3. desc 为 ? obj.[[GetOwnProperty]](propertyKey)
  4. 如果 descundefined,返回 false
  5. 返回 desc.[[Enumerable]]
Note 1

此方法不考虑原型链中的对象。

Note 2

选择步骤 12 的执行顺序,是为了确保在本规范早期版本中会被步骤 1 抛出的任何异常,即便 this 值为 undefinednull,仍会继续被抛出。

20.1.3.5 Object.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] )

调用此方法时执行下列步骤:

  1. thisValuethis 值。
  2. 返回 ? Invoke(thisValue, "toString")。

此方法的可选参数未被使用,但旨在对应 ECMA-402 的 toLocaleString 方法所使用的参数模式。不包含 ECMA-402 支持的实现不得将这些参数位置用于其他目的。

Note 1

此方法为那些没有本地化敏感 toString 行为的对象提供通用的 toLocaleString 实现。ArrayNumberDate%TypedArray% 提供了它们自己的本地化 toLocaleString 方法。

Note 2

ECMA-402 有意不为该默认实现提供替代实现。

20.1.3.6 Object.prototype.toString ( )

调用此方法时执行下列步骤:

  1. 如果 this 值为 undefined,返回 "[object Undefined]"
  2. 如果 this 值为 null,返回 "[object Null]"
  3. obj 为 ! ToObject(this value)。
  4. isArray 为 ? IsArray(obj)。
  5. 如果 isArraytrue,令 builtinTag"Array"
  6. 否则如果 obj[[ParameterMap]] 内部槽,令 builtinTag"Arguments"
  7. 否则如果 obj[[Call]] 内部方法,令 builtinTag"Function"
  8. 否则如果 obj[[ErrorData]] 内部槽,令 builtinTag"Error"
  9. 否则如果 obj[[BooleanData]] 内部槽,令 builtinTag"Boolean"
  10. 否则如果 obj[[NumberData]] 内部槽,令 builtinTag"Number"
  11. 否则如果 obj[[StringData]] 内部槽,令 builtinTag"String"
  12. 否则如果 obj[[DateValue]] 内部槽,令 builtinTag"Date"
  13. 否则如果 obj[[RegExpMatcher]] 内部槽,令 builtinTag"RegExp"
  14. 否则,令 builtinTag"Object"
  15. tag 为 ? Get(obj, %Symbol.toStringTag%)。
  16. 如果 tag 不是一个 String,则将 tag 设为 builtinTag
  17. 返回字符串拼接 "[object ", tag, 和 "]" 的结果。
Note

历史上,此方法有时被用来访问在规范早期版本中用作各种内建对象名义类型标记的 [[Class]] 内部槽的字符串值。上述 toString 的定义为那些将 toString 用作检测特定内建对象类型的遗留代码保留了兼容性。它并不为其它类型的内建对象或程序定义的对象提供可靠的类型检测机制。此外,程序可以以使此类遗留类型检测失效的方式使用 %Symbol.toStringTag%

20.1.3.7 Object.prototype.valueOf ( )

调用此方法时执行下列步骤:

  1. 返回 ? ToObject(this value)。
Normative Optional, Legacy

20.1.3.8 Object.prototype.__proto__

Object.prototype.__proto__ 是一个访问器属性,属性为 { [[Enumerable]]: false, [[Configurable]]: true }。其 [[Get]][[Set]] 属性定义如下:

20.1.3.8.1 get Object.prototype.__proto__

[[Get]] 属性的值是一个不接受参数的内建函数。调用时执行下列步骤:

  1. obj 为 ? ToObject(this value)。
  2. 返回 ? obj.[[GetPrototypeOf]]()

20.1.3.8.2 set Object.prototype.__proto__

[[Set]] 属性的值是一个接受参数 proto 的内建函数。调用时执行下列步骤:

  1. thisValuethis 值。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. 如果 proto 既不是一个 Object 也不是 null,返回 undefined
  4. 如果 thisValue 不是一个 Object,返回 undefined
  5. status 为 ? thisValue.[[SetPrototypeOf]](proto)
  6. 如果 statusfalse,抛出 TypeError 异常。
  7. 返回 undefined
Normative Optional, Legacy

20.1.3.9 遗留的 Object.prototype 访问器方法

20.1.3.9.1 Object.prototype.__defineGetter__ ( propertyKey, getter )

调用此方法时执行下列步骤:

  1. obj 为 ? ToObject(this value)。
  2. 如果 IsCallable(getter) 为 false,抛出 TypeError 异常。
  3. desc 为 PropertyDescriptor { [[Get]]: getter, [[Enumerable]]: true, [[Configurable]]: true }。
  4. key 为 ? ToPropertyKey(propertyKey)。
  5. 执行 ? DefinePropertyOrThrow(obj, key, desc)。
  6. 返回 undefined

20.1.3.9.2 Object.prototype.__defineSetter__ ( propertyKey, setter )

调用此方法时执行下列步骤:

  1. obj 为 ? ToObject(this value)。
  2. 如果 IsCallable(setter) 为 false,抛出 TypeError 异常。
  3. desc 为 PropertyDescriptor { [[Set]]: setter, [[Enumerable]]: true, [[Configurable]]: true }。
  4. key 为 ? ToPropertyKey(propertyKey)。
  5. 执行 ? DefinePropertyOrThrow(obj, key, desc)。
  6. 返回 undefined

20.1.3.9.3 Object.prototype.__lookupGetter__ ( propertyKey )

调用此方法时执行下列步骤:

  1. obj 为 ? ToObject(this value)。
  2. key 为 ? ToPropertyKey(propertyKey)。
  3. 重复,
    1. desc 为 ? obj.[[GetOwnProperty]](key)
    2. 如果 desc 不是 undefined,则
      1. 如果 IsAccessorDescriptor(desc) 为 true,返回 desc.[[Get]]
      2. 返回 undefined
    3. obj 设为 ? obj.[[GetPrototypeOf]]()
    4. 如果 objnull,返回 undefined

20.1.3.9.4 Object.prototype.__lookupSetter__ ( propertyKey )

调用此方法时执行下列步骤:

  1. obj 为 ? ToObject(this value)。
  2. key 为 ? ToPropertyKey(propertyKey)。
  3. 重复,
    1. desc 为 ? obj.[[GetOwnProperty]](key)
    2. 如果 desc 不是 undefined,则
      1. 如果 IsAccessorDescriptor(desc) 为 true,返回 desc.[[Set]]
      2. 返回 undefined
    3. obj 设为 ? obj.[[GetPrototypeOf]]()
    4. 如果 objnull,返回 undefined

20.1.4 对象实例的属性

对象实例除了从 Object 原型对象继承的属性外没有特殊属性。

20.2 函数对象

20.2.1 Function 构造函数

Function 构造函数:

  • %Function%
  • 全局对象"Function" 属性的初始值。
  • 当作为函数而非构造函数调用时创建并初始化一个新的函数对象。因此函数调用 Function(…) 等价于使用相同参数的对象创建表达式 new Function(…)
  • 可用作类定义的 extends 子句的值。打算继承指定 Function 行为的子类构造函数必须包含对 Function 构造函数的 super 调用,以创建并初始化具有内建函数行为所需内部槽的子类实例。所有用于定义函数对象的 ECMAScript 语法形式都会创建 Function 的实例。除内建的 GeneratorFunction、AsyncFunction 和 AsyncGeneratorFunction 子类外,没有语法方式可以创建 Function 子类的实例。

20.2.1.1 Function ( ...parameterArgs, bodyArg )

最后一个参数(如果存在)指定函数体(可执行代码);任何前面的参数指定形式参数。

调用此函数时执行下列步骤:

  1. constructor活动函数对象
  2. 如果 bodyArg 缺失,将 bodyArg 设为空字符串。
  3. 返回 ? CreateDynamicFunction(constructor, NewTarget, normal, parameterArgs, bodyArg)。
Note

对于要指定的每个形式参数,拥有一个参数是允许的但非必须。例如,下面三种表达式都产生相同结果:

new Function("a", "b", "c", "return a+b+c")
new Function("a, b, c", "return a+b+c")
new Function("a,b", "c", "return a+b+c")

20.2.1.1.1 CreateDynamicFunction ( constructor, newTarget, kind, parameterArgs, bodyArg )

The abstract operation CreateDynamicFunction takes arguments constructor (a constructor), newTarget (a constructor or undefined), kind (normal, generator, async, or async-generator), parameterArgs (a List of ECMAScript language values), and bodyArg (an ECMAScript language value) and returns either a normal completion containing an ECMAScript function object or a throw completion. constructor 是执行此操作的构造函数。newTarget 是最初被 new 应用的构造函数。parameterArgsbodyArg 反映传递给 constructor 的参数值。 It performs the following steps when called:

  1. 如果 newTargetundefined,将 newTarget 设为 constructor
  2. 如果 kindnormal,则
    1. prefix"function"
    2. exprSym 为语法符号 FunctionExpression
    3. bodySym 为语法符号 FunctionBody[~Yield, ~Await]
    4. parameterSym 为语法符号 FormalParameters[~Yield, ~Await]
    5. fallbackProto"%Function.prototype%"
  3. 否则如果 kindgenerator,则
    1. prefix"function*"
    2. exprSym 为语法符号 GeneratorExpression
    3. bodySym 为语法符号 GeneratorBody
    4. parameterSym 为语法符号 FormalParameters[+Yield, ~Await]
    5. fallbackProto"%GeneratorFunction.prototype%"
  4. 否则如果 kindasync,则
    1. prefix"async function"
    2. exprSym 为语法符号 AsyncFunctionExpression
    3. bodySym 为语法符号 AsyncFunctionBody
    4. parameterSym 为语法符号 FormalParameters[~Yield, +Await]
    5. fallbackProto"%AsyncFunction.prototype%"
  5. 否则,
    1. 断言:kindasync-generator
    2. prefix"async function*"
    3. exprSym 为语法符号 AsyncGeneratorExpression
    4. bodySym 为语法符号 AsyncGeneratorBody
    5. parameterSym 为语法符号 FormalParameters[+Yield, +Await]
    6. fallbackProto"%AsyncGeneratorFunction.prototype%"
  6. argCountparameterArgs 中元素的数量。
  7. parameterStrings 为新的空列表。
  8. parameterArgs 的每个元素 arg 执行
    1. 将 ? ToString(arg) 附加到 parameterStrings
  9. bodyString 为 ? ToString(bodyArg)。
  10. currentRealm 为当前的 Realm 记录。
  11. 执行 ? HostEnsureCanCompileStrings(currentRealm, parameterStrings, bodyString, false)。
  12. parameterString 为空字符串。
  13. 如果 argCount > 0,则
    1. parameterString 设为 parameterStrings[0]。
    2. k 为 1。
    3. 重复,直到 k < argCount
      1. nextArgStringparameterStrings[k]。
      2. parameterString 设为字符串拼接 parameterString","(逗号)与 nextArgString
      3. k 设为 k + 1。
  14. bodyParseString 为字符串拼接 0x000A (LINE FEED)、bodyString、和 0x000A (LINE FEED)。
  15. sourceString 为字符串拼接 prefix" anonymous(", parameterString、0x000A (LINE FEED)、") {"bodyParseString、和 "}"
  16. sourceTextStringToCodePoints(sourceString)。
  17. parametersParseText(parameterString, parameterSym)。
  18. 如果 parameters 是一个错误列表,抛出 SyntaxError 异常。
  19. bodyParseText(bodyParseString, bodySym)。
  20. 如果 body 是一个错误列表,抛出 SyntaxError 异常。
  21. 注意:参数与函数体分别解析以确保各自单独有效。例如,new Function("/*", "*/ ) {") 不会被解析为一个函数。
  22. 注意:如果到达此步骤,sourceText 必定具有 exprSym 的语法(尽管反向不成立)。下面两步的目的是强制应用直接作用于 exprSym 的任何早期错误规则
  23. exprParseText(sourceText, exprSym)。
  24. 如果 expr 是一个错误列表,抛出 SyntaxError 异常。
  25. proto 为 ? GetPrototypeFromConstructor(newTarget, fallbackProto)。
  26. envcurrentRealm.[[GlobalEnv]]
  27. privateEnvnull
  28. funcOrdinaryFunctionCreate(proto, sourceText, parameters, body, non-lexical-this, env, privateEnv)。
  29. 执行 SetFunctionName(func, "anonymous")。
  30. 如果 kindgenerator,则
    1. prototypeOrdinaryObjectCreate(%GeneratorPrototype%)。
    2. 执行 ! DefinePropertyOrThrow(func, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  31. 否则如果 kindasync-generator,则
    1. prototypeOrdinaryObjectCreate(%AsyncGeneratorPrototype%)。
    2. 执行 ! DefinePropertyOrThrow(func, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  32. 否则如果 kindnormal,则
    1. 执行 MakeConstructor(func)。
  33. 注意:kindasync 的函数不可构造,且不具有 [[Construct]] 内部方法或 "prototype" 属性。
  34. 返回 func
Note

CreateDynamicFunction 会在其创建的任何非 async 类型的函数上定义一个 "prototype" 属性,以便该函数可能被用作构造函数。

20.2.2 Function 构造函数的属性

Function 构造函数:

  • 自身是一个内建函数对象
  • 有一个 [[Prototype]] 内部槽,其值为 %Function.prototype%
  • 具有 "length" 属性,其值为 1𝔽
  • 具有下列属性:

20.2.2.1 Function.prototype

Function.prototype 的值为 Function 原型对象

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.2.3 Function 原型对象的属性

Function 原型对象

  • %Function.prototype%
  • 自身是一个内建函数对象
  • 接受任意参数并在调用时返回 undefined
  • 没有 [[Construct]] 内部方法;不能用 new 操作符作为构造函数使用。
  • 有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%
  • 没有 "prototype" 属性。
  • 有一个 "length" 属性,其值为 +0𝔽
  • 有一个 "name" 属性,其值为空字符串。
Note

Function 原型对象被指定为一个函数对象,以确保与 ECMAScript 2015 之前创建的 ECMAScript 代码兼容。

20.2.3.1 Function.prototype.apply ( thisArg, argArray )

调用此方法时执行下列步骤:

  1. functhis 值。
  2. 如果 IsCallable(func) 为 false,抛出 TypeError 异常。
  3. 如果 argArrayundefinednull,则
    1. 执行 PrepareForTailCall()。
    2. 返回 ? Call(func, thisArg)。
  4. argList 为 ? CreateListFromArrayLike(argArray)。
  5. 执行 PrepareForTailCall()。
  6. 返回 ? Call(func, thisArg, argList)。
Note 1

thisArg 值未经修改即作为 this 值传入。这与第 3 版不同,第 3 版中 undefinednullthisArg 会被替换为全局对象,且对其他值会应用 ToObject 并将结果作为 this 值传入。尽管 thisArg 未被修改传入,非严格函数在进入函数时仍然会执行这些转换。

Note 2

如果 func 是箭头函数或绑定函数特殊对象,则在步骤 6 中,函数的 [[Call]] 会忽略 thisArg

20.2.3.2 Function.prototype.bind ( thisArg, ...args )

调用此方法时执行下列步骤:

  1. targetthis 值。
  2. 如果 IsCallable(target) 为 false,抛出 TypeError 异常。
  3. boundFunc 为 ? BoundFunctionCreate(target, thisArg, args)。
  4. length 为 0。
  5. targetHasLength 为 ? HasOwnProperty(target, "length")。
  6. 如果 targetHasLengthtrue,则
    1. targetLen 为 ? Get(target, "length")。
    2. 如果 targetLen 是一个 Number,则
      1. 如果 targetLen+∞𝔽,则
        1. length 设为 +∞。
      2. 否则如果 targetLen-∞𝔽,则
        1. length 设为 0。
      3. 否则,
        1. targetLenAsInt 为 ! ToIntegerOrInfinity(targetLen)。
        2. 断言:targetLenAsInt有限的。
        3. argCountargs 中元素的数量。
        4. length 设为 max(targetLenAsInt - argCount, 0)。
  7. 执行 SetFunctionLength(boundFunc, length)。
  8. targetName 为 ? Get(target, "name")。
  9. 如果 targetName 不是一个 String,将 targetName 设为空字符串。
  10. 执行 SetFunctionName(boundFunc, targetName, "bound")。
  11. 返回 boundFunc
Note 1

使用 Function.prototype.bind 创建的函数对象是特殊对象。它们也没有 "prototype" 属性。

Note 2

如果 target 是箭头函数或绑定函数特殊对象,则传递给此方法的 thisArg 不会被 func 的后续调用使用。

20.2.3.3 Function.prototype.call ( thisArg, ...args )

调用此方法时执行下列步骤:

  1. functhis 值。
  2. 如果 IsCallable(func) 为 false,抛出 TypeError 异常。
  3. 执行 PrepareForTailCall()。
  4. 返回 ? Call(func, thisArg, args)。
Note 1

thisArg 值未经修改即作为 this 值传入。这与第 3 版不同,第 3 版中 undefinednullthisArg 会被替换为全局对象,且对其他值会应用 ToObject 并将结果作为 this 值传入。尽管 thisArg 未被修改传入,非严格函数在进入函数时仍然会执行这些转换。

Note 2

如果 func 是箭头函数或绑定函数特殊对象,则在步骤 4 中,函数的 [[Call]] 会忽略 thisArg

20.2.3.4 Function.prototype.constructor

Function.prototype.constructor 的初始值为 %Function%

20.2.3.5 Function.prototype.toString ( )

调用此方法时执行下列步骤:

  1. functhis 值。
  2. 如果 func 是一个 Object,func 拥有 [[SourceText]] 内部槽,且 func.[[SourceText]] 为 Unicode 代码点序列,并且 HostHasSourceTextAvailable(func) 为 true,则
    1. 返回 CodePointsToString(func.[[SourceText]])。
  3. 如果 func 是一个 内建函数对象,返回由实现定义func 的字符串源代码表示。该表示必须具有 NativeFunction 的语法。此外,如果 func 拥有 [[InitialName]] 内部槽且 func.[[InitialName]] 是一个字符串,则返回字符串中可由 NativeFunctionAccessoropt PropertyName 匹配的部分必须为 func.[[InitialName]]
  4. 如果 func 是一个 Object 且 IsCallable(func) 为 true,返回由实现定义func 的字符串源代码表示。该表示必须具有 NativeFunction 的语法。
  5. 抛出 TypeError 异常。
NativeFunction : function NativeFunctionAccessoropt PropertyName[~Yield, ~Await]opt ( FormalParameters[~Yield, ~Await] ) { [ native code ] } NativeFunctionAccessor : get set

20.2.3.6 Function.prototype [ %Symbol.hasInstance% ] ( value )

调用此方法时执行下列步骤:

  1. thisValuethis 值。
  2. 返回 ? OrdinaryHasInstance(thisValue, value)。

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

Note

这是大多数函数继承的 %Symbol.hasInstance% 的默认实现。instanceof 操作符在确定某个值是否为特定构造函数的实例时会调用 %Symbol.hasInstance%。例如表达式

v instanceof F

等价于

F[%Symbol.hasInstance%](v)

构造函数可以通过在函数上公开不同的 %Symbol.hasInstance% 方法来控制 instanceof 识别哪些对象为其实例。

此属性为不可写且不可配置,以防止通过篡改可被用来全局暴露绑定函数目标函数的情况。

此方法的 "name" 属性值为 "[Symbol.hasInstance]"

20.2.4 函数实例

每个函数实例都是一个 ECMAScript 函数对象,并具有 Table 25 中列出的内部槽。使用 Function.prototype.bind 方法(20.2.3.2)创建的函数对象具有 Table 26 中列出的内部槽。

函数实例具有下列属性:

20.2.4.1 length

"length" 属性的值是一个整数 Number,指示函数期望的典型参数数量。然而,语言允许以其他数量的参数调用函数。函数在被以与其 "length" 属性不同的参数数量调用时的行为取决于该函数。此属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

20.2.4.2 name

"name" 属性的值是描述函数的字符串。名称没有语义意义,但通常是 ECMAScript 源文本中用于在定义点引用该函数的变量或属性名。此属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

未由本规范在上下文中关联名称的匿名函数对象使用空字符串作为 "name" 属性的值。

20.2.4.3 prototype

可用作构造函数的函数实例具有 "prototype" 属性。每当创建这样的函数实例时,也会创建另一个普通对象作为该函数 "prototype" 属性的初始值。除非另有说明,prototype 属性的值用于初始化当该函数作为构造函数调用时所创建对象的 [[Prototype]] 内部槽。

此属性具有属性 { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }。

Note

通过 Function.prototype.bind 创建的函数对象,或评估 MethodDefinition(且非 GeneratorMethodAsyncGeneratorMethod)或 ArrowFunction 时创建的函数对象不具有 "prototype" 属性。

20.2.5 HostHasSourceTextAvailable ( func )

The host-defined abstract operation HostHasSourceTextAvailable takes argument func (a function object) and returns a Boolean. 它允许宿主环境阻止为 func 提供源文本。

HostHasSourceTextAvailable 的实现必须符合下列要求:

  • 对于其参数必须是确定性的。每次以相同的 func 作为参数调用时,必须返回相同结果。

HostHasSourceTextAvailable 的默认实现返回 true

20.3 Boolean 对象

20.3.1 Boolean 构造函数

Boolean 构造函数:

  • %Boolean%
  • 全局对象"Boolean" 属性的初始值。
  • 当作为构造函数调用时创建并初始化新的 Boolean 对象。
  • 当作为函数而非构造函数调用时会执行类型转换。
  • 可用作类定义的 extends 子句的值。打算继承指定 Boolean 行为的子类构造函数必须包含对 Boolean 构造函数的 super 调用,以创建并初始化具有 [[BooleanData]] 内部槽的子类实例。

20.3.1.1 Boolean ( value )

调用此函数时执行下列步骤:

  1. bToBoolean(value)。
  2. 如果 NewTarget 为 undefined,返回 b
  3. obj 为 ? OrdinaryCreateFromConstructor(NewTarget, "%Boolean.prototype%", « [[BooleanData]] »)。
  4. obj.[[BooleanData]] 设为 b
  5. 返回 obj

20.3.2 Boolean 构造函数的属性

Boolean 构造函数:

20.3.2.1 Boolean.prototype

Boolean.prototype 的初始值为 Boolean 原型对象

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.3.3 Boolean 原型对象的属性

Boolean 原型对象

  • %Boolean.prototype%
  • 是一个普通对象
  • 自身是一个 Boolean 对象;它有一个 [[BooleanData]] 内部槽,值为 false
  • 有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%

20.3.3.1 Boolean.prototype.constructor

Boolean.prototype.constructor 的初始值为 %Boolean%

20.3.3.2 Boolean.prototype.toString ( )

调用此方法时执行下列步骤:

  1. b 为 ? ThisBooleanValue(this value)。
  2. 如果 btrue,返回 "true"
  3. 返回 "false"

20.3.3.3 Boolean.prototype.valueOf ( )

调用此方法时执行下列步骤:

  1. 返回 ? ThisBooleanValue(this value)。

20.3.3.3.1 ThisBooleanValue ( value )

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

  1. 如果 value 是一个 Boolean,返回 value
  2. 如果 value 是一个 Object 且 value 拥有 [[BooleanData]] 内部槽,则
    1. bvalue.[[BooleanData]]
    2. 断言:b 是一个 Boolean。
    3. 返回 b
  3. 抛出 TypeError 异常。

20.3.4 Boolean 实例的属性

Boolean 实例是普通对象,从 Boolean 原型对象继承属性。Boolean 实例具有一个 [[BooleanData]] 内部槽。[[BooleanData]] 内部槽是该 Boolean 对象所表示的布尔值。

20.4 Symbol 对象

20.4.1 Symbol 构造函数

Symbol 构造函数:

  • %Symbol%
  • 全局对象"Symbol" 属性的初始值。
  • 作为函数调用时返回一个新的 Symbol 值。
  • 不应与 new 操作符一起使用。
  • 不应被子类化。
  • 可用作类定义的 extends 子句的值,但对其的 super 调用会导致异常。

20.4.1.1 Symbol ( [ description ] )

调用此函数时执行下列步骤:

  1. 如果 NewTarget 不是 undefined,抛出 TypeError 异常。
  2. 如果 descriptionundefined,令 descStringundefined
  3. 否则,令 descString 为 ? ToString(description)。
  4. 返回一个新的 Symbol,其 [[Description]]descString

20.4.2 Symbol 构造函数的属性

Symbol 构造函数:

20.4.2.1 Symbol.asyncIterator

Symbol.asyncIterator 的初始值是内建符号 %Symbol.asyncIterator%Table 1)。

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.2 Symbol.for ( key )

调用此函数时执行下列步骤:

  1. stringKey 为 ? ToString(key)。
  2. GlobalSymbolRegistry 列表的每个元素 e 执行
    1. 如果 e.[[Key]]stringKey,返回 e.[[Symbol]]
  3. 断言:GlobalSymbolRegistry 列表当前不包含用于 stringKey 的条目。
  4. newSymbol 为一个新的 Symbol,其 [[Description]]stringKey
  5. 将 GlobalSymbolRegistry 记录 { [[Key]]: stringKey, [[Symbol]]: newSymbol } 附加到 GlobalSymbolRegistry 列表
  6. 返回 newSymbol

GlobalSymbolRegistry 列表 是一个追加专用的全局可用列表,由所有 realms 共享。在评估任何 ECMAScript 代码之前,它被初始化为空列表。GlobalSymbolRegistry 列表的元素是具有 Table 58 中定义结构的记录。

Table 58: GlobalSymbolRegistry 记录字段
字段名 用途
[[Key]] 一个 String 用于全局标识一个 Symbol 的字符串键。
[[Symbol]] 一个 Symbol 一个可以从任何 realm 检索的符号。

20.4.2.3 Symbol.hasInstance

Symbol.hasInstance 的初始值是内建符号 %Symbol.hasInstance%Table 1)。

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.4 Symbol.isConcatSpreadable

Symbol.isConcatSpreadable 的初始值是内建符号 %Symbol.isConcatSpreadable%Table 1)。

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.5 Symbol.iterator

Symbol.iterator 的初始值是内建符号 %Symbol.iterator%Table 1)。

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.6 Symbol.keyFor ( sym )

调用此函数时执行下列步骤:

  1. 如果 sym 不是一个 Symbol,抛出 TypeError 异常。
  2. 返回 KeyForSymbol(sym)。

20.4.2.7 Symbol.match

Symbol.match 的初始值是内建符号 %Symbol.match%Table 1)。

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.8 Symbol.matchAll

Symbol.matchAll 的初始值是内建符号 %Symbol.matchAll%Table 1)。

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.9 Symbol.prototype

Symbol.prototype 的初始值是 Symbol 原型对象

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.10 Symbol.replace

Symbol.replace 的初始值是内建符号 %Symbol.replace%Table 1)。

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.11 Symbol.search

Symbol.search 的初始值是内建符号 %Symbol.search%Table 1)。

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.12 Symbol.species

Symbol.species 的初始值是内建符号 %Symbol.species%Table 1)。

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.13 Symbol.split

Symbol.split 的初始值是内建符号 %Symbol.split%Table 1)。

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.14 Symbol.toPrimitive

Symbol.toPrimitive 的初始值是内建符号 %Symbol.toPrimitive%Table 1)。

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.15 Symbol.toStringTag

Symbol.toStringTag 的初始值是内建符号 %Symbol.toStringTag%Table 1)。

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.16 Symbol.unscopables

Symbol.unscopables 的初始值是内建符号 %Symbol.unscopables%Table 1)。

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.3 Symbol 原型对象的属性

Symbol 原型对象

  • %Symbol.prototype%
  • 是一个普通对象
  • 不是 Symbol 实例且不具有 [[SymbolData]] 内部槽。
  • 有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%

20.4.3.1 Symbol.prototype.constructor

Symbol.prototype.constructor 的初始值为 %Symbol%

20.4.3.2 get Symbol.prototype.description

Symbol.prototype.description 是一个访问器属性,其设置访问器函数为 undefined。其获取访问器函数在调用时执行下列步骤:

  1. sthis 值。
  2. sym 为 ? ThisSymbolValue(s)。
  3. 返回 sym.[[Description]]

20.4.3.3 Symbol.prototype.toString ( )

调用此方法时执行下列步骤:

  1. sym 为 ? ThisSymbolValue(this value)。
  2. 返回 SymbolDescriptiveString(sym)。

20.4.3.3.1 SymbolDescriptiveString ( sym )

The abstract operation SymbolDescriptiveString takes argument sym (a Symbol) and returns a String. It performs the following steps when called:

  1. descsym.[[Description]]
  2. 如果 descundefined,将 desc 设为空字符串。
  3. 断言:desc 是一个字符串。
  4. 返回字符串拼接 "Symbol(", desc, 和 ")" 的结果。

20.4.3.4 Symbol.prototype.valueOf ( )

调用此方法时执行下列步骤:

  1. 返回 ? ThisSymbolValue(this value)。

20.4.3.4.1 ThisSymbolValue ( value )

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

  1. 如果 value 是一个 Symbol,返回 value
  2. 如果 value 是一个 Object 且 value[[SymbolData]] 内部槽,则
    1. svalue.[[SymbolData]]
    2. 断言:s 是一个 Symbol。
    3. 返回 s
  3. 抛出 TypeError 异常。

20.4.3.5 Symbol.prototype [ %Symbol.toPrimitive% ] ( hint )

ECMAScript 语言操作符调用此方法以将 Symbol 对象转换为原始值。

调用时执行下列步骤:

  1. 返回 ? ThisSymbolValue(this value)。
Note

该参数会被忽略。

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

此方法的 "name" 属性值为 "[Symbol.toPrimitive]"

20.4.3.6 Symbol.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值为字符串 "Symbol"

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

20.4.4 Symbol 实例的属性

Symbol 实例是普通对象,从 Symbol 原型对象继承属性。Symbol 实例具有一个 [[SymbolData]] 内部槽。[[SymbolData]] 内部槽是该 Symbol 对象所表示的 Symbol 值。

20.4.5 关于符号的抽象操作

20.4.5.1 KeyForSymbol ( sym )

The abstract operation KeyForSymbol takes argument sym (a Symbol) and returns a String or undefined. 如果 symGlobalSymbolRegistry 列表中,则返回用于注册 sym 的字符串。 It performs the following steps when called:

  1. GlobalSymbolRegistry 列表的每个元素 e 执行
    1. 如果 SameValue(e.[[Symbol]], sym) 为 true,返回 e.[[Key]]
  2. 断言:GlobalSymbolRegistry 列表当前不包含用于 sym 的条目。
  3. 返回 undefined

20.5 Error 对象

Error 对象的实例在运行时错误发生时被作为异常抛出。Error 对象也可作为用户定义异常类的基对象。

当 ECMAScript 实现检测到运行时错误时,会抛出下列 20.5.5 中定义的某一 NativeError 对象的一个新实例,或 20.5.7 中定义的 AggregateError 对象的一个新实例。

20.5.1 Error 构造函数

Error 构造函数:

  • %Error%
  • 全局对象"Error" 属性的初始值。
  • 当作为函数而非构造函数调用时创建并初始化一个新的 Error 对象。因此函数调用 Error(…) 等价于使用相同参数的对象创建表达式 new Error(…)
  • 可用作类定义的 extends 子句的值。打算继承指定 Error 行为的子类构造函数必须包含对 Error 构造函数的 super 调用,以创建并初始化具有 [[ErrorData]] 内部槽的子类实例。

20.5.1.1 Error ( message [ , options ] )

调用此函数时执行下列步骤:

  1. 如果 NewTarget 为 undefined,令 newTarget活动函数对象;否则令 newTarget 为 NewTarget。
  2. obj 为 ? OrdinaryCreateFromConstructor(newTarget, "%Error.prototype%", « [[ErrorData]] »)。
  3. 如果 message 不是 undefined,则
    1. msg 为 ? ToString(message)。
    2. 执行 CreateNonEnumerableDataPropertyOrThrow(obj, "message", msg)。
  4. 执行 ? InstallErrorCause(obj, options)。
  5. 返回 obj

20.5.2 Error 构造函数的属性

Error 构造函数:

20.5.2.1 Error.isError ( arg )

调用此函数时执行下列步骤:

  1. 如果 arg 不是一个 Object,返回 false
  2. 如果 arg 不具有 [[ErrorData]] 内部槽,返回 false
  3. 返回 true

20.5.2.2 Error.prototype

Error.prototype 的初始值为 Error 原型对象

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.5.3 Error 原型对象的属性

Error 原型对象

  • %Error.prototype%
  • 是一个普通对象
  • 不是 Error 实例且不具有 [[ErrorData]] 内部槽。
  • 有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%

20.5.3.1 Error.prototype.constructor

Error.prototype.constructor 的初始值为 %Error%

20.5.3.2 Error.prototype.message

Error.prototype.message 的初始值为空字符串。

20.5.3.3 Error.prototype.name

Error.prototype.name 的初始值为 "Error"

20.5.3.4 Error.prototype.toString ( )

调用此方法时执行下列步骤:

  1. objthis 值。
  2. 如果 obj 不是一个 Object,抛出 TypeError 异常。
  3. name 为 ? Get(obj, "name")。
  4. 如果 nameundefined,将 name 设为 "Error";否则将 name 设为 ? ToString(name)。
  5. msg 为 ? Get(obj, "message")。
  6. 如果 msgundefined,将 msg 设为空字符串;否则将 msg 设为 ? ToString(msg)。
  7. 如果 name 是空字符串,返回 msg
  8. 如果 msg 是空字符串,返回 name
  9. 返回字符串拼接 name、代码单元 0x003A (COLON)、代码单元 0x0020 (SPACE) 与 msg 的结果。

20.5.4 Error 实例的属性

Error 实例是普通对象,从 Error 原型对象继承属性并具有一个值为 undefined[[ErrorData]] 内部槽。[[ErrorData]] 的唯一指定用途是将 Error、AggregateError 与 NativeError 实例在 Object.prototype.toStringError.isError 中识别为 Error 对象。

20.5.5 本规范中使用的原生错误类型

当检测到运行时错误时,会抛出下列某个 NativeError 对象或 AggregateError 对象的新实例。所有 NativeError 对象具有相同的结构,如 20.5.6 所述。

20.5.5.1 EvalError

EvalError 构造函数为 %EvalError%

本异常当前在本规范中未被使用。该对象保留以兼容规范的早期版本。

20.5.5.2 RangeError

RangeError 构造函数为 %RangeError%

表示值不在允许值集合或范围内。

20.5.5.3 ReferenceError

ReferenceError 构造函数为 %ReferenceError%

表示检测到无效引用。

20.5.5.4 SyntaxError

SyntaxError 构造函数为 %SyntaxError%

表示发生了解析错误。

20.5.5.5 TypeError

TypeError 构造函数为 %TypeError%

当没有其它 NativeError 对象适当地指示失败原因时,TypeError 用于表示操作失败。

20.5.5.6 URIError

URIError 构造函数为 %URIError%

表示某个全局 URI 处理函数以与其定义不兼容的方式使用。

20.5.6 NativeError 对象结构

这些对象中的每个具有下述所示的结构,仅在构造函数名和原型对象的 "name" 属性字符串值上有所不同。

对于每个错误对象,定义中对 NativeError 的引用应替换为 20.5.5 中相应的错误对象名称。

20.5.6.1 NativeError 构造函数

每个 NativeError 构造函数:

  • 当作为函数而非构造函数调用时会创建并初始化一个新的 NativeError 对象。作为函数调用对象等价于用相同参数调用其作为构造函数。因此函数调用 NativeError(…) 等价于对象创建表达式 new NativeError(…)
  • 可用作类定义的 extends 子句的值。打算继承指定 NativeError 行为的子类构造函数必须包含对 NativeError 构造函数的 super 调用,以创建并初始化具有 [[ErrorData]] 内部槽的子类实例。

20.5.6.1.1 NativeError ( message [ , options ] )

每个 NativeError 函数在被调用时执行下列步骤:

  1. 如果 NewTarget 为 undefined,令 newTarget活动函数对象;否则令 newTarget 为 NewTarget。
  2. obj 为 ? OrdinaryCreateFromConstructor(newTarget, "%NativeError.prototype%", « [[ErrorData]] »)。
  3. 如果 message 不是 undefined,则
    1. msg 为 ? ToString(message)。
    2. 执行 CreateNonEnumerableDataPropertyOrThrow(obj, "message", msg)。
  4. 执行 ? InstallErrorCause(obj, options)。
  5. 返回 obj

在步骤 2 中传入的字符串实际值为 "%EvalError.prototype%""%RangeError.prototype%""%ReferenceError.prototype%""%SyntaxError.prototype%""%TypeError.prototype%""%URIError.prototype%" 中对应的那一项,取决于正在定义的是哪个 NativeError 构造函数。

20.5.6.2 NativeError 构造函数的属性

每个 NativeError 构造函数:

  • 具有一个 [[Prototype]] 内部槽,其值为 %Error%
  • 具有 "name" 属性,其值为字符串 "NativeError"
  • 具有下列属性:

20.5.6.2.1 NativeError.prototype

NativeError.prototype 的初始值是一个 NativeError 原型对象(参见 20.5.6.3)。每个 NativeError 构造函数都有一个不同的原型对象。

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.5.6.3 NativeError 原型对象的属性

每个 NativeError 原型对象

  • 是一个普通对象
  • 不是 Error 实例且不具有 [[ErrorData]] 内部槽。
  • 有一个 [[Prototype]] 内部槽,其值为 %Error.prototype%

20.5.6.3.1 NativeError.prototype.constructor

给定 NativeError 构造函数的原型的 "constructor" 属性的初始值为该构造函数本身。

20.5.6.3.2 NativeError.prototype.message

给定 NativeError 构造函数的原型的 "message" 属性的初始值为空字符串。

20.5.6.3.3 NativeError.prototype.name

给定 NativeError 构造函数的原型的 "name" 属性的初始值为构造函数的名称(用于替代 NativeError 的名称)。

20.5.6.4 NativeError 实例的属性

NativeError 实例是普通对象,从其 NativeError 原型对象继承属性,并且具有一个值为 undefined[[ErrorData]] 内部槽。[[ErrorData]] 的唯一指定用途是由 Object.prototype.toString (20.1.3.6) 与 Error.isError (20.5.2.1) 用来识别 Error、AggregateError 或 NativeError 实例。

20.5.7 AggregateError 对象

20.5.7.1 AggregateError 构造函数

AggregateError 构造函数:

  • %AggregateError%
  • 全局对象"AggregateError" 属性的初始值。
  • 当作为函数而非构造函数调用时会创建并初始化一个新的 AggregateError 对象。因此函数调用 AggregateError(…) 等价于使用相同参数的对象创建表达式 new AggregateError(…)
  • 可用作类定义的 extends 子句的值。打算继承指定 AggregateError 行为的子类构造函数必须包含对 AggregateError 构造函数的 super 调用,以创建并初始化具有 [[ErrorData]] 内部槽的子类实例。

20.5.7.1.1 AggregateError ( errors, message [ , options ] )

调用此函数时执行下列步骤:

  1. 如果 NewTarget 为 undefined,令 newTarget活动函数对象;否则令 newTarget 为 NewTarget。
  2. obj 为 ? OrdinaryCreateFromConstructor(newTarget, "%AggregateError.prototype%", « [[ErrorData]] »)。
  3. 如果 message 不是 undefined,则
    1. msg 为 ? ToString(message)。
    2. 执行 CreateNonEnumerableDataPropertyOrThrow(obj, "message", msg)。
  4. 执行 ? InstallErrorCause(obj, options)。
  5. errorsList 为 ? IteratorToList(? GetIterator(errors, sync))。
  6. 执行 ! DefinePropertyOrThrow(obj, "errors", PropertyDescriptor { [[Configurable]]: true, [[Enumerable]]: false, [[Writable]]: true, [[Value]]: CreateArrayFromList(errorsList) })。
  7. 返回 obj

20.5.7.2 AggregateError 构造函数的属性

AggregateError 构造函数:

  • 具有一个 [[Prototype]] 内部槽,其值为 %Error%
  • 具有下列属性:

20.5.7.2.1 AggregateError.prototype

AggregateError.prototype 的初始值为 %AggregateError.prototype%

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.5.7.3 AggregateError 原型对象的属性

AggregateError 原型对象

  • %AggregateError.prototype%
  • 是一个普通对象
  • 既不是 Error 实例也不是 AggregateError 实例,且不具有 [[ErrorData]] 内部槽。
  • 有一个 [[Prototype]] 内部槽,其值为 %Error.prototype%

20.5.7.3.1 AggregateError.prototype.constructor

AggregateError.prototype.constructor 的初始值为 %AggregateError%

20.5.7.3.2 AggregateError.prototype.message

AggregateError.prototype.message 的初始值为空字符串。

20.5.7.3.3 AggregateError.prototype.name

AggregateError.prototype.name 的初始值为 "AggregateError"

20.5.7.4 AggregateError 实例的属性

AggregateError 实例是普通对象,从其 AggregateError 原型对象继承属性,并具有一个值为 undefined[[ErrorData]] 内部槽。[[ErrorData]] 的唯一指定用途是由 Object.prototype.toString (20.1.3.6) 与 Error.isError (20.5.2.1) 用来识别 Error、AggregateError 或 NativeError 实例。

20.5.8 Error 对象的抽象操作

20.5.8.1 InstallErrorCause ( obj, options )

The abstract operation InstallErrorCause takes arguments obj (an Object) and options (an ECMAScript language value) and returns either a normal completion containing unused or a throw completion. 当 options 上存在 "cause" 属性时,用于在 obj 上创建一个 "cause" 属性。 It performs the following steps when called:

  1. 如果 options 是一个 Object 且 ? HasProperty(options, "cause") 为 true,则
    1. cause 为 ? Get(options, "cause")。
    2. 执行 CreateNonEnumerableDataPropertyOrThrow(obj, "cause", cause)。
  2. 返回 unused

21 数字与日期

21.1 Number 对象

21.1.1 Number 构造函数

Number 构造函数:

  • %Number%
  • 全局对象"Number" 属性的初始值。
  • 当作为构造函数调用时,会创建并初始化一个新的 Number 对象。
  • 当作为函数而非构造函数调用时,会执行类型转换。
  • 可用作类定义的 extends 子句的值。打算继承指定 Number 行为的子类构造函数必须包含对 Number 构造函数的 super 调用,以创建并初始化具有 [[NumberData]] 内部槽的子类实例。

21.1.1.1 Number ( value )

调用此函数时执行下列步骤:

  1. 如果存在 value,则
    1. prim 为 ? ToNumeric(value)。
    2. 如果 prim 是 BigInt,令 n𝔽((prim))。
    3. 否则,令 nprim
  2. 否则,
    1. n+0𝔽
  3. 如果 NewTarget 为 undefined,则返回 n
  4. obj 为 ? OrdinaryCreateFromConstructor(NewTarget, "%Number.prototype%", « [[NumberData]] »)。
  5. obj.[[NumberData]] 设为 n
  6. 返回 obj

21.1.2 Number 构造函数的属性

Number 构造函数:

21.1.2.1 Number.EPSILON

Number.EPSILON 的值是表示 1 与可以作为 Number 值表示的比 1 稍大的最小值之间差值幅度的 Number 值,约为 2.2204460492503130808472633361816 × 10-16

此属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.1.2.2 Number.isFinite ( number )

调用此函数时执行下列步骤:

  1. 如果 number 不是 Number,返回 false
  2. 如果 number 不是有限值,返回 false
  3. 返回 true

21.1.2.3 Number.isInteger ( number )

调用此函数时执行下列步骤:

  1. 如果 number 是整型 Number,则返回 true
  2. 返回 false

21.1.2.4 Number.isNaN ( number )

调用此函数时执行下列步骤:

  1. 如果 number 不是 Number,返回 false
  2. 如果 numberNaN,返回 true
  3. 返回 false
Note

此函数不同于全局的 isNaN 函数(19.2.3),因为它在判断参数是否为 NaN 之前不会将其转换为 Number。

21.1.2.5 Number.isSafeInteger ( number )

Note

整数 n 当且仅当对应的 Number 值不等于任何其它整数Number 值时,称为“安全整数safe integer

调用此函数时执行下列步骤:

  1. 如果 number 是整型 Number,则
    1. 如果 abs((number)) ≤ 253 - 1,返回 true
  2. 返回 false

21.1.2.6 Number.MAX_SAFE_INTEGER

Note

由于 IEEE 754-2019 的精度限制导致的舍入行为,每个大于 Number.MAX_SAFE_INTEGER整数Number 值都与至少另一个整数共享相同的 Number 值。因此,此类大幅度整数并非 安全,不能保证能够被精确地表示为 Number 值,甚至不能保证彼此可区分。例如,90071992547409929007199254740993 的计算结果均为 Number 值 9007199254740992𝔽

Number.MAX_SAFE_INTEGER 的值为 9007199254740991𝔽 (𝔽(253 - 1))。

此属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.1.2.7 Number.MAX_VALUE

Number.MAX_VALUE 的值是 Number 类型的最大正有限值,约为 1.7976931348623157 × 10308

此属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.1.2.8 Number.MIN_SAFE_INTEGER

Note

由于 IEEE 754-2019 的精度限制导致的舍入行为,每个小于 Number.MIN_SAFE_INTEGER整数Number 值都与至少另一个整数共享相同的 Number 值。因此,此类大幅度整数并非 安全,不能保证能够被精确地表示为 Number 值,甚至不能保证彼此可区分。例如,-9007199254740992-9007199254740993 的计算结果均为 Number 值 -9007199254740992𝔽

Number.MIN_SAFE_INTEGER 的值为 -9007199254740991𝔽 (𝔽(-(253 - 1)))。

此属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.1.2.9 Number.MIN_VALUE

Number.MIN_VALUE 的值是 Number 类型的最小正值,约为 5 × 10-324

IEEE 754-2019 的双精度二进制表示中,最小可能值是一个非规格化(denormalized)数。如果实现不支持非规格化值,则 Number.MIN_VALUE 的值必须是实现实际能够表示的最小非零正值。

此属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.1.2.10 Number.NaN

Number.NaN 的值是 NaN

此属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.1.2.11 Number.NEGATIVE_INFINITY

Number.NEGATIVE_INFINITY 的值是 -∞𝔽

此属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.1.2.12 Number.parseFloat ( string )

"parseFloat" 属性的初始值为 %parseFloat%

21.1.2.13 Number.parseInt ( string, radix )

"parseInt" 属性的初始值为 %parseInt%

21.1.2.14 Number.POSITIVE_INFINITY

Number.POSITIVE_INFINITY 的值是 +∞𝔽

此属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.1.2.15 Number.prototype

Number.prototype 的初始值为 Number 原型对象

此属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.1.3 Number 原型对象的属性

Number 原型对象

  • %Number.prototype%
  • 是一个普通对象
  • 自身是一个 Number 对象;它具有一个值为 +0𝔽[[NumberData]] 内部槽。
  • 有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%

除非另有明确说明,下面定义的 Number 原型对象的方法不是通用的,传递给它们的 this 值必须是一个 Number 值或一个已将 [[NumberData]] 内部槽初始化为 Number 值的对象。

在方法规范中短语“this Number value”指的是通过调用抽象操作 ThisNumberValue 并将方法调用的 this 值作为参数传入时返回的结果。

21.1.3.1 Number.prototype.constructor

Number.prototype.constructor 的初始值为 %Number%

21.1.3.2 Number.prototype.toExponential ( fractionDigits )

此方法返回一个字符串,其中包含该 Number 值以十进制指数记法表示的形式:在有效数字的小数点前有 1 位数字,并在小数点后有 fractionDigits 位数字。如果 fractionDigitsundefined,则包含足够的有效数字以唯一指定该 Number(类似 ToString,但在此情况下一律以指数表示法输出 Number)。

调用时执行下列步骤:

  1. numberValue 为 ? ThisNumberValue(this value)。
  2. fractionCount 为 ? ToIntegerOrInfinity(fractionDigits)。
  3. 断言:如果 fractionDigitsundefined,则 fractionCount 为 0。
  4. 如果 numberValue 不是有限值,返回 Number::toString(numberValue, 10)。
  5. 如果 fractionCount < 0 或 fractionCount > 100,抛出 RangeError 异常。
  6. numberValue 设为 (numberValue)。
  7. sign 为空字符串。
  8. 如果 numberValue < 0,则
    1. sign 设为 "-"
    2. numberValue 设为 -numberValue
  9. 如果 numberValue = 0,则
    1. significand 为由 fractionCount + 1 个代码单元 0x0030 (DIGIT ZERO) 组成的字符串值。
    2. exponent 为 0。
  10. 否则,
    1. 如果 fractionDigits 不是 undefined,则
      1. exponentintSignificand 为满足 10fractionCountintSignificand < 10fractionCount + 1 且使 intSignificand × 10exponent - fractionCount - numberValue 尽可能接近零的整数。如果存在两组这样的 exponentintSignificand,选择使 intSignificand × 10exponent - fractionCount 更大的那组 exponentintSignificand
    2. 否则,
      1. exponentintSignificandff 为满足 ff ≥ 0、10ffintSignificand < 10ff + 1𝔽(intSignificand × 10exponent - ff) 为 𝔽(numberValue) 且 ff 尽可能小的整数。注意 intSignificand 的十进制表示具有 ff + 1 位数,intSignificand 不可被 10 整除,并且 intSignificand 的最低有效位不一定可由这些条件唯一确定。
      2. fractionCount 设为 ff
    3. significand 为由 intSignificand 的十进制表示的数字(按顺序,无前导零)组成的字符串值。
  11. 如果 fractionCount ≠ 0,则
    1. integerPartsignificand 的第一个代码单元。
    2. fractionalPartsignificand 的其余 fractionCount 个代码单元。
    3. significand 设为 integerPart"."fractionalPart字符串连接
  12. 如果 exponent = 0,则
    1. exponentSign"+"
    2. exponentDigits"0"
  13. 否则,
    1. 如果 exponent > 0,则
      1. exponentSign"+"
    2. 否则,
      1. 断言:exponent < 0。
      2. exponentSign"-"
      3. exponent 设为 -exponent
    3. exponentDigits 为由 exponent 的十进制表示的数字(按顺序,无前导零)组成的字符串值。
  14. significand 设为 significand"e"exponentSignexponentDigits字符串连接
  15. 返回 signsignificand字符串连接
Note

对于提供比上述规则更精确转换的实现,建议(但标准不规定)在作为指引的情况下使用如下替代的第 10.b.i 步的版本:

  1. exponentintSignificandff 为满足 ff ≥ 0、10ffintSignificand < 10ff + 1𝔽(intSignificand × 10exponent - ff) 为 𝔽(numberValue) 且 ff 尽可能小的整数。如果对于 intSignificand 存在多种可能性,选择使 𝔽(intSignificand × 10exponent - ff) 最接近 𝔽(numberValue) 的 intSignificand。如果存在两个此类可能的 intSignificand 值,则选择偶数值。

21.1.3.3 Number.prototype.toFixed ( fractionDigits )

Note 1

此方法返回一个字符串,其中包含该 Number 值以十进制定点记法表示的形式,在小数点后有 fractionDigits 位。如果 fractionDigitsundefined,则假定为 0。

调用时执行下列步骤:

  1. numberValue 为 ? ThisNumberValue(this value)。
  2. fractionCount 为 ? ToIntegerOrInfinity(fractionDigits)。
  3. 断言:如果 fractionDigitsundefined,则 fractionCount 为 0。
  4. 如果 fractionCount 不是有限值,抛出 RangeError 异常。
  5. 如果 fractionCount < 0 或 fractionCount > 100,抛出 RangeError 异常。
  6. 如果 numberValue 不是有限值,返回 Number::toString(numberValue, 10)。
  7. numberValue 设为 (numberValue)。
  8. sign 为空字符串。
  9. 如果 numberValue < 0,则
    1. sign 设为 "-"
    2. numberValue 设为 -numberValue
  10. 如果 numberValue ≥ 1021,则
    1. digitString 为 ! ToString(𝔽(numberValue))。
  11. 否则,
    1. intValue 为一个整数,使 intValue / 10fractionCount - numberValue 尽可能接近零。如果有两个这样的 intValue,选择较大的 intValue
    2. 如果 intValue = 0,则令 digitString"0";否则令 digitString 为由 intValue 的十进制表示的数字组成的字符串值(按顺序,无前导零)。
    3. 如果 fractionCount ≠ 0,则
      1. digitCountdigitString 的长度。
      2. 如果 digitCountfractionCount,则
        1. zeroPad 为由 fractionCount + 1 - digitCount 个代码单元 0x0030 (DIGIT ZERO) 组成的字符串值。
        2. digitString 设为 zeroPaddigitString字符串连接
        3. digitCount 设为 fractionCount + 1。
      3. integerPartdigitString 的前 digitCount - fractionCount 个代码单元。
      4. fractionalPartdigitString 的其余 fractionCount 个代码单元。
      5. digitString 设为 integerPart"."fractionalPart字符串连接
  12. 返回 signdigitString字符串连接
Note 2

对于某些值,toFixed 的输出可能比 toString 更精确,因为 toString 只打印足以将该数与相邻的 Number 值区分开的有效数字。例如,

(1000000000000000128).toString() 返回 "1000000000000000100", while
(1000000000000000128).toFixed(0) returns "1000000000000000128".

21.1.3.4 Number.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] )

包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按照 ECMA-402 规范实现此方法。如果实现不包含 ECMA-402 API,则使用以下对该方法的规范:

此方法生成一个字符串值,表示根据宿主环境当前区域设置约定格式化的该 Number 值。该方法由实现定义,并且允许(但不鼓励)返回与 toString 相同的内容。

对于此方法的可选参数的含义在 ECMA-402 规范中定义;不包含 ECMA-402 支持的实现不得将这些参数位置用于其他目的。

21.1.3.5 Number.prototype.toPrecision ( precision )

此方法返回一个字符串,其中包含该 Number 值表示为十进制指数记法(在有效数字的小数点前有一位且小数点后有 precision - 1 位)或以十进制定点记法表示为具有 precision 个有效数字的形式。如果 precisionundefined,则调用 ToString

调用时执行下列步骤:

  1. numberValue 为 ? ThisNumberValue(this value)。
  2. 如果 precisionundefined,返回 ! ToString(numberValue)。
  3. precisionCount 为 ? ToIntegerOrInfinity(precision)。
  4. 如果 numberValue 不是有限值,返回 Number::toString(numberValue, 10)。
  5. 如果 precisionCount < 1 或 precisionCount > 100,抛出 RangeError 异常。
  6. numberValue 设为 (numberValue)。
  7. sign 为空字符串。
  8. 如果 numberValue < 0,则
    1. sign 设为代码单元 0x002D (HYPHEN-MINUS)。
    2. numberValue 设为 -numberValue
  9. 如果 numberValue = 0,则
    1. significand 为由 precisionCount 个代码单元 0x0030 (DIGIT ZERO) 组成的字符串值。
    2. exponent 为 0。
  10. 否则,
    1. exponentintSignificand 为满足 10precisionCount - 1intSignificand < 10precisionCount 且使 intSignificand × 10exponent - precisionCount + 1 - numberValue 尽可能接近零的整数。如果存在两组这样的 exponentintSignificand,选择使 intSignificand × 10exponent - precisionCount + 1 更大的那组 exponentintSignificand
    2. significand 为由 intSignificand 的十进制表示的数字(按顺序,无前导零)组成的字符串值。
    3. 如果 exponent < -6 或 exponentprecisionCount,则
      1. 断言:exponent ≠ 0。
      2. 如果 precisionCount ≠ 1,则
        1. integerPartsignificand 的第一个代码单元。
        2. fractionalPartsignificand 的其余 precisionCount - 1 个代码单元。
        3. significand 设为 integerPart"."fractionalPart字符串连接
      3. 如果 exponent > 0,则
        1. exponentSign 为代码单元 0x002B (PLUS SIGN)。
      4. 否则,
        1. 断言:exponent < 0。
        2. exponentSign 为代码单元 0x002D (HYPHEN-MINUS)。
        3. exponent 设为 -exponent
      5. exponentDigits 为由 exponent 的十进制表示的数字(按顺序,无前导零)组成的字符串值。
      6. 返回 signsignificand、代码单元 0x0065 (LATIN SMALL LETTER E)、exponentSignexponentDigits字符串连接
  11. 如果 exponent = precisionCount - 1,返回 signsignificand字符串连接
  12. 如果 exponent ≥ 0,则
    1. significand 设为由 significand 的前 exponent + 1 个代码单元、代码单元 0x002E (FULL STOP) 和剩余的 precisionCount - (exponent + 1) 个代码单元组成的字符串连接
  13. 否则,
    1. significand 设为代码单元 0x0030 (DIGIT ZERO)、代码单元 0x002E (FULL STOP)、-(exponent + 1) 个代码单元 0x0030 (DIGIT ZERO) 以及字符串 significand字符串连接
  14. 返回 signsignificand字符串连接

21.1.3.6 Number.prototype.toString ( [ radix ] )

Note

可选的 radix 应为包含在闭区间 2𝔽36𝔽 内的整数 Number 值。如果 radixundefined,则使用 10𝔽 作为 radix 的值。

调用此方法时执行下列步骤:

  1. x 为 ? ThisNumberValue(this value)。
  2. 如果 radixundefined,令 radixMV 为 10。
  3. 否则,令 radixMV 为 ? ToIntegerOrInfinity(radix)。
  4. 如果 radixMV 不在 2 到 36 的闭区间内,抛出 RangeError 异常。
  5. 返回 Number::toString(x, radixMV)。

此方法不是通用的;如果其 this 值既不是 Number 也不是 Number 对象,则抛出 TypeError 异常。因此,不能将其转移给其他类型的对象来作为方法使用。

此方法的 "length" 属性为 1𝔽

21.1.3.7 Number.prototype.valueOf ( )

  1. 返回 ? ThisNumberValue(this value)。

21.1.3.7.1 ThisNumberValue ( value )

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

  1. 如果 value 是一个 Number,返回 value
  2. 如果 value 是一个对象且 value 拥有 [[NumberData]] 内部槽,则
    1. nvalue.[[NumberData]]
    2. 断言:n 是一个 Number。
    3. 返回 n
  3. 抛出 TypeError 异常。

21.1.4 Number 实例的属性

Number 实例是普通对象,从 Number 原型对象继承属性。Number 实例也具有一个 [[NumberData]] 内部槽。[[NumberData]] 内部槽是该 Number 对象所表示的 Number 值

21.2 BigInt 对象

21.2.1 BigInt 构造函数

BigInt 构造函数:

  • %BigInt%
  • 全局对象"BigInt" 属性的初始值。
  • 当作为函数而非构造函数调用时执行类型转换。
  • 不应与 new 操作符一起使用,也不应被子类化。它可用作类定义的 extends 子句的值,但对其的 super 调用会导致异常。

21.2.1.1 BigInt ( value )

调用此函数时执行下列步骤:

  1. 如果 NewTarget 不是 undefined,抛出 TypeError 异常。
  2. prim 为 ? ToPrimitive(value, number)。
  3. 如果 prim 是一个 Number,返回 ? NumberToBigInt(prim)。
  4. 返回 ? ToBigInt(prim)。

21.2.1.1.1 NumberToBigInt ( number )

The abstract operation NumberToBigInt takes argument number (a Number) and returns either a normal completion containing a BigInt or a throw completion. It performs the following steps when called:

  1. 如果 number 不是整型 Number,抛出 RangeError 异常。
  2. 返回 ((number))。

21.2.2 BigInt 构造函数的属性

BigInt 构造函数:

21.2.2.1 BigInt.asIntN ( bits, bigint )

调用此函数时执行下列步骤:

  1. bits 设为 ? ToIndex(bits)。
  2. bigint 设为 ? ToBigInt(bigint)。
  3. mod(bigint) 模 2bits
  4. 如果 mod ≥ 2bits - 1,返回 (mod - 2bits)。
  5. 返回 (mod)。

21.2.2.2 BigInt.asUintN ( bits, bigint )

调用此函数时执行下列步骤:

  1. bits 设为 ? ToIndex(bits)。
  2. bigint 设为 ? ToBigInt(bigint)。
  3. 返回 ((bigint) 模 2bits)。

21.2.2.3 BigInt.prototype

BigInt.prototype 的初始值为 BigInt 原型对象

此属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.2.3 BigInt 原型对象的属性

BigInt 原型对象

  • %BigInt.prototype%
  • 是一个普通对象
  • 不是 BigInt 对象;它不具有 [[BigIntData]] 内部槽。
  • 有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%

在方法规范中短语“this BigInt value”指的是通过调用抽象操作 ThisBigIntValue 并将方法调用的 this 值作为参数传入时返回的结果。

21.2.3.1 BigInt.prototype.constructor

BigInt.prototype.constructor 的初始值为 %BigInt%

21.2.3.2 BigInt.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] )

包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按照 ECMA-402 规范实现此方法。如果实现不包含 ECMA-402 API,则使用以下对该方法的规范:

此方法生成一个字符串值,表示根据宿主环境当前区域设置约定格式化的该 BigInt 值。该方法由实现定义,并且允许(但不鼓励)返回与 toString 相同的内容。

对于此方法的可选参数的含义在 ECMA-402 规范中定义;不包含 ECMA-402 支持的实现不得将这些参数位置用于其他目的。

21.2.3.3 BigInt.prototype.toString ( [ radix ] )

Note

可选的 radix 应为包含在闭区间 2𝔽36𝔽 内的整数 Number 值。如果 radixundefined,则使用 10𝔽 作为 radix 的值。

调用此方法时执行下列步骤:

  1. x 为 ? ThisBigIntValue(this value)。
  2. 如果 radixundefined,令 radixMV 为 10。
  3. 否则,令 radixMV 为 ? ToIntegerOrInfinity(radix)。
  4. 如果 radixMV 不在 2 到 36 的闭区间内,抛出 RangeError 异常。
  5. 返回 BigInt::toString(x, radixMV)。

此方法不是通用的;如果其 this 值既不是 BigInt 也不是 BigInt 对象,则抛出 TypeError 异常。因此,不能将其转移给其他类型的对象来作为方法使用。

21.2.3.4 BigInt.prototype.valueOf ( )

  1. 返回 ? ThisBigIntValue(this value)。

21.2.3.4.1 ThisBigIntValue ( value )

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

  1. 如果 value 是一个 BigInt,返回 value
  2. 如果 value 是一个对象且 value 拥有 [[BigIntData]] 内部槽,则
    1. 断言:value.[[BigIntData]] 是一个 BigInt。
    2. 返回 value.[[BigIntData]]
  3. 抛出 TypeError 异常。

21.2.3.5 BigInt.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值为字符串 "BigInt"

此属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

21.2.4 BigInt 实例的属性

BigInt 实例是普通对象,从 BigInt 原型对象继承属性。BigInt 实例也具有一个 [[BigIntData]] 内部槽。[[BigIntData]] 内部槽是该 BigInt 对象所表示的 BigInt 值

21.3 Math 对象

Math 对象:

  • %Math%
  • 全局对象"Math" 属性的初始值。
  • 是一个普通对象
  • 有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%
  • 不是一个函数对象
  • 没有 [[Construct]] 内部方法;不能用 new 操作符作为构造函数使用。
  • 没有 [[Call]] 内部方法;不能被当作函数调用。
Note

在本规范中,短语“x 的 Number 值”具有在 6.1.6.1 中定义的技术含义。

21.3.1 Math 对象的数值属性

21.3.1.1 Math.E

自然对数的底数 e 的 Number 值,约为 2.7182818284590452354。

此属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.3.1.2 Math.LN10

10 的自然对数的 Number 值,约为 2.302585092994046。

此属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.3.1.3 Math.LN2

2 的自然对数的 Number 值,约为 0.6931471805599453。

此属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.3.1.4 Math.LOG10E

e 的以 10 为底的对数的 Number 值;该值约为 0.4342944819032518。

此属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

Note

Math.LOG10E 的值约等于 Math.LN10 值的倒数。

21.3.1.5 Math.LOG2E

e 的以 2 为底的对数的 Number 值;该值约为 1.4426950408889634。

此属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

Note

Math.LOG2E 的值约等于 Math.LN2 值的倒数。

21.3.1.6 Math.PI

圆周与直径之比 π 的 Number 值,约为 3.1415926535897932。

此属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.3.1.7 Math.SQRT1_2

½ 的平方根的 Number 值,约为 0.7071067811865476。

此属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

Note

Math.SQRT1_2 的值约等于 Math.SQRT2 值的倒数。

21.3.1.8 Math.SQRT2

2 的平方根的 Number 值,约为 1.4142135623730951。

此属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.3.1.9 Math [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值为字符串 "Math"

此属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

21.3.2 Math 对象的函数属性

Note

函数 acos, acosh, asin, asinh, atan, atanh, atan2, cbrt, cos, cosh, exp, expm1, hypot, log, log1p, log2, log10, pow, random, sin, sinh, tan, 和 tanh 的行为在此并未被精确规定,仅要求在一些表示边界情况的参数值上产生特定结果。对于其他参数值,这些函数旨在计算熟悉的数学函数的近似值,但在近似算法的选择上允许具有一定的自由度。总体意图是实现者应当能够在给定硬件平台上对 ECMAScript 使用与该平台上为 C 程序员可用的相同数学库。

虽然算法的选择留给实现,但建议(标准不强制)实现使用 Sun Microsystems 提供的可自由分发数学库 fdlibm 中针对 IEEE 754-2019 算术的近似算法(http://www.netlib.org/fdlibm)。

21.3.2.1 Math.abs ( x )

此函数返回 x 的绝对值;结果具有与 x 相同的幅度但为正号。

调用时执行下列步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN,返回 NaN
  3. 如果 n-0𝔽,返回 +0𝔽
  4. 如果 n-∞𝔽,返回 +∞𝔽
  5. 如果 n < -0𝔽,返回 -n
  6. 返回 n

21.3.2.2 Math.acos ( x )

此函数返回 x 的反余弦。结果以弧度表示,并位于闭区间+0𝔽𝔽(π) 之内。

调用时执行下列步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaNn > 1𝔽,或 n < -1𝔽,返回 NaN
  3. 如果 n1𝔽,返回 +0𝔽
  4. 返回表示 (n) 的反余弦的实现近似的 Number 值

21.3.2.3 Math.acosh ( x )

此函数返回 x 的反双曲余弦。

调用时执行下列步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+∞𝔽,返回 n
  3. 如果 n1𝔽,返回 +0𝔽
  4. 如果 n < 1𝔽,返回 NaN
  5. 返回表示 (n) 的反双曲余弦的实现近似的 Number 值

21.3.2.4 Math.asin ( x )

此函数返回 x 的反正弦。结果以弧度表示,并位于闭区间𝔽(-π / 2) 到 𝔽(π / 2) 之内。

调用时执行下列步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+0𝔽-0𝔽 之一,返回 n
  3. 如果 n > 1𝔽n < -1𝔽,返回 NaN
  4. 返回表示 (n) 的反正弦的实现近似的 Number 值

21.3.2.5 Math.asinh ( x )

此函数返回 x 的反双曲正弦。

调用时执行下列步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 n 不是有限值或 n+0𝔽-0𝔽,则返回 n
  3. 返回表示 (n) 的反双曲正弦的实现近似的 Number 值

21.3.2.6 Math.atan ( x )

此函数返回 x 的反正切。结果以弧度表示,并位于闭区间𝔽(-π / 2) 到 𝔽(π / 2) 之内。

调用时执行下列步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+0𝔽-0𝔽 之一,返回 n
  3. 如果 n+∞𝔽,返回表示 π / 2 的实现近似的 Number 值
  4. 如果 n-∞𝔽,返回表示 -π / 2 的实现近似的 Number 值
  5. 返回表示 (n) 的反正切的实现近似的 Number 值

21.3.2.7 Math.atanh ( x )

此函数返回 x 的反双曲正切。

调用时执行下列步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+0𝔽-0𝔽 之一,返回 n
  3. 如果 n > 1𝔽n < -1𝔽,返回 NaN
  4. 如果 n1𝔽,返回 +∞𝔽
  5. 如果 n-1𝔽,返回 -∞𝔽
  6. 返回表示 (n) 的反双曲正切的实现近似的 Number 值

21.3.2.8 Math.atan2 ( y, x )

此函数返回参数 yx 的商 y / x 的反正切,其结果象限由 yx 的符号决定。注意,对于两参数反正切函数,习惯上并且有意将名为 y 的参数放在第一位,将名为 x 的参数放在第二位。结果以弧度表示,并位于包含 -π 到 +π 的闭区间内。

调用时执行下列步骤:

  1. ny 为 ? ToNumber(y)。
  2. nx 为 ? ToNumber(x)。
  3. 如果 nyNaNnxNaN,返回 NaN
  4. 如果 ny+∞𝔽,则
    1. 如果 nx+∞𝔽,返回表示 π / 4 的实现近似的 Number 值
    2. 如果 nx-∞𝔽,返回表示 3π / 4 的实现近似的 Number 值
    3. 返回表示 π / 2 的实现近似的 Number 值
  5. 如果 ny-∞𝔽,则
    1. 如果 nx+∞𝔽,返回表示 -π / 4 的实现近似的 Number 值
    2. 如果 nx-∞𝔽,返回表示 -3π / 4 的實现近似的 Number 值
    3. 返回表示 -π / 2 的实现近似的 Number 值
  6. 如果 ny+0𝔽,则
    1. 如果 nx > +0𝔽nx+0𝔽,返回 +0𝔽
    2. 返回表示 π 的实现近似的 Number 值
  7. 如果 ny-0𝔽,则
    1. 如果 nx > +0𝔽nx+0𝔽,返回 -0𝔽
    2. 返回表示 -π 的实现近似的 Number 值
  8. 断言:ny有限值并且既不是 +0𝔽 也不是 -0𝔽
  9. 如果 ny > +0𝔽,则
    1. 如果 nx+∞𝔽,返回 +0𝔽
    2. 如果 nx-∞𝔽,返回表示 π 的实现近似的 Number 值
    3. 如果 nx+0𝔽-0𝔽,返回表示 π / 2 的实现近似的 Number 值
  10. 如果 ny < -0𝔽,则
    1. 如果 nx+∞𝔽,返回 -0𝔽
    2. 如果 nx-∞𝔽,返回表示 -π 的实现近似的 Number 值
    3. 如果 nx+0𝔽-0𝔽,返回表示 -π / 2 的实现近似的 Number 值
  11. 断言:nx有限值并且既不是 +0𝔽 也不是 -0𝔽
  12. rabs((ny) / (nx)) 的反正切。
  13. 如果 nx < -0𝔽,则
    1. 如果 ny > +0𝔽,将 r 设为 π - r
    2. 否则,将 r 设为 -π + r
  14. 否则,
    1. 如果 ny < -0𝔽,将 r 设为 -r
  15. 返回表示 r 的实现近似的 Number 值

21.3.2.9 Math.cbrt ( x )

此函数返回 x 的立方根。

调用时执行下列步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 n 不是有限值或 n+0𝔽-0𝔽,返回 n
  3. 返回表示 (n) 的立方根的实现近似的 Number 值

21.3.2.10 Math.ceil ( x )

此函数返回不小于 x 的最小(最接近 -∞)的整数 Number 值。如果 x 已经是整数 Number,则结果为 x

调用时执行下列步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 n 不是有限值或 n+0𝔽-0𝔽,返回 n
  3. 如果 n < -0𝔽n > -1𝔽,返回 -0𝔽
  4. 如果 n 是整型 Number,返回 n
  5. 返回不小于 n 的最小(最接近 -∞)的整数 Number 值。
Note

Math.ceil(x) 的值等于 -Math.floor(-x) 的值。

21.3.2.11 Math.clz32 ( x )

此函数在被调用时执行下列步骤:

  1. n 为 ? ToUint32(x) 的 表示。
  2. pn 的无符号 32 位二进制表示中的前导零位数。
  3. 返回 𝔽(p)。
Note

如果 n+0𝔽-0𝔽,此方法返回 32𝔽。如果 n 的 32 位二进制编码的最高有效位为 1,则此方法返回 +0𝔽

21.3.2.12 Math.cos ( x )

此函数返回 x 的余弦。参数以弧度表示。

调用时执行下列步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 n 不是有限值,返回 NaN
  3. 如果 n+0𝔽-0𝔽,返回 1𝔽
  4. 返回表示 (n) 的余弦的实现近似的 Number 值

21.3.2.13 Math.cosh ( x )

此函数返回 x 的双曲余弦。

调用时执行下列步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN,返回 NaN
  3. 如果 n+∞𝔽-∞𝔽,返回 +∞𝔽
  4. 如果 n+0𝔽-0𝔽,返回 1𝔽
  5. 返回表示 (n) 的双曲余弦的实现近似的 Number 值
Note

Math.cosh(x) 的值等于 (Math.exp(x) + Math.exp(-x)) / 2 的值。

21.3.2.14 Math.exp ( x )

此函数返回 x 的指数函数(e 的 x 次方,其中 e 为自然对数的底数)。

调用时执行下列步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+∞𝔽,返回 n
  3. 如果 n+0𝔽-0𝔽,返回 1𝔽
  4. 如果 n-∞𝔽,返回 +0𝔽
  5. 返回表示 (n) 的指数函数的实现近似的 Number 值

21.3.2.15 Math.expm1 ( x )

此函数返回指数函数减 1 的结果(e 的 x 次方减 1)。该结果以在 x 接近 0 时仍能保持准确的方式计算。

调用时执行下列步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+0𝔽-0𝔽+∞𝔽 之一,返回 n
  3. 如果 n-∞𝔽,返回 -1𝔽
  4. exp(n) 的指数函数。
  5. 返回表示 exp - 1 的实现近似的 Number 值

21.3.2.16 Math.floor ( x )

此函数返回不大于 x 的最大(最接近 +∞)的整数 Number 值。如果 x 已经是整数 Number,则结果为 x

调用时执行下列步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 n 不是有限值或 n+0𝔽-0𝔽,返回 n
  3. 如果 n < 1𝔽n > +0𝔽,返回 +0𝔽
  4. 如果 n 是整型 Number,返回 n
  5. 返回不大于 n 的最大(最接近 +∞)的整数 Number 值。
Note

Math.floor(x) 的值等于 -Math.ceil(-x) 的值。

21.3.2.17 Math.fround ( x )

此函数在被调用时执行下列步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN,返回 NaN
  3. 如果 n+0𝔽-0𝔽+∞𝔽-∞𝔽 之一,返回 n
  4. n32 为使用 roundTiesToEven 模式将 n 转换为 IEEE 754-2019 binary32 格式的结果。
  5. n64 为将 n32 转换为 IEEE 754-2019 binary64 格式的结果。
  6. 返回与 n64 对应的 ECMAScript Number 值

21.3.2.18 Math.f16round ( x )

此函数在被调用时执行下列步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN,返回 NaN
  3. 如果 n+0𝔽-0𝔽+∞𝔽-∞𝔽 之一,返回 n
  4. n16 为使用 roundTiesToEven 模式将 n 转换为 IEEE 754-2019 binary16 格式的结果。
  5. n64 为将 n16 转换为 IEEE 754-2019 binary64 格式的结果。
  6. 返回与 n64 对应的 ECMAScript Number 值
Note

此操作不同于先转为 binary32 然后再转为 binary16,因为可能发生双重舍入:例如,考虑数值 k = 1.00048828125000022204𝔽,对于该数 Math.f16round(k) 为 1.0009765625𝔽,但 Math.f16round(Math.fround(k)) 为 1𝔽

并非所有平台都提供从 binary64 到 binary16 的本地转换支持。有多种库可以提供此功能,包括 MIT 许可的 half 库。或者,也可以先在 roundTiesToEven 下将 binary64 转为 binary32,然后检查该结果是否可能导致不正确的双重舍入。此类情况可通过调整 binary32 值的尾数来显式处理,使其成为在 roundTiesToOdd 下执行初始转换时将产生的值。然后在 roundTiesToEven 下将调整后的值转换为 binary16 即可得到正确值。

21.3.2.19 Math.hypot ( ...args )

给定零个或多个参数,此函数返回其参数的平方和的平方根。

调用时执行下列步骤:

  1. coerced 为一个新的空列表。
  2. 对于 args 的每个元素 arg,执行
    1. n 为 ? ToNumber(arg)。
    2. n 附加到 coerced
  3. 对于 coerced 的每个元素 number,执行
    1. 如果 number+∞𝔽-∞𝔽,返回 +∞𝔽
  4. onlyZerotrue
  5. 对于 coerced 的每个元素 number,执行
    1. 如果 numberNaN,返回 NaN
    2. 如果 number 既不是 +0𝔽 也不是 -0𝔽,将 onlyZero 设为 false
  6. 如果 onlyZerotrue,返回 +0𝔽
  7. 返回表示 coerced 中元素的数学值的平方和的平方根的实现近似的 Number 值

此函数的 "length" 属性为 2𝔽

Note

实现应注意避免在带有两个或更多参数的朴素实现中容易发生的溢出和下溢导致的精度丢失。

21.3.2.20 Math.imul ( x, y )

此函数在被调用时执行下列步骤:

  1. a(? ToUint32(x))。
  2. b(? ToUint32(y))。
  3. product 为 (a × b) 模 232
  4. 如果 product ≥ 231,返回 𝔽(product - 232)。
  5. 返回 𝔽(product)。

21.3.2.21 Math.log ( x )

此函数返回 x 的自然对数。

调用时执行下列步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+∞𝔽,返回 n
  3. 如果 n1𝔽,返回 +0𝔽
  4. 如果 n+0𝔽-0𝔽,返回 -∞𝔽
  5. 如果 n < -0𝔽,返回 NaN
  6. 返回表示 ln((n)) 的实现近似的 Number 值

21.3.2.22 Math.log1p ( x )

此函数返回 1 + x 的自然对数。该结果以在 x 接近 0 时仍能保持准确的方式计算。

调用时执行下列步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+0𝔽-0𝔽+∞𝔽 之一,返回 n
  3. 如果 n-1𝔽,返回 -∞𝔽
  4. 如果 n < -1𝔽,返回 NaN
  5. 返回表示 ln(1 + (n)) 的实现近似的 Number 值

21.3.2.23 Math.log10 ( x )

此函数返回 x 的以 10 为底的对数。

调用时执行下列步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+∞𝔽,返回 n
  3. 如果 n1𝔽,返回 +0𝔽
  4. 如果 n+0𝔽-0𝔽,返回 -∞𝔽
  5. 如果 n < -0𝔽,返回 NaN
  6. 返回表示 log10((n)) 的实现近似的 Number 值

21.3.2.24 Math.log2 ( x )

此函数返回 x 的以 2 为底的对数。

调用时执行下列步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+∞𝔽,返回 n
  3. 如果 n1𝔽,返回 +0𝔽
  4. 如果 n+0𝔽-0𝔽,返回 -∞𝔽
  5. 如果 n < -0𝔽,返回 NaN
  6. 返回表示 log2((n)) 的实现近似的 Number 值

21.3.2.25 Math.max ( ...args )

给定零个或多个参数,此函数对每个参数调用 ToNumber 并返回所得值中的最大值。

调用时执行下列步骤:

  1. coerced 为一个新的空列表。
  2. 对于 args 的每个元素 arg,执行
    1. n 为 ? ToNumber(arg)。
    2. n 附加到 coerced
  3. highest-∞𝔽
  4. 对于 coerced 的每个元素 number,执行
    1. 如果 numberNaN,返回 NaN
    2. 如果 number+0𝔽highest-0𝔽,将 highest 设为 +0𝔽
    3. 如果 number > highest,将 highest 设为 number
  5. 返回 highest
Note

用于确定最大值的比较使用 IsLessThan 算法,但将 +0𝔽 视为大于 -0𝔽

此函数的 "length" 属性为 2𝔽

21.3.2.26 Math.min ( ...args )

给定零个或多个参数,此函数对每个参数调用 ToNumber 并返回所得值中的最小值。

调用时执行下列步骤:

  1. coerced 为一个新的空列表。
  2. 对于 args 的每个元素 arg,执行
    1. n 为 ? ToNumber(arg)。
    2. n 附加到 coerced
  3. lowest+∞𝔽
  4. 对于 coerced 的每个元素 number,执行
    1. 如果 numberNaN,返回 NaN
    2. 如果 number-0𝔽lowest+0𝔽,将 lowest 设为 -0𝔽
    3. 如果 number < lowest,将 lowest 设为 number
  5. 返回 lowest
Note

用于确定最小值的比较使用 IsLessThan 算法,但将 +0𝔽 视为大于 -0𝔽

此函数的 "length" 属性为 2𝔽

21.3.2.27 Math.pow ( base, exponent )

此函数在被调用时执行下列步骤:

  1. base 设为 ? ToNumber(base)。
  2. exponent 设为 ? ToNumber(exponent)。
  3. 返回 Number::exponentiate(base, exponent)。

21.3.2.28 Math.random ( )

此函数返回一个具有正号的 Number 值,>= +0𝔽 且严格小于 1𝔽,该值由实现定义的算法或策略以近似均匀分布随机或伪随机选择。

为不同 realm 创建的每个 Math.random 函数在连续调用时必须产生不同的值序列。

21.3.2.29 Math.round ( x )

此函数返回最接近且为整数Number 值。如果两个整数同样接近 x,结果为更接近 +∞ 的 Number 值。如果 x 已为整数,则结果为 x

调用时执行下列步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 n 不是有限值或 n 是整型 Number,返回 n
  3. 如果 n < 0.5𝔽n > +0𝔽,返回 +0𝔽
  4. 如果 n < -0𝔽n-0.5𝔽,返回 -0𝔽
  5. 返回最接近 n整数 Number 值;在平局情况下偏向接近 +∞ 的值。
Note 1

Math.round(3.5) 返回 4,但 Math.round(-3.5) 返回 -3。

Note 2

Math.round(x) 的值不总是等于 Math.floor(x + 0.5) 的值。当 x-0𝔽x 小于 -0𝔽 但大于等于 -0.5𝔽 时,Math.round(x) 返回 -0𝔽,而 Math.floor(x + 0.5) 返回 +0𝔽。在计算 x + 0.5 时的内部舍入也可能导致 Math.round(x)Math.floor(x + 0.5) 不同。

21.3.2.30 Math.sign ( x )

此函数返回 x 的符号,指示 x 为正、负或零。

调用时执行下列步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+0𝔽-0𝔽 之一,返回 n
  3. 如果 n < -0𝔽,返回 -1𝔽
  4. 返回 1𝔽

21.3.2.31 Math.sin ( x )

此函数返回 x 的正弦。参数以弧度表示。

调用时执行下列步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+0𝔽-0𝔽 之一,返回 n
  3. 如果 n+∞𝔽-∞𝔽,返回 NaN
  4. 返回表示 (n) 的正弦的实现近似的 Number 值

21.3.2.32 Math.sinh ( x )

此函数返回 x 的双曲正弦。

调用时执行下列步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 n 不是有限值或 n+0𝔽-0𝔽,返回 n
  3. 返回表示 (n) 的双曲正弦的实现近似的 Number 值
Note

Math.sinh(x) 的值等于 (Math.exp(x) - Math.exp(-x)) / 2 的值。

21.3.2.33 Math.sqrt ( x )

此函数返回 x 的平方根。

调用时执行下列步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+0𝔽-0𝔽+∞𝔽 之一,返回 n
  3. 如果 n < -0𝔽,返回 NaN
  4. 返回 𝔽((n) 的平方根)。

21.3.2.34 Math.sumPrecise ( items )

给定一个 Number 的可迭代对象,此函数对可迭代对象中的每个值求和并返回它们的总和。如果任一值不是 Number,则抛出 TypeError 异常。

调用时执行下列步骤:

  1. 执行 ? RequireObjectCoercible(items)。
  2. iteratorRecord 为 ? GetIterator(items, sync)。
  3. stateminus-zero
  4. sum 为 0。
  5. count 为 0。
  6. nextnot-started
  7. 重复,直到 nextdone
    1. next 设为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 next 不是 done,则
      1. 如果 count ≥ 253 - 1,则
        1. 注意:此步骤在实践中预计不会达到,仅包含以便实现可依赖输入为“合理大小”而不违反本规范。
        2. errorThrowCompletion(新创建的 RangeError 对象)。
        3. 返回 ? IteratorClose(iteratorRecord, error)。
      2. 如果 next 不是 Number,则
        1. errorThrowCompletion(新创建的 TypeError 对象)。
        2. 返回 ? IteratorClose(iteratorRecord, error)。
      3. nnext
      4. 如果 state 不是 not-a-number,则
        1. 如果 nNaN,则
          1. state 设为 not-a-number
        2. 否则如果 n+∞𝔽,则
          1. 如果 stateminus-infinity,将 state 设为 not-a-number
          2. 否则,将 state 设为 plus-infinity
        3. 否则如果 n-∞𝔽,则
          1. 如果 stateplus-infinity,将 state 设为 not-a-number
          2. 否则,将 state 设为 minus-infinity
        4. 否则如果 n 不是 -0𝔽stateminus-zerofinite,则
          1. state 设为 finite
          2. sum 设为 sum + (n)。
      5. count 设为 count + 1。
  8. 如果 statenot-a-number,返回 NaN
  9. 如果 stateplus-infinity,返回 +∞𝔽
  10. 如果 stateminus-infinity,返回 -∞𝔽
  11. 如果 stateminus-zero,返回 -0𝔽
  12. 返回 𝔽(sum)。
Note

可以通过多种算法在无需任意精度算术的情况下计算 sum 的值。一个此类算法是 Jonathan Richard Shewchuk 在 Adaptive Precision Floating-Point Arithmetic and Fast Robust Geometric Predicates 中给出的 "Grow-Expansion" 算法。一个较新的算法见 "Fast exact summation using small and large superaccumulators",其代码可在 https://gitlab.com/radfordneal/xsum 获取。

21.3.2.35 Math.tan ( x )

此函数返回 x 的正切。参数以弧度表示。

调用时执行下列步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+0𝔽-0𝔽 之一,返回 n
  3. 如果 n+∞𝔽-∞𝔽,返回 NaN
  4. 返回表示 (n) 的正切的实现近似的 Number 值

21.3.2.36 Math.tanh ( x )

此函数返回 x 的双曲正切。

调用时执行下列步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+0𝔽-0𝔽 之一,返回 n
  3. 如果 n+∞𝔽,返回 1𝔽
  4. 如果 n-∞𝔽,返回 -1𝔽
  5. 返回表示 (n) 的双曲正切的实现近似的 Number 值
Note

Math.tanh(x) 的值等于 (Math.exp(x) - Math.exp(-x)) / (Math.exp(x) + Math.exp(-x)) 的值。

21.3.2.37 Math.trunc ( x )

此函数返回数字 x整数部分,去除任何小数位。如果 x 已为整数,则结果为 x

调用时执行下列步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 n 不是有限值或 n+0𝔽-0𝔽,返回 n
  3. 如果 n < 1𝔽n > +0𝔽,返回 +0𝔽
  4. 如果 n < -0𝔽n > -1𝔽,返回 -0𝔽
  5. 返回朝向 +0𝔽 的最接近 n整数 Number 值。

21.4 Date 对象

21.4.1 Date 对象概述与抽象操作定义

下列抽象操作作用于时间值(在 21.4.1.1 中定义)。注意,在每种情况下,如果这些函数的任何参数为 NaN,结果都将为 NaN

21.4.1.1 时间值与时间范围

ECMAScript 中的时间测量类似于 POSIX 中的时间测量,特别是在使用追溯(proleptic)格里高利历、以协调世界时 1970 年 1 月 1 日午夜为 纪元、并且规定每一天恰好包含 86,400 秒(每秒为 1000 毫秒)的定义方面保持一致。

ECMAScript 的 时间值 是一个 Number,要么是表示以毫秒精度的时刻的有限整数,要么是表示无特定时刻的 NaN。如果时间值是 24 × 60 × 60 × 1000 = 86,400,000(即为某整数 d 的 86,400,000 × d)的倍数,则表示该时间值对应的时刻为自纪元起经过 d 个完整 UTC 天后某天开始的瞬间(对于负的 d 则在纪元之前)。每一个其它有限时间值 t 相对于最大的前一个该类倍数的时间值 s 定义,表示在与 s 同一 UTC 日内但在其之后 (t - s) 毫秒处发生的时刻。

时间值不计入 UTC 闰秒——不存在表示正闰秒内瞬间的时间值,并且存在被负闰秒从 UTC 时间线移除的瞬间的时间值。然而,时间值的定义在闰秒边界之外仍然与 UTC 分段对齐,只有在闰秒处存在不连续。

Number 可以精确表示从 -9,007,199,254,740,992 到 9,007,199,254,740,992 的所有整数(参见 21.1.2.821.1.2.6)。时间值支持略小的范围:-8,640,000,000,000,000 到 8,640,000,000,000,000 毫秒。由此得到的支持时间值范围正好为相对于 1970 年 1 月 1 日午夜的 -100,000,000 天到 100,000,000 天。

表示 1970 年 1 月 1 日午夜瞬间的精确时刻的时间值为 +0𝔽

Note

在追溯格里高利历中,闰年精确地是能被 4 整除且要么能被 400 整除要么不能被 100 整除的年份。

追溯格里高利历的 400 年周期包含 97 个闰年。这使得每年的平均天数为 365.2425 天,即 31,556,952,000 毫秒。因此,Number 在毫秒精度下能精确表示的最大范围大约是相对于 1970 年的 -285,426 到 285,426 年。本节所规范的时间值支持的较小范围大约是相对于 1970 年的 -273,790 到 273,790 年。

21.4.1.2 与时间相关的常量

这些常量在下列节的算法中被引用。

HoursPerDay = 24
MinutesPerHour = 60
SecondsPerMinute = 60
msPerSecond = 1000𝔽
msPerMinute = 60000𝔽 = msPerSecond × 𝔽(SecondsPerMinute)
msPerHour = 3600000𝔽 = msPerMinute × 𝔽(MinutesPerHour)
msPerDay = 86400000𝔽 = msPerHour × 𝔽(HoursPerDay)

21.4.1.3 Day ( t )

The abstract operation Day takes argument t (a finite time value) and returns an integral Number. 返回 t 所在日的日序号。 It performs the following steps when called:

  1. 返回 𝔽(floor((t / msPerDay)))。

21.4.1.4 TimeWithinDay ( t )

The abstract operation TimeWithinDay takes argument t (a finite time value) and returns an integral Number in the interval from +0𝔽 (inclusive) to msPerDay (exclusive). 返回 t 所在日自该日开始经过的毫秒数。 It performs the following steps when called:

  1. 返回 𝔽((t) modulo (msPerDay))。

21.4.1.5 DaysInYear ( y )

The abstract operation DaysInYear takes argument y (an integral Number) and returns 365𝔽 or 366𝔽. 返回年份 y 的天数。闰年有 366 天;其它年份有 365 天。 It performs the following steps when called:

  1. ry(y)。
  2. 如果 (ry modulo 400) = 0,返回 366𝔽
  3. 如果 (ry modulo 100) = 0,返回 365𝔽
  4. 如果 (ry modulo 4) = 0,返回 366𝔽
  5. 返回 365𝔽

21.4.1.6 DayFromYear ( y )

The abstract operation DayFromYear takes argument y (an integral Number) and returns an integral Number. 返回年份 y 的第一天的日序号。 It performs the following steps when called:

  1. ry(y)。
  2. 注意:在下列步骤中,numYears1, numYears4, numYears100, 和 numYears400 表示从纪元到年份 y 开始之间可被 1、4、100、和 400 整除的年份数。若 y纪元之前,则该数为负。
  3. numYears1 为 (ry - 1970)。
  4. numYears4floor((ry - 1969) / 4)。
  5. numYears100floor((ry - 1901) / 100)。
  6. numYears400floor((ry - 1601) / 400)。
  7. 返回 𝔽(365 × numYears1 + numYears4 - numYears100 + numYears400)。

21.4.1.7 TimeFromYear ( y )

The abstract operation TimeFromYear takes argument y (an integral Number) and returns a time value. 返回年份 y 开始时刻的时间值。 It performs the following steps when called:

  1. 返回 msPerDay × DayFromYear(y)。

21.4.1.8 YearFromTime ( t )

The abstract operation YearFromTime takes argument t (a finite time value) and returns an integral Number. 返回 t 所在的年份。 It performs the following steps when called:

  1. 返回最大的整数 Number y(最接近 +∞),使得 TimeFromYear(y) ≤ t

21.4.1.9 DayWithinYear ( t )

The abstract operation DayWithinYear takes argument t (a finite time value) and returns an integral Number in the inclusive interval from +0𝔽 to 365𝔽. It performs the following steps when called:

  1. 返回 Day(t) - DayFromYear(YearFromTime(t))。

21.4.1.10 InLeapYear ( t )

The abstract operation InLeapYear takes argument t (a finite time value) and returns +0𝔽 or 1𝔽. 如果 t 在闰年内则返回 1𝔽,否则返回 +0𝔽。 It performs the following steps when called:

  1. 如果 DaysInYear(YearFromTime(t)) 为 366𝔽,返回 1𝔽
  2. 返回 +0𝔽

21.4.1.11 MonthFromTime ( t )

The abstract operation MonthFromTime takes argument t (a finite time value) and returns an integral Number in the inclusive interval from +0𝔽 to 11𝔽. 返回一个 Number,标识 t 所在的月份。月份值 +0𝔽 表示一月;1𝔽 表示二月;...;11𝔽 表示十二月。注意 MonthFromTime(+0𝔽) = +0𝔽,对应于 1970-01-01(星期四)。 It performs the following steps when called:

  1. inLeapYearInLeapYear(t)。
  2. dayWithinYearDayWithinYear(t)。
  3. 如果 dayWithinYear < 31𝔽,返回 +0𝔽
  4. 如果 dayWithinYear < 59𝔽 + inLeapYear,返回 1𝔽
  5. 如果 dayWithinYear < 90𝔽 + inLeapYear,返回 2𝔽
  6. 如果 dayWithinYear < 120𝔽 + inLeapYear,返回 3𝔽
  7. 如果 dayWithinYear < 151𝔽 + inLeapYear,返回 4𝔽
  8. 如果 dayWithinYear < 181𝔽 + inLeapYear,返回 5𝔽
  9. 如果 dayWithinYear < 212𝔽 + inLeapYear,返回 6𝔽
  10. 如果 dayWithinYear < 243𝔽 + inLeapYear,返回 7𝔽
  11. 如果 dayWithinYear < 273𝔽 + inLeapYear,返回 8𝔽
  12. 如果 dayWithinYear < 304𝔽 + inLeapYear,返回 9𝔽
  13. 如果 dayWithinYear < 334𝔽 + inLeapYear,返回 10𝔽
  14. 断言:dayWithinYear < 365𝔽 + inLeapYear
  15. 返回 11𝔽

21.4.1.12 DateFromTime ( t )

The abstract operation DateFromTime takes argument t (a finite time value) and returns an integral Number in the inclusive interval from 1𝔽 to 31𝔽. 返回 t 所在月的日数(日期)。 It performs the following steps when called:

  1. inLeapYearInLeapYear(t)。
  2. dayWithinYearDayWithinYear(t)。
  3. monthMonthFromTime(t)。
  4. 如果 month+0𝔽,返回 dayWithinYear + 1𝔽
  5. 如果 month1𝔽,返回 dayWithinYear - 30𝔽
  6. 如果 month2𝔽,返回 dayWithinYear - 58𝔽 - inLeapYear
  7. 如果 month3𝔽,返回 dayWithinYear - 89𝔽 - inLeapYear
  8. 如果 month4𝔽,返回 dayWithinYear - 119𝔽 - inLeapYear
  9. 如果 month5𝔽,返回 dayWithinYear - 150𝔽 - inLeapYear
  10. 如果 month6𝔽,返回 dayWithinYear - 180𝔽 - inLeapYear
  11. 如果 month7𝔽,返回 dayWithinYear - 211𝔽 - inLeapYear
  12. 如果 month8𝔽,返回 dayWithinYear - 242𝔽 - inLeapYear
  13. 如果 month9𝔽,返回 dayWithinYear - 272𝔽 - inLeapYear
  14. 如果 month10𝔽,返回 dayWithinYear - 303𝔽 - inLeapYear
  15. 断言:month11𝔽
  16. 返回 dayWithinYear - 333𝔽 - inLeapYear

21.4.1.13 WeekDay ( t )

The abstract operation WeekDay takes argument t (a finite time value) and returns an integral Number in the inclusive interval from +0𝔽 to 6𝔽. 返回一个 Number,标识 t 所在的星期几。星期值 +0𝔽 表示星期日;1𝔽 表示星期一;...;6𝔽 表示星期六。注意 WeekDay(+0𝔽) = 4𝔽,对应于 1970-01-01(星期四)。 It performs the following steps when called:

  1. 返回 𝔽((Day(t) + 4𝔽) modulo 7)。

21.4.1.14 HourFromTime ( t )

The abstract operation HourFromTime takes argument t (a finite time value) and returns an integral Number in the inclusive interval from +0𝔽 to 23𝔽. 返回 t 所在日的小时数(0-23)。 It performs the following steps when called:

  1. 返回 𝔽(floor((t / msPerHour)) modulo HoursPerDay)。

21.4.1.15 MinFromTime ( t )

The abstract operation MinFromTime takes argument t (a finite time value) and returns an integral Number in the inclusive interval from +0𝔽 to 59𝔽. 返回 t 所在小时的分钟数(0-59)。 It performs the following steps when called:

  1. 返回 𝔽(floor((t / msPerMinute)) modulo MinutesPerHour)。

21.4.1.16 SecFromTime ( t )

The abstract operation SecFromTime takes argument t (a finite time value) and returns an integral Number in the inclusive interval from +0𝔽 to 59𝔽. 返回 t 所在分钟的秒数(0-59)。 It performs the following steps when called:

  1. 返回 𝔽(floor((t / msPerSecond)) modulo SecondsPerMinute)。

21.4.1.17 msFromTime ( t )

The abstract operation msFromTime takes argument t (a finite time value) and returns an integral Number in the inclusive interval from +0𝔽 to 999𝔽. 返回 t 所在秒的毫秒数(0-999)。 It performs the following steps when called:

  1. 返回 𝔽((t) modulo (msPerSecond))。

21.4.1.18 GetUTCEpochNanoseconds ( year, month, day, hour, minute, second, millisecond, microsecond, nanosecond )

The abstract operation GetUTCEpochNanoseconds takes arguments year (an integer), month (an integer in the inclusive interval from 1 to 12), day (an integer in the inclusive interval from 1 to 31), hour (an integer in the inclusive interval from 0 to 23), minute (an integer in the inclusive interval from 0 to 59), second (an integer in the inclusive interval from 0 to 59), millisecond (an integer in the inclusive interval from 0 to 999), microsecond (an integer in the inclusive interval from 0 to 999), and nanosecond (an integer in the inclusive interval from 0 to 999) and returns a BigInt. 返回值表示自纪元以来的纳秒数,该纳秒数对应于给定的 ISO 8601 日历日期和 UTC 时刻(壁钟时间)。 It performs the following steps when called:

  1. dateMakeDay(𝔽(year), 𝔽(month - 1), 𝔽(day))。
  2. timeMakeTime(𝔽(hour), 𝔽(minute), 𝔽(second), 𝔽(millisecond))。
  3. msMakeDate(date, time)。
  4. 断言:ms 是整型 Number。
  5. 返回 ((ms) × 106 + microsecond × 103 + nanosecond)。

21.4.1.19 时区标识符

ECMAScript 中的时区由 时区标识符 表示,这些字符串完全由代码单元在包含区间 0x0000 到 0x007F 内组成。 ECMAScript 实现支持的时区可以是由 AvailableNamedTimeZoneIdentifiers 返回的时区标识记录的 [[Identifier]] 字段表示的 可用命名时区,或者是由 IsTimeZoneOffsetString 返回 true 的字符串表示的 偏移时区

主时区标识符 是可用命名时区的首选标识符。 非主时区标识符 是实现中某可用命名时区的非主标识符。 可用命名时区标识符 是主时区标识符或非主时区标识符。 每个可用命名时区标识符与恰好一个可用命名时区关联。 每个可用命名时区与恰好一个主时区标识符以及零个或多个非主时区标识符关联。

ECMAScript 实现必须支持标识符为 "UTC" 的可用命名时区,该标识符必须是 UTC 时区的主时区标识符。 此外,实现可以支持任意数量的其它可命名时区。

遵循 ECMA-402 国际化 API 所描述的时区要求的实现称为 时区感知。 时区感知实现必须支持与 IANA 时区数据库的 Zone 和 Link 名称对应的可用命名时区,且仅支持这些名称。 在时区感知实现中,主时区标识符为 IANA 时区数据库中的 Zone 名称,非主时区标识符为 Link 名称,除非 AvailableNamedTimeZoneIdentifiers(在 ECMA-402 规范中)有具体覆盖说明。 不支持整个 IANA 时区数据库的实现仍建议使用 IANA 时区数据库名称作为表示时区的标识符。

21.4.1.20 GetNamedTimeZoneEpochNanoseconds ( timeZoneIdentifier, year, month, day, hour, minute, second, millisecond, microsecond, nanosecond )

The implementation-defined abstract operation GetNamedTimeZoneEpochNanoseconds takes arguments timeZoneIdentifier (a String), year (an integer), month (an integer in the inclusive interval from 1 to 12), day (an integer in the inclusive interval from 1 to 31), hour (an integer in the inclusive interval from 0 to 23), minute (an integer in the inclusive interval from 0 to 59), second (an integer in the inclusive interval from 0 to 59), millisecond (an integer in the inclusive interval from 0 to 999), microsecond (an integer in the inclusive interval from 0 to 999), and nanosecond (an integer in the inclusive interval from 0 to 999) and returns a List of BigInts. 返回列表中的每个值都表示自纪元以来的纳秒数,该纳秒数对应于给定的 ISO 8601 日历日期和以 timeZoneIdentifier 所标识的命名时区的壁钟时间。

当输入表示由于负时区转换(例如夏令时结束或由于时区规则变更导致的 UTC 偏移减少)而发生多次的本地时间时,返回的列表将包含多个元素并按升序排序。 当输入表示由于正时区转换(例如夏令时开始或时区规则变更导致 UTC 偏移增加)而被跳过的本地时间时,返回的列表将为空。 否则,返回的列表将只有一个元素。

默认的 GetNamedTimeZoneEpochNanoseconds 实现(供不包含任何本地政治时区规则的 ECMAScript 实现使用)在被调用时执行下列步骤:

  1. 断言:timeZoneIdentifier"UTC"
  2. epochNanosecondsGetUTCEpochNanoseconds(year, month, day, hour, minute, second, millisecond, microsecond, nanosecond)。
  3. 返回 « epochNanoseconds »。
Note

对于时区感知实现(并建议所有其它实现)必须使用 IANA 时区数据库的时区信息 https://www.iana.org/time-zones/

2017 年 11 月 5 日美国纽约时间 01:30(America/New_York)被重复两次,因此 GetNamedTimeZoneEpochNanoseconds("America/New_York", 2017, 11, 5, 1, 30, 0, 0, 0, 0) 将返回长度为 2 的列表,第一元素表示 05:30 UTC(对应于夏令时偏移 -04:00 的 01:30),第二元素表示 06:30 UTC(对应于标准时偏移 -05:00 的 01:30)。

2017 年 3 月 12 日美国纽约时间 02:30 不存在,因此 GetNamedTimeZoneEpochNanoseconds("America/New_York", 2017, 3, 12, 2, 30, 0, 0, 0, 0) 将返回空列表。

21.4.1.21 GetNamedTimeZoneOffsetNanoseconds ( timeZoneIdentifier, epochNanoseconds )

The implementation-defined abstract operation GetNamedTimeZoneOffsetNanoseconds takes arguments timeZoneIdentifier (a String) and epochNanoseconds (a BigInt) and returns an integer.

返回的整数表示在与 epochNanoseconds 对应的时刻相对于纪元的纳秒数单位计的由 timeZoneIdentifier 所标识的命名时区相对于 UTC 的偏移量。

默认的 GetNamedTimeZoneOffsetNanoseconds 实现(供不包含任何本地政治时区规则的 ECMAScript 实现使用)在被调用时执行下列步骤:

  1. 断言:timeZoneIdentifier"UTC"
  2. 返回 0。
Note

时区偏移值可能为正或负。

21.4.1.22 时区标识符记录

时区标识符记录 是用于描述可用命名时区标识符及其对应主时区标识符的记录。

时区标识符记录具有 Table 59 列出的字段。

Table 59: 时区标识符记录字段
字段名 含义
[[Identifier]] a String 实现支持的一个可用命名时区标识符
[[PrimaryIdentifier]] a String [[Identifier]] 解析到的主时区标识符
Note

如果 [[Identifier]]主时区标识符,则 [[Identifier]] 即为 [[PrimaryIdentifier]]

21.4.1.23 AvailableNamedTimeZoneIdentifiers ( )

The implementation-defined abstract operation AvailableNamedTimeZoneIdentifiers takes no arguments and returns a List of Time Zone Identifier Records. 其结果描述此实现中所有可用的命名时区标识符,以及对应的主时区标识符。 列表按每个时区标识记录的 [[Identifier]] 字段排序。

时区感知实现(包括实现 ECMA-402 国际化 API 的所有实现)必须按照 ECMA-402 规范实现 AvailableNamedTimeZoneIdentifiers 抽象操作。 对于非时区感知的实现,AvailableNamedTimeZoneIdentifiers 在被调用时执行下列步骤:

  1. 如果实现不包含任何时区的本地政治规则,则
    1. 返回 « the Time Zone Identifier Record { [[Identifier]]: "UTC", [[PrimaryIdentifier]]: "UTC" } »。
  2. identifiers 为唯一可用命名时区标识符的列表,按字典编码单元顺序排序。
  3. result 为一个新的空列表。
  4. 对于 identifiers 的每个元素 identifier,执行
    1. primaryidentifier
    2. 如果 identifier 在该实现中为非主时区标识符identifier 不是 "UTC",则
      1. primary 设为与 identifier 关联的主时区标识符
      2. 注意:实现可能需要迭代解析 identifier 以获得主时区标识符
    3. record时区标识符记录 { [[Identifier]]: identifier, [[PrimaryIdentifier]]: primary }。
    4. record 附加到 result
  5. 断言:result 包含一个时区标识符记录 r 使得 r.[[Identifier]]"UTC"r.[[PrimaryIdentifier]]"UTC"
  6. 返回 result

21.4.1.24 SystemTimeZoneIdentifier ( )

The implementation-defined abstract operation SystemTimeZoneIdentifier takes no arguments and returns a String. 返回表示宿主环境当前时区的字符串,该字符串要么是满足 IsTimeZoneOffsetString 返回 true 的 UTC 偏移字符串,要么是一个主时区标识符。 It performs the following steps when called:

  1. 如果实现仅支持 UTC 时区,则返回 "UTC"
  2. systemTimeZoneString 为表示宿主环境当前时区的字符串,要么是主时区标识符,要么是偏移时区标识符。
  3. 返回 systemTimeZoneString
Note

为确保 Date 对象方法中实现通常提供的功能,建议 SystemTimeZoneIdentifier 返回与宿主环境时区设置对应的 IANA 时区名称(如果存在)。 GetNamedTimeZoneEpochNanosecondsGetNamedTimeZoneOffsetNanoseconds 必须反映该时区的本地政治规则(标准时与夏令时),如果存在这样的规则。

例如,如果宿主环境为浏览器且系统将用户时区设置为美东时区(US Eastern Time),则 SystemTimeZoneIdentifier 返回 "America/New_York"

21.4.1.25 LocalTime ( t )

The abstract operation LocalTime takes argument t (a finite time value) and returns an integral Number. 将 t 从 UTC 转换为本地时间。 应使用在 t 时刻生效的本地政治规则来确定结果,如本节所述。 It performs the following steps when called:

  1. systemTimeZoneIdentifierSystemTimeZoneIdentifier()。
  2. 如果 IsTimeZoneOffsetString(systemTimeZoneIdentifier) 为 true,则
    1. offsetNsParseTimeZoneOffsetString(systemTimeZoneIdentifier)。
  3. 否则,
    1. offsetNsGetNamedTimeZoneOffsetNanoseconds(systemTimeZoneIdentifier, ((t) × 106))。
  4. offsetMstruncate(offsetNs / 106)。
  5. 返回 t + 𝔽(offsetMs)。
Note 1

如果实现中不存在本地时间的政治规则,结果为 t,因为 SystemTimeZoneIdentifier 返回 "UTC"GetNamedTimeZoneOffsetNanoseconds 返回 0。

Note 2

要求时区感知实现(并建议所有其它实现)使用 IANA 时区数据库的时区信息 https://www.iana.org/time-zones/

Note 3

在负时区转换发生重复时间(例如夏令时结束或时区调整减少)时,两个不同的输入时间值 tUTC 会转换为相同的本地时间 tlocal

LocalTime(UTC(tlocal)) 不必总是等于 tlocal。相应地,UTC(LocalTime(tUTC)) 也不必总是等于 tUTC

21.4.1.26 UTC ( t )

The abstract operation UTC takes argument t (a Number) and returns a time value. 将 t 从本地时间转换为 UTC 时间值。 应使用在 t 时刻生效的本地政治规则来确定结果,如本节所述。 It performs the following steps when called:

  1. 如果 t 不是有限值,返回 NaN
  2. systemTimeZoneIdentifierSystemTimeZoneIdentifier()。
  3. 如果 IsTimeZoneOffsetString(systemTimeZoneIdentifier) 为 true,则
    1. offsetNsParseTimeZoneOffsetString(systemTimeZoneIdentifier)。
  4. 否则,
    1. possibleInstantsGetNamedTimeZoneEpochNanoseconds(systemTimeZoneIdentifier, (YearFromTime(t)), (MonthFromTime(t)) + 1, (DateFromTime(t)), (HourFromTime(t)), (MinFromTime(t)), (SecFromTime(t)), (msFromTime(t)), 0, 0)。
    2. 注意:下列步骤确保当 t 表示在负时区转换时(例如夏令时结束或时区规则变更导致 UTC 偏移减少)重复多次的本地时间或在正时区转换时被跳过的本地时间时,t 使用转换前的时区偏移来解释。
    3. 如果 possibleInstants 非空,则
      1. disambiguatedInstantpossibleInstants[0]。
    4. 否则,
      1. 注意:t 表示在正时区转换时被跳过的本地时间(例如由于夏令时开始或时区规则变更增加 UTC 偏移)。
      2. possibleInstantsBeforeGetNamedTimeZoneEpochNanoseconds(systemTimeZoneIdentifier, (YearFromTime(tBefore)), (MonthFromTime(tBefore)) + 1, (DateFromTime(tBefore)), (HourFromTime(tBefore)), (MinFromTime(tBefore)), (SecFromTime(tBefore)), (msFromTime(tBefore)), 0, 0),其中 tBefore 为小于 t 的最大整型 Number,使得 possibleInstantsBefore 非空(即 tBefore 表示转换前的最后一个本地时间)。
      3. disambiguatedInstantpossibleInstantsBefore 的最后一个元素。
    5. offsetNsGetNamedTimeZoneOffsetNanoseconds(systemTimeZoneIdentifier, disambiguatedInstant)。
  5. offsetMstruncate(offsetNs / 106)。
  6. 返回 t - 𝔽(offsetMs)。

输入 t 名义上为时间值,但可能是任意 Number 值。 算法不得将 t 限制在时间值范围内,以便支持与边界时间值范围对应的输入,无论本地 UTC 偏移如何。 例如,最大时间值为 8.64 × 1015,对应 "+275760-09-13T00:00:00Z"。 在本地时区偏移在该瞬间领先于 UTC 1 小时的环境中,它由更大的输入 8.64 × 1015 + 3.6 × 106 表示,对应 "+275760-09-13T01:00:00+01:00"

如果实现中不存在本地时间的政治规则,结果为 t,因为 SystemTimeZoneIdentifier 返回 "UTC"GetNamedTimeZoneOffsetNanoseconds 返回 0。

Note 1

要求时区感知实现(并建议所有其它实现)使用 IANA 时区数据库的时区信息 https://www.iana.org/time-zones/

2017 年 11 月 5 日美国纽约时间 01:30 被重复两次(回退),但必须将其解释为 UTC-04 的 01:30 而不是 UTC-05 的 01:30。 在 UTC(TimeClip(MakeDate(MakeDay(2017, 10, 5), MakeTime(1, 30, 0, 0)))), offsetMs 的值为 -4 × msPerHour

2017 年 3 月 12 日美国纽约时间 02:30 不存在,但必须将其解释为 UTC-05 的 02:30(等价于 UTC-04 的 03:30)。 在 UTC(TimeClip(MakeDate(MakeDay(2017, 2, 12), MakeTime(2, 30, 0, 0)))), offsetMs 的值为 -5 × msPerHour

Note 2

UTC(LocalTime(tUTC)) 不必总是等于 tUTC。相应地,LocalTime(UTC(tlocal)) 不必总是等于 tlocal

21.4.1.27 MakeTime ( hour, min, sec, ms )

The abstract operation MakeTime takes arguments hour (a Number), min (a Number), sec (a Number), and ms (a Number) and returns a Number. 计算毫秒数。 It performs the following steps when called:

  1. 如果 hourminsecms 中有非有限值,返回 NaN
  2. h𝔽(! ToIntegerOrInfinity(hour))。
  3. m𝔽(! ToIntegerOrInfinity(min))。
  4. s𝔽(! ToIntegerOrInfinity(sec))。
  5. milli𝔽(! ToIntegerOrInfinity(ms))。
  6. 返回 ((h × msPerHour + m × msPerMinute) + s × msPerSecond) + milli
Note

MakeTime 中的算术为浮点算术,非结合律,因此必须按正确顺序执行这些操作。

21.4.1.28 MakeDay ( year, month, date )

The abstract operation MakeDay takes arguments year (a Number), month (a Number), and date (a Number) and returns a finite Number or NaN. 计算天数。 It performs the following steps when called:

  1. 如果 yearmonthdate 中有非有限值,返回 NaN
  2. y𝔽(! ToIntegerOrInfinity(year))。
  3. m𝔽(! ToIntegerOrInfinity(month))。
  4. dt𝔽(! ToIntegerOrInfinity(date))。
  5. ymy + 𝔽(floor((m) / 12))。
  6. 如果 ym 不是有限值,返回 NaN
  7. mn𝔽((m) modulo 12)。
  8. 寻找一个有限时间值 t,使 YearFromTime(t) 为 ymMonthFromTime(t) 为 mn,且 DateFromTime(t) 为 1𝔽;但如果这不可行(因为某些参数超出范围),则返回 NaN
  9. 返回 Day(t) + dt - 1𝔽

21.4.1.29 MakeDate ( day, time )

The abstract operation MakeDate takes arguments day (a Number) and time (a Number) and returns a finite Number or NaN. 计算毫秒数。 It performs the following steps when called:

  1. 如果 daytime 不是有限值,返回 NaN
  2. tvday × msPerDay + time
  3. 如果 tv 不是有限值,返回 NaN
  4. 返回 tv

21.4.1.30 MakeFullYear ( year )

The abstract operation MakeFullYear takes argument year (a Number) and returns an integral Number or NaN. 返回与 year整数部分关联的完整年份,将任何在 0 到 99 范围内的值解释为自 1900 年开始的年数。为与追溯格里高利历对齐,“完整年份”定义为自公元 0 年(公元前 1 年)起完整年数的有符号计数。 It performs the following steps when called:

  1. 如果 yearNaN+∞𝔽-∞𝔽,返回 NaN
  2. truncated 为 ! ToIntegerOrInfinity(year)。
  3. 如果 truncated 在 0 到 99 的闭区间内,返回 1900𝔽 + 𝔽(truncated)。
  4. 返回 𝔽(truncated)。

21.4.1.31 TimeClip ( time )

The abstract operation TimeClip takes argument time (a Number) and returns a time value. 计算毫秒数。 It performs the following steps when called:

  1. 如果 time 不是有限值,返回 NaN
  2. 如果 abs((time)) > 8.64 × 1015,返回 NaN
  3. 返回 𝔽(! ToIntegerOrInfinity(time))。

21.4.1.32 日期时间字符串格式

ECMAScript 定义了基于简化的 ISO 8601 扩展日历日期格式的日期时间字符串交换格式。格式如下:YYYY-MM-DDTHH:mm:ss.sssZ

其中各元素含义如下:

YYYY 是追溯格里高利历中的年份,表示为从 0000 到 9999 的四位十进制数字,或作为带有 '+' 或 '-' 前缀的 6 位扩展年份(参见 expanded year)。
- 字符 "-"(连字符)在字符串中字面出现两次。
MM 是月份,表示为两位十进制数字,从 01(一月)到 12(十二月)。
DD 是月中的日,表示为两位十进制数字,从 01 到 31。
T 字符 "T" 字面出现在字符串中,标示时间部分的开始。
HH 表示自午夜以来完整小时数的两位十进制数字,范围 00 到 24。
: 字符 ":"(冒号)在字符串中字面出现两次。
mm 表示自小时开始以来的完整分钟数的两位十进制数字,范围 00 到 59。
ss 表示自分钟开始以来的完整秒数的两位十进制数字,范围 00 到 59。
. 字符 "."(点)字面出现在字符串中。
sss 表示自秒开始以来的完整毫秒数,作为三位十进制数字。
Z 为 UTC 偏移表示,指定为 "Z"(表示无偏移的 UTC)或以 "+""-" 开头后跟时间表达 HH:mm(表示本地时间相对于 UTC 的提前或滞后,属于用于指示本地时间偏离 UTC 的时区偏移字符串格式的一个子集)

该格式包括仅日期形式:

YYYY
YYYY-MM
YYYY-MM-DD
        

它还包括“日期-时间”形式,即以上任一仅日期形式后紧接以下某一时间形式,可附加可选的 UTC 偏移表示:

THH:mm
THH:mm:ss
THH:mm:ss.sss
        

包含超出范围或不符合格式元素的字符串不是该格式的有效实例。

Note 1

由于每一天既以午夜开始也以午夜结束,字符串 00:0024:00 两种表示可用于区分与同一日期关联的两个午夜。这意味着下列两种表示指向完全相同的时刻:1995-02-04T24:001995-02-05T00:00。此处将后者解释为“日历日的结束”的语义与 ISO 8601 一致,尽管该规范将其保留用于描述时间区间并不允许在单点时间的表示中使用。

Note 2

不存在规定民用时区缩写(如 CET、EST 等)的国际标准,而且同一缩写有时被用于两个截然不同的时区。因此,ISO 8601 与本格式都指定了数值形式的时区偏移。

21.4.1.32.1 扩展年份

覆盖大约相对于 1970 年向前或向后 273,790 年范围内的全部时间值(参见 21.4.1.1)需要表示 0 年之前或 9999 年之后的年份。ISO 8601 允许扩展年份表示,但仅在交换各方达成一致时。 在简化的 ECMAScript 格式中,此类扩展年份表示应为 6 位,并且始终以 + 或 - 符号前缀。年份 0 被视为正数并且必须以 + 前缀。将年份 0 表示为 -000000 是无效的。匹配带扩展年且表示超出时间值范围的时刻的字符串将被视为 Date.parse 无法识别并使该函数返回 NaN,不会回退到实现特定行为或启发式方法。

Note

带扩展年份的日期-时间示例:

-271821-04-20T00:00:00Z 公元前 271822 年
-000001-01-01T00:00:00Z 公元前 2 年
+000000-01-01T00:00:00Z 公元前 1 年
+000001-01-01T00:00:00Z 公元 1 年
+001970-01-01T00:00:00Z 公元 1970 年
+002009-12-15T00:00:00Z 公元 2009 年
+275760-09-13T00:00:00Z 公元 275760 年

21.4.1.33 时区偏移字符串格式

ECMAScript 定义了源自 ISO 8601 的 UTC 偏移字符串交换格式。 该格式由下列语法描述。

语法

UTCOffset ::: ASCIISign Hour ASCIISign Hour HourSubcomponents[+Extended] ASCIISign Hour HourSubcomponents[~Extended] ASCIISign ::: one of + - Hour ::: 0 DecimalDigit 1 DecimalDigit 20 21 22 23 HourSubcomponents[Extended] ::: TimeSeparator[?Extended] MinuteSecond TimeSeparator[?Extended] MinuteSecond TimeSeparator[?Extended] MinuteSecond TemporalDecimalFractionopt TimeSeparator[Extended] ::: [+Extended] : [~Extended] [empty] MinuteSecond ::: 0 DecimalDigit 1 DecimalDigit 2 DecimalDigit 3 DecimalDigit 4 DecimalDigit 5 DecimalDigit TemporalDecimalFraction ::: TemporalDecimalSeparator DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator ::: one of . ,

21.4.1.33.1 IsTimeZoneOffsetString ( offsetString )

The abstract operation IsTimeZoneOffsetString takes argument offsetString (a String) and returns a Boolean. 返回值指示 offsetString 是否符合 UTCOffset 给出的语法。 It performs the following steps when called:

  1. parseResultParseText(offsetString, UTCOffset)。
  2. 如果 parseResult 为错误列表,返回 false
  3. 返回 true

21.4.1.33.2 ParseTimeZoneOffsetString ( offsetString )

The abstract operation ParseTimeZoneOffsetString takes argument offsetString (a String) and returns an integer. 返回值为与字符串 offsetString 对应的 UTC 偏移量,以纳秒为单位的整数。 It performs the following steps when called:

  1. parseResultParseText(offsetString, UTCOffset)。
  2. 断言:parseResult 不是错误列表。
  3. 断言:parseResult 包含一个 ASCIISign 解析节点
  4. parsedSignASCIISign 解析节点匹配的源文本
  5. 如果 parsedSign 为单个代码点 U+002D(HYPHEN-MINUS),则
    1. sign 为 -1。
  6. 否则,
    1. sign 为 1。
  7. 注意:下面对 StringToNumber 的应用不会丢失精度,因为每个被解析的值都保证是足够短的十进制数字字符串。
  8. 断言:parseResult 包含一个 Hour 解析节点
  9. parsedHoursHour 解析节点匹配的源文本
  10. hours(StringToNumber(CodePointsToString(parsedHours)))。
  11. 如果 parseResult 不包含 MinuteSecond 解析节点,则
    1. minutes 为 0。
  12. 否则,
    1. parsedMinutesparseResult 中第一个 MinuteSecond 解析节点匹配的源文本
    2. minutes(StringToNumber(CodePointsToString(parsedMinutes))).
  13. 如果 parseResult 不包含两个 MinuteSecond 解析节点,则
    1. seconds 为 0。
  14. 否则,
    1. parsedSecondsparseResult 中第二个 MinuteSecond 解析节点匹配的源文本
    2. seconds(StringToNumber(CodePointsToString(parsedSeconds)))。
  15. 如果 parseResult 不包含 TemporalDecimalFraction 解析节点,则
    1. nanoseconds 为 0。
  16. 否则,
    1. parsedFractionparseResultTemporalDecimalFraction 解析节点匹配的源文本
    2. fractionCodePointsToString(parsedFraction) 与 "000000000"字符串连接
    3. nanosecondsStringfraction 的子串,从 1 到 10(含)。
    4. nanoseconds(StringToNumber(nanosecondsString))。
  17. 返回 sign × (((hours × 60 + minutes) × 60 + seconds) × 109 + nanoseconds)。

21.4.2 Date 构造函数

Date 构造函数:

  • %Date%
  • 全局对象"Date" 属性的初始值。
  • 当作为构造函数调用时,会创建并初始化一个新的 Date。
  • 当作为函数而非构造函数调用时,返回表示当前时间(UTC)的字符串。
  • 是一个函数,其行为取决于参数的数量和类型。
  • 可用作类定义的 extends 子句的值。打算继承指定 Date 行为的子类构造函数必须包含对 Date 构造函数的 super 调用,以创建并初始化具有 [[DateValue]] 内部槽的子类实例。

21.4.2.1 Date ( ...values )

调用此函数时执行下列步骤:

  1. 如果 NewTarget 为 undefined,则
    1. now 为标识当前时间的时间值(UTC)。
    2. 返回 ToDateString(now)。
  2. numberOfArgsvalues 中元素的数量。
  3. 如果 numberOfArgs = 0,则
    1. dv 为标识当前时间的时间值(UTC)。
  4. 否则如果 numberOfArgs = 1,则
    1. valuevalues[0]。
    2. 如果 value 是一个对象且 value 具有 [[DateValue]] 内部槽,则
      1. tvvalue.[[DateValue]]
    3. 否则,
      1. v 为 ? ToPrimitive(value)。
      2. 如果 v 是字符串,则
        1. 断言:下一步不会返回突发完成,因为 v 是字符串。
        2. tv 为将 v 解析为日期的结果,解析方式与 parse 方法(21.4.3.2)完全相同。
      3. 否则,
        1. tv 为 ? ToNumber(v)。
    4. dvTimeClip(tv)。
  5. 否则,
    1. 断言:numberOfArgs ≥ 2。
    2. y 为 ? ToNumber(values[0])。
    3. m 为 ? ToNumber(values[1])。
    4. 如果 numberOfArgs > 2,令 dt 为 ? ToNumber(values[2]);否则令 dt1𝔽
    5. 如果 numberOfArgs > 3,令 h 为 ? ToNumber(values[3]);否则令 h+0𝔽
    6. 如果 numberOfArgs > 4,令 min 为 ? ToNumber(values[4]);否则令 min+0𝔽
    7. 如果 numberOfArgs > 5,令 s 为 ? ToNumber(values[5]);否则令 s+0𝔽
    8. 如果 numberOfArgs > 6,令 milli 为 ? ToNumber(values[6]);否则令 milli+0𝔽
    9. yrMakeFullYear(y)。
    10. finalDateMakeDate(MakeDay(yr, m, dt), MakeTime(h, min, s, milli))。
    11. dvTimeClip(UTC(finalDate))。
  6. obj 为 ? OrdinaryCreateFromConstructor(NewTarget, "%Date.prototype%", « [[DateValue]] »)。
  7. obj.[[DateValue]] 设为 dv
  8. 返回 obj

21.4.3 Date 构造函数的属性

Date 构造函数:

  • 具有一个 [[Prototype]] 内部槽,其值为 %Function.prototype%
  • 具有一个值为 7𝔽"length" 属性。
  • 具有下列属性:

21.4.3.1 Date.now ( )

此函数返回标示调用发生时 UTC 日期和时间的时间值

21.4.3.2 Date.parse ( string )

此函数对其参数应用 ToString 操作。如果 ToString 导致突发完成,则立即返回该完成记录。否则,此函数将所得字符串解释为日期和时间;它返回一个 Number,即与该日期和时间对应的 UTC 时间值。该字符串可被解释为本地时间、UTC 时间或某一时区中的时间,取决于字符串内容。函数首先尝试按日期时间字符串格式(21.4.1.32,包括扩展年)解析字符串。如果字符串不符合该格式,函数可回退到任何实现特定的启发式或日期格式。不可识别或包含超出格式元素值的字符串应使该函数返回 NaN

如果字符串符合 日期时间字符串格式,则缺失的格式元素由替代值代替。当缺失 MMDD 元素时,使用 "01"。当缺失 HHmmss 元素时,使用 "00"。当缺失 sss 元素时,使用 "000"。当缺失 UTC 偏移表示时,仅日期形式按 UTC 时间解释,而日期-时间形式按本地时间解释。

如果 x 为任何在特定 ECMAScript 实现中毫秒数为零的 Date,则在该实现中(若所有引用的属性都具有其初始值)下列表达式应产生相同的数值:

x.valueOf()
Date.parse(x.toString())
Date.parse(x.toUTCString())
Date.parse(x.toISOString())

然而,表达式

Date.parse(x.toLocaleString())

不要求产生与前面三者相同的 Number 值,并且一般而言,当给定任何不符合日期时间字符串格式(21.4.1.32)且不能由该实现的 toStringtoUTCString 方法生成的字符串值时,返回值为实现定义的。

21.4.3.3 Date.prototype

Date.prototype 的初始值为 Date 原型对象

此属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.4.3.4 Date.UTC ( year [ , month [ , date [ , hours [ , minutes [ , seconds [ , ms ] ] ] ] ] ] )

调用此函数时执行下列步骤:

  1. y 为 ? ToNumber(year)。
  2. 如果 month 存在,令 m 为 ? ToNumber(month);否则令 m+0𝔽
  3. 如果 date 存在,令 dt 为 ? ToNumber(date);否则令 dt1𝔽
  4. 如果 hours 存在,令 h 为 ? ToNumber(hours);否则令 h+0𝔽
  5. 如果 minutes 存在,令 min 为 ? ToNumber(minutes);否则令 min+0𝔽
  6. 如果 seconds 存在,令 s 为 ? ToNumber(seconds);否则令 s+0𝔽
  7. 如果 ms 存在,令 milli 为 ? ToNumber(ms);否则令 milli+0𝔽
  8. yrMakeFullYear(y)。
  9. 返回 TimeClip(MakeDate(MakeDay(yr, m, dt), MakeTime(h, min, s, milli)))。

此函数的 "length" 属性为 7𝔽

Note

此函数与 Date 构造函数有两点不同:它返回一个作为 Number 的时间值,而不是创建 Date;并且它将参数解释为 UTC 而非本地时间。

21.4.4 Date 原型对象的属性

Date 原型对象

  • %Date.prototype%
  • 本身是一个普通对象
  • 不是 Date 实例并且不具有 [[DateValue]] 内部槽。
  • 有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%

除非另有定义,下列 Date 原型对象的方法不是通用的,传递给它们的 this 值必须是已将 [[DateValue]] 内部槽初始化为时间值的对象。

21.4.4.1 Date.prototype.constructor

Date.prototype.constructor 的初始值为 %Date%

21.4.4.2 Date.prototype.getDate ( )

此方法在被调用时执行下列步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,返回 NaN
  5. 返回 DateFromTime(LocalTime(t))。

21.4.4.3 Date.prototype.getDay ( )

此方法在被调用时执行下列步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,返回 NaN
  5. 返回 WeekDay(LocalTime(t))。

21.4.4.4 Date.prototype.getFullYear ( )

此方法在被调用时执行下列步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,返回 NaN
  5. 返回 YearFromTime(LocalTime(t))。

21.4.4.5 Date.prototype.getHours ( )

此方法在被调用时执行下列步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,返回 NaN
  5. 返回 HourFromTime(LocalTime(t))。

21.4.4.6 Date.prototype.getMilliseconds ( )

此方法在被调用时执行下列步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,返回 NaN
  5. 返回 msFromTime(LocalTime(t))。

21.4.4.7 Date.prototype.getMinutes ( )

此方法在被调用时执行下列步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,返回 NaN
  5. 返回 MinFromTime(LocalTime(t))。

21.4.4.8 Date.prototype.getMonth ( )

此方法在被调用时执行下列步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,返回 NaN
  5. 返回 MonthFromTime(LocalTime(t))。

21.4.4.9 Date.prototype.getSeconds ( )

此方法在被调用时执行下列步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,返回 NaN
  5. 返回 SecFromTime(LocalTime(t))。

21.4.4.10 Date.prototype.getTime ( )

此方法在被调用时执行下列步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. 返回 dateObject.[[DateValue]]

21.4.4.11 Date.prototype.getTimezoneOffset ( )

此方法在被调用时执行下列步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,返回 NaN
  5. 返回 (t - LocalTime(t)) / msPerMinute

21.4.4.12 Date.prototype.getUTCDate ( )

此方法在被调用时执行下列步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,返回 NaN
  5. 返回 DateFromTime(t)。

21.4.4.13 Date.prototype.getUTCDay ( )

此方法在被调用时执行下列步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,返回 NaN
  5. 返回 WeekDay(t)。

21.4.4.14 Date.prototype.getUTCFullYear ( )

此方法在被调用时执行下列步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,返回 NaN
  5. 返回 YearFromTime(t)。

21.4.4.15 Date.prototype.getUTCHours ( )

此方法在被调用时执行下列步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,返回 NaN
  5. 返回 HourFromTime(t)。

21.4.4.16 Date.prototype.getUTCMilliseconds ( )

此方法在被调用时执行下列步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,返回 NaN
  5. 返回 msFromTime(t)。

21.4.4.17 Date.prototype.getUTCMinutes ( )

此方法在被调用时执行下列步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,返回 NaN
  5. 返回 MinFromTime(t)。

21.4.4.18 Date.prototype.getUTCMonth ( )

此方法在被调用时执行下列步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,返回 NaN
  5. 返回 MonthFromTime(t)。

21.4.4.19 Date.prototype.getUTCSeconds ( )

此方法在被调用时执行下列步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,返回 NaN
  5. 返回 SecFromTime(t)。

21.4.4.20 Date.prototype.setDate ( date )

此方法在被调用时执行下列步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. dt 为 ? ToNumber(date)。
  5. 如果 tNaN,返回 NaN
  6. t 设为 LocalTime(t)。
  7. newDateMakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), dt), TimeWithinDay(t))。
  8. uTimeClip(UTC(newDate))。
  9. dateObject.[[DateValue]] 设为 u
  10. 返回 u

21.4.4.21 Date.prototype.setFullYear ( year [ , month [ , date ] ] )

此方法在被调用时执行下列步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. y 为 ? ToNumber(year)。
  5. 如果 tNaN,将 t 设为 +0𝔽;否则将 t 设为 LocalTime(t)。
  6. 如果 month 存在,令 m 为 ? ToNumber(month);否则令 mMonthFromTime(t)。
  7. 如果 date 存在,令 dt 为 ? ToNumber(date);否则令 dtDateFromTime(t)。
  8. newDateMakeDate(MakeDay(y, m, dt), TimeWithinDay(t))。
  9. uTimeClip(UTC(newDate))。
  10. dateObject.[[DateValue]] 设为 u
  11. 返回 u

此方法的 "length" 属性为 3𝔽

Note

如果未提供 month,此方法的行为等同于将 month 视为 getMonth() 的值。如果未提供 date,则视为 getDate() 的值。

21.4.4.22 Date.prototype.setHours ( hour [ , min [ , sec [ , ms ] ] ] )

此方法在被调用时执行下列步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. h 为 ? ToNumber(hour)。
  5. 如果 min 存在,令 m 为 ? ToNumber(min)。
  6. 如果 sec 存在,令 s 为 ? ToNumber(sec)。
  7. 如果 ms 存在,令 milli 为 ? ToNumber(ms)。
  8. 如果 tNaN,返回 NaN
  9. t 设为 LocalTime(t)。
  10. 如果 未提供 min,令 mMinFromTime(t)。
  11. 如果 未提供 sec,令 sSecFromTime(t)。
  12. 如果 未提供 ms,令 millimsFromTime(t)。
  13. dateMakeDate(Day(t), MakeTime(h, m, s, milli))。
  14. uTimeClip(UTC(date))。
  15. dateObject.[[DateValue]] 设为 u
  16. 返回 u

此方法的 "length" 属性为 4𝔽

Note

如果 未提供 min,此方法行为如同提供了 getMinutes() 的值。如果 未提供 sec,行为如同提供了 getSeconds() 的值。如果 未提供 ms,行为如同提供了 getMilliseconds() 的值。

21.4.4.23 Date.prototype.setMilliseconds ( ms )

此方法在被调用时执行下列步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. ms 设为 ? ToNumber(ms)。
  5. 如果 tNaN,返回 NaN
  6. t 设为 LocalTime(t)。
  7. timeMakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms)。
  8. uTimeClip(UTC(MakeDate(Day(t), time))).
  9. dateObject.[[DateValue]] 设为 u
  10. 返回 u

21.4.4.24 Date.prototype.setMinutes ( min [ , sec [ , ms ] ] )

此方法在被调用时执行下列步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. m 为 ? ToNumber(min)。
  5. 如果 sec 存在,令 s 为 ? ToNumber(sec)。
  6. 如果 ms 存在,令 milli 为 ? ToNumber(ms)。
  7. 如果 tNaN,返回 NaN
  8. t 设为 LocalTime(t)。
  9. 如果 未提供 sec,令 sSecFromTime(t)。
  10. 如果 未提供 ms,令 millimsFromTime(t)。
  11. dateMakeDate(Day(t), MakeTime(HourFromTime(t), m, s, milli))。
  12. uTimeClip(UTC(date))。
  13. dateObject.[[DateValue]] 设为 u
  14. 返回 u

此方法的 "length" 属性为 3𝔽

Note

如果 未提供 sec,此方法行为如同提供了 getSeconds() 的值。如果 未提供 ms,行为如同提供了 getMilliseconds() 的值。

21.4.4.25 Date.prototype.setMonth ( month [ , date ] )

此方法在被调用时执行下列步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. m 为 ? ToNumber(month)。
  5. 如果 date 存在,令 dt 为 ? ToNumber(date)。
  6. 如果 tNaN,返回 NaN
  7. t 设为 LocalTime(t)。
  8. 如果 未提供 date,令 dtDateFromTime(t)。
  9. newDateMakeDate(MakeDay(YearFromTime(t), m, dt), TimeWithinDay(t))。
  10. uTimeClip(UTC(newDate))。
  11. dateObject.[[DateValue]] 设为 u
  12. 返回 u

此方法的 "length" 属性为 2𝔽

Note

如果 未提供 date,此方法行为如同提供了 getDate() 的值。

21.4.4.26 Date.prototype.setSeconds ( sec [ , ms ] )

此方法在被调用时执行下列步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. s 为 ? ToNumber(sec)。
  5. 如果 ms 存在,令 milli 为 ? ToNumber(ms)。
  6. 如果 tNaN,返回 NaN
  7. t 设为 LocalTime(t)。
  8. 如果 未提供 ms,令 millimsFromTime(t)。
  9. dateMakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), s, milli))。
  10. uTimeClip(UTC(date))。
  11. dateObject.[[DateValue]] 设为 u
  12. 返回 u

此方法的 "length" 属性为 2𝔽

Note

如果 未提供 ms,此方法行为如同提供了 getMilliseconds() 的值。

21.4.4.27 Date.prototype.setTime ( time )

此方法在被调用时执行下列步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. t 为 ? ToNumber(time)。
  4. vTimeClip(t)。
  5. dateObject.[[DateValue]] 设为 v
  6. 返回 v

21.4.4.28 Date.prototype.setUTCDate ( date )

此方法在被调用时执行下列步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. dt 为 ? ToNumber(date)。
  5. 如果 tNaN,返回 NaN
  6. newDateMakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), dt), TimeWithinDay(t))。
  7. vTimeClip(newDate)。
  8. dateObject.[[DateValue]] 设为 v
  9. 返回 v

21.4.4.29 Date.prototype.setUTCFullYear ( year [ , month [ , date ] ] )

此方法在被调用时执行下列步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,将 t 设为 +0𝔽
  5. y 为 ? ToNumber(year)。
  6. 如果 month 存在,令 m 为 ? ToNumber(month);否则令 mMonthFromTime(t)。
  7. 如果 date 存在,令 dt 为 ? ToNumber(date);否则令 dtDateFromTime(t)。
  8. newDateMakeDate(MakeDay(y, m, dt), TimeWithinDay(t))。
  9. vTimeClip(newDate)。
  10. dateObject.[[DateValue]] 设为 v
  11. 返回 v

此方法的 "length" 属性为 3𝔽

Note

如果 未提供 month,此方法行为如同提供了 getUTCMonth() 的值。如果 未提供 date,行为如同提供了 getUTCDate() 的值。

21.4.4.30 Date.prototype.setUTCHours ( hour [ , min [ , sec [ , ms ] ] ] )

此方法在被调用时执行下列步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. h 为 ? ToNumber(hour)。
  5. 如果 min 存在,令 m 为 ? ToNumber(min)。
  6. 如果 sec 存在,令 s 为 ? ToNumber(sec)。
  7. 如果 ms 存在,令 milli 为 ? ToNumber(ms)。
  8. 如果 tNaN,返回 NaN
  9. 如果 未提供 min,令 mMinFromTime(t)。
  10. 如果 未提供 sec,令 sSecFromTime(t)。
  11. 如果 未提供 ms,令 millimsFromTime(t)。
  12. dateMakeDate(Day(t), MakeTime(h, m, s, milli))。
  13. vTimeClip(date)。
  14. dateObject.[[DateValue]] 设为 v
  15. 返回 v

此方法的 "length" 属性为 4𝔽

Note

如果 未提供 min,此方法行为如同提供了 getUTCMinutes() 的值。如果 未提供 sec,行为如同提供了 getUTCSeconds() 的值。如果 未提供 ms,行为如同提供了 getUTCMilliseconds() 的值。

21.4.4.31 Date.prototype.setUTCMilliseconds ( ms )

此方法在被调用时执行下列步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. ms 设为 ? ToNumber(ms)。
  5. 如果 tNaN,返回 NaN
  6. timeMakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms)。
  7. vTimeClip(MakeDate(Day(t), time))。
  8. dateObject.[[DateValue]] 设为 v
  9. 返回 v

21.4.4.32 Date.prototype.setUTCMinutes ( min [ , sec [ , ms ] ] )

此方法在被调用时执行下列步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. m 为 ? ToNumber(min)。
  5. 如果 sec 存在,令 s 为 ? ToNumber(sec)。
  6. 如果 ms 存在,令 milli 为 ? ToNumber(ms)。
  7. 如果 tNaN,返回 NaN
  8. 如果 未提供 sec,令 sSecFromTime(t)。
  9. 如果 未提供 ms,令 millimsFromTime(t)。
  10. dateMakeDate(Day(t), MakeTime(HourFromTime(t), m, s, milli))。
  11. vTimeClip(date)。
  12. dateObject.[[DateValue]] 设为 v
  13. 返回 v

此方法的 "length" 属性为 3𝔽

Note

如果 未提供 sec,此方法行为如同提供了 getUTCSeconds() 的值。如果 未提供 ms,行为如同提供了 getUTCMilliseconds() 的返回值。

21.4.4.33 Date.prototype.setUTCMonth ( month [ , date ] )

此方法在被调用时执行下列步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. m 为 ? ToNumber(month)。
  5. 如果 date 存在,令 dt 为 ? ToNumber(date)。
  6. 如果 tNaN,返回 NaN
  7. 如果 未提供 date,令 dtDateFromTime(t)。
  8. newDateMakeDate(MakeDay(YearFromTime(t), m, dt), TimeWithinDay(t))。
  9. vTimeClip(newDate)。
  10. dateObject.[[DateValue]] 设为 v
  11. 返回 v

此方法的 "length" 属性为 2𝔽

Note

如果 未提供 date,此方法行为如同提供了 getUTCDate() 的值。

21.4.4.34 Date.prototype.setUTCSeconds ( sec [ , ms ] )

此方法在被调用时执行下列步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. s 为 ? ToNumber(sec)。
  5. 如果 ms 存在,令 milli 为 ? ToNumber(ms)。
  6. 如果 tNaN,返回 NaN
  7. 如果 未提供 ms,令 millimsFromTime(t)。
  8. dateMakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), s, milli))。
  9. vTimeClip(date)。
  10. dateObject.[[DateValue]] 设为 v
  11. 返回 v

此方法的 "length" 属性为 2𝔽

Note

如果 未提供 ms,此方法行为如同提供了 getUTCMilliseconds() 的值。

21.4.4.35 Date.prototype.toDateString ( )

此方法在被调用时执行下列步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tvdateObject.[[DateValue]]
  4. 如果 tvNaN,返回 "Invalid Date"
  5. tLocalTime(tv)。
  6. 返回 DateString(t)。

21.4.4.36 Date.prototype.toISOString ( )

此方法在被调用时执行下列步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tvdateObject.[[DateValue]]
  4. 如果 tvNaN,抛出 RangeError 异常。
  5. 断言:tv 为整型 Number。
  6. 如果 tv 对应的年份不能在 日期时间字符串格式 中表示,抛出 RangeError 异常。
  7. 在 UTC 时间尺度上返回包含所有格式元素并附带 UTC 偏移表示 "Z"tv日期时间字符串格式 中的字符串表示。

21.4.4.37 Date.prototype.toJSON ( key )

此方法为 JSON.stringify (25.5.4) 提供 Date 的字符串表示。

调用时执行下列步骤:

  1. obj 为 ? ToObject(this value)。
  2. tv 为 ? ToPrimitive(obj, number)。
  3. 如果 tv 是 Number 且 tv 不是有限值,返回 null
  4. 返回 ? Invoke(obj, "toISOString")。
Note 1

忽略参数。

Note 2

此方法是有意设计为通用的;它不要求其 this 值为 Date。因此,它可以被转移到其他类型的对象上作为方法使用。但是,它要求任何此类对象具有 toISOString 方法。

21.4.4.38 Date.prototype.toLocaleDateString ( [ reserved1 [ , reserved2 ] ] )

包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按照 ECMA-402 规范实现此方法。如果实现不包含 ECMA-402 API,则使用以下对该方法的规范:

此方法返回一个字符串值。该字符串的内容由实现定义,但旨在以宿主环境当前区域设置的惯例以一种方便的、可读的形式表示 Date 的“日期”部分(基于当前时区)。

此方法的可选参数意义在 ECMA-402 规范中定义;不包含 ECMA-402 支持的实现不得将这些参数位置用于其他目的。

21.4.4.39 Date.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] )

包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按照 ECMA-402 规范实现此方法。如果实现不包含 ECMA-402 API,则使用以下对该方法的规范:

此方法返回一个字符串值。该字符串的内容由实现定义,但旨在以宿主环境当前区域设置的惯例以一种方便的、可读的形式表示 Date(基于当前时区)。

此方法的可选参数意义在 ECMA-402 规范中定义;不包含 ECMA-402 支持的实现不得将这些参数位置用于其他目的。

21.4.4.40 Date.prototype.toLocaleTimeString ( [ reserved1 [ , reserved2 ] ] )

包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按照 ECMA-402 规范实现此方法。如果实现不包含 ECMA-402 API,则使用以下对该方法的规范:

此方法返回一个字符串值。该字符串的内容由实现定义,但旨在以宿主环境当前区域设置的惯例以一种方便的、可读的形式表示 Date 的“时间”部分(基于当前时区)。

此方法的可选参数意义在 ECMA-402 规范中定义;不包含 ECMA-402 支持的实现不得将这些参数位置用于其他目的。

21.4.4.41 Date.prototype.toString ( )

此方法在被调用时执行下列步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tvdateObject.[[DateValue]]
  4. 返回 ToDateString(tv)。
Note 1

对于任意 Date d 使得 d.[[DateValue]] 能被 1000 整除,Date.parse(d.toString()) 的结果 = d.valueOf()。参见 21.4.3.2

Note 2

此方法不是通用的;如果其 this 值不是 Date,则抛出 TypeError 异常。因此,不能将其转移给其他类型的对象使用。

21.4.4.41.1 TimeString ( tv )

The abstract operation TimeString takes argument tv (a Number, but not NaN) and returns a String. It performs the following steps when called:

  1. hourToZeroPaddedDecimalString((HourFromTime(tv)), 2)。
  2. minuteToZeroPaddedDecimalString((MinFromTime(tv)), 2)。
  3. secondToZeroPaddedDecimalString((SecFromTime(tv)), 2)。
  4. 返回 hour":"minute":"second、代码单元 0x0020 (SPACE) 与 "GMT"字符串连接

21.4.4.41.2 DateString ( tv )

The abstract operation DateString takes argument tv (a Number, but not NaN) and returns a String. It performs the following steps when called:

  1. weekday 为表 Table 60 中与 Number WeekDay(tv) 对应项的名称。
  2. month 为表 Table 61 中与 Number MonthFromTime(tv) 对应项的名称。
  3. dayToZeroPaddedDecimalString((DateFromTime(tv)), 2)。
  4. yvYearFromTime(tv)。
  5. 如果 yv+0𝔽yv > +0𝔽,令 yearSign 为空字符串;否则令 yearSign"-"
  6. paddedYearToZeroPaddedDecimalString(abs((yv)), 4)。
  7. 返回 weekday、代码单元 0x0020 (SPACE)、month、代码单元 0x0020 (SPACE)、day、代码单元 0x0020 (SPACE)、yearSignpaddedYear字符串连接
Table 60: 星期名称表
Number Name
+0𝔽 "Sun"
1𝔽 "Mon"
2𝔽 "Tue"
3𝔽 "Wed"
4𝔽 "Thu"
5𝔽 "Fri"
6𝔽 "Sat"
Table 61: 月份名称表
Number Name
+0𝔽 "Jan"
1𝔽 "Feb"
2𝔽 "Mar"
3𝔽 "Apr"
4𝔽 "May"
5𝔽 "Jun"
6𝔽 "Jul"
7𝔽 "Aug"
8𝔽 "Sep"
9𝔽 "Oct"
10𝔽 "Nov"
11𝔽 "Dec"

21.4.4.41.3 TimeZoneString ( tv )

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

  1. systemTimeZoneIdentifierSystemTimeZoneIdentifier()。
  2. 如果 IsTimeZoneOffsetString(systemTimeZoneIdentifier) 为 true,则
    1. offsetNsParseTimeZoneOffsetString(systemTimeZoneIdentifier)。
  3. 否则,
    1. offsetNsGetNamedTimeZoneOffsetNanoseconds(systemTimeZoneIdentifier, ((tv) × 106))。
  4. offset𝔽(truncate(offsetNs / 106))。
  5. 如果 offset+0𝔽offset > +0𝔽,则
    1. offsetSign"+"
    2. absOffsetoffset
  6. 否则,
    1. offsetSign"-"
    2. absOffset 为 -offset
  7. offsetMinToZeroPaddedDecimalString((MinFromTime(absOffset)), 2)。
  8. offsetHourToZeroPaddedDecimalString((HourFromTime(absOffset)), 2)。
  9. tzName 为一个实现定义的字符串,该字符串要么为空,要么是代码单元 0x0020 (SPACE)、代码单元 0x0028 (LEFT PARENTHESIS)、实现定义的时区名称和代码单元 0x0029 (RIGHT PARENTHESIS) 的字符串连接
  10. 返回 offsetSignoffsetHouroffsetMintzName字符串连接

21.4.4.41.4 ToDateString ( tv )

The abstract operation ToDateString takes argument tv (an integral Number or NaN) and returns a String. It performs the following steps when called:

  1. 如果 tvNaN,返回 "Invalid Date"
  2. tLocalTime(tv)。
  3. 返回 DateString(t)、代码单元 0x0020 (SPACE)、TimeString(t) 与 TimeZoneString(tv) 的字符串连接

21.4.4.42 Date.prototype.toTimeString ( )

此方法在被调用时执行下列步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tvdateObject.[[DateValue]]
  4. 如果 tvNaN,返回 "Invalid Date"
  5. tLocalTime(tv)。
  6. 返回 TimeString(t) 与 TimeZoneString(tv) 的字符串连接

21.4.4.43 Date.prototype.toUTCString ( )

此方法返回表示 this 值所对应时刻的字符串值。该字符串的格式基于 RFC 7231 的 "HTTP-date",并对 ECMAScript Date 支持的完整时间范围进行了推广。

调用时执行下列步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tvdateObject.[[DateValue]]
  4. 如果 tvNaN,返回 "Invalid Date"
  5. weekday 为表 Table 60 中与 Number WeekDay(tv) 对应项的名称。
  6. month 为表 Table 61 中与 Number MonthFromTime(tv) 对应项的名称。
  7. dayToZeroPaddedDecimalString((DateFromTime(tv)), 2)。
  8. yvYearFromTime(tv)。
  9. 如果 yv+0𝔽yv > +0𝔽,令 yearSign 为空字符串;否则令 yearSign"-"
  10. paddedYearToZeroPaddedDecimalString(abs((yv)), 4)。
  11. 返回 weekday","、代码单元 0x0020 (SPACE)、day、代码单元 0x0020 (SPACE)、month、代码单元 0x0020 (SPACE)、yearSignpaddedYear、代码单元 0x0020 (SPACE) 与 TimeString(tv) 的字符串连接

21.4.4.44 Date.prototype.valueOf ( )

此方法在被调用时执行下列步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. 返回 dateObject.[[DateValue]]

21.4.4.45 Date.prototype [ %Symbol.toPrimitive% ] ( hint )

此方法由 ECMAScript 语言操作调用以将 Date 转换为原始值。允许的 hint 值为 "default""number""string"。Date 在内置 ECMAScript 对象中是独特的,因为它将 "default" 视为等同于 "string";其它内置对象将 "default" 视为等同于 "number"

调用时执行下列步骤:

  1. objthis 值。
  2. 如果 obj 不是对象,抛出 TypeError 异常。
  3. 如果 hint"string""default",则
    1. tryFirststring
  4. 否则如果 hint"number",则
    1. tryFirstnumber
  5. 否则,
    1. 抛出 TypeError 异常。
  6. 返回 ? OrdinaryToPrimitive(obj, tryFirst)。

此属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

此方法的 "name" 属性的值为 "[Symbol.toPrimitive]"

21.4.5 Date 实例的属性

Date 实例是普通对象,从 Date 原型对象继承属性。Date 实例也具有一个 [[DateValue]] 内部槽。[[DateValue]] 内部槽是该 Date 所表示的时间值

22 文本处理

22.1 String 对象

22.1.1 String 构造器

String 构造器

  • %String%
  • 全局对象"String" 属性的初始值。
  • 当作为构造器调用时,创建并初始化一个新的 String 对象。
  • 当作为函数而不是构造器调用时,执行类型转换。
  • 可用作类定义中 extends 子句的值。意图继承指定 String 行为的子类构造器必须包含对 String 构造器super 调用,以创建并初始化带有 [[StringData]] 内部槽的子类实例。

22.1.1.1 String ( value )

此函数在被调用时执行以下步骤:

  1. 如果 value 不存在,则
    1. str 为空 String。
  2. 否则,
    1. 如果 NewTarget 是 undefinedvalue 是一个 Symbol,返回 SymbolDescriptiveString(value)。
    2. str 为 ? ToString(value)。
  3. 如果 NewTarget 是 undefined,返回 str
  4. 返回 StringCreate(str, ? GetPrototypeFromConstructor(NewTarget, "%String.prototype%"))。

22.1.2 String 构造器的属性

String 构造器

22.1.2.1 String.fromCharCode ( ...codeUnits )

此函数可使用任意数量的参数调用,这些参数构成剩余参数 codeUnits

它在被调用时执行以下步骤:

  1. result 为空 String。
  2. 对于 codeUnits 的每个元素 next,执行
    1. nextCU 为数值为 (? ToUint16(next)) 的码元。
    2. result 设置为 resultnextCU 的字符串拼接。
  3. 返回 result

此函数的 "length" 属性为 1𝔽

22.1.2.2 String.fromCodePoint ( ...codePoints )

此函数可使用任意数量的参数调用,这些参数构成剩余参数 codePoints

它在被调用时执行以下步骤:

  1. result 为空 String。
  2. 对于 codePoints 的每个元素 next,执行
    1. nextCP 为 ? ToNumber(next)。
    2. 如果 nextCP 不是一个整数 Number,抛出 RangeError 异常。
    3. 如果 (nextCP) < 0 或 (nextCP) > 0x10FFFF,抛出 RangeError 异常。
    4. result 设置为 resultUTF16EncodeCodePoint((nextCP)) 的字符串拼接。
  3. 断言:如果 codePoints 为空,则 result 为空 String。
  4. 返回 result

此函数的 "length" 属性为 1𝔽

22.1.2.3 String.prototype

String.prototype 的初始值是 String 原型对象

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

22.1.2.4 String.raw ( template, ...substitutions )

此函数可使用可变数量的参数调用。第一个参数是 template,其余参数构成 List substitutions

它在被调用时执行以下步骤:

  1. substitutionCountsubstitutions 中元素的数量。
  2. cooked 为 ? ToObject(template)。
  3. literals 为 ? ToObject(? Get(cooked, "raw"))。
  4. literalCount 为 ? LengthOfArrayLike(literals)。
  5. 如果 literalCount ≤ 0,返回空 String。
  6. result 为空 String。
  7. nextIndex 为 0。
  8. 重复,
    1. nextLiteralVal 为 ? Get(literals, ! ToString(𝔽(nextIndex)))。
    2. nextLiteral 为 ? ToString(nextLiteralVal)。
    3. result 设置为 resultnextLiteral 的字符串拼接。
    4. 如果 nextIndex + 1 = literalCount,返回 result
    5. 如果 nextIndex < substitutionCount,则
      1. nextSubValsubstitutions[nextIndex]。
      2. nextSub 为 ? ToString(nextSubVal)。
      3. result 设置为 resultnextSub 的字符串拼接。
    6. nextIndex 设置为 nextIndex + 1。
Note

此函数旨在用作 Tagged Template(13.3.11)的标签函数。当如此调用时,第一个参数将是一个良构模板对象,剩余参数将包含替换值。

22.1.3 String 原型对象的属性

String 原型对象

  • %String.prototype%
  • 是一个 String 异质对象,并具有为此类对象指定的内部方法。
  • 有一个 [[StringData]] 内部槽,其值为空 String。
  • 有一个 "length" 属性,其初始值为 +0𝔽,且其特性为 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。
  • 有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%

除非另有明确说明,下文定义的 String 原型对象的方法不是泛型的,传递给它们的 this 值必须是 String 值,或是一个具有 [[StringData]] 内部槽且该内部槽已被初始化为 String 值的对象。

22.1.3.1 String.prototype.at ( index )

  1. thisValuethis 值。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. str 为 ? ToString(thisValue)。
  4. lenstr 的长度。
  5. relativeIndex 为 ? ToIntegerOrInfinity(index)。
  6. 如果 relativeIndex ≥ 0,则
    1. krelativeIndex
  7. 否则,
    1. klen + relativeIndex
  8. 如果 k < 0 或 klen,返回 undefined
  9. 返回 str 中从 kk + 1 的子字符串

22.1.3.2 String.prototype.charAt ( pos )

Note 1

此方法返回一个单元素 String,该元素为将此对象转换为 String 后所得 String 值中索引 pos 处的码元。如果该索引处没有元素,则结果为空 String。结果是 String 值,而不是 String 对象。

如果 pos 是一个整数 Number,则 x.charAt(pos) 的结果等价于 x.substring(pos, pos + 1) 的结果。

此方法在被调用时执行以下步骤:

  1. thisValuethis 值。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. str 为 ? ToString(thisValue)。
  4. position 为 ? ToIntegerOrInfinity(pos)。
  5. sizestr 的长度。
  6. 如果 position < 0 或 positionsize,返回空 String。
  7. 返回 str 中从 positionposition + 1 的子字符串
Note 2

此方法有意设计为泛型;它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

22.1.3.3 String.prototype.charCodeAt ( pos )

Note 1

此方法返回一个 Number(小于 216 的非负整数 Number),该 Number 是将此对象转换为 String 后所得 String 中索引 pos 处码元的数值。如果该索引处没有元素,则结果为 NaN

此方法在被调用时执行以下步骤:

  1. thisValuethis 值。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. str 为 ? ToString(thisValue)。
  4. position 为 ? ToIntegerOrInfinity(pos)。
  5. sizestr 的长度。
  6. 如果 position < 0 或 positionsize,返回 NaN
  7. 返回 String str 中索引 position 处码元数值的 Number 值
Note 2

此方法有意设计为泛型;它不要求其 this 值是 String 对象。因此它可以被转移到其他种类的对象上作为方法使用。

22.1.3.4 String.prototype.codePointAt ( pos )

Note 1

此方法返回一个小于或等于 0x10FFFF𝔽 的非负整数 Number,该 Number 是从将此对象转换为 String 后所得 String 中索引 pos 处的字符串元素开始的 UTF-16 编码码点(6.1.4)的数值。如果该索引处没有元素,则结果为 undefined。如果一个有效的 UTF-16 代理对不是从 pos 开始,则结果为 pos 处的码元。

此方法在被调用时执行以下步骤:

  1. thisValuethis 值。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. str 为 ? ToString(thisValue)。
  4. position 为 ? ToIntegerOrInfinity(pos)。
  5. sizestr 的长度。
  6. 如果 position < 0 或 positionsize,返回 undefined
  7. cpCodePointAt(str, position)。
  8. 返回 𝔽(cp.[[CodePoint]])。
Note 2

此方法有意设计为泛型;它不要求其 this 值是 String 对象。因此它可以被转移到其他种类的对象上作为方法使用。

22.1.3.5 String.prototype.concat ( ...args )

Note 1

当调用此方法时,它返回由 this 值(转换为 String)的码元后跟每个参数转换为 String 后的码元所组成的 String 值。结果是 String 值,而不是 String 对象。

此方法在被调用时执行以下步骤:

  1. thisValuethis 值。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. str 为 ? ToString(thisValue)。
  4. resultstr
  5. 对于 args 的每个元素 next,执行
    1. nextString 为 ? ToString(next)。
    2. result 设置为 resultnextString 的字符串拼接。
  6. 返回 result

此方法的 "length" 属性为 1𝔽

Note 2

此方法有意设计为泛型;它不要求其 this 值是 String 对象。因此它可以被转移到其他种类的对象上作为方法使用。

22.1.3.6 String.prototype.constructor

String.prototype.constructor 的初始值是 %String%

22.1.3.7 String.prototype.endsWith ( searchString [ , endPosition ] )

此方法在被调用时执行以下步骤:

  1. thisValuethis 值。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. str 为 ? ToString(thisValue)。
  4. isRegExp 为 ? IsRegExp(searchString)。
  5. 如果 isRegExptrue,抛出 TypeError 异常。
  6. searchStr 为 ? ToString(searchString)。
  7. lenstr 的长度。
  8. 如果 endPositionundefined,令 poslen;否则令 pos 为 ? ToIntegerOrInfinity(endPosition)。
  9. end 为将 pos 夹在 0 和 len 之间的结果。
  10. searchLengthsearchStr 的长度。
  11. 如果 searchLength = 0,返回 true
  12. startend - searchLength
  13. 如果 start < 0,返回 false
  14. substringstr 中从 startend子字符串
  15. 如果 substringsearchStr,返回 true
  16. 返回 false
Note 1

指定当第一个参数是 RegExp 时抛出异常,是为了允许未来版本定义允许此类参数值的扩展。

Note 2

此方法有意设计为泛型;它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

22.1.3.8 String.prototype.includes ( searchString [ , position ] )

此方法在被调用时执行以下步骤:

  1. thisValuethis 值。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. str 为 ? ToString(thisValue)。
  4. isRegExp 为 ? IsRegExp(searchString)。
  5. 如果 isRegExptrue,抛出 TypeError 异常。
  6. searchStr 为 ? ToString(searchString)。
  7. pos 为 ? ToIntegerOrInfinity(position)。
  8. 断言:如果 positionundefined,则 pos 为 0。
  9. lenstr 的长度。
  10. start 为将 pos 夹在 0 和 len 之间的结果。
  11. indexStringIndexOf(str, searchStr, start)。
  12. 如果 indexnot-found,返回 false
  13. 返回 true
Note 1

如果 searchString 作为将此对象转换为 String 后所得结果的一个 substring 出现在一个或多个大于或等于 position 的索引处,则此函数返回 true;否则返回 false。如果 positionundefined,则假定为 0,以便搜索整个 String。

Note 2

指定当第一个参数是 RegExp 时抛出异常,是为了允许未来版本定义允许此类参数值的扩展。

Note 3

此方法有意设计为泛型;它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

22.1.3.9 String.prototype.indexOf ( searchString [ , position ] )

Note 1

如果 searchString 作为将此对象转换为 String 后所得结果的一个 substring 出现在一个或多个大于或等于 position 的索引处,则返回此类索引中最小的一个;否则返回 -1𝔽。如果 positionundefined,则假定为 +0𝔽,以便搜索整个 String。

此方法在被调用时执行以下步骤:

  1. thisValuethis 值。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. str 为 ? ToString(thisValue)。
  4. searchStr 为 ? ToString(searchString)。
  5. pos 为 ? ToIntegerOrInfinity(position)。
  6. 断言:如果 positionundefined,则 pos 为 0。
  7. lenstr 的长度。
  8. start 为将 pos 夹在 0 和 len 之间的结果。
  9. resultStringIndexOf(str, searchStr, start)。
  10. 如果 resultnot-found,返回 -1𝔽
  11. 返回 𝔽(result)。
Note 2

此方法有意设计为泛型;它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

22.1.3.10 String.prototype.isWellFormed ( )

此方法在被调用时执行以下步骤:

  1. thisValuethis 值。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. str 为 ? ToString(thisValue)。
  4. 返回 IsStringWellFormedUnicode(str)。

22.1.3.11 String.prototype.lastIndexOf ( searchString [ , position ] )

Note 1

如果 searchString 作为将此对象转换为 String 后所得结果的一个 substring 出现在一个或多个小于或等于 position 的索引处,则返回此类索引中最大的一个;否则返回 -1𝔽。如果 positionundefined,则假定为 String 值的长度,以便搜索整个 String。

此方法在被调用时执行以下步骤:

  1. thisValuethis 值。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. str 为 ? ToString(thisValue)。
  4. searchStr 为 ? ToString(searchString)。
  5. numPos 为 ? ToNumber(position)。
  6. 断言:如果 positionundefined,则 numPosNaN
  7. 如果 numPosNaN,令 pos 为 +∞;否则令 pos 为 ! ToIntegerOrInfinity(numPos)。
  8. lenstr 的长度。
  9. searchLensearchStr 的长度。
  10. 如果 len < searchLen,返回 -1𝔽
  11. start 为将 pos 夹在 0 和 len - searchLen 之间的结果。
  12. resultStringLastIndexOf(str, searchStr, start)。
  13. 如果 resultnot-found,返回 -1𝔽
  14. 返回 𝔽(result)。
Note 2

此方法有意设计为泛型;它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

22.1.3.12 String.prototype.localeCompare ( that [ , reserved1 [ , reserved2 ] ] )

包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按照 ECMA-402 规范中的规定实现此方法。如果 ECMAScript 实现不包含 ECMA-402 API,则使用以下对此方法的规范:

此方法返回一个非 NaN 的 Number,表示对 this 值(转换为 String str)与 that(转换为 String thatValue)进行实现定义的区域设置敏感 String 比较的结果。该结果旨在对应于按照宿主环境当前区域设置的约定对 String 值进行排序的顺序;当 str 排在 thatValue 之前时为负,当 str 排在 thatValue 之后时为正,在所有其他情况下为零(表示 strthatValue 之间没有相对顺序)。

在执行比较之前,此方法执行以下步骤来准备 String:

  1. thisValuethis 值。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. str 为 ? ToString(thisValue)。
  4. thatValue 为 ? ToString(that)。

此方法的可选第二和第三参数的含义在 ECMA-402 规范中定义;不包含 ECMA-402 支持的实现不得为这些参数位置赋予任何其他解释。

实际返回值是实现定义的,以允许在其中编码额外信息,但当此方法被视为一个双参数方法时,它必须是一个一致的比较器,为所有 String 的集合定义一个全序。此方法还必须识别并遵守 Unicode 标准中的规范等价性,包括在比较可区分但规范等价的 String 时返回 +0𝔽

Note 1

此方法本身并不直接适合作为 Array.prototype.sort 的参数,因为后者需要一个双参数函数。

Note 2

此方法可以依赖 ECMAScript 环境从宿主环境获得的任何语言和/或区域设置敏感比较功能,并旨在按照宿主环境当前区域设置的约定进行比较。然而,无论比较能力如何,此方法都必须识别并遵守 Unicode 标准中的规范等价性——例如,以下比较必须全部返回 +0𝔽

// Å ANGSTROM SIGN vs.
// Å LATIN CAPITAL LETTER A + COMBINING RING ABOVE
"\u212B".localeCompare("A\u030A")

// Ω OHM SIGN vs.
// Ω GREEK CAPITAL LETTER OMEGA
"\u2126".localeCompare("\u03A9")

// ṩ LATIN SMALL LETTER S WITH DOT BELOW AND DOT ABOVE vs.
// ṩ LATIN SMALL LETTER S + COMBINING DOT ABOVE + COMBINING DOT BELOW
"\u1E69".localeCompare("s\u0307\u0323")

// ḍ̇ LATIN SMALL LETTER D WITH DOT ABOVE + COMBINING DOT BELOW vs.
// ḍ̇ LATIN SMALL LETTER D WITH DOT BELOW + COMBINING DOT ABOVE
"\u1E0B\u0323".localeCompare("\u1E0D\u0307")

// 가 HANGUL CHOSEONG KIYEOK + HANGUL JUNGSEONG A vs.
// 가 HANGUL SYLLABLE GA
"\u1100\u1161".localeCompare("\uAC00")

关于规范等价性的定义和讨论,参见 Unicode 标准第 2 章和第 3 章,以及 Unicode Standard Annex #15, Unicode Normalization FormsUnicode Technical Note #5, Canonical Equivalence in Applications。另见 Unicode Technical Standard #10, Unicode Collation Algorithm

建议此方法不应遵守 Unicode 标准第 3 章第 3.7 节中定义的 Unicode 兼容等价或兼容分解。

Note 3

此方法有意设计为泛型;它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

22.1.3.13 String.prototype.match ( regexpOrPattern )

此方法在被调用时执行以下步骤:

  1. thisValuethis 值。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. 如果 regexpOrPattern 是一个 Object,则
    1. matcher 为 ? GetMethod(regexpOrPattern, %Symbol.match%)。
    2. 如果 matcher 不是 undefined,则
      1. 返回 ? Call(matcher, regexpOrPattern, « thisValue »)。
  4. str 为 ? ToString(thisValue)。
  5. regexp 为 ? RegExpCreate(regexpOrPattern, undefined)。
  6. 返回 ? Invoke(regexp, %Symbol.match%, « str »)。
Note

此方法有意设计为泛型;它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

22.1.3.14 String.prototype.matchAll ( regexpOrPattern )

此方法对表示 this 值的 String 与 regexpOrPattern 执行正则表达式匹配,并返回一个产生匹配结果的迭代器。每个匹配结果都是一个 Array,其第一个元素为 String 中被匹配的部分,后续元素为任何捕获组所匹配的部分。如果正则表达式从未匹配,则返回的迭代器不会产生任何匹配结果。

它在被调用时执行以下步骤:

  1. thisValuethis 值。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. 如果 regexpOrPattern 是一个 Object,则
    1. isRegExp 为 ? IsRegExp(regexpOrPattern)。
    2. 如果 isRegExptrue,则
      1. flags 为 ? Get(regexpOrPattern, "flags")。
      2. 执行 ? RequireObjectCoercible(flags)。
      3. 如果 ? ToString(flags) 不包含 "g",抛出 TypeError 异常。
    3. matcher 为 ? GetMethod(regexpOrPattern, %Symbol.matchAll%)。
    4. 如果 matcher 不是 undefined,则
      1. 返回 ? Call(matcher, regexpOrPattern, « thisValue »)。
  4. str 为 ? ToString(thisValue)。
  5. regexp 为 ? RegExpCreate(regexpOrPattern, "g")。
  6. 返回 ? Invoke(regexp, %Symbol.matchAll%, « str »)。
Note 1
此方法有意设计为泛型,它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。
Note 2
类似于 String.prototype.splitString.prototype.matchAll 被设计为通常不改变其输入。

22.1.3.15 String.prototype.normalize ( [ form ] )

此方法在被调用时执行以下步骤:

  1. thisValuethis 值。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. str 为 ? ToString(thisValue)。
  4. 如果 formundefined,令 f"NFC"
  5. 否则,令 f 为 ? ToString(form)。
  6. 如果 f 不是 "NFC""NFD""NFKC""NFKD" 之一,抛出 RangeError 异常。
  7. ns 为 String 值,该值是按照 最新 Unicode 标准的 Normalization Forms 中所指定的、将 str 规范化为名为 f 的规范化形式的结果。
  8. 返回 ns
Note

此方法有意设计为泛型;它不要求其 this 值是 String 对象。因此它可以被转移到其他种类的对象上作为方法使用。

22.1.3.16 String.prototype.padEnd ( maxLength [ , fillString ] )

此方法在被调用时执行以下步骤:

  1. thisValuethis 值。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. 返回 ? StringPaddingBuiltinsImpl(thisValue, maxLength, fillString, end)。

22.1.3.17 String.prototype.padStart ( maxLength [ , fillString ] )

此方法在被调用时执行以下步骤:

  1. thisValuethis 值。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. 返回 ? StringPaddingBuiltinsImpl(thisValue, maxLength, fillString, start)。

22.1.3.17.1 StringPaddingBuiltinsImpl ( thisValue, maxLength, fillString, placement )

The abstract operation StringPaddingBuiltinsImpl takes arguments thisValue (一个 ECMAScript 语言值,), maxLength (一个 ECMAScript 语言值,), fillString (一个 ECMAScript 语言值,), and placement (startend,) and returns 要么是一个包含 String 的正常完成,要么是一个抛出完成. It performs the following steps when called:

  1. str 为 ? ToString(thisValue)。
  2. intMaxLength(? ToLength(maxLength))。
  3. stringLengthstr 的长度。
  4. 如果 intMaxLengthstringLength,返回 str
  5. 如果 fillStringundefined,将 fillString 设置为仅由码元 0x0020 (SPACE) 组成的 String 值。
  6. 否则,将 fillString 设置为 ? ToString(fillString)。
  7. 返回 StringPad(str, intMaxLength, fillString, placement)。

22.1.3.17.2 StringPad ( str, maxLength, fillString, placement )

The abstract operation StringPad takes arguments str (一个 String,), maxLength (一个非负整数,), fillString (一个 String,), and placement (startend,) and returns 一个 String. It performs the following steps when called:

  1. stringLengthstr 的长度。
  2. 如果 maxLengthstringLength,返回 str
  3. 如果 fillString 是空 String,返回 str
  4. fillLenmaxLength - stringLength
  5. truncatedStringFiller 为由重复拼接 fillString 并截断到长度 fillLen 所组成的 String 值。
  6. 如果 placementstart,返回 truncatedStringFillerstr 的字符串拼接。
  7. 返回 strtruncatedStringFiller 的字符串拼接。
Note 1

参数 maxLength 将被夹取,使其不可能小于 str 的长度。

Note 2

参数 fillString 默认为 " "(由码元 0x0020 SPACE 组成的 String 值)。

22.1.3.17.3 ToZeroPaddedDecimalString ( n, minLength )

The abstract operation ToZeroPaddedDecimalString takes arguments n (一个非负整数,) and minLength (一个非负整数,) and returns 一个 String. It performs the following steps when called:

  1. strn 的 String 表示,按十进制数格式化。
  2. 返回 StringPad(str, minLength, "0", start)。

22.1.3.18 String.prototype.repeat ( count )

此方法在被调用时执行以下步骤:

  1. thisValuethis 值。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. str 为 ? ToString(thisValue)。
  4. n 为 ? ToIntegerOrInfinity(count)。
  5. 如果 n < 0 或 n = +∞,抛出 RangeError 异常。
  6. 如果 n = 0,返回空 String。
  7. 返回由 strn 个副本追加在一起形成的 String 值。
Note 1

此方法创建由 this 值(转换为 String)的码元重复 count 次组成的 String 值。

Note 2

此方法有意设计为泛型;它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

22.1.3.19 String.prototype.replace ( searchValue, replaceValue )

此方法在被调用时执行以下步骤:

  1. thisValuethis 值。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. 如果 searchValue 是一个 Object,则
    1. replacer 为 ? GetMethod(searchValue, %Symbol.replace%)。
    2. 如果 replacer 不是 undefined,则
      1. 返回 ? Call(replacer, searchValue, « thisValue, replaceValue »)。
  4. string 为 ? ToString(thisValue)。
  5. searchString 为 ? ToString(searchValue)。
  6. functionalReplaceIsCallable(replaceValue)。
  7. 如果 functionalReplacefalse,则
    1. replaceValue 设置为 ? ToString(replaceValue)。
  8. searchLengthsearchString 的长度。
  9. positionStringIndexOf(string, searchString, 0)。
  10. 如果 positionnot-found,返回 string
  11. precedingstring 中从 0 到 position子字符串
  12. followingstring 中从 position + searchLength 开始的子字符串
  13. 如果 functionalReplacetrue,则
    1. replacement 为 ? ToString(? Call(replaceValue, undefined, « searchString, 𝔽(position), string »))。
  14. 否则,
    1. 断言:replaceValue 是一个 String。
    2. captures 为一个新的空 List
    3. replacement 为 ! GetSubstitution(searchString, string, position, captures, undefined, replaceValue)。
  15. 返回 precedingreplacementfollowing 的字符串拼接。
Note

此方法有意设计为泛型;它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

22.1.3.19.1 GetSubstitution ( matched, str, position, captures, namedCaptures, replacementTemplate )

The abstract operation GetSubstitution takes arguments matched (一个 String,), str (一个 String,), position (一个非负整数,), captures (一个由 String 或 undefined 组成的 List,), namedCaptures (一个 Object 或 undefined,), and replacementTemplate (一个 String,) and returns 要么是一个包含 String 的正常完成,要么是一个抛出完成. 对于此抽象操作而言,十进制数字是位于从 0x0030 (DIGIT ZERO) 到 0x0039 (DIGIT NINE) 的闭区间内的码元。 It performs the following steps when called:

  1. stringLengthstr 的长度。
  2. 断言:positionstringLength
  3. result 为空 String。
  4. templateRemainderreplacementTemplate
  5. 重复,当 templateRemainder 不是空 String 时,
    1. 注:以下步骤隔离 reftemplateRemainder 的一个前缀),确定 refReplacement(其替换),然后将该替换追加到 result
    2. 如果 templateRemainder"$$" 开始,则
      1. ref"$$"
      2. refReplacement"$"
    3. 否则如果 templateRemainder"$`" 开始,则
      1. ref"$`"
      2. refReplacementstr 中从 0 到 position子字符串
    4. 否则如果 templateRemainder"$&" 开始,则
      1. ref"$&"
      2. refReplacementmatched
    5. 否则如果 templateRemainder"$'"(0x0024 (DOLLAR SIGN) 后跟 0x0027 (APOSTROPHE))开始,则
      1. ref"$'"
      2. matchLengthmatched 的长度。
      3. tailPosposition + matchLength
      4. refReplacementstr 中从 min(tailPos, stringLength) 开始的子字符串
      5. 注:只有当此抽象操作是由对象上 %RegExp.prototype% 的内在 %Symbol.replace% 方法调用,且该对象的 "exec" 属性不是内在 %RegExp.prototype.exec% 时,tailPos 才可能超过 stringLength
    6. 否则如果 templateRemainder"$" 后跟 1 个或多个十进制数字开始,则
      1. 如果 templateRemainder"$" 后跟 2 个或更多十进制数字开始,令 digitCount 为 2;否则令 digitCount 为 1。
      2. digitstemplateRemainder 中从 1 到 1 + digitCount子字符串
      3. index(StringToNumber(digits))。
      4. 断言:0 ≤ index ≤ 99。
      5. captureLencaptures 中元素的数量。
      6. 如果 index > captureLendigitCount = 2,则
        1. 注:当一个两位数替换模式指定了超过捕获组数量的索引时,它被视为一个一位数替换模式后跟一个字面数字。
        2. digitCount 设置为 1。
        3. digits 设置为 digits 中从 0 到 1 的子字符串
        4. index 设置为 (StringToNumber(digits))。
      7. reftemplateRemainder 中从 0 到 1 + digitCount子字符串
      8. 如果 1 ≤ indexcaptureLen,则
        1. capturecaptures[index - 1]。
        2. 如果 captureundefined,则
          1. refReplacement 为空 String。
        3. 否则,
          1. refReplacementcapture
      9. 否则,
        1. refReplacementref
    7. 否则如果 templateRemainder"$<" 开始,则
      1. gtPosStringIndexOf(templateRemainder, ">", 0)。
      2. 如果 gtPosnot-foundnamedCapturesundefined,则
        1. ref"$<"
        2. refReplacementref
      3. 否则,
        1. reftemplateRemainder 中从 0 到 gtPos + 1 的子字符串
        2. groupNametemplateRemainder 中从 2 到 gtPos子字符串
        3. 断言:namedCaptures 是一个 Object。
        4. capture 为 ? Get(namedCaptures, groupName)。
        5. 如果 captureundefined,则
          1. refReplacement 为空 String。
        6. 否则,
          1. refReplacement 为 ? ToString(capture)。
    8. 否则,
      1. reftemplateRemainder 中从 0 到 1 的子字符串
      2. refReplacementref
    9. refLengthref 的长度。
    10. templateRemainder 设置为 templateRemainder 中从 refLength 开始的子字符串
    11. result 设置为 resultrefReplacement 的字符串拼接。
  6. 返回 result

22.1.3.20 String.prototype.replaceAll ( searchValue, replaceValue )

此方法在被调用时执行以下步骤:

  1. thisValuethis 值。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. 如果 searchValue 是一个 Object,则
    1. isRegExp 为 ? IsRegExp(searchValue)。
    2. 如果 isRegExptrue,则
      1. flags 为 ? Get(searchValue, "flags")。
      2. 执行 ? RequireObjectCoercible(flags)。
      3. 如果 ? ToString(flags) 不包含 "g",抛出 TypeError 异常。
    3. replacer 为 ? GetMethod(searchValue, %Symbol.replace%)。
    4. 如果 replacer 不是 undefined,则
      1. 返回 ? Call(replacer, searchValue, « thisValue, replaceValue »)。
  4. string 为 ? ToString(thisValue)。
  5. searchString 为 ? ToString(searchValue)。
  6. functionalReplaceIsCallable(replaceValue)。
  7. 如果 functionalReplacefalse,则
    1. replaceValue 设置为 ? ToString(replaceValue)。
  8. searchLengthsearchString 的长度。
  9. advanceBymax(1, searchLength)。
  10. matchPositions 为一个新的空 List
  11. positionStringIndexOf(string, searchString, 0)。
  12. 重复,当 position 不是 not-found 时,
    1. position 追加到 matchPositions
    2. position 设置为 StringIndexOf(string, searchString, position + advanceBy)。
  13. endOfLastMatch 为 0。
  14. result 为空 String。
  15. 对于 matchPositions 的每个元素 matchPosition,执行
    1. preservedstring 中从 endOfLastMatchmatchPosition子字符串
    2. 如果 functionalReplacetrue,则
      1. replacement 为 ? ToString(? Call(replaceValue, undefined, « searchString, 𝔽(matchPosition), string »))。
    3. 否则,
      1. 断言:replaceValue 是一个 String。
      2. captures 为一个新的空 List
      3. replacement 为 ! GetSubstitution(searchString, string, matchPosition, captures, undefined, replaceValue)。
    4. result 设置为 resultpreservedreplacement 的字符串拼接。
    5. endOfLastMatch 设置为 matchPosition + searchLength
  16. 如果 endOfLastMatch < string 的长度,则
    1. result 设置为 resultstring 中从 endOfLastMatch 开始的子字符串的字符串拼接。
  17. 返回 result

22.1.3.21 String.prototype.search ( regexpOrPattern )

此方法在被调用时执行以下步骤:

  1. thisValuethis 值。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. 如果 regexpOrPattern 是一个 Object,则
    1. searcher 为 ? GetMethod(regexpOrPattern, %Symbol.search%)。
    2. 如果 searcher 不是 undefined,则
      1. 返回 ? Call(searcher, regexpOrPattern, « thisValue »)。
  4. string 为 ? ToString(thisValue)。
  5. regexp 为 ? RegExpCreate(regexpOrPattern, undefined)。
  6. 返回 ? Invoke(regexp, %Symbol.search%, « string »)。
Note

此方法有意设计为泛型;它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

22.1.3.22 String.prototype.slice ( start, end )

此方法返回将此对象转换为 String 后所得结果的一个 substring,该子字符串从索引 start 开始并持续到但不包括索引 end(如果 endundefined,则一直到 String 末尾)。如果 start 为负,则将其视为 sourceLength + start,其中 sourceLength 是 String 的长度。如果 end 为负,则将其视为 sourceLength + end,其中 sourceLength 是 String 的长度。结果是 String 值,而不是 String 对象。

它在被调用时执行以下步骤:

  1. thisValuethis 值。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. str 为 ? ToString(thisValue)。
  4. lenstr 的长度。
  5. intStart 为 ? ToIntegerOrInfinity(start)。
  6. 如果 intStart = -∞,令 from 为 0。
  7. 否则如果 intStart < 0,令 frommax(len + intStart, 0)。
  8. 否则,令 frommin(intStart, len)。
  9. 如果 endundefined,令 intEndlen;否则令 intEnd 为 ? ToIntegerOrInfinity(end)。
  10. 如果 intEnd = -∞,令 to 为 0。
  11. 否则如果 intEnd < 0,令 tomax(len + intEnd, 0)。
  12. 否则,令 tomin(intEnd, len)。
  13. 如果 fromto,返回空 String。
  14. 返回 str 中从 fromto子字符串
Note

此方法有意设计为泛型;它不要求其 this 值是 String 对象。因此它可以被转移到其他种类的对象上作为方法使用。

22.1.3.23 String.prototype.split ( separator, limit )

此方法返回一个 Array,其中存储了将此对象转换为 String 后所得结果的各个子字符串。这些子字符串通过从左到右搜索 separator 的出现来确定;这些出现不是返回数组中任何 String 的一部分,而是用于分割 String 值。separator 的值可以是任意长度的 String,也可以是具有 %Symbol.split% 方法的对象,例如 RegExp。

它在被调用时执行以下步骤:

  1. thisValuethis 值。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. 如果 separator 是一个 Object,则
    1. splitter 为 ? GetMethod(separator, %Symbol.split%)。
    2. 如果 splitter 不是 undefined,则
      1. 返回 ? Call(splitter, separator, « thisValue, limit »)。
  4. str 为 ? ToString(thisValue)。
  5. 如果 limitundefined,令 lim 为 232 - 1;否则令 lim(? ToUint32(limit))。
  6. separatorStr 为 ? ToString(separator)。
  7. 如果 lim = 0,则
    1. 返回 CreateArrayFromList(« »)。
  8. 如果 separatorundefined,则
    1. 返回 CreateArrayFromListstr »)。
  9. separatorLengthseparatorStr 的长度。
  10. 如果 separatorLength = 0,则
    1. strLenstr 的长度。
    2. outLen 为将 lim 夹在 0 和 strLen 之间的结果。
    3. headstr 中从 0 到 outLen子字符串
    4. codeUnits 为一个 List,它由作为 head 元素的码元序列组成。
    5. 返回 CreateArrayFromList(codeUnits)。
  11. 如果 str 是空 String,返回 CreateArrayFromListstr »)。
  12. substrings 为一个新的空 List
  13. searchStart 为 0。
  14. matchIndexStringIndexOf(str, separatorStr, 0)。
  15. 重复,当 matchIndex 不是 not-found 时,
    1. substringstr 中从 searchStartmatchIndex子字符串
    2. substring 追加到 substrings
    3. 如果 substrings 中元素的数量是 lim,返回 CreateArrayFromList(substrings)。
    4. searchStart 设置为 matchIndex + separatorLength
    5. matchIndex 设置为 StringIndexOf(str, separatorStr, searchStart)。
  16. substringstr 中从 searchStart 开始的子字符串
  17. substring 追加到 substrings
  18. 返回 CreateArrayFromList(substrings)。
Note 1

separator 的值可以是空 String。在这种情况下,separator 不匹配输入 String 开头或结尾处的空 substring,也不匹配上一个分隔符匹配结尾处的空 substring。如果 separator 是空 String,则 String 被分割为单个码元元素;结果数组的长度等于 String 的长度,并且每个 substring 包含一个码元。

如果 this 值是(或转换为)空 String,则结果取决于 separator 是否能够匹配空 String。如果可以,则结果数组不包含任何元素。否则,结果数组包含一个元素,即空 String。

如果 separatorundefined,则结果数组只包含一个 String,即 this 值(转换为 String)。如果 limit 不是 undefined,则输出数组会被截断,使其包含不超过 limit 个元素。

Note 2

此方法有意设计为泛型;它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

22.1.3.24 String.prototype.startsWith ( searchString [ , position ] )

此方法在被调用时执行以下步骤:

  1. thisValuethis 值。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. str 为 ? ToString(thisValue)。
  4. isRegExp 为 ? IsRegExp(searchString)。
  5. 如果 isRegExptrue,抛出 TypeError 异常。
  6. searchStr 为 ? ToString(searchString)。
  7. lenstr 的长度。
  8. 如果 positionundefined,令 pos 为 0;否则令 pos 为 ? ToIntegerOrInfinity(position)。
  9. start 为将 pos 夹在 0 和 len 之间的结果。
  10. searchLengthsearchStr 的长度。
  11. 如果 searchLength = 0,返回 true
  12. endstart + searchLength
  13. 如果 end > len,返回 false
  14. substringstr 中从 startend子字符串
  15. 如果 substringsearchStr,返回 true
  16. 返回 false
Note 1

指定当第一个参数是 RegExp 时抛出异常,是为了允许未来版本定义允许此类参数值的扩展。

Note 2

此方法有意设计为泛型;它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

22.1.3.25 String.prototype.substring ( start, end )

此方法返回将此对象转换为 String 后所得结果的一个 substring,该子字符串从索引 start 开始并持续到但不包括 String 的索引 end(如果 endundefined,则一直到 String 末尾)。结果是 String 值,而不是 String 对象。

如果任一参数是 NaN 或为负,则将其替换为零;如果任一参数严格大于 String 的长度,则将其替换为 String 的长度。

如果 start 严格大于 end,则交换它们。

它在被调用时执行以下步骤:

  1. thisValuethis 值。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. str 为 ? ToString(thisValue)。
  4. lenstr 的长度。
  5. intStart 为 ? ToIntegerOrInfinity(start)。
  6. 如果 endundefined,令 intEndlen;否则令 intEnd 为 ? ToIntegerOrInfinity(end)。
  7. finalStart 为将 intStart 夹在 0 和 len 之间的结果。
  8. finalEnd 为将 intEnd 夹在 0 和 len 之间的结果。
  9. frommin(finalStart, finalEnd)。
  10. tomax(finalStart, finalEnd)。
  11. 返回 str 中从 fromto子字符串
Note

此方法有意设计为泛型;它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

22.1.3.26 String.prototype.toLocaleLowerCase ( [ reserved1 [ , reserved2 ] ] )

包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按照 ECMA-402 规范中的规定实现此方法。如果 ECMAScript 实现不包含 ECMA-402 API,则使用以下对此方法的规范:

此方法将 String 值解释为 UTF-16 编码码点的序列,如 6.1.4 中所述。

它的工作方式与 toLowerCase 完全相同,只是它旨在产生与宿主环境当前区域设置约定相对应的区域设置敏感结果。只有在少数情况下(例如土耳其语),该语言的规则与常规 Unicode 大小写映射冲突时,才会出现差异。

此方法的可选参数的含义在 ECMA-402 规范中定义;不包含 ECMA-402 支持的实现不得将这些参数位置用于任何其他用途。

Note

此方法有意设计为泛型;它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

22.1.3.27 String.prototype.toLocaleUpperCase ( [ reserved1 [ , reserved2 ] ] )

包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按照 ECMA-402 规范中的规定实现此方法。如果 ECMAScript 实现不包含 ECMA-402 API,则使用以下对此方法的规范:

此方法将 String 值解释为 UTF-16 编码码点的序列,如 6.1.4 中所述。

它的工作方式与 toUpperCase 完全相同,只是它旨在产生与宿主环境当前区域设置约定相对应的区域设置敏感结果。只有在少数情况下(例如土耳其语),该语言的规则与常规 Unicode 大小写映射冲突时,才会出现差异。

此方法的可选参数的含义在 ECMA-402 规范中定义;不包含 ECMA-402 支持的实现不得将这些参数位置用于任何其他用途。

Note

此方法有意设计为泛型;它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

22.1.3.28 String.prototype.toLowerCase ( )

此方法将 String 值解释为 UTF-16 编码码点的序列,如 6.1.4 中所述。

它在被调用时执行以下步骤:

  1. thisValuethis 值。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. str 为 ? ToString(thisValue)。
  4. sTextStringToCodePoints(str)。
  5. lowerText 为按照 Unicode 默认大小写转换算法得到的 toLowercase(sText)。
  6. lowercaseStringCodePointsToString(lowerText)。
  7. 返回 lowercaseString

结果必须根据 Unicode 字符数据库中的非区域设置敏感大小写映射派生(这明确不仅包括文件 UnicodeData.txt,还包括随附文件 SpecialCasing.txt 中所有非区域设置敏感映射)。

Note 1

某些码点的大小写映射可能产生多个码点。在这种情况下,结果 String 的长度可能与源 String 不同。由于 toUpperCasetoLowerCase 都具有上下文敏感行为,这些方法并不对称。换句话说,s.toUpperCase().toLowerCase() 不一定等于 s.toLowerCase()

Note 2

此方法有意设计为泛型;它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

22.1.3.29 String.prototype.toString ( )

此方法在被调用时执行以下步骤:

  1. 返回 ? ThisStringValue(this value)。
Note

对于 String 对象,此方法碰巧返回与 valueOf 方法相同的内容。

22.1.3.30 String.prototype.toUpperCase ( )

此方法将 String 值解释为 UTF-16 编码码点的序列,如 6.1.4 中所述。

它的行为与 String.prototype.toLowerCase 完全相同,只是使用 Unicode 默认大小写转换的 toUppercase 算法来映射 String。

Note

此方法有意设计为泛型;它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

22.1.3.31 String.prototype.toWellFormed ( )

此方法返回此对象的 String 表示,其中所有不属于代理对前导代理项和尾随代理项都被替换为 U+FFFD (REPLACEMENT CHARACTER)。

它在被调用时执行以下步骤:

  1. thisValuethis 值。
  2. 执行 ? RequireObjectCoercible(thisValue)。
  3. str 为 ? ToString(thisValue)。
  4. strLenstr 的长度。
  5. k 为 0。
  6. result 为空 String。
  7. 重复,当 k < strLen 时,
    1. cpCodePointAt(str, k)。
    2. 如果 cp.[[IsUnpairedSurrogate]]true,则
      1. result 设置为 result 与 0xFFFD (REPLACEMENT CHARACTER) 的字符串拼接。
    3. 否则,
      1. result 设置为 resultUTF16EncodeCodePoint(cp.[[CodePoint]]) 的字符串拼接。
    4. k 设置为 k + cp.[[CodeUnitCount]]
  8. 返回 result

22.1.3.32 String.prototype.trim ( )

此方法将 String 值解释为 UTF-16 编码码点的序列,如 6.1.4 中所述。

它在被调用时执行以下步骤:

  1. thisValuethis 值。
  2. 返回 ? TrimString(thisValue, start+end)。
Note

此方法有意设计为泛型;它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

22.1.3.32.1 TrimString ( string, where )

The abstract operation TrimString takes arguments string (一个 ECMAScript 语言值,) and where (startendstart+end,) and returns 要么是一个包含 String 的正常完成,要么是一个抛出完成. 它将 string 解释为 UTF-16 编码码点的序列,如 6.1.4 中所述。 It performs the following steps when called:

  1. 执行 ? RequireObjectCoercible(string)。
  2. str 为 ? ToString(string)。
  3. 如果 wherestart,则
    1. trimmedStringstr 的一个副本所成的 String 值,其中前导空白已被移除。
  4. 否则如果 whereend,则
    1. trimmedStringstr 的一个副本所成的 String 值,其中尾随空白已被移除。
  5. 否则,
    1. 断言:wherestart+end
    2. trimmedStringstr 的一个副本所成的 String 值,其中前导和尾随空白都已被移除。
  6. 返回 trimmedString

空白的定义是 WhiteSpaceLineTerminator 的并集。在确定 Unicode 码点是否属于 Unicode 通用类别 “Space_Separator”(“Zs”)时,码元序列按 6.1.4 中指定的 UTF-16 编码码点序列进行解释。

22.1.3.33 String.prototype.trimEnd ( )

此方法将 String 值解释为 UTF-16 编码码点的序列,如 6.1.4 中所述。

它在被调用时执行以下步骤:

  1. strthis 值。
  2. 返回 ? TrimString(str, end)。
Note

此方法有意设计为泛型;它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

22.1.3.34 String.prototype.trimStart ( )

此方法将 String 值解释为 UTF-16 编码码点的序列,如 6.1.4 中所述。

它在被调用时执行以下步骤:

  1. strthis 值。
  2. 返回 ? TrimString(str, start)。
Note

此方法有意设计为泛型;它不要求其 this 值是 String 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

22.1.3.35 String.prototype.valueOf ( )

此方法在被调用时执行以下步骤:

  1. 返回 ? ThisStringValue(this value)。

22.1.3.35.1 ThisStringValue ( value )

The abstract operation ThisStringValue takes argument value (一个 ECMAScript 语言值,) and returns 要么是一个包含 String 的正常完成,要么是一个抛出完成. It performs the following steps when called:

  1. 如果 value 是一个 String,返回 value
  2. 如果 value 是一个 Object 且 value 具有 [[StringData]] 内部槽,则
    1. strvalue.[[StringData]]
    2. 断言:str 是一个 String。
    3. 返回 str
  3. 抛出 TypeError 异常。

22.1.3.36 String.prototype [ %Symbol.iterator% ] ( )

此方法返回一个迭代器对象,该对象迭代 String 值的码点,并将每个码点作为 String 值返回。

它在被调用时执行以下步骤:

  1. strthis 值。
  2. 执行 ? RequireObjectCoercible(str)。
  3. str 设置为 ? ToString(str)。
  4. closure 为一个没有参数的新 Abstract Closure,它捕获 str,并在被调用时执行以下步骤:
    1. lenstr 的长度。
    2. position 为 0。
    3. 重复,当 position < len 时,
      1. cpCodePointAt(str, position)。
      2. nextIndexposition + cp.[[CodeUnitCount]]
      3. resultStringstr 中从 positionnextIndex子字符串
      4. position 设置为 nextIndex
      5. 执行 ? GeneratorYield(CreateIteratorResultObject(resultString, false))。
    4. 返回 NormalCompletion(unused)。
  5. 返回 CreateIteratorFromClosure(closure, "%StringIteratorPrototype%", %StringIteratorPrototype%)。

此方法的 "name" 属性的值为 "[Symbol.iterator]"

22.1.4 String 实例的属性

String 实例是 String 异质对象,并具有为此类对象指定的内部方法。String 实例从 String 原型对象继承属性。String 实例还有一个 [[StringData]] 内部槽。[[StringData]] 内部槽是由此 String 对象表示的 String 值。

String 实例有一个 "length" 属性,以及一组具有整数索引名称的可枚举属性。

22.1.4.1 length

由此 String 对象表示的 String 值中的元素数量。

一旦 String 对象被初始化,此属性即不可更改。它具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

22.1.5 String Iterator 对象

String Iterator 是一个表示对某个特定 String 实例对象进行特定迭代的对象。String Iterator 对象没有具名构造器。相反,String Iterator 对象是通过调用 String 实例对象的某些方法创建的。

22.1.5.1 %StringIteratorPrototype% 对象

%StringIteratorPrototype% 对象:

22.1.5.1.1 %StringIteratorPrototype%.next ( )

  1. 返回 ? GeneratorResume(this value, empty, "%StringIteratorPrototype%")。

22.1.5.1.2 %StringIteratorPrototype% [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "String Iterator"

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

22.2 RegExp(正则表达式)对象

RegExp 对象包含一个正则表达式和关联的标志。

Note

正则表达式的形式和功能以 Perl 5 编程语言中的正则表达式设施为模型。

22.2.1 模式

RegExp 构造器将以下文法应用于输入的 pattern String。如果文法无法将该 String 解释为 Pattern 的展开,则发生错误。

语法

Pattern[UnicodeMode, UnicodeSetsMode, NamedCaptureGroups] :: Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Disjunction[UnicodeMode, UnicodeSetsMode, NamedCaptureGroups] :: Alternative[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Alternative[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] | Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Alternative[UnicodeMode, UnicodeSetsMode, NamedCaptureGroups] :: [empty] Alternative[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Term[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Term[UnicodeMode, UnicodeSetsMode, NamedCaptureGroups] :: Assertion[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Atom[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Atom[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Quantifier Assertion[UnicodeMode, UnicodeSetsMode, NamedCaptureGroups] :: ^ $ \b \B (?= Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) (?! Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) (?<= Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) (?<! Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) Quantifier :: QuantifierPrefix QuantifierPrefix ? QuantifierPrefix :: * + ? { DecimalDigits[~Sep] } { DecimalDigits[~Sep] ,} { DecimalDigits[~Sep] , DecimalDigits[~Sep] } Atom[UnicodeMode, UnicodeSetsMode, NamedCaptureGroups] :: PatternCharacter . \ AtomEscape[?UnicodeMode, ?NamedCaptureGroups] CharacterClass[?UnicodeMode, ?UnicodeSetsMode] ( GroupSpecifier[?UnicodeMode]opt Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) (? RegularExpressionModifiers : Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) (? RegularExpressionModifiers - RegularExpressionModifiers : Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) RegularExpressionModifiers :: [empty] RegularExpressionModifiers RegularExpressionModifier RegularExpressionModifier :: one of i m s SyntaxCharacter :: one of ^ $ \ . * + ? ( ) [ ] { } | PatternCharacter :: SourceCharacter but not SyntaxCharacter AtomEscape[UnicodeMode, NamedCaptureGroups] :: DecimalEscape CharacterClassEscape[?UnicodeMode] CharacterEscape[?UnicodeMode] [+NamedCaptureGroups] k GroupName[?UnicodeMode] CharacterEscape[UnicodeMode] :: ControlEscape c AsciiLetter 0 [lookahead ∉ DecimalDigit] HexEscapeSequence RegExpUnicodeEscapeSequence[?UnicodeMode] IdentityEscape[?UnicodeMode] ControlEscape :: one of f n r t v GroupSpecifier[UnicodeMode] :: ? GroupName[?UnicodeMode] GroupName[UnicodeMode] :: < RegExpIdentifierName[?UnicodeMode] > RegExpIdentifierName[UnicodeMode] :: RegExpIdentifierStart[?UnicodeMode] RegExpIdentifierName[?UnicodeMode] RegExpIdentifierPart[?UnicodeMode] RegExpIdentifierStart[UnicodeMode] :: IdentifierStartChar \ RegExpUnicodeEscapeSequence[+UnicodeMode] [~UnicodeMode] UnicodeLeadSurrogate UnicodeTrailSurrogate RegExpIdentifierPart[UnicodeMode] :: IdentifierPartChar \ RegExpUnicodeEscapeSequence[+UnicodeMode] [~UnicodeMode] UnicodeLeadSurrogate UnicodeTrailSurrogate RegExpUnicodeEscapeSequence[UnicodeMode] :: [+UnicodeMode] u HexLeadSurrogate \u HexTrailSurrogate [+UnicodeMode] u HexLeadSurrogate [+UnicodeMode] u HexTrailSurrogate [+UnicodeMode] u HexNonSurrogate [~UnicodeMode] u Hex4Digits [+UnicodeMode] u{ CodePoint } UnicodeLeadSurrogate :: any Unicode code point in the inclusive interval from U+D800 to U+DBFF UnicodeTrailSurrogate :: any Unicode code point in the inclusive interval from U+DC00 to U+DFFF

对于每个关联的 u HexLeadSurrogate 选择存在歧义的 \u HexTrailSurrogate,都应与最近的可能的 u HexLeadSurrogate 关联,且该 u HexLeadSurrogate 原本不会有对应的 \u HexTrailSurrogate

HexLeadSurrogate :: Hex4Digits but only if the MV of Hex4Digits is in the inclusive interval from 0xD800 to 0xDBFF HexTrailSurrogate :: Hex4Digits but only if the MV of Hex4Digits is in the inclusive interval from 0xDC00 to 0xDFFF HexNonSurrogate :: Hex4Digits but only if the MV of Hex4Digits is not in the inclusive interval from 0xD800 to 0xDFFF IdentityEscape[UnicodeMode] :: [+UnicodeMode] SyntaxCharacter [+UnicodeMode] / [~UnicodeMode] SourceCharacter but not UnicodeIDContinue DecimalEscape :: NonZeroDigit DecimalDigits[~Sep]opt [lookahead ∉ DecimalDigit] CharacterClassEscape[UnicodeMode] :: d D s S w W [+UnicodeMode] p{ UnicodePropertyValueExpression } [+UnicodeMode] P{ UnicodePropertyValueExpression } UnicodePropertyValueExpression :: UnicodePropertyName = UnicodePropertyValue LoneUnicodePropertyNameOrValue UnicodePropertyName :: UnicodePropertyNameCharacters UnicodePropertyNameCharacters :: UnicodePropertyNameCharacter UnicodePropertyNameCharactersopt UnicodePropertyValue :: UnicodePropertyValueCharacters LoneUnicodePropertyNameOrValue :: UnicodePropertyValueCharacters UnicodePropertyValueCharacters :: UnicodePropertyValueCharacter UnicodePropertyValueCharactersopt UnicodePropertyValueCharacter :: UnicodePropertyNameCharacter DecimalDigit UnicodePropertyNameCharacter :: AsciiLetter _ CharacterClass[UnicodeMode, UnicodeSetsMode] :: [ [lookahead ≠ ^] ClassContents[?UnicodeMode, ?UnicodeSetsMode] ] [^ ClassContents[?UnicodeMode, ?UnicodeSetsMode] ] ClassContents[UnicodeMode, UnicodeSetsMode] :: [empty] [~UnicodeSetsMode] NonemptyClassRanges[?UnicodeMode] [+UnicodeSetsMode] ClassSetExpression NonemptyClassRanges[UnicodeMode] :: ClassAtom[?UnicodeMode] ClassAtom[?UnicodeMode] NonemptyClassRangesNoDash[?UnicodeMode] ClassAtom[?UnicodeMode] - ClassAtom[?UnicodeMode] ClassContents[?UnicodeMode, ~UnicodeSetsMode] NonemptyClassRangesNoDash[UnicodeMode] :: ClassAtom[?UnicodeMode] ClassAtomNoDash[?UnicodeMode] NonemptyClassRangesNoDash[?UnicodeMode] ClassAtomNoDash[?UnicodeMode] - ClassAtom[?UnicodeMode] ClassContents[?UnicodeMode, ~UnicodeSetsMode] ClassAtom[UnicodeMode] :: - ClassAtomNoDash[?UnicodeMode] ClassAtomNoDash[UnicodeMode] :: SourceCharacter but not one of \ or ] or - \ ClassEscape[?UnicodeMode] ClassEscape[UnicodeMode] :: b [+UnicodeMode] - CharacterClassEscape[?UnicodeMode] CharacterEscape[?UnicodeMode] ClassSetExpression :: ClassUnion ClassIntersection ClassSubtraction ClassUnion :: ClassSetRange ClassUnionopt ClassSetOperand ClassUnionopt ClassIntersection :: ClassSetOperand && [lookahead ≠ &] ClassSetOperand ClassIntersection && [lookahead ≠ &] ClassSetOperand ClassSubtraction :: ClassSetOperand -- ClassSetOperand ClassSubtraction -- ClassSetOperand ClassSetRange :: ClassSetCharacter - ClassSetCharacter ClassSetOperand :: NestedClass ClassStringDisjunction ClassSetCharacter NestedClass :: [ [lookahead ≠ ^] ClassContents[+UnicodeMode, +UnicodeSetsMode] ] [^ ClassContents[+UnicodeMode, +UnicodeSetsMode] ] \ CharacterClassEscape[+UnicodeMode] Note 1

这里的前两行等价于 CharacterClass。

ClassStringDisjunction :: \q{ ClassStringDisjunctionContents } ClassStringDisjunctionContents :: ClassString ClassString | ClassStringDisjunctionContents ClassString :: [empty] NonEmptyClassString NonEmptyClassString :: ClassSetCharacter NonEmptyClassStringopt ClassSetCharacter :: [lookahead ∉ ClassSetReservedDoublePunctuator] SourceCharacter but not ClassSetSyntaxCharacter \ CharacterEscape[+UnicodeMode] \ ClassSetReservedPunctuator \b ClassSetReservedDoublePunctuator :: one of && !! ## $$ %% ** ++ ,, .. :: ;; << == >> ?? @@ ^^ `` ~~ ClassSetSyntaxCharacter :: one of ( ) [ ] { } / - \ | ClassSetReservedPunctuator :: one of & - ! # % , : ; < = > @ ` ~ Note 2

本节中的若干产生式在 B.1.2 一节中给出了替代定义。

22.2.1.1 Static Semantics: 早期错误

Note

本节在 B.1.2.1 中被修订。

Pattern :: Disjunction QuantifierPrefix :: { DecimalDigits , DecimalDigits } Atom :: (? RegularExpressionModifiers : Disjunction ) Atom :: (? RegularExpressionModifiers - RegularExpressionModifiers : Disjunction ) AtomEscape :: k GroupName AtomEscape :: DecimalEscape NonemptyClassRanges :: ClassAtom - ClassAtom ClassContents NonemptyClassRangesNoDash :: ClassAtomNoDash - ClassAtom ClassContents RegExpIdentifierStart :: \ RegExpUnicodeEscapeSequence RegExpIdentifierStart :: UnicodeLeadSurrogate UnicodeTrailSurrogate RegExpIdentifierPart :: \ RegExpUnicodeEscapeSequence RegExpIdentifierPart :: UnicodeLeadSurrogate UnicodeTrailSurrogate UnicodePropertyValueExpression :: UnicodePropertyName = UnicodePropertyValue UnicodePropertyValueExpression :: LoneUnicodePropertyNameOrValue CharacterClassEscape :: P{ UnicodePropertyValueExpression } CharacterClass :: [^ ClassContents ] NestedClass :: [^ ClassContents ] ClassSetRange :: ClassSetCharacter - ClassSetCharacter

22.2.1.2 Static Semantics: CountLeftCapturingParensWithin ( node )

The abstract operation CountLeftCapturingParensWithin takes argument node (一个 Parse Node,) and returns 一个非负整数. 它返回 node 中左捕获括号的数量。左捕获括号是任意由 Atom :: ( GroupSpecifieropt Disjunction ) 产生式的 ( 终结符所匹配的 ( 模式字符。

Note

本节在 B.1.2.2 中被修订。

It performs the following steps when called:

  1. 断言:nodeRegExp Pattern 文法 中某个产生式的实例。
  2. 返回 node 中包含的 Atom :: ( GroupSpecifieropt Disjunction ) Parse Node 的数量。

22.2.1.3 Static Semantics: CountLeftCapturingParensBefore ( node )

The abstract operation CountLeftCapturingParensBefore takes argument node (一个 Parse Node,) and returns 一个非负整数. 它返回外围 pattern 中位于 node 左侧的左捕获括号的数量。

Note

本节在 B.1.2.2 中被修订。

It performs the following steps when called:

  1. 断言:nodeRegExp Pattern 文法 中某个产生式的实例。
  2. pattern 为包含 nodePattern
  3. 返回 pattern 中包含的、出现在 node 之前或包含 node Atom :: ( GroupSpecifieropt Disjunction ) Parse Node 的数量。

22.2.1.4 Static Semantics: MightBothParticipate ( x, y )

The abstract operation MightBothParticipate takes arguments x (一个 Parse Node,) and y (一个 Parse Node,) and returns 一个 Boolean. It performs the following steps when called:

  1. 断言:xy 具有相同的外围 Pattern
  2. 如果外围 Pattern 包含一个 Disjunction :: Alternative | Disjunction Parse Node,使得 x 包含在 Alternative 中且 y 包含在派生的 Disjunction 中,或者 x 包含在派生的 Disjunction 中且 y 包含在 Alternative 中,返回 false
  3. 返回 true

22.2.1.5 Static Semantics: CapturingGroupNumber

The syntax-directed operation CapturingGroupNumber takes no arguments and returns 一个正整数.

Note

本节在 B.1.2.1 中被修订。

It is defined piecewise over the following productions:

DecimalEscape :: NonZeroDigit
  1. 返回 NonZeroDigit 的 MV。
DecimalEscape :: NonZeroDigit DecimalDigits
  1. nDecimalDigits 中码点的数量。
  2. 返回(NonZeroDigit 的 MV × 10n 加上 DecimalDigits 的 MV)。

NonZeroDigit 的 MV”和“DecimalDigits 的 MV”的定义在 12.9.3 中。

22.2.1.6 Static Semantics: IsCharacterClass

The syntax-directed operation IsCharacterClass takes no arguments and returns 一个 Boolean.

Note

本节在 B.1.2.3 中被修订。

It is defined piecewise over the following productions:

ClassAtom :: - ClassAtomNoDash :: SourceCharacter but not one of \ or ] or - ClassEscape :: b - CharacterEscape
  1. 返回 false
ClassEscape :: CharacterClassEscape
  1. 返回 true

22.2.1.7 Static Semantics: CharacterValue

The syntax-directed operation CharacterValue takes no arguments and returns 一个非负整数.

Note 1

本节在 B.1.2.4 中被修订。

It is defined piecewise over the following productions:

ClassAtom :: -
  1. 返回 U+002D (HYPHEN-MINUS) 的数值。
ClassAtomNoDash :: SourceCharacter but not one of \ or ] or -
  1. ch 为由 SourceCharacter 匹配的码点。
  2. 返回 ch 的数值。
ClassEscape :: b
  1. 返回 U+0008 (BACKSPACE) 的数值。
ClassEscape :: -
  1. 返回 U+002D (HYPHEN-MINUS) 的数值。
CharacterEscape :: ControlEscape
  1. 返回根据 Table 62 的数值。
Table 62: ControlEscape 码点值
ControlEscape 数值 码点 Unicode 名称 符号
t 9 U+0009 CHARACTER TABULATION <HT>
n 10 U+000A LINE FEED (LF) <LF>
v 11 U+000B LINE TABULATION <VT>
f 12 U+000C FORM FEED (FF) <FF>
r 13 U+000D CARRIAGE RETURN (CR) <CR>
CharacterEscape :: c AsciiLetter
  1. ch 为由 AsciiLetter 匹配的码点。
  2. ich 的数值。
  3. 返回 i 除以 32 的余数。
CharacterEscape :: 0 [lookahead ∉ DecimalDigit]
  1. 返回 U+0000 (NULL) 的数值。
Note 2

\0 表示 <NUL> 字符,且其后不能跟十进制数字。

CharacterEscape :: HexEscapeSequence
  1. 返回 HexEscapeSequence 的 MV。
RegExpUnicodeEscapeSequence :: u HexLeadSurrogate \u HexTrailSurrogate
  1. leadHexLeadSurrogateCharacterValue
  2. trailHexTrailSurrogateCharacterValue
  3. cpUTF16SurrogatePairToCodePoint(lead, trail)。
  4. 返回 cp 的数值。
RegExpUnicodeEscapeSequence :: u Hex4Digits
  1. 返回 Hex4Digits 的 MV。
RegExpUnicodeEscapeSequence :: u{ CodePoint }
  1. 返回 CodePoint 的 MV。
HexLeadSurrogate :: Hex4Digits HexTrailSurrogate :: Hex4Digits HexNonSurrogate :: Hex4Digits
  1. 返回 Hex4Digits 的 MV。
CharacterEscape :: IdentityEscape
  1. ch 为由 IdentityEscape 匹配的码点。
  2. 返回 ch 的数值。
ClassSetCharacter :: SourceCharacter but not ClassSetSyntaxCharacter
  1. ch 为由 SourceCharacter 匹配的码点。
  2. 返回 ch 的数值。
ClassSetCharacter :: \ ClassSetReservedPunctuator
  1. ch 为由 ClassSetReservedPunctuator 匹配的码点。
  2. 返回 ch 的数值。
ClassSetCharacter :: \b
  1. 返回 U+0008 (BACKSPACE) 的数值。

22.2.1.8 Static Semantics: MayContainStrings

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

CharacterClassEscape :: d D s S w W P{ UnicodePropertyValueExpression } UnicodePropertyValueExpression :: UnicodePropertyName = UnicodePropertyValue NestedClass :: [^ ClassContents ] ClassContents :: [empty] NonemptyClassRanges ClassSetOperand :: ClassSetCharacter
  1. 返回 false
UnicodePropertyValueExpression :: LoneUnicodePropertyNameOrValue
  1. 如果 LoneUnicodePropertyNameOrValue 匹配的源文本Table 66 的 “Property name” 列中列出的字符串二元属性,返回 true
  2. 返回 false
ClassUnion :: ClassSetRange ClassUnionopt
  1. 如果 ClassUnion 存在,返回 ClassUnionMayContainStrings
  2. 返回 false
ClassUnion :: ClassSetOperand ClassUnionopt
  1. 如果 ClassSetOperandMayContainStringstrue,返回 true
  2. 如果 ClassUnion 存在,返回 ClassUnionMayContainStrings
  3. 返回 false
ClassIntersection :: ClassSetOperand && ClassSetOperand
  1. 如果第一个 ClassSetOperandMayContainStringsfalse,返回 false
  2. 如果第二个 ClassSetOperandMayContainStringsfalse,返回 false
  3. 返回 true
ClassIntersection :: ClassIntersection && ClassSetOperand
  1. 如果 ClassIntersectionMayContainStringsfalse,返回 false
  2. 如果 ClassSetOperandMayContainStringsfalse,返回 false
  3. 返回 true
ClassSubtraction :: ClassSetOperand -- ClassSetOperand
  1. 返回第一个 ClassSetOperandMayContainStrings
ClassSubtraction :: ClassSubtraction -- ClassSetOperand
  1. 返回 ClassSubtractionMayContainStrings
ClassStringDisjunctionContents :: ClassString | ClassStringDisjunctionContents
  1. 如果 ClassStringMayContainStringstrue,返回 true
  2. 返回 ClassStringDisjunctionContentsMayContainStrings
ClassString :: [empty]
  1. 返回 true
ClassString :: NonEmptyClassString
  1. 返回 NonEmptyClassStringMayContainStrings
NonEmptyClassString :: ClassSetCharacter NonEmptyClassStringopt
  1. 如果 NonEmptyClassString 存在,返回 true
  2. 返回 false

22.2.1.9 Static Semantics: GroupSpecifiersThatMatch ( thisGroupName )

The abstract operation GroupSpecifiersThatMatch takes argument thisGroupName (一个 GroupName Parse Node,) and returns 一个 GroupSpecifier Parse Node 的 List. It performs the following steps when called:

  1. namethisGroupNameCapturingGroupName
  2. pattern 为包含 thisGroupNamePattern
  3. result 为一个新的空 List
  4. 对于 pattern 包含的每个 GroupSpecifier gs,执行
    1. 如果 gsCapturingGroupNamename,则
      1. gs 追加到 result
  5. 返回 result

22.2.1.10 Static Semantics: CapturingGroupName

The syntax-directed operation CapturingGroupName takes no arguments and returns 一个 String. It is defined piecewise over the following productions:

GroupName :: < RegExpIdentifierName >
  1. idTextUnescapedRegExpIdentifierNameRegExpIdentifierCodePoints
  2. 返回 CodePointsToString(idTextUnescaped)。

22.2.1.11 Static Semantics: RegExpIdentifierCodePoints

The syntax-directed operation RegExpIdentifierCodePoints takes no arguments and returns 一个码点 List. It is defined piecewise over the following productions:

RegExpIdentifierName :: RegExpIdentifierStart
  1. cpRegExpIdentifierStartRegExpIdentifierCodePoint
  2. 返回 « cp »。
RegExpIdentifierName :: RegExpIdentifierName RegExpIdentifierPart
  1. cps 为派生的 RegExpIdentifierNameRegExpIdentifierCodePoints
  2. cpRegExpIdentifierPartRegExpIdentifierCodePoint
  3. 返回 cps 与 « cp » 的列表拼接。

22.2.1.12 Static Semantics: RegExpIdentifierCodePoint

The syntax-directed operation RegExpIdentifierCodePoint takes no arguments and returns 一个码点. It is defined piecewise over the following productions:

RegExpIdentifierStart :: IdentifierStartChar
  1. 返回由 IdentifierStartChar 匹配的码点。
RegExpIdentifierPart :: IdentifierPartChar
  1. 返回由 IdentifierPartChar 匹配的码点。
RegExpIdentifierStart :: \ RegExpUnicodeEscapeSequence RegExpIdentifierPart :: \ RegExpUnicodeEscapeSequence
  1. 返回其数值为 RegExpUnicodeEscapeSequenceCharacterValue 的码点。
RegExpIdentifierStart :: UnicodeLeadSurrogate UnicodeTrailSurrogate RegExpIdentifierPart :: UnicodeLeadSurrogate UnicodeTrailSurrogate
  1. lead 为其数值是由 UnicodeLeadSurrogate 匹配的码点数值的码元。
  2. trail 为其数值是由 UnicodeTrailSurrogate 匹配的码点数值的码元。
  3. 返回 UTF16SurrogatePairToCodePoint(lead, trail)。

22.2.2 模式语义

正则表达式模式会通过下文描述的过程被转换为一个 Abstract Closure。鼓励实现使用比下列算法更高效的算法,只要结果相同即可。该 Abstract Closure 用作 RegExp 对象的 [[RegExpMatcher]] 内部槽的值。

如果一个 Pattern 的关联标志既不包含 u 也不包含 v,则它是 BMP 模式。否则,它是 Unicode 模式。BMP 模式匹配一个被解释为由 16 位值序列组成的 String,这些 16 位值是基本多文种平面范围内的 Unicode 码点。Unicode 模式匹配一个被解释为由使用 UTF-16 编码的 Unicode 码点组成的 String。在描述 BMP 模式行为的上下文中,“字符”指单个 16 位 Unicode BMP 码点。在描述 Unicode 模式行为的上下文中,“字符”指一个 UTF-16 编码码点(6.1.4)。在任一上下文中,“字符值”指对应的未编码码点的数值。

Pattern 的语法和语义被定义为仿佛 Pattern 的源文本是一个 SourceCharacter 值的 List,其中每个 SourceCharacter 对应一个 Unicode 码点。如果 BMP 模式包含一个非 BMP SourceCharacter,则整个模式使用 UTF-16 编码,并将该编码的各个码元用作该 List 的元素。

Note

例如,考虑一个在源文本中表示为单个非 BMP 字符 U+1D11E (MUSICAL SYMBOL G CLEF) 的模式。将其解释为 Unicode 模式时,它将是一个由单个码点 U+1D11E 组成的单元素(字符)List。然而,将其解释为 BMP 模式时,它首先会被 UTF-16 编码,从而产生一个由码元 0xD834 和 0xDD1E 组成的双元素 List

模式作为 ECMAScript String 值传递给 RegExp 构造器,其中非 BMP 字符以 UTF-16 编码。例如,单个字符 MUSICAL SYMBOL G CLEF 模式表示为 String 值时,是一个长度为 2 的 String,其元素为码元 0xD834 和 0xDD1E。因此,将它作为由两个模式字符组成的 BMP 模式处理时,无需对该字符串进行进一步转换。然而,要将它作为 Unicode 模式处理,必须使用 UTF16SurrogatePairToCodePoint 来产生一个 List,其唯一元素是单个模式字符,即码点 U+1D11E。

实现实际上可以不执行这种到 UTF-16 或从 UTF-16 的转换,但本规范的语义要求模式匹配的结果仿佛这些转换已经执行。

22.2.2.1 记法

以下描述使用下列内部数据结构:

  • CharSetElement 是以下两个实体之一:
    • 如果 regexpRecord.[[UnicodeSets]]false,则 CharSetElement 是上文模式语义意义上的一个字符。
    • 如果 regexpRecord.[[UnicodeSets]]true,则 CharSetElement 是一个序列,其元素是上文模式语义意义上的字符。这包括空序列、单字符序列以及多字符序列。为方便起见,在处理此类 CharSetElement 时,单个字符可与单字符序列互换对待。
  • CharSet 是 CharSetElement 的数学集合。
  • CaptureRange 是一个 Record { [[StartIndex]], [[EndIndex]] },表示包含在一次捕获中的字符范围,其中 [[StartIndex]] 是一个整数,表示该范围在 input 中的起始索引(包含),[[EndIndex]] 是一个整数,表示该范围在 input 中的结束索引(不包含)。对于任何 CaptureRange,这些索引必须满足 [[StartIndex]][[EndIndex]] 的不变式。
  • MatchState 是一个 Record { [[Input]], [[EndIndex]], [[Captures]] },其中 [[Input]] 是表示正在匹配的 String 的字符 List[[EndIndex]] 是一个整数[[Captures]] 是一个值的 List,模式中每个左捕获括号对应一个值。MatchState 用于在正则表达式匹配算法中表示部分匹配状态。[[EndIndex]] 是到目前为止被模式匹配的最后一个输入字符的索引加一,而 [[Captures]] 保存捕获括号的结果。[[Captures]] 的第 nth 个元素要么是一个 CaptureRange,表示第 nth 组捕获括号所捕获的字符范围,要么是 undefined,表示第 nth 组捕获括号尚未到达。由于回溯,在匹配过程中任意时刻可能有多个 MatchState 正在使用。
  • MatcherContinuation 是一个 Abstract Closure,它接受一个 MatchState 参数并返回一个 MatchStatefailureMatcherContinuation 尝试将模式的剩余部分(由该闭包捕获的值指定)与 input 进行匹配,从其 MatchState 参数给出的中间状态开始。如果匹配成功,MatcherContinuation 返回它到达的最终 MatchState;如果匹配失败,MatcherContinuation 返回 failure
  • Matcher 是一个 Abstract Closure,它接受两个参数——一个 MatchState 和一个 MatcherContinuation——并返回一个 MatchStatefailureMatcher 尝试将模式的中间子模式(由该闭包捕获的值指定)与 MatchState[[Input]] 匹配,从其 MatchState 参数给出的中间状态开始。MatcherContinuation 参数应是一个匹配模式其余部分的闭包。在匹配模式的子模式以获得新的 MatchState 之后,Matcher 随后在该新的 MatchState 上调用 MatcherContinuation,以测试模式的其余部分是否也能匹配。如果可以,Matcher 返回 MatcherContinuation 返回的 MatchState;如果不可以,Matcher 可以在其选择点尝试不同选择,反复调用 MatcherContinuation,直到成功或所有可能性耗尽。

22.2.2.1.1 RegExp Record

RegExp Record 是一个 Record 值,用于存储在编译期间以及可能在匹配期间需要的 RegExp 相关信息。

它具有以下字段:

Table 63: RegExp Record 字段
字段名 含义
[[IgnoreCase]] 一个 Boolean 指示 RegExp 的标志中是否出现 "i"
[[Multiline]] 一个 Boolean 指示 RegExp 的标志中是否出现 "m"
[[DotAll]] 一个 Boolean 指示 RegExp 的标志中是否出现 "s"
[[Unicode]] 一个 Boolean 指示 RegExp 的标志中是否出现 "u"
[[UnicodeSets]] 一个 Boolean 指示 RegExp 的标志中是否出现 "v"
[[CapturingGroupsCount]] 一个非负整数 RegExp 的模式中左捕获括号的数量

22.2.2.2 Runtime Semantics: CompilePattern

The syntax-directed operation CompilePattern takes argument regexpRecord (一个 RegExp Record,) and returns 一个 Abstract Closure,该闭包接受一个字符 List 和一个非负整数,并返回一个 MatchStatefailure. It is defined piecewise over the following productions:

Pattern :: Disjunction
  1. m 为以 regexpRecordforward 为参数的 DisjunctionCompileSubpattern
  2. 返回一个新的 Abstract Closure,其参数为 (input, index),捕获 regexpRecordm,并在被调用时执行以下步骤:
    1. 断言:input 是一个字符 List
    2. 断言:0 ≤ indexinput 中元素的数量。
    3. c 为一个新的 MatcherContinuation,其参数为 (y),不捕获任何内容,并在被调用时执行以下步骤:
      1. 断言:y 是一个 MatchState
      2. 返回 y
    4. cap 为由 regexpRecord.[[CapturingGroupsCount]]undefined 值组成的 List,索引从 1 到 regexpRecord.[[CapturingGroupsCount]]
    5. xMatchState { [[Input]]: input, [[EndIndex]]: index, [[Captures]]: cap }。
    6. 返回 m(x, c)。
Note

Pattern 会编译为一个 Abstract Closure 值。随后 RegExpBuiltinExec 可将此过程应用于一个字符 List 和该 List 中的偏移量,以确定模式是否会从该 List 中恰好该偏移量处开始匹配,并且如果确实匹配,捕获括号的值会是什么。22.2.2 中的算法被设计为使得编译模式可能抛出 SyntaxError 异常;另一方面,一旦模式成功编译,将得到的 Abstract Closure 应用于在字符 List 中查找匹配就不能抛出异常(除了可能在任何地方发生的任何实现定义异常,例如内存不足)。

22.2.2.3 Runtime Semantics: CompileSubpattern

The syntax-directed operation CompileSubpattern takes arguments regexpRecord (一个 RegExp Record,) and direction (forwardbackward,) and returns 一个 Matcher.

Note 1

本节在 B.1.2.5 中被修订。

It is defined piecewise over the following productions:

Disjunction :: Alternative | Disjunction
  1. m1 为以 regexpRecorddirection 为参数的 AlternativeCompileSubpattern
  2. m2 为以 regexpRecorddirection 为参数的 DisjunctionCompileSubpattern
  3. 返回 MatchTwoAlternatives(m1, m2)。
Note 2

| 正则表达式运算符分隔两个替代项。模式首先尝试匹配左侧 Alternative(后跟正则表达式的后续部分);如果失败,则尝试匹配右侧 Disjunction(后跟正则表达式的后续部分)。如果左侧 Alternative、右侧 Disjunction 和后续部分都具有选择点,则在转向左侧 Alternative 的下一个选择之前,会先尝试后续部分中的所有选择。如果左侧 Alternative 中的选择被耗尽,则尝试右侧 Disjunction 而不是左侧 Alternative。模式中被 | 跳过的部分内的任何捕获括号都会产生 undefined 值而不是 String。因此,例如,

/a|ab/.exec("abc")

返回结果 "a" 而不是 "ab"。此外,

/((a)|(ab))((c)|(bc))/.exec("abc")

返回数组

["abc", "a", "a", undefined, "bc", undefined, "bc"]

而不是

["abc", "ab", undefined, "ab", "c", "c", undefined]

尝试这两个替代项的顺序独立于 direction 的值。

Alternative :: [empty]
  1. 返回 EmptyMatcher()。
Alternative :: Alternative Term
  1. m1 为以 regexpRecorddirection 为参数的 AlternativeCompileSubpattern
  2. m2 为以 regexpRecorddirection 为参数的 TermCompileSubpattern
  3. 返回 MatchSequence(m1, m2, direction)。
Note 3

连续的 Term 会尝试同时匹配 input 的连续部分。当 directionforward 时,如果左侧 Alternative、右侧 Term 和正则表达式的后续部分都具有选择点,则在转向右侧 Term 的下一个选择之前,会先尝试后续部分中的所有选择;在转向左侧 Alternative 的下一个选择之前,会先尝试右侧 Term 中的所有选择。当 directionbackward 时,AlternativeTerm 的求值顺序相反。

Term :: Assertion
  1. 返回以 regexpRecord 为参数的 AssertionCompileAssertion
Note 4

得到的 Matcher 独立于 direction

Term :: Atom
  1. 返回以 regexpRecorddirection 为参数的 AtomCompileAtom
Term :: Atom Quantifier
  1. m 为以 regexpRecorddirection 为参数的 AtomCompileAtom
  2. qQuantifierCompileQuantifier
  3. 断言:q.[[Min]]q.[[Max]]
  4. parenIndexCountLeftCapturingParensBefore(Term)。
  5. parenCountCountLeftCapturingParensWithin(Atom)。
  6. 返回一个新的 Matcher,其参数为 (x, c),捕获 mqparenIndexparenCount,并在被调用时执行以下步骤:
    1. 断言:x 是一个 MatchState
    2. 断言:c 是一个 MatcherContinuation
    3. 返回 RepeatMatcher(m, q.[[Min]], q.[[Max]], q.[[Greedy]], x, c, parenIndex, parenCount)。

22.2.2.3.1 RepeatMatcher ( m, min, max, greedy, matchState, continue, parenIndex, parenCount )

The abstract operation RepeatMatcher takes arguments m (一个 Matcher,), min (一个非负整数,), max (一个非负整数或 +∞,), greedy (一个 Boolean,), matchState (一个 MatchState,), continue (一个 MatcherContinuation,), parenIndex (一个非负整数,), and parenCount (一个非负整数,) and returns 一个 MatchStatefailure. It performs the following steps when called:

  1. 如果 max = 0,返回 continue(matchState)。
  2. d 为一个新的 MatcherContinuation,其参数为 (y),捕获 mminmaxgreedymatchStatecontinueparenIndexparenCount,并在被调用时执行以下步骤:
    1. 断言:y 是一个 MatchState
    2. 如果 min = 0 且 y.[[EndIndex]] = matchState.[[EndIndex]],返回 failure
    3. 如果 min = 0,令 min2 为 0;否则令 min2min - 1。
    4. 如果 max = +∞,令 max2 为 +∞;否则令 max2max - 1。
    5. 返回 RepeatMatcher(m, min2, max2, greedy, y, continue, parenIndex, parenCount)。
  3. capmatchState.[[Captures]] 的副本。
  4. 对于从 parenIndex + 1 到 parenIndex + parenCount 闭区间内的每个整数 k,将 cap[k] 设置为 undefined
  5. inputmatchState.[[Input]]
  6. ematchState.[[EndIndex]]
  7. xrMatchState { [[Input]]: input, [[EndIndex]]: e, [[Captures]]: cap }。
  8. 如果 min ≠ 0,返回 m(xr, d)。
  9. 如果 greedyfalse,则
    1. zcontinue(matchState)。
    2. 如果 z 不是 failure,返回 z
    3. 返回 m(xr, d)。
  10. zm(xr, d)。
  11. 如果 z 不是 failure,返回 z
  12. 返回 continue(matchState)。
Note 1

Atom 后跟 Quantifier 会按 Quantifier 指定的次数重复。Quantifier 可以是非贪婪的,在这种情况下 Atom 模式会尽可能少地重复,同时仍然匹配后续部分;也可以是贪婪的,在这种情况下 Atom 模式会尽可能多地重复,同时仍然匹配后续部分。重复的是 Atom 模式,而不是它所匹配的输入字符序列,因此 Atom 的不同重复可以匹配不同的输入子字符串

Note 2

如果 Atom 和正则表达式的后续部分都具有选择点,则首先使 Atom 匹配尽可能多(或者如果非贪婪则尽可能少)的次数。在转向 Atom 最后一次重复中的下一个选择之前,会先尝试后续部分中的所有选择。在转向 Atom 倒数第二次(第 n - 1 次)重复中的下一个选择之前,会先尝试 Atom 最后一次(第 nth 次)重复中的所有选择;此时可能会发现现在可以进行更多或更少次 Atom 重复;这些可能性会被耗尽(同样,从尽可能少或尽可能多开始),然后再转向 Atom 第 (n - 1)st 次重复中的下一个选择,依此类推。

比较

/a[a-z]{2,4}/.exec("abcdefghi")

它返回 "abcde",而

/a[a-z]{2,4}?/.exec("abcdefghi")

返回 "abc"

另请考虑

/(aa|aabaac|ba|b|c)*/.exec("aabaac")

根据上述选择点顺序,它返回数组

["aaba", "ba"]

而不是以下任何一个:

["aabaac", "aabaac"]
["aabaac", "c"]

上述选择点顺序可用于编写一个计算两个数(以一元记法表示)最大公约数的正则表达式。以下示例计算 10 和 15 的 gcd:

"aaaaaaaaaa,aaaaaaaaaaaaaaa".replace(/^(a+)\1*,\1+$/, "$1")

它返回一元记法的 gcd "aaaaa"

Note 3

RepeatMatcher 的步骤 4 在每次重复 Atom 时都会清除 Atom 的捕获。我们可以在正则表达式

/(z)((a+)?(b+)?(c))*/.exec("zaacbbbcac")

中看到其行为,它返回数组

["zaacbbbcac", "z", "ac", "a", undefined, "c"]

而不是

["zaacbbbcac", "z", "ac", "a", "bbb", "c"]

因为最外层 * 的每次迭代都会清除量化 Atom 中包含的所有捕获 String,在本例中包括编号为 2、3、4 和 5 的捕获 String。

Note 4

RepeatMatcher 的步骤 2.b 说明,一旦最小重复次数已满足,任何更多匹配空字符序列的 Atom 展开都不会被考虑用于进一步重复。这防止正则表达式引擎在如下模式上陷入无限循环:

/(a*)*/.exec("b")

或稍微复杂一些的:

/(a*)b\1+/.exec("baaaac")

它返回数组

["b", ""]

22.2.2.3.2 EmptyMatcher ( )

The abstract operation EmptyMatcher takes no arguments and returns 一个 Matcher. It performs the following steps when called:

  1. 返回一个新的 Matcher,其参数为 (matchState, continue),不捕获任何内容,并在被调用时执行以下步骤:
    1. 断言:matchState 是一个 MatchState
    2. 断言:continue 是一个 MatcherContinuation
    3. 返回 continue(matchState)。

22.2.2.3.3 MatchTwoAlternatives ( m1, m2 )

The abstract operation MatchTwoAlternatives takes arguments m1 (一个 Matcher,) and m2 (一个 Matcher,) and returns 一个 Matcher. It performs the following steps when called:

  1. 返回一个新的 Matcher,其参数为 (matchState, continue),捕获 m1m2,并在被调用时执行以下步骤:
    1. 断言:matchState 是一个 MatchState
    2. 断言:continue 是一个 MatcherContinuation
    3. rm1(matchState, continue)。
    4. 如果 r 不是 failure,返回 r
    5. 返回 m2(matchState, continue)。

22.2.2.3.4 MatchSequence ( m1, m2, direction )

The abstract operation MatchSequence takes arguments m1 (一个 Matcher,), m2 (一个 Matcher,), and direction (forwardbackward,) and returns 一个 Matcher. It performs the following steps when called:

  1. 如果 directionforward,则
    1. 返回一个新的 Matcher,其参数为 (matchState, continue),捕获 m1m2,并在被调用时执行以下步骤:
      1. 断言:matchState 是一个 MatchState
      2. 断言:continue 是一个 MatcherContinuation
      3. d 为一个新的 MatcherContinuation,其参数为 (y),捕获 continuem2,并在被调用时执行以下步骤:
        1. 断言:y 是一个 MatchState
        2. 返回 m2(y, continue)。
      4. 返回 m1(matchState, d)。
  2. 断言:directionbackward
  3. 返回一个新的 Matcher,其参数为 (matchState, continue),捕获 m1m2,并在被调用时执行以下步骤:
    1. 断言:matchState 是一个 MatchState
    2. 断言:continue 是一个 MatcherContinuation
    3. d 为一个新的 MatcherContinuation,其参数为 (y),捕获 continuem1,并在被调用时执行以下步骤:
      1. 断言:y 是一个 MatchState
      2. 返回 m1(y, continue)。
    4. 返回 m2(matchState, d)。

22.2.2.4 Runtime Semantics: CompileAssertion

The syntax-directed operation CompileAssertion takes argument regexpRecord (一个 RegExp Record,) and returns 一个 Matcher.

Note 1

本节在 B.1.2.6 中被修订。

It is defined piecewise over the following productions:

Assertion :: ^
  1. 返回一个新的 Matcher,其参数为 (matchState, continue),捕获 regexpRecord,并在被调用时执行以下步骤:
    1. 断言:matchState 是一个 MatchState
    2. 断言:continue 是一个 MatcherContinuation
    3. inputmatchState.[[Input]]
    4. ematchState.[[EndIndex]]
    5. 如果 e = 0,或者如果 regexpRecord.[[Multiline]]true 且字符 input[e - 1] 被 LineTerminator 匹配,则
      1. 返回 continue(matchState)。
    6. 返回 failure
Note 2

即使 y 标志与模式一起使用,^ 也始终只匹配 input 的开头,或者(如果 regexpRecord.[[Multiline]]true)匹配行首。

Assertion :: $
  1. 返回一个新的 Matcher,其参数为 (matchState, continue),捕获 regexpRecord,并在被调用时执行以下步骤:
    1. 断言:matchState 是一个 MatchState
    2. 断言:continue 是一个 MatcherContinuation
    3. inputmatchState.[[Input]]
    4. ematchState.[[EndIndex]]
    5. inputLengthinput 中元素的数量。
    6. 如果 e = inputLength,或者如果 regexpRecord.[[Multiline]]true 且字符 input[e] 被 LineTerminator 匹配,则
      1. 返回 continue(matchState)。
    7. 返回 failure
Assertion :: \b
  1. 返回一个新的 Matcher,其参数为 (matchState, continue),捕获 regexpRecord,并在被调用时执行以下步骤:
    1. 断言:matchState 是一个 MatchState
    2. 断言:continue 是一个 MatcherContinuation
    3. inputmatchState.[[Input]]
    4. ematchState.[[EndIndex]]
    5. aIsWordChar(regexpRecord, input, e - 1)。
    6. bIsWordChar(regexpRecord, input, e)。
    7. 如果 atruebfalse,或者如果 afalsebtrue,返回 continue(matchState)。
    8. 返回 failure
Assertion :: \B
  1. 返回一个新的 Matcher,其参数为 (matchState, continue),捕获 regexpRecord,并在被调用时执行以下步骤:
    1. 断言:matchState 是一个 MatchState
    2. 断言:continue 是一个 MatcherContinuation
    3. inputmatchState.[[Input]]
    4. ematchState.[[EndIndex]]
    5. aIsWordChar(regexpRecord, input, e - 1)。
    6. bIsWordChar(regexpRecord, input, e)。
    7. 如果 atruebtrue,或者如果 afalsebfalse,返回 continue(matchState)。
    8. 返回 failure
Assertion :: (?= Disjunction )
  1. m 为以 regexpRecordforward 为参数的 DisjunctionCompileSubpattern
  2. 返回一个新的 Matcher,其参数为 (matchState, continue),捕获 m,并在被调用时执行以下步骤:
    1. 断言:matchState 是一个 MatchState
    2. 断言:continue 是一个 MatcherContinuation
    3. d 为一个新的 MatcherContinuation,其参数为 (y),不捕获任何内容,并在被调用时执行以下步骤:
      1. 断言:y 是一个 MatchState
      2. 返回 y
    4. rm(matchState, d)。
    5. 如果 rfailure,返回 failure
    6. 断言:r 是一个 MatchState
    7. capr.[[Captures]]
    8. inputmatchState.[[Input]]
    9. xematchState.[[EndIndex]]
    10. zMatchState { [[Input]]: input, [[EndIndex]]: xe, [[Captures]]: cap }。
    11. 返回 continue(z)。
Note 3

形式 (?= Disjunction ) 指定一个零宽正向先行断言。为了使其成功,Disjunction 内部的模式必须在当前位置匹配,但在匹配后续部分之前不会推进当前位置。如果 Disjunction 可以以多种方式在当前位置匹配,则只尝试第一种。与其他正则表达式运算符不同,不会回溯进入 (?= 形式(这种不寻常的行为继承自 Perl)。这只有在 Disjunction 包含捕获括号且模式后续部分包含对这些捕获的反向引用时才重要。

例如,

/(?=(a+))/.exec("baaabac")

匹配第一个 b 之后的空 String,因此返回数组:

["", "aaa"]

为说明不会回溯进入先行断言,请考虑:

/(?=(a+))a*b\1/.exec("baaabac")

此表达式返回

["aba", "a"]

而不是:

["aaaba", "a"]
Assertion :: (?! Disjunction )
  1. m 为以 regexpRecordforward 为参数的 DisjunctionCompileSubpattern
  2. 返回一个新的 Matcher,其参数为 (matchState, continue),捕获 m,并在被调用时执行以下步骤:
    1. 断言:matchState 是一个 MatchState
    2. 断言:continue 是一个 MatcherContinuation
    3. d 为一个新的 MatcherContinuation,其参数为 (y),不捕获任何内容,并在被调用时执行以下步骤:
      1. 断言:y 是一个 MatchState
      2. 返回 y
    4. rm(matchState, d)。
    5. 如果 r 不是 failure,返回 failure
    6. 返回 continue(matchState)。
Note 4

形式 (?! Disjunction ) 指定一个零宽负向先行断言。为了使其成功,Disjunction 内部的模式必须无法在当前位置匹配。在匹配后续部分之前不会推进当前位置。Disjunction 可以包含捕获括号,但对它们的反向引用只有在 Disjunction 自身内部才有意义。从模式其他位置对这些捕获括号的反向引用总是返回 undefined,因为负向先行断言必须失败才能使模式成功。例如,

/(.*?)a(?!(a+)b\2c)\2(.*)/.exec("baaabaac")

查找一个 a,其后不是立即跟随某个正数 n 个 a、一个 b、另外 n 个 a(由第一个 \2 指定)以及一个 c。第二个 \2 位于负向先行断言之外,因此它与 undefined 匹配,从而总是成功。整个表达式返回数组:

["baaabaac", "ba", undefined, "abaac"]
Assertion :: (?<= Disjunction )
  1. m 为以 regexpRecordbackward 为参数的 DisjunctionCompileSubpattern
  2. 返回一个新的 Matcher,其参数为 (matchState, continue),捕获 m,并在被调用时执行以下步骤:
    1. 断言:matchState 是一个 MatchState
    2. 断言:continue 是一个 MatcherContinuation
    3. d 为一个新的 MatcherContinuation,其参数为 (y),不捕获任何内容,并在被调用时执行以下步骤:
      1. 断言:y 是一个 MatchState
      2. 返回 y
    4. rm(matchState, d)。
    5. 如果 rfailure,返回 failure
    6. 断言:r 是一个 MatchState
    7. capr.[[Captures]]
    8. inputmatchState.[[Input]]
    9. xematchState.[[EndIndex]]
    10. zMatchState { [[Input]]: input, [[EndIndex]]: xe, [[Captures]]: cap }。
    11. 返回 continue(z)。
Assertion :: (?<! Disjunction )
  1. m 为以 regexpRecordbackward 为参数的 DisjunctionCompileSubpattern
  2. 返回一个新的 Matcher,其参数为 (matchState, continue),捕获 m,并在被调用时执行以下步骤:
    1. 断言:matchState 是一个 MatchState
    2. 断言:continue 是一个 MatcherContinuation
    3. d 为一个新的 MatcherContinuation,其参数为 (y),不捕获任何内容,并在被调用时执行以下步骤:
      1. 断言:y 是一个 MatchState
      2. 返回 y
    4. rm(matchState, d)。
    5. 如果 r 不是 failure,返回 failure
    6. 返回 continue(matchState)。

22.2.2.4.1 IsWordChar ( regexpRecord, input, e )

The abstract operation IsWordChar takes arguments regexpRecord (一个 RegExp Record,), input (一个字符 List,), and e (一个整数,) and returns 一个 Boolean. It performs the following steps when called:

  1. inputLengthinput 中元素的数量。
  2. 如果 e = -1 或 e = inputLength,返回 false
  3. c 为字符 input[e]。
  4. 如果 WordCharacters(regexpRecord) 包含 c,返回 true
  5. 返回 false

22.2.2.5 Runtime Semantics: CompileQuantifier

The syntax-directed operation CompileQuantifier takes no arguments and returns 一个具有字段 [[Min]](一个非负整数)、[[Max]](一个非负整数或 +∞)和 [[Greedy]](一个 Boolean)的 Record. It is defined piecewise over the following productions:

Quantifier :: QuantifierPrefix
  1. qpQuantifierPrefixCompileQuantifierPrefix
  2. 返回 Record { [[Min]]: qp.[[Min]], [[Max]]: qp.[[Max]], [[Greedy]]: true }。
Quantifier :: QuantifierPrefix ?
  1. qpQuantifierPrefixCompileQuantifierPrefix
  2. 返回 Record { [[Min]]: qp.[[Min]], [[Max]]: qp.[[Max]], [[Greedy]]: false }。

22.2.2.6 Runtime Semantics: CompileQuantifierPrefix

The syntax-directed operation CompileQuantifierPrefix takes no arguments and returns 一个具有字段 [[Min]](一个非负整数)和 [[Max]](一个非负整数或 +∞)的 Record. It is defined piecewise over the following productions:

QuantifierPrefix :: *
  1. 返回 Record { [[Min]]: 0, [[Max]]: +∞ }。
QuantifierPrefix :: +
  1. 返回 Record { [[Min]]: 1, [[Max]]: +∞ }。
QuantifierPrefix :: ?
  1. 返回 Record { [[Min]]: 0, [[Max]]: 1 }。
QuantifierPrefix :: { DecimalDigits }
  1. iDecimalDigits 的 MV(见 12.9.3)。
  2. 返回 Record { [[Min]]: i, [[Max]]: i }。
QuantifierPrefix :: { DecimalDigits ,}
  1. iDecimalDigits 的 MV。
  2. 返回 Record { [[Min]]: i, [[Max]]: +∞ }。
QuantifierPrefix :: { DecimalDigits , DecimalDigits }
  1. i 为第一个 DecimalDigits 的 MV。
  2. j 为第二个 DecimalDigits 的 MV。
  3. 返回 Record { [[Min]]: i, [[Max]]: j }。

22.2.2.7 Runtime Semantics: CompileAtom

The syntax-directed operation CompileAtom takes arguments regexpRecord (一个 RegExp Record,) and direction (forwardbackward,) and returns 一个 Matcher.

Note 1

本节在 B.1.2.7 中被修订。

It is defined piecewise over the following productions:

Atom :: PatternCharacter
  1. ch 为由 PatternCharacter 匹配的字符。
  2. charSet 为一个包含字符 ch 的单元素 CharSet
  3. 返回 CharacterSetMatcher(regexpRecord, charSet, false, direction)。
Atom :: .
  1. charSetAllCharacters(regexpRecord)。
  2. 如果 regexpRecord.[[DotAll]] 不是 true,则
    1. charSet 中移除所有对应于 LineTerminator 产生式右侧码点的字符。
  3. 返回 CharacterSetMatcher(regexpRecord, charSet, false, direction)。
Atom :: CharacterClass
  1. cc 为以 regexpRecord 为参数的 CharacterClassCompileCharacterClass
  2. cscc.[[CharSet]]
  3. 如果 regexpRecord.[[UnicodeSets]]false,或者 cs 的每个 CharSetElement 都由单个字符组成(包括 cs 为空的情况),返回 CharacterSetMatcher(regexpRecord, cs, cc.[[Invert]], direction)。
  4. 断言:cc.[[Invert]]false
  5. lm 为一个空的 Matcher List
  6. 对于 cs 中包含多于 1 个字符的每个 CharSetElement s,按长度降序迭代,执行
    1. cs2 为一个包含 s 最后一个码点的单元素 CharSet
    2. m2CharacterSetMatcher(regexpRecord, cs2, false, direction)。
    3. 对于 s 中的每个码点 c1,从倒数第二个码点开始向后迭代,执行
      1. cs1 为一个包含 c1 的单元素 CharSet
      2. m1CharacterSetMatcher(regexpRecord, cs1, false, direction)。
      3. m2 设置为 MatchSequence(m1, m2, direction)。
    4. m2 追加到 lm
  7. singles 为包含 cs 中每个由单个字符组成的 CharSetElementCharSet
  8. CharacterSetMatcher(regexpRecord, singles, false, direction) 追加到 lm
  9. 如果 cs 包含空字符序列,将 EmptyMatcher() 追加到 lm
  10. m2lm 中最后一个 Matcher
  11. 对于 lm 的每个 Matcher m1,从倒数第二个元素开始向后迭代,执行
    1. m2 设置为 MatchTwoAlternatives(m1, m2)。
  12. 返回 m2
Atom :: ( GroupSpecifieropt Disjunction )
  1. m 为以 regexpRecorddirection 为参数的 DisjunctionCompileSubpattern
  2. parenIndexCountLeftCapturingParensBefore(Atom)。
  3. 返回一个新的 Matcher,其参数为 (x, c),捕获 directionmparenIndex,并在被调用时执行以下步骤:
    1. 断言:x 是一个 MatchState
    2. 断言:c 是一个 MatcherContinuation
    3. d 为一个新的 MatcherContinuation,其参数为 (y),捕获 xcdirectionparenIndex,并在被调用时执行以下步骤:
      1. 断言:y 是一个 MatchState
      2. capy.[[Captures]] 的副本。
      3. inputx.[[Input]]
      4. xex.[[EndIndex]]
      5. yey.[[EndIndex]]
      6. 如果 directionforward,则
        1. 断言:xeye
        2. rCaptureRange { [[StartIndex]]: xe, [[EndIndex]]: ye }。
      7. 否则,
        1. 断言:directionbackward
        2. 断言:yexe
        3. rCaptureRange { [[StartIndex]]: ye, [[EndIndex]]: xe }。
      8. cap[parenIndex + 1] 设置为 r
      9. zMatchState { [[Input]]: input, [[EndIndex]]: ye, [[Captures]]: cap }。
      10. 返回 c(z)。
    4. 返回 m(x, d)。
Note 2

形式为 ( Disjunction ) 的括号既用于将 Disjunction 模式的组成部分组合在一起,也用于保存匹配结果。结果可以用于反向引用(\ 后跟一个非零十进制数)、在替换 String 中引用,或者作为正则表达式匹配 Abstract Closure 返回的数组的一部分。要抑制括号的捕获行为,请使用形式 (?: Disjunction )

Atom :: (? RegularExpressionModifiers : Disjunction )
  1. addModifiersRegularExpressionModifiers 匹配的源文本
  2. removeModifiers 为空 String。
  3. modifiedRerUpdateModifiers(regexpRecord, CodePointsToString(addModifiers), removeModifiers)。
  4. 返回以 modifiedRerdirection 为参数的 DisjunctionCompileSubpattern
Atom :: (? RegularExpressionModifiers - RegularExpressionModifiers : Disjunction )
  1. addModifiers 为第一个 RegularExpressionModifiers 匹配的源文本
  2. removeModifiers 为第二个 RegularExpressionModifiers 匹配的源文本
  3. modifiedRerUpdateModifiers(regexpRecord, CodePointsToString(addModifiers), CodePointsToString(removeModifiers))。
  4. 返回以 modifiedRerdirection 为参数的 DisjunctionCompileSubpattern
AtomEscape :: DecimalEscape
  1. nDecimalEscapeCapturingGroupNumber
  2. 断言:nregexpRecord.[[CapturingGroupsCount]]
  3. 返回 BackreferenceMatcher(regexpRecord, « n », direction)。
Note 3

形式为 \ 后跟非零十进制数 n 的转义序列,匹配第 nth 组捕获括号(22.2.2.1)的结果。如果正则表达式少于 n 个捕获括号,则是错误。如果正则表达式有 n 个或更多捕获括号,但第 nth 个因为尚未捕获任何内容而为 undefined,则该反向引用总是成功。

AtomEscape :: CharacterEscape
  1. cvCharacterEscapeCharacterValue
  2. ch 为字符值为 cv 的字符。
  3. charSet 为一个包含字符 ch 的单元素 CharSet
  4. 返回 CharacterSetMatcher(regexpRecord, charSet, false, direction)。
AtomEscape :: CharacterClassEscape
  1. cs 为以 regexpRecord 为参数的 CharacterClassEscapeCompileToCharSet
  2. 如果 regexpRecord.[[UnicodeSets]]false,或者 cs 的每个 CharSetElement 都由单个字符组成(包括 cs 为空的情况),返回 CharacterSetMatcher(regexpRecord, cs, false, direction)。
  3. lm 为一个空的 Matcher List
  4. 对于 cs 中包含多于 1 个字符的每个 CharSetElement s,按长度降序迭代,执行
    1. cs2 为一个包含 s 最后一个码点的单元素 CharSet
    2. m2CharacterSetMatcher(regexpRecord, cs2, false, direction)。
    3. 对于 s 中的每个码点 c1,从倒数第二个码点开始向后迭代,执行
      1. cs1 为一个包含 c1 的单元素 CharSet
      2. m1CharacterSetMatcher(regexpRecord, cs1, false, direction)。
      3. m2 设置为 MatchSequence(m1, m2, direction)。
    4. m2 追加到 lm
  5. singles 为包含 cs 中每个由单个字符组成的 CharSetElementCharSet
  6. CharacterSetMatcher(regexpRecord, singles, false, direction) 追加到 lm
  7. 如果 cs 包含空字符序列,将 EmptyMatcher() 追加到 lm
  8. m2lm 中最后一个 Matcher
  9. 对于 lm 的每个 Matcher m1,从倒数第二个元素开始向后迭代,执行
    1. m2 设置为 MatchTwoAlternatives(m1, m2)。
  10. 返回 m2
AtomEscape :: k GroupName
  1. matchingGroupSpecifiersGroupSpecifiersThatMatch(GroupName)。
  2. parenIndices 为一个新的空 List
  3. 对于 matchingGroupSpecifiers 的每个 GroupSpecifier groupSpecifier,执行
    1. parenIndexCountLeftCapturingParensBefore(groupSpecifier)。
    2. parenIndex 追加到 parenIndices
  4. 返回 BackreferenceMatcher(regexpRecord, parenIndices, direction)。

22.2.2.7.1 CharacterSetMatcher ( regexpRecord, charSet, invert, direction )

The abstract operation CharacterSetMatcher takes arguments regexpRecord (一个 RegExp Record,), charSet (一个 CharSet,), invert (一个 Boolean,), and direction (forwardbackward,) and returns 一个 Matcher. It performs the following steps when called:

  1. 如果 regexpRecord.[[UnicodeSets]]true,则
    1. 断言:invertfalse
    2. 断言:charSet 的每个 CharSetElement 都由单个字符组成。
  2. 返回一个新的 Matcher,其参数为 (x, c),捕获 regexpRecordcharSetinvertdirection,并在被调用时执行以下步骤:
    1. 断言:x 是一个 MatchState
    2. 断言:c 是一个 MatcherContinuation
    3. inputx.[[Input]]
    4. endIndexx.[[EndIndex]]
    5. 如果 directionforward,令 fendIndex + 1。
    6. 否则,令 fendIndex - 1。
    7. inputLengthinput 中元素的数量。
    8. 如果 f < 0 或 f > inputLength,返回 failure
    9. indexmin(endIndex, f)。
    10. ch 为字符 input[index]。
    11. ccCanonicalize(regexpRecord, ch)。
    12. 如果 charSet 中存在一个恰好包含一个字符 aCharSetElement,使得 Canonicalize(regexpRecord, a) 是 cc,则令 foundtrue;否则令 foundfalse
    13. 如果 invertfalsefoundfalse,返回 failure
    14. 如果 inverttruefoundtrue,返回 failure
    15. capx.[[Captures]]
    16. yMatchState { [[Input]]: input, [[EndIndex]]: f, [[Captures]]: cap }。
    17. 返回 c(y)。

22.2.2.7.2 BackreferenceMatcher ( regexpRecord, ns, direction )

The abstract operation BackreferenceMatcher takes arguments regexpRecord (一个 RegExp Record,), ns (一个正整数 List,), and direction (forwardbackward,) and returns 一个 Matcher. It performs the following steps when called:

  1. 返回一个新的 Matcher,其参数为 (x, c),捕获 regexpRecordnsdirection,并在被调用时执行以下步骤:
    1. 断言:x 是一个 MatchState
    2. 断言:c 是一个 MatcherContinuation
    3. inputx.[[Input]]
    4. capx.[[Captures]]
    5. rundefined
    6. 对于 ns 的每个整数 n,执行
      1. 如果 cap[n] 不是 undefined,则
        1. 断言:rundefined
        2. r 设置为 cap[n]。
    7. 如果 rundefined,返回 c(x)。
    8. endIndexx.[[EndIndex]]
    9. rsr.[[StartIndex]]
    10. rer.[[EndIndex]]
    11. lenre - rs
    12. 如果 directionforward,令 fendIndex + len
    13. 否则,令 fendIndex - len
    14. inputLengthinput 中元素的数量。
    15. 如果 f < 0 或 f > inputLength,返回 failure
    16. gmin(endIndex, f)。
    17. 如果存在区间从 0(包含)到 len(不包含)内的整数 i,使得 Canonicalize(regexpRecord, input[rs + i]) 不是 Canonicalize(regexpRecord, input[g + i]),返回 failure
    18. yMatchState { [[Input]]: input, [[EndIndex]]: f, [[Captures]]: cap }。
    19. 返回 c(y)。

22.2.2.7.3 Canonicalize ( regexpRecord, ch )

The abstract operation Canonicalize takes arguments regexpRecord (一个 RegExp Record,) and ch (一个字符,) and returns 一个字符. It performs the following steps when called:

  1. 如果 HasEitherUnicodeFlag(regexpRecord) 是 trueregexpRecord.[[IgnoreCase]]true,则
    1. 如果 Unicode 字符数据库的文件 CaseFolding.txtch 提供了简单或公共大小写折叠映射,返回将该映射应用于 ch 的结果。
    2. 返回 ch
  2. 如果 regexpRecord.[[IgnoreCase]]false,返回 ch
  3. 断言:ch 是一个 UTF-16 码元。
  4. cp 为其数值为 ch 的数值的码点。
  5. u 为按照 Unicode 默认大小写转换算法得到的 toUppercase(« cp »)。
  6. uStrCodePointsToString(u)。
  7. 如果 uStr 的长度 ≠ 1,返回 ch
  8. cuuStr 的单个码元元素。
  9. 如果 ch 的数值 ≥ 128 且 cu 的数值 < 128,返回 ch
  10. 返回 cu
Note

HasEitherUnicodeFlag(regexpRecord) 是 true 的大小写不敏感匹配中,所有字符在比较之前都会隐式地使用 Unicode 标准提供的简单映射进行大小写折叠。简单映射总是映射到单个码点,因此它不会例如将 ß(U+00DF LATIN SMALL LETTER SHARP S)映射为 ssSS。然而,它可能将基本拉丁块之外的码点映射到其中的码点——例如,ſ(U+017F LATIN SMALL LETTER LONG S)大小写折叠为 s(U+0073 LATIN SMALL LETTER S),而 (U+212A KELVIN SIGN)大小写折叠为 k(U+006B LATIN SMALL LETTER K)。包含这些码点的 String 会被诸如 /[a-z]/ui 的正则表达式匹配。

HasEitherUnicodeFlag(regexpRecord) 是 false 的大小写不敏感匹配中,映射基于 Unicode 默认大小写转换算法 toUppercase,而不是 toCasefold,这会导致一些细微差异。例如,(U+2126 OHM SIGN)通过 toUppercase 映射到自身,但通过 toCasefold 与 Ω(U+03A9 GREEK CAPITAL LETTER OMEGA)一起映射到 ω(U+03C9 GREEK SMALL LETTER OMEGA),因此 "\u2126" 会被 /[ω]/ui/[\u03A9]/ui 匹配,但不会被 /[ω]/i/[\u03A9]/i 匹配。此外,基本拉丁块之外的码点不会被映射到其中的码点,因此诸如 "\u017F ſ""\u212A K" 的 String 不会被 /[a-z]/i 匹配。

22.2.2.7.4 UpdateModifiers ( regexpRecord, add, remove )

The abstract operation UpdateModifiers takes arguments regexpRecord (一个 RegExp Record,), add (一个 String,), and remove (一个 String,) and returns 一个 RegExp Record. It performs the following steps when called:

  1. 断言:addremove 没有共同元素。
  2. ignoreCaseregexpRecord.[[IgnoreCase]]
  3. multilineregexpRecord.[[Multiline]]
  4. dotAllregexpRecord.[[DotAll]]
  5. unicoderegexpRecord.[[Unicode]]
  6. unicodeSetsregexpRecord.[[UnicodeSets]]
  7. capturingGroupsCountregexpRecord.[[CapturingGroupsCount]]
  8. 如果 remove 包含 "i",将 ignoreCase 设置为 false
  9. 否则如果 add 包含 "i",将 ignoreCase 设置为 true
  10. 如果 remove 包含 "m",将 multiline 设置为 false
  11. 否则如果 add 包含 "m",将 multiline 设置为 true
  12. 如果 remove 包含 "s",将 dotAll 设置为 false
  13. 否则如果 add 包含 "s",将 dotAll 设置为 true
  14. 返回 RegExp Record { [[IgnoreCase]]: ignoreCase, [[Multiline]]: multiline, [[DotAll]]: dotAll, [[Unicode]]: unicode, [[UnicodeSets]]: unicodeSets, [[CapturingGroupsCount]]: capturingGroupsCount }。

22.2.2.8 Runtime Semantics: CompileCharacterClass

The syntax-directed operation CompileCharacterClass takes argument regexpRecord (一个 RegExp Record,) and returns 一个具有字段 [[CharSet]](一个 CharSet)和 [[Invert]](一个 Boolean)的 Record. It is defined piecewise over the following productions:

CharacterClass :: [ ClassContents ]
  1. charSet 为以 regexpRecord 为参数的 ClassContentsCompileToCharSet
  2. 返回 Record { [[CharSet]]: charSet, [[Invert]]: false }。
CharacterClass :: [^ ClassContents ]
  1. charSet 为以 regexpRecord 为参数的 ClassContentsCompileToCharSet
  2. 如果 regexpRecord.[[UnicodeSets]]true,则
    1. 返回 Record { [[CharSet]]: CharacterComplement(regexpRecord, charSet), [[Invert]]: false }。
  3. 返回 Record { [[CharSet]]: charSet, [[Invert]]: true }。

22.2.2.9 Runtime Semantics: CompileToCharSet

The syntax-directed operation CompileToCharSet takes argument regexpRecord (一个 RegExp Record,) and returns 一个 CharSet.

Note 1

本节在 B.1.2.8 中被修订。

It is defined piecewise over the following productions:

ClassContents :: [empty]
  1. 返回空 CharSet
NonemptyClassRanges :: ClassAtom NonemptyClassRangesNoDash
  1. charSet 为以 regexpRecord 为参数的 ClassAtomCompileToCharSet
  2. otherSet 为以 regexpRecord 为参数的 NonemptyClassRangesNoDashCompileToCharSet
  3. 返回 CharSet charSetotherSet 的并集。
NonemptyClassRanges :: ClassAtom - ClassAtom ClassContents
  1. charSet 为以 regexpRecord 为参数的第一个 ClassAtomCompileToCharSet
  2. otherSet 为以 regexpRecord 为参数的第二个 ClassAtomCompileToCharSet
  3. remainingSet 为以 regexpRecord 为参数的 ClassContentsCompileToCharSet
  4. rangeSetCharacterRange(charSet, otherSet)。
  5. 返回 rangeSetremainingSet 的并集。
NonemptyClassRangesNoDash :: ClassAtomNoDash NonemptyClassRangesNoDash
  1. charSet 为以 regexpRecord 为参数的 ClassAtomNoDashCompileToCharSet
  2. otherSet 为以 regexpRecord 为参数的 NonemptyClassRangesNoDashCompileToCharSet
  3. 返回 CharSet charSetotherSet 的并集。
NonemptyClassRangesNoDash :: ClassAtomNoDash - ClassAtom ClassContents
  1. charSet 为以 regexpRecord 为参数的 ClassAtomNoDashCompileToCharSet
  2. otherSet 为以 regexpRecord 为参数的 ClassAtomCompileToCharSet
  3. remainingSet 为以 regexpRecord 为参数的 ClassContentsCompileToCharSet
  4. rangeSetCharacterRange(charSet, otherSet)。
  5. 返回 rangeSetremainingSet 的并集。
Note 2

ClassContents 可以展开为单个 ClassAtom 和/或由连字符分隔的两个 ClassAtom 的范围。在后一种情况下,ClassContents 包括第一个 ClassAtom 和第二个 ClassAtom 之间的所有字符(含两端);如果任一 ClassAtom 不表示单个字符(例如,如果其中一个是 \w),或者如果第一个 ClassAtom 的字符值严格大于第二个 ClassAtom 的字符值,则发生错误。

Note 3

即使模式忽略大小写,范围两端的大小写在确定哪些字符属于该范围时仍然重要。因此,例如,模式 /[E-F]/i 只匹配字母 EFef,而模式 /[E-f]/i 匹配 Unicode 基本拉丁块中的所有大写和小写字母,以及符号 [, \, ], ^, _`

Note 4

- 字符可以按字面量处理,也可以表示一个范围。如果它是 ClassContents 的第一个或最后一个字符、范围指定的起始或结束界限,或者紧跟在范围指定之后,则按字面量处理。

ClassAtom :: -
  1. 返回包含单个字符 - U+002D (HYPHEN-MINUS) 的 CharSet
ClassAtomNoDash :: SourceCharacter but not one of \ or ] or -
  1. 返回包含由 SourceCharacter 匹配的字符的 CharSet
ClassEscape :: b - CharacterEscape
  1. cv 为此 ClassEscapeCharacterValue
  2. c 为字符值为 cv 的字符。
  3. 返回包含单个字符 cCharSet
Note 5

ClassAtom 可以使用正则表达式其余部分中允许的任何转义序列,但 \b\B 和反向引用除外。在 CharacterClass 内部,\b 表示退格字符,而 \B 和反向引用会引发错误。在 ClassAtom 内部使用反向引用会导致错误。

CharacterClassEscape :: d
  1. 返回包含字符 0123456789 的十元素 CharSet
CharacterClassEscape :: D
  1. charSet 为由 CharacterClassEscape :: d 返回的 CharSet
  2. 返回 CharacterComplement(regexpRecord, charSet)。
CharacterClassEscape :: s
  1. 返回包含所有对应于 WhiteSpaceLineTerminator 产生式右侧码点的字符的 CharSet
CharacterClassEscape :: S
  1. charSet 为由 CharacterClassEscape :: s 返回的 CharSet
  2. 返回 CharacterComplement(regexpRecord, charSet)。
CharacterClassEscape :: w
  1. 返回 MaybeSimpleCaseFolding(regexpRecord, WordCharacters(regexpRecord))。
CharacterClassEscape :: W
  1. charSet 为由 CharacterClassEscape :: w 返回的 CharSet
  2. 返回 CharacterComplement(regexpRecord, charSet)。
CharacterClassEscape :: p{ UnicodePropertyValueExpression }
  1. 返回以 regexpRecord 为参数的 UnicodePropertyValueExpressionCompileToCharSet
CharacterClassEscape :: P{ UnicodePropertyValueExpression }
  1. charSet 为以 regexpRecord 为参数的 UnicodePropertyValueExpressionCompileToCharSet
  2. 断言:charSet 只包含单个码点。
  3. 返回 CharacterComplement(regexpRecord, charSet)。
UnicodePropertyValueExpression :: UnicodePropertyName = UnicodePropertyValue
  1. ps 为由 UnicodePropertyName 匹配的源文本
  2. pUnicodeMatchProperty(regexpRecord, ps)。
  3. 断言:pTable 64 的 “Property name and aliases” 列中列出的 Unicode property name 或属性别名。
  4. vs 为由 UnicodePropertyValue 匹配的源文本
  5. vUnicodeMatchPropertyValue(p, vs)。
  6. charSet 为包含所有 Unicode 码点的 CharSet,这些码点的字符数据库定义包含属性 p 且值为 v
  7. 返回 MaybeSimpleCaseFolding(regexpRecord, charSet)。
UnicodePropertyValueExpression :: LoneUnicodePropertyNameOrValue
  1. s 为由 LoneUnicodePropertyNameOrValue 匹配的源文本
  2. 如果 UnicodeMatchPropertyValue(General_Category, s) 是 PropertyValueAliases.txt 中列出的 General_Category (gc) 属性的 Unicode 属性值或属性值别名,则
    1. 返回包含所有 Unicode 码点的 CharSet,这些码点的字符数据库定义包含属性 “General_Category” 且值为 s
  3. pUnicodeMatchProperty(regexpRecord, s)。
  4. 断言:pTable 65 的 “Property name and aliases” 列中列出的二元 Unicode 属性或二元属性别名,或 Table 66 的 “Property name” 列中列出的字符串二元 Unicode 属性。
  5. charSet 为包含所有 CharSetElementCharSet,这些 CharSetElement 的字符数据库定义包含属性 p 且值为 “True”。
  6. 返回 MaybeSimpleCaseFolding(regexpRecord, charSet)。
ClassUnion :: ClassSetRange ClassUnionopt
  1. charSet 为以 regexpRecord 为参数的 ClassSetRangeCompileToCharSet
  2. 如果 ClassUnion 存在,则
    1. otherSet 为以 regexpRecord 为参数的 ClassUnionCompileToCharSet
    2. 返回 CharSet charSetotherSet 的并集。
  3. 返回 charSet
ClassUnion :: ClassSetOperand ClassUnionopt
  1. charSet 为以 regexpRecord 为参数的 ClassSetOperandCompileToCharSet
  2. 如果 ClassUnion 存在,则
    1. otherSet 为以 regexpRecord 为参数的 ClassUnionCompileToCharSet
    2. 返回 CharSet charSetotherSet 的并集。
  3. 返回 charSet
ClassIntersection :: ClassSetOperand && ClassSetOperand
  1. charSet 为以 regexpRecord 为参数的第一个 ClassSetOperandCompileToCharSet
  2. otherSet 为以 regexpRecord 为参数的第二个 ClassSetOperandCompileToCharSet
  3. 返回 CharSet charSetotherSet 的交集。
ClassIntersection :: ClassIntersection && ClassSetOperand
  1. charSet 为以 regexpRecord 为参数的 ClassIntersectionCompileToCharSet
  2. otherSet 为以 regexpRecord 为参数的 ClassSetOperandCompileToCharSet
  3. 返回 CharSet charSetotherSet 的交集。
ClassSubtraction :: ClassSetOperand -- ClassSetOperand
  1. charSet 为以 regexpRecord 为参数的第一个 ClassSetOperandCompileToCharSet
  2. otherSet 为以 regexpRecord 为参数的第二个 ClassSetOperandCompileToCharSet
  3. 返回包含 charSet 中也不是 otherSetCharSetElementCharSetElementCharSet
ClassSubtraction :: ClassSubtraction -- ClassSetOperand
  1. charSet 为以 regexpRecord 为参数的 ClassSubtractionCompileToCharSet
  2. otherSet 为以 regexpRecord 为参数的 ClassSetOperandCompileToCharSet
  3. 返回包含 charSet 中也不是 otherSetCharSetElementCharSetElementCharSet
ClassSetRange :: ClassSetCharacter - ClassSetCharacter
  1. charSet 为以 regexpRecord 为参数的第一个 ClassSetCharacterCompileToCharSet
  2. otherSet 为以 regexpRecord 为参数的第二个 ClassSetCharacterCompileToCharSet
  3. 返回 MaybeSimpleCaseFolding(regexpRecord, CharacterRange(charSet, otherSet))。
Note 6

结果通常会由两个或更多范围组成。当 UnicodeSets 是 true 且 IgnoreCase 是 true 时,MaybeSimpleCaseFolding(regexpRecord, [Ā-č]) 将只包含该范围中的奇数编号码点。

ClassSetOperand :: ClassSetCharacter
  1. charSet 为以 regexpRecord 为参数的 ClassSetCharacterCompileToCharSet
  2. 返回 MaybeSimpleCaseFolding(regexpRecord, charSet)。
ClassSetOperand :: ClassStringDisjunction
  1. charSet 为以 regexpRecord 为参数的 ClassStringDisjunctionCompileToCharSet
  2. 返回 MaybeSimpleCaseFolding(regexpRecord, charSet)。
ClassSetOperand :: NestedClass
  1. 返回以 regexpRecord 为参数的 NestedClassCompileToCharSet
NestedClass :: [ ClassContents ]
  1. 返回以 regexpRecord 为参数的 ClassContentsCompileToCharSet
NestedClass :: [^ ClassContents ]
  1. charSet 为以 regexpRecord 为参数的 ClassContentsCompileToCharSet
  2. 返回 CharacterComplement(regexpRecord, charSet)。
NestedClass :: \ CharacterClassEscape
  1. 返回以 regexpRecord 为参数的 CharacterClassEscapeCompileToCharSet
ClassStringDisjunction :: \q{ ClassStringDisjunctionContents }
  1. 返回以 regexpRecord 为参数的 ClassStringDisjunctionContentsCompileToCharSet
ClassStringDisjunctionContents :: ClassString
  1. s 为以 regexpRecord 为参数的 ClassStringCompileClassSetString
  2. 返回包含一个字符串 sCharSet
ClassStringDisjunctionContents :: ClassString | ClassStringDisjunctionContents
  1. s 为以 regexpRecord 为参数的 ClassStringCompileClassSetString
  2. charSet 为包含一个字符串 sCharSet
  3. otherSet 为以 regexpRecord 为参数的 ClassStringDisjunctionContentsCompileToCharSet
  4. 返回 CharSet charSetotherSet 的并集。
ClassSetCharacter :: SourceCharacter but not ClassSetSyntaxCharacter \ CharacterEscape \ ClassSetReservedPunctuator
  1. cv 为此 ClassSetCharacterCharacterValue
  2. c 为字符值为 cv 的字符。
  3. 返回包含单个字符 cCharSet
ClassSetCharacter :: \b
  1. 返回包含单个字符 U+0008 (BACKSPACE) 的 CharSet

22.2.2.9.1 CharacterRange ( charSet, otherSet )

The abstract operation CharacterRange takes arguments charSet (一个 CharSet,) and otherSet (一个 CharSet,) and returns 一个 CharSet. It performs the following steps when called:

  1. 断言:charSetotherSet 各自恰好包含一个字符。
  2. aCharSet charSet 中的一个字符。
  3. bCharSet otherSet 中的一个字符。
  4. i 为字符 a 的字符值。
  5. j 为字符 b 的字符值。
  6. 断言:ij
  7. 返回包含所有字符值位于从 ij闭区间内的字符的 CharSet

22.2.2.9.2 HasEitherUnicodeFlag ( regexpRecord )

The abstract operation HasEitherUnicodeFlag takes argument regexpRecord (一个 RegExp Record,) and returns 一个 Boolean. It performs the following steps when called:

  1. 如果 regexpRecord.[[Unicode]]trueregexpRecord.[[UnicodeSets]]true,返回 true
  2. 返回 false

22.2.2.9.3 WordCharacters ( regexpRecord )

The abstract operation WordCharacters takes argument regexpRecord (一个 RegExp Record,) and returns 一个 CharSet. 返回一个 CharSet,其中包含出于 \b\B\w\W 的目的而被视为“单词字符”的字符。 It performs the following steps when called:

  1. basicWordChars 为包含 ASCII 单词字符中每个字符的 CharSet
  2. extraWordChars 为包含所有字符 cCharSet,使得 c 不在 basicWordChars 中,但 Canonicalize(regexpRecord, c) 在 basicWordChars 中。
  3. 断言:除非 HasEitherUnicodeFlag(regexpRecord) 是 trueregexpRecord.[[IgnoreCase]]true,否则 extraWordChars 为空。
  4. 返回 basicWordCharsextraWordChars 的并集。

22.2.2.9.4 AllCharacters ( regexpRecord )

The abstract operation AllCharacters takes argument regexpRecord (一个 RegExp Record,) and returns 一个 CharSet. 根据正则表达式标志返回“所有字符”的集合。 It performs the following steps when called:

  1. 如果 regexpRecord.[[UnicodeSets]]trueregexpRecord.[[IgnoreCase]]true,则
    1. 返回包含所有没有 Simple Case Folding 映射(即 scf(c)=c)的 Unicode 码点 cCharSet
  2. 如果 HasEitherUnicodeFlag(regexpRecord) 是 true,则
    1. 返回包含所有码点值的 CharSet
  3. 返回包含所有码元值的 CharSet

22.2.2.9.5 MaybeSimpleCaseFolding ( regexpRecord, charSet )

The abstract operation MaybeSimpleCaseFolding takes arguments regexpRecord (一个 RegExp Record,) and charSet (一个 CharSet,) and returns 一个 CharSet. 如果 regexpRecord.[[UnicodeSets]]falseregexpRecord.[[IgnoreCase]]false,则返回 charSet。否则,它使用 Unicode 字符数据库文件 CaseFolding.txt 中的 Simple Case Foldingscf(cp))定义(每个定义都将单个码点映射到另一个单个码点),逐字符地将 charSet 的每个 CharSetElement 映射为规范形式,并返回所得的 CharSet。 It performs the following steps when called:

  1. 如果 regexpRecord.[[UnicodeSets]]falseregexpRecord.[[IgnoreCase]]false,返回 charSet
  2. otherSet 为一个新的空 CharSet
  3. 对于 charSet 的每个 CharSetElement s,执行
    1. t 为空字符序列。
    2. 对于 s 中的每个单个码点 cp,执行
      1. scf(cp) 追加到 t
    3. t 添加到 otherSet
  4. 返回 otherSet

22.2.2.9.6 CharacterComplement ( regexpRecord, complement )

The abstract operation CharacterComplement takes arguments regexpRecord (一个 RegExp Record,) and complement (一个 CharSet,) and returns 一个 CharSet. It performs the following steps when called:

  1. charSetAllCharacters(regexpRecord)。
  2. 返回包含 charSet 中也不是 complementCharSetElementCharSetElementCharSet

22.2.2.9.7 UnicodeMatchProperty ( regexpRecord, p )

The abstract operation UnicodeMatchProperty takes arguments regexpRecord (一个 RegExp Record,) and p (ECMAScript 源文本,) and returns 一个 Unicode property name. It performs the following steps when called:

  1. 如果 regexpRecord.[[UnicodeSets]]truepTable 66 的 “Property name” 列中列出的 Unicode property name,则
    1. 返回 Unicode 码点 List p
  2. 断言:pTable 64Table 65 的 “Property name and aliases” 列中列出的 Unicode property name 或属性别名。
  3. cp 的规范 property name,如相应行的 “Canonical property name” 列中所给出。
  4. 返回 Unicode 码点 List c

实现必须支持 Table 64Table 65Table 66 中列出的 Unicode property names 和别名。为确保互操作性,实现不得支持任何其他 property names 或别名。

Note 1

例如,Script_Extensionsproperty name)和 scx(属性别名)是有效的,但 script_extensionsScx 不是。

Note 2

列出的属性构成了 UTS18 RL1.2 要求内容的超集。

Note 3

这些表中条目的拼写(包括大小写)与 Unicode 字符数据库中的文件 PropertyAliases.txt 所使用的拼写一致。该文件中的精确拼写保证稳定

Table 64: Non-binary Unicode property aliases and their canonical property names
Property name and aliases Canonical property name
General_Category General_Category
gc
Script Script
sc
Script_Extensions Script_Extensions
scx
Table 65: Binary Unicode property aliases and their canonical property names
Property name and aliases Canonical property name
ASCII ASCII
ASCII_Hex_Digit ASCII_Hex_Digit
AHex
Alphabetic Alphabetic
Alpha
Any Any
Assigned Assigned
Bidi_Control Bidi_Control
Bidi_C
Bidi_Mirrored Bidi_Mirrored
Bidi_M
Case_Ignorable Case_Ignorable
CI
Cased Cased
Changes_When_Casefolded Changes_When_Casefolded
CWCF
Changes_When_Casemapped Changes_When_Casemapped
CWCM
Changes_When_Lowercased Changes_When_Lowercased
CWL
Changes_When_NFKC_Casefolded Changes_When_NFKC_Casefolded
CWKCF
Changes_When_Titlecased Changes_When_Titlecased
CWT
Changes_When_Uppercased Changes_When_Uppercased
CWU
Dash Dash
Default_Ignorable_Code_Point Default_Ignorable_Code_Point
DI
Deprecated Deprecated
Dep
Diacritic Diacritic
Dia
Emoji Emoji
Emoji_Component Emoji_Component
EComp
Emoji_Modifier Emoji_Modifier
EMod
Emoji_Modifier_Base Emoji_Modifier_Base
EBase
Emoji_Presentation Emoji_Presentation
EPres
Extended_Pictographic Extended_Pictographic
ExtPict
Extender Extender
Ext
Grapheme_Base Grapheme_Base
Gr_Base
Grapheme_Extend Grapheme_Extend
Gr_Ext
Hex_Digit Hex_Digit
Hex
IDS_Binary_Operator IDS_Binary_Operator
IDSB
IDS_Trinary_Operator IDS_Trinary_Operator
IDST
ID_Continue ID_Continue
IDC
ID_Start ID_Start
IDS
Ideographic Ideographic
Ideo
Join_Control Join_Control
Join_C
Logical_Order_Exception Logical_Order_Exception
LOE
Lowercase Lowercase
Lower
Math Math
Noncharacter_Code_Point Noncharacter_Code_Point
NChar
Pattern_Syntax Pattern_Syntax
Pat_Syn
Pattern_White_Space Pattern_White_Space
Pat_WS
Quotation_Mark Quotation_Mark
QMark
Radical Radical
Regional_Indicator Regional_Indicator
RI
Sentence_Terminal Sentence_Terminal
STerm
Soft_Dotted Soft_Dotted
SD
Terminal_Punctuation Terminal_Punctuation
Term
Unified_Ideograph Unified_Ideograph
UIdeo
Uppercase Uppercase
Upper
Variation_Selector Variation_Selector
VS
White_Space White_Space
space
XID_Continue XID_Continue
XIDC
XID_Start XID_Start
XIDS
Table 66: Binary Unicode properties of strings
Property name
Basic_Emoji
Emoji_Keycap_Sequence
RGI_Emoji_Modifier_Sequence
RGI_Emoji_Flag_Sequence
RGI_Emoji_Tag_Sequence
RGI_Emoji_ZWJ_Sequence
RGI_Emoji

22.2.2.9.8 UnicodeMatchPropertyValue ( p, v )

The abstract operation UnicodeMatchPropertyValue takes arguments p (ECMAScript 源文本,) and v (ECMAScript 源文本,) and returns 一个 Unicode 属性值. It performs the following steps when called:

  1. 断言:pTable 64 的 “Canonical property name” 列中列出的规范、无别名 Unicode property name
  2. 断言:vPropertyValueAliases.txt 中列出的 Unicode 属性 p 的属性值或属性值别名。
  3. valuev 的规范属性值,如相应行的 “Canonical property value” 列中所给出。
  4. 返回 Unicode 码点 List value

实现必须支持 PropertyValueAliases.txt 中针对 Table 64 中列出的属性所列出的 Unicode 属性值和属性值别名。为确保互操作性,实现不得支持任何其他属性值或属性值别名。

Note 1

例如,XpeoOld_Persian 是有效的 Script_Extensions 值,但 xpeoOld Persian 不是。

Note 2

此算法不同于 UAX44 中列出的符号值匹配规则:大小写、空白、U+002D (HYPHEN-MINUS) 和 U+005F (LOW LINE) 不会被忽略,并且不支持 Is 前缀。

22.2.2.10 Runtime Semantics: CompileClassSetString

The syntax-directed operation CompileClassSetString takes argument regexpRecord (一个 RegExp Record,) and returns 一个字符序列. It is defined piecewise over the following productions:

ClassString :: [empty]
  1. 返回一个空字符序列。
ClassString :: NonEmptyClassString
  1. 返回以 regexpRecord 为参数的 NonEmptyClassStringCompileClassSetString
NonEmptyClassString :: ClassSetCharacter NonEmptyClassStringopt
  1. cs 为以 regexpRecord 为参数的 ClassSetCharacterCompileToCharSet
  2. s1 为字符序列,它是 cs 的唯一 CharSetElement
  3. 如果 NonEmptyClassString 存在,则
    1. s2 为以 regexpRecord 为参数的 NonEmptyClassStringCompileClassSetString
    2. 返回 s1s2 的拼接。
  4. 返回 s1

22.2.3 用于 RegExp 创建的抽象操作

22.2.3.1 RegExpCreate ( pattern, flags )

The abstract operation RegExpCreate takes arguments pattern (一个 ECMAScript 语言值,) and flags (一个 String 或 undefined,) and returns 要么是一个包含 Object 的正常完成,要么是一个抛出完成. It performs the following steps when called:

  1. obj 为 ! RegExpAlloc(%RegExp%)。
  2. 返回 ? RegExpInitialize(obj, pattern, flags)。

22.2.3.2 RegExpAlloc ( newTarget )

The abstract operation RegExpAlloc takes argument newTarget (一个构造器,) and returns 要么是一个包含 Object 的正常完成,要么是一个抛出完成. It performs the following steps when called:

  1. obj 为 ? OrdinaryCreateFromConstructor(newTarget, "%RegExp.prototype%", « [[OriginalSource]], [[OriginalFlags]], [[RegExpRecord]], [[RegExpMatcher]] »)。
  2. 执行 ! DefinePropertyOrThrow(obj, "lastIndex", PropertyDescriptor { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  3. 返回 obj

22.2.3.3 RegExpInitialize ( obj, pattern, flags )

The abstract operation RegExpInitialize takes arguments obj (一个 Object,), pattern (一个 ECMAScript 语言值,), and flags (一个 ECMAScript 语言值,) and returns 要么是一个包含 Object 的正常完成,要么是一个抛出完成. It performs the following steps when called:

  1. 如果 patternundefined,将 pattern 设置为空 String。
  2. 否则,将 pattern 设置为 ? ToString(pattern)。
  3. 如果 flagsundefined,将 flags 设置为空 String。
  4. 否则,将 flags 设置为 ? ToString(flags)。
  5. 如果 flags 包含除 "d""g""i""m""s""u""v""y" 之外的任何码元,抛出 SyntaxError 异常。
  6. 如果 flags 多次包含任何码元,抛出 SyntaxError 异常。
  7. 如果 flags 包含 "i",令 itrue;否则令 ifalse
  8. 如果 flags 包含 "m",令 mtrue;否则令 mfalse
  9. 如果 flags 包含 "s",令 strue;否则令 sfalse
  10. 如果 flags 包含 "u",令 utrue;否则令 ufalse
  11. 如果 flags 包含 "v",令 vtrue;否则令 vfalse
  12. 如果 utruevtrue,则
    1. patternTextStringToCodePoints(pattern)。
  13. 否则,
    1. patternText 为将 pattern 的每个 16 位元素解释为 Unicode BMP 码点的结果。不对这些元素应用 UTF-16 解码。
  14. parseResultParsePattern(patternText, u, v)。
  15. 如果 parseResult 是一个由 SyntaxError 对象组成的非空 List,抛出 SyntaxError 异常。
  16. 断言:parseResult 是一个 Pattern Parse Node。
  17. obj.[[OriginalSource]] 设置为 pattern
  18. obj.[[OriginalFlags]] 设置为 flags
  19. capturingGroupsCountCountLeftCapturingParensWithin(parseResult)。
  20. regexpRecordRegExp Record { [[IgnoreCase]]: i, [[Multiline]]: m, [[DotAll]]: s, [[Unicode]]: u, [[UnicodeSets]]: v, [[CapturingGroupsCount]]: capturingGroupsCount }。
  21. obj.[[RegExpRecord]] 设置为 regexpRecord
  22. obj.[[RegExpMatcher]] 设置为以 regexpRecord 为参数的 parseResultCompilePattern
  23. 执行 ? Set(obj, "lastIndex", +0𝔽, true)。
  24. 返回 obj

22.2.3.4 Static Semantics: ParsePattern ( patternText, u, v )

The abstract operation ParsePattern takes arguments patternText (一个 Unicode 码点序列,), u (一个 Boolean,), and v (一个 Boolean,) and returns 一个 Parse Node 或一个由 SyntaxError 对象组成的非空 List.

Note

本节在 B.1.2.9 中被修订。

It performs the following steps when called:

  1. 如果 vtrueutrue,则
    1. parseResult 为一个包含一个或多个 SyntaxError 对象的 List
  2. 否则如果 vtrue,则
    1. parseResultParseText(patternText, Pattern[+UnicodeMode, +UnicodeSetsMode, +NamedCaptureGroups])。
  3. 否则如果 utrue,则
    1. parseResultParseText(patternText, Pattern[+UnicodeMode, ~UnicodeSetsMode, +NamedCaptureGroups])。
  4. 否则,
    1. parseResultParseText(patternText, Pattern[~UnicodeMode, ~UnicodeSetsMode, +NamedCaptureGroups])。
  5. 返回 parseResult

22.2.4 RegExp 构造器

RegExp 构造器

  • %RegExp%
  • 全局对象"RegExp" 属性的初始值。
  • 当作为构造器调用时,创建并初始化一个新的 RegExp 对象。
  • 当作为函数而不是构造器调用时,返回一个新的 RegExp 对象,或者如果唯一参数是一个 RegExp 对象,则返回该参数本身。
  • 可用作类定义中 extends 子句的值。意图继承指定 RegExp 行为的子类构造器必须包含对 RegExp 构造器super 调用,以创建并初始化带有必要内部槽的子类实例。

22.2.4.1 RegExp ( patternOrRegexp, flags )

此函数在被调用时执行以下步骤:

  1. patternIsRegExp 为 ? IsRegExp(patternOrRegexp)。
  2. 如果 NewTarget 是 undefined,则
    1. newTarget活动函数对象
    2. 如果 patternIsRegExptrueflagsundefined,则
      1. patternConstructor 为 ? Get(patternOrRegexp, "constructor")。
      2. 如果 SameValue(newTarget, patternConstructor) 是 true,返回 patternOrRegexp
  3. 否则,
    1. newTarget 为 NewTarget。
  4. 如果 patternOrRegexp 是一个 Object 且 patternOrRegexp 具有 [[RegExpMatcher]] 内部槽,则
    1. patternSourcepatternOrRegexp.[[OriginalSource]]
    2. 如果 flagsundefined,将 flags 设置为 patternOrRegexp.[[OriginalFlags]]
  5. 否则如果 patternIsRegExptrue,则
    1. patternSource 为 ? Get(patternOrRegexp, "source")。
    2. 如果 flagsundefined,则
      1. flags 设置为 ? Get(patternOrRegexp, "flags")。
  6. 否则,
    1. patternSourcepatternOrRegexp
  7. obj 为 ? RegExpAlloc(newTarget)。
  8. 返回 ? RegExpInitialize(obj, patternSource, flags)。
Note

如果使用 StringLiteral 提供 pattern,则在此函数处理该 String 之前会执行通常的转义序列替换。如果 pattern 必须包含一个由此函数识别的转义序列,则任何 U+005C (REVERSE SOLIDUS) 码点都必须在 StringLiteral 内转义,以防它们在形成 StringLiteral 的内容时被移除。

22.2.5 RegExp 构造器的属性

RegExp 构造器

22.2.5.1 RegExp.escape ( str )

此函数返回 str 的一个副本,其中在正则表达式 Pattern 中可能具有特殊含义的字符已被等价的转义序列替换。

它在被调用时执行以下步骤:

  1. 如果 str 不是 String,抛出 TypeError 异常。
  2. escaped 为空 String。
  3. cpListStringToCodePoints(str)。
  4. 对于 cpList 的每个码点 cp,执行
    1. 如果 escaped 为空 String 且 cpDecimalDigitAsciiLetter 匹配,则
      1. 注:转义前导数字确保输出对应于可在 \0 字符转义或诸如 \1DecimalEscape 之后使用的模式文本,并且仍然匹配 str,而不是被解释为前一个转义序列的扩展。转义前导 ASCII 字母对 \c 之后的上下文具有相同作用。
      2. numericValuecp 的数值。
      3. hexNumber::toString(𝔽(numericValue), 16)。
      4. 断言:hex 的长度为 2。
      5. escaped 设置为码元 0x005C (REVERSE SOLIDUS)、"x"hex 的字符串拼接。
    2. 否则,
      1. escaped 设置为 escapedEncodeForRegExpEscape(cp) 的字符串拼接。
  5. 返回 escaped
Note

尽管名称相似,EscapeRegExpPatternRegExp.escape 并不执行相似的动作。前者转义模式以表示为字符串,而此函数转义字符串以表示在模式内部。

22.2.5.1.1 EncodeForRegExpEscape ( cp )

The abstract operation EncodeForRegExpEscape takes argument cp (一个码点,) and returns 一个 String. 它返回一个表示用于匹配 cpPattern 的 String。如果 cp 是空白或 ASCII 标点符号,则返回值是一个转义序列。否则,返回值是 cp 自身的 String 表示。 It performs the following steps when called:

  1. 如果 cpSyntaxCharacter 匹配,或 cp 是 U+002F (SOLIDUS),则
    1. 返回 0x005C (REVERSE SOLIDUS) 与 UTF16EncodeCodePoint(cp) 的字符串拼接。
  2. 如果 cpTable 62 的 “Code Point” 列中列出的码点,则
    1. 返回 0x005C (REVERSE SOLIDUS) 与其 “Code Point” 列包含 cp 的那一行中 “ControlEscape” 列的字符串的字符串拼接。
  3. otherPunctuators",-=<>#&!%:;@~'`" 和码元 0x0022 (QUOTATION MARK) 的字符串拼接。
  4. toEscapeStringToCodePoints(otherPunctuators)。
  5. 如果 toEscape 包含 cpcpWhiteSpaceLineTerminator 匹配,或 cp 具有与前导代理项或尾随代理项相同的数值,则
    1. cpNumcp 的数值。
    2. 如果 cpNum ≤ 0xFF,则
      1. hexNumber::toString(𝔽(cpNum), 16)。
      2. 返回码元 0x005C (REVERSE SOLIDUS)、"x"StringPad(hex, 2, "0", start) 的字符串拼接。
    3. escaped 为空 String。
    4. codeUnitsUTF16EncodeCodePoint(cp)。
    5. 对于 codeUnits 的每个码元 cu,执行
      1. escaped 设置为 escapedUnicodeEscape(cu) 的字符串拼接。
    6. 返回 escaped
  6. 返回 UTF16EncodeCodePoint(cp)。

22.2.5.2 RegExp.prototype

RegExp.prototype 的初始值是 RegExp 原型对象

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

22.2.5.3 get RegExp [ %Symbol.species% ]

RegExp[%Symbol.species%] 是一个访问器属性,其 set 访问器函数为 undefined。它的 get 访问器函数在被调用时执行以下步骤:

  1. 返回 this 值。

此函数的 "name" 属性的值为 "get [Symbol.species]"

Note

RegExp 原型方法通常使用其 this 值的构造器来创建派生对象。然而,子类构造器可以通过重新定义其 %Symbol.species% 属性来覆写该默认行为。

22.2.6 RegExp 原型对象的属性

RegExp 原型对象

  • %RegExp.prototype%
  • 是一个普通对象
  • 不是 RegExp 实例,并且没有 [[RegExpMatcher]] 内部槽或 RegExp 实例对象的任何其他内部槽。
  • 有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%
Note

RegExp 原型对象自身没有 "valueOf" 属性;然而,它从 Object 原型对象继承了 "valueOf" 属性。

22.2.6.1 RegExp.prototype.constructor

RegExp.prototype.constructor 的初始值是 %RegExp%

22.2.6.2 RegExp.prototype.exec ( string )

此方法在 string 中搜索正则表达式模式的一次出现,并返回一个包含匹配结果的 Array;如果 string 未匹配,则返回 null

它在被调用时执行以下步骤:

  1. regexpthis 值。
  2. 执行 ? RequireInternalSlot(regexp, [[RegExpMatcher]])。
  3. str 为 ? ToString(string)。
  4. 返回 ? RegExpBuiltinExec(regexp, str)。

22.2.6.3 get RegExp.prototype.dotAll

RegExp.prototype.dotAll 是一个访问器属性,其 set 访问器函数为 undefined。它的 get 访问器函数在被调用时执行以下步骤:

  1. regexpthis 值。
  2. cu 为码元 0x0073 (LATIN SMALL LETTER S)。
  3. 返回 ? RegExpHasFlag(regexp, cu)。

22.2.6.4 get RegExp.prototype.flags

RegExp.prototype.flags 是一个访问器属性,其 set 访问器函数为 undefined。它的 get 访问器函数在被调用时执行以下步骤:

  1. regexpthis 值。
  2. 如果 regexp 不是一个 Object,抛出 TypeError 异常。
  3. codeUnits 为一个新的空 List
  4. hasIndicesToBoolean(? Get(regexp, "hasIndices"))。
  5. 如果 hasIndicestrue,将码元 0x0064 (LATIN SMALL LETTER D) 追加到 codeUnits
  6. globalToBoolean(? Get(regexp, "global"))。
  7. 如果 globaltrue,将码元 0x0067 (LATIN SMALL LETTER G) 追加到 codeUnits
  8. ignoreCaseToBoolean(? Get(regexp, "ignoreCase"))。
  9. 如果 ignoreCasetrue,将码元 0x0069 (LATIN SMALL LETTER I) 追加到 codeUnits
  10. multilineToBoolean(? Get(regexp, "multiline"))。
  11. 如果 multilinetrue,将码元 0x006D (LATIN SMALL LETTER M) 追加到 codeUnits
  12. dotAllToBoolean(? Get(regexp, "dotAll"))。
  13. 如果 dotAlltrue,将码元 0x0073 (LATIN SMALL LETTER S) 追加到 codeUnits
  14. unicodeToBoolean(? Get(regexp, "unicode"))。
  15. 如果 unicodetrue,将码元 0x0075 (LATIN SMALL LETTER U) 追加到 codeUnits
  16. unicodeSetsToBoolean(? Get(regexp, "unicodeSets"))。
  17. 如果 unicodeSetstrue,将码元 0x0076 (LATIN SMALL LETTER V) 追加到 codeUnits
  18. stickyToBoolean(? Get(regexp, "sticky"))。
  19. 如果 stickytrue,将码元 0x0079 (LATIN SMALL LETTER Y) 追加到 codeUnits
  20. 返回其码元为 List codeUnits 元素的 String 值。如果 codeUnits 没有元素,则返回空 String。

22.2.6.4.1 RegExpHasFlag ( regexp, codeUnit )

The abstract operation RegExpHasFlag takes arguments regexp (一个 ECMAScript 语言值,) and codeUnit (一个码元,) and returns 要么是一个包含 Boolean 或 undefined正常完成,要么是一个抛出完成. It performs the following steps when called:

  1. 如果 regexp 不是一个 Object,抛出 TypeError 异常。
  2. 如果 regexp 没有 [[OriginalFlags]] 内部槽,则
    1. 如果 SameValue(regexp, %RegExp.prototype%) 是 true,返回 undefined
    2. 抛出 TypeError 异常。
  3. flagsregexp.[[OriginalFlags]]
  4. 如果 flags 包含 codeUnit,返回 true
  5. 返回 false

22.2.6.5 get RegExp.prototype.global

RegExp.prototype.global 是一个访问器属性,其 set 访问器函数为 undefined。它的 get 访问器函数在被调用时执行以下步骤:

  1. regexpthis 值。
  2. cu 为码元 0x0067 (LATIN SMALL LETTER G)。
  3. 返回 ? RegExpHasFlag(regexp, cu)。

22.2.6.6 get RegExp.prototype.hasIndices

RegExp.prototype.hasIndices 是一个访问器属性,其 set 访问器函数为 undefined。它的 get 访问器函数在被调用时执行以下步骤:

  1. regexpthis 值。
  2. cu 为码元 0x0064 (LATIN SMALL LETTER D)。
  3. 返回 ? RegExpHasFlag(regexp, cu)。

22.2.6.7 get RegExp.prototype.ignoreCase

RegExp.prototype.ignoreCase 是一个访问器属性,其 set 访问器函数为 undefined。它的 get 访问器函数在被调用时执行以下步骤:

  1. regexpthis 值。
  2. cu 为码元 0x0069 (LATIN SMALL LETTER I)。
  3. 返回 ? RegExpHasFlag(regexp, cu)。

22.2.6.8 RegExp.prototype [ %Symbol.match% ] ( string )

此方法在被调用时执行以下步骤:

  1. regexpthis 值。
  2. 如果 regexp 不是一个 Object,抛出 TypeError 异常。
  3. str 为 ? ToString(string)。
  4. flags 为 ? ToString(? Get(regexp, "flags"))。
  5. 如果 flags 不包含 "g",返回 ? RegExpExec(regexp, str)。
  6. 如果 flags 包含 "u"flags 包含 "v",令 fullUnicodetrue;否则令 fullUnicodefalse
  7. 执行 ? Set(regexp, "lastIndex", +0𝔽, true)。
  8. array 为 ! ArrayCreate(0)。
  9. matchCount 为 0。
  10. 重复,
    1. result 为 ? RegExpExec(regexp, str)。
    2. 如果 resultnull,则
      1. 如果 matchCount = 0,返回 null
      2. 返回 array
    3. matchStr 为 ? ToString(? Get(result, "0"))。
    4. 执行 ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(matchCount)), matchStr)。
    5. 如果 matchStr 是空 String,则
      1. thisIndex(? ToLength(? Get(regexp, "lastIndex")))。
      2. nextIndexAdvanceStringIndex(str, thisIndex, fullUnicode)。
      3. 执行 ? Set(regexp, "lastIndex", 𝔽(nextIndex), true)。
    6. matchCount 设置为 matchCount + 1。

此方法的 "name" 属性的值为 "[Symbol.match]"

Note

%Symbol.match% 属性由 IsRegExp 抽象操作用于识别具有正则表达式基本行为的对象。不存在 %Symbol.match% 属性,或存在此类属性但其值无法布尔强制转换为 true,表示该对象并非旨在用作正则表达式对象。

22.2.6.9 RegExp.prototype [ %Symbol.matchAll% ] ( string )

此方法在被调用时执行以下步骤:

  1. regexpthis 值。
  2. 如果 regexp 不是一个 Object,抛出 TypeError 异常。
  3. str 为 ? ToString(string)。
  4. speciesConstructor 为 ? SpeciesConstructor(regexp, %RegExp%)。
  5. flags 为 ? ToString(? Get(regexp, "flags"))。
  6. matcher 为 ? Construct(speciesConstructor, « regexp, flags »)。
  7. lastIndex 为 ? ToLength(? Get(regexp, "lastIndex")).
  8. 执行 ? Set(matcher, "lastIndex", lastIndex, true)。
  9. 如果 flags 包含 "g",令 globaltrue
  10. 否则,令 globalfalse
  11. 如果 flags 包含 "u"flags 包含 "v",令 fullUnicodetrue
  12. 否则,令 fullUnicodefalse
  13. 返回 CreateRegExpStringIterator(matcher, str, global, fullUnicode)。

此方法的 "name" 属性的值为 "[Symbol.matchAll]"

22.2.6.10 get RegExp.prototype.multiline

RegExp.prototype.multiline 是一个访问器属性,其 set 访问器函数为 undefined。它的 get 访问器函数在被调用时执行以下步骤:

  1. regexpthis 值。
  2. cu 为码元 0x006D (LATIN SMALL LETTER M)。
  3. 返回 ? RegExpHasFlag(regexp, cu)。

22.2.6.11 RegExp.prototype [ %Symbol.replace% ] ( string, replaceValue )

此方法在被调用时执行以下步骤:

  1. regexpthis 值。
  2. 如果 regexp 不是一个 Object,抛出 TypeError 异常。
  3. str 为 ? ToString(string)。
  4. lengthSstr 的长度。
  5. functionalReplaceIsCallable(replaceValue)。
  6. 如果 functionalReplacefalse,则
    1. replaceValue 设置为 ? ToString(replaceValue)。
  7. flags 为 ? ToString(? Get(regexp, "flags"))。
  8. 如果 flags 包含 "g",令 globaltrue;否则令 globalfalse
  9. 如果 globaltrue,则
    1. 执行 ? Set(regexp, "lastIndex", +0𝔽, true)。
  10. results 为一个新的空 List
  11. donefalse
  12. 重复,当 donefalse 时,
    1. result 为 ? RegExpExec(regexp, str)。
    2. 如果 resultnull,则
      1. done 设置为 true
    3. 否则,
      1. result 追加到 results
      2. 如果 globalfalse,则
        1. done 设置为 true
      3. 否则,
        1. matchStr 为 ? ToString(? Get(result, "0"))。
        2. 如果 matchStr 是空 String,则
          1. thisIndex(? ToLength(? Get(regexp, "lastIndex")))。
          2. 如果 flags 包含 "u"flags 包含 "v",令 fullUnicodetrue;否则令 fullUnicodefalse
          3. nextIndexAdvanceStringIndex(str, thisIndex, fullUnicode)。
          4. 执行 ? Set(regexp, "lastIndex", 𝔽(nextIndex), true)。
  13. accumulatedResult 为空 String。
  14. nextSourcePosition 为 0。
  15. 对于 results 的每个元素 result,执行
    1. resultLength 为 ? LengthOfArrayLike(result)。
    2. nCapturesmax(resultLength - 1, 0)。
    3. matched 为 ? ToString(? Get(result, "0"))。
    4. matchLengthmatched 的长度。
    5. position 为 ? ToIntegerOrInfinity(? Get(result, "index"))。
    6. position 设置为将 position 夹在 0 和 lengthS 之间的结果。
    7. captures 为一个新的空 List
    8. captureNumber 为 1。
    9. 重复,当 captureNumbernCaptures 时,
      1. capN 为 ? Get(result, ! ToString(𝔽(captureNumber)))。
      2. 如果 capN 不是 undefined,则
        1. capN 设置为 ? ToString(capN)。
      3. capN 追加到 captures
      4. 注:当 captureNumber = 1 时,前一步将第一个元素放入 captures(索引为 0)。更一般地说,第 captureNumberth 个捕获(由第 captureNumberth 组捕获括号捕获的字符)位于 captures[captureNumber - 1]。
      5. captureNumber 设置为 captureNumber + 1。
    10. namedCaptures 为 ? Get(result, "groups")。
    11. 如果 functionalReplacetrue,则
      1. replacerArgs 为 « matched »、captures 和 « 𝔽(position), str » 的列表拼接。
      2. 如果 namedCaptures 不是 undefined,则
        1. namedCaptures 追加到 replacerArgs
      3. replacementValue 为 ? Call(replaceValue, undefined, replacerArgs)。
      4. replacementString 为 ? ToString(replacementValue)。
    12. 否则,
      1. 如果 namedCaptures 不是 undefined,则
        1. namedCaptures 设置为 ? ToObject(namedCaptures)。
      2. replacementString 为 ? GetSubstitution(matched, str, position, captures, namedCaptures, replaceValue)。
    13. 如果 positionnextSourcePosition,则
      1. 注:position 通常不应向后移动。如果确实向后移动,则表明存在行为不良的 RegExp 子类,或使用访问触发的副作用来更改 regexp 的 global 标志或其他特性。在此类情况下,相应的替换会被忽略。
      2. accumulatedResult 设置为 accumulatedResultstr 中从 nextSourcePositionposition子字符串以及 replacementString 的字符串拼接。
      3. nextSourcePosition 设置为 position + matchLength
  16. 如果 nextSourcePositionlengthS,返回 accumulatedResult
  17. 返回 accumulatedResultstr 中从 nextSourcePosition 开始的子字符串的字符串拼接。

此方法的 "name" 属性的值为 "[Symbol.replace]"

22.2.6.12 RegExp.prototype [ %Symbol.search% ] ( string )

此方法在被调用时执行以下步骤:

  1. regexpthis 值。
  2. 如果 regexp 不是一个 Object,抛出 TypeError 异常。
  3. str 为 ? ToString(string)。
  4. previousLastIndex 为 ? Get(regexp, "lastIndex")。
  5. 如果 previousLastIndex 不是 +0𝔽,则
    1. 执行 ? Set(regexp, "lastIndex", +0𝔽, true)。
  6. result 为 ? RegExpExec(regexp, str)。
  7. currentLastIndex 为 ? Get(regexp, "lastIndex")。
  8. 如果 SameValue(currentLastIndex, previousLastIndex) 是 false,则
    1. 执行 ? Set(regexp, "lastIndex", previousLastIndex, true)。
  9. 如果 resultnull,返回 -1𝔽
  10. 返回 ? Get(result, "index")。

此方法的 "name" 属性的值为 "[Symbol.search]"

Note

执行搜索时会忽略此 RegExp 对象的 "lastIndex""global" 属性。"lastIndex" 属性保持不变。

22.2.6.13 get RegExp.prototype.source

RegExp.prototype.source 是一个访问器属性,其 set 访问器函数为 undefined。它的 get 访问器函数在被调用时执行以下步骤:

  1. regexpthis 值。
  2. 如果 regexp 不是一个 Object,抛出 TypeError 异常。
  3. 如果 regexp 没有 [[OriginalSource]] 内部槽,则
    1. 如果 SameValue(regexp, %RegExp.prototype%) 是 true,返回 "(?:)"
    2. 抛出 TypeError 异常。
  4. 断言:regexp 具有 [[OriginalFlags]] 内部槽。
  5. srcregexp.[[OriginalSource]]
  6. flagsregexp.[[OriginalFlags]]
  7. 返回 EscapeRegExpPattern(src, flags)。

22.2.6.13.1 EscapeRegExpPattern ( pattern, flags )

The abstract operation EscapeRegExpPattern takes arguments pattern (一个 String,) and flags (一个 String,) and returns 一个 String. It performs the following steps when called:

  1. 如果 flags 包含 "v",则
    1. patternSymbolPattern[+UnicodeMode, +UnicodeSetsMode]
  2. 否则如果 flags 包含 "u",则
    1. patternSymbolPattern[+UnicodeMode, ~UnicodeSetsMode]
  3. 否则,
    1. patternSymbolPattern[~UnicodeMode, ~UnicodeSetsMode]
  4. escapedPattern 为形式为 patternSymbol 的一个 String,等价于将 pattern 解释为 UTF-16 编码的 Unicode 码点(6.1.4),其中某些码点按下文描述进行转义。escapedPattern 可以与 pattern 不同,也可以相同;然而,将 escapedPattern 作为 patternSymbol 求值所得的 Abstract Closure 必须与构造对象的 [[RegExpMatcher]] 内部槽给出的 Abstract Closure 行为相同。使用相同的 patternflags 值多次调用此抽象操作,必须产生相同结果。
  5. 模式中出现的码点 / 或任何 LineTerminator 应在 escapedPattern 中按需转义,以确保 "/"escapedPattern"/"flags 的字符串拼接可(在适当的词法上下文中)解析为一个 RegularExpressionLiteral,且其行为与构造的正则表达式相同。例如,如果 pattern"/",则 escapedPattern 可以是 "\/""\u002F" 等可能形式,但不能是 "/",因为 /// 后跟 flags 将被解析为 SingleLineComment 而不是 RegularExpressionLiteral。如果 pattern 是空 String,则可通过令 escapedPattern"(?:)" 来满足本规范。
  6. 返回 escapedPattern
Note

尽管名称相似,RegExp.escape 和 EscapeRegExpPattern 并不执行相似的动作。前者转义字符串以表示在模式内部,而此函数转义模式以表示为字符串。

22.2.6.14 RegExp.prototype [ %Symbol.split% ] ( string, limit )

Note 1

此方法返回一个 Array,其中存储了将 string 转换为 String 后所得结果的各个子字符串。这些子字符串通过从左到右搜索 this 值正则表达式的匹配来确定;这些出现不是返回数组中任何 String 的一部分,而是用于分割 String 值。

this 值可以是空正则表达式,也可以是能匹配空 String 的正则表达式。在这种情况下,正则表达式不匹配输入 String 开头或结尾处的空 substring,也不匹配上一个分隔符匹配结尾处的空 substring。(例如,如果正则表达式匹配空 String,则 String 被分割为单个码元元素;结果数组的长度等于 String 的长度,并且每个 substring 包含一个码元。)即使回溯可以在 String 的给定索引处产生非空 substring 匹配,也只考虑该索引处的第一个匹配。(例如,/a*?/[Symbol.split]("ab") 求值为数组 ["a", "b"],而 /a*/[Symbol.split]("ab") 求值为数组 ["","b"]。)

如果 string 是(或转换为)空 String,则结果取决于正则表达式是否能匹配空 String。如果能,则结果数组不包含任何元素。否则,结果数组包含一个元素,即空 String。

如果正则表达式包含捕获括号,则每次 separator 被匹配时,捕获括号的结果(包括任何 undefined 结果)都会被拼接到输出数组中。例如,

/<(\/)?([^<>]+)>/[Symbol.split]("A<B>bold</B>and<CODE>coded</CODE>")

求值为数组

["A", undefined, "B", "bold", "/", "B", "and", undefined, "CODE", "coded", "/", "CODE", ""]

如果 limit 不是 undefined,则输出数组会被截断,使其包含不超过 limit 个元素。

此方法在被调用时执行以下步骤:

  1. regexpthis 值。
  2. 如果 regexp 不是一个 Object,抛出 TypeError 异常。
  3. str 为 ? ToString(string)。
  4. speciesConstructor 为 ? SpeciesConstructor(regexp, %RegExp%)。
  5. flags 为 ? ToString(? Get(regexp, "flags"))。
  6. 如果 flags 包含 "u"flags 包含 "v",令 unicodeMatchingtrue
  7. 否则,令 unicodeMatchingfalse
  8. 如果 flags 包含 "y",令 newFlagsflags
  9. 否则,令 newFlagsflags"y" 的字符串拼接。
  10. splitter 为 ? Construct(speciesConstructor, « regexp, newFlags »)。
  11. array 为 ! ArrayCreate(0)。
  12. lengthA 为 0。
  13. 如果 limitundefined,令 lim 为 232 - 1;否则令 lim(? ToUint32(limit))。
  14. 如果 lim = 0,返回 array
  15. 如果 str 是空 String,则
    1. matchResult 为 ? RegExpExec(splitter, str)。
    2. 如果 matchResult 不是 null,返回 array
    3. 执行 ! CreateDataPropertyOrThrow(array, "0", str)。
    4. 返回 array
  16. sizestr 的长度。
  17. lastMatchEnd 为 0。
  18. searchIndexlastMatchEnd
  19. 重复,当 searchIndex < size 时,
    1. 执行 ? Set(splitter, "lastIndex", 𝔽(searchIndex), true)。
    2. matchResult 为 ? RegExpExec(splitter, str)。
    3. 如果 matchResultnull,则
      1. searchIndex 设置为 AdvanceStringIndex(str, searchIndex, unicodeMatching)。
    4. 否则,
      1. matchEnd(? ToLength(? Get(splitter, "lastIndex")))。
      2. matchEnd 设置为 min(matchEnd, size)。
      3. 如果 matchEnd = lastMatchEnd,则
        1. searchIndex 设置为 AdvanceStringIndex(str, searchIndex, unicodeMatching)。
      4. 否则,
        1. substringstr 中从 lastMatchEndsearchIndex子字符串
        2. 执行 ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(lengthA)), substring)。
        3. lengthA 设置为 lengthA + 1。
        4. 如果 lengthA = lim,返回 array
        5. lastMatchEnd 设置为 matchEnd
        6. numberOfCaptures 为 ? LengthOfArrayLike(matchResult)。
        7. numberOfCaptures 设置为 max(numberOfCaptures - 1, 0)。
        8. captureIndex 为 1。
        9. 重复,当 captureIndexnumberOfCaptures 时,
          1. nextCapture 为 ? Get(matchResult, ! ToString(𝔽(captureIndex)))。
          2. 执行 ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(lengthA)), nextCapture)。
          3. captureIndex 设置为 captureIndex + 1。
          4. lengthA 设置为 lengthA + 1。
          5. 如果 lengthA = lim,返回 array
        10. searchIndex 设置为 lastMatchEnd
  20. substringstr 中从 lastMatchEndsize子字符串
  21. 执行 ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(lengthA)), substring)。
  22. 返回 array

此方法的 "name" 属性的值为 "[Symbol.split]"

Note 2

此方法会忽略此 RegExp 对象的 "global""sticky" 属性的值。

22.2.6.15 get RegExp.prototype.sticky

RegExp.prototype.sticky 是一个访问器属性,其 set 访问器函数为 undefined。它的 get 访问器函数在被调用时执行以下步骤:

  1. regexpthis 值。
  2. cu 为码元 0x0079 (LATIN SMALL LETTER Y)。
  3. 返回 ? RegExpHasFlag(regexp, cu)。

22.2.6.16 RegExp.prototype.test ( str )

此方法在被调用时执行以下步骤:

  1. regexpthis 值。
  2. 如果 regexp 不是一个 Object,抛出 TypeError 异常。
  3. string 为 ? ToString(str)。
  4. match 为 ? RegExpExec(regexp, string)。
  5. 如果 matchnull,返回 false
  6. 返回 true

22.2.6.17 RegExp.prototype.toString ( )

  1. regexpthis 值。
  2. 如果 regexp 不是一个 Object,抛出 TypeError 异常。
  3. pattern 为 ? ToString(? Get(regexp, "source"))。
  4. flags 为 ? ToString(? Get(regexp, "flags"))。
  5. result"/"pattern"/"flags 的字符串拼接。
  6. 返回 result
Note

返回的 String 具有 RegularExpressionLiteral 的形式,该字面量求值为另一个与此对象具有相同行为的 RegExp 对象。

22.2.6.18 get RegExp.prototype.unicode

RegExp.prototype.unicode 是一个访问器属性,其 set 访问器函数为 undefined。它的 get 访问器函数在被调用时执行以下步骤:

  1. regexpthis 值。
  2. cu 为码元 0x0075 (LATIN SMALL LETTER U)。
  3. 返回 ? RegExpHasFlag(regexp, cu)。

22.2.6.19 get RegExp.prototype.unicodeSets

RegExp.prototype.unicodeSets 是一个访问器属性,其 set 访问器函数为 undefined。它的 get 访问器函数在被调用时执行以下步骤:

  1. regexpthis 值。
  2. cu 为码元 0x0076 (LATIN SMALL LETTER V)。
  3. 返回 ? RegExpHasFlag(regexp, cu)。

22.2.7 用于 RegExp 匹配的抽象操作

22.2.7.1 RegExpExec ( regexp, str )

The abstract operation RegExpExec takes arguments regexp (一个 Object,) and str (一个 String,) and returns 要么是一个包含 Object 或 null正常完成,要么是一个抛出完成. It performs the following steps when called:

  1. exec 为 ? Get(regexp, "exec")。
  2. 如果 IsCallable(exec) 是 true,则
    1. result 为 ? Call(exec, regexp, « str »)。
    2. 如果 result 不是 Object 且 result 不是 null,抛出 TypeError 异常。
    3. 返回 result
  3. 执行 ? RequireInternalSlot(regexp, [[RegExpMatcher]])。
  4. 返回 ? RegExpBuiltinExec(regexp, str)。
Note

如果未找到可调用的 "exec" 属性,此算法会退回到尝试使用内置 RegExp 匹配算法。对于为早期版本编写的代码,这提供了兼容行为;在那些版本中,大多数使用正则表达式的内置算法不会对 "exec" 执行动态属性查找。

22.2.7.2 RegExpBuiltinExec ( regexp, str )

The abstract operation RegExpBuiltinExec takes arguments regexp (一个已初始化的 RegExp 实例,) and str (一个 String,) and returns 要么是一个包含 Array 异质对象null正常完成,要么是一个抛出完成. It performs the following steps when called:

  1. lengthstr 的长度。
  2. lastIndex(? ToLength(! Get(regexp, "lastIndex")))。
  3. flagsregexp.[[OriginalFlags]]
  4. 如果 flags 包含 "g",令 globaltrue;否则令 globalfalse
  5. 如果 flags 包含 "y",令 stickytrue;否则令 stickyfalse
  6. 如果 flags 包含 "d",令 hasIndicestrue;否则令 hasIndicesfalse
  7. 如果 globalfalsestickyfalse,将 lastIndex 设置为 0。
  8. matcherregexp.[[RegExpMatcher]]
  9. 如果 flags 包含 "u"flags 包含 "v",令 fullUnicodetrue;否则令 fullUnicodefalse
  10. matchSucceededfalse
  11. 如果 fullUnicodetrue,令 inputStringToCodePoints(str);否则令 input 为一个 List,其元素为作为 str 元素的码元。
  12. 注:input 的每个元素都被视为一个字符。
  13. 重复,当 matchSucceededfalse 时,
    1. 如果 lastIndex > length,则
      1. 如果 globaltruestickytrue,则
        1. 执行 ? Set(regexp, "lastIndex", +0𝔽, true)。
      2. 返回 null
    2. inputIndexinput 中从 str 的元素 lastIndex 获得的字符的索引。
    3. rmatcher(input, inputIndex)。
    4. 如果 rfailure,则
      1. 如果 stickytrue,则
        1. 执行 ? Set(regexp, "lastIndex", +0𝔽, true)。
        2. 返回 null
      2. lastIndex 设置为 AdvanceStringIndex(str, lastIndex, fullUnicode)。
    5. 否则,
      1. 断言:r 是一个 MatchState
      2. matchSucceeded 设置为 true
  14. endIndexr.[[EndIndex]]
  15. 如果 fullUnicodetrue,将 endIndex 设置为 GetStringIndex(str, endIndex)。
  16. 如果 globaltruestickytrue,则
    1. 执行 ? Set(regexp, "lastIndex", 𝔽(endIndex), true)。
  17. nr.[[Captures]] 中元素的数量。
  18. 断言:n = regexp.[[RegExpRecord]].[[CapturingGroupsCount]]
  19. 断言:n < 232 - 1。
  20. array 为 ! ArrayCreate(n + 1)。
  21. 断言:array"length" 属性的数学值n + 1。
  22. 执行 ! CreateDataPropertyOrThrow(array, "index", 𝔽(lastIndex))。
  23. 执行 ! CreateDataPropertyOrThrow(array, "input", str)。
  24. matchMatch Record { [[StartIndex]]: lastIndex, [[EndIndex]]: endIndex }。
  25. indices 为一个新的空 List
  26. groupNames 为一个新的空 List
  27. match 追加到 indices
  28. matchedSubstrGetMatchString(str, match)。
  29. 执行 ! CreateDataPropertyOrThrow(array, "0", matchedSubstr)。
  30. 如果 regexp 包含任何 GroupName,则
    1. groupsOrdinaryObjectCreate(null)。
    2. hasGroupstrue
  31. 否则,
    1. groupsundefined
    2. hasGroupsfalse
  32. 执行 ! CreateDataPropertyOrThrow(array, "groups", groups)。
  33. matchedGroupNames 为一个新的空 List
  34. 对于满足 1 ≤ in 的每个整数 i,按升序执行
    1. captureIr.[[Captures]] 的第 ith 个元素。
    2. 如果 captureIundefined,则
      1. capturedValueundefined
      2. undefined 追加到 indices
    3. 否则,
      1. captureStartcaptureI.[[StartIndex]]
      2. captureEndcaptureI.[[EndIndex]]
      3. 如果 fullUnicodetrue,则
        1. captureStart 设置为 GetStringIndex(str, captureStart)。
        2. captureEnd 设置为 GetStringIndex(str, captureEnd)。
      4. captureMatch Record { [[StartIndex]]: captureStart, [[EndIndex]]: captureEnd }。
      5. capturedValueGetMatchString(str, capture)。
      6. capture 追加到 indices
    4. 执行 ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(i)), capturedValue)。
    5. 如果 regexp 的第 ith 个捕获是用 GroupName 定义的,则
      1. s 为该 GroupNameCapturingGroupName
      2. 如果 matchedGroupNames 包含 s,则
        1. 断言:capturedValueundefined
        2. undefined 追加到 groupNames
      3. 否则,
        1. 如果 capturedValue 不是 undefined,将 s 追加到 matchedGroupNames
        2. 注:如果存在多个名为 s 的组,则 groups 此时可能已经具有一个 s 属性。然而,因为 groups 是一个普通对象,其属性都是可写的数据属性,所以对 CreateDataPropertyOrThrow 的调用仍然保证成功。
        3. 执行 ! CreateDataPropertyOrThrow(groups, s, capturedValue)。
        4. s 追加到 groupNames
    6. 否则,
      1. undefined 追加到 groupNames
  35. 如果 hasIndicestrue,则
    1. indicesArrayMakeMatchIndicesIndexPairArray(str, indices, groupNames, hasGroups)。
    2. 执行 ! CreateDataPropertyOrThrow(array, "indices", indicesArray)。
  36. 返回 array

22.2.7.3 AdvanceStringIndex ( str, index, unicode )

The abstract operation AdvanceStringIndex takes arguments str (a String), index (a non-negative integer), and unicode (a Boolean) and returns a non-negative integer. It performs the following steps when called:

  1. 断言:index ≤ 253 - 1。
  2. 如果 unicodefalse,返回 index + 1。
  3. lengthstr 的长度。
  4. 如果 index + 1 ≥ length,返回 index + 1。
  5. cpCodePointAt(str, index)。
  6. 返回 index + cp.[[CodeUnitCount]]

22.2.7.4 GetStringIndex ( str, codePointIndex )

The abstract operation GetStringIndex takes arguments str (一个 String,) and codePointIndex (一个非负整数,) and returns 一个非负整数. 它按照 6.1.4 中所述,将 str 解释为 UTF-16 编码码点序列,并在存在对应于码点索引 codePointIndex 的码元索引时返回该码元索引。否则,它返回 str 的长度。 It performs the following steps when called:

  1. 如果 str 是空 String,返回 0。
  2. lenstr 的长度。
  3. codeUnitCount 为 0。
  4. codePointCount 为 0。
  5. 重复,当 codeUnitCount < len 时,
    1. 如果 codePointCount = codePointIndex,返回 codeUnitCount
    2. cpCodePointAt(str, codeUnitCount)。
    3. codeUnitCount 设置为 codeUnitCount + cp.[[CodeUnitCount]]
    4. codePointCount 设置为 codePointCount + 1。
  6. 返回 len

22.2.7.5 Match Record

Match Record 是一个 Record 值,用于封装正则表达式匹配或捕获的起始索引和结束索引。

Match Record 具有 Table 67 中列出的字段。

Table 67: Match Record 字段
字段名 含义
[[StartIndex]] 一个非负整数 从字符串开头到匹配开始处(包含)的码元数量。
[[EndIndex]] 一个整数[[StartIndex]] 从字符串开头到匹配结束处(不包含)的码元数量。

22.2.7.6 GetMatchString ( str, match )

The abstract operation GetMatchString takes arguments str (一个 String,) and match (一个 Match Record,) and returns 一个 String. It performs the following steps when called:

  1. 断言:match.[[StartIndex]]match.[[EndIndex]]str 的长度。
  2. 返回 str 中从 match.[[StartIndex]]match.[[EndIndex]]子字符串

22.2.7.7 GetMatchIndexPair ( str, match )

The abstract operation GetMatchIndexPair takes arguments str (一个 String,) and match (一个 Match Record,) and returns 一个 Array. It performs the following steps when called:

  1. 断言:match.[[StartIndex]]match.[[EndIndex]]str 的长度。
  2. 返回 CreateArrayFromList𝔽(match.[[StartIndex]]), 𝔽(match.[[EndIndex]]) »)。

22.2.7.8 MakeMatchIndicesIndexPairArray ( str, indices, groupNames, hasGroups )

The abstract operation MakeMatchIndicesIndexPairArray takes arguments str (一个 String,), indices (一个由 Match Recordundefined 组成的 List,), groupNames (一个由 String 或 undefined 组成的 List,), and hasGroups (一个 Boolean,) and returns 一个 Array. It performs the following steps when called:

  1. nindices 中元素的数量。
  2. 断言:n < 232 - 1。
  3. 断言:groupNamesn - 1 个元素。
  4. 注:groupNames List 包含从 indices[1] 开始与 indices List 对齐的元素。
  5. array 为 ! ArrayCreate(n)。
  6. 如果 hasGroupstrue,则
    1. groupsOrdinaryObjectCreate(null)。
  7. 否则,
    1. groupsundefined
  8. 执行 ! CreateDataPropertyOrThrow(array, "groups", groups)。
  9. 对于满足 0 ≤ i < n 的每个整数 i,按升序执行
    1. matchIndicesindices[i]。
    2. 如果 matchIndices 不是 undefined,则
      1. matchIndexPairGetMatchIndexPair(str, matchIndices)。
    3. 否则,
      1. matchIndexPairundefined
    4. 执行 ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(i)), matchIndexPair)。
    5. 如果 i > 0,则
      1. namegroupNames[i - 1]。
      2. 如果 name 不是 undefined,则
        1. 断言:groups 不是 undefined
        2. 注:如果存在多个名为 name 的组,则 groups 此时可能已经具有一个 name 属性。然而,因为 groups 是一个普通对象,其属性都是可写的数据属性,所以对 CreateDataPropertyOrThrow 的调用仍然保证成功。
        3. 执行 ! CreateDataPropertyOrThrow(groups, name, matchIndexPair)。
  10. 返回 array

22.2.8 RegExp 实例的属性

RegExp 实例是普通对象,从 RegExp 原型对象继承属性。RegExp 实例具有内部槽 [[OriginalSource]][[OriginalFlags]][[RegExpRecord]][[RegExpMatcher]][[RegExpMatcher]] 内部槽的值是 RegExp 对象的 PatternAbstract Closure 表示。

Note

在 ECMAScript 2015 之前,RegExp 实例被指定为具有自身数据属性 "source""global""ignoreCase""multiline"。这些属性现在被指定为 RegExp.prototype访问器属性

RegExp 实例还具有以下属性:

22.2.8.1 lastIndex

"lastIndex" 属性的值指定下一次匹配开始的 String 索引。使用时它会被强制转换为整数 Number(见 22.2.7.2)。此属性应具有特性 { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }。

22.2.9 RegExp String Iterator 对象

RegExp String Iterator 是一个对象,表示对某个特定 String 实例对象进行的特定迭代,并与某个特定 RegExp 实例对象进行匹配。RegExp String Iterator 对象没有具名构造器。相反,RegExp String Iterator 对象是通过调用 RegExp 实例对象的某些方法创建的。

22.2.9.1 CreateRegExpStringIterator ( regexp, str, global, fullUnicode )

The abstract operation CreateRegExpStringIterator takes arguments regexp (一个 Object,), str (一个 String,), global (一个 Boolean,), and fullUnicode (一个 Boolean,) and returns 一个 Object. It performs the following steps when called:

  1. iteratorOrdinaryObjectCreate(%RegExpStringIteratorPrototype%, « [[IteratingRegExp]], [[IteratedString]], [[Global]], [[Unicode]], [[Done]] »)。
  2. iterator.[[IteratingRegExp]] 设置为 regexp
  3. iterator.[[IteratedString]] 设置为 str
  4. iterator.[[Global]] 设置为 global
  5. iterator.[[Unicode]] 设置为 fullUnicode
  6. iterator.[[Done]] 设置为 false
  7. 返回 iterator

22.2.9.2 %RegExpStringIteratorPrototype% 对象

%RegExpStringIteratorPrototype% 对象:

22.2.9.2.1 %RegExpStringIteratorPrototype%.next ( )

  1. iteratorObjthis 值。
  2. 如果 iteratorObj 不是一个 Object,抛出 TypeError 异常。
  3. 如果 iteratorObj 不具有 RegExp String Iterator 对象实例的所有内部槽(见 22.2.9.3),抛出 TypeError 异常。
  4. 如果 iteratorObj.[[Done]]true,则
    1. 返回 CreateIteratorResultObject(undefined, true)。
  5. regexpiteratorObj.[[IteratingRegExp]]
  6. striteratorObj.[[IteratedString]]
  7. globaliteratorObj.[[Global]]
  8. fullUnicodeiteratorObj.[[Unicode]]
  9. match 为 ? RegExpExec(regexp, str)。
  10. 如果 matchnull,则
    1. iteratorObj.[[Done]] 设置为 true
    2. 返回 CreateIteratorResultObject(undefined, true)。
  11. 如果 globalfalse,则
    1. iteratorObj.[[Done]] 设置为 true
    2. 返回 CreateIteratorResultObject(match, false)。
  12. matchStr 为 ? ToString(? Get(match, "0"))。
  13. 如果 matchStr 是空 String,则
    1. thisIndex(? ToLength(? Get(regexp, "lastIndex")))。
    2. nextIndexAdvanceStringIndex(str, thisIndex, fullUnicode)。
    3. 执行 ? Set(regexp, "lastIndex", 𝔽(nextIndex), true)。
  14. 返回 CreateIteratorResultObject(match, false)。

22.2.9.2.2 %RegExpStringIteratorPrototype% [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "RegExp String Iterator"

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

22.2.9.3 RegExp String Iterator 实例的属性

RegExp String Iterator 实例是普通对象,从 %RegExpStringIteratorPrototype% 内在对象继承属性。RegExp String Iterator 实例最初会创建为具有 Table 68 中列出的内部槽。

Table 68: RegExp String Iterator 实例的内部槽
内部槽 类型 描述
[[IteratingRegExp]] 一个 Object 用于迭代的正则表达式。IsRegExp([[IteratingRegExp]]) 最初为 true
[[IteratedString]] 一个 String 正在被迭代的 String 值。
[[Global]] 一个 Boolean 指示 [[IteratingRegExp]] 是否为 global。
[[Unicode]] 一个 Boolean 指示 [[IteratingRegExp]] 是否处于 Unicode 模式。
[[Done]] 一个 Boolean 指示迭代是否完成。

23 索引集合

23.1 Array 对象

Array 是异质对象,会对某一类属性名给予特殊处理。关于这种特殊处理的定义,见 10.4.2

23.1.1 Array 构造器

Array 构造器

  • %Array%
  • 全局对象"Array" 属性的初始值。
  • 当作为构造器调用时,创建并初始化一个新的 Array。
  • 当作为函数而不是构造器调用时,也会创建并初始化一个新的 Array。因此,函数调用 Array(…) 等价于带有相同参数的对象创建表达式 new Array(…)
  • 是一个其行为会根据参数数量和类型而不同的函数。
  • 可用作类定义中 extends 子句的值。意图继承异质 Array 行为的子类构造器必须包含对 Array 构造器super 调用,以初始化作为 Array 异质对象的子类实例。然而,大多数 Array.prototype 方法都是泛型方法,并不依赖其 this 值是一个 Array 异质对象

23.1.1.1 Array ( ...values )

此函数在被调用时执行以下步骤:

  1. 如果 NewTarget 是 undefined,令 newTarget活动函数对象;否则令 newTarget 为 NewTarget。
  2. proto 为 ? GetPrototypeFromConstructor(newTarget, "%Array.prototype%")。
  3. numberOfArgsvalues 中元素的数量。
  4. 如果 numberOfArgs = 0,返回 ! ArrayCreate(0, proto)。
  5. 如果 numberOfArgs = 1,则
    1. lenvalues[0]。
    2. array 为 ! ArrayCreate(0, proto)。
    3. 如果 len 不是 Number,则
      1. 执行 ! CreateDataPropertyOrThrow(array, "0", len)。
      2. intLen1𝔽
    4. 否则,
      1. intLen 为 ! ToUint32(len)。
      2. 如果 SameValueZero(intLen, len) 是 false,抛出 RangeError 异常。
    5. 执行 ! Set(array, "length", intLen, true)。
    6. 返回 array
  6. 断言:numberOfArgs ≥ 2。
  7. array 为 ? ArrayCreate(numberOfArgs, proto)。
  8. k 为 0。
  9. 重复,当 k < numberOfArgs 时,
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. itemKvalues[k]。
    3. 执行 ! CreateDataPropertyOrThrow(array, propertyKey, itemK)。
    4. k 设置为 k + 1。
  10. 断言:array"length" 属性的数学值numberOfArgs
  11. 返回 array

23.1.2 Array 构造器的属性

Array 构造器

  • 有一个 [[Prototype]] 内部槽,其值为 %Function.prototype%
  • 有一个值为 1𝔽"length" 属性。
  • 具有以下属性:

23.1.2.1 Array.from ( items [ , mapper [ , thisArg ] ] )

此函数在被调用时执行以下步骤:

  1. constructorthis 值。
  2. 如果 mapperundefined,则
    1. mappingfalse
  3. 否则,
    1. 如果 IsCallable(mapper) 是 false,抛出 TypeError 异常。
    2. mappingtrue
  4. usingIterator 为 ? GetMethod(items, %Symbol.iterator%)。
  5. 如果 usingIterator 不是 undefined,则
    1. 如果 IsConstructor(constructor) 是 true,则
      1. array 为 ? Construct(constructor)。
    2. 否则,
      1. array 为 ! ArrayCreate(0)。
    3. iteratorRecord 为 ? GetIteratorFromMethod(items, usingIterator)。
    4. k 为 0。
    5. 重复,
      1. 如果 k ≥ 253 - 1,则
        1. errorThrowCompletion(一个新创建的 TypeError 对象)。
        2. 返回 ? IteratorClose(iteratorRecord, error)。
      2. propertyKey 为 ! ToString(𝔽(k))。
      3. next 为 ? IteratorStepValue(iteratorRecord)。
      4. 如果 nextdone,则
        1. 执行 ? Set(array, "length", 𝔽(k), true)。
        2. 返回 array
      5. 如果 mappingtrue,则
        1. mappedValueCompletion(Call(mapper, thisArg, « next, 𝔽(k) »))。
        2. IfAbruptCloseIterator(mappedValue, iteratorRecord)。
      6. 否则,
        1. mappedValuenext
      7. defineStatusCompletion(CreateDataPropertyOrThrow(array, propertyKey, mappedValue))。
      8. IfAbruptCloseIterator(defineStatus, iteratorRecord)。
      9. k 设置为 k + 1。
  6. 注:items 不可迭代,因此假定它是一个类数组对象
  7. arrayLike 为 ! ToObject(items)。
  8. len 为 ? LengthOfArrayLike(arrayLike)。
  9. 如果 IsConstructor(constructor) 是 true,则
    1. array 为 ? Construct(constructor, « 𝔽(len) »)。
  10. 否则,
    1. array 为 ? ArrayCreate(len)。
  11. k 为 0。
  12. 重复,当 k < len 时,
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. kValue 为 ? Get(arrayLike, propertyKey)。
    3. 如果 mappingtrue,则
      1. mappedValue 为 ? Call(mapper, thisArg, « kValue, 𝔽(k) »)。
    4. 否则,
      1. mappedValuekValue
    5. 执行 ? CreateDataPropertyOrThrow(array, propertyKey, mappedValue)。
    6. k 设置为 k + 1。
  13. 执行 ? Set(array, "length", 𝔽(len), true)。
  14. 返回 array
Note

此方法是有意设计的泛型工厂方法;它不要求其 this 值是 Array 构造器。因此,它可以被转移到或由任何其他可用单个数字参数调用的构造器继承。

23.1.2.2 Array.fromAsync ( items [ , mapper [ , thisArg ] ] )

此 async 函数在被调用时执行以下步骤:

  1. constructorthis 值。
  2. mappingfalse
  3. 如果 mapper 不是 undefined,则
    1. 如果 IsCallable(mapper) 是 false,抛出 TypeError 异常。
    2. mapping 设置为 true
  4. iteratorRecordundefined
  5. usingAsyncIterator 为 ? GetMethod(items, %Symbol.asyncIterator%)。
  6. 如果 usingAsyncIteratorundefined,则
    1. usingSyncIterator 为 ? GetMethod(items, %Symbol.iterator%)。
    2. 如果 usingSyncIterator 不是 undefined,则
      1. iteratorRecord 设置为 CreateAsyncFromSyncIterator(? GetIteratorFromMethod(items, usingSyncIterator))。
  7. 否则,
    1. iteratorRecord 设置为 ? GetIteratorFromMethod(items, usingAsyncIterator)。
  8. 如果 iteratorRecord 不是 undefined,则
    1. 如果 IsConstructor(constructor) 是 true,则
      1. array 为 ? Construct(constructor)。
    2. 否则,
      1. array 为 ! ArrayCreate(0)。
    3. k 为 0。
    4. 重复,
      1. 如果 k ≥ 253 - 1,则
        1. errorThrowCompletion(一个新创建的 TypeError 对象)。
        2. 返回 ? AsyncIteratorClose(iteratorRecord, error)。
      2. propertyKey 为 ! ToString(𝔽(k))。
      3. nextResult 为 ? Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]])。
      4. nextResult 设置为 ? Await(nextResult)。
      5. 如果 nextResult 不是 Object,抛出 TypeError 异常。
      6. done 为 ? IteratorComplete(nextResult)。
      7. 如果 donetrue,则
        1. 执行 ? Set(array, "length", 𝔽(k), true)。
        2. 返回 array
      8. nextValue 为 ? IteratorValue(nextResult)。
      9. 如果 mappingtrue,则
        1. mappedValueCompletion(Call(mapper, thisArg, « nextValue, 𝔽(k) »))。
        2. IfAbruptCloseAsyncIterator(mappedValue, iteratorRecord)。
        3. mappedValue 设置为 Completion(Await(mappedValue))。
        4. IfAbruptCloseAsyncIterator(mappedValue, iteratorRecord)。
      10. 否则,
        1. mappedValuenextValue
      11. defineStatusCompletion(CreateDataPropertyOrThrow(array, propertyKey, mappedValue))。
      12. IfAbruptCloseAsyncIterator(defineStatus, iteratorRecord)。
      13. k 设置为 k + 1。
  9. 否则,
    1. 注:items 既不是异步可迭代,也不是可迭代,因此假定它是一个类数组对象
    2. arrayLike 为 ! ToObject(items)。
    3. len 为 ? LengthOfArrayLike(arrayLike)。
    4. 如果 IsConstructor(constructor) 是 true,则
      1. array 为 ? Construct(constructor, « 𝔽(len) »)。
    5. 否则,
      1. array 为 ? ArrayCreate(len)。
    6. k 为 0。
    7. 重复,当 k < len 时,
      1. propertyKey 为 ! ToString(𝔽(k))。
      2. kValue 为 ? Get(arrayLike, propertyKey)。
      3. kValue 设置为 ? Await(kValue)。
      4. 如果 mappingtrue,则
        1. mappedValue 为 ? Call(mapper, thisArg, « kValue, 𝔽(k) »)。
        2. mappedValue 设置为 ? Await(mappedValue)。
      5. 否则,
        1. mappedValuekValue
      6. 执行 ? CreateDataPropertyOrThrow(array, propertyKey, mappedValue)。
      7. k 设置为 k + 1。
    8. 执行 ? Set(array, "length", 𝔽(len), true)。
    9. 返回 array
Note

此方法是有意设计的泛型工厂方法;它不要求其 this 值是 Array 构造器。因此,它可以被转移到或由任何其他可用单个数字参数调用的构造器继承。

23.1.2.3 Array.isArray ( arg )

此函数在被调用时执行以下步骤:

  1. 返回 ? IsArray(arg)。

23.1.2.4 Array.of ( ...items )

此方法在被调用时执行以下步骤:

  1. lenitems 中元素的数量。
  2. lenNumber𝔽(len)。
  3. constructorthis 值。
  4. 如果 IsConstructor(constructor) 是 true,则
    1. array 为 ? Construct(constructor, « lenNumber »)。
  5. 否则,
    1. array 为 ? ArrayCreate(len)。
  6. k 为 0。
  7. 重复,当 k < len 时,
    1. kValueitems[k]。
    2. propertyKey 为 ! ToString(𝔽(k))。
    3. 执行 ? CreateDataPropertyOrThrow(array, propertyKey, kValue)。
    4. k 设置为 k + 1。
  8. 执行 ? Set(array, "length", lenNumber, true)。
  9. 返回 array
Note

此方法是有意设计的泛型工厂方法;它不要求其 this 值是 Array 构造器。因此,它可以被转移到或由其他可用单个数字参数调用的构造器继承。

23.1.2.5 Array.prototype

Array.prototype 的值是 Array 原型对象

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

23.1.2.6 get Array [ %Symbol.species% ]

Array[%Symbol.species%] 是一个访问器属性,其 set 访问器函数为 undefined。它的 get 访问器函数在被调用时执行以下步骤:

  1. 返回 this 值。

此函数的 "name" 属性的值为 "get [Symbol.species]"

Note

Array 原型方法通常使用其 this 值的构造器来创建派生对象。然而,子类构造器可以通过重新定义其 %Symbol.species% 属性来覆写该默认行为。

23.1.3 Array 原型对象的属性

Array 原型对象

  • %Array.prototype%
  • 是一个 Array 异质对象,并具有为此类对象指定的内部方法。
  • 有一个 "length" 属性,其初始值为 +0𝔽,且其特性为 { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }。
  • 有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%
Note

Array 原型对象被指定为 Array 异质对象,是为了确保与 ECMAScript 2015 规范之前创建的 ECMAScript 代码兼容。

23.1.3.1 Array.prototype.at ( index )

  1. obj 为 ? ToObject(this value)。
  2. len 为 ? LengthOfArrayLike(obj)。
  3. relativeIndex 为 ? ToIntegerOrInfinity(index)。
  4. 如果 relativeIndex ≥ 0,则
    1. krelativeIndex
  5. 否则,
    1. klen + relativeIndex
  6. 如果 k < 0 或 klen,返回 undefined
  7. 返回 ? Get(obj, ! ToString(𝔽(k)))。

23.1.3.2 Array.prototype.concat ( ...items )

此方法返回一个数组,其中包含该对象的数组元素,后跟每个参数的数组元素。

它在被调用时执行以下步骤:

  1. obj 为 ? ToObject(this value)。
  2. array 为 ? ArraySpeciesCreate(obj, 0)。
  3. nextIndex 为 0。
  4. obj 前置到 items
  5. 对于 items 的每个元素 item,执行
    1. spreadable 为 ? IsConcatSpreadable(item)。
    2. 如果 spreadabletrue,则
      1. len 为 ? LengthOfArrayLike(item)。
      2. 如果 nextIndex + len > 253 - 1,抛出 TypeError 异常。
      3. sourceIndex 为 0。
      4. 重复,当 sourceIndex < len 时,
        1. propertyKey 为 ! ToString(𝔽(sourceIndex))。
        2. exists 为 ? HasProperty(item, propertyKey)。
        3. 如果 existstrue,则
          1. subElement 为 ? Get(item, propertyKey)。
          2. 执行 ? CreateDataPropertyOrThrow(array, ! ToString(𝔽(nextIndex)), subElement)。
        4. nextIndex 设置为 nextIndex + 1。
        5. sourceIndex 设置为 sourceIndex + 1。
    3. 否则,
      1. 注:item 作为单个项添加,而不是展开。
      2. 如果 nextIndex ≥ 253 - 1,抛出 TypeError 异常。
      3. 执行 ? CreateDataPropertyOrThrow(array, ! ToString(𝔽(nextIndex)), item)。
      4. nextIndex 设置为 nextIndex + 1。
  6. 执行 ? Set(array, "length", 𝔽(nextIndex), true)。
  7. 返回 array

此方法的 "length" 属性为 1𝔽

Note 1

步骤 6 中对 "length" 属性的显式设置,旨在确保当 items 中最后一个非空元素有尾随空洞,或 array 不是内置 Array 时,长度是正确的。

Note 2

此方法有意设计为泛型;它不要求其 this 值是 Array。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.2.1 IsConcatSpreadable ( obj )

The abstract operation IsConcatSpreadable takes argument obj (一个 ECMAScript 语言值,) and returns 要么是一个包含 Boolean 的正常完成,要么是一个抛出完成. It performs the following steps when called:

  1. 如果 obj 不是 Object,返回 false
  2. spreadable 为 ? Get(obj, %Symbol.isConcatSpreadable%)。
  3. 如果 spreadable 不是 undefined,返回 ToBoolean(spreadable)。
  4. 返回 ? IsArray(obj)。

23.1.3.3 Array.prototype.constructor

Array.prototype.constructor 的初始值是 %Array%

23.1.3.4 Array.prototype.copyWithin ( target, start [ , end ] )

Note 1

end 参数是可选的。如果未提供,则使用 this 值的长度。

Note 2

如果 target 为负,则将其视为 length + target,其中 length 是数组的长度。如果 start 为负,则将其视为 length + start。如果 end 为负,则将其视为 length + end

此方法在被调用时执行以下步骤:

  1. obj 为 ? ToObject(this value)。
  2. len 为 ? LengthOfArrayLike(obj)。
  3. relativeTarget 为 ? ToIntegerOrInfinity(target)。
  4. 如果 relativeTarget = -∞,令 to 为 0。
  5. 否则如果 relativeTarget < 0,令 tomax(len + relativeTarget, 0)。
  6. 否则,令 tomin(relativeTarget, len)。
  7. relativeStart 为 ? ToIntegerOrInfinity(start)。
  8. 如果 relativeStart = -∞,令 from 为 0。
  9. 否则如果 relativeStart < 0,令 frommax(len + relativeStart, 0)。
  10. 否则,令 frommin(relativeStart, len)。
  11. 如果 endundefined,令 relativeEndlen;否则令 relativeEnd 为 ? ToIntegerOrInfinity(end)。
  12. 如果 relativeEnd = -∞,令 final 为 0。
  13. 否则如果 relativeEnd < 0,令 finalmax(len + relativeEnd, 0)。
  14. 否则,令 finalmin(relativeEnd, len)。
  15. countmin(final - from, len - to)。
  16. 如果 from < toto < from + count,则
    1. direction 为 -1。
    2. from 设置为 from + count - 1。
    3. to 设置为 to + count - 1。
  17. 否则,
    1. direction 为 1。
  18. 重复,当 count > 0 时,
    1. fromKey 为 ! ToString(𝔽(from))。
    2. toKey 为 ! ToString(𝔽(to))。
    3. fromPresent 为 ? HasProperty(obj, fromKey)。
    4. 如果 fromPresenttrue,则
      1. fromValue 为 ? Get(obj, fromKey)。
      2. 执行 ? Set(obj, toKey, fromValue, true)。
    5. 否则,
      1. 断言:fromPresentfalse
      2. 执行 ? DeletePropertyOrThrow(obj, toKey)。
    6. from 设置为 from + direction
    7. to 设置为 to + direction
    8. count 设置为 count - 1。
  19. 返回 obj
Note 3

此方法有意设计为泛型;它不要求其 this 值是 Array。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.5 Array.prototype.entries ( )

此方法在被调用时执行以下步骤:

  1. obj 为 ? ToObject(this value)。
  2. 返回 CreateArrayIterator(obj, key+value)。

23.1.3.6 Array.prototype.every ( callback [ , thisArg ] )

Note 1

callback 应是一个接受三个参数并返回可强制转换为 Boolean 值的值的函数。every 按升序对数组中存在的每个元素调用一次 callback,直到发现某个元素使 callback 返回 false。如果发现这样的元素,every 立即返回 false。否则,every 返回 truecallback 只会对数组中实际存在的元素调用;不会对数组中缺失的元素调用。

如果提供了 thisArg 参数,则它将用作每次调用 callback 时的 this 值。如果未提供,则使用 undefined

调用 callback 时传入三个参数:元素的值、元素的索引以及正在遍历的对象。

every 不会直接修改调用它的对象,但该对象可能会被对 callback 的调用修改。

every 处理的元素范围在第一次调用 callback 之前确定。在 every 调用开始后追加到数组的元素不会被 callback 访问。如果数组的现有元素被更改,则传给 callback 的值将是 every 访问它们时的值;在 every 调用开始后且被访问之前被删除的元素不会被访问。every 的行为类似于数学中的“全称”量词。特别是,对于空数组,它返回 true

此方法在被调用时执行以下步骤:

  1. obj 为 ? ToObject(this value)。
  2. len 为 ? LengthOfArrayLike(obj)。
  3. 如果 IsCallable(callback) 是 false,抛出 TypeError 异常。
  4. k 为 0。
  5. 重复,当 k < len 时,
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. kPresent 为 ? HasProperty(obj, propertyKey)。
    3. 如果 kPresenttrue,则
      1. kValue 为 ? Get(obj, propertyKey)。
      2. testResultToBoolean(? Call(callback, thisArg, « kValue, 𝔽(k), obj »))。
      3. 如果 testResultfalse,返回 false
    4. k 设置为 k + 1。
  6. 返回 true
Note 2

此方法有意设计为泛型;它不要求其 this 值是 Array。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.7 Array.prototype.fill ( value [ , start [ , end ] ] )

Note 1

start 参数是可选的。如果未提供,则使用 +0𝔽

end 参数是可选的。如果未提供,则使用 this 值的长度。

Note 2

如果 start 为负,则将其视为 length + start,其中 length 是数组的长度。如果 end 为负,则将其视为 length + end

此方法在被调用时执行以下步骤:

  1. obj 为 ? ToObject(this value)。
  2. len 为 ? LengthOfArrayLike(obj)。
  3. relativeStart 为 ? ToIntegerOrInfinity(start)。
  4. 如果 relativeStart = -∞,令 k 为 0。
  5. 否则如果 relativeStart < 0,令 kmax(len + relativeStart, 0)。
  6. 否则,令 kmin(relativeStart, len)。
  7. 如果 endundefined,令 relativeEndlen;否则令 relativeEnd 为 ? ToIntegerOrInfinity(end)。
  8. 如果 relativeEnd = -∞,令 final 为 0。
  9. 否则如果 relativeEnd < 0,令 finalmax(len + relativeEnd, 0)。
  10. 否则,令 finalmin(relativeEnd, len)。
  11. 重复,当 k < final 时,
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. 执行 ? Set(obj, propertyKey, value, true)。
    3. k 设置为 k + 1。
  12. 返回 obj
Note 3

此方法有意设计为泛型;它不要求其 this 值是 Array。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.8 Array.prototype.filter ( callback [ , thisArg ] )

Note 1

callback 应是一个接受三个参数并返回可强制转换为 Boolean 值的值的函数。filter 按升序对数组中的每个元素调用一次 callback,并构造一个新数组,其中包含所有使 callback 返回 true 的值。callback 只会对数组中实际存在的元素调用;不会对数组中缺失的元素调用。

如果提供了 thisArg 参数,则它将用作每次调用 callback 时的 this 值。如果未提供,则使用 undefined

调用 callback 时传入三个参数:元素的值、元素的索引以及正在遍历的对象。

filter 不会直接修改调用它的对象,但该对象可能会被对 callback 的调用修改。

filter 处理的元素范围在第一次调用 callback 之前确定。在 filter 调用开始后追加到数组的元素不会被 callback 访问。如果数组的现有元素被更改,则传给 callback 的值将是 filter 访问它们时的值;在 filter 调用开始后且被访问之前被删除的元素不会被访问。

此方法在被调用时执行以下步骤:

  1. obj 为 ? ToObject(this value)。
  2. len 为 ? LengthOfArrayLike(obj)。
  3. 如果 IsCallable(callback) 是 false,抛出 TypeError 异常。
  4. array 为 ? ArraySpeciesCreate(obj, 0)。
  5. k 为 0。
  6. to 为 0。
  7. 重复,当 k < len 时,
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. kPresent 为 ? HasProperty(obj, propertyKey)。
    3. 如果 kPresenttrue,则
      1. kValue 为 ? Get(obj, propertyKey)。
      2. selectedToBoolean(? Call(callback, thisArg, « kValue, 𝔽(k), obj »))。
      3. 如果 selectedtrue,则
        1. 执行 ? CreateDataPropertyOrThrow(array, ! ToString(𝔽(to)), kValue)。
        2. to 设置为 to + 1。
    4. k 设置为 k + 1。
  8. 返回 array
Note 2

此方法有意设计为泛型;它不要求其 this 值是 Array。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.9 Array.prototype.find ( predicate [ , thisArg ] )

Note 1

此方法按升序索引顺序对数组的每个元素调用一次 predicate,直到找到一个使 predicate 返回可强制转换为 true 的值的元素。如果找到这样的元素,find 立即返回该元素值。否则,find 返回 undefined

更多信息见 FindViaPredicate

此方法在被调用时执行以下步骤:

  1. obj 为 ? ToObject(this value)。
  2. len 为 ? LengthOfArrayLike(obj)。
  3. findRec 为 ? FindViaPredicate(obj, len, ascending, predicate, thisArg)。
  4. 返回 findRec.[[Value]]
Note 2

此方法有意设计为泛型;它不要求其 this 值是 Array。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.10 Array.prototype.findIndex ( predicate [ , thisArg ] )

Note 1

此方法按升序索引顺序对数组的每个元素调用一次 predicate,直到找到一个使 predicate 返回可强制转换为 true 的值的元素。如果找到这样的元素,findIndex 立即返回该元素值的索引。否则,findIndex 返回 -1。

更多信息见 FindViaPredicate

此方法在被调用时执行以下步骤:

  1. obj 为 ? ToObject(this value)。
  2. len 为 ? LengthOfArrayLike(obj)。
  3. findRec 为 ? FindViaPredicate(obj, len, ascending, predicate, thisArg)。
  4. 返回 findRec.[[Index]]
Note 2

此方法有意设计为泛型;它不要求其 this 值是 Array。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.11 Array.prototype.findLast ( predicate [ , thisArg ] )

Note 1

此方法按降序索引顺序对数组的每个元素调用一次 predicate,直到找到一个使 predicate 返回可强制转换为 true 的值的元素。如果找到这样的元素,findLast 立即返回该元素值。否则,findLast 返回 undefined

更多信息见 FindViaPredicate

此方法在被调用时执行以下步骤:

  1. obj 为 ? ToObject(this value)。
  2. len 为 ? LengthOfArrayLike(obj)。
  3. findRec 为 ? FindViaPredicate(obj, len, descending, predicate, thisArg)。
  4. 返回 findRec.[[Value]]
Note 2

此方法有意设计为泛型;它不要求其 this 值是 Array 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.12 Array.prototype.findLastIndex ( predicate [ , thisArg ] )

Note 1

此方法按降序索引顺序对数组的每个元素调用一次 predicate,直到找到一个使 predicate 返回可强制转换为 true 的值的元素。如果找到这样的元素,findLastIndex 立即返回该元素值的索引。否则,findLastIndex 返回 -1。

更多信息见 FindViaPredicate

此方法在被调用时执行以下步骤:

  1. obj 为 ? ToObject(this value)。
  2. len 为 ? LengthOfArrayLike(obj)。
  3. findRec 为 ? FindViaPredicate(obj, len, descending, predicate, thisArg)。
  4. 返回 findRec.[[Index]]
Note 2

此方法有意设计为泛型;它不要求其 this 值是 Array 对象。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.12.1 FindViaPredicate ( obj, len, direction, predicate, thisArg )

The abstract operation FindViaPredicate takes arguments obj (一个 Object,), len (一个非负整数,), direction (ascendingdescending,), predicate (一个 ECMAScript 语言值,), and thisArg (一个 ECMAScript 语言值,) and returns 要么是一个包含具有字段 [[Index]](一个整数 Number)和 [[Value]](一个 ECMAScript 语言值)的 Record正常完成,要么是一个抛出完成.

obj 应是一个类数组对象TypedArray。此操作按升序索引顺序或降序索引顺序(由 direction 指示)对 obj 的每个元素调用一次 predicate,直到找到一个使 predicate 返回可强制转换为 true 的值的元素。此时,此操作返回一个给出所找到元素索引和值的 Record。如果没有找到这样的元素,此操作返回一个 Record,其中索引指定为 -1𝔽,值指定为 undefined

predicate 应是一个函数。当针对数组元素调用时,会向它传入三个参数:元素的值、元素的索引以及正在遍历的对象。它的返回值将被强制转换为 Boolean 值。

thisArg 将用作每次调用 predicate 时的 this 值。

此操作不会直接修改调用它的对象,但该对象可能会被对 predicate 的调用修改。

处理的元素范围在第一次调用 predicate 之前、遍历即将开始时确定。此后追加到数组的元素不会被 predicate 访问。如果数组的现有元素被更改,则传给 predicate 的值将是此操作访问它们时的值。在遍历开始后且被访问之前被删除的元素仍会被访问,并且要么从原型查找,要么为 undefined

It performs the following steps when called:

  1. 如果 IsCallable(predicate) 是 false,抛出 TypeError 异常。
  2. 如果 directionascending,则
    1. indices 为从 0(包含)到 len(不包含)区间内的整数 List,按升序排列。
  3. 否则,
    1. indices 为从 0(包含)到 len(不包含)区间内的整数 List,按降序排列。
  4. 对于 indices 的每个整数 k,执行
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. 注:如果 objTypedArray,下面对 Get 的调用将返回一个正常完成
    3. kValue 为 ? Get(obj, propertyKey)。
    4. testResult 为 ? Call(predicate, thisArg, « kValue, 𝔽(k), obj »)。
    5. 如果 ToBoolean(testResult) 是 true,返回 Record { [[Index]]: 𝔽(k), [[Value]]: kValue }。
  5. 返回 Record { [[Index]]: -1𝔽, [[Value]]: undefined }。

23.1.3.13 Array.prototype.flat ( [ depth ] )

此方法在被调用时执行以下步骤:

  1. obj 为 ? ToObject(this value)。
  2. sourceLen 为 ? LengthOfArrayLike(obj)。
  3. depthNum 为 1。
  4. 如果 depth 不是 undefined,则
    1. depthNum 设置为 ? ToIntegerOrInfinity(depth)。
    2. 如果 depthNum < 0,将 depthNum 设置为 0。
  5. array 为 ? ArraySpeciesCreate(obj, 0)。
  6. 执行 ? FlattenIntoArray(array, obj, sourceLen, 0, depthNum)。
  7. 返回 array

23.1.3.13.1 FlattenIntoArray ( target, source, sourceLen, start, depth [ , mapperFunction [ , thisArg ] ] )

The abstract operation FlattenIntoArray takes arguments target (一个 Object,), source (一个 Object,), sourceLen (一个非负整数,), start (一个非负整数,), and depth (一个非负整数或 +∞,) and optional arguments mapperFunction (一个函数对象,) and thisArg (一个 ECMAScript 语言值,) and returns 要么是一个包含非负整数正常完成,要么是一个抛出完成. It performs the following steps when called:

  1. 断言:如果 mapperFunction 存在,则 IsCallable(mapperFunction) 是 truethisArg 存在,且 depth 为 1。
  2. targetIndexstart
  3. sourceIndex+0𝔽
  4. 重复,当 (sourceIndex) < sourceLen 时,
    1. propertyKey 为 ! ToString(sourceIndex)。
    2. exists 为 ? HasProperty(source, propertyKey)。
    3. 如果 existstrue,则
      1. element 为 ? Get(source, propertyKey)。
      2. 如果 mapperFunction 存在,则
        1. element 设置为 ? Call(mapperFunction, thisArg, « element, sourceIndex, source »)。
      3. shouldFlattenfalse
      4. 如果 depth > 0,则
        1. shouldFlatten 设置为 ? IsArray(element)。
      5. 如果 shouldFlattentrue,则
        1. 如果 depth = +∞,令 newDepth 为 +∞。
        2. 否则,令 newDepthdepth - 1。
        3. elementLen 为 ? LengthOfArrayLike(element)。
        4. targetIndex 设置为 ? FlattenIntoArray(target, element, elementLen, targetIndex, newDepth)。
      6. 否则,
        1. 如果 targetIndex ≥ 253 - 1,抛出 TypeError 异常。
        2. 执行 ? CreateDataPropertyOrThrow(target, ! ToString(𝔽(targetIndex)), element)。
        3. targetIndex 设置为 targetIndex + 1。
    4. sourceIndex 设置为 sourceIndex + 1𝔽
  5. 返回 targetIndex

23.1.3.14 Array.prototype.flatMap ( mapperFunction [ , thisArg ] )

此方法在被调用时执行以下步骤:

  1. obj 为 ? ToObject(this value)。
  2. sourceLen 为 ? LengthOfArrayLike(obj)。
  3. 如果 IsCallable(mapperFunction) 是 false,抛出 TypeError 异常。
  4. array 为 ? ArraySpeciesCreate(obj, 0)。
  5. 执行 ? FlattenIntoArray(array, obj, sourceLen, 0, 1, mapperFunction, thisArg)。
  6. 返回 array

23.1.3.15 Array.prototype.forEach ( callback [ , thisArg ] )

Note 1

callback 应是一个接受三个参数的函数。forEach 按升序对数组中存在的每个元素调用一次 callbackcallback 只会对数组中实际存在的元素调用;不会对数组中缺失的元素调用。

如果提供了 thisArg 参数,则它将用作每次调用 callback 时的 this 值。如果未提供,则使用 undefined

调用 callback 时传入三个参数:元素的值、元素的索引以及正在遍历的对象。

forEach 不会直接修改调用它的对象,但该对象可能会被对 callback 的调用修改。

forEach 处理的元素范围在第一次调用 callback 之前确定。在 forEach 调用开始后追加到数组的元素不会被 callback 访问。如果数组的现有元素被更改,则传给 callback 的值将是 forEach 访问它们时的值;在 forEach 调用开始后且被访问之前被删除的元素不会被访问。

此方法在被调用时执行以下步骤:

  1. obj 为 ? ToObject(this value)。
  2. len 为 ? LengthOfArrayLike(obj)。
  3. 如果 IsCallable(callback) 是 false,抛出 TypeError 异常。
  4. k 为 0。
  5. 重复,当 k < len 时,
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. kPresent 为 ? HasProperty(obj, propertyKey)。
    3. 如果 kPresenttrue,则
      1. kValue 为 ? Get(obj, propertyKey)。
      2. 执行 ? Call(callback, thisArg, « kValue, 𝔽(k), obj »)。
    4. k 设置为 k + 1。
  6. 返回 undefined
Note 2

此方法有意设计为泛型;它不要求其 this 值是 Array。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.16 Array.prototype.includes ( searchElement [ , fromIndex ] )

Note 1

此方法按升序使用 SameValueZero 算法将 searchElement 与数组元素进行比较,如果在任何位置找到,则返回 true;否则返回 false

可选的第二参数 fromIndex 默认为 +0𝔽(即搜索整个数组)。如果它大于或等于数组的长度,则返回 false,即不会搜索该数组。如果它小于 -0𝔽,则它被用作从数组末尾开始的偏移量来计算 fromIndex。如果计算出的索引小于或等于 +0𝔽,则会搜索整个数组。

此方法在被调用时执行以下步骤:

  1. obj 为 ? ToObject(this value)。
  2. len 为 ? LengthOfArrayLike(obj)。
  3. 如果 len = 0,返回 false
  4. startIndex 为 ? ToIntegerOrInfinity(fromIndex)。
  5. 断言:如果 fromIndexundefined,则 startIndex 为 0。
  6. 如果 startIndex = +∞,返回 false
  7. 如果 startIndex = -∞,将 startIndex 设置为 0。
  8. 如果 startIndex ≥ 0,则
    1. kstartIndex
  9. 否则,
    1. klen + startIndex
    2. 如果 k < 0,将 k 设置为 0。
  10. 重复,当 k < len 时,
    1. elementK 为 ? Get(obj, ! ToString(𝔽(k)))。
    2. 如果 SameValueZero(searchElement, elementK) 是 true,返回 true
    3. k 设置为 k + 1。
  11. 返回 false
Note 2

此方法有意设计为泛型;它不要求其 this 值是 Array。因此,它可以被转移到其他种类的对象上作为方法使用。

Note 3

此方法有意在两个方面不同于类似的 indexOf 方法。第一,它使用 SameValueZero 算法,而不是 IsStrictlyEqual,从而允许它检测 NaN 数组元素。第二,它不会跳过缺失的数组元素,而是将它们视为 undefined

23.1.3.17 Array.prototype.indexOf ( searchElement [ , fromIndex ] )

此方法按升序使用 IsStrictlyEqual 算法将 searchElement 与数组元素进行比较,如果在一个或多个索引处找到,则返回此类索引中最小的一个;否则返回 -1𝔽

Note 1

可选的第二参数 fromIndex 默认为 +0𝔽(即搜索整个数组)。如果它大于或等于数组的长度,则返回 -1𝔽,即不会搜索该数组。如果它小于 -0𝔽,则用它来计算从数组末尾开始的偏移量。如果计算出的索引小于或等于 +0𝔽,则会搜索整个数组。

此方法在被调用时执行以下步骤:

  1. obj 为 ? ToObject(this value)。
  2. len 为 ? LengthOfArrayLike(obj)。
  3. 如果 len = 0,返回 -1𝔽
  4. startIndex 为 ? ToIntegerOrInfinity(fromIndex)。
  5. 断言:如果 fromIndexundefined,则 startIndex 为 0。
  6. 如果 startIndex = +∞,返回 -1𝔽
  7. 如果 startIndex = -∞,将 startIndex 设置为 0。
  8. 如果 startIndex ≥ 0,则
    1. kstartIndex
  9. 否则,
    1. klen + startIndex
    2. 如果 k < 0,将 k 设置为 0。
  10. 重复,当 k < len 时,
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. kPresent 为 ? HasProperty(obj, propertyKey)。
    3. 如果 kPresenttrue,则
      1. elementK 为 ? Get(obj, propertyKey)。
      2. 如果 IsStrictlyEqual(searchElement, elementK) 是 true,返回 𝔽(k)。
    4. k 设置为 k + 1。
  11. 返回 -1𝔽
Note 2

此方法有意设计为泛型;它不要求其 this 值是 Array。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.18 Array.prototype.join ( separator )

此方法将数组的元素转换为 String,然后将这些 String 拼接起来,并用 separator 的出现分隔。如果未提供分隔符,则使用单个逗号作为分隔符。

它在被调用时执行以下步骤:

  1. obj 为 ? ToObject(this value)。
  2. len 为 ? LengthOfArrayLike(obj)。
  3. 如果 separatorundefined,令 sep","
  4. 否则,令 sep 为 ? ToString(separator)。
  5. result 为空 String。
  6. k 为 0。
  7. 重复,当 k < len 时,
    1. 如果 k > 0,将 result 设置为 resultsep 的字符串拼接。
    2. element 为 ? Get(obj, ! ToString(𝔽(k)))。
    3. 如果 element 既不是 undefined 也不是 null,则
      1. elementStr 为 ? ToString(element)。
      2. result 设置为 resultelementStr 的字符串拼接。
    4. k 设置为 k + 1。
  8. 返回 result
Note

此方法有意设计为泛型;它不要求其 this 值是 Array。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.19 Array.prototype.keys ( )

此方法在被调用时执行以下步骤:

  1. obj 为 ? ToObject(this value)。
  2. 返回 CreateArrayIterator(obj, key)。

23.1.3.20 Array.prototype.lastIndexOf ( searchElement [ , fromIndex ] )

Note 1

此方法按降序使用 IsStrictlyEqual 算法将 searchElement 与数组元素进行比较,如果在一个或多个索引处找到,则返回此类索引中最大的一个;否则返回 -1𝔽

可选的第二参数 fromIndex 默认为数组长度减一(即搜索整个数组)。如果它大于或等于数组的长度,则会搜索整个数组。如果它小于 -0𝔽,则用它来计算从数组末尾开始的偏移量。如果计算出的索引小于 -0𝔽,则返回 -1𝔽

此方法在被调用时执行以下步骤:

  1. obj 为 ? ToObject(this value)。
  2. len 为 ? LengthOfArrayLike(obj)。
  3. 如果 len = 0,返回 -1𝔽
  4. 如果 fromIndex 存在,令 startIndex 为 ? ToIntegerOrInfinity(fromIndex);否则令 startIndexlen - 1。
  5. 如果 startIndex = -∞,返回 -1𝔽
  6. 如果 startIndex ≥ 0,则
    1. kmin(startIndex, len - 1)。
  7. 否则,
    1. klen + startIndex
  8. 重复,当 k ≥ 0 时,
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. kPresent 为 ? HasProperty(obj, propertyKey)。
    3. 如果 kPresenttrue,则
      1. elementK 为 ? Get(obj, propertyKey)。
      2. 如果 IsStrictlyEqual(searchElement, elementK) 是 true,返回 𝔽(k)。
    4. k 设置为 k - 1。
  9. 返回 -1𝔽
Note 2

此方法有意设计为泛型;它不要求其 this 值是 Array。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.21 Array.prototype.map ( callback [ , thisArg ] )

Note 1

callback 应是一个接受三个参数的函数。map 按升序对数组中的每个元素调用一次 callback,并根据结果构造一个新的 Array。callback 只会对数组中实际存在的元素调用;不会对数组中缺失的元素调用。

如果提供了 thisArg 参数,则它将用作每次调用 callback 时的 this 值。如果未提供,则使用 undefined

调用 callback 时传入三个参数:元素的值、元素的索引以及正在遍历的对象。

map 不会直接修改调用它的对象,但该对象可能会被对 callback 的调用修改。

map 处理的元素范围在第一次调用 callback 之前确定。在 map 调用开始后追加到数组的元素不会被 callback 访问。如果数组的现有元素被更改,则传给 callback 的值将是 map 访问它们时的值;在 map 调用开始后且被访问之前被删除的元素不会被访问。

此方法在被调用时执行以下步骤:

  1. obj 为 ? ToObject(this value)。
  2. len 为 ? LengthOfArrayLike(obj)。
  3. 如果 IsCallable(callback) 是 false,抛出 TypeError 异常。
  4. array 为 ? ArraySpeciesCreate(obj, len)。
  5. k 为 0。
  6. 重复,当 k < len 时,
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. kPresent 为 ? HasProperty(obj, propertyKey)。
    3. 如果 kPresenttrue,则
      1. kValue 为 ? Get(obj, propertyKey)。
      2. mappedValue 为 ? Call(callback, thisArg, « kValue, 𝔽(k), obj »)。
      3. 执行 ? CreateDataPropertyOrThrow(array, propertyKey, mappedValue)。
    4. k 设置为 k + 1。
  7. 返回 array
Note 2

此方法有意设计为泛型;它不要求其 this 值是 Array。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.22 Array.prototype.pop ( )

Note 1

此方法移除数组的最后一个元素并返回它。

此方法在被调用时执行以下步骤:

  1. obj 为 ? ToObject(this value)。
  2. len 为 ? LengthOfArrayLike(obj)。
  3. 如果 len = 0,则
    1. 执行 ? Set(obj, "length", +0𝔽, true)。
    2. 返回 undefined
  4. 断言:len > 0。
  5. newLen𝔽(len - 1)。
  6. index 为 ! ToString(newLen)。
  7. element 为 ? Get(obj, index)。
  8. 执行 ? DeletePropertyOrThrow(obj, index)。
  9. 执行 ? Set(obj, "length", newLen, true)。
  10. 返回 element
Note 2

此方法有意设计为泛型;它不要求其 this 值是 Array。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.23 Array.prototype.push ( ...items )

Note 1

此方法按参数出现的顺序将参数追加到数组末尾。它返回数组的新长度。

此方法在被调用时执行以下步骤:

  1. obj 为 ? ToObject(this value)。
  2. len 为 ? LengthOfArrayLike(obj)。
  3. argCountitems 中元素的数量。
  4. 如果 len + argCount > 253 - 1,抛出 TypeError 异常。
  5. 对于 items 的每个元素 item,执行
    1. 执行 ? Set(obj, ! ToString(𝔽(len)), item, true)。
    2. len 设置为 len + 1。
  6. 执行 ? Set(obj, "length", 𝔽(len), true)。
  7. 返回 𝔽(len)。

此方法的 "length" 属性为 1𝔽

Note 2

此方法有意设计为泛型;它不要求其 this 值是 Array。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.24 Array.prototype.reduce ( callback [ , initialValue ] )

Note 1

callback 应是一个接受四个参数的函数。reduce 会按升序对数组中存在的每个元素调用一次 callback,除非提供了 initialValue,否则会跳过第一个元素。

调用 callback 时传入四个参数:previousValue(前一次调用 callback 得到的值)、currentValue(当前元素的值)、currentIndex 以及正在遍历的对象。第一次调用 callback 时,previousValuecurrentValue 可以是两种值之一。如果调用 reduce 时提供了 initialValue,则 previousValue 将是 initialValuecurrentValue 将是数组中的第一个值。如果未提供 initialValue,则 previousValue 将是数组中的第一个值,currentValue 将是第二个值。如果数组不包含任何元素且未提供 initialValue,则为 TypeError

reduce 不会直接修改调用它的对象,但该对象可能会被对 callback 的调用修改。

reduce 处理的元素范围在第一次调用 callback 之前确定。在 reduce 调用开始后追加到数组的元素不会被 callback 访问。如果数组的现有元素被更改,则传给 callback 的值将是 reduce 访问它们时的值;在 reduce 调用开始后且被访问之前被删除的元素不会被访问。

此方法在被调用时执行以下步骤:

  1. obj 为 ? ToObject(this value)。
  2. len 为 ? LengthOfArrayLike(obj)。
  3. 如果 IsCallable(callback) 是 false,抛出 TypeError 异常。
  4. 如果 len = 0 且 initialValue 不存在,抛出 TypeError 异常。
  5. k 为 0。
  6. accumulatorundefined
  7. 如果 initialValue 存在,则
    1. accumulator 设置为 initialValue
  8. 否则,
    1. kPresentfalse
    2. 重复,当 kPresentfalsek < len 时,
      1. propertyKey 为 ! ToString(𝔽(k))。
      2. kPresent 设置为 ? HasProperty(obj, propertyKey)。
      3. 如果 kPresenttrue,则
        1. accumulator 设置为 ? Get(obj, propertyKey)。
      4. k 设置为 k + 1。
    3. 如果 kPresentfalse,抛出 TypeError 异常。
  9. 重复,当 k < len 时,
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. kPresent 为 ? HasProperty(obj, propertyKey)。
    3. 如果 kPresenttrue,则
      1. kValue 为 ? Get(obj, propertyKey)。
      2. accumulator 设置为 ? Call(callback, undefined, « accumulator, kValue, 𝔽(k), obj »)。
    4. k 设置为 k + 1。
  10. 返回 accumulator
Note 2

此方法有意设计为泛型;它不要求其 this 值是 Array。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.25 Array.prototype.reduceRight ( callback [ , initialValue ] )

Note 1

callback 应是一个接受四个参数的函数。reduceRight 会按降序对数组中存在的每个元素调用一次 callback,除非提供了 initialValue,否则会跳过第一次调用。

调用 callback 时传入四个参数:previousValue(前一次调用 callback 得到的值)、currentValue(当前元素的值)、currentIndex 以及正在遍历的对象。第一次调用该函数时,previousValuecurrentValue 可以是两种值之一。如果调用 reduceRight 时提供了 initialValue,则 previousValue 将是 initialValuecurrentValue 将是数组中的最后一个值。如果未提供 initialValue,则 previousValue 将是数组中的最后一个值,currentValue 将是倒数第二个值。如果数组不包含任何元素且未提供 initialValue,则为 TypeError

reduceRight 不会直接修改调用它的对象,但该对象可能会被对 callback 的调用修改。

reduceRight 处理的元素范围在第一次调用 callback 之前确定。在 reduceRight 调用开始后追加到数组的元素不会被 callback 访问。如果数组的现有元素被 callback 更改,则传给 callback 的值将是 reduceRight 访问它们时的值;在 reduceRight 调用开始后且被访问之前被删除的元素不会被访问。

此方法在被调用时执行以下步骤:

  1. obj 为 ? ToObject(this value)。
  2. len 为 ? LengthOfArrayLike(obj)。
  3. 如果 IsCallable(callback) 是 false,抛出 TypeError 异常。
  4. 如果 len = 0 且 initialValue 不存在,抛出 TypeError 异常。
  5. klen - 1。
  6. accumulatorundefined
  7. 如果 initialValue 存在,则
    1. accumulator 设置为 initialValue
  8. 否则,
    1. kPresentfalse
    2. 重复,当 kPresentfalsek ≥ 0 时,
      1. propertyKey 为 ! ToString(𝔽(k))。
      2. kPresent 设置为 ? HasProperty(obj, propertyKey)。
      3. 如果 kPresenttrue,则
        1. accumulator 设置为 ? Get(obj, propertyKey)。
      4. k 设置为 k - 1。
    3. 如果 kPresentfalse,抛出 TypeError 异常。
  9. 重复,当 k ≥ 0 时,
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. kPresent 为 ? HasProperty(obj, propertyKey)。
    3. 如果 kPresenttrue,则
      1. kValue 为 ? Get(obj, propertyKey)。
      2. accumulator 设置为 ? Call(callback, undefined, « accumulator, kValue, 𝔽(k), obj »)。
    4. k 设置为 k - 1。
  10. 返回 accumulator
Note 2

此方法有意设计为泛型;它不要求其 this 值是 Array。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.26 Array.prototype.reverse ( )

Note 1

此方法重新排列数组的元素,以反转其顺序。它返回反转后的数组。

此方法在被调用时执行以下步骤:

  1. obj 为 ? ToObject(this value)。
  2. len 为 ? LengthOfArrayLike(obj)。
  3. middlefloor(len / 2)。
  4. lower 为 0。
  5. 重复,当 lowermiddle 时,
    1. upperlen - lower - 1。
    2. upperP 为 ! ToString(𝔽(upper))。
    3. lowerP 为 ! ToString(𝔽(lower))。
    4. lowerExists 为 ? HasProperty(obj, lowerP)。
    5. 如果 lowerExiststrue,则
      1. lowerValue 为 ? Get(obj, lowerP)。
    6. upperExists 为 ? HasProperty(obj, upperP)。
    7. 如果 upperExiststrue,则
      1. upperValue 为 ? Get(obj, upperP)。
    8. 如果 lowerExiststrueupperExiststrue,则
      1. 执行 ? Set(obj, lowerP, upperValue, true)。
      2. 执行 ? Set(obj, upperP, lowerValue, true)。
    9. 否则如果 lowerExistsfalseupperExiststrue,则
      1. 执行 ? Set(obj, lowerP, upperValue, true)。
      2. 执行 ? DeletePropertyOrThrow(obj, upperP)。
    10. 否则如果 lowerExiststrueupperExistsfalse,则
      1. 执行 ? DeletePropertyOrThrow(obj, lowerP)。
      2. 执行 ? Set(obj, upperP, lowerValue, true)。
    11. 否则,
      1. 断言:lowerExistsupperExists 都是 false
      2. 注:不需要任何动作。
    12. lower 设置为 lower + 1。
  6. 返回 obj
Note 2

此方法有意设计为泛型;它不要求其 this 值是 Array。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.27 Array.prototype.shift ( )

此方法移除数组的第一个元素并返回它。

它在被调用时执行以下步骤:

  1. obj 为 ? ToObject(this value)。
  2. len 为 ? LengthOfArrayLike(obj)。
  3. 如果 len = 0,则
    1. 执行 ? Set(obj, "length", +0𝔽, true)。
    2. 返回 undefined
  4. first 为 ? Get(obj, "0")。
  5. k 为 1。
  6. 重复,当 k < len 时,
    1. from 为 ! ToString(𝔽(k))。
    2. to 为 ! ToString(𝔽(k - 1))。
    3. fromPresent 为 ? HasProperty(obj, from)。
    4. 如果 fromPresenttrue,则
      1. fromValue 为 ? Get(obj, from)。
      2. 执行 ? Set(obj, to, fromValue, true)。
    5. 否则,
      1. 断言:fromPresentfalse
      2. 执行 ? DeletePropertyOrThrow(obj, to)。
    6. k 设置为 k + 1。
  7. 执行 ? DeletePropertyOrThrow(obj, ! ToString(𝔽(len - 1)))。
  8. 执行 ? Set(obj, "length", 𝔽(len - 1), true)。
  9. 返回 first
Note

此方法有意设计为泛型;它不要求其 this 值是 Array。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.28 Array.prototype.slice ( start, end )

此方法返回一个数组,其中包含从元素 start 到元素 end(不包含)的数组元素(如果 endundefined,则一直到数组末尾)。如果 start 为负,则将其视为 length + start,其中 length 是数组的长度。如果 end 为负,则将其视为 length + end,其中 length 是数组的长度。

它在被调用时执行以下步骤:

  1. obj 为 ? ToObject(this value)。
  2. len 为 ? LengthOfArrayLike(obj)。
  3. relativeStart 为 ? ToIntegerOrInfinity(start)。
  4. 如果 relativeStart = -∞,令 k 为 0。
  5. 否则如果 relativeStart < 0,令 kmax(len + relativeStart, 0)。
  6. 否则,令 kmin(relativeStart, len)。
  7. 如果 endundefined,令 relativeEndlen;否则令 relativeEnd 为 ? ToIntegerOrInfinity(end)。
  8. 如果 relativeEnd = -∞,令 final 为 0。
  9. 否则如果 relativeEnd < 0,令 finalmax(len + relativeEnd, 0)。
  10. 否则,令 finalmin(relativeEnd, len)。
  11. countmax(final - k, 0)。
  12. array 为 ? ArraySpeciesCreate(obj, count)。
  13. resultIndex 为 0。
  14. 重复,当 k < final 时,
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. kPresent 为 ? HasProperty(obj, propertyKey)。
    3. 如果 kPresenttrue,则
      1. kValue 为 ? Get(obj, propertyKey)。
      2. 执行 ? CreateDataPropertyOrThrow(array, ! ToString(𝔽(resultIndex)), kValue)。
    4. k 设置为 k + 1。
    5. resultIndex 设置为 resultIndex + 1。
  15. 执行 ? Set(array, "length", 𝔽(resultIndex), true)。
  16. 返回 array
Note 1

步骤 15 中对 "length" 属性的显式设置,旨在确保即使 array 不是内置 Array,长度也是正确的。

Note 2

此方法有意设计为泛型;它不要求其 this 值是 Array。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.29 Array.prototype.some ( callback [ , thisArg ] )

Note 1

callback 应是一个接受三个参数并返回可强制转换为 Boolean 值的值的函数。some 按升序对数组中存在的每个元素调用一次 callback,直到发现某个元素使 callback 返回 true。如果发现这样的元素,some 立即返回 true。否则,some 返回 falsecallback 只会对数组中实际存在的元素调用;不会对数组中缺失的元素调用。

如果提供了 thisArg 参数,则它将用作每次调用 callback 时的 this 值。如果未提供,则使用 undefined

调用 callback 时传入三个参数:元素的值、元素的索引以及正在遍历的对象。

some 不会直接修改调用它的对象,但该对象可能会被对 callback 的调用修改。

some 处理的元素范围在第一次调用 callback 之前确定。在 some 调用开始后追加到数组的元素不会被 callback 访问。如果数组的现有元素被更改,则传给 callback 的值将是 some 访问它们时的值;在 some 调用开始后且被访问之前被删除的元素不会被访问。some 的行为类似于数学中的“存在”量词。特别是,对于空数组,它返回 false

此方法在被调用时执行以下步骤:

  1. obj 为 ? ToObject(this value)。
  2. len 为 ? LengthOfArrayLike(obj)。
  3. 如果 IsCallable(callback) 是 false,抛出 TypeError 异常。
  4. k 为 0。
  5. 重复,当 k < len 时,
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. kPresent 为 ? HasProperty(obj, propertyKey)。
    3. 如果 kPresenttrue,则
      1. kValue 为 ? Get(obj, propertyKey)。
      2. testResultToBoolean(? Call(callback, thisArg, « kValue, 𝔽(k), obj »))。
      3. 如果 testResulttrue,返回 true
    4. k 设置为 k + 1。
  6. 返回 false
Note 2

此方法有意设计为泛型;它不要求其 this 值是 Array。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.30 Array.prototype.sort ( comparator )

此方法对该数组的元素进行排序。如果 comparator 不是 undefined,则它应是一个接受两个参数 xy 的函数,并在 x < y 时返回一个负 Number,在 x > y 时返回一个正 Number,其他情况下返回零。

它在被调用时执行以下步骤:

  1. 如果 comparator 不是 undefinedIsCallable(comparator) 是 false,抛出 TypeError 异常。
  2. obj 为 ? ToObject(this value)。
  3. len 为 ? LengthOfArrayLike(obj)。
  4. sortCompare 为一个新的 Abstract Closure,其参数为 (x, y),捕获 comparator,并在被调用时执行以下步骤:
    1. 返回 ? CompareArrayElements(x, y, comparator)。
  5. sortedList 为 ? SortIndexedProperties(obj, len, sortCompare, skip-holes)。
  6. itemCountsortedList 中元素的数量。
  7. j 为 0。
  8. 重复,当 j < itemCount 时,
    1. 执行 ? Set(obj, ! ToString(𝔽(j)), sortedList[j], true)。
    2. j 设置为 j + 1。
  9. 注:步骤 5 中对 SortIndexedProperties 的调用使用 skip-holes。剩余索引会被删除,以保留检测到并从排序中排除的空洞数量。
  10. 重复,当 j < len 时,
    1. 执行 ? DeletePropertyOrThrow(obj, ! ToString(𝔽(j)))。
    2. j 设置为 j + 1。
  11. 返回 obj
Note 1

由于不存在的属性值总是比较为大于 undefined 属性值,而 undefined 总是比较为大于任何其他值(见 CompareArrayElements),因此 undefined 属性值总是排序到结果末尾,其后是不存的属性值。

Note 2

步骤 56 中由 ToString 抽象操作执行的方法调用,可能导致 sortCompare 不再表现为一致比较器

Note 3

此方法有意设计为泛型;它不要求其 this 值是 Array。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.30.1 SortIndexedProperties ( obj, len, sortCompare, holes )

The abstract operation SortIndexedProperties takes arguments obj (一个 Object,), len (一个非负整数,), sortCompare (一个带有两个参数的 Abstract Closure,), and holes (skip-holesread-through-holes,) and returns 要么是一个包含 ECMAScript 语言值 List正常完成,要么是一个抛出完成. It performs the following steps when called:

  1. items 为一个新的空 List
  2. k 为 0。
  3. 重复,当 k < len 时,
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. 如果 holesskip-holes,则
      1. kRead 为 ? HasProperty(obj, propertyKey)。
    3. 否则,
      1. 断言:holesread-through-holes
      2. kReadtrue
    4. 如果 kReadtrue,则
      1. kValue 为 ? Get(obj, propertyKey)。
      2. kValue 追加到 items
    5. k 设置为 k + 1。
  4. 使用实现定义sortCompare 的调用序列对 items 排序。如果任何此类调用返回 abrupt completion,则在执行任何进一步的 sortCompare 调用之前停止,并返回该 Completion Record
  5. 返回 items

排序顺序是在上述算法步骤 4 完成后 items 的顺序。如果 sortCompare 不是 items 元素的一致比较器,则排序顺序实现定义的。当 SortIndexedProperties 被 Array.prototype.sortArray.prototype.toSorted 调用时,如果 comparatorundefined,并且对传递给 sortCompare 的任何特定值应用 ToString 并不都产生相同结果,则排序顺序也是实现定义的。

除非排序顺序被指定为实现定义,否则它必须满足以下所有条件:

  • 必须存在某个小于 itemCount 的非负整数的数学排列 π,使得对于每个小于 itemCount 的非负整数 j,元素 old[j]new[π(j)] 完全相同。
  • 然后对于所有小于 itemCount 的非负整数 jk,如果 (sortCompare(old[j], old[k])) < 0,则 π(j) < π(k)
  • 并且对于所有满足 j < k < itemCount 的非负整数 jk,如果 (sortCompare(old[j], old[k])) = 0,则 π(j) < π(k);即,排序是稳定的。

这里使用记法 old[j] 指代执行步骤 4 之前的 items[j],使用记法 new[j] 指代执行步骤 4 之后的 items[j]

如果对于集合 values 中的所有值 abc(可能是同一个值)都满足下列要求,则 Abstract Closure 或函数 comparator 是值集合 values一致比较器:记法 a <C b 表示 (comparator(a, b)) < 0a =C b 表示 (comparator(a, b)) = 0;而 a >C b 表示 (comparator(a, b)) > 0

  • 对给定的一对值 ab 作为两个参数调用 comparator(a, b) 时,总是返回相同的值 v。此外,v 是一个 Number,并且 v 不是 NaN。注意,这意味着对于给定的一对 aba <C ba =C ba >C b 中恰好有一个为 true。
  • 调用 comparator(a, b) 不会修改 objobj 原型链上的任何对象。
  • a =C a(自反性)
  • 如果 a =C b,则 b =C a(对称性)
  • 如果 a =C bb =C c,则 a =C c(=C 的传递性)
  • 如果 a <C bb <C c,则 a <C c(<C 的传递性)
  • 如果 a >C bb >C c,则 a >C c(>C 的传递性)
Note

上述条件是确保 comparator 将集合 values 划分为等价类,并且这些等价类被全序排列的必要且充分条件。

23.1.3.30.2 CompareArrayElements ( x, y, comparator )

The abstract operation CompareArrayElements takes arguments x (一个 ECMAScript 语言值,), y (一个 ECMAScript 语言值,), and comparator (一个函数对象undefined,) and returns 要么是一个包含 Number 的正常完成,要么是一个 abrupt completion. It performs the following steps when called:

  1. 如果 xundefinedyundefined,返回 +0𝔽
  2. 如果 xundefined,返回 1𝔽
  3. 如果 yundefined,返回 -1𝔽
  4. 如果 comparator 不是 undefined,则
    1. result 为 ? ToNumber(? Call(comparator, undefined, « x, y »))。
    2. 如果 resultNaN,返回 +0𝔽
    3. 返回 result
  5. xString 为 ? ToString(x)。
  6. yString 为 ? ToString(y)。
  7. xSmaller 为 ! IsLessThan(xString, yString, true)。
  8. 如果 xSmallertrue,返回 -1𝔽
  9. ySmaller 为 ! IsLessThan(yString, xString, true)。
  10. 如果 ySmallertrue,返回 1𝔽
  11. 返回 +0𝔽

23.1.3.31 Array.prototype.splice ( start, deleteCount, ...items )

Note 1

此方法删除数组中从整数索引 start 开始的 deleteCount 个元素,并用 items 的元素替换它们。它返回一个包含被删除元素(如果有)的 Array。

此方法在被调用时执行以下步骤:

  1. obj 为 ? ToObject(this value)。
  2. len 为 ? LengthOfArrayLike(obj)。
  3. relativeStart 为 ? ToIntegerOrInfinity(start)。
  4. 如果 relativeStart = -∞,令 actualStart 为 0。
  5. 否则如果 relativeStart < 0,令 actualStartmax(len + relativeStart, 0)。
  6. 否则,令 actualStartmin(relativeStart, len)。
  7. itemCountitems 中元素的数量。
  8. 如果 start 不存在,则
    1. actualDeleteCount 为 0。
  9. 否则如果 deleteCount 不存在,则
    1. actualDeleteCountlen - actualStart
  10. 否则,
    1. dc 为 ? ToIntegerOrInfinity(deleteCount)。
    2. actualDeleteCount 为将 dc 夹在 0 和 len - actualStart 之间的结果。
  11. 如果 len + itemCount - actualDeleteCount > 253 - 1,抛出 TypeError 异常。
  12. deletedArray 为 ? ArraySpeciesCreate(obj, actualDeleteCount)。
  13. k 为 0。
  14. 重复,当 k < actualDeleteCount 时,
    1. from 为 ! ToString(𝔽(actualStart + k))。
    2. 如果 ? HasProperty(obj, from) 是 true,则
      1. fromValue 为 ? Get(obj, from)。
      2. 执行 ? CreateDataPropertyOrThrow(deletedArray, ! ToString(𝔽(k)), fromValue)。
    3. k 设置为 k + 1。
  15. 执行 ? Set(deletedArray, "length", 𝔽(actualDeleteCount), true)。
  16. 如果 itemCount < actualDeleteCount,则
    1. k 设置为 actualStart
    2. 重复,当 k < (len - actualDeleteCount) 时,
      1. from 为 ! ToString(𝔽(k + actualDeleteCount))。
      2. to 为 ! ToString(𝔽(k + itemCount))。
      3. 如果 ? HasProperty(obj, from) 是 true,则
        1. fromValue 为 ? Get(obj, from)。
        2. 执行 ? Set(obj, to, fromValue, true)。
      4. 否则,
        1. 执行 ? DeletePropertyOrThrow(obj, to)。
      5. k 设置为 k + 1。
    3. k 设置为 len
    4. 重复,当 k > (len - actualDeleteCount + itemCount) 时,
      1. 执行 ? DeletePropertyOrThrow(obj, ! ToString(𝔽(k - 1)))。
      2. k 设置为 k - 1。
  17. 否则如果 itemCount > actualDeleteCount,则
    1. k 设置为 (len - actualDeleteCount)。
    2. 重复,当 k > actualStart 时,
      1. from 为 ! ToString(𝔽(k + actualDeleteCount - 1))。
      2. to 为 ! ToString(𝔽(k + itemCount - 1))。
      3. 如果 ? HasProperty(obj, from) 是 true,则
        1. fromValue 为 ? Get(obj, from)。
        2. 执行 ? Set(obj, to, fromValue, true)。
      4. 否则,
        1. 执行 ? DeletePropertyOrThrow(obj, to)。
      5. k 设置为 k - 1。
  18. k 设置为 actualStart
  19. 对于 items 的每个元素 item,执行
    1. 执行 ? Set(obj, ! ToString(𝔽(k)), item, true)。
    2. k 设置为 k + 1。
  20. 执行 ? Set(obj, "length", 𝔽(len - actualDeleteCount + itemCount), true)。
  21. 返回 deletedArray
Note 2

步骤 1520 中对 "length" 属性的显式设置,旨在确保即使对象不是内置 Array,长度也是正确的。

Note 3

此方法有意设计为泛型;它不要求其 this 值是 Array。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.32 Array.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] )

包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按照 ECMA-402 规范中的规定实现此方法。如果 ECMAScript 实现不包含 ECMA-402 API,则使用以下对此方法的规范。

Note 1

ECMA-402 第一版未包含此方法的替代规范。

此方法的可选参数的含义在 ECMA-402 规范中定义;不包含 ECMA-402 支持的实现不得将这些参数位置用于任何其他用途。

此方法在被调用时执行以下步骤:

  1. array 为 ? ToObject(this value)。
  2. len 为 ? LengthOfArrayLike(array)。
  3. separator 为适合宿主环境当前区域设置的实现定义的列表分隔符 String 值(例如 ", ")。
  4. result 为空 String。
  5. k 为 0。
  6. 重复,当 k < len 时,
    1. 如果 k > 0,将 result 设置为 resultseparator 的字符串拼接。
    2. element 为 ? Get(array, ! ToString(𝔽(k)))。
    3. 如果 element 既不是 undefined 也不是 null,则
      1. elementStr 为 ? ToString(? Invoke(element, "toLocaleString")).
      2. result 设置为 resultelementStr 的字符串拼接。
    4. k 设置为 k + 1。
  7. 返回 result
Note 2

此方法使用数组元素的 toLocaleString 方法将其转换为 String,然后拼接这些 String,并用实现定义的区域设置敏感分隔符 String 的出现分隔。此方法类似于 toString,但它旨在产生与宿主环境当前区域设置的约定相对应的区域设置敏感结果。

Note 3

此方法有意设计为泛型;它不要求其 this 值是 Array。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.33 Array.prototype.toReversed ( )

此方法在被调用时执行以下步骤:

  1. obj 为 ? ToObject(this value)。
  2. len 为 ? LengthOfArrayLike(obj)。
  3. array 为 ? ArrayCreate(len)。
  4. k 为 0。
  5. 重复,当 k < len 时,
    1. from 为 ! ToString(𝔽(len - k - 1))。
    2. propertyKey 为 ! ToString(𝔽(k))。
    3. fromValue 为 ? Get(obj, from)。
    4. 执行 ! CreateDataPropertyOrThrow(array, propertyKey, fromValue)。
    5. k 设置为 k + 1。
  6. 返回 array

23.1.3.34 Array.prototype.toSorted ( comparator )

此方法在被调用时执行以下步骤:

  1. 如果 comparator 不是 undefinedIsCallable(comparator) 是 false,抛出 TypeError 异常。
  2. obj 为 ? ToObject(this value)。
  3. len 为 ? LengthOfArrayLike(obj)。
  4. array 为 ? ArrayCreate(len)。
  5. sortCompare 为一个新的 Abstract Closure,其参数为 (x, y),捕获 comparator,并在被调用时执行以下步骤:
    1. 返回 ? CompareArrayElements(x, y, comparator)。
  6. sortedList 为 ? SortIndexedProperties(obj, len, sortCompare, read-through-holes)。
  7. j 为 0。
  8. 重复,当 j < len 时,
    1. 执行 ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(j)), sortedList[j])。
    2. j 设置为 j + 1。
  9. 返回 array

23.1.3.35 Array.prototype.toSpliced ( start, skipCount, ...items )

此方法在被调用时执行以下步骤:

  1. obj 为 ? ToObject(this value)。
  2. len 为 ? LengthOfArrayLike(obj)。
  3. relativeStart 为 ? ToIntegerOrInfinity(start)。
  4. 如果 relativeStart = -∞,令 actualStart 为 0。
  5. 否则如果 relativeStart < 0,令 actualStartmax(len + relativeStart, 0)。
  6. 否则,令 actualStartmin(relativeStart, len)。
  7. insertCountitems 中元素的数量。
  8. 如果 start 不存在,则
    1. actualSkipCount 为 0。
  9. 否则如果 skipCount 不存在,则
    1. actualSkipCountlen - actualStart
  10. 否则,
    1. sc 为 ? ToIntegerOrInfinity(skipCount)。
    2. actualSkipCount 为将 sc 夹在 0 和 len - actualStart 之间的结果。
  11. newLenlen + insertCount - actualSkipCount
  12. 如果 newLen > 253 - 1,抛出 TypeError 异常。
  13. newArray 为 ? ArrayCreate(newLen)。
  14. writeIndex 为 0。
  15. readIndexactualStart + actualSkipCount
  16. 重复,当 writeIndex < actualStart 时,
    1. propertyKey 为 ! ToString(𝔽(writeIndex))。
    2. iValue 为 ? Get(obj, propertyKey)。
    3. 执行 ! CreateDataPropertyOrThrow(newArray, propertyKey, iValue)。
    4. writeIndex 设置为 writeIndex + 1。
  17. 对于 items 的每个元素 item,执行
    1. propertyKey 为 ! ToString(𝔽(writeIndex))。
    2. 执行 ! CreateDataPropertyOrThrow(newArray, propertyKey, item)。
    3. writeIndex 设置为 writeIndex + 1。
  18. 重复,当 writeIndex < newLen 时,
    1. propertyKey 为 ! ToString(𝔽(writeIndex))。
    2. from 为 ! ToString(𝔽(readIndex))。
    3. fromValue 为 ? Get(obj, from)。
    4. 执行 ! CreateDataPropertyOrThrow(newArray, propertyKey, fromValue)。
    5. writeIndex 设置为 writeIndex + 1。
    6. readIndex 设置为 readIndex + 1。
  19. 返回 newArray

23.1.3.36 Array.prototype.toString ( )

此方法在被调用时执行以下步骤:

  1. array 为 ? ToObject(this value)。
  2. func 为 ? Get(array, "join")。
  3. 如果 IsCallable(func) 是 false,将 func 设置为内在函数 %Object.prototype.toString%。
  4. 返回 ? Call(func, array)。
Note

此方法有意设计为泛型;它不要求其 this 值是 Array。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.37 Array.prototype.unshift ( ...items )

此方法将参数前置到数组开头,使它们在数组中的顺序与其在参数列表中出现的顺序相同。

它在被调用时执行以下步骤:

  1. obj 为 ? ToObject(this value)。
  2. len 为 ? LengthOfArrayLike(obj)。
  3. argCountitems 中元素的数量。
  4. 如果 argCount > 0,则
    1. 如果 len + argCount > 253 - 1,抛出 TypeError 异常。
    2. klen
    3. 重复,当 k > 0 时,
      1. from 为 ! ToString(𝔽(k - 1))。
      2. to 为 ! ToString(𝔽(k + argCount - 1))。
      3. fromPresent 为 ? HasProperty(obj, from)。
      4. 如果 fromPresenttrue,则
        1. fromValue 为 ? Get(obj, from)。
        2. 执行 ? Set(obj, to, fromValue, true)。
      5. 否则,
        1. 断言:fromPresentfalse
        2. 执行 ? DeletePropertyOrThrow(obj, to)。
      6. k 设置为 k - 1。
    4. j+0𝔽
    5. 对于 items 的每个元素 item,执行
      1. 执行 ? Set(obj, ! ToString(j), item, true)。
      2. j 设置为 j + 1𝔽
  5. 执行 ? Set(obj, "length", 𝔽(len + argCount), true)。
  6. 返回 𝔽(len + argCount)。

此方法的 "length" 属性为 1𝔽

Note

此方法有意设计为泛型;它不要求其 this 值是 Array。因此,它可以被转移到其他种类的对象上作为方法使用。

23.1.3.38 Array.prototype.values ( )

此方法在被调用时执行以下步骤:

  1. obj 为 ? ToObject(this value)。
  2. 返回 CreateArrayIterator(obj, value)。

23.1.3.39 Array.prototype.with ( index, value )

此方法在被调用时执行以下步骤:

  1. obj 为 ? ToObject(this value)。
  2. len 为 ? LengthOfArrayLike(obj)。
  3. relativeIndex 为 ? ToIntegerOrInfinity(index)。
  4. 如果 relativeIndex ≥ 0,令 actualIndexrelativeIndex
  5. 否则,令 actualIndexlen + relativeIndex
  6. 如果 actualIndexlenactualIndex < 0,抛出 RangeError 异常。
  7. array 为 ? ArrayCreate(len)。
  8. k 为 0。
  9. 重复,当 k < len 时,
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. 如果 k = actualIndex,令 fromValuevalue
    3. 否则,令 fromValue 为 ? Get(obj, propertyKey)。
    4. 执行 ! CreateDataPropertyOrThrow(array, propertyKey, fromValue)。
    5. k 设置为 k + 1。
  10. 返回 array

23.1.3.40 Array.prototype [ %Symbol.iterator% ] ( )

%Symbol.iterator% 属性的初始值为 %Array.prototype.values%,定义见 23.1.3.38

23.1.3.41 Array.prototype [ %Symbol.unscopables% ]

%Symbol.unscopables% 数据属性的初始值是由以下步骤创建的对象:

  1. unscopableListOrdinaryObjectCreate(null)。
  2. 执行 ! CreateDataPropertyOrThrow(unscopableList, "at", true)。
  3. 执行 ! CreateDataPropertyOrThrow(unscopableList, "copyWithin", true)。
  4. 执行 ! CreateDataPropertyOrThrow(unscopableList, "entries", true)。
  5. 执行 ! CreateDataPropertyOrThrow(unscopableList, "fill", true)。
  6. 执行 ! CreateDataPropertyOrThrow(unscopableList, "find", true)。
  7. 执行 ! CreateDataPropertyOrThrow(unscopableList, "findIndex", true)。
  8. 执行 ! CreateDataPropertyOrThrow(unscopableList, "findLast", true)。
  9. 执行 ! CreateDataPropertyOrThrow(unscopableList, "findLastIndex", true)。
  10. 执行 ! CreateDataPropertyOrThrow(unscopableList, "flat", true)。
  11. 执行 ! CreateDataPropertyOrThrow(unscopableList, "flatMap", true)。
  12. 执行 ! CreateDataPropertyOrThrow(unscopableList, "includes", true)。
  13. 执行 ! CreateDataPropertyOrThrow(unscopableList, "keys", true)。
  14. 执行 ! CreateDataPropertyOrThrow(unscopableList, "toReversed", true)。
  15. 执行 ! CreateDataPropertyOrThrow(unscopableList, "toSorted", true)。
  16. 执行 ! CreateDataPropertyOrThrow(unscopableList, "toSpliced", true)。
  17. 执行 ! CreateDataPropertyOrThrow(unscopableList, "values", true)。
  18. 返回 unscopableList

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

Note

此对象的自身属性名是在 ECMAScript 2015 规范之前未作为 Array.prototype 标准属性包含的属性名。为了保留现有代码的行为,这些名称会在 with 语句绑定目的下被忽略;现有代码可能在外层作用域中将其中一个名称用作绑定,而该绑定会被以 Array 作为绑定对象的 with 语句遮蔽。

"with" 未包含在 unscopableList 中的原因是它已经是一个 保留字

23.1.4 Array 实例的属性

Array 实例是 Array 异质对象,并具有为此类对象指定的内部方法。Array 实例从 Array 原型对象继承属性。

Array 实例有一个 "length" 属性,以及一组具有数组索引名称的可枚举属性。

23.1.4.1 length

Array 实例的 "length" 属性是一个数据属性,其值总是在数值上大于每个名称为数组索引的可配置自身属性的名称。

"length" 属性初始具有特性 { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }。

Note

减小 "length" 属性的值具有删除自身数组元素的副作用,这些数组元素的数组索引位于旧长度值和新长度值之间。然而,不可配置属性不能被删除。尝试将 Array 的 "length" 属性设置为一个在数值上小于或等于该数组现有不可配置 数组索引 属性的最大数值自身属性名的值,将导致长度被设置为比该不可配置数值自身属性名大一的数值。见 10.4.2.1

23.1.5 Array Iterator 对象

Array Iterator 是一个表示对某个特定 Array 实例对象进行特定迭代的对象。Array Iterator 对象没有具名构造器。相反,Array Iterator 对象是通过调用 Array 实例对象的某些方法创建的。

23.1.5.1 CreateArrayIterator ( array, kind )

The abstract operation CreateArrayIterator takes arguments array (一个 Object,) and kind (key+valuekeyvalue,) and returns 一个 Object. 它用于为返回此类迭代器的 Array 方法创建迭代器对象。 It performs the following steps when called:

  1. iteratorOrdinaryObjectCreate(%ArrayIteratorPrototype%, « [[IteratedArrayLike]], [[ArrayLikeNextIndex]], [[ArrayLikeIterationKind]] »)。
  2. iterator.[[IteratedArrayLike]] 设置为 array
  3. iterator.[[ArrayLikeNextIndex]] 设置为 0。
  4. iterator.[[ArrayLikeIterationKind]] 设置为 kind
  5. 返回 iterator

23.1.5.2 %ArrayIteratorPrototype% 对象

%ArrayIteratorPrototype% 对象:

23.1.5.2.1 %ArrayIteratorPrototype%.next ( )

  1. iteratorObjthis 值。
  2. 如果 iteratorObj 不是 Object,抛出 TypeError 异常。
  3. 如果 iteratorObj 不具有 Array Iterator 实例的所有内部槽(23.1.5.3),抛出 TypeError 异常。
  4. arrayiteratorObj.[[IteratedArrayLike]]
  5. 如果 arrayundefined,返回 CreateIteratorResultObject(undefined, true)。
  6. indexiteratorObj.[[ArrayLikeNextIndex]]
  7. kinditeratorObj.[[ArrayLikeIterationKind]]
  8. 如果 array 具有 [[TypedArrayName]] 内部槽,则
    1. taRecordMakeTypedArrayWithBufferWitnessRecord(array, seq-cst)。
    2. 如果 IsTypedArrayOutOfBounds(taRecord) 是 true,抛出 TypeError 异常。
    3. lenTypedArrayLength(taRecord)。
  9. 否则,
    1. len 为 ? LengthOfArrayLike(array)。
  10. 如果 indexlen,则
    1. iteratorObj.[[IteratedArrayLike]] 设置为 undefined
    2. 返回 CreateIteratorResultObject(undefined, true)。
  11. iteratorObj.[[ArrayLikeNextIndex]] 设置为 index + 1。
  12. indexNumber𝔽(index)。
  13. 如果 kindkey,则
    1. resultindexNumber
  14. 否则,
    1. elementKey 为 ! ToString(indexNumber)。
    2. elementValue 为 ? Get(array, elementKey)。
    3. 如果 kindvalue,则
      1. resultelementValue
    4. 否则,
      1. 断言:kindkey+value
      2. resultCreateArrayFromListindexNumber, elementValue »)。
  15. 返回 CreateIteratorResultObject(result, false)。

23.1.5.2.2 %ArrayIteratorPrototype% [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "Array Iterator"

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

23.1.5.3 Array Iterator 实例的属性

Array Iterator 实例是普通对象,从 %ArrayIteratorPrototype% 内在对象继承属性。Array Iterator 实例最初会创建为具有 Table 69 中列出的内部槽。

Table 69: Array Iterator 实例的内部槽
内部槽 类型 描述
[[IteratedArrayLike]] 一个 Object 或 undefined 正在被迭代的类数组对象
[[ArrayLikeNextIndex]] 一个非负整数 此迭代器要检查的下一个元素的整数索引。
[[ArrayLikeIterationKind]] key+valuekeyvalue 一个标识每次迭代的元素返回内容的值。

23.2 TypedArray 对象

TypedArray 表示底层二进制数据缓冲区(25.1)的类数组视图。TypedArray 元素类型TypedArray 实例的所有元素所具有的底层二进制标量数据类型。对于每种受支持的元素类型,都有一个不同的 TypedArray 构造器,列于 Table 70Table 70 中的每个构造器都有一个对应的不同原型对象。

Table 70: TypedArray 构造器
构造器名称和内在对象 元素类型 元素大小 转换操作 描述
Int8Array
%Int8Array%
int8 1 ToInt8 8 位二进制补码有符号整数
Uint8Array
%Uint8Array%
uint8 1 ToUint8 8 位无符号整数
Uint8ClampedArray
%Uint8ClampedArray%
uint8clamped 1 ToUint8Clamp 8 位无符号整数(夹紧转换)
Int16Array
%Int16Array%
int16 2 ToInt16 16 位二进制补码有符号整数
Uint16Array
%Uint16Array%
uint16 2 ToUint16 16 位无符号整数
Int32Array
%Int32Array%
int32 4 ToInt32 32 位二进制补码有符号整数
Uint32Array
%Uint32Array%
uint32 4 ToUint32 32 位无符号整数
BigInt64Array
%BigInt64Array%
bigint64 8 ToBigInt64 64 位二进制补码有符号整数
BigUint64Array
%BigUint64Array%
biguint64 8 ToBigUint64 64 位无符号整数
Float16Array
%Float16Array%
float16 2 16 位 IEEE 浮点数
Float32Array
%Float32Array%
float32 4 32 位 IEEE 浮点数
Float64Array
%Float64Array%
float64 8 64 位 IEEE 浮点数

在下面的定义中,对 TypedArray 的引用应替换为上表中适当的构造器名称。

23.2.1 %TypedArray% 内在对象

%TypedArray% 内在对象:

  • 是一个构造器函数对象,所有 TypedArray 构造器对象都继承自它。
  • 连同其对应的原型对象,提供由所有 TypedArray 构造器及其实例继承的公共属性。
  • 没有全局名称,也不作为全局对象的属性出现。
  • 充当各种 TypedArray 构造器的抽象超类。
  • 被调用时会抛出错误,因为它是一个抽象类构造器TypedArray 构造器不会对它执行 super 调用。

23.2.1.1 %TypedArray% ( )

此函数在被调用时执行以下步骤:

  1. 抛出 TypeError 异常。

此函数的 "length" 属性为 +0𝔽

23.2.2 %TypedArray% 内在对象的属性

%TypedArray% 内在对象:

  • 有一个 [[Prototype]] 内部槽,其值为 %Function.prototype%
  • 有一个值为 "TypedArray""name" 属性。
  • 具有以下属性:

23.2.2.1 %TypedArray%.from ( source [ , mapper [ , thisArg ] ] )

此方法在被调用时执行以下步骤:

  1. constructorthis 值。
  2. 如果 IsConstructor(constructor) 是 false,抛出 TypeError 异常。
  3. 如果 mapperundefined,则
    1. mappingfalse
  4. 否则,
    1. 如果 IsCallable(mapper) 是 false,抛出 TypeError 异常。
    2. mappingtrue
  5. usingIterator 为 ? GetMethod(source, %Symbol.iterator%)。
  6. 如果 usingIterator 不是 undefined,则
    1. values 为 ? IteratorToList(? GetIteratorFromMethod(source, usingIterator))。
    2. lenvalues 中元素的数量。
    3. targetObj 为 ? TypedArrayCreateFromConstructor(constructor, « 𝔽(len) »)。
    4. k 为 0。
    5. 重复,当 k < len 时,
      1. propertyKey 为 ! ToString(𝔽(k))。
      2. kValuevalues 的第一个元素。
      3. values 中移除第一个元素。
      4. 如果 mappingtrue,则
        1. mappedValue 为 ? Call(mapper, thisArg, « kValue, 𝔽(k) »)。
      5. 否则,
        1. mappedValuekValue
      6. 执行 ? Set(targetObj, propertyKey, mappedValue, true)。
      7. k 设置为 k + 1。
    6. 断言:values 现在是一个空 List
    7. 返回 targetObj
  7. 注:source 不是可迭代对象,因此假定它已经是一个类数组对象
  8. arrayLike 为 ! ToObject(source)。
  9. len 为 ? LengthOfArrayLike(arrayLike)。
  10. targetObj 为 ? TypedArrayCreateFromConstructor(constructor, « 𝔽(len) »)。
  11. k 为 0。
  12. 重复,当 k < len 时,
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. kValue 为 ? Get(arrayLike, propertyKey)。
    3. 如果 mappingtrue,则
      1. mappedValue 为 ? Call(mapper, thisArg, « kValue, 𝔽(k) »)。
    4. 否则,
      1. mappedValuekValue
    5. 执行 ? Set(targetObj, propertyKey, mappedValue, true)。
    6. k 设置为 k + 1。
  13. 返回 targetObj

23.2.2.2 %TypedArray%.of ( ...items )

此方法在被调用时执行以下步骤:

  1. lenitems 中元素的数量。
  2. constructorthis 值。
  3. 如果 IsConstructor(constructor) 是 false,抛出 TypeError 异常。
  4. newObj 为 ? TypedArrayCreateFromConstructor(constructor, « 𝔽(len) »)。
  5. k 为 0。
  6. 重复,当 k < len 时,
    1. kValueitems[k]。
    2. propertyKey 为 ! ToString(𝔽(k))。
    3. 执行 ? Set(newObj, propertyKey, kValue, true)。
    4. k 设置为 k + 1。
  7. 返回 newObj

23.2.2.3 %TypedArray%.prototype

%TypedArray%.prototype 的初始值是 %TypedArray% 原型对象

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

23.2.2.4 get %TypedArray% [ %Symbol.species% ]

%TypedArray%[%Symbol.species%] 是一个访问器属性,其 set 访问器函数为 undefined。它的 get 访问器函数在被调用时执行以下步骤:

  1. 返回 this 值。

此函数的 "name" 属性的值为 "get [Symbol.species]"

Note

%TypedArray.prototype% 方法通常使用其 this 值的构造器来创建派生对象。然而,子类构造器可以通过重新定义其 %Symbol.species% 属性来覆写该默认行为。

23.2.3 %TypedArray% 原型对象的属性

%TypedArray% 原型对象

  • 有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%
  • %TypedArray.prototype%
  • 是一个普通对象
  • 没有 [[ViewedArrayBuffer]] 或任何其他特定于 TypedArray 实例对象的内部槽。

23.2.3.1 %TypedArray%.prototype.at ( index )

  1. objthis 值。
  2. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. relativeIndex 为 ? ToIntegerOrInfinity(index)。
  5. 如果 relativeIndex ≥ 0,则
    1. krelativeIndex
  6. 否则,
    1. klen + relativeIndex
  7. 如果 k < 0 或 klen,返回 undefined
  8. 返回 ! Get(obj, ! ToString(𝔽(k)))。

23.2.3.2 get %TypedArray%.prototype.buffer

%TypedArray%.prototype.buffer 是一个访问器属性,其 set 访问器函数为 undefined。它的 get 访问器函数在被调用时执行以下步骤:

  1. objthis 值。
  2. 执行 ? RequireInternalSlot(obj, [[TypedArrayName]])。
  3. 断言:obj[[ViewedArrayBuffer]] 内部槽。
  4. bufferobj.[[ViewedArrayBuffer]]
  5. 返回 buffer

23.2.3.3 get %TypedArray%.prototype.byteLength

%TypedArray%.prototype.byteLength 是一个访问器属性,其 set 访问器函数为 undefined。它的 get 访问器函数在被调用时执行以下步骤:

  1. objthis 值。
  2. 执行 ? RequireInternalSlot(obj, [[TypedArrayName]])。
  3. 断言:obj[[ViewedArrayBuffer]] 内部槽。
  4. taRecordMakeTypedArrayWithBufferWitnessRecord(obj, seq-cst)。
  5. 如果 IsTypedArrayOutOfBounds(taRecord) 是 true,返回 +0𝔽
  6. sizeTypedArrayByteLength(taRecord)。
  7. 返回 𝔽(size)。

23.2.3.4 get %TypedArray%.prototype.byteOffset

%TypedArray%.prototype.byteOffset 是一个访问器属性,其 set 访问器函数为 undefined。它的 get 访问器函数在被调用时执行以下步骤:

  1. objthis 值。
  2. 执行 ? RequireInternalSlot(obj, [[TypedArrayName]])。
  3. 断言:obj[[ViewedArrayBuffer]] 内部槽。
  4. taRecordMakeTypedArrayWithBufferWitnessRecord(obj, seq-cst)。
  5. 如果 IsTypedArrayOutOfBounds(taRecord) 是 true,返回 +0𝔽
  6. offsetobj.[[ByteOffset]]
  7. 返回 𝔽(offset)。

23.2.3.5 %TypedArray%.prototype.constructor

%TypedArray%.prototype.constructor 的初始值是 %TypedArray%

23.2.3.6 %TypedArray%.prototype.copyWithin ( target, start [ , end ] )

此方法的参数解释和使用方式与 23.1.3.4 中定义的 Array.prototype.copyWithin 相同。

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. relativeTarget 为 ? ToIntegerOrInfinity(target)。
  5. 如果 relativeTarget = -∞,令 targetIndex 为 0。
  6. 否则如果 relativeTarget < 0,令 targetIndexmax(len + relativeTarget, 0)。
  7. 否则,令 targetIndexmin(relativeTarget, len)。
  8. relativeStart 为 ? ToIntegerOrInfinity(start)。
  9. 如果 relativeStart = -∞,令 startIndex 为 0。
  10. 否则如果 relativeStart < 0,令 startIndexmax(len + relativeStart, 0)。
  11. 否则,令 startIndexmin(relativeStart, len)。
  12. 如果 endundefined,令 relativeEndlen;否则令 relativeEnd 为 ? ToIntegerOrInfinity(end)。
  13. 如果 relativeEnd = -∞,令 endIndex 为 0。
  14. 否则如果 relativeEnd < 0,令 endIndexmax(len + relativeEnd, 0)。
  15. 否则,令 endIndexmin(relativeEnd, len)。
  16. countmin(endIndex - startIndex, len - targetIndex)。
  17. 如果 count > 0,则
    1. 注:复制必须以保留源数据位级编码的方式执行。
    2. bufferobj.[[ViewedArrayBuffer]]
    3. taRecord 设置为 MakeTypedArrayWithBufferWitnessRecord(obj, seq-cst)。
    4. 如果 IsTypedArrayOutOfBounds(taRecord) 是 true,抛出 TypeError 异常。
    5. len 设置为 TypedArrayLength(taRecord)。
    6. 注:上述步骤的副作用可能减小了 obj 的大小,在这种情况下复制应按仍适用的最长前缀继续进行。
    7. count 设置为 min(count, len - startIndex, len - targetIndex)。
    8. elementSizeTypedArrayElementSize(obj)。
    9. byteOffsetobj.[[ByteOffset]]
    10. toByteIndex 为 (targetIndex × elementSize) + byteOffset
    11. fromByteIndex 为 (startIndex × elementSize) + byteOffset
    12. countBytescount × elementSize
    13. 如果 fromByteIndex < toByteIndextoByteIndex < fromByteIndex + countBytes,则
      1. direction 为 -1。
      2. fromByteIndex 设置为 fromByteIndex + countBytes - 1。
      3. toByteIndex 设置为 toByteIndex + countBytes - 1。
    14. 否则,
      1. direction 为 1。
    15. 重复,当 countBytes > 0 时,
      1. valueGetValueFromBuffer(buffer, fromByteIndex, uint8, true, unordered)。
      2. 执行 SetValueInBuffer(buffer, toByteIndex, uint8, value, true, unordered)。
      3. fromByteIndex 设置为 fromByteIndex + direction
      4. toByteIndex 设置为 toByteIndex + direction
      5. countBytes 设置为 countBytes - 1。
  18. 返回 obj

23.2.3.7 %TypedArray%.prototype.entries ( )

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. 执行 ? ValidateTypedArray(obj, seq-cst)。
  3. 返回 CreateArrayIterator(obj, key+value)。

23.2.3.8 %TypedArray%.prototype.every ( callback [ , thisArg ] )

此方法的参数解释和使用方式与 23.1.3.6 中定义的 Array.prototype.every 相同。

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. 如果 IsCallable(callback) 是 false,抛出 TypeError 异常。
  5. k 为 0。
  6. 重复,当 k < len 时,
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. kValue 为 ! Get(obj, propertyKey)。
    3. testResultToBoolean(? Call(callback, thisArg, « kValue, 𝔽(k), obj »))。
    4. 如果 testResultfalse,返回 false
    5. k 设置为 k + 1。
  7. 返回 true

此方法不是泛型的。this 值必须是一个具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.9 %TypedArray%.prototype.fill ( value [ , start [ , end ] ] )

此方法的参数解释和使用方式与 23.1.3.7 中定义的 Array.prototype.fill 相同。

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. 如果 obj.[[ContentType]]bigint,将 value 设置为 ? ToBigInt(value)。
  5. 否则,将 value 设置为 ? ToNumber(value)。
  6. relativeStart 为 ? ToIntegerOrInfinity(start)。
  7. 如果 relativeStart = -∞,令 startIndex 为 0。
  8. 否则如果 relativeStart < 0,令 startIndexmax(len + relativeStart, 0)。
  9. 否则,令 startIndexmin(relativeStart, len)。
  10. 如果 endundefined,令 relativeEndlen;否则令 relativeEnd 为 ? ToIntegerOrInfinity(end)。
  11. 如果 relativeEnd = -∞,令 endIndex 为 0。
  12. 否则如果 relativeEnd < 0,令 endIndexmax(len + relativeEnd, 0)。
  13. 否则,令 endIndexmin(relativeEnd, len)。
  14. taRecord 设置为 MakeTypedArrayWithBufferWitnessRecord(obj, seq-cst)。
  15. 如果 IsTypedArrayOutOfBounds(taRecord) 是 true,抛出 TypeError 异常。
  16. len 设置为 TypedArrayLength(taRecord)。
  17. endIndex 设置为 min(endIndex, len)。
  18. kstartIndex
  19. 重复,当 k < endIndex 时,
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. 执行 ! Set(obj, propertyKey, value, true)。
    3. k 设置为 k + 1。
  20. 返回 obj

23.2.3.10 %TypedArray%.prototype.filter ( callback [ , thisArg ] )

此方法的参数解释和使用方式与 23.1.3.8 中定义的 Array.prototype.filter 相同。

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. 如果 IsCallable(callback) 是 false,抛出 TypeError 异常。
  5. kept 为一个新的空 List
  6. captured 为 0。
  7. k 为 0。
  8. 重复,当 k < len 时,
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. kValue 为 ! Get(obj, propertyKey)。
    3. selectedToBoolean(? Call(callback, thisArg, « kValue, 𝔽(k), obj »))。
    4. 如果 selectedtrue,则
      1. kValue 追加到 kept
      2. captured 设置为 captured + 1。
    5. k 设置为 k + 1。
  9. resultTypedArray 为 ? TypedArraySpeciesCreate(obj, « 𝔽(captured) »)。
  10. n 为 0。
  11. 对于 kept 的每个元素 e,执行
    1. 执行 ! Set(resultTypedArray, ! ToString(𝔽(n)), e, true)。
    2. n 设置为 n + 1。
  12. 返回 resultTypedArray

此方法不是泛型的。this 值必须是一个具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.11 %TypedArray%.prototype.find ( predicate [ , thisArg ] )

此方法的参数解释和使用方式与 23.1.3.9 中定义的 Array.prototype.find 相同。

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. findRec 为 ? FindViaPredicate(obj, len, ascending, predicate, thisArg)。
  5. 返回 findRec.[[Value]]

此方法不是泛型的。this 值必须是一个具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.12 %TypedArray%.prototype.findIndex ( predicate [ , thisArg ] )

此方法的参数解释和使用方式与 23.1.3.10 中定义的 Array.prototype.findIndex 相同。

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. findRec 为 ? FindViaPredicate(obj, len, ascending, predicate, thisArg)。
  5. 返回 findRec.[[Index]]

此方法不是泛型的。this 值必须是一个具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.13 %TypedArray%.prototype.findLast ( predicate [ , thisArg ] )

此方法的参数解释和使用方式与 23.1.3.11 中定义的 Array.prototype.findLast 相同。

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. findRec 为 ? FindViaPredicate(obj, len, descending, predicate, thisArg)。
  5. 返回 findRec.[[Value]]

此方法不是泛型的。this 值必须是一个具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.14 %TypedArray%.prototype.findLastIndex ( predicate [ , thisArg ] )

此方法的参数解释和使用方式与 23.1.3.12 中定义的 Array.prototype.findLastIndex 相同。

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. findRec 为 ? FindViaPredicate(obj, len, descending, predicate, thisArg)。
  5. 返回 findRec.[[Index]]

此方法不是泛型的。this 值必须是一个具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.15 %TypedArray%.prototype.forEach ( callback [ , thisArg ] )

此方法的参数解释和使用方式与 23.1.3.15 中定义的 Array.prototype.forEach 相同。

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. 如果 IsCallable(callback) 是 false,抛出 TypeError 异常。
  5. k 为 0。
  6. 重复,当 k < len 时,
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. kValue 为 ! Get(obj, propertyKey)。
    3. 执行 ? Call(callback, thisArg, « kValue, 𝔽(k), obj »)。
    4. k 设置为 k + 1。
  7. 返回 undefined

此方法不是泛型的。this 值必须是一个具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.16 %TypedArray%.prototype.includes ( searchElement [ , fromIndex ] )

此方法的参数解释和使用方式与 23.1.3.16 中定义的 Array.prototype.includes 相同。

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. 如果 len = 0,返回 false
  5. n 为 ? ToIntegerOrInfinity(fromIndex)。
  6. 断言:如果 fromIndexundefined,则 n 为 0。
  7. 如果 n = +∞,返回 false
  8. 如果 n = -∞,将 n 设置为 0。
  9. 如果 n ≥ 0,则
    1. kn
  10. 否则,
    1. klen + n
    2. 如果 k < 0,将 k 设置为 0。
  11. 重复,当 k < len 时,
    1. elementK 为 ! Get(obj, ! ToString(𝔽(k)))。
    2. 如果 SameValueZero(searchElement, elementK) 是 true,返回 true
    3. k 设置为 k + 1。
  12. 返回 false

此方法不是泛型的。this 值必须是一个具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.17 %TypedArray%.prototype.indexOf ( searchElement [ , fromIndex ] )

此方法的参数解释和使用方式与 23.1.3.17 中定义的 Array.prototype.indexOf 相同。

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. 如果 len = 0,返回 -1𝔽
  5. n 为 ? ToIntegerOrInfinity(fromIndex)。
  6. 断言:如果 fromIndexundefined,则 n 为 0。
  7. 如果 n = +∞,返回 -1𝔽
  8. 如果 n = -∞,将 n 设置为 0。
  9. 如果 n ≥ 0,则
    1. kn
  10. 否则,
    1. klen + n
    2. 如果 k < 0,将 k 设置为 0。
  11. 重复,当 k < len 时,
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. kPresent 为 ! HasProperty(obj, propertyKey)。
    3. 如果 kPresenttrue,则
      1. elementK 为 ! Get(obj, propertyKey)。
      2. 如果 IsStrictlyEqual(searchElement, elementK) 是 true,返回 𝔽(k)。
    4. k 设置为 k + 1。
  12. 返回 -1𝔽

此方法不是泛型的。this 值必须是一个具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.18 %TypedArray%.prototype.join ( separator )

此方法的参数解释和使用方式与 23.1.3.18 中定义的 Array.prototype.join 相同。

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. 如果 separatorundefined,令 sep","
  5. 否则,令 sep 为 ? ToString(separator)。
  6. result 为空 String。
  7. k 为 0。
  8. 重复,当 k < len 时,
    1. 如果 k > 0,将 result 设置为 resultsep 的字符串拼接。
    2. element 为 ! Get(obj, ! ToString(𝔽(k)))。
    3. 如果 element 不是 undefined,则
      1. elementStr 为 ! ToString(element)。
      2. result 设置为 resultelementStr 的字符串拼接。
    4. k 设置为 k + 1。
  9. 返回 result

此方法不是泛型的。this 值必须是一个具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.19 %TypedArray%.prototype.keys ( )

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. 执行 ? ValidateTypedArray(obj, seq-cst)。
  3. 返回 CreateArrayIterator(obj, key)。

23.2.3.20 %TypedArray%.prototype.lastIndexOf ( searchElement [ , fromIndex ] )

此方法的参数解释和使用方式与 23.1.3.20 中定义的 Array.prototype.lastIndexOf 相同。

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. 如果 len = 0,返回 -1𝔽
  5. 如果 fromIndex 存在,令 n 为 ? ToIntegerOrInfinity(fromIndex);否则令 nlen - 1。
  6. 如果 n = -∞,返回 -1𝔽
  7. 如果 n ≥ 0,则
    1. kmin(n, len - 1)。
  8. 否则,
    1. klen + n
  9. 重复,当 k ≥ 0 时,
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. kPresent 为 ! HasProperty(obj, propertyKey)。
    3. 如果 kPresenttrue,则
      1. elementK 为 ! Get(obj, propertyKey)。
      2. 如果 IsStrictlyEqual(searchElement, elementK) 是 true,返回 𝔽(k)。
    4. k 设置为 k - 1。
  10. 返回 -1𝔽

此方法不是泛型的。this 值必须是一个具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.21 get %TypedArray%.prototype.length

%TypedArray%.prototype.length 是一个访问器属性,其 set 访问器函数为 undefined。它的 get 访问器函数在被调用时执行以下步骤:

  1. objthis 值。
  2. 执行 ? RequireInternalSlot(obj, [[TypedArrayName]])。
  3. 断言:obj[[ViewedArrayBuffer]][[ArrayLength]] 内部槽。
  4. taRecordMakeTypedArrayWithBufferWitnessRecord(obj, seq-cst)。
  5. 如果 IsTypedArrayOutOfBounds(taRecord) 是 true,返回 +0𝔽
  6. lengthTypedArrayLength(taRecord)。
  7. 返回 𝔽(length)。

此函数不是泛型的。this 值必须是一个具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.22 %TypedArray%.prototype.map ( callback [ , thisArg ] )

此方法的参数解释和使用方式与 23.1.3.21 中定义的 Array.prototype.map 相同。

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. 如果 IsCallable(callback) 是 false,抛出 TypeError 异常。
  5. resultTypedArray 为 ? TypedArraySpeciesCreate(obj, « 𝔽(len) »)。
  6. k 为 0。
  7. 重复,当 k < len 时,
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. kValue 为 ! Get(obj, propertyKey)。
    3. mappedValue 为 ? Call(callback, thisArg, « kValue, 𝔽(k), obj »)。
    4. 执行 ? Set(resultTypedArray, propertyKey, mappedValue, true)。
    5. k 设置为 k + 1。
  8. 返回 resultTypedArray

此方法不是泛型的。this 值必须是一个具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.23 %TypedArray%.prototype.reduce ( callback [ , initialValue ] )

此方法的参数解释和使用方式与 23.1.3.24 中定义的 Array.prototype.reduce 相同。

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. 如果 IsCallable(callback) 是 false,抛出 TypeError 异常。
  5. 如果 len = 0 且 initialValue 不存在,抛出 TypeError 异常。
  6. k 为 0。
  7. accumulatorundefined
  8. 如果 initialValue 存在,则
    1. accumulator 设置为 initialValue
  9. 否则,
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. accumulator 设置为 ! Get(obj, propertyKey)。
    3. k 设置为 k + 1。
  10. 重复,当 k < len 时,
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. kValue 为 ! Get(obj, propertyKey)。
    3. accumulator 设置为 ? Call(callback, undefined, « accumulator, kValue, 𝔽(k), obj »)。
    4. k 设置为 k + 1。
  11. 返回 accumulator

此方法不是泛型的。this 值必须是一个具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.24 %TypedArray%.prototype.reduceRight ( callback [ , initialValue ] )

此方法的参数解释和使用方式与 23.1.3.25 中定义的 Array.prototype.reduceRight 相同。

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. 如果 IsCallable(callback) 是 false,抛出 TypeError 异常。
  5. 如果 len = 0 且 initialValue 不存在,抛出 TypeError 异常。
  6. klen - 1。
  7. accumulatorundefined
  8. 如果 initialValue 存在,则
    1. accumulator 设置为 initialValue
  9. 否则,
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. accumulator 设置为 ! Get(obj, propertyKey)。
    3. k 设置为 k - 1。
  10. 重复,当 k ≥ 0 时,
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. kValue 为 ! Get(obj, propertyKey)。
    3. accumulator 设置为 ? Call(callback, undefined, « accumulator, kValue, 𝔽(k), obj »)。
    4. k 设置为 k - 1。
  11. 返回 accumulator

此方法不是泛型的。this 值必须是一个具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.25 %TypedArray%.prototype.reverse ( )

此方法的参数解释和使用方式与 23.1.3.26 中定义的 Array.prototype.reverse 相同。

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. middlefloor(len / 2)。
  5. lower 为 0。
  6. 重复,当 lowermiddle 时,
    1. upperlen - lower - 1。
    2. upperP 为 ! ToString(𝔽(upper))。
    3. lowerP 为 ! ToString(𝔽(lower))。
    4. lowerValue 为 ! Get(obj, lowerP)。
    5. upperValue 为 ! Get(obj, upperP)。
    6. 执行 ! Set(obj, lowerP, upperValue, true)。
    7. 执行 ! Set(obj, upperP, lowerValue, true)。
    8. lower 设置为 lower + 1。
  7. 返回 obj

此方法不是泛型的。this 值必须是一个具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.26 %TypedArray%.prototype.set ( source [ , offset ] )

此方法在此 TypedArray 中设置多个值,从 source 读取值。细节取决于 source 的类型。可选的 offset 值指示在此 TypedArray 中写入值的第一个元素索引。如果省略,则假定为 0。

它在被调用时执行以下步骤:

  1. targetthis 值。
  2. 执行 ? RequireInternalSlot(target, [[TypedArrayName]])。
  3. 断言:target[[ViewedArrayBuffer]] 内部槽。
  4. targetOffset 为 ? ToIntegerOrInfinity(offset)。
  5. 如果 targetOffset < 0,抛出 RangeError 异常。
  6. 如果 source 是一个具有 [[TypedArrayName]] 内部槽的 Object,则
    1. 执行 ? SetTypedArrayFromTypedArray(target, targetOffset, source)。
  7. 否则,
    1. 执行 ? SetTypedArrayFromArrayLike(target, targetOffset, source)。
  8. 返回 undefined

此方法不是泛型的。this 值必须是一个具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.26.1 SetTypedArrayFromArrayLike ( target, targetOffset, source )

The abstract operation SetTypedArrayFromArrayLike takes arguments target (一个 TypedArray,), targetOffset (一个非负整数或 +∞,), and source (一个 ECMAScript 语言值,但不是 TypedArray,) and returns 要么是一个包含 unused正常完成,要么是一个抛出完成. 它从 source 读取值,从索引 targetOffset 开始在 target 中设置多个值。 It performs the following steps when called:

  1. targetRecordMakeTypedArrayWithBufferWitnessRecord(target, seq-cst)。
  2. 如果 IsTypedArrayOutOfBounds(targetRecord) 是 true,抛出 TypeError 异常。
  3. targetLengthTypedArrayLength(targetRecord)。
  4. src 为 ? ToObject(source)。
  5. srcLength 为 ? LengthOfArrayLike(src)。
  6. 如果 targetOffset = +∞,抛出 RangeError 异常。
  7. 如果 srcLength + targetOffset > targetLength,抛出 RangeError 异常。
  8. k 为 0。
  9. 重复,当 k < srcLength 时,
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. value 为 ? Get(src, propertyKey)。
    3. targetIndex𝔽(targetOffset + k)。
    4. 执行 ? TypedArraySetElement(target, targetIndex, value)。
    5. k 设置为 k + 1。
  10. 返回 unused

23.2.3.26.2 SetTypedArrayFromTypedArray ( target, targetOffset, source )

The abstract operation SetTypedArrayFromTypedArray takes arguments target (一个 TypedArray,), targetOffset (一个非负整数或 +∞,), and source (一个 TypedArray,) and returns 要么是一个包含 unused正常完成,要么是一个抛出完成. 它从 source 读取值,从索引 targetOffset 开始在 target 中设置多个值。 It performs the following steps when called:

  1. targetBuffertarget.[[ViewedArrayBuffer]]
  2. targetRecordMakeTypedArrayWithBufferWitnessRecord(target, seq-cst)。
  3. 如果 IsTypedArrayOutOfBounds(targetRecord) 是 true,抛出 TypeError 异常。
  4. targetLengthTypedArrayLength(targetRecord)。
  5. srcBuffersource.[[ViewedArrayBuffer]]
  6. srcRecordMakeTypedArrayWithBufferWitnessRecord(source, seq-cst)。
  7. 如果 IsTypedArrayOutOfBounds(srcRecord) 是 true,抛出 TypeError 异常。
  8. srcLengthTypedArrayLength(srcRecord)。
  9. targetTypeTypedArrayElementType(target)。
  10. targetElementSizeTypedArrayElementSize(target)。
  11. targetByteOffsettarget.[[ByteOffset]]
  12. srcTypeTypedArrayElementType(source)。
  13. srcElementSizeTypedArrayElementSize(source)。
  14. srcByteOffsetsource.[[ByteOffset]]
  15. 如果 targetOffset = +∞,抛出 RangeError 异常。
  16. 如果 srcLength + targetOffset > targetLength,抛出 RangeError 异常。
  17. 如果 target.[[ContentType]] 不是 source.[[ContentType]],抛出 TypeError 异常。
  18. 如果 IsSharedArrayBuffer(srcBuffer) 是 trueIsSharedArrayBuffer(targetBuffer) 是 true,并且 srcBuffer.[[ArrayBufferData]]targetBuffer.[[ArrayBufferData]],令 sameSharedArrayBuffertrue;否则令 sameSharedArrayBufferfalse
  19. 如果 SameValue(srcBuffer, targetBuffer) 是 truesameSharedArrayBuffertrue,则
    1. srcByteLengthTypedArrayByteLength(srcRecord)。
    2. srcBuffer 设置为 ? CloneArrayBuffer(srcBuffer, srcByteOffset, srcByteLength)。
    3. srcByteIndex 为 0。
  20. 否则,
    1. srcByteIndexsrcByteOffset
  21. targetByteIndex 为 (targetOffset × targetElementSize) + targetByteOffset
  22. limittargetByteIndex + (targetElementSize × srcLength)。
  23. 如果 srcTypetargetType,则
    1. 注:传输必须以保留源数据位级编码的方式执行。
    2. 重复,当 targetByteIndex < limit 时,
      1. valueGetValueFromBuffer(srcBuffer, srcByteIndex, uint8, true, unordered)。
      2. 执行 SetValueInBuffer(targetBuffer, targetByteIndex, uint8, value, true, unordered)。
      3. srcByteIndex 设置为 srcByteIndex + 1。
      4. targetByteIndex 设置为 targetByteIndex + 1。
  24. 否则,
    1. 重复,当 targetByteIndex < limit 时,
      1. valueGetValueFromBuffer(srcBuffer, srcByteIndex, srcType, true, unordered)。
      2. 执行 SetValueInBuffer(targetBuffer, targetByteIndex, targetType, value, true, unordered)。
      3. srcByteIndex 设置为 srcByteIndex + srcElementSize
      4. targetByteIndex 设置为 targetByteIndex + targetElementSize
  25. 返回 unused

23.2.3.27 %TypedArray%.prototype.slice ( start, end )

此方法的参数解释和使用方式与 23.1.3.28 中定义的 Array.prototype.slice 相同。

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. srcArrayLengthTypedArrayLength(taRecord)。
  4. relativeStart 为 ? ToIntegerOrInfinity(start)。
  5. 如果 relativeStart = -∞,令 startIndex 为 0。
  6. 否则如果 relativeStart < 0,令 startIndexmax(srcArrayLength + relativeStart, 0)。
  7. 否则,令 startIndexmin(relativeStart, srcArrayLength)。
  8. 如果 endundefined,令 relativeEndsrcArrayLength;否则令 relativeEnd 为 ? ToIntegerOrInfinity(end)。
  9. 如果 relativeEnd = -∞,令 endIndex 为 0。
  10. 否则如果 relativeEnd < 0,令 endIndexmax(srcArrayLength + relativeEnd, 0)。
  11. 否则,令 endIndexmin(relativeEnd, srcArrayLength)。
  12. countBytesmax(endIndex - startIndex, 0)。
  13. resultArray 为 ? TypedArraySpeciesCreate(obj, « 𝔽(countBytes) »)。
  14. 如果 countBytes > 0,则
    1. taRecord 设置为 MakeTypedArrayWithBufferWitnessRecord(obj, seq-cst)。
    2. 如果 IsTypedArrayOutOfBounds(taRecord) 是 true,抛出 TypeError 异常。
    3. endIndex 设置为 min(endIndex, TypedArrayLength(taRecord))。
    4. countBytes 设置为 max(endIndex - startIndex, 0)。
    5. srcTypeTypedArrayElementType(obj)。
    6. targetTypeTypedArrayElementType(resultArray)。
    7. 如果 srcTypetargetType,则
      1. 注:传输必须以保留源数据位级编码的方式执行。
      2. srcBufferobj.[[ViewedArrayBuffer]]
      3. targetBufferresultArray.[[ViewedArrayBuffer]]
      4. elementSizeTypedArrayElementSize(obj)。
      5. srcByteOffsetobj.[[ByteOffset]]
      6. srcByteIndex 为 (startIndex × elementSize) + srcByteOffset
      7. targetByteIndexresultArray.[[ByteOffset]]
      8. endByteIndextargetByteIndex + (countBytes × elementSize)。
      9. 重复,当 targetByteIndex < endByteIndex 时,
        1. valueGetValueFromBuffer(srcBuffer, srcByteIndex, uint8, true, unordered)。
        2. 执行 SetValueInBuffer(targetBuffer, targetByteIndex, uint8, value, true, unordered)。
        3. srcByteIndex 设置为 srcByteIndex + 1。
        4. targetByteIndex 设置为 targetByteIndex + 1。
    8. 否则,
      1. n 为 0。
      2. kstartIndex
      3. 重复,当 k < endIndex 时,
        1. propertyKey 为 ! ToString(𝔽(k))。
        2. kValue 为 ! Get(obj, propertyKey)。
        3. 执行 ! Set(resultArray, ! ToString(𝔽(n)), kValue, true)。
        4. k 设置为 k + 1。
        5. n 设置为 n + 1。
  15. 返回 resultArray

此方法不是泛型的。this 值必须是一个具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.28 %TypedArray%.prototype.some ( callback [ , thisArg ] )

此方法的参数解释和使用方式与 23.1.3.29 中定义的 Array.prototype.some 相同。

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. 如果 IsCallable(callback) 是 false,抛出 TypeError 异常。
  5. k 为 0。
  6. 重复,当 k < len 时,
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. kValue 为 ! Get(obj, propertyKey)。
    3. testResultToBoolean(? Call(callback, thisArg, « kValue, 𝔽(k), obj »))。
    4. 如果 testResulttrue,返回 true
    5. k 设置为 k + 1。
  7. 返回 false

此方法不是泛型的。this 值必须是一个具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.29 %TypedArray%.prototype.sort ( comparator )

这是一个不同的方法,除下文所述外,它实现与 23.1.3.30 中定义的 Array.prototype.sort 相同的要求。此方法的实现可以基于以下事实进行优化:this 值是一个具有固定长度且其整数索引属性不稀疏的对象。

此方法不是泛型的。this 值必须是一个具有 [[TypedArrayName]] 内部槽的对象。

它在被调用时执行以下步骤:

  1. 如果 comparator 不是 undefinedIsCallable(comparator) 是 false,抛出 TypeError 异常。
  2. objthis 值。
  3. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  4. lenTypedArrayLength(taRecord)。
  5. 注:下面的闭包执行数值比较,而不是 23.1.3.30 中使用的字符串比较。
  6. sortCompare 为一个新的 Abstract Closure,其参数为 (x, y),捕获 comparator,并在被调用时执行以下步骤:
    1. 返回 ? CompareTypedArrayElements(x, y, comparator)。
  7. sortedList 为 ? SortIndexedProperties(obj, len, sortCompare, read-through-holes)。
  8. j 为 0。
  9. 重复,当 j < len 时,
    1. 执行 ! Set(obj, ! ToString(𝔽(j)), sortedList[j], true)。
    2. j 设置为 j + 1。
  10. 返回 obj
Note

因为 NaN 总是比较为大于任何其他值(见 CompareTypedArrayElements),所以当未提供 comparator 时,NaN 属性值总是排序到结果末尾。

23.2.3.30 %TypedArray%.prototype.subarray ( start, end )

此方法返回一个新的 TypedArray,其元素类型是此 TypedArray 的元素类型,其 ArrayBuffer 是此 TypedArray 的 ArrayBuffer,并引用从 start(包含)到 end(不包含)区间内的元素。如果 startend 为负,则它引用的是从数组末尾开始的索引,而不是从开头开始。

它在被调用时执行以下步骤:

  1. objthis 值。
  2. 执行 ? RequireInternalSlot(obj, [[TypedArrayName]])。
  3. 断言:obj[[ViewedArrayBuffer]] 内部槽。
  4. bufferobj.[[ViewedArrayBuffer]]
  5. srcRecordMakeTypedArrayWithBufferWitnessRecord(obj, seq-cst)。
  6. 如果 IsTypedArrayOutOfBounds(srcRecord) 是 true,则
    1. srcLength 为 0。
  7. 否则,
    1. srcLengthTypedArrayLength(srcRecord)。
  8. relativeStart 为 ? ToIntegerOrInfinity(start)。
  9. 如果 relativeStart = -∞,令 startIndex 为 0。
  10. 否则如果 relativeStart < 0,令 startIndexmax(srcLength + relativeStart, 0)。
  11. 否则,令 startIndexmin(relativeStart, srcLength)。
  12. elementSizeTypedArrayElementSize(obj)。
  13. srcByteOffsetobj.[[ByteOffset]]
  14. beginByteOffsetsrcByteOffset + (startIndex × elementSize)。
  15. 如果 obj.[[ArrayLength]]autoendundefined,则
    1. argumentsList 为 « buffer, 𝔽(beginByteOffset) »。
  16. 否则,
    1. 如果 endundefined,令 relativeEndsrcLength;否则令 relativeEnd 为 ? ToIntegerOrInfinity(end)。
    2. 如果 relativeEnd = -∞,令 endIndex 为 0。
    3. 否则如果 relativeEnd < 0,令 endIndexmax(srcLength + relativeEnd, 0)。
    4. 否则,令 endIndexmin(relativeEnd, srcLength)。
    5. newLengthmax(endIndex - startIndex, 0)。
    6. argumentsList 为 « buffer, 𝔽(beginByteOffset), 𝔽(newLength) »。
  17. 返回 ? TypedArraySpeciesCreate(obj, argumentsList)。

此方法不是泛型的。this 值必须是一个具有 [[TypedArrayName]] 内部槽的对象。

23.2.3.31 %TypedArray%.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] )

这是一个不同的方法,它实现与 23.1.3.32 中定义的 Array.prototype.toLocaleString 相同的算法,不同之处在于调用 TypedArrayLength 代替执行对 "length"[[Get]]。在底层缓冲区不可调整大小时,可以基于以下事实优化该算法的实现:this 值具有固定长度且其整数索引属性不稀疏。然而,此类优化不得在算法的指定行为中引入任何可观察变化。

此方法不是泛型的。在求值该算法之前,会以 this 值和 seq-cst 作为参数调用 ValidateTypedArray。如果其结果是一个 abrupt completion,则抛出该异常,而不是求值该算法。

Note

如果 ECMAScript 实现包含 ECMA-402 国际化 API,则此方法基于 ECMA-402 规范中的 Array.prototype.toLocaleString 算法。

23.2.3.32 %TypedArray%.prototype.toReversed ( )

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. resultArray 为 ? TypedArrayCreateSameType(obj, len)。
  5. k 为 0。
  6. 重复,当 k < len 时,
    1. from 为 ! ToString(𝔽(len - k - 1))。
    2. propertyKey 为 ! ToString(𝔽(k))。
    3. fromValue 为 ! Get(obj, from)。
    4. 执行 ! Set(resultArray, propertyKey, fromValue, true)。
    5. k 设置为 k + 1。
  7. 返回 resultArray

23.2.3.33 %TypedArray%.prototype.toSorted ( comparator )

此方法在被调用时执行以下步骤:

  1. 如果 comparator 不是 undefinedIsCallable(comparator) 是 false,抛出 TypeError 异常。
  2. objthis 值。
  3. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  4. lenTypedArrayLength(taRecord)。
  5. resultArray 为 ? TypedArrayCreateSameType(obj, len)。
  6. 注:下面的闭包执行数值比较,而不是 23.1.3.34 中使用的字符串比较。
  7. sortCompare 为一个新的 Abstract Closure,其参数为 (x, y),捕获 comparator,并在被调用时执行以下步骤:
    1. 返回 ? CompareTypedArrayElements(x, y, comparator)。
  8. sortedList 为 ? SortIndexedProperties(obj, len, sortCompare, read-through-holes)。
  9. j 为 0。
  10. 重复,当 j < len 时,
    1. 执行 ! Set(resultArray, ! ToString(𝔽(j)), sortedList[j], true)。
    2. j 设置为 j + 1。
  11. 返回 resultArray

23.2.3.34 %TypedArray%.prototype.toString ( )

"toString" 属性的初始值为 %Array.prototype.toString%,定义见 23.1.3.36

23.2.3.35 %TypedArray%.prototype.values ( )

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. 执行 ? ValidateTypedArray(obj, seq-cst)。
  3. 返回 CreateArrayIterator(obj, value)。

23.2.3.36 %TypedArray%.prototype.with ( index, value )

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. relativeIndex 为 ? ToIntegerOrInfinity(index)。
  5. 如果 relativeIndex ≥ 0,令 actualIndexrelativeIndex
  6. 否则,令 actualIndexlen + relativeIndex
  7. 如果 obj.[[ContentType]]bigint,令 numericValue 为 ? ToBigInt(value)。
  8. 否则,令 numericValue 为 ? ToNumber(value)。
  9. 如果 IsValidIntegerIndex(obj, 𝔽(actualIndex)) 是 false,抛出 RangeError 异常。
  10. resultArray 为 ? TypedArrayCreateSameType(obj, len)。
  11. k 为 0。
  12. 重复,当 k < len 时,
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. 如果 k = actualIndex,令 fromValuenumericValue
    3. 否则,令 fromValue 为 ! Get(obj, propertyKey)。
    4. 执行 ! Set(resultArray, propertyKey, fromValue, true)。
    5. k 设置为 k + 1。
  13. 返回 resultArray

23.2.3.37 %TypedArray%.prototype [ %Symbol.iterator% ] ( )

%Symbol.iterator% 属性的初始值为 %TypedArray.prototype.values%,定义见 23.2.3.35

23.2.3.38 get %TypedArray%.prototype [ %Symbol.toStringTag% ]

%TypedArray%.prototype[%Symbol.toStringTag%] 是一个访问器属性,其 set 访问器函数为 undefined。它的 get 访问器函数在被调用时执行以下步骤:

  1. objthis 值。
  2. 如果 obj 不是 Object,返回 undefined
  3. 如果 obj 没有 [[TypedArrayName]] 内部槽,返回 undefined
  4. nameobj.[[TypedArrayName]]
  5. 断言:name 是一个 String。
  6. 返回 name

此属性具有特性 { [[Enumerable]]: false, [[Configurable]]: true }。

此函数的 "name" 属性的初始值为 "get [Symbol.toStringTag]"

23.2.4 TypedArray 对象的抽象操作

23.2.4.1 TypedArrayCreateFromConstructor ( constructor, argumentList )

The abstract operation TypedArrayCreateFromConstructor takes arguments constructor (一个构造器,) and argumentList (一个 ECMAScript 语言值 List,) and returns 要么是一个包含 TypedArray正常完成,要么是一个抛出完成. 它用于指定使用构造器函数创建一个新的 TypedArray。 It performs the following steps when called:

  1. newTypedArray 为 ? Construct(constructor, argumentList)。
  2. taRecord 为 ? ValidateTypedArray(newTypedArray, seq-cst)。
  3. 断言:newTypedArray 具有 TypedArray 实例的属性 中提到的所有内部槽。
  4. 如果 argumentList 中的元素数量为 1,且 argumentList[0] 是 Number,则
    1. 如果 IsTypedArrayOutOfBounds(taRecord) 是 true,抛出 TypeError 异常。
    2. lengthTypedArrayLength(taRecord)。
    3. 如果 length < (argumentList[0]),抛出 TypeError 异常。
  5. 返回 newTypedArray

23.2.4.2 TypedArrayCreateSameType ( exemplar, length )

The abstract operation TypedArrayCreateSameType takes arguments exemplar (一个 TypedArray,) and length (一个非负整数,) and returns 要么是一个包含 TypedArray正常完成,要么是一个抛出完成. 它用于指定使用从 exemplar 派生的构造器函数创建一个新的 TypedArray。与可以通过使用 %Symbol.species% 构造自定义 TypedArray 子类的 TypedArraySpeciesCreate 不同,此操作始终使用内置 TypedArray 构造器之一。 It performs the following steps when called:

  1. constructorTable 70 中与构造器名称 exemplar.[[TypedArrayName]] 关联的内在对象。
  2. result 为 ? TypedArrayCreateFromConstructor(constructor, « 𝔽(length) »)。
  3. 断言:result 具有 [[TypedArrayName]][[ContentType]] 内部槽。
  4. 断言:result.[[ContentType]]exemplar.[[ContentType]]
  5. 返回 result

23.2.4.3 TypedArraySpeciesCreate ( exemplar, argumentList )

The abstract operation TypedArraySpeciesCreate takes arguments exemplar (一个 TypedArray,) and argumentList (一个 ECMAScript 语言值 List,) and returns 要么是一个包含 TypedArray正常完成,要么是一个抛出完成. 它用于指定使用从 exemplar 派生的构造器函数创建一个新的 TypedArray。与可以通过使用 %Symbol.species% 创建非 Array 对象的 ArraySpeciesCreate 不同,此操作强制要求该构造器函数创建一个真正的 TypedArray。 It performs the following steps when called:

  1. defaultConstructorTable 70 中与构造器名称 exemplar.[[TypedArrayName]] 关联的内在对象。
  2. constructor 为 ? SpeciesConstructor(exemplar, defaultConstructor)。
  3. result 为 ? TypedArrayCreateFromConstructor(constructor, argumentList)。
  4. 如果 result.[[ContentType]] 不是 exemplar.[[ContentType]],抛出 TypeError 异常。
  5. 返回 result

23.2.4.4 ValidateTypedArray ( obj, order )

The abstract operation ValidateTypedArray takes arguments obj (一个 ECMAScript 语言值,) and order (seq-cstunordered,) and returns 要么是一个包含 TypedArray With Buffer Witness Record正常完成,要么是一个抛出完成. It performs the following steps when called:

  1. 执行 ? RequireInternalSlot(obj, [[TypedArrayName]])。
  2. 断言:obj[[ViewedArrayBuffer]] 内部槽。
  3. taRecordMakeTypedArrayWithBufferWitnessRecord(obj, order)。
  4. 如果 IsTypedArrayOutOfBounds(taRecord) 是 true,抛出 TypeError 异常。
  5. 返回 taRecord

23.2.4.5 TypedArrayElementSize ( obj )

The abstract operation TypedArrayElementSize takes argument obj (一个 TypedArray,) and returns 一个非负整数. It performs the following steps when called:

  1. 返回 Table 70 中为 obj.[[TypedArrayName]] 指定的 Element Size 值。

23.2.4.6 TypedArrayElementType ( obj )

The abstract operation TypedArrayElementType takes argument obj (一个 TypedArray,) and returns 一个 TypedArray 元素类型. It performs the following steps when called:

  1. 返回 Table 70 中为 obj.[[TypedArrayName]] 指定的 Element Type 值。

23.2.4.7 CompareTypedArrayElements ( x, y, comparator )

The abstract operation CompareTypedArrayElements takes arguments x (一个 Number 或 BigInt,), y (一个 Number 或 BigInt,), and comparator (一个函数对象undefined,) and returns 要么是一个包含 Number 的正常完成,要么是一个 abrupt completion. It performs the following steps when called:

  1. 断言:x 是 Number 且 y 是 Number,或者 x 是 BigInt 且 y 是 BigInt。
  2. 如果 comparator 不是 undefined,则
    1. result 为 ? ToNumber(? Call(comparator, undefined, « x, y »))。
    2. 如果 resultNaN,返回 +0𝔽
    3. 返回 result
  3. 如果 xNaNyNaN,返回 +0𝔽
  4. 如果 xNaN,返回 1𝔽
  5. 如果 yNaN,返回 -1𝔽
  6. 如果 x < y,返回 -1𝔽
  7. 如果 x > y,返回 1𝔽
  8. 如果 x-0𝔽y+0𝔽,返回 -1𝔽
  9. 如果 x+0𝔽y-0𝔽,返回 1𝔽
  10. 返回 +0𝔽
Note
此操作执行数值比较,而不是 23.1.3.30.2 中使用的字符串比较。

23.2.5 TypedArray 构造器

每个 TypedArray 构造器

  • 是一个内在对象,具有下文所述的结构,除非另有说明,否则仅在 Table 70 中使用的构造器名称替代 TypedArray 这一点上有所不同。
  • 是一个其行为会根据参数数量和类型而不同的函数。TypedArray 调用的实际行为取决于传递给它的参数数量和种类。
  • 不意图作为函数调用,并且以这种方式调用时会抛出异常。
  • 可用作类定义中 extends 子句的值。意图继承指定 TypedArray 行为的子类构造器必须包含对 TypedArray 构造器super 调用,以创建并初始化带有支持 %TypedArray%.prototype 内置方法所需内部状态的子类实例。

23.2.5.1 TypedArray ( ...args )

每个 TypedArray 构造器在被调用时执行以下步骤:

  1. 如果 NewTarget 是 undefined,抛出 TypeError 异常。
  2. constructorNameTable 70 中为此 TypedArray 构造器指定的 Constructor Name 值的 String 值。
  3. proto"%TypedArray.prototype%"
  4. numberOfArgsargs 中元素的数量。
  5. 如果 numberOfArgs = 0,返回 ? AllocateTypedArray(constructorName, NewTarget, proto, 0)。
  6. firstArgumentargs[0]。
  7. 如果 firstArgument 是 Object,则
    1. obj 为 ? AllocateTypedArray(constructorName, NewTarget, proto)。
    2. 如果 firstArgument[[TypedArrayName]] 内部槽,则
      1. 执行 ? InitializeTypedArrayFromTypedArray(obj, firstArgument)。
    3. 否则如果 firstArgument[[ArrayBufferData]] 内部槽,则
      1. 如果 numberOfArgs > 1,令 byteOffsetargs[1];否则令 byteOffsetundefined
      2. 如果 numberOfArgs > 2,令 lengthargs[2];否则令 lengthundefined
      3. 执行 ? InitializeTypedArrayFromArrayBuffer(obj, firstArgument, byteOffset, length)。
    4. 否则,
      1. 断言:firstArgument 是 Object,并且 firstArgument 既没有 [[TypedArrayName]] 内部槽,也没有 [[ArrayBufferData]] 内部槽。
      2. usingIterator 为 ? GetMethod(firstArgument, %Symbol.iterator%)。
      3. 如果 usingIterator 不是 undefined,则
        1. values 为 ? IteratorToList(? GetIteratorFromMethod(firstArgument, usingIterator))。
        2. 执行 ? InitializeTypedArrayFromList(obj, values)。
      4. 否则,
        1. 注:firstArgument 不是可迭代对象,因此假定它已经是一个类数组对象
        2. 执行 ? InitializeTypedArrayFromArrayLike(obj, firstArgument)。
    5. 返回 obj
  8. 断言:firstArgument 不是 Object。
  9. elementLength 为 ? ToIndex(firstArgument)。
  10. 返回 ? AllocateTypedArray(constructorName, NewTarget, proto, elementLength)。

23.2.5.1.1 AllocateTypedArray ( constructorName, newTarget, defaultProto [ , length ] )

The abstract operation AllocateTypedArray takes arguments constructorName (一个 String,它是 Table 70 中的 TypedArray 构造器名称,), newTarget (一个构造器,), and defaultProto (一个 String,) and optional argument length (一个非负整数,) and returns 要么是一个包含 TypedArray正常完成,要么是一个抛出完成. 它用于验证并创建 TypedArray 构造器的实例。如果传递了 length 参数,还会分配该长度的 ArrayBuffer 并与新的 TypedArray 实例关联。AllocateTypedArray 提供由 TypedArray 使用的公共语义。 It performs the following steps when called:

  1. proto 为 ? GetPrototypeFromConstructor(newTarget, defaultProto)。
  2. objTypedArrayCreate(proto)。
  3. 断言:obj.[[ViewedArrayBuffer]]undefined
  4. obj.[[TypedArrayName]] 设置为 constructorName
  5. 如果 constructorName"BigInt64Array""BigUint64Array",将 obj.[[ContentType]] 设置为 bigint
  6. 否则,将 obj.[[ContentType]] 设置为 number
  7. 如果 length 不存在,则
    1. obj.[[ByteLength]] 设置为 0。
    2. obj.[[ByteOffset]] 设置为 0。
    3. obj.[[ArrayLength]] 设置为 0。
  8. 否则,
    1. 执行 ? AllocateTypedArrayBuffer(obj, length)。
  9. 返回 obj

23.2.5.1.2 InitializeTypedArrayFromTypedArray ( obj, srcArray )

The abstract operation InitializeTypedArrayFromTypedArray takes arguments obj (一个 TypedArray,) and srcArray (一个 TypedArray,) and returns 要么是一个包含 unused正常完成,要么是一个抛出完成. It performs the following steps when called:

  1. srcDatasrcArray.[[ViewedArrayBuffer]]
  2. elementTypeTypedArrayElementType(obj)。
  3. elementSizeTypedArrayElementSize(obj)。
  4. srcTypeTypedArrayElementType(srcArray)。
  5. srcElementSizeTypedArrayElementSize(srcArray)。
  6. srcByteOffsetsrcArray.[[ByteOffset]]
  7. srcRecordMakeTypedArrayWithBufferWitnessRecord(srcArray, seq-cst)。
  8. 如果 IsTypedArrayOutOfBounds(srcRecord) 是 true,抛出 TypeError 异常。
  9. elementLengthTypedArrayLength(srcRecord)。
  10. byteLengthelementSize × elementLength
  11. 如果 elementTypesrcType,则
    1. data 为 ? CloneArrayBuffer(srcData, srcByteOffset, byteLength)。
  12. 否则,
    1. data 为 ? AllocateArrayBuffer(%ArrayBuffer%, byteLength)。
    2. 如果 srcArray.[[ContentType]] 不是 obj.[[ContentType]],抛出 TypeError 异常。
    3. srcByteIndexsrcByteOffset
    4. targetByteIndex 为 0。
    5. countelementLength
    6. 重复,当 count > 0 时,
      1. valueGetValueFromBuffer(srcData, srcByteIndex, srcType, true, unordered)。
      2. 执行 SetValueInBuffer(data, targetByteIndex, elementType, value, true, unordered)。
      3. srcByteIndex 设置为 srcByteIndex + srcElementSize
      4. targetByteIndex 设置为 targetByteIndex + elementSize
      5. count 设置为 count - 1。
  13. obj.[[ViewedArrayBuffer]] 设置为 data
  14. obj.[[ByteLength]] 设置为 byteLength
  15. obj.[[ByteOffset]] 设置为 0。
  16. obj.[[ArrayLength]] 设置为 elementLength
  17. 返回 unused

23.2.5.1.3 InitializeTypedArrayFromArrayBuffer ( obj, buffer, byteOffset, length )

The abstract operation InitializeTypedArrayFromArrayBuffer takes arguments obj (一个 TypedArray,), buffer (一个 ArrayBuffer 或 SharedArrayBuffer,), byteOffset (一个 ECMAScript 语言值,), and length (一个 ECMAScript 语言值,) and returns 要么是一个包含 unused正常完成,要么是一个抛出完成. It performs the following steps when called:

  1. elementSizeTypedArrayElementSize(obj)。
  2. offset 为 ? ToIndex(byteOffset)。
  3. 如果 offset modulo elementSize ≠ 0,抛出 RangeError 异常。
  4. bufferIsFixedLengthIsFixedLengthArrayBuffer(buffer)。
  5. 如果 length 不是 undefined,则
    1. newLength 为 ? ToIndex(length)。
  6. 如果 IsDetachedBuffer(buffer) 是 true,抛出 TypeError 异常。
  7. bufferByteLengthArrayBufferByteLength(buffer, seq-cst)。
  8. 如果 lengthundefinedbufferIsFixedLengthfalse,则
    1. 如果 offset > bufferByteLength,抛出 RangeError 异常。
    2. obj.[[ByteLength]] 设置为 auto
    3. obj.[[ArrayLength]] 设置为 auto
  9. 否则,
    1. 如果 lengthundefined,则
      1. 如果 bufferByteLength modulo elementSize ≠ 0,抛出 RangeError 异常。
      2. newByteLengthbufferByteLength - offset
      3. 如果 newByteLength < 0,抛出 RangeError 异常。
    2. 否则,
      1. newByteLengthnewLength × elementSize
      2. 如果 offset + newByteLength > bufferByteLength,抛出 RangeError 异常。
    3. obj.[[ByteLength]] 设置为 newByteLength
    4. obj.[[ArrayLength]] 设置为 newByteLength / elementSize
  10. obj.[[ViewedArrayBuffer]] 设置为 buffer
  11. obj.[[ByteOffset]] 设置为 offset
  12. 返回 unused

23.2.5.1.4 InitializeTypedArrayFromList ( obj, values )

The abstract operation InitializeTypedArrayFromList takes arguments obj (一个 TypedArray,) and values (一个 ECMAScript 语言值 List,) and returns 要么是一个包含 unused正常完成,要么是一个抛出完成. It performs the following steps when called:

  1. lenvalues 中元素的数量。
  2. 执行 ? AllocateTypedArrayBuffer(obj, len)。
  3. k 为 0。
  4. 重复,当 k < len 时,
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. kValuevalues 的第一个元素。
    3. values 中移除第一个元素。
    4. 执行 ? Set(obj, propertyKey, kValue, true)。
    5. k 设置为 k + 1。
  5. 断言:values 现在是一个空 List
  6. 返回 unused

23.2.5.1.5 InitializeTypedArrayFromArrayLike ( obj, arrayLike )

The abstract operation InitializeTypedArrayFromArrayLike takes arguments obj (一个 TypedArray,) and arrayLike (一个 Object,但不是 TypedArray 或 ArrayBuffer,) and returns 要么是一个包含 unused正常完成,要么是一个抛出完成. It performs the following steps when called:

  1. len 为 ? LengthOfArrayLike(arrayLike)。
  2. 执行 ? AllocateTypedArrayBuffer(obj, len)。
  3. k 为 0。
  4. 重复,当 k < len 时,
    1. propertyKey 为 ! ToString(𝔽(k))。
    2. kValue 为 ? Get(arrayLike, propertyKey)。
    3. 执行 ? Set(obj, propertyKey, kValue, true)。
    4. k 设置为 k + 1。
  5. 返回 unused

23.2.5.1.6 AllocateTypedArrayBuffer ( obj, length )

The abstract operation AllocateTypedArrayBuffer takes arguments obj (一个 TypedArray,) and length (一个非负整数,) and returns 要么是一个包含 unused正常完成,要么是一个抛出完成. 它分配一个 ArrayBuffer 并将其与 obj 关联。 It performs the following steps when called:

  1. 断言:obj.[[ViewedArrayBuffer]]undefined
  2. elementSizeTypedArrayElementSize(obj)。
  3. byteLengthelementSize × length
  4. data 为 ? AllocateArrayBuffer(%ArrayBuffer%, byteLength)。
  5. obj.[[ViewedArrayBuffer]] 设置为 data
  6. obj.[[ByteLength]] 设置为 byteLength
  7. obj.[[ByteOffset]] 设置为 0。
  8. obj.[[ArrayLength]] 设置为 length
  9. 返回 unused

23.2.6 TypedArray 构造器的属性

每个 TypedArray 构造器

  • 有一个 [[Prototype]] 内部槽,其值为 %TypedArray%
  • 有一个值为 3𝔽"length" 属性。
  • 有一个 "name" 属性,其值是在 Table 70 中为它指定的构造器名称的 String 值。
  • 具有以下属性:

23.2.6.1 TypedArray.BYTES_PER_ELEMENT

TypedArray.BYTES_PER_ELEMENT 的值是 Table 70 中为 TypedArray 指定的 Element Size 值。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

23.2.6.2 TypedArray.prototype

TypedArray.prototype 的初始值是对应的 TypedArray 原型内在对象(23.2.7)。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

23.2.7 TypedArray 原型对象的属性

每个 TypedArray 原型对象:

  • 有一个 [[Prototype]] 内部槽,其值为 %TypedArray.prototype%
  • 是一个普通对象
  • 没有 [[ViewedArrayBuffer]] 或任何其他特定于 TypedArray 实例对象的内部槽。

23.2.7.1 TypedArray.prototype.BYTES_PER_ELEMENT

TypedArray.prototype.BYTES_PER_ELEMENT 的值是 Table 70 中为 TypedArray 指定的 Element Size 值。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

23.2.7.2 TypedArray.prototype.constructor

给定 TypedArray 构造器的原型的 "constructor" 属性的初始值是该构造器自身。

23.2.8 TypedArray 实例的属性

TypedArray 实例是 TypedArray。每个 TypedArray 实例从对应的 TypedArray 原型对象继承属性。每个 TypedArray 实例都有以下内部槽:[[ViewedArrayBuffer]][[TypedArrayName]][[ContentType]][[ByteLength]][[ByteOffset]][[ArrayLength]]

23.3 Uint8Array 对象

Uint8Array 是上文所述的一种特定 TypedArray。此外,Uint8Array 构造器23.3.1)和 Uint8Array 原型对象(23.3.2)上还有附加方法。

23.3.1 Uint8Array 构造器的附加属性

23.3.1.1 Uint8Array.fromBase64 ( string [ , options ] )

  1. 如果 string 不是 String,抛出 TypeError 异常。
  2. opts 为 ? GetOptionsObject(options)。
  3. alphabet 为 ? Get(opts, "alphabet")。
  4. 如果 alphabetundefined,将 alphabet 设置为 "base64"
  5. 如果 alphabet 既不是 "base64" 也不是 "base64url",抛出 TypeError 异常。
  6. lastChunkHandling 为 ? Get(opts, "lastChunkHandling")。
  7. 如果 lastChunkHandlingundefined,将 lastChunkHandling 设置为 "loose"
  8. 如果 lastChunkHandling 不是 "loose""strict""stop-before-partial" 之一,抛出 TypeError 异常。
  9. resultFromBase64(string, alphabet, lastChunkHandling)。
  10. 如果 result.[[Error]] 不是 none,则
    1. 抛出 result.[[Error]]
  11. resultLengthresult.[[Bytes]] 中元素的数量。
  12. ta 为 ? AllocateTypedArray("Uint8Array", %Uint8Array%, "%Uint8Array.prototype%", resultLength)。
  13. 断言:ta.[[ViewedArrayBuffer]].[[ArrayBufferByteLength]]result.[[Bytes]] 中元素的数量。
  14. ta.[[ViewedArrayBuffer]].[[ArrayBufferData]] 每个索引处的值设置为 result.[[Bytes]] 中对应索引处的值。
  15. 返回 ta

23.3.1.2 Uint8Array.fromHex ( string )

  1. 如果 string 不是 String,抛出 TypeError 异常。
  2. resultFromHex(string)。
  3. 如果 result.[[Error]] 不是 none,则
    1. 抛出 result.[[Error]]
  4. resultLengthresult.[[Bytes]] 中元素的数量。
  5. ta 为 ? AllocateTypedArray("Uint8Array", %Uint8Array%, "%Uint8Array.prototype%", resultLength)。
  6. 断言:ta.[[ViewedArrayBuffer]].[[ArrayBufferByteLength]]result.[[Bytes]] 中元素的数量。
  7. ta.[[ViewedArrayBuffer]].[[ArrayBufferData]] 每个索引处的值设置为 result.[[Bytes]] 中对应索引处的值。
  8. 返回 ta

23.3.2 Uint8Array 原型对象的附加属性

23.3.2.1 Uint8Array.prototype.setFromBase64 ( string [ , options ] )

  1. intothis 值。
  2. 执行 ? ValidateUint8Array(into)。
  3. 如果 string 不是 String,抛出 TypeError 异常。
  4. opts 为 ? GetOptionsObject(options)。
  5. alphabet 为 ? Get(opts, "alphabet")。
  6. 如果 alphabetundefined,将 alphabet 设置为 "base64"
  7. 如果 alphabet 既不是 "base64" 也不是 "base64url",抛出 TypeError 异常。
  8. lastChunkHandling 为 ? Get(opts, "lastChunkHandling")。
  9. 如果 lastChunkHandlingundefined,将 lastChunkHandling 设置为 "loose"
  10. 如果 lastChunkHandling 不是 "loose""strict""stop-before-partial" 之一,抛出 TypeError 异常。
  11. taRecordMakeTypedArrayWithBufferWitnessRecord(into, seq-cst)。
  12. 如果 IsTypedArrayOutOfBounds(taRecord) 是 true,抛出 TypeError 异常。
  13. byteLengthTypedArrayLength(taRecord)。
  14. resultFromBase64(string, alphabet, lastChunkHandling, byteLength)。
  15. bytesresult.[[Bytes]]
  16. writtenbytes 中元素的数量。
  17. 注:FromBase64 不调用任何用户代码,因此支持 into 的 ArrayBuffer 不可能已经被分离或缩小。
  18. 断言:writtenbyteLength
  19. 执行 SetUint8ArrayBytes(into, bytes)。
  20. 如果 result.[[Error]] 不是 none,则
    1. 抛出 result.[[Error]]
  21. resultObjectOrdinaryObjectCreate(%Object.prototype%)。
  22. 执行 ! CreateDataPropertyOrThrow(resultObject, "read", 𝔽(result.[[Read]]))。
  23. 执行 ! CreateDataPropertyOrThrow(resultObject, "written", 𝔽(written))。
  24. 返回 resultObject

23.3.2.2 Uint8Array.prototype.setFromHex ( string )

  1. intothis 值。
  2. 执行 ? ValidateUint8Array(into)。
  3. 如果 string 不是 String,抛出 TypeError 异常。
  4. taRecordMakeTypedArrayWithBufferWitnessRecord(into, seq-cst)。
  5. 如果 IsTypedArrayOutOfBounds(taRecord) 是 true,抛出 TypeError 异常。
  6. byteLengthTypedArrayLength(taRecord)。
  7. resultFromHex(string, byteLength)。
  8. bytesresult.[[Bytes]]
  9. writtenbytes 中元素的数量。
  10. 注:FromHex 不调用任何用户代码,因此支持 into 的 ArrayBuffer 不可能已经被分离或缩小。
  11. 断言:writtenbyteLength
  12. 执行 SetUint8ArrayBytes(into, bytes)。
  13. 如果 result.[[Error]] 不是 none,则
    1. 抛出 result.[[Error]]
  14. resultObjectOrdinaryObjectCreate(%Object.prototype%)。
  15. 执行 ! CreateDataPropertyOrThrow(resultObject, "read", 𝔽(result.[[Read]]))。
  16. 执行 ! CreateDataPropertyOrThrow(resultObject, "written", 𝔽(written))。
  17. 返回 resultObject

23.3.2.3 Uint8Array.prototype.toBase64 ( [ options ] )

  1. objthis 值。
  2. 执行 ? ValidateUint8Array(obj)。
  3. opts 为 ? GetOptionsObject(options)。
  4. alphabet 为 ? Get(opts, "alphabet")。
  5. 如果 alphabetundefined,将 alphabet 设置为 "base64"
  6. 如果 alphabet 既不是 "base64" 也不是 "base64url",抛出 TypeError 异常。
  7. omitPaddingToBoolean(? Get(opts, "omitPadding")).
  8. toEncode 为 ? GetUint8ArrayBytes(obj)。
  9. 如果 alphabet"base64",则
    1. outAscii 为按照 RFC 4648 第 4 节中指定的 base64 编码对 toEncode 编码所得的码点序列。当且仅当 omitPaddingfalse 时包含填充。
  10. 否则,
    1. 断言:alphabet"base64url"
    2. outAscii 为按照 RFC 4648 第 5 节中指定的 base64url 编码对 toEncode 编码所得的码点序列。当且仅当 omitPaddingfalse 时包含填充。
  11. 返回 CodePointsToString(outAscii)。

23.3.2.4 Uint8Array.prototype.toHex ( )

  1. objthis 值。
  2. 执行 ? ValidateUint8Array(obj)。
  3. toEncode 为 ? GetUint8ArrayBytes(obj)。
  4. out 为空 String。
  5. 对于 toEncode 的每个字节 byte,执行
    1. hexNumber::toString(𝔽(byte), 16)。
    2. hex 设置为 StringPad(hex, 2, "0", start)。
    3. out 设置为 outhex 的字符串拼接。
  6. 返回 out

23.3.3 Uint8Array 对象的抽象操作

23.3.3.1 ValidateUint8Array ( ta )

The abstract operation ValidateUint8Array takes argument ta (一个 ECMAScript 语言值,) and returns 要么是一个包含 unused正常完成,要么是一个抛出完成. It performs the following steps when called:

  1. 执行 ? RequireInternalSlot(ta, [[TypedArrayName]])。
  2. 如果 ta.[[TypedArrayName]] 不是 "Uint8Array",抛出 TypeError 异常。
  3. 返回 unused

23.3.3.2 GetUint8ArrayBytes ( ta )

The abstract operation GetUint8ArrayBytes takes argument ta (一个 Uint8Array,) and returns 要么是一个包含字节值 List正常完成,要么是一个抛出完成. It performs the following steps when called:

  1. bufferta.[[ViewedArrayBuffer]]
  2. taRecordMakeTypedArrayWithBufferWitnessRecord(ta, seq-cst)。
  3. 如果 IsTypedArrayOutOfBounds(taRecord) 是 true,抛出 TypeError 异常。
  4. lenTypedArrayLength(taRecord)。
  5. byteOffsetta.[[ByteOffset]]
  6. bytes 为一个新的空 List
  7. index 为 0。
  8. 重复,当 index < len 时,
    1. byteIndexbyteOffset + index
    2. byte(GetValueFromBuffer(buffer, byteIndex, uint8, true, unordered))。
    3. byte 追加到 bytes
    4. index 设置为 index + 1。
  9. 返回 bytes

23.3.3.3 SetUint8ArrayBytes ( into, bytes )

The abstract operation SetUint8ArrayBytes takes arguments into (一个 Uint8Array,) and bytes (一个字节值 List,) and returns unused. It performs the following steps when called:

  1. offsetinto.[[ByteOffset]]
  2. lenbytes 中元素的数量。
  3. index 为 0。
  4. 重复,当 index < len 时,
    1. bytebytes[index]。
    2. byteIndexInBufferindex + offset
    3. 执行 SetValueInBuffer(into.[[ViewedArrayBuffer]], byteIndexInBuffer, uint8, 𝔽(byte), true, unordered)。
    4. index 设置为 index + 1。
  5. 返回 unused

23.3.3.4 SkipAsciiWhitespace ( string, index )

The abstract operation SkipAsciiWhitespace takes arguments string (一个 String,) and index (一个非负整数,) and returns 一个非负整数. It performs the following steps when called:

  1. lengthstring 的长度。
  2. 重复,当 index < length 时,
    1. charstring 中索引 index 处的码元。
    2. 如果 char 不是 0x0009 (TAB)、0x000A (LF)、0x000C (FF)、0x000D (CR) 或 0x0020 (SPACE) 之一,则
      1. 返回 index
    3. index 设置为 index + 1。
  3. 返回 index

23.3.3.5 DecodeFinalBase64Chunk ( chunk, throwOnExtraBits )

The abstract operation DecodeFinalBase64Chunk takes arguments chunk (一个长度为 2 或 3 的 String,) and throwOnExtraBits (一个 Boolean,) and returns 要么是一个包含字节值 List正常完成,要么是一个抛出完成. It performs the following steps when called:

  1. chunkLengthchunk 的长度。
  2. 如果 chunkLength = 2,则
    1. chunk 设置为 chunk"AA" 的字符串拼接。
  3. 否则,
    1. 断言:chunkLength 为 3。
    2. chunk 设置为 chunk"A" 的字符串拼接。
  4. bytesDecodeFullLengthBase64Chunk(chunk)。
  5. 如果 chunkLength = 2,则
    1. 如果 throwOnExtraBitstruebytes[1] ≠ 0,抛出 SyntaxError 异常。
    2. 返回 « bytes[0] »。
  6. 如果 throwOnExtraBitstruebytes[2] ≠ 0,抛出 SyntaxError 异常。
  7. 返回 « bytes[0], bytes[1] »。

23.3.3.6 DecodeFullLengthBase64Chunk ( chunk )

The abstract operation DecodeFullLengthBase64Chunk takes argument chunk (一个长度为 4 的 String,) and returns 一个长度为 3 的字节值 List.

标准 base64 字母表"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",即其元素为对应 Unicode Basic Latin 块中每个字母和数字以及 "+""/" 的码元的 String。

  1. byteSequence 为将 chunk 作为 base64 解码所得的唯一 3 字节序列(即对 byteSequence 应用 RFC 4648 第 4 节中指定的 base64 编码会产生 chunk 的那个序列)。
  2. 返回一个 List,其元素按顺序为 byteSequence 的元素。

23.3.3.7 FromBase64 ( string, alphabet, lastChunkHandling [ , maxLength ] )

The abstract operation FromBase64 takes arguments string (一个 String,), alphabet ("base64""base64url",), and lastChunkHandling ("loose""strict""stop-before-partial",) and optional argument maxLength (一个非负整数,) and returns 一个具有字段 [[Read]](一个整数)、[[Bytes]](一个字节值 List)和 [[Error]](一个 SyntaxError 对象或 none)的 Record. It performs the following steps when called:

  1. 如果 maxLength 不存在,则
    1. maxLength 设置为 253 - 1。
    2. 注:因为输入是 String,String 的长度限制为 253 - 1 个字符,并且输出所需字节数不超过输入字符数,所以永远不会达到此限制。然而,使用有限值在编辑上更方便。
  2. 注:下面算法中的验证和解码顺序是不可观察的。鼓励实现以最高效的任何顺序执行它们,也可以将验证与解码交错进行。
  3. 如果 maxLength = 0,则
    1. 返回 Record { [[Read]]: 0, [[Bytes]]: « », [[Error]]: none }。
  4. read 为 0。
  5. bytes 为一个新的空 List
  6. chunk 为空 String。
  7. chunkLength 为 0。
  8. index 为 0。
  9. lengthstring 的长度。
  10. 重复,
    1. index 设置为 SkipAsciiWhitespace(string, index)。
    2. 如果 index = length,则
      1. 如果 chunkLength > 0,则
        1. 如果 lastChunkHandling"stop-before-partial",则
          1. 返回 Record { [[Read]]: read, [[Bytes]]: bytes, [[Error]]: none }。
        2. 如果 lastChunkHandling"strict",则
          1. error 为一个新创建的 SyntaxError 对象。
          2. 返回 Record { [[Read]]: read, [[Bytes]]: bytes, [[Error]]: error }。
        3. 断言:lastChunkHandling"loose"
        4. 如果 chunkLength = 1,则
          1. error 为一个新创建的 SyntaxError 对象。
          2. 返回 Record { [[Read]]: read, [[Bytes]]: bytes, [[Error]]: error }。
        5. bytes 设置为 bytes 与 ! DecodeFinalBase64Chunk(chunk, false) 的列表拼接。
      2. 返回 Record { [[Read]]: length, [[Bytes]]: bytes, [[Error]]: none }。
    3. charstring 中从 indexindex + 1 的子字符串
    4. index 设置为 index + 1。
    5. 如果 char"=",则
      1. 如果 chunkLength < 2,则
        1. error 为一个新创建的 SyntaxError 对象。
        2. 返回 Record { [[Read]]: read, [[Bytes]]: bytes, [[Error]]: error }。
      2. index 设置为 SkipAsciiWhitespace(string, index)。
      3. 如果 chunkLength = 2,则
        1. 如果 index = length,则
          1. 如果 lastChunkHandling"stop-before-partial",则
            1. 返回 Record { [[Read]]: read, [[Bytes]]: bytes, [[Error]]: none }。
          2. error 为一个新创建的 SyntaxError 对象。
          3. 返回 Record { [[Read]]: read, [[Bytes]]: bytes, [[Error]]: error }。
        2. char 设置为 string 中从 indexindex + 1 的子字符串
        3. 如果 char"=",则
          1. index 设置为 SkipAsciiWhitespace(string, index + 1)。
      4. 如果 index < length,则
        1. error 为一个新创建的 SyntaxError 对象。
        2. 返回 Record { [[Read]]: read, [[Bytes]]: bytes, [[Error]]: error }。
      5. 如果 lastChunkHandling"strict",令 throwOnExtraBitstrue;否则令 throwOnExtraBitsfalse
      6. decodeResultCompletion(DecodeFinalBase64Chunk(chunk, throwOnExtraBits))。
      7. 如果 decodeResult 是一个 abrupt completion,则
        1. errordecodeResult.[[Value]]
        2. 返回 Record { [[Read]]: read, [[Bytes]]: bytes, [[Error]]: error }。
      8. bytes 设置为 bytes 与 ! decodeResult 的列表拼接。
      9. 返回 Record { [[Read]]: length, [[Bytes]]: bytes, [[Error]]: none }。
    6. 如果 alphabet"base64url",则
      1. 如果 char"+""/",则
        1. error 为一个新创建的 SyntaxError 对象。
        2. 返回 Record { [[Read]]: read, [[Bytes]]: bytes, [[Error]]: error }。
      2. 否则如果 char"-",则
        1. char 设置为 "+"
      3. 否则如果 char"_",则
        1. char 设置为 "/"
    7. 如果 char 的唯一码元不是标准 base64 字母表的元素,则
      1. error 为一个新创建的 SyntaxError 对象。
      2. 返回 Record { [[Read]]: read, [[Bytes]]: bytes, [[Error]]: error }。
    8. remainingmaxLength - bytes 中元素的数量。
    9. 如果 remaining = 1 且 chunkLength = 2,或如果 remaining = 2 且 chunkLength = 3,则
      1. 返回 Record { [[Read]]: read, [[Bytes]]: bytes, [[Error]]: none }。
    10. chunk 设置为 chunkchar 的字符串拼接。
    11. chunkLength 设置为 chunk 的长度。
    12. 如果 chunkLength = 4,则
      1. bytes 设置为 bytesDecodeFullLengthBase64Chunk(chunk) 的列表拼接。
      2. chunk 设置为空 String。
      3. chunkLength 设置为 0。
      4. read 设置为 index
      5. 如果 bytes 中元素的数量 = maxLength,则
        1. 返回 Record { [[Read]]: read, [[Bytes]]: bytes, [[Error]]: none }。

23.3.3.8 FromHex ( string [ , maxLength ] )

The abstract operation FromHex takes argument string (一个 String,) and optional argument maxLength (一个非负整数,) and returns 一个具有字段 [[Read]](一个整数)、[[Bytes]](一个字节值 List)和 [[Error]](一个 SyntaxError 对象或 none)的 Record. It performs the following steps when called:

  1. 如果 maxLength 不存在,将 maxLength 设置为 253 - 1。
  2. lengthstring 的长度。
  3. bytes 为一个新的空 List
  4. read 为 0。
  5. 如果 length modulo 2 ≠ 0,则
    1. error 为一个新创建的 SyntaxError 对象。
    2. 返回 Record { [[Read]]: read, [[Bytes]]: bytes, [[Error]]: error }。
  6. 重复,当 read < lengthbytes 中元素的数量 < maxLength 时,
    1. hexitsstring 中从 readread + 2 的子字符串
    2. 如果 hexits 包含任何不在 "0123456789abcdefABCDEF" 中的码元,则
      1. error 为一个新创建的 SyntaxError 对象。
      2. 返回 Record { [[Read]]: read, [[Bytes]]: bytes, [[Error]]: error }。
    3. read 设置为 read + 2。
    4. bytehexits 以 16 进制表示法表示的整数值,其中使用字母 AFaf 表示值为 10 到 15 的数字。
    5. byte 追加到 bytes
  7. 返回 Record { [[Read]]: read, [[Bytes]]: bytes, [[Error]]: none }。

24 键控集合

24.1 Map 对象

Map 是键/值对的集合,其中键和值都可以是任意 ECMAScript 语言值。在 Map 的集合中,一个不同的键值只能出现在一个键/值对中。不同键值使用 SameValueZero 比较算法的语义加以区分。

Map 必须使用哈希表或其他机制来实现,这些机制平均而言能提供相对于集合中元素数量为次线性的访问时间。本规范中使用的数据结构仅用于描述 Map 所要求的可观察语义。它并不意图作为可行的实现模型。

24.1.1 Map 构造器

Map 构造器

  • %Map%
  • 全局对象"Map" 属性的初始值。
  • 当作为构造器调用时,创建并初始化一个新的 Map。
  • 不意图作为函数调用,并且以这种方式调用时会抛出异常。
  • 可用作类定义中 extends 子句的值。意图继承指定 Map 行为的子类构造器必须包含对 Map 构造器super 调用,以创建并初始化带有支持 Map.prototype 内置方法所需内部状态的子类实例。

24.1.1.1 Map ( [ iterable ] )

此函数在被调用时执行以下步骤:

  1. 如果 NewTarget 是 undefined,抛出 TypeError 异常。
  2. map 为 ? OrdinaryCreateFromConstructor(NewTarget, "%Map.prototype%", « [[MapData]] »)。
  3. map.[[MapData]] 设置为一个新的空 List
  4. 如果 iterableundefinednull,返回 map
  5. adder 为 ? Get(map, "set")。
  6. 如果 IsCallable(adder) 是 false,抛出 TypeError 异常。
  7. 返回 ? AddEntriesFromIterable(map, iterable, adder)。
Note

如果存在参数 iterable,则期望它是一个实现了 %Symbol.iterator% 方法的对象,该方法返回一个迭代器对象,产生一个双元素类数组对象,其第一个元素是将用作 Map 键的值,第二个元素是要与该键关联的值。

24.1.1.2 AddEntriesFromIterable ( target, iterable, adder )

The abstract operation AddEntriesFromIterable takes arguments target (an Object), iterable (an ECMAScript language value, but not undefined or null), and adder (a function object) and returns either a normal completion containing an Object or a throw completion. adder 将以 target 作为接收者被调用。 It performs the following steps when called:

  1. iteratorRecord 为 ? GetIterator(iterable, sync)。
  2. 重复,
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 nextdone,返回 target
    3. 如果 next 不是 Object,则
      1. errorThrowCompletion(一个新创建的 TypeError 对象)。
      2. 返回 ? IteratorClose(iteratorRecord, error)。
    4. keyCompletion(Get(next, "0"))。
    5. IfAbruptCloseIterator(key, iteratorRecord)。
    6. valueCompletion(Get(next, "1"))。
    7. IfAbruptCloseIterator(value, iteratorRecord)。
    8. statusCompletion(Call(adder, target, « key, value »))。
    9. IfAbruptCloseIterator(status, iteratorRecord)。
Note

期望参数 iterable 是一个实现了 %Symbol.iterator% 方法的对象,该方法返回一个迭代器对象,产生一个双元素类数组对象,其第一个元素是将用作 Map 键的值,第二个元素是要与该键关联的值。

24.1.2 Map 构造器的属性

Map 构造器

24.1.2.1 Map.groupBy ( items, callback )

Note

callback 应是一个接受两个参数的函数。groupBy 按升序对 items 中的每个元素调用一次 callback,并构造一个新的 Map。callback 返回的每个值都用作 Map 中的键。对于每个这样的键,结果 Map 都有一个条目,其键为该键,其值为一个数组,包含所有使 callback 返回该键的元素。

调用 callback 时传入两个参数:元素的值和元素的索引。

groupBy 的返回值是一个 Map。

此函数在被调用时执行以下步骤:

  1. groups 为 ? GroupBy(items, callback, collection)。
  2. map 为 ! Construct(%Map%)。
  3. 对于 groups 的每个 Record { [[Key]], [[Elements]] } group,执行
    1. elementsCreateArrayFromList(group.[[Elements]])。
    2. entryRecord { [[Key]]: group.[[Key]], [[Value]]: elements }。
    3. entry 追加到 map.[[MapData]]
  4. 返回 map

24.1.2.2 Map.prototype

Map.prototype 的初始值是 Map 原型对象

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

24.1.2.3 get Map [ %Symbol.species% ]

Map[%Symbol.species%] 是一个访问器属性,其 set 访问器函数为 undefined。它的 get 访问器函数在被调用时执行以下步骤:

  1. 返回 this 值。

此函数的 "name" 属性的值为 "get [Symbol.species]"

Note

创建派生集合对象的方法应调用 %Symbol.species%,以确定用于创建派生对象的构造器。子类构造器可以覆写 %Symbol.species% 以更改默认构造器分配。

24.1.3 Map 原型对象的属性

Map 原型对象

24.1.3.1 Map.prototype.clear ( )

此方法在被调用时执行以下步骤:

  1. mapthis 值。
  2. 执行 ? RequireInternalSlot(map, [[MapData]])。
  3. 对于 map.[[MapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. entry.[[Key]] 设置为 empty
    2. entry.[[Value]] 设置为 empty
  4. 返回 undefined
Note

保留现有的 [[MapData]] List,因为可能存在已在遍历该 List 的中途挂起的 Map Iterator 对象。

24.1.3.2 Map.prototype.constructor

Map.prototype.constructor 的初始值是 %Map%

24.1.3.3 Map.prototype.delete ( key )

此方法在被调用时执行以下步骤:

  1. mapthis 值。
  2. 执行 ? RequireInternalSlot(map, [[MapData]])。
  3. key 设置为 CanonicalizeKeyedCollectionKey(key)。
  4. 对于 map.[[MapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 emptySameValue(entry.[[Key]], key) 是 true,则
      1. entry.[[Key]] 设置为 empty
      2. entry.[[Value]] 设置为 empty
      3. 返回 true
  5. 返回 false
Note

empty 用作规范装置,以指示一个条目已被删除。实际实现可以采取其他动作,例如从内部数据结构中物理移除该条目。

24.1.3.4 Map.prototype.entries ( )

此方法在被调用时执行以下步骤:

  1. mapthis 值。
  2. 返回 ? CreateMapIterator(map, key+value)。

24.1.3.5 Map.prototype.forEach ( callback [ , thisArg ] )

此方法在被调用时执行以下步骤:

  1. mapthis 值。
  2. 执行 ? RequireInternalSlot(map, [[MapData]])。
  3. 如果 IsCallable(callback) 是 false,抛出 TypeError 异常。
  4. entriesmap.[[MapData]]
  5. numEntriesentries 中元素的数量。
  6. index 为 0。
  7. 重复,当 index < numEntries 时,
    1. eentries[index]。
    2. index 设置为 index + 1。
    3. 如果 e.[[Key]] 不是 empty,则
      1. 执行 ? Call(callback, thisArg, « e.[[Value]], e.[[Key]], map »)。
      2. 注:在执行 callback 期间,entries 中的元素数量可能已增加。
      3. numEntries 设置为 entries 中元素的数量。
  8. 返回 undefined
Note

callback 应是一个接受三个参数的函数。forEach 按键插入顺序对 Map 中存在的每个键/值对调用一次 callbackcallback 只会针对 Map 中实际存在的键调用;不会针对已从 Map 中删除的键调用。

如果提供了 thisArg 参数,则它将用作每次调用 callback 时的 this 值。如果未提供,则使用 undefined

调用 callback 时传入三个参数:项的值、项的键以及正在遍历的 Map。

forEach 不会直接改变调用它的对象,但该对象可能会被对 callback 的调用改变。map 的 [[MapData]] 中的每个条目只会被访问一次。在 forEach 调用开始后添加的新键会被访问。某个键如果在被访问后被删除,然后在 forEach 调用完成前重新添加,则会被再次访问。在 forEach 调用开始后且被访问之前被删除的键不会被访问,除非该键在 forEach 调用完成前再次被添加。

24.1.3.6 Map.prototype.get ( key )

此方法在被调用时执行以下步骤:

  1. mapthis 值。
  2. 执行 ? RequireInternalSlot(map, [[MapData]])。
  3. key 设置为 CanonicalizeKeyedCollectionKey(key)。
  4. 对于 map.[[MapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 emptySameValue(entry.[[Key]], key) 是 true,返回 entry.[[Value]]
  5. 返回 undefined

24.1.3.7 Map.prototype.getOrInsert ( key, value )

此方法在被调用时执行以下步骤:

  1. mapthis 值。
  2. 执行 ? RequireInternalSlot(map, [[MapData]])。
  3. key 设置为 CanonicalizeKeyedCollectionKey(key)。
  4. 对于 map.[[MapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 emptySameValue(entry.[[Key]], key) 是 true,返回 entry.[[Value]]
  5. entryRecord { [[Key]]: key, [[Value]]: value }。
  6. entry 追加到 map.[[MapData]]
  7. 返回 value

24.1.3.8 Map.prototype.getOrInsertComputed ( key, callback )

此方法在被调用时执行以下步骤:

  1. mapthis 值。
  2. 执行 ? RequireInternalSlot(map, [[MapData]])。
  3. 如果 IsCallable(callback) 是 false,抛出 TypeError 异常。
  4. key 设置为 CanonicalizeKeyedCollectionKey(key)。
  5. 对于 map.[[MapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 emptySameValue(entry.[[Key]], key) 是 true,返回 entry.[[Value]]
  6. value 为 ? Call(callback, undefined, « key »)。
  7. 注:在执行 callback 期间,Map 可能已被修改。
  8. 对于 map.[[MapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 emptySameValue(entry.[[Key]], key) 是 true,则
      1. entry.[[Value]] 设置为 value
      2. 返回 value
  9. entryRecord { [[Key]]: key, [[Value]]: value }。
  10. entry 追加到 map.[[MapData]]
  11. 返回 value

24.1.3.9 Map.prototype.has ( key )

此方法在被调用时执行以下步骤:

  1. mapthis 值。
  2. 执行 ? RequireInternalSlot(map, [[MapData]])。
  3. key 设置为 CanonicalizeKeyedCollectionKey(key)。
  4. 对于 map.[[MapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 emptySameValue(entry.[[Key]], key) 是 true,返回 true
  5. 返回 false

24.1.3.10 Map.prototype.keys ( )

此方法在被调用时执行以下步骤:

  1. mapthis 值。
  2. 返回 ? CreateMapIterator(map, key)。

24.1.3.11 Map.prototype.set ( key, value )

此方法在被调用时执行以下步骤:

  1. mapthis 值。
  2. 执行 ? RequireInternalSlot(map, [[MapData]])。
  3. key 设置为 CanonicalizeKeyedCollectionKey(key)。
  4. 对于 map.[[MapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 emptySameValue(entry.[[Key]], key) 是 true,则
      1. entry.[[Value]] 设置为 value
      2. 返回 map
  5. entryRecord { [[Key]]: key, [[Value]]: value }。
  6. entry 追加到 map.[[MapData]]
  7. 返回 map

24.1.3.12 get Map.prototype.size

Map.prototype.size 是一个访问器属性,其 set 访问器函数为 undefined。它的 get 访问器函数在被调用时执行以下步骤:

  1. mapthis 值。
  2. 执行 ? RequireInternalSlot(map, [[MapData]])。
  3. count 为 0。
  4. 对于 map.[[MapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 empty,将 count 设置为 count + 1。
  5. 返回 𝔽(count)。

24.1.3.13 Map.prototype.values ( )

此方法在被调用时执行以下步骤:

  1. mapthis 值。
  2. 返回 ? CreateMapIterator(map, value)。

24.1.3.14 Map.prototype [ %Symbol.iterator% ] ( )

%Symbol.iterator% 属性的初始值为 %Map.prototype.entries%,定义见 24.1.3.4

24.1.3.15 Map.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "Map"

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

24.1.4 Map 实例的属性

Map 实例是普通对象,从 Map 原型对象继承属性。Map 实例还具有 [[MapData]] 内部槽。

24.1.5 Map Iterator 对象

Map Iterator 是一个对象,表示对某个特定 Map 实例对象进行的特定迭代。Map Iterator 对象没有具名构造器。相反,Map Iterator 对象是通过调用 Map 实例对象的某些方法创建的。

24.1.5.1 CreateMapIterator ( map, kind )

The abstract operation CreateMapIterator takes arguments map (一个 ECMAScript 语言值,) and kind (key+valuekeyvalue,) and returns 要么是一个包含 Generator 的正常完成,要么是一个抛出完成. 它用于为返回此类迭代器的 Map 方法创建迭代器对象。 It performs the following steps when called:

  1. 执行 ? RequireInternalSlot(map, [[MapData]])。
  2. closure 为一个新的无参数 Abstract Closure,捕获 mapkind,并在被调用时执行以下步骤:
    1. entriesmap.[[MapData]]
    2. index 为 0。
    3. numEntriesentries 中元素的数量。
    4. 重复,当 index < numEntries 时,
      1. entryentries[index]。
      2. index 设置为 index + 1。
      3. 如果 entry.[[Key]] 不是 empty,则
        1. 如果 kindkey,则
          1. resultentry.[[Key]]
        2. 否则如果 kindvalue,则
          1. resultentry.[[Value]]
        3. 否则,
          1. 断言:kindkey+value
          2. resultCreateArrayFromListentry.[[Key]], entry.[[Value]] »)。
        4. 执行 ? GeneratorYield(CreateIteratorResultObject(result, false))。
        5. 注:当此抽象操作的执行被 GeneratorYield 暂停时,entries 中的元素数量可能已增加。
        6. numEntries 设置为 entries 中元素的数量。
    5. 返回 NormalCompletion(unused)。
  3. 返回 CreateIteratorFromClosure(closure, "%MapIteratorPrototype%", %MapIteratorPrototype%)。

24.1.5.2 %MapIteratorPrototype% 对象

%MapIteratorPrototype% 对象:

24.1.5.2.1 %MapIteratorPrototype%.next ( )

  1. 返回 ? GeneratorResume(this value, empty, "%MapIteratorPrototype%")。

24.1.5.2.2 %MapIteratorPrototype% [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "Map Iterator"

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

24.2 Set 对象

Set 对象ECMAScript 语言值的集合。一个 Set 最多只能包含每个不同值一次。不同值使用 SameValueZero 比较算法的语义加以区分。

Set 对象必须使用哈希表或其他机制来实现,这些机制平均而言能提供相对于集合中元素数量为次线性的访问时间。本规范中使用的数据结构仅用于描述 Set 对象所要求的可观察语义。它并不意图作为可行的实现模型。

24.2.1 Set 对象的抽象操作

24.2.1.1 Set Record

Set Record 是一个 Record 值,用于封装 Set 或类似对象的接口。

Set Record 具有 Table 71 中列出的字段。

Table 71: Set Record 字段
字段名 含义
[[SetObject]] 一个 Object 该 Set 或类似对象。
[[Size]] 一个非负整数或 +∞ 该对象报告的大小。
[[Has]] 一个函数对象 该对象的 has 方法。
[[Keys]] 一个函数对象 该对象的 keys 方法。

24.2.1.2 GetSetRecord ( obj )

The abstract operation GetSetRecord takes argument obj (一个 ECMAScript 语言值,) and returns 要么是一个包含 Set Record正常完成,要么是一个抛出完成. It performs the following steps when called:

  1. 如果 obj 不是 Object,抛出 TypeError 异常。
  2. rawSize 为 ? Get(obj, "size")。
  3. numSize 为 ? ToNumber(rawSize)。
  4. 注:如果 rawSizeundefined,则 numSize 将是 NaN
  5. 如果 numSizeNaN,抛出 TypeError 异常。
  6. intSize 为 ! ToIntegerOrInfinity(numSize)。
  7. 如果 intSize < 0,抛出 RangeError 异常。
  8. has 为 ? Get(obj, "has")。
  9. 如果 IsCallable(has) 是 false,抛出 TypeError 异常。
  10. keys 为 ? Get(obj, "keys")。
  11. 如果 IsCallable(keys) 是 false,抛出 TypeError 异常。
  12. 返回一个新的 Set Record { [[SetObject]]: obj, [[Size]]: intSize, [[Has]]: has, [[Keys]]: keys }。

24.2.1.3 SetDataHas ( setData, value )

The abstract operation SetDataHas takes arguments setData (一个由 ECMAScript 语言值empty 组成的 List,) and value (一个 ECMAScript 语言值,) and returns 一个 Boolean. It performs the following steps when called:

  1. 如果 SetDataIndex(setData, value) 是 not-found,返回 false
  2. 返回 true

24.2.1.4 SetDataIndex ( setData, value )

The abstract operation SetDataIndex takes arguments setData (一个由 ECMAScript 语言值empty 组成的 List,) and value (一个 ECMAScript 语言值,) and returns 一个非负整数not-found. It performs the following steps when called:

  1. value 设置为 CanonicalizeKeyedCollectionKey(value)。
  2. sizesetData 中元素的数量。
  3. index 为 0。
  4. 重复,当 index < size 时,
    1. esetData[index]。
    2. 如果 e 不是 emptyevalue,则
      1. 返回 index
    3. index 设置为 index + 1。
  5. 返回 not-found

24.2.1.5 SetDataSize ( setData )

The abstract operation SetDataSize takes argument setData (一个由 ECMAScript 语言值empty 组成的 List,) and returns 一个非负整数. It performs the following steps when called:

  1. count 为 0。
  2. 对于 setData 的每个元素 e,执行
    1. 如果 e 不是 empty,将 count 设置为 count + 1。
  3. 返回 count

24.2.2 Set 构造器

Set 构造器

  • %Set%
  • 全局对象"Set" 属性的初始值。
  • 当作为构造器调用时,创建并初始化一个新的 Set 对象
  • 不意图作为函数调用,并且以这种方式调用时会抛出异常。
  • 可用作类定义中 extends 子句的值。意图继承指定 Set 行为的子类构造器必须包含对 Set 构造器super 调用,以创建并初始化带有支持 Set.prototype 内置方法所需内部状态的子类实例。

24.2.2.1 Set ( [ iterable ] )

此函数在被调用时执行以下步骤:

  1. 如果 NewTarget 是 undefined,抛出 TypeError 异常。
  2. set 为 ? OrdinaryCreateFromConstructor(NewTarget, "%Set.prototype%", « [[SetData]] »)。
  3. set.[[SetData]] 设置为一个新的空 List
  4. 如果 iterableundefinednull,返回 set
  5. adder 为 ? Get(set, "add")。
  6. 如果 IsCallable(adder) 是 false,抛出 TypeError 异常。
  7. iteratorRecord 为 ? GetIterator(iterable, sync)。
  8. 重复,
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 nextdone,返回 set
    3. statusCompletion(Call(adder, set, « next »))。
    4. IfAbruptCloseIterator(status, iteratorRecord)。

24.2.3 Set 构造器的属性

Set 构造器

24.2.3.1 Set.prototype

Set.prototype 的初始值是 Set 原型对象

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

24.2.3.2 get Set [ %Symbol.species% ]

Set[%Symbol.species%] 是一个访问器属性,其 set 访问器函数为 undefined。它的 get 访问器函数在被调用时执行以下步骤:

  1. 返回 this 值。

此函数的 "name" 属性的值为 "get [Symbol.species]"

Note

创建派生集合对象的方法应调用 %Symbol.species%,以确定用于创建派生对象的构造器。子类构造器可以覆写 %Symbol.species% 以更改默认构造器分配。

24.2.4 Set 原型对象的属性

Set 原型对象

24.2.4.1 Set.prototype.add ( value )

此方法在被调用时执行以下步骤:

  1. setthis 值。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. value 设置为 CanonicalizeKeyedCollectionKey(value)。
  4. 对于 set.[[SetData]] 的每个元素 entry,执行
    1. 如果 entry 不是 emptySameValue(entry, value) 是 true,则
      1. 返回 set
  5. value 追加到 set.[[SetData]]
  6. 返回 set

24.2.4.2 Set.prototype.clear ( )

此方法在被调用时执行以下步骤:

  1. setthis 值。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. 对于 set.[[SetData]] 的每个元素 entry,执行
    1. set.[[SetData]] 中值为 entry 的元素替换为值为 empty 的元素。
  4. 返回 undefined
Note

保留现有的 [[SetData]] List,因为可能存在已在遍历该 List 的中途挂起的 Set Iterator 对象。

24.2.4.3 Set.prototype.constructor

Set.prototype.constructor 的初始值是 %Set%

24.2.4.4 Set.prototype.delete ( value )

此方法在被调用时执行以下步骤:

  1. setthis 值。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. value 设置为 CanonicalizeKeyedCollectionKey(value)。
  4. 对于 set.[[SetData]] 的每个元素 entry,执行
    1. 如果 entry 不是 emptySameValue(entry, value) 是 true,则
      1. set.[[SetData]] 中值为 entry 的元素替换为值为 empty 的元素。
      2. 返回 true
  5. 返回 false
Note

empty 用作规范装置,以指示一个条目已被删除。实际实现可以采取其他动作,例如从内部数据结构中物理移除该条目。

24.2.4.5 Set.prototype.difference ( other )

此方法在被调用时执行以下步骤:

  1. setthis 值。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. otherRec 为 ? GetSetRecord(other)。
  4. resultSetDataset.[[SetData]] 的副本。
  5. 如果 SetDataSize(set.[[SetData]]) ≤ otherRec.[[Size]],则
    1. thisSizeset.[[SetData]] 中元素的数量。
    2. index 为 0。
    3. 重复,当 index < thisSize 时,
      1. entryresultSetData[index]。
      2. 如果 entry 不是 empty,则
        1. inOtherToBoolean(? Call(otherRec.[[Has]], otherRec.[[SetObject]], « entry »))。
        2. 如果 inOthertrue,则
          1. resultSetData[index] 设置为 empty
      3. index 设置为 index + 1。
  6. 否则,
    1. keysIter 为 ? GetIteratorFromMethod(otherRec.[[SetObject]], otherRec.[[Keys]])。
    2. nextnot-started
    3. 重复,当 next 不是 done 时,
      1. next 设置为 ? IteratorStepValue(keysIter)。
      2. 如果 next 不是 done,则
        1. next 设置为 CanonicalizeKeyedCollectionKey(next)。
        2. valueIndexSetDataIndex(resultSetData, next)。
        3. 如果 valueIndex 不是 not-found,则
          1. resultSetData[valueIndex] 设置为 empty
  7. resultOrdinaryObjectCreate(%Set.prototype%, « [[SetData]] »)。
  8. result.[[SetData]] 设置为 resultSetData
  9. 返回 result

24.2.4.6 Set.prototype.entries ( )

此方法在被调用时执行以下步骤:

  1. setthis 值。
  2. 返回 ? CreateSetIterator(set, key+value)。
Note

为迭代目的,Set 看起来类似于一个 Map,其中每个条目的键和值具有相同的值。

24.2.4.7 Set.prototype.forEach ( callback [ , thisArg ] )

此方法在被调用时执行以下步骤:

  1. setthis 值。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. 如果 IsCallable(callback) 是 false,抛出 TypeError 异常。
  4. entriesset.[[SetData]]
  5. numEntriesentries 中元素的数量。
  6. index 为 0。
  7. 重复,当 index < numEntries 时,
    1. entryentries[index]。
    2. index 设置为 index + 1。
    3. 如果 entry 不是 empty,则
      1. 执行 ? Call(callback, thisArg, « entry, entry, set »)。
      2. 注:在执行 callback 期间,entries 中的元素数量可能已增加。
      3. numEntries 设置为 entries 中元素的数量。
  8. 返回 undefined
Note

callback 应是一个接受三个参数的函数。forEach 按值插入顺序对 Set 对象中存在的每个值调用一次 callbackcallback 只会针对 Set 中实际存在的值调用;不会针对已从 set 中删除的键调用。

如果提供了 thisArg 参数,则它将用作每次调用 callback 时的 this 值。如果未提供,则使用 undefined

调用 callback 时传入三个参数:前两个参数是 Set 中包含的一个值。两个参数传入相同的值。正在遍历的 Set 对象作为第三个参数传入。

callback 以三个参数调用,是为了与 Map 和 Array 的 forEach 方法所使用的回调函数保持一致。对于 Set,每个项值都被视为键和值。

forEach 不会直接改变调用它的对象,但该对象可能会被对 callback 的调用改变。

通常每个值只会被访问一次。然而,如果某个值在被访问后被删除,然后在 forEach 调用完成前重新添加,则该值会被再次访问。在 forEach 调用开始后且被访问之前被删除的值不会被访问,除非该值在 forEach 调用完成前再次被添加。在 forEach 调用开始后添加的新值会被访问。

24.2.4.8 Set.prototype.has ( value )

此方法在被调用时执行以下步骤:

  1. setthis 值。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. value 设置为 CanonicalizeKeyedCollectionKey(value)。
  4. 对于 set.[[SetData]] 的每个元素 entry,执行
    1. 如果 entry 不是 emptySameValue(entry, value) 是 true,返回 true
  5. 返回 false

24.2.4.9 Set.prototype.intersection ( other )

此方法在被调用时执行以下步骤:

  1. setthis 值。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. otherRec 为 ? GetSetRecord(other)。
  4. resultSetData 为一个新的空 List
  5. 如果 SetDataSize(set.[[SetData]]) ≤ otherRec.[[Size]],则
    1. thisSizeset.[[SetData]] 中元素的数量。
    2. index 为 0。
    3. 重复,当 index < thisSize 时,
      1. entryset.[[SetData]][index]。
      2. index 设置为 index + 1。
      3. 如果 entry 不是 empty,则
        1. inOtherToBoolean(? Call(otherRec.[[Has]], otherRec.[[SetObject]], « entry »))。
        2. 如果 inOthertrue,则
          1. 注:较早的 otherRec.[[Has]] 调用可能移除并重新添加 set.[[SetData]] 的一个元素,这可能导致同一元素在此迭代期间被访问两次。
          2. 如果 SetDataHas(resultSetData, entry) 是 false,则
            1. entry 追加到 resultSetData
        3. 注:在执行 otherRec.[[Has]] 期间,set.[[SetData]] 中的元素数量可能已增加。
        4. thisSize 设置为 set.[[SetData]] 中元素的数量。
  6. 否则,
    1. keysIter 为 ? GetIteratorFromMethod(otherRec.[[SetObject]], otherRec.[[Keys]])。
    2. nextnot-started
    3. 重复,当 next 不是 done 时,
      1. next 设置为 ? IteratorStepValue(keysIter)。
      2. 如果 next 不是 done,则
        1. next 设置为 CanonicalizeKeyedCollectionKey(next)。
        2. inThisSetDataHas(set.[[SetData]], next)。
        3. 如果 inThistrue,则
          1. 注:因为 other 是任意对象,所以其 "keys" 迭代器可能多次产生相同的值。
          2. 如果 SetDataHas(resultSetData, next) 是 false,则
            1. next 追加到 resultSetData
  7. resultOrdinaryObjectCreate(%Set.prototype%, « [[SetData]] »)。
  8. result.[[SetData]] 设置为 resultSetData
  9. 返回 result

24.2.4.10 Set.prototype.isDisjointFrom ( other )

此方法在被调用时执行以下步骤:

  1. setthis 值。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. otherRec 为 ? GetSetRecord(other)。
  4. 如果 SetDataSize(set.[[SetData]]) ≤ otherRec.[[Size]],则
    1. thisSizeset.[[SetData]] 中元素的数量。
    2. index 为 0。
    3. 重复,当 index < thisSize 时,
      1. entryset.[[SetData]][index]。
      2. index 设置为 index + 1。
      3. 如果 entry 不是 empty,则
        1. inOtherToBoolean(? Call(otherRec.[[Has]], otherRec.[[SetObject]], « entry »))。
        2. 如果 inOthertrue,返回 false
        3. 注:在执行 otherRec.[[Has]] 期间,set.[[SetData]] 中的元素数量可能已增加。
        4. thisSize 设置为 set.[[SetData]] 中元素的数量。
  5. 否则,
    1. keysIter 为 ? GetIteratorFromMethod(otherRec.[[SetObject]], otherRec.[[Keys]])。
    2. nextnot-started
    3. 重复,当 next 不是 done 时,
      1. next 设置为 ? IteratorStepValue(keysIter)。
      2. 如果 next 不是 done,则
        1. 如果 SetDataHas(set.[[SetData]], next) 是 true,则
          1. 执行 ? IteratorClose(keysIter, NormalCompletion(unused))。
          2. 返回 false
  6. 返回 true

24.2.4.11 Set.prototype.isSubsetOf ( other )

此方法在被调用时执行以下步骤:

  1. setthis 值。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. otherRec 为 ? GetSetRecord(other)。
  4. 如果 SetDataSize(set.[[SetData]]) > otherRec.[[Size]],返回 false
  5. thisSizeset.[[SetData]] 中元素的数量。
  6. index 为 0。
  7. 重复,当 index < thisSize 时,
    1. entryset.[[SetData]][index]。
    2. index 设置为 index + 1。
    3. 如果 entry 不是 empty,则
      1. inOtherToBoolean(? Call(otherRec.[[Has]], otherRec.[[SetObject]], « entry »))。
      2. 如果 inOtherfalse,返回 false
      3. 注:在执行 otherRec.[[Has]] 期间,set.[[SetData]] 中的元素数量可能已增加。
      4. thisSize 设置为 set.[[SetData]] 中元素的数量。
  8. 返回 true

24.2.4.12 Set.prototype.isSupersetOf ( other )

此方法在被调用时执行以下步骤:

  1. setthis 值。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. otherRec 为 ? GetSetRecord(other)。
  4. 如果 SetDataSize(set.[[SetData]]) < otherRec.[[Size]],返回 false
  5. keysIter 为 ? GetIteratorFromMethod(otherRec.[[SetObject]], otherRec.[[Keys]])。
  6. nextnot-started
  7. 重复,当 next 不是 done 时,
    1. next 设置为 ? IteratorStepValue(keysIter)。
    2. 如果 next 不是 done,则
      1. 如果 SetDataHas(set.[[SetData]], next) 是 false,则
        1. 执行 ? IteratorClose(keysIter, NormalCompletion(unused))。
        2. 返回 false
  8. 返回 true

24.2.4.13 Set.prototype.keys ( )

"keys" 属性的初始值为 %Set.prototype.values%,定义见 24.2.4.17

Note

为迭代目的,Set 看起来类似于一个 Map,其中每个条目的键和值具有相同的值。

24.2.4.14 get Set.prototype.size

Set.prototype.size 是一个访问器属性,其 set 访问器函数为 undefined。它的 get 访问器函数在被调用时执行以下步骤:

  1. setthis 值。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. sizeSetDataSize(set.[[SetData]])。
  4. 返回 𝔽(size)。

24.2.4.15 Set.prototype.symmetricDifference ( other )

此方法在被调用时执行以下步骤:

  1. setthis 值。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. otherRec 为 ? GetSetRecord(other)。
  4. keysIter 为 ? GetIteratorFromMethod(otherRec.[[SetObject]], otherRec.[[Keys]])。
  5. resultSetDataset.[[SetData]] 的副本。
  6. nextnot-started
  7. 重复,当 next 不是 done 时,
    1. next 设置为 ? IteratorStepValue(keysIter)。
    2. 如果 next 不是 done,则
      1. next 设置为 CanonicalizeKeyedCollectionKey(next)。
      2. resultIndexSetDataIndex(resultSetData, next)。
      3. 如果 resultIndexnot-found,令 alreadyInResultfalse;否则令 alreadyInResulttrue
      4. 如果 SetDataHas(set.[[SetData]], next) 是 true,则
        1. 如果 alreadyInResulttrue,将 resultSetData[resultIndex] 设置为 empty
      5. 否则,
        1. 如果 alreadyInResultfalse,将 next 追加到 resultSetData
  8. resultOrdinaryObjectCreate(%Set.prototype%, « [[SetData]] »)。
  9. result.[[SetData]] 设置为 resultSetData
  10. 返回 result

24.2.4.16 Set.prototype.union ( other )

此方法在被调用时执行以下步骤:

  1. setthis 值。
  2. 执行 ? RequireInternalSlot(set, [[SetData]])。
  3. otherRec 为 ? GetSetRecord(other)。
  4. keysIter 为 ? GetIteratorFromMethod(otherRec.[[SetObject]], otherRec.[[Keys]])。
  5. resultSetDataset.[[SetData]] 的副本。
  6. nextnot-started
  7. 重复,当 next 不是 done 时,
    1. next 设置为 ? IteratorStepValue(keysIter)。
    2. 如果 next 不是 done,则
      1. next 设置为 CanonicalizeKeyedCollectionKey(next)。
      2. 如果 SetDataHas(resultSetData, next) 是 false,则
        1. next 追加到 resultSetData
  8. resultOrdinaryObjectCreate(%Set.prototype%, « [[SetData]] »)。
  9. result.[[SetData]] 设置为 resultSetData
  10. 返回 result

24.2.4.17 Set.prototype.values ( )

此方法在被调用时执行以下步骤:

  1. setthis 值。
  2. 返回 ? CreateSetIterator(set, value)。

24.2.4.18 Set.prototype [ %Symbol.iterator% ] ( )

%Symbol.iterator% 属性的初始值为 %Set.prototype.values%,定义见 24.2.4.17

24.2.4.19 Set.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "Set"

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

24.2.5 Set 实例的属性

Set 实例是普通对象,从 Set 原型对象继承属性。Set 实例还具有 [[SetData]] 内部槽。

24.2.6 Set Iterator 对象

Set Iterator 是一个普通对象,具有下文定义的结构,表示对某个特定 Set 实例对象进行的特定迭代。Set Iterator 对象没有具名构造器。相反,Set Iterator 对象是通过调用 Set 实例对象的某些方法创建的。

24.2.6.1 CreateSetIterator ( set, kind )

The abstract operation CreateSetIterator takes arguments set (一个 ECMAScript 语言值,) and kind (key+valuevalue,) and returns 要么是一个包含 Generator 的正常完成,要么是一个抛出完成. 它用于为返回此类迭代器的 Set 方法创建迭代器对象。 It performs the following steps when called:

  1. 执行 ? RequireInternalSlot(set, [[SetData]])。
  2. closure 为一个新的无参数 Abstract Closure,捕获 setkind,并在被调用时执行以下步骤:
    1. index 为 0。
    2. entriesset.[[SetData]]
    3. numEntriesentries 中元素的数量。
    4. 重复,当 index < numEntries 时,
      1. entryentries[index]。
      2. index 设置为 index + 1。
      3. 如果 entry 不是 empty,则
        1. 如果 kindkey+value,则
          1. resultCreateArrayFromListentry, entry »)。
          2. 执行 ? GeneratorYield(CreateIteratorResultObject(result, false))。
        2. 否则,
          1. 断言:kindvalue
          2. 执行 ? GeneratorYield(CreateIteratorResultObject(entry, false))。
        3. 注:当此抽象操作的执行被 GeneratorYield 暂停时,entries 中的元素数量可能已增加。
        4. numEntries 设置为 entries 中元素的数量。
    5. 返回 NormalCompletion(unused)。
  3. 返回 CreateIteratorFromClosure(closure, "%SetIteratorPrototype%", %SetIteratorPrototype%)。

24.2.6.2 %SetIteratorPrototype% 对象

%SetIteratorPrototype% 对象:

24.2.6.2.1 %SetIteratorPrototype%.next ( )

  1. 返回 ? GeneratorResume(this value, empty, "%SetIteratorPrototype%")。

24.2.6.2.2 %SetIteratorPrototype% [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "Set Iterator"

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

24.3 WeakMap 对象

WeakMap 是键/值对的集合,其中键是对象和/或符号,值可以是任意 ECMAScript 语言值。可以查询 WeakMap 以查看它是否包含具有特定键的键/值对,但不提供枚举它作为键所持有的值的机制。在某些条件下,不再存活的值会作为 WeakMap 键被移除,如 9.9.3 中所述。

实现可以在 WeakMap 的某个键/值对变得不可访问的时间与该键/值对从 WeakMap 中移除的时间之间施加任意确定的延迟。如果此延迟可被 ECMAScript 程序观察到,它将成为一种可能影响程序执行的不确定性来源。因此,ECMAScript 实现不得提供任何手段来观察 WeakMap 的某个键,除非该观察要求观察者提供被观察的键。

WeakMap 必须使用哈希表或其他机制来实现,这些机制平均而言能提供相对于集合中键/值对数量为次线性的访问时间。本规范中使用的数据结构仅用于描述 WeakMap 所要求的可观察语义。它并不意图作为可行的实现模型。

Note

WeakMap 和 WeakSet 意图提供一种机制,用于以不会“泄漏”内存资源的方式动态地将状态与对象或符号关联起来;也就是说,如果没有 WeakMap 或 WeakSet 实例,该对象或符号本来会变得不可访问并受实现的垃圾收集机制回收。此特性可以通过使用 WeakMap 或 WeakSet 实例到键的反向每对象/符号映射来实现。或者,每个 WeakMap 或 WeakSet 实例也可以在内部存储其键和值数据,但这种方式要求 WeakMap 或 WeakSet 实现与垃圾收集器协调。以下参考文献描述了可能对 WeakMap 和 WeakSet 实现有用的机制:

Barry Hayes. 1997. Ephemerons: a new finalization mechanism. In Proceedings of the 12th ACM SIGPLAN conference on Object-oriented programming, systems, languages, and applications (OOPSLA '97), A. Michael Berman (Ed.). ACM, New York, NY, USA, 176-183, http://doi.acm.org/10.1145/263698.263733.

Alexandra Barros, Roberto Ierusalimschy, Eliminating Cycles in Weak Tables. Journal of Universal Computer Science - J.UCS, vol. 14, no. 21, pp. 3481-3497, 2008, http://www.jucs.org/jucs_14_21/eliminating_cycles_in_weak

24.3.1 WeakMap 构造器

WeakMap 构造器

  • %WeakMap%
  • 全局对象"WeakMap" 属性的初始值。
  • 当作为构造器调用时,创建并初始化一个新的 WeakMap。
  • 不意图作为函数调用,并且以这种方式调用时会抛出异常。
  • 可用作类定义中 extends 子句的值。意图继承指定 WeakMap 行为的子类构造器必须包含对 WeakMap 构造器super 调用,以创建并初始化带有支持 WeakMap.prototype 内置方法所需内部状态的子类实例。

24.3.1.1 WeakMap ( [ iterable ] )

此函数在被调用时执行以下步骤:

  1. 如果 NewTarget 是 undefined,抛出 TypeError 异常。
  2. map 为 ? OrdinaryCreateFromConstructor(NewTarget, "%WeakMap.prototype%", « [[WeakMapData]] »)。
  3. map.[[WeakMapData]] 设置为一个新的空 List
  4. 如果 iterableundefinednull,返回 map
  5. adder 为 ? Get(map, "set")。
  6. 如果 IsCallable(adder) 是 false,抛出 TypeError 异常。
  7. 返回 ? AddEntriesFromIterable(map, iterable, adder)。
Note

如果存在参数 iterable,则期望它是一个实现了 %Symbol.iterator% 方法的对象,该方法返回一个迭代器对象,产生一个双元素类数组对象,其第一个元素是将用作 WeakMap 键的值,第二个元素是要与该键关联的值。

24.3.2 WeakMap 构造器的属性

WeakMap 构造器

24.3.2.1 WeakMap.prototype

WeakMap.prototype 的初始值是 WeakMap 原型对象

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

24.3.3 WeakMap 原型对象的属性

WeakMap 原型对象

  • %WeakMap.prototype%
  • 有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%
  • 是一个普通对象
  • 没有 [[WeakMapData]] 内部槽。

24.3.3.1 WeakMap.prototype.constructor

WeakMap.prototype.constructor 的初始值是 %WeakMap%

24.3.3.2 WeakMap.prototype.delete ( key )

此方法在被调用时执行以下步骤:

  1. weakMapthis 值。
  2. 执行 ? RequireInternalSlot(weakMap, [[WeakMapData]])。
  3. 如果 CanBeHeldWeakly(key) 是 false,返回 false
  4. 对于 weakMap.[[WeakMapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 emptySameValue(entry.[[Key]], key) 是 true,则
      1. entry.[[Key]] 设置为 empty
      2. entry.[[Value]] 设置为 empty
      3. 返回 true
  5. 返回 false
Note

empty 用作规范装置,以指示一个条目已被删除。实际实现可以采取其他动作,例如从内部数据结构中物理移除该条目。

24.3.3.3 WeakMap.prototype.get ( key )

此方法在被调用时执行以下步骤:

  1. weakMapthis 值。
  2. 执行 ? RequireInternalSlot(weakMap, [[WeakMapData]])。
  3. 如果 CanBeHeldWeakly(key) 是 false,返回 undefined
  4. 对于 weakMap.[[WeakMapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 emptySameValue(entry.[[Key]], key) 是 true,返回 entry.[[Value]]
  5. 返回 undefined

24.3.3.4 WeakMap.prototype.getOrInsert ( key, value )

此方法在被调用时执行以下步骤:

  1. weakMapthis 值。
  2. 执行 ? RequireInternalSlot(weakMap, [[WeakMapData]])。
  3. 如果 CanBeHeldWeakly(key) 是 false,抛出 TypeError 异常。
  4. 对于 weakMap.[[WeakMapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 emptySameValue(entry.[[Key]], key) 是 true,返回 entry.[[Value]]
  5. entryRecord { [[Key]]: key, [[Value]]: value }。
  6. entry 追加到 weakMap.[[WeakMapData]]
  7. 返回 value

24.3.3.5 WeakMap.prototype.getOrInsertComputed ( key, callback )

此方法在被调用时执行以下步骤:

  1. weakMapthis 值。
  2. 执行 ? RequireInternalSlot(weakMap, [[WeakMapData]])。
  3. 如果 CanBeHeldWeakly(key) 是 false,抛出 TypeError 异常。
  4. 如果 IsCallable(callback) 是 false,抛出 TypeError 异常。
  5. 对于 weakMap.[[WeakMapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 emptySameValue(entry.[[Key]], key) 是 true,返回 entry.[[Value]]
  6. value 为 ? Call(callback, undefined, « key »)。
  7. 注:在执行 callback 期间,WeakMap 可能已被修改。
  8. 对于 weakMap.[[WeakMapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 emptySameValue(entry.[[Key]], key) 是 true,则
      1. entry.[[Value]] 设置为 value
      2. 返回 value
  9. entryRecord { [[Key]]: key, [[Value]]: value }。
  10. entry 追加到 weakMap.[[WeakMapData]]
  11. 返回 value

24.3.3.6 WeakMap.prototype.has ( key )

此方法在被调用时执行以下步骤:

  1. weakMapthis 值。
  2. 执行 ? RequireInternalSlot(weakMap, [[WeakMapData]])。
  3. 如果 CanBeHeldWeakly(key) 是 false,返回 false
  4. 对于 weakMap.[[WeakMapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 emptySameValue(entry.[[Key]], key) 是 true,返回 true
  5. 返回 false

24.3.3.7 WeakMap.prototype.set ( key, value )

此方法在被调用时执行以下步骤:

  1. weakMapthis 值。
  2. 执行 ? RequireInternalSlot(weakMap, [[WeakMapData]])。
  3. 如果 CanBeHeldWeakly(key) 是 false,抛出 TypeError 异常。
  4. 对于 weakMap.[[WeakMapData]] 的每个 Record { [[Key]], [[Value]] } entry,执行
    1. 如果 entry.[[Key]] 不是 emptySameValue(entry.[[Key]], key) 是 true,则
      1. entry.[[Value]] 设置为 value
      2. 返回 weakMap
  5. entryRecord { [[Key]]: key, [[Value]]: value }。
  6. entry 追加到 weakMap.[[WeakMapData]]
  7. 返回 weakMap

24.3.3.8 WeakMap.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "WeakMap"

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

24.3.4 WeakMap 实例的属性

WeakMap 实例是普通对象,从 WeakMap 原型对象继承属性。WeakMap 实例还具有 [[WeakMapData]] 内部槽。

24.4 WeakSet 对象

WeakSet 是对象和/或符号的集合。一个不同的对象或符号作为 WeakSet 集合的元素只能出现一次。可以查询 WeakSet 以查看它是否包含某个特定值,但不提供枚举它所持有的值的机制。在某些条件下,不再存活的值会作为 WeakSet 元素被移除,如 9.9.3 中所述。

实现可以在 WeakSet 中包含的某个值变得不可访问的时间与该值从 WeakSet 中移除的时间之间施加任意确定的延迟。如果此延迟可被 ECMAScript 程序观察到,它将成为一种可能影响程序执行的不确定性来源。因此,ECMAScript 实现不得提供任何手段来确定 WeakSet 是否包含某个特定值,除非该确定要求观察者提供被观察的值。

WeakSet 必须使用哈希表或其他机制来实现,这些机制平均而言能提供相对于集合中元素数量为次线性的访问时间。本规范中使用的数据结构仅用于描述 WeakSet 所要求的可观察语义。它并不意图作为可行的实现模型。

Note

24.3 中的注。

24.4.1 WeakSet 构造器

WeakSet 构造器

  • %WeakSet%
  • 全局对象"WeakSet" 属性的初始值。
  • 当作为构造器调用时,创建并初始化一个新的 WeakSet。
  • 不意图作为函数调用,并且以这种方式调用时会抛出异常。
  • 可用作类定义中 extends 子句的值。意图继承指定 WeakSet 行为的子类构造器必须包含对 WeakSet 构造器super 调用,以创建并初始化带有支持 WeakSet.prototype 内置方法所需内部状态的子类实例。

24.4.1.1 WeakSet ( [ iterable ] )

此函数在被调用时执行以下步骤:

  1. 如果 NewTarget 是 undefined,抛出 TypeError 异常。
  2. set 为 ? OrdinaryCreateFromConstructor(NewTarget, "%WeakSet.prototype%", « [[WeakSetData]] »)。
  3. set.[[WeakSetData]] 设置为一个新的空 List
  4. 如果 iterableundefinednull,返回 set
  5. adder 为 ? Get(set, "add")。
  6. 如果 IsCallable(adder) 是 false,抛出 TypeError 异常。
  7. iteratorRecord 为 ? GetIterator(iterable, sync)。
  8. 重复,
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 nextdone,返回 set
    3. statusCompletion(Call(adder, set, « next »))。
    4. IfAbruptCloseIterator(status, iteratorRecord)。

24.4.2 WeakSet 构造器的属性

WeakSet 构造器

24.4.2.1 WeakSet.prototype

WeakSet.prototype 的初始值是 WeakSet 原型对象

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

24.4.3 WeakSet 原型对象的属性

WeakSet 原型对象

  • %WeakSet.prototype%
  • 有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%
  • 是一个普通对象
  • 没有 [[WeakSetData]] 内部槽。

24.4.3.1 WeakSet.prototype.add ( value )

此方法在被调用时执行以下步骤:

  1. weakSetthis 值。
  2. 执行 ? RequireInternalSlot(weakSet, [[WeakSetData]])。
  3. 如果 CanBeHeldWeakly(value) 是 false,抛出 TypeError 异常。
  4. 对于 weakSet.[[WeakSetData]] 的每个元素 entry,执行
    1. 如果 entry 不是 emptySameValue(entry, value) 是 true,则
      1. 返回 weakSet
  5. value 追加到 weakSet.[[WeakSetData]]
  6. 返回 weakSet

24.4.3.2 WeakSet.prototype.constructor

WeakSet.prototype.constructor 的初始值是 %WeakSet%

24.4.3.3 WeakSet.prototype.delete ( value )

此方法在被调用时执行以下步骤:

  1. weakSetthis 值。
  2. 执行 ? RequireInternalSlot(weakSet, [[WeakSetData]])。
  3. 如果 CanBeHeldWeakly(value) 是 false,返回 false
  4. 对于 weakSet.[[WeakSetData]] 的每个元素 entry,执行
    1. 如果 entry 不是 emptySameValue(entry, value) 是 true,则
      1. weakSet.[[WeakSetData]] 中值为 entry 的元素替换为值为 empty 的元素。
      2. 返回 true
  5. 返回 false
Note

empty 用作规范装置,以指示一个条目已被删除。实际实现可以采取其他动作,例如从内部数据结构中物理移除该条目。

24.4.3.4 WeakSet.prototype.has ( value )

此方法在被调用时执行以下步骤:

  1. weakSetthis 值。
  2. 执行 ? RequireInternalSlot(weakSet, [[WeakSetData]])。
  3. 如果 CanBeHeldWeakly(value) 是 false,返回 false
  4. 对于 weakSet.[[WeakSetData]] 的每个元素 entry,执行
    1. 如果 entry 不是 emptySameValue(entry, value) 是 true,返回 true
  5. 返回 false

24.4.3.5 WeakSet.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "WeakSet"

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

24.4.4 WeakSet 实例的属性

WeakSet 实例是普通对象,从 WeakSet 原型对象继承属性。WeakSet 实例还具有 [[WeakSetData]] 内部槽。

24.5 键控集合的抽象操作

24.5.1 CanonicalizeKeyedCollectionKey ( key )

The abstract operation CanonicalizeKeyedCollectionKey takes argument key (一个 ECMAScript 语言值,) and returns 一个 ECMAScript 语言值. It performs the following steps when called:

  1. 如果 key-0𝔽,返回 +0𝔽
  2. 返回 key

25 结构化数据

25.1 ArrayBuffer 对象

25.1.1 记号

本节、25.429 中的描述使用读-改-写修改函数内部数据结构。

读-改-写修改函数是一个数学函数,表示为一个 Abstract Closure,它接受两个由字节值组成的 List 作为参数,并返回一个由字节值组成的 List。这些 Abstract Closure 满足以下所有性质:

  • 它们以原子方式执行其所有算法步骤。
  • 它们各自的算法步骤不可被观察。
Note

为有助于验证读-改-写修改函数的算法步骤构成一个纯数学函数,建议采用以下编辑约定:

25.1.2 固定长度和可调整大小的 ArrayBuffer 对象

固定长度 ArrayBuffer 是创建之后其字节长度不能改变的 ArrayBuffer。

可调整大小 ArrayBuffer 是创建之后其字节长度可以通过调用 ArrayBuffer.prototype.resize ( newLength ) 来改变的 ArrayBuffer。

所创建的 ArrayBuffer 对象种类取决于传递给 ArrayBuffer ( length [ , options ] ) 的参数。

25.1.3 ArrayBuffer 对象的抽象操作

25.1.3.1 AllocateArrayBuffer ( constructor, byteLength [ , maxByteLength ] )

The abstract operation AllocateArrayBuffer takes arguments constructor (一个构造器,) and byteLength (一个非负整数,) and optional argument maxByteLength (一个非负整数empty,) and returns 要么是一个包含 ArrayBuffer 的正常完成,要么是一个抛出完成. 它用于创建一个 ArrayBuffer。 It performs the following steps when called:

  1. slots 为 « [[ArrayBufferData]], [[ArrayBufferByteLength]], [[ArrayBufferDetachKey]] »。
  2. 如果 maxByteLength 存在且 maxByteLength 不是 empty,令 allocatingResizableBuffertrue;否则令 allocatingResizableBufferfalse
  3. 如果 allocatingResizableBuffertrue,则
    1. 如果 byteLength > maxByteLength,抛出 RangeError 异常。
    2. [[ArrayBufferMaxByteLength]] 追加到 slots
  4. obj 为 ? OrdinaryCreateFromConstructor(constructor, "%ArrayBuffer.prototype%", slots)。
  5. block 为 ? CreateByteDataBlock(byteLength)。
  6. obj.[[ArrayBufferData]] 设置为 block
  7. obj.[[ArrayBufferByteLength]] 设置为 byteLength
  8. 如果 allocatingResizableBuffertrue,则
    1. 如果无法创建由 maxByteLength 个字节组成的 Data Block block,抛出 RangeError 异常。
    2. 注:可调整大小的 ArrayBuffer 被设计为可以通过就地增长来实现。例如,如果无法预先保留虚拟内存,实现可以抛出。
    3. obj.[[ArrayBufferMaxByteLength]] 设置为 maxByteLength
  9. 返回 obj

25.1.3.2 ArrayBufferByteLength ( arrayBuffer, order )

The abstract operation ArrayBufferByteLength takes arguments arrayBuffer (一个 ArrayBuffer 或 SharedArrayBuffer,) and order (seq-cstunordered,) and returns 一个非负整数. It performs the following steps when called:

  1. 如果 IsGrowableSharedArrayBuffer(arrayBuffer) 是 true,则
    1. bufferByteLengthBlockarrayBuffer.[[ArrayBufferByteLengthData]]
    2. rawLengthGetRawBytesFromSharedBlock(bufferByteLengthBlock, 0, biguint64, true, order)。
    3. agentRecord 为周围 agentAgent Record
    4. isLittleEndianagentRecord.[[LittleEndian]]
    5. 返回 (RawBytesToNumeric(biguint64, rawLength, isLittleEndian))。
  2. 断言:IsDetachedBuffer(arrayBuffer) 是 false
  3. 返回 arrayBuffer.[[ArrayBufferByteLength]]

25.1.3.3 ArrayBufferCopyAndDetach ( arrayBuffer, newLength, preserveResizability )

The abstract operation ArrayBufferCopyAndDetach takes arguments arrayBuffer (一个 ECMAScript 语言值,), newLength (一个 ECMAScript 语言值,), and preserveResizability (preserve-resizabilityfixed-length,) and returns 要么是一个包含 ArrayBuffer 的正常完成,要么是一个抛出完成. It performs the following steps when called:

  1. 执行 ? RequireInternalSlot(arrayBuffer, [[ArrayBufferData]])。
  2. 如果 IsSharedArrayBuffer(arrayBuffer) 是 true,抛出 TypeError 异常。
  3. 如果 newLengthundefined,则
    1. newByteLengtharrayBuffer.[[ArrayBufferByteLength]]
  4. 否则,
    1. newByteLength 为 ? ToIndex(newLength)。
  5. 如果 IsDetachedBuffer(arrayBuffer) 是 true,抛出 TypeError 异常。
  6. 如果 preserveResizabilitypreserve-resizabilityIsFixedLengthArrayBuffer(arrayBuffer) 是 false,则
    1. newMaxByteLengtharrayBuffer.[[ArrayBufferMaxByteLength]]
  7. 否则,
    1. newMaxByteLengthempty
  8. 如果 arrayBuffer.[[ArrayBufferDetachKey]] 不是 undefined,抛出 TypeError 异常。
  9. newBuffer 为 ? AllocateArrayBuffer(%ArrayBuffer%, newByteLength, newMaxByteLength)。
  10. copyLengthmin(newByteLength, arrayBuffer.[[ArrayBufferByteLength]])。
  11. fromBlockarrayBuffer.[[ArrayBufferData]]
  12. toBlocknewBuffer.[[ArrayBufferData]]
  13. 执行 CopyDataBlockBytes(toBlock, 0, fromBlock, 0, copyLength)。
  14. 注:新 Data Block 的创建以及从旧 Data Block 的复制都不可被观察。实现可以将此方法实现为零复制移动或 realloc
  15. 执行 ! DetachArrayBuffer(arrayBuffer)。
  16. 返回 newBuffer

25.1.3.4 IsDetachedBuffer ( arrayBuffer )

The abstract operation IsDetachedBuffer takes argument arrayBuffer (一个 ArrayBuffer 或 SharedArrayBuffer,) and returns 一个 Boolean. It performs the following steps when called:

  1. 如果 arrayBuffer.[[ArrayBufferData]]null,返回 true
  2. 返回 false

25.1.3.5 DetachArrayBuffer ( arrayBuffer [ , key ] )

The abstract operation DetachArrayBuffer takes argument arrayBuffer (一个 ArrayBuffer,) and optional argument key (任意值,) and returns 要么是一个包含 unused正常完成,要么是一个抛出完成. It performs the following steps when called:

  1. 断言:IsSharedArrayBuffer(arrayBuffer) 是 false
  2. 如果 key 不存在,将 key 设置为 undefined
  3. 如果 arrayBuffer.[[ArrayBufferDetachKey]] 不是 key,抛出 TypeError 异常。
  4. arrayBuffer.[[ArrayBufferData]] 设置为 null
  5. arrayBuffer.[[ArrayBufferByteLength]] 设置为 0。
  6. 返回 unused
Note

分离 ArrayBuffer 实例会将作为其后备存储的 Data Block 与该实例解除关联,并将该 buffer 的字节长度设置为 0。

25.1.3.6 CloneArrayBuffer ( srcBuffer, srcByteOffset, srcLength )

The abstract operation CloneArrayBuffer takes arguments srcBuffer (一个 ArrayBuffer 或 SharedArrayBuffer,), srcByteOffset (一个非负整数,), and srcLength (一个非负整数,) and returns 要么是一个包含 ArrayBuffer 的正常完成,要么是一个抛出完成. 它创建一个新的 ArrayBuffer,其数据是 srcBuffer 的数据在从 srcByteOffset 开始并持续 srcLength 个字节的范围内的副本。 It performs the following steps when called:

  1. 断言:IsDetachedBuffer(srcBuffer) 是 false
  2. targetBuffer 为 ? AllocateArrayBuffer(%ArrayBuffer%, srcLength)。
  3. srcBlocksrcBuffer.[[ArrayBufferData]]
  4. targetBlocktargetBuffer.[[ArrayBufferData]]
  5. 执行 CopyDataBlockBytes(targetBlock, 0, srcBlock, srcByteOffset, srcLength)。
  6. 返回 targetBuffer

25.1.3.7 GetArrayBufferMaxByteLengthOption ( options )

The abstract operation GetArrayBufferMaxByteLengthOption takes argument options (一个 ECMAScript 语言值,) and returns 要么是一个包含非负整数empty正常完成,要么是一个抛出完成. It performs the following steps when called:

  1. 如果 options 不是 Object,返回 empty
  2. maxByteLength 为 ? Get(options, "maxByteLength")。
  3. 如果 maxByteLengthundefined,返回 empty
  4. 返回 ? ToIndex(maxByteLength)。

25.1.3.8 HostResizeArrayBuffer ( buffer, newByteLength )

The host-defined abstract operation HostResizeArrayBuffer takes arguments buffer (一个 ArrayBuffer,) and newByteLength (一个非负整数,) and returns 要么是一个包含 handledunhandled正常完成,要么是一个抛出完成. 它给予宿主执行 buffer实现定义调整大小的机会。如果宿主选择不处理 buffer 的调整大小,则可返回 unhandled 以采用默认行为。

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

HostResizeArrayBuffer 的默认实现是返回 NormalCompletion(unhandled)。

25.1.3.9 IsFixedLengthArrayBuffer ( arrayBuffer )

The abstract operation IsFixedLengthArrayBuffer takes argument arrayBuffer (一个 ArrayBuffer 或 SharedArrayBuffer,) and returns 一个 Boolean. It performs the following steps when called:

  1. 如果 arrayBuffer[[ArrayBufferMaxByteLength]] 内部槽,返回 false
  2. 返回 true

25.1.3.10 IsUnsignedElementType ( type )

The abstract operation IsUnsignedElementType takes argument type (一个 TypedArray 元素类型,) and returns 一个 Boolean. 它验证参数 type 是否为一个无符号 TypedArray 元素类型。 It performs the following steps when called:

  1. 如果 typeuint8uint8clampeduint16uint32biguint64 之一,返回 true
  2. 返回 false

25.1.3.11 IsUnclampedIntegerElementType ( type )

The abstract operation IsUnclampedIntegerElementType takes argument type (一个 TypedArray 元素类型,) and returns 一个 Boolean. 它验证参数 type 是否为一个 Integer TypedArray 元素类型,且不包括 uint8clamped。 It performs the following steps when called:

  1. 如果 typeint8uint8int16uint16int32uint32 之一,返回 true
  2. 返回 false

25.1.3.12 IsBigIntElementType ( type )

The abstract operation IsBigIntElementType takes argument type (一个 TypedArray 元素类型,) and returns 一个 Boolean. 它验证参数 type 是否为一个 BigInt TypedArray 元素类型。 It performs the following steps when called:

  1. 如果 typebiguint64bigint64,返回 true
  2. 返回 false

25.1.3.13 IsNoTearConfiguration ( type, order )

The abstract operation IsNoTearConfiguration takes arguments type (一个 TypedArray 元素类型,) and order (seq-cstunorderedinit,) and returns 一个 Boolean. It performs the following steps when called:

  1. 如果 IsUnclampedIntegerElementType(type) 是 true,返回 true
  2. 如果 IsBigIntElementType(type) 是 trueorder 既不是 init 也不是 unordered,返回 true
  3. 返回 false

25.1.3.14 RawBytesToNumeric ( type, rawBytes, isLittleEndian )

The abstract operation RawBytesToNumeric takes arguments type (一个 TypedArray 元素类型,), rawBytes (一个由字节值组成的 List,), and isLittleEndian (一个 Boolean,) and returns 一个 Number 或一个 BigInt. It performs the following steps when called:

  1. elementSizeTable 70 中为 Element Type type 指定的 Element Size 值。
  2. 如果 isLittleEndianfalse,反转 rawBytes 各元素的顺序。
  3. 如果 typefloat16,则
    1. valuerawBytes 的字节元素拼接后并解释为 IEEE 754-2019 binary16 值的小端 bit string 编码。
    2. 如果 value 是 NaN,返回 NaN
    3. 返回对应于 valueNumber 值
  4. 如果 typefloat32,则
    1. valuerawBytes 的字节元素拼接后并解释为 IEEE 754-2019 binary32 值的小端 bit string 编码。
    2. 如果 value 是 NaN,返回 NaN
    3. 返回对应于 valueNumber 值
  5. 如果 typefloat64,则
    1. valuerawBytes 的字节元素拼接后并解释为 IEEE 754-2019 binary64 值的小端 bit string 编码。
    2. 如果 value 是 NaN,返回 NaN
    3. 返回对应于 valueNumber 值
  6. 如果 IsUnsignedElementType(type) 是 true,则
    1. intValuerawBytes 的字节元素拼接后并解释为无符号小端二进制数 bit string 编码所得的值。
  7. 否则,
    1. intValuerawBytes 的字节元素拼接后并解释为 bit 长度为 elementSize × 8 的二进制小端二进制补码数 bit string 编码所得的值。
  8. 如果 IsBigIntElementType(type) 是 true,返回对应于 intValueBigInt 值
  9. 返回对应于 intValueNumber 值

25.1.3.15 GetRawBytesFromSharedBlock ( block, byteIndex, type, isTypedArray, order )

The abstract operation GetRawBytesFromSharedBlock takes arguments block (一个 Shared Data Block,), byteIndex (一个非负整数,), type (一个 TypedArray 元素类型,), isTypedArray (一个 Boolean,), and order (seq-cstunordered,) and returns 一个由字节值组成的 List. It performs the following steps when called:

  1. elementSizeTable 70 中为 Element Type type 指定的 Element Size 值。
  2. agentRecord 为周围 agentAgent Record
  3. executionagentRecord.[[CandidateExecution]]
  4. eventsRecordexecution.[[EventsRecords]][[AgentSignifier]]AgentSignifier() 的 Agent Events Record
  5. 如果 isTypedArraytrueIsNoTearConfiguration(type, order) 是 true,令 noTeartrue;否则令 noTearfalse
  6. rawValue 为一个长度为 elementSizeList,其元素为非确定性选择的字节值
  7. 注:在实现中,rawValue 是底层硬件上非原子或原子读取指令的结果。该非确定性是内存模型的一种语义规定,用来描述具有弱一致性的硬件的可观察行为。
  8. readEvent 为 ReadSharedMemory { [[Order]]: order, [[NoTear]]: noTear, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize }。
  9. readEvent 追加到 eventsRecord.[[EventList]]
  10. Chosen Value Record { [[Event]]: readEvent, [[ChosenValue]]: rawValue } 追加到 execution.[[ChosenValues]]
  11. 返回 rawValue

25.1.3.16 GetValueFromBuffer ( arrayBuffer, byteIndex, type, isTypedArray, order [ , isLittleEndian ] )

The abstract operation GetValueFromBuffer takes arguments arrayBuffer (一个 ArrayBuffer 或 SharedArrayBuffer,), byteIndex (一个非负整数,), type (一个 TypedArray 元素类型,), isTypedArray (一个 Boolean,), and order (seq-cstunordered,) and optional argument isLittleEndian (一个 Boolean,) and returns 一个 Number 或一个 BigInt. It performs the following steps when called:

  1. 断言:IsDetachedBuffer(arrayBuffer) 是 false
  2. 断言:arrayBuffer 中从 byteIndex 开始有足够的字节来表示一个 type 的值。
  3. blockarrayBuffer.[[ArrayBufferData]]
  4. elementSizeTable 70 中为 Element Type type 指定的 Element Size 值。
  5. 如果 IsSharedArrayBuffer(arrayBuffer) 是 true,则
    1. 断言:block 是一个 Shared Data Block
    2. rawValueGetRawBytesFromSharedBlock(block, byteIndex, type, isTypedArray, order)。
  6. 否则,
    1. rawValue 为一个 List,其元素是 block 中索引位于从 byteIndex(包含)到 byteIndex + elementSize(不包含)区间内的字节。
  7. 断言:rawValue 中元素的数量为 elementSize
  8. 如果 isLittleEndian 不存在,则
    1. agentRecord 为周围 agentAgent Record
    2. isLittleEndian 设置为 agentRecord.[[LittleEndian]]
  9. 返回 RawBytesToNumeric(type, rawValue, isLittleEndian)。

25.1.3.17 NumericToRawBytes ( type, value, isLittleEndian )

The abstract operation NumericToRawBytes takes arguments type (一个 TypedArray 元素类型,), value (一个 Number 或一个 BigInt,), and isLittleEndian (一个 Boolean,) and returns 一个由字节值组成的 List. It performs the following steps when called:

  1. 如果 typefloat16,则
    1. rawBytes 为一个 List,其元素为使用 roundTiesToEven 模式将 value 转换为 IEEE 754-2019 binary16 格式所得的 2 个字节。这些字节按小端顺序排列。如果 valueNaNrawBytes 可被设置为任意由实现选择的 IEEE 754-2019 binary16 格式 NaN 编码。实现必须始终为每个实现可区分的 NaN 值选择相同的编码。
  2. 否则如果 typefloat32,则
    1. rawBytes 为一个 List,其元素为使用 roundTiesToEven 模式将 value 转换为 IEEE 754-2019 binary32 格式所得的 4 个字节。这些字节按小端顺序排列。如果 valueNaNrawBytes 可被设置为任意由实现选择的 IEEE 754-2019 binary32 格式 NaN 编码。实现必须始终为每个实现可区分的 NaN 值选择相同的编码。
  3. 否则如果 typefloat64,则
    1. rawBytes 为一个 List,其元素为 valueIEEE 754-2019 binary64 格式编码的 8 个字节。这些字节按小端顺序排列。如果 valueNaNrawBytes 可被设置为任意由实现选择的 IEEE 754-2019 binary64 格式 NaN 编码。实现必须始终为每个实现可区分的 NaN 值选择相同的编码。
  4. 否则,
    1. nTable 70 中为 Element Type type 指定的 Element Size 值。
    2. conversionOperationTable 70 中 Element Type type 的 “Conversion Operation” 列中命名的抽象操作
    3. intValue(! conversionOperation(value))。
    4. 如果 intValue ≥ 0,则
      1. rawBytes 为一个 List,其元素为 intValuen 字节二进制编码。这些字节按小端顺序排列。
    5. 否则,
      1. rawBytes 为一个 List,其元素为 intValuen 字节二进制补码编码。这些字节按小端顺序排列。
  5. 如果 isLittleEndianfalse,反转 rawBytes 各元素的顺序。
  6. 返回 rawBytes

25.1.3.18 SetValueInBuffer ( arrayBuffer, byteIndex, type, value, isTypedArray, order [ , isLittleEndian ] )

The abstract operation SetValueInBuffer takes arguments arrayBuffer (一个 ArrayBuffer 或 SharedArrayBuffer,), byteIndex (一个非负整数,), type (一个 TypedArray 元素类型,), value (一个 Number 或一个 BigInt,), isTypedArray (一个 Boolean,), and order (seq-cstunorderedinit,) and optional argument isLittleEndian (一个 Boolean,) and returns unused. It performs the following steps when called:

  1. 断言:IsDetachedBuffer(arrayBuffer) 是 false
  2. 断言:arrayBuffer 中从 byteIndex 开始有足够的字节来表示一个 type 的值。
  3. 断言:如果 IsBigIntElementType(type) 是 true,则 value 是一个 BigInt;否则,value 是一个 Number。
  4. blockarrayBuffer.[[ArrayBufferData]]
  5. elementSizeTable 70 中为 Element Type type 指定的 Element Size 值。
  6. agentRecord 为周围 agentAgent Record
  7. 如果 isLittleEndian 不存在,则
    1. isLittleEndian 设置为 agentRecord.[[LittleEndian]]
  8. rawBytesNumericToRawBytes(type, value, isLittleEndian)。
  9. 如果 IsSharedArrayBuffer(arrayBuffer) 是 true,则
    1. executionagentRecord.[[CandidateExecution]]
    2. eventsRecordexecution.[[EventsRecords]][[AgentSignifier]]AgentSignifier() 的 Agent Events Record
    3. 如果 isTypedArraytrueIsNoTearConfiguration(type, order) 是 true,令 noTeartrue;否则令 noTearfalse
    4. 将 WriteSharedMemory { [[Order]]: order, [[NoTear]]: noTear, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes } 追加到 eventsRecord.[[EventList]]
  10. 否则,
    1. rawBytes 的各个字节存储进 block,从 block[byteIndex] 开始。
  11. 返回 unused

25.1.3.19 GetModifySetValueInBuffer ( arrayBuffer, byteIndex, type, value, op )

The abstract operation GetModifySetValueInBuffer takes arguments arrayBuffer (一个 ArrayBuffer 或一个 SharedArrayBuffer,), byteIndex (一个非负整数,), type (一个 TypedArray 元素类型,), value (一个 Number 或一个 BigInt,), and op (一个读-改-写修改函数,) and returns 一个 Number 或一个 BigInt. It performs the following steps when called:

  1. 断言:IsDetachedBuffer(arrayBuffer) 是 false
  2. 断言:arrayBuffer 中从 byteIndex 开始有足够的字节来表示一个 type 的值。
  3. 断言:如果 IsBigIntElementType(type) 是 true,则 value 是一个 BigInt;否则,value 是一个 Number。
  4. blockarrayBuffer.[[ArrayBufferData]]
  5. elementSizeTable 70 中为 Element Type type 指定的 Element Size 值。
  6. agentRecord 为周围 agentAgent Record
  7. isLittleEndianagentRecord.[[LittleEndian]]
  8. rawBytesNumericToRawBytes(type, value, isLittleEndian)。
  9. 如果 IsSharedArrayBuffer(arrayBuffer) 是 true,则
    1. executionagentRecord.[[CandidateExecution]]
    2. eventsRecordexecution.[[EventsRecords]][[AgentSignifier]]AgentSignifier() 的 Agent Events Record
    3. rawBytesRead 为一个长度为 elementSizeList,其元素为非确定性选择的字节值
    4. 注:在实现中,rawBytesRead 是底层硬件上的 load-link、load-exclusive 或读-改-写指令的一个操作数的结果。该非确定性是内存模型的一种语义规定,用来描述具有弱一致性的硬件的可观察行为。
    5. rmwEvent 为 ReadModifyWriteSharedMemory { [[Order]]: seq-cst, [[NoTear]]: true, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes, [[ModifyOp]]: op }。
    6. rmwEvent 追加到 eventsRecord.[[EventList]]
    7. Chosen Value Record { [[Event]]: rmwEvent, [[ChosenValue]]: rawBytesRead } 追加到 execution.[[ChosenValues]]
  10. 否则,
    1. rawBytesRead 为一个长度为 elementSizeList,其元素为从 block[byteIndex] 开始的 elementSize 个字节序列。
    2. rawBytesModifiedop(rawBytesRead, rawBytes)。
    3. rawBytesModified 的各个字节存储进 block,从 block[byteIndex] 开始。
  11. 返回 RawBytesToNumeric(type, rawBytesRead, isLittleEndian)。

25.1.4 ArrayBuffer 构造器

ArrayBuffer 构造器

  • %ArrayBuffer%
  • 全局对象"ArrayBuffer" 属性的初始值。
  • 当作为构造器调用时,创建并初始化一个新的 ArrayBuffer。
  • 不意图作为函数调用,并且在以这种方式调用时会抛出异常。
  • 可用作类定义中 extends 子句的值。意图继承指定 ArrayBuffer 行为的子类构造器必须包含对 ArrayBuffer 构造器super 调用,以创建并初始化具有支持 ArrayBuffer.prototype 内置方法所必需内部状态的子类实例。

25.1.4.1 ArrayBuffer ( length [ , options ] )

此函数在被调用时执行以下步骤:

  1. 如果 NewTarget 是 undefined,抛出 TypeError 异常。
  2. byteLength 为 ? ToIndex(length)。
  3. requestedMaxByteLength 为 ? GetArrayBufferMaxByteLengthOption(options)。
  4. 返回 ? AllocateArrayBuffer(NewTarget, byteLength, requestedMaxByteLength)。

25.1.5 ArrayBuffer 构造器的属性

ArrayBuffer 构造器

25.1.5.1 ArrayBuffer.isView ( arg )

此函数在被调用时执行以下步骤:

  1. 如果 arg 不是 Object,返回 false
  2. 如果 arg[[ViewedArrayBuffer]] 内部槽,返回 true
  3. 返回 false

25.1.5.2 ArrayBuffer.prototype

ArrayBuffer.prototype 的初始值是 ArrayBuffer 原型对象

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

25.1.5.3 get ArrayBuffer [ %Symbol.species% ]

ArrayBuffer[%Symbol.species%] 是一个访问器属性,其 set 访问器函数是 undefined。它的 get 访问器函数在被调用时执行以下步骤:

  1. 返回 this 值。

此函数的 "name" 属性的值为 "get [Symbol.species]"

Note

ArrayBuffer.prototype.slice ( start, end ) 通常使用其 this 值的构造器来创建派生对象。不过,子类构造器可以通过重新定义其 %Symbol.species% 属性,为 ArrayBuffer.prototype.slice ( start, end ) 方法覆盖该默认行为。

25.1.6 ArrayBuffer 原型对象的属性

ArrayBuffer 原型对象

  • %ArrayBuffer.prototype%
  • 有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%
  • 是一个普通对象
  • 没有 [[ArrayBufferData]][[ArrayBufferByteLength]] 内部槽。

25.1.6.1 get ArrayBuffer.prototype.byteLength

ArrayBuffer.prototype.byteLength 是一个访问器属性,其 set 访问器函数是 undefined。它的 get 访问器函数在被调用时执行以下步骤:

  1. objthis 值。
  2. 执行 ? RequireInternalSlot(obj, [[ArrayBufferData]])。
  3. 如果 IsSharedArrayBuffer(obj) 是 true,抛出 TypeError 异常。
  4. 如果 IsDetachedBuffer(obj) 是 true,返回 +0𝔽
  5. lengthobj.[[ArrayBufferByteLength]]
  6. 返回 𝔽(length)。

25.1.6.2 ArrayBuffer.prototype.constructor

ArrayBuffer.prototype.constructor 的初始值是 %ArrayBuffer%

25.1.6.3 get ArrayBuffer.prototype.detached

ArrayBuffer.prototype.detached 是一个访问器属性,其 set 访问器函数是 undefined。它的 get 访问器函数在被调用时执行以下步骤:

  1. objthis 值。
  2. 执行 ? RequireInternalSlot(obj, [[ArrayBufferData]])。
  3. 如果 IsSharedArrayBuffer(obj) 是 true,抛出 TypeError 异常。
  4. 返回 IsDetachedBuffer(obj)。

25.1.6.4 get ArrayBuffer.prototype.maxByteLength

ArrayBuffer.prototype.maxByteLength 是一个访问器属性,其 set 访问器函数是 undefined。它的 get 访问器函数在被调用时执行以下步骤:

  1. objthis 值。
  2. 执行 ? RequireInternalSlot(obj, [[ArrayBufferData]])。
  3. 如果 IsSharedArrayBuffer(obj) 是 true,抛出 TypeError 异常。
  4. 如果 IsDetachedBuffer(obj) 是 true,返回 +0𝔽
  5. 如果 IsFixedLengthArrayBuffer(obj) 是 true,则
    1. lengthobj.[[ArrayBufferByteLength]]
  6. 否则,
    1. lengthobj.[[ArrayBufferMaxByteLength]]
  7. 返回 𝔽(length)。

25.1.6.5 get ArrayBuffer.prototype.resizable

ArrayBuffer.prototype.resizable 是一个访问器属性,其 set 访问器函数是 undefined。它的 get 访问器函数在被调用时执行以下步骤:

  1. objthis 值。
  2. 执行 ? RequireInternalSlot(obj, [[ArrayBufferData]])。
  3. 如果 IsSharedArrayBuffer(obj) 是 true,抛出 TypeError 异常。
  4. 如果 IsFixedLengthArrayBuffer(obj) 是 false,返回 true
  5. 返回 false

25.1.6.6 ArrayBuffer.prototype.resize ( newLength )

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. 执行 ? RequireInternalSlot(obj, [[ArrayBufferMaxByteLength]])。
  3. 如果 IsSharedArrayBuffer(obj) 是 true,抛出 TypeError 异常。
  4. newByteLength 为 ? ToIndex(newLength)。
  5. 如果 IsDetachedBuffer(obj) 是 true,抛出 TypeError 异常。
  6. 如果 newByteLength > obj.[[ArrayBufferMaxByteLength]],抛出 RangeError 异常。
  7. hostHandled 为 ? HostResizeArrayBuffer(obj, newByteLength)。
  8. 如果 hostHandledhandled,返回 undefined
  9. oldBlockobj.[[ArrayBufferData]]
  10. newBlock 为 ? CreateByteDataBlock(newByteLength)。
  11. copyLengthmin(newByteLength, obj.[[ArrayBufferByteLength]])。
  12. 执行 CopyDataBlockBytes(newBlock, 0, oldBlock, 0, copyLength)。
  13. 注:新 Data Block 的创建以及从旧 Data Block 的复制都不可被观察。实现可以将此方法实现为就地增长或收缩。
  14. obj.[[ArrayBufferData]] 设置为 newBlock
  15. obj.[[ArrayBufferByteLength]] 设置为 newByteLength
  16. 返回 undefined

25.1.6.7 ArrayBuffer.prototype.slice ( start, end )

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. 执行 ? RequireInternalSlot(obj, [[ArrayBufferData]])。
  3. 如果 IsSharedArrayBuffer(obj) 是 true,抛出 TypeError 异常。
  4. 如果 IsDetachedBuffer(obj) 是 true,抛出 TypeError 异常。
  5. lenobj.[[ArrayBufferByteLength]]
  6. relativeStart 为 ? ToIntegerOrInfinity(start)。
  7. 如果 relativeStart = -∞,令 first 为 0。
  8. 否则如果 relativeStart < 0,令 firstmax(len + relativeStart, 0)。
  9. 否则,令 firstmin(relativeStart, len)。
  10. 如果 endundefined,令 relativeEndlen;否则令 relativeEnd 为 ? ToIntegerOrInfinity(end)。
  11. 如果 relativeEnd = -∞,令 final 为 0。
  12. 否则如果 relativeEnd < 0,令 finalmax(len + relativeEnd, 0)。
  13. 否则,令 finalmin(relativeEnd, len)。
  14. newLenmax(final - first, 0)。
  15. ctor 为 ? SpeciesConstructor(obj, %ArrayBuffer%)。
  16. new 为 ? Construct(ctor, « 𝔽(newLen) »)。
  17. 执行 ? RequireInternalSlot(new, [[ArrayBufferData]])。
  18. 如果 IsSharedArrayBuffer(new) 是 true,抛出 TypeError 异常。
  19. 如果 IsDetachedBuffer(new) 是 true,抛出 TypeError 异常。
  20. 如果 SameValue(new, obj) 是 true,抛出 TypeError 异常。
  21. 如果 new.[[ArrayBufferByteLength]] < newLen,抛出 TypeError 异常。
  22. 注:上述步骤的副作用可能已分离或调整了 obj 的大小。
  23. 如果 IsDetachedBuffer(obj) 是 true,抛出 TypeError 异常。
  24. fromBufobj.[[ArrayBufferData]]
  25. toBufnew.[[ArrayBufferData]]
  26. currentLenobj.[[ArrayBufferByteLength]]
  27. 如果 first < currentLen,则
    1. countmin(newLen, currentLen - first)。
    2. 执行 CopyDataBlockBytes(toBuf, 0, fromBuf, first, count)。
  28. 返回 new

25.1.6.8 ArrayBuffer.prototype.transfer ( [ newLength ] )

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. 返回 ? ArrayBufferCopyAndDetach(obj, newLength, preserve-resizability)。

25.1.6.9 ArrayBuffer.prototype.transferToFixedLength ( [ newLength ] )

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. 返回 ? ArrayBufferCopyAndDetach(obj, newLength, fixed-length)。

25.1.6.10 ArrayBuffer.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "ArrayBuffer"

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

25.1.7 ArrayBuffer 实例的属性

ArrayBuffer 实例从 ArrayBuffer 原型对象继承属性。每个 ArrayBuffer 实例都有一个 [[ArrayBufferData]] 内部槽、一个 [[ArrayBufferByteLength]] 内部槽和一个 [[ArrayBufferDetachKey]] 内部槽。可调整大小的 ArrayBuffer 实例各自都有一个 [[ArrayBufferMaxByteLength]] 内部槽。

[[ArrayBufferData]]null 的 ArrayBuffer 实例被认为是已分离的,并且所有访问或修改该 ArrayBuffer 实例中所含数据的操作符都会失败。

[[ArrayBufferDetachKey]] 被设置为 undefined 以外值的 ArrayBuffer 实例,需要所有 DetachArrayBuffer 调用都传入同一个“detach key”作为参数,否则会导致 TypeError。此内部槽只会由某些嵌入环境设置,而不会由本规范中的算法设置。

25.1.8 可调整大小 ArrayBuffer 指南

Note 1

以下是供处理可调整大小 ArrayBuffer 的 ECMAScript 程序员使用的指南。

建议尽可能在程序的部署环境中进行测试。可用物理内存的数量在不同硬件设备之间差异很大。同样,虚拟内存子系统在不同硬件设备以及操作系统之间也差异很大。一个在 64 位桌面 Web 浏览器中运行而不会出现内存不足错误的应用,可能会在 32 位移动 Web 浏览器中耗尽内存。

可调整大小 ArrayBuffer 选择 "maxByteLength" 选项的值时,建议选择应用所需的尽可能小的大小。建议 "maxByteLength" 不超过 1,073,741,824(230 字节或 1GiB)。

请注意,成功为某个特定最大大小构造可调整大小 ArrayBuffer,并不能保证未来的 resize 会成功。

Note 2

以下是供实现可调整大小 ArrayBuffer 的 ECMAScript 实现者使用的指南。

可调整大小 ArrayBuffer 可以实现为在 resize 时复制、通过预先保留虚拟内存进行就地增长,或针对构造器"maxByteLength" 选项的不同值结合使用二者。

如果宿主是多租户的(即同时运行许多 ECMAScript 应用),例如 Web 浏览器,并且其实现选择通过保留虚拟内存来实现就地增长,则建议 32 位和 64 位实现都对 "maxByteLength" ≥ 1GiB 到 1.5GiB 的值抛出。这是为了降低单个应用耗尽虚拟内存地址空间的可能性,并降低互操作性风险。

如果宿主没有虚拟内存,例如在没有 MMU 的嵌入式设备上运行,或者宿主只通过复制来实现调整大小,则它可以接受 "maxByteLength" 选项的任何 Number 值。但是,如果所请求大小的内存块永远无法分配,建议抛出 RangeError。例如,当所请求的大小大于设备上的最大可用内存量时。

25.2 SharedArrayBuffer 对象

25.2.1 固定长度和可增长的 SharedArrayBuffer 对象

固定长度 SharedArrayBuffer 是创建之后其字节长度不能改变的 SharedArrayBuffer。

可增长 SharedArrayBuffer 是创建之后其字节长度可以通过调用 SharedArrayBuffer.prototype.grow ( newLength ) 而增加的 SharedArrayBuffer。

所创建的 SharedArrayBuffer 对象种类取决于传递给 SharedArrayBuffer ( length [ , options ] ) 的参数。

25.2.2 SharedArrayBuffer 对象的抽象操作

25.2.2.1 AllocateSharedArrayBuffer ( constructor, byteLength [ , maxByteLength ] )

The abstract operation AllocateSharedArrayBuffer takes arguments constructor (一个构造器,) and byteLength (一个非负整数,) and optional argument maxByteLength (一个非负整数empty,) and returns 要么是一个包含 SharedArrayBuffer 的正常完成,要么是一个抛出完成. 它用于创建一个 SharedArrayBuffer。 It performs the following steps when called:

  1. slots 为 « [[ArrayBufferData]] »。
  2. 如果 maxByteLength 存在且 maxByteLength 不是 empty,令 allocatingGrowableBuffertrue;否则令 allocatingGrowableBufferfalse
  3. 如果 allocatingGrowableBuffertrue,则
    1. 如果 byteLength > maxByteLength,抛出 RangeError 异常。
    2. [[ArrayBufferByteLengthData]][[ArrayBufferMaxByteLength]] 追加到 slots
  4. 否则,
    1. [[ArrayBufferByteLength]] 追加到 slots
  5. obj 为 ? OrdinaryCreateFromConstructor(constructor, "%SharedArrayBuffer.prototype%", slots)。
  6. 如果 allocatingGrowableBuffertrue,令 allocLengthmaxByteLength;否则令 allocLengthbyteLength
  7. block 为 ? CreateSharedByteDataBlock(allocLength)。
  8. obj.[[ArrayBufferData]] 设置为 block
  9. 如果 allocatingGrowableBuffertrue,则
    1. 断言:byteLengthmaxByteLength
    2. byteLengthBlock 为 ? CreateSharedByteDataBlock(8)。
    3. 执行 SetValueInBuffer(byteLengthBlock, 0, biguint64, (byteLength), true, seq-cst)。
    4. obj.[[ArrayBufferByteLengthData]] 设置为 byteLengthBlock
    5. obj.[[ArrayBufferMaxByteLength]] 设置为 maxByteLength
  10. 否则,
    1. obj.[[ArrayBufferByteLength]] 设置为 byteLength
  11. 返回 obj

25.2.2.2 IsSharedArrayBuffer ( obj )

The abstract operation IsSharedArrayBuffer takes argument obj (一个 ArrayBuffer 或一个 SharedArrayBuffer,) and returns 一个 Boolean. 它测试一个对象是否为 SharedArrayBuffer。 It performs the following steps when called:

  1. 如果 obj.[[ArrayBufferData]] 是一个 Shared Data Block,返回 true
  2. 返回 false

25.2.2.3 IsGrowableSharedArrayBuffer ( obj )

The abstract operation IsGrowableSharedArrayBuffer takes argument obj (一个 ArrayBuffer 或一个 SharedArrayBuffer,) and returns 一个 Boolean. 它测试一个对象是否为可增长的 SharedArrayBuffer。 It performs the following steps when called:

  1. 如果 IsSharedArrayBuffer(obj) 是 trueobj[[ArrayBufferByteLengthData]] 内部槽,返回 true
  2. 返回 false

25.2.2.4 HostGrowSharedArrayBuffer ( buffer, newByteLength )

The host-defined abstract operation HostGrowSharedArrayBuffer takes arguments buffer (一个 SharedArrayBuffer,) and newByteLength (一个非负整数,) and returns 要么是一个包含 handledunhandled正常完成,要么是一个抛出完成. 它给予宿主执行 buffer实现定义增长的机会。如果宿主选择不处理 buffer 的增长,则可返回 unhandled 以采用默认行为。

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

  • 如果该抽象操作没有以 unhandled 正常完成,且 newByteLength < buffer 的当前字节长度或 newByteLength > buffer.[[ArrayBufferMaxByteLength]],则抛出 RangeError 异常。
  • agentRecord 为周围 agentAgent Record。令 isLittleEndianagentRecord.[[LittleEndian]]。如果该抽象操作handled 正常完成,则向周围 agent候选执行添加一个 WriteSharedMemory 或 ReadModifyWriteSharedMemory 事件,其 [[Order]]seq-cst[[Payload]]NumericToRawBytes(biguint64, newByteLength, isLittleEndian),[[Block]]buffer.[[ArrayBufferByteLengthData]][[ByteIndex]] 为 0,且 [[ElementSize]] 为 8,使得对 SharedArrayBuffer.prototype.grow ( newLength ) 的竞争调用不会“丢失”,即不会静默地什么也不做。
Note

上面的第二项要求有意对如何或何时读取 buffer 的当前字节长度保持模糊。因为字节长度必须通过底层硬件上的原子读-改-写操作来更新,所以使用 load-link/store-conditional 或 load-exclusive/store-exclusive 指令对的架构可能希望让成对指令在指令流中彼此接近。因此,SharedArrayBuffer.prototype.grow ( newLength ) 本身在调用 HostGrowSharedArrayBuffer 之前不会对 newByteLength 执行边界检查,也没有关于何时读取当前字节长度的要求。

这与 HostResizeArrayBuffer 形成对比,后者保证 0 ≤ newByteLengthbuffer.[[ArrayBufferMaxByteLength]]

HostGrowSharedArrayBuffer 的默认实现是返回 NormalCompletion(unhandled)。

25.2.3 SharedArrayBuffer 构造器

SharedArrayBuffer 构造器

  • %SharedArrayBuffer%
  • 如果全局对象"SharedArrayBuffer" 属性存在(见下文),则它是该属性的初始值。
  • 当作为构造器调用时,创建并初始化一个新的 SharedArrayBuffer。
  • 不意图作为函数调用,并且在以这种方式调用时会抛出异常。
  • 可用作类定义中 extends 子句的值。意图继承指定 SharedArrayBuffer 行为的子类构造器必须包含对 SharedArrayBuffer 构造器super 调用,以创建并初始化具有支持 SharedArrayBuffer.prototype 内置方法所必需内部状态的子类实例。

每当宿主不提供对 SharedArrayBuffer 的并发访问时,它可以省略全局对象"SharedArrayBuffer" 属性。

Note

ArrayBuffer 不同,SharedArrayBuffer 不能变为已分离,并且其内部 [[ArrayBufferData]] 槽永远不是 null

25.2.3.1 SharedArrayBuffer ( length [ , options ] )

此函数在被调用时执行以下步骤:

  1. 如果 NewTarget 是 undefined,抛出 TypeError 异常。
  2. byteLength 为 ? ToIndex(length)。
  3. requestedMaxByteLength 为 ? GetArrayBufferMaxByteLengthOption(options)。
  4. 返回 ? AllocateSharedArrayBuffer(NewTarget, byteLength, requestedMaxByteLength)。

25.2.4 SharedArrayBuffer 构造器的属性

SharedArrayBuffer 构造器

25.2.4.1 SharedArrayBuffer.prototype

SharedArrayBuffer.prototype 的初始值是 SharedArrayBuffer 原型对象

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

25.2.4.2 get SharedArrayBuffer [ %Symbol.species% ]

SharedArrayBuffer[%Symbol.species%] 是一个访问器属性,其 set 访问器函数是 undefined。它的 get 访问器函数在被调用时执行以下步骤:

  1. 返回 this 值。

此函数的 "name" 属性的值为 "get [Symbol.species]"

25.2.5 SharedArrayBuffer 原型对象的属性

SharedArrayBuffer 原型对象

  • %SharedArrayBuffer.prototype%
  • 有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%
  • 是一个普通对象
  • 没有 [[ArrayBufferData]][[ArrayBufferByteLength]] 内部槽。

25.2.5.1 get SharedArrayBuffer.prototype.byteLength

SharedArrayBuffer.prototype.byteLength 是一个访问器属性,其 set 访问器函数是 undefined。它的 get 访问器函数在被调用时执行以下步骤:

  1. objthis 值。
  2. 执行 ? RequireInternalSlot(obj, [[ArrayBufferData]])。
  3. 如果 IsSharedArrayBuffer(obj) 是 false,抛出 TypeError 异常。
  4. lengthArrayBufferByteLength(obj, seq-cst)。
  5. 返回 𝔽(length)。

25.2.5.2 SharedArrayBuffer.prototype.constructor

SharedArrayBuffer.prototype.constructor 的初始值是 %SharedArrayBuffer%

25.2.5.3 SharedArrayBuffer.prototype.grow ( newLength )

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. 执行 ? RequireInternalSlot(obj, [[ArrayBufferMaxByteLength]])。
  3. 如果 IsSharedArrayBuffer(obj) 是 false,抛出 TypeError 异常。
  4. newByteLength 为 ? ToIndex(newLength)。
  5. hostHandled 为 ? HostGrowSharedArrayBuffer(obj, newByteLength)。
  6. 如果 hostHandledhandled,返回 undefined
  7. agentRecord 为周围 agentAgent Record
  8. isLittleEndianagentRecord.[[LittleEndian]]
  9. byteLengthBlockobj.[[ArrayBufferByteLengthData]]
  10. currentByteLengthRawBytesGetRawBytesFromSharedBlock(byteLengthBlock, 0, biguint64, true, seq-cst)。
  11. newByteLengthRawBytesNumericToRawBytes(biguint64, (newByteLength), isLittleEndian)。
  12. 重复,
    1. 注:这是一个 compare-and-exchange 循环,用于确保同一 buffer 的并行竞争增长是全序的、不会丢失,也不会静默地什么也不做。如果它能够尝试无竞争地增长,则循环退出。
    2. currentByteLength(RawBytesToNumeric(biguint64, currentByteLengthRawBytes, isLittleEndian))。
    3. 如果 newByteLength = currentByteLength,返回 undefined
    4. 如果 newByteLength < currentByteLengthnewByteLength > obj.[[ArrayBufferMaxByteLength]],抛出 RangeError 异常。
    5. byteLengthDeltanewByteLength - currentByteLength
    6. 如果不可能创建由 byteLengthDelta 个字节组成的新 Shared Data Block 值,抛出 RangeError 异常。
    7. 注:这里不会构造并使用新的 Shared Data Block可增长 SharedArrayBuffer 的可观察行为是通过在构造时分配最大大小的 Shared Data Block 来指定的,而此步骤捕获了耗尽内存的实现必须抛出 RangeError 的要求。
    8. readByteLengthRawBytesAtomicCompareExchangeInSharedBlock(byteLengthBlock, 0, 8, currentByteLengthRawBytes, newByteLengthRawBytes)。
    9. 如果 ByteListEqual(readByteLengthRawBytes, currentByteLengthRawBytes) 是 true,返回 undefined
    10. currentByteLengthRawBytes 设置为 readByteLengthRawBytes
Note

禁止 compare-exchange 在更新长度时发生虚假失败。如果新长度的边界检查通过,且实现没有内存不足,则总是会向候选执行中添加一个 ReadModifyWriteSharedMemory 事件(即一次成功的 compare-exchange)。

对 SharedArrayBuffer.prototype.grow 的并行调用是全序的。例如,考虑两个竞争调用:sab.grow(10)sab.grow(20)。这两个调用之一保证会赢得竞争。即使 sab.grow(20) 先发生,sab.grow(10) 的调用也永远不会收缩 sab;在这种情况下,它会改为抛出 RangeError。

25.2.5.4 get SharedArrayBuffer.prototype.growable

SharedArrayBuffer.prototype.growable 是一个访问器属性,其 set 访问器函数是 undefined。它的 get 访问器函数在被调用时执行以下步骤:

  1. objthis 值。
  2. 执行 ? RequireInternalSlot(obj, [[ArrayBufferData]])。
  3. 如果 IsSharedArrayBuffer(obj) 是 false,抛出 TypeError 异常。
  4. 如果 IsFixedLengthArrayBuffer(obj) 是 false,返回 true
  5. 返回 false

25.2.5.5 get SharedArrayBuffer.prototype.maxByteLength

SharedArrayBuffer.prototype.maxByteLength 是一个访问器属性,其 set 访问器函数是 undefined。它的 get 访问器函数在被调用时执行以下步骤:

  1. objthis 值。
  2. 执行 ? RequireInternalSlot(obj, [[ArrayBufferData]])。
  3. 如果 IsSharedArrayBuffer(obj) 是 false,抛出 TypeError 异常。
  4. 如果 IsFixedLengthArrayBuffer(obj) 是 true,则
    1. lengthobj.[[ArrayBufferByteLength]]
  5. 否则,
    1. lengthobj.[[ArrayBufferMaxByteLength]]
  6. 返回 𝔽(length)。

25.2.5.6 SharedArrayBuffer.prototype.slice ( start, end )

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. 执行 ? RequireInternalSlot(obj, [[ArrayBufferData]])。
  3. 如果 IsSharedArrayBuffer(obj) 是 false,抛出 TypeError 异常。
  4. lenArrayBufferByteLength(obj, seq-cst)。
  5. relativeStart 为 ? ToIntegerOrInfinity(start)。
  6. 如果 relativeStart = -∞,令 first 为 0。
  7. 否则如果 relativeStart < 0,令 firstmax(len + relativeStart, 0)。
  8. 否则,令 firstmin(relativeStart, len)。
  9. 如果 endundefined,令 relativeEndlen;否则令 relativeEnd 为 ? ToIntegerOrInfinity(end)。
  10. 如果 relativeEnd = -∞,令 final 为 0。
  11. 否则如果 relativeEnd < 0,令 finalmax(len + relativeEnd, 0)。
  12. 否则,令 finalmin(relativeEnd, len)。
  13. newLenmax(final - first, 0)。
  14. ctor 为 ? SpeciesConstructor(obj, %SharedArrayBuffer%)。
  15. new 为 ? Construct(ctor, « 𝔽(newLen) »)。
  16. 执行 ? RequireInternalSlot(new, [[ArrayBufferData]])。
  17. 如果 IsSharedArrayBuffer(new) 是 false,抛出 TypeError 异常。
  18. 如果 new.[[ArrayBufferData]]obj.[[ArrayBufferData]],抛出 TypeError 异常。
  19. 如果 ArrayBufferByteLength(new, seq-cst) < newLen,抛出 TypeError 异常。
  20. fromBufobj.[[ArrayBufferData]]
  21. toBufnew.[[ArrayBufferData]]
  22. 执行 CopyDataBlockBytes(toBuf, 0, fromBuf, first, newLen)。
  23. 返回 new

25.2.5.7 SharedArrayBuffer.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "SharedArrayBuffer"

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

25.2.6 SharedArrayBuffer 实例的属性

SharedArrayBuffer 实例从 SharedArrayBuffer 原型对象继承属性。每个 SharedArrayBuffer 实例都有一个 [[ArrayBufferData]] 内部槽。不可增长的 SharedArrayBuffer 实例各自都有一个 [[ArrayBufferByteLength]] 内部槽。可增长的 SharedArrayBuffer 实例各自都有一个 [[ArrayBufferByteLengthData]] 内部槽和一个 [[ArrayBufferMaxByteLength]] 内部槽。

Note

SharedArrayBuffer 实例不同于 ArrayBuffer 实例,它们永远不会被分离。

25.2.7 可增长 SharedArrayBuffer 指南

Note 1

以下是供处理可增长 SharedArrayBuffer 的 ECMAScript 程序员使用的指南。

建议尽可能在程序的部署环境中进行测试。可用物理内存的数量在不同硬件设备之间差异很大。同样,虚拟内存子系统在不同硬件设备以及操作系统之间也差异很大。一个在 64 位桌面 Web 浏览器中运行而不会出现内存不足错误的应用,可能会在 32 位移动 Web 浏览器中耗尽内存。

可增长 SharedArrayBuffer 选择 "maxByteLength" 选项的值时,建议选择应用所需的尽可能小的大小。建议 "maxByteLength" 不超过 1073741824,即 1GiB。

请注意,成功为某个特定最大大小构造可增长 SharedArrayBuffer,并不能保证未来的 grow 会成功。

并非所有对可增长 SharedArrayBuffer 长度的加载都是同步性的 seq-cst 加载。用于整数索引属性访问(例如 u8[idx])边界检查的长度加载不是同步性的。通常,在没有显式同步的情况下,某次属性访问在边界内并不意味着同一 agent 中后续属性访问也在边界内。相比之下,通过 SharedArrayBuffer、%TypedArray%.prototype 和 DataView.prototype 上的 lengthbyteLength getter 对长度的显式加载是同步性的。由内置方法为了检查 TypedArray 是否完全越界而执行的长度加载也是同步性的。

Note 2

以下是供实现可增长 SharedArrayBuffer 的 ECMAScript 实现者使用的指南。

建议将可增长 SharedArrayBuffer 实现为通过预先保留虚拟内存进行就地增长。

因为 grow 操作可能与可增长 SharedArrayBuffer 上的内存访问并行发生,所以内存模型的约束要求即使 unordered 访问也不会“撕裂”(其值的位不会被混合)。实践中,这意味着可增长 SharedArrayBuffer 的底层数据块不能在不停顿整个世界的情况下通过复制来增长。不建议将停顿整个世界作为实现策略,因为它会引入一个序列化点并且速度很慢。

增长出来的内存从创建的那一刻起就必须表现为已清零,包括对任何并行的竞争访问也是如此。这可以通过按需填零的虚拟内存页实现,或者在手动清零内存时通过仔细同步实现。

可增长 SharedArrayBufferTypedArray 视图上的整数索引属性访问意图能够像不可增长 SharedArrayBufferTypedArray 视图上的访问一样被优化,因为整数索引属性加载不会在底层 buffer 的长度上同步(见上文程序员指南)。例如,属性访问的边界检查仍可被提升到循环之外。

实践中,在没有虚拟内存的宿主上,例如在没有 MMU 的嵌入式设备上运行的宿主,很难通过复制来实现可增长 SharedArrayBuffer。此类宿主可增长 SharedArrayBuffer 的内存使用行为可能与具有虚拟内存的宿主显著不同。此类宿主应向用户清楚传达内存使用预期。

25.3 DataView 对象

25.3.1 DataView 对象的抽象操作

25.3.1.1 DataView With Buffer Witness Records

DataView With Buffer Witness Record 是一个 Record 值,用于封装一个 DataView 以及被查看 buffer 的缓存字节长度。当被查看 buffer 是可增长 SharedArrayBuffer 时,它用于帮助确保只存在一个针对字节长度数据块的 ReadSharedMemory 事件。

DataView With Buffer Witness Record 具有 Table 72 中列出的字段。

Table 72: DataView With Buffer Witness Record 字段
字段名 含义
[[Object]] 一个 DataView 加载其 buffer 字节长度的 DataView 对象。
[[CachedBufferByteLength]] 一个非负整数detached 创建该 Record 时对象的 [[ViewedArrayBuffer]] 的字节长度。

25.3.1.2 MakeDataViewWithBufferWitnessRecord ( obj, order )

The abstract operation MakeDataViewWithBufferWitnessRecord takes arguments obj (一个 DataView,) and order (seq-cstunordered,) and returns 一个 DataView With Buffer Witness Record. It performs the following steps when called:

  1. bufferobj.[[ViewedArrayBuffer]]
  2. 如果 IsDetachedBuffer(buffer) 是 true,则
    1. byteLengthdetached
  3. 否则,
    1. byteLengthArrayBufferByteLength(buffer, order)。
  4. 返回 DataView With Buffer Witness Record { [[Object]]: obj, [[CachedBufferByteLength]]: byteLength }。

25.3.1.3 GetViewByteLength ( viewRecord )

The abstract operation GetViewByteLength takes argument viewRecord (一个 DataView With Buffer Witness Record,) and returns 一个非负整数. It performs the following steps when called:

  1. 断言:IsViewOutOfBounds(viewRecord) 是 false
  2. viewviewRecord.[[Object]]
  3. 如果 view.[[ByteLength]] 不是 auto,返回 view.[[ByteLength]]
  4. 断言:IsFixedLengthArrayBuffer(view.[[ViewedArrayBuffer]]) 是 false
  5. byteOffsetview.[[ByteOffset]]
  6. byteLengthviewRecord.[[CachedBufferByteLength]]
  7. 断言:byteLength 不是 detached
  8. 返回 byteLength - byteOffset

25.3.1.4 IsViewOutOfBounds ( viewRecord )

The abstract operation IsViewOutOfBounds takes argument viewRecord (一个 DataView With Buffer Witness Record,) and returns 一个 Boolean. It performs the following steps when called:

  1. viewviewRecord.[[Object]]
  2. bufferByteLengthviewRecord.[[CachedBufferByteLength]]
  3. 如果 IsDetachedBuffer(view.[[ViewedArrayBuffer]]) 是 true,则
    1. 断言:bufferByteLengthdetached
    2. 返回 true
  4. 断言:bufferByteLength 是一个非负整数
  5. byteOffsetStartview.[[ByteOffset]]
  6. 如果 view.[[ByteLength]]auto,则
    1. byteOffsetEndbufferByteLength
  7. 否则,
    1. byteOffsetEndbyteOffsetStart + view.[[ByteLength]]
  8. 注:[[ByteOffset]]bufferByteLength 的 0 长度 DataView 不被视为越界。
  9. 如果 byteOffsetStart > bufferByteLengthbyteOffsetEnd > bufferByteLength,返回 true
  10. 返回 false

25.3.1.5 GetViewValue ( view, requestIndex, isLittleEndian, type )

The abstract operation GetViewValue takes arguments view (一个 ECMAScript 语言值,), requestIndex (一个 ECMAScript 语言值,), isLittleEndian (一个 ECMAScript 语言值,), and type (一个 TypedArray 元素类型,) and returns 要么是一个包含 Number 或 BigInt 的正常完成,要么是一个抛出完成. 它由 DataView 实例上的函数用于从该 view 的 buffer 中检索值。 It performs the following steps when called:

  1. 执行 ? RequireInternalSlot(view, [[DataView]])。
  2. 断言:view[[ViewedArrayBuffer]] 内部槽。
  3. getIndex 为 ? ToIndex(requestIndex)。
  4. isLittleEndian 设置为 ToBoolean(isLittleEndian)。
  5. viewOffsetview.[[ByteOffset]]
  6. viewRecordMakeDataViewWithBufferWitnessRecord(view, unordered)。
  7. 注:当 view 的后备 buffer 是可增长 SharedArrayBuffer 时,边界检查不是同步操作。
  8. 如果 IsViewOutOfBounds(viewRecord) 是 true,抛出 TypeError 异常。
  9. viewSizeGetViewByteLength(viewRecord)。
  10. elementSizeTable 70 中为 Element Type type 指定的 Element Size 值。
  11. 如果 getIndex + elementSize > viewSize,抛出 RangeError 异常。
  12. bufferIndexgetIndex + viewOffset
  13. 返回 GetValueFromBuffer(view.[[ViewedArrayBuffer]], bufferIndex, type, false, unordered, isLittleEndian)。

25.3.1.6 SetViewValue ( view, requestIndex, isLittleEndian, type, value )

The abstract operation SetViewValue takes arguments view (一个 ECMAScript 语言值,), requestIndex (一个 ECMAScript 语言值,), isLittleEndian (一个 ECMAScript 语言值,), type (一个 TypedArray 元素类型,), and value (一个 ECMAScript 语言值,) and returns 要么是一个包含 undefined正常完成,要么是一个抛出完成. 它由 DataView 实例上的函数用于将值存储进该 view 的 buffer。 It performs the following steps when called:

  1. 执行 ? RequireInternalSlot(view, [[DataView]])。
  2. 断言:view[[ViewedArrayBuffer]] 内部槽。
  3. getIndex 为 ? ToIndex(requestIndex)。
  4. 如果 IsBigIntElementType(type) 是 true,令 numberValue 为 ? ToBigInt(value)。
  5. 否则,令 numberValue 为 ? ToNumber(value)。
  6. isLittleEndian 设置为 ToBoolean(isLittleEndian)。
  7. viewOffsetview.[[ByteOffset]]
  8. viewRecordMakeDataViewWithBufferWitnessRecord(view, unordered)。
  9. 注:当 view 的后备 buffer 是可增长 SharedArrayBuffer 时,边界检查不是同步操作。
  10. 如果 IsViewOutOfBounds(viewRecord) 是 true,抛出 TypeError 异常。
  11. viewSizeGetViewByteLength(viewRecord)。
  12. elementSizeTable 70 中为 Element Type type 指定的 Element Size 值。
  13. 如果 getIndex + elementSize > viewSize,抛出 RangeError 异常。
  14. bufferIndexgetIndex + viewOffset
  15. 执行 SetValueInBuffer(view.[[ViewedArrayBuffer]], bufferIndex, type, numberValue, false, unordered, isLittleEndian)。
  16. 返回 undefined

25.3.2 DataView 构造器

DataView 构造器

  • %DataView%
  • 全局对象"DataView" 属性的初始值。
  • 当作为构造器调用时,创建并初始化一个新的 DataView。
  • 不意图作为函数调用,并且在以这种方式调用时会抛出异常。
  • 可用作类定义中 extends 子句的值。意图继承指定 DataView 行为的子类构造器必须包含对 DataView 构造器super 调用,以创建并初始化具有支持 DataView.prototype 内置方法所必需内部状态的子类实例。

25.3.2.1 DataView ( buffer [ , byteOffset [ , byteLength ] ] )

此函数在被调用时执行以下步骤:

  1. 如果 NewTarget 是 undefined,抛出 TypeError 异常。
  2. 执行 ? RequireInternalSlot(buffer, [[ArrayBufferData]])。
  3. offset 为 ? ToIndex(byteOffset)。
  4. 如果 IsDetachedBuffer(buffer) 是 true,抛出 TypeError 异常。
  5. bufferByteLengthArrayBufferByteLength(buffer, seq-cst)。
  6. 如果 offset > bufferByteLength,抛出 RangeError 异常。
  7. bufferIsFixedLengthIsFixedLengthArrayBuffer(buffer)。
  8. 如果 byteLengthundefined,则
    1. 如果 bufferIsFixedLengthtrue,则
      1. viewByteLengthbufferByteLength - offset
    2. 否则,
      1. viewByteLengthauto
  9. 否则,
    1. viewByteLength 为 ? ToIndex(byteLength)。
    2. 如果 offset + viewByteLength > bufferByteLength,抛出 RangeError 异常。
  10. obj 为 ? OrdinaryCreateFromConstructor(NewTarget, "%DataView.prototype%", « [[DataView]], [[ViewedArrayBuffer]], [[ByteLength]], [[ByteOffset]] »)。
  11. 如果 IsDetachedBuffer(buffer) 是 true,抛出 TypeError 异常。
  12. bufferByteLength 设置为 ArrayBufferByteLength(buffer, seq-cst)。
  13. 如果 offset > bufferByteLength,抛出 RangeError 异常。
  14. 如果 byteLength 不是 undefined,则
    1. 如果 offset + viewByteLength > bufferByteLength,抛出 RangeError 异常。
  15. obj.[[ViewedArrayBuffer]] 设置为 buffer
  16. obj.[[ByteLength]] 设置为 viewByteLength
  17. obj.[[ByteOffset]] 设置为 offset
  18. 返回 obj

25.3.3 DataView 构造器的属性

DataView 构造器

25.3.3.1 DataView.prototype

DataView.prototype 的初始值是 DataView 原型对象

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

25.3.4 DataView 原型对象的属性

DataView 原型对象

  • %DataView.prototype%
  • 有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%
  • 是一个普通对象
  • 没有 [[DataView]][[ViewedArrayBuffer]][[ByteLength]][[ByteOffset]] 内部槽。

25.3.4.1 get DataView.prototype.buffer

DataView.prototype.buffer 是一个访问器属性,其 set 访问器函数是 undefined。它的 get 访问器函数在被调用时执行以下步骤:

  1. objthis 值。
  2. 执行 ? RequireInternalSlot(obj, [[DataView]])。
  3. 断言:obj[[ViewedArrayBuffer]] 内部槽。
  4. bufferobj.[[ViewedArrayBuffer]]
  5. 返回 buffer

25.3.4.2 get DataView.prototype.byteLength

DataView.prototype.byteLength 是一个访问器属性,其 set 访问器函数是 undefined。它的 get 访问器函数在被调用时执行以下步骤:

  1. objthis 值。
  2. 执行 ? RequireInternalSlot(obj, [[DataView]])。
  3. 断言:obj[[ViewedArrayBuffer]] 内部槽。
  4. viewRecordMakeDataViewWithBufferWitnessRecord(obj, seq-cst)。
  5. 如果 IsViewOutOfBounds(viewRecord) 是 true,抛出 TypeError 异常。
  6. sizeGetViewByteLength(viewRecord)。
  7. 返回 𝔽(size)。

25.3.4.3 get DataView.prototype.byteOffset

DataView.prototype.byteOffset 是一个访问器属性,其 set 访问器函数是 undefined。它的 get 访问器函数在被调用时执行以下步骤:

  1. objthis 值。
  2. 执行 ? RequireInternalSlot(obj, [[DataView]])。
  3. 断言:obj[[ViewedArrayBuffer]] 内部槽。
  4. viewRecordMakeDataViewWithBufferWitnessRecord(obj, seq-cst)。
  5. 如果 IsViewOutOfBounds(viewRecord) 是 true,抛出 TypeError 异常。
  6. offsetobj.[[ByteOffset]]
  7. 返回 𝔽(offset)。

25.3.4.4 DataView.prototype.constructor

DataView.prototype.constructor 的初始值是 %DataView%

25.3.4.5 DataView.prototype.getBigInt64 ( byteOffset [ , littleEndian ] )

此方法在被调用时执行以下步骤:

  1. viewthis 值。
  2. 返回 ? GetViewValue(view, byteOffset, littleEndian, bigint64)。

25.3.4.6 DataView.prototype.getBigUint64 ( byteOffset [ , littleEndian ] )

此方法在被调用时执行以下步骤:

  1. viewthis 值。
  2. 返回 ? GetViewValue(view, byteOffset, littleEndian, biguint64)。

25.3.4.7 DataView.prototype.getFloat16 ( byteOffset [ , littleEndian ] )

此方法在被调用时执行以下步骤:

  1. viewthis 值。
  2. 如果 littleEndian 不存在,将 littleEndian 设置为 false
  3. 返回 ? GetViewValue(view, byteOffset, littleEndian, float16)。

25.3.4.8 DataView.prototype.getFloat32 ( byteOffset [ , littleEndian ] )

此方法在被调用时执行以下步骤:

  1. viewthis 值。
  2. 如果 littleEndian 不存在,将 littleEndian 设置为 false
  3. 返回 ? GetViewValue(view, byteOffset, littleEndian, float32)。

25.3.4.9 DataView.prototype.getFloat64 ( byteOffset [ , littleEndian ] )

此方法在被调用时执行以下步骤:

  1. viewthis 值。
  2. 如果 littleEndian 不存在,将 littleEndian 设置为 false
  3. 返回 ? GetViewValue(view, byteOffset, littleEndian, float64)。

25.3.4.10 DataView.prototype.getInt8 ( byteOffset )

此方法在被调用时执行以下步骤:

  1. viewthis 值。
  2. 返回 ? GetViewValue(view, byteOffset, true, int8)。

25.3.4.11 DataView.prototype.getInt16 ( byteOffset [ , littleEndian ] )

此方法在被调用时执行以下步骤:

  1. viewthis 值。
  2. 如果 littleEndian 不存在,将 littleEndian 设置为 false
  3. 返回 ? GetViewValue(view, byteOffset, littleEndian, int16)。

25.3.4.12 DataView.prototype.getInt32 ( byteOffset [ , littleEndian ] )

此方法在被调用时执行以下步骤:

  1. viewthis 值。
  2. 如果 littleEndian 不存在,将 littleEndian 设置为 false
  3. 返回 ? GetViewValue(view, byteOffset, littleEndian, int32)。

25.3.4.13 DataView.prototype.getUint8 ( byteOffset )

此方法在被调用时执行以下步骤:

  1. viewthis 值。
  2. 返回 ? GetViewValue(view, byteOffset, true, uint8)。

25.3.4.14 DataView.prototype.getUint16 ( byteOffset [ , littleEndian ] )

此方法在被调用时执行以下步骤:

  1. viewthis 值。
  2. 如果 littleEndian 不存在,将 littleEndian 设置为 false
  3. 返回 ? GetViewValue(view, byteOffset, littleEndian, uint16)。

25.3.4.15 DataView.prototype.getUint32 ( byteOffset [ , littleEndian ] )

此方法在被调用时执行以下步骤:

  1. viewthis 值。
  2. 如果 littleEndian 不存在,将 littleEndian 设置为 false
  3. 返回 ? GetViewValue(view, byteOffset, littleEndian, uint32)。

25.3.4.16 DataView.prototype.setBigInt64 ( byteOffset, value [ , littleEndian ] )

此方法在被调用时执行以下步骤:

  1. viewthis 值。
  2. 返回 ? SetViewValue(view, byteOffset, littleEndian, bigint64, value)。

25.3.4.17 DataView.prototype.setBigUint64 ( byteOffset, value [ , littleEndian ] )

此方法在被调用时执行以下步骤:

  1. viewthis 值。
  2. 返回 ? SetViewValue(view, byteOffset, littleEndian, biguint64, value)。

25.3.4.18 DataView.prototype.setFloat16 ( byteOffset, value [ , littleEndian ] )

此方法在被调用时执行以下步骤:

  1. viewthis 值。
  2. 如果 littleEndian 不存在,将 littleEndian 设置为 false
  3. 返回 ? SetViewValue(view, byteOffset, littleEndian, float16, value)。

25.3.4.19 DataView.prototype.setFloat32 ( byteOffset, value [ , littleEndian ] )

此方法在被调用时执行以下步骤:

  1. viewthis 值。
  2. 如果 littleEndian 不存在,将 littleEndian 设置为 false
  3. 返回 ? SetViewValue(view, byteOffset, littleEndian, float32, value)。

25.3.4.20 DataView.prototype.setFloat64 ( byteOffset, value [ , littleEndian ] )

此方法在被调用时执行以下步骤:

  1. viewthis 值。
  2. 如果 littleEndian 不存在,将 littleEndian 设置为 false
  3. 返回 ? SetViewValue(view, byteOffset, littleEndian, float64, value)。

25.3.4.21 DataView.prototype.setInt8 ( byteOffset, value )

此方法在被调用时执行以下步骤:

  1. viewthis 值。
  2. 返回 ? SetViewValue(view, byteOffset, true, int8, value)。

25.3.4.22 DataView.prototype.setInt16 ( byteOffset, value [ , littleEndian ] )

此方法在被调用时执行以下步骤:

  1. viewthis 值。
  2. 如果 littleEndian 不存在,将 littleEndian 设置为 false
  3. 返回 ? SetViewValue(view, byteOffset, littleEndian, int16, value)。

25.3.4.23 DataView.prototype.setInt32 ( byteOffset, value [ , littleEndian ] )

此方法在被调用时执行以下步骤:

  1. viewthis 值。
  2. 如果 littleEndian 不存在,将 littleEndian 设置为 false
  3. 返回 ? SetViewValue(view, byteOffset, littleEndian, int32, value)。

25.3.4.24 DataView.prototype.setUint8 ( byteOffset, value )

此方法在被调用时执行以下步骤:

  1. viewthis 值。
  2. 返回 ? SetViewValue(view, byteOffset, true, uint8, value)。

25.3.4.25 DataView.prototype.setUint16 ( byteOffset, value [ , littleEndian ] )

此方法在被调用时执行以下步骤:

  1. viewthis 值。
  2. 如果 littleEndian 不存在,将 littleEndian 设置为 false
  3. 返回 ? SetViewValue(view, byteOffset, littleEndian, uint16, value)。

25.3.4.26 DataView.prototype.setUint32 ( byteOffset, value [ , littleEndian ] )

此方法在被调用时执行以下步骤:

  1. viewthis 值。
  2. 如果 littleEndian 不存在,将 littleEndian 设置为 false
  3. 返回 ? SetViewValue(view, byteOffset, littleEndian, uint32, value)。

25.3.4.27 DataView.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "DataView"

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

25.3.5 DataView 实例的属性

DataView 实例是从 DataView 原型对象继承属性的普通对象。每个 DataView 实例都有 [[DataView]][[ViewedArrayBuffer]][[ByteLength]][[ByteOffset]] 内部槽。

Note

[[DataView]] 内部槽的值在本规范中并未使用。规范中仅使用该内部槽的存在来识别使用 DataView 构造器创建的对象。

25.4 Atomics 对象

Atomics 对象:

  • %Atomics%
  • 全局对象"Atomics" 属性的初始值。
  • 是一个普通对象
  • 有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%
  • 没有 [[Construct]] 内部方法;不能与 new 运算符一起用作构造器
  • 没有 [[Call]] 内部方法;不能作为函数调用。

Atomics 对象提供一些函数,这些函数以不可分割(原子)的方式操作共享内存数组单元,也提供一些使 agents 能够等待并派发原始事件的函数。当以有纪律的方式使用时,Atomics 函数允许通过共享内存通信的多 agent 程序即使在并行 CPU 上也能以可充分理解的顺序执行。支配共享内存通信的规则由下面定义的内存模型提供。

Note

关于在 ECMAScript 中编程和实现共享内存的信息性指南,请参见内存模型节末尾的注释。

25.4.1 Waiter Record

Waiter Record 是一个 Record 值,用于表示对 Atomics.waitAtomics.waitAsync 的某个特定调用。

Waiter Record 具有 Table 73 中列出的字段。

Table 73: Waiter Record 字段
字段名 含义
[[AgentSignifier]] 一个 agent signifier 调用 Atomics.waitAtomics.waitAsyncagent
[[PromiseCapability]] 一个 PromiseCapability Recordblocking 如果表示对 Atomics.waitAsync 的调用,则为产生的 promise;否则为 blocking
[[TimeoutTime]] 一个非负扩展数学值 timeout 可以被触发的最早时间;使用时间值计算。
[[Result]] "ok""timed-out" 该调用的返回值。

25.4.2 WaiterList Records

WaiterList Record 用于解释 agents 通过 Atomics.waitAtomics.waitAsyncAtomics.notify 进行等待和通知。

WaiterList Record 具有 Table 74 中列出的字段。

Table 74: WaiterList Record 字段
字段名 含义
[[Waiters]] 一个由 Waiter Records 组成的 List 正在等待与此 WaiterList 相关联位置的 Atomics.waitAtomics.waitAsync 调用。
[[MostRecentLeaveEvent]] 一个 Synchronize 事件empty 最近一次离开其临界区的事件;如果其临界区从未被进入过,则为 empty

一个 WaiterList 中可以有多个具有相同 agent signifier 的 Waiter Records

agent cluster 有一个 WaiterList Records 存储;该存储按 (block, i) 索引,其中 block 是一个 Shared Data Block,而 i 是进入 block 内存的一个字节偏移。WaiterList Records 与 agent 无关:在 agent cluster 中的任意 agent 内,通过 (block, i) 查询 WaiterList Records 存储都会得到同一个 WaiterList Record。

每个 WaiterList Record 都有一个临界区,该临界区在求值期间控制对该 WaiterList Record 的排他访问。同一时间只有一个 agent 可以进入某个 WaiterList Record 的临界区。进入和离开 WaiterList Record 的临界区由抽象操作 EnterCriticalSectionLeaveCriticalSection 控制。对 WaiterList Record 的操作——添加和移除等待中的 agents、遍历 agents 列表、挂起和通知列表上的 agents、设置和检索 Synchronize 事件——只能由已经进入该 WaiterList Record 临界区的 agents 执行。

25.4.3 Atomics 的抽象操作

25.4.3.1 ValidateIntegerTypedArray ( typedArray, waitable )

The abstract operation ValidateIntegerTypedArray takes arguments typedArray (一个 ECMAScript 语言值,) and waitable (一个 Boolean,) and returns 要么是一个包含 TypedArray With Buffer Witness Record正常完成,要么是一个抛出完成. It performs the following steps when called:

  1. taRecord 为 ? ValidateTypedArray(typedArray, unordered)。
  2. 注:当 typedArray 的后备 buffer 是可增长 SharedArrayBuffer 时,边界检查不是同步操作。
  3. 如果 waitabletrue,则
    1. 如果 typedArray.[[TypedArrayName]] 既不是 "Int32Array" 也不是 "BigInt64Array",抛出 TypeError 异常。
  4. 否则,
    1. typeTypedArrayElementType(typedArray)。
    2. 如果 IsUnclampedIntegerElementType(type) 是 falseIsBigIntElementType(type) 是 false,抛出 TypeError 异常。
  5. 返回 taRecord

25.4.3.2 ValidateAtomicAccess ( taRecord, requestIndex )

The abstract operation ValidateAtomicAccess takes arguments taRecord (a TypedArray With Buffer Witness Record) and requestIndex (an ECMAScript language value) and returns either a normal completion containing a non-negative integer or a throw completion. It performs the following steps when called:

  1. lengthTypedArrayLength(taRecord)。
  2. accessIndex 为 ? ToIndex(requestIndex)。
  3. 断言:accessIndex ≥ 0。
  4. 如果 accessIndexlength,抛出 RangeError 异常。
  5. typedArraytaRecord.[[Object]]
  6. elementSizeTypedArrayElementSize(typedArray)。
  7. offsettypedArray.[[ByteOffset]]
  8. 返回 (accessIndex × elementSize) + offset

25.4.3.3 ValidateAtomicAccessOnIntegerTypedArray ( typedArray, requestIndex )

The abstract operation ValidateAtomicAccessOnIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and requestIndex (an ECMAScript language value) and returns either a normal completion containing a non-negative integer or a throw completion. It performs the following steps when called:

  1. taRecord 为 ? ValidateIntegerTypedArray(typedArray, false)。
  2. 返回 ? ValidateAtomicAccess(taRecord, requestIndex)。

25.4.3.4 RevalidateAtomicAccess ( typedArray, byteIndexInBuffer )

The abstract operation RevalidateAtomicAccess takes arguments typedArray (a TypedArray) and byteIndexInBuffer (a non-negative integer) and returns either a normal completion containing unused or a throw completion. 在 Atomics 方法中执行完所有参数强制转换之后,此操作会为原子操作重新验证后备 buffer 内的索引,因为参数强制转换可以有任意副作用,这可能导致 buffer 变为越界。当 typedArray 的后备 buffer 是 SharedArrayBuffer 时,此操作不会抛出。 It performs the following steps when called:

  1. taRecordMakeTypedArrayWithBufferWitnessRecord(typedArray, unordered)。
  2. 注:当 typedArray 的后备 buffer 是可增长 SharedArrayBuffer 时,边界检查不是同步操作。
  3. 如果 IsTypedArrayOutOfBounds(taRecord) 是 true,抛出 TypeError 异常。
  4. 断言:byteIndexInBuffertypedArray.[[ByteOffset]]
  5. 如果 byteIndexInBuffertaRecord.[[CachedBufferByteLength]],抛出 RangeError 异常。
  6. 返回 unused

25.4.3.5 GetWaiterList ( block, i )

The abstract operation GetWaiterList takes arguments block (一个 Shared Data Block,) and i (一个可被 4 整除的非负整数,) and returns 一个 WaiterList Record. It performs the following steps when called:

  1. 断言:ii + 3 都是 block 内存中的有效字节偏移。
  2. 返回由 pair (block, i) 所引用的 WaiterList Record

25.4.3.6 EnterCriticalSection ( waiterList )

The abstract operation EnterCriticalSection takes argument waiterList (一个 WaiterList Record,) and returns unused. It performs the following steps when called:

  1. 断言:周围 agent 不在任何 WaiterList Record临界区中。
  2. 等待直到没有 agent 处于 waiterList临界区中,然后进入 waiterList临界区(不允许任何其他 agent 进入)。
  3. 如果 waiterList.[[MostRecentLeaveEvent]] 不是 empty,则
    1. 注:临界区已至少进入过一次的 waiterList 具有由 LeaveCriticalSection 设置的 Synchronize 事件
    2. agentRecord 为周围 agentAgent Record
    3. executionagentRecord.[[CandidateExecution]]
    4. eventsRecordexecution.[[EventsRecords]][[AgentSignifier]]AgentSignifier() 的 Agent Events Record
    5. enterEvent 为一个新的 Synchronize 事件
    6. enterEvent 追加到 eventsRecord.[[EventList]]
    7. 将 (waiterList.[[MostRecentLeaveEvent]], enterEvent) 追加到 eventsRecord.[[AgentSynchronizesWith]]
  4. 返回 unused

当尝试进入临界区agent 必须等待另一个 agent 离开临界区时,EnterCriticalSection 具有争用。没有争用时,EnterCriticalSection 调用的 FIFO 顺序是可观察的。有争用时,实现可以选择任意顺序,但不得导致某个 agent 无限期等待。

25.4.3.7 LeaveCriticalSection ( waiterList )

The abstract operation LeaveCriticalSection takes argument waiterList (一个 WaiterList Record,) and returns unused. It performs the following steps when called:

  1. 断言:周围 agent 处于 waiterList临界区中。
  2. agentRecord 为周围 agentAgent Record
  3. executionagentRecord.[[CandidateExecution]]
  4. eventsRecordexecution.[[EventsRecords]][[AgentSignifier]]AgentSignifier() 的 Agent Events Record
  5. leaveEvent 为一个新的 Synchronize 事件
  6. leaveEvent 追加到 eventsRecord.[[EventList]]
  7. waiterList.[[MostRecentLeaveEvent]] 设置为 leaveEvent
  8. 离开 waiterList临界区
  9. 返回 unused

25.4.3.8 AddWaiter ( waiterList, waiterRecord )

The abstract operation AddWaiter takes arguments waiterList (一个 WaiterList Record,) and waiterRecord (一个 Waiter Record,) and returns unused. It performs the following steps when called:

  1. 断言:周围 agent 处于 waiterList临界区中。
  2. 断言:waiterList.[[Waiters]] 中不存在其 [[PromiseCapability]] 字段为 waiterRecord.[[PromiseCapability]] 且其 [[AgentSignifier]] 字段为 waiterRecord.[[AgentSignifier]]Waiter Record
  3. waiterRecord 追加到 waiterList.[[Waiters]]
  4. 返回 unused

25.4.3.9 RemoveWaiter ( waiterList, waiterRecord )

The abstract operation RemoveWaiter takes arguments waiterList (一个 WaiterList Record,) and waiterRecord (一个 Waiter Record,) and returns unused. It performs the following steps when called:

  1. 断言:周围 agent 处于 waiterList临界区中。
  2. 断言:waiterList.[[Waiters]] 包含 waiterRecord
  3. waiterList.[[Waiters]] 中移除 waiterRecord
  4. 返回 unused

25.4.3.10 RemoveWaiters ( waiterList, count )

The abstract operation RemoveWaiters takes arguments waiterList (一个 WaiterList Record,) and count (一个非负整数或 +∞,) and returns 一个由 Waiter Records 组成的 List. It performs the following steps when called:

  1. 断言:周围 agent 处于 waiterList临界区中。
  2. lenwaiterList.[[Waiters]] 中元素的数量。
  3. count 设置为 min(count, len)。
  4. waiters 为一个 List,其元素为 waiterList.[[Waiters]] 的前 count 个元素。
  5. 移除 waiterList.[[Waiters]] 的前 count 个元素。
  6. 返回 waiters

25.4.3.11 SuspendThisAgent ( waiterList, waiterRecord )

The abstract operation SuspendThisAgent takes arguments waiterList (一个 WaiterList Record,) and waiterRecord (一个 Waiter Record,) and returns unused. It performs the following steps when called:

  1. 断言:周围 agent 处于 waiterList临界区中。
  2. 断言:waiterList.[[Waiters]] 包含 waiterRecord
  3. thisAgentAgentSignifier()。
  4. 断言:waiterRecord.[[AgentSignifier]]thisAgent
  5. 断言:waiterRecord.[[PromiseCapability]]blocking
  6. 断言:AgentCanSuspend() 是 true
  7. 执行 LeaveCriticalSection(waiterList) 并挂起周围 agent,直到时间为 waiterRecord.[[TimeoutTime]];以这样一种方式执行该组合操作,使得在退出临界区之后但在挂起生效之前到达的通知不会丢失。周围 agent 只能因 timeout 或因另一个 agent 使用参数 waiterListthisAgent 调用 NotifyWaiter(即通过调用 Atomics.notify)而从挂起中醒来。
  8. 执行 EnterCriticalSection(waiterList)。
  9. 返回 unused

25.4.3.12 NotifyWaiter ( waiterList, waiterRecord )

The abstract operation NotifyWaiter takes arguments waiterList (一个 WaiterList Record,) and waiterRecord (一个 Waiter Record,) and returns unused. It performs the following steps when called:

  1. 断言:周围 agent 处于 waiterList临界区中。
  2. 如果 waiterRecord.[[PromiseCapability]]blocking,则
    1. 将其 signifier 为 waiterRecord.[[AgentSignifier]]agent 从挂起中唤醒。
    2. 注:这会导致该 agentSuspendThisAgent 中恢复执行。
  3. 否则如果 AgentSignifier() 是 waiterRecord.[[AgentSignifier]],则
    1. promiseCapabilitywaiterRecord.[[PromiseCapability]]
    2. 执行 ! Call(promiseCapability.[[Resolve]], undefined, « waiterRecord.[[Result]] »)。
  4. 否则,
    1. 执行 EnqueueResolveInAgentJob(waiterRecord.[[AgentSignifier]], waiterRecord.[[PromiseCapability]], waiterRecord.[[Result]])。
  5. 返回 unused
Note

一个 agent 不得以除传递给宿主之外的任何方式访问另一个 agent 的 promise capability。

25.4.3.13 EnqueueResolveInAgentJob ( agentSignifier, promiseCapability, resolution )

The abstract operation EnqueueResolveInAgentJob takes arguments agentSignifier (一个 agent signifier,), promiseCapability (一个 PromiseCapability Record,), and resolution ("ok""timed-out",) and returns unused. It performs the following steps when called:

  1. resolveJob 为一个新的无参数 Job Abstract Closure,捕获 agentSignifierpromiseCapabilityresolution,并在被调用时执行以下步骤:
    1. 断言:AgentSignifier() 是 agentSignifier
    2. 执行 ! Call(promiseCapability.[[Resolve]], undefined, « resolution »)。
    3. 返回 unused
  2. realmInTargetAgent 为 ! GetFunctionRealm(promiseCapability.[[Resolve]])。
  3. 断言:agentSignifierrealmInTargetAgent.[[AgentSignifier]]
  4. 执行 HostEnqueueGenericJob(resolveJob, realmInTargetAgent)。
  5. 返回 unused

25.4.3.14 DoWait ( mode, typedArray, index, value, timeout )

The abstract operation DoWait takes arguments mode (syncasync,), typedArray (一个 ECMAScript 语言值,), index (一个 ECMAScript 语言值,), value (一个 ECMAScript 语言值,), and timeout (一个 ECMAScript 语言值,) and returns 要么是一个包含 Object、"not-equal""timed-out""ok"正常完成,要么是一个抛出完成. It performs the following steps when called:

  1. taRecord 为 ? ValidateIntegerTypedArray(typedArray, true)。
  2. buffertaRecord.[[Object]].[[ViewedArrayBuffer]]
  3. 如果 IsSharedArrayBuffer(buffer) 是 false,抛出 TypeError 异常。
  4. byteIndexInBuffer 为 ? ValidateAtomicAccess(taRecord, index)。
  5. arrayTypeNametypedArray.[[TypedArrayName]]
  6. 如果 arrayTypeName"BigInt64Array",令 expected 为 ? ToBigInt64(value)。
  7. 否则,令 expected 为 ? ToInt32(value)。
  8. timeoutNumber 为 ? ToNumber(timeout)。
  9. 如果 timeoutNumberNaN+∞𝔽,令 realTimeout 为 +∞。
  10. 否则如果 timeoutNumber-∞𝔽,令 realTimeout 为 0。
  11. 否则,令 realTimeoutmax((timeoutNumber), 0)。
  12. 如果 modesyncAgentCanSuspend() 是 false,抛出 TypeError 异常。
  13. blockbuffer.[[ArrayBufferData]]
  14. waiterListGetWaiterList(block, byteIndexInBuffer)。
  15. 如果 modesync,则
    1. promiseCapabilityblocking
    2. resultObjectundefined
  16. 否则,
    1. promiseCapability 为 ! NewPromiseCapability(%Promise%)。
    2. resultObjectOrdinaryObjectCreate(%Object.prototype%)。
  17. 执行 EnterCriticalSection(waiterList)。
  18. elementTypeTypedArrayElementType(typedArray)。
  19. witnessGetValueFromBuffer(buffer, byteIndexInBuffer, elementType, true, seq-cst)。
  20. 如果 expectedwitness,则
    1. 执行 LeaveCriticalSection(waiterList)。
    2. 如果 modesync,返回 "not-equal"
    3. 执行 ! CreateDataPropertyOrThrow(resultObject, "async", false)。
    4. 执行 ! CreateDataPropertyOrThrow(resultObject, "value", "not-equal")。
    5. 返回 resultObject
  21. 如果 realTimeout = 0 且 modeasync,则
    1. 注:同步的立即 timeout 没有特殊处理。异步的立即 timeout 有特殊处理,以便快速失败并避免不必要的 Promise jobs。
    2. 执行 LeaveCriticalSection(waiterList)。
    3. 执行 ! CreateDataPropertyOrThrow(resultObject, "async", false)。
    4. 执行 ! CreateDataPropertyOrThrow(resultObject, "value", "timed-out")。
    5. 返回 resultObject
  22. thisAgentAgentSignifier()。
  23. now 为标识当前时间的时间值(UTC)。
  24. additionalTimeout 为一个实现定义的非负数学值
  25. timeoutTime(now) + realTimeout + additionalTimeout
  26. 注:当 realTimeout 为 +∞ 时,timeoutTime 也为 +∞。
  27. waiterRecord 为一个新的 Waiter Record { [[AgentSignifier]]: thisAgent, [[PromiseCapability]]: promiseCapability, [[TimeoutTime]]: timeoutTime, [[Result]]: "ok" }。
  28. 执行 AddWaiter(waiterList, waiterRecord)。
  29. 如果 modesync,则
    1. 执行 SuspendThisAgent(waiterList, waiterRecord)。
  30. 否则如果 timeoutTime有限的,则
    1. 执行 EnqueueAtomicsWaitAsyncTimeoutJob(waiterList, waiterRecord)。
  31. 执行 LeaveCriticalSection(waiterList)。
  32. 如果 modesync,返回 waiterRecord.[[Result]]
  33. 执行 ! CreateDataPropertyOrThrow(resultObject, "async", true)。
  34. 执行 ! CreateDataPropertyOrThrow(resultObject, "value", promiseCapability.[[Promise]])。
  35. 返回 resultObject
Note

additionalTimeout 允许实现按需填充 timeout,例如用于降低功耗或粗化计时器分辨率以缓解定时攻击。该值在 DoWait 的不同调用之间可以不同。

25.4.3.15 EnqueueAtomicsWaitAsyncTimeoutJob ( waiterList, waiterRecord )

The abstract operation EnqueueAtomicsWaitAsyncTimeoutJob takes arguments waiterList (一个 WaiterList Record,) and waiterRecord (一个 Waiter Record,) and returns unused. It performs the following steps when called:

  1. timeoutJob 为一个新的无参数 Job Abstract Closure,捕获 waiterListwaiterRecord,并在被调用时执行以下步骤:
    1. 执行 EnterCriticalSection(waiterList)。
    2. 如果 waiterList.[[Waiters]] 包含 waiterRecord,则
      1. timeOfJobExecution 为标识当前时间的时间值(UTC)。
      2. 断言:(timeOfJobExecution) ≥ waiterRecord.[[TimeoutTime]](忽略时间值潜在的非单调性)。
      3. waiterRecord.[[Result]] 设置为 "timed-out"
      4. 执行 RemoveWaiter(waiterList, waiterRecord)。
      5. 执行 NotifyWaiter(waiterList, waiterRecord)。
    3. 执行 LeaveCriticalSection(waiterList)。
    4. 返回 unused
  2. now 为标识当前时间的时间值(UTC)。
  3. currentRealm当前 Realm Record
  4. 执行 HostEnqueueTimeoutJob(timeoutJob, currentRealm, 𝔽(waiterRecord.[[TimeoutTime]]) - now)。
  5. 返回 unused

25.4.3.16 AtomicCompareExchangeInSharedBlock ( block, byteIndexInBuffer, elementSize, expectedBytes, replacementBytes )

The abstract operation AtomicCompareExchangeInSharedBlock takes arguments block (一个 Shared Data Block,), byteIndexInBuffer (一个整数,), elementSize (一个非负整数,), expectedBytes (一个由字节值组成的 List,), and replacementBytes (一个由字节值组成的 List,) and returns 一个由字节值组成的 List. It performs the following steps when called:

  1. agentRecord 为周围 agentAgent Record
  2. executionagentRecord.[[CandidateExecution]]
  3. eventsRecordexecution.[[EventsRecords]][[AgentSignifier]]AgentSignifier() 的 Agent Events Record
  4. rawBytesRead 为一个长度为 elementSizeList,其元素为非确定性选择的字节值
  5. 注:在实现中,rawBytesRead 是底层硬件上的 load-link、load-exclusive 或读-改-写指令的一个操作数的结果。该非确定性是内存模型的一种语义规定,用来描述具有弱一致性的硬件的可观察行为。
  6. 注:期望值与读取值的比较是在读-改-写修改函数之外执行的,以避免在期望值不等于读取值时产生不必要的强同步。
  7. 如果 ByteListEqual(rawBytesRead, expectedBytes) 是 true,则
    1. second 为一个新的读-改-写修改函数,带参数 (oldBytes, newBytes),不捕获任何内容,并在被调用时以原子方式执行以下步骤:
      1. 返回 newBytes
    2. event 为 ReadModifyWriteSharedMemory { [[Order]]: seq-cst, [[NoTear]]: true, [[Block]]: block, [[ByteIndex]]: byteIndexInBuffer, [[ElementSize]]: elementSize, [[Payload]]: replacementBytes, [[ModifyOp]]: second }。
  8. 否则,
    1. event 为 ReadSharedMemory { [[Order]]: seq-cst, [[NoTear]]: true, [[Block]]: block, [[ByteIndex]]: byteIndexInBuffer, [[ElementSize]]: elementSize }。
  9. event 追加到 eventsRecord.[[EventList]]
  10. Chosen Value Record { [[Event]]: event, [[ChosenValue]]: rawBytesRead } 追加到 execution.[[ChosenValues]]
  11. 返回 rawBytesRead

25.4.3.17 AtomicReadModifyWrite ( typedArray, index, value, op )

The abstract operation AtomicReadModifyWrite takes arguments typedArray (一个 ECMAScript 语言值,), index (一个 ECMAScript 语言值,), value (一个 ECMAScript 语言值,), and op (一个读-改-写修改函数,) and returns 要么是一个包含 Number 或 BigInt 的正常完成,要么是一个抛出完成. op 接受两个由字节值组成的 List 参数,并返回一个由字节值组成的 List。此操作以原子方式加载一个值,将它与另一个值组合,并存储该组合。它返回被加载的值。 It performs the following steps when called:

  1. byteIndexInBuffer 为 ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index)。
  2. 如果 typedArray.[[ContentType]]bigint,令 coerced 为 ? ToBigInt(value)。
  3. 否则,令 coerced𝔽(? ToIntegerOrInfinity(value))。
  4. 执行 ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer)。
  5. buffertypedArray.[[ViewedArrayBuffer]]
  6. elementTypeTypedArrayElementType(typedArray)。
  7. 返回 GetModifySetValueInBuffer(buffer, byteIndexInBuffer, elementType, coerced, op)。

25.4.3.18 ByteListBitwiseOp ( op, xBytes, yBytes )

The abstract operation ByteListBitwiseOp takes arguments op (&^|,), xBytes (一个由字节值组成的 List,), and yBytes (一个由字节值组成的 List,) and returns 一个由字节值组成的 List. 该操作以原子方式对参数的所有字节值执行按位操作,并返回一个由字节值组成的 List。 It performs the following steps when called:

  1. 断言:xBytesyBytes 具有相同数量的元素。
  2. result 为一个新的空 List
  3. i 为 0。
  4. 对于 xBytes 的每个元素 xByte,执行
    1. yByteyBytes[i]。
    2. 如果 op&,则
      1. resultByte 为对 xByteyByte 应用按位 AND 操作的结果。
    3. 否则如果 op^,则
      1. resultByte 为对 xByteyByte 应用按位 exclusive OR(XOR)操作的结果。
    4. 否则,
      1. 断言:op|
      2. resultByte 为对 xByteyByte 应用按位 inclusive OR 操作的结果。
    5. i 设置为 i + 1。
    6. resultByte 追加到 result
  5. 返回 result

25.4.3.19 ByteListEqual ( xBytes, yBytes )

The abstract operation ByteListEqual takes arguments xBytes (一个由字节值组成的 List,) and yBytes (一个由字节值组成的 List,) and returns 一个 Boolean. It performs the following steps when called:

  1. 如果 xBytesyBytes 不具有相同数量的元素,返回 false
  2. i 为 0。
  3. 对于 xBytes 的每个元素 xByte,执行
    1. yByteyBytes[i]。
    2. 如果 xByteyByte,返回 false
    3. i 设置为 i + 1。
  4. 返回 true

25.4.4 Atomics.add ( typedArray, index, value )

此函数在被调用时执行以下步骤:

  1. add 为一个新的读-改-写修改函数,带参数 (xBytes, yBytes),捕获 typedArray,并在被调用时以原子方式执行以下步骤:
    1. typeTypedArrayElementType(typedArray)。
    2. agentRecord 为周围 agentAgent Record
    3. isLittleEndianagentRecord.[[LittleEndian]]
    4. xRawBytesToNumeric(type, xBytes, isLittleEndian)。
    5. yRawBytesToNumeric(type, yBytes, isLittleEndian)。
    6. 如果 x 是一个 Number,则
      1. sumNumber::add(x, y)。
    7. 否则,
      1. 断言:x 是一个 BigInt。
      2. sumBigInt::add(x, y)。
    8. sumBytesNumericToRawBytes(type, sum, isLittleEndian)。
    9. 断言:sumBytesxBytesyBytes 具有相同数量的元素。
    10. 返回 sumBytes
  2. 返回 ? AtomicReadModifyWrite(typedArray, index, value, add)。

25.4.5 Atomics.and ( typedArray, index, value )

此函数在被调用时执行以下步骤:

  1. and 为一个新的读-改-写修改函数,带参数 (xBytes, yBytes),不捕获任何内容,并在被调用时以原子方式执行以下步骤:
    1. 返回 ByteListBitwiseOp(&, xBytes, yBytes)。
  2. 返回 ? AtomicReadModifyWrite(typedArray, index, value, and)。

25.4.6 Atomics.compareExchange ( typedArray, index, expectedValue, replacementValue )

此函数在被调用时执行以下步骤:

  1. byteIndexInBuffer 为 ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index)。
  2. buffertypedArray.[[ViewedArrayBuffer]]
  3. blockbuffer.[[ArrayBufferData]]
  4. 如果 typedArray.[[ContentType]]bigint,则
    1. expected 为 ? ToBigInt(expectedValue)。
    2. replacement 为 ? ToBigInt(replacementValue)。
  5. 否则,
    1. expected𝔽(? ToIntegerOrInfinity(expectedValue))。
    2. replacement𝔽(? ToIntegerOrInfinity(replacementValue))。
  6. 执行 ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer)。
  7. elementTypeTypedArrayElementType(typedArray)。
  8. elementSizeTypedArrayElementSize(typedArray)。
  9. agentRecord 为周围 agentAgent Record
  10. isLittleEndianagentRecord.[[LittleEndian]]
  11. expectedBytesNumericToRawBytes(elementType, expected, isLittleEndian)。
  12. replacementBytesNumericToRawBytes(elementType, replacement, isLittleEndian)。
  13. 如果 IsSharedArrayBuffer(buffer) 是 true,则
    1. rawBytesReadAtomicCompareExchangeInSharedBlock(block, byteIndexInBuffer, elementSize, expectedBytes, replacementBytes)。
  14. 否则,
    1. rawBytesRead 为一个长度为 elementSizeList,其元素是从 block[byteIndexInBuffer] 开始的 elementSize 个字节序列。
    2. 如果 ByteListEqual(rawBytesRead, expectedBytes) 是 true,则
      1. replacementBytes 的各个字节存储进 block,从 block[byteIndexInBuffer] 开始。
  15. 返回 RawBytesToNumeric(elementType, rawBytesRead, isLittleEndian)。

25.4.7 Atomics.exchange ( typedArray, index, value )

此函数在被调用时执行以下步骤:

  1. second 为一个新的读-改-写修改函数,带参数 (oldBytes, newBytes),不捕获任何内容,并在被调用时以原子方式执行以下步骤:
    1. 返回 newBytes
  2. 返回 ? AtomicReadModifyWrite(typedArray, index, value, second)。

25.4.8 Atomics.isLockFree ( size )

此函数在被调用时执行以下步骤:

  1. n 为 ? ToIntegerOrInfinity(size)。
  2. agentRecord 为周围 agentAgent Record
  3. 如果 n = 1,返回 agentRecord.[[IsLockFree1]]
  4. 如果 n = 2,返回 agentRecord.[[IsLockFree2]]
  5. 如果 n = 4,返回 true
  6. 如果 n = 8,返回 agentRecord.[[IsLockFree8]]
  7. 返回 false
Note

此函数是一个优化原语。其直觉是:如果大小为 n 字节的数据上的原子原语(compareExchangeloadstoreaddsubandorxorexchange)的原子步骤将在不让周围 agent 获取由该数据组成的 n 个字节之外的锁的情况下执行,那么 Atomics.isLockFree(n) 将返回 true。高性能算法会使用此函数来决定在临界区中使用锁还是原子操作。如果某个原子原语不是 lock-free,则算法提供自己的锁通常更高效。

Atomics.isLockFree(4) 总是返回 true,因为所有已知相关硬件都能支持这一点。能够假定这一点通常会简化程序。

无论此函数返回的值是什么,所有原子操作都保证是原子的。例如,它们永远不会在操作中间发生可见操作(例如“撕裂”)。

25.4.9 Atomics.load ( typedArray, index )

此函数在被调用时执行以下步骤:

  1. byteIndexInBuffer 为 ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index)。
  2. 执行 ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer)。
  3. buffertypedArray.[[ViewedArrayBuffer]]
  4. elementTypeTypedArrayElementType(typedArray)。
  5. 返回 GetValueFromBuffer(buffer, byteIndexInBuffer, elementType, true, seq-cst)。

25.4.10 Atomics.or ( typedArray, index, value )

此函数在被调用时执行以下步骤:

  1. or 为一个新的读-改-写修改函数,带参数 (xBytes, yBytes),不捕获任何内容,并在被调用时以原子方式执行以下步骤:
    1. 返回 ByteListBitwiseOp(|, xBytes, yBytes)。
  2. 返回 ? AtomicReadModifyWrite(typedArray, index, value, or)。

25.4.11 Atomics.store ( typedArray, index, value )

此函数在被调用时执行以下步骤:

  1. byteIndexInBuffer 为 ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index)。
  2. 如果 typedArray.[[ContentType]]bigint,令 coerced 为 ? ToBigInt(value)。
  3. 否则,令 coerced𝔽(? ToIntegerOrInfinity(value))。
  4. 执行 ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer)。
  5. buffertypedArray.[[ViewedArrayBuffer]]
  6. elementTypeTypedArrayElementType(typedArray)。
  7. 执行 SetValueInBuffer(buffer, byteIndexInBuffer, elementType, coerced, true, seq-cst)。
  8. 返回 coerced

25.4.12 Atomics.sub ( typedArray, index, value )

此函数在被调用时执行以下步骤:

  1. subtract 为一个新的读-改-写修改函数,带参数 (xBytes, yBytes),捕获 typedArray,并在被调用时以原子方式执行以下步骤:
    1. typeTypedArrayElementType(typedArray)。
    2. agentRecord 为周围 agentAgent Record
    3. isLittleEndianagentRecord.[[LittleEndian]]
    4. xRawBytesToNumeric(type, xBytes, isLittleEndian)。
    5. yRawBytesToNumeric(type, yBytes, isLittleEndian)。
    6. 如果 x 是一个 Number,则
      1. differenceNumber::subtract(x, y)。
    7. 否则,
      1. 断言:x 是一个 BigInt。
      2. differenceBigInt::subtract(x, y)。
    8. differenceBytesNumericToRawBytes(type, difference, isLittleEndian)。
    9. 断言:differenceBytesxBytesyBytes 具有相同数量的元素。
    10. 返回 differenceBytes
  2. 返回 ? AtomicReadModifyWrite(typedArray, index, value, subtract)。

25.4.13 Atomics.wait ( typedArray, index, value, timeout )

此函数将周围 agent 放入等待队列并将其挂起,直到收到通知或等待超时为止,并返回一个 String 来区分这些情况。

它在被调用时执行以下步骤:

  1. 返回 ? DoWait(sync, typedArray, index, value, timeout)。

25.4.14 Atomics.waitAsync ( typedArray, index, value, timeout )

此函数返回一个 Promise,该 Promise 会在调用 agent 收到通知或到达 timeout 时被解决。

它在被调用时执行以下步骤:

  1. 返回 ? DoWait(async, typedArray, index, value, timeout)。

25.4.15 Atomics.notify ( typedArray, index, count )

此函数通知一些正在等待队列中休眠的 agents

它在被调用时执行以下步骤:

  1. taRecord 为 ? ValidateIntegerTypedArray(typedArray, true)。
  2. byteIndexInBuffer 为 ? ValidateAtomicAccess(taRecord, index)。
  3. 如果 countundefined,则
    1. count 设置为 +∞。
  4. 否则,
    1. intCount 为 ? ToIntegerOrInfinity(count)。
    2. count 设置为 max(intCount, 0)。
  5. buffertypedArray.[[ViewedArrayBuffer]]
  6. blockbuffer.[[ArrayBufferData]]
  7. 如果 IsSharedArrayBuffer(buffer) 是 false,返回 +0𝔽
  8. waiterListGetWaiterList(block, byteIndexInBuffer)。
  9. 执行 EnterCriticalSection(waiterList)。
  10. waitersRemoveWaiters(waiterList, count)。
  11. 对于 waiters 的每个元素 waiterRecord,执行
    1. 执行 NotifyWaiter(waiterList, waiterRecord)。
  12. 执行 LeaveCriticalSection(waiterList)。
  13. nwaiters 中元素的数量。
  14. 返回 𝔽(n)。

25.4.16 Atomics.xor ( typedArray, index, value )

此函数在被调用时执行以下步骤:

  1. xor 为一个新的读-改-写修改函数,带参数 (xBytes, yBytes),不捕获任何内容,并在被调用时以原子方式执行以下步骤:
    1. 返回 ByteListBitwiseOp(^, xBytes, yBytes)。
  2. 返回 ? AtomicReadModifyWrite(typedArray, index, value, xor)。

25.4.17 Atomics [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "Atomics"

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

25.5 JSON 对象

JSON 对象:

  • %JSON%
  • 全局对象"JSON" 属性的初始值。
  • 是一个普通对象
  • 包含两个函数 parsestringify,它们用于解析和构造 JSON 文本。
  • 有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%
  • 没有 [[Construct]] 内部方法;不能与 new 运算符一起用作构造器
  • 没有 [[Call]] 内部方法;不能作为函数调用。

JSON Data Interchange Format 在 ECMA-404 中定义。本规范中使用的 JSON 交换格式正是 ECMA-404 所描述的格式。JSON.parseJSON.stringify 的符合实现必须支持 ECMA-404 规范中描述的精确交换格式,不得对该格式进行任何删除或扩展。

25.5.1 JSON.isRawJSON ( obj )

此函数在被调用时执行以下步骤:

  1. 如果 obj 是 Object 且 obj[[IsRawJSON]] 内部槽,返回 true
  2. 返回 false

25.5.2 JSON.parse ( text [ , reviver ] )

此函数解析一个 JSON 文本(JSON 格式的 String)并产生一个 ECMAScript 语言值。JSON 格式使用类似于 ECMAScript 字面量、Array Initializers 和 Object Initializers 语法的语法来表示字面量、数组和对象。解析之后,JSON 对象被实现为 ECMAScript 对象。JSON 数组被实现为 ECMAScript Array 实例。JSON 字符串、数字、布尔值和 null 被实现为 ECMAScript Strings、Numbers、Booleans 和 null

可选的 reviver 参数是一个可以过滤和转换结果的函数。对于 parse 产生的每个值,都会以三个参数(关联的属性键、该值和一个 context 对象)调用 reviver。如果属性未被修改且其值为 primitive,则所提供的 context 对象具有一个 "source" 属性,其中包含对应 Parse Node 的源文本。如果该调用返回 undefined,则该属性会被删除。否则,该属性会被重新定义为使用返回值。

  1. jsonString 为 ? ToString(text)。
  2. parseResult 为 ? ParseJSON(jsonString)。
  3. unfilteredparseResult.[[Value]]
  4. 如果 IsCallable(reviver) 是 false,返回 unfiltered
  5. rootOrdinaryObjectCreate(%Object.prototype%)。
  6. rootName 为空 String。
  7. 执行 ! CreateDataPropertyOrThrow(root, rootName, unfiltered)。
  8. snapshotCreateJSONParseRecord(parseResult.[[ParseNode]], rootName, unfiltered)。
  9. 返回 ? InternalizeJSONProperty(root, rootName, reviver, snapshot)。

此函数的 "length" 属性为 2𝔽

25.5.2.1 ParseJSON ( text )

The abstract operation ParseJSON takes argument text (一个 String,) and returns 要么是一个包含字段 [[ParseNode]](一个 Parse Node)和 [[Value]](一个 ECMAScript 语言值)的 Record正常完成,要么是一个抛出完成. It performs the following steps when called:

  1. 如果 StringToCodePoints(text) 不是 ECMA-404 中指定的有效 JSON 文本,抛出 SyntaxError 异常。
  2. scriptString"("text");" 的字符串拼接。
  3. scriptParseText(scriptString, Script)。
  4. 注:13.2.5.1 中定义的早期错误规则对上述 ParseText 调用有特殊处理。
  5. 断言:script 是一个 Parse Node。
  6. result 为 ! scriptEvaluation
  7. 注:13.2.5.6 中定义的 PropertyDefinitionEvaluation 语义对上述求值有特殊处理。
  8. 断言:result 要么是 String、Number、Boolean、由 ArrayLiteralObjectLiteral 定义的 Object,要么是 null
  9. 返回 Record { [[ParseNode]]: script, [[Value]]: result }。

符合实现的 JSON.parse 不允许扩展 JSON 语法。如果某个实现希望支持修改过或扩展过的 JSON 交换格式,它必须通过定义另一个 parse 函数来做到这一点。

Note 1

有效 JSON 文本是 ECMAScript PrimaryExpression 语法的子集。步骤 1 验证 jsonString 符合该子集,步骤 8 断言求值返回一个具有适当类型的值。

然而,由于 13.2.5.6 在 ParseJSON 期间表现不同,同一源文本作为 PrimaryExpression 求值时可能产生不同于作为 JSON 时的结果。此外,对象字面量中重复 "__proto__" 属性的 Early Error 同样不适用于 ParseJSON,这意味着尽管匹配语法,并非所有被 ParseJSON 接受的文本都是有效的 PrimaryExpression

Note 2

在一个对象中存在重复 name Strings 的情况下,词法上靠前的同一键的值应被覆盖

25.5.2.2 JSON Parse Record

JSON Parse Record 是一个 Record 值,用于描述从 JSON 文本解析出的值的初始状态。

JSON Parse Records 具有 Table 75 中列出的字段。

Table 75: JSON Parse Record 字段
字段名 含义
[[ParseNode]] 一个 Parse Node context Parse Node。
[[Key]] 一个属性名 [[Value]] 相关联的属性名
[[Value]] 一个 ECMAScript 语言值 [[ParseNode]] 的求值产生的值。
[[Elements]] 一个由 JSON Parse Records 组成的 List 如果 [[Value]] 是一个 Array,则它包含与 [[Value]] 的元素相对应的 JSON Parse Records。否则,它是一个空 List
[[Entries]] 一个由 JSON Parse Records 组成的 List 如果 [[Value]] 是一个非 Array Object,则它包含与 [[Value]] 的 entries 相对应的 JSON Parse Records。否则,它是一个空 List

25.5.2.3 CreateJSONParseRecord ( parseNode, key, val )

The abstract operation CreateJSONParseRecord takes arguments parseNode (一个 Parse Node,), key (一个属性名,), and val (一个 ECMAScript 语言值,) and returns 一个 JSON Parse Record. 它递归地组合从 JSON 文本解析出的 parseNode 以及其求值产生的 val。 It performs the following steps when called:

  1. typedValNodeShallowestContainedJSONValue(parseNode)。
  2. 断言:typedValNode 不是 empty
  3. elements 为一个新的空 List
  4. entries 为一个新的空 List
  5. 如果 val 是一个 Object,则
    1. isArray 为 ! IsArray(val)。
    2. 如果 isArraytrue,则
      1. 断言:typedValNode 是一个 ArrayLiteral Parse Node。
      2. contentNodestypedValNodeJSONArrayLiteralContentNodes
      3. lencontentNodes 中元素的数量。
      4. valLen 为 ! LengthOfArrayLike(val)。
      5. 断言:valLenlen
      6. index 为 0。
      7. 重复,当 index < len 时,
        1. propName 为 ! ToString(𝔽(index))。
        2. elementParseRecordCreateJSONParseRecord(contentNodes[index], propName, ! Get(val, propName))。
        3. elementParseRecord 追加到 elements
        4. index 设置为 index + 1。
    3. 否则,
      1. 断言:typedValNode 是一个 ObjectLiteral Parse Node。
      2. propertyNodestypedValNodePropertyDefinitionNodes
      3. 注:因为 val 是从 JSON 文本产生且尚未被修改,所以它的所有属性键都是 Strings,并将被穷尽枚举。
      4. keys 为 ! EnumerableOwnProperties(val, key)。
      5. 对于 keys 的每个 String propertyKey,执行
        1. 注:在 JSON 文本为单个对象指定多个具有相同 name 的 name/value pairs(例如 {"a":"lost","a":"kept"})的情况下,结果 ECMAScript 对象对应属性的值由具有该 name 的最后一个 pair 指定。
        2. propertyDefinitionempty
        3. 对于 propertyNodes 的每个 Parse Node propertyNode,执行
          1. propNamepropertyNodePropName
          2. 如果 propNamepropertyKey,将 propertyDefinition 设置为 propertyNode
        4. 断言:propertyDefinition PropertyDefinition : PropertyName : AssignmentExpression
        5. propertyValueNodepropertyDefinitionAssignmentExpression
        6. entryParseRecordCreateJSONParseRecord(propertyValueNode, propertyKey, ! Get(val, propertyKey))。
        7. entryParseRecord 追加到 entries
  6. 否则,
    1. 断言:typedValNode 既不是 ArrayLiteral Parse Node,也不是 ObjectLiteral Parse Node。
  7. 返回 JSON Parse Record { [[ParseNode]]: typedValNode, [[Key]]: key, [[Value]]: val, [[Elements]]: elements, [[Entries]]: entries }。

25.5.2.4 InternalizeJSONProperty ( holder, name, reviver, parseRecord )

The abstract operation InternalizeJSONProperty takes arguments holder (一个 Object,), name (一个 String,), reviver (一个函数对象,), and parseRecord (一个 JSON Parse Recordempty,) and returns 要么是一个包含 ECMAScript 语言值正常完成,要么是一个抛出完成.

Note

如果 [[Delete]]CreateDataProperty 返回 false,此算法有意不抛出异常。

它在被调用时执行以下步骤:

  1. val 为 ? Get(holder, name)。
  2. contextOrdinaryObjectCreate(%Object.prototype%)。
  3. 如果 parseRecord 是一个 JSON Parse RecordSameValue(parseRecord.[[Value]], val) 是 true,则
    1. 如果 val 不是 Object,则
      1. parseNodeparseRecord.[[ParseNode]]
      2. 断言:parseNode 既不是 ArrayLiteral Parse Node,也不是 ObjectLiteral Parse Node。
      3. sourceTextparseNode匹配的源文本
      4. 执行 ! CreateDataPropertyOrThrow(context, "source", CodePointsToString(sourceText))。
    2. elementRecordsparseRecord.[[Elements]]
    3. entryRecordsparseRecord.[[Entries]]
  4. 否则,
    1. elementRecords 为一个新的空 List
    2. entryRecords 为一个新的空 List
  5. 如果 val 是一个 Object,则
    1. isArray 为 ? IsArray(val)。
    2. 如果 isArraytrue,则
      1. elementRecordsLenelementRecords 中元素的数量。
      2. len 为 ? LengthOfArrayLike(val)。
      3. index 为 0。
      4. 重复,当 index < len 时,
        1. propertyKey 为 ! ToString(𝔽(index))。
        2. 如果 index < elementRecordsLen,令 elementRecordelementRecords[index];否则令 elementRecordempty
        3. newElement 为 ? InternalizeJSONProperty(val, propertyKey, reviver, elementRecord)。
        4. 如果 newElementundefined,则
          1. 执行 ? val.[[Delete]](propertyKey)
        5. 否则,
          1. 执行 ? CreateDataProperty(val, propertyKey, newElement)。
        6. index 设置为 index + 1。
    3. 否则,
      1. keys 为 ? EnumerableOwnProperties(val, key)。
      2. 对于 keys 的每个 String propertyKey,执行
        1. 如果存在 entryRecords 的某个元素 entry 使得 entry.[[Key]]propertyKey,令 entryRecordentry;否则令 entryRecordempty
        2. newElement 为 ? InternalizeJSONProperty(val, propertyKey, reviver, entryRecord)。
        3. 如果 newElementundefined,则
          1. 执行 ? val.[[Delete]](propertyKey)
        4. 否则,
          1. 执行 ? CreateDataProperty(val, propertyKey, newElement)。
  6. 返回 ? Call(reviver, holder, « name, val, context »)。

25.5.2.5 Static Semantics: ShallowestContainedJSONValue ( root )

The abstract operation ShallowestContainedJSONValue takes argument root (一个 Parse Node,) and returns 一个 Parse Node 或 empty. 它对以 root 为根的 parse tree 执行广度优先搜索,并返回第一个属于对应 JSON value 的 nonterminal 实例的节点;如果没有这样的节点,则返回 empty。 It performs the following steps when called:

  1. activeFunc活动函数对象
  2. 断言:activeFunc 是一个 JSON.parse 内置函数对象(见 JSON.parse)。
  3. types 为 « NullLiteral, BooleanLiteral, NumericLiteral, StringLiteral, ArrayLiteral, ObjectLiteral, UnaryExpression »。
  4. unaryExpressionempty
  5. queue 为 « root »。
  6. 重复,当 queue 不是空时,
    1. candidatequeue 的第一个元素。
    2. queue 中移除第一个元素。
    3. queuedChildrenfalse
    4. 对于 types 的每个 nonterminal type,执行
      1. 如果 candidatetype 的一个实例,则
        1. 注:在 JSON 语法中,number token 可以表示一个负值。在 ECMAScript 中,取负表示为一元操作,其中 UnaryExpression 解析为 - 后跟一个派生的 UnaryExpression
        2. 如果 typeUnaryExpression,则
          1. 如果 candidate 的 parent 不是 UnaryExpression Parse Node,将 unaryExpression 设置为 candidate
        3. 否则如果 typeNumericLiteral,则
          1. 断言:candidate 包含于 unaryExpression 中。
          2. 返回 unaryExpression
        4. 否则,
          1. 返回 candidate
      2. 如果 queuedChildrenfalsecandidate 是一个 nonterminal 的实例,且 candidate Contains typetrue,则
        1. children 为一个包含 candidate 的每个子节点且按顺序排列的 List
        2. queue 设置为 queuechildren 的列表拼接。
        3. queuedChildren 设置为 true
  7. 返回 empty

25.5.2.6 Static Semantics: JSONArrayLiteralContentNodes

The syntax-directed operation JSONArrayLiteralContentNodes takes no arguments and returns 一个由 Parse Nodes 组成的 List. It is defined piecewise over the following productions:

ArrayLiteral : [ Elisionopt ] [ ElementList ] [ ElementList , Elisionopt ]
  1. 断言:Elision 不存在。
  2. 如果 ElementList 不存在,返回一个新的空 List
  3. 返回 ElementListJSONArrayLiteralContentNodes
ElementList : Elisionopt AssignmentExpression
  1. 断言:Elision 不存在。
  2. 返回 « AssignmentExpression »。
ElementList : ElementList , Elisionopt AssignmentExpression
  1. 断言:Elision 不存在。
  2. elements 为派生的 ElementListJSONArrayLiteralContentNodes
  3. 返回 elements 和 « AssignmentExpression » 的列表拼接。
ElementList : Elisionopt SpreadElement ElementList , Elisionopt SpreadElement
  1. 注:ECMA-404 中指定的 JSON 文本不包含 SpreadElement
  2. 断言:此步骤永远不会到达。

25.5.3 JSON.rawJSON ( text )

此函数返回一个对象,该对象表示字符串、数字、布尔值或 null 值的原始 JSON 文本。

  1. jsonString 为 ? ToString(text)。
  2. 如果 jsonString 是空 String,抛出 SyntaxError 异常。
  3. 如果 jsonString 的第一个 code unit 既不是 ASCII 小写字母 code unit(0x0061 到 0x007A,包含两端)、ASCII 数字 code unit(0x0030 到 0x0039,包含两端)、0x0022 (QUOTATION MARK),也不是 0x002D (HYPHEN-MINUS),抛出 SyntaxError 异常。
  4. 如果 jsonString 的最后一个 code unit 既不是 ASCII 小写字母 code unit(0x0061 到 0x007A,包含两端)、ASCII 数字 code unit(0x0030 到 0x0039,包含两端),也不是 0x0022 (QUOTATION MARK),抛出 SyntaxError 异常。
  5. parseResult 为 ? ParseJSON(jsonString)。
  6. 断言:parseResult.[[Value]] 要么是 String、Number、Boolean,要么是 null
  7. internalSlotsList 为 « [[IsRawJSON]] »。
  8. objOrdinaryObjectCreate(null, internalSlotsList)。
  9. 执行 ! CreateDataPropertyOrThrow(obj, "rawJSON", jsonString)。
  10. 执行 ! SetIntegrityLevel(obj, frozen)。
  11. 返回 obj

25.5.4 JSON.stringify ( value [ , replacer [ , space ] ] )

此函数返回一个采用 UTF-16 编码 JSON 格式的 String,用于表示一个 ECMAScript 语言值;或者返回 undefined。它可以接受三个参数。value 参数是一个 ECMAScript 语言值,通常是对象或数组,不过也可以是 String、Boolean、Number 或 null。可选的 replacer 参数要么是一个改变对象和数组被字符串化方式的函数,要么是一个由 Strings 和 Numbers 组成的数组,该数组作为 inclusion list 来选择将被字符串化的对象属性。可选的 space 参数是一个 String 或 Number,它允许向结果中注入 white space,以提高人类可读性。

它在被调用时执行以下步骤:

  1. stack 为一个新的空 List
  2. indent 为空 String。
  3. propertyListundefined
  4. replacerFunctionundefined
  5. 如果 replacer 是 Object,则
    1. 如果 IsCallable(replacer) 是 true,则
      1. replacerFunction 设置为 replacer
    2. 否则,
      1. isArray 为 ? IsArray(replacer)。
      2. 如果 isArraytrue,则
        1. propertyList 设置为一个新的空 List
        2. len 为 ? LengthOfArrayLike(replacer)。
        3. k 为 0。
        4. 重复,当 k < len 时,
          1. propertyKey 为 ! ToString(𝔽(k))。
          2. propertyValue 为 ? Get(replacer, propertyKey)。
          3. itemundefined
          4. 如果 propertyValue 是 String,则
            1. item 设置为 propertyValue
          5. 否则如果 propertyValue 是 Number,则
            1. item 设置为 ! ToString(propertyValue)。
          6. 否则如果 propertyValue 是 Object,则
            1. 如果 propertyValue[[StringData]][[NumberData]] 内部槽,将 item 设置为 ? ToString(propertyValue)。
          7. 如果 item 不是 undefinedpropertyList 不包含 item,则
            1. item 追加到 propertyList
          8. k 设置为 k + 1。
  6. 如果 space 是 Object,则
    1. 如果 space[[NumberData]] 内部槽,则
      1. space 设置为 ? ToNumber(space)。
    2. 否则如果 space[[StringData]] 内部槽,则
      1. space 设置为 ? ToString(space)。
  7. 如果 space 是 Number,则
    1. spaceMV 为 ! ToIntegerOrInfinity(space)。
    2. spaceMV 设置为 min(10, spaceMV)。
    3. 如果 spaceMV < 1,令 gap 为空 String;否则令 gap 为包含 spaceMV 次 code unit 0x0020 (SPACE) 出现的 String 值。
  8. 否则如果 space 是 String,则
    1. 如果 space 的长度 ≤ 10,令 gapspace;否则令 gapspace 从 0 到 10 的子字符串
  9. 否则,
    1. gap 为空 String。
  10. wrapperOrdinaryObjectCreate(%Object.prototype%)。
  11. 执行 ! CreateDataPropertyOrThrow(wrapper, 空 String, value)。
  12. stateJSON Serialization Record { [[ReplacerFunction]]: replacerFunction, [[Stack]]: stack, [[Indent]]: indent, [[Gap]]: gap, [[PropertyList]]: propertyList }。
  13. 返回 ? SerializeJSONProperty(state, 空 String, wrapper)。

此函数的 "length" 属性为 3𝔽

Note 1

JSON 结构允许嵌套到任意深度,但它们必须是无环的。如果 value 是或包含一个循环结构,则此函数必须抛出 TypeError 异常。以下是一个不能被字符串化的值的示例:

a = [];
a[0] = a;
my_text = JSON.stringify(a); // This must throw a TypeError.
Note 2

符号性 primitive 值按如下方式渲染:

  • null 值在 JSON 文本中渲染为 String 值 "null"
  • undefined 值不会被渲染。
  • true 值在 JSON 文本中渲染为 String 值 "true"
  • false 值在 JSON 文本中渲染为 String 值 "false"
Note 3

String 值被包裹在 QUOTATION MARK (") code units 中。code units "\ 会以 \ 前缀转义。控制字符 code units 会被替换为 escape sequences \uHHHH,或替换为较短形式 \b (BACKSPACE)、\f (FORM FEED)、\n (LINE FEED)、\r (CARRIAGE RETURN)、\t (CHARACTER TABULATION)。

Note 4

有限 numbers 会像调用 ToString(number) 一样被字符串化。无论符号如何,NaNInfinity 都表示为 String 值 "null"

Note 5

没有 JSON 表示的值(例如 undefined 和函数)不会产生 String。它们反而产生 undefined 值。在数组中,这些值表示为 String 值 "null"。在对象中,不可表示值会导致该属性从字符串化中被排除。

Note 6

对象被渲染为 U+007B (LEFT CURLY BRACKET),后跟零个或多个属性,属性之间以 U+002C (COMMA) 分隔,并以 U+007D (RIGHT CURLY BRACKET) 闭合。属性是一个表示属性名的带引号 String、一个 U+003A (COLON),然后是字符串化后的属性值。数组被渲染为开头的 U+005B (LEFT SQUARE BRACKET),后跟零个或多个值,值之间以 U+002C (COMMA) 分隔,并以 U+005D (RIGHT SQUARE BRACKET) 闭合。

25.5.4.1 JSON Serialization Record

JSON Serialization Record 是一个 Record 值,用于启用向 JSON 格式的序列化。

JSON Serialization Records 具有 Table 76 中列出的字段。

Table 76: JSON Serialization Record 字段
字段名 含义
[[ReplacerFunction]] 一个函数对象undefined 能够为对象属性提供替换值的函数(来自 JSON.stringify 的 replacer 参数)。
[[PropertyList]] 要么是一个由 Strings 组成的 List,要么是 undefined 序列化非数组对象时要包含的属性名(来自 JSON.stringify 的 replacer 参数)。
[[Gap]] 一个 String 缩进单位(来自 JSON.stringify 的 space 参数)。
[[Stack]] 一个由 Objects 组成的 List 正在序列化过程中的嵌套对象集合。用于检测循环结构。
[[Indent]] 一个 String 当前缩进。

25.5.4.2 SerializeJSONProperty ( state, key, holder )

The abstract operation SerializeJSONProperty takes arguments state (一个 JSON Serialization Record,), key (一个 String,), and holder (一个 Object,) and returns 要么是一个包含 String 或 undefined正常完成,要么是一个抛出完成. It performs the following steps when called:

  1. value 为 ? Get(holder, key)。
  2. 如果 value 是一个 Object 或 value 是一个 BigInt,则
    1. toJSON 为 ? GetV(value, "toJSON")。
    2. 如果 IsCallable(toJSON) 为 true,则
      1. value 设为 ? Call(toJSON, value, « key »)。
  3. 如果 state.[[ReplacerFunction]] 不是 undefined,则
    1. value 设为 ? Call(state.[[ReplacerFunction]], holder, « key, value »)。
  4. 如果 value 是一个 Object,则
    1. 如果 value 具有 [[IsRawJSON]] 内部槽,则
      1. rawJSON 为 ! Get(value, "rawJSON")。
      2. 断言:rawJSON 是一个 String。
      3. 返回 rawJSON
    2. 如果 value 具有 [[NumberData]] 内部槽,则
      1. value 设为 ? ToNumber(value)。
    3. 否则,如果 value 具有 [[StringData]] 内部槽,则
      1. value 设为 ? ToString(value)。
    4. 否则,如果 value 具有 [[BooleanData]] 内部槽,则
      1. value 设为 value.[[BooleanData]]
    5. 否则,如果 value 具有 [[BigIntData]] 内部槽,则
      1. value 设为 value.[[BigIntData]]
  5. 如果 valuenull,返回 "null"
  6. 如果 valuetrue,返回 "true"
  7. 如果 valuefalse,返回 "false"
  8. 如果 value 是一个 String,返回 QuoteJSONString(value)。
  9. 如果 value 是一个 Number,则
    1. 如果 value有限的,返回 ! ToString(value)。
    2. 返回 "null"
  10. 如果 value 是一个 BigInt,抛出一个 TypeError 异常。
  11. 如果 value 是一个 Object 且 IsCallable(value) 为 false,则
    1. isArray 为 ? IsArray(value)。
    2. 如果 isArraytrue,则
      1. 返回 ? SerializeJSONArray(state, value)。
    3. 返回 ? SerializeJSONObject(state, value)。
  12. 返回 undefined

25.5.4.3 QuoteJSONString ( value )

The abstract operation QuoteJSONString takes argument value (一个 String,) and returns 一个 String. 它用 0x0022 (QUOTATION MARK) code units 包裹 value,并转义其中的某些其他 code units。此操作按 6.1.4 中描述的方式,将 value 解释为一个 UTF-16 编码 code points 序列。 It performs the following steps when called:

  1. product 为仅由 code unit 0x0022 (QUOTATION MARK) 组成的 String 值。
  2. 对于 StringToCodePoints(value) 的每个 code point cp,执行
    1. 如果 cp 列于 Table 77 的 “Code Point” 列中,则
      1. product 设置为 product 与对应行 “Escape Sequence” 列中指定的 cp 的 escape sequence 的字符串拼接。
    2. 否则如果 cp 的数值小于 0x0020 (SPACE),或 cp 具有与 leading surrogate 或 trailing surrogate 相同的数值,则
      1. unit 为其数值等于 cp 数值的 code unit。
      2. product 设置为 productUnicodeEscape(unit) 的字符串拼接。
    3. 否则,
      1. product 设置为 productUTF16EncodeCodePoint(cp) 的字符串拼接。
  3. product 设置为 product 与 code unit 0x0022 (QUOTATION MARK) 的字符串拼接。
  4. 返回 product
Table 77: JSON 单字符转义序列
Code Point Unicode 字符名称 转义序列
U+0008 BACKSPACE \b
U+0009 CHARACTER TABULATION \t
U+000A LINE FEED (LF) \n
U+000C FORM FEED (FF) \f
U+000D CARRIAGE RETURN (CR) \r
U+0022 QUOTATION MARK \"
U+005C REVERSE SOLIDUS \\

25.5.4.4 UnicodeEscape ( constructor )

The abstract operation UnicodeEscape takes argument constructor (一个 code unit,) and returns 一个 String. 它将 constructor 表示为一个 Unicode escape sequence。 It performs the following steps when called:

  1. nconstructor 的数值。
  2. 断言:n ≤ 0xFFFF。
  3. hexn 的 String 表示,格式化为小写十六进制数。
  4. 返回 code unit 0x005C (REVERSE SOLIDUS)、"u"StringPad(hex, 4, "0", start) 的字符串拼接。

25.5.4.5 SerializeJSONObject ( state, value )

The abstract operation SerializeJSONObject takes arguments state (一个 JSON Serialization Record,) and value (一个 Object,) and returns 要么是一个包含 String 的正常完成,要么是一个抛出完成. 它序列化一个对象。 It performs the following steps when called:

  1. 如果 state.[[Stack]] 包含 value,抛出 TypeError 异常,因为该结构是循环的。
  2. value 追加到 state.[[Stack]]
  3. stepBackstate.[[Indent]]
  4. state.[[Indent]] 设置为 state.[[Indent]]state.[[Gap]] 的字符串拼接。
  5. 如果 state.[[PropertyList]] 不是 undefined,则
    1. keysstate.[[PropertyList]]
  6. 否则,
    1. keys 为 ? EnumerableOwnProperties(value, key)。
  7. partial 为一个新的空 List
  8. 对于 keys 的每个元素 propertyKey,执行
    1. strP 为 ? SerializeJSONProperty(state, propertyKey, value)。
    2. 如果 strP 不是 undefined,则
      1. memberQuoteJSONString(propertyKey)。
      2. member 设置为 member":" 的字符串拼接。
      3. 如果 state.[[Gap]] 不是空 String,则
        1. member 设置为 member 和 code unit 0x0020 (SPACE) 的字符串拼接。
      4. member 设置为 memberstrP 的字符串拼接。
      5. member 追加到 partial
  9. 如果 partial 为空,则
    1. final"{}"
  10. 否则,
    1. 如果 state.[[Gap]] 是空 String,则
      1. properties 为通过拼接 partial 中所有元素 Strings 形成的 String 值,相邻每对 Strings 之间以 code unit 0x002C (COMMA) 分隔。逗号既不会插入在第一个 String 之前,也不会插入在最后一个 String 之后。
      2. final"{"properties"}" 的字符串拼接。
    2. 否则,
      1. separator 为 code unit 0x002C (COMMA)、code unit 0x000A (LINE FEED) 和 state.[[Indent]] 的字符串拼接。
      2. properties 为通过拼接 partial 中所有元素 Strings 形成的 String 值,相邻每对 Strings 之间以 separator 分隔。separator String 既不会插入在第一个 String 之前,也不会插入在最后一个 String 之后。
      3. final"{"、code unit 0x000A (LINE FEED)、state.[[Indent]]properties、code unit 0x000A (LINE FEED)、stepBack"}" 的字符串拼接。
  11. 移除 state.[[Stack]] 的最后一个元素。
  12. state.[[Indent]] 设置为 stepBack
  13. 返回 final

25.5.4.6 SerializeJSONArray ( state, value )

The abstract operation SerializeJSONArray takes arguments state (a JSON Serialization Record) and value (an Object) and returns either a normal completion containing a String or a throw completion. 它序列化一个数组。 It performs the following steps when called:

  1. 如果 state.[[Stack]] 包含 value,抛出 TypeError 异常,因为该结构是循环的。
  2. value 追加到 state.[[Stack]]
  3. stepBackstate.[[Indent]]
  4. state.[[Indent]] 设置为 state.[[Indent]]state.[[Gap]] 的字符串拼接。
  5. partial 为一个新的空 List
  6. len 为 ? LengthOfArrayLike(value)。
  7. index 为 0。
  8. 重复,当 index < len 时,
    1. strP 为 ? SerializeJSONProperty(state, ! ToString(𝔽(index)), value)。
    2. 如果 strPundefined,则
      1. "null" 追加到 partial
    3. 否则,
      1. strP 追加到 partial
    4. index 设置为 index + 1。
  9. 如果 partial 为空,则
    1. final"[]"
  10. 否则,
    1. 如果 state.[[Gap]] 是空 String,则
      1. properties 为通过拼接 partial 中所有元素 Strings 形成的 String 值,相邻每对 Strings 之间以 code unit 0x002C (COMMA) 分隔。逗号既不会插入在第一个 String 之前,也不会插入在最后一个 String 之后。
      2. final"["properties"]" 的字符串拼接。
    2. 否则,
      1. separator 为 code unit 0x002C (COMMA)、code unit 0x000A (LINE FEED) 和 state.[[Indent]] 的字符串拼接。
      2. properties 为通过拼接 partial 中所有元素 Strings 形成的 String 值,相邻每对 Strings 之间以 separator 分隔。separator String 既不会插入在第一个 String 之前,也不会插入在最后一个 String 之后。
      3. final"["、code unit 0x000A (LINE FEED)、state.[[Indent]]properties、code unit 0x000A (LINE FEED)、stepBack"]" 的字符串拼接。
  11. 移除 state.[[Stack]] 的最后一个元素。
  12. state.[[Indent]] 设置为 stepBack
  13. 返回 final
Note

数组的表示仅包括从 +0𝔽(包含)到 array.length(不包含)区间内的元素。键不是数组索引的属性会从字符串化中被排除。数组被字符串化为一个开头的 LEFT SQUARE BRACKET、以 COMMA 分隔的元素,以及一个闭合的 RIGHT SQUARE BRACKET。

25.5.5 JSON [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "JSON"

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

26 管理内存

26.1 WeakRef 对象

WeakRef 是一种对象,用于引用目标对象或符号,而不阻止其被垃圾回收。WeakRefs 可以被解引用,以便在目标尚未被垃圾回收回收的情况下允许访问目标值。

26.1.1 WeakRef 构造器

WeakRef 构造器

  • %WeakRef%
  • 全局对象"WeakRef" 属性的初始值。
  • 当作为构造器调用时,创建并初始化一个新的 WeakRef。
  • 不意图作为函数调用,并且在以这种方式调用时会抛出异常。
  • 可用作类定义中 extends 子句的值。意图继承指定 WeakRef 行为的子类构造器必须包含对 WeakRef 构造器super 调用,以创建并初始化具有支持 WeakRef.prototype 内置方法所必需内部状态的子类实例。

26.1.1.1 WeakRef ( target )

此函数在被调用时执行以下步骤:

  1. 如果 NewTarget 是 undefined,抛出 TypeError 异常。
  2. 如果 CanBeHeldWeakly(target) 是 false,抛出 TypeError 异常。
  3. weakRef 为 ? OrdinaryCreateFromConstructor(NewTarget, "%WeakRef.prototype%", « [[WeakRefTarget]] »)。
  4. 执行 AddToKeptObjects(target)。
  5. weakRef.[[WeakRefTarget]] 设置为 target
  6. 返回 weakRef

26.1.2 WeakRef 构造器的属性

WeakRef 构造器

26.1.2.1 WeakRef.prototype

WeakRef.prototype 的初始值是 WeakRef 原型对象

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

26.1.3 WeakRef 原型对象的属性

WeakRef 原型对象

  • %WeakRef.prototype%
  • 有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%
  • 是一个普通对象
  • 没有 [[WeakRefTarget]] 内部槽。
Normative Optional

26.1.3.1 WeakRef.prototype.constructor

WeakRef.prototype.constructor 的初始值是 %WeakRef%

26.1.3.2 WeakRef.prototype.deref ( )

此方法在被调用时执行以下步骤:

  1. weakRefthis 值。
  2. 执行 ? RequireInternalSlot(weakRef, [[WeakRefTarget]])。
  3. 返回 WeakRefDeref(weakRef)。
Note

如果 WeakRef 返回一个不是 undefinedtarget 值,则在当前 ECMAScript 代码执行完成之前,不应对该 target 值进行垃圾回收。AddToKeptObjects 操作用于确保保持读取一致性。

let target = { foo() {} };
let weakRef = new WeakRef(target);

// ... 稍后 ...

if (weakRef.deref()) {
  weakRef.deref().foo();
}

在上述示例中,如果第一次 deref 未求值为 undefined,则第二次 deref 也不可能求值为 undefined

26.1.3.3 WeakRef.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "WeakRef"

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

26.1.4 WeakRef 抽象操作

26.1.4.1 WeakRefDeref ( weakRef )

The abstract operation WeakRefDeref takes argument weakRef (一个 WeakRef,) and returns 一个 ECMAScript 语言值. It performs the following steps when called:

  1. targetweakRef.[[WeakRefTarget]]
  2. 如果 target 不是 empty,则
    1. 执行 AddToKeptObjects(target)。
    2. 返回 target
  3. 返回 undefined
Note

抽象操作与 WeakRef.prototype.deref 分开定义,严格来说是为了能够简洁地定义 liveness。

26.1.5 WeakRef 实例的属性

WeakRef 实例是从 WeakRef 原型对象继承属性的普通对象WeakRef 实例还具有 [[WeakRefTarget]] 内部槽。

26.2 FinalizationRegistry 对象

FinalizationRegistry 是一种对象,用于管理在目标对象和符号被垃圾回收时执行的清理操作的注册和注销。

26.2.1 FinalizationRegistry 构造器

FinalizationRegistry 构造器

  • %FinalizationRegistry%
  • 全局对象"FinalizationRegistry" 属性的初始值。
  • 当作为构造器调用时,创建并初始化一个新的 FinalizationRegistry。
  • 不意图作为函数调用,并且在以这种方式调用时会抛出异常。
  • 可用作类定义中 extends 子句的值。意图继承指定 FinalizationRegistry 行为的子类构造器必须包含对 FinalizationRegistry 构造器super 调用,以创建并初始化具有支持 FinalizationRegistry.prototype 内置方法所必需内部状态的子类实例。

26.2.1.1 FinalizationRegistry ( cleanupCallback )

此函数在被调用时执行以下步骤:

  1. 如果 NewTarget 是 undefined,抛出 TypeError 异常。
  2. 如果 IsCallable(cleanupCallback) 是 false,抛出 TypeError 异常。
  3. finalizationRegistry 为 ? OrdinaryCreateFromConstructor(NewTarget, "%FinalizationRegistry.prototype%", « [[Realm]], [[CleanupCallback]], [[Cells]] »)。
  4. fn活动函数对象
  5. finalizationRegistry.[[Realm]] 设置为 fn.[[Realm]]
  6. finalizationRegistry.[[CleanupCallback]] 设置为 HostMakeJobCallback(cleanupCallback)。
  7. finalizationRegistry.[[Cells]] 设置为一个新的空 List
  8. 返回 finalizationRegistry

26.2.2 FinalizationRegistry 构造器的属性

FinalizationRegistry 构造器

26.2.2.1 FinalizationRegistry.prototype

FinalizationRegistry.prototype 的初始值是 FinalizationRegistry 原型对象

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

26.2.3 FinalizationRegistry 原型对象的属性

FinalizationRegistry 原型对象

  • %FinalizationRegistry.prototype%
  • 有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%
  • 是一个普通对象
  • 没有 [[Cells]][[CleanupCallback]] 内部槽。

26.2.3.1 FinalizationRegistry.prototype.constructor

FinalizationRegistry.prototype.constructor 的初始值是 %FinalizationRegistry%

26.2.3.2 FinalizationRegistry.prototype.register ( target, heldValue [ , unregisterToken ] )

此方法在被调用时执行以下步骤:

  1. finalizationRegistrythis 值。
  2. 执行 ? RequireInternalSlot(finalizationRegistry, [[Cells]])。
  3. 如果 CanBeHeldWeakly(target) 是 false,抛出 TypeError 异常。
  4. 如果 SameValue(target, heldValue) 是 true,抛出 TypeError 异常。
  5. 如果 CanBeHeldWeakly(unregisterToken) 是 false,则
    1. 如果 unregisterToken 不是 undefined,抛出 TypeError 异常。
    2. unregisterToken 设置为 empty
  6. cellRecord { [[WeakRefTarget]]: target, [[HeldValue]]: heldValue, [[UnregisterToken]]: unregisterToken }。
  7. cell 追加到 finalizationRegistry.[[Cells]]
  8. 返回 undefined
Note

根据本规范中的算法和定义,当 finalizationRegistry.[[Cells]] 包含 cell 时,cell.[[HeldValue]] 是 live 的;然而,这并不必然意味着 cell.[[UnregisterToken]]cell.[[Target]] 是 live 的。例如,将一个对象以其自身作为 unregister token 注册,并不会让该对象永远保持存活。

26.2.3.3 FinalizationRegistry.prototype.unregister ( unregisterToken )

此方法在被调用时执行以下步骤:

  1. finalizationRegistrythis 值。
  2. 执行 ? RequireInternalSlot(finalizationRegistry, [[Cells]])。
  3. 如果 CanBeHeldWeakly(unregisterToken) 是 false,抛出 TypeError 异常。
  4. removedfalse
  5. 对于 finalizationRegistry.[[Cells]] 的每个 Record { [[WeakRefTarget]], [[HeldValue]], [[UnregisterToken]] } cell,执行
    1. 如果 cell.[[UnregisterToken]] 不是 emptySameValue(cell.[[UnregisterToken]], unregisterToken) 是 true,则
      1. finalizationRegistry.[[Cells]] 中移除 cell
      2. removed 设置为 true
  6. 返回 removed

26.2.3.4 FinalizationRegistry.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "FinalizationRegistry"

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

26.2.4 FinalizationRegistry 实例的属性

FinalizationRegistry 实例是从 FinalizationRegistry 原型对象继承属性的普通对象FinalizationRegistry 实例还具有 [[Cells]][[CleanupCallback]] 内部槽。

27 控制抽象对象

27.1 迭代

27.1.1 通用迭代接口

接口是一组属性键,其关联值匹配特定规范。任何提供接口规范所描述的全部属性的对象都符合该接口。接口并不由一个不同的对象来表示。可以有许多分别实现的对象符合任一接口。单个对象可以符合多个接口。

27.1.1.1 可迭代接口

可迭代接口包含 Table 78 中描述的属性:

Table 78: 可迭代接口的必需属性
属性 要求
%Symbol.iterator% 一个返回迭代器对象的函数 返回的对象必须符合迭代器接口

27.1.1.2 迭代器接口

实现迭代器接口的对象必须包含 Table 79 中的属性。这样的对象也可以实现 Table 80 中的属性。

Table 79: 迭代器接口的必需属性
属性 要求
"next" 一个返回 IteratorResult 对象的函数 返回的对象必须符合 IteratorResult 接口。如果对某个迭代器的 next 方法的前一次调用返回了一个 "done" 属性为 true 的 IteratorResult 对象,那么之后对该对象的 next 方法的所有调用也应返回一个 "done" 属性为 true 的 IteratorResult 对象。不过,此要求不强制执行。
Note 1

可以向 next 函数传递实参,但这些实参的解释和有效性取决于目标迭代器。for-of 语句和迭代器的其他常见使用者不会传递任何实参,因此期望以这种方式使用的迭代器对象必须准备好处理无实参调用。

Table 80: 迭代器接口的可选属性
属性 要求
"return" 一个返回 IteratorResult 对象的函数 返回的对象必须符合 IteratorResult 接口。调用此方法会通知迭代器对象,调用者不打算再对该迭代器调用任何 next 方法。返回的 IteratorResult 对象通常会有一个值为 true"done" 属性,以及一个 "value" 属性,其值为作为 return 方法实参传入的值。不过,此要求不强制执行。
"throw" 一个返回 IteratorResult 对象的函数 返回的对象必须符合 IteratorResult 接口。调用此方法会通知迭代器对象,调用者已检测到错误条件。实参可用于标识该错误条件,通常会是一个异常对象。典型的响应是 throw 作为实参传入的值。如果该方法不 throw,则返回的 IteratorResult 对象通常会有一个值为 true"done" 属性。
Note 2

通常,这些方法的调用者在调用之前应检查它们是否存在。某些 ECMAScript 语言特性,包括 for-ofyield* 和数组解构,会在执行存在性检查后调用这些方法。大多数接受可迭代对象作为实参的 ECMAScript 库函数也会有条件地调用它们。

27.1.1.3 异步可迭代接口

异步可迭代接口包含 Table 81 中描述的属性:

Table 81: 异步可迭代接口的必需属性
属性 要求
%Symbol.asyncIterator% 一个返回异步迭代器对象的函数 返回的对象必须符合异步迭代器接口

27.1.1.4 异步迭代器接口

实现异步迭代器接口的对象必须包含 Table 82 中的属性。这样的对象也可以实现 Table 83 中的属性。

Table 82: 异步迭代器接口的必需属性
属性 要求
"next" 一个返回 IteratorResult 对象 promise 的函数

返回的 promise 在兑现时,必须以一个符合 IteratorResult 接口的对象兑现。如果对某个异步迭代器的 next 方法的前一次调用返回了一个 IteratorResult 对象的 promise,且该对象的 "done" 属性为 true,那么之后对该对象的 next 方法的所有调用也应返回一个 IteratorResult 对象的 promise,且该对象的 "done" 属性为 true。不过,此要求不强制执行。

此外,作为兑现值的 IteratorResult 对象应有一个 "value" 属性,其值不是 promise(也不是“thenable”)。不过,此要求也不强制执行。

Note 1

可以向 next 函数传递实参,但这些实参的解释和有效性取决于目标异步迭代器。for-await-of 语句和异步迭代器的其他常见使用者不会传递任何实参,因此期望以这种方式使用的异步迭代器对象必须准备好处理无实参调用。

Table 83: 异步迭代器接口的可选属性
属性 要求
"return" 一个返回 IteratorResult 对象 promise 的函数

返回的 promise 在兑现时,必须以一个符合 IteratorResult 接口的对象兑现。调用此方法会通知异步迭代器对象,调用者不打算再对该异步迭代器调用任何 next 方法。返回的 promise 将以一个 IteratorResult 对象兑现,该对象通常会有一个值为 true"done" 属性,以及一个 "value" 属性,其值为作为 return 方法实参传入的值。不过,此要求不强制执行。

此外,作为兑现值的 IteratorResult 对象应有一个 "value" 属性,其值不是 promise(也不是“thenable”)。如果实参值按典型方式使用,那么如果它是一个被拒绝的 promise,则应返回一个以相同原因拒绝的 promise;如果它是一个已兑现的 promise,则应将其兑现值用作返回的 promise 的 IteratorResult 对象兑现值的 "value" 属性。不过,这些要求也不强制执行。

"throw" 一个返回 IteratorResult 对象 promise 的函数

返回的 promise 在兑现时,必须以一个符合 IteratorResult 接口的对象兑现。调用此方法会通知异步迭代器对象,调用者已检测到错误条件。实参可用于标识该错误条件,通常会是一个异常对象。典型的响应是返回一个被拒绝的 promise,并以作为实参传入的值作为拒绝原因。

如果返回的 promise 被兑现,则 IteratorResult 对象兑现值通常会有一个值为 true"done" 属性。此外,它应有一个 "value" 属性,其值不是 promise(也不是“thenable”),但此要求不强制执行。

Note 2

通常,这些方法的调用者在调用之前应检查它们是否存在。某些 ECMAScript 语言特性,包括 for-await-ofyield*,会在执行存在性检查后调用这些方法。

27.1.1.5 IteratorResult 接口

IteratorResult 接口包含 Table 84 中列出的属性:

Table 84: IteratorResult 接口属性
属性 要求
"done" 一个布尔值 这是迭代器 next 方法调用的结果状态。如果已到达迭代器的末尾,"done"true。如果尚未到达末尾,"done"false,并且有一个值可用。如果 "done" 属性(自有或继承的)不存在,则认为其值为 false
"value" 一个 ECMAScript 语言值 如果 done 为 false,这是当前迭代元素的值。如果 done 为 true,这是迭代器的返回值(如果它提供了一个)。如果迭代器没有返回值,则 "value"undefined。在这种情况下,如果符合接口的对象没有继承显式的 "value" 属性,则该对象可以不存在 "value" 属性。

27.1.2 迭代器辅助对象

迭代器辅助对象是一个普通对象,表示对某个特定源迭代器对象的惰性变换。Iterator Helper 对象没有具名构造器Iterator Helper 对象是通过调用 Iterator 实例对象的某些方法创建的。

27.1.2.1 %IteratorHelperPrototype% 对象

%IteratorHelperPrototype% 对象:

27.1.2.1.1 %IteratorHelperPrototype%.next ( )

  1. 返回 ? GeneratorResume(this value, undefined, "Iterator Helper")。

27.1.2.1.2 %IteratorHelperPrototype%.return ( )

  1. objthis 值。
  2. 执行 ? RequireInternalSlot(obj, [[UnderlyingIterators]])。
  3. 断言:obj 具有 [[GeneratorState]] 内部槽。
  4. 如果 obj.[[GeneratorState]]suspended-start,则
    1. obj.[[GeneratorState]] 设为 completed
    2. 注:一旦生成器进入 completed 状态,它就永远不会离开该状态,并且其关联的执行上下文永远不会恢复。此时可以丢弃与 obj 关联的任何执行状态。
    3. 执行 ? IteratorCloseAll(obj.[[UnderlyingIterators]], NormalCompletion(unused))。
    4. 返回 CreateIteratorResultObject(undefined, true)。
  5. completionReturnCompletion(undefined)。
  6. 返回 ? GeneratorResumeAbrupt(obj, completion, "Iterator Helper")。

27.1.2.1.3 %IteratorHelperPrototype% [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是字符串值 "Iterator Helper"

此属性具有属性特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

27.1.3 Iterator 对象

27.1.3.1 Iterator 构造器

Iterator 构造器

  • %Iterator%
  • 全局对象"Iterator" 属性的初始值。
  • 被设计为可子类化。它可用作类定义的 extends 子句的值。

27.1.3.1.1 Iterator ( )

此函数在被调用时执行以下步骤:

  1. 如果 NewTarget 是 undefined活动函数对象,则抛出 TypeError 异常。
  2. 返回 ? OrdinaryCreateFromConstructor(NewTarget, "%Iterator.prototype%")。

27.1.3.2 Iterator 构造器的属性

Iterator 构造器

27.1.3.2.1 Iterator.concat ( ...items )

  1. iterables 为一个新的空 List
  2. 对于 items 的每个元素 item,执行
    1. 如果 item 不是 Object,则抛出 TypeError 异常。
    2. method 为 ? GetMethod(item, %Symbol.iterator%)。
    3. 如果 methodundefined,则抛出 TypeError 异常。
    4. Record { [[OpenMethod]]: method, [[Iterable]]: item } 追加到 iterables
  3. closure 为一个新的无参数抽象闭包,它捕获 iterables,并在被调用时执行以下步骤:
    1. 对于 iterables 的每个 Record iterable,执行
      1. iter 为 ? Call(iterable.[[OpenMethod]], iterable.[[Iterable]])。
      2. 如果 iter 不是 Object,则抛出 TypeError 异常。
      3. iteratorRecord 为 ? GetIteratorDirect(iter)。
      4. innerAlivetrue
      5. 重复,当 innerAlivetrue 时,
        1. innerValue 为 ? IteratorStepValue(iteratorRecord)。
        2. 如果 innerValuedone,则
          1. innerAlive 设为 false
        3. 否则,
          1. completionCompletion(Yield(innerValue))。
          2. 如果 completion 是 abrupt completion,则
            1. 返回 ? IteratorClose(iteratorRecord, completion)。
    2. 返回 ReturnCompletion(undefined)。
  4. genCreateIteratorFromClosure(closure, "Iterator Helper", %IteratorHelperPrototype%, « [[UnderlyingIterators]] »)。
  5. gen.[[UnderlyingIterators]] 设为一个新的空 List
  6. 返回 gen

27.1.3.2.2 Iterator.from ( obj )

  1. iteratorRecord 为 ? GetIteratorFlattenable(obj, iterate-string-primitives)。
  2. hasInstance 为 ? OrdinaryHasInstance(%Iterator%, iteratorRecord.[[Iterator]])。
  3. 如果 hasInstancetrue,则
    1. 返回 iteratorRecord.[[Iterator]]
  4. wrapperOrdinaryObjectCreate(%WrapForValidIteratorPrototype%, « [[Iterated]] »)。
  5. wrapper.[[Iterated]] 设为 iteratorRecord
  6. 返回 wrapper

27.1.3.2.2.1 %WrapForValidIteratorPrototype% 对象

%WrapForValidIteratorPrototype% 对象:

27.1.3.2.2.1.1 %WrapForValidIteratorPrototype%.next ( )

  1. objthis 值。
  2. 执行 ? RequireInternalSlot(obj, [[Iterated]])。
  3. iteratorRecordobj.[[Iterated]]
  4. 返回 ? Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]])。

27.1.3.2.2.1.2 %WrapForValidIteratorPrototype%.return ( )

  1. objthis 值。
  2. 执行 ? RequireInternalSlot(obj, [[Iterated]])。
  3. iteratorobj.[[Iterated]].[[Iterator]]
  4. 断言:iterator 是 Object。
  5. returnMethod 为 ? GetMethod(iterator, "return")。
  6. 如果 returnMethodundefined,则
    1. 返回 CreateIteratorResultObject(undefined, true)。
  7. 返回 ? Call(returnMethod, iterator)。

27.1.3.2.3 Iterator.prototype

Iterator.prototype 的初始值是 Iterator 原型对象

此属性具有属性特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

27.1.3.3 Iterator 原型对象的属性

Iterator 原型对象

Note

本规范中定义的所有实现迭代器接口的对象也都继承自 %Iterator.prototype%。ECMAScript 代码也可以定义继承自 %Iterator.prototype% 的对象。%Iterator.prototype% 提供了一个位置,可在其中添加适用于所有迭代器对象的其他方法。

以下表达式是 ECMAScript 代码访问 %Iterator.prototype% 对象的一种方式:

Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()))

27.1.3.3.1 Iterator.prototype.constructor

Iterator.prototype.constructor 是一个访问器属性,具有属性特性 { [[Enumerable]]: false, [[Configurable]]: true }。[[Get]][[Set]] 属性特性定义如下:

27.1.3.3.1.1 get Iterator.prototype.constructor

[[Get]] 属性特性的值是一个不需要实参的内置函数。它在被调用时执行以下步骤:

  1. 返回 %Iterator%

27.1.3.3.1.2 set Iterator.prototype.constructor

[[Set]] 属性特性的值是一个接受实参 v 的内置函数。它在被调用时执行以下步骤:

  1. 执行 ? SetterThatIgnoresPrototypeProperties(this value, %Iterator.prototype%, "constructor", v)。
  2. 返回 undefined
Note

与大多数内置原型上的 "constructor" 属性不同,出于 Web 兼容性原因,此属性必须是访问器。

27.1.3.3.2 Iterator.prototype.drop ( limit )

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. 如果 obj 不是 Object,则抛出 TypeError 异常。
  3. iteratedIterator Record { [[Iterator]]: obj, [[NextMethod]]: undefined, [[Done]]: false }。
  4. numLimitCompletion(ToNumber(limit))。
  5. IfAbruptCloseIterator(numLimit, iterated)。
  6. 如果 numLimitNaN,则
    1. errorThrowCompletion(一个新创建的 RangeError 对象)。
    2. 返回 ? IteratorClose(iterated, error)。
  7. integerLimit 为 ! ToIntegerOrInfinity(numLimit)。
  8. 如果 integerLimit < 0,则
    1. errorThrowCompletion(一个新创建的 RangeError 对象)。
    2. 返回 ? IteratorClose(iterated, error)。
  9. iterated 设为 ? GetIteratorDirect(obj)。
  10. closure 为一个新的无参数抽象闭包,它捕获 iteratedintegerLimit,并在被调用时执行以下步骤:
    1. remainingintegerLimit
    2. 重复,当 remaining > 0 时,
      1. 如果 remaining ≠ +∞,则
        1. remaining 设为 remaining - 1。
      2. next 为 ? IteratorStep(iterated)。
      3. 如果 nextdone,返回 ReturnCompletion(undefined)。
    3. 重复,
      1. value 为 ? IteratorStepValue(iterated)。
      2. 如果 valuedone,返回 ReturnCompletion(undefined)。
      3. completionCompletion(Yield(value))。
      4. IfAbruptCloseIterator(completion, iterated)。
  11. resultCreateIteratorFromClosure(closure, "Iterator Helper", %IteratorHelperPrototype%, « [[UnderlyingIterators]] »)。
  12. result.[[UnderlyingIterators]] 设为 « iterated »。
  13. 返回 result

27.1.3.3.3 Iterator.prototype.every ( predicate )

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. 如果 obj 不是 Object,则抛出 TypeError 异常。
  3. iteratedIterator Record { [[Iterator]]: obj, [[NextMethod]]: undefined, [[Done]]: false }。
  4. 如果 IsCallable(predicate) 为 false,则
    1. errorThrowCompletion(一个新创建的 TypeError 对象)。
    2. 返回 ? IteratorClose(iterated, error)。
  5. iterated 设为 ? GetIteratorDirect(obj)。
  6. counter 为 0。
  7. 重复,
    1. value 为 ? IteratorStepValue(iterated)。
    2. 如果 valuedone,返回 true
    3. resultCompletion(Call(predicate, undefined, « value, 𝔽(counter) »))。
    4. IfAbruptCloseIterator(result, iterated)。
    5. 如果 ToBoolean(result) 为 false,返回 ? IteratorClose(iterated, NormalCompletion(false))。
    6. counter 设为 counter + 1。

27.1.3.3.4 Iterator.prototype.filter ( predicate )

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. 如果 obj 不是 Object,则抛出 TypeError 异常。
  3. iteratedIterator Record { [[Iterator]]: obj, [[NextMethod]]: undefined, [[Done]]: false }。
  4. 如果 IsCallable(predicate) 为 false,则
    1. errorThrowCompletion(一个新创建的 TypeError 对象)。
    2. 返回 ? IteratorClose(iterated, error)。
  5. iterated 设为 ? GetIteratorDirect(obj)。
  6. closure 为一个新的无参数抽象闭包,它捕获 iteratedpredicate,并在被调用时执行以下步骤:
    1. counter 为 0。
    2. 重复,
      1. value 为 ? IteratorStepValue(iterated)。
      2. 如果 valuedone,返回 ReturnCompletion(undefined)。
      3. selectedCompletion(Call(predicate, undefined, « value, 𝔽(counter) »))。
      4. IfAbruptCloseIterator(selected, iterated)。
      5. 如果 ToBoolean(selected) 为 true,则
        1. completionCompletion(Yield(value))。
        2. IfAbruptCloseIterator(completion, iterated)。
      6. counter 设为 counter + 1。
  7. resultCreateIteratorFromClosure(closure, "Iterator Helper", %IteratorHelperPrototype%, « [[UnderlyingIterators]] »)。
  8. result.[[UnderlyingIterators]] 设为 « iterated »。
  9. 返回 result

27.1.3.3.5 Iterator.prototype.find ( predicate )

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. 如果 obj 不是 Object,则抛出 TypeError 异常。
  3. iteratedIterator Record { [[Iterator]]: obj, [[NextMethod]]: undefined, [[Done]]: false }。
  4. 如果 IsCallable(predicate) 为 false,则
    1. errorThrowCompletion(一个新创建的 TypeError 对象)。
    2. 返回 ? IteratorClose(iterated, error)。
  5. iterated 设为 ? GetIteratorDirect(obj)。
  6. counter 为 0。
  7. 重复,
    1. value 为 ? IteratorStepValue(iterated)。
    2. 如果 valuedone,返回 undefined
    3. resultCompletion(Call(predicate, undefined, « value, 𝔽(counter) »))。
    4. IfAbruptCloseIterator(result, iterated)。
    5. 如果 ToBoolean(result) 为 true,返回 ? IteratorClose(iterated, NormalCompletion(value))。
    6. counter 设为 counter + 1。

27.1.3.3.6 Iterator.prototype.flatMap ( mapper )

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. 如果 obj 不是 Object,则抛出 TypeError 异常。
  3. iteratedIterator Record { [[Iterator]]: obj, [[NextMethod]]: undefined, [[Done]]: false }。
  4. 如果 IsCallable(mapper) 为 false,则
    1. errorThrowCompletion(一个新创建的 TypeError 对象)。
    2. 返回 ? IteratorClose(iterated, error)。
  5. iterated 设为 ? GetIteratorDirect(obj)。
  6. closure 为一个新的无参数抽象闭包,它捕获 iteratedmapper,并在被调用时执行以下步骤:
    1. counter 为 0。
    2. 重复,
      1. value 为 ? IteratorStepValue(iterated)。
      2. 如果 valuedone,返回 ReturnCompletion(undefined)。
      3. mappedCompletion(Call(mapper, undefined, « value, 𝔽(counter) »))。
      4. IfAbruptCloseIterator(mapped, iterated)。
      5. innerIteratorCompletion(GetIteratorFlattenable(mapped, reject-primitives))。
      6. IfAbruptCloseIterator(innerIterator, iterated)。
      7. innerAlivetrue
      8. 重复,当 innerAlivetrue 时,
        1. innerValueCompletion(IteratorStepValue(innerIterator))。
        2. IfAbruptCloseIterator(innerValue, iterated)。
        3. 如果 innerValuedone,则
          1. innerAlive 设为 false
        4. 否则,
          1. completionCompletion(Yield(innerValue))。
          2. 如果 completion 是 abrupt completion,则
            1. backupCompletionCompletion(IteratorClose(innerIterator, completion))。
            2. IfAbruptCloseIterator(backupCompletion, iterated)。
            3. 返回 ? IteratorClose(iterated, completion)。
      9. counter 设为 counter + 1。
  7. resultCreateIteratorFromClosure(closure, "Iterator Helper", %IteratorHelperPrototype%, « [[UnderlyingIterators]] »)。
  8. result.[[UnderlyingIterators]] 设为 « iterated »。
  9. 返回 result

27.1.3.3.7 Iterator.prototype.forEach ( procedure )

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. 如果 obj 不是 Object,则抛出 TypeError 异常。
  3. iteratedIterator Record { [[Iterator]]: obj, [[NextMethod]]: undefined, [[Done]]: false }。
  4. 如果 IsCallable(procedure) 为 false,则
    1. errorThrowCompletion(一个新创建的 TypeError 对象)。
    2. 返回 ? IteratorClose(iterated, error)。
  5. iterated 设为 ? GetIteratorDirect(obj)。
  6. counter 为 0。
  7. 重复,
    1. value 为 ? IteratorStepValue(iterated)。
    2. 如果 valuedone,返回 undefined
    3. resultCompletion(Call(procedure, undefined, « value, 𝔽(counter) »))。
    4. IfAbruptCloseIterator(result, iterated)。
    5. counter 设为 counter + 1。

27.1.3.3.8 Iterator.prototype.map ( mapper )

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. 如果 obj 不是 Object,则抛出 TypeError 异常。
  3. iteratedIterator Record { [[Iterator]]: obj, [[NextMethod]]: undefined, [[Done]]: false }。
  4. 如果 IsCallable(mapper) 为 false,则
    1. errorThrowCompletion(一个新创建的 TypeError 对象)。
    2. 返回 ? IteratorClose(iterated, error)。
  5. iterated 设为 ? GetIteratorDirect(obj)。
  6. closure 为一个新的无参数抽象闭包,它捕获 iteratedmapper,并在被调用时执行以下步骤:
    1. counter 为 0。
    2. 重复,
      1. value 为 ? IteratorStepValue(iterated)。
      2. 如果 valuedone,返回 ReturnCompletion(undefined)。
      3. mappedCompletion(Call(mapper, undefined, « value, 𝔽(counter) »))。
      4. IfAbruptCloseIterator(mapped, iterated)。
      5. completionCompletion(Yield(mapped))。
      6. IfAbruptCloseIterator(completion, iterated)。
      7. counter 设为 counter + 1。
  7. resultCreateIteratorFromClosure(closure, "Iterator Helper", %IteratorHelperPrototype%, « [[UnderlyingIterators]] »)。
  8. result.[[UnderlyingIterators]] 设为 « iterated »。
  9. 返回 result

27.1.3.3.9 Iterator.prototype.reduce ( reducer [ , initialValue ] )

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. 如果 obj 不是 Object,则抛出 TypeError 异常。
  3. iteratedIterator Record { [[Iterator]]: obj, [[NextMethod]]: undefined, [[Done]]: false }。
  4. 如果 IsCallable(reducer) 为 false,则
    1. errorThrowCompletion(一个新创建的 TypeError 对象)。
    2. 返回 ? IteratorClose(iterated, error)。
  5. iterated 设为 ? GetIteratorDirect(obj)。
  6. 如果 initialValue 不存在,则
    1. accumulator 为 ? IteratorStepValue(iterated)。
    2. 如果 accumulatordone,抛出 TypeError 异常。
    3. counter 为 1。
  7. 否则,
    1. accumulatorinitialValue
    2. counter 为 0。
  8. 重复,
    1. value 为 ? IteratorStepValue(iterated)。
    2. 如果 valuedone,返回 accumulator
    3. resultCompletion(Call(reducer, undefined, « accumulator, value, 𝔽(counter) »))。
    4. IfAbruptCloseIterator(result, iterated)。
    5. accumulator 设为 result
    6. counter 设为 counter + 1。

27.1.3.3.10 Iterator.prototype.some ( predicate )

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. 如果 obj 不是 Object,则抛出 TypeError 异常。
  3. iteratedIterator Record { [[Iterator]]: obj, [[NextMethod]]: undefined, [[Done]]: false }。
  4. 如果 IsCallable(predicate) 为 false,则
    1. errorThrowCompletion(一个新创建的 TypeError 对象)。
    2. 返回 ? IteratorClose(iterated, error)。
  5. iterated 设为 ? GetIteratorDirect(obj)。
  6. counter 为 0。
  7. 重复,
    1. value 为 ? IteratorStepValue(iterated)。
    2. 如果 valuedone,返回 false
    3. resultCompletion(Call(predicate, undefined, « value, 𝔽(counter) »))。
    4. IfAbruptCloseIterator(result, iterated)。
    5. 如果 ToBoolean(result) 为 true,返回 ? IteratorClose(iterated, NormalCompletion(true))。
    6. counter 设为 counter + 1。

27.1.3.3.11 Iterator.prototype.take ( limit )

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. 如果 obj 不是 Object,则抛出 TypeError 异常。
  3. iteratedIterator Record { [[Iterator]]: obj, [[NextMethod]]: undefined, [[Done]]: false }。
  4. numLimitCompletion(ToNumber(limit))。
  5. IfAbruptCloseIterator(numLimit, iterated)。
  6. 如果 numLimitNaN,则
    1. errorThrowCompletion(一个新创建的 RangeError 对象)。
    2. 返回 ? IteratorClose(iterated, error)。
  7. integerLimit 为 ! ToIntegerOrInfinity(numLimit)。
  8. 如果 integerLimit < 0,则
    1. errorThrowCompletion(一个新创建的 RangeError 对象)。
    2. 返回 ? IteratorClose(iterated, error)。
  9. iterated 设为 ? GetIteratorDirect(obj)。
  10. closure 为一个新的无参数抽象闭包,它捕获 iteratedintegerLimit,并在被调用时执行以下步骤:
    1. remainingintegerLimit
    2. 重复,
      1. 如果 remaining = 0,则
        1. 返回 ? IteratorClose(iterated, ReturnCompletion(undefined))。
      2. 如果 remaining ≠ +∞,则
        1. remaining 设为 remaining - 1。
      3. value 为 ? IteratorStepValue(iterated)。
      4. 如果 valuedone,返回 ReturnCompletion(undefined)。
      5. completionCompletion(Yield(value))。
      6. IfAbruptCloseIterator(completion, iterated)。
  11. resultCreateIteratorFromClosure(closure, "Iterator Helper", %IteratorHelperPrototype%, « [[UnderlyingIterators]] »)。
  12. result.[[UnderlyingIterators]] 设为 « iterated »。
  13. 返回 result

27.1.3.3.12 Iterator.prototype.toArray ( )

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. 如果 obj 不是 Object,则抛出 TypeError 异常。
  3. iterated 为 ? GetIteratorDirect(obj)。
  4. items 为一个新的空 List
  5. 重复,
    1. value 为 ? IteratorStepValue(iterated)。
    2. 如果 valuedone,返回 CreateArrayFromList(items)。
    3. value 追加到 items

27.1.3.3.13 Iterator.prototype [ %Symbol.iterator% ] ( )

此函数在被调用时执行以下步骤:

  1. 返回 this 值。

此函数的 "name" 属性的值为 "[Symbol.iterator]"

27.1.3.3.14 Iterator.prototype [ %Symbol.toStringTag% ]

Iterator.prototype[%Symbol.toStringTag%] 是一个访问器属性,具有属性特性 { [[Enumerable]]: false, [[Configurable]]: true }。[[Get]][[Set]] 属性特性定义如下:

27.1.3.3.14.1 get Iterator.prototype [ %Symbol.toStringTag% ]

[[Get]] 属性特性的值是一个不需要实参的内置函数。它在被调用时执行以下步骤:

  1. 返回 "Iterator"

27.1.3.3.14.2 set Iterator.prototype [ %Symbol.toStringTag% ]

[[Set]] 属性特性的值是一个接受实参 v 的内置函数。它在被调用时执行以下步骤:

  1. 执行 ? SetterThatIgnoresPrototypeProperties(this value, %Iterator.prototype%, %Symbol.toStringTag%, v)。
  2. 返回 undefined
Note

与大多数内置原型上的 %Symbol.toStringTag% 属性不同,出于 Web 兼容性原因,此属性必须是访问器。

27.1.4 %AsyncIteratorPrototype% 对象

%AsyncIteratorPrototype% 对象:

Note

本规范中定义的所有实现异步迭代器接口的对象也都继承自 %AsyncIteratorPrototype%。ECMAScript 代码也可以定义继承自 %AsyncIteratorPrototype% 的对象。%AsyncIteratorPrototype% 对象提供了一个位置,可在其中添加适用于所有异步迭代器对象的其他方法。

27.1.4.1 %AsyncIteratorPrototype% [ %Symbol.asyncIterator% ] ( )

此函数在被调用时执行以下步骤:

  1. 返回 this 值。

此函数的 "name" 属性的值为 "[Symbol.asyncIterator]"

27.1.5 Async-from-Sync Iterator 对象

Async-from-Sync Iterator 对象是适配特定同步迭代器的异步迭代器。Async-from-Sync Iterator 对象永远不能被 ECMAScript 代码直接访问。Async-from-Sync Iterator 对象没有具名构造器。Async-from-Sync Iterator 对象是由 CreateAsyncFromSyncIterator 抽象操作在需要时创建的。

27.1.5.1 CreateAsyncFromSyncIterator ( syncIteratorRecord )

The abstract operation CreateAsyncFromSyncIterator takes argument syncIteratorRecord (一个 Iterator Record) and returns 一个 Iterator Record. 它用于从同步 Iterator Record 创建异步 Iterator Record。 It performs the following steps when called:

  1. asyncIteratorOrdinaryObjectCreate(%AsyncFromSyncIteratorPrototype%, « [[SyncIteratorRecord]] »)。
  2. asyncIterator.[[SyncIteratorRecord]] 设为 syncIteratorRecord
  3. nextMethod 为 ! Get(asyncIterator, "next")。
  4. iteratorRecordIterator Record { [[Iterator]]: asyncIterator, [[NextMethod]]: nextMethod, [[Done]]: false }。
  5. 返回 iteratorRecord

27.1.5.2 %AsyncFromSyncIteratorPrototype% 对象

%AsyncFromSyncIteratorPrototype% 对象:

27.1.5.2.1 %AsyncFromSyncIteratorPrototype%.next ( [ value ] )

  1. objthis 值。
  2. 断言:obj 是具有 [[SyncIteratorRecord]] 内部槽的 Object。
  3. promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  4. syncIteratorRecordobj.[[SyncIteratorRecord]]
  5. 如果 value 存在,则
    1. resultCompletion(IteratorNext(syncIteratorRecord, value))。
  6. 否则,
    1. resultCompletion(IteratorNext(syncIteratorRecord))。
  7. IfAbruptRejectPromise(result, promiseCapability)。
  8. 返回 AsyncFromSyncIteratorContinuation(result, promiseCapability, syncIteratorRecord, true)。

27.1.5.2.2 %AsyncFromSyncIteratorPrototype%.return ( [ value ] )

  1. objthis 值。
  2. 断言:obj 是具有 [[SyncIteratorRecord]] 内部槽的 Object。
  3. promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  4. syncIteratorRecordobj.[[SyncIteratorRecord]]
  5. syncIteratorsyncIteratorRecord.[[Iterator]]
  6. returnCompletion(GetMethod(syncIterator, "return"))。
  7. IfAbruptRejectPromise(return, promiseCapability)。
  8. 如果 returnundefined,则
    1. iteratorResultCreateIteratorResultObject(value, true)。
    2. 执行 ! Call(promiseCapability.[[Resolve]], undefined, « iteratorResult »)。
    3. 返回 promiseCapability.[[Promise]]
  9. 如果 value 存在,则
    1. resultCompletion(Call(return, syncIterator, « value »))。
  10. 否则,
    1. resultCompletion(Call(return, syncIterator))。
  11. IfAbruptRejectPromise(result, promiseCapability)。
  12. 如果 result 不是 Object,则
    1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « 一个新创建的 TypeError 对象 »)。
    2. 返回 promiseCapability.[[Promise]]
  13. 返回 AsyncFromSyncIteratorContinuation(result, promiseCapability, syncIteratorRecord, false)。

27.1.5.2.3 %AsyncFromSyncIteratorPrototype%.throw ( [ value ] )

Note
在本规范中,value 始终会被提供,但为与 %AsyncFromSyncIteratorPrototype%.return ( [ value ] ) 保持一致而保留为可选。
  1. objthis 值。
  2. 断言:obj 是具有 [[SyncIteratorRecord]] 内部槽的 Object。
  3. promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  4. syncIteratorRecordobj.[[SyncIteratorRecord]]
  5. syncIteratorsyncIteratorRecord.[[Iterator]]
  6. throwCompletion(GetMethod(syncIterator, "throw"))。
  7. IfAbruptRejectPromise(throw, promiseCapability)。
  8. 如果 throwundefined,则
    1. 注:如果 syncIterator 没有 throw 方法,则关闭它,让它有机会在我们拒绝 capability 之前进行清理。
    2. closeCompletionNormalCompletion(empty)。
    3. resultCompletion(IteratorClose(syncIteratorRecord, closeCompletion))。
    4. IfAbruptRejectPromise(result, promiseCapability)。
    5. 注:下一步抛出 TypeError,用于表示发生了协议违例:syncIterator 没有 throw 方法。
    6. 注:如果关闭 syncIterator 没有抛出,则该操作的结果会被忽略,即使它产出一个被拒绝的 promise。
    7. 执行 ! Call(promiseCapability.[[Reject]], undefined, « 一个新创建的 TypeError 对象 »)。
    8. 返回 promiseCapability.[[Promise]]
  9. 如果 value 存在,则
    1. resultCompletion(Call(throw, syncIterator, « value »))。
  10. 否则,
    1. resultCompletion(Call(throw, syncIterator))。
  11. IfAbruptRejectPromise(result, promiseCapability)。
  12. 如果 result 不是 Object,则
    1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « 一个新创建的 TypeError 对象 »)。
    2. 返回 promiseCapability.[[Promise]]
  13. 返回 AsyncFromSyncIteratorContinuation(result, promiseCapability, syncIteratorRecord, true)。

27.1.5.3 Async-from-Sync Iterator 实例的属性

Async-from-Sync Iterator 实例是普通对象,继承来自 %AsyncFromSyncIteratorPrototype% 内在对象的属性。Async-from-Sync Iterator 实例最初会以 Table 85 中列出的内部槽创建。

Table 85: Async-from-Sync Iterator 实例的内部槽
内部槽 类型 描述
[[SyncIteratorRecord]] 一个 Iterator Record 表示正在被适配的原始同步迭代器。

27.1.5.4 AsyncFromSyncIteratorContinuation ( result, promiseCapability, syncIteratorRecord, closeOnRejection )

The abstract operation AsyncFromSyncIteratorContinuation takes arguments result (一个 Object), promiseCapability (内在 %Promise%PromiseCapability Record), syncIteratorRecord (一个 Iterator Record), and closeOnRejection (一个 Boolean) and returns 一个 Promise. It performs the following steps when called:

  1. 注:由于 promiseCapability 派生自内在 %Promise%,因此下面使用 IfAbruptRejectPromise 所导致的对 promiseCapability.[[Reject]] 的调用保证不会抛出。
  2. doneCompletion(IteratorComplete(result))。
  3. IfAbruptRejectPromise(done, promiseCapability)。
  4. valueCompletion(IteratorValue(result))。
  5. IfAbruptRejectPromise(value, promiseCapability)。
  6. valueWrapperCompletion(PromiseResolve(%Promise%, value))。
  7. 如果 valueWrapper 是 abrupt completion,donefalse,且 closeOnRejectiontrue,则
    1. valueWrapper 设为 Completion(IteratorClose(syncIteratorRecord, valueWrapper))。
  8. IfAbruptRejectPromise(valueWrapper, promiseCapability)。
  9. unwrap 为一个新的抽象闭包,带有参数 (v),它捕获 done,并在被调用时执行以下步骤:
    1. 返回 CreateIteratorResultObject(v, done)。
  10. onFulfilledCreateBuiltinFunction(unwrap, 1, "", « »)。
  11. 注:onFulfilled 用于处理 IteratorResult 对象的 "value" 属性,以等待其值(如果它是 promise),并将结果重新封装到一个新的“已解包” IteratorResult 对象中。
  12. 如果 donetruecloseOnRejectionfalse,则
    1. onRejectedundefined
  13. 否则,
    1. closeIterator 为一个新的抽象闭包,带有参数 (error),它捕获 syncIteratorRecord,并在被调用时执行以下步骤:
      1. 返回 ? IteratorClose(syncIteratorRecord, ThrowCompletion(error))。
    2. onRejectedCreateBuiltinFunction(closeIterator, 1, "", « »)。
    3. 注:当 IteratorResult 对象所产出的 "value" 属性是一个被拒绝的 promise 时,onRejected 用于关闭 Iterator
  14. 执行 PerformPromiseThen(valueWrapper, onFulfilled, onRejected, promiseCapability)。
  15. 返回 promiseCapability.[[Promise]]

27.2 Promise 对象

Promise 是一种对象,用作延迟的(并且可能是异步的)计算的最终结果的占位符。

任何 Promise 都处于三种互斥状态之一:fulfilledrejectedpending

  • 如果 p.then(f, r) 会立即将一个调用函数 fJob 入队,则 promise p 为 fulfilled。
  • 如果 p.then(f, r) 会立即将一个调用函数 rJob 入队,则 promise p 为 rejected。
  • 如果一个 promise 既不是 fulfilled 也不是 rejected,则它为 pending。

如果一个 promise 不是 pending,也就是说如果它是 fulfilled 或 rejected,则称该 promise 为 settled

如果一个 promise 已 settled,或者已被“锁定”以匹配另一个 promise 的状态,则该 promise 为 resolved。尝试 resolve 或 reject 一个已 resolved 的 promise 不会产生任何效果。如果一个 promise 不是 resolved,则它为 unresolved。一个 unresolved 的 promise 总是处于 pending 状态。一个 resolved 的 promise 可以是 pending、fulfilled 或 rejected。

27.2.1 Promise 抽象操作

27.2.1.1 PromiseCapability Record

PromiseCapability Record 是一种 Record 值,用于封装一个 Promise 或类 promise 对象,以及能够 resolve 或 reject 该 promise 的函数。PromiseCapability Record 由 NewPromiseCapability 抽象操作产生。

PromiseCapability Record 具有 Table 86 中列出的字段。

Table 86: PromiseCapability Record 字段
字段名 含义
[[Promise]] 一个 Object 一个可用作 promise 的对象。
[[Resolve]] 一个函数对象 用于 resolve 给定 promise 的函数。
[[Reject]] 一个函数对象 用于 reject 给定 promise 的函数。

27.2.1.1.1 IfAbruptRejectPromise ( value, capability )

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

  1. IfAbruptRejectPromise(value, capability).

含义与以下内容相同:

  1. 断言:valueCompletion Record
  2. 如果 value 是 abrupt completion,则
    1. 执行 ? Call(capability.[[Reject]], undefined, « value.[[Value]] »)。
    2. 返回 capability.[[Promise]]
  3. value 设为 ! value

27.2.1.2 PromiseReaction Record

PromiseReaction Record 是一种 Record 值,用于存储关于 promise 在以给定值变为 resolved 或 rejected 时应如何反应的信息。PromiseReaction Record 由 PerformPromiseThen 抽象操作创建,并由 NewPromiseReactionJob 返回的 Abstract Closure 使用。

PromiseReaction Record 具有 Table 87 中列出的字段。

Table 87: PromiseReaction Record 字段
字段名 含义
[[Capability]] 一个 PromiseCapability Recordundefined 此记录为其提供 reaction 处理器的 promise 的 capability。
[[Type]] fulfillreject [[Handler]]empty 时,[[Type]] 用于允许特定于 settled 类型的行为。
[[Handler]] 一个 JobCallback Recordempty 应应用于传入值的函数,其返回值将决定派生 promise 会发生什么。如果 [[Handler]]empty,则改用一个取决于 [[Type]] 值的函数。

27.2.1.3 CreateResolvingFunctions ( toResolve )

The abstract operation CreateResolvingFunctions takes argument toResolve (一个 Promise) and returns 一个具有字段 [[Resolve]](一个函数对象)和 [[Reject]](一个函数对象)的 Record. It performs the following steps when called:

  1. promiseOrEmptyRecord { [[Value]]: toResolve }。
  2. resolveSteps 为一个新的 Abstract Closure,带有参数 (resolution),它捕获 promiseOrEmpty,并在被调用时执行以下步骤:
    1. 如果 promiseOrEmpty.[[Value]]empty,返回 undefined
    2. promisepromiseOrEmpty.[[Value]]
    3. promiseOrEmpty.[[Value]] 设为 empty
    4. 如果 SameValue(resolution, promise) 为 true,则
      1. selfResolutionError 为一个新创建的 TypeError 对象。
      2. 执行 RejectPromise(promise, selfResolutionError)。
      3. 返回 undefined
    5. 如果 resolution 不是 Object,则
      1. 执行 FulfillPromise(promise, resolution)。
      2. 返回 undefined
    6. thenCompletion(Get(resolution, "then"))。
    7. 如果 then 是 abrupt completion,则
      1. 执行 RejectPromise(promise, then.[[Value]])。
      2. 返回 undefined
    8. thenActionthen.[[Value]]
    9. 如果 IsCallable(thenAction) 为 false,则
      1. 执行 FulfillPromise(promise, resolution)。
      2. 返回 undefined
    10. thenJobCallbackHostMakeJobCallback(thenAction)。
    11. jobNewPromiseResolveThenableJob(promise, resolution, thenJobCallback)。
    12. 执行 HostEnqueuePromiseJob(job.[[Job]], job.[[Realm]])。
    13. 返回 undefined
  3. resolveCreateBuiltinFunction(resolveSteps, 1, "", « »)。
  4. rejectSteps 为一个新的 Abstract Closure,带有参数 (reason),它捕获 promiseOrEmpty,并在被调用时执行以下步骤:
    1. 如果 promiseOrEmpty.[[Value]]empty,返回 undefined
    2. promisepromiseOrEmpty.[[Value]]
    3. promiseOrEmpty.[[Value]] 设为 empty
    4. 执行 RejectPromise(promise, reason)。
    5. 返回 undefined
  5. rejectCreateBuiltinFunction(rejectSteps, 1, "", « »)。
  6. 返回 Record { [[Resolve]]: resolve, [[Reject]]: reject }。

27.2.1.4 FulfillPromise ( promise, value )

The abstract operation FulfillPromise takes arguments promise (一个 Promise) and value (一个 ECMAScript 语言值) and returns unused. It performs the following steps when called:

  1. 断言:promise.[[PromiseState]]pending
  2. reactionspromise.[[PromiseFulfillReactions]]
  3. promise.[[PromiseResult]] 设为 value
  4. promise.[[PromiseFulfillReactions]] 设为 undefined
  5. promise.[[PromiseRejectReactions]] 设为 undefined
  6. promise.[[PromiseState]] 设为 fulfilled
  7. 执行 TriggerPromiseReactions(reactions, value)。
  8. 返回 unused

27.2.1.5 NewPromiseCapability ( constructor )

The abstract operation NewPromiseCapability takes argument constructor (一个 ECMAScript 语言值) and returns 一个包含 PromiseCapability Record 的 normal completion 或一个 throw completion. 它尝试以类似内置 Promise 构造器的方式,将 constructor 用作构造器来创建 promise,并提取其 resolvereject 函数。该 promise 以及 resolvereject 函数用于初始化新的 PromiseCapability Record。 It performs the following steps when called:

  1. 如果 IsConstructor(constructor) 为 false,抛出 TypeError 异常。
  2. 注:假定 constructor 是一个支持 Promise 构造器参数约定的构造器函数(见 27.2.3.1)。
  3. resolvingFunctionsRecord { [[Resolve]]: undefined, [[Reject]]: undefined }。
  4. executorClosure 为一个新的 Abstract Closure,带有参数 (resolve, reject),它捕获 resolvingFunctions,并在被调用时执行以下步骤:
    1. 如果 resolvingFunctions.[[Resolve]] 不是 undefined,抛出 TypeError 异常。
    2. 如果 resolvingFunctions.[[Reject]] 不是 undefined,抛出 TypeError 异常。
    3. resolvingFunctions.[[Resolve]] 设为 resolve
    4. resolvingFunctions.[[Reject]] 设为 reject
    5. 返回 NormalCompletion(undefined)。
  5. executorCreateBuiltinFunction(executorClosure, 2, "", « »)。
  6. promise 为 ? Construct(constructor, « executor »)。
  7. 如果 IsCallable(resolvingFunctions.[[Resolve]]) 为 false,抛出 TypeError 异常。
  8. 如果 IsCallable(resolvingFunctions.[[Reject]]) 为 false,抛出 TypeError 异常。
  9. 返回 PromiseCapability Record { [[Promise]]: promise, [[Resolve]]: resolvingFunctions.[[Resolve]], [[Reject]]: resolvingFunctions.[[Reject]] }。
Note

抽象操作支持 Promise 子类化,因为它对任何构造器都是泛型的,只要该构造器以与 Promise 构造器相同的方式调用传入的 executor 函数实参。它用于将 Promise 构造器的静态方法泛化到任何子类。

27.2.1.6 IsPromise ( value )

The abstract operation IsPromise takes argument value (一个 ECMAScript 语言值) and returns 一个 Boolean. 它检查对象上的 promise 品牌。 It performs the following steps when called:

  1. 如果 value 不是 Object,返回 false
  2. 如果 value 没有 [[PromiseState]] 内部槽,返回 false
  3. 返回 true

27.2.1.7 RejectPromise ( promise, reason )

The abstract operation RejectPromise takes arguments promise (一个 Promise) and reason (一个 ECMAScript 语言值) and returns unused. It performs the following steps when called:

  1. 断言:promise.[[PromiseState]]pending
  2. reactionspromise.[[PromiseRejectReactions]]
  3. promise.[[PromiseResult]] 设为 reason
  4. promise.[[PromiseFulfillReactions]] 设为 undefined
  5. promise.[[PromiseRejectReactions]] 设为 undefined
  6. promise.[[PromiseState]] 设为 rejected
  7. 如果 promise.[[PromiseIsHandled]]false,执行 HostPromiseRejectionTracker(promise, "reject")。
  8. 执行 TriggerPromiseReactions(reactions, reason)。
  9. 返回 unused

27.2.1.8 TriggerPromiseReactions ( reactions, argument )

The abstract operation TriggerPromiseReactions takes arguments reactions (PromiseReaction RecordList) and argument (一个 ECMAScript 语言值) and returns unused. 它为 reactions 中的每个记录入队一个新的 Job。每个这样的 Job 会处理 PromiseReaction Record[[Type]][[Handler]],并且如果 [[Handler]] 不是 empty,就调用它并传入给定实参。如果 [[Handler]]empty,则行为由 [[Type]] 决定。 It performs the following steps when called:

  1. 对于 reactions 的每个元素 reaction,执行
    1. jobNewPromiseReactionJob(reaction, argument)。
    2. 执行 HostEnqueuePromiseJob(job.[[Job]], job.[[Realm]])。
  2. 返回 unused

27.2.1.9 HostPromiseRejectionTracker ( promise, operation )

The host-defined abstract operation HostPromiseRejectionTracker takes arguments promise (一个 Promise) and operation ("reject""handle") and returns unused. 它允许宿主环境跟踪 promise rejection。

HostPromiseRejectionTracker 的默认实现是返回 unused

Note 1

HostPromiseRejectionTracker 在两种场景中被调用:

  • 当 promise 在没有任何处理器的情况下被 rejected 时,会以其 operation 实参设为 "reject" 调用它。
  • 当首次向 rejected 的 promise 添加处理器时,会以其 operation 实参设为 "handle" 调用它。

HostPromiseRejectionTracker 的典型实现可能会尝试通知开发者未处理的 rejection,同时也会注意在这种先前通知后来因附加了新处理器而失效时通知他们。

Note 2

如果 operation"handle",实现不应以会干扰垃圾回收的方式持有对 promise 的引用。如果 operation"reject",实现可以持有对 promise 的引用,因为预期 rejection 会很少见且不在热代码路径上。

27.2.2 Promise Job

27.2.2.1 NewPromiseReactionJob ( reaction, argument )

The abstract operation NewPromiseReactionJob takes arguments reaction (一个 PromiseReaction Record) and argument (一个 ECMAScript 语言值) and returns 一个具有字段 [[Job]](一个 Job Abstract Closure)和 [[Realm]](一个 Realm Recordnull)的 Record. 它返回一个新的 Job Abstract Closure,该闭包会将适当的处理器应用于传入值,并使用该处理器的返回值来 resolve 或 reject 与该处理器关联的派生 promise。 It performs the following steps when called:

  1. job 为一个新的无参数 Job Abstract Closure,它捕获 reactionargument,并在被调用时执行以下步骤:
    1. promiseCapabilityreaction.[[Capability]]
    2. typereaction.[[Type]]
    3. handlerreaction.[[Handler]]
    4. 如果 handlerempty,则
      1. 如果 typefulfill,则
        1. handlerResultNormalCompletion(argument)。
      2. 否则,
        1. 断言:typereject
        2. handlerResultThrowCompletion(argument)。
    5. 否则,
      1. handlerResultCompletion(HostCallJobCallback(handler, undefined, « argument »))。
    6. 如果 promiseCapabilityundefined,则
      1. 断言:handlerResult 不是 abrupt completion。
      2. 返回 empty
    7. 断言:promiseCapabilityPromiseCapability Record
    8. 如果 handlerResult 是 abrupt completion,则
      1. 返回 ? Call(promiseCapability.[[Reject]], undefined, « handlerResult.[[Value]] »)。
    9. 返回 ? Call(promiseCapability.[[Resolve]], undefined, « handlerResult.[[Value]] »)。
  2. handlerRealmnull
  3. 如果 reaction.[[Handler]] 不是 empty,则
    1. getHandlerRealmResultCompletion(GetFunctionRealm(reaction.[[Handler]].[[Callback]]))。
    2. 如果 getHandlerRealmResult 是 normal completion,将 handlerRealm 设为 getHandlerRealmResult.[[Value]]
    3. 否则,将 handlerRealm 设为当前 Realm Record
    4. 注:除非处理器是 undefined,否则 handlerRealm 永远不是 null。当处理器是已撤销的 Proxy 且没有 ECMAScript 代码运行时,handlerRealm 用于创建错误对象。
  4. 返回 Record { [[Job]]: job, [[Realm]]: handlerRealm }。

27.2.2.2 NewPromiseResolveThenableJob ( promiseToResolve, thenable, then )

The abstract operation NewPromiseResolveThenableJob takes arguments promiseToResolve (一个 Promise), thenable (一个 Object), and then (一个 JobCallback Record) and returns 一个具有字段 [[Job]](一个 Job Abstract Closure)和 [[Realm]](一个 Realm Record)的 Record. It performs the following steps when called:

  1. job 为一个新的无参数 Job Abstract Closure,它捕获 promiseToResolvethenablethen,并在被调用时执行以下步骤:
    1. resolvingFunctionsCreateResolvingFunctions(promiseToResolve)。
    2. thenCallResultCompletion(HostCallJobCallback(then, thenable, « resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]] »))。
    3. 如果 thenCallResult 是 abrupt completion,则
      1. 返回 ? Call(resolvingFunctions.[[Reject]], undefined, « thenCallResult.[[Value]] »)。
    4. 返回 ! thenCallResult
  2. getThenRealmResultCompletion(GetFunctionRealm(then.[[Callback]]))。
  3. 如果 getThenRealmResult 是 normal completion,令 thenRealmgetThenRealmResult.[[Value]]
  4. 否则,令 thenRealm当前 Realm Record
  5. 注:thenRealm 永远不是 null。当 then.[[Callback]] 是已撤销的 Proxy 且没有代码运行时,thenRealm 用于创建错误对象。
  6. 返回 Record { [[Job]]: job, [[Realm]]: thenRealm }。
Note

Job 使用提供的 thenable 及其 then 方法来 resolve 给定 promise。此过程必须作为 Job 进行,以确保 then 方法的求值发生在任何外围代码完成求值之后。

27.2.3 Promise 构造器

Promise 构造器

  • %Promise%
  • 全局对象"Promise" 属性的初始值。
  • 作为构造器调用时,创建并初始化一个新的 Promise。
  • 并非旨在作为函数调用,并且以这种方式调用时会抛出异常。
  • 可以用作类定义的 extends 子句中的值。意图继承指定 Promise 行为的子类构造器必须包含对 Promise 构造器super 调用,以使用支持 PromisePromise.prototype 内置方法所需的内部状态来创建并初始化子类实例。

27.2.3.1 Promise ( executor )

此函数在被调用时执行以下步骤:

  1. 如果 NewTarget 是 undefined,抛出 TypeError 异常。
  2. 如果 IsCallable(executor) 为 false,抛出 TypeError 异常。
  3. promise 为 ? OrdinaryCreateFromConstructor(NewTarget, "%Promise.prototype%", « [[PromiseState]], [[PromiseResult]], [[PromiseFulfillReactions]], [[PromiseRejectReactions]], [[PromiseIsHandled]] »)。
  4. promise.[[PromiseState]] 设为 pending
  5. promise.[[PromiseResult]] 设为 empty
  6. promise.[[PromiseFulfillReactions]] 设为一个新的空 List
  7. promise.[[PromiseRejectReactions]] 设为一个新的空 List
  8. promise.[[PromiseIsHandled]] 设为 false
  9. resolvingFunctionsCreateResolvingFunctions(promise)。
  10. completionCompletion(Call(executor, undefined, « resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]] »))。
  11. 如果 completion 是 abrupt completion,则
    1. 执行 ? Call(resolvingFunctions.[[Reject]], undefined, « completion.[[Value]] »)。
  12. 返回 promise
Note

executor 实参必须是函数对象。调用它是为了启动并报告此 Promise 所表示的可能延迟的动作的完成情况。executor 会以两个实参调用:resolvereject。这些函数可由 executor 函数用于报告延迟计算的最终完成或失败。从 executor 函数返回并不意味着延迟动作已经完成,而只意味着最终执行该延迟动作的请求已被接受。

传递给 executor 函数的 resolve 函数接受一个实参。executor 代码最终可以调用 resolve 函数,以指示它希望 resolve 关联的 Promise。传递给 resolve 函数的实参表示延迟动作的最终值,可以是实际的 fulfillment 值,也可以是另一个 promise;如果该 promise 被 fulfilled,它将提供该值。

传递给 executor 函数的 reject 函数接受一个实参。executor 代码最终可以调用 reject 函数,以指示关联的 Promise 被 rejected 且永远不会 fulfilled。传递给 reject 函数的实参用作该 promise 的 rejection 值。通常它会是一个 Error 对象。

Promise 构造器传递给 executor 函数的 resolve 和 reject 函数具有实际 resolve 和 reject 关联 promise 的 capability。子类可以具有不同的构造器行为,传入自定义的 resolve 和 reject 值。

27.2.4 Promise 构造器的属性

Promise 构造器

27.2.4.1 Promise.all ( iterable )

此函数返回一个新的 promise,该 promise 以传入的各 promise 的 fulfillment 值数组 fulfilled,或者以第一个被 rejected 的传入 promise 的 reason rejected。它在运行此算法时将传入 iterable 的所有元素 resolve 为 promise。

  1. constructorthis 值。
  2. promiseCapability 为 ? NewPromiseCapability(constructor)。
  3. promiseResolveCompletion(GetPromiseResolve(constructor))。
  4. IfAbruptRejectPromise(promiseResolve, promiseCapability)。
  5. iteratorRecordCompletion(GetIterator(iterable, sync))。
  6. IfAbruptRejectPromise(iteratorRecord, promiseCapability)。
  7. resultCompletion(PerformPromiseAll(iteratorRecord, constructor, promiseCapability, promiseResolve))。
  8. 如果 result 是 abrupt completion,则
    1. 如果 iteratorRecord.[[Done]]false,将 result 设为 Completion(IteratorClose(iteratorRecord, result))。
    2. IfAbruptRejectPromise(result, promiseCapability)。
  9. 返回 ! result
Note

此函数要求其 this 值为支持 Promise 构造器参数约定的构造器函数。

27.2.4.1.1 GetPromiseResolve ( promiseConstructor )

The abstract operation GetPromiseResolve takes argument promiseConstructor (一个构造器) and returns 一个包含函数对象的 normal completion 或一个 throw completion. It performs the following steps when called:

  1. promiseResolve 为 ? Get(promiseConstructor, "resolve")。
  2. 如果 IsCallable(promiseResolve) 为 false,抛出 TypeError 异常。
  3. 返回 promiseResolve

27.2.4.1.2 PerformPromiseAll ( iteratorRecord, constructor, resultCapability, promiseResolve )

The abstract operation PerformPromiseAll takes arguments iteratorRecord (an Iterator Record), constructor (a constructor), resultCapability (a PromiseCapability Record), and promiseResolve (a function object) and returns either a normal completion containing an Object or a throw completion. It performs the following steps when called:

  1. values 为一个新的空 List
  2. 注:remainingElementsCount 从 1 而不是 0 开始,以确保 resultCapability.[[Resolve]] 只被调用一次,即使存在行为不当的 "then",它在输入迭代器耗尽之前调用传入的回调。
  3. remainingElementsCountRecord { [[Value]]: 1 }。
  4. index 为 0。
  5. 重复,
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 nextdone,则
      1. remainingElementsCount.[[Value]] 设为 remainingElementsCount.[[Value]] - 1。
      2. 如果 remainingElementsCount.[[Value]] = 0,则
        1. valuesArrayCreateArrayFromList(values)。
        2. 执行 ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »)。
      3. 返回 resultCapability.[[Promise]]
    3. undefined 追加到 values
    4. nextPromise 为 ? Call(promiseResolve, constructor, « next »)。
    5. fulfilledSteps 为一个新的 Abstract Closure,带有参数 (value),它捕获 valuesresultCapabilityremainingElementsCount,并在被调用时执行以下步骤:
      1. activeFunc活动函数对象
      2. 如果 activeFunc.[[AlreadyCalled]]true,返回 undefined
      3. activeFunc.[[AlreadyCalled]] 设为 true
      4. thisIndexactiveFunc.[[Index]]
      5. values[thisIndex] 设为 value
      6. remainingElementsCount.[[Value]] 设为 remainingElementsCount.[[Value]] - 1。
      7. 如果 remainingElementsCount.[[Value]] = 0,则
        1. valuesArrayCreateArrayFromList(values)。
        2. 返回 ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »)。
      8. 返回 undefined
    6. onFulfilledCreateBuiltinFunction(fulfilledSteps, 1, "", « [[AlreadyCalled]], [[Index]] »)。
    7. onFulfilled.[[AlreadyCalled]] 设为 false
    8. onFulfilled.[[Index]] 设为 index
    9. index 设为 index + 1。
    10. remainingElementsCount.[[Value]] 设为 remainingElementsCount.[[Value]] + 1。
    11. 执行 ? Invoke(nextPromise, "then", « onFulfilled, resultCapability.[[Reject]] »)。

27.2.4.2 Promise.allSettled ( iterable )

此函数返回一个 promise,该 promise 以 promise 状态快照数组 fulfilled,但仅在所有原始 promise 都 settled,即变为 fulfilled 或 rejected 之后才会如此。它在运行此算法时将传入 iterable 的所有元素 resolve 为 promise。

  1. constructorthis 值。
  2. promiseCapability 为 ? NewPromiseCapability(constructor)。
  3. promiseResolveCompletion(GetPromiseResolve(constructor))。
  4. IfAbruptRejectPromise(promiseResolve, promiseCapability)。
  5. iteratorRecordCompletion(GetIterator(iterable, sync))。
  6. IfAbruptRejectPromise(iteratorRecord, promiseCapability)。
  7. resultCompletion(PerformPromiseAllSettled(iteratorRecord, constructor, promiseCapability, promiseResolve))。
  8. 如果 result 是 abrupt completion,则
    1. 如果 iteratorRecord.[[Done]]false,将 result 设为 Completion(IteratorClose(iteratorRecord, result))。
    2. IfAbruptRejectPromise(result, promiseCapability)。
  9. 返回 ! result
Note

此函数要求其 this 值为支持 Promise 构造器参数约定的构造器函数。

27.2.4.2.1 PerformPromiseAllSettled ( iteratorRecord, constructor, resultCapability, promiseResolve )

The abstract operation PerformPromiseAllSettled takes arguments iteratorRecord (an Iterator Record), constructor (a constructor), resultCapability (a PromiseCapability Record), and promiseResolve (a function object) and returns either a normal completion containing an Object or a throw completion. It performs the following steps when called:

  1. values 为一个新的空 List
  2. 注:remainingElementsCount 从 1 而不是 0 开始,以确保 resultCapability.[[Resolve]] 只被调用一次,即使存在行为不当的 "then",它在输入迭代器耗尽之前调用传入的回调之一。
  3. remainingElementsCountRecord { [[Value]]: 1 }。
  4. index 为 0。
  5. 重复,
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 nextdone,则
      1. remainingElementsCount.[[Value]] 设为 remainingElementsCount.[[Value]] - 1。
      2. 如果 remainingElementsCount.[[Value]] = 0,则
        1. valuesArrayCreateArrayFromList(values)。
        2. 执行 ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »)。
      3. 返回 resultCapability.[[Promise]]
    3. undefined 追加到 values
    4. nextPromise 为 ? Call(promiseResolve, constructor, « next »)。
    5. alreadyCalledRecord { [[Value]]: false }。
    6. fulfilledSteps 为一个新的 Abstract Closure,带有参数 (value),它捕获 valuesresultCapabilityremainingElementsCount,并在被调用时执行以下步骤:
      1. activeFunc活动函数对象
      2. 如果 activeFunc.[[AlreadyCalled]].[[Value]]true,返回 undefined
      3. activeFunc.[[AlreadyCalled]].[[Value]] 设为 true
      4. objOrdinaryObjectCreate(%Object.prototype%)。
      5. 执行 ! CreateDataPropertyOrThrow(obj, "status", "fulfilled")。
      6. 执行 ! CreateDataPropertyOrThrow(obj, "value", value)。
      7. thisIndexactiveFunc.[[Index]]
      8. values[thisIndex] 设为 obj
      9. remainingElementsCount.[[Value]] 设为 remainingElementsCount.[[Value]] - 1。
      10. 如果 remainingElementsCount.[[Value]] = 0,则
        1. valuesArrayCreateArrayFromList(values)。
        2. 返回 ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »)。
      11. 返回 undefined
    7. onFulfilledCreateBuiltinFunction(fulfilledSteps, 1, "", « [[AlreadyCalled]], [[Index]] »)。
    8. onFulfilled.[[AlreadyCalled]] 设为 alreadyCalled
    9. onFulfilled.[[Index]] 设为 index
    10. rejectedSteps 为一个新的 Abstract Closure,带有参数 (error),它捕获 valuesresultCapabilityremainingElementsCount,并在被调用时执行以下步骤:
      1. activeFunc活动函数对象
      2. 如果 activeFunc.[[AlreadyCalled]].[[Value]]true,返回 undefined
      3. activeFunc.[[AlreadyCalled]].[[Value]] 设为 true
      4. objOrdinaryObjectCreate(%Object.prototype%)。
      5. 执行 ! CreateDataPropertyOrThrow(obj, "status", "rejected")。
      6. 执行 ! CreateDataPropertyOrThrow(obj, "reason", error)。
      7. thisIndexactiveFunc.[[Index]]
      8. values[thisIndex] 设为 obj
      9. remainingElementsCount.[[Value]] 设为 remainingElementsCount.[[Value]] - 1。
      10. 如果 remainingElementsCount.[[Value]] = 0,则
        1. valuesArrayCreateArrayFromList(values)。
        2. 返回 ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »)。
      11. 返回 undefined
    11. onRejectedCreateBuiltinFunction(rejectedSteps, 1, "", « [[AlreadyCalled]], [[Index]] »)。
    12. onRejected.[[AlreadyCalled]] 设为 alreadyCalled
    13. onRejected.[[Index]] 设为 index
    14. index 设为 index + 1。
    15. remainingElementsCount.[[Value]] 设为 remainingElementsCount.[[Value]] + 1。
    16. 执行 ? Invoke(nextPromise, "then", « onFulfilled, onRejected »)。

27.2.4.3 Promise.any ( iterable )

此函数返回一个 promise,该 promise 由第一个 fulfilled 的给定 promise 使其 fulfilled,或者如果所有给定 promise 都被 rejected,则以持有各 rejection reason 的 AggregateError rejected。它在运行此算法时将传入 iterable 的所有元素 resolve 为 promise。

  1. constructorthis 值。
  2. promiseCapability 为 ? NewPromiseCapability(constructor)。
  3. promiseResolveCompletion(GetPromiseResolve(constructor))。
  4. IfAbruptRejectPromise(promiseResolve, promiseCapability)。
  5. iteratorRecordCompletion(GetIterator(iterable, sync))。
  6. IfAbruptRejectPromise(iteratorRecord, promiseCapability)。
  7. resultCompletion(PerformPromiseAny(iteratorRecord, constructor, promiseCapability, promiseResolve))。
  8. 如果 result 是 abrupt completion,则
    1. 如果 iteratorRecord.[[Done]]false,将 result 设为 Completion(IteratorClose(iteratorRecord, result))。
    2. IfAbruptRejectPromise(result, promiseCapability)。
  9. 返回 ! result
Note

此函数要求其 this 值为支持 Promise 构造器参数约定的构造器函数。

27.2.4.3.1 PerformPromiseAny ( iteratorRecord, constructor, resultCapability, promiseResolve )

The abstract operation PerformPromiseAny takes arguments iteratorRecord (an Iterator Record), constructor (a constructor), resultCapability (a PromiseCapability Record), and promiseResolve (a function object) and returns either a normal completion containing an Object or a throw completion. It performs the following steps when called:

  1. errors 为一个新的空 List
  2. 注:remainingElementsCount 从 1 而不是 0 开始,以确保 resultCapability.[[Reject]] 只被调用一次,即使存在行为不当的 "then",它在输入迭代器耗尽之前调用传入的回调。
  3. remainingElementsCountRecord { [[Value]]: 1 }。
  4. index 为 0。
  5. 重复,
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 nextdone,则
      1. remainingElementsCount.[[Value]] 设为 remainingElementsCount.[[Value]] - 1。
      2. 如果 remainingElementsCount.[[Value]] = 0,则
        1. aggregateError 为一个新创建的 AggregateError 对象。
        2. 执行 ! DefinePropertyOrThrow(aggregateError, "errors", PropertyDescriptor { [[Configurable]]: true, [[Enumerable]]: false, [[Writable]]: true, [[Value]]: CreateArrayFromList(errors) })。
        3. 执行 ? Call(resultCapability.[[Reject]], undefined, « aggregateError »)。
      3. 返回 resultCapability.[[Promise]]
    3. undefined 追加到 errors
    4. nextPromise 为 ? Call(promiseResolve, constructor, « next »)。
    5. rejectedSteps 为一个新的 Abstract Closure,带有参数 (error),它捕获 errorsresultCapabilityremainingElementsCount,并在被调用时执行以下步骤:
      1. activeFunc活动函数对象
      2. 如果 activeFunc.[[AlreadyCalled]]true,返回 undefined
      3. activeFunc.[[AlreadyCalled]] 设为 true
      4. thisIndexactiveFunc.[[Index]]
      5. errors[thisIndex] 设为 error
      6. remainingElementsCount.[[Value]] 设为 remainingElementsCount.[[Value]] - 1。
      7. 如果 remainingElementsCount.[[Value]] = 0,则
        1. aggregateError 为一个新创建的 AggregateError 对象。
        2. 执行 ! DefinePropertyOrThrow(aggregateError, "errors", PropertyDescriptor { [[Configurable]]: true, [[Enumerable]]: false, [[Writable]]: true, [[Value]]: CreateArrayFromList(errors) })。
        3. 返回 ? Call(resultCapability.[[Reject]], undefined, « aggregateError »)。
      8. 返回 undefined
    6. onRejectedCreateBuiltinFunction(rejectedSteps, 1, "", « [[AlreadyCalled]], [[Index]] »)。
    7. onRejected.[[AlreadyCalled]] 设为 false
    8. onRejected.[[Index]] 设为 index
    9. index 设为 index + 1。
    10. remainingElementsCount.[[Value]] 设为 remainingElementsCount.[[Value]] + 1。
    11. 执行 ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], onRejected »)。

27.2.4.4 Promise.prototype

Promise.prototype 的初始值是 Promise 原型对象

此属性具有属性特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

27.2.4.5 Promise.race ( iterable )

此函数返回一个新的 promise,其 settled 方式与第一个 settled 的传入 promise 相同。它在运行此算法时将传入的 iterable 的所有元素 resolve 为 promise。

  1. constructorthis 值。
  2. promiseCapability 为 ? NewPromiseCapability(constructor)。
  3. promiseResolveCompletion(GetPromiseResolve(constructor))。
  4. IfAbruptRejectPromise(promiseResolve, promiseCapability)。
  5. iteratorRecordCompletion(GetIterator(iterable, sync))。
  6. IfAbruptRejectPromise(iteratorRecord, promiseCapability)。
  7. resultCompletion(PerformPromiseRace(iteratorRecord, constructor, promiseCapability, promiseResolve))。
  8. 如果 result 是 abrupt completion,则
    1. 如果 iteratorRecord.[[Done]]false,将 result 设为 Completion(IteratorClose(iteratorRecord, result))。
    2. IfAbruptRejectPromise(result, promiseCapability)。
  9. 返回 ! result
Note 1

如果 iterable 实参不产生任何值,或者 iterable 产生的 promise 都永远不 settle,那么此方法返回的 pending promise 将永远不会 settled。

Note 2

此函数期望其 this 值为支持 Promise 构造器参数约定的构造器函数。它还期望其 this 值提供一个 resolve 方法。

27.2.4.5.1 PerformPromiseRace ( iteratorRecord, constructor, resultCapability, promiseResolve )

The abstract operation PerformPromiseRace takes arguments iteratorRecord (an Iterator Record), constructor (a constructor), resultCapability (a PromiseCapability Record), and promiseResolve (a function object) and returns either a normal completion containing an Object or a throw completion. It performs the following steps when called:

  1. 重复,
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 nextdone,则
      1. 返回 resultCapability.[[Promise]]
    3. nextPromise 为 ? Call(promiseResolve, constructor, « next »)。
    4. 执行 ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], resultCapability.[[Reject]] »)。

27.2.4.6 Promise.reject ( reason )

此函数返回一个以传入实参 rejected 的新 promise。

  1. constructorthis 值。
  2. promiseCapability 为 ? NewPromiseCapability(constructor)。
  3. 执行 ? Call(promiseCapability.[[Reject]], undefined, « reason »)。
  4. 返回 promiseCapability.[[Promise]]
Note

此函数期望其 this 值为支持 Promise 构造器参数约定的构造器函数。

27.2.4.7 Promise.resolve ( resolution )

此函数返回一个以传入实参 resolved 的新 promise,或者如果该实参是由此构造器产生的 promise,则返回该实参本身。

  1. constructorthis 值。
  2. 如果 constructor 不是 Object,抛出 TypeError 异常。
  3. 返回 ? PromiseResolve(constructor, resolution)。
Note

此函数期望其 this 值为支持 Promise 构造器参数约定的构造器函数。

27.2.4.7.1 PromiseResolve ( constructor, resolution )

The abstract operation PromiseResolve takes arguments constructor (an Object) and resolution (an ECMAScript language value) and returns either a normal completion containing an Object or a throw completion. 它返回一个以 resolution resolved 的新 promise。 It performs the following steps when called:

  1. 如果 IsPromise(resolution) 为 true,则
    1. xConstructor 为 ? Get(resolution, "constructor")。
    2. 如果 SameValue(xConstructor, constructor) 为 true,返回 resolution
  2. promiseCapability 为 ? NewPromiseCapability(constructor)。
  3. 执行 ? Call(promiseCapability.[[Resolve]], undefined, « resolution »)。
  4. 返回 promiseCapability.[[Promise]]

27.2.4.8 Promise.try ( callback, ...args )

此函数在被调用时执行以下步骤:

  1. constructorthis 值。
  2. 如果 constructor 不是 Object,抛出 TypeError 异常。
  3. promiseCapability 为 ? NewPromiseCapability(constructor)。
  4. statusCompletion(Call(callback, undefined, args))。
  5. 如果 status 是 abrupt completion,则
    1. 执行 ? Call(promiseCapability.[[Reject]], undefined, « status.[[Value]] »)。
  6. 否则,
    1. 执行 ? Call(promiseCapability.[[Resolve]], undefined, « status.[[Value]] »)。
  7. 返回 promiseCapability.[[Promise]]
Note

此函数期望其 this 值为支持 Promise 构造器参数约定的构造器函数。

27.2.4.9 Promise.withResolvers ( )

此函数返回一个具有三个属性的对象:一个新的 promise,以及与其关联的 resolvereject 函数。

  1. constructorthis 值。
  2. promiseCapability 为 ? NewPromiseCapability(constructor)。
  3. objOrdinaryObjectCreate(%Object.prototype%)。
  4. 执行 ! CreateDataPropertyOrThrow(obj, "promise", promiseCapability.[[Promise]])。
  5. 执行 ! CreateDataPropertyOrThrow(obj, "resolve", promiseCapability.[[Resolve]])。
  6. 执行 ! CreateDataPropertyOrThrow(obj, "reject", promiseCapability.[[Reject]])。
  7. 返回 obj

27.2.4.10 get Promise [ %Symbol.species% ]

Promise[%Symbol.species%] 是一个访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数在被调用时执行以下步骤:

  1. 返回 this 值。

此函数的 "name" 属性的值为 "get [Symbol.species]"

Note

Promise 原型方法通常使用其 this 值的构造器来创建派生对象。不过,子类构造器可以通过重新定义其 %Symbol.species% 属性来覆盖该默认行为。

27.2.5 Promise 原型对象的属性

Promise 原型对象

  • %Promise.prototype%
  • 有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%
  • 是一个普通对象
  • 没有 [[PromiseState]] 内部槽,也没有 Promise 实例的任何其他内部槽。

27.2.5.1 Promise.prototype.catch ( onRejected )

此方法在被调用时执行以下步骤:

  1. promisethis 值。
  2. 返回 ? Invoke(promise, "then", « undefined, onRejected »)。

27.2.5.2 Promise.prototype.constructor

Promise.prototype.constructor 的初始值为 %Promise%

27.2.5.3 Promise.prototype.finally ( onFinally )

此方法在被调用时执行以下步骤:

  1. promisethis 值。
  2. 如果 promise 不是 Object,抛出 TypeError 异常。
  3. constructor 为 ? SpeciesConstructor(promise, %Promise%)。
  4. 断言:IsConstructor(constructor) 为 true
  5. 如果 IsCallable(onFinally) 为 false,则
    1. thenFinallyonFinally
    2. catchFinallyonFinally
  6. 否则,
    1. thenFinallyClosure 为一个新的 Abstract Closure,带有参数 (value),它捕获 onFinallyconstructor,并在被调用时执行以下步骤:
      1. result 为 ? Call(onFinally, undefined)。
      2. p 为 ? PromiseResolve(constructor, result)。
      3. returnValue 为一个新的无参数 Abstract Closure,它捕获 value,并在被调用时执行以下步骤:
        1. 返回 NormalCompletion(value)。
      4. valueThunkCreateBuiltinFunction(returnValue, 0, "", « »)。
      5. 返回 ? Invoke(p, "then", « valueThunk »)。
    2. thenFinallyCreateBuiltinFunction(thenFinallyClosure, 1, "", « »)。
    3. catchFinallyClosure 为一个新的 Abstract Closure,带有参数 (reason),它捕获 onFinallyconstructor,并在被调用时执行以下步骤:
      1. result 为 ? Call(onFinally, undefined)。
      2. p 为 ? PromiseResolve(constructor, result)。
      3. throwReason 为一个新的无参数 Abstract Closure,它捕获 reason,并在被调用时执行以下步骤:
        1. 抛出 reason
      4. throwerCreateBuiltinFunction(throwReason, 0, "", « »)。
      5. 返回 ? Invoke(p, "then", « thrower »)。
    4. catchFinallyCreateBuiltinFunction(catchFinallyClosure, 1, "", « »)。
  7. 返回 ? Invoke(promise, "then", « thenFinally, catchFinally »)。

27.2.5.4 Promise.prototype.then ( onFulfilled, onRejected )

此方法在被调用时执行以下步骤:

  1. promisethis 值。
  2. 如果 IsPromise(promise) 为 false,抛出 TypeError 异常。
  3. constructor 为 ? SpeciesConstructor(promise, %Promise%)。
  4. resultCapability 为 ? NewPromiseCapability(constructor)。
  5. 返回 PerformPromiseThen(promise, onFulfilled, onRejected, resultCapability)。

27.2.5.4.1 PerformPromiseThen ( promise, onFulfilled, onRejected [ , resultCapability ] )

The abstract operation PerformPromiseThen takes arguments promise (a Promise), onFulfilled (an ECMAScript language value), and onRejected (an ECMAScript language value) and optional argument resultCapability (a PromiseCapability Record) and returns an Object or undefined. 它使用 onFulfilledonRejected 作为其 settlement 动作,对 promise 执行“then”操作。如果传入 resultCapability,则通过更新 resultCapability 的 promise 来存储结果。如果未传入,则 PerformPromiseThen 是由规范内部操作调用的,其结果并不重要。 It performs the following steps when called:

  1. 断言:IsPromise(promise) 为 true
  2. 如果 resultCapability 不存在,则
    1. resultCapability 设为 undefined
  3. 如果 IsCallable(onFulfilled) 为 false,则
    1. onFulfilledJobCallbackempty
  4. 否则,
    1. onFulfilledJobCallbackHostMakeJobCallback(onFulfilled)。
  5. 如果 IsCallable(onRejected) 为 false,则
    1. onRejectedJobCallbackempty
  6. 否则,
    1. onRejectedJobCallbackHostMakeJobCallback(onRejected)。
  7. fulfillReactionPromiseReaction Record { [[Capability]]: resultCapability, [[Type]]: fulfill, [[Handler]]: onFulfilledJobCallback }。
  8. rejectReactionPromiseReaction Record { [[Capability]]: resultCapability, [[Type]]: reject, [[Handler]]: onRejectedJobCallback }。
  9. 如果 promise.[[PromiseState]]pending,则
    1. fulfillReaction 追加到 promise.[[PromiseFulfillReactions]]
    2. rejectReaction 追加到 promise.[[PromiseRejectReactions]]
  10. 否则,如果 promise.[[PromiseState]]fulfilled,则
    1. valuepromise.[[PromiseResult]]
    2. fulfillJobNewPromiseReactionJob(fulfillReaction, value)。
    3. 执行 HostEnqueuePromiseJob(fulfillJob.[[Job]], fulfillJob.[[Realm]])。
  11. 否则,
    1. 断言:promise.[[PromiseState]]rejected
    2. reasonpromise.[[PromiseResult]]
    3. 如果 promise.[[PromiseIsHandled]]false,执行 HostPromiseRejectionTracker(promise, "handle")。
    4. rejectJobNewPromiseReactionJob(rejectReaction, reason)。
    5. 执行 HostEnqueuePromiseJob(rejectJob.[[Job]], rejectJob.[[Realm]])。
  12. promise.[[PromiseIsHandled]] 设为 true
  13. 如果 resultCapabilityundefined,返回 undefined
  14. 返回 resultCapability.[[Promise]]

27.2.5.5 Promise.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是字符串值 "Promise"

此属性具有属性特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

27.2.6 Promise 实例的属性

Promise 实例是普通对象,它们继承来自 Promise 原型对象(内在对象 %Promise.prototype%)的属性。Promise 实例最初会以 Table 88 中描述的内部槽创建。

Table 88: Promise 实例的内部槽
内部槽 类型 描述
[[PromiseState]] pendingfulfilledrejected 控制 promise 如何对传入的对其 then 方法的调用作出反应。
[[PromiseResult]] 一个 ECMAScript 语言值empty promise 已被 fulfilled 或 rejected 时所使用的值(如果有)。当且仅当 [[PromiseState]]pending 时为 empty
[[PromiseFulfillReactions]] PromiseReaction RecordList 当/如果 promise 从 pending 状态转换到 fulfilled 状态时要处理的记录。
[[PromiseRejectReactions]] PromiseReaction RecordList 当/如果 promise 从 pending 状态转换到 rejected 状态时要处理的记录。
[[PromiseIsHandled]] 一个 Boolean 表示该 promise 是否曾经有过 fulfillment 或 rejection 处理器;用于未处理 rejection 跟踪。

27.3 GeneratorFunction 对象

GeneratorFunction 是通常通过求值 GeneratorDeclarationGeneratorExpressionGeneratorMethod 创建的函数。它们也可以通过调用 %GeneratorFunction% 内在对象来创建。

Figure 6 (Informative): Generator 对象关系
种类繁多的框和箭头。

27.3.1 GeneratorFunction 构造器

GeneratorFunction 构造器

  • %GeneratorFunction%
  • Function 的子类。
  • 当作为函数而不是构造器调用时,创建并初始化一个新的 GeneratorFunction。因此函数调用 GeneratorFunction (…) 等价于使用相同实参的对象创建表达式 new GeneratorFunction (…)
  • 可以用作类定义的 extends 子句的值。意图继承指定 GeneratorFunction 行为的子类构造器必须包含对 GeneratorFunction 构造器super 调用,以使用内置 GeneratorFunction 行为所需的内部槽来创建并初始化子类实例。所有用于定义 generator 函数对象的 ECMAScript 语法形式都会创建 GeneratorFunction 的直接实例。没有语法手段可以创建 GeneratorFunction 子类的实例。

27.3.1.1 GeneratorFunction ( ...parameterArgs, bodyArg )

最后一个实参(如果有)指定 generator 函数的函数体(可执行代码);任何前面的实参指定形式参数。

此函数在被调用时执行以下步骤:

  1. activeFunc活动函数对象
  2. 如果 bodyArg 不存在,将 bodyArg 设为空字符串。
  3. 返回 ? CreateDynamicFunction(activeFunc, NewTarget, generator, parameterArgs, bodyArg)。
Note

20.2.1.1 的注。

27.3.2 GeneratorFunction 构造器的属性

GeneratorFunction 构造器

  • 是一个继承自 Function 构造器的标准内置函数对象
  • 有一个 [[Prototype]] 内部槽,其值为 %Function%
  • 有一个 "length" 属性,其值为 1𝔽
  • 有一个 "name" 属性,其值为 "GeneratorFunction"
  • 具有以下属性:

27.3.2.1 GeneratorFunction.prototype

GeneratorFunction.prototype 的初始值是 GeneratorFunction 原型对象

此属性具有属性特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

27.3.3 GeneratorFunction 原型对象的属性

GeneratorFunction 原型对象

27.3.3.1 GeneratorFunction.prototype.constructor

GeneratorFunction.prototype.constructor 的初始值是 %GeneratorFunction%

此属性具有属性特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

27.3.3.2 GeneratorFunction.prototype.prototype

GeneratorFunction.prototype.prototype 的初始值是 %GeneratorPrototype%

此属性具有属性特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

27.3.3.3 GeneratorFunction.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是字符串值 "GeneratorFunction"

此属性具有属性特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

27.3.4 GeneratorFunction 实例

每个 GeneratorFunction 实例都是 ECMAScript 函数对象,并具有 Table 25 中列出的内部槽。所有此类实例的 [[IsClassConstructor]] 内部槽的值都是 false

每个 GeneratorFunction 实例都具有以下自有属性:

27.3.4.1 length

20.2.4.1 中给出的 Function 实例的 "length" 属性规范同样适用于 GeneratorFunction 实例。

27.3.4.2 name

20.2.4.2 中给出的 Function 实例的 "name" 属性规范同样适用于 GeneratorFunction 实例。

27.3.4.3 prototype

每当创建 GeneratorFunction 实例时,也会创建另一个普通对象,并且该对象是 generator 函数的 "prototype" 属性的初始值。当 generator 函数对象使用 [[Call]] 被调用时,prototype 属性的值用于初始化新创建的 Generator 的 [[Prototype]] 内部槽。

此属性具有属性特性 { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }。

Note

与 Function 实例不同,作为 GeneratorFunction 的 "prototype" 属性值的对象没有值为该 GeneratorFunction 实例的 "constructor" 属性。

27.4 AsyncGeneratorFunction 对象

AsyncGeneratorFunction 是通常通过求值 AsyncGeneratorDeclarationAsyncGeneratorExpressionAsyncGeneratorMethod 语法产生式创建的函数。它们也可以通过调用 %AsyncGeneratorFunction% 内在对象来创建。

27.4.1 AsyncGeneratorFunction 构造器

AsyncGeneratorFunction 构造器

  • %AsyncGeneratorFunction%
  • Function 的子类。
  • 当作为函数而不是构造器调用时,创建并初始化一个新的 AsyncGeneratorFunction。因此函数调用 AsyncGeneratorFunction (...) 等价于使用相同实参的对象创建表达式 new AsyncGeneratorFunction (...)
  • 可以用作类定义的 extends 子句的值。意图继承指定 AsyncGeneratorFunction 行为的子类构造器必须包含对 AsyncGeneratorFunction 构造器super 调用,以使用内置 AsyncGeneratorFunction 行为所需的内部槽来创建并初始化子类实例。所有用于定义 async generator 函数对象的 ECMAScript 语法形式都会创建 AsyncGeneratorFunction 的直接实例。没有语法手段可以创建 AsyncGeneratorFunction 子类的实例。

27.4.1.1 AsyncGeneratorFunction ( ...parameterArgs, bodyArg )

最后一个实参(如果有)指定 async generator 函数的函数体(可执行代码);任何前面的实参指定形式参数。

此函数在被调用时执行以下步骤:

  1. activeFunc活动函数对象
  2. 如果 bodyArg 不存在,将 bodyArg 设为空字符串。
  3. 返回 ? CreateDynamicFunction(activeFunc, NewTarget, async-generator, parameterArgs, bodyArg)。
Note

20.2.1.1 的注。

27.4.2 AsyncGeneratorFunction 构造器的属性

AsyncGeneratorFunction 构造器

  • 是一个继承自 Function 构造器的标准内置函数对象
  • 有一个 [[Prototype]] 内部槽,其值为 %Function%
  • 有一个 "length" 属性,其值为 1𝔽
  • 有一个 "name" 属性,其值为 "AsyncGeneratorFunction"
  • 具有以下属性:

27.4.2.1 AsyncGeneratorFunction.prototype

AsyncGeneratorFunction.prototype 的初始值是 AsyncGeneratorFunction 原型对象

此属性具有属性特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

27.4.3 AsyncGeneratorFunction 原型对象的属性

AsyncGeneratorFunction 原型对象

27.4.3.1 AsyncGeneratorFunction.prototype.constructor

AsyncGeneratorFunction.prototype.constructor 的初始值是 %AsyncGeneratorFunction%

此属性具有属性特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

27.4.3.2 AsyncGeneratorFunction.prototype.prototype

AsyncGeneratorFunction.prototype.prototype 的初始值是 %AsyncGeneratorPrototype%

此属性具有属性特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

27.4.3.3 AsyncGeneratorFunction.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是字符串值 "AsyncGeneratorFunction"

此属性具有属性特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

27.4.4 AsyncGeneratorFunction 实例

每个 AsyncGeneratorFunction 实例都是 ECMAScript 函数对象,并具有 Table 25 中列出的内部槽。所有此类实例的 [[IsClassConstructor]] 内部槽的值都是 false

每个 AsyncGeneratorFunction 实例都具有以下自有属性:

27.4.4.1 length

"length" 属性的值是一个整数 Number,表示 AsyncGeneratorFunction 通常期望的实参数量。不过,语言允许以其他数量的实参调用该函数。当以不同于其 "length" 属性指定数量的实参数量调用 AsyncGeneratorFunction 时,其行为取决于该函数。

此属性具有属性特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

27.4.4.2 name

20.2.4.2 中给出的 Function 实例的 "name" 属性规范同样适用于 AsyncGeneratorFunction 实例。

27.4.4.3 prototype

每当创建 AsyncGeneratorFunction 实例时,也会创建另一个普通对象,并且该对象是 async generator 函数的 "prototype" 属性的初始值。当 generator 函数对象使用 [[Call]] 被调用时,prototype 属性的值用于初始化新创建的 AsyncGenerator 的 [[Prototype]] 内部槽。

此属性具有属性特性 { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }。

Note

与函数实例不同,作为 AsyncGeneratorFunction 的 "prototype" 属性值的对象没有值为该 AsyncGeneratorFunction 实例的 "constructor" 属性。

27.5 Generator 对象

Generator 通过调用 generator 函数创建,并且同时符合迭代器接口可迭代接口

Generator 实例直接继承创建该实例的 generator 函数的 "prototype" 属性初始值中的属性。Generator 实例间接继承来自 %GeneratorPrototype% 的属性。

27.5.1 %GeneratorPrototype% 对象

%GeneratorPrototype% 对象:

  • %GeneratorFunction.prototype.prototype%
  • 是一个普通对象
  • 不是 Generator 实例,并且没有 [[GeneratorState]] 内部槽。
  • 有一个 [[Prototype]] 内部槽,其值为 %Iterator.prototype%
  • 具有由所有 Generator 实例间接继承的属性。

27.5.1.1 %GeneratorPrototype%.constructor

%GeneratorPrototype%.constructor 的初始值是 %GeneratorFunction.prototype%

此属性具有属性特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

27.5.1.2 %GeneratorPrototype%.next ( value )

  1. 返回 ? GeneratorResume(this value, value, empty)。

27.5.1.3 %GeneratorPrototype%.return ( value )

此方法在被调用时执行以下步骤:

  1. generatorthis 值。
  2. completionReturnCompletion(value)。
  3. 返回 ? GeneratorResumeAbrupt(generator, completion, empty)。

27.5.1.4 %GeneratorPrototype%.throw ( exception )

此方法在被调用时执行以下步骤:

  1. generatorthis 值。
  2. completionThrowCompletion(exception)。
  3. 返回 ? GeneratorResumeAbrupt(generator, completion, empty)。

27.5.1.5 %GeneratorPrototype% [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是字符串值 "Generator"

此属性具有属性特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

27.5.2 Generator 实例的属性

Generator 实例最初会以 Table 89 中描述的内部槽创建。

Table 89: Generator 实例的内部槽
内部槽 类型 描述
[[GeneratorState]] suspended-startsuspended-yieldexecutingcompleted generator 的当前执行状态。
[[GeneratorContext]] 一个执行上下文 执行此 generator 的代码时使用的执行上下文
[[GeneratorBrand]] 一个 String 或 empty 用于区分不同种类 generator 的品牌。由 ECMAScript 源文本声明的 generator 的 [[GeneratorBrand]] 始终是 empty

27.5.3 Generator 抽象操作

27.5.3.1 GeneratorStart ( generator, generatorBody )

The abstract operation GeneratorStart takes arguments generator (一个 Generator) and generatorBody (一个 FunctionBody Parse Node 或一个无参数 Abstract Closure) and returns unused. It performs the following steps when called:

  1. 断言:generator.[[GeneratorState]]suspended-start
  2. genContext 为运行中的执行上下文
  3. genContext 的 Generator 组件设为 generator
  4. closure 为一个新的无参数 Abstract Closure,它捕获 generatorBody,并在被调用时执行以下步骤:
    1. acGenContext 为运行中的执行上下文
    2. acGeneratoracGenContext 的 Generator 组件。
    3. 如果 generatorBody 是 Parse Node,则
      1. resultCompletion(对 generatorBody 求值)。
    4. 否则,
      1. 断言:generatorBody 是一个无参数 Abstract Closure
      2. resultCompletion(generatorBody())。
    5. 断言:如果我们返回到这里,则 generator 要么抛出了异常,要么执行了隐式或显式 return。
    6. 执行上下文栈中移除 acGenContext,并将位于执行上下文栈顶部的执行上下文恢复为运行中的执行上下文
    7. acGenerator.[[GeneratorState]] 设为 completed
    8. 注:一旦 generator 进入 completed 状态,它就永远不会离开该状态,并且其关联的执行上下文永远不会恢复。此时可以丢弃与 acGenerator 关联的任何执行状态。
    9. 如果 result 是 normal completion,则
      1. resultValueundefined
    10. 否则,如果 result 是 return completion,则
      1. resultValueresult.[[Value]]
    11. 否则,
      1. 断言:result 是 throw completion。
      2. 返回 ? result
    12. 返回 NormalCompletion(CreateIteratorResultObject(resultValue, true))。
  5. 设置 genContext 的代码求值状态,使得当该执行上下文的求值被恢复时,将无实参调用 closure
  6. generator.[[GeneratorContext]] 设为 genContext
  7. 返回 unused

27.5.3.2 GeneratorValidate ( generator, generatorBrand )

The abstract operation GeneratorValidate takes arguments generator (一个 ECMAScript 语言值) and generatorBrand (一个 String 或 empty) and returns 一个包含 suspended-startsuspended-yieldcompleted 之一的 normal completion,或一个 throw completion. It performs the following steps when called:

  1. 执行 ? RequireInternalSlot(generator, [[GeneratorState]])。
  2. 执行 ? RequireInternalSlot(generator, [[GeneratorBrand]])。
  3. 如果 generator.[[GeneratorBrand]] 不是 generatorBrand,抛出 TypeError 异常。
  4. 断言:generator 具有 [[GeneratorContext]] 内部槽。
  5. stategenerator.[[GeneratorState]]
  6. 如果 stateexecuting,抛出 TypeError 异常。
  7. 返回 state

27.5.3.3 GeneratorResume ( generator, value, generatorBrand )

The abstract operation GeneratorResume takes arguments generator (一个 ECMAScript 语言值), value (一个 ECMAScript 语言值empty), and generatorBrand (一个 String 或 empty) and returns 一个包含 ECMAScript 语言值的 normal completion 或一个 throw completion. It performs the following steps when called:

  1. state 为 ? GeneratorValidate(generator, generatorBrand)。
  2. 如果 statecompleted,则返回 CreateIteratorResultObject(undefined, true)。
  3. 断言:statesuspended-startsuspended-yield
  4. genContextgenerator.[[GeneratorContext]]
  5. generator.[[GeneratorState]] 设置为 executing
  6. 返回 ? RunSuspendedContext(genContext, NormalCompletion(value))。

27.5.3.4 GeneratorResumeAbrupt ( generator, abruptCompletion, generatorBrand )

The abstract operation GeneratorResumeAbrupt takes arguments generator (一个 ECMAScript 语言值), abruptCompletion (一个 return completion 或一个 throw completion), and generatorBrand (一个 String 或 empty) and returns 一个包含 ECMAScript 语言值的 normal completion 或一个 throw completion. It performs the following steps when called:

  1. state 为 ? GeneratorValidate(generator, generatorBrand)。
  2. 如果 statesuspended-start,则
    1. generator.[[GeneratorState]] 设置为 completed
    2. 注:一旦生成器进入 completed 状态,它就永远不会离开该状态,并且其关联的执行上下文永远不会被恢复。此时可以丢弃与 generator 关联的任何执行状态。
    3. state 设置为 completed
  3. 如果 statecompleted,则
    1. 如果 abruptCompletion 是一个 return 完成,则
      1. 返回 CreateIteratorResultObject(abruptCompletion.[[Value]], true)。
    2. 返回 ? abruptCompletion
  4. 断言:statesuspended-yield
  5. genContextgenerator.[[GeneratorContext]]
  6. generator.[[GeneratorState]] 设置为 executing
  7. 返回 ? RunSuspendedContext(genContext, abruptCompletion)。

27.5.3.5 GetGeneratorKind ( )

The abstract operation GetGeneratorKind takes no arguments and returns non-generatorsyncasync. It performs the following steps when called:

  1. genContext 为运行中的执行上下文
  2. 如果 genContext 没有 Generator 组件,返回 non-generator
  3. generatorgenContext 的 Generator 组件。
  4. 如果 generator 具有 [[AsyncGeneratorState]] 内部槽,返回 async
  5. 返回 sync

27.5.3.6 GeneratorYield ( iteratorResult )

The abstract operation GeneratorYield takes argument iteratorResult (一个符合 IteratorResult 接口的 Object) and returns 一个包含 ECMAScript 语言值的 normal completion 或一个 abrupt completion. It performs the following steps when called:

  1. genContext 为运行中的执行上下文
  2. 断言:genContext 是某个 generator 的执行上下文
  3. generatorgenContext 的 Generator 组件的值。
  4. 断言:GetGeneratorKind() 是 sync
  5. generator.[[GeneratorState]] 设为 suspended-yield
  6. 执行上下文栈中移除 genContext,并将位于执行上下文栈顶部的执行上下文恢复为运行中的执行上下文
  7. callerContext 为运行中的执行上下文
  8. 恢复 callerContext,传入 NormalCompletion(iteratorResult)。如果 genContext 曾经再次被恢复,令 resumptionValue 为它被恢复时所用的 Completion Record
  9. 断言:如果控制到达这里,则 genContext 又是运行中的执行上下文
  10. 返回 resumptionValue

27.5.3.7 Yield ( value )

The abstract operation Yield takes argument value (一个 ECMAScript 语言值) and returns 一个包含 ECMAScript 语言值的 normal completion 或一个 abrupt completion. It performs the following steps when called:

  1. generatorKindGetGeneratorKind()。
  2. 如果 generatorKindasync,返回 ? AsyncGeneratorYield(? Await(value))。
  3. 返回 ? GeneratorYield(CreateIteratorResultObject(value, false))。

27.5.3.8 CreateIteratorFromClosure ( closure, generatorBrand, generatorPrototype [ , extraSlots ] )

The abstract operation CreateIteratorFromClosure takes arguments closure (一个无参数 Abstract Closure), generatorBrand (一个 String 或 empty), and generatorPrototype (一个 Object) and optional argument extraSlots (一个内部槽名称的 List) and returns 一个 Generator. It performs the following steps when called:

  1. 注:closure 可以包含对 Yield 操作的使用,以产出 IteratorResult 对象。
  2. 如果 extraSlots 不存在,将 extraSlots 设为一个新的空 List
  3. internalSlotsListextraSlots 与 « [[GeneratorState]], [[GeneratorContext]], [[GeneratorBrand]] » 的列表连接
  4. generatorOrdinaryObjectCreate(generatorPrototype, internalSlotsList)。
  5. generator.[[GeneratorBrand]] 设为 generatorBrand
  6. generator.[[GeneratorState]] 设为 suspended-start
  7. callerContext 为运行中的执行上下文
  8. calleeContext 为一个新的执行上下文
  9. calleeContext 的 Function 设为 null
  10. calleeContextRealm 设为当前 Realm Record
  11. calleeContext 的 ScriptOrModule 设为 callerContext 的 ScriptOrModule。
  12. 如果 callerContext 尚未挂起,则挂起 callerContext
  13. calleeContext 压入执行上下文栈calleeContext 现在是运行中的执行上下文
  14. 执行 GeneratorStart(generator, closure)。
  15. 执行上下文栈中移除 calleeContext,并将 callerContext 恢复为运行中的执行上下文
  16. 返回 generator

27.6 AsyncGenerator 对象

AsyncGenerator 通过调用 async generator 函数创建,并且同时符合异步迭代器接口异步可迭代接口

AsyncGenerator 实例直接继承创建该实例的 async generator 函数的 "prototype" 属性初始值中的属性。AsyncGenerator 实例间接继承来自 %AsyncGeneratorPrototype% 的属性。

27.6.1 %AsyncGeneratorPrototype% 对象

%AsyncGeneratorPrototype% 对象:

  • %AsyncGeneratorFunction.prototype.prototype%
  • 是一个普通对象
  • 不是 AsyncGenerator 实例,并且没有 [[AsyncGeneratorState]] 内部槽。
  • 有一个 [[Prototype]] 内部槽,其值为 %AsyncIteratorPrototype%
  • 具有由所有 AsyncGenerator 实例间接继承的属性。

27.6.1.1 %AsyncGeneratorPrototype%.constructor

%AsyncGeneratorPrototype%.constructor 的初始值是 %AsyncGeneratorFunction.prototype%

此属性具有属性特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

27.6.1.2 %AsyncGeneratorPrototype%.next ( value )

  1. generatorthis 值。
  2. promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  3. resultCompletion(AsyncGeneratorValidate(generator, empty))。
  4. IfAbruptRejectPromise(result, promiseCapability)。
  5. stategenerator.[[AsyncGeneratorState]]
  6. 如果 statecompleted,则
    1. iteratorResultCreateIteratorResultObject(undefined, true)。
    2. 执行 ! Call(promiseCapability.[[Resolve]], undefined, « iteratorResult »)。
    3. 返回 promiseCapability.[[Promise]]
  7. completionNormalCompletion(value)。
  8. 执行 AsyncGeneratorEnqueue(generator, completion, promiseCapability)。
  9. 如果 statesuspended-startsuspended-yield,则
    1. 执行 AsyncGeneratorResume(generator, completion)。
  10. 否则,
    1. 断言:stateexecutingdraining-queue
  11. 返回 promiseCapability.[[Promise]]

27.6.1.3 %AsyncGeneratorPrototype%.return ( value )

  1. generatorthis 值。
  2. promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  3. resultCompletion(AsyncGeneratorValidate(generator, empty))。
  4. IfAbruptRejectPromise(result, promiseCapability)。
  5. completionReturnCompletion(value)。
  6. 执行 AsyncGeneratorEnqueue(generator, completion, promiseCapability)。
  7. stategenerator.[[AsyncGeneratorState]]
  8. 如果 statesuspended-startcompleted,则
    1. generator.[[AsyncGeneratorState]] 设为 draining-queue
    2. 执行 AsyncGeneratorAwaitReturn(generator)。
  9. 否则,如果 statesuspended-yield,则
    1. 执行 AsyncGeneratorResume(generator, completion)。
  10. 否则,
    1. 断言:stateexecutingdraining-queue
  11. 返回 promiseCapability.[[Promise]]

27.6.1.4 %AsyncGeneratorPrototype%.throw ( exception )

  1. generatorthis 值。
  2. promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  3. resultCompletion(AsyncGeneratorValidate(generator, empty))。
  4. IfAbruptRejectPromise(result, promiseCapability)。
  5. stategenerator.[[AsyncGeneratorState]]
  6. 如果 statesuspended-start,则
    1. generator.[[AsyncGeneratorState]] 设为 completed
    2. state 设为 completed
  7. 如果 statecompleted,则
    1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « exception »)。
    2. 返回 promiseCapability.[[Promise]]
  8. completionThrowCompletion(exception)。
  9. 执行 AsyncGeneratorEnqueue(generator, completion, promiseCapability)。
  10. 如果 statesuspended-yield,则
    1. 执行 AsyncGeneratorResume(generator, completion)。
  11. 否则,
    1. 断言:stateexecutingdraining-queue
  12. 返回 promiseCapability.[[Promise]]

27.6.1.5 %AsyncGeneratorPrototype% [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是字符串值 "AsyncGenerator"

此属性具有属性特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

27.6.2 AsyncGenerator 实例的属性

AsyncGenerator 实例最初会以下面描述的内部槽创建:

Table 90: AsyncGenerator 实例的内部槽
内部槽 类型 描述
[[AsyncGeneratorState]] suspended-startsuspended-yieldexecutingdraining-queuecompleted async generator 的当前执行状态。
[[AsyncGeneratorContext]] 一个执行上下文 执行此 async generator 的代码时使用的执行上下文
[[AsyncGeneratorQueue]] AsyncGeneratorRequest RecordList 表示恢复 async generator 请求的记录。除状态转换期间外,当且仅当 [[AsyncGeneratorState]]executingdraining-queue 时,它非空。
[[GeneratorBrand]] 一个 String 或 empty 用于区分不同种类 async generator 的品牌。由 ECMAScript 源文本声明的 async generator 的 [[GeneratorBrand]] 始终是 empty

27.6.3 AsyncGenerator 抽象操作

27.6.3.1 AsyncGeneratorRequest Record

AsyncGeneratorRequest 是一种 Record 值,用于存储关于 async generator 应如何恢复的信息,并包含用于 fulfill 或 reject 对应 promise 的 capability。

它们具有以下字段:

Table 91: AsyncGeneratorRequest Record 字段
字段名 含义
[[Completion]] 一个 Completion Record 应当用于恢复 async generator 的 Completion Record
[[Capability]] 一个 PromiseCapability Record 与此请求关联的 promise capability。

27.6.3.2 AsyncGeneratorStart ( generator, generatorBody )

The abstract operation AsyncGeneratorStart takes arguments generator (一个 AsyncGenerator) and generatorBody (一个 FunctionBody Parse Node 或一个无参数 Abstract Closure) and returns unused. It performs the following steps when called:

  1. 断言:generator.[[AsyncGeneratorState]]suspended-start
  2. genContext 为运行中的执行上下文
  3. genContext 的 Generator 组件设为 generator
  4. closure 为一个新的无参数 Abstract Closure,它捕获 generatorBody,并在被调用时执行以下步骤:
    1. acGenContext 为运行中的执行上下文
    2. acGeneratoracGenContext 的 Generator 组件。
    3. 如果 generatorBody 是 Parse Node,则
      1. resultCompletion(对 generatorBody 求值)。
    4. 否则,
      1. 断言:generatorBody 是一个无参数 Abstract Closure
      2. resultCompletion(generatorBody())。
    5. 断言:如果我们返回到这里,则 async generator 要么抛出了异常,要么执行了隐式或显式 return。
    6. 执行上下文栈中移除 acGenContext,并将位于执行上下文栈顶部的执行上下文恢复为运行中的执行上下文
    7. acGenerator.[[AsyncGeneratorState]] 设为 draining-queue
    8. 如果 result 是 normal completion,将 result 设为 NormalCompletion(undefined)。
    9. 如果 result 是 return completion,将 result 设为 NormalCompletion(result.[[Value]])。
    10. 执行 AsyncGeneratorCompleteStep(acGenerator, result, true)。
    11. 执行 AsyncGeneratorDrainQueue(acGenerator)。
    12. 返回 NormalCompletion(undefined)。
  5. 设置 genContext 的代码求值状态,使得当该执行上下文的求值被恢复时,将无实参调用 closure
  6. generator.[[AsyncGeneratorContext]] 设为 genContext
  7. generator.[[AsyncGeneratorQueue]] 设为一个新的空 List
  8. 返回 unused

27.6.3.3 AsyncGeneratorValidate ( generator, generatorBrand )

The abstract operation AsyncGeneratorValidate takes arguments generator (一个 ECMAScript 语言值) and generatorBrand (一个 String 或 empty) and returns 一个包含 unused 的 normal completion 或一个 throw completion. It performs the following steps when called:

  1. 执行 ? RequireInternalSlot(generator, [[AsyncGeneratorContext]])。
  2. 执行 ? RequireInternalSlot(generator, [[AsyncGeneratorState]])。
  3. 执行 ? RequireInternalSlot(generator, [[AsyncGeneratorQueue]])。
  4. 如果 generator.[[GeneratorBrand]] 不是 generatorBrand,抛出 TypeError 异常。
  5. 返回 unused

27.6.3.4 AsyncGeneratorEnqueue ( generator, completion, promiseCapability )

The abstract operation AsyncGeneratorEnqueue takes arguments generator (一个 AsyncGenerator), completion (一个 Completion Record), and promiseCapability (一个 PromiseCapability Record) and returns unused. It performs the following steps when called:

  1. requestAsyncGeneratorRequest { [[Completion]]: completion, [[Capability]]: promiseCapability }。
  2. request 追加到 generator.[[AsyncGeneratorQueue]]
  3. 返回 unused

27.6.3.5 AsyncGeneratorCompleteStep ( generator, completion, done [ , realm ] )

The abstract operation AsyncGeneratorCompleteStep takes arguments generator (一个 AsyncGenerator), completion (一个 Completion Record), and done (一个 Boolean) and optional argument realm (一个 Realm Record) and returns unused. It performs the following steps when called:

  1. 断言:generator.[[AsyncGeneratorQueue]] 非空。
  2. nextgenerator.[[AsyncGeneratorQueue]] 的第一个元素。
  3. generator.[[AsyncGeneratorQueue]] 中移除第一个元素。
  4. promiseCapabilitynext.[[Capability]]
  5. valuecompletion.[[Value]]
  6. 如果 completion 是 throw completion,则
    1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « value »)。
  7. 否则,
    1. 断言:completion 是 normal completion。
    2. 如果 realm 存在,则
      1. oldRealm 为运行中的执行上下文Realm
      2. 将运行中的执行上下文Realm 设为 realm
      3. iteratorResultCreateIteratorResultObject(value, done)。
      4. 将运行中的执行上下文Realm 设为 oldRealm
    3. 否则,
      1. iteratorResultCreateIteratorResultObject(value, done)。
    4. 执行 ! Call(promiseCapability.[[Resolve]], undefined, « iteratorResult »)。
  8. 返回 unused

27.6.3.6 AsyncGeneratorResume ( generator, completion )

The abstract operation AsyncGeneratorResume takes arguments generator (一个 AsyncGenerator) and completion (一个 Completion Record) and returns unused. It performs the following steps when called:

  1. 断言:generator.[[AsyncGeneratorState]]suspended-startsuspended-yield
  2. genContextgenerator.[[AsyncGeneratorContext]]
  3. generator.[[AsyncGeneratorState]] 设置为 executing
  4. 执行 ! RunSuspendedContext(genContext, completion)。
  5. 返回 unused

27.6.3.7 AsyncGeneratorUnwrapYieldResumption ( resumptionValue )

The abstract operation AsyncGeneratorUnwrapYieldResumption takes argument resumptionValue (一个 Completion Record) and returns 一个包含 ECMAScript 语言值的 normal completion 或一个 abrupt completion. It performs the following steps when called:

  1. 如果 resumptionValue 不是 return completion,返回 ? resumptionValue
  2. awaitedCompletion(Await(resumptionValue.[[Value]]))。
  3. 如果 awaited 是 throw completion,返回 ? awaited
  4. 断言:awaited 是 normal completion。
  5. 返回 ReturnCompletion(awaited.[[Value]])。

27.6.3.8 AsyncGeneratorYield ( value )

The abstract operation AsyncGeneratorYield takes argument value (一个 ECMAScript 语言值) and returns 一个包含 ECMAScript 语言值的 normal completion 或一个 abrupt completion. It performs the following steps when called:

  1. genContext 为运行中的执行上下文
  2. 断言:genContext 是某个 generator 的执行上下文
  3. generatorgenContext 的 Generator 组件的值。
  4. 断言:GetGeneratorKind() 是 async
  5. completionNormalCompletion(value)。
  6. 断言:执行上下文栈至少有两个元素。
  7. previousContext执行上下文栈中倒数第二个元素。
  8. previousRealmpreviousContextRealm
  9. 执行 AsyncGeneratorCompleteStep(generator, completion, false, previousRealm)。
  10. queuegenerator.[[AsyncGeneratorQueue]]
  11. 如果 queue 非空,则
    1. 注:执行会继续,而不挂起 generator。
    2. toYieldqueue 的第一个元素。
    3. resumptionValueCompletion(toYield.[[Completion]])。
    4. 返回 ? AsyncGeneratorUnwrapYieldResumption(resumptionValue)。
  12. generator.[[AsyncGeneratorState]] 设为 suspended-yield
  13. 执行上下文栈中移除 genContext,并将位于执行上下文栈顶部的执行上下文恢复为运行中的执行上下文
  14. callerContext 为运行中的执行上下文
  15. 恢复 callerContext,传入 undefined。如果 genContext 曾经再次被恢复,令 resumptionValue 为它被恢复时所用的 Completion Record
  16. 断言:如果控制到达这里,则 genContext 又是运行中的执行上下文
  17. 返回 ? AsyncGeneratorUnwrapYieldResumption(resumptionValue)。

27.6.3.9 AsyncGeneratorAwaitReturn ( generator )

The abstract operation AsyncGeneratorAwaitReturn takes argument generator (一个 AsyncGenerator) and returns unused. It performs the following steps when called:

  1. 断言:generator.[[AsyncGeneratorState]]draining-queue
  2. queuegenerator.[[AsyncGeneratorQueue]]
  3. 断言:queue 非空。
  4. nextqueue 的第一个元素。
  5. completionCompletion(next.[[Completion]])。
  6. 断言:completion 是 return completion。
  7. promiseCompletionCompletion(PromiseResolve(%Promise%, completion.[[Value]]))。
  8. 如果 promiseCompletion 是 abrupt completion,则
    1. 执行 AsyncGeneratorCompleteStep(generator, promiseCompletion, true)。
    2. 执行 AsyncGeneratorDrainQueue(generator)。
    3. 返回 unused
  9. 断言:promiseCompletion 是 normal completion。
  10. promisepromiseCompletion.[[Value]]
  11. fulfilledClosure 为一个新的 Abstract Closure,带有参数 (value),它捕获 generator,并在被调用时执行以下步骤:
    1. 断言:generator.[[AsyncGeneratorState]]draining-queue
    2. resultNormalCompletion(value)。
    3. 执行 AsyncGeneratorCompleteStep(generator, result, true)。
    4. 执行 AsyncGeneratorDrainQueue(generator)。
    5. 返回 NormalCompletion(undefined)。
  12. onFulfilledCreateBuiltinFunction(fulfilledClosure, 1, "", « »)。
  13. rejectedClosure 为一个新的 Abstract Closure,带有参数 (reason),它捕获 generator,并在被调用时执行以下步骤:
    1. 断言:generator.[[AsyncGeneratorState]]draining-queue
    2. resultThrowCompletion(reason)。
    3. 执行 AsyncGeneratorCompleteStep(generator, result, true)。
    4. 执行 AsyncGeneratorDrainQueue(generator)。
    5. 返回 NormalCompletion(undefined)。
  14. onRejectedCreateBuiltinFunction(rejectedClosure, 1, "", « »)。
  15. 执行 PerformPromiseThen(promise, onFulfilled, onRejected)。
  16. 返回 unused

27.6.3.10 AsyncGeneratorDrainQueue ( generator )

The abstract operation AsyncGeneratorDrainQueue takes argument generator (一个 AsyncGenerator) and returns unused. 它会清空 generator 的 AsyncGeneratorQueue,直到遇到一个持有 return completion 的 AsyncGeneratorRequest。 It performs the following steps when called:

  1. 断言:generator.[[AsyncGeneratorState]]draining-queue
  2. queuegenerator.[[AsyncGeneratorQueue]]
  3. 重复,当 queue 非空时,
    1. nextqueue 的第一个元素。
    2. completionCompletion(next.[[Completion]])。
    3. 如果 completion 是 return completion,则
      1. 执行 AsyncGeneratorAwaitReturn(generator)。
      2. 返回 unused
    4. 如果 completion 是 normal completion,则
      1. completion 设为 NormalCompletion(undefined)。
    5. 执行 AsyncGeneratorCompleteStep(generator, completion, true)。
  4. generator.[[AsyncGeneratorState]] 设为 completed
  5. 返回 unused

27.7 AsyncFunction 对象

AsyncFunction 是通常通过求值 AsyncFunctionDeclarationAsyncFunctionExpressionAsyncMethodAsyncArrowFunction 创建的函数。它们也可以通过调用 %AsyncFunction% 内在对象来创建。

27.7.1 AsyncFunction 构造器

AsyncFunction 构造器

  • %AsyncFunction%
  • Function 的子类。
  • 当作为函数而不是构造器调用时,创建并初始化一个新的 AsyncFunction。因此函数调用 AsyncFunction(…) 等价于使用相同实参的对象创建表达式 new AsyncFunction(…)
  • 可以用作类定义的 extends 子句的值。意图继承指定 AsyncFunction 行为的子类构造器必须包含对 AsyncFunction 构造器super 调用,以使用内置 async 函数行为所需的内部槽来创建并初始化子类实例。所有用于定义 async 函数对象的 ECMAScript 语法形式都会创建 AsyncFunction 的直接实例。没有语法手段可以创建 AsyncFunction 子类的实例。

27.7.1.1 AsyncFunction ( ...parameterArgs, bodyArg )

最后一个实参(如果有)指定 async 函数的函数体(可执行代码)。任何前面的实参指定形式参数。

此函数在被调用时执行以下步骤:

  1. activeFunc活动函数对象
  2. 如果 bodyArg 不存在,将 bodyArg 设为空字符串。
  3. 返回 ? CreateDynamicFunction(activeFunc, NewTarget, async, parameterArgs, bodyArg)。
Note
20.2.1.1 的注。

27.7.2 AsyncFunction 构造器的属性

AsyncFunction 构造器

  • 是一个继承自 Function 构造器的标准内置函数对象
  • 有一个 [[Prototype]] 内部槽,其值为 %Function%
  • 有一个 "length" 属性,其值为 1𝔽
  • 有一个 "name" 属性,其值为 "AsyncFunction"
  • 具有以下属性:

27.7.2.1 AsyncFunction.prototype

AsyncFunction.prototype 的初始值是 AsyncFunction 原型对象

此属性具有属性特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

27.7.3 AsyncFunction 原型对象的属性

AsyncFunction 原型对象

27.7.3.1 AsyncFunction.prototype.constructor

AsyncFunction.prototype.constructor 的初始值是 %AsyncFunction%

此属性具有属性特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

27.7.3.2 AsyncFunction.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是字符串值 "AsyncFunction"

此属性具有属性特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

27.7.4 AsyncFunction 实例

每个 AsyncFunction 实例都是 ECMAScript 函数对象,并具有 Table 25 中列出的内部槽。所有此类实例的 [[IsClassConstructor]] 内部槽的值都是 false。AsyncFunction 实例不是构造器,并且没有 [[Construct]] 内部方法。AsyncFunction 实例没有 prototype 属性,因为它们不可构造。

每个 AsyncFunction 实例都具有以下自有属性:

27.7.4.1 length

20.2.4.1 中给出的 Function 实例的 "length" 属性规范同样适用于 AsyncFunction 实例。

27.7.4.2 name

20.2.4.2 中给出的 Function 实例的 "name" 属性规范同样适用于 AsyncFunction 实例。

27.7.5 Async Function 抽象操作

27.7.5.1 AsyncFunctionStart ( promiseCapability, asyncFunctionBody )

The abstract operation AsyncFunctionStart takes arguments promiseCapability (一个 PromiseCapability Record) and asyncFunctionBody (一个 FunctionBody Parse Node、一个 ExpressionBody Parse Node 或一个无参数 Abstract Closure) and returns unused. It performs the following steps when called:

  1. runningContext 为运行中的执行上下文
  2. asyncContextrunningContext 的副本。
  3. 注:复制执行状态是 AsyncBlockStart 恢复其执行所必需的。恢复当前正在执行的上下文是定义不良的。
  4. 执行 AsyncBlockStart(promiseCapability, asyncFunctionBody, asyncContext)。
  5. 返回 unused

27.7.5.2 AsyncBlockStart ( promiseCapability, asyncBody, asyncContext )

The abstract operation AsyncBlockStart takes arguments promiseCapability (一个 PromiseCapability Record), asyncBody (一个 Parse Node 或一个无参数 Abstract Closure), and asyncContext (一个执行上下文) and returns unused. It performs the following steps when called:

  1. closure 为一个无参数的新抽象闭包,它捕获 promiseCapabilityasyncBody,并在被调用时执行以下步骤:
    1. acAsyncContext正在运行的执行上下文
    2. 如果 asyncBody解析节点,则
      1. resultCompletion(对 asyncBody 求值)。
    3. 否则,
      1. 断言:asyncBody 是一个无参数的抽象闭包。
      2. resultCompletion(asyncBody())。
    4. 断言:如果我们在这里返回,则该 async 函数要么抛出了异常,要么执行了隐式或显式 return;所有 await 都已完成。
    5. 执行上下文栈中移除 acAsyncContext,并将执行上下文栈顶的执行上下文恢复为正在运行的执行上下文
    6. 如果 result 是一个正常完成,则
      1. 执行 ! Call(promiseCapability.[[Resolve]], undefined, « undefined »)。
    7. 否则,如果 result 是一个 return 完成,则
      1. 执行 ! Call(promiseCapability.[[Resolve]], undefined, « result.[[Value]] »)。
    8. 否则,
      1. 断言:result 是一个 throw 完成
      2. 执行 ! Call(promiseCapability.[[Reject]], undefined, « result.[[Value]] »)。
    9. 返回 NormalCompletion(unused)。
  2. 设置 asyncContext 的代码求值状态,使得当该执行上下文的求值被恢复时,将不带参数调用 closure
  3. result 为 ! RunSuspendedContext(asyncContext, NormalCompletion(empty))。
  4. 断言:resultunused
  5. 注:result 值的可能来源是 Await,或者如果该 async 函数没有 await 任何内容,则为上面的步骤 1.i
  6. 返回 unused

27.7.5.3 Await ( value )

The abstract operation Await takes argument value (一个 ECMAScript 语言值) and returns 一个包含 ECMAScript 语言值empty 的 normal completion,或一个 throw completion. It performs the following steps when called:

  1. asyncContext正在运行的执行上下文
  2. promise 为 ? PromiseResolve(%Promise%, value)。
  3. fulfilledClosure 为一个带参数 (v) 的新抽象闭包,它捕获 asyncContext,并在被调用时执行以下步骤:
    1. 执行 Completion(RunSuspendedContext(asyncContext, NormalCompletion(v)))。
    2. 注:RunSuspendedContext 返回的完成记录会被有意忽略。
    3. 返回 NormalCompletion(undefined)。
  4. onFulfilledCreateBuiltinFunction(fulfilledClosure, 1, "", « »)。
  5. rejectedClosure 为一个带参数 (reason) 的新抽象闭包,它捕获 asyncContext,并在被调用时执行以下步骤:
    1. 执行 Completion(RunSuspendedContext(asyncContext, ThrowCompletion(reason)))。
    2. 注:RunSuspendedContext 返回的完成记录会被有意忽略。
    3. 返回 NormalCompletion(undefined)。
  6. onRejectedCreateBuiltinFunction(rejectedClosure, 1, "", « »)。
  7. 执行 PerformPromiseThen(promise, onFulfilled, onRejected)。
  8. 执行上下文栈中移除 asyncContext,并将位于执行上下文栈顶的执行上下文恢复为正在运行的执行上下文
  9. callerContext正在运行的执行上下文
  10. 恢复 callerContext,传入 empty。如果 asyncContext 再次被恢复,则令 completion 为恢复它所用的完成记录。
  11. 断言:如果控制到达这里,则 asyncContext 再次成为正在运行的执行上下文
  12. 返回 completion

28 反射

28.1 Reflect 对象

Reflect 对象:

  • %Reflect%
  • 全局对象"Reflect" 属性的初始值。
  • 是一个普通对象
  • 有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%
  • 不是函数对象
  • 没有 [[Construct]] 内部方法;它不能作为构造器new 运算符一起使用。
  • 没有 [[Call]] 内部方法;它不能作为函数被调用。

28.1.1 Reflect.apply ( target, thisArgument, argumentsList )

此函数在被调用时执行以下步骤:

  1. 如果 IsCallable(target) 为 false,抛出 TypeError 异常。
  2. args 为 ? CreateListFromArrayLike(argumentsList)。
  3. 执行 PrepareForTailCall()。
  4. 返回 ? Call(target, thisArgument, args)。

28.1.2 Reflect.construct ( target, argumentsList [ , newTarget ] )

此函数在被调用时执行以下步骤:

  1. 如果 IsConstructor(target) 为 false,抛出 TypeError 异常。
  2. 如果 newTarget 不存在,将 newTarget 设为 target
  3. 否则,如果 IsConstructor(newTarget) 为 false,抛出 TypeError 异常。
  4. args 为 ? CreateListFromArrayLike(argumentsList)。
  5. 返回 ? Construct(target, args, newTarget)。

28.1.3 Reflect.defineProperty ( target, propertyKey, attributes )

此函数在被调用时执行以下步骤:

  1. 如果 target 不是 Object,抛出 TypeError 异常。
  2. key 为 ? ToPropertyKey(propertyKey)。
  3. desc 为 ? ToPropertyDescriptor(attributes)。
  4. 返回 ? target.[[DefineOwnProperty]](key, desc)

28.1.4 Reflect.deleteProperty ( target, propertyKey )

此函数在被调用时执行以下步骤:

  1. 如果 target 不是 Object,抛出 TypeError 异常。
  2. key 为 ? ToPropertyKey(propertyKey)。
  3. 返回 ? target.[[Delete]](key)

28.1.5 Reflect.get ( target, propertyKey [ , receiver ] )

此函数在被调用时执行以下步骤:

  1. 如果 target 不是 Object,抛出 TypeError 异常。
  2. key 为 ? ToPropertyKey(propertyKey)。
  3. 如果 receiver 不存在,则
    1. receiver 设为 target
  4. 返回 ? target.[[Get]](key, receiver)

28.1.6 Reflect.getOwnPropertyDescriptor ( target, propertyKey )

此函数在被调用时执行以下步骤:

  1. 如果 target 不是 Object,抛出 TypeError 异常。
  2. key 为 ? ToPropertyKey(propertyKey)。
  3. desc 为 ? target.[[GetOwnProperty]](key)
  4. 返回 FromPropertyDescriptor(desc)。

28.1.7 Reflect.getPrototypeOf ( target )

此函数在被调用时执行以下步骤:

  1. 如果 target 不是 Object,抛出 TypeError 异常。
  2. 返回 ? target.[[GetPrototypeOf]]()

28.1.8 Reflect.has ( target, propertyKey )

此函数在被调用时执行以下步骤:

  1. 如果 target 不是 Object,抛出 TypeError 异常。
  2. key 为 ? ToPropertyKey(propertyKey)。
  3. 返回 ? target.[[HasProperty]](key)

28.1.9 Reflect.isExtensible ( target )

此函数在被调用时执行以下步骤:

  1. 如果 target 不是 Object,抛出 TypeError 异常。
  2. 返回 ? target.[[IsExtensible]]()

28.1.10 Reflect.ownKeys ( target )

此函数在被调用时执行以下步骤:

  1. 如果 target 不是 Object,抛出 TypeError 异常。
  2. keys 为 ? target.[[OwnPropertyKeys]]()
  3. 返回 CreateArrayFromList(keys)。

28.1.11 Reflect.preventExtensions ( target )

此函数在被调用时执行以下步骤:

  1. 如果 target 不是 Object,抛出 TypeError 异常。
  2. 返回 ? target.[[PreventExtensions]]()

28.1.12 Reflect.set ( target, propertyKey, value [ , receiver ] )

此函数在被调用时执行以下步骤:

  1. 如果 target 不是 Object,抛出 TypeError 异常。
  2. key 为 ? ToPropertyKey(propertyKey)。
  3. 如果 receiver 不存在,则
    1. receiver 设为 target
  4. 返回 ? target.[[Set]](key, value, receiver)

28.1.13 Reflect.setPrototypeOf ( target, proto )

此函数在被调用时执行以下步骤:

  1. 如果 target 不是 Object,抛出 TypeError 异常。
  2. 如果 proto 不是 Object 且 proto 不是 null,抛出 TypeError 异常。
  3. 返回 ? target.[[SetPrototypeOf]](proto)

28.1.14 Reflect [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是字符串值 "Reflect"

此属性具有属性特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

28.2 Proxy 对象

28.2.1 Proxy 构造器

Proxy 构造器

  • %Proxy%
  • 全局对象"Proxy" 属性的初始值。
  • 作为构造器调用时,创建并初始化一个新的 Proxy 对象。
  • 并非旨在作为函数调用,并且以这种方式调用时会抛出异常。

28.2.1.1 Proxy ( target, handler )

此函数在被调用时执行以下步骤:

  1. 如果 NewTarget 是 undefined,抛出 TypeError 异常。
  2. 返回 ? ProxyCreate(target, handler)。

28.2.2 Proxy 构造器的属性

Proxy 构造器

  • 有一个 [[Prototype]] 内部槽,其值为 %Function.prototype%
  • 没有 "prototype" 属性,因为 Proxy 对象没有需要初始化的 [[Prototype]] 内部槽。
  • 具有以下属性:

28.2.2.1 Proxy.revocable ( target, handler )

此函数创建一个可撤销的 Proxy 对象。

它在被调用时执行以下步骤:

  1. proxy 为 ? ProxyCreate(target, handler)。
  2. revokerClosure 为一个新的无参数 Abstract Closure,它不捕获任何内容,并在被调用时执行以下步骤:
    1. activeFunc活动函数对象
    2. pactiveFunc.[[RevocableProxy]]
    3. 如果 pnull,返回 NormalCompletion(undefined)。
    4. activeFunc.[[RevocableProxy]] 设为 null
    5. 断言:p 是一个 Proxy exotic object。
    6. p.[[ProxyTarget]] 设为 null
    7. p.[[ProxyHandler]] 设为 null
    8. 返回 NormalCompletion(undefined)。
  3. revokerCreateBuiltinFunction(revokerClosure, 0, "", « [[RevocableProxy]] »)。
  4. revoker.[[RevocableProxy]] 设为 proxy
  5. resultOrdinaryObjectCreate(%Object.prototype%)。
  6. 执行 ! CreateDataPropertyOrThrow(result, "proxy", proxy)。
  7. 执行 ! CreateDataPropertyOrThrow(result, "revoke", revoker)。
  8. 返回 result

28.3 模块命名空间对象

模块命名空间对象是一种模块命名空间异质对象,它提供对模块导出绑定的基于属性的运行时访问。模块命名空间对象没有构造器函数。相反,对于每个由包含 NameSpaceImportImportDeclaration 导入的模块,都会创建这样的一个对象。

除了 10.4.6 中指定的属性之外,每个模块命名空间对象还具有以下自有属性:

28.3.1 %Symbol.toStringTag%

%Symbol.toStringTag% 属性的初始值是字符串值 "Module"

此属性具有属性特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

29 内存模型

内存一致性模型,或称内存模型,规定了共享数据块事件的可能排序,这些事件来源于访问以 SharedArrayBuffer 为后备的 TypedArray 实例,以及来源于 Atomics 对象上的方法。当程序没有数据竞争(如下定义)时,事件的排序表现为顺序一致,即表现为来自每个 agent 的动作交错执行。当程序有数据竞争时,共享内存操作可能表现为非顺序一致。例如,程序可能表现出违反因果关系的行为以及其他令人惊讶的行为。这些令人惊讶的行为来源于编译器变换和 CPU 的设计(例如乱序执行和推测执行)。内存模型既定义了程序表现出顺序一致行为的精确条件,也定义了从数据竞争读取到的可能值。也就是说,不存在未定义行为。

内存模型被定义为对 Memory 事件的关系约束,这些事件由 SharedArrayBuffer 上的抽象操作或 Atomics 对象上的方法在一次求值期间引入。

Note

本节提供了一个关于 Memory 事件的公理化模型,这些事件由 SharedArrayBuffer 上的抽象操作引入。需要强调的是,与本规范其余部分不同,该模型无法用算法表达。抽象操作对事件的非确定性引入,是 ECMAScript 求值的操作语义与内存模型的公理语义之间的接口。这些事件的语义通过考虑一次求值中所有事件的图来定义。这些既不是静态语义,也不是运行时语义。这里没有给出已证明的算法实现,而是给出一组约束,用于确定某个特定事件图是被允许还是被禁止。

29.1 内存模型基础

共享内存访问(读和写)分为两组:原子访问和数据访问,如下所定义。原子访问是顺序一致的,即存在一个由 agent 集群中的所有 agent 共同认可的事件严格全序。非原子访问没有由所有 agent 共同认可的严格全序,即无序。

Note 1

不支持弱于顺序一致且强于无序的排序,例如 release-acquire。

共享数据块事件是 ReadSharedMemory、WriteSharedMemory 或 ReadModifyWriteSharedMemory Record读事件是 ReadSharedMemory 或 ReadModifyWriteSharedMemory。写事件是 WriteSharedMemory 或 ReadModifyWriteSharedMemory。

Table 92: ReadSharedMemory 事件字段
字段名 含义
[[Order]] seq-cstunordered 内存模型为该事件保证的最弱排序。
[[NoTear]] 一个 Boolean 此事件是否允许从与此事件具有相同内存范围的多个写事件中读取。
[[Block]] 一个共享数据块 该事件所操作的块。
[[ByteIndex]] 一个非负整数 [[Block]] 中读的字节地址。
[[ElementSize]] 一个非负整数 读的大小。
Table 93: WriteSharedMemory 事件字段
字段名 含义
[[Order]] seq-cstunorderedinit 内存模型为该事件保证的最弱排序。
[[NoTear]] 一个 Boolean 此事件是否允许被与此事件具有相同内存范围的多个读事件读取。
[[Block]] 一个共享数据块 该事件所操作的块。
[[ByteIndex]] 一个非负整数 [[Block]] 中写的字节地址。
[[ElementSize]] 一个非负整数 写的大小。
[[Payload]] 字节值List 将由其他事件读取的字节值 List
Table 94: ReadModifyWriteSharedMemory 事件字段
字段名 含义
[[Order]] seq-cst 读-改-写事件始终是顺序一致的。
[[NoTear]] true 读-改-写事件不能撕裂。
[[Block]] 一个共享数据块 该事件所操作的块。
[[ByteIndex]] 一个非负整数 [[Block]] 中读-改-写的字节地址。
[[ElementSize]] 一个非负整数 读-改-写的大小。
[[Payload]] 字节值List 将传递给 [[ModifyOp]]字节值 List
[[ModifyOp]] 一个读-改-写修改函数 一个 Abstract Closure,它从一个读取到的字节值 List[[Payload]] 返回一个修改后的字节值 List

共享数据块事件由抽象操作或 Atomics 对象上的方法引入到候选执行Agent Events Record 中。某些操作还会引入Synchronize 事件,它们没有字段,纯粹用于直接约束其他事件允许的排序。最后,还有宿主特定事件。Memory 事件是共享数据块事件、Synchronize 事件或此类宿主特定事件。

令共享数据块事件 e内存范围为从 e.[[ByteIndex]](包含)到 e.[[ByteIndex]] + e.[[ElementSize]](不包含)区间内所有整数的 Set。当两个事件具有相同的 [[Block]][[ByteIndex]][[ElementSize]] 时,它们的内存范围相等。当两个事件具有相同的 [[Block]]、范围不相等且交集非空时,它们的内存范围重叠。当两个事件不具有相同的 [[Block]],或者它们的范围既不相等也不重叠时,它们的内存范围不相交。

Note 2

应予以考虑的宿主特定同步事件的例子包括:将 SharedArrayBuffer 从一个 agent 发送到另一个 agent(例如通过浏览器中的 postMessage)、启动和停止 agent,以及通过共享内存之外的通道在 agent 集群内通信。对于某个特定执行 execution,这些事件由宿主通过 host-synchronizes-with 严格偏序提供。此外,宿主可以向 execution.[[EventList]] 添加宿主特定同步事件,以便参与 is-agent-order-before 关系。

事件在候选执行中由下面定义的关系进行排序。

29.2 Agent Events Record

Agent Events Record 是具有以下字段的 Record

Table 95: Agent Events Record 字段
字段名 含义
[[AgentSignifier]] 一个 agent signifier 其求值导致此排序的 agent
[[EventList]] Memory 事件List 事件在求值期间被追加到该列表。
[[AgentSynchronizesWith]] Synchronize 事件对的 List 由操作语义引入的 Synchronize 关系。

29.3 Chosen Value Record

Chosen Value Record 是具有以下字段的 Record

Table 96: Chosen Value Record 字段
字段名 含义
[[Event]] 一个共享数据块事件 为此 chosen value 引入的 ReadSharedMemory 或 ReadModifyWriteSharedMemory 事件。
[[ChosenValue]] 字节值List 求值期间被非确定性选择的字节。

29.4 候选执行

agent 集群求值的候选执行是具有以下字段的 Record

Table 97: 候选执行 Record 字段
字段名 含义
[[EventsRecords]] Agent Events RecordList 将一个 agent 映射到求值期间追加的 Memory 事件 List
[[ChosenValues]] Chosen Value RecordList 将 ReadSharedMemory 或 ReadModifyWriteSharedMemory 事件映射到求值期间选择的字节值 List

空候选执行是其字段为空 List 的候选执行 Record

29.5 内存模型的抽象操作

29.5.1 EventSet ( execution )

The abstract operation EventSet takes argument execution (一个候选执行) and returns Memory 事件的 Set. It performs the following steps when called:

  1. events 为一个空 Set。
  2. 对于 execution.[[EventsRecords]] 的每个 Agent Events Record aer,执行
    1. 对于 aer.[[EventList]] 的每个 Memory 事件 event,执行
      1. event 添加到 events
  3. 返回 events

29.5.2 SharedDataBlockEventSet ( execution )

The abstract operation SharedDataBlockEventSet takes argument execution (一个候选执行) and returns 共享数据块事件的 Set. It performs the following steps when called:

  1. events 为一个空 Set。
  2. 对于 EventSet(execution) 的每个 Memory 事件 event,执行
    1. 如果 event共享数据块事件,将 event 添加到 events
  3. 返回 events

29.5.3 HostEventSet ( execution )

The abstract operation HostEventSet takes argument execution (一个候选执行) and returns Memory 事件的 Set. It performs the following steps when called:

  1. 返回一个新的 Set,包含 EventSet(execution) 中所有不在 SharedDataBlockEventSet(execution) 中的元素。

29.5.4 ComposeWriteEventBytes ( execution, byteIndex, writes )

The abstract operation ComposeWriteEventBytes takes arguments execution (一个候选执行), byteIndex (一个非负整数), and writes (WriteSharedMemory 或 ReadModifyWriteSharedMemory 事件的 List) and returns 字节值List. It performs the following steps when called:

  1. byteLocationbyteIndex
  2. bytesRead 为一个新的空 List
  3. 对于 writes 的每个元素 writeEvent,执行
    1. 断言:writeEvent内存范围中含有 byteLocation
    2. payloadIndexbyteLocation - writeEvent.[[ByteIndex]]
    3. 如果 writeEvent 是 WriteSharedMemory 事件,则
      1. bytewriteEvent.[[Payload]][payloadIndex]。
    4. 否则,
      1. 断言:writeEvent 是 ReadModifyWriteSharedMemory 事件。
      2. bytesValueOfReadEvent(execution, writeEvent)。
      3. bytesModifiedwriteEvent.[[ModifyOp]](bytes, writeEvent.[[Payload]])。
      4. bytebytesModified[payloadIndex]。
    5. byte 追加到 bytesRead
    6. byteLocation 设为 byteLocation + 1。
  4. 返回 bytesRead
Note 1

读-改-写修改 [[ModifyOp]] 由 Atomics 对象上引入 ReadModifyWriteSharedMemory 事件的函数属性给出。

Note 2

抽象操作写事件List 组合成字节值List。它用于 ReadSharedMemory 和 ReadModifyWriteSharedMemory 事件的事件语义。

29.5.5 ValueOfReadEvent ( execution, readEvent )

The abstract operation ValueOfReadEvent takes arguments execution (一个候选执行) and readEvent (一个 ReadSharedMemory 或 ReadModifyWriteSharedMemory 事件) and returns 字节值List. It performs the following steps when called:

  1. writesexecutionreads-bytes-from(readEvent)。
  2. 断言:writes 是 WriteSharedMemory 或 ReadModifyWriteSharedMemory 事件的 List,其长度等于 readEvent.[[ElementSize]]
  3. 返回 ComposeWriteEventBytes(execution, readEvent.[[ByteIndex]], writes)。

29.6 候选执行的关系

以下关系和数学函数以某个特定候选执行为参数,并对其 Memory 事件进行排序。

29.6.1 is-agent-order-before

对于候选执行 execution,其 is-agent-order-before 关系是满足以下条件的 Memory 事件上的最小关系。

  • 对于事件 eventAeventB,如果在 execution.[[EventsRecords]] 中存在某个 Agent Events Record aer,使得 aer.[[EventList]] 同时包含 eventAeventB,且 eventAaer.[[EventList]]List 顺序中位于 eventB 之前,则 eventAexecution 中 is-agent-order-before eventB
Note

每个 agent 在求值期间以每 agent 严格全序引入事件。这是这些严格全序的并集。

29.6.2 reads-bytes-from

对于候选执行 execution,其 reads-bytes-from 函数是一个数学函数,它将 SharedDataBlockEventSet(execution) 中的 Memory 事件映射到 SharedDataBlockEventSet(execution) 中事件的 List,并满足以下条件。

  • 对于 SharedDataBlockEventSet(execution) 中的每个 ReadSharedMemory 或 ReadModifyWriteSharedMemory 事件 readEventexecution 中的 reads-bytes-from(readEvent) 是一个长度为 readEvent.[[ElementSize]]List,其元素是 WriteSharedMemory 或 ReadModifyWriteSharedMemory 事件 writes,且满足以下全部条件。

    • writes 中索引为 i 的每个事件 writeEvent内存范围中都含有 readEvent.[[ByteIndex]] + i
    • result 不在 writes 中。

候选执行总是允许一个 reads-bytes-from 函数。

29.6.3 reads-from

对于候选执行 execution,其 reads-from 关系是满足以下条件的 Memory 事件上的最小关系。

  • 对于事件 readEventwriteEvent,如果 SharedDataBlockEventSet(execution) 同时包含 readEventwriteEvent,并且 execution 中的 reads-bytes-from(readEvent) 包含 writeEvent,则 readEventexecution 中 reads-from writeEvent

29.6.4 host-synchronizes-with

对于候选执行 execution,其 host-synchronizes-with 关系是宿主提供的宿主特定 Memory 事件上的严格偏序,至少满足以下条件。

  • 如果 eventAexecution 中 host-synchronizes-with eventB,则 HostEventSet(execution) 包含 eventAeventB
  • execution 中,host-synchronizes-with 和 is-agent-order-before 的并集中不存在环。
Note 1

对于候选执行 execution 中的两个宿主特定事件 eventAeventBeventAexecution 中 host-synchronizes-with eventB 蕴含 eventAexecutionhappens-before eventB

Note 2

此关系允许宿主提供额外的同步机制,例如 HTML worker 之间的 postMessage

29.6.5 synchronizes-with

对于候选执行 execution,其 synchronizes-with 关系是满足以下条件的 Memory 事件上的最小关系。

  • 对于事件 readEventwriteEvent,如果 readEventexecutionreads-from writeEventreadEvent.[[Order]]seq-cstwriteEvent.[[Order]]seq-cst,并且 readEventwriteEvent 具有相等的内存范围,则 writeEventexecution 中 synchronizes-with readEvent
  • 对于 execution.[[EventsRecords]] 的每个元素 eventsRecord,以下为真。
    • 对于事件 eventAeventB,如果 eventsRecord.[[AgentSynchronizesWith]] 包含 (eventA, eventB),则 eventAexecution 中 synchronizes-with eventB
  • 对于事件 eventAeventB,如果 execution.[[HostSynchronizesWith]] 包含 (eventA, eventB),则 eventAexecution 中 synchronizes-with eventB
Note 1

由于内存模型文献中的惯例,在候选执行 execution 中,写事件 synchronizes-with 读事件,而不是读事件 synchronizes-with 写事件

Note 2

候选执行 execution 中,init 事件不参与此关系,而是由 happens-before 直接约束。

Note 3

候选执行 execution 中,并非所有通过 reads-from 相关的 seq-cst 事件都通过 synchronizes-with 相关。只有还具有相等内存范围的事件才通过 synchronizes-with 相关。

Note 4

对于候选执行 execution 中的共享数据块事件 readEventwriteEvent,如果 writeEvent synchronizes-with readEvent,则 readEvent 可以 reads-fromwriteEvent 以外的其他写事件

29.6.6 happens-before

对于候选执行 execution,其 happens-before 关系是满足以下条件的 Memory 事件上的最小关系。

  • 对于事件 eventAeventB,如果以下任一条件为真,则 eventAexecution 中 happens-before eventB

    • eventAexecutionis-agent-order-before eventB
    • eventAexecutionsynchronizes-with eventB
    • SharedDataBlockEventSet(execution) 同时包含 eventAeventBeventA.[[Order]]init,并且 eventAeventB 具有重叠的内存范围
    • 存在事件 eventC,使得 eventAexecution 中 happens-before eventC,且 eventCexecution 中 happens-before eventB
Note

因为 happens-before 是 agent-order 的超集,所以候选执行与 ECMAScript 的单线程求值语义一致。

29.7 有效执行的属性

29.7.1 有效的选择读

如果以下算法返回 true,则候选执行 execution 具有有效的选择读。

  1. 对于 SharedDataBlockEventSet(execution) 的每个 ReadSharedMemory 或 ReadModifyWriteSharedMemory 事件 readEvent,执行
    1. chosenValueRecordexecution.[[ChosenValues]] 中其 [[Event]] 字段为 readEvent 的元素。
    2. chosenValuechosenValueRecord.[[ChosenValue]]
    3. readValueValueOfReadEvent(execution, readEvent)。
    4. chosenLenchosenValue 中元素的数量。
    5. readLenreadValue 中元素的数量。
    6. 如果 chosenLenreadLen,则
      1. 返回 false
    7. 如果对于从 0(包含)到 chosenLen(不包含)区间内的某个整数 ichosenValue[i] ≠ readValue[i],则
      1. 返回 false
  2. 返回 true

29.7.2 一致读

如果以下算法返回 true,则候选执行 execution 具有一致读。

  1. 对于 SharedDataBlockEventSet(execution) 的每个 ReadSharedMemory 或 ReadModifyWriteSharedMemory 事件 readEvent,执行
    1. writesexecutionreads-bytes-from(readEvent)。
    2. byteLocationreadEvent.[[ByteIndex]]
    3. 对于 writes 的每个元素 writeEvent,执行
      1. 如果 readEventexecutionhappens-before writeEvent,则
        1. 返回 false
      2. 如果存在某个 WriteSharedMemory 或 ReadModifyWriteSharedMemory 事件 value,其内存范围中含有 byteLocation,且 writeEventexecutionhappens-before value,并且 valueexecutionhappens-before readEvent,则
        1. 返回 false
      3. byteLocation 设为 byteLocation + 1。
  2. 返回 true

29.7.3 无撕裂读

如果以下算法返回 true,则候选执行 execution 具有无撕裂读。

  1. 对于 SharedDataBlockEventSet(execution) 的每个 ReadSharedMemory 或 ReadModifyWriteSharedMemory 事件 readEvent,执行
    1. 如果 readEvent.[[NoTear]]true,则
      1. 断言:readEvent.[[ByteIndex]] 除以 readEvent.[[ElementSize]] 的余数为 0。
      2. 对于每个 Memory 事件 writeEvent,若 readEventexecutionreads-from writeEventwriteEvent.[[NoTear]]true,执行
        1. 如果 readEventwriteEvent 具有相等的内存范围,并且存在某个 Memory 事件 value,使得 valuewriteEvent 具有相等的内存范围value.[[NoTear]]truewriteEventvalue 不是同一个共享数据块事件,并且 readEventexecutionreads-from value,则
          1. 返回 false
  2. 返回 true
Note

共享数据块事件是通过访问整数 TypedArray 引入时,该事件的 [[NoTear]] 字段为 true;当通过访问浮点 TypedArray 或 DataView 引入时为 false

直观地说,此要求表示:当内存范围通过整数 TypedArray 以对齐方式访问时,在与其他具有相等范围的写事件发生数据竞争时,该范围上的单个写事件必须“获胜”。更准确地说,此要求表示,一个对齐的读事件不能读取由多个不同写事件的字节组成的值,而这些写事件都具有相等范围。不过,对齐的读事件可以从多个具有重叠范围的写事件读取。

29.7.4 顺序一致原子

对于候选执行 executionis-memory-order-beforeEventSet(execution) 中所有 Memory 事件严格全序,并满足以下条件。

  • 对于事件 eventAeventB,如果 eventAexecutionhappens-before eventB,则 eventAexecution 中 is-memory-order-before eventB
  • 对于事件 readEventwriteEvent,若 readEventexecutionreads-from writeEvent,则不存在 SharedDataBlockEventSet(execution) 中的 WriteSharedMemory 或 ReadModifyWriteSharedMemory 事件 value,使得 value.[[Order]]seq-cstwriteEventexecution 中 is-memory-order-before valuevalueexecution 中 is-memory-order-before readEvent,并且以下任一条件为真。

    Note 1

    此条款额外约束相等内存范围上的 seq-cst 事件。

  • 对于 SharedDataBlockEventSet(execution) 中的每个 WriteSharedMemory 或 ReadModifyWriteSharedMemory 事件 writeEvent,如果 writeEvent.[[Order]]seq-cst,则不存在无限多个 SharedDataBlockEventSet(execution) 中具有相等内存范围的 ReadSharedMemory 或 ReadModifyWriteSharedMemory 事件,它们在 memory-order 中位于 writeEvent 之前。

    Note 2

    此条款与 agent 的前进进度保证一起,确保 seq-cst 有限时间内对具有相等内存范围seq-cst 可见这一活性条件。

如果候选执行允许一个 is-memory-order-before 关系,则该候选执行具有顺序一致原子。

Note 3

虽然 is-memory-order-before 包含 EventSet(execution) 中的所有事件,但 execution 中未受 happens-beforesynchronizes-with 约束的事件允许出现在该顺序中的任意位置。

29.7.5 有效执行

如果以下全部为真,则候选执行 execution 是一个有效执行(或简称执行)。

所有程序都至少有一个有效执行。

29.8 竞争

对于执行 execution 以及包含在 SharedDataBlockEventSet(execution) 中的事件 eventAeventB,如果以下算法返回 true,则 eventAeventB 处于竞争中。

  1. 如果 eventAeventB 不是同一个共享数据块事件,则
    1. 如果并非 eventAexecutionhappens-before eventBeventBexecutionhappens-before eventA,则
      1. 如果 eventA 是 WriteSharedMemory 或 ReadModifyWriteSharedMemory 事件,eventB 是 WriteSharedMemory 或 ReadModifyWriteSharedMemory 事件,并且 eventAeventB内存范围并非互不相交,则
        1. 返回 true
      2. 如果 eventAexecutionreads-from eventB,或 eventBexecutionreads-from eventA,则
        1. 返回 true
  2. 返回 false

29.9 数据竞争

对于执行 execution 以及包含在 SharedDataBlockEventSet(execution) 中的事件 eventAeventB,如果以下算法返回 true,则 eventAeventB 处于数据竞争中。

  1. 如果 eventAeventBexecution 中处于竞争中,则
    1. 如果 eventA.[[Order]] 不是 seq-csteventB.[[Order]] 不是 seq-cst,则
      1. 返回 true
    2. 如果 eventAeventB 具有重叠的内存范围,则
      1. 返回 true
  2. 返回 false

29.10 无数据竞争

如果在 SharedDataBlockEventSet(execution) 中不存在两个事件处于数据竞争中,则执行 execution无数据竞争的。

如果一个程序的所有执行都是无数据竞争的,则该程序是无数据竞争的。

内存模型保证无数据竞争程序的所有事件具有顺序一致性。

29.11 共享内存指南

Note 1

以下是面向使用共享内存的 ECMAScript 程序员的指南。

我们建议程序保持无数据竞争,即,使得同一内存位置上不可能存在并发的非原子操作。无数据竞争程序具有交错语义,其中每个 agent 的求值语义中的每一步都彼此交错。对于无数据竞争程序,无需理解内存模型的细节。这些细节不太可能建立有助于更好编写 ECMAScript 的直觉。

更一般地,即使程序不是无数据竞争的,只要原子操作不涉及任何数据竞争,并且发生竞争的操作都具有相同的访问大小,它仍可能具有可预测的行为。安排原子操作不涉及竞争的最简单方式,是确保原子操作和非原子操作使用不同的内存单元,并且不同大小的原子访问不会同时访问相同单元。实际上,程序应尽可能将共享内存视为强类型的。人们仍然不能依赖发生竞争的非原子访问的排序和时机,但如果内存被视为强类型,那么竞争访问不会“撕裂”(其值的位不会被混合)。

Note 2

以下是面向为使用共享内存的程序编写编译器变换的 ECMAScript 实现者的指南。

理想情况下,应允许大多数在单 agent 设置中有效的程序变换在多 agent 设置中同样有效,以确保多 agent 程序中每个 agent 的性能与单 agent 设置中的性能一样好。这些变换往往难以判断。我们概述了一些关于程序变换的规则,这些规则旨在被视为规范性的(因为它们由内存模型蕴含,或强于内存模型所蕴含的内容),但很可能并不穷尽。这些规则旨在适用于发生在构成 is-agent-order-before 关系的 Memory 事件被引入之前的程序变换。

agent-order 切片为与单个 agent 相关的 is-agent-order-before 关系的子集。

读事件可能读取值为该事件在所有有效执行中 ValueOfReadEvent 的所有值的集合。

在没有共享内存时有效的任何 agent-order 切片变换,在存在共享内存时也是有效的,但有以下例外。

  • Atomics 被刻在石头上:程序变换不得导致任何 [[Order]]seq-cst共享数据块事件is-agent-order-before 关系中移除,也不得导致它们彼此重排序,或在 agent-order 切片内相对于 [[Order]]unordered 的事件重排序。

    (实践中,对重排序的禁止迫使编译器假定每个 seq-cst 操作都是一个同步,并包含在最终的 is-memory-order-before 关系中;在缺少跨 agent 程序分析的情况下,编译器通常无论如何都必须这样假定。它还迫使编译器假定每个其对 memory-order 影响未知的被调用方调用都可能包含 seq-cst 操作。)

  • 读必须稳定:任何给定的共享内存读取在一次执行中必须只观察到一个值。

    (例如,如果程序中语义上的单次读取被执行了多次,那么随后程序只允许观察到读取到的值之一。一种称为重物化的变换可能违反此规则。)

  • 写必须稳定:所有对共享内存的可观察写都必须来自一次执行中的程序语义。

    (例如,变换不得引入某些可观察写,例如通过在更大的位置上使用读-改-写操作来写入更小的数据、向内存写入程序不可能写入的值,或将刚读到的值写回其读取位置,如果该位置可能在读取后已被另一个 agent 覆写。)

  • 可能读取值必须非空:程序变换不能导致共享内存读取的可能读取值变为空。

    (反直觉的是,此规则实际上限制了对写的变换,因为写在内存模型中之所以有作用,是因为可被读事件读取。例如,写可以在两个 seq-cst 操作之间被移动、合并,有时也可以重排序,但变换不得移除更新某个位置的每一个写;必须保留某个写。)

仍然有效的变换例子包括:合并来自同一位置的多个非原子读、重排序非原子读、引入推测性非原子读、合并到同一位置的多个非原子写、重排序到不同位置的非原子写,以及将非原子读提升出循环,即使这会影响终止性。注意,一般来说,别名化的 TypedArray 会使证明位置不同变得困难。

Note 3

以下是面向为共享内存访问生成机器代码的 ECMAScript 实现者的指南。

对于内存模型不弱于 ARM 或 Power 的架构,非原子存储和加载可以被编译为目标架构上的裸存储和裸加载。原子存储和加载可以被编译为保证顺序一致性的指令。如果不存在这样的指令,则要使用内存屏障,例如在裸存储或裸加载的两侧放置屏障。读-改-写操作可以被编译为目标架构上的读-改-写指令,例如 x86 上带 LOCK 前缀的指令、ARM 上的 load-exclusive/store-exclusive 指令,以及 Power 上的 load-link/store-conditional 指令。

具体而言,内存模型旨在允许如下代码生成。

  • 程序中的每个原子操作都被假定为必要的。
  • 原子操作永远不会彼此重排,也不会与非原子操作重排。
  • 函数始终被假定会执行原子操作。
  • 原子操作永远不会作为更大数据上的读-改-写操作来实现;如果平台没有适当大小的原子操作,则作为非无锁原子来实现。(我们已经假定每个平台都具有每种有意义大小的普通内存访问操作。)

朴素代码生成使用以下模式:

  • 常规加载和存储编译为单条加载和存储指令。
  • 无锁原子加载和存储编译为一个完整(顺序一致)栅栏、一个常规加载或存储,以及一个完整栅栏。
  • 无锁原子读-改-写访问编译为一个完整栅栏、一个原子读-改-写指令序列,以及一个完整栅栏。
  • 非无锁原子编译为一次自旋锁获取、一个完整栅栏、一系列非原子加载和存储指令、一个完整栅栏,以及一次自旋锁释放。

只要某个内存范围上的原子操作不与非原子写或不同大小的原子操作竞争,该映射就是正确的。不过,这就是我们所需要的一切:内存模型实际上会将涉及竞争的原子操作降级为非原子状态。另一方面,朴素映射相当强:它允许原子操作被用作顺序一致栅栏,而内存模型实际上并不保证这一点。

在这些基本模式上的局部改进也是允许的,但须受内存模型约束。例如:

  • 存在显而易见的平台相关改进,可以移除冗余栅栏。例如,在 x86 上,围绕无锁原子加载和存储的栅栏总是可以省略,除了存储之后的栅栏;并且无锁读-改-写指令不需要栅栏,因为这些都使用带 LOCK 前缀的指令。在许多平台上有多种强度的栅栏,在某些上下文中可以使用较弱的栅栏而不破坏顺序一致性。
  • 大多数现代平台支持 ECMAScript 原子所需的所有数据大小的无锁原子。如果需要非无锁原子,围绕原子操作主体的栅栏通常可以折叠到加锁和解锁步骤中。非无锁原子的最简单解决方案是为每个 SharedArrayBuffer 设置一个单独的锁字。
  • 还有更复杂的平台相关局部改进,需要一些代码分析。例如,两个背靠背的栅栏通常与单个栅栏具有相同效果,因此如果为连续两个原子操作生成代码,只需一个栅栏将它们分开。在 x86 上,即使分隔原子存储的单个栅栏也可以省略,因为存储后的栅栏只需要用于将该存储与后续加载分开。

Annex A (informative) 语法摘要

A.1 词法语法

SourceCharacter :: 任意 Unicode 码点 InputElementDiv :: WhiteSpace LineTerminator Comment CommonToken DivPunctuator RightBracePunctuator InputElementRegExp :: WhiteSpace LineTerminator Comment CommonToken RightBracePunctuator RegularExpressionLiteral InputElementRegExpOrTemplateTail :: WhiteSpace LineTerminator Comment CommonToken RegularExpressionLiteral TemplateSubstitutionTail InputElementTemplateTail :: WhiteSpace LineTerminator Comment CommonToken DivPunctuator TemplateSubstitutionTail InputElementHashbangOrRegExp :: WhiteSpace LineTerminator Comment CommonToken HashbangComment RegularExpressionLiteral WhiteSpace :: <TAB> <VT> <FF> <ZWNBSP> <USP> LineTerminator :: <LF> <CR> <LS> <PS> LineTerminatorSequence :: <LF> <CR> [lookahead ≠ <LF>] <LS> <PS> <CR> <LF> Comment :: MultiLineComment SingleLineComment MultiLineComment :: /* MultiLineCommentCharsopt */ MultiLineCommentChars :: MultiLineNotAsteriskChar MultiLineCommentCharsopt * PostAsteriskCommentCharsopt PostAsteriskCommentChars :: MultiLineNotForwardSlashOrAsteriskChar MultiLineCommentCharsopt * PostAsteriskCommentCharsopt MultiLineNotAsteriskChar :: SourceCharacter but not * MultiLineNotForwardSlashOrAsteriskChar :: SourceCharacter but not one of / or * SingleLineComment :: // SingleLineCommentCharsopt SingleLineCommentChars :: SingleLineCommentChar SingleLineCommentCharsopt SingleLineCommentChar :: SourceCharacter but not LineTerminator HashbangComment :: #! SingleLineCommentCharsopt CommonToken :: IdentifierName PrivateIdentifier Punctuator NumericLiteral StringLiteral Template PrivateIdentifier :: # IdentifierName IdentifierName :: IdentifierStart IdentifierName IdentifierPart IdentifierStart :: IdentifierStartChar \ UnicodeEscapeSequence IdentifierPart :: IdentifierPartChar \ UnicodeEscapeSequence IdentifierStartChar :: UnicodeIDStart $ _ IdentifierPartChar :: UnicodeIDContinue $ AsciiLetter :: one of a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z UnicodeIDStart :: 任何具有 Unicode 属性 “ID_Start” 的 Unicode 码点 UnicodeIDContinue :: 任何具有 Unicode 属性 “ID_Continue” 的 Unicode 码点 ReservedWord :: one of await break case catch class const continue debugger default delete do else enum export extends false finally for function if import in instanceof new null return super switch this throw true try typeof var void while with yield Punctuator :: OptionalChainingPunctuator OtherPunctuator OptionalChainingPunctuator :: ?. [lookahead ∉ DecimalDigit] OtherPunctuator :: one of { ( ) [ ] . ... ; , < > <= >= == != === !== + - * % ** ++ -- << >> >>> & | ^ ! ~ && || ?? ? : = += -= *= %= **= <<= >>= >>>= &= |= ^= &&= ||= ??= => DivPunctuator :: / /= RightBracePunctuator :: } NullLiteral :: null BooleanLiteral :: true false NumericLiteralSeparator :: _ NumericLiteral :: DecimalLiteral DecimalBigIntegerLiteral NonDecimalIntegerLiteral[+Sep] NonDecimalIntegerLiteral[+Sep] BigIntLiteralSuffix LegacyOctalIntegerLiteral DecimalBigIntegerLiteral :: 0 BigIntLiteralSuffix NonZeroDigit DecimalDigits[+Sep]opt BigIntLiteralSuffix NonZeroDigit NumericLiteralSeparator DecimalDigits[+Sep] BigIntLiteralSuffix NonDecimalIntegerLiteral[Sep] :: BinaryIntegerLiteral[?Sep] OctalIntegerLiteral[?Sep] HexIntegerLiteral[?Sep] BigIntLiteralSuffix :: n DecimalLiteral :: DecimalIntegerLiteral . DecimalDigits[+Sep]opt ExponentPart[+Sep]opt . DecimalDigits[+Sep] ExponentPart[+Sep]opt DecimalIntegerLiteral ExponentPart[+Sep]opt DecimalIntegerLiteral :: 0 NonZeroDigit NonZeroDigit NumericLiteralSeparatoropt DecimalDigits[+Sep] NonOctalDecimalIntegerLiteral DecimalDigits[Sep] :: DecimalDigit DecimalDigits[?Sep] DecimalDigit [+Sep] DecimalDigits[+Sep] NumericLiteralSeparator DecimalDigit DecimalDigit :: one of 0 1 2 3 4 5 6 7 8 9 NonZeroDigit :: one of 1 2 3 4 5 6 7 8 9 ExponentPart[Sep] :: ExponentIndicator SignedInteger[?Sep] ExponentIndicator :: one of e E SignedInteger[Sep] :: DecimalDigits[?Sep] + DecimalDigits[?Sep] - DecimalDigits[?Sep] BinaryIntegerLiteral[Sep] :: 0b BinaryDigits[?Sep] 0B BinaryDigits[?Sep] BinaryDigits[Sep] :: BinaryDigit BinaryDigits[?Sep] BinaryDigit [+Sep] BinaryDigits[+Sep] NumericLiteralSeparator BinaryDigit BinaryDigit :: one of 0 1 OctalIntegerLiteral[Sep] :: 0o OctalDigits[?Sep] 0O OctalDigits[?Sep] OctalDigits[Sep] :: OctalDigit OctalDigits[?Sep] OctalDigit [+Sep] OctalDigits[+Sep] NumericLiteralSeparator OctalDigit LegacyOctalIntegerLiteral :: 0 OctalDigit LegacyOctalIntegerLiteral OctalDigit NonOctalDecimalIntegerLiteral :: 0 NonOctalDigit LegacyOctalLikeDecimalIntegerLiteral NonOctalDigit NonOctalDecimalIntegerLiteral DecimalDigit LegacyOctalLikeDecimalIntegerLiteral :: 0 OctalDigit LegacyOctalLikeDecimalIntegerLiteral OctalDigit OctalDigit :: one of 0 1 2 3 4 5 6 7 NonOctalDigit :: one of 8 9 HexIntegerLiteral[Sep] :: 0x HexDigits[?Sep] 0X HexDigits[?Sep] HexDigits[Sep] :: HexDigit HexDigits[?Sep] HexDigit [+Sep] HexDigits[+Sep] NumericLiteralSeparator HexDigit HexDigit :: one of 0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F StringLiteral :: " DoubleStringCharactersopt " ' SingleStringCharactersopt ' DoubleStringCharacters :: DoubleStringCharacter DoubleStringCharactersopt SingleStringCharacters :: SingleStringCharacter SingleStringCharactersopt DoubleStringCharacter :: SourceCharacter but not one of " or \ or LineTerminator <LS> <PS> \ EscapeSequence LineContinuation SingleStringCharacter :: SourceCharacter but not one of ' or \ or LineTerminator <LS> <PS> \ EscapeSequence LineContinuation LineContinuation :: \ LineTerminatorSequence EscapeSequence :: CharacterEscapeSequence 0 [lookahead ∉ DecimalDigit] LegacyOctalEscapeSequence NonOctalDecimalEscapeSequence HexEscapeSequence UnicodeEscapeSequence CharacterEscapeSequence :: SingleEscapeCharacter NonEscapeCharacter SingleEscapeCharacter :: one of ' " \ b f n r t v NonEscapeCharacter :: SourceCharacter but not one of EscapeCharacter or LineTerminator EscapeCharacter :: SingleEscapeCharacter DecimalDigit x u LegacyOctalEscapeSequence :: 0 [lookahead ∈ { 8, 9 }] NonZeroOctalDigit [lookahead ∉ OctalDigit] ZeroToThree OctalDigit [lookahead ∉ OctalDigit] FourToSeven OctalDigit ZeroToThree OctalDigit OctalDigit NonZeroOctalDigit :: OctalDigit but not 0 ZeroToThree :: one of 0 1 2 3 FourToSeven :: one of 4 5 6 7 NonOctalDecimalEscapeSequence :: one of 8 9 HexEscapeSequence :: x HexDigit HexDigit UnicodeEscapeSequence :: u Hex4Digits u{ CodePoint } Hex4Digits :: HexDigit HexDigit HexDigit HexDigit RegularExpressionLiteral :: / RegularExpressionBody / RegularExpressionFlags RegularExpressionBody :: RegularExpressionFirstChar RegularExpressionChars RegularExpressionChars :: [empty] RegularExpressionChars RegularExpressionChar RegularExpressionFirstChar :: RegularExpressionNonTerminator but not one of * or \ or / or [ RegularExpressionBackslashSequence RegularExpressionClass RegularExpressionChar :: RegularExpressionNonTerminator but not one of \ or / or [ RegularExpressionBackslashSequence RegularExpressionClass RegularExpressionBackslashSequence :: \ RegularExpressionNonTerminator RegularExpressionNonTerminator :: SourceCharacter but not LineTerminator RegularExpressionClass :: [ RegularExpressionClassChars ] RegularExpressionClassChars :: [empty] RegularExpressionClassChars RegularExpressionClassChar RegularExpressionClassChar :: RegularExpressionNonTerminator but not one of ] or \ RegularExpressionBackslashSequence RegularExpressionFlags :: [empty] RegularExpressionFlags IdentifierPartChar Template :: NoSubstitutionTemplate TemplateHead NoSubstitutionTemplate :: ` TemplateCharactersopt ` TemplateHead :: ` TemplateCharactersopt ${ TemplateSubstitutionTail :: TemplateMiddle TemplateTail TemplateMiddle :: } TemplateCharactersopt ${ TemplateTail :: } TemplateCharactersopt ` TemplateCharacters :: TemplateCharacter TemplateCharactersopt TemplateCharacter :: $ [lookahead ≠ {] \ TemplateEscapeSequence \ NotEscapeSequence LineContinuation LineTerminatorSequence SourceCharacter but not one of ` or \ or $ or LineTerminator TemplateEscapeSequence :: CharacterEscapeSequence 0 [lookahead ∉ DecimalDigit] HexEscapeSequence UnicodeEscapeSequence NotEscapeSequence :: 0 DecimalDigit DecimalDigit but not 0 x [lookahead ∉ HexDigit] x HexDigit [lookahead ∉ HexDigit] u [lookahead ∉ HexDigit] [lookahead ≠ {] u HexDigit [lookahead ∉ HexDigit] u HexDigit HexDigit [lookahead ∉ HexDigit] u HexDigit HexDigit HexDigit [lookahead ∉ HexDigit] u { [lookahead ∉ HexDigit] u { NotCodePoint [lookahead ∉ HexDigit] u { CodePoint [lookahead ∉ HexDigit] [lookahead ≠ }] NotCodePoint :: HexDigits[~Sep] but only if the MV of HexDigits > 0x10FFFF CodePoint :: HexDigits[~Sep] but only if the MV of HexDigits ≤ 0x10FFFF

A.2 表达式

IdentifierReference[Yield, Await] : Identifier [~Yield] yield [~Await] await BindingIdentifier[Yield, Await] : Identifier yield await LabelIdentifier[Yield, Await] : Identifier [~Yield] yield [~Await] await Identifier : IdentifierName but not ReservedWord PrimaryExpression[Yield, Await] : this IdentifierReference[?Yield, ?Await] Literal ArrayLiteral[?Yield, ?Await] ObjectLiteral[?Yield, ?Await] FunctionExpression ClassExpression[?Yield, ?Await] GeneratorExpression AsyncFunctionExpression AsyncGeneratorExpression RegularExpressionLiteral TemplateLiteral[?Yield, ?Await, ~Tagged] CoverParenthesizedExpressionAndArrowParameterList[?Yield, ?Await] CoverParenthesizedExpressionAndArrowParameterList[Yield, Await] : ( Expression[+In, ?Yield, ?Await] ) ( Expression[+In, ?Yield, ?Await] , ) ( ) ( ... BindingIdentifier[?Yield, ?Await] ) ( ... BindingPattern[?Yield, ?Await] ) ( Expression[+In, ?Yield, ?Await] , ... BindingIdentifier[?Yield, ?Await] ) ( Expression[+In, ?Yield, ?Await] , ... BindingPattern[?Yield, ?Await] )

当处理产生式的一个实例
PrimaryExpression[Yield, Await] : CoverParenthesizedExpressionAndArrowParameterList[?Yield, ?Await]
时,使用以下语法来细化 CoverParenthesizedExpressionAndArrowParameterList 的解释:

ParenthesizedExpression[Yield, Await] : ( Expression[+In, ?Yield, ?Await] )

 

Literal : NullLiteral BooleanLiteral NumericLiteral StringLiteral ArrayLiteral[Yield, Await] : [ Elisionopt ] [ ElementList[?Yield, ?Await] ] [ ElementList[?Yield, ?Await] , Elisionopt ] ElementList[Yield, Await] : Elisionopt AssignmentExpression[+In, ?Yield, ?Await] Elisionopt SpreadElement[?Yield, ?Await] ElementList[?Yield, ?Await] , Elisionopt AssignmentExpression[+In, ?Yield, ?Await] ElementList[?Yield, ?Await] , Elisionopt SpreadElement[?Yield, ?Await] Elision : , Elision , SpreadElement[Yield, Await] : ... AssignmentExpression[+In, ?Yield, ?Await] ObjectLiteral[Yield, Await] : { } { PropertyDefinitionList[?Yield, ?Await] } { PropertyDefinitionList[?Yield, ?Await] , } PropertyDefinitionList[Yield, Await] : PropertyDefinition[?Yield, ?Await] PropertyDefinitionList[?Yield, ?Await] , PropertyDefinition[?Yield, ?Await] PropertyDefinition[Yield, Await] : IdentifierReference[?Yield, ?Await] CoverInitializedName[?Yield, ?Await] PropertyName[?Yield, ?Await] : AssignmentExpression[+In, ?Yield, ?Await] MethodDefinition[?Yield, ?Await] ... AssignmentExpression[+In, ?Yield, ?Await] PropertyName[Yield, Await] : LiteralPropertyName ComputedPropertyName[?Yield, ?Await] LiteralPropertyName : IdentifierName StringLiteral NumericLiteral ComputedPropertyName[Yield, Await] : [ AssignmentExpression[+In, ?Yield, ?Await] ] CoverInitializedName[Yield, Await] : IdentifierReference[?Yield, ?Await] Initializer[+In, ?Yield, ?Await] Initializer[In, Yield, Await] : = AssignmentExpression[?In, ?Yield, ?Await] TemplateLiteral[Yield, Await, Tagged] : NoSubstitutionTemplate SubstitutionTemplate[?Yield, ?Await, ?Tagged] SubstitutionTemplate[Yield, Await, Tagged] : TemplateHead Expression[+In, ?Yield, ?Await] TemplateSpans[?Yield, ?Await, ?Tagged] TemplateSpans[Yield, Await, Tagged] : TemplateTail TemplateMiddleList[?Yield, ?Await, ?Tagged] TemplateTail TemplateMiddleList[Yield, Await, Tagged] : TemplateMiddle Expression[+In, ?Yield, ?Await] TemplateMiddleList[?Yield, ?Await, ?Tagged] TemplateMiddle Expression[+In, ?Yield, ?Await] MemberExpression[Yield, Await] : PrimaryExpression[?Yield, ?Await] MemberExpression[?Yield, ?Await] [ Expression[+In, ?Yield, ?Await] ] MemberExpression[?Yield, ?Await] . IdentifierName MemberExpression[?Yield, ?Await] TemplateLiteral[?Yield, ?Await, +Tagged] SuperProperty[?Yield, ?Await] MetaProperty new MemberExpression[?Yield, ?Await] Arguments[?Yield, ?Await] MemberExpression[?Yield, ?Await] . PrivateIdentifier SuperProperty[Yield, Await] : super [ Expression[+In, ?Yield, ?Await] ] super . IdentifierName MetaProperty : NewTarget ImportMeta NewTarget : new . target ImportMeta : import . meta NewExpression[Yield, Await] : MemberExpression[?Yield, ?Await] new NewExpression[?Yield, ?Await] CallExpression[Yield, Await] : CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await] SuperCall[?Yield, ?Await] ImportCall[?Yield, ?Await] CallExpression[?Yield, ?Await] Arguments[?Yield, ?Await] CallExpression[?Yield, ?Await] [ Expression[+In, ?Yield, ?Await] ] CallExpression[?Yield, ?Await] . IdentifierName CallExpression[?Yield, ?Await] TemplateLiteral[?Yield, ?Await, +Tagged] CallExpression[?Yield, ?Await] . PrivateIdentifier

当处理产生式的一个实例
CallExpression[Yield, Await] : CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await]
时,使用以下语法来细化 CoverCallExpressionAndAsyncArrowHead 的解释:

CallMemberExpression[Yield, Await] : MemberExpression[?Yield, ?Await] Arguments[?Yield, ?Await]

 

SuperCall[Yield, Await] : super Arguments[?Yield, ?Await] ImportCall[Yield, Await] : import ( AssignmentExpression[+In, ?Yield, ?Await] ,opt ) import ( AssignmentExpression[+In, ?Yield, ?Await] , AssignmentExpression[+In, ?Yield, ?Await] ,opt ) Arguments[Yield, Await] : ( ) ( ArgumentList[?Yield, ?Await] ) ( ArgumentList[?Yield, ?Await] , ) ArgumentList[Yield, Await] : AssignmentExpression[+In, ?Yield, ?Await] ... AssignmentExpression[+In, ?Yield, ?Await] ArgumentList[?Yield, ?Await] , AssignmentExpression[+In, ?Yield, ?Await] ArgumentList[?Yield, ?Await] , ... AssignmentExpression[+In, ?Yield, ?Await] OptionalExpression[Yield, Await] : MemberExpression[?Yield, ?Await] OptionalChain[?Yield, ?Await] CallExpression[?Yield, ?Await] OptionalChain[?Yield, ?Await] OptionalExpression[?Yield, ?Await] OptionalChain[?Yield, ?Await] OptionalChain[Yield, Await] : ?. Arguments[?Yield, ?Await] ?. [ Expression[+In, ?Yield, ?Await] ] ?. IdentifierName ?. TemplateLiteral[?Yield, ?Await, +Tagged] ?. PrivateIdentifier OptionalChain[?Yield, ?Await] Arguments[?Yield, ?Await] OptionalChain[?Yield, ?Await] [ Expression[+In, ?Yield, ?Await] ] OptionalChain[?Yield, ?Await] . IdentifierName OptionalChain[?Yield, ?Await] TemplateLiteral[?Yield, ?Await, +Tagged] OptionalChain[?Yield, ?Await] . PrivateIdentifier LeftHandSideExpression[Yield, Await] : NewExpression[?Yield, ?Await] CallExpression[?Yield, ?Await] OptionalExpression[?Yield, ?Await] UpdateExpression[Yield, Await] : LeftHandSideExpression[?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] [no LineTerminator here] ++ LeftHandSideExpression[?Yield, ?Await] [no LineTerminator here] -- ++ UnaryExpression[?Yield, ?Await] -- UnaryExpression[?Yield, ?Await] UnaryExpression[Yield, Await] : UpdateExpression[?Yield, ?Await] delete UnaryExpression[?Yield, ?Await] void UnaryExpression[?Yield, ?Await] typeof UnaryExpression[?Yield, ?Await] + UnaryExpression[?Yield, ?Await] - UnaryExpression[?Yield, ?Await] ~ UnaryExpression[?Yield, ?Await] ! UnaryExpression[?Yield, ?Await] [+Await] AwaitExpression[?Yield] ExponentiationExpression[Yield, Await] : UnaryExpression[?Yield, ?Await] UpdateExpression[?Yield, ?Await] ** ExponentiationExpression[?Yield, ?Await] MultiplicativeExpression[Yield, Await] : ExponentiationExpression[?Yield, ?Await] MultiplicativeExpression[?Yield, ?Await] MultiplicativeOperator ExponentiationExpression[?Yield, ?Await] MultiplicativeOperator : one of * / % AdditiveExpression[Yield, Await] : MultiplicativeExpression[?Yield, ?Await] AdditiveExpression[?Yield, ?Await] + MultiplicativeExpression[?Yield, ?Await] AdditiveExpression[?Yield, ?Await] - MultiplicativeExpression[?Yield, ?Await] ShiftExpression[Yield, Await] : AdditiveExpression[?Yield, ?Await] ShiftExpression[?Yield, ?Await] << AdditiveExpression[?Yield, ?Await] ShiftExpression[?Yield, ?Await] >> AdditiveExpression[?Yield, ?Await] ShiftExpression[?Yield, ?Await] >>> AdditiveExpression[?Yield, ?Await] RelationalExpression[In, Yield, Await] : ShiftExpression[?Yield, ?Await] RelationalExpression[?In, ?Yield, ?Await] < ShiftExpression[?Yield, ?Await] RelationalExpression[?In, ?Yield, ?Await] > ShiftExpression[?Yield, ?Await] RelationalExpression[?In, ?Yield, ?Await] <= ShiftExpression[?Yield, ?Await] RelationalExpression[?In, ?Yield, ?Await] >= ShiftExpression[?Yield, ?Await] RelationalExpression[?In, ?Yield, ?Await] instanceof ShiftExpression[?Yield, ?Await] [+In] RelationalExpression[+In, ?Yield, ?Await] in ShiftExpression[?Yield, ?Await] [+In] PrivateIdentifier in ShiftExpression[?Yield, ?Await] EqualityExpression[In, Yield, Await] : RelationalExpression[?In, ?Yield, ?Await] EqualityExpression[?In, ?Yield, ?Await] == RelationalExpression[?In, ?Yield, ?Await] EqualityExpression[?In, ?Yield, ?Await] != RelationalExpression[?In, ?Yield, ?Await] EqualityExpression[?In, ?Yield, ?Await] === RelationalExpression[?In, ?Yield, ?Await] EqualityExpression[?In, ?Yield, ?Await] !== RelationalExpression[?In, ?Yield, ?Await] BitwiseANDExpression[In, Yield, Await] : EqualityExpression[?In, ?Yield, ?Await] BitwiseANDExpression[?In, ?Yield, ?Await] & EqualityExpression[?In, ?Yield, ?Await] BitwiseXORExpression[In, Yield, Await] : BitwiseANDExpression[?In, ?Yield, ?Await] BitwiseXORExpression[?In, ?Yield, ?Await] ^ BitwiseANDExpression[?In, ?Yield, ?Await] BitwiseORExpression[In, Yield, Await] : BitwiseXORExpression[?In, ?Yield, ?Await] BitwiseORExpression[?In, ?Yield, ?Await] | BitwiseXORExpression[?In, ?Yield, ?Await] LogicalANDExpression[In, Yield, Await] : BitwiseORExpression[?In, ?Yield, ?Await] LogicalANDExpression[?In, ?Yield, ?Await] && BitwiseORExpression[?In, ?Yield, ?Await] LogicalORExpression[In, Yield, Await] : LogicalANDExpression[?In, ?Yield, ?Await] LogicalORExpression[?In, ?Yield, ?Await] || LogicalANDExpression[?In, ?Yield, ?Await] CoalesceExpression[In, Yield, Await] : CoalesceExpressionHead[?In, ?Yield, ?Await] ?? BitwiseORExpression[?In, ?Yield, ?Await] CoalesceExpressionHead[In, Yield, Await] : CoalesceExpression[?In, ?Yield, ?Await] BitwiseORExpression[?In, ?Yield, ?Await] ShortCircuitExpression[In, Yield, Await] : LogicalORExpression[?In, ?Yield, ?Await] CoalesceExpression[?In, ?Yield, ?Await] ConditionalExpression[In, Yield, Await] : ShortCircuitExpression[?In, ?Yield, ?Await] ShortCircuitExpression[?In, ?Yield, ?Await] ? AssignmentExpression[+In, ?Yield, ?Await] : AssignmentExpression[?In, ?Yield, ?Await] AssignmentExpression[In, Yield, Await] : ConditionalExpression[?In, ?Yield, ?Await] [+Yield] YieldExpression[?In, ?Await] ArrowFunction[?In, ?Yield, ?Await] AsyncArrowFunction[?In, ?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] = AssignmentExpression[?In, ?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] AssignmentOperator AssignmentExpression[?In, ?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] &&= AssignmentExpression[?In, ?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] ||= AssignmentExpression[?In, ?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] ??= AssignmentExpression[?In, ?Yield, ?Await] AssignmentOperator : one of *= /= %= += -= <<= >>= >>>= &= ^= |= **=

在某些情况下,当处理产生式的一个实例
AssignmentExpression[In, Yield, Await] : LeftHandSideExpression[?Yield, ?Await] = AssignmentExpression[?In, ?Yield, ?Await]
时,使用以下语法来细化 LeftHandSideExpression 的解释:

AssignmentPattern[Yield, Await] : ObjectAssignmentPattern[?Yield, ?Await] ArrayAssignmentPattern[?Yield, ?Await] ObjectAssignmentPattern[Yield, Await] : { } { AssignmentRestProperty[?Yield, ?Await] } { AssignmentPropertyList[?Yield, ?Await] } { AssignmentPropertyList[?Yield, ?Await] , AssignmentRestProperty[?Yield, ?Await]opt } ArrayAssignmentPattern[Yield, Await] : [ Elisionopt AssignmentRestElement[?Yield, ?Await]opt ] [ AssignmentElementList[?Yield, ?Await] ] [ AssignmentElementList[?Yield, ?Await] , Elisionopt AssignmentRestElement[?Yield, ?Await]opt ] AssignmentRestProperty[Yield, Await] : ... DestructuringAssignmentTarget[?Yield, ?Await] AssignmentPropertyList[Yield, Await] : AssignmentProperty[?Yield, ?Await] AssignmentPropertyList[?Yield, ?Await] , AssignmentProperty[?Yield, ?Await] AssignmentElementList[Yield, Await] : AssignmentElisionElement[?Yield, ?Await] AssignmentElementList[?Yield, ?Await] , AssignmentElisionElement[?Yield, ?Await] AssignmentElisionElement[Yield, Await] : Elisionopt AssignmentElement[?Yield, ?Await] AssignmentProperty[Yield, Await] : IdentifierReference[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]opt PropertyName[?Yield, ?Await] : AssignmentElement[?Yield, ?Await] AssignmentElement[Yield, Await] : DestructuringAssignmentTarget[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]opt AssignmentRestElement[Yield, Await] : ... DestructuringAssignmentTarget[?Yield, ?Await] DestructuringAssignmentTarget[Yield, Await] : LeftHandSideExpression[?Yield, ?Await]

 

Expression[In, Yield, Await] : AssignmentExpression[?In, ?Yield, ?Await] Expression[?In, ?Yield, ?Await] , AssignmentExpression[?In, ?Yield, ?Await]

A.3 语句

Statement[Yield, Await, Return] : BlockStatement[?Yield, ?Await, ?Return] VariableStatement[?Yield, ?Await] EmptyStatement ExpressionStatement[?Yield, ?Await] IfStatement[?Yield, ?Await, ?Return] BreakableStatement[?Yield, ?Await, ?Return] ContinueStatement[?Yield, ?Await] BreakStatement[?Yield, ?Await] [+Return] ReturnStatement[?Yield, ?Await] WithStatement[?Yield, ?Await, ?Return] LabelledStatement[?Yield, ?Await, ?Return] ThrowStatement[?Yield, ?Await] TryStatement[?Yield, ?Await, ?Return] DebuggerStatement Declaration[Yield, Await] : HoistableDeclaration[?Yield, ?Await, ~Default] ClassDeclaration[?Yield, ?Await, ~Default] LexicalDeclaration[+In, ?Yield, ?Await] HoistableDeclaration[Yield, Await, Default] : FunctionDeclaration[?Yield, ?Await, ?Default] GeneratorDeclaration[?Yield, ?Await, ?Default] AsyncFunctionDeclaration[?Yield, ?Await, ?Default] AsyncGeneratorDeclaration[?Yield, ?Await, ?Default] BreakableStatement[Yield, Await, Return] : IterationStatement[?Yield, ?Await, ?Return] SwitchStatement[?Yield, ?Await, ?Return] BlockStatement[Yield, Await, Return] : Block[?Yield, ?Await, ?Return] Block[Yield, Await, Return] : { StatementList[?Yield, ?Await, ?Return]opt } StatementList[Yield, Await, Return] : StatementListItem[?Yield, ?Await, ?Return] StatementList[?Yield, ?Await, ?Return] StatementListItem[?Yield, ?Await, ?Return] StatementListItem[Yield, Await, Return] : Statement[?Yield, ?Await, ?Return] Declaration[?Yield, ?Await] LexicalDeclaration[In, Yield, Await] : LetOrConst BindingList[?In, ?Yield, ?Await] ; LetOrConst : let const BindingList[In, Yield, Await] : LexicalBinding[?In, ?Yield, ?Await] BindingList[?In, ?Yield, ?Await] , LexicalBinding[?In, ?Yield, ?Await] LexicalBinding[In, Yield, Await] : BindingIdentifier[?Yield, ?Await] Initializer[?In, ?Yield, ?Await]opt BindingPattern[?Yield, ?Await] Initializer[?In, ?Yield, ?Await] VariableStatement[Yield, Await] : var VariableDeclarationList[+In, ?Yield, ?Await] ; VariableDeclarationList[In, Yield, Await] : VariableDeclaration[?In, ?Yield, ?Await] VariableDeclarationList[?In, ?Yield, ?Await] , VariableDeclaration[?In, ?Yield, ?Await] VariableDeclaration[In, Yield, Await] : BindingIdentifier[?Yield, ?Await] Initializer[?In, ?Yield, ?Await]opt BindingPattern[?Yield, ?Await] Initializer[?In, ?Yield, ?Await] BindingPattern[Yield, Await] : ObjectBindingPattern[?Yield, ?Await] ArrayBindingPattern[?Yield, ?Await] ObjectBindingPattern[Yield, Await] : { } { BindingRestProperty[?Yield, ?Await] } { BindingPropertyList[?Yield, ?Await] } { BindingPropertyList[?Yield, ?Await] , BindingRestProperty[?Yield, ?Await]opt } ArrayBindingPattern[Yield, Await] : [ Elisionopt BindingRestElement[?Yield, ?Await]opt ] [ BindingElementList[?Yield, ?Await] ] [ BindingElementList[?Yield, ?Await] , Elisionopt BindingRestElement[?Yield, ?Await]opt ] BindingRestProperty[Yield, Await] : ... BindingIdentifier[?Yield, ?Await] BindingPropertyList[Yield, Await] : BindingProperty[?Yield, ?Await] BindingPropertyList[?Yield, ?Await] , BindingProperty[?Yield, ?Await] BindingElementList[Yield, Await] : BindingElisionElement[?Yield, ?Await] BindingElementList[?Yield, ?Await] , BindingElisionElement[?Yield, ?Await] BindingElisionElement[Yield, Await] : Elisionopt BindingElement[?Yield, ?Await] BindingProperty[Yield, Await] : SingleNameBinding[?Yield, ?Await] PropertyName[?Yield, ?Await] : BindingElement[?Yield, ?Await] BindingElement[Yield, Await] : SingleNameBinding[?Yield, ?Await] BindingPattern[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]opt SingleNameBinding[Yield, Await] : BindingIdentifier[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]opt BindingRestElement[Yield, Await] : ... BindingIdentifier[?Yield, ?Await] ... BindingPattern[?Yield, ?Await] EmptyStatement : ; ExpressionStatement[Yield, Await] : [lookahead ∉ { {, function, async [no LineTerminator here] function, class, let [ }] Expression[+In, ?Yield, ?Await] ; IfStatement[Yield, Await, Return] : if ( Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] else Statement[?Yield, ?Await, ?Return] if ( Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] [lookahead ≠ else] IterationStatement[Yield, Await, Return] : DoWhileStatement[?Yield, ?Await, ?Return] WhileStatement[?Yield, ?Await, ?Return] ForStatement[?Yield, ?Await, ?Return] ForInOfStatement[?Yield, ?Await, ?Return] DoWhileStatement[Yield, Await, Return] : do Statement[?Yield, ?Await, ?Return] while ( Expression[+In, ?Yield, ?Await] ) ; WhileStatement[Yield, Await, Return] : while ( Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] ForStatement[Yield, Await, Return] : for ( [lookahead ≠ let [] Expression[~In, ?Yield, ?Await]opt ; Expression[+In, ?Yield, ?Await]opt ; Expression[+In, ?Yield, ?Await]opt ) Statement[?Yield, ?Await, ?Return] for ( var VariableDeclarationList[~In, ?Yield, ?Await] ; Expression[+In, ?Yield, ?Await]opt ; Expression[+In, ?Yield, ?Await]opt ) Statement[?Yield, ?Await, ?Return] for ( LexicalDeclaration[~In, ?Yield, ?Await] Expression[+In, ?Yield, ?Await]opt ; Expression[+In, ?Yield, ?Await]opt ) Statement[?Yield, ?Await, ?Return] ForInOfStatement[Yield, Await, Return] : for ( [lookahead ≠ let [] LeftHandSideExpression[?Yield, ?Await] in Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] for ( var ForBinding[?Yield, ?Await] in Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] for ( ForDeclaration[?Yield, ?Await] in Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] for ( [lookahead ∉ { let, async of }] LeftHandSideExpression[?Yield, ?Await] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] for ( var ForBinding[?Yield, ?Await] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] for ( ForDeclaration[?Yield, ?Await] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] [+Await] for await ( [lookahead ≠ let] LeftHandSideExpression[?Yield, ?Await] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] [+Await] for await ( var ForBinding[?Yield, ?Await] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] [+Await] for await ( ForDeclaration[?Yield, ?Await] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] ForDeclaration[Yield, Await] : LetOrConst ForBinding[?Yield, ?Await] ForBinding[Yield, Await] : BindingIdentifier[?Yield, ?Await] BindingPattern[?Yield, ?Await] ContinueStatement[Yield, Await] : continue ; continue [no LineTerminator here] LabelIdentifier[?Yield, ?Await] ; BreakStatement[Yield, Await] : break ; break [no LineTerminator here] LabelIdentifier[?Yield, ?Await] ; ReturnStatement[Yield, Await] : return ; return [no LineTerminator here] Expression[+In, ?Yield, ?Await] ; WithStatement[Yield, Await, Return] : with ( Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] SwitchStatement[Yield, Await, Return] : switch ( Expression[+In, ?Yield, ?Await] ) CaseBlock[?Yield, ?Await, ?Return] CaseBlock[Yield, Await, Return] : { CaseClauses[?Yield, ?Await, ?Return]opt } { CaseClauses[?Yield, ?Await, ?Return]opt DefaultClause[?Yield, ?Await, ?Return] CaseClauses[?Yield, ?Await, ?Return]opt } CaseClauses[Yield, Await, Return] : CaseClause[?Yield, ?Await, ?Return] CaseClauses[?Yield, ?Await, ?Return] CaseClause[?Yield, ?Await, ?Return] CaseClause[Yield, Await, Return] : case Expression[+In, ?Yield, ?Await] : StatementList[?Yield, ?Await, ?Return]opt DefaultClause[Yield, Await, Return] : default : StatementList[?Yield, ?Await, ?Return]opt LabelledStatement[Yield, Await, Return] : LabelIdentifier[?Yield, ?Await] : LabelledItem[?Yield, ?Await, ?Return] LabelledItem[Yield, Await, Return] : Statement[?Yield, ?Await, ?Return] FunctionDeclaration[?Yield, ?Await, ~Default] ThrowStatement[Yield, Await] : throw [no LineTerminator here] Expression[+In, ?Yield, ?Await] ; TryStatement[Yield, Await, Return] : try Block[?Yield, ?Await, ?Return] Catch[?Yield, ?Await, ?Return] try Block[?Yield, ?Await, ?Return] Finally[?Yield, ?Await, ?Return] try Block[?Yield, ?Await, ?Return] Catch[?Yield, ?Await, ?Return] Finally[?Yield, ?Await, ?Return] Catch[Yield, Await, Return] : catch ( CatchParameter[?Yield, ?Await] ) Block[?Yield, ?Await, ?Return] catch Block[?Yield, ?Await, ?Return] Finally[Yield, Await, Return] : finally Block[?Yield, ?Await, ?Return] CatchParameter[Yield, Await] : BindingIdentifier[?Yield, ?Await] BindingPattern[?Yield, ?Await] DebuggerStatement : debugger ;

A.4 函数和类

UniqueFormalParameters[Yield, Await] : FormalParameters[?Yield, ?Await] FormalParameters[Yield, Await] : [empty] FunctionRestParameter[?Yield, ?Await] FormalParameterList[?Yield, ?Await] FormalParameterList[?Yield, ?Await] , FormalParameterList[?Yield, ?Await] , FunctionRestParameter[?Yield, ?Await] FormalParameterList[Yield, Await] : FormalParameter[?Yield, ?Await] FormalParameterList[?Yield, ?Await] , FormalParameter[?Yield, ?Await] FunctionRestParameter[Yield, Await] : BindingRestElement[?Yield, ?Await] FormalParameter[Yield, Await] : BindingElement[?Yield, ?Await] FunctionDeclaration[Yield, Await, Default] : function BindingIdentifier[?Yield, ?Await] ( FormalParameters[~Yield, ~Await] ) { FunctionBody[~Yield, ~Await] } [+Default] function ( FormalParameters[~Yield, ~Await] ) { FunctionBody[~Yield, ~Await] } FunctionExpression : function BindingIdentifier[~Yield, ~Await]opt ( FormalParameters[~Yield, ~Await] ) { FunctionBody[~Yield, ~Await] } FunctionBody[Yield, Await] : FunctionStatementList[?Yield, ?Await] FunctionStatementList[Yield, Await] : StatementList[?Yield, ?Await, +Return]opt ArrowFunction[In, Yield, Await] : ArrowParameters[?Yield, ?Await] [no LineTerminator here] => ConciseBody[?In] ArrowParameters[Yield, Await] : BindingIdentifier[?Yield, ?Await] CoverParenthesizedExpressionAndArrowParameterList[?Yield, ?Await] ConciseBody[In] : [lookahead ≠ {] ExpressionBody[?In, ~Await] { FunctionBody[~Yield, ~Await] } ExpressionBody[In, Await] : AssignmentExpression[?In, ~Yield, ?Await]

当处理产生式的一个实例
ArrowParameters[Yield, Await] : CoverParenthesizedExpressionAndArrowParameterList[?Yield, ?Await]
时,使用以下语法来细化 CoverParenthesizedExpressionAndArrowParameterList 的解释:

ArrowFormalParameters[Yield, Await] : ( UniqueFormalParameters[?Yield, ?Await] )

 

AsyncArrowFunction[In, Yield, Await] : async [no LineTerminator here] AsyncArrowBindingIdentifier[?Yield] [no LineTerminator here] => AsyncConciseBody[?In] CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await] [no LineTerminator here] => AsyncConciseBody[?In] AsyncConciseBody[In] : [lookahead ≠ {] ExpressionBody[?In, +Await] { AsyncFunctionBody } AsyncArrowBindingIdentifier[Yield] : BindingIdentifier[?Yield, +Await] CoverCallExpressionAndAsyncArrowHead[Yield, Await] : MemberExpression[?Yield, ?Await] Arguments[?Yield, ?Await]

当处理产生式的一个实例
AsyncArrowFunction[In, Yield, Await] : CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await] [no LineTerminator here] => AsyncConciseBody[?In]
时,使用以下语法来细化 CoverCallExpressionAndAsyncArrowHead 的解释:

AsyncArrowHead : async [no LineTerminator here] ArrowFormalParameters[~Yield, +Await]

 

MethodDefinition[Yield, Await] : ClassElementName[?Yield, ?Await] ( UniqueFormalParameters[~Yield, ~Await] ) { FunctionBody[~Yield, ~Await] } GeneratorMethod[?Yield, ?Await] AsyncMethod[?Yield, ?Await] AsyncGeneratorMethod[?Yield, ?Await] get ClassElementName[?Yield, ?Await] ( ) { FunctionBody[~Yield, ~Await] } set ClassElementName[?Yield, ?Await] ( PropertySetParameterList ) { FunctionBody[~Yield, ~Await] } PropertySetParameterList : FormalParameter[~Yield, ~Await] GeneratorDeclaration[Yield, Await, Default] : function * BindingIdentifier[?Yield, ?Await] ( FormalParameters[+Yield, ~Await] ) { GeneratorBody } [+Default] function * ( FormalParameters[+Yield, ~Await] ) { GeneratorBody } GeneratorExpression : function * BindingIdentifier[+Yield, ~Await]opt ( FormalParameters[+Yield, ~Await] ) { GeneratorBody } GeneratorMethod[Yield, Await] : * ClassElementName[?Yield, ?Await] ( UniqueFormalParameters[+Yield, ~Await] ) { GeneratorBody } GeneratorBody : FunctionBody[+Yield, ~Await] YieldExpression[In, Await] : yield yield [no LineTerminator here] AssignmentExpression[?In, +Yield, ?Await] yield [no LineTerminator here] * AssignmentExpression[?In, +Yield, ?Await] AsyncGeneratorDeclaration[Yield, Await, Default] : async [no LineTerminator here] function * BindingIdentifier[?Yield, ?Await] ( FormalParameters[+Yield, +Await] ) { AsyncGeneratorBody } [+Default] async [no LineTerminator here] function * ( FormalParameters[+Yield, +Await] ) { AsyncGeneratorBody } AsyncGeneratorExpression : async [no LineTerminator here] function * BindingIdentifier[+Yield, +Await]opt ( FormalParameters[+Yield, +Await] ) { AsyncGeneratorBody } AsyncGeneratorMethod[Yield, Await] : async [no LineTerminator here] * ClassElementName[?Yield, ?Await] ( UniqueFormalParameters[+Yield, +Await] ) { AsyncGeneratorBody } AsyncGeneratorBody : FunctionBody[+Yield, +Await] AsyncFunctionDeclaration[Yield, Await, Default] : async [no LineTerminator here] function BindingIdentifier[?Yield, ?Await] ( FormalParameters[~Yield, +Await] ) { AsyncFunctionBody } [+Default] async [no LineTerminator here] function ( FormalParameters[~Yield, +Await] ) { AsyncFunctionBody } AsyncFunctionExpression : async [no LineTerminator here] function BindingIdentifier[~Yield, +Await]opt ( FormalParameters[~Yield, +Await] ) { AsyncFunctionBody } AsyncMethod[Yield, Await] : async [no LineTerminator here] ClassElementName[?Yield, ?Await] ( UniqueFormalParameters[~Yield, +Await] ) { AsyncFunctionBody } AsyncFunctionBody : FunctionBody[~Yield, +Await] AwaitExpression[Yield] : await UnaryExpression[?Yield, +Await] ClassDeclaration[Yield, Await, Default] : class BindingIdentifier[?Yield, ?Await] ClassTail[?Yield, ?Await] [+Default] class ClassTail[?Yield, ?Await] ClassExpression[Yield, Await] : class BindingIdentifier[?Yield, ?Await]opt ClassTail[?Yield, ?Await] ClassTail[Yield, Await] : ClassHeritage[?Yield, ?Await]opt { ClassBody[?Yield, ?Await]opt } ClassHeritage[Yield, Await] : extends LeftHandSideExpression[?Yield, ?Await] ClassBody[Yield, Await] : ClassElementList[?Yield, ?Await] ClassElementList[Yield, Await] : ClassElement[?Yield, ?Await] ClassElementList[?Yield, ?Await] ClassElement[?Yield, ?Await] ClassElement[Yield, Await] : MethodDefinition[?Yield, ?Await] static MethodDefinition[?Yield, ?Await] FieldDefinition[?Yield, ?Await] ; static FieldDefinition[?Yield, ?Await] ; ClassStaticBlock ; FieldDefinition[Yield, Await] : ClassElementName[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]opt ClassElementName[Yield, Await] : PropertyName[?Yield, ?Await] PrivateIdentifier ClassStaticBlock : static { ClassStaticBlockBody } ClassStaticBlockBody : ClassStaticBlockStatementList ClassStaticBlockStatementList : StatementList[~Yield, +Await, ~Return]opt

A.5 脚本和模块

Script : ScriptBodyopt ScriptBody : StatementList[~Yield, ~Await, ~Return] Module : ModuleBodyopt ModuleBody : ModuleItemList ModuleItemList : ModuleItem ModuleItemList ModuleItem ModuleItem : ImportDeclaration ExportDeclaration StatementListItem[~Yield, +Await, ~Return] ModuleExportName : IdentifierName StringLiteral ImportDeclaration : import ImportClause FromClause WithClauseopt ; import ModuleSpecifier WithClauseopt ; ImportClause : ImportedDefaultBinding NameSpaceImport NamedImports ImportedDefaultBinding , NameSpaceImport ImportedDefaultBinding , NamedImports ImportedDefaultBinding : ImportedBinding NameSpaceImport : * as ImportedBinding NamedImports : { } { ImportsList } { ImportsList , } FromClause : from ModuleSpecifier ImportsList : ImportSpecifier ImportsList , ImportSpecifier ImportSpecifier : ImportedBinding ModuleExportName as ImportedBinding ModuleSpecifier : StringLiteral ImportedBinding : BindingIdentifier[~Yield, +Await] WithClause : with { } with { WithEntries ,opt } WithEntries : AttributeKey : StringLiteral AttributeKey : StringLiteral , WithEntries AttributeKey : IdentifierName StringLiteral ExportDeclaration : export ExportFromClause FromClause WithClauseopt ; export NamedExports ; export VariableStatement[~Yield, +Await] export Declaration[~Yield, +Await] export default HoistableDeclaration[~Yield, +Await, +Default] export default ClassDeclaration[~Yield, +Await, +Default] export default [lookahead ∉ { function, async [no LineTerminator here] function, class }] AssignmentExpression[+In, ~Yield, +Await] ; ExportFromClause : * * as ModuleExportName NamedExports NamedExports : { } { ExportsList } { ExportsList , } ExportsList : ExportSpecifier ExportsList , ExportSpecifier ExportSpecifier : ModuleExportName ModuleExportName as ModuleExportName

A.6 Number 转换

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

未由 StringNumericLiteral 语法显式定义的所有语法符号,均采用数值字面量的词法语法中使用的定义。

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

A.7 时区偏移字符串格式

UTCOffset ::: ASCIISign Hour ASCIISign Hour HourSubcomponents[+Extended] ASCIISign Hour HourSubcomponents[~Extended] ASCIISign ::: one of + - Hour ::: 0 DecimalDigit 1 DecimalDigit 20 21 22 23 HourSubcomponents[Extended] ::: TimeSeparator[?Extended] MinuteSecond TimeSeparator[?Extended] MinuteSecond TimeSeparator[?Extended] MinuteSecond TemporalDecimalFractionopt TimeSeparator[Extended] ::: [+Extended] : [~Extended] [empty] MinuteSecond ::: 0 DecimalDigit 1 DecimalDigit 2 DecimalDigit 3 DecimalDigit 4 DecimalDigit 5 DecimalDigit TemporalDecimalFraction ::: TemporalDecimalSeparator DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator ::: one of . ,

A.8 正则表达式

Pattern[UnicodeMode, UnicodeSetsMode, NamedCaptureGroups] :: Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Disjunction[UnicodeMode, UnicodeSetsMode, NamedCaptureGroups] :: Alternative[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Alternative[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] | Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Alternative[UnicodeMode, UnicodeSetsMode, NamedCaptureGroups] :: [empty] Alternative[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Term[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Term[UnicodeMode, UnicodeSetsMode, NamedCaptureGroups] :: Assertion[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Atom[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Atom[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Quantifier Assertion[UnicodeMode, UnicodeSetsMode, NamedCaptureGroups] :: ^ $ \b \B (?= Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) (?! Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) (?<= Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) (?<! Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) Quantifier :: QuantifierPrefix QuantifierPrefix ? QuantifierPrefix :: * + ? { DecimalDigits[~Sep] } { DecimalDigits[~Sep] ,} { DecimalDigits[~Sep] , DecimalDigits[~Sep] } Atom[UnicodeMode, UnicodeSetsMode, NamedCaptureGroups] :: PatternCharacter . \ AtomEscape[?UnicodeMode, ?NamedCaptureGroups] CharacterClass[?UnicodeMode, ?UnicodeSetsMode] ( GroupSpecifier[?UnicodeMode]opt Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) (? RegularExpressionModifiers : Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) (? RegularExpressionModifiers - RegularExpressionModifiers : Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) RegularExpressionModifiers :: [empty] RegularExpressionModifiers RegularExpressionModifier RegularExpressionModifier :: one of i m s SyntaxCharacter :: one of ^ $ \ . * + ? ( ) [ ] { } | PatternCharacter :: SourceCharacter but not SyntaxCharacter AtomEscape[UnicodeMode, NamedCaptureGroups] :: DecimalEscape CharacterClassEscape[?UnicodeMode] CharacterEscape[?UnicodeMode] [+NamedCaptureGroups] k GroupName[?UnicodeMode] CharacterEscape[UnicodeMode] :: ControlEscape c AsciiLetter 0 [lookahead ∉ DecimalDigit] HexEscapeSequence RegExpUnicodeEscapeSequence[?UnicodeMode] IdentityEscape[?UnicodeMode] ControlEscape :: one of f n r t v GroupSpecifier[UnicodeMode] :: ? GroupName[?UnicodeMode] GroupName[UnicodeMode] :: < RegExpIdentifierName[?UnicodeMode] > RegExpIdentifierName[UnicodeMode] :: RegExpIdentifierStart[?UnicodeMode] RegExpIdentifierName[?UnicodeMode] RegExpIdentifierPart[?UnicodeMode] RegExpIdentifierStart[UnicodeMode] :: IdentifierStartChar \ RegExpUnicodeEscapeSequence[+UnicodeMode] [~UnicodeMode] UnicodeLeadSurrogate UnicodeTrailSurrogate RegExpIdentifierPart[UnicodeMode] :: IdentifierPartChar \ RegExpUnicodeEscapeSequence[+UnicodeMode] [~UnicodeMode] UnicodeLeadSurrogate UnicodeTrailSurrogate RegExpUnicodeEscapeSequence[UnicodeMode] :: [+UnicodeMode] u HexLeadSurrogate \u HexTrailSurrogate [+UnicodeMode] u HexLeadSurrogate [+UnicodeMode] u HexTrailSurrogate [+UnicodeMode] u HexNonSurrogate [~UnicodeMode] u Hex4Digits [+UnicodeMode] u{ CodePoint } UnicodeLeadSurrogate :: any Unicode code point in the inclusive interval from U+D800 to U+DBFF UnicodeTrailSurrogate :: any Unicode code point in the inclusive interval from U+DC00 to U+DFFF

对于每个 \u HexTrailSurrogate,如果其关联的 u HexLeadSurrogate 的选择存在歧义,则应将其关联到最近的、否则不会有对应 \u HexTrailSurrogate 的可能 u HexLeadSurrogate

 

HexLeadSurrogate :: Hex4Digits but only if the MV of Hex4Digits is in the inclusive interval from 0xD800 to 0xDBFF HexTrailSurrogate :: Hex4Digits but only if the MV of Hex4Digits is in the inclusive interval from 0xDC00 to 0xDFFF HexNonSurrogate :: Hex4Digits but only if the MV of Hex4Digits is not in the inclusive interval from 0xD800 to 0xDFFF IdentityEscape[UnicodeMode] :: [+UnicodeMode] SyntaxCharacter [+UnicodeMode] / [~UnicodeMode] SourceCharacter but not UnicodeIDContinue DecimalEscape :: NonZeroDigit DecimalDigits[~Sep]opt [lookahead ∉ DecimalDigit] CharacterClassEscape[UnicodeMode] :: d D s S w W [+UnicodeMode] p{ UnicodePropertyValueExpression } [+UnicodeMode] P{ UnicodePropertyValueExpression } UnicodePropertyValueExpression :: UnicodePropertyName = UnicodePropertyValue LoneUnicodePropertyNameOrValue UnicodePropertyName :: UnicodePropertyNameCharacters UnicodePropertyNameCharacters :: UnicodePropertyNameCharacter UnicodePropertyNameCharactersopt UnicodePropertyValue :: UnicodePropertyValueCharacters LoneUnicodePropertyNameOrValue :: UnicodePropertyValueCharacters UnicodePropertyValueCharacters :: UnicodePropertyValueCharacter UnicodePropertyValueCharactersopt UnicodePropertyValueCharacter :: UnicodePropertyNameCharacter DecimalDigit UnicodePropertyNameCharacter :: AsciiLetter _ CharacterClass[UnicodeMode, UnicodeSetsMode] :: [ [lookahead ≠ ^] ClassContents[?UnicodeMode, ?UnicodeSetsMode] ] [^ ClassContents[?UnicodeMode, ?UnicodeSetsMode] ] ClassContents[UnicodeMode, UnicodeSetsMode] :: [empty] [~UnicodeSetsMode] NonemptyClassRanges[?UnicodeMode] [+UnicodeSetsMode] ClassSetExpression NonemptyClassRanges[UnicodeMode] :: ClassAtom[?UnicodeMode] ClassAtom[?UnicodeMode] NonemptyClassRangesNoDash[?UnicodeMode] ClassAtom[?UnicodeMode] - ClassAtom[?UnicodeMode] ClassContents[?UnicodeMode, ~UnicodeSetsMode] NonemptyClassRangesNoDash[UnicodeMode] :: ClassAtom[?UnicodeMode] ClassAtomNoDash[?UnicodeMode] NonemptyClassRangesNoDash[?UnicodeMode] ClassAtomNoDash[?UnicodeMode] - ClassAtom[?UnicodeMode] ClassContents[?UnicodeMode, ~UnicodeSetsMode] ClassAtom[UnicodeMode] :: - ClassAtomNoDash[?UnicodeMode] ClassAtomNoDash[UnicodeMode] :: SourceCharacter but not one of \ or ] or - \ ClassEscape[?UnicodeMode] ClassEscape[UnicodeMode] :: b [+UnicodeMode] - CharacterClassEscape[?UnicodeMode] CharacterEscape[?UnicodeMode] ClassSetExpression :: ClassUnion ClassIntersection ClassSubtraction ClassUnion :: ClassSetRange ClassUnionopt ClassSetOperand ClassUnionopt ClassIntersection :: ClassSetOperand && [lookahead ≠ &] ClassSetOperand ClassIntersection && [lookahead ≠ &] ClassSetOperand ClassSubtraction :: ClassSetOperand -- ClassSetOperand ClassSubtraction -- ClassSetOperand ClassSetRange :: ClassSetCharacter - ClassSetCharacter ClassSetOperand :: NestedClass ClassStringDisjunction ClassSetCharacter NestedClass :: [ [lookahead ≠ ^] ClassContents[+UnicodeMode, +UnicodeSetsMode] ] [^ ClassContents[+UnicodeMode, +UnicodeSetsMode] ] \ CharacterClassEscape[+UnicodeMode] ClassStringDisjunction :: \q{ ClassStringDisjunctionContents } ClassStringDisjunctionContents :: ClassString ClassString | ClassStringDisjunctionContents ClassString :: [empty] NonEmptyClassString NonEmptyClassString :: ClassSetCharacter NonEmptyClassStringopt ClassSetCharacter :: [lookahead ∉ ClassSetReservedDoublePunctuator] SourceCharacter but not ClassSetSyntaxCharacter \ CharacterEscape[+UnicodeMode] \ ClassSetReservedPunctuator \b ClassSetReservedDoublePunctuator :: one of && !! ## $$ %% ** ++ ,, .. :: ;; << == >> ?? @@ ^^ `` ~~ ClassSetSyntaxCharacter :: one of ( ) [ ] { } / - \ | ClassSetReservedPunctuator :: one of & - ! # % , : ; < = > @ ` ~

Annex B (normative) Web 浏览器的附加 ECMAScript 特性

当 ECMAScript 宿主是 Web 浏览器时,本附录中定义的 ECMAScript 语言语法和语义是必需的。如果 ECMAScript 宿主不是 Web 浏览器,则本附录内容是规范性的但可选。

本附录中定义的一些特性在本附录中规定,另一些则在本文档主体中规定。

当某个特性在主体中规定时,它影响文档的每一点都会以彩色框标记“Normative Optional”字样。此外,当该特性涉及算法或早期错误规则中的特定措辞时,会以“宿主支持”相关特性这一条件作为保护。Web 浏览器必须支持所有这些特性。

Note

本附录描述了 Web 浏览器 ECMAScript 宿主的各种遗留特性和其他特征。本附录中规定的所有语言特性和行为都具有一个或多个不理想的特征,如果没有遗留使用,本应从本规范中移除。然而,由于大量现有网页使用这些特性,Web 浏览器必须继续支持它们。本附录中的规范定义了这些遗留特性的可互操作实现要求。

这些特性不被认为是核心 ECMAScript 语言的一部分。程序员在编写新的 ECMAScript 代码时不应使用或假定这些特性和行为的存在。除非实现是 Web 浏览器的一部分,或需要运行 Web 浏览器所遇到的相同遗留 ECMAScript 代码,否则不鼓励 ECMAScript 实现实现这些特性。

B.1 附加语法

B.1.1 类 HTML 注释

12.4 的语法和语义扩展如下,但当使用目标符号 Module 解析源文本时,不允许此扩展:

语法

InputElementHashbangOrRegExp :: WhiteSpace LineTerminator Comment CommonToken HashbangComment RegularExpressionLiteral HTMLCloseComment Comment :: MultiLineComment SingleLineComment SingleLineHTMLOpenComment SingleLineHTMLCloseComment SingleLineDelimitedComment MultiLineComment :: /* FirstCommentLineopt LineTerminator MultiLineCommentCharsopt */ HTMLCloseCommentopt FirstCommentLine :: SingleLineDelimitedCommentChars SingleLineHTMLOpenComment :: <!-- SingleLineCommentCharsopt SingleLineHTMLCloseComment :: LineTerminatorSequence HTMLCloseComment SingleLineDelimitedComment :: /* SingleLineDelimitedCommentCharsopt */ HTMLCloseComment :: WhiteSpaceSequenceopt SingleLineDelimitedCommentSequenceopt --> SingleLineCommentCharsopt SingleLineDelimitedCommentChars :: SingleLineNotAsteriskChar SingleLineDelimitedCommentCharsopt * SingleLinePostAsteriskCommentCharsopt SingleLineNotAsteriskChar :: SourceCharacter but not one of * or LineTerminator SingleLinePostAsteriskCommentChars :: SingleLineNotForwardSlashOrAsteriskChar SingleLineDelimitedCommentCharsopt * SingleLinePostAsteriskCommentCharsopt SingleLineNotForwardSlashOrAsteriskChar :: SourceCharacter but not one of / or * or LineTerminator WhiteSpaceSequence :: WhiteSpace WhiteSpaceSequenceopt SingleLineDelimitedCommentSequence :: SingleLineDelimitedComment WhiteSpaceSequenceopt SingleLineDelimitedCommentSequenceopt

类似于包含行终止符码点的 MultiLineComment,为了按句法语法进行解析,SingleLineHTMLCloseComment 被视为 LineTerminator

B.1.2 正则表达式模式

22.2.1 的语法按如下方式修改和扩展。这些更改引入了歧义,这些歧义通过语法产生式的顺序和上下文信息来消解。使用以下语法进行解析时,只有在先前的产生式替代项不匹配时,才会考虑每个替代项。

此替代模式语法和语义只改变 BMP 模式的语法和语义。以下语法扩展包括带有 [UnicodeMode] 参数的产生式。然而,这些扩展均不改变在目标符号上存在 [UnicodeMode] 参数时解析所识别的 Unicode 模式语法。

语法

Term[UnicodeMode, UnicodeSetsMode, NamedCaptureGroups] :: [+UnicodeMode] Assertion[+UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] [+UnicodeMode] Atom[+UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Quantifier [+UnicodeMode] Atom[+UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] [~UnicodeMode] QuantifiableAssertion[?NamedCaptureGroups] Quantifier [~UnicodeMode] Assertion[~UnicodeMode, ~UnicodeSetsMode, ?NamedCaptureGroups] [~UnicodeMode] ExtendedAtom[?NamedCaptureGroups] Quantifier [~UnicodeMode] ExtendedAtom[?NamedCaptureGroups] Assertion[UnicodeMode, UnicodeSetsMode, NamedCaptureGroups] :: ^ $ \b \B [+UnicodeMode] (?= Disjunction[+UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) [+UnicodeMode] (?! Disjunction[+UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) [~UnicodeMode] QuantifiableAssertion[?NamedCaptureGroups] (?<= Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) (?<! Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) QuantifiableAssertion[NamedCaptureGroups] :: (?= Disjunction[~UnicodeMode, ~UnicodeSetsMode, ?NamedCaptureGroups] ) (?! Disjunction[~UnicodeMode, ~UnicodeSetsMode, ?NamedCaptureGroups] ) ExtendedAtom[NamedCaptureGroups] :: . \ AtomEscape[~UnicodeMode, ?NamedCaptureGroups] \ [lookahead = c] CharacterClass[~UnicodeMode, ~UnicodeSetsMode] ( GroupSpecifier[~UnicodeMode]opt Disjunction[~UnicodeMode, ~UnicodeSetsMode, ?NamedCaptureGroups] ) (? RegularExpressionModifiers : Disjunction[~UnicodeMode, ~UnicodeSetsMode, ?NamedCaptureGroups] ) (? RegularExpressionModifiers - RegularExpressionModifiers : Disjunction[~UnicodeMode, ~UnicodeSetsMode, ?NamedCaptureGroups] ) InvalidBracedQuantifier ExtendedPatternCharacter InvalidBracedQuantifier :: { DecimalDigits[~Sep] } { DecimalDigits[~Sep] ,} { DecimalDigits[~Sep] , DecimalDigits[~Sep] } ExtendedPatternCharacter :: SourceCharacter but not one of ^ $ \ . * + ? ( ) [ | AtomEscape[UnicodeMode, NamedCaptureGroups] :: [+UnicodeMode] DecimalEscape [~UnicodeMode] DecimalEscape but only if the CapturingGroupNumber of DecimalEscape is ≤ CountLeftCapturingParensWithin(the Pattern containing DecimalEscape) CharacterClassEscape[?UnicodeMode] CharacterEscape[?UnicodeMode, ?NamedCaptureGroups] [+NamedCaptureGroups] k GroupName[?UnicodeMode] CharacterEscape[UnicodeMode, NamedCaptureGroups] :: ControlEscape c AsciiLetter 0 [lookahead ∉ DecimalDigit] HexEscapeSequence RegExpUnicodeEscapeSequence[?UnicodeMode] [~UnicodeMode] LegacyOctalEscapeSequence IdentityEscape[?UnicodeMode, ?NamedCaptureGroups] IdentityEscape[UnicodeMode, NamedCaptureGroups] :: [+UnicodeMode] SyntaxCharacter [+UnicodeMode] / [~UnicodeMode] SourceCharacterIdentityEscape[?NamedCaptureGroups] SourceCharacterIdentityEscape[NamedCaptureGroups] :: [~NamedCaptureGroups] SourceCharacter but not c [+NamedCaptureGroups] SourceCharacter but not one of c or k ClassAtomNoDash[UnicodeMode, NamedCaptureGroups] :: SourceCharacter but not one of \ or ] or - \ ClassEscape[?UnicodeMode, ?NamedCaptureGroups] \ [lookahead = c] ClassEscape[UnicodeMode, NamedCaptureGroups] :: b [+UnicodeMode] - [~UnicodeMode] c ClassControlLetter CharacterClassEscape[?UnicodeMode] CharacterEscape[?UnicodeMode, ?NamedCaptureGroups] ClassControlLetter :: DecimalDigit _ Note

当相同的左侧同时以 [+UnicodeMode] 和 [~UnicodeMode] 保护出现时,这是为了控制消歧优先级。

B.1.2.1 静态语义:早期错误

22.2.1.1 的语义扩展如下:

ExtendedAtom :: InvalidBracedQuantifier
  • 如果任何源文本与此产生式匹配,则为语法错误。

此外,以下产生式的规则通过加入高亮文本进行修改:

NonemptyClassRanges :: ClassAtom - ClassAtom ClassContents NonemptyClassRangesNoDash :: ClassAtomNoDash - ClassAtom ClassContents

B.1.2.2 静态语义:CountLeftCapturingParensWithin 和 CountLeftCapturingParensBefore

CountLeftCapturingParensWithinCountLeftCapturingParensBefore 的定义中,对 “ Atom :: ( GroupSpecifieropt Disjunction ) ” 的引用应解释为表示 “ Atom :: ( GroupSpecifieropt Disjunction ) ” 或 “ ExtendedAtom :: ( GroupSpecifieropt Disjunction ) ”。

B.1.2.3 静态语义:IsCharacterClass

22.2.1.6 的语义扩展如下:

ClassAtomNoDash :: \ [lookahead = c]
  1. 返回 false

B.1.2.4 静态语义:CharacterValue

22.2.1.7 的语义扩展如下:

ClassAtomNoDash :: \ [lookahead = c]
  1. 返回 U+005C (REVERSE SOLIDUS) 的数值。
ClassEscape :: c ClassControlLetter
  1. ch 为与 ClassControlLetter 匹配的码点。
  2. ich 的数值。
  3. 返回 i 除以 32 的余数。
CharacterEscape :: LegacyOctalEscapeSequence
  1. 返回 LegacyOctalEscapeSequence 的 MV(见 12.9.4.3)。

B.1.2.5 运行时语义:CompileSubpattern

CompileSubpattern 的语义扩展如下:

Term :: QuantifiableAssertion Quantifier 的规则与 Term :: Atom Quantifier 的规则相同,但以 QuantifiableAssertion 替代 Atom

Term :: ExtendedAtom Quantifier 的规则与 Term :: Atom Quantifier 的规则相同,但以 ExtendedAtom 替代 Atom

Term :: ExtendedAtom 的规则与 Term :: Atom 的规则相同,但以 ExtendedAtom 替代 Atom

B.1.2.6 运行时语义:CompileAssertion

Assertion :: (?= Disjunction ) Assertion :: (?! Disjunction ) 产生式的 CompileAssertion 规则也用于 QuantifiableAssertion 产生式,但以 QuantifiableAssertion 替代 Assertion

B.1.2.7 运行时语义:CompileAtom

Atom :: PatternCharacter 外,Atom 产生式的 CompileAtom 规则也用于 ExtendedAtom 产生式,但以 ExtendedAtom 替代 Atom。还添加以下带参数 direction 的规则:

ExtendedAtom :: \ [lookahead = c]
  1. charSet 为包含单个字符 \ U+005C (REVERSE SOLIDUS) 的 CharSet
  2. 返回 CharacterSetMatcher(regexpRecord, charSet, false, direction)。
ExtendedAtom :: ExtendedPatternCharacter
  1. chExtendedPatternCharacter 所表示的字符。
  2. charSet 为包含字符 ch 的单元素 CharSet
  3. 返回 CharacterSetMatcher(regexpRecord, charSet, false, direction)。

B.1.2.8 运行时语义:CompileToCharSet

22.2.2.9 的语义扩展如下:

以下两条规则替换 CompileToCharSet 的对应规则。

NonemptyClassRanges :: ClassAtom - ClassAtom ClassContents
  1. charSet 为第一个 ClassAtomregexpRecord 为实参的 CompileToCharSet
  2. otherSet 为第二个 ClassAtomregexpRecord 为实参的 CompileToCharSet
  3. remainingSetClassContentsregexpRecord 为实参的 CompileToCharSet
  4. rangeSetCharacterRangeOrUnion(regexpRecord, charSet, otherSet)。
  5. 返回 rangeSetremainingSet 的并集。
NonemptyClassRangesNoDash :: ClassAtomNoDash - ClassAtom ClassContents
  1. charSetClassAtomNoDashregexpRecord 为实参的 CompileToCharSet
  2. otherSetClassAtomregexpRecord 为实参的 CompileToCharSet
  3. remainingSetClassContentsregexpRecord 为实参的 CompileToCharSet
  4. rangeSetCharacterRangeOrUnion(regexpRecord, charSet, otherSet)。
  5. 返回 rangeSetremainingSet 的并集。

此外,向 CompileToCharSet 添加以下规则。

ClassEscape :: c ClassControlLetter
  1. cv 为此 ClassEscapeCharacterValue
  2. c 为字符值为 cv 的字符。
  3. 返回包含单个字符 cCharSet
ClassAtomNoDash :: \ [lookahead = c]
  1. 返回包含单个字符 \ U+005C (REVERSE SOLIDUS) 的 CharSet
Note
此产生式只能从字符类中的序列 \c 到达,且其后未跟随可接受的控制字符。

B.1.2.8.1 CharacterRangeOrUnion ( regexpRecord, charSet, otherSet )

The abstract operation CharacterRangeOrUnion takes arguments regexpRecord (一个 RegExp Record), charSet (一个 CharSet), and otherSet (一个 CharSet) and returns 一个 CharSet. It performs the following steps when called:

  1. 如果 HasEitherUnicodeFlag(regexpRecord) 为 false,则
    1. 如果 charSet 不恰好包含一个字符,或 otherSet 不恰好包含一个字符,则
      1. remainingSet 为包含单个字符 - U+002D (HYPHEN-MINUS) 的 CharSet
      2. 返回 CharSet charSetotherSetremainingSet 的并集。
  2. 返回 CharacterRange(charSet, otherSet)。

B.1.2.9 静态语义:ParsePattern ( patternText, u, v )

22.2.3.4 的语义扩展如下:

抽象操作 ParsePattern 接受实参 patternText(一个 Unicode 码点序列)、u(一个 Boolean)和 v(一个 Boolean)。它在被调用时执行以下步骤:

  1. 如果 vtrueutrue,则
    1. parseResult 为包含一个或多个 SyntaxError 对象的 List
  2. 否则,如果 vtrue,则
    1. parseResultParseText(patternText, Pattern[+UnicodeMode, +UnicodeSetsMode, +NamedCaptureGroups])。
  3. 否则,如果 utrue,则
    1. parseResultParseText(patternText, Pattern[+UnicodeMode, ~UnicodeSetsMode, +NamedCaptureGroups])。
  4. 否则,
    1. parseResultParseText(patternText, Pattern[~UnicodeMode, ~UnicodeSetsMode, ~NamedCaptureGroups])。
    2. 如果 parseResult 是 Parse Node 且 parseResult 包含 GroupName,则
      1. parseResult 设为 ParseText(patternText, Pattern[~UnicodeMode, ~UnicodeSetsMode, +NamedCaptureGroups])。
  5. 返回 parseResult

B.2 附加内置属性

当 ECMAScript 宿主是 Web 浏览器时,定义标准内置对象的以下附加属性。

B.2.1 全局对象的附加属性

Table 98 中的条目被添加到 Table 6

Table 98: 附加知名内在对象
内在名称 全局名称 ECMAScript 语言关联
%escape% escape escape 函数(B.2.1.1
%unescape% unescape unescape 函数(B.2.1.2

B.2.1.1 escape ( string )

此函数是全局对象的属性。它计算一个 String 值的新版本,其中某些代码单元已被十六进制转义序列替换。

当替换数值小于或等于 0x00FF 的代码单元时,使用形如 %xx 的两位转义序列。当替换数值严格大于 0x00FF 的代码单元时,使用形如 %uxxxx 的四位转义序列。

它是 %escape% 内在对象。

它在被调用时执行以下步骤:

  1. string 设为 ? ToString(string)。
  2. lenstring 的长度。
  3. result 为空字符串。
  4. unescapedSet 为 ASCII word characters 与 "@*+-./" 的字符串拼接。
  5. k 为 0。
  6. 重复,当 k < len 时,
    1. codeUnitstring 中索引 k 处的代码单元。
    2. 如果 unescapedSet 包含 codeUnit,则
      1. strcodeUnit
    3. 否则,
      1. ncodeUnit 的数值。
      2. 如果 n < 256,则
        1. hexn 的 String 表示,格式化为大写十六进制数。
        2. str"%"StringPad(hex, 2, "0", start) 的字符串拼接。
      3. 否则,
        1. hexn 的 String 表示,格式化为大写十六进制数。
        2. str"%u"StringPad(hex, 4, "0", start) 的字符串拼接。
    4. result 设为 resultstr 的字符串拼接。
    5. k 设为 k + 1。
  7. 返回 result
Note

该编码部分基于 RFC 1738 中描述的编码,但本标准中指定的整个编码已在上文描述,而不考虑 RFC 1738 的内容。该编码不反映 RFC 3986 对 RFC 1738 所作的更改。

B.2.1.2 unescape ( string )

此函数是全局对象的属性。它计算一个 String 值的新版本,其中每个可能由 escape 函数引入的那类转义序列都被替换为其表示的代码单元。

它是 %unescape% 内在对象。

它在被调用时执行以下步骤:

  1. string 设为 ? ToString(string)。
  2. lenstring 的长度。
  3. result 为空字符串。
  4. k 为 0。
  5. 重复,当 k < len 时,
    1. codeUnitstring 中索引 k 处的代码单元。
    2. 如果 codeUnit 是代码单元 0x0025 (PERCENT SIGN),则
      1. hexDigits 为空字符串。
      2. optionalAdvance 为 0。
      3. 如果 k + 5 < lenstring 中索引 k + 1 处的代码单元是代码单元 0x0075 (LATIN SMALL LETTER U),则
        1. hexDigits 设为 stringk + 2 到 k + 6 的子字符串
        2. optionalAdvance 设为 5。
      4. 否则,如果 k + 3 ≤ len,则
        1. hexDigits 设为 stringk + 1 到 k + 3 的子字符串
        2. optionalAdvance 设为 2。
      5. parseResultParseText(hexDigits, HexDigits[~Sep])。
      6. 如果 parseResult 是 Parse Node,则
        1. nparseResult 的 MV。
        2. codeUnit 设为数值为 n 的代码单元。
        3. k 设为 k + optionalAdvance
    3. result 设为 resultcodeUnit 的字符串拼接。
    4. k 设为 k + 1。
  6. 返回 result

B.2.2 String.prototype 对象的附加属性

B.2.2.1 String.prototype.substr ( start, length )

此方法返回将 this 值转换为 String 后所得结果的一个子字符串,从索引 start 开始并持续 length 个代码单元(如果 lengthundefined,则直到 String 末尾)。如果 start 为负,则将其视为 sourceLength + start,其中 sourceLength 是该 String 的长度。结果是一个 String 值,而不是 String 对象。

它在被调用时执行以下步骤:

  1. objthis 值。
  2. 执行 ? RequireObjectCoercible(obj)。
  3. str 为 ? ToString(obj)。
  4. sizestr 的长度。
  5. intStart 为 ? ToIntegerOrInfinity(start)。
  6. 如果 intStart = -∞,将 intStart 设为 0。
  7. 否则,如果 intStart < 0,将 intStart 设为 max(size + intStart, 0)。
  8. 否则,将 intStart 设为 min(intStart, size)。
  9. 如果 lengthundefined,令 intLengthsize;否则令 intLength 为 ? ToIntegerOrInfinity(length)。
  10. intLength 设为把 intLength 夹在 0 和 size 之间的结果。
  11. intEndmin(intStart + intLength, size)。
  12. 返回 strintStartintEnd子字符串
Note

此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此它可以转移到其他种类的对象上作为方法使用。

B.2.2.2 String.prototype.anchor ( name )

此方法在被调用时执行以下步骤:

  1. strthis 值。
  2. 返回 ? CreateHTML(str, "a", "name", name)。

B.2.2.2.1 CreateHTML ( contents, tag, attribute, attrValue )

The abstract operation CreateHTML takes arguments contents (一个 ECMAScript 语言值), tag (一个 String), attribute (一个 String), and attrValue (一个 ECMAScript 语言值) and returns 一个包含 String 的 normal completion 或一个 throw completion. It performs the following steps when called:

  1. 执行 ? RequireObjectCoercible(contents)。
  2. contentsStr 为 ? ToString(contents)。
  3. p1"<"tag 的字符串拼接。
  4. 如果 attribute 不是空字符串,则
    1. attrValueStr 为 ? ToString(attrValue)。
    2. escapedAttrValue 为一个 String 值,它与 attrValueStr 相同,但 attrValueStr 中每次出现的代码单元 0x0022 (QUOTATION MARK) 都被替换为六代码单元序列 "&quot;"
    3. p1 设为以下项的字符串拼接:
      • p1
      • 代码单元 0x0020 (SPACE)
      • attribute
      • 代码单元 0x003D (EQUALS SIGN)
      • 代码单元 0x0022 (QUOTATION MARK)
      • escapedAttrValue
      • 代码单元 0x0022 (QUOTATION MARK)
  5. p2p1">" 的字符串拼接。
  6. p3p2contentsStr 的字符串拼接。
  7. p4p3"</"tag">" 的字符串拼接。
  8. 返回 p4

B.2.2.3 String.prototype.big ( )

此方法在被调用时执行以下步骤:

  1. strthis 值。
  2. 返回 ? CreateHTML(str, "big", "", "")。

B.2.2.4 String.prototype.blink ( )

此方法在被调用时执行以下步骤:

  1. strthis 值。
  2. 返回 ? CreateHTML(str, "blink", "", "")。

B.2.2.5 String.prototype.bold ( )

此方法在被调用时执行以下步骤:

  1. strthis 值。
  2. 返回 ? CreateHTML(str, "b", "", "")。

B.2.2.6 String.prototype.fixed ( )

此方法在被调用时执行以下步骤:

  1. strthis 值。
  2. 返回 ? CreateHTML(str, "tt", "", "")。

B.2.2.7 String.prototype.fontcolor ( colour )

此方法在被调用时执行以下步骤:

  1. strthis 值。
  2. 返回 ? CreateHTML(str, "font", "color", colour)。

B.2.2.8 String.prototype.fontsize ( size )

此方法在被调用时执行以下步骤:

  1. strthis 值。
  2. 返回 ? CreateHTML(str, "font", "size", size)。

B.2.2.9 String.prototype.italics ( )

此方法在被调用时执行以下步骤:

  1. strthis 值。
  2. 返回 ? CreateHTML(str, "i", "", "")。

B.2.2.10 String.prototype.link ( url )

此方法在被调用时执行以下步骤:

  1. strthis 值。
  2. 返回 ? CreateHTML(str, "a", "href", url)。

B.2.2.11 String.prototype.small ( )

此方法在被调用时执行以下步骤:

  1. strthis 值。
  2. 返回 ? CreateHTML(str, "small", "", "")。

B.2.2.12 String.prototype.strike ( )

此方法在被调用时执行以下步骤:

  1. strthis 值。
  2. 返回 ? CreateHTML(str, "strike", "", "")。

B.2.2.13 String.prototype.sub ( )

此方法在被调用时执行以下步骤:

  1. strthis 值。
  2. 返回 ? CreateHTML(str, "sub", "", "")。

B.2.2.14 String.prototype.sup ( )

此方法在被调用时执行以下步骤:

  1. strthis 值。
  2. 返回 ? CreateHTML(str, "sup", "", "")。

B.2.2.15 String.prototype.trimLeft ( )

Note

属性 "trimStart" 是首选。"trimLeft" 属性主要为兼容旧代码而提供。建议在新的 ECMAScript 代码中使用 "trimStart" 属性。

"trimLeft" 属性的初始值是 %String.prototype.trimStart%,定义于 22.1.3.34

B.2.2.16 String.prototype.trimRight ( )

Note

属性 "trimEnd" 是首选。"trimRight" 属性主要为兼容旧代码而提供。建议在新的 ECMAScript 代码中使用 "trimEnd" 属性。

"trimRight" 属性的初始值是 %String.prototype.trimEnd%,定义于 22.1.3.33

B.2.3 Date.prototype 对象的附加属性

B.2.3.1 Date.prototype.getYear ( )

Note

几乎所有用途都首选 getFullYear 方法,因为它避免了“2000 年问题”。

此方法在被调用时执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,返回 NaN
  5. 返回 YearFromTime(LocalTime(t)) - 1900𝔽

B.2.3.2 Date.prototype.setYear ( year )

Note

几乎所有用途都首选 setFullYear 方法,因为它避免了“2000 年问题”。

此方法在被调用时执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. timedateObject.[[DateValue]]
  4. year 为 ? ToNumber(year)。
  5. 如果 timeNaN,将 time 设为 +0𝔽;否则将 time 设为 LocalTime(time)。
  6. fullYearMakeFullYear(year)。
  7. dayMakeDay(fullYear, MonthFromTime(time), DateFromTime(time))。
  8. dateMakeDate(day, TimeWithinDay(time))。
  9. utcTimestampTimeClip(UTC(date))。
  10. dateObject.[[DateValue]] 设为 utcTimestamp
  11. 返回 utcTimestamp

B.2.3.3 Date.prototype.toGMTString ( )

Note

toUTCString 方法是首选。此方法主要为兼容旧代码而提供。

"toGMTString" 属性的初始值是 %Date.prototype.toUTCString%,定义于 21.4.4.43

B.2.4 RegExp.prototype 对象的附加属性

B.2.4.1 RegExp.prototype.compile ( pattern, flags )

此方法在被调用时执行以下步骤:

  1. objthis 值。
  2. 执行 ? RequireInternalSlot(obj, [[RegExpMatcher]])。
  3. 如果 pattern 是 Object 且 pattern 具有 [[RegExpMatcher]] 内部槽,则
    1. 如果 flags 不是 undefined,抛出 TypeError 异常。
    2. flags 设为 pattern.[[OriginalFlags]]
    3. pattern 设为 pattern.[[OriginalSource]]
  4. 返回 ? RegExpInitialize(obj, pattern, flags)。
Note

此方法会用新的模式和标志完全重新初始化 this 值 RegExp。实现可以将对此方法的使用解释为一种断言,即所得 RegExp 对象将被多次使用,因此是额外优化的候选对象。

B.3 其他附加特性

B.3.1 带标签的函数声明

在 ECMAScript 2015 之前,LabelledStatement 的规范不允许将语句标签与 FunctionDeclaration 关联。然而,带标签的 FunctionDeclaration非严格代码中允许的扩展,并且大多数浏览器托管的 ECMAScript 实现都支持该扩展。在 ECMAScript 2015 及以后版本中,LabelledStatement 的语法产生式允许将 FunctionDeclaration 用作 LabelledItem,但 14.13.1 包含一个 Early Error 规则,如果发生这种情况会产生语法错误。随后修改该规则,以便在宿主支持此特性时,在非严格代码中抑制该语法错误。

Note

WithStatementIfStatementIterationStatement早期错误规则会阻止这些语句在非严格代码中包含带标签的 FunctionDeclaration

B.3.2 块级函数声明的 Web 遗留兼容性语义

在 ECMAScript 2015 之前,ECMAScript 规范没有定义 FunctionDeclaration 作为 Block 语句的 StatementList 元素出现的情况。然而,对这种 FunctionDeclaration 形式的支持是允许的扩展,并且大多数浏览器托管的 ECMAScript 实现都允许它们。不幸的是,这类声明的语义在这些实现之间有所不同。由于这些语义差异,使用 Block 级函数声明的现有 Web ECMAScript 源文本,只有当其用法仅依赖所有浏览器实现对此类声明的语义交集时,才可在浏览器实现之间移植。以下是落入该交集语义范围内的用例:

  1. 函数被声明且仅在单个块内被引用。

  2. 函数被声明且可能在单个 Block 内使用,但也被不包含在该同一 Block 内的内部函数定义引用。

  3. 函数被声明且可能在单个块内使用,但也在后续块中被引用。

第一个用例可与 ECMAScript 2015 提供的 Block 级函数声明语义互操作。任何采用该用例的既有 ECMAScript 源文本都将使用条款 101415 所定义的块级函数声明语义运行。

第二和第三个用例的 ECMAScript 2015 互操作性需要对条款 10、条款 15、条款 19.2.1 和条款 16.1.7 的语义进行以下扩展。

如果 ECMAScript 实现具有报告诊断警告消息的机制,则当代码包含适用了这些兼容性语义且引入了与非兼容性语义可观察差异的 FunctionDeclaration 时,应产生警告。例如,如果未引入 var 绑定是因为其引入会造成早期错误,则不应产生警告消息。

此特性在以下位置涉及特殊语义:

B.3.3 IfStatement 语句子句中的 FunctionDeclaration

以下内容扩充了 14.6 中的 IfStatement 产生式:

IfStatement[Yield, Await, Return] : if ( Expression[+In, ?Yield, ?Await] ) FunctionDeclaration[?Yield, ?Await, ~Default] else Statement[?Yield, ?Await, ?Return] if ( Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] else FunctionDeclaration[?Yield, ?Await, ~Default] if ( Expression[+In, ?Yield, ?Await] ) FunctionDeclaration[?Yield, ?Await, ~Default] else FunctionDeclaration[?Yield, ?Await, ~Default] if ( Expression[+In, ?Yield, ?Await] ) FunctionDeclaration[?Yield, ?Await, ~Default] [lookahead ≠ else]

此产生式仅在解析非严格代码时适用。与此产生式匹配的源文本会被处理为:每个匹配出现的 FunctionDeclaration[?Yield, ?Await, ~Default] 都是一个占据源文本中该位置的 BlockStatement 的唯一 StatementListItem。此类合成 BlockStatement 的语义包括 B.3.2 中规定的 Web 遗留兼容性语义。

B.3.4 Catch 块中的 VariableStatement

在此特性中,Catch 子句的 Block 可以包含绑定某个名称的 var 声明,而该名称也由 CatchParameter 绑定。这是通过修改 14.15.1 Catch : catch ( CatchParameter ) Block 的一个早期错误规则来实现的。

Note

运行时,此类绑定在 VariableDeclarationEnvironment 中实例化。它们不会遮蔽由 CatchParameter 引入的同名绑定,因此此类 var 声明的 Initializer 将赋值给对应的 catch 参数,而不是 var 绑定。

此修改后的行为也适用于由包含在 Catch 子句的 Block 内的直接 eval 调用引入的 varfunction 声明。此更改通过修改 EvalDeclarationInstantiation 中的步骤 3.d.i.2.a.i13.b.ii.4.a.i.i 来实现。

B.3.5 ForIn 语句头中的初始化器

以下内容扩充了 14.7.5 中的 ForInOfStatement 产生式:

ForInOfStatement[Yield, Await, Return] : for ( var BindingIdentifier[?Yield, ?Await] Initializer[~In, ?Yield, ?Await] in Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return]

此产生式仅在解析非严格代码时适用。

8.3.1ContainsDuplicateLabels静态语义扩充如下:

ForInOfStatement : for ( var BindingIdentifier Initializer in Expression ) Statement
  1. 返回 StatementlabelSet 为实参的 ContainsDuplicateLabels

8.3.2ContainsUndefinedBreakTarget静态语义扩充如下:

ForInOfStatement : for ( var BindingIdentifier Initializer in Expression ) Statement
  1. 返回 StatementlabelSet 为实参的 ContainsUndefinedBreakTarget

8.3.3ContainsUndefinedContinueTarget静态语义扩充如下:

ForInOfStatement : for ( var BindingIdentifier Initializer in Expression ) Statement
  1. 返回 StatementiterationSet 和 « » 为实参的 ContainsUndefinedContinueTarget

14.7.5.2IsDestructuring静态语义扩充如下:

BindingIdentifier : Identifier yield await
  1. 返回 false

8.2.6VarDeclaredNames静态语义扩充如下:

ForInOfStatement : for ( var BindingIdentifier Initializer in Expression ) Statement
  1. names1BindingIdentifierBoundNames
  2. names2StatementVarDeclaredNames
  3. 返回 names1names2列表连接

8.2.7VarScopedDeclarations静态语义扩充如下:

ForInOfStatement : for ( var BindingIdentifier Initializer in Expression ) Statement
  1. declarations1 为 « BindingIdentifier »。
  2. declarations2StatementVarScopedDeclarations
  3. 返回 declarations1declarations2列表连接

14.7.5.5ForInOfLoopEvaluation运行时语义扩充如下:

ForInOfStatement : for ( var BindingIdentifier Initializer in Expression ) Statement
  1. bindingIdBindingIdentifierStringValue
  2. lhs 为 ? ResolveBinding(bindingId)。
  3. 如果 IsAnonymousFunctionDefinition(Initializer) 为 true,则
    1. valueInitializerbindingId 为实参的 NamedEvaluation
  4. 否则,
    1. rhs 为 ? 对 Initializer 求值。
    2. value 为 ? GetValue(rhs)。
  5. 执行 ? PutValue(lhs, value)。
  6. keyResult 为 ? ForIn/OfHeadEvaluation(« », Expression, enumerate)。
  7. 返回 ? ForIn/OfBodyEvaluation(BindingIdentifier, Statement, keyResult, enumerate, var-binding, labelSet)。

B.3.6 [[IsHTMLDDA]] 内部槽

[[IsHTMLDDA]] 内部槽可以存在于宿主定义对象上。具有 [[IsHTMLDDA]] 内部槽的对象在 ToBooleanIsLooselyEqual 抽象操作中,以及用作 typeof 运算符的操作数时,表现得像 undefined

Note

具有 [[IsHTMLDDA]] 内部槽的对象从不会由本规范创建。然而,Web 浏览器中的 document.all 对象是一个具有此槽的宿主定义异质对象,它为 Web 兼容性目的而存在。除此 document.all 外,没有其他已知的此类对象示例,实现不应创建任何此类对象。

此特性在以下位置涉及特殊语义:

B.3.7 HostMakeJobCallback 中的非默认行为

HostMakeJobCallback 抽象操作允许作为 Web 浏览器的宿主指定非默认行为。

B.3.8 HostEnsureCanAddPrivateElement 中的非默认行为

HostEnsureCanAddPrivateElement 抽象操作允许作为 Web 浏览器的宿主指定非默认行为。

B.3.9 函数调用作为赋值目标时的运行时错误

当函数调用(13.3.6)在非严格代码中用作赋值目标时,不会产生早期错误,而是在赋值求值期间抛出 ReferenceError 异常。

Note

当赋值目标是 AssignmentExpressionLeftHandSideExpression 时,赋值运算符必须是 =AssignmentOperator;特别地,此处的允许并不适用于逻辑赋值运算符(??=&&=||=)。

AssignmentTargetType 中针对 CallExpression : CoverCallExpressionAndAsyncArrowHead CallExpression : CallExpression Arguments 的步骤 1

Annex C (informative) ECMAScript 的严格模式

严格模式限制和异常

Annex D (informative) 宿主分层点

宿主的定义见 4.2

D.1 宿主钩子

HostCallJobCallback(...)

HostEnqueueFinalizationRegistryCleanupJob(...)

HostEnqueueGenericJob(...)

HostEnqueuePromiseJob(...)

HostEnqueueTimeoutJob(...)

HostEnsureCanCompileStrings(...)

HostFinalizeImportMeta(...)

HostGetImportMetaProperties(...)

HostGrowSharedArrayBuffer(...)

HostHasSourceTextAvailable(...)

HostLoadImportedModule(...)

HostGetSupportedImportAttributes(...)

HostMakeJobCallback(...)

HostPromiseRejectionTracker(...)

HostResizeArrayBuffer(...)

InitializeHostDefinedRealm(...)

D.2 宿主定义字段

Realm Record 上的 [[HostDefined]]:见 Table 19

Script Record 上的 [[HostDefined]]:见 Table 34

Module Record 上的 [[HostDefined]]:见 Table 38

JobCallback Record 上的 [[HostDefined]]:见 Table 23

候选执行上的 [[HostSynchronizesWith]]:见 Table 97

[[IsHTMLDDA]]:见 B.3.6

D.3 宿主定义对象

全局对象:见条款 19

D.4 运行 Job

调用 Job Abstract Closure 之前的准备步骤和之后的清理步骤。见 9.5

D.5 异质对象的内部方法

对于本规范中未规定的任何异质对象Table 4 中的任一基本内部方法。

D.6 内置对象和方法

本规范中未定义的任何内置对象和方法,但受 17.1 中限制的除外。

Annex E (informative) ECMAScript 2015 中可能影响兼容性的修正和澄清

9.1.1.4.14-9.1.1.4.17 第 5 版和第 5.1 版使用属性存在性测试来确定与新全局声明对应的全局对象属性是否已存在。ECMAScript 2015 使用自有属性存在性测试。这对应于 Web 浏览器最常实现的行为。

10.4.2.1:第 5 版将当前数组长度的捕获移动到数组索引或新长度值的整数转换之前。然而,如果转换过程具有改变数组长度的副作用,被捕获的长度值可能会失效。ECMAScript 2015 规定,必须在这种副作用可能发生之后捕获当前数组长度。

21.4.1.31:先前版本允许 TimeClip 抽象操作返回 +0𝔽-0𝔽 作为 0 时间值的表示。ECMAScript 2015 规定始终返回 +0𝔽。这意味着对 ECMAScript 2015 而言,Date 的时间值永远不会可观察地为 -0𝔽,并且返回时间值的方法永远不会返回 -0𝔽

21.4.1.32:如果不存在 UTC 偏移表示,则使用本地时区。第 5.1 版错误地声明缺失的时区应解释为 "z"

21.4.4.36:如果年份无法使用 21.4.1.32 中指定的日期时间字符串格式表示,则抛出 RangeError 异常。先前版本没有规定这种情况的行为。

21.4.4.41:先前版本没有规定当时间值NaNDate.prototype.toString 返回的值。ECMAScript 2015 规定结果为 String 值 "Invalid Date"

22.2.4.122.2.6.13.1:RegExp 实例的 "source" 属性值中的任何 LineTerminator 码点必须使用转义序列表达。第 5.1 版只要求对 / 进行转义。

22.2.6.822.2.6.11:在先前版本中,对于模式实参是 global 标志被设置的 RegExp 值的情况,String.prototype.matchString.prototype.replace 的规范不正确。先前规范声明,对于每次尝试匹配该模式,如果 lastIndex 没有改变,则应将其递增 1。正确行为是仅当该模式匹配空 String 时才应将 lastIndex 递增 1。

23.1.3.30:先前版本没有规定 Array.prototype.sort 如何解释 comparator 返回的 NaN 值。ECMAScript 2015 规定这样的值被视为 comparator 返回了 +0𝔽。ECMAScript 2015 还规定,对 comparator 返回的结果应用 ToNumber。在先前版本中,非 Number 值comparator 结果的效果是实现定义的。实践中,实现会调用 ToNumber

Annex F (informative) 引入与先前版本不兼容的新增和更改

6.2.5:在 ECMAScript 2015 中,函数调用不允许返回 Reference Record

7.1.4.1:在 ECMAScript 2015 中,应用于 String 值的 ToNumber 现在会识别并转换 BinaryIntegerLiteralOctalIntegerLiteral 数值字符串。在先前版本中,这类字符串会被转换为 NaN

9.3:在 ECMAScript 2018 中,Template 对象基于 Parse Node(源位置)规范化,而不是像先前版本中那样跨一个 Realm 中该模板字面量或带标签模板的所有出现规范化。

12.2:在 ECMAScript 2016 中,强制要求 Unicode 8.0.0 或更高版本,而 ECMAScript 2015 强制要求 Unicode 5.1。特别是,这导致 U+180E MONGOLIAN VOWEL SEPARATOR 从 Space_Separator (Zs) 类别移动到 Format (Cf) 类别(自 Unicode 6.3.0 起),而它在 ECMAScript 2015 中被视为空白。这会导致对空白敏感的方法表现不同。例如,"\u180E".trim().length 在先前版本中为 0,但在 ECMAScript 2016 及以后版本中为 1。此外,ECMAScript 2017 强制要求始终使用 Unicode 标准的最新版本。

12.7:在 ECMAScript 2015 中,IdentifierName 的有效码点是根据 Unicode 属性 “ID_Start” 和 “ID_Continue” 指定的。在先前版本中,有效的 IdentifierNameIdentifier 码点通过枚举各种 Unicode 码点类别来指定。

12.10.1:在 ECMAScript 2015 中,如果 do-while 语句末尾缺少分号,自动分号插入会在其末尾添加分号。此更改使规范与大多数现有实现的实际行为保持一致。

13.2.5.1:在 ECMAScript 2015 中,Object Initializer 中存在重复属性名不再是早期错误

13.15.1:在 ECMAScript 2015 中,严格模式代码中对不可变绑定(例如 FunctionExpression 的函数名)的赋值不会产生早期错误,而是产生运行时错误。

14.2:在 ECMAScript 2015 中,以标记 let 开头,后跟输入元素 LineTerminator 再后跟 IdentifierStatementListLexicalDeclaration 的开始。在先前版本中,自动分号插入总会在 Identifier 输入元素之前插入分号。

14.5:在 ECMAScript 2015 中,以标记 let 开头,后跟标记 [StatementListItemLexicalDeclaration 的开始。在先前版本中,这样的序列会是 ExpressionStatement 的开始。

14.6.2:在 ECMAScript 2015 中,IfStatement 的 normal 结果永远不是值 empty。如果没有 Statement 部分被求值,或者被求值的 Statement 部分产生包含 empty 的 normal completion,则 IfStatement 的结果是 undefined

14.7:在 ECMAScript 2015 中,如果 for 语句的 ( 标记后紧跟标记序列 let [,则该 let 被视为 LexicalDeclaration 的开始。在先前版本中,这样的标记序列会是 Expression 的开始。

14.7:在 ECMAScript 2015 中,如果 for-in 语句的 ( 标记后紧跟标记序列 let [,则该 let 被视为 ForDeclaration 的开始。在先前版本中,这样的标记序列会是 LeftHandSideExpression 的开始。

14.7:在 ECMAScript 2015 之前,初始化表达式可以作为 in 关键字之前的 VariableDeclaration 的一部分出现。在 ECMAScript 2015 中,同一位置的 ForBinding 不允许出现这样的初始化器。在 ECMAScript 2017 中,仅在非严格代码中允许这样的初始化器。

14.7:在 ECMAScript 2015 中,对 IterationStatement 求值的结果永远不会是其 [[Value]]empty 的 normal completion。如果 IterationStatementStatement 部分未被求值,或者 Statement 部分的最终求值产生其 [[Value]]empty 的 normal completion,则对 IterationStatement 求值的结果是其 [[Value]]undefined 的 normal completion。

14.11.2:在 ECMAScript 2015 中,对 WithStatement 求值的结果永远不会是其 [[Value]]empty 的 normal completion。如果 WithStatementStatement 部分求值产生其 [[Value]]empty 的 normal completion,则对 WithStatement 求值的结果是其 [[Value]]undefined 的 normal completion。

14.12.4:在 ECMAScript 2015 中,对 SwitchStatement 求值的结果永远不会是其 [[Value]]empty 的 normal completion。如果 SwitchStatementCaseBlock 部分求值产生其 [[Value]]empty 的 normal completion,则对 SwitchStatement 求值的结果是其 [[Value]]undefined 的 normal completion。

14.15:在 ECMAScript 2015 中,Catch 子句包含一个与 Catch 子句参数相同 Identifiervar 声明是早期错误。在先前版本中,这样的变量声明会在外围变量环境中实例化,但该声明的 Initializer 值会赋给 Catch 参数。

14.1519.2.1.3:在 ECMAScript 2015 中,如果 Catch 子句求值一个非严格直接 eval,且其 eval 代码包含绑定与 Catch 子句参数相同 IdentifiervarFunctionDeclaration 声明,则会抛出运行时 SyntaxError

14.15.3:在 ECMAScript 2015 中,TryStatement 的结果永远不是值 empty。如果 TryStatementBlock 部分求值为包含 empty 的 normal completion,则 TryStatement 的结果是 undefined。如果 TryStatementBlock 部分求值为 throw completion,并且它有一个 Catch 部分求值为包含 empty 的 normal completion,则在没有 Finally 子句或其 Finally 子句求值为 empty normal completion 时,TryStatement 的结果是 undefined

15.4.5 在 ECMAScript 2015 中,作为 ObjectLiteral访问器属性 [[Get]][[Set]] 特性值创建的函数对象不是构造器函数,并且它们没有 "prototype" 自有属性。在先前版本中,它们是构造器并具有 "prototype" 属性。

20.1.2.6:在 ECMAScript 2015 中,如果 Object.freeze 的实参不是对象,则将其视为没有自有属性的不可扩展普通对象。在先前版本中,非对象实参总会导致抛出 TypeError

20.1.2.8:在 ECMAScript 2015 中,如果 Object.getOwnPropertyDescriptor 的实参不是对象,则会尝试使用 ToObject 强制转换该实参。如果强制转换成功,则结果会替代原始实参值使用。在先前版本中,非对象实参总会导致抛出 TypeError

20.1.2.10:在 ECMAScript 2015 中,如果 Object.getOwnPropertyNames 的实参不是对象,则会尝试使用 ToObject 强制转换该实参。如果强制转换成功,则结果会替代原始实参值使用。在先前版本中,非对象实参总会导致抛出 TypeError

20.1.2.12:在 ECMAScript 2015 中,如果 Object.getPrototypeOf 的实参不是对象,则会尝试使用 ToObject 强制转换该实参。如果强制转换成功,则结果会替代原始实参值使用。在先前版本中,非对象实参总会导致抛出 TypeError

20.1.2.16:在 ECMAScript 2015 中,如果 Object.isExtensible 的实参不是对象,则将其视为没有自有属性的不可扩展普通对象。在先前版本中,非对象实参总会导致抛出 TypeError

20.1.2.17:在 ECMAScript 2015 中,如果 Object.isFrozen 的实参不是对象,则将其视为没有自有属性的不可扩展普通对象。在先前版本中,非对象实参总会导致抛出 TypeError

20.1.2.18:在 ECMAScript 2015 中,如果 Object.isSealed 的实参不是对象,则将其视为没有自有属性的不可扩展普通对象。在先前版本中,非对象实参总会导致抛出 TypeError

20.1.2.19:在 ECMAScript 2015 中,如果 Object.keys 的实参不是对象,则会尝试使用 ToObject 强制转换该实参。如果强制转换成功,则结果会替代原始实参值使用。在先前版本中,非对象实参总会导致抛出 TypeError

20.1.2.20:在 ECMAScript 2015 中,如果 Object.preventExtensions 的实参不是对象,则将其视为没有自有属性的不可扩展普通对象。在先前版本中,非对象实参总会导致抛出 TypeError

20.1.2.22:在 ECMAScript 2015 中,如果 Object.seal 的实参不是对象,则将其视为没有自有属性的不可扩展普通对象。在先前版本中,非对象实参总会导致抛出 TypeError

20.2.3.2:在 ECMAScript 2015 中,绑定函数的 [[Prototype]] 内部槽被设置为其目标函数的 [[GetPrototypeOf]] 值。在先前版本中,[[Prototype]] 始终被设置为 %Function.prototype%

20.2.4.1:在 ECMAScript 2015 中,函数实例的 "length" 属性是可配置的。在先前版本中它是不可配置的。

20.5.6.2:在 ECMAScript 2015 中,NativeError 构造器[[Prototype]] 内部槽是 Error 构造器。在先前版本中它是 Function 原型对象

21.4.4 在 ECMAScript 2015 中,Date 原型对象不是 Date 实例。在先前版本中,它是 TimeValue 为 NaN 的 Date 实例。

22.1.3.12 在 ECMAScript 2015 中,String.prototype.localeCompare 函数必须将根据 Unicode 标准规范等价的 String 视为相同。在先前版本中,实现被允许忽略规范等价性,转而使用按位比较。

22.1.3.2822.1.3.30 在 ECMAScript 2015 中,小写/大写转换处理作用于码点。在先前版本中,此类转换处理仅应用于单个代码单元。唯一受影响的码点是 Unicode 的 Deseret 区块中的码点。

22.1.3.32 在 ECMAScript 2015 中,String.prototype.trim 方法被定义为识别可能存在于 Unicode BMP 之外的空白码点。然而,截至 Unicode 7 尚未定义这样的码点。在先前版本中,这样的码点不会被识别为空白。

22.2.4.1 在 ECMAScript 2015 中,如果 pattern 实参是 RegExp 实例且 flags 实参不是 undefined,则会创建一个新的 RegExp 实例,它与 pattern 相同,但 pattern 的标志被实参 flags 替换。在先前版本中,当 pattern 是 RegExp 实例且 flags 不是 undefined 时,会抛出 TypeError 异常。

22.2.6 在 ECMAScript 2015 中,RegExp 原型对象不是 RegExp 实例。在先前版本中,它是模式为空 String 的 RegExp 实例。

22.2.6 在 ECMAScript 2015 中,"source""global""ignoreCase""multiline" 是定义在 RegExp 原型对象上的访问器属性。在先前版本中,它们是定义在 RegExp 实例上的数据属性

25.4.15:在 ECMAScript 2019 中,Atomics.wake 已重命名为 Atomics.notify,以避免与 Atomics.wait 混淆。

27.1.5.427.6.3.6:在 ECMAScript 2019 中,await 入队的 Job 数量被减少,这可能在 then() 调用和 await 表达式之间的解析顺序上产生可观察差异。

参考文献

  1. IEEE 754-2019IEEE 浮点算术标准。Institute of Electrical and Electronic Engineers, New York (2019) Note

    IEEE 754-2008 与 IEEE 754-2019 之间不存在影响 ECMA-262 规范的规范性更改。

  2. Unicode 标准,可在 <https://unicode.org/versions/latest> 获取
  3. Unicode Technical Note #5:应用中的规范等价性,可在 <https://unicode.org/notes/tn5/> 获取
  4. Unicode Technical Standard #10:Unicode 排序算法,可在 <https://unicode.org/reports/tr10/> 获取
  5. Unicode Standard Annex #15,Unicode 规范化形式,可在 <https://unicode.org/reports/tr15/> 获取
  6. Unicode Standard Annex #18:Unicode 正则表达式,可在 <https://unicode.org/reports/tr18/> 获取
  7. Unicode Standard Annex #24:Unicode Script 属性,可在 <https://unicode.org/reports/tr24/> 获取
  8. Unicode Standard Annex #31,Unicode 标识符和模式语法,可在 <https://unicode.org/reports/tr31/> 获取
  9. Unicode Standard Annex #44:Unicode 字符数据库,可在 <https://unicode.org/reports/tr44/> 获取
  10. Unicode Technical Standard #51:Unicode Emoji,可在 <https://unicode.org/reports/tr51/> 获取
  11. IANA 时区数据库,可在 <https://www.iana.org/time-zones> 获取
  12. ISO 8601:2004(E) 数据元素和交换格式 — 信息交换 — 日期和时间表示法
  13. RFC 1738 “统一资源定位符 (URL)”,可在 <https://tools.ietf.org/html/rfc1738> 获取
  14. RFC 2396 “统一资源标识符 (URI):通用语法”,可在 <https://tools.ietf.org/html/rfc2396> 获取
  15. RFC 3629 “UTF-8,ISO 10646 的一种转换格式”,可在 <https://tools.ietf.org/html/rfc3629> 获取
  16. RFC 7231 “超文本传输协议 (HTTP/1.1):语义和内容”,可在 <https://tools.ietf.org/html/rfc7231> 获取

制作说明

本规范在 GitHub 上以一种称为 Ecmarkup 的纯文本源格式编写。Ecmarkup 是一种 HTML 和 Markdown 方言,它提供了一个框架和工具集,用于以纯文本编写 Ecma 规范,并将规范处理为遵循本文档编辑惯例的完整 HTML 渲染。Ecmarkup 构建于并集成了许多其他格式和技术,包括用于定义语法的 Grammarkdown 和用于编写算法步骤的 Ecmarkdown。本规范的 PDF 渲染使用利用 CSS Paged Media 规范的打印样式表生成,并使用 PrinceXML 转换。

本规范的先前版本使用 Word 编写——构成本版基础的 Ecmarkup 源文本是通过自动转换工具将 ECMAScript 2015 Word 文档转换为 Ecmarkup 而产生的。

Copyright & Software License

Ecma International

Rue du Rhone 114

CH-1204 Geneva

Tel: +41 22 849 6000

Fax: +41 22 849 6001

Web: https://ecma-international.org/

Software License

All Software contained in this document ("Software") is protected by copyright and is being made available under the "BSD License", included below. This Software may be subject to third party rights (rights from parties other than Ecma International), including patent rights, and no licenses under such third party rights are granted under this license even if the third party concerned is a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS AVAILABLE AT https://ecma-international.org/memento/codeofconduct.htm FOR INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO IMPLEMENT ECMA INTERNATIONAL STANDARDS.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  3. Neither the name of the authors nor Ecma International may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ECMA INTERNATIONAL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.