ECMA-262 草案 / 2025年5月19日
ECMAScript® 2026 语言规范
介绍
本 Ecma 标准定义了 ECMAScript 2026 语言。这是 ECMAScript 语言规范的第十七版。自 1997 年第一版发布以来,ECMAScript
已经发展成为世界上最广泛使用的通用编程语言之一。它最为人所知的是作为嵌入在 Web 浏览器中的语言,但也被广泛应用于服务器和嵌入式应用程序。
ECMAScript 基于几种原创技术,最著名的是 JavaScript(Netscape)和 JScript(Microsoft)。该语言由 Brendan Eich 在 Netscape
发明,首次出现在该公司的 Navigator 2.0 浏览器中。它出现在 Netscape 的所有后续浏览器中,以及从 Internet Explorer 3.0 开始的所有 Microsoft 浏览器中。
ECMAScript 语言规范的开发始于 1996 年 11 月。本 Ecma 标准的第一版于 1997 年 6 月由 Ecma 大会通过。
该 Ecma 标准已提交给 ISO/IEC JTC 1,按照快速通道程序通过,并于 1998 年 4 月批准为国际标准 ISO/IEC 16262。1998 年 6 月的 Ecma 大会批准了 ECMA-262
的第二版,以保持与 ISO/IEC 16262 完全一致。第一版和第二版之间的变化在性质上是编辑性的。
该标准的第三版引入了强大的正则表达式、更好的字符串处理、新的控制语句、try/catch 异常处理、更严格的错误定义、数值输出格式化以及为预期的未来语言增长而进行的小幅更改。ECMAScript 标准的第三版于
1999 年 12 月由 Ecma 大会通过,并于 2002 年 6 月作为 ISO/IEC 16262:2002 发布。
第三版发布后,ECMAScript 与万维网结合实现了大规模应用,成为几乎所有 Web 浏览器支持的编程语言。为开发 ECMAScript 第四版做了大量工作。然而,这项工作没有完成,也没有作为
ECMAScript 第四版发布,但其中一些内容被纳入了第六版的开发中。
ECMAScript 第五版(作为 ECMA-262 第 5 版发布)编纂了在浏览器实现中已经常见的语言规范的事实解释,并增加了对自第三版发布以来出现的新功能的支持。这些功能包括访问器属性 、对象的反射创建和检查、属性特性的程序控制、额外的数组操作函数、对 JSON
对象编码格式的支持,以及提供增强错误检查和程序安全性的严格模式。第五版于 2009 年 12 月由 Ecma 大会通过。
第五版已提交给 ISO/IEC JTC 1,按照快速通道程序通过,并批准为国际标准 ISO/IEC 16262:2011。ECMAScript 标准的 5.1 版纳入了小幅更正,与 ISO/IEC
16262:2011 文本相同。5.1 版于 2011 年 6 月由 Ecma 大会通过。
第六版的重点开发始于 2009 年,当时第五版正在准备发布。然而,这之前进行了大量的实验和语言增强设计工作,可以追溯到 1999
年第三版的发布。从很真实的意义上说,第六版的完成是十五年努力的顶峰。这一版的目标包括为大型应用程序、库创建以及将 ECMAScript
用作其他语言的编译目标提供更好的支持。它的一些主要增强功能包括模块、类声明、词法块作用域、迭代器 和生成器、用于异步编程的 promise、解构模式和适当的尾调用。ECMAScript
内置库得到扩展,支持额外的数据抽象,包括映射、集合和二进制数值数组,以及对字符串和正则表达式中 Unicode
补充字符的额外支持。内置功能也通过子类化变得可扩展。第六版为常规的、增量的语言和库增强提供了基础。第六版于 2015 年 6 月由大会通过。
ECMAScript 2016 是在 Ecma TC39 新的年度发布节奏和开放开发过程下发布的第一个 ECMAScript 版本。从 ECMAScript 2015 源文档构建了一个纯文本源文档,作为完全在
GitHub 上进一步开发的基础。在这个标准开发的一年中,提交了数百个拉取请求和问题,代表了数千个错误修复、编辑修复和其他改进。此外,还开发了许多软件工具来帮助这一工作,包括
Ecmarkup、Ecmarkdown 和 Grammarkdown。ES2016 还包括对新指数运算符的支持,并向 Array.prototype
添加了一个名为
includes
的新方法。
ECMAScript 2017 引入了异步函数、共享内存和原子操作,以及较小的语言和库增强、错误修复和编辑更新。异步函数通过为返回 promise
的函数提供语法来改善异步编程体验。共享内存和原子操作引入了新的内存模型 ,允许多代理 程序使用原子操作进行通信,确保即使在并行 CPU 上也有明确定义的执行顺序。它还包括 Object
上的新静态方法:Object.values
、Object.entries
和
Object.getOwnPropertyDescriptors
。
ECMAScript 2018 通过异步迭代器 协议和异步生成器引入了对异步迭代的支持。它还包括四个新的正则表达式功能:dotAll
标志、命名捕获组、Unicode 属性转义和后行断言。最后,它包括对象 rest 和展开属性。
ECMAScript 2019 引入了一些新的内置函数:Array.prototype
上用于扁平化数组的 flat
和
flatMap
,用于直接将 Object.entries
的返回值转换为新 Object 的
Object.fromEntries
,以及 String.prototype
上的 trimStart
和
trimEnd
,作为广泛实现但非标准的 String.prototype.trimLeft
和 trimRight
内置功能的更好命名替代品。此外,它还包括语法和语义的一些小更新。更新的语法包括可选的 catch 绑定参数,以及允许在字符串字面量中使用 U+2028(行分隔符)和 U+2029(段落分隔符)以与 JSON
保持一致。其他更新包括要求 Array.prototype.sort
为稳定排序,要求 JSON.stringify
无论输入如何都返回格式良好的
UTF-8,以及通过要求它返回相应的原始源文本或标准占位符来澄清 Function.prototype.toString
。
ECMAScript 2020,第 11 版,为字符串引入了 matchAll
方法,为全局正则表达式生成的所有匹配对象产生一个迭代器 ;import()
,一种使用动态说明符异步导入模块的语法;BigInt
,用于处理任意精度整数 的新数字原始类型;Promise.allSettled
,一个不会短路的新 Promise
组合器;globalThis
,访问全局 this
值的通用方式;专用的 export * as ns from 'module'
语法,用于在模块内使用;增加了 for-in
枚举顺序的标准化;import.meta
,一个在模块中可用的宿主 填充对象,可能包含关于模块的上下文信息;以及添加了两个新的语法功能来改善处理"nullish"值(undefined
或 null )的工作:空值合并,一个值选择运算符;以及可选链,一个属性访问和函数调用运算符,如果要访问/调用的值为 nullish,则会短路。
ECMAScript 2021,第 12 版,为字符串引入了 replaceAll
方法;Promise.any
,一个在输入值被满足时短路的 Promise
组合器;AggregateError
,一个同时表示多个错误的新 Error
类型;逻辑赋值运算符(??=
、&&=
、||=
);WeakRef
,用于引用目标对象而不阻止其被垃圾回收,以及
FinalizationRegistry
,用于管理目标对象被垃圾回收时执行的清理操作的注册和注销;数字字面量的分隔符(1_000
);以及
Array.prototype.sort
变得更加精确,减少了导致实现定义 的排序顺序 的情况。
ECMAScript 2022,第 13 版,引入了顶级 await
,允许在模块顶级使用该关键字 ;新的类元素:公共和私有实例字段、公共和私有静态字段、私有实例方法和访问器,以及私有静态方法和访问器;类内的静态块,用于执行每个类的评估初始化;#x in obj
语法,用于测试对象上私有字段的存在;通过 /d
标志的正则表达式匹配索引,提供匹配子字符串的开始和结束索引;Error
对象上的
cause
属性,可用于在错误中记录因果链;字符串、数组和 TypedArray 的 at
方法,允许相对索引;以及
Object.hasOwn
,Object.prototype.hasOwnProperty
的便捷替代品。
ECMAScript 2023,第 14 版,在 Array.prototype
和 TypedArray.prototype
上引入了
toSorted
、toReversed
、with
、findLast
和
findLastIndex
方法,以及 Array.prototype
上的 toSpliced
方法;增加了对文件开头
#!
注释的支持,以更好地促进可执行的 ECMAScript 文件;并允许在弱集合中使用大多数 Symbol 作为键。
ECMAScript 2024,第 15 版,增加了调整大小和传输 ArrayBuffer 和 SharedArrayBuffer 的功能;增加了新的 RegExp /v
标志,用于创建具有更高级功能的 RegExp 以处理字符串集合;并引入了用于构造 Promise 的 Promise.withResolvers
便捷方法,用于聚合数据的
Object.groupBy
和 Map.groupBy
方法,用于异步等待共享内存更改的 Atomics.waitAsync
方法,以及用于检查和确保字符串仅包含格式良好的 Unicode 的 String.prototype.isWellFormed
和
String.prototype.toWellFormed
方法。
ECMAScript 2025,第 16 版,添加了一个新的 Iterator
全局对象,带有相关的静态和原型方法,用于处理迭代器 ;向
Set.prototype
添加了用于对 Set 执行常见操作的方法;增加了对导入 JSON 模块的支持以及用于声明导入模块属性的语法;添加了用于转义字符串以在正则表达式中安全使用的
RegExp.escape
方法;添加了用于在正则表达式内内联启用和禁用修饰符标志的语法;添加了用于调用可能返回或可能不返回 Promise
的函数并确保结果始终为 Promise
的 Promise.try
方法;并添加了新的 Float16Array
TypedArray 类型以及相关的
DataView.prototype.getFloat16
、DataView.prototype.setFloat16
和
Math.f16round
方法。
代表众多组织的数十名个人在 Ecma TC39 内对本版本和以前版本的开发做出了非常重要的贡献。此外,已经形成了一个充满活力的社区来支持 TC39 的 ECMAScript
工作。这个社区审查了许多草案,提交了数千个错误报告,进行了实现实验,贡献了测试套件,并向全球开发者社区介绍了 ECMAScript。不幸的是,无法识别和承认每个为这一努力做出贡献的个人和组织。
Allen Wirfs-Brock
ECMA-262,项目编辑,第 6 版
Brian Terlson
ECMA-262,项目编辑,第 7 至第 10 版
Jordan Harband
ECMA-262,项目编辑,第 10 至第 12 版
Shu-yu Guo
ECMA-262,项目编辑,第 12 至第 16 版
Michael Ficarra
ECMA-262,项目编辑,第 12 至第 16 版
Kevin Gibbons
ECMA-262,项目编辑,第 12 至第 16 版
1 范围
本标准定义了 ECMAScript 2026 通用编程语言。
2 一致性
ECMAScript 的一致性实现必须提供并支持本规范中描述的所有类型、值、对象、属性、函数以及程序语法和语义。
ECMAScript 的一致性实现必须按照最新版本的 Unicode 标准和 ISO/IEC 10646 来解释源文本输入。
提供应用程序编程接口 (API) 的 ECMAScript 一致性实现,如果该 API 支持需要适应不同人类语言和国家使用的语言和文化约定的程序,则必须实现与本规范兼容的最新版本 ECMA-402
中定义的接口。
ECMAScript 的一致性实现可以提供本规范中描述的类型、值、对象、属性和函数之外的其他类型、值、对象、属性和函数。特别是,ECMAScript
的一致性实现可以为本规范中描述的对象提供本规范中未描述的属性以及这些属性的值。
ECMAScript 的一致性实现可以支持本规范中未描述的程序和正则表达式语法。特别是,ECMAScript 的一致性实现可以支持使用本规范子条款 12.7.2 中注明的任何"未来保留字 "的程序语法。
ECMAScript 的一致性实现不得实现子条款 17.1 中列为禁止扩展的任何扩展。
ECMAScript 的一致性实现不得重新定义任何不是实现定义 、实现近似 或宿主定义 的功能。
ECMAScript 的一致性实现可以选择实现或不实现规范可选 子条款。如果实现了任何规范可选行为,则必须实现包含规范可选条款中的所有行为。规范可选条款在本规范中用彩色框中的"规范可选"字样表示,如下所示。
2.1 示例规范可选条款标题
示例条款内容。
ECMAScript 的一致性实现必须实现遗留 子条款,除非它们也被标记为规范可选。遗留子条款中指定的所有语言功能和行为都具有一个或多个不良特征。然而,它们在现有应用程序中的持续使用阻止了它们从本规范中被移除。这些功能不被视为核心
ECMAScript 语言的一部分。程序员在编写新的 ECMAScript 代码时不应使用或假设这些功能和行为的存在。
2.2 示例遗留条款标题
示例条款内容。
2.3 示例遗留规范可选条款标题
示例条款内容。
3 规范性引用
以下引用文档对于本文档的应用是必不可少的。对于注明日期的引用,只适用所引用的版本。对于未注明日期的引用,适用引用文档的最新版本(包括任何修订)。
IEEE
754-2019 ,IEEE 浮点运算标准 。
Unicode 标准。
https://unicode.org/versions/latest
ISO/IEC 10646,信息技术 — 通用多八位编码字符集 (UCS) 加上修订 1:2005、修订 2:2006、修订 3:2008、修订 4:2008,以及其他修订和勘误,或后续版本。
ECMA-402,ECMAScript 国际化 API 规范 ,特指与本规范版本对应的年度版本。
https://www.ecma-international.org/publications-and-standards/standards/ecma-402/
ECMA-404,JSON 数据交换格式 。
https://www.ecma-international.org/publications-and-standards/standards/ecma-404/
4 概述
本节包含对 ECMAScript 语言的非规范性概述。
ECMAScript 是一种面向对象的编程语言,用于在宿主环境 中执行计算和操作计算对象。这里定义的 ECMAScript
并不打算在计算上自给自足;实际上,本规范中没有外部数据输入或计算结果输出的规定。相反,预期 ECMAScript
程序的计算环境不仅提供本规范中描述的对象和其他设施,还提供某些特定于环境的对象,其描述和行为超出了本规范的范围,除了指出它们可能提供某些可从 ECMAScript
程序访问的属性和某些可调用的函数。
ECMAScript
最初被设计用作脚本语言,但现已广泛用作通用编程语言。脚本语言 是一种编程语言,用于操作、自定义和自动化现有系统的设施。在这样的系统中,有用的功能已经通过用户界面可用,脚本语言是将该功能暴露给程序控制的机制。通过这种方式,现有系统被称为提供对象和设施的宿主环境 ,这完善了脚本语言的功能。脚本语言旨在供专业和非专业程序员使用。
ECMAScript 最初被设计为Web 脚本语言 ,提供在浏览器中活跃网页并作为基于 Web 的客户端-服务器架构的一部分执行服务器计算的机制。ECMAScript
现在用于为各种宿主环境 提供核心脚本功能。因此,核心语言在本文档中独立于任何特定的宿主环境 进行规定。
ECMAScript 的使用已经超越了简单的脚本编写,现在用于许多不同环境和规模中编程任务的全谱。随着 ECMAScript
使用的扩展,它提供的功能和设施也在扩展。ECMAScript 现在是一种功能齐全的通用编程语言。
4.1 Web 脚本
Web 浏览器为客户端计算提供 ECMAScript 宿主环境 ,例如,包括表示窗口、菜单、弹出窗口、对话框、文本区域、锚点、框架、历史记录、cookie
和输入/输出的对象。此外,宿主环境 提供了将脚本代码附加到事件(如焦点变化、页面和图像加载、卸载、错误和中止、选择、表单提交和鼠标操作)的方法。脚本代码出现在
HTML 中,显示的页面是用户界面元素和固定及计算文本和图像的组合。脚本代码对用户交互是响应式的,不需要主程序。
Web 服务器为服务器端计算提供不同的宿主环境 ,包括表示请求、客户端和文件的对象;以及锁定和共享数据的机制。通过同时使用浏览器端和服务器端脚本,可以在客户端和服务器之间分布计算,同时为基于
Web 的应用程序提供自定义用户界面。
每个支持 ECMAScript 的 Web 浏览器和服务器都提供自己的宿主环境 ,完成 ECMAScript 执行环境。
4.2 宿主和实现
为了帮助将 ECMAScript 集成到宿主环境 中,本规范将某些设施(例如,抽象操作 )的定义,无论是全部还是部分,推迟到本规范之外的来源。编辑上,本规范区分了以下几种推迟类型。
实现 是进一步定义附录 D 中列举的设施或那些标记为实现定义 或实现近似 的设施的外部来源。在非正式使用中,实现指的是具体的产物,如特定的
Web 浏览器。
实现定义 设施是将其定义推迟到外部来源而无需进一步限定的设施。本规范不对特定行为提出任何建议,符合规范的实现可以在本规范提出的约束内自由选择任何行为。
实现近似 设施是将其定义推迟到外部来源同时推荐理想行为的设施。虽然符合规范的实现可以在本规范提出的约束内自由选择任何行为,但鼓励它们努力接近理想。某些数学运算,如Math.exp
,是实现近似 的。
宿主 是进一步定义附录 D 中列出的设施但不进一步定义其他实现定义 或实现近似 设施的外部来源。在非正式使用中,宿主 指的是所有实现的集合,如所有 Web
浏览器的集合,它们通过附录 D 以相同方式与本规范接口。宿主 通常是外部规范,如 WHATWG HTML (https://html.spec.whatwg.org/ )。换句话说,宿主定义 的设施通常在外部规范中进一步定义。
宿主钩子 是全部或部分由外部来源定义的抽象操作。所有宿主钩子 必须在附录 D 中列出。宿主钩子 必须至少符合以下要求:
宿主定义 设施是将其定义推迟到外部来源而无需进一步限定并在附录 D 中列出的设施。不是宿主 的实现也可以为宿主定义 设施提供定义。
宿主环境 是对所有宿主定义 设施定义的特定选择。宿主环境 通常包括允许获取输入和提供输出的对象或函数,作为全局对象 的宿主定义 属性。
本规范遵循始终使用最具体术语的编辑约定。例如,如果一个设施是宿主定义 的,它不应该被称为实现定义 的。
宿主 和实现都可以通过语言类型、规范类型、抽象操作 、语法产生式、内置对象和本文定义的内置符号与本规范接口。
4.3 ECMAScript 概述
以下是 ECMAScript 的非正式概述——并非语言的所有部分都被描述。这个概述不是标准本身的一部分。
ECMAScript 是基于对象的:基本语言和宿主 设施由对象提供,ECMAScript 程序是一个通信对象的集群。在 ECMAScript
中,对象 是零个或多个属性 的集合,每个属性都有特性 ,这些特性决定了每个属性如何使用——例如,当属性的 Writable
特性设置为 false 时,执行的 ECMAScript
代码尝试将不同值赋给该属性的任何尝试都会失败。属性是容纳其他对象、原始值 或函数 的容器。原始值是以下内置类型之一的成员:Undefined 、Null 、Boolean 、Number 、BigInt 、String
和 Symbol ;对象是内置类型 Object 的成员;函数是可调用对象。通过属性与对象关联的函数称为方法 。
ECMAScript 定义了一个内置对象 集合,完善了 ECMAScript 实体的定义。这些内置对象包括全局对象 ;对语言的运行时语义 基础的对象,包括
Object
、Function
、Boolean
、Symbol
和各种
Error
对象;表示和操作数值的对象,包括 Math
、Number
和
Date
;文本处理对象 String
和 RegExp
;作为值的索引集合的对象,包括
Array
和九种不同类型的类型化数组,其元素都有特定的数值数据表示;键值集合,包括 Map
和
Set
对象;支持结构化数据的对象,包括 JSON
对象、ArrayBuffer
、SharedArrayBuffer
和 DataView
;支持控制抽象的对象,包括生成器函数和 Promise
对象;以及反射对象,包括
Proxy
和 Reflect
。
ECMAScript 还定义了一组内置操作符 。ECMAScript
操作符包括各种一元运算、乘法运算符、加法运算符、按位移位运算符、关系运算符、相等运算符、二元按位运算符、二元逻辑运算符、赋值运算符和逗号运算符。
大型 ECMAScript 程序由模块 支持,模块允许程序被分为多个语句和声明序列。每个模块明确标识它使用的需要由其他模块提供的声明,以及它的哪些声明可供其他模块使用。
ECMAScript 语法有意类似 Java 语法。ECMAScript
语法被放宽以使其能够作为易于使用的脚本语言。例如,变量不需要声明其类型,类型也不与属性关联,定义的函数不需要在调用之前在文本上出现其声明。
4.3.1 对象
尽管 ECMAScript 包含类定义的语法,但 ECMAScript 对象在根本上不是基于类的,如 C++、Smalltalk 或 Java
中的对象。相反,对象可以通过各种方式创建,包括通过字面量表示法或通过构造函数 ,构造函数创建对象然后执行代码,通过为其属性分配初始值来初始化全部或部分对象。每个构造函数 是具有名为
"prototype" 属性的函数,该属性用于实现基于原型的继承 和共享属性 。对象通过在 new
表达式中使用构造函数 创建;例如,new Date(2009, 11)
创建一个新的
Date 对象。在不使用 new 的情况下调用构造函数 的后果取决于构造函数 。例如,Date()
产生当前日期和时间的字符串表示,而不是对象。
每个由构造函数 创建的对象都有一个对其构造函数 的
"prototype"
属性值的隐式引用(称为对象的原型 )。此外,原型可能有一个对其原型的非null 隐式引用,以此类推;这称为原型链 。当对对象中的属性进行引用时,该引用是对原型链中包含该名称属性的第一个对象中该名称的属性的引用。换句话说,首先检查直接提到的对象是否有这样的属性;如果该对象包含命名属性,那就是引用所指的属性;如果该对象不包含命名属性,则接下来检查该对象的原型;以此类推。
图 1:对象/原型关系
在基于类的面向对象语言中,一般来说,状态由实例承载,方法由类承载,继承只是结构和行为的继承。在 ECMAScript 中,状态和方法由对象承载,而结构、行为和状态都被继承。
所有不直接包含其原型包含的特定属性的对象都共享该属性及其值。图 1 说明了这一点:
CF 是一个构造函数 (也是一个对象)。使用 new
表达式创建了五个对象:cf1 、cf2 、cf3 、cf4
和 cf5 。这些对象中的每一个都包含名为 "q1" 和 "q2"
的属性。虚线表示隐式原型关系;例如,cf3 的原型是 CFp 。构造函数
CF 本身有两个属性,名为 "P1" 和 "P2" ,这些属性对
CFp 、cf1 、cf2 、cf3 、cf4
或 cf5 是不可见的。CFp 中名为 "CFP1" 的属性被
cf1 、cf2 、cf3 、cf4 和
cf5 (但不是 CF )共享,以及在 CFp
的隐式原型链中找到的不名为 "q1" 、"q2" 或 "CFP1"
的任何属性。注意 CF 和 CFp 之间没有隐式原型链接。
与大多数基于类的对象语言不同,可以通过为对象赋值来动态添加属性。也就是说,构造函数 不需要命名或为构造对象的所有或任何属性赋值。在上图中,可以通过为
CFp 中的属性赋新值来为
cf1 、cf2 、cf3 、cf4
和 cf5 添加新的共享属性。
虽然 ECMAScript 对象本质上不是基于类的,但基于构造函数 函数、原型对象和方法的常见模式定义类似类的抽象通常是方便的。ECMAScript
内置对象本身遵循这样的类似类的模式。从 ECMAScript 2015 开始,ECMAScript
语言包括语法类定义,允许程序员简洁地定义符合内置对象使用的相同类似类抽象模式的对象。
4.3.2 ECMAScript 的严格变体
ECMAScript
语言认识到一些语言用户可能希望限制使用语言中可用的某些功能的可能性。他们可能出于安全考虑、避免他们认为容易出错的功能、获得增强的错误检查或其他他们选择的原因而这样做。为了支持这种可能性,ECMAScript
定义了语言的严格变体。语言的严格变体排除了常规 ECMAScript
语言的一些特定语法和语义功能,并修改了一些功能的详细语义。严格变体还指定了必须通过在非严格形式的语言未指定为错误的情况下抛出错误异常来报告的额外错误条件。
ECMAScript 的严格变体通常被称为语言的严格模式 。严格模式的选择和使用以及 ECMAScript 的严格模式语法和语义在个别ECMAScript
源文本 单元级别上明确进行,如 11.2.2
中所述。因为严格模式在语法源文本单元级别上被选择,严格模式只施加在这样的源文本单元内具有局部效果的限制。严格模式不限制或修改必须在多个源文本单元中一致运行的
ECMAScript 语义的任何方面。完整的 ECMAScript 程序可以由严格模式和非严格模式ECMAScript
源文本 单元组成。在这种情况下,严格模式只在实际执行在严格模式源文本单元中定义的代码时应用。
为了符合本规范,ECMAScript 实现必须实现完整的无限制 ECMAScript 语言和本规范定义的 ECMAScript
语言的严格变体。此外,实现必须支持将无限制和严格模式源文本单元组合到单个复合程序中。
4.4 术语和定义
就本文档而言,以下术语和定义适用。
4.4.1 实现近似
实现近似 设施是全部或部分由外部来源定义但在本规范中具有推荐的理想行为的设施
4.4.2 实现定义
实现定义 设施是全部或部分由本规范外部来源定义的设施
4.4.3 宿主定义
与实现定义 相同
注
4.4.4 类型
如条款 6 中定义的数据值集合
4.4.5 原始值
Undefined、Null、Boolean、Number、BigInt、Symbol 或 String 类型之一的成员,如条款 6 中定义
注
4.4.6 对象
Object 类型的成员
注
对象是属性的集合,并且有一个原型对象。原型可能是 null 。
4.4.7 构造函数
创建和初始化对象的函数对象
注
构造函数 的
"prototype" 属性的值是用于实现继承和共享属性的原型对象。
4.4.8 原型
为其他对象提供共享属性的对象
注
当构造函数 创建对象时,该对象隐式引用构造函数 的
"prototype" 属性以解决属性引用。构造函数 的 "prototype"
属性可以通过程序表达式 constructor .prototype
引用,添加到对象原型的属性通过继承被所有共享该原型的对象共享。或者,可以使用 Object.create
内置函数创建具有明确指定原型的新对象。
4.4.9 普通对象
对于所有对象必须支持的基本内部方法具有默认行为的对象
4.4.10 异质对象
对于一个或多个基本内部方法没有默认行为的对象
注
4.4.11 标准对象
语义由本规范定义的对象
4.4.12 内置对象
由 ECMAScript 实现指定和提供的对象
注
标准内置对象在本规范中定义。ECMAScript 实现可以指定和提供本规范中未描述的其他类型的内置对象。
4.4.13 undefined 值
在变量未被赋值时使用的原始值
4.4.14 Undefined 类型
唯一值为 undefined 值的类型
4.4.15 null 值
表示故意缺少任何对象值的原始值
4.4.16 Null 类型
唯一值为 null 值的类型
4.4.17 Boolean 值
Boolean 类型 的成员
注
只有两个 Boolean 值,true 和 false 。
4.4.18 Boolean 类型
由原始值 true 和 false 组成的类型
4.4.19 Boolean 对象
Object
类型 的成员,是标准内置
Boolean 构造函数 的实例
注
Boolean 对象通过在 new
表达式中使用 Boolean 构造函数 创建,提供 Boolean
值作为参数。生成的对象有一个内部槽,其值是 Boolean 值。Boolean 对象可以被强制转换为 Boolean 值。
4.4.20 String 值
原始值,是零个或多个 16 位无符号整数 值的有限 有序序列
注
String 值是String
类型 的成员。序列中的每个整数 值通常表示 UTF-16
文本的单个 16 位单元。但是,ECMAScript 对值没有任何限制或要求,除了它们必须是 16 位无符号整数 。
4.4.21 String 类型
所有可能 String 值的集合
4.4.22 String 对象
Object
类型 的成员,是标准内置
String 构造函数 的实例
注
String 对象通过在 new
表达式中使用 String 构造函数 创建,提供 String
值作为参数。生成的对象有一个内部槽,其值是 String 值。String 对象可以通过调用 String 构造函数 作为函数被强制转换为 String
值(22.1.1.1 )。
4.4.23 Number 值
对应于双精度 64 位二进制格式 IEEE 754-2019 值的原始值
注
Number 值是Number
类型 的成员,是数字的直接表示。
4.4.24 Number 类型
所有可能 Number 值的集合,包括 NaN ("非数字")、+∞ 𝔽 (正无穷大)和
-∞ 𝔽 (负无穷大)
4.4.25 Number 对象
Object
类型 的成员,是标准内置
Number 构造函数 的实例
注
Number 对象通过在 new
表达式中使用 Number 构造函数 创建,提供 Number
值作为参数。生成的对象有一个内部槽,其值是 Number 值。Number 对象可以通过调用 Number 构造函数 作为函数被强制转换为 Number
值(21.1.1.1 )。
4.4.26 Infinity
正无限 Number 值的 Number 值
4.4.27 NaN
IEEE
754-2019 NaN("非数字")值的 Number 值
4.4.28 BigInt 值
对应于任意精度整数 值的原始值
4.4.29 BigInt 类型
所有可能 BigInt 值的集合
4.4.30 BigInt 对象
Object
类型 的成员,是标准内置
BigInt 构造函数 的实例
4.4.31 Symbol 值
表示唯一、非 String 对象属性键 的原始值
4.4.32 Symbol 类型
所有可能 Symbol 值的集合
4.4.33 Symbol 对象
Object
类型 的成员,是标准内置
Symbol 构造函数 的实例
4.4.34 函数
Object
类型 的成员,可以作为子程序调用
注
除了其属性外,函数包含可执行代码和状态,这些决定了调用时的行为。函数的代码可能用 ECMAScript 编写,也可能不是。
4.4.35 内置函数
是函数的内置对象
注
内置函数的例子包括 parseInt
和 Math.exp
。宿主 或实现可能提供本规范中未描述的其他内置函数。
4.4.36 内置构造函数
是构造函数 的内置函数
注
内置构造函数 的例子包括
Object
和 Function
。宿主 或实现可能提供本规范中未描述的其他内置构造函数 。
4.4.37 属性
对象的一部分,将键(String 值或 Symbol 值)与值关联
注
根据属性的形式,值可以直接表示为数据值(原始值、对象或函数对象 )或间接通过一对访问器函数表示。
4.4.38 方法
作为属性值的函数
注
当函数作为对象的方法调用时,对象作为其 this 值传递给函数。
4.4.39 内置方法
是内置函数的方法
注
标准内置方法在本规范中定义。宿主 或实现可能提供本规范中未描述的其他内置方法。
4.4.40 特性
定义属性某些特征的内部值
4.4.41 自有属性
直接包含在其对象中的属性
4.4.42 继承属性
对象的属性,不是自有属性但是对象原型的属性(自有或继承)
4.5 本规范的组织结构
本规范的其余部分组织如下:
章节 5 定义了整个规范中使用的记号约定。
章节 6 到 10 定义了 ECMAScript
程序运行的执行环境。
章节 11 到 17 定义了实际的 ECMAScript
编程语言,包括其语法编码和所有语言功能的执行语义。
章节 18 到 28 定义了 ECMAScript
标准库。它们包括所有标准对象的定义,这些对象可供 ECMAScript 程序在执行时使用。
章节 29
描述了对 SharedArrayBuffer 支持的内存的访问的内存一致性模型以及 Atomics 对象的方法。
5 记号约定
5.1 语法和词法文法
5.1.1 上下文无关文法
上下文无关文法 由若干产生式 组成。每个产生式的左侧 有一个称为非终结符 的抽象符号,右侧 是零个或多个非终结符和终结符 符号的序列。对于每个文法,终结符都从指定的字母表中选取。
链式产生式 是在其右侧恰好有一个非终结符号以及零个或多个终结符的产生式。
从一个由单一特殊非终结符组成的句子开始,称为目标符号 ,给定的上下文无关文法指定一种语言 ,即,通过反复将序列中的任何非终结符替换为以该非终结符作为左侧的产生式的右侧,可能产生的终结符序列的(可能无限的)集合。
5.1.2 词法和 RegExp 文法
ECMAScript 的词法文法 在 第 12
条 中给出。该文法以符合 11.1 中定义的 SourceCharacter 规则的 Unicode
码点作为其终结符。它定义了一组产生式,从目标符号 InputElementDiv 、InputElementTemplateTail 、InputElementRegExp 、InputElementRegExpOrTemplateTail
或 InputElementHashbangOrRegExp
开始,这些产生式描述了此类码点序列如何转换为输入元素序列。
除空白和注释之外的输入元素构成了 ECMAScript 句法文法的终结符,并被称为 ECMAScript 标记 。这些标记是 ECMAScript 语言的保留字 、标识符、字面量和标点符号。此外,行终止符虽然不被视作标记,但也成为输入元素流的一部分,并指导自动分号插入(12.10 )的过程。简单的空白和单行注释会被丢弃,不会出现在句法文法的输入元素流中。如果
MultiLineComment (即形式为
/*
…*/
的注释,无论其是否跨越多行)不包含行终止符,则同样会被简单丢弃;但如果 MultiLineComment
包含一个或多个行终止符,则它会被替换为单个行终止符,该行终止符成为句法文法输入元素流的一部分。
ECMAScript 的 RegExp 文法 在章节 22.2.1 中给出。此文法的终结符也是由 SourceCharacter 定义的代码点。它定义了一组产生式,从目标符号 Pattern 开始,描述如何将代码点序列转换为正则表达式模式。
词法文法和 RegExp 文法的产生式以两个冒号":: "作为分隔标点符号来区分。词法文法和 RegExp 文法共享一些产生式。
5.1.3 数值字符串文法
数值字符串文法 出现在章节 7.1.4.1 中。它以 SourceCharacter
作为终结符,用于从目标符号 StringNumericLiteral
开始将字符串转换为数值(这与数值字面量的词法文法 相似但不同)。
数值字符串文法的产生式以三个冒号"::: "作为标点符号来区分,从不用于解析源文本。
5.1.4 语法文法
ECMAScript 的语法文法 在章节 13 到 16 中给出。此文法以词法文法定义的
ECMAScript 标记作为终结符(5.1.2 )。它定义了一组产生式,从两个可选的目标符号 Script 和 Module 开始,描述标记序列如何构成语法上正确的 ECMAScript 程序独立组件。
当代码点流要被解析为 ECMAScript Script 或
Module
时,首先通过反复应用词法文法将其转换为输入元素流;然后通过单次应用语法文法解析此输入元素流。如果输入元素流中的标记无法解析为目标非终结符(Script 或 Module )的单个实例且没有剩余标记,则输入流在语法上是错误的。
当解析成功时,它构造一个解析树 ,这是一个根树结构,其中每个节点都是一个解析节点 。每个解析节点是文法中符号的一个实例 ;它表示可以从该符号派生的源文本范围。表示整个源文本的解析树根节点是解析的目标符号 的实例。当解析节点是非终结符的实例时,它也是以该非终结符作为左侧的某个产生式的实例。此外,它有零个或多个子节点 ,对应产生式右侧的每个符号:每个子节点都是对应符号实例的解析节点。
为每次解析器调用实例化新的解析节点,即使是相同源文本的解析也从不重用。当且仅当解析节点表示相同的源文本范围、是相同文法符号的实例且来自相同的解析器调用时,才被认为是同一个解析节点 。
注 1
多次解析相同的字符串将导致不同的解析节点。例如,考虑:
let str = "1 + 1;" ;
eval (str);
eval (str);
每次调用 eval
都将 str
的值转换为 ECMAScript
源文本 并执行独立的解析,创建自己独立的解析节点树。即使每次解析都操作从相同字符串值派生的源文本,这些树也是不同的。
注 2
解析节点是规范产物,实现不需要使用类似的数据结构。
语法文法的产生式以仅一个冒号": "作为标点符号来区分。
章节 13 到 16
中呈现的语法文法并不完整地说明哪些标记序列被接受为正确的 ECMAScript Script 或 Module 。某些额外的标记序列也被接受,即那些如果只在序列的某些位置(如行结束符字符之前)添加分号就会被文法描述的序列。此外,如果行结束符字符出现在某些"尴尬"位置,那么文法描述的某些标记序列不被认为是可接受的。
在某些情况下,为了避免歧义,语法文法使用广义产生式,允许不构成有效 ECMAScript Script 或 Module
的标记序列。例如,这种技术用于对象字面量和对象解构模式。在这种情况下,提供更严格的补充文法 来进一步限制可接受的标记序列。通常,早期错误 规则会声明,在某些上下文中,"P 必须覆盖 一个 N ",其中 P 是解析节点(广义产生式的实例),N
是补充文法中的非终结符。这意味着:
最初由 P 匹配的标记序列使用 N 作为目标符号 重新解析。如果
N 接受文法参数,则设置为最初解析 P 时使用的相同值。
如果标记序列可以解析为 N 的单个实例且没有剩余标记,则:
我们将 N 的该实例(对于给定的 P 是唯一的解析节点)称为"被 P 覆盖 的 N "。
N 及其派生产生式的所有早期错误规则也适用于被 P 覆盖的 N 。
否则(如果解析失败),这是早期语法错误。
5.1.5 文法符号
5.1.5.1 终结符号
在 ECMAScript 文法中,一些终结符号以 固定宽度
字体显示。
这些符号必须在源文本中完全按照所写的方式出现。以这种方式指定的所有终结符号代码点
都应理解为来自基本拉丁块的适当 Unicode 代码点,而不是来自其他 Unicode 范围的任何类似代码点。
终结符号中的代码点不能用 \
UnicodeEscapeSequence 表示。
在终结符号为单个 Unicode 代码点的文法中(即词法、正则表达式和数字字符串文法),
产生式中出现的多个连续固定宽度代码点是相同代码点序列的简写,
写作独立的终结符号。
例如,产生式:
HexIntegerLiteral
::
0x
HexDigits
是以下的简写:
HexIntegerLiteral
::
0
x
HexDigits
相比之下,在语法文法中,连续的固定宽度代码点是单个终结符号。
终结符号有另外两种形式:
5.1.5.2 非终结符号和产生式
非终结符号以 斜体 显示。非终结符的定义(也称为"产生式")
由要定义的非终结符的名称后跟一个或多个冒号引入。(冒号的数量表示产生式属于哪个文法。)
然后在后续行中跟随非终结符的一个或多个可选右侧。例如,语法定义:
WhileStatement
:
while
(
Expression
)
Statement
表示非终结符 WhileStatement 代表
token while
,后跟左括号 token,后跟 Expression ,后跟右
括号 token,后跟 Statement 。Expression 和 Statement 的出现本身就是
非终结符。另一个例子,语法定义:
ArgumentList
:
AssignmentExpression
ArgumentList
,
AssignmentExpression
表示 ArgumentList 可以代表
单个 AssignmentExpression ,或者 ArgumentList
后跟逗号,后跟 AssignmentExpression 。这个
ArgumentList 的定义是递归的,
即它是根据自身定义的。结果是 ArgumentList 可以包含任意
正数个参数,用逗号分隔,其中每个参数表达式都是 AssignmentExpression 。这种非终结符的递归定义很常见。
5.1.5.3 可选符号
下标后缀 "opt " 可能出现在终结符或非终结符之后,表示可选符号。
包含可选符号的选择实际上指定了两个右侧,一个省略可选元素,一个包含它。这意味着:
VariableDeclaration
:
BindingIdentifier
Initializer opt
是以下的便利缩写:
VariableDeclaration
:
BindingIdentifier
BindingIdentifier
Initializer
并且:
ForStatement
:
for
(
LexicalDeclaration
Expression opt
;
Expression opt
)
Statement
是以下的便利缩写:
ForStatement
:
for
(
LexicalDeclaration
;
Expression opt
)
Statement
for
(
LexicalDeclaration
Expression
;
Expression opt
)
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 是否为结果标记序列的前缀,则认为这是编辑错误。
如果短语 "[no LineTerminator
here]" 出现在语法文法产生式的右侧,它表示该产生式是受限产生式 :如果在输入流的指定位置出现 LineTerminator ,则不能使用该产生式。例如,产生式:
ThrowStatement
:
throw
[no LineTerminator here]
Expression
;
表示如果在脚本的 throw
标记和 Expression 之间出现 LineTerminator ,则不能使用该产生式。
除非受限产生式禁止出现 LineTerminator ,否则在输入元素流中任意两个连续标记之间可以出现任意数量的
LineTerminator ,而不会影响脚本的语法可接受性。
5.1.5.9 but not
产生式的右侧可以通过使用短语 "but not " 然后指出要排除的展开来指定某些展开是不被允许的。例如,产生式:
Identifier
::
IdentifierName
but not ReservedWord
意味着非终结符 Identifier 可以被任何能够替换 IdentifierName
的代码点序列所替换,但前提是相同的代码点序列不能替换 ReservedWord 。
5.1.5.10 描述性短语
最后,少数非终结符通过无衬线字体的描述性短语来描述,这是在列出所有选择不切实际的情况下:
SourceCharacter
::
any Unicode code point
5.2 算法约定
本规范通常使用编号列表来指定算法中的步骤。这些算法用于精确指定 ECMAScript 语言构造所需的语义。这些算法并非旨在暗示使用任何特定的实现技术。实际上,可能存在更有效的算法来实现给定的特性。
算法可以使用有序的、逗号分隔的别名序列进行显式参数化,这些别名可以在算法步骤中用于引用在该位置传入的参数。可选参数用方括号([ , name
])表示,在算法步骤中与必需参数没有区别。剩余参数可以出现在参数列表的末尾,用前导省略号(, ...name )表示。剩余参数将捕获在必需参数和可选参数之后提供的所有参数到一个
列表 中。如果没有此类附加参数,则该 列表 为空。
算法步骤可以细分为顺序的子步骤。子步骤是缩进的,并且它们本身可以进一步划分为缩进的子步骤。使用大纲编号约定来标识子步骤,第一级子步骤用小写字母标记,第二级子步骤用小写罗马数字标记。如果需要三个以上的级别,则这些规则会重复,第四级使用数字标签。例如:
顶层步骤
子步骤。
子步骤。
子子步骤。
子子子步骤
子子子子步骤
子子子子子步骤
一个步骤或子步骤可以写成一个“if”谓词,该谓词对其子步骤进行条件限制。在这种情况下,仅当谓词为真时才应用子步骤。如果一个步骤或子步骤以单词“else”开头,则它是一个谓词,该谓词是同一级别上在前的“if”谓词步骤的否定。
一个步骤可以指定其子步骤的迭代应用。
以“断言 :”开头的步骤断言其算法的不变条件。此类断言用于明确算法中否则将是隐式的不变量。此类断言不增加额外的语义要求,因此实现无需检查。它们仅用于阐明算法。
算法步骤可以使用“令 x 为 someValue ”的形式为任何值声明命名别名。这些别名是引用式的,即 x 和
someValue 都引用相同的基础数据,对其中任何一个的修改对两者都可见。希望避免这种引用式行为的算法步骤应显式复制右侧的值:“令 x 为
someValue 的副本”会创建 someValue 的浅拷贝。
一旦声明,别名就可以在任何后续步骤中引用,并且不得在别名声明之前的步骤中引用。可以使用“将 x 设置为 someOtherValue ”的形式修改别名。
5.2.1 抽象操作
为了便于在规范的多个部分中使用,一些算法(称为抽象操作 )被命名并以参数化函数形式编写,以便可以从其他算法中按名称引用它们。抽象操作通常使用函数应用样式(如
OperationName(arg1 , arg2 ))进行引用。一些抽象操作被视为类规范抽象的多态分派方法。此类方法式抽象操作通常使用方法应用样式(如
someValue .OperationName(arg1 , arg2 ))进行引用。
5.2.2 语法导向操作
语法导向操作 是一种命名操作,其定义由算法组成,每个算法都与 ECMAScript
语法中的一个或多个产生式相关联。具有多个备选定义的产生式通常会为每个备选方案提供一个不同的算法。当算法与语法产生式相关联时,它可以像引用算法参数一样引用产生式备选方案的终结符和非终结符。以这种方式使用时,非终结符指的是解析源文本时匹配的实际备选定义。语法产生式或由其派生的
解析节点 匹配的源文本 是源文本中从参与匹配的第一个终结符的开头开始到参与匹配的最后一个终结符的结尾结束的部分。
当算法与产生式备选方案相关联时,该备选方案通常不带任何“[ ]”语法注释。此类注释仅影响备选方案的语法识别,对备选方案的相关语义没有影响。
语法导向操作通过使用以下算法中的步骤 1 、3 和 4 的约定,使用解析节点以及可选的其他参数来调用:
令 status 为
SomeNonTerminal 的 SyntaxDirectedOperation。
令 someParseNode 为某个源文本的解析结果。
执行 someParseNode 的
SyntaxDirectedOperation。
执行 someParseNode 的
SyntaxDirectedOperation,参数为 "value" 。
除非另有明确规定,否则所有 链式产生式 对于可能应用于该产生式左侧非终结符的每个操作都有一个隐式定义。该隐式定义只是将相同的操作(以及任何参数)重新应用于链式产生式 的唯一右侧非终结符,然后返回结果。例如,假设某个算法有一个步骤的形式为:“返回
块 的 求值 ”,并且有一个产生式:
块 :
{
语句列表
}
但是 求值
操作没有将算法与该产生式关联起来。在这种情况下,求值 操作隐式地包含一个形式如下的关联:
运行时语义:求值
块 :
{
语句列表
}
返回 语句列表 的 求值 。
5.2.3 运行时语义
指定必须在运行时调用的语义的算法称为运行时语义 。运行时语义由 抽象操作 或 语法导向操作 定义。
5.2.3.1 Completion ( completionRecord )
抽象操作 Completion 接受参数 completionRecord (一个 完成记录 )并返回一个 完成记录 。它用于强调正在返回一个
完成记录 。调用时它执行以下步骤:
断言 :completionRecord 是一个 完成记录 。
返回 completionRecord 。
5.2.3.2 抛出异常
算法步骤中说要抛出异常,例如:
抛出一个 TypeError 异常。
与以下含义相同:
返回 ThrowCompletion (一个新创建的
TypeError 对象)。
5.2.3.3 ReturnIfAbrupt
算法步骤中说或等效于:
ReturnIfAbrupt (argument )。
与以下含义相同:
断言 :argument 是一个 完成记录 。
如果 argument 是一个 突然完成 ,则返回
Completion (argument )。
否则,将 argument 设置为 argument .[[Value]] 。
算法步骤中说或等效于:
ReturnIfAbrupt (AbstractOperation())。
与以下含义相同:
令 hygienicTemp 为 AbstractOperation()。
断言 :hygienicTemp 是一个 完成记录 。
如果 hygienicTemp 是一个 突然完成 ,则返回
Completion (hygienicTemp )。
否则,将 hygienicTemp 设置为 hygienicTemp .[[Value]] 。
其中 hygienicTemp 是临时的,并且仅在与 ReturnIfAbrupt 相关的步骤中可见。
算法步骤中说或等效于:
令 result 为 AbstractOperation(ReturnIfAbrupt (argument ))。
与以下含义相同:
断言 :argument 是一个 完成记录 。
如果 argument 是一个 突然完成 ,则返回
Completion (argument )。
否则,将 argument 设置为 argument .[[Value]] 。
令 result 为 AbstractOperation(argument )。
5.2.3.4 ReturnIfAbrupt 简写
以 ?
为前缀的 抽象操作 和 语法导向操作 的调用表示应将
ReturnIfAbrupt 应用于结果 完成记录 。例如,步骤:
? OperationName()。
等效于以下步骤:
ReturnIfAbrupt (OperationName())。
类似地,对于方法应用样式,步骤:
? someValue .OperationName()。
等效于:
ReturnIfAbrupt (someValue .OperationName())。
类似地,前缀 !
用于指示以下抽象操作或 语法导向操作 的调用永远不会返回
突然完成 ,并且应使用结果
完成记录 的 [[Value]] 字段代替操作的返回值。例如,步骤:
令 val 为 ! OperationName()。
等效于以下步骤:
令 val 为 OperationName()。
断言 :val 是一个 正常完成 。
将 val 设置为 val .[[Value]] 。
语法导向操作 的
运行时语义 通过在操作调用前放置 !
或
?
来使用此简写:
执行 ! NonTerminal 的 SyntaxDirectedOperation。
5.2.3.5 隐式正常完成
在声明返回 完成记录 的 抽象操作 内的算法中,以及在所有内置函数中,返回值首先传递给
NormalCompletion ,并使用其结果。此规则不适用于
Completion 算法内,或者当返回的值在该步骤中明确标记为 完成记录 时;这些情况是:
如果通过任何其他方式从此类抽象操作返回 完成记录 ,则属于编辑错误。例如,在这些
抽象操作 中,
返回 true 。
与以下任何一种含义相同:
返回 NormalCompletion (true )。
或
令 completion 为 NormalCompletion (true )。
返回 Completion (completion )。
或
返回 完成记录 { [[Type]] : normal , [[Value]] : true , [[Target]] : empty }。
请注意,通过 ReturnIfAbrupt 展开,以下示例是允许的,因为在展开的步骤中,应用
Completion 的结果在突然情况下直接返回,而隐式的 NormalCompletion 应用在正常情况下解包后发生。
返回 ? completion 。
以下示例将是编辑错误,因为正在返回一个 完成记录 ,而没有在该步骤中进行注释。
令 completion 为 NormalCompletion (true )。
返回 completion 。
5.2.4 静态语义
上下文无关文法不足以表达所有规则,这些规则定义输入元素流是否形成一个有效的、可以求值的 ECMAScript 脚本 或 模块 。在某些情况下,需要额外的规则,这些规则可以使用 ECMAScript
算法约定或散文要求来表达。此类规则始终与语法的产生式相关联,并称为产生式的静态语义 。
静态语义规则具有名称,并且通常使用算法定义。命名的静态语义规则与语法产生式相关联,具有多个备选定义的产生式通常会为每个备选方案的每个适用的命名静态语义规则提供一个不同的算法。
一种特殊的静态语义规则是早期错误规则 。早期错误 规则定义了与特定语法产生式相关的早期错误 条件(参见第
17
条)。本规范的算法中并未显式调用大多数早期错误 规则的求值 。一致性实现必须在首次求值 脚本 或 模块 之前,验证用于解析该 脚本 或 模块 的产生式的所有早期错误 规则。如果违反了任何早期错误 规则,则该 脚本 或 模块 无效且无法求值 。
5.2.5 数学运算
本规范引用以下类型的数值:
在本规范的语言中,使用下标后缀来区分不同数值种类的数值。下标 𝔽 指的是数字,下标 ℤ 指的是
BigInts。没有下标后缀的数值指的是数学值 。本规范以十进制表示大多数数值;它也使用 0x 后跟数字 0-9 或 A-F
的形式的数值作为十六进制值。
通常,当本规范引用一个数值时,例如在短语“y 的长度”或“由四个十六进制数字表示的整数 ...”中,而没有明确指定数值种类时,该短语指的是一个数学值 。引用数字或 BigInt
值的短语会明确注释;例如,“...中代码点数量的数字值 ”或“...的BigInt 值 ”。
当本规范中使用术语 整数 时,它指的是一个数学值 ,该值在整数 集合中,除非另有说明。当本规范中使用术语 整数数字值 时,它指的是一个有限 数字值,其数学值 在整数 集合中。
诸如 +、×、= 和 ≥ 之类的数值运算符指的是由操作数类型决定的那些运算。当应用于数学值 时,这些运算符指的是通常的数学运算。当应用于扩展数学值 时,这些运算符指的是扩展实数上的通常数学运算;不确定形式未定义,在本规范中使用它们应被视为编辑错误。当应用于数字时,这些运算符指的是IEEE
754-2019 中的相关运算。当应用于 BigInts 时,这些运算符指的是应用于 BigInt 的数学值 的通常数学运算。应用于混合类型操作数(例如数字和数学值 )的数值运算符未定义,在本规范中应被视为编辑错误。
数学值 与数字或 BigInts 之间的转换在本文档中始终是显式的。从数学值 或扩展数学值 x
到数字的转换表示为“x 的数字值 ”或 𝔽(x ) ,并在 6.1.6.1 中定义。从整数 x 到 BigInt
的转换表示为“x 的BigInt 值 ”或 ℤ(x ) 。从数字或 BigInt x 到数学值 的转换表示为“x 的数学值 ”,或 ℝ(x ) 。+0 𝔽 和
-0 𝔽 的数学值 是数学值 0。非有限 值的数学值 未定义。x 的扩展数学值 对于有限 值是 x 的数学值 ,对于 +∞ 𝔽 和
-∞ 𝔽 分别是 +∞ 和 -∞;对于 NaN 未定义。
数学函数 abs(x ) 产生 x
的绝对值,如果 x < 0 则为 -x ,否则为 x
本身。
数学函数 min(x1 , x2 , … ,
xN ) 产生 x1 到 xN 中数学上最小的值。数学函数 max(x1 , x2 , ..., xN ) 产生 x1 到 xN
中数学上最大的值。这些数学函数的定义域和值域是扩展数学值 。
符号“x 模
y ”(y 必须是有限 且非零)计算一个与 y 同符号(或为零)的值 k ,使得
abs (k ) < abs (y ) 且 x -
k = q × y 对于某个整数 q 成立。
短语“将 x 限制 在 lower 和 upper
之间”的结果(其中 x 是一个扩展数学值 ,lower 和
upper 是数学值 且 lower ≤ upper )是:如果
x < lower 则为 lower ,如果 x > upper 则为
upper ,否则为 x 。
数学函数 floor(x ) 产生不大于
x 的最大整数 (最接近 +∞)。
注意
数学函数 truncate(x )
通过向零取整来移除 x 的小数部分,如果 x < 0 则产生 -floor (-x ) ,否则产生 floor (x ) 。
数学函数 min 、max 、abs 、floor 和 truncate 未针对数字和 BigInts
定义,任何使用非数学值 参数的这些方法的用法在本规范中都应视为编辑错误。
从下界 a 到上界 b 的区间 是一个可能是无限的、可能是空的、相同数值类型的数值集合。每个界限将被描述为包含的或排除的,但不能两者都是。有四种区间,如下所示:
从 a (包含)到 b (包含)的区间 ,也称为从 a 到 b 的闭区间 ,包括所有相同数值类型的数值 x ,使得
a ≤ x ≤ b ,且不包括其他值。
从 a (包含)到 b (排除)的区间 包括所有相同数值类型的数值 x ,使得 a ≤
x < b ,且不包括其他值。
从 a (排除)到 b (包含)的区间 包括所有相同数值类型的数值 x ,使得 a <
x ≤ b ,且不包括其他值。
从 a (排除)到 b (排除)的区间 包括所有相同数值类型的数值 x ,使得 a <
x < b ,且不包括其他值。
例如,从 1(包含)到 2(排除)的区间 包含所有介于 1 和 2 之间的数学值 ,包括 1 但不包括
2。为了定义区间,-0 𝔽 <
+0 𝔽 ,因此,例如,下界为 +0 𝔽 的闭区间 包括
+0 𝔽 但不包括
-0 𝔽 。NaN 从不包含在区间 中。
5.2.6 值表示法
在本规范中,ECMAScript
语言值 以粗体 显示。示例包括
null 、true 或 "hello" 。这些与 ECMAScript
源文本 (如 Function.prototype.apply
或
let n = 42;
)相区别。
5.2.7 同一性
在本规范中,规范值和 ECMAScript
语言值 都会进行相等性比较。在比较相等性时,值分为两类。无同一性的值 如果其所有固有特征(例如整数 的大小或序列的长度)都相同,则与其他无同一性的值相等。无同一性的值可以通过完全描述其特征来体现,而无需事先引用。相比之下,每个有同一性的值 都是唯一的,因此只等于其自身。有同一性的值类似于无同一性的值,但具有一个额外的、不可猜测的、不可改变的、普遍唯一的特征,称为同一性 。对现有有同一性的值的引用不能简单地通过描述它们来体现,因为同一性本身是不可描述的;相反,对这些值的引用必须从一个地方显式传递到另一个地方。一些有同一性的值是可变的,因此可以就地更改其特征(除了其同一性),从而使该值的所有持有者都观察到新的特征。无同一性的值永远不等于有同一性的值。
从本规范的角度来看,“是”用于比较两个值的相等性,如“如果 bool 是 true ,则
...”,而“包含”用于使用相等性比较在列表中搜索值,如“如果 list 包含一个 记录 r 使得
r .[[Foo]] 是 true ,则
...”。值的规范同一性 决定了这些比较的结果,并且在本规范中是公理性的。
从 ECMAScript 语言的角度来看,语言值使用 SameValue 抽象操作及其传递调用的 抽象操作 进行相等性比较。这些比较抽象操作 的算法确定了
ECMAScript 语言值 的语言同一性 。
对于规范值,无规范同一性的值的示例包括但不限于:数学值 和扩展数学值 ;ECMAScript
源文本 、代理对 、指令序言 等;UTF-16 代码单元;Unicode
码点;枚举 ;抽象操作 ,包括语法导向操作 、宿主钩子 等;以及有序对。有规范同一性的规范值的示例包括但不限于:任何类型的记录 ,包括属性描述符 、私有元素 等;解析节点 ;列表 ;集合 和关系 ;抽象闭包 ;数据块 ;私有名称 ;执行上下文 和执行上下文栈 ;代理标识符 ;以及WaiterList
记录 。
对于所有 ECMAScript 语言值 ,规范同一性与语言同一性一致,但由
Symbol.for 产生的 Symbol 值除外。无规范同一性和无语言同一性的 ECMAScript 语言值 是 undefined 、null 、布尔值 、字符串 、数字 和BigInts 。有规范同一性和语言同一性的
ECMAScript 语言值 是并非由 Symbol.for 产生的
Symbols 和 对象 。由
Symbol.for 产生的 Symbol 值具有规范同一性,但没有语言同一性。
6 ECMAScript 数据类型和值
本规范中的算法操作的值都具有关联的类型。可能的值类型正是本条款中定义的那些类型。类型进一步分为 ECMAScript 语言类型 和规范类型。
6.1 ECMAScript 语言类型
ECMAScript 语言类型 对应于 ECMAScript 程序员使用 ECMAScript
语言直接操作的值。ECMAScript 语言类型包括 Undefined、Null、Boolean、String、Symbol、Number、BigInt 和 Object。 ECMAScript 语言值 是由 ECMAScript 语言类型表征的值。
6.1.1 Undefined 类型
Undefined 类型只有一个值,称为 undefined 。任何未赋值的变量都具有值 undefined 。
6.1.2 Null 类型
Null 类型只有一个值,称为 null 。
6.1.3 Boolean 类型
Boolean 类型 表示一个逻辑实体,具有两个值,称为
true 和 false 。
6.1.4 字符串类型
字符串类型 是所有长度不超过 253 - 1 个元素的零个或多个 16
位无符号整数 值(“元素”)的有序序列的集合。字符串类型通常用于在运行的 ECMAScript
程序中表示文本数据,在这种情况下,字符串中的每个元素都被视为一个 UTF-16 代码单元值。每个元素都被认为在序列中占据一个位置。这些位置用非负整数 进行索引。第一个元素(如果存在)位于索引
0,下一个元素(如果存在)位于索引 1,依此类推。字符串的长度是其中元素的数量(即 16 位值的数量)。空字符串的长度为零,因此不包含任何元素。
不解释字符串内容的 ECMAScript 操作不应用任何进一步的语义。解释字符串值的操作将每个元素视为单个 UTF-16 代码单元。但是,ECMAScript
不限制这些代码单元的值或它们之间的关系,因此将字符串内容进一步解释为以 UTF-16 编码的 Unicode 码点序列的操作必须考虑到格式错误的子序列。此类操作对数值在 闭区间
0xD800 到 0xDBFF(由 Unicode 标准定义为前导代理项 ,或更正式地称为高位代理代码单元 )内的每个代码单元以及数值在 闭区间 0xDC00 到 0xDFFF(定义为后尾代理项 ,或更正式地称为低位代理代码单元 )内的每个代码单元应用以下规则进行特殊处理:
一个既不是前导代理项 也不是后尾代理项 的代码单元被解释为具有相同值的码点。
一个由两个代码单元组成的序列,其中第一个代码单元 c1 是一个前导代理项 ,第二个代码单元 c2
是一个后尾代理项 ,则该序列是一个代理对 ,并被解释为具有值 (c1 - 0xD800) × 0x400 +
(c2 - 0xDC00) + 0x10000 的码点。(参见 11.1.3 )
一个前导代理项 或后尾代理项 ,但不是代理对 的一部分,则被解释为具有相同值的码点。
函数 String.prototype.normalize
(参见 22.1.3.15 )可用于显式规范化字符串值。String.prototype.localeCompare
(参见
22.1.3.12 )在内部规范化字符串值,但没有其他操作会隐式规范化它们操作的字符串。除非另有说明,否则操作结果对语言和/或区域设置不敏感。
注意
这种设计背后的基本原理是使字符串的实现尽可能简单和高性能。如果 ECMAScript 源文本 采用规范化形式 C,则只要字符串字面量不包含任何
Unicode 转义序列,就可以保证它们也是规范化的。
在本规范中,短语“A 、B 、... 的字符串连接 ”(其中每个参数都是字符串值、代码单元或代码单元序列)表示其代码单元序列是每个参数(按顺序)的代码单元(按顺序)连接而成的字符串值。
短语“S 从 inclusiveStart 到 exclusiveEnd 的子字符串 ”(其中 S 是字符串值或代码单元序列,inclusiveStart 和
exclusiveEnd 是整数 )表示由 S 的从索引 inclusiveStart 开始到索引
exclusiveEnd 之前结束的连续代码单元组成的字符串值(当 inclusiveStart = exclusiveEnd
时为空字符串)。如果省略“to”后缀,则使用 S 的长度作为 exclusiveEnd 的值。
短语“ASCII 词字符 ”表示以下字符串值,该值仅由 Unicode
基本拉丁块中的所有字母和数字以及 U+005F (LOW LINE) 组成:
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_" 。
由于历史原因,它对各种算法具有重要意义。
6.1.4.1 StringIndexOf ( string ,
searchValue , fromIndex )
抽象操作 StringIndexOf 接受参数 string (一个字符串)、searchValue (一个字符串) 和
fromIndex (一个非负整数 ),并返回一个非负整数 或
not-found 。调用时它执行以下步骤:
令 len 为 string 的长度。
如果 searchValue 是空字符串且 fromIndex ≤ len ,则返回
fromIndex 。
令 searchLen 为 searchValue 的长度。
对于每个整数
i ,使得 fromIndex ≤ i ≤ len -
searchLen ,按升序执行:
令 candidate 为 string 从 i 到 i +
searchLen 的子字符串 。
如果 candidate 是 searchValue ,则返回 i 。
返回 not-found 。
注1
如果 searchValue 是空字符串且 fromIndex ≤ string 的长度,则此算法返回
fromIndex 。空字符串实际上在字符串中的每个位置都能找到,包括最后一个代码单元之后。
注2
如果 fromIndex + searchValue 的长度 > string 的长度,则此算法始终返回
not-found 。
6.1.4.2 StringLastIndexOf ( string ,
searchValue , fromIndex )
抽象操作 StringLastIndexOf 接受参数 string (一个字符串)、searchValue (一个字符串) 和
fromIndex (一个非负整数 ),并返回一个非负整数 或
not-found 。调用时它执行以下步骤:
令 len 为 string 的长度。
令 searchLen 为 searchValue 的长度。
断言 :fromIndex + searchLen
≤ len 。
对于每个整数
i ,使得 0 ≤ i ≤ fromIndex ,按降序执行:
令 candidate 为 string 从 i 到 i +
searchLen 的子字符串 。
如果 candidate 是 searchValue ,则返回 i 。
返回 not-found 。
注意
如果 searchValue 是空字符串,则此算法返回
fromIndex 。空字符串实际上在字符串中的每个位置都能找到,包括最后一个代码单元之后。
6.1.5 Symbol 类型
Symbol 类型 是所有可用作对象属性键(6.1.7 )的非字符串值的集合。
每个可能的 Symbol 值都是唯一且不可变的。
每个 Symbol 值都不可变地持有一个关联值,称为 [[Description]] ,该值要么是
undefined ,要么是字符串值。
6.1.5.1 知名符号
知名符号是本规范算法明确引用的内置 Symbol 值。它们通常用作属性的键,这些属性的值充当规范算法的扩展点。除非另有规定,否则知名符号值由所有领域 (9.3 )共享。
在本规范中,使用标准的内在符号表示法 引用知名符号,其中内在符号是表
1 中列出的值之一。
注意
本规范的先前版本使用 @@name 形式的表示法,而当前版本将使用
%Symbol.name%
。特别是,使用了以下名称:@@asyncIterator、@@hasInstance、@@isConcatSpreadable、@@iterator 、@@match、@@matchAll、@@replace、@@search、@@species、@@split、@@toPrimitive、@@toStringTag
和 @@unscopables。
表 1:知名符号
规范名称
[[Description]]
值和用途
%Symbol.asyncIterator%
"Symbol.asyncIterator"
一个返回对象默认异步迭代器 的方法。由
for
-await
-of
语句的语义调用。
%Symbol.hasInstance%
"Symbol.hasInstance"
一个确定构造函数 对象是否将一个对象识别为该构造函数 的实例的方法。由
instanceof
运算符的语义调用。
%Symbol.isConcatSpreadable%
"Symbol.isConcatSpreadable"
一个布尔值属性,如果为 true,则表示一个对象应由 Array.prototype.concat
展平为其数组元素。
%Symbol.iterator%
"Symbol.iterator"
一个返回对象默认迭代器 的方法。由 for-of
语句的语义调用。
%Symbol.match%
"Symbol.match"
一个正则表达式方法,用于将正则表达式与字符串进行匹配。由 String.prototype.match
方法调用。
%Symbol.matchAll%
"Symbol.matchAll"
一个正则表达式方法,返回一个迭代器 ,该迭代器产生正则表达式与字符串匹配的结果。由
String.prototype.matchAll
方法调用。
%Symbol.replace%
"Symbol.replace"
一个正则表达式方法,用于替换字符串中匹配的子字符串。由 String.prototype.replace
方法调用。
%Symbol.search%
"Symbol.search"
一个正则表达式方法,返回字符串中与正则表达式匹配的索引。由 String.prototype.search
方法调用。
%Symbol.species%
"Symbol.species"
一个函数值属性,是用于创建派生对象的构造函数 。
%Symbol.split%
"Symbol.split"
一个正则表达式方法,用于在与正则表达式匹配的索引处拆分字符串。由 String.prototype.split
方法调用。
%Symbol.toPrimitive%
"Symbol.toPrimitive"
一个将对象转换为相应原始值的方法。由 ToPrimitive 抽象操作调用。
%Symbol.toStringTag%
"Symbol.toStringTag"
一个字符串值属性,用于创建对象的默认字符串描述。由内置方法 Object.prototype.toString
访问。
%Symbol.unscopables%
"Symbol.unscopables"
一个对象值属性,其自身和继承的属性名称是从关联对象的 with
环境绑定中排除的属性名称。
6.1.6 数字类型
ECMAScript 有两种内置的数字类型:Number 和 BigInt。以下抽象操作 是在这些数字类型上定义的。“结果”列显示返回类型,并指示该操作的某些调用是否可能返回突然完成 。
表 2:数字类型操作
由于数字类型通常无法在不损失精度或截断的情况下进行转换,因此 ECMAScript 语言不提供这些类型之间的隐式转换。在调用需要另一种类型的函数时,程序员必须显式调用
Number
和 BigInt
函数在类型之间进行转换。
注意
ECMAScript 的第一版及后续版本为某些运算符提供了可能损失精度或截断 的隐式数字转换。为了向后兼容,这些遗留的隐式转换得以保留,但为了最大限度地减少程序员出错的机会,并为未来版本中广义值类型 的选择留有余地,BigInt
不提供这些转换。
6.1.6.1 Number 类型
Number 类型 恰好有
18,437,736,874,454,810,627 (即 264 - 253 +
3 ) 个值,表示 IEEE 754-2019 二进制64位双精度浮点值,如 IEEE
二进制浮点算术标准中所指定,但 IEEE 标准中的 9,007,199,254,740,990 (即 253 -
2 ) 个不同的 NaN 值在 ECMAScript 中表示为单个特殊的 NaN
值。(注意,NaN 值由程序表达式 NaN
产生。)在某些实现中,外部代码可能能够检测到各种 NaN
值之间的差异,但这种行为是实现定义的 ;对于 ECMAScript 代码,所有
NaN 值彼此之间无法区分。
注意
在将 Number 值存储到 ArrayBuffer (参见 25.1 ) 或
SharedArrayBuffer (参见 25.2 )
后可能观察到的位模式不一定与 ECMAScript 实现使用的该 Number 值的内部表示相同。
还有另外两个特殊值,称为正无穷大 和负无穷大 。为简洁起见,出于说明目的,这些值也分别用符号
+∞ 𝔽 和 -∞ 𝔽 表示。(注意,这两个无限 Number
值由程序表达式 +Infinity
(或简称 Infinity
) 和 -Infinity
产生。)
其余 18,437,736,874,454,810,624 (即 264 -
253 ) 个值称为有限 数。其中一半是正数,一半是负数;对于每个有限 正 Number 值,都有一个对应的具有相同大小的负值。
注意,既有正零 也有负零 。为简洁起见,出于说明目的,这些值也分别用符号
+0 𝔽 和 -0 𝔽 表示。(注意,这两个不同的零
Number 值由程序表达式 +0
(或简称 0
) 和 -0
产生。)
18,437,736,874,454,810,622 (即 264 - 253 -
2 ) 个有限 非零值有两种:
其中 18,428,729,675,200,069,632 (即 264 -
254 ) 个是规范化的,形式为
s × m × 2e
其中 s 是 1 或 -1,m 是区间 [252 , 253 ) 内的整数 ,e
是闭区间 [-1074, 971] 内的整数 。
其余 9,007,199,254,740,990 (即 253 - 2 )
个值是非规范化的,形式为
s × m × 2e
其中 s 是 1 或 -1,m 是区间 (0, 252 ) 内的整数 ,e 是 -1074。
注意,所有大小不超过 253 的正负整数 都可以在 Number 类型中表示。整数 0 在 Number
类型中有两种表示:+0 𝔽 和 -0 𝔽 。
如果一个有限 数非零,并且用于表示它(以上述两种形式之一)的整数 m
是奇数,则该数具有奇数有效数 。否则,它具有偶数有效数 。
在本规范中,短语“x 的 Number 值 ”(其中 x 表示一个精确的实数数学量,甚至可能是一个无理数,如
π)指的是按以下方式选择的 Number 值。考虑 Number 类型的所有有限 值的集合,去掉 -0 𝔽 ,并向其添加两个
Number 类型中无法表示的附加值,即 21024 (即 +1 × 253 ×
2971 ) 和 -21024 (即
-1 × 253 × 2971 )。选择此集合中与
x 值最接近的成员。如果集合中的两个值同样接近,则选择具有偶数有效数的那个;为此,两个额外的值 21024 和 -21024 被认为具有偶数有效数。最后,如果选择了 21024 ,则将其替换为
+∞ 𝔽 ;如果选择了 -21024 ,则将其替换为
-∞ 𝔽 ;如果选择了 +0 𝔽 ,则当且仅当
x < 0 时将其替换为 -0 𝔽 ;任何其他选择的值保持不变。结果是 x
的Number
值 。(此过程与 IEEE 754-2019 roundTiesToEven 模式的行为完全对应。)
+∞ 的Number
值 是 +∞ 𝔽 ,-∞ 的Number
值 是 -∞ 𝔽 。
某些 ECMAScript 运算符仅处理特定范围内的整数 ,例如闭区间 [-231 , 231 -
1 ] 或闭区间 [0, 216 - 1 ]。这些运算符接受 Number
类型的任何值,但首先将每个此类值转换为预期范围内的整数 值。请参见 7.1 中数字转换操作的说明。
6.1.6.1.1 Number::unaryMinus ( x )
抽象操作 Number::unaryMinus 接受参数 x (一个 Number) 并返回一个 Number。调用时它执行以下步骤:
如果 x 是 NaN ,则返回 NaN 。
返回 x 的负值;即,计算一个具有相同大小但符号相反的 Number。
6.1.6.1.2 Number::bitwiseNOT ( x )
抽象操作 Number::bitwiseNOT 接受参数 x (一个 Number) 并返回一个整数
Number 。调用时它执行以下步骤:
令 oldValue 为 ! ToInt32 (x )。
返回 oldValue 的按位补码。结果的数学值 可以精确地表示为一个
32 位二进制补码位串。
6.1.6.1.3 Number::exponentiate ( base ,
exponent )
抽象操作 Number::exponentiate 接受参数 base (一个 Number) 和 exponent (一个
Number) 并返回一个 Number。它返回一个实现近似 的值,表示
base 的 exponent 次幂的结果。调用时它执行以下步骤:
如果 exponent 是 NaN ,则返回 NaN 。
如果 exponent 是 +0 𝔽 或
-0 𝔽 ,则返回 1 𝔽 。
如果 base 是 NaN ,则返回 NaN 。
如果 base 是 +∞ 𝔽 ,则
如果 exponent > +0 𝔽 ,则返回
+∞ 𝔽 。否则,返回
+0 𝔽 。
如果 base 是 -∞ 𝔽 ,则
如果 exponent > +0 𝔽 ,则
如果 exponent 是一个奇数整数
Number ,则返回
-∞ 𝔽 。否则,返回
+∞ 𝔽 。
否则,
如果 exponent 是一个奇数整数
Number ,则返回
-0 𝔽 。否则,返回
+0 𝔽 。
如果 base 是 +0 𝔽 ,则
如果 exponent > +0 𝔽 ,则返回
+0 𝔽 。否则,返回
+∞ 𝔽 。
如果 base 是 -0 𝔽 ,则
如果 exponent > +0 𝔽 ,则
如果 exponent 是一个奇数整数
Number ,则返回
-0 𝔽 。否则,返回
+0 𝔽 。
否则,
如果 exponent 是一个奇数整数
Number ,则返回
-∞ 𝔽 。否则,返回
+∞ 𝔽 。
断言 :base 是有限的 ,并且既不是
+0 𝔽 也不是 -0 𝔽 。
如果 exponent 是 +∞ 𝔽 ,则
如果 abs (ℝ (base )) >
1,则返回 +∞ 𝔽 。
如果 abs (ℝ (base )) =
1,则返回 NaN 。
如果 abs (ℝ (base )) <
1,则返回 +0 𝔽 。
如果 exponent 是 -∞ 𝔽 ,则
如果 abs (ℝ (base )) >
1,则返回 +0 𝔽 。
如果 abs (ℝ (base )) =
1,则返回 NaN 。
如果 abs (ℝ (base )) <
1,则返回 +∞ 𝔽 。
断言 :exponent 是有限的 ,并且既不是
+0 𝔽 也不是 -0 𝔽 。
如果 base < -0 𝔽 且 exponent
不是一个整数 Number ,则返回
NaN 。
返回一个实现近似 的 Number 值,表示
ℝ (base )
的 ℝ (exponent ) 次幂的结果。
注意
当 base 是 1 𝔽 或
-1 𝔽 且 exponent 是
+∞ 𝔽 或 -∞ 𝔽 时,或者当
base 是 1 𝔽 且 exponent 是
NaN 时,base **
exponent
的结果与 IEEE 754-2019 不同。ECMAScript
的第一版为此操作指定了 NaN 的结果,而 IEEE 754 的后续修订版指定了
1 𝔽 。出于兼容性原因,保留了历史上的 ECMAScript 行为。
6.1.6.1.4 Number::multiply ( x , y )
抽象操作 Number::multiply 接受参数 x (一个 Number) 和 y (一个 Number) 并返回一个
Number。它根据 IEEE 754-2019 二进制双精度算术规则执行乘法,产生
x 和 y 的乘积。调用时它执行以下步骤:
如果 x 是 NaN 或 y 是
NaN ,则返回 NaN 。
如果 x 是 +∞ 𝔽 或
-∞ 𝔽 ,则
如果 y 是 +0 𝔽 或
-0 𝔽 ,则返回 NaN 。
如果 y > +0 𝔽 ,则返回
x 。
返回 -x 。
如果 y 是 +∞ 𝔽 或
-∞ 𝔽 ,则
如果 x 是 +0 𝔽 或
-0 𝔽 ,则返回 NaN 。
如果 x > +0 𝔽 ,则返回
y 。
返回 -y 。
如果 x 是 -0 𝔽 ,则
如果 y 是 -0 𝔽 或 y <
-0 𝔽 ,则返回
+0 𝔽 。
否则,返回 -0 𝔽 。
如果 y 是 -0 𝔽 ,则
如果 x < -0 𝔽 ,则返回
+0 𝔽 。
否则,返回 -0 𝔽 。
返回 𝔽 (ℝ (x ) ×
ℝ (y ))。
注意
6.1.6.1.5 Number::divide ( x , y )
抽象操作 Number::divide 接受参数 x (一个 Number) 和 y (一个 Number) 并返回一个
Number。它根据 IEEE 754-2019 二进制双精度算术规则执行除法,产生
x 和 y 的商,其中 x 是被除数,y 是除数。调用时它执行以下步骤:
如果 x 是 NaN 或 y 是
NaN ,则返回 NaN 。
如果 x 是 +∞ 𝔽 或
-∞ 𝔽 ,则
如果 y 是 +∞ 𝔽 或
-∞ 𝔽 ,则返回 NaN 。
如果 y 是 +0 𝔽 或 y >
+0 𝔽 ,则返回 x 。
返回 -x 。
如果 y 是 +∞ 𝔽 ,则
如果 x 是 +0 𝔽 或 x >
+0 𝔽 ,则返回
+0 𝔽 。否则,返回
-0 𝔽 。
如果 y 是 -∞ 𝔽 ,则
如果 x 是 +0 𝔽 或 x >
+0 𝔽 ,则返回
-0 𝔽 。否则,返回
+0 𝔽 。
如果 x 是 +0 𝔽 或
-0 𝔽 ,则
如果 y 是 +0 𝔽 或
-0 𝔽 ,则返回 NaN 。
如果 y > +0 𝔽 ,则返回
x 。
返回 -x 。
如果 y 是 +0 𝔽 ,则
如果 x > +0 𝔽 ,则返回
+∞ 𝔽 。否则,返回
-∞ 𝔽 。
如果 y 是 -0 𝔽 ,则
如果 x > +0 𝔽 ,则返回
-∞ 𝔽 。否则,返回
+∞ 𝔽 。
返回 𝔽 (ℝ (x ) /
ℝ (y ))。
6.1.6.1.6 Number::remainder ( n , d )
抽象操作 Number::remainder 接受参数 n (一个 Number) 和 d (一个 Number) 并返回一个
Number。它产生其操作数隐式除法的余数,其中 n 是被除数,d 是除数。调用时它执行以下步骤:
如果 n 是 NaN 或 d 是
NaN ,则返回 NaN 。
如果 n 是 +∞ 𝔽 或
-∞ 𝔽 ,则返回 NaN 。
如果 d 是 +∞ 𝔽 或
-∞ 𝔽 ,则返回 n 。
如果 d 是 +0 𝔽 或
-0 𝔽 ,则返回 NaN 。
如果 n 是 +0 𝔽 或
-0 𝔽 ,则返回 n 。
断言 :n 和 d 是有限的 且非零。
令 quotient 为 ℝ (n ) / ℝ (d )。
令 q 为 truncate (quotient )。
令 r 为 ℝ (n ) - (ℝ (d ) × q )。
如果 r = 0 且 n < -0 𝔽 ,则返回
-0 𝔽 。
返回 𝔽 (r )。
注1
在 C 和 C++ 中,余数运算符仅接受整数操作数;在 ECMAScript 中,它也接受浮点操作数。
注2
由
%
运算符计算的浮点余数运算的结果与
IEEE
754-2019 定义的“余数”运算不同。
IEEE 754-2019
“余数”运算计算的是舍入除法的余数,而不是截断除法的余数,因此其行为与通常的
整数 余数运算符不同。相反,ECMAScript
语言定义
%
在浮点运算上的行为类似于 Java
整数 余数运算符的行为;这可以与 C
库函数 fmod 进行比较。
6.1.6.1.7 Number::add ( x , y )
抽象操作 Number::add 接受参数 x (一个 Number) 和 y (一个 Number) 并返回一个
Number。它根据 IEEE 754-2019
二进制双精度算术规则执行加法,产生其参数的和。调用时它执行以下步骤:
如果 x 是 NaN 或 y 是
NaN ,则返回 NaN 。
如果 x 是 +∞ 𝔽 且 y 是
-∞ 𝔽 ,则返回 NaN 。
如果 x 是 -∞ 𝔽 且 y 是
+∞ 𝔽 ,则返回 NaN 。
如果 x 是 +∞ 𝔽 或
-∞ 𝔽 ,则返回 x 。
如果 y 是 +∞ 𝔽 或
-∞ 𝔽 ,则返回 y 。
断言 :x 和 y 都是有限的 。
如果 x 是 -0 𝔽 且 y 是
-0 𝔽 ,则返回 -0 𝔽 。
返回 𝔽 (ℝ (x ) +
ℝ (y ))。
注意
6.1.6.1.8 Number::subtract ( x , y )
抽象操作 Number::subtract 接受参数 x (一个 Number) 和 y (一个 Number) 并返回一个
Number。它执行减法,产生其操作数的差;x 是被减数,y 是减数。调用时它执行以下步骤:
返回 Number::add (x ,
Number::unaryMinus (y ))。
注意
x - y
总是产生与 x + (-y)
相同的结果。
6.1.6.1.9 Number::leftShift ( x , y )
抽象操作 Number::leftShift 接受参数 x (一个 Number) 和 y (一个 Number)
并返回一个整数
Number 。调用时它执行以下步骤:
令 lNum 为 ! ToInt32 (x )。
令 rNum 为 ! ToUint32 (y )。
令 shiftCount 为 ℝ (rNum ) modulo 32。
返回将 lNum 左移 shiftCount 位的结果。结果的数学值 可以精确地表示为一个 32 位二进制补码位串。
6.1.6.1.10 Number::signedRightShift ( x ,
y )
抽象操作 Number::signedRightShift 接受参数 x (一个 Number) 和 y (一个 Number)
并返回一个整数
Number 。调用时它执行以下步骤:
令 lNum 为 ! ToInt32 (x )。
令 rNum 为 ! ToUint32 (y )。
令 shiftCount 为 ℝ (rNum ) modulo 32。
返回对 lNum 执行符号扩展右移 shiftCount 位的结果。最高有效位被传播。结果的数学值 可以精确地表示为一个 32 位二进制补码位串。
6.1.6.1.11 Number::unsignedRightShift ( x ,
y )
抽象操作 Number::unsignedRightShift 接受参数 x (一个 Number) 和 y (一个 Number)
并返回一个整数
Number 。调用时它执行以下步骤:
令 lNum 为 ! ToUint32 (x )。
令 rNum 为 ! ToUint32 (y )。
令 shiftCount 为 ℝ (rNum ) modulo 32。
返回对 lNum 执行零填充右移 shiftCount 位的结果。空出的位用零填充。结果的数学值 可以精确地表示为一个 32 位无符号位串。
6.1.6.1.12 Number::lessThan ( x , y )
抽象操作 Number::lessThan 接受参数 x (一个 Number) 和 y (一个 Number) 并返回一个
Boolean 或 undefined 。调用时它执行以下步骤:
如果 x 是 NaN ,则返回 undefined 。
如果 y 是 NaN ,则返回 undefined 。
如果 x 是 y ,则返回 false 。
如果 x 是 +0 𝔽 且 y 是
-0 𝔽 ,则返回 false 。
如果 x 是 -0 𝔽 且 y 是
+0 𝔽 ,则返回 false 。
如果 x 是 +∞ 𝔽 ,则返回
false 。
如果 y 是 +∞ 𝔽 ,则返回
true 。
如果 y 是 -∞ 𝔽 ,则返回
false 。
如果 x 是 -∞ 𝔽 ,则返回
true 。
断言 :x 和 y 是有限的 。
如果 ℝ (x )
< ℝ (y ),则返回
true 。否则,返回 false 。
6.1.6.1.13 Number::equal ( x , y )
抽象操作 Number::equal 接受参数 x (一个 Number) 和 y (一个 Number) 并返回一个
Boolean。调用时它执行以下步骤:
如果 x 是 NaN ,则返回 false 。
如果 y 是 NaN ,则返回 false 。
如果 x 是 y ,则返回 true 。
如果 x 是 +0 𝔽 且 y 是
-0 𝔽 ,则返回 true 。
如果 x 是 -0 𝔽 且 y 是
+0 𝔽 ,则返回 true 。
返回 false 。
6.1.6.1.14 Number::sameValue ( x , y )
抽象操作 Number::sameValue 接受参数 x (一个 Number) 和 y (一个 Number) 并返回一个
Boolean。调用时它执行以下步骤:
如果 x 是 NaN 且 y 是
NaN ,则返回 true 。
如果 x 是 +0 𝔽 且 y 是
-0 𝔽 ,则返回 false 。
如果 x 是 -0 𝔽 且 y 是
+0 𝔽 ,则返回 false 。
如果 x 是 y ,则返回 true 。
返回 false 。
6.1.6.1.15 Number::sameValueZero ( x ,
y )
抽象操作 Number::sameValueZero 接受参数 x (一个 Number) 和 y (一个 Number) 并返回一个
Boolean。调用时它执行以下步骤:
如果 x 是 NaN 且 y 是
NaN ,则返回 true 。
如果 x 是 +0 𝔽 且 y 是
-0 𝔽 ,则返回 true 。
如果 x 是 -0 𝔽 且 y 是
+0 𝔽 ,则返回 true 。
如果 x 是 y ,则返回 true 。
返回 false 。
6.1.6.1.16 NumberBitwiseOp ( op , x ,
y )
抽象操作 NumberBitwiseOp 接受参数 op (&
、^
或
|
)、x (一个 Number) 和 y (一个 Number) 并返回一个整数
Number 。调用时它执行以下步骤:
令 lNum 为 ! ToInt32 (x )。
令 rNum 为 ! ToInt32 (y )。
令 lBits 为表示 ℝ (lNum ) 的 32 位二进制补码位串。
令 rBits 为表示 ℝ (rNum ) 的 32 位二进制补码位串。
如果 op 是 &
,则
令 result 为对 lBits 和 rBits 应用按位与运算的结果。
否则,如果 op 是 ^
,则
令 result 为对 lBits 和 rBits 应用按位异或 (XOR)
运算的结果。
否则,
断言 :op 是 |
。
令 result 为对 lBits 和 rBits 应用按位或运算的结果。
返回由 32 位二进制补码位串 result 表示的整数 的Number 值 。
6.1.6.1.17 Number::bitwiseAND ( x , y )
抽象操作 Number::bitwiseAND 接受参数 x (一个 Number) 和 y (一个 Number)
并返回一个整数
Number 。调用时它执行以下步骤:
返回 NumberBitwiseOp (&
,
x , y )。
6.1.6.1.18 Number::bitwiseXOR ( x , y )
抽象操作 Number::bitwiseXOR 接受参数 x (一个 Number) 和 y (一个 Number)
并返回一个整数
Number 。调用时它执行以下步骤:
返回 NumberBitwiseOp (^
,
x , y )。
6.1.6.1.19 Number::bitwiseOR ( x , y )
抽象操作 Number::bitwiseOR 接受参数 x (一个 Number) 和 y (一个 Number)
并返回一个整数
Number 。调用时它执行以下步骤:
返回 NumberBitwiseOp (|
,
x , y )。
6.1.6.1.20 Number::toString ( x , radix
)
抽象操作 Number::toString 接受参数 x (一个 Number) 和 radix (一个闭区间 [2, 36] 内的整数 ) 并返回一个
String。它使用基数为 radix 的位置数字系统将 x 表示为字符串。使用基数 r
表示数字时使用的数字取自 "0123456789abcdefghijklmnopqrstuvwxyz" 的前 r
个代码单元(按顺序)。大小大于或等于 1 𝔽 的数字的表示永远不包含前导零。调用时它执行以下步骤:
如果 x 是 NaN ,则返回 "NaN" 。
如果 x 是 +0 𝔽 或
-0 𝔽 ,则返回 "0" 。
如果 x < -0 𝔽 ,则返回字符串连接 "-"
和 Number::toString (-x ,
radix )。
如果 x 是 +∞ 𝔽 ,则返回
"Infinity" 。
令 n 、k 和
s 为整数 ,使得 k ≥
1,radix k - 1 ≤ s <
radix k ,𝔽 (s ×
radix n - k ) 是 x ,并且
k 尽可能小。注意,k 是使用基数 radix 表示 s
的位数,s 不能被 radix 整除,并且 s 的最低有效位不一定由这些标准唯一确定。
如果 radix ≠ 10 或 n 在闭区间 [-5, 21] 内,则
如果 n ≥ k ,则
返回以下各项的字符串连接 :
使用基数 radix 表示 s 的 k
位数字的代码单元
n - k 个代码单元 0x0030 (DIGIT ZERO)
否则,如果 n > 0,则
返回以下各项的字符串连接 :
使用基数 radix 表示 s 的最高有效 n
位数字的代码单元
代码单元 0x002E (FULL STOP)
使用基数 radix 表示 s 的其余 k -
n 位数字的代码单元
否则,
断言 :n ≤ 0。
返回以下各项的字符串连接 :
代码单元 0x0030 (DIGIT ZERO)
代码单元 0x002E (FULL STOP)
-n 个代码单元 0x0030 (DIGIT ZERO)
使用基数 radix 表示 s 的 k
位数字的代码单元
注意:在这种情况下,输入将使用科学 E 表示法表示,例如 1.2e+3
。
断言 :radix 是 10。
如果 n < 0,则
令 exponentSign 为代码单元 0x002D (HYPHEN-MINUS)。
否则,
令 exponentSign 为代码单元 0x002B (PLUS SIGN)。
如果 k = 1,则
返回以下各项的字符串连接 :
s 的单个数字的代码单元
代码单元 0x0065 (LATIN SMALL LETTER E)
exponentSign
abs (n - 1)
的十进制表示的代码单元
返回以下各项的字符串连接 :
s 的十进制表示的最高有效数字的代码单元
代码单元 0x002E (FULL STOP)
s 的十进制表示的其余 k - 1 位数字的代码单元
代码单元 0x0065 (LATIN SMALL LETTER E)
exponentSign
abs (n - 1) 的十进制表示的代码单元
注1
以下观察结果可能对实现有所帮助,但并非本标准的规范性要求的一部分:
注2
对于提供比上述规则要求的转换更精确的实现,建议使用以下步骤 5
的替代版本作为指导:
令 n 、k 和 s 为整数 ,使得 k
≥ 1,radix k - 1 ≤ s <
radix k ,𝔽 (s ×
radix n - k ) 是
x ,并且 k 尽可能小。如果 s 有多种可能性,则选择使
s × radix n - k
的值最接近 ℝ (x ) 的 s
值。如果存在两个这样的 s 可能值,则选择偶数那个。注意,k 是使用基数
radix 表示 s 的位数,并且 s 不能被
radix 整除。
注3
ECMAScript 的实现者可能会发现 David M. Gay 编写的用于浮点数二进制到十进制转换的论文和代码很有用:
Gay, David M. Correctly Rounded Binary-Decimal and Decimal-Binary Conversions.
Numerical Analysis, Manuscript 90-10. AT&T Bell Laboratories (Murray Hill,
New Jersey). 1990年11月30日。可从以下网址获取:
https://ampl.com/_archive/first-website/REFS/rounding.pdf 。
相关代码可从以下网址获取:
http://netlib.sandia.gov/fp/dtoa.c
和
http://netlib.sandia.gov/fp/g_fmt.c
也可以在各种 netlib
镜像站点找到。
6.1.6.2 BigInt 类型
BigInt 类型 表示一个整数 值。该值可以是任意大小,不限于特定的位宽。一般来说,除非另有说明,操作被设计为返回精确的基于数学的答案。对于二进制操作,BigInt
表现为二进制补码字符串,负数被视为左侧无限设置位。
6.1.6.2.1 BigInt::unaryMinus ( x )
抽象操作 BigInt::unaryMinus 接受参数 x (一个 BigInt)并返回一个 BigInt。调用时执行以下步骤:
如果 x = 0 ℤ ,返回
0 ℤ 。
返回 -x 。
6.1.6.2.2 BigInt::bitwiseNOT ( x )
抽象操作 BigInt::bitwiseNOT 接受参数 x (一个 BigInt)并返回一个 BigInt。它返回 x
的一的补码。调用时执行以下步骤:
返回 -x - 1 ℤ 。
6.1.6.2.3 BigInt::exponentiate ( base ,
exponent )
抽象操作 BigInt::exponentiate 接受参数 base (一个 BigInt)和 exponent (一个
BigInt),返回包含 BigInt
的正常完成或抛出完成 。调用时执行以下步骤:
如果 exponent < 0 ℤ ,抛出
RangeError 异常。
如果 base = 0 ℤ 且 exponent =
0 ℤ ,返回 1 ℤ 。
返回 base 的 exponent 次幂。
6.1.6.2.4 BigInt::multiply ( x , y )
抽象操作 BigInt::multiply 接受参数 x (一个 BigInt)和 y (一个 BigInt)并返回一个
BigInt。调用时执行以下步骤:
返回 x × y 。
注意
即使结果的位宽比输入大得多,也会给出精确的数学答案。
6.1.6.2.5 BigInt::divide ( x , y )
抽象操作 BigInt::divide 接受参数 x (一个 BigInt)和 y (一个 BigInt),返回包含 BigInt
的正常完成或抛出完成 。调用时执行以下步骤:
如果 y = 0 ℤ ,抛出
RangeError 异常。
令 quotient 为 ℝ (x ) / ℝ (y )。
返回 ℤ (truncate (quotient ))。
6.1.6.2.6 BigInt::remainder ( n , d )
抽象操作 BigInt::remainder 接受参数 n (一个 BigInt)和 d (一个 BigInt),返回包含 BigInt
的正常完成或抛出完成 。调用时执行以下步骤:
如果 d = 0 ℤ ,抛出
RangeError 异常。
如果 n = 0 ℤ ,返回
0 ℤ 。
令 quotient 为 ℝ (n ) / ℝ (d )。
令 q 为 ℤ (truncate (quotient ))。
返回 n - (d × q )。
注意
结果的符号是被除数的符号。
6.1.6.2.7 BigInt::add ( x , y )
抽象操作 BigInt::add 接受参数 x (一个 BigInt)和 y (一个 BigInt)并返回一个
BigInt。调用时执行以下步骤:
返回 x + y 。
6.1.6.2.8 BigInt::subtract ( x , y )
抽象操作 BigInt::subtract 接受参数 x (一个 BigInt)和 y (一个 BigInt)并返回一个
BigInt。调用时执行以下步骤:
返回 x - y 。
6.1.6.2.9 BigInt::leftShift ( x , y )
抽象操作 BigInt::leftShift 接受参数 x (一个 BigInt)和 y (一个 BigInt)并返回一个
BigInt。调用时执行以下步骤:
如果 y < 0 ℤ ,则
返回 ℤ (floor (ℝ (x )
/ 2-ℝ (y ) ))。
返回 x × 2 ℤ y 。
注意
这里的语义应该等同于按位移位,将 BigInt 视为无限长度的二进制补码数字字符串。
6.1.6.2.10 BigInt::signedRightShift ( x ,
y )
抽象操作 BigInt::signedRightShift 接受参数 x (一个 BigInt)和 y (一个 BigInt)并返回一个
BigInt。调用时执行以下步骤:
返回 BigInt::leftShift (x ,
-y )。
6.1.6.2.11 BigInt::unsignedRightShift ( x ,
y )
抽象操作 BigInt::unsignedRightShift 接受参数 x (一个 BigInt)和 y (一个
BigInt)并返回抛出完成 。调用时执行以下步骤:
抛出 TypeError 异常。
6.1.6.2.12 BigInt::lessThan ( x , y )
抽象操作 BigInt::lessThan 接受参数 x (一个 BigInt)和 y (一个
BigInt)并返回一个布尔值。调用时执行以下步骤:
如果 ℝ (x )
< ℝ (y ),返回 true ;否则返回
false 。
6.1.6.2.13 BigInt::equal ( x , y )
抽象操作 BigInt::equal 接受参数 x (一个 BigInt)和 y (一个
BigInt)并返回一个布尔值。调用时执行以下步骤:
如果 ℝ (x )
= ℝ (y ),返回 true ;否则返回
false 。
6.1.6.2.14 BinaryAnd ( x , y )
抽象操作 BinaryAnd 接受参数 x (0 或 1)和 y (0 或 1)并返回 0 或 1。调用时执行以下步骤:
如果 x = 1 且 y = 1,返回 1。
否则,返回 0。
6.1.6.2.15 BinaryOr ( x , y )
抽象操作 BinaryOr 接受参数 x (0 或 1)和 y (0 或 1)并返回 0 或 1。调用时执行以下步骤:
如果 x = 1 或 y = 1,返回 1。
否则,返回 0。
6.1.6.2.16 BinaryXor ( x , y )
抽象操作 BinaryXor 接受参数 x (0 或 1)和 y (0 或 1)并返回 0 或 1。调用时执行以下步骤:
如果 x = 1 且 y = 0,返回 1。
否则如果 x = 0 且 y = 1,返回 1。
否则,返回 0。
6.1.6.2.17 BigIntBitwiseOp ( op , x ,
y )
抽象操作 BigIntBitwiseOp 接受参数 op (&
、^
或
|
)、x (一个 BigInt)和 y (一个 BigInt)并返回一个 BigInt。调用时执行以下步骤:
设置 x 为 ℝ (x )。
设置 y 为 ℝ (y )。
令 result 为 0。
令 shift 为 0。
重复执行,直到 (x = 0 或 x = -1) 且 (y = 0 或
y = -1):
令 xDigit 为 x modulo 2。
令 yDigit 为 y modulo 2。
如果 op 是 &
,则
设置 result 为 result +
2shift × BinaryAnd (xDigit ,
yDigit )。
否则如果 op 是 |
,则
设置 result 为 result +
2shift × BinaryOr (xDigit ,
yDigit )。
否则,
断言 :op 是
^
。
设置 result 为 result +
2shift × BinaryXor (xDigit ,
yDigit )。
设置 shift 为 shift + 1。
设置 x 为 (x - xDigit ) / 2。
设置 y 为 (y - yDigit ) / 2。
如果 op 是 &
,则
令 tmp 为 BinaryAnd (x
modulo 2, y
modulo 2)。
否则如果 op 是 |
,则
令 tmp 为 BinaryOr (x
modulo 2, y
modulo 2)。
否则,
断言 :op 是 ^
。
令 tmp 为 BinaryXor (x
modulo 2, y
modulo 2)。
如果 tmp ≠ 0,则
设置 result 为 result - 2shift 。
注意:这扩展了符号。
返回 result 的 BigInt 值 。
6.1.6.2.18 BigInt::bitwiseAND ( x , y )
抽象操作 BigInt::bitwiseAND 接受参数 x (一个 BigInt)和 y (一个 BigInt)并返回一个
BigInt。调用时执行以下步骤:
返回 BigIntBitwiseOp (&
,
x , y )。
6.1.6.2.19 BigInt::bitwiseXOR ( x , y )
抽象操作 BigInt::bitwiseXOR 接受参数 x (一个 BigInt)和 y (一个 BigInt)并返回一个
BigInt。调用时执行以下步骤:
返回 BigIntBitwiseOp (^
,
x , y )。
6.1.6.2.20 BigInt::bitwiseOR ( x , y )
抽象操作 BigInt::bitwiseOR 接受参数 x (一个 BigInt)和 y (一个 BigInt)并返回一个
BigInt。调用时执行以下步骤:
返回 BigIntBitwiseOp (|
,
x , y )。
6.1.6.2.21 BigInt::toString ( x , radix
)
抽象操作 BigInt::toString 接受参数 x (一个 BigInt)和 radix (一个在 2 到 36
的闭区间 内的整数 )并返回一个字符串。它使用基数为 radix
的位置记数法将 x 表示为字符串。在基数为 r 的 BigInt 表示中使用的数字取自
"0123456789abcdefghijklmnopqrstuvwxyz" 的前 r 个代码单元。除了
0 ℤ 之外的 BigInt 表示从不包含前导零。调用时执行以下步骤:
如果 x < 0 ℤ ,返回 "-"
和 BigInt::toString (-x ,
radix ) 的字符串连接 。
返回使用基数 radix 表示 x 的字符串值。
6.1.7 Object 类型
Object 类型 的每个实例,也简称为"一个
Object",表示属性的集合。每个属性要么是数据属性,要么是访问器属性:
对象的属性使用属性键 唯一标识。 属性键 要么是字符串,要么是符号。所有字符串和符号(包括空字符串)都可以作为属性键 。属性名 是字符串 类型的属性键 。
整数索引 是属性名 n ,使得 CanonicalNumericIndexString (n )
返回闭区间 从 +0 𝔽 到
𝔽 (253 - 1)
的整数 。数组索引 是整数索引 n ,使得 CanonicalNumericIndexString (n )
返回闭区间 从 +0 𝔽 到
𝔽 (232 - 2)
的整数 。
注意
每个非负安全整数 都有对应的整数索引 。除了 232 - 1 之外的每个 32 位无符号整数 都有对应的数组索引 。"-0" 既不是整数索引 也不是数组索引 。
属性键 用于访问属性及其值。属性有两种访问方式:get 和
set ,分别对应值检索和赋值。通过 get 和 set
访问的属性包括作为对象直接部分的自有属性 和通过属性继承关系由另一个关联对象提供的继承属性 。继承属性可能是关联对象的自有属性或继承属性。对象的每个自有属性都必须具有与该对象的其他自有属性的键值不同的键值。
所有对象在逻辑上都是属性的集合,但存在多种形式的对象,它们在访问和操作属性的语义上有所不同。请参见6.1.7.2 了解多种形式对象的定义。
此外,某些对象是可调用的;这些被称为函数或函数对象 ,下面将进一步描述。ECMAScript 中的所有函数都是 Object 类型的成员。
6.1.7.1 属性特性
本规范使用特性来定义和解释 Object 属性的状态,如表
3 所述。除非明确指定,否则每个特性的初始值是其默认值。
表 3:Object 属性的特性
特性名称
存在该特性的属性类型
值域
默认值
描述
[[Value]]
数据属性
ECMAScript
语言值
undefined
通过对属性的 get 访问检索到的值。
[[Writable]]
数据属性
布尔值
false
如果为 false ,ECMAScript 代码尝试使用 [[Set]] 更改属性的 [[Value]]
特性将不会成功。
[[Get]]
访问器属性
Object 或 undefined
undefined
如果值是一个 Object ,它必须是函数对象 。每当执行对属性的 get
访问时,都会使用空参数列表调用该函数的 [[Call]] 内部方法(表
5 )来检索属性值。
[[Set]]
访问器属性
Object 或 undefined
undefined
如果值是一个 Object ,它必须是函数对象 。每当执行对属性的 set
访问时,都会使用包含赋值作为其唯一参数的参数列表调用该函数的 [[Call]]
内部方法(表
5 )。属性的 [[Set]]
内部方法的效果可能但不一定会影响后续调用属性的 [[Get]] 内部方法返回的值。
[[Enumerable]]
数据属性 或访问器属性
布尔值
false
如果为 true ,该属性将被 for-in 枚举(参见14.7.5 )枚举。否则,该属性被称为不可枚举的。
[[Configurable]]
数据属性 或访问器属性
布尔值
false
如果为 false ,尝试删除属性、将其从数据属性 更改为访问器属性 或从访问器属性 更改为数据属性 ,或对其特性进行任何更改(除了替换现有的
[[Value]] 或将 [[Writable]] 设置为 false )都将失败。
6.1.7.2 对象内部方法和内部槽
在 ECMAScript 中,对象的实际语义通过称为内部方法 的算法指定。ECMAScript 引擎中的每个对象都与一组定义其运行时行为的内部方法相关联。这些内部方法不是
ECMAScript 语言的一部分。它们由本规范纯粹为了解释目的而定义。但是,ECMAScript
实现中的每个对象都必须按照与其关联的内部方法所指定的方式行为。实现这一点的确切方式由实现决定。
内部方法名称是多态的。这意味着当在不同的对象值上调用相同的内部方法名称时,可能执行不同的算法。实际调用内部方法的对象是调用的"目标"。如果在运行时,算法的实现尝试使用对象不支持的内部方法,则抛出
TypeError 异常。
内部槽对应于与对象关联并由各种 ECMAScript 规范算法使用的内部状态。内部槽不是对象属性,它们不被继承。根据特定的内部槽规范,这种状态可能由任何ECMAScript 语言类型 的值或特定 ECMAScript
规范类型值组成。除非明确指定,否则内部槽作为创建对象过程的一部分分配,并且不能动态添加到对象中。除非另有指定,内部槽的初始值是
undefined 。本规范中的各种算法创建具有内部槽的对象。但是,ECMAScript 语言没有提供将内部槽与对象关联的直接方法。
所有对象都有一个名为 [[PrivateElements]] 的内部槽,它是PrivateElements
的列表 。这个列表 表示对象的私有字段、方法和访问器的值。最初,它是一个空列表 。
内部方法和内部槽在本规范中使用双方括号 [[ ]] 括起来的名称标识。
表
4 总结了本规范使用的基本内部方法 ,适用于 ECMAScript
代码创建或操作的所有对象。每个对象都必须具有所有基本内部方法的算法。但是,并非所有对象都必须为这些方法使用相同的算法。
普通对象 是满足以下所有条件的对象:
异质对象 是不是普通对象 的对象。
本规范通过对象的内部方法识别不同种类的异质对象 。行为上等同于特定种类异质对象 (如数组异质对象 或绑定函数异质对象 )但没有为该种类指定的相同内部方法集合的对象,不被识别为该种类的异质对象 。
表
4 和其他类似表的"签名"列描述了每个内部方法的调用模式。调用模式总是包括描述性参数名称的括号列表。如果参数名称与 ECMAScript
类型名称相同,则该名称描述参数值的所需类型。如果内部方法明确返回值,其参数列表后跟符号"→"和返回值的类型名称。签名中使用的类型名称指的是第6 节中定义的类型,并由以下附加名称扩展。"any "意味着该值可能是任何ECMAScript 语言类型 。
除了参数之外,内部方法始终可以访问作为方法调用目标的对象。
内部方法隐式返回完成记录 ,要么是包装其调用模式中显示的返回类型值的正常完成 ,要么是抛出完成 。
表 4:基本内部方法
内部方法
签名
描述
[[GetPrototypeOf]]
( ) → Object | Null
确定为此对象提供继承属性的对象。null 值表示没有继承属性。
[[SetPrototypeOf]]
(Object | Null) → Boolean
将此对象与提供继承属性的另一个对象关联。传递 null 表示没有继承属性。返回
true 表示操作成功完成,或 false 表示操作不成功。
[[IsExtensible]]
( ) → Boolean
确定是否允许向此对象添加额外属性。
[[PreventExtensions]]
( ) → Boolean
控制是否可以向此对象添加新属性。如果操作成功则返回 true ,如果操作不成功则返回
false 。
[[GetOwnProperty]]
(propertyKey ) → Undefined | Property
Descriptor
返回此对象键为 propertyKey 的自有属性的属性描述符 ,如果不存在这样的属性则返回
undefined 。
[[DefineOwnProperty]]
(propertyKey , PropertyDescriptor ) → Boolean
创建或更改键为 propertyKey 的自有属性,使其具有 PropertyDescriptor
描述的状态。如果该属性成功创建/更新则返回 true ,如果无法创建或更新该属性则返回
false 。
[[HasProperty]]
(propertyKey ) → Boolean
返回布尔值,表示此对象是否已经具有键为 propertyKey 的自有或继承属性。
[[Get]]
(propertyKey , Receiver ) → any
从此对象返回键为 propertyKey 的属性值。如果必须执行任何 ECMAScript
代码来检索属性值,Receiver 用作评估代码时的 this 值。
[[Set]]
(propertyKey , value , Receiver ) →
Boolean
将键为 propertyKey 的属性值设置为 value 。如果必须执行任何 ECMAScript
代码来设置属性值,Receiver 用作评估代码时的 this
值。如果属性值已设置则返回 true ,如果无法设置则返回
false 。
[[Delete]]
(propertyKey ) → Boolean
从此对象中删除键为 propertyKey 的自有属性。如果属性未被删除且仍然存在则返回
false 。如果属性已被删除或不存在则返回 true 。
[[OwnPropertyKeys]]
( ) → List
of property keys
返回一个列表 ,其元素是对象的所有自有属性键 。
表
5 总结了可作为函数调用的对象支持的额外基本内部方法。函数对象 是支持 [[Call]] 内部方法的对象。构造器 是支持 [[Construct]] 内部方法的对象。每个支持 [[Construct]] 的对象都必须支持 [[Call]] ;也就是说,每个构造器 都必须是函数对象 。因此,构造器 也可以称为构造器 函数 或构造器 函数对象 。
表 5:函数对象的额外基本内部方法
内部方法
签名
描述
[[Call]]
(any , a List
of any ) → any
执行与此对象关联的代码。通过函数调用表达式调用。内部方法的参数是 this 值和一个列表 ,其元素是通过调用表达式传递给函数的参数。实现此内部方法的对象是可调用的 。
[[Construct]]
(a List
of any , Object) → Object
创建对象。通过 new
操作符或 super
调用调用。内部方法的第一个参数是一个列表 ,其元素是构造器 调用或 super
调用的参数。第二个参数是最初应用 new
操作符的对象。实现此内部方法的对象称为构造器 。函数对象 不一定是构造器 ,这种非构造器 函数对象 没有 [[Construct]] 内部方法。
普通对象 和标准异质对象 的基本内部方法的语义在第10 节中指定。如果实现不支持异质对象 的内部方法的任何指定使用,则在尝试时该使用必须抛出
TypeError 异常。
6.1.7.3 基本内部方法的不变式
ECMAScript 引擎中对象的内部方法必须符合下面指定的不变式列表。本规范中的普通 ECMAScript 对象以及所有标准异质对象 都保持这些不变式。ECMAScript 代理对象通过对 [[ProxyHandler]] 对象上调用的陷阱结果进行运行时检查来维持这些不变式。
任何实现提供的异质对象 也必须为这些对象维持这些不变式。违反这些不变式可能导致 ECMAScript
代码出现不可预测的行为并产生安全问题。但是,违反这些不变式绝不能损害实现的内存安全。
实现不得允许以任何方式规避这些不变式,例如通过提供实现基本内部方法功能但不强制执行其不变式的替代接口。
定义:
内部方法的 目标 是调用内部方法的对象。
如果目标被观察到从其 [[IsExtensible]] 内部方法返回 false ,或从其
[[PreventExtensions]] 内部方法返回 true ,则目标是
不可扩展的 。
不存在的 属性是在不可扩展目标上不作为自有属性存在的属性。
所有对 SameValue 的引用都根据 SameValue
算法的定义。
返回值:
任何内部方法返回的值必须是一个完成记录 ,具有以下之一:
[[Type]] = normal ,[[Target]] = empty ,并且 [[Value]] = 下面为该内部方法显示的"正常返回类型"的值,或
[[Type]] = throw ,[[Target]] = empty ,并且 [[Value]] = 任何ECMAScript
语言值 。
注意 1
[[GetPrototypeOf]] ( )
正常返回类型是 Object 或 Null。
如果目标是不可扩展的,并且 [[GetPrototypeOf]] 返回值 V ,那么将来对 [[GetPrototypeOf]] 的所有调用都应该返回与 V SameValue
相同的值。
注意 2
对象的原型链应该具有有限 长度(即,从任何对象开始,递归地将 [[GetPrototypeOf]] 内部方法应用于其结果最终应该导致值
null )。但是,如果原型链包含任何不使用普通对象 的 [[GetPrototypeOf]] 定义的异质对象 ,则此要求无法作为对象级不变式强制执行。这样的循环原型链在访问对象属性时可能导致无限循环。
[[SetPrototypeOf]] ( V )
正常返回类型是 Boolean。
如果目标是不可扩展的,[[SetPrototypeOf]] 必须返回 false ,除非
V 与目标观察到的 [[GetPrototypeOf]] 值为SameValue 。
[[IsExtensible]] ( )
正常返回类型是 Boolean。
如果 [[IsExtensible]] 返回 false ,将来在目标上的所有 [[IsExtensible]] 调用必须返回 false 。
[[PreventExtensions]] ( )
正常返回类型是 Boolean。
如果 [[PreventExtensions]] 返回 true ,将来在目标上的所有
[[IsExtensible]] 调用必须返回
false ,并且目标现在被视为不可扩展的。
[[GetOwnProperty]] ( P )
正常返回类型是属性描述符 或
Undefined。
如果返回值是属性描述符 ,它必须是一个完全填充的属性描述符 。
如果 P 被描述为不可配置、不可写的自有数据属性 ,将来对 [[GetOwnProperty]] ( P ) 的所有调用必须返回其 [[Value]] 与 P 的 [[Value]]
特性为SameValue 的属性描述符 。
如果 P 的除 [[Writable]] 和 [[Value]] 之外的特性可能随时间改变,或者属性可能被删除,那么 P 的 [[Configurable]] 特性必须是 true 。
如果 [[Writable]] 特性可能从 false 变为
true ,那么 [[Configurable]] 特性必须是
true 。
如果目标是不可扩展的并且 P 是不存在的,那么将来在目标上对 [[GetOwnProperty]]
(P ) 的所有调用必须将 P 描述为不存在的(即 [[GetOwnProperty]] (P ) 必须返回
undefined )。
注意 3
作为第三个不变式的结果,如果属性被描述为数据属性 并且它可能随时间返回不同的值,那么 [[Writable]] 和 [[Configurable]]
特性中的一个或两个必须是 true ,即使没有通过其他基本内部方法暴露改变值的机制。
[[DefineOwnProperty]] ( P , Desc )
正常返回类型是 Boolean。
如果 P 之前被观察为目标的不可配置自有属性,那么 [[DefineOwnProperty]] 必须返回
false ,除非以下之一:
P 是可写的数据属性 。不可配置的可写数据属性 可以更改为不可配置的不可写数据属性 。
Desc 的所有特性都与 P 的特性为SameValue 。
如果目标是不可扩展的并且 P 是不存在的自有属性,那么 [[DefineOwnProperty]]
(P , Desc ) 必须返回 false 。也就是说,不可扩展的目标对象不能用新属性扩展。
[[HasProperty]] ( P )
正常返回类型是 Boolean。
如果 P 之前被观察为目标的不可配置自有数据或访问器属性 ,那么 [[HasProperty]] 必须返回 true 。
[[Get]] ( P , Receiver )
正常返回类型是任何ECMAScript 语言类型 。
如果 P 之前被观察为目标的值为 V 的不可配置、不可写的自有数据属性 ,那么 [[Get]] 必须返回与 V SameValue 相同的值。
如果 P 之前被观察为目标的 [[Get]] 特性为
undefined 的不可配置自有访问器属性 ,那么 [[Get]]
操作必须返回 undefined 。
[[Set]] ( P , V , Receiver )
正常返回类型是 Boolean。
如果 P 之前被观察为目标的不可配置、不可写的自有数据属性 ,那么 [[Set]]
必须返回 false ,除非 V 与 P 的 [[Value]] 特性为SameValue 。
如果 P 之前被观察为目标的 [[Set]] 特性为
undefined 的不可配置自有访问器属性 ,那么 [[Set]]
操作必须返回 false 。
[[Delete]] ( P )
正常返回类型是 Boolean。
如果 P 之前被观察为目标的不可配置自有数据或访问器属性 ,那么 [[Delete]] 必须返回 false 。
[[OwnPropertyKeys]] ( )
正常返回类型是列表 。
返回的列表 不得包含任何重复条目。
返回的列表 的每个元素必须是属性键 。
返回的列表 必须至少包含所有之前被观察到的不可配置自有属性的键。
如果目标是不可扩展的,返回的列表 必须只包含使用 [[GetOwnProperty]] 可观察到的目标的所有自有属性的键。
[[Call]] ( )
[[Construct]] ( )
正常返回类型是 Object。
目标也必须有一个 [[Call]] 内部方法。
6.1.7.4 知名内置对象
知名内置对象是被本规范算法明确引用的内置对象,通常具有域 特定的标识。除非另有说明,每个内置对象实际上对应一组相似的对象,每个域 一个。
在本规范中,像 %name% 这样的引用意味着与当前域 关联的、对应于该名称的内置对象。像 %name.a.b% 这样的引用意味着,就像在任何 ECMAScript
代码被评估之前访问内置对象 %name% 的 "a" 属性的值的 "b" 属性一样。当前域 及其内置对象的确定在9.4 中描述。知名内置对象列在表 6 中。
表 6:知名内置对象
注意
6.2 ECMAScript 规范类型
规范类型对应于在算法中用于描述 ECMAScript 语言构造和ECMAScript 语言类型 语义的元值。规范类型包括引用记录 、列表 、完成记录 、属性描述符 、环境记录 、抽象闭包 和数据块 。规范类型值是规范工件,不一定对应于 ECMAScript
实现中的任何特定实体。规范类型值可用于描述 ECMAScript 表达式求值的中间结果,但此类值不能存储为对象的属性或 ECMAScript 语言变量的值。
6.2.1 枚举规范类型
枚举 是规范内部的值,不能从 ECMAScript
代码直接观察到。枚举使用无衬线 字体表示。例如,完成记录 的 [[Type]] 字段取值如
normal 、return 或
throw 。枚举除了名称之外没有其他特征。枚举的名称除了将其与其他枚举区分开来之外没有其他目的,并且不暗示其在上下文中的用法或含义。
6.2.2 列表和记录规范类型
列表 类型用于解释 new
表达式、函数调用和其他需要简单有序值列表的算法中参数列表的求值(参见13.3.8 )。列表类型的值只是包含各个值的列表元素的有序序列。这些序列可以是任意长度。列表的元素可以使用从
0 开始的索引随机访问。为了方便表示,可以使用类似数组的语法来访问列表元素。例如,arguments [2] 是表示列表 arguments 第 3
个元素的简写。
当算法遍历列表的元素而不指定顺序时,使用的顺序是列表中元素的顺序。
为了在本规范中方便表示,可以使用字面量语法来表达新的列表值。例如,« 1, 2 » 定义了一个有两个元素的列表值,每个元素都初始化为特定值。新的空列表可以表示为 « »。
在本规范中,短语"A 、B 、... 的列表连接 "(其中每个参数都是可能为空的列表)表示一个新的列表值,其元素是每个参数的元素(按顺序)的连接(按顺序)。
当应用于字符串列表时,短语"按字典序码元顺序 排序"意味着按每个码元的数值排序,直到较短字符串的长度,如果所有都相等,则较短的字符串排在较长的字符串之前,如抽象操作IsLessThan 中所述。
记录 类型用于描述本规范算法中的数据聚合。记录类型值由一个或多个命名字段组成。每个字段的值是ECMAScript 语言值 或规范值。字段名总是用双括号括起来,例如
[[Value]] 。
为了在本规范中方便表示,可以使用类似对象字面量的语法来表达记录值。例如,{ [[Field1]] : 42, [[Field2]] : false , [[Field3]] : empty }
定义了一个有三个字段的记录值,每个字段都初始化为特定值。字段名顺序不重要。任何未明确列出的字段都被认为是缺失的。
在规范文本和算法中,可以使用点记法来引用记录值的特定字段。例如,如果 R 是前一段中显示的记录,那么 R.[[Field2]] 是"R 中名为
[[Field2]] 的字段"的简写。
常用记录字段组合的模式可以被命名,该名称可以用作字面量记录值的前缀,以标识所描述的特定类型的聚合。例如:PropertyDescriptor { [[Value]] : 42, [[Writable]] :
false , [[Configurable]] : true }。
6.2.3 集合和关系规范类型
集合 类型用于解释在内存模型 中使用的无序元素集合。它不同于同名的 ECMAScript
集合类型。为了消除歧义,ECMAScript 集合的实例在本规范中始终称为"Set
对象"。集合类型的值是元素的简单集合,其中没有元素出现超过一次。元素可以添加到集合中或从集合中移除。集合可以进行并集、交集或相减操作。
关系 类型用于解释对集合的约束。关系类型的值是其值域中值的有序对的集合。例如,事件上的关系是事件有序对的集合。对于关系 R
和 R 值域中的两个值 a 和 b ,a R b 是说有序对
(a , b ) 是 R 的成员的简写。关系是相对于某些条件的最小关系 ,当它是满足这些条件的最小关系时。
严格偏序 是满足以下条件的关系值 R 。
对于 R 域中的所有 a 、b 和 c :
a R a 不成立,并且
如果 a R b 且 b R
c ,那么 a R c 。
注意 1
严格全序 是满足以下条件的关系值 R 。
对于 R 域中的所有 a 、b 和 c :
a 是 b 或 a R b 或 b
R a ,并且
a R a 不成立,并且
如果 a R b 且 b R
c ,那么 a R c 。
注意 2
6.2.4 完成记录规范类型
完成记录 规范类型用于解释值和控制流的运行时传播,例如执行非本地控制转移的语句(break
、continue
、return
和 throw
)的行为。
完成记录具有表 7 中定义的字段。
表 7:完成记录 字段
字段名
值
含义
[[Type]]
normal 、break 、continue 、return
或 throw
发生的完成类型。
[[Value]]
除完成记录 之外的任何值
产生的值。
[[Target]]
一个字符串或 empty
定向控制转移的目标标签。
以下简写术语有时用于指代完成记录。
正常完成 指任何 [[Type]] 值为 normal 的完成记录。
break 完成 指任何 [[Type]] 值为 break 的完成记录。
continue 完成 指任何 [[Type]] 值为 continue 的完成记录。
return 完成 指任何 [[Type]] 值为 return 的完成记录。
throw 完成 指任何 [[Type]] 值为 throw 的完成记录。
突然完成 指任何 [[Type]] 值不是 normal 的完成记录。
包含某种类型值的正常完成 指在其 [[Value]] 字段中具有该类型值的正常完成。
本规范中定义的可调用对象只返回正常完成或 throw 完成。返回任何其他类型的完成记录被认为是编辑错误。
实现定义的 可调用对象必须返回正常完成或 throw 完成。
6.2.4.1 NormalCompletion ( value )
抽象操作 NormalCompletion 接受参数 value (除完成记录 之外的任何值)并返回一个正常完成 。它在被调用时执行以下步骤:
返回完成记录 { [[Type]] : normal , [[Value]] : value , [[Target]] : empty }。
6.2.4.2 ThrowCompletion ( value )
抽象操作 ThrowCompletion 接受参数 value (一个ECMAScript
语言值 )并返回一个throw
完成 。它在被调用时执行以下步骤:
返回完成记录 { [[Type]] : throw , [[Value]] : value , [[Target]] : empty }。
6.2.4.3 ReturnCompletion ( value )
抽象操作 ReturnCompletion 接受参数 value (一个ECMAScript
语言值 )并返回一个return
完成 。它在被调用时执行以下步骤:
返回完成记录 { [[Type]] : return , [[Value]] : value , [[Target]] : empty }。
6.2.4.4 UpdateEmpty ( completionRecord ,
value )
抽象操作 UpdateEmpty 接受参数 completionRecord (一个完成记录 )和
value (除完成记录 之外的任何值)并返回一个完成记录 。它在被调用时执行以下步骤:
断言 :如果
completionRecord 是return
完成 或throw
完成 ,那么 completionRecord .[[Value]] 不是 empty 。
如果 completionRecord .[[Value]] 不是
empty ,返回 ? completionRecord 。
返回完成记录 { [[Type]] : completionRecord .[[Type]] , [[Value]] :
value , [[Target]] :
completionRecord .[[Target]] }。
6.2.5 引用记录规范类型
引用记录 类型用于解释诸如
delete
、typeof
、赋值运算符、super
关键字 和其他语言特性的行为。例如,赋值的左操作数应该产生一个引用记录。
引用记录是一个已解析的名称或(可能尚未解析的)属性绑定;其字段由表 8 定义。
表 8:引用记录 字段
本规范中使用以下抽象操作 来操作引用记录:
6.2.5.1 IsPropertyReference ( V )
抽象操作 IsPropertyReference 接受参数 V (一个引用记录 )并返回一个布尔值。它在被调用时执行以下步骤:
如果 V .[[Base]] 是
unresolvable ,返回 false 。
如果 V .[[Base]] 是环境记录 ,返回
false ;否则返回 true 。
6.2.5.2 IsUnresolvableReference ( V )
抽象操作 IsUnresolvableReference 接受参数 V (一个引用记录 )并返回一个布尔值。它在被调用时执行以下步骤:
如果 V .[[Base]] 是
unresolvable ,返回 true ;否则返回
false 。
6.2.5.3 IsSuperReference ( V )
抽象操作 IsSuperReference 接受参数 V (一个引用记录 )并返回一个布尔值。它在被调用时执行以下步骤:
如果 V .[[ThisValue]] 不是
empty ,返回 true ;否则返回
false 。
6.2.5.4 IsPrivateReference ( V )
抽象操作 IsPrivateReference 接受参数 V (一个引用记录 )并返回一个布尔值。它在被调用时执行以下步骤:
如果 V .[[ReferencedName]] 是私有名称 ,返回
true ;否则返回 false 。
6.2.5.5 GetValue ( V )
抽象操作 GetValue 接受参数 V (一个引用记录 或一个ECMAScript 语言值 )并返回一个包含 ECMAScript 语言值 的正常完成 或一个突然完成 。它在被调用时执行以下步骤:
如果 V 不是引用记录 ,返回
V 。
如果IsUnresolvableReference (V )
是 true ,抛出 ReferenceError 异常。
如果IsPropertyReference (V )
是 true ,那么
设 baseObj 为 ? ToObject (V .[[Base]] )。
如果IsPrivateReference (V )
是 true ,那么
返回 ? PrivateGet (baseObj ,
V .[[ReferencedName]] )。
如果 V .[[ReferencedName]] 不是属性键 ,那么
设 V .[[ReferencedName]] 为
? ToPropertyKey (V .[[ReferencedName]] )。
返回 ? baseObj .[[Get]] (V .[[ReferencedName]] , GetThisValue (V ))。
否则,
设 base 为 V .[[Base]] 。
断言 :base 是环境记录 。
返回 ? base .GetBindingValue (V .[[ReferencedName]] , V .[[Strict]] )(参见9.1 )。
注意
在步骤3.a 中可能创建的对象在上述抽象操作和普通对象 的 [[Get]] 内部方法之外是不可访问的。实现可能选择避免实际创建该对象。
6.2.5.6 PutValue ( V , W )
抽象操作 PutValue 接受参数 V (一个引用记录 或一个ECMAScript 语言值 )和
W (一个ECMAScript 语言值 )并返回一个包含
unused 的正常完成 或一个突然完成 。它在被调用时执行以下步骤:
如果 V 不是引用记录 ,抛出
ReferenceError 异常。
如果IsUnresolvableReference (V )
是 true ,那么
如果 V .[[Strict]] 是
true ,抛出 ReferenceError 异常。
设 globalObj 为GetGlobalObject ()。
执行 ? Set (globalObj ,
V .[[ReferencedName]] , W ,
false )。
返回 unused 。
如果IsPropertyReference (V )
是 true ,那么
设 baseObj 为 ? ToObject (V .[[Base]] )。
如果IsPrivateReference (V )
是 true ,那么
返回 ? PrivateSet (baseObj ,
V .[[ReferencedName]] ,
W )。
如果 V .[[ReferencedName]] 不是属性键 ,那么
设 V .[[ReferencedName]] 为
? ToPropertyKey (V .[[ReferencedName]] )。
设 succeeded 为 ? baseObj .[[Set]] (V .[[ReferencedName]] , W , GetThisValue (V ))。
如果 succeeded 是 false 且 V .[[Strict]] 是 true ,抛出
TypeError 异常。
返回 unused 。
否则,
设 base 为 V .[[Base]] 。
断言 :base 是环境记录 。
返回 ? base .SetMutableBinding (V .[[ReferencedName]] , W , V .[[Strict]] )(参见9.1 )。
注意
在步骤3.a 中可能创建的对象在上述抽象操作和普通对象 的 [[Set]] 内部方法之外是不可访问的。实现可能选择避免实际创建该对象。
6.2.5.7 GetThisValue ( V )
抽象操作 GetThisValue 接受参数 V (一个引用记录 )并返回一个ECMAScript 语言值 。它在被调用时执行以下步骤:
断言 :IsPropertyReference (V )
是 true 。
如果IsSuperReference (V ) 是
true ,返回 V .[[ThisValue]] ;否则返回
V .[[Base]] 。
6.2.5.8 InitializeReferencedBinding ( V , W
)
抽象操作 InitializeReferencedBinding 接受参数 V (一个引用记录 )和
W (一个ECMAScript 语言值 )并返回一个包含
unused 的正常完成 或一个突然完成 。它在被调用时执行以下步骤:
断言 :IsUnresolvableReference (V )
是 false 。
设 base 为 V .[[Base]] 。
断言 :base 是环境记录 。
返回 ? base .InitializeBinding(V .[[ReferencedName]] , W )。
6.2.5.9 MakePrivateReference ( baseValue ,
privateIdentifier )
抽象操作 MakePrivateReference 接受参数 baseValue (一个ECMAScript 语言值 )和
privateIdentifier (一个字符串)并返回一个引用记录 。它在被调用时执行以下步骤:
设 privateEnv 为运行执行上下文 的
PrivateEnvironment。
断言 :privateEnv 不是
null 。
设 privateName 为ResolvePrivateIdentifier (privateEnv ,
privateIdentifier )。
返回引用记录 { [[Base]] : baseValue , [[ReferencedName]] : privateName , [[Strict]] : true , [[ThisValue]] : empty }。
6.2.6 属性描述符规范类型
属性描述符 类型用于解释对象属性特性的操作和具体化。属性描述符是一个具有零个或多个字段的记录 ,其中每个字段的名称是一个特性名称,其值是6.1.7.1 中指定的相应特性值。本规范中用于标记属性描述符记录字面量描述的模式名称是"PropertyDescriptor"。
属性描述符值可以根据某些字段的存在或使用进一步分类为数据属性描述符和访问器属性描述符。数据属性描述符是包含名为 [[Value]] 或 [[Writable]] 的任何字段的描述符。访问器属性描述符是包含名为 [[Get]] 或
[[Set]] 的任何字段的描述符。任何属性描述符都可以有名为 [[Enumerable]]
和 [[Configurable]]
的字段。属性描述符值不能既是数据属性描述符又是访问器属性描述符;但是,它可以两者都不是(在这种情况下它是通用属性描述符)。完全填充的属性描述符 是访问器属性描述符或数据属性描述符,并且具有表 3 中定义的所有相应字段。
本规范中使用以下抽象操作 来操作属性描述符值:
6.2.6.1 IsAccessorDescriptor ( Desc )
抽象操作 IsAccessorDescriptor 接受参数 Desc (一个属性描述符 )并返回一个布尔值。它在被调用时执行以下步骤:
如果 Desc 有 [[Get]] 字段,返回 true 。
如果 Desc 有 [[Set]] 字段,返回 true 。
返回 false 。
6.2.6.2 IsDataDescriptor ( Desc )
抽象操作 IsDataDescriptor 接受参数 Desc (一个属性描述符 )并返回一个布尔值。它在被调用时执行以下步骤:
如果 Desc 有 [[Value]] 字段,返回
true 。
如果 Desc 有 [[Writable]] 字段,返回
true 。
返回 false 。
6.2.6.3 IsGenericDescriptor ( Desc )
抽象操作 IsGenericDescriptor 接受参数 Desc (一个属性描述符 )并返回一个布尔值。它在被调用时执行以下步骤:
如果IsAccessorDescriptor (Desc )
是 true ,返回 false 。
如果IsDataDescriptor (Desc )
是 true ,返回 false 。
返回 true 。
6.2.6.4 FromPropertyDescriptor ( Desc )
抽象操作 FromPropertyDescriptor 接受参数 Desc (一个属性描述符 或
undefined )并返回一个对象或 undefined 。它在被调用时执行以下步骤:
如果 Desc 是 undefined ,返回 undefined 。
设 obj 为OrdinaryObjectCreate (%Object.prototype% )。
断言 :obj 是一个可扩展的普通对象 ,没有自有属性。
如果 Desc 有 [[Value]] 字段,那么
执行 ! CreateDataPropertyOrThrow (obj ,
"value" , Desc .[[Value]] )。
如果 Desc 有 [[Writable]] 字段,那么
执行 ! CreateDataPropertyOrThrow (obj ,
"writable" , Desc .[[Writable]] )。
如果 Desc 有 [[Get]] 字段,那么
执行 ! CreateDataPropertyOrThrow (obj ,
"get" , Desc .[[Get]] )。
如果 Desc 有 [[Set]] 字段,那么
执行 ! CreateDataPropertyOrThrow (obj ,
"set" , Desc .[[Set]] )。
如果 Desc 有 [[Enumerable]] 字段,那么
执行 ! CreateDataPropertyOrThrow (obj ,
"enumerable" , Desc .[[Enumerable]] )。
如果 Desc 有 [[Configurable]] 字段,那么
执行 ! CreateDataPropertyOrThrow (obj ,
"configurable" , Desc .[[Configurable]] )。
返回 obj 。
6.2.6.5 ToPropertyDescriptor ( Obj )
抽象操作 ToPropertyDescriptor 接受参数 Obj (一个ECMAScript 语言值 )并返回一个包含 属性描述符 的正常完成 或一个throw
完成 。它在被调用时执行以下步骤:
如果 Obj 不是对象 ,抛出 TypeError
异常。
设 desc 为一个新的属性描述符 ,初始时没有字段。
设 hasEnumerable 为 ? HasProperty (Obj ,
"enumerable" )。
如果 hasEnumerable 是 true ,那么
设 enumerable 为ToBoolean (? Get (Obj ,
"enumerable" ))。
设 desc .[[Enumerable]] 为
enumerable 。
设 hasConfigurable 为 ? HasProperty (Obj ,
"configurable" )。
如果 hasConfigurable 是 true ,那么
设 configurable 为ToBoolean (? Get (Obj ,
"configurable" ))。
设 desc .[[Configurable]] 为
configurable 。
设 hasValue 为 ? HasProperty (Obj ,
"value" )。
如果 hasValue 是 true ,那么
设 value 为 ? Get (Obj ,
"value" )。
设 desc .[[Value]] 为 value 。
设 hasWritable 为 ? HasProperty (Obj ,
"writable" )。
如果 hasWritable 是 true ,那么
设 writable 为ToBoolean (? Get (Obj ,
"writable" ))。
设 desc .[[Writable]] 为
writable 。
设 hasGet 为 ? HasProperty (Obj ,
"get" )。
如果 hasGet 是 true ,那么
设 getter 为 ? Get (Obj ,
"get" )。
如果IsCallable (getter )
是 false 且 getter 不是
undefined ,抛出 TypeError 异常。
设 desc .[[Get]] 为 getter 。
设 hasSet 为 ? HasProperty (Obj ,
"set" )。
如果 hasSet 是 true ,那么
设 setter 为 ? Get (Obj ,
"set" )。
如果IsCallable (setter )
是 false 且 setter 不是
undefined ,抛出 TypeError 异常。
设 desc .[[Set]] 为 setter 。
如果 desc 有 [[Get]] 字段或 desc 有 [[Set]] 字段,那么
如果 desc 有 [[Value]] 字段或 desc
有 [[Writable]] 字段,抛出 TypeError
异常。
返回 desc 。
6.2.6.6 CompletePropertyDescriptor ( Desc )
抽象操作 CompletePropertyDescriptor 接受参数 Desc (一个属性描述符 )并返回
unused 。它在被调用时执行以下步骤:
设 like 为记录 { [[Value]] : undefined , [[Writable]] : false , [[Get]] : undefined , [[Set]] : undefined , [[Enumerable]] : false , [[Configurable]] : false }。
如果IsGenericDescriptor (Desc )
是 true 或IsDataDescriptor (Desc )
是 true ,那么
如果 Desc 没有 [[Value]] 字段,设
Desc .[[Value]] 为 like .[[Value]] 。
如果 Desc 没有 [[Writable]] 字段,设
Desc .[[Writable]] 为 like .[[Writable]] 。
否则,
如果 Desc 没有 [[Get]] 字段,设
Desc .[[Get]] 为 like .[[Get]] 。
如果 Desc 没有 [[Set]] 字段,设
Desc .[[Set]] 为 like .[[Set]] 。
如果 Desc 没有 [[Enumerable]] 字段,设
Desc .[[Enumerable]] 为 like .[[Enumerable]] 。
如果 Desc 没有 [[Configurable]] 字段,设
Desc .[[Configurable]] 为 like .[[Configurable]] 。
返回 unused 。
6.2.7 环境记录规范类型
环境记录 类型用于解释嵌套函数和块中名称解析的行为。此类型及其操作在9.1 中定义。
6.2.8 抽象闭包规范类型
抽象闭包 规范类型用于引用算法步骤以及一系列值。抽象闭包是元值,使用函数调用样式调用,例如
closure (arg1 , arg2 )。与抽象操作 类似,调用执行抽象闭包描述的算法步骤。
在创建抽象闭包的算法步骤中,值使用动词"capture"后跟别名列表来捕获。当创建抽象闭包时,它捕获当时与每个别名关联的值。在指定调用抽象闭包时要执行的算法的步骤中,每个捕获的值都通过用于捕获该值的别名来引用。
如果抽象闭包返回完成记录 ,该完成记录 必须是正常完成 或throw 完成 。
抽象闭包作为其他算法的一部分内联创建,如以下示例所示。
设 addend 为 41。
设 closure 为一个新的抽象闭包 ,参数为 (x ),捕获
addend 并在调用时执行以下步骤:
返回 x + addend 。
设 val 为 closure (1)。
断言 :val 是 42。
6.2.9 数据块
数据块 规范类型用于描述一个不同且可变的字节大小(8位)数值序列。字节值 是闭区间 从 0 到 255 的整数 。数据块值使用固定数量的字节创建,每个字节的初始值为 0。
为了在本规范中表示方便,可以使用类似数组的语法来访问数据块值的各个字节。此表示法将数据块值表示为基于 0 的整数索引 字节序列。例如,如果
db 是一个 5 字节的数据块值,则可以使用 db [2] 来访问其第 3 个字节。
驻留在内存中且可以被多个代理 并发引用的数据块被指定为共享数据块 。共享数据块具有一个标识(用于相等性测试共享数据块值的目的),该标识是地址无关的 :它不与块在任何进程中映射到的虚拟地址绑定,而是与块表示的内存位置集合绑定。两个数据块仅在它们包含的位置集合相等时才相等;否则,它们不相等,且它们包含的位置集合的交集为空。最后,共享数据块可以与数据块区分开来。
共享数据块的语义通过内存模型 使用共享数据块事件 定义。下面的抽象操作 引入共享数据块事件 ,并作为评估语义和内存模型 事件语义之间的接口。这些事件形成一个候选执行 ,内存模型 对其起过滤器作用。请参考内存模型 以获取完整语义。
共享数据块事件 由内存模型 中定义的记录 建模。
本规范中使用以下抽象操作 来操作数据块值:
6.2.9.1 CreateByteDataBlock ( size )
抽象操作 CreateByteDataBlock 接受参数 size (一个非负整数 )并返回一个包含 数据块 的正常完成 或一个throw
完成 。它在被调用时执行以下步骤:
如果 size > 253 - 1,抛出 RangeError 异常。
设 db 为一个新的数据块 值,由 size
个字节组成。如果无法创建这样的数据块 ,抛出 RangeError
异常。
将 db 的所有字节设置为 0。
返回 db 。
6.2.9.2 CreateSharedByteDataBlock ( size )
抽象操作 CreateSharedByteDataBlock 接受参数 size (一个非负整数 )并返回一个包含 共享数据块 的正常完成 或一个throw
完成 。它在被调用时执行以下步骤:
设 db 为一个新的共享数据块 值,由 size
个字节组成。如果无法创建这样的共享数据块 ,抛出
RangeError 异常。
设 execution 为周围代理 的代理记录 的 [[CandidateExecution]] 字段。
设 eventsRecord 为 execution .[[EventsRecords]] 中 [[AgentSignifier]] 为AgentSignifier ()
的代理事件记录 。
设 zero 为 « 0 »。
对于 db 的每个索引 i ,执行
将WriteSharedMemory
{ [[Order]] : init , [[NoTear]] : true , [[Block]] : db , [[ByteIndex]] : i , [[ElementSize]] : 1, [[Payload]] : zero } 追加到
eventsRecord .[[EventList]] 。
返回 db 。
6.2.9.3 CopyDataBlockBytes ( toBlock ,
toIndex , fromBlock , fromIndex , count )
抽象操作 CopyDataBlockBytes 接受参数 toBlock (一个数据块 或一个共享数据块 )、toIndex (一个非负整数 )、fromBlock (一个数据块 或一个共享数据块 )、fromIndex (一个非负整数 )和
count (一个非负整数 )并返回 unused 。它在被调用时执行以下步骤:
断言 :fromBlock 和 toBlock
是不同的值。
设 fromSize 为 fromBlock 中的字节数。
断言 :fromIndex + count ≤
fromSize 。
设 toSize 为 toBlock 中的字节数。
断言 :toIndex + count ≤
toSize 。
重复,当 count > 0 时,
如果 fromBlock 是共享数据块 ,那么
设 execution 为周围代理 的代理记录 的 [[CandidateExecution]] 字段。
设 eventsRecord 为 execution .[[EventsRecords]] 中 [[AgentSignifier]] 为AgentSignifier ()
的代理事件记录 。
设 bytes 为一个列表 ,其唯一元素是一个非确定性选择的字节值 。
注意:在实现中,bytes 是底层硬件上非原子读取指令的结果。非确定性是内存模型 对描述弱一致性硬件可观察行为的语义规定。
设 readEvent 为ReadSharedMemory
{ [[Order]] :
unordered , [[NoTear]] : true , [[Block]] : fromBlock , [[ByteIndex]] : fromIndex , [[ElementSize]] : 1 }。
将 readEvent 追加到 eventsRecord .[[EventList]] 。
将选择值记录 { [[Event]] : readEvent , [[ChosenValue]] : bytes } 追加到
execution .[[ChosenValues]] 。
如果 toBlock 是共享数据块 ,那么
将WriteSharedMemory
{ [[Order]] :
unordered , [[NoTear]] : true ,
[[Block]] : toBlock , [[ByteIndex]] : toIndex ,
[[ElementSize]] : 1, [[Payload]] : bytes }
追加到 eventsRecord .[[EventList]] 。
否则,
设 toBlock [toIndex ] 为
bytes [0]。
否则,
断言 :toBlock
不是共享数据块 。
设 toBlock [toIndex ] 为
fromBlock [fromIndex ]。
设 toIndex 为 toIndex + 1。
设 fromIndex 为 fromIndex + 1。
设 count 为 count - 1。
返回 unused 。
6.2.10 PrivateElement 规范类型
PrivateElement 类型是一个记录 ,用于私有类字段、方法和访问器的规范。虽然属性描述符 不用于私有元素,但私有字段的行为类似于不可配置、不可枚举、可写的数据属性 ,私有方法的行为类似于不可配置、不可枚举、不可写的数据属性 ,私有访问器的行为类似于不可配置、不可枚举的访问器属性 。
PrivateElement 类型的值是记录 值,其字段由表
9 定义。这些值被称为PrivateElement 。
表 9:PrivateElement 字段
字段名
出现该字段的 [[Kind]] 字段值
值
含义
[[Key]]
全部
一个私有名称
字段、方法或访问器的名称。
[[Kind]]
全部
field 、method 或
accessor
元素的类型。
[[Value]]
field 和 method
一个ECMAScript 语言值
字段的值。
[[Get]]
accessor
一个函数对象 或
undefined
私有访问器的 getter。
[[Set]]
accessor
一个函数对象 或
undefined
私有访问器的 setter。
6.2.11 ClassFieldDefinition 记录规范类型
ClassFieldDefinition 类型是一个记录 ,用于类字段的规范。
ClassFieldDefinition 类型的值是记录 值,其字段由表 10 定义。这些值被称为ClassFieldDefinition 记录 。
表 10:ClassFieldDefinition
记录 字段
字段名
值
含义
[[Name]]
一个私有名称 、字符串或符号
字段的名称。
[[Initializer]]
一个 ECMAScript 函数对象 或
empty
字段的初始化器(如果有)。
6.2.12 私有名称
私有名称 规范类型用于描述一个全局唯一值(即使与其他私有名称在其他方面无法区分,该值也与任何其他私有名称不同),它表示私有类元素(字段、方法或访问器)的键。每个私有名称都有一个关联的不可变
[[Description]] ,它是一个字符串 值。私有名称可以通过PrivateFieldAdd 或PrivateMethodOrAccessorAdd 安装在任何
ECMAScript 对象上,然后使用PrivateGet 和PrivateSet 进行读取或写入。
6.2.13 ClassStaticBlockDefinition 记录规范类型
ClassStaticBlockDefinition
记录 是一个记录 值,用于封装类静态初始化块的可执行代码。
ClassStaticBlockDefinition 记录具有表
11 中列出的字段。
表 11:ClassStaticBlockDefinition
记录 字段
字段名
值
含义
[[BodyFunction]]
一个 ECMAScript 函数对象
在类的静态初始化期间要调用的函数对象 。
7 抽象操作
这些操作不是 ECMAScript 语言的一部分;定义它们仅是为了帮助说明 ECMAScript 语言的语义。其他更专门的抽象操作 在本规范中都有定义。
7.1 类型转换
ECMAScript 语言根据需要隐式执行自动类型转换。为了阐明某些构造的语义,定义一组转换抽象操作 是有用的。转换抽象操作 是多态的;它们可以接受任何ECMAScript 语言类型 的值。但这些操作不使用其他规范类型。
BigInt 类型 在 ECMAScript
语言中没有隐式转换;程序员必须显式调用 BigInt 来将值从其他类型转换。
7.1.1 ToPrimitive ( input [ , preferredType ]
)
抽象操作 ToPrimitive 接受参数 input (一个ECMAScript 语言值 )和可选参数
preferredType (string 或
number )并返回一个包含 ECMAScript 语言值 的正常完成 或一个throw 完成 。它将其
input 参数转换为非对象类型 。如果对象能够转换为多个原始类型,它可以使用可选提示
preferredType 来偏向该类型。它在被调用时执行以下步骤:
如果 input 是对象 ,那么
设 exoticToPrim 为 ? GetMethod (input , %Symbol.toPrimitive% )。
如果 exoticToPrim 不是 undefined ,那么
如果 preferredType 不存在,那么
设 hint 为 "default" 。
否则如果 preferredType 是 string ,那么
设 hint 为 "string" 。
否则,
断言 :preferredType
是 number 。
设 hint 为 "number" 。
设 result 为 ? Call (exoticToPrim ,
input , « hint »)。
如果 result 不是对象 ,返回
result 。
抛出 TypeError 异常。
如果 preferredType 不存在,设 preferredType 为
number 。
返回 ? OrdinaryToPrimitive (input ,
preferredType )。
返回 input 。
注意
当调用 ToPrimitive 时不带提示,那么它通常表现为提示是 number 。但是,对象可以通过定义 %Symbol.toPrimitive%
方法来覆盖此行为。在本规范中定义的对象中,只有 Date(参见 21.4.4.45 )和
Symbol 对象(参见 20.4.3.5 )覆盖默认的
ToPrimitive 行为。Date 将提示的缺失视为提示是 string 。
7.1.1.1 OrdinaryToPrimitive ( O , hint )
抽象操作 OrdinaryToPrimitive 接受参数 O (一个对象)和
hint (string 或 number )并返回一个包含 ECMAScript 语言值 的正常完成 或一个throw
完成 。它在被调用时执行以下步骤:
如果 hint 是 string ,那么
设 methodNames 为 « "toString" ,
"valueOf" »。
否则,
设 methodNames 为 « "valueOf" ,
"toString" »。
对于 methodNames 的每个元素 name ,执行
设 method 为 ? Get (O ,
name )。
如果 IsCallable (method )
是 true ,那么
设 result 为 ? Call (method ,
O )。
如果 result 不是对象 ,返回
result 。
抛出 TypeError 异常。
7.1.2 ToBoolean ( argument )
抽象操作 ToBoolean 接受参数 argument (一个ECMAScript
语言值 )并返回一个布尔值。它将 argument 转换为布尔类型的值。它在被调用时执行以下步骤:
如果 argument 是布尔值 ,返回
argument 。
如果 argument 是
undefined 、null 、+0 𝔽 、-0 𝔽 、NaN 、0 ℤ
或空字符串之一,返回 false 。
注意:此步骤在章节 B.3.6.1 中被替换。
返回 true 。
7.1.3 ToNumeric ( value )
抽象操作 ToNumeric 接受参数 value (一个ECMAScript
语言值 )并返回一个包含 数字或
BigInt 的正常完成 ,或一个throw 完成 。它返回转换为数字或
BigInt 的 value 。它在被调用时执行以下步骤:
设 primValue 为 ? ToPrimitive (value ,
number )。
如果 primValue 是
BigInt ,返回 primValue 。
返回 ? ToNumber (primValue )。
7.1.4 ToNumber ( argument )
抽象操作 ToNumber 接受参数 argument (一个ECMAScript
语言值 )并返回一个包含 数字的正常完成 或一个throw 完成 。它将
argument 转换为数字类型的值。它在被调用时执行以下步骤:
如果 argument 是数字 ,返回
argument 。
如果 argument 是符号或 BigInt,抛出 TypeError 异常。
如果 argument 是 undefined ,返回 NaN 。
如果 argument 是 null 或 false ,返回
+0 𝔽 。
如果 argument 是 true ,返回 1 𝔽 。
如果 argument 是字符串 ,返回
StringToNumber (argument )。
断言 :argument 是对象 。
设 primValue 为 ? ToPrimitive (argument ,
number )。
断言 :primValue 不是对象 。
返回 ? ToNumber (primValue )。
7.1.4.1 ToNumber 应用于字符串类型
抽象操作 StringToNumber 指定如何使用以下语法将字符串值转换为数字值。
语法
StringNumericLiteral
:::
StrWhiteSpace opt
StrWhiteSpace opt
StrNumericLiteral
StrWhiteSpace opt
StrWhiteSpace
:::
StrWhiteSpaceChar
StrWhiteSpace opt
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 )
注意
7.1.4.1.1 StringToNumber ( str )
抽象操作 StringToNumber 接受参数 str (一个字符串)并返回一个数字。它在被调用时执行以下步骤:
设 literal 为 ParseText (str , StringNumericLiteral )。
如果 literal 是错误的列表 ,返回
NaN 。
返回 literal 的 StringNumericValue 。
7.1.4.1.2 运行时语义:StringNumericValue
语法导向操作
StringNumericValue 不接受参数并返回一个数字。
注意
它在以下产生式上分段定义:
StringNumericLiteral
:::
StrWhiteSpace
opt
返回 +0 𝔽 。
StringNumericLiteral
:::
StrWhiteSpace
opt
StrNumericLiteral
StrWhiteSpace
opt
返回 StrNumericLiteral 的
StringNumericValue 。
StrNumericLiteral
:::
NonDecimalIntegerLiteral
返回 𝔽 (NonDecimalIntegerLiteral
的 MV)。
StrDecimalLiteral
:::
-
StrUnsignedDecimalLiteral
设 a 为 StrUnsignedDecimalLiteral
的 StringNumericValue 。
如果 a 是 +0 𝔽 ,返回
-0 𝔽 。
返回 -a 。
StrUnsignedDecimalLiteral
:::
Infinity
返回 +∞ 𝔽 。
StrUnsignedDecimalLiteral
:::
DecimalDigits
.
DecimalDigits
opt
ExponentPart
opt
设 a 为第一个 DecimalDigits 的 MV。
如果第二个 DecimalDigits 存在,那么
设 b 为第二个 DecimalDigits 的 MV。
设 n 为第二个 DecimalDigits 中的代码点数。
否则,
设 b 为 0。
设 n 为 0。
如果 ExponentPart 存在,设 e 为
ExponentPart 的
MV。否则,设 e 为 0。
返回 RoundMVResult ((a +
(b × 10-n )) × 10e )。
StrUnsignedDecimalLiteral
:::
.
DecimalDigits
ExponentPart
opt
设 b 为 DecimalDigits 的 MV。
如果 ExponentPart 存在,设 e 为
ExponentPart 的
MV。否则,设 e 为 0。
设 n 为 DecimalDigits 中的代码点数。
返回 RoundMVResult (b ×
10e - n )。
StrUnsignedDecimalLiteral
:::
DecimalDigits
ExponentPart
opt
设 a 为 DecimalDigits 的 MV。
如果 ExponentPart 存在,设 e 为
ExponentPart 的
MV。否则,设 e 为 0。
返回 RoundMVResult (a ×
10e )。
7.1.4.1.3 RoundMVResult ( n )
抽象操作 RoundMVResult 接受参数 n (一个数学值 )并返回一个数字。它以实现定义 的方式将 n
转换为数字。对于此抽象操作的目的,如果数字不是零或其左侧有非零数字且其右侧有非零数字,则该数字是有效的。对于此抽象操作的目的,数学值 表示法的"表示的数学值"是数学值 的"十进制表示"的逆。它在被调用时执行以下步骤:
如果 n 的十进制表示有 20 或更少的有效数字,返回 𝔽 (n )。
设 option1 为将 n 的十进制表示中第 20 位后的每个有效数字替换为 0
数字的结果表示的数学值 。
设 option2 为将 n 的十进制表示中第 20 位后的每个有效数字替换为 0 数字,然后在第 20 位增加
1(根据需要进位)的结果表示的数学值 。
设 chosen 为 option1 或 option2 的实现定义 选择。
返回 𝔽 (chosen )。
7.1.5 ToIntegerOrInfinity ( argument )
抽象操作 ToIntegerOrInfinity 接受参数 argument (一个ECMAScript 语言值 )并返回一个包含 整数 、+∞ 或 -∞ 的正常完成 或一个throw 完成 。它将
argument 转换为表示其数字值的整数 (小数部分被截断),或者当该数字值是无限时转换为 +∞ 或 -∞。它在被调用时执行以下步骤:
设 number 为 ? ToNumber (argument )。
如果 number 是 NaN 、+0 𝔽 或
-0 𝔽 之一,返回 0。
如果 number 是 +∞ 𝔽 ,返回 +∞。
如果 number 是 -∞ 𝔽 ,返回 -∞。
返回 truncate (ℝ (number ))。
注意
对于任何值
x ,
𝔽 (ToIntegerOrInfinity(
x )) 永远不会返回
-0 𝔽 。小数部分的截断在将
x 转换为
数学值 之后执行。
7.1.6 ToInt32 ( argument )
抽象操作 ToInt32 接受参数 argument (一个ECMAScript
语言值 )并返回一个包含 整数数字 的正常完成 或一个throw 完成 。它将
argument 转换为从 𝔽 (-231 ) 到 𝔽 (231 - 1) 的闭区间 内的 232 个整数数字 值之一。它在被调用时执行以下步骤:
设 number 为 ? ToNumber (argument )。
如果 number 不是有限的 或 number 是
+0 𝔽 或 -0 𝔽 ,返回
+0 𝔽 。
设 int 为 truncate (ℝ (number ))。
设 int32bit 为 int modulo 232 。
如果 int32bit ≥ 231 ,返回 𝔽 (int32bit - 232 );否则返回
𝔽 (int32bit )。
注意
根据 ToInt32 的上述定义:
ToInt32 抽象操作是幂等的:如果应用于它产生的结果,第二次应用不会改变该值。
对于所有值 x ,ToInt32(ToUint32 (x )) 与
ToInt32(x ) 是相同的值。(为了保持这个后续属性,+∞ 𝔽 和
-∞ 𝔽 被映射为 +0 𝔽 。)
ToInt32 将 -0 𝔽 映射为 +0 𝔽 。
7.1.7 ToUint32 ( argument )
抽象操作 ToUint32 接受参数 argument (一个ECMAScript
语言值 )并返回一个包含 整数数字 的正常完成 或一个throw 完成 。它将
argument 转换为从 +0 𝔽 到 𝔽 (232 - 1) 的闭区间 内的
232 个整数数字 值之一。它在被调用时执行以下步骤:
设 number 为 ? ToNumber (argument )。
如果 number 不是有限的 或 number 是
+0 𝔽 或 -0 𝔽 ,返回
+0 𝔽 。
设 int 为 truncate (ℝ (number ))。
设 int32bit 为 int modulo 232 。
返回 𝔽 (int32bit )。
注意
根据 ToUint32 的上述定义:
步骤 5 是 ToUint32 和 ToInt32
之间的唯一区别。
ToUint32 抽象操作是幂等的:如果应用于它产生的结果,第二次应用不会改变该值。
对于所有值 x ,ToUint32(ToInt32 (x )) 与
ToUint32(x ) 是相同的值。(为了保持这个后续属性,+∞ 𝔽 和
-∞ 𝔽 被映射为 +0 𝔽 。)
ToUint32 将 -0 𝔽 映射为
+0 𝔽 。
7.1.8 ToInt16 ( argument )
抽象操作 ToInt16 接受参数 argument (一个ECMAScript
语言值 )并返回一个包含 整数数字 的正常完成 或一个throw 完成 。它将
argument 转换为从 𝔽 (-215 ) 到 𝔽 (215 - 1) 的闭区间 内的 216 个整数数字 值之一。它在被调用时执行以下步骤:
设 number 为 ? ToNumber (argument )。
如果 number 不是有限的 或 number 是
+0 𝔽 或 -0 𝔽 ,返回
+0 𝔽 。
设 int 为 truncate (ℝ (number ))。
设 int16bit 为 int modulo 216 。
如果 int16bit ≥ 215 ,返回 𝔽 (int16bit - 216 );否则返回
𝔽 (int16bit )。
7.1.9 ToUint16 ( argument )
抽象操作 ToUint16 接受参数 argument (一个ECMAScript
语言值 )并返回一个包含 整数数字 的正常完成 或一个throw 完成 。它将
argument 转换为从 +0 𝔽 到 𝔽 (216 - 1) 的闭区间 内的
216 个整数数字 值之一。它在被调用时执行以下步骤:
设 number 为 ? ToNumber (argument )。
如果 number 不是有限的 或 number 是
+0 𝔽 或 -0 𝔽 ,返回
+0 𝔽 。
设 int 为 truncate (ℝ (number ))。
设 int16bit 为 int modulo 216 。
返回 𝔽 (int16bit )。
注意
根据 ToUint16 的上述定义:
在步骤 4 中将 232 替换为
216 是 ToUint32 和 ToUint16 之间的唯一区别。
ToUint16 将 -0 𝔽 映射为
+0 𝔽 。
7.1.10 ToInt8 ( argument )
抽象操作 ToInt8 接受参数 argument (一个ECMAScript
语言值 )并返回一个包含 整数数字 的正常完成 或一个throw 完成 。它将
argument 转换为从 -128 𝔽 到
127 𝔽 的闭区间 内的 28 个整数数字 值之一。它在被调用时执行以下步骤:
设 number 为 ? ToNumber (argument )。
如果 number 不是有限的 或 number 是
+0 𝔽 或 -0 𝔽 ,返回
+0 𝔽 。
设 int 为 truncate (ℝ (number ))。
设 int8bit 为 int modulo 28 。
如果 int8bit ≥ 27 ,返回 𝔽 (int8bit - 28 );否则返回 𝔽 (int8bit )。
7.1.11 ToUint8 ( argument )
抽象操作 ToUint8 接受参数 argument (一个ECMAScript
语言值 )并返回一个包含 整数数字 的正常完成 或一个throw 完成 。它将
argument 转换为从 +0 𝔽 到
255 𝔽 的闭区间 内的 28 个整数数字 值之一。它在被调用时执行以下步骤:
设 number 为 ? ToNumber (argument )。
如果 number 不是有限的 或 number 是
+0 𝔽 或 -0 𝔽 ,返回
+0 𝔽 。
设 int 为 truncate (ℝ (number ))。
设 int8bit 为 int modulo 28 。
返回 𝔽 (int8bit )。
7.1.12 ToUint8Clamp ( argument )
抽象操作 ToUint8Clamp 接受参数 argument (一个ECMAScript
语言值 )并返回一个包含 整数数字 的正常完成 或一个throw 完成 。它将
argument 限制并舍入为从 +0 𝔽 到
255 𝔽 的闭区间 内的 28 个整数数字 值之一。它在被调用时执行以下步骤:
设 number 为 ? ToNumber (argument )。
如果 number 是 NaN ,返回 +0 𝔽 。
设 mv 为 number 的扩展数学值 。
设 clamped 为将 mv 限制 在 0 和 255 之间的结果。
设 f 为 floor (clamped )。
如果 clamped < f + 0.5,返回 𝔽 (f )。
如果 clamped > f + 0.5,返回 𝔽 (f + 1)。
如果 f 是偶数,返回 𝔽 (f )。否则,返回 𝔽 (f + 1)。
注意
与大多数其他 ECMAScript 整数 转换操作不同,ToUint8Clamp
舍入而不是截断非整数值。它还使用"舍入到最近偶数"的平分策略,这与 Math.round
的"舍入到更大值"平分策略不同。
7.1.13 ToBigInt ( argument )
抽象操作 ToBigInt 接受参数 argument (一个ECMAScript
语言值 )并返回一个包含 BigInt
的正常完成 或一个throw 完成 。它将
argument 转换为 BigInt 值,或者如果需要从数字进行隐式转换则抛出异常。它在被调用时执行以下步骤:
设 prim 为 ? ToPrimitive (argument ,
number )。
返回 prim 在表 12 中对应的值。
表 12:BigInt 转换
参数类型
结果
Undefined
抛出 TypeError 异常。
Null
抛出 TypeError 异常。
Boolean
如果 prim 是 true 返回 1n
,如果
prim 是 false 返回 0n
。
BigInt
返回 prim 。
Number
抛出 TypeError 异常。
String
设 n 为 StringToBigInt (prim )。
如果 n 是 undefined ,抛出
SyntaxError 异常。
返回 n 。
Symbol
抛出 TypeError 异常。
7.1.14 StringToBigInt ( str )
抽象操作 StringToBigInt 接受参数 str (一个字符串)并返回一个 BigInt 或
undefined 。它在被调用时执行以下步骤:
设 literal 为 ParseText (str , StringIntegerLiteral )。
如果 literal 是错误的列表 ,返回
undefined 。
设 mv 为 literal 的 MV。
断言 :mv 是一个整数 。
返回 ℤ (mv )。
7.1.14.1 StringIntegerLiteral 语法
StringToBigInt 使用以下语法。
语法
StringIntegerLiteral
:::
StrWhiteSpace opt
StrWhiteSpace opt
StrIntegerLiteral
StrWhiteSpace opt
StrIntegerLiteral
:::
SignedInteger [~Sep]
NonDecimalIntegerLiteral [~Sep]
7.1.14.2 运行时语义:MV
7.1.15 ToBigInt64 ( argument )
抽象操作 ToBigInt64 接受参数 argument (一个ECMAScript
语言值 )并返回一个包含 BigInt
的正常完成 或一个throw 完成 。它将
argument 转换为从 ℤ (-263 ) 到 ℤ (263 - 1) 的闭区间 内的 264 个 BigInt
值之一。它在被调用时执行以下步骤:
设 n 为 ? ToBigInt (argument )。
设 int64bit 为 ℝ (n ) modulo 264 。
如果 int64bit ≥ 263 ,返回 ℤ (int64bit - 264 );否则返回 ℤ (int64bit )。
7.1.16 ToBigUint64 ( argument )
抽象操作 ToBigUint64 接受参数 argument (一个ECMAScript
语言值 )并返回一个包含 BigInt
的正常完成 或一个throw 完成 。它将
argument 转换为从 0 ℤ 到 ℤ (264 - 1) 的闭区间 内的 264 个 BigInt
值之一。它在被调用时执行以下步骤:
设 n 为 ? ToBigInt (argument )。
设 int64bit 为 ℝ (n ) modulo 264 。
返回 ℤ (int64bit )。
7.1.17 ToString ( argument )
抽象操作 ToString 接受参数 argument (一个ECMAScript
语言值 )并返回一个包含 字符串的正常完成 或一个throw 完成 。它将
argument 转换为字符串类型的值。它在被调用时执行以下步骤:
如果 argument 是字符串 ,返回
argument 。
如果 argument 是符号 ,抛出
TypeError 异常。
如果 argument 是 undefined ,返回 "undefined" 。
如果 argument 是 null ,返回 "null" 。
如果 argument 是 true ,返回 "true" 。
如果 argument 是 false ,返回 "false" 。
如果 argument 是数字 ,返回
Number::toString (argument ,
10)。
如果 argument 是
BigInt ,返回 BigInt::toString (argument ,
10)。
断言 :argument 是对象 。
设 primValue 为 ? ToPrimitive (argument ,
string )。
断言 :primValue 不是对象 。
返回 ? ToString (primValue )。
7.1.18 ToObject ( argument )
抽象操作 ToObject 接受参数 argument (一个ECMAScript
语言值 )并返回一个包含 对象的正常完成 或一个throw 完成 。它根据表
13 将 argument 转换为对象类型的值:
表 13:ToObject 转换
参数类型
结果
Undefined
抛出 TypeError 异常。
Null
抛出 TypeError 异常。
Boolean
返回一个新的布尔对象,其 [[BooleanData]] 内部槽设置为
argument 。有关布尔对象的描述,请参见 20.3 。
Number
返回一个新的数字对象,其 [[NumberData]] 内部槽设置为
argument 。有关数字对象的描述,请参见 21.1 。
String
返回一个新的字符串对象,其 [[StringData]] 内部槽设置为
argument 。有关字符串对象的描述,请参见 22.1 。
Symbol
返回一个新的符号对象,其 [[SymbolData]] 内部槽设置为
argument 。有关符号对象的描述,请参见 20.4 。
BigInt
返回一个新的 BigInt 对象,其 [[BigIntData]] 内部槽设置为
argument 。有关 BigInt 对象的描述,请参见 21.2 。
Object
返回 argument 。
7.1.19 ToPropertyKey ( argument )
抽象操作 ToPropertyKey 接受参数 argument (一个ECMAScript
语言值 )并返回一个包含 属性键 的正常完成 或一个throw 完成 。它将
argument 转换为可用作属性键 的值。它在被调用时执行以下步骤:
设 key 为 ? ToPrimitive (argument ,
string )。
如果 key 是符号 ,那么
返回 key 。
返回 ! ToString (key )。
7.1.20 ToLength ( argument )
抽象操作 ToLength 接受参数 argument (一个ECMAScript
语言值 )并返回一个包含 非负整数数字 的正常完成 或一个throw 完成 。它将
argument 限制并截断为适合用作类数组对象 长度的非负整数数字 。它在被调用时执行以下步骤:
设 len 为 ? ToIntegerOrInfinity (argument )。
如果 len ≤ 0,返回 +0 𝔽 。
返回 𝔽 (min (len ,
253 - 1))。
7.1.21 CanonicalNumericIndexString ( argument )
抽象操作 CanonicalNumericIndexString 接受参数 argument (一个字符串)并返回一个数字或
undefined 。如果 argument 是 "-0" 或完全匹配某个数字值
n 的 ToString (n ),它返回相应的数字值。否则,它返回
undefined 。它在被调用时执行以下步骤:
如果 argument 是 "-0" ,返回 -0 𝔽 。
设 n 为 ! ToNumber (argument )。
如果 ! ToString (n ) 是
argument ,返回 n 。
返回 undefined 。
规范数字字符串 是 CanonicalNumericIndexString 抽象操作不返回
undefined 的任何字符串。
7.1.22 ToIndex ( value )
抽象操作 ToIndex 接受参数 value (一个ECMAScript
语言值 )并返回一个包含 非负整数 的正常完成 或一个throw 完成 。它将
value 转换为整数 ,如果该整数 非负且对应于整数索引 则返回该整数。否则,它抛出异常。它在被调用时执行以下步骤:
设 integer 为 ? ToIntegerOrInfinity (value )。
如果 integer 不在从 0 到 253 - 1 的闭区间 内,抛出
RangeError 异常。
返回 integer 。
7.2 测试和比较操作
7.2.1 RequireObjectCoercible ( argument )
抽象操作 RequireObjectCoercible 接受参数 argument (一个ECMAScript 语言值 )并返回一个包含 ECMAScript 语言值 的正常完成 或一个throw 完成 。如果
argument 是不能使用 ToObject 转换为对象的值,它抛出错误。它由表 14 定义:
表 14:RequireObjectCoercible 结果
参数类型
结果
Undefined
抛出 TypeError 异常。
Null
抛出 TypeError 异常。
Boolean
返回 argument 。
Number
返回 argument 。
String
返回 argument 。
Symbol
返回 argument 。
BigInt
返回 argument 。
Object
返回 argument 。
7.2.2 IsArray ( argument )
抽象操作 IsArray 接受参数 argument (一个ECMAScript
语言值 )并返回一个包含 布尔值的正常完成 或一个throw 完成 。它在被调用时执行以下步骤:
如果 argument 不是对象 ,返回 false 。
如果 argument 是数组异质对象 ,返回 true 。
如果 argument 是代理异质对象 ,那么
执行 ? ValidateNonRevokedProxy (argument )。
设 proxyTarget 为 argument .[[ProxyTarget]] 。
返回 ? IsArray (proxyTarget )。
返回 false 。
7.2.3 IsCallable ( argument )
抽象操作 IsCallable 接受参数 argument (一个ECMAScript
语言值 )并返回一个布尔值。它确定 argument 是否是具有 [[Call]] 内部方法的可调用函数。它在被调用时执行以下步骤:
如果 argument 不是对象 ,返回 false 。
如果 argument 有 [[Call]] 内部方法,返回
true 。
返回 false 。
7.2.4 IsConstructor ( argument )
抽象操作 IsConstructor 接受参数 argument (一个ECMAScript
语言值 )并返回一个布尔值。它确定 argument 是否是具有 [[Construct]] 内部方法的函数对象 。它在被调用时执行以下步骤:
如果 argument 不是对象 ,返回 false 。
如果 argument 有 [[Construct]] 内部方法,返回
true 。
返回 false 。
7.2.5 IsExtensible ( O )
抽象操作 IsExtensible 接受参数 O (一个对象)并返回一个包含 布尔值的正常完成 或一个throw 完成 。它用于确定是否可以向
O 添加其他属性。它在被调用时执行以下步骤:
返回 ? O .[[IsExtensible]] ()。
7.2.6 IsRegExp ( argument )
抽象操作 IsRegExp 接受参数 argument (一个ECMAScript
语言值 )并返回一个包含 布尔值的正常完成 或一个throw 完成 。它在被调用时执行以下步骤:
如果 argument 不是对象 ,返回 false 。
设 matcher 为 ? Get (argument , %Symbol.match% )。
如果 matcher 不是 undefined ,返回 ToBoolean (matcher )。
如果 argument 有 [[RegExpMatcher]] 内部槽,返回
true 。
返回 false 。
7.2.7 静态语义:IsStringWellFormedUnicode ( string )
抽象操作 IsStringWellFormedUnicode 接受参数 string (一个字符串)并返回一个布尔值。它将 string 解释为
UTF-16 编码代码点的序列,如6.1.4 中所述,并确定它是否是一个格式正确的 UTF-16
序列。它在被调用时执行以下步骤:
设 len 为 string 的长度。
设 k 为 0。
重复,当 k < len 时,
设 cp 为 CodePointAt (string ,
k )。
如果 cp .[[IsUnpairedSurrogate]] 是
true ,返回 false 。
设 k 为 k + cp .[[CodeUnitCount]] 。
返回 true 。
7.2.8 SameType ( x , y )
抽象操作 SameType 接受参数 x (一个ECMAScript 语言值 )和
y (一个ECMAScript
语言值 )并返回一个布尔值。它确定两个参数是否为相同类型。它在被调用时执行以下步骤:
如果 x 是 undefined 且 y 是
undefined ,返回 true 。
如果 x 是 null 且 y 是 null ,返回
true 。
如果 x 是布尔值 且
y 是布尔值 ,返回
true 。
如果 x 是数字 且
y 是数字 ,返回
true 。
如果 x 是
BigInt 且 y 是 BigInt ,返回
true 。
如果 x 是符号 且
y 是符号 ,返回
true 。
如果 x 是字符串 且
y 是字符串 ,返回
true 。
如果 x 是对象 且 y 是对象 ,返回 true 。
返回 false 。
7.2.9 SameValue ( x , y )
抽象操作 SameValue 接受参数 x (一个ECMAScript 语言值 )和
y (一个ECMAScript
语言值 )并返回一个布尔值。它确定两个参数是否为相同值。它在被调用时执行以下步骤:
如果 SameType (x , y ) 是
false ,返回 false 。
如果 x 是数字 ,那么
返回 Number::sameValue (x ,
y )。
返回 SameValueNonNumber (x ,
y )。
注意
此算法与 IsStrictlyEqual 算法不同,它将所有
NaN 值视为等价,并区分 +0 𝔽 和
-0 𝔽 。
7.2.10 SameValueZero ( x , y )
抽象操作 SameValueZero 接受参数 x (一个ECMAScript 语言值 )和
y (一个ECMAScript
语言值 )并返回一个布尔值。它确定两个参数是否为相同值(忽略 +0 𝔽 和
-0 𝔽 之间的区别)。它在被调用时执行以下步骤:
如果 SameType (x , y ) 是
false ,返回 false 。
如果 x 是数字 ,那么
返回 Number::sameValueZero (x ,
y )。
返回 SameValueNonNumber (x ,
y )。
注意
SameValueZero 与 SameValue 的区别仅在于它将
+0 𝔽 和 -0 𝔽 视为等价。
7.2.11 SameValueNonNumber ( x , y )
抽象操作 SameValueNonNumber 接受参数 x (一个ECMAScript
语言值 ,但不是数字)和 y (一个ECMAScript
语言值 ,但不是数字)并返回一个布尔值。它在被调用时执行以下步骤:
断言 :SameType (x , y ) 是
true 。
如果 x 是 null 或 undefined ,返回
true 。
如果 x 是
BigInt ,那么
返回 BigInt::equal (x ,
y )。
如果 x 是字符串 ,那么
如果 x 和 y 有相同的长度且在相同位置有相同的代码单元,返回
true ;否则,返回 false 。
如果 x 是布尔值 ,那么
如果 x 和 y 都是 true 或都是
false ,返回 true ;否则,返回
false 。
注意:所有其他ECMAScript 语言值 按标识进行比较。
如果 x 是 y ,返回 true ;否则,返回
false 。
注意 1
为了说明目的,即使不必要,此算法中的某些情况也被单独处理。
注意 2
7.2.12 IsLessThan ( x , y , LeftFirst
)
抽象操作 IsLessThan 接受参数 x (一个ECMAScript
语言值 )、y (一个ECMAScript 语言值 )和
LeftFirst (一个布尔值)并返回一个包含 布尔值或
undefined 的正常完成 ,或一个throw 完成 。它为比较
x < y 提供语义,返回 true 、false 或
undefined (表示至少一个操作数是 NaN )。LeftFirst 标志用于控制对
x 和 y 执行可能具有可见副作用的操作的顺序。这是必要的,因为 ECMAScript 指定表达式的从左到右求值。如果
LeftFirst 是 true ,x 参数对应于出现在 y
参数对应表达式左侧的表达式。如果 LeftFirst 是 false ,则相反,必须在 x 之前对
y 执行操作。它在被调用时执行以下步骤:
如果 LeftFirst 是 true ,那么
设 px 为 ? ToPrimitive (x ,
number )。
设 py 为 ? ToPrimitive (y ,
number )。
否则,
注意:需要颠倒求值顺序以保持从左到右的求值。
设 py 为 ? ToPrimitive (y ,
number )。
设 px 为 ? ToPrimitive (x ,
number )。
如果 px 是字符串 且
py 是字符串 ,那么
设 lx 为 px 的长度。
设 ly 为 py 的长度。
对于每个整数 i ,满足 0 ≤ i <
min (lx , ly ),按升序执行
设 cx 为 px 中索引 i 处代码单元的数值。
设 cy 为 py 中索引 i 处代码单元的数值。
如果 cx < cy ,返回 true 。
如果 cx > cy ,返回 false 。
如果 lx < ly ,返回 true 。否则,返回
false 。
否则,
如果 px 是
BigInt 且 py 是字符串 ,那么
设 ny 为 StringToBigInt (py )。
如果 ny 是 undefined ,返回
undefined 。
返回 BigInt::lessThan (px ,
ny )。
如果 px 是字符串 且
py 是
BigInt ,那么
设 nx 为 StringToBigInt (px )。
如果 nx 是 undefined ,返回
undefined 。
返回 BigInt::lessThan (nx ,
py )。
注意:因为 px 和 py 是原始值,求值顺序不重要。
设 nx 为 ? ToNumeric (px )。
设 ny 为 ? ToNumeric (py )。
如果 SameType (nx ,
ny ) 是 true ,那么
如果 nx 是数字 ,那么
返回 Number::lessThan (nx ,
ny )。
否则,
断言 :nx 是
BigInt 。
返回 BigInt::lessThan (nx ,
ny )。
断言 :nx 是
BigInt 且 ny 是数字 ,或
nx 是数字 且
ny 是
BigInt 。
如果 nx 或 ny 是 NaN ,返回
undefined 。
如果 nx 是 -∞ 𝔽 或 ny 是
+∞ 𝔽 ,返回 true 。
如果 nx 是 +∞ 𝔽 或 ny 是
-∞ 𝔽 ,返回 false 。
如果 ℝ (nx ) < ℝ (ny ),返回
true ;否则返回 false 。
注意 1
步骤 3 与处理加法运算符 +
(13.15.3 )的算法中的步骤
1.c 不同,它使用逻辑与操作而不是逻辑或操作。
注意 2
字符串的比较使用 UTF-16 代码单元值序列的简单字典序。没有尝试使用 Unicode 规范中定义的更复杂的、面向语义的字符或字符串相等性和整理顺序定义。因此,根据
Unicode 标准规范相等但不在相同规范化形式中的字符串值可能测试为不相等。还要注意,对于包含代理对 的字符串,按代码单元 的字典序与按代码点 的顺序不同。
7.2.13 IsLooselyEqual ( x , y )
抽象操作 IsLooselyEqual 接受参数 x (一个ECMAScript 语言值 )和
y (一个ECMAScript 语言值 )并返回一个包含 布尔值的正常完成 或一个throw 完成 。它为
==
运算符提供语义。它在被调用时执行以下步骤:
如果 SameType (x , y ) 是
true ,那么
返回 IsStrictlyEqual (x ,
y )。
如果 x 是 null 且 y 是
undefined ,返回 true 。
如果 x 是 undefined 且 y 是
null ,返回 true 。
注意:此步骤在B.3.6.2 节中被替换。
如果 x 是数字 且
y 是字符串 ,返回
! IsLooselyEqual (x ,
! ToNumber (y ))。
如果 x 是字符串 且
y 是数字 ,返回
! IsLooselyEqual (! ToNumber (x ), y )。
如果 x 是
BigInt 且 y 是字符串 ,那么
设 n 为 StringToBigInt (y )。
如果 n 是 undefined ,返回 false 。
返回 ! IsLooselyEqual (x ,
n )。
如果 x 是字符串 且
y 是
BigInt ,返回 ! IsLooselyEqual (y ,
x )。
如果 x 是布尔值 ,返回
! IsLooselyEqual (! ToNumber (x ), y )。
如果 y 是布尔值 ,返回
! IsLooselyEqual (x ,
! ToNumber (y ))。
如果 x 是字符串、数字、BigInt 或符号,且 y 是对象 ,返回 ! IsLooselyEqual (x ,
? ToPrimitive (y ))。
如果 x 是对象 且 y 是字符串、数字、BigInt 或符号,返回
! IsLooselyEqual (? ToPrimitive (x ), y )。
如果 x 是
BigInt 且 y 是数字 ,或如果
x 是数字 且
y 是
BigInt ,那么
如果 x 不是有限的 或 y 不是有限的 ,返回
false 。
如果 ℝ (x )
= ℝ (y ),返回 true ;否则返回
false 。
返回 false 。
7.2.14 IsStrictlyEqual ( x , y )
抽象操作 IsStrictlyEqual 接受参数 x (一个ECMAScript 语言值 )和
y (一个ECMAScript 语言值 )并返回一个布尔值。它为
===
运算符提供语义。它在被调用时执行以下步骤:
如果 SameType (x , y ) 是
false ,返回 false 。
如果 x 是数字 ,那么
返回 Number::equal (x ,
y )。
返回 SameValueNonNumber (x ,
y )。
注意
此算法与 SameValue 算法在处理有符号零和 NaN 方面有所不同。
7.3 对象操作
7.3.1 MakeBasicObject ( internalSlotsList )
抽象操作 MakeBasicObject 接受参数 internalSlotsList (一个内部槽名称的列表 )并返回一个对象。它是所有算法创建的
ECMAScript 对象的源头,包括普通对象 和异质对象 。它提取了创建所有对象时使用的通用步骤,并集中了对象创建过程。它在被调用时执行以下步骤:
设 internalSlotsList 为 internalSlotsList 和 « [[PrivateElements]] » 的列表连接 。
设 obj 为一个新创建的对象,为 internalSlotsList 中的每个名称都有一个内部槽。
注意:如对象内部方法和内部槽 中所述,除非另有规定,每个这样的内部槽的初始值都是
undefined 。
设 obj .[[PrivateElements]] 为一个新的空列表 。
将 obj 的基本内部方法设置为10.1
中指定的默认普通对象 定义。
断言 :如果调用者不会覆盖
obj 的 [[GetPrototypeOf]] 和 [[SetPrototypeOf]] 基本内部方法,那么 internalSlotsList 包含
[[Prototype]] 。
断言 :如果调用者不会覆盖
obj 的所有 [[SetPrototypeOf]] 、[[IsExtensible]] 和 [[PreventExtensions]] 基本内部方法,那么 internalSlotsList 包含
[[Extensible]] 。
如果 internalSlotsList 包含 [[Extensible]] ,设
obj .[[Extensible]] 为 true 。
返回 obj 。
注意
在本规范中,异质对象 是在诸如 ArrayCreate 和 BoundFunctionCreate 等抽象操作 中创建的,首先调用
MakeBasicObject 来获得一个基本的基础对象,然后覆盖该对象的一些或所有内部方法。为了封装异质对象 的创建,对象的基本内部方法永远不会在这些操作之外被修改。
7.3.2 Get ( O , P )
抽象操作 Get 接受参数 O (一个对象)和 P (一个属性键 )并返回一个包含 一个ECMAScript 语言值 的正常完成 或一个throw
完成 。它用于检索对象的特定属性的值。它在被调用时执行以下步骤:
返回 ? O .[[Get]] (P , O )。
7.3.3 GetV ( V , P )
抽象操作 GetV 接受参数 V (一个ECMAScript 语言值 )和
P (一个属性键 )并返回一个包含 一个ECMAScript 语言值 的正常完成 或一个throw 完成 。它用于检索ECMAScript
语言值 的特定属性的值。如果该值不是对象,则使用适合该值类型的包装器对象执行属性查找。它在被调用时执行以下步骤:
设 O 为 ? ToObject (V )。
返回 ? O .[[Get]] (P , V )。
7.3.4 Set ( O , P , V ,
Throw )
抽象操作 Set 接受参数 O (一个对象)、P (一个属性键 )、V (一个ECMAScript 语言值 )和
Throw (一个布尔值)并返回一个包含
unused 的正常完成 或一个throw
完成 。它用于设置对象的特定属性的值。V 是该属性的新值。它在被调用时执行以下步骤:
设 success 为 ? O .[[Set]] (P , V , O )。
如果 success 是 false 且 Throw 是
true ,抛出 TypeError 异常。
返回 unused 。
7.3.5 CreateDataProperty ( O , P , V
)
抽象操作 CreateDataProperty 接受参数 O (一个对象)、P (一个属性键 )和 V (一个ECMAScript 语言值 )并返回一个包含 布尔值的正常完成 或一个throw
完成 。它用于创建对象的新自有属性。它在被调用时执行以下步骤:
设 newDesc 为 PropertyDescriptor { [[Value]] :
V , [[Writable]] : true , [[Enumerable]] : true , [[Configurable]] : true }。
返回 ? O .[[DefineOwnProperty]] (P ,
newDesc )。
注意
此抽象操作创建一个属性,其特性设置为与 ECMAScript 语言赋值运算符创建的属性相同的默认值。通常,该属性还不存在。如果它存在且不可配置,或者如果 O
不可扩展,[[DefineOwnProperty]] 将返回 false 。
7.3.6 CreateDataPropertyOrThrow ( O , P ,
V )
抽象操作 CreateDataPropertyOrThrow 接受参数 O (一个对象)、P (一个属性键 )和
V (一个ECMAScript 语言值 )并返回一个包含
unused 的正常完成 或一个throw
完成 。它用于创建对象的新自有属性。如果请求的属性更新无法执行,它抛出 TypeError
异常。它在被调用时执行以下步骤:
设 success 为 ? CreateDataProperty (O ,
P , V )。
如果 success 是 false ,抛出 TypeError 异常。
返回 unused 。
注意
此抽象操作创建一个属性,其特性设置为与 ECMAScript 语言赋值运算符创建的属性相同的默认值。通常,该属性还不存在。如果它存在且不可配置,或者如果 O
不可扩展,[[DefineOwnProperty]] 将返回 false ,导致此操作抛出
TypeError 异常。
7.3.7 CreateNonEnumerableDataPropertyOrThrow ( O ,
P , V )
抽象操作 CreateNonEnumerableDataPropertyOrThrow 接受参数 O (一个对象)、P (一个属性键 )和
V (一个ECMAScript 语言值 )并返回
unused 。它用于创建普通对象 的新的不可枚举自有属性。它在被调用时执行以下步骤:
断言 :O
是一个普通的、可扩展的、没有不可配置属性的对象。
设 newDesc 为 PropertyDescriptor { [[Value]] :
V , [[Writable]] : true , [[Enumerable]] : false , [[Configurable]] : true }。
执行 ! DefinePropertyOrThrow (O ,
P , newDesc )。
返回 unused 。
注意
此抽象操作创建一个属性,其特性设置为与 ECMAScript 语言赋值运算符创建的属性相同的默认值,但它不可枚举。通常,该属性还不存在。如果它存在,DefinePropertyOrThrow 保证正常完成。
7.3.8 DefinePropertyOrThrow ( O , P ,
desc )
抽象操作 DefinePropertyOrThrow 接受参数 O (一个对象)、P (一个属性键 )和 desc (一个属性描述符 )并返回一个包含
unused 的正常完成 或一个throw 完成 。它用于以一种方式调用对象的
[[DefineOwnProperty]] 内部方法,如果请求的属性更新无法执行,将抛出
TypeError 异常。它在被调用时执行以下步骤:
设 success 为 ? O .[[DefineOwnProperty]] (P , desc )。
如果 success 是 false ,抛出 TypeError 异常。
返回 unused 。
7.3.9 DeletePropertyOrThrow ( O , P )
抽象操作 DeletePropertyOrThrow 接受参数 O (一个对象)和 P (一个属性键 )并返回一个包含
unused 的正常完成 或一个throw
完成 。它用于删除对象的特定自有属性。如果属性不可配置,它抛出异常。它在被调用时执行以下步骤:
设 success 为 ? O .[[Delete]] (P )。
如果 success 是 false ,抛出 TypeError 异常。
返回 unused 。
7.3.10 GetMethod ( V , P )
抽象操作 GetMethod 接受参数 V (一个ECMAScript 语言值 )和
P (一个属性键 )并返回一个包含 一个函数对象 或
undefined 的正常完成 ,或一个throw 完成 。它用于获取ECMAScript
语言值 的特定属性的值,当该属性的值预期是一个函数时。它在被调用时执行以下步骤:
设 func 为 ? GetV (V , P )。
如果 func 是 undefined 或 null ,返回
undefined 。
如果 IsCallable (func ) 是
false ,抛出 TypeError 异常。
返回 func 。
7.3.11 HasProperty ( O , P )
抽象操作 HasProperty 接受参数 O (一个对象)和 P (一个属性键 )并返回一个包含 布尔值的正常完成 或一个throw
完成 。它用于确定对象是否具有指定属性键 的属性。该属性可能是自有的或继承的。它在被调用时执行以下步骤:
返回 ? O .[[HasProperty]] (P )。
7.3.12 HasOwnProperty ( O , P )
抽象操作 HasOwnProperty 接受参数 O (一个对象)和 P (一个属性键 )并返回一个包含 布尔值的正常完成 或一个throw
完成 。它用于确定对象是否具有指定属性键 的自有属性。它在被调用时执行以下步骤:
设 desc 为 ? O .[[GetOwnProperty]] (P )。
如果 desc 是 undefined ,返回 false 。
返回 true 。
7.3.13 Call ( F , V [ ,
argumentsList ] )
抽象操作 Call 接受参数 F (一个ECMAScript 语言值 )和
V (一个ECMAScript 语言值 )以及可选参数
argumentsList (一个ECMAScript 语言值 的列表 )并返回一个包含 一个ECMAScript 语言值 的正常完成 或一个throw 完成 。它用于调用函数对象 的 [[Call]] 内部方法。F 是函数对象 ,V 是作为 [[Call]] 的 this 值的ECMAScript
语言值 ,argumentsList 是传递给内部方法相应参数的值。如果 argumentsList
不存在,则使用一个新的空列表 作为其值。它在被调用时执行以下步骤:
如果 argumentsList 不存在,设 argumentsList 为一个新的空列表 。
如果 IsCallable (F ) 是
false ,抛出 TypeError 异常。
返回 ? F .[[Call]] (V , argumentsList )。
7.3.14 Construct ( F [ , argumentsList [ ,
newTarget ] ] )
抽象操作 Construct 接受参数 F (一个构造器 )以及可选参数 argumentsList (一个ECMAScript 语言值 的列表 )和
newTarget (一个构造器 )并返回一个包含 对象的正常完成 或一个throw 完成 。它用于调用函数对象 的 [[Construct]] 内部方法。argumentsList 和 newTarget
是要作为内部方法相应参数传递的值。如果 argumentsList 不存在,则使用一个新的空列表 作为其值。如果
newTarget 不存在,则使用 F 作为其值。它在被调用时执行以下步骤:
如果 newTarget 不存在,设 newTarget 为 F 。
如果 argumentsList 不存在,设 argumentsList 为一个新的空列表 。
返回 ? F .[[Construct]] (argumentsList ,
newTarget )。
注意
如果 newTarget 不存在,此操作等价于:new F(...argumentsList)
7.3.15 SetIntegrityLevel ( O , level )
抽象操作 SetIntegrityLevel 接受参数 O (一个对象)和 level (sealed 或
frozen )并返回一个包含 布尔值的正常完成 或一个throw
完成 。它用于固定对象自有属性的集合。它在被调用时执行以下步骤:
设 status 为 ? O .[[PreventExtensions]] ()。
如果 status 是 false ,返回 false 。
设 keys 为 ? O .[[OwnPropertyKeys]] ()。
如果 level 是 sealed ,那么
对于 keys 的每个元素 k ,执行
执行 ? DefinePropertyOrThrow (O ,
k , PropertyDescriptor { [[Configurable]] :
false })。
否则,
断言 :level 是
frozen 。
对于 keys 的每个元素 k ,执行
设 currentDesc 为 ? O .[[GetOwnProperty]] (k )。
如果 currentDesc 不是 undefined ,那么
如果 IsAccessorDescriptor (currentDesc )
是 true ,那么
设 desc 为 PropertyDescriptor { [[Configurable]] :
false }。
否则,
设 desc 为 PropertyDescriptor { [[Configurable]] :
false , [[Writable]] :
false }。
执行 ? DefinePropertyOrThrow (O ,
k , desc )。
返回 true 。
7.3.16 TestIntegrityLevel ( O , level )
抽象操作 TestIntegrityLevel 接受参数 O (一个对象)和 level (sealed 或
frozen )并返回一个包含 布尔值的正常完成 或一个throw
完成 。它用于确定对象自有属性的集合是否被固定。它在被调用时执行以下步骤:
设 extensible 为 ? IsExtensible (O )。
如果 extensible 是 true ,返回 false 。
注意:如果对象是可扩展的,则不检查其任何属性。
设 keys 为 ? O .[[OwnPropertyKeys]] ()。
对于 keys 的每个元素 k ,执行
设 currentDesc 为 ? O .[[GetOwnProperty]] (k )。
如果 currentDesc 不是 undefined ,那么
如果 currentDesc .[[Configurable]] 是
true ,返回 false 。
如果 level 是 frozen 且 IsDataDescriptor (currentDesc )
是 true ,那么
如果 currentDesc .[[Writable]]
是 true ,返回 false 。
返回 true 。
7.3.17 CreateArrayFromList ( elements )
抽象操作 CreateArrayFromList 接受参数 elements (一个ECMAScript 语言值 的列表 )并返回一个数组。它用于创建一个由
elements 提供元素的数组。它在被调用时执行以下步骤:
设 array 为 ! ArrayCreate (0)。
设 n 为 0。
对于 elements 的每个元素 e ,执行
执行 ! CreateDataPropertyOrThrow (array ,
! ToString (𝔽 (n )),
e )。
设 n 为 n + 1。
返回 array 。
7.3.18 LengthOfArrayLike ( obj )
抽象操作 LengthOfArrayLike 接受参数 obj (一个对象)并返回一个包含 非负整数 的正常完成 或一个throw 完成 。它返回类数组对象的
"length" 属性的值。它在被调用时执行以下步骤:
返回 ℝ (? ToLength (? Get (obj ,
"length" )))。
类数组对象 是此操作返回正常完成 的任何对象。
注意 1
通常,类数组对象还会有一些带有
整数索引 名称的属性。但是,这不是此定义的要求。
注意 2
数组和字符串对象是类数组对象的例子。
7.3.19 CreateListFromArrayLike ( obj [ ,
validElementTypes ] )
抽象操作 CreateListFromArrayLike 接受参数 obj (一个ECMAScript 语言值 )和可选参数
validElementTypes (all 或
property-key )并返回一个包含 ECMAScript 语言值 的列表 的正常完成 或一个throw
完成 。它用于创建一个列表 值,其元素由
obj 的索引属性提供。validElementTypes 指示允许作为元素的值的类型。它在被调用时执行以下步骤:
如果 validElementTypes 不存在,设 validElementTypes 为
all 。
如果 obj 不是对象 ,抛出 TypeError 异常。
设 len 为 ? LengthOfArrayLike (obj )。
设 list 为一个新的空列表 。
设 index 为 0。
重复,当 index < len 时,
设 indexName 为 ! ToString (𝔽 (index ))。
设 next 为 ? Get (obj ,
indexName )。
如果 validElementTypes 是 property-key 且
next 不是属性键 ,抛出 TypeError
异常。
将 next 追加到 list 。
设 index 为 index + 1。
返回 list 。
7.3.20 Invoke ( V , P [ ,
argumentsList ] )
抽象操作 Invoke 接受参数 V (一个ECMAScript 语言值 )和
P (一个属性键 )以及可选参数 argumentsList (一个ECMAScript 语言值 的列表 )并返回一个包含 一个ECMAScript 语言值 的正常完成 或一个throw 完成 。它用于调用ECMAScript 语言值 的方法属性。V
既作为属性的查找点,也作为调用的 this 值。argumentsList 是传递给方法的参数值列表。如果
argumentsList 不存在,则使用一个新的空列表 作为其值。它在被调用时执行以下步骤:
如果 argumentsList 不存在,设 argumentsList 为一个新的空列表 。
设 func 为 ? GetV (V , P )。
返回 ? Call (func , V ,
argumentsList )。
7.3.21 OrdinaryHasInstance ( C , O )
抽象操作 OrdinaryHasInstance 接受参数 C (一个ECMAScript 语言值 )和
O (一个ECMAScript 语言值 )并返回一个包含 布尔值的正常完成 或一个throw 完成 。它实现了确定
O 是否继承自 C 提供的实例对象继承路径的默认算法。它在被调用时执行以下步骤:
如果 IsCallable (C ) 是
false ,返回 false 。
如果 C 有 [[BoundTargetFunction]] 内部槽,那么
设 BC 为 C .[[BoundTargetFunction]] 。
返回 ? InstanceofOperator (O ,
BC )。
如果 O 不是对象 ,返回 false 。
设 P 为 ? Get (C ,
"prototype" )。
如果 P 不是对象 ,抛出 TypeError 异常。
重复,
设 O 为 ? O .[[GetPrototypeOf]] ()。
如果 O 是 null ,返回 false 。
如果 SameValue (P ,
O ) 是 true ,返回 true 。
7.3.22 SpeciesConstructor ( O ,
defaultConstructor )
抽象操作 SpeciesConstructor 接受参数 O (一个对象)和 defaultConstructor (一个构造器 )并返回一个包含 一个构造器 的正常完成 或一个throw 完成 。它用于检索应该用于创建从
O 派生的新对象的构造器 。defaultConstructor 是当从 O
开始无法找到构造器
%Symbol.species% 属性时要使用的构造器 。它在被调用时执行以下步骤:
设 C 为 ? Get (O ,
"constructor" )。
如果 C 是 undefined ,返回 defaultConstructor 。
如果 C 不是对象 ,抛出 TypeError 异常。
设 S 为 ? Get (C , %Symbol.species% )。
如果 S 是 undefined 或 null ,返回
defaultConstructor 。
如果 IsConstructor (S ) 是
true ,返回 S 。
抛出 TypeError 异常。
7.3.23 EnumerableOwnProperties ( O , kind )
抽象操作 EnumerableOwnProperties 接受参数 O (一个对象)和
kind (key 、value 或
key+value )并返回一个包含 ECMAScript 语言值 的列表 的正常完成 或一个throw 完成 。它在被调用时执行以下步骤:
设 ownKeys 为 ? O .[[OwnPropertyKeys]] ()。
设 results 为一个新的空列表 。
对于 ownKeys 的每个元素 key ,执行
如果 key 是字符串 ,那么
设 desc 为 ? O .[[GetOwnProperty]] (key )。
如果 desc 不是 undefined 且
desc .[[Enumerable]] 是
true ,那么
如果 kind 是 key ,那么
将 key 追加到 results 。
否则,
设 value 为 ? Get (O ,
key )。
如果 kind 是 value ,那么
将 value 追加到 results 。
否则,
断言 :kind
是 key+value 。
设 entry 为 CreateArrayFromList («
key , value »)。
将 entry 追加到 results 。
返回 results 。
7.3.24 GetFunctionRealm ( obj )
抽象操作 GetFunctionRealm 接受参数 obj (一个函数对象 )并返回一个包含 一个Realm
Record 的正常完成 或一个throw 完成 。它在被调用时执行以下步骤:
如果 obj 有 [[Realm]] 内部槽,那么
返回 obj .[[Realm]] 。
如果 obj 是绑定函数异质对象 ,那么
设 boundTargetFunction 为 obj .[[BoundTargetFunction]] 。
返回 ? GetFunctionRealm (boundTargetFunction )。
如果 obj 是代理异质对象 ,那么
执行 ? ValidateNonRevokedProxy (obj )。
设 proxyTarget 为 obj .[[ProxyTarget]] 。
断言 :proxyTarget 是一个函数对象 。
返回 ? GetFunctionRealm (proxyTarget )。
返回当前 Realm Record 。
注意
只有当 obj 是一个没有 [[Realm]] 内部槽的非标准函数异质对象 时,才会执行步骤4 。
7.3.25 CopyDataProperties ( target , source ,
excludedItems )
抽象操作 CopyDataProperties 接受参数 target (一个对象)、source (一个ECMAScript 语言值 )和
excludedItems (一个属性键 的列表 )并返回一个包含
unused 的正常完成 或一个throw 完成 。它在被调用时执行以下步骤:
如果 source 是 undefined 或 null ,返回
unused 。
设 from 为 ! ToObject (source )。
设 keys 为 ? from .[[OwnPropertyKeys]] ()。
对于 keys 的每个元素 nextKey ,执行
设 excluded 为 false 。
对于 excludedItems 的每个元素 e ,执行
如果 SameValue (e ,
nextKey ) 是 true ,那么
设 excluded 为 true 。
如果 excluded 是 false ,那么
设 desc 为 ? from .[[GetOwnProperty]] (nextKey )。
如果 desc 不是 undefined 且
desc .[[Enumerable]] 是
true ,那么
设 propValue 为 ? Get (from ,
nextKey )。
执行 ! CreateDataPropertyOrThrow (target ,
nextKey , propValue )。
返回 unused 。
注意
这里传入的目标总是一个新创建的对象,在抛出错误的情况下不能直接访问。
7.3.26 PrivateElementFind ( O , P )
抽象操作 PrivateElementFind 接受参数 O (一个对象)和 P (一个私有名称 )并返回一个PrivateElement 或
empty 。它在被调用时执行以下步骤:
如果 O .[[PrivateElements]] 包含一个PrivateElement
pe ,其中 pe .[[Key]] 是 P ,那么
返回 pe 。
返回 empty 。
7.3.27 PrivateFieldAdd ( O , P ,
value )
抽象操作 PrivateFieldAdd 接受参数 O (一个对象)、P (一个私有名称 )和
value (一个ECMAScript 语言值 )并返回一个包含
unused 的正常完成 或一个throw 完成 。它在被调用时执行以下步骤:
如果宿主 是 Web 浏览器,那么
执行 ? HostEnsureCanAddPrivateElement (O )。
设 entry 为 PrivateElementFind (O ,
P )。
如果 entry 不是 empty ,抛出 TypeError 异常。
将 PrivateElement {
[[Key]] : P , [[Kind]] :
field , [[Value]] :
value } 追加到 O .[[PrivateElements]] 。
返回 unused 。
7.3.28 PrivateMethodOrAccessorAdd ( O , method
)
抽象操作 PrivateMethodOrAccessorAdd 接受参数 O (一个对象)和 method (一个PrivateElement )并返回一个包含
unused 的正常完成 或一个throw 完成 。它在被调用时执行以下步骤:
断言 :method .[[Kind]] 是 method 或
accessor 。
如果宿主 是 Web 浏览器,那么
执行 ? HostEnsureCanAddPrivateElement (O )。
设 entry 为 PrivateElementFind (O ,
method .[[Key]] )。
如果 entry 不是 empty ,抛出 TypeError 异常。
将 method 追加到 O .[[PrivateElements]] 。
返回 unused 。
注意
私有方法和访问器的值在实例之间共享。此操作不会创建方法或访问器的新副本。
7.3.29 HostEnsureCanAddPrivateElement ( O )
宿主定义的 抽象操作
HostEnsureCanAddPrivateElement 接受参数 O (一个对象)并返回一个包含
unused 的正常完成 或一个throw 完成 。它允许宿主环境 阻止向特定的宿主定义的 异质对象 添加私有元素。
HostEnsureCanAddPrivateElement 的实现必须符合以下要求:
HostEnsureCanAddPrivateElement 的默认实现是返回 NormalCompletion (unused )。
此抽象操作仅由作为 Web 浏览器的 ECMAScript 宿主 调用。
7.3.30 PrivateGet ( O , P )
抽象操作 PrivateGet 接受参数 O (一个对象)和 P (一个私有名称 )并返回一个包含 一个ECMAScript 语言值 的正常完成 或一个throw 完成 。它在被调用时执行以下步骤:
设 entry 为 PrivateElementFind (O ,
P )。
如果 entry 是 empty ,抛出 TypeError 异常。
如果 entry .[[Kind]] 是 field 或
method ,那么
返回 entry .[[Value]] 。
断言 :entry .[[Kind]] 是 accessor 。
如果 entry .[[Get]] 是 undefined ,抛出
TypeError 异常。
设 getter 为 entry .[[Get]] 。
返回 ? Call (getter , O )。
7.3.31 PrivateSet ( O , P , value )
抽象操作 PrivateSet 接受参数 O (一个对象)、P (一个私有名称 )和
value (一个ECMAScript 语言值 )并返回一个包含
unused 的正常完成 或一个throw 完成 。它在被调用时执行以下步骤:
设 entry 为 PrivateElementFind (O ,
P )。
如果 entry 是 empty ,抛出 TypeError 异常。
如果 entry .[[Kind]] 是 field ,那么
设 entry .[[Value]] 为 value 。
否则如果 entry .[[Kind]] 是
method ,那么
抛出 TypeError 异常。
否则,
断言 :entry .[[Kind]] 是 accessor 。
如果 entry .[[Set]] 是
undefined ,抛出 TypeError 异常。
设 setter 为 entry .[[Set]] 。
执行 ? Call (setter , O ,
« value »)。
返回 unused 。
7.3.32 DefineField ( receiver , fieldRecord )
抽象操作 DefineField 接受参数 receiver (一个对象)和 fieldRecord (一个ClassFieldDefinition
Record )并返回一个包含
unused 的正常完成 或一个throw 完成 。它在被调用时执行以下步骤:
设 fieldName 为 fieldRecord .[[Name]] 。
设 initializer 为 fieldRecord .[[Initializer]] 。
如果 initializer 不是 empty ,那么
设 initValue 为 ? Call (initializer ,
receiver )。
否则,
设 initValue 为 undefined 。
如果 fieldName 是私有名称 ,那么
执行 ? PrivateFieldAdd (receiver ,
fieldName , initValue )。
否则,
断言 :fieldName 是一个属性键 。
执行 ? CreateDataPropertyOrThrow (receiver ,
fieldName , initValue )。
返回 unused 。
7.3.33 InitializeInstanceElements ( O ,
constructor )
抽象操作 InitializeInstanceElements 接受参数 O (一个对象)和 constructor (一个 ECMAScript
函数对象 )并返回一个包含
unused 的正常完成 或一个throw 完成 。它在被调用时执行以下步骤:
设 methods 为 constructor .[[PrivateMethods]] 的值。
对于 methods 的每个PrivateElement
method ,执行
执行 ? PrivateMethodOrAccessorAdd (O ,
method )。
设 fields 为 constructor .[[Fields]] 的值。
对于 fields 的每个元素 fieldRecord ,执行
执行 ? DefineField (O ,
fieldRecord )。
返回 unused 。
7.3.34 AddValueToKeyedGroup ( groups , key ,
value )
抽象操作 AddValueToKeyedGroup 接受参数 groups (一个记录 的列表 ,具有字段 [[Key]] (一个ECMAScript 语言值 )和 [[Elements]] (一个ECMAScript
语言值 的列表 ))、key (一个ECMAScript 语言值 )和
value (一个ECMAScript 语言值 )并返回
unused 。它在被调用时执行以下步骤:
对于 groups 的每个记录 {
[[Key]] , [[Elements]] }
g ,执行
如果 SameValue (g .[[Key]] , key ) 是 true ,那么
断言 :groups
中恰好有一个元素满足此条件。
将 value 追加到 g .[[Elements]] 。
返回 unused 。
设 group 为记录 {
[[Key]] : key , [[Elements]] :
« value » }。
将 group 追加到 groups 。
返回 unused 。
7.3.35 GroupBy ( items , callback ,
keyCoercion )
抽象操作 GroupBy 接受参数 items (一个ECMAScript
语言值 )、callback (一个ECMAScript 语言值 )和
keyCoercion (property 或
collection )并返回一个包含 记录 的列表 的正常完成 (具有字段 [[Key]] (一个ECMAScript 语言值 )和 [[Elements]] (一个ECMAScript
语言值 的列表 ))或一个throw 完成 。它在被调用时执行以下步骤:
执行 ? RequireObjectCoercible (items )。
如果 IsCallable (callback ) 是
false ,抛出 TypeError 异常。
设 groups 为一个新的空列表 。
设 iteratorRecord 为 ? GetIterator (items ,
sync )。
设 k 为 0。
重复,
如果 k ≥ 253 - 1,那么
设 error 为 ThrowCompletion (新创建的
TypeError 对象)。
返回 ? IteratorClose (iteratorRecord ,
error )。
设 next 为 ? IteratorStepValue (iteratorRecord )。
如果 next 是 done ,那么
返回 groups 。
设 value 为 next 。
设 key 为 Completion (Call (callback ,
undefined , « value , 𝔽 (k ) »))。
IfAbruptCloseIterator (key ,
iteratorRecord )。
如果 keyCoercion 是 property ,那么
设 key 为 Completion (ToPropertyKey (key ))。
IfAbruptCloseIterator (key ,
iteratorRecord )。
否则,
断言 :keyCoercion 是
collection 。
设 key 为 CanonicalizeKeyedCollectionKey (key )。
执行 AddValueToKeyedGroup (groups ,
key , value )。
设 k 为 k + 1。
7.3.36 SetterThatIgnoresPrototypeProperties ( thisValue ,
home , p , v )
抽象操作 SetterThatIgnoresPrototypeProperties 接受参数 thisValue (一个ECMAScript
语言值 )、home (一个对象)、p (一个属性键 )和 v (一个ECMAScript 语言值 )并返回一个包含
unused 的正常完成 或一个throw 完成 。它在被调用时执行以下步骤:
如果 thisValue 不是对象 ,那么
抛出 TypeError 异常。
如果 SameValue (thisValue ,
home ) 是 true ,那么
注意:这里抛出异常模拟了在严格模式代码 中对 home
对象上不可写数据属性 的赋值。
抛出 TypeError 异常。
设 desc 为 ? thisValue .[[GetOwnProperty]] (p )。
如果 desc 是 undefined ,那么
执行 ? CreateDataPropertyOrThrow (thisValue ,
p , v )。
否则,
执行 ? Set (thisValue ,
p , v , true )。
返回 unused 。
7.4 迭代器对象上的操作
参见通用迭代接口(27.1 )。
7.4.1 迭代器记录
迭代器记录 是一个记录 值,用于封装一个迭代器 或异步迭代器 以及其 next
方法。
迭代器记录具有表 15 中列出的字段。
表 15:迭代器记录 字段
7.4.2 GetIteratorDirect ( obj )
抽象操作 GetIteratorDirect 接受参数 obj (一个对象)并返回一个包含 一个迭代器记录 的正常完成 或一个throw 完成 。它在被调用时执行以下步骤:
设 nextMethod 为 ? Get (obj ,
"next" )。
设 iteratorRecord 为迭代器记录 { [[Iterator]] : obj , [[NextMethod]] : nextMethod , [[Done]] : false }。
返回 iteratorRecord 。
7.4.3 GetIteratorFromMethod ( obj , method )
抽象操作 GetIteratorFromMethod 接受参数 obj (一个ECMAScript 语言值 )和
method (一个函数对象 )并返回一个包含 一个迭代器记录 的正常完成 或一个throw 完成 。它在被调用时执行以下步骤:
设 iterator 为 ? Call (method , obj )。
如果 iterator 不是对象 ,抛出 TypeError 异常。
返回 ? GetIteratorDirect (iterator )。
7.4.4 GetIterator ( obj , kind )
抽象操作 GetIterator 接受参数 obj (一个ECMAScript 语言值 )和
kind (sync 或 async )并返回一个包含 一个迭代器记录 的正常完成 或一个throw 完成 。它在被调用时执行以下步骤:
如果 kind 是 async ,那么
设 method 为 ? GetMethod (obj , %Symbol.asyncIterator% )。
如果 method 是 undefined ,那么
设 syncMethod 为 ? GetMethod (obj ,
%Symbol.iterator% )。
如果 syncMethod 是 undefined ,抛出
TypeError 异常。
设 syncIteratorRecord 为 ? GetIteratorFromMethod (obj ,
syncMethod )。
返回 CreateAsyncFromSyncIterator (syncIteratorRecord )。
否则,
设 method 为 ? GetMethod (obj , %Symbol.iterator% )。
如果 method 是 undefined ,抛出 TypeError 异常。
返回 ? GetIteratorFromMethod (obj ,
method )。
7.4.5 GetIteratorFlattenable ( obj ,
primitiveHandling )
抽象操作 GetIteratorFlattenable 接受参数 obj (一个ECMAScript 语言值 )和
primitiveHandling (iterate-string-primitives 或
reject-primitives )并返回一个包含 一个迭代器记录 的正常完成 或一个throw 完成 。它在被调用时执行以下步骤:
如果 obj 不是对象 ,那么
如果 primitiveHandling 是 reject-primitives ,抛出
TypeError 异常。
断言 :primitiveHandling 是
iterate-string-primitives 。
如果 obj 不是字符串 ,抛出
TypeError 异常。
设 method 为 ? GetMethod (obj , %Symbol.iterator% )。
如果 method 是 undefined ,那么
设 iterator 为 obj 。
否则,
设 iterator 为 ? Call (method ,
obj )。
如果 iterator 不是对象 ,抛出 TypeError 异常。
返回 ? GetIteratorDirect (iterator )。
7.4.6 IteratorNext ( iteratorRecord [ , value
] )
抽象操作 IteratorNext 接受参数 iteratorRecord (一个迭代器记录 )和可选参数
value (一个ECMAScript 语言值 )并返回一个包含 一个对象的正常完成 或一个throw 完成 。它在被调用时执行以下步骤:
如果 value 不存在,那么
设 result 为 Completion (Call (iteratorRecord .[[NextMethod]] , iteratorRecord .[[Iterator]] ))。
否则,
设 result 为 Completion (Call (iteratorRecord .[[NextMethod]] , iteratorRecord .[[Iterator]] , « value »))。
如果 result 是throw
完成 ,那么
设 iteratorRecord .[[Done]] 为
true 。
返回 ? result 。
设 result 为 ! result 。
如果 result 不是对象 ,那么
设 iteratorRecord .[[Done]] 为
true 。
抛出 TypeError 异常。
返回 result 。
7.4.7 IteratorComplete ( iteratorResult )
抽象操作 IteratorComplete 接受参数 iteratorResult (一个对象)并返回一个包含 一个布尔值的正常完成 或一个throw 完成 。它在被调用时执行以下步骤:
返回 ToBoolean (? Get (iteratorResult ,
"done" ))。
7.4.8 IteratorValue ( iteratorResult )
抽象操作 IteratorValue 接受参数 iteratorResult (一个对象)并返回一个包含 一个ECMAScript 语言值 的正常完成 或一个throw 完成 。它在被调用时执行以下步骤:
返回 ? Get (iteratorResult ,
"value" )。
7.4.9 IteratorStep ( iteratorRecord )
抽象操作 IteratorStep 接受参数 iteratorRecord (一个迭代器记录 )并返回一个包含 一个对象或
done 的正常完成 ,或一个throw 完成 。它通过调用
iteratorRecord .[[NextMethod]] 从
iteratorRecord .[[Iterator]] 请求下一个值,并返回
done (表示迭代器 已到达末尾)或IteratorResult
对象 (如果下一个值可用)。它在被调用时执行以下步骤:
设 result 为 ? IteratorNext (iteratorRecord )。
设 done 为 Completion (IteratorComplete (result ))。
如果 done 是throw
完成 ,那么
设 iteratorRecord .[[Done]] 为
true 。
返回 ? done 。
设 done 为 ! done 。
如果 done 是 true ,那么
设 iteratorRecord .[[Done]] 为
true 。
返回 done 。
返回 result 。
7.4.10 IteratorStepValue ( iteratorRecord )
抽象操作 IteratorStepValue 接受参数 iteratorRecord (一个迭代器记录 )并返回一个包含 一个ECMAScript 语言值 或
done 的正常完成 ,或一个throw 完成 。它通过调用
iteratorRecord .[[NextMethod]] 从
iteratorRecord .[[Iterator]] 请求下一个值,并返回
done (表示迭代器 已到达末尾)或来自IteratorResult
对象 的值(如果下一个值可用)。它在被调用时执行以下步骤:
设 result 为 ? IteratorStep (iteratorRecord )。
如果 result 是 done ,那么
返回 done 。
设 value 为 Completion (IteratorValue (result ))。
如果 value 是throw
完成 ,那么
设 iteratorRecord .[[Done]] 为
true 。
返回 ? value 。
7.4.11 IteratorClose ( iteratorRecord ,
completion )
抽象操作 IteratorClose 接受参数 iteratorRecord (一个迭代器记录 )和
completion (一个完成记录 )并返回一个完成记录 。它用于通知迭代器 应该执行它在到达完成状态时通常要执行的任何操作。它在被调用时执行以下步骤:
断言 :iteratorRecord .[[Iterator]] 是一个对象 。
设 iterator 为 iteratorRecord .[[Iterator]] 。
设 innerResult 为 Completion (GetMethod (iterator ,
"return" ))。
如果 innerResult 是正常完成 ,那么
设 return 为 innerResult .[[Value]] 。
如果 return 是 undefined ,返回
? completion 。
设 innerResult 为 Completion (Call (return ,
iterator ))。
如果 completion 是throw
完成 ,返回 ? completion 。
如果 innerResult 是throw
完成 ,返回 ? innerResult 。
如果 innerResult .[[Value]] 不是对象 ,抛出 TypeError 异常。
返回 ? completion 。
7.4.12 IfAbruptCloseIterator ( value ,
iteratorRecord )
IfAbruptCloseIterator 是使用迭代器记录 的算法步骤序列的简写。形式为以下的算法步骤:
IfAbruptCloseIterator (value ,
iteratorRecord )。
与以下含义相同:
断言 :value 是一个完成记录 。
如果 value 是异常完成 ,返回
? IteratorClose (iteratorRecord ,
value )。
否则,设 value 为 ! value 。
7.4.13 AsyncIteratorClose ( iteratorRecord ,
completion )
抽象操作 AsyncIteratorClose 接受参数 iteratorRecord (一个迭代器记录 )和
completion (一个完成记录 )并返回一个完成记录 。它用于通知异步迭代器 应该执行它在到达完成状态时通常要执行的任何操作。它在被调用时执行以下步骤:
断言 :iteratorRecord .[[Iterator]] 是一个对象 。
设 iterator 为 iteratorRecord .[[Iterator]] 。
设 innerResult 为 Completion (GetMethod (iterator ,
"return" ))。
如果 innerResult 是正常完成 ,那么
设 return 为 innerResult .[[Value]] 。
如果 return 是 undefined ,返回
? completion 。
设 innerResult 为 Completion (Call (return ,
iterator ))。
如果 innerResult 是正常完成 ,设
innerResult 为 Completion (Await (innerResult .[[Value]] ))。
如果 completion 是throw
完成 ,返回 ? completion 。
如果 innerResult 是throw
完成 ,返回 ? innerResult 。
如果 innerResult .[[Value]] 不是对象 ,抛出 TypeError 异常。
返回 ? completion 。
7.4.14 CreateIteratorResultObject ( value ,
done )
抽象操作 CreateIteratorResultObject 接受参数 value (一个ECMAScript 语言值 )和
done (一个布尔值)并返回一个符合IteratorResult
接口 的对象。它创建一个符合IteratorResult
接口 的对象。它在被调用时执行以下步骤:
设 obj 为 OrdinaryObjectCreate (%Object.prototype% )。
执行 ! CreateDataPropertyOrThrow (obj ,
"value" , value )。
执行 ! CreateDataPropertyOrThrow (obj ,
"done" , done )。
返回 obj 。
7.4.15 CreateListIteratorRecord ( list )
抽象操作 CreateListIteratorRecord 接受参数 list (一个包含ECMAScript 语言值 的列表 )并返回一个迭代器记录 。它创建一个迭代器记录 ,其 [[NextMethod]] 返回 list 的连续元素。它在被调用时执行以下步骤:
设 closure 为一个新的抽象闭包 ,它没有参数,捕获
list ,并在被调用时执行以下步骤:
对于 list 的每个元素 E ,执行
执行 ? GeneratorYield (CreateIteratorResultObject (E ,
false ))。
返回 NormalCompletion (undefined )。
设 iterator 为 CreateIteratorFromClosure (closure ,
empty , %Iterator.prototype% )。
返回迭代器记录 { [[Iterator]] : iterator , [[NextMethod]] : %GeneratorPrototype.next%, [[Done]] : false }。
注意
列表迭代器对象 永远不会直接暴露给 ECMAScript 代码。
7.4.16 IteratorToList ( iteratorRecord )
抽象操作 IteratorToList 接受参数 iteratorRecord (一个迭代器记录 )并返回一个包含 一个列表 (包含ECMAScript 语言值 )的正常完成 或一个throw 完成 。它在被调用时执行以下步骤:
设 values 为一个新的空列表 。
重复,
设 next 为 ? IteratorStepValue (iteratorRecord )。
如果 next 是 done ,那么
返回 values 。
将 next 追加到 values 。
8 语法定向操作
除了本节中定义的操作外,专用的语法定向操作 在本规范中各处都有定义。
8.1 运行时语义:Evaluation
语法定向操作
Evaluation 不接受参数并返回一个完成记录 。
注意
此操作的定义分布在本规范的"ECMAScript 语言"章节中。每个定义都出现在相关产生式的定义出现之后。
8.2 作用域分析
8.2.1 静态语义:BoundNames
语法定向操作
BoundNames 不接受参数并返回一个字符串的列表 。
注意
"*default*" 在本规范中用作模块的默认导出在没有其他名称时的合成名称。模块的 [[Environment]] 中会创建一个具有该名称的条目并保存相应的值,通过为模块调用 ResolveExport ( exportName [ ,
resolveSet ] ) 来解析名为 "default"
的导出将返回一个 ResolvedBinding 记录 ,其 [[BindingName]] 是 "*default*" ,然后在模块的 [[Environment]] 中解析为上述值。这样做只是为了便于规范,使匿名默认导出可以像任何其他导出一样解析。这个
"*default*" 字符串永远不会暴露给 ECMAScript 代码或模块链接算法。
它在以下产生式上分段定义:
BindingIdentifier
:
Identifier
返回一个列表 ,其唯一元素是 Identifier 的StringValue 。
BindingIdentifier
:
yield
返回 « "yield" »。
BindingIdentifier
:
await
返回 « "await" »。
LexicalDeclaration
:
LetOrConst
BindingList
;
返回 BindingList
的BoundNames 。
BindingList
:
BindingList
,
LexicalBinding
设 names1 为 BindingList 的BoundNames 。
设 names2 为 LexicalBinding 的BoundNames 。
返回 names1 和 names2 的列表连接 。
LexicalBinding
:
BindingIdentifier
Initializer opt
返回 BindingIdentifier 的BoundNames 。
LexicalBinding
:
BindingPattern
Initializer
返回 BindingPattern
的BoundNames 。
VariableDeclarationList
:
VariableDeclarationList
,
VariableDeclaration
设 names1 为 VariableDeclarationList
的BoundNames 。
设 names2 为 VariableDeclaration 的BoundNames 。
返回 names1 和 names2 的列表连接 。
VariableDeclaration
:
BindingIdentifier
Initializer opt
返回 BindingIdentifier 的BoundNames 。
VariableDeclaration
:
BindingPattern
Initializer
返回 BindingPattern
的BoundNames 。
ObjectBindingPattern
:
{
}
返回一个新的空列表 。
ObjectBindingPattern
:
{
BindingPropertyList
,
BindingRestProperty
}
设 names1 为 BindingPropertyList 的BoundNames 。
设 names2 为 BindingRestProperty 的BoundNames 。
返回 names1 和 names2 的列表连接 。
ArrayBindingPattern
:
[
Elision opt
]
返回一个新的空列表 。
ArrayBindingPattern
:
[
Elision opt
BindingRestElement
]
返回 BindingRestElement 的BoundNames 。
ArrayBindingPattern
:
[
BindingElementList
,
Elision opt
]
返回 BindingElementList 的BoundNames 。
ArrayBindingPattern
:
[
BindingElementList
,
Elision opt
BindingRestElement
]
设 names1 为 BindingElementList 的BoundNames 。
设 names2 为 BindingRestElement 的BoundNames 。
返回 names1 和 names2 的列表连接 。
BindingPropertyList
:
BindingPropertyList
,
BindingProperty
设 names1 为 BindingPropertyList 的BoundNames 。
设 names2 为 BindingProperty 的BoundNames 。
返回 names1 和 names2 的列表连接 。
BindingElementList
:
BindingElementList
,
BindingElisionElement
设 names1 为 BindingElementList 的BoundNames 。
设 names2 为 BindingElisionElement 的BoundNames 。
返回 names1 和 names2 的列表连接 。
BindingElisionElement
:
Elision opt
BindingElement
返回 BindingElement
的BoundNames 。
BindingProperty
:
PropertyName
:
BindingElement
返回 BindingElement
的BoundNames 。
SingleNameBinding
:
BindingIdentifier
Initializer opt
返回 BindingIdentifier 的BoundNames 。
BindingElement
:
BindingPattern
Initializer opt
返回 BindingPattern
的BoundNames 。
ForDeclaration
:
LetOrConst
ForBinding
返回 ForBinding 的BoundNames 。
FunctionDeclaration
:
function
BindingIdentifier
(
FormalParameters
)
{
FunctionBody
}
返回 BindingIdentifier 的BoundNames 。
FunctionDeclaration
:
function
(
FormalParameters
)
{
FunctionBody
}
返回 « "*default*" »。
FormalParameters
:
[empty]
返回一个新的空列表 。
FormalParameters
:
FormalParameterList
,
FunctionRestParameter
设 names1 为 FormalParameterList 的BoundNames 。
设 names2 为 FunctionRestParameter 的BoundNames 。
返回 names1 和 names2 的列表连接 。
FormalParameterList
:
FormalParameterList
,
FormalParameter
设 names1 为 FormalParameterList 的BoundNames 。
设 names2 为 FormalParameter 的BoundNames 。
返回 names1 和 names2 的列表连接 。
ArrowParameters
:
CoverParenthesizedExpressionAndArrowParameterList
设 formals 为被 CoverParenthesizedExpressionAndArrowParameterList
覆盖 的 ArrowFormalParameters 。
返回 formals 的BoundNames 。
GeneratorDeclaration
:
function
*
BindingIdentifier
(
FormalParameters
)
{
GeneratorBody
}
返回 BindingIdentifier 的BoundNames 。
GeneratorDeclaration
:
function
*
(
FormalParameters
)
{
GeneratorBody
}
返回 « "*default*" »。
AsyncGeneratorDeclaration
:
async
function
*
BindingIdentifier
(
FormalParameters
)
{
AsyncGeneratorBody
}
返回 BindingIdentifier 的BoundNames 。
AsyncGeneratorDeclaration
:
async
function
*
(
FormalParameters
)
{
AsyncGeneratorBody
}
返回 « "*default*" »。
ClassDeclaration
:
class
BindingIdentifier
ClassTail
返回 BindingIdentifier 的BoundNames 。
ClassDeclaration
:
class
ClassTail
返回 « "*default*" »。
AsyncFunctionDeclaration
:
async
function
BindingIdentifier
(
FormalParameters
)
{
AsyncFunctionBody
}
返回 BindingIdentifier 的BoundNames 。
AsyncFunctionDeclaration
:
async
function
(
FormalParameters
)
{
AsyncFunctionBody
}
返回 « "*default*" »。
CoverCallExpressionAndAsyncArrowHead
:
MemberExpression
Arguments
设 head 为被 CoverCallExpressionAndAsyncArrowHead
覆盖 的 AsyncArrowHead 。
返回 head 的BoundNames 。
ImportDeclaration
:
import
ImportClause
FromClause
WithClause opt
;
返回 ImportClause
的BoundNames 。
ImportDeclaration
:
import
ModuleSpecifier
WithClause opt
;
返回一个新的空列表 。
ImportClause
:
ImportedDefaultBinding
,
NameSpaceImport
设 names1 为 ImportedDefaultBinding
的BoundNames 。
设 names2 为 NameSpaceImport 的BoundNames 。
返回 names1 和 names2 的列表连接 。
ImportClause
:
ImportedDefaultBinding
,
NamedImports
设 names1 为 ImportedDefaultBinding
的BoundNames 。
设 names2 为 NamedImports 的BoundNames 。
返回 names1 和 names2 的列表连接 。
NamedImports
:
{
}
返回一个新的空列表 。
ImportsList
:
ImportsList
,
ImportSpecifier
设 names1 为 ImportsList 的BoundNames 。
设 names2 为 ImportSpecifier 的BoundNames 。
返回 names1 和 names2 的列表连接 。
ImportSpecifier
:
ModuleExportName
as
ImportedBinding
返回 ImportedBinding
的BoundNames 。
ExportDeclaration
:
export
ExportFromClause
FromClause
WithClause opt
;
export
NamedExports
;
返回一个新的空列表 。
ExportDeclaration
:
export
VariableStatement
返回 VariableStatement 的BoundNames 。
ExportDeclaration
:
export
Declaration
返回 Declaration
的BoundNames 。
ExportDeclaration
:
export
default
HoistableDeclaration
设 declarationNames 为 HoistableDeclaration 的BoundNames 。
如果 declarationNames 不包含元素 "*default*" ,则将
"*default*" 追加到 declarationNames 。
返回 declarationNames 。
ExportDeclaration
:
export
default
ClassDeclaration
设 declarationNames 为 ClassDeclaration 的BoundNames 。
如果 declarationNames 不包含元素 "*default*" ,则将
"*default*" 追加到 declarationNames 。
返回 declarationNames 。
ExportDeclaration
:
export
default
AssignmentExpression
;
返回 « "*default*" »。
8.2.2 静态语义:DeclarationPart
语法定向操作
DeclarationPart 不接受参数并返回一个解析节点 。它在以下产生式上分段定义:
HoistableDeclaration
: FunctionDeclaration
返回 FunctionDeclaration 。
HoistableDeclaration
: GeneratorDeclaration
返回 GeneratorDeclaration 。
HoistableDeclaration
: AsyncFunctionDeclaration
返回 AsyncFunctionDeclaration 。
HoistableDeclaration
: AsyncGeneratorDeclaration
返回 AsyncGeneratorDeclaration 。
Declaration : ClassDeclaration
返回 ClassDeclaration 。
Declaration : LexicalDeclaration
返回 LexicalDeclaration 。
8.2.3 静态语义:IsConstantDeclaration
语法定向操作
IsConstantDeclaration 不接受参数并返回一个布尔值。它在以下产生式上分段定义:
LexicalDeclaration
:
LetOrConst
BindingList
;
返回 LetOrConst 的IsConstantDeclaration 。
LetOrConst : let
返回 false 。
LetOrConst : const
返回 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
}
返回 false 。
ClassDeclaration :
class
BindingIdentifier
ClassTail
class
ClassTail
返回 false 。
ExportDeclaration
:
export
ExportFromClause
FromClause
;
export
NamedExports
;
export
default
AssignmentExpression
;
返回 false 。
注意
没有必要将 export default
AssignmentExpression
视为常量声明,因为没有语法允许对用于引用模块默认对象的内部绑定名称进行赋值。
8.2.4 静态语义:词法声明的名称 (LexicallyDeclaredNames)
语法导向操作
LexicallyDeclaredNames 不接受参数,并返回一个字符串列表 。它根据以下产生式分段定义:
Block :
{
}
返回一个新的空列表 。
StatementList :
StatementList
StatementListItem
令 names1 为 StatementList 的 LexicallyDeclaredNames 。
令 names2 为 StatementListItem 的 LexicallyDeclaredNames 。
返回 names1 和 names2 的列表连接 。
StatementListItem
: Statement
如果 Statement 是
Statement :
LabelledStatement
,则返回 LabelledStatement 的 LexicallyDeclaredNames 。
返回一个新的空列表 。
StatementListItem
: Declaration
返回 Declaration 的
BoundNames 。
CaseBlock :
{
}
返回一个新的空列表 。
CaseBlock :
{
CaseClauses opt
DefaultClause
CaseClauses opt
}
如果第一个 CaseClauses 存在,令
names1 为第一个 CaseClauses 的 LexicallyDeclaredNames 。
否则,令 names1 为一个新的空列表 。
令 names2 为 DefaultClause 的 LexicallyDeclaredNames 。
如果第二个 CaseClauses 存在,令
names3 为第二个 CaseClauses 的 LexicallyDeclaredNames 。
否则,令 names3 为一个新的空列表 。
返回 names1 、names2 和 names3 的列表连接 。
CaseClauses :
CaseClauses
CaseClause
令 names1 为 CaseClauses 的 LexicallyDeclaredNames 。
令 names2 为 CaseClause 的 LexicallyDeclaredNames 。
返回 names1 和 names2 的列表连接 。
CaseClause :
case
Expression
:
StatementList opt
如果 StatementList
存在,则返回 StatementList
的 LexicallyDeclaredNames 。
返回一个新的空列表 。
DefaultClause :
default
:
StatementList opt
如果 StatementList
存在,则返回 StatementList
的 LexicallyDeclaredNames 。
返回一个新的空列表 。
LabelledStatement
:
LabelIdentifier
:
LabelledItem
返回 LabelledItem 的
LexicallyDeclaredNames 。
LabelledItem : Statement
返回一个新的空列表 。
LabelledItem : FunctionDeclaration
返回 FunctionDeclaration 的 BoundNames 。
FunctionStatementList
: [空]
返回一个新的空列表 。
FunctionStatementList
: StatementList
返回 StatementList 的
TopLevelLexicallyDeclaredNames 。
ClassStaticBlockStatementList
: [空]
返回一个新的空列表 。
ClassStaticBlockStatementList
: StatementList
返回 StatementList 的
TopLevelLexicallyDeclaredNames 。
ConciseBody : ExpressionBody
返回一个新的空列表 。
AsyncConciseBody :
ExpressionBody
返回一个新的空列表 。
Script : [空]
返回一个新的空列表 。
ScriptBody : StatementList
返回 StatementList 的
TopLevelLexicallyDeclaredNames 。
注 1
在 Script 的顶层,函数声明被视为类似 var
声明,而不是类似词法声明。
注 2
Module 的
LexicallyDeclaredNames 包含其所有导入绑定的名称。
ModuleItemList :
ModuleItemList
ModuleItem
令 names1 为 ModuleItemList 的 LexicallyDeclaredNames 。
令 names2 为 ModuleItem 的 LexicallyDeclaredNames 。
返回 names1 和 names2 的列表连接 。
ModuleItem : ImportDeclaration
返回 ImportDeclaration 的 BoundNames 。
ModuleItem : ExportDeclaration
如果 ExportDeclaration 是
export
VariableStatement ,则返回一个新的
空列表 。
返回 ExportDeclaration 的 BoundNames 。
ModuleItem : StatementListItem
返回 StatementListItem 的 LexicallyDeclaredNames 。
注 3
在 Module
的顶层,函数声明被视为类似词法声明,而不是类似 var 声明。
8.2.5 静态语义:词法作用域声明 (LexicallyScopedDeclarations)
语法导向操作
LexicallyScopedDeclarations 不接受参数,并返回一个解析节点 的列表 。它根据以下产生式分段定义:
StatementList :
StatementList
StatementListItem
令 declarations1 为 StatementList 的 LexicallyScopedDeclarations 。
令 declarations2 为 StatementListItem 的 LexicallyScopedDeclarations 。
返回 declarations1 和 declarations2 的列表连接 。
StatementListItem
: Statement
如果 Statement 是
Statement :
LabelledStatement
,则返回 LabelledStatement 的 LexicallyScopedDeclarations 。
返回一个新的空列表 。
StatementListItem
: Declaration
返回一个列表 ,其唯一元素是 Declaration 的 DeclarationPart 。
CaseBlock :
{
}
返回一个新的空列表 。
CaseBlock :
{
CaseClauses opt
DefaultClause
CaseClauses opt
}
如果第一个 CaseClauses 存在,令
declarations1 为第一个 CaseClauses 的 LexicallyScopedDeclarations 。
否则,令 declarations1 为一个新的空列表 。
令 declarations2 为 DefaultClause 的 LexicallyScopedDeclarations 。
如果第二个 CaseClauses 存在,令
declarations3 为第二个 CaseClauses 的 LexicallyScopedDeclarations 。
否则,令 declarations3 为一个新的空列表 。
返回 declarations1 、declarations2 和 declarations3
的列表连接 。
CaseClauses :
CaseClauses
CaseClause
令 declarations1 为 CaseClauses 的 LexicallyScopedDeclarations 。
令 declarations2 为 CaseClause 的 LexicallyScopedDeclarations 。
返回 declarations1 和 declarations2 的列表连接 。
CaseClause :
case
Expression
:
StatementList opt
如果 StatementList
存在,则返回 StatementList
的 LexicallyScopedDeclarations 。
返回一个新的空列表 。
DefaultClause :
default
:
StatementList opt
如果 StatementList
存在,则返回 StatementList
的 LexicallyScopedDeclarations 。
返回一个新的空列表 。
LabelledStatement
:
LabelIdentifier
:
LabelledItem
返回 LabelledItem 的
LexicallyScopedDeclarations 。
LabelledItem : Statement
返回一个新的空列表 。
LabelledItem : FunctionDeclaration
返回 « FunctionDeclaration »。
FunctionStatementList
: [空]
返回一个新的空列表 。
FunctionStatementList
: StatementList
返回 StatementList 的
TopLevelLexicallyScopedDeclarations 。
ClassStaticBlockStatementList
: [空]
返回一个新的空列表 。
ClassStaticBlockStatementList
: StatementList
返回 StatementList 的
TopLevelLexicallyScopedDeclarations 。
ConciseBody : ExpressionBody
返回一个新的空列表 。
AsyncConciseBody :
ExpressionBody
返回一个新的空列表 。
Script : [空]
返回一个新的空列表 。
ScriptBody : StatementList
返回 StatementList 的
TopLevelLexicallyScopedDeclarations 。
Module : [空]
返回一个新的空列表 。
ModuleItemList :
ModuleItemList
ModuleItem
令 declarations1 为 ModuleItemList 的 LexicallyScopedDeclarations 。
令 declarations2 为 ModuleItem 的 LexicallyScopedDeclarations 。
返回 declarations1 和 declarations2 的列表连接 。
ModuleItem : ImportDeclaration
返回一个新的空列表 。
ExportDeclaration
:
export
ExportFromClause
FromClause
WithClause opt
;
export
NamedExports
;
export
VariableStatement
返回一个新的空列表 。
ExportDeclaration
:
export
Declaration
返回一个列表 ,其唯一元素是 Declaration 的 DeclarationPart 。
ExportDeclaration
:
export
default
HoistableDeclaration
返回一个列表 ,其唯一元素是 HoistableDeclaration 的 DeclarationPart 。
ExportDeclaration
:
export
default
ClassDeclaration
返回一个列表 ,其唯一元素是 ClassDeclaration 。
ExportDeclaration
:
export
default
AssignmentExpression
;
返回一个列表 ,其唯一元素是这个
ExportDeclaration 。
8.2.6 静态语义:VarDeclaredNames
语法导向操作
VarDeclaredNames 不接受参数,并返回一个字符串列表 。它根据以下产生式分段定义:
Statement :
EmptyStatement
ExpressionStatement
ContinueStatement
BreakStatement
ReturnStatement
ThrowStatement
DebuggerStatement
返回一个新的空列表 。
Block :
{
}
返回一个新的空列表 。
StatementList :
StatementList
StatementListItem
令 names1 为 StatementList 的 VarDeclaredNames 。
令 names2 为 StatementListItem 的 VarDeclaredNames 。
返回 names1 和 names2 的列表连接 。
StatementListItem
: Declaration
返回一个新的空列表 。
VariableStatement
:
var
VariableDeclarationList
;
返回 VariableDeclarationList 的
BoundNames 。
IfStatement :
if
(
Expression
)
Statement
else
Statement
令 names1 为第一个 Statement 的 VarDeclaredNames 。
令 names2 为第二个 Statement 的 VarDeclaredNames 。
返回 names1 和 names2 的列表连接 。
IfStatement :
if
(
Expression
)
Statement
返回 Statement 的 VarDeclaredNames 。
DoWhileStatement :
do
Statement
while
(
Expression
)
;
返回 Statement 的 VarDeclaredNames 。
WhileStatement :
while
(
Expression
)
Statement
返回 Statement 的 VarDeclaredNames 。
ForStatement :
for
(
Expression opt
;
Expression opt
;
Expression opt
)
Statement
返回 Statement 的 VarDeclaredNames 。
ForStatement :
for
(
var
VariableDeclarationList
;
Expression opt
;
Expression opt
)
Statement
令 names1 为 VariableDeclarationList 的
BoundNames 。
令 names2 为 Statement 的 VarDeclaredNames 。
返回 names1 和 names2 的列表连接 。
ForStatement :
for
(
LexicalDeclaration
Expression opt
;
Expression opt
)
Statement
返回 Statement 的 VarDeclaredNames 。
ForInOfStatement :
for
(
LeftHandSideExpression
in
Expression
)
Statement
for
(
ForDeclaration
in
Expression
)
Statement
for
(
LeftHandSideExpression
of
AssignmentExpression
)
Statement
for
(
ForDeclaration
of
AssignmentExpression
)
Statement
for
await
(
LeftHandSideExpression
of
AssignmentExpression
)
Statement
for
await
(
ForDeclaration
of
AssignmentExpression
)
Statement
返回 Statement 的 VarDeclaredNames 。
ForInOfStatement :
for
(
var
ForBinding
in
Expression
)
Statement
for
(
var
ForBinding
of
AssignmentExpression
)
Statement
for
await
(
var
ForBinding
of
AssignmentExpression
)
Statement
令 names1 为 ForBinding 的 BoundNames 。
令 names2 为 Statement 的 VarDeclaredNames 。
返回 names1 和 names2 的列表连接 。
注
WithStatement :
with
(
Expression
)
Statement
返回 Statement 的 VarDeclaredNames 。
SwitchStatement :
switch
(
Expression
)
CaseBlock
返回 CaseBlock 的 VarDeclaredNames 。
CaseBlock :
{
}
返回一个新的空列表 。
CaseBlock :
{
CaseClauses opt
DefaultClause
CaseClauses opt
}
如果第一个 CaseClauses 存在,令
names1 为第一个 CaseClauses 的 VarDeclaredNames 。
否则,令 names1 为一个新的空列表 。
令 names2 为 DefaultClause 的 VarDeclaredNames 。
如果第二个 CaseClauses 存在,令
names3 为第二个 CaseClauses 的 VarDeclaredNames 。
否则,令 names3 为一个新的空列表 。
返回 names1 、names2 和 names3 的列表连接 。
CaseClauses :
CaseClauses
CaseClause
令 names1 为 CaseClauses 的 VarDeclaredNames 。
令 names2 为 CaseClause 的 VarDeclaredNames 。
返回 names1 和 names2 的列表连接 。
CaseClause :
case
Expression
:
StatementList opt
如果 StatementList
存在,则返回 StatementList
的 VarDeclaredNames 。
返回一个新的空列表 。
DefaultClause :
default
:
StatementList opt
如果 StatementList
存在,则返回 StatementList
的 VarDeclaredNames 。
返回一个新的空列表 。
LabelledStatement
:
LabelIdentifier
:
LabelledItem
返回 LabelledItem 的
VarDeclaredNames 。
LabelledItem : FunctionDeclaration
返回一个新的空列表 。
TryStatement :
try
Block
Catch
令 names1 为 Block 的
VarDeclaredNames 。
令 names2 为 Catch 的
VarDeclaredNames 。
返回 names1 和 names2 的列表连接 。
TryStatement :
try
Block
Finally
令 names1 为 Block 的
VarDeclaredNames 。
令 names2 为 Finally 的 VarDeclaredNames 。
返回 names1 和 names2 的列表连接 。
TryStatement :
try
Block
Catch
Finally
令 names1 为 Block 的
VarDeclaredNames 。
令 names2 为 Catch 的
VarDeclaredNames 。
令 names3 为 Finally 的 VarDeclaredNames 。
返回 names1 、names2 和 names3 的列表连接 。
Catch :
catch
(
CatchParameter
)
Block
返回 Block 的 VarDeclaredNames 。
FunctionStatementList
: [空]
返回一个新的空列表 。
FunctionStatementList
: StatementList
返回 StatementList 的
TopLevelVarDeclaredNames 。
ClassStaticBlockStatementList
: [空]
返回一个新的空列表 。
ClassStaticBlockStatementList
: StatementList
返回 StatementList 的
TopLevelVarDeclaredNames 。
ConciseBody : ExpressionBody
返回一个新的空列表 。
AsyncConciseBody :
ExpressionBody
返回一个新的空列表 。
Script : [空]
返回一个新的空列表 。
ScriptBody : StatementList
返回 StatementList 的
TopLevelVarDeclaredNames 。
ModuleItemList :
ModuleItemList
ModuleItem
令 names1 为 ModuleItemList 的 VarDeclaredNames 。
令 names2 为 ModuleItem 的 VarDeclaredNames 。
返回 names1 和 names2 的列表连接 。
ModuleItem : ImportDeclaration
返回一个新的空列表 。
ModuleItem : ExportDeclaration
如果 ExportDeclaration 是
export
VariableStatement ,则返回 ExportDeclaration 的
BoundNames 。
返回一个新的空列表 。
8.2.7 静态语义:VarScopedDeclarations
语法导向操作
VarScopedDeclarations 不接受参数,返回一个包含
解析节点 的
列表 。它针对以下产生式分段定义:
Statement :
EmptyStatement
ExpressionStatement
ContinueStatement
BreakStatement
ReturnStatement
ThrowStatement
DebuggerStatement
返回一个新的空列表 。
Block :
{
}
返回一个新的空列表 。
StatementList :
StatementList
StatementListItem
令 declarations1 为 StatementList 的 VarScopedDeclarations 。
令 declarations2 为 StatementListItem 的 VarScopedDeclarations 。
返回 declarations1 和 declarations2 的 列表连接 。
StatementListItem
: Declaration
返回一个新的空列表 。
VariableDeclarationList
: VariableDeclaration
返回 « VariableDeclaration »。
VariableDeclarationList
:
VariableDeclarationList
,
VariableDeclaration
令 declarations1 为 VariableDeclarationList 的
VarScopedDeclarations 。
返回 declarations1 和 « VariableDeclaration » 的
列表连接 。
IfStatement :
if
(
Expression
)
Statement
else
Statement
令 declarations1 为第一个 Statement 的 VarScopedDeclarations 。
令 declarations2 为第二个 Statement 的 VarScopedDeclarations 。
返回 declarations1 和 declarations2 的 列表连接 。
IfStatement :
if
(
Expression
)
Statement
返回 Statement 的 VarScopedDeclarations 。
DoWhileStatement :
do
Statement
while
(
Expression
)
;
返回 Statement 的 VarScopedDeclarations 。
WhileStatement :
while
(
Expression
)
Statement
返回 Statement 的 VarScopedDeclarations 。
ForStatement :
for
(
Expression opt
;
Expression opt
;
Expression opt
)
Statement
返回 Statement 的 VarScopedDeclarations 。
ForStatement :
for
(
var
VariableDeclarationList
;
Expression opt
;
Expression opt
)
Statement
令 declarations1 为 VariableDeclarationList 的
VarScopedDeclarations 。
令 declarations2 为 Statement 的 VarScopedDeclarations 。
返回 declarations1 和 declarations2 的 列表连接 。
ForStatement :
for
(
LexicalDeclaration
Expression opt
;
Expression opt
)
Statement
返回 Statement 的 VarScopedDeclarations 。
ForInOfStatement :
for
(
LeftHandSideExpression
in
Expression
)
Statement
for
(
ForDeclaration
in
Expression
)
Statement
for
(
LeftHandSideExpression
of
AssignmentExpression
)
Statement
for
(
ForDeclaration
of
AssignmentExpression
)
Statement
for
await
(
LeftHandSideExpression
of
AssignmentExpression
)
Statement
for
await
(
ForDeclaration
of
AssignmentExpression
)
Statement
返回 Statement 的 VarScopedDeclarations 。
ForInOfStatement :
for
(
var
ForBinding
in
Expression
)
Statement
for
(
var
ForBinding
of
AssignmentExpression
)
Statement
for
await
(
var
ForBinding
of
AssignmentExpression
)
Statement
令 declarations1 为 « ForBinding »。
令 declarations2 为 Statement 的 VarScopedDeclarations 。
返回 declarations1 和 declarations2 的 列表连接 。
注
WithStatement :
with
(
Expression
)
Statement
返回 Statement 的 VarScopedDeclarations 。
SwitchStatement :
switch
(
Expression
)
CaseBlock
返回 CaseBlock 的 VarScopedDeclarations 。
CaseBlock :
{
}
返回一个新的空列表 。
CaseBlock :
{
CaseClauses opt
DefaultClause
CaseClauses opt
}
如果第一个 CaseClauses 存在,令
declarations1 为第一个 CaseClauses 的 VarScopedDeclarations 。
否则,令 declarations1 为一个新的空列表 。
令 declarations2 为 DefaultClause 的 VarScopedDeclarations 。
如果第二个 CaseClauses 存在,令
declarations3 为第二个 CaseClauses 的 VarScopedDeclarations 。
否则,令 declarations3 为一个新的空列表 。
返回 declarations1 、declarations2 和 declarations3 的
列表连接 。
CaseClauses :
CaseClauses
CaseClause
令 declarations1 为 CaseClauses 的 VarScopedDeclarations 。
令 declarations2 为 CaseClause 的 VarScopedDeclarations 。
返回 declarations1 和 declarations2 的 列表连接 。
CaseClause :
case
Expression
:
StatementList opt
如果 StatementList
存在,返回 StatementList 的
VarScopedDeclarations 。
返回一个新的空列表 。
DefaultClause :
default
:
StatementList opt
如果 StatementList
存在,返回 StatementList 的
VarScopedDeclarations 。
返回一个新的空列表 。
LabelledStatement
:
LabelIdentifier
:
LabelledItem
返回 LabelledItem 的
VarScopedDeclarations 。
LabelledItem : FunctionDeclaration
返回一个新的空列表 。
TryStatement :
try
Block
Catch
令 declarations1 为 Block 的 VarScopedDeclarations 。
令 declarations2 为 Catch 的 VarScopedDeclarations 。
返回 declarations1 和 declarations2 的 列表连接 。
TryStatement :
try
Block
Finally
令 declarations1 为 Block 的 VarScopedDeclarations 。
令 declarations2 为 Finally 的 VarScopedDeclarations 。
返回 declarations1 和 declarations2 的 列表连接 。
TryStatement :
try
Block
Catch
Finally
令 declarations1 为 Block 的 VarScopedDeclarations 。
令 declarations2 为 Catch 的 VarScopedDeclarations 。
令 declarations3 为 Finally 的 VarScopedDeclarations 。
返回 declarations1 、declarations2 和 declarations3 的
列表连接 。
Catch :
catch
(
CatchParameter
)
Block
返回 Block 的 VarScopedDeclarations 。
FunctionStatementList
: [空]
返回一个新的空 列表 。
FunctionStatementList
: StatementList
返回 StatementList 的
TopLevelVarScopedDeclarations 。
ClassStaticBlockStatementList
: [空]
返回一个新的空 列表 。
ClassStaticBlockStatementList
: StatementList
返回 StatementList 的
TopLevelVarScopedDeclarations 。
ConciseBody : ExpressionBody
返回一个新的空 列表 。
AsyncConciseBody :
ExpressionBody
返回一个新的空 列表 。
Script : [空]
返回一个新的空 列表 。
ScriptBody : StatementList
返回 StatementList 的
TopLevelVarScopedDeclarations 。
Module : [空]
返回一个新的空 列表 。
ModuleItemList :
ModuleItemList
ModuleItem
令 declarations1 为 ModuleItemList 的 VarScopedDeclarations 。
令 declarations2 为 ModuleItem 的 VarScopedDeclarations 。
返回 declarations1 和 declarations2 的 列表连接 。
ModuleItem : ImportDeclaration
返回一个新的空 列表 。
ModuleItem : ExportDeclaration
如果 ExportDeclaration 是
export
VariableStatement ,返回 VariableStatement 的
VarScopedDeclarations 。
返回一个新的空 列表 。
8.2.8 静态语义:TopLevelLexicallyDeclaredNames
语法导向操作
TopLevelLexicallyDeclaredNames 不接受参数并返回一个字符串的 列表 。它在以下产生式上分段定义:
StatementList :
StatementList
StatementListItem
令 names1 为 StatementList 的 TopLevelLexicallyDeclaredNames 。
令 names2 为 StatementListItem 的 TopLevelLexicallyDeclaredNames 。
返回 names1 和 names2 的 列表连接 。
StatementListItem
: Statement
返回一个新的空 列表 。
StatementListItem
: Declaration
如果 Declaration 是
Declaration
: HoistableDeclaration
,那么
返回一个新的空 列表 。
返回 Declaration 的
BoundNames 。
注意
在函数或脚本的顶层,函数声明被当作 var 声明处理,而不是词法声明。
8.2.9 静态语义:TopLevelLexicallyScopedDeclarations
语法导向操作
TopLevelLexicallyScopedDeclarations 不接受参数并返回一个 解析节点 的 列表 。它在以下产生式上分段定义:
StatementList :
StatementList
StatementListItem
令 declarations1 为 StatementList 的 TopLevelLexicallyScopedDeclarations 。
令 declarations2 为 StatementListItem 的 TopLevelLexicallyScopedDeclarations 。
返回 declarations1 和 declarations2 的 列表连接 。
StatementListItem
: Statement
返回一个新的空 列表 。
StatementListItem
: Declaration
如果 Declaration 是
Declaration
: HoistableDeclaration
,那么
返回一个新的空 列表 。
返回 « Declaration »。
8.2.10 静态语义:TopLevelVarDeclaredNames
语法导向操作
TopLevelVarDeclaredNames 不接受参数并返回一个字符串的 列表 。它在以下产生式上分段定义:
StatementList :
StatementList
StatementListItem
令 names1 为 StatementList 的 TopLevelVarDeclaredNames 。
令 names2 为 StatementListItem 的 TopLevelVarDeclaredNames 。
返回 names1 和 names2 的 列表连接 。
StatementListItem
: Declaration
如果 Declaration 是
Declaration
: HoistableDeclaration
,那么
返回 HoistableDeclaration 的
BoundNames 。
返回一个新的空 列表 。
StatementListItem
: Statement
如果 Statement 是
Statement :
LabelledStatement
,返回 Statement 的 TopLevelVarDeclaredNames 。
返回 Statement 的 VarDeclaredNames 。
注意
在函数或脚本的顶层,内部函数声明被当作 var 声明处理。
LabelledStatement
:
LabelIdentifier
:
LabelledItem
返回 LabelledItem 的
TopLevelVarDeclaredNames 。
LabelledItem : Statement
如果 Statement 是
Statement :
LabelledStatement
,返回 Statement 的 TopLevelVarDeclaredNames 。
返回 Statement 的 VarDeclaredNames 。
LabelledItem : FunctionDeclaration
返回 FunctionDeclaration 的 BoundNames 。
8.2.11 静态语义:TopLevelVarScopedDeclarations
语法导向操作
TopLevelVarScopedDeclarations 不接受参数并返回一个 解析节点 的 列表 。它在以下产生式上分段定义:
StatementList :
StatementList
StatementListItem
令 declarations1 为 StatementList 的 TopLevelVarScopedDeclarations 。
令 declarations2 为 StatementListItem 的 TopLevelVarScopedDeclarations 。
返回 declarations1 和 declarations2 的 列表连接 。
StatementListItem
: Statement
如果 Statement 是
Statement :
LabelledStatement
,返回 Statement 的 TopLevelVarScopedDeclarations 。
返回 Statement 的 VarScopedDeclarations 。
StatementListItem
: Declaration
如果 Declaration 是
Declaration
: HoistableDeclaration
,那么
令 declaration 为 HoistableDeclaration 的
DeclarationPart 。
返回 « declaration »。
返回一个新的空 列表 。
LabelledStatement
:
LabelIdentifier
:
LabelledItem
返回 LabelledItem 的
TopLevelVarScopedDeclarations 。
LabelledItem : Statement
如果 Statement 是
Statement :
LabelledStatement
,返回 Statement 的 TopLevelVarScopedDeclarations 。
返回 Statement 的 VarScopedDeclarations 。
LabelledItem : FunctionDeclaration
返回 « FunctionDeclaration »。
8.3 标签
8.3.1 静态语义:ContainsDuplicateLabels
语法导向操作
ContainsDuplicateLabels 接受参数 labelSet (一个字符串的 列表 )并返回一个布尔值。它在以下产生式上分段定义:
Statement :
VariableStatement
EmptyStatement
ExpressionStatement
ContinueStatement
BreakStatement
ReturnStatement
ThrowStatement
DebuggerStatement
Block :
{
}
StatementListItem
:
Declaration
返回 false 。
StatementList :
StatementList
StatementListItem
令 hasDuplicates 为以参数 labelSet 调用 StatementList 的 ContainsDuplicateLabels 。
如果 hasDuplicates 是 true ,返回 true 。
返回以参数 labelSet 调用 StatementListItem 的 ContainsDuplicateLabels 。
IfStatement :
if
(
Expression
)
Statement
else
Statement
令 hasDuplicate 为以参数 labelSet 调用第一个 Statement 的 ContainsDuplicateLabels 。
如果 hasDuplicate 是 true ,返回 true 。
返回以参数 labelSet 调用第二个 Statement 的 ContainsDuplicateLabels 。
IfStatement :
if
(
Expression
)
Statement
返回以参数 labelSet 调用 Statement 的 ContainsDuplicateLabels 。
DoWhileStatement :
do
Statement
while
(
Expression
)
;
返回以参数 labelSet 调用 Statement 的 ContainsDuplicateLabels 。
WhileStatement :
while
(
Expression
)
Statement
返回以参数 labelSet 调用 Statement 的 ContainsDuplicateLabels 。
ForStatement :
for
(
Expression opt
;
Expression opt
;
Expression opt
)
Statement
for
(
var
VariableDeclarationList
;
Expression opt
;
Expression opt
)
Statement
for
(
LexicalDeclaration
Expression opt
;
Expression opt
)
Statement
返回以参数 labelSet 调用 Statement 的 ContainsDuplicateLabels 。
ForInOfStatement :
for
(
LeftHandSideExpression
in
Expression
)
Statement
for
(
var
ForBinding
in
Expression
)
Statement
for
(
ForDeclaration
in
Expression
)
Statement
for
(
LeftHandSideExpression
of
AssignmentExpression
)
Statement
for
(
var
ForBinding
of
AssignmentExpression
)
Statement
for
(
ForDeclaration
of
AssignmentExpression
)
Statement
for
await
(
LeftHandSideExpression
of
AssignmentExpression
)
Statement
for
await
(
var
ForBinding
of
AssignmentExpression
)
Statement
for
await
(
ForDeclaration
of
AssignmentExpression
)
Statement
返回以参数 labelSet 调用 Statement 的 ContainsDuplicateLabels 。
注意
WithStatement :
with
(
Expression
)
Statement
返回以参数 labelSet 调用 Statement 的 ContainsDuplicateLabels 。
SwitchStatement :
switch
(
Expression
)
CaseBlock
返回以参数 labelSet 调用 CaseBlock 的 ContainsDuplicateLabels 。
CaseBlock :
{
}
返回 false 。
CaseBlock :
{
CaseClauses opt
DefaultClause
CaseClauses opt
}
如果第一个 CaseClauses 存在,那么
如果以参数 labelSet 调用第一个 CaseClauses 的 ContainsDuplicateLabels
是 true ,返回 true 。
如果以参数 labelSet 调用 DefaultClause 的 ContainsDuplicateLabels
是 true ,返回 true 。
如果第二个 CaseClauses
不存在,返回 false 。
返回以参数 labelSet 调用第二个 CaseClauses 的 ContainsDuplicateLabels 。
CaseClauses :
CaseClauses
CaseClause
令 hasDuplicates 为以参数 labelSet 调用 CaseClauses 的 ContainsDuplicateLabels 。
如果 hasDuplicates 是 true ,返回 true 。
返回以参数 labelSet 调用 CaseClause 的 ContainsDuplicateLabels 。
CaseClause :
case
Expression
:
StatementList opt
如果 StatementList
存在,返回以参数 labelSet 调用 StatementList 的 ContainsDuplicateLabels 。
返回 false 。
DefaultClause :
default
:
StatementList opt
如果 StatementList
存在,返回以参数 labelSet 调用 StatementList 的 ContainsDuplicateLabels 。
返回 false 。
LabelledStatement
:
LabelIdentifier
:
LabelledItem
令 label 为 LabelIdentifier 的 StringValue 。
如果 labelSet 包含 label ,返回 true 。
令 newLabelSet 为 labelSet 和 « label » 的 列表连接 。
返回以参数 newLabelSet 调用 LabelledItem 的 ContainsDuplicateLabels 。
LabelledItem : FunctionDeclaration
返回 false 。
TryStatement :
try
Block
Catch
令 hasDuplicates 为以参数 labelSet 调用 Block 的 ContainsDuplicateLabels 。
如果 hasDuplicates 是 true ,返回 true 。
返回以参数 labelSet 调用 Catch 的 ContainsDuplicateLabels 。
TryStatement :
try
Block
Finally
令 hasDuplicates 为以参数 labelSet 调用 Block 的 ContainsDuplicateLabels 。
如果 hasDuplicates 是 true ,返回 true 。
返回以参数 labelSet 调用 Finally 的 ContainsDuplicateLabels 。
TryStatement :
try
Block
Catch
Finally
如果以参数 labelSet 调用 Block 的 ContainsDuplicateLabels
是 true ,返回 true 。
如果以参数 labelSet 调用 Catch 的 ContainsDuplicateLabels
是 true ,返回 true 。
返回以参数 labelSet 调用 Finally 的 ContainsDuplicateLabels 。
Catch :
catch
(
CatchParameter
)
Block
返回以参数 labelSet 调用 Block 的 ContainsDuplicateLabels 。
FunctionStatementList
: [空]
返回 false 。
ClassStaticBlockStatementList
: [空]
返回 false 。
ModuleItemList :
ModuleItemList
ModuleItem
令 hasDuplicates 为以参数 labelSet 调用 ModuleItemList 的 ContainsDuplicateLabels 。
如果 hasDuplicates 是 true ,返回 true 。
返回以参数 labelSet 调用 ModuleItem 的 ContainsDuplicateLabels 。
ModuleItem :
ImportDeclaration
ExportDeclaration
返回 false 。
8.3.2 静态语义:ContainsUndefinedBreakTarget
语法导向操作
ContainsUndefinedBreakTarget 接受参数 labelSet
(一个字符串的 列表 )并返回一个布尔值。它在以下产生式上分段定义:
Statement :
VariableStatement
EmptyStatement
ExpressionStatement
ContinueStatement
ReturnStatement
ThrowStatement
DebuggerStatement
Block :
{
}
StatementListItem
:
Declaration
返回 false 。
StatementList :
StatementList
StatementListItem
令 hasUndefinedLabels 为以参数 labelSet 调用 StatementList 的 ContainsUndefinedBreakTarget 。
如果 hasUndefinedLabels 是 true ,返回 true 。
返回以参数 labelSet 调用 StatementListItem 的 ContainsUndefinedBreakTarget 。
IfStatement :
if
(
Expression
)
Statement
else
Statement
令 hasUndefinedLabels 为以参数 labelSet 调用第一个 Statement 的 ContainsUndefinedBreakTarget 。
如果 hasUndefinedLabels 是 true ,返回 true 。
返回以参数 labelSet 调用第二个 Statement 的 ContainsUndefinedBreakTarget 。
IfStatement :
if
(
Expression
)
Statement
返回以参数 labelSet 调用 Statement 的 ContainsUndefinedBreakTarget 。
DoWhileStatement :
do
Statement
while
(
Expression
)
;
返回以参数 labelSet 调用 Statement 的 ContainsUndefinedBreakTarget 。
WhileStatement :
while
(
Expression
)
Statement
返回以参数 labelSet 调用 Statement 的 ContainsUndefinedBreakTarget 。
ForStatement :
for
(
Expression opt
;
Expression opt
;
Expression opt
)
Statement
for
(
var
VariableDeclarationList
;
Expression opt
;
Expression opt
)
Statement
for
(
LexicalDeclaration
Expression opt
;
Expression opt
)
Statement
返回以参数 labelSet 调用 Statement 的 ContainsUndefinedBreakTarget 。
ForInOfStatement :
for
(
LeftHandSideExpression
in
Expression
)
Statement
for
(
var
ForBinding
in
Expression
)
Statement
for
(
ForDeclaration
in
Expression
)
Statement
for
(
LeftHandSideExpression
of
AssignmentExpression
)
Statement
for
(
var
ForBinding
of
AssignmentExpression
)
Statement
for
(
ForDeclaration
of
AssignmentExpression
)
Statement
for
await
(
LeftHandSideExpression
of
AssignmentExpression
)
Statement
for
await
(
var
ForBinding
of
AssignmentExpression
)
Statement
for
await
(
ForDeclaration
of
AssignmentExpression
)
Statement
返回以参数 labelSet 调用 Statement 的 ContainsUndefinedBreakTarget 。
注
BreakStatement :
break
;
返回 false 。
BreakStatement :
break
LabelIdentifier
;
如果 labelSet 不包含 LabelIdentifier 的 StringValue ,返回
true 。
返回 false 。
WithStatement :
with
(
Expression
)
Statement
返回以参数 labelSet 调用 Statement 的 ContainsUndefinedBreakTarget 。
SwitchStatement :
switch
(
Expression
)
CaseBlock
返回以参数 labelSet 调用 CaseBlock 的 ContainsUndefinedBreakTarget 。
CaseBlock :
{
}
返回 false 。
CaseBlock :
{
CaseClauses opt
DefaultClause
CaseClauses opt
}
如果第一个 CaseClauses 存在,那么
如果以参数 labelSet 调用第一个 CaseClauses 的 ContainsUndefinedBreakTarget
是 true ,返回 true 。
如果以参数 labelSet 调用 DefaultClause 的 ContainsUndefinedBreakTarget
是 true ,返回 true 。
如果第二个 CaseClauses
不存在,返回 false 。
返回以参数 labelSet 调用第二个 CaseClauses 的 ContainsUndefinedBreakTarget 。
CaseClauses :
CaseClauses
CaseClause
令 hasUndefinedLabels 为以参数 labelSet 调用 CaseClauses 的 ContainsUndefinedBreakTarget 。
如果 hasUndefinedLabels 是 true ,返回 true 。
返回以参数 labelSet 调用 CaseClause 的 ContainsUndefinedBreakTarget 。
CaseClause :
case
Expression
:
StatementList opt
如果 StatementList
存在,返回以参数 labelSet 调用 StatementList 的 ContainsUndefinedBreakTarget 。
返回 false 。
DefaultClause :
default
:
StatementList opt
如果 StatementList
存在,返回以参数 labelSet 调用 StatementList 的 ContainsUndefinedBreakTarget 。
返回 false 。
LabelledStatement
:
LabelIdentifier
:
LabelledItem
令 label 为 LabelIdentifier 的 StringValue 。
令 newLabelSet 为 labelSet 和 « label » 的 列表连接 。
返回以参数 newLabelSet 调用 LabelledItem 的 ContainsUndefinedBreakTarget 。
LabelledItem : FunctionDeclaration
返回 false 。
TryStatement :
try
Block
Catch
令 hasUndefinedLabels 为以参数 labelSet 调用 Block 的 ContainsUndefinedBreakTarget 。
如果 hasUndefinedLabels 是 true ,返回 true 。
返回以参数 labelSet 调用 Catch 的 ContainsUndefinedBreakTarget 。
TryStatement :
try
Block
Finally
令 hasUndefinedLabels 为以参数 labelSet 调用 Block 的 ContainsUndefinedBreakTarget 。
如果 hasUndefinedLabels 是 true ,返回 true 。
返回以参数 labelSet 调用 Finally 的 ContainsUndefinedBreakTarget 。
TryStatement :
try
Block
Catch
Finally
如果以参数 labelSet 调用 Block 的 ContainsUndefinedBreakTarget
是 true ,返回 true 。
如果以参数 labelSet 调用 Catch 的 ContainsUndefinedBreakTarget
是 true ,返回 true 。
返回以参数 labelSet 调用 Finally 的 ContainsUndefinedBreakTarget 。
Catch :
catch
(
CatchParameter
)
Block
返回以参数 labelSet 调用 Block 的 ContainsUndefinedBreakTarget 。
FunctionStatementList
: [empty]
返回 false 。
ClassStaticBlockStatementList
: [empty]
返回 false 。
ModuleItemList :
ModuleItemList
ModuleItem
令 hasUndefinedLabels 为以参数 labelSet 调用 ModuleItemList 的 ContainsUndefinedBreakTarget 。
如果 hasUndefinedLabels 是 true ,返回 true 。
返回以参数 labelSet 调用 ModuleItem 的 ContainsUndefinedBreakTarget 。
ModuleItem :
ImportDeclaration
ExportDeclaration
返回 false 。
8.3.3 静态语义:ContainsUndefinedContinueTarget
语法导向操作
ContainsUndefinedContinueTarget 接受参数
iterationSet (一个字符串的 列表 )和
labelSet (一个字符串的 列表 )并返回一个布尔值。它在以下产生式上分段定义:
Statement :
VariableStatement
EmptyStatement
ExpressionStatement
BreakStatement
ReturnStatement
ThrowStatement
DebuggerStatement
Block :
{
}
StatementListItem
:
Declaration
返回 false 。
Statement : BlockStatement
返回以参数 iterationSet 和 « » 调用 BlockStatement 的 ContainsUndefinedContinueTarget 。
BreakableStatement
: IterationStatement
令 newIterationSet 为 iterationSet 和 labelSet 的 列表连接 。
返回以参数 newIterationSet 和 « » 调用 IterationStatement 的 ContainsUndefinedContinueTarget 。
StatementList :
StatementList
StatementListItem
令 hasUndefinedLabels 为以参数 iterationSet 和 « » 调用 StatementList 的 ContainsUndefinedContinueTarget 。
如果 hasUndefinedLabels 是 true ,返回 true 。
返回以参数 iterationSet 和 « » 调用 StatementListItem 的 ContainsUndefinedContinueTarget 。
IfStatement :
if
(
Expression
)
Statement
else
Statement
令 hasUndefinedLabels 为以参数 iterationSet 和 « » 调用第一个 Statement 的 ContainsUndefinedContinueTarget 。
如果 hasUndefinedLabels 是 true ,返回 true 。
返回以参数 iterationSet 和 « » 调用第二个 Statement 的 ContainsUndefinedContinueTarget 。
IfStatement :
if
(
Expression
)
Statement
返回以参数 iterationSet 和 « » 调用 Statement 的 ContainsUndefinedContinueTarget 。
DoWhileStatement :
do
Statement
while
(
Expression
)
;
返回以参数 iterationSet 和 « » 调用 Statement 的 ContainsUndefinedContinueTarget 。
WhileStatement :
while
(
Expression
)
Statement
返回以参数 iterationSet 和 « » 调用 Statement 的 ContainsUndefinedContinueTarget 。
ForStatement :
for
(
Expression opt
;
Expression opt
;
Expression opt
)
Statement
for
(
var
VariableDeclarationList
;
Expression opt
;
Expression opt
)
Statement
for
(
LexicalDeclaration
Expression opt
;
Expression opt
)
Statement
返回以参数 iterationSet 和 « » 调用 Statement 的 ContainsUndefinedContinueTarget 。
ForInOfStatement :
for
(
LeftHandSideExpression
in
Expression
)
Statement
for
(
var
ForBinding
in
Expression
)
Statement
for
(
ForDeclaration
in
Expression
)
Statement
for
(
LeftHandSideExpression
of
AssignmentExpression
)
Statement
for
(
var
ForBinding
of
AssignmentExpression
)
Statement
for
(
ForDeclaration
of
AssignmentExpression
)
Statement
for
await
(
LeftHandSideExpression
of
AssignmentExpression
)
Statement
for
await
(
var
ForBinding
of
AssignmentExpression
)
Statement
for
await
(
ForDeclaration
of
AssignmentExpression
)
Statement
返回以参数 iterationSet 和 « » 调用 Statement 的 ContainsUndefinedContinueTarget 。
注
ContinueStatement
:
continue
;
返回 false 。
ContinueStatement
:
continue
LabelIdentifier
;
如果 iterationSet 不包含 LabelIdentifier 的 StringValue ,返回
true 。
返回 false 。
WithStatement :
with
(
Expression
)
Statement
返回以参数 iterationSet 和 « » 调用 Statement 的 ContainsUndefinedContinueTarget 。
SwitchStatement :
switch
(
Expression
)
CaseBlock
返回以参数 iterationSet 和 « » 调用 CaseBlock 的 ContainsUndefinedContinueTarget 。
CaseBlock :
{
}
返回 false 。
CaseBlock :
{
CaseClauses opt
DefaultClause
CaseClauses opt
}
如果第一个 CaseClauses 存在,那么
如果以参数 iterationSet 和 « » 调用第一个 CaseClauses 的 ContainsUndefinedContinueTarget
是 true ,返回 true 。
如果以参数 iterationSet 和 « » 调用 DefaultClause 的 ContainsUndefinedContinueTarget
是 true ,返回 true 。
如果第二个 CaseClauses
不存在,返回 false 。
返回以参数 iterationSet 和 « » 调用第二个 CaseClauses 的 ContainsUndefinedContinueTarget 。
CaseClauses :
CaseClauses
CaseClause
令 hasUndefinedLabels 为以参数 iterationSet 和 « » 调用 CaseClauses 的 ContainsUndefinedContinueTarget 。
如果 hasUndefinedLabels 是 true ,返回 true 。
返回以参数 iterationSet 和 « » 调用 CaseClause 的 ContainsUndefinedContinueTarget 。
CaseClause :
case
Expression
:
StatementList opt
如果 StatementList
存在,返回以参数 iterationSet 和 « » 调用 StatementList 的 ContainsUndefinedContinueTarget 。
返回 false 。
DefaultClause :
default
:
StatementList opt
如果 StatementList
存在,返回以参数 iterationSet 和 « » 调用 StatementList 的 ContainsUndefinedContinueTarget 。
返回 false 。
LabelledStatement
:
LabelIdentifier
:
LabelledItem
令 label 为 LabelIdentifier 的 StringValue 。
令 newLabelSet 为 labelSet 和 « label » 的 列表连接 。
返回以参数 iterationSet 和 newLabelSet 调用 LabelledItem 的 ContainsUndefinedContinueTarget 。
LabelledItem : FunctionDeclaration
返回 false 。
TryStatement :
try
Block
Catch
令 hasUndefinedLabels 为以参数 iterationSet 和 « » 调用 Block 的 ContainsUndefinedContinueTarget 。
如果 hasUndefinedLabels 是 true ,返回 true 。
返回以参数 iterationSet 和 « » 调用 Catch 的 ContainsUndefinedContinueTarget 。
TryStatement :
try
Block
Finally
令 hasUndefinedLabels 为以参数 iterationSet 和 « » 调用 Block 的 ContainsUndefinedContinueTarget 。
如果 hasUndefinedLabels 是 true ,返回 true 。
返回以参数 iterationSet 和 « » 调用 Finally 的 ContainsUndefinedContinueTarget 。
TryStatement :
try
Block
Catch
Finally
如果以参数 iterationSet 和 « » 调用 Block 的 ContainsUndefinedContinueTarget
是 true ,返回 true 。
如果以参数 iterationSet 和 « » 调用 Catch 的 ContainsUndefinedContinueTarget
是 true ,返回 true 。
返回以参数 iterationSet 和 « » 调用 Finally 的 ContainsUndefinedContinueTarget 。
Catch :
catch
(
CatchParameter
)
Block
返回以参数 iterationSet 和 « » 调用 Block 的 ContainsUndefinedContinueTarget 。
FunctionStatementList
: [empty]
返回 false 。
ClassStaticBlockStatementList
: [empty]
返回 false 。
ModuleItemList :
ModuleItemList
ModuleItem
令 hasUndefinedLabels 为以参数 iterationSet 和 « » 调用 ModuleItemList 的
ContainsUndefinedContinueTarget 。
如果 hasUndefinedLabels 是 true ,返回 true 。
返回以参数 iterationSet 和 « » 调用 ModuleItem 的 ContainsUndefinedContinueTarget 。
ModuleItem :
ImportDeclaration
ExportDeclaration
返回 false 。
8.4 函数名推断
8.4.1 静态语义:HasName
语法导向操作
HasName 不接受任何参数并返回一个布尔值。它在以下产生式上分段定义:
PrimaryExpression
: CoverParenthesizedExpressionAndArrowParameterList
令 expr 为被 CoverParenthesizedExpressionAndArrowParameterList
覆盖 的 ParenthesizedExpression 。
如果 expr 的 IsFunctionDefinition
是 false ,返回 false 。
返回 expr 的 HasName 。
FunctionExpression
:
function
(
FormalParameters
)
{
FunctionBody
}
GeneratorExpression
:
function
*
(
FormalParameters
)
{
GeneratorBody
}
AsyncGeneratorExpression
:
async
function
*
(
FormalParameters
)
{
AsyncGeneratorBody
}
AsyncFunctionExpression
:
async
function
(
FormalParameters
)
{
AsyncFunctionBody
}
ArrowFunction :
ArrowParameters
=>
ConciseBody
AsyncArrowFunction
:
async
AsyncArrowBindingIdentifier
=>
AsyncConciseBody
CoverCallExpressionAndAsyncArrowHead
=>
AsyncConciseBody
ClassExpression :
class
ClassTail
返回 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
返回 true 。
8.4.2 静态语义:IsFunctionDefinition
语法导向操作
IsFunctionDefinition 不接受任何参数并返回一个布尔值。它在以下产生式上分段定义:
PrimaryExpression
: CoverParenthesizedExpressionAndArrowParameterList
令 expr 为被 CoverParenthesizedExpressionAndArrowParameterList
覆盖 的 ParenthesizedExpression 。
返回 expr 的 IsFunctionDefinition 。
PrimaryExpression
:
this
IdentifierReference
Literal
ArrayLiteral
ObjectLiteral
RegularExpressionLiteral
TemplateLiteral
MemberExpression :
MemberExpression
[
Expression
]
MemberExpression
.
IdentifierName
MemberExpression
TemplateLiteral
SuperProperty
MetaProperty
new
MemberExpression
Arguments
MemberExpression
.
PrivateIdentifier
NewExpression :
new
NewExpression
LeftHandSideExpression
:
CallExpression
OptionalExpression
UpdateExpression :
LeftHandSideExpression
++
LeftHandSideExpression
--
++
UnaryExpression
--
UnaryExpression
UnaryExpression :
delete
UnaryExpression
void
UnaryExpression
typeof
UnaryExpression
+
UnaryExpression
-
UnaryExpression
~
UnaryExpression
!
UnaryExpression
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
返回 false 。
AssignmentExpression
:
ArrowFunction
AsyncArrowFunction
FunctionExpression
:
function
BindingIdentifier opt
(
FormalParameters
)
{
FunctionBody
}
GeneratorExpression
:
function
*
BindingIdentifier opt
(
FormalParameters
)
{
GeneratorBody
}
AsyncGeneratorExpression
:
async
function
*
BindingIdentifier opt
(
FormalParameters
)
{
AsyncGeneratorBody
}
AsyncFunctionExpression
:
async
function
BindingIdentifier opt
(
FormalParameters
)
{
AsyncFunctionBody
}
ClassExpression :
class
BindingIdentifier opt
ClassTail
返回 true 。
8.4.3 静态语义:IsAnonymousFunctionDefinition (
expr )
抽象操作 IsAnonymousFunctionDefinition 接受参数 expr (一个 AssignmentExpression
解析节点 、一个 Initializer 解析节点 ,或一个 Expression 解析节点 )并返回一个布尔值。它确定其参数是否为不绑定名称的函数定义。当被调用时执行以下步骤:
如果 expr 的 IsFunctionDefinition
是 false ,返回 false 。
令 hasName 为 expr 的 HasName 。
如果 hasName 是 true ,返回 false 。
返回 true 。
8.4.4 静态语义:IsIdentifierRef
语法导向操作
IsIdentifierRef 不接受任何参数并返回一个布尔值。它在以下产生式上分段定义:
PrimaryExpression
: IdentifierReference
返回 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
返回 false 。
8.4.5 运行时语义:NamedEvaluation
语法导向操作
NamedEvaluation 接受参数 name (一个 属性键 或一个 私有名称 )并返回要么 包含 函数对象 的正常完成,要么 中断完成 。它在以下产生式上分段定义:
PrimaryExpression
: CoverParenthesizedExpressionAndArrowParameterList
令 expr 为被 CoverParenthesizedExpressionAndArrowParameterList
覆盖 的 ParenthesizedExpression 。
返回 ? expr 以参数 name 执行的 NamedEvaluation 。
ParenthesizedExpression
:
(
Expression
)
断言 :
IsAnonymousFunctionDefinition (Expression ) 是
true 。
返回 ? Expression 以参数
name 执行的 NamedEvaluation 。
FunctionExpression
:
function
(
FormalParameters
)
{
FunctionBody
}
返回 FunctionExpression 以参数
name 执行的 InstantiateOrdinaryFunctionExpression 。
GeneratorExpression
:
function
*
(
FormalParameters
)
{
GeneratorBody
}
返回 GeneratorExpression 以参数
name 执行的 InstantiateGeneratorFunctionExpression 。
AsyncGeneratorExpression
:
async
function
*
(
FormalParameters
)
{
AsyncGeneratorBody
}
返回 AsyncGeneratorExpression 以参数
name 执行的 InstantiateAsyncGeneratorFunctionExpression 。
AsyncFunctionExpression
:
async
function
(
FormalParameters
)
{
AsyncFunctionBody
}
返回 AsyncFunctionExpression 以参数
name 执行的 InstantiateAsyncFunctionExpression 。
ArrowFunction :
ArrowParameters
=>
ConciseBody
返回 ArrowFunction 以参数
name 执行的 InstantiateArrowFunctionExpression 。
AsyncArrowFunction
:
async
AsyncArrowBindingIdentifier
=>
AsyncConciseBody
CoverCallExpressionAndAsyncArrowHead
=>
AsyncConciseBody
返回 AsyncArrowFunction 以参数
name 执行的 InstantiateAsyncArrowFunctionExpression 。
ClassExpression :
class
ClassTail
令 value 为 ? ClassTail 以参数
undefined 和 name 执行的 ClassDefinitionEvaluation 。
设置 value .[[SourceText]] 为 ClassExpression 匹配的源文本 。
返回 value 。
8.5 包含 (Contains)
8.5.1 静态语义:包含 (Contains)
语法导向操作 包含
(Contains) 接受参数 symbol (一个语法符号) 并返回一个布尔值。
本规范中所有未在下面列出的语法产生式备选都隐式具有以下 包含 (Contains) 的默认定义:
对于此 解析节点 的每个子节点 child ,执行:
如果 child 是 symbol 的实例,返回 true 。
如果 child 是一个非终结符的实例,则:
令 contained 为 child 包含
symbol 的结果。
如果 contained 为 true ,返回
true 。
返回 false 。
函数声明
:
function
绑定标识符
(
形式参数
)
{
函数体
}
function
(
形式参数
)
{
函数体
}
函数表达式
:
function
绑定标识符 opt
(
形式参数
)
{
函数体
}
生成器声明
:
function
*
绑定标识符
(
形式参数
)
{
生成器体
}
function
*
(
形式参数
)
{
生成器体
}
生成器表达式
:
function
*
绑定标识符 opt
(
形式参数
)
{
生成器体
}
异步生成器声明
:
async
function
*
绑定标识符
(
形式参数
)
{
异步生成器体
}
async
function
*
(
形式参数
)
{
异步生成器体
}
异步生成器表达式
:
async
function
*
绑定标识符 opt
(
形式参数
)
{
异步生成器体
}
异步函数声明
:
async
function
绑定标识符
(
形式参数
)
{
异步函数体
}
async
function
(
形式参数
)
{
异步函数体
}
异步函数表达式
:
async
function
绑定标识符 opt
(
形式参数
)
{
异步函数体
}
返回 false 。
注 1
类尾 :
类继承 opt
{
类体
}
如果 symbol 是 类体 ,返回 true 。
如果 symbol 是 类继承 ,则:
如果 类继承 存在,返回
true ;否则返回 false 。
如果 类继承 存在,则:
如果 类继承
包含
symbol 为 true ,返回 true 。
返回以 symbol 为参数的 类体 的 计算属性包含 的结果。
注 2
依赖于子结构的静态语义规则通常不深入类体,除了 属性名 。
类静态块 :
static
{
类静态块体
}
返回 false 。
注 3
依赖于子结构的静态语义规则通常不深入 static
初始化块。
箭头函数 :
箭头参数
=>
简洁体
如果 symbol 不是 NewTarget 、SuperProperty 、SuperCall 、super
或
this
之一,返回 false 。
如果 箭头参数 包含 symbol 为
true ,返回 true 。
返回 简洁体 包含 symbol 。
箭头参数 :
覆盖带括号的表达式和箭头参数列表
令 formals 为被 覆盖带括号的表达式和箭头参数列表
覆盖 的 箭头形式参数 。
返回 formals 包含 symbol 。
异步箭头函数
:
async
异步箭头绑定标识符
=>
异步简洁体
如果 symbol 不是 NewTarget 、SuperProperty 、SuperCall 、super
或
this
之一,返回 false 。
返回 异步简洁体 包含 symbol 。
异步箭头函数
:
覆盖调用表达式和异步箭头头部
=>
异步简洁体
如果 symbol 不是 NewTarget 、SuperProperty 、SuperCall 、super
或
this
之一,返回 false 。
令 head 为被 覆盖调用表达式和异步箭头头部
覆盖 的 异步箭头头部 。
如果 head 包含 symbol 为
true ,返回 true 。
返回 异步简洁体 包含 symbol 。
注 4
包含 (Contains) 用于检测 箭头函数 或 异步箭头函数 中
new.target
、this
和 super
的使用情况。
属性定义
: 方法定义
如果 symbol 是 方法定义 ,返回 true 。
返回以 symbol 为参数的 方法定义 的 计算属性包含 的结果。
字面量属性名
: 标识符名称
返回 false 。
成员表达式 :
成员表达式
.
标识符名称
如果 成员表达式 包含 symbol 为
true ,返回 true 。
返回 false 。
Super属性 :
super
.
标识符名称
如果 symbol 是 保留字 super
,返回
true 。
返回 false 。
调用表达式 :
调用表达式
.
标识符名称
如果 调用表达式 包含 symbol 为
true ,返回 true 。
返回 false 。
可选链 :
?.
标识符名称
返回 false 。
可选链 :
可选链
.
标识符名称
如果 可选链 包含 symbol 为
true ,返回 true 。
返回 false 。
8.5.2 静态语义:计算属性包含 (ComputedPropertyContains)
语法导向操作
计算属性包含 (ComputedPropertyContains) 接受参数 symbol (一个语法符号) 并返回一个布尔值。它在以下产生式中分段定义:
类元素名称 :
私有标识符
属性名 : 字面量属性名
返回 false 。
属性名 : 计算属性名
返回 计算属性名
包含 symbol 的结果。
方法定义 :
类元素名称
(
唯一形式参数
)
{
函数体
}
get
类元素名称
(
)
{
函数体
}
set
类元素名称
(
属性设置器参数列表
)
{
函数体
}
返回以 symbol 为参数的 类元素名称 的 计算属性包含 的结果。
生成器方法 :
*
类元素名称
(
唯一形式参数
)
{
生成器体
}
返回以 symbol 为参数的 类元素名称 的 计算属性包含 的结果。
异步生成器方法
:
async
*
类元素名称
(
唯一形式参数
)
{
异步生成器体
}
返回以 symbol 为参数的 类元素名称 的 计算属性包含 的结果。
类元素列表 :
类元素列表
类元素
令 inList 为以 symbol 为参数的 类元素列表 的 计算属性包含 。
如果 inList 为 true ,返回 true 。
返回以 symbol 为参数的 类元素 的 计算属性包含 的结果。
类元素 : 类静态块
返回 false 。
类元素 : ;
返回 false 。
异步方法 :
async
类元素名称
(
唯一形式参数
)
{
异步函数体
}
返回以 symbol 为参数的 类元素名称 的 计算属性包含 的结果。
字段定义 :
类元素名称
初始化器 opt
返回以 symbol 为参数的 类元素名称 的 计算属性包含 的结果。
8.6 杂项
这些操作在规范中的多个地方使用。
8.6.1 运行时语义:InstantiateFunctionObject
语法导向操作
InstantiateFunctionObject 接收参数 env (一个 环境记录 ) 和
privateEnv (一个 私有环境记录 或 null ),并返回一个
ECMAScript 函数对象 。它在以下产生式上分段定义:
FunctionDeclaration
:
function
BindingIdentifier
(
FormalParameters
)
{
FunctionBody
}
function
(
FormalParameters
)
{
FunctionBody
}
返回 InstantiateOrdinaryFunctionObject ,其参数为
FunctionDeclaration ,以及参数
env 和 privateEnv 。
GeneratorDeclaration
:
function
*
BindingIdentifier
(
FormalParameters
)
{
GeneratorBody
}
function
*
(
FormalParameters
)
{
GeneratorBody
}
返回 InstantiateGeneratorFunctionObject ,其参数为
GeneratorDeclaration ,以及参数
env 和 privateEnv 。
AsyncGeneratorDeclaration
:
async
function
*
BindingIdentifier
(
FormalParameters
)
{
AsyncGeneratorBody
}
async
function
*
(
FormalParameters
)
{
AsyncGeneratorBody
}
返回 InstantiateAsyncGeneratorFunctionObject ,其参数为
AsyncGeneratorDeclaration ,以及参数
env 和 privateEnv 。
AsyncFunctionDeclaration
:
async
function
BindingIdentifier
(
FormalParameters
)
{
AsyncFunctionBody
}
async
function
(
FormalParameters
)
{
AsyncFunctionBody
}
返回 InstantiateAsyncFunctionObject ,其参数为
AsyncFunctionDeclaration ,以及参数
env 和 privateEnv 。
8.6.2 运行时语义:BindingInitialization
语法导向操作
BindingInitialization 接受参数 value (一个 ECMAScript 语言值 )和
environment (一个 环境记录 或
undefined ),并返回一个
包含
unused 的正常完成,或者一个 异常完成 。
注意
undefined 作为 environment 传递,以指示应使用 PutValue
操作来分配初始化值。对于 var
语句和某些 非严格函数
的形式参数列表(参见 10.2.11 )就是这种情况。在这些情况下,词法绑定会在其初始化程序的评估之前被提升和预初始化。
它在以下产生式上分段定义:
BindingIdentifier
: Identifier
令 name 为 Identifier 的 StringValue 。
返回 ? InitializeBoundName (name ,
value , environment ).
BindingIdentifier
: yield
返回 ? InitializeBoundName ("yield" ,
value , environment ).
BindingIdentifier
: await
返回 ? InitializeBoundName ("await" ,
value , environment ).
BindingPattern :
ObjectBindingPattern
执行 ? RequireObjectCoercible (value ).
返回 ? BindingInitialization (ObjectBindingPattern with
arguments value 和 environment .
BindingPattern :
ArrayBindingPattern
令 iteratorRecord 为 ? GetIterator (value ,
sync ).
令 result 为 Completion (IteratorBindingInitialization of ArrayBindingPattern
with arguments iteratorRecord 和 environment ).
如果 iteratorRecord .[[Done]] 为
false ,则返回 ? IteratorClose (iteratorRecord ,
result ).
返回 ? result .
ObjectBindingPattern
:
{
}
返回 unused .
ObjectBindingPattern
:
{
BindingPropertyList
}
{
BindingPropertyList
,
}
执行 ? PropertyBindingInitialization (BindingPropertyList
with arguments value 和 environment .
返回 unused .
ObjectBindingPattern
:
{
BindingRestProperty
}
令 excludedNames 为一个新的空 列表 。
返回 ? RestBindingInitialization (BindingRestProperty
with arguments value , environment , 和 excludedNames .
ObjectBindingPattern
:
{
BindingPropertyList
,
BindingRestProperty
}
令 excludedNames 为 ? PropertyBindingInitialization (BindingPropertyList
with arguments value 和 environment .
返回 ? RestBindingInitialization (BindingRestProperty
with arguments value , environment , 和 excludedNames .
8.6.2.1 InitializeBoundName ( name , value ,
environment )
抽象操作 InitializeBoundName 接受参数 name (一个字符串)、value (一个
ECMAScript 语言值 )和
environment (一个 环境记录 或
undefined ),并返回一个
包含
unused 的正常完成,或者一个 异常完成 。调用时,它执行以下步骤:
如果 environment 不是 undefined ,则:
执行 ! environment .InitializeBinding(name ,
value ).
返回 unused .
否则:
令 lhs 为 ? ResolveBinding (name ).
返回 ? PutValue (lhs ,
value ).
8.6.3 运行时语义:IteratorBindingInitialization
语法导向操作
IteratorBindingInitialization 接受参数
iteratorRecord (一个迭代器记录 )和 environment
(一个环境记录 或
undefined ),并返回包含
unused 的正常完成 或异常完成 。
注
当 environment 传递 undefined 时,表示应该使用PutValue
操作来分配初始化值。这是非严格函数 的形式参数列表的情况。在这种情况下,形式参数绑定被预初始化,以处理具有相同名称的多个参数的可能性。
它在以下产生式上分段定义:
ArrayBindingPattern
:
[
]
返回 unused 。
ArrayBindingPattern
:
[
Elision
]
返回 ? IteratorDestructuringAssignmentEvaluation of
Elision with argument
iteratorRecord 。
ArrayBindingPattern
:
[
Elision opt
BindingRestElement
]
如果 Elision 存在,则
执行 ? IteratorDestructuringAssignmentEvaluation
of Elision with
argument iteratorRecord 。
返回 ? IteratorBindingInitialization of BindingRestElement
with arguments iteratorRecord and environment 。
ArrayBindingPattern
:
[
BindingElementList
,
Elision
]
执行 ? IteratorBindingInitialization of BindingElementList
with arguments iteratorRecord and environment 。
返回 ? IteratorDestructuringAssignmentEvaluation of
Elision with argument
iteratorRecord 。
ArrayBindingPattern
:
[
BindingElementList
,
Elision opt
BindingRestElement
]
执行 ? IteratorBindingInitialization of BindingElementList
with arguments iteratorRecord and environment 。
如果 Elision 存在,则
执行 ? IteratorDestructuringAssignmentEvaluation
of Elision with
argument iteratorRecord 。
返回 ? IteratorBindingInitialization of BindingRestElement
with arguments iteratorRecord and environment 。
BindingElementList
:
BindingElementList
,
BindingElisionElement
执行 ? IteratorBindingInitialization of BindingElementList
with arguments iteratorRecord and environment 。
返回 ? IteratorBindingInitialization of BindingElisionElement with
arguments iteratorRecord and environment 。
BindingElisionElement
:
Elision
BindingElement
执行 ? IteratorDestructuringAssignmentEvaluation of
Elision with argument
iteratorRecord 。
返回 ? IteratorBindingInitialization of BindingElement with
arguments iteratorRecord and environment 。
SingleNameBinding
:
BindingIdentifier
Initializer opt
设 bindingId 为 BindingIdentifier 的StringValue 。
设 lhs 为 ? ResolveBinding (bindingId ,
environment )。
设 v 为 undefined 。
如果 iteratorRecord .[[Done]] 是
false ,则
设 next 为 ? IteratorStepValue (iteratorRecord )。
如果 next 不是 done ,则
设置 v 为 next 。
如果 Initializer 存在且
v 是 undefined ,则
如果 IsAnonymousFunctionDefinition (Initializer ) 是
true ,则
设置 v 为 ? NamedEvaluation of Initializer
with argument bindingId 。
否则,
设 defaultValue 为 ? Evaluation of Initializer 。
设置 v 为 ? GetValue (defaultValue )。
如果 environment 是 undefined ,则返回 ? PutValue (lhs , v )。
返回 ? InitializeReferencedBinding (lhs ,
v )。
BindingElement :
BindingPattern
Initializer opt
设 v 为 undefined 。
如果 iteratorRecord .[[Done]] 是
false ,则
设 next 为 ? IteratorStepValue (iteratorRecord )。
如果 next 不是 done ,则
设置 v 为 next 。
如果 Initializer 存在且
v 是 undefined ,则
设 defaultValue 为 ? Evaluation of
Initializer 。
设置 v 为 ? GetValue (defaultValue )。
返回 ? BindingInitialization of BindingPattern with
arguments v and environment 。
BindingRestElement
:
...
BindingIdentifier
设 lhs 为 ? ResolveBinding (BindingIdentifier 的StringValue ,
environment )。
设 A 为 ! ArrayCreate (0)。
设 n 为 0。
重复,
设 next 为 done 。
如果 iteratorRecord .[[Done]] 是
false ,则
设置 next 为 ? IteratorStepValue (iteratorRecord )。
如果 next 是 done ,则
如果 environment 是 undefined ,则返回
? PutValue (lhs ,
A )。
返回 ? InitializeReferencedBinding (lhs ,
A )。
执行 ! CreateDataPropertyOrThrow (A ,
! ToString (𝔽 (n )),
next )。
设置 n 为 n + 1。
BindingRestElement
:
...
BindingPattern
设 A 为 ! ArrayCreate (0)。
设 n 为 0。
重复,
设 next 为 done 。
如果 iteratorRecord .[[Done]] 是
false ,则
设置 next 为 ? IteratorStepValue (iteratorRecord )。
如果 next 是 done ,则
返回 ? BindingInitialization of
BindingPattern with
arguments A and environment 。
执行 ! CreateDataPropertyOrThrow (A ,
! ToString (𝔽 (n )),
next )。
设置 n 为 n + 1。
FormalParameters :
[empty]
返回 unused 。
FormalParameters :
FormalParameterList
,
FunctionRestParameter
执行 ? IteratorBindingInitialization of FormalParameterList
with arguments iteratorRecord and environment 。
返回 ? IteratorBindingInitialization of FunctionRestParameter with
arguments iteratorRecord and environment 。
FormalParameterList
:
FormalParameterList
,
FormalParameter
执行 ? IteratorBindingInitialization of FormalParameterList
with arguments iteratorRecord and environment 。
返回 ? IteratorBindingInitialization of FormalParameter with
arguments iteratorRecord and environment 。
ArrowParameters :
BindingIdentifier
设 v 为 undefined 。
断言 :
iteratorRecord .[[Done]] 是 false 。
设 next 为 ? IteratorStepValue (iteratorRecord )。
如果 next 不是 done ,则
设置 v 为 next 。
返回 ? BindingInitialization of BindingIdentifier
with arguments v and environment 。
ArrowParameters :
CoverParenthesizedExpressionAndArrowParameterList
设 formals 为被 CoverParenthesizedExpressionAndArrowParameterList
覆盖 的ArrowFormalParameters 。
返回 ? IteratorBindingInitialization of
formals with arguments iteratorRecord and environment 。
AsyncArrowBindingIdentifier
: BindingIdentifier
设 v 为 undefined 。
断言 :
iteratorRecord .[[Done]] 是 false 。
设 next 为 ? IteratorStepValue (iteratorRecord )。
如果 next 不是 done ,则
设置 v 为 next 。
返回 ? BindingInitialization of BindingIdentifier
with arguments v and environment 。
8.6.4 静态语义:AssignmentTargetType
语法导向操作
AssignmentTargetType 不接受参数并返回
simple 或 invalid 。它在以下产生式上分段定义:
IdentifierReference
: Identifier
如果 IsStrict (this IdentifierReference ) 是
true 且 Identifier 的 StringValue 是
"eval" 或 "arguments" ,返回
invalid 。
返回 simple 。
IdentifierReference
:
yield
await
CallExpression :
CallExpression
[
Expression
]
CallExpression
.
IdentifierName
CallExpression
.
PrivateIdentifier
MemberExpression :
MemberExpression
[
Expression
]
MemberExpression
.
IdentifierName
SuperProperty
MemberExpression
.
PrivateIdentifier
返回 simple 。
PrimaryExpression
:
CoverParenthesizedExpressionAndArrowParameterList
设 expr 为被 CoverParenthesizedExpressionAndArrowParameterList
覆盖 的 ParenthesizedExpression 。
返回 expr 的 AssignmentTargetType 。
PrimaryExpression
:
this
Literal
ArrayLiteral
ObjectLiteral
FunctionExpression
ClassExpression
GeneratorExpression
AsyncFunctionExpression
AsyncGeneratorExpression
RegularExpressionLiteral
TemplateLiteral
CallExpression :
CoverCallExpressionAndAsyncArrowHead
SuperCall
ImportCall
CallExpression
Arguments
CallExpression
TemplateLiteral
NewExpression :
new
NewExpression
MemberExpression :
MemberExpression
TemplateLiteral
new
MemberExpression
Arguments
NewTarget :
new
.
target
ImportMeta :
import
.
meta
LeftHandSideExpression
:
OptionalExpression
UpdateExpression :
LeftHandSideExpression
++
LeftHandSideExpression
--
++
UnaryExpression
--
UnaryExpression
UnaryExpression :
delete
UnaryExpression
void
UnaryExpression
typeof
UnaryExpression
+
UnaryExpression
-
UnaryExpression
~
UnaryExpression
!
UnaryExpression
AwaitExpression
ExponentiationExpression
:
UpdateExpression
**
ExponentiationExpression
MultiplicativeExpression
:
MultiplicativeExpression
MultiplicativeOperator
ExponentiationExpression
AdditiveExpression
:
AdditiveExpression
+
MultiplicativeExpression
AdditiveExpression
-
MultiplicativeExpression
ShiftExpression :
ShiftExpression
<<
AdditiveExpression
ShiftExpression
>>
AdditiveExpression
ShiftExpression
>>>
AdditiveExpression
RelationalExpression
:
RelationalExpression
<
ShiftExpression
RelationalExpression
>
ShiftExpression
RelationalExpression
<=
ShiftExpression
RelationalExpression
>=
ShiftExpression
RelationalExpression
instanceof
ShiftExpression
RelationalExpression
in
ShiftExpression
PrivateIdentifier
in
ShiftExpression
EqualityExpression
:
EqualityExpression
==
RelationalExpression
EqualityExpression
!=
RelationalExpression
EqualityExpression
===
RelationalExpression
EqualityExpression
!==
RelationalExpression
BitwiseANDExpression
:
BitwiseANDExpression
&
EqualityExpression
BitwiseXORExpression
:
BitwiseXORExpression
^
BitwiseANDExpression
BitwiseORExpression
:
BitwiseORExpression
|
BitwiseXORExpression
LogicalANDExpression
:
LogicalANDExpression
&&
BitwiseORExpression
LogicalORExpression
:
LogicalORExpression
||
LogicalANDExpression
CoalesceExpression
:
CoalesceExpressionHead
??
BitwiseORExpression
ConditionalExpression
:
ShortCircuitExpression
?
AssignmentExpression
:
AssignmentExpression
AssignmentExpression
:
YieldExpression
ArrowFunction
AsyncArrowFunction
LeftHandSideExpression
=
AssignmentExpression
LeftHandSideExpression
AssignmentOperator
AssignmentExpression
LeftHandSideExpression
&&=
AssignmentExpression
LeftHandSideExpression
||=
AssignmentExpression
LeftHandSideExpression
??=
AssignmentExpression
Expression :
Expression
,
AssignmentExpression
返回 invalid 。
8.6.5 静态语义:PropName
语法导向操作
PropName 不接受参数并返回一个字符串或
empty 。它在以下产生式上分段定义:
PropertyDefinition
: IdentifierReference
返回 IdentifierReference 的 StringValue 。
PropertyDefinition
:
...
AssignmentExpression
返回 empty 。
PropertyDefinition
:
PropertyName
:
AssignmentExpression
返回 PropertyName 的
PropName 。
LiteralPropertyName
: IdentifierName
AttributeKey : IdentifierName
返回 IdentifierName 的
StringValue 。
LiteralPropertyName
: StringLiteral
AttributeKey : StringLiteral
返回 StringLiteral 的
SV 。
LiteralPropertyName
: NumericLiteral
设 nbr 为 NumericLiteral 的 NumericValue 。
返回 ! ToString (nbr )。
ComputedPropertyName
:
[
AssignmentExpression
]
返回 empty 。
MethodDefinition :
ClassElementName
(
UniqueFormalParameters
)
{
FunctionBody
}
get
ClassElementName
(
)
{
FunctionBody
}
set
ClassElementName
(
PropertySetParameterList
)
{
FunctionBody
}
返回 ClassElementName 的 PropName 。
GeneratorMethod :
*
ClassElementName
(
UniqueFormalParameters
)
{
GeneratorBody
}
返回 ClassElementName 的 PropName 。
AsyncGeneratorMethod
:
async
*
ClassElementName
(
UniqueFormalParameters
)
{
AsyncGeneratorBody
}
返回 ClassElementName 的 PropName 。
ClassElement : ClassStaticBlock
返回 empty 。
ClassElement : ;
返回 empty 。
AsyncMethod :
async
ClassElementName
(
UniqueFormalParameters
)
{
AsyncFunctionBody
}
返回 ClassElementName 的 PropName 。
FieldDefinition :
ClassElementName
Initializer opt
返回 ClassElementName 的 PropName 。
ClassElementName :
PrivateIdentifier
返回 empty 。
9 可执行代码和执行上下文
9.1 环境记录
环境记录 是一种规范类型,
用于定义标识符 与特定变量和函数的关联,基于
ECMAScript代码的词法嵌套结构。通常环境记录与ECMAScript代码的某些特定语法结构相关联,
如函数声明 、块语句 或try语句 的catch 子句。每次求值这样的代码时,
都会创建一个新的环境记录来记录该代码创建的标识符绑定。
每个环境记录都有一个[[OuterEnv]] 字段,它要么是
null ,要么是对外部环境记录的引用。这用于建模环境记录值的逻辑嵌套。
(内部)环境记录的外部引用是对逻辑上围绕内部环境记录的环境记录的引用。
外部环境记录当然可能有自己的外部环境记录。一个环境记录可以作为多个内部环境记录的外部环境。
例如,如果一个函数声明
包含两个嵌套的函数声明 ,
那么每个嵌套函数的环境记录都将以周围函数的当前求值的环境记录作为其外部环境记录。
环境记录纯粹是规范机制,不需要对应于ECMAScript实现的任何特定构件。
ECMAScript程序不可能直接访问或操作这样的值。
9.1.1 环境记录类型层次结构
环境记录 可以看作存在于一个简单的面向对象层次结构中,
其中环境记录 是一个
抽象类,有三个具体子类:声明式环境记录 、对象环境记录 和全局环境记录 。函数环境记录 和模块环境记录 是声明式环境记录 的子类。
环境记录 抽象类
包含表16 中定义的抽象规范方法。
这些抽象方法对于每个具体子类都有不同的具体算法。
表16:环境记录 的抽象方法
方法
目的
HasBinding(N)
确定环境记录
是否具有字符串值N 的绑定。如果有则返回
true ,如果没有则返回false 。
CreateMutableBinding(N, D)
在环境记录 中
创建一个新的但未初始化的可变绑定。
字符串值N 是绑定名称的文本。如果布尔参数D 是
true ,则绑定可以随后被删除。
CreateImmutableBinding(N, S)
在环境记录 中
创建一个新的但未初始化的不可变绑定。
字符串值N 是绑定名称的文本。如果S 是
true ,那么在初始化后尝试设置它时
总是会抛出异常,无论引用该绑定的操作的严格模式设置如何。
InitializeBinding(N, V)
设置环境记录 中
已存在但未初始化的绑定的值。
字符串值N 是绑定名称的文本。V 是
绑定的值,是任何ECMAScript语言类型 的值。
SetMutableBinding(N, V, S)
设置环境记录 中
已存在的可变绑定的值。
字符串值N 是绑定名称的文本。V 是
绑定的值,可能是任何ECMAScript语言类型 的值。S 是布尔值 标志。如果S 是
true 且绑定无法设置,则抛出
TypeError 异常。
GetBindingValue(N, S)
从环境记录 返回
已存在绑定的值。
字符串值N 是绑定名称的文本。S
用于标识源自严格模式代码 或
其他需要严格模式引用语义的引用。如果S 是
true 且绑定不存在,则抛出
ReferenceError 异常。如果绑定存在但未初始化,
则抛出ReferenceError ,无论S 的值如何。
DeleteBinding(N)
从环境记录 删除绑定。字符串值N 是
绑定名称的文本。如果N 的绑定存在,则移除绑定并
返回true 。如果绑定存在但无法移除,
则返回false 。如果绑定不存在,则返回
true 。
HasThisBinding()
确定环境记录
是否建立this
绑定。如果建立则返回true ,
如果不建立则返回false 。
HasSuperBinding()
确定环境记录
是否建立super
方法绑定。如果建立则返回
true ,如果不建立则返回false 。
如果返回true ,则暗示环境记录 是
函数环境记录 ,
但反向推导不成立。
WithBaseObject()
如果此环境记录 与
with
语句关联,则返回with对象。
否则,返回undefined 。
9.1.1.1 声明式环境记录
每个声明式环境记录 都与包含变量、常量、let、类、模块、导入和/或函数声明的ECMAScript程序作用域相关联。声明式环境记录绑定其作用域内包含的声明所定义的标识符集合。
9.1.1.1.1 HasBinding ( N )
声明式环境记录
envRec 的HasBinding具体方法接受参数N
(字符串)并返回包含 布尔值的正常完成 。它确定参数标识符是否是记录绑定的标识符之一。调用时执行以下步骤:
如果envRec 具有N 的绑定,返回
true 。
返回false 。
9.1.1.1.2 CreateMutableBinding ( N , D
)
声明式环境记录
envRec 的CreateMutableBinding具体方法接受参数N (字符串)
和D (布尔值)并返回包含
unused 的正常完成 。它为名称N 创建一个新的未初始化的可变绑定。此环境记录 中不得已存在N 的绑定。如果D 是true ,则新绑定被标记为可删除的。调用时执行以下步骤:
断言 :
envRec 不已经具有N 的绑定。
在envRec 中为N 创建可变绑定并记录它是未初始化的。如果D 是true ,记录新创建的绑定可以被后续的DeleteBinding调用删除。
返回unused 。
9.1.1.1.3 CreateImmutableBinding ( N ,
S )
声明式环境记录
envRec 的CreateImmutableBinding具体方法接受参数N (字符串)
和S (布尔值)并返回包含
unused 的正常完成 。它为名称N 创建一个新的未初始化的不可变绑定。此环境记录 中不得已存在N 的绑定。如果S 是true ,则新绑定被标记为严格绑定。调用时执行以下步骤:
断言 :
envRec 不已经具有N 的绑定。
在envRec 中为N 创建不可变绑定并记录它是未初始化的。如果S 是true ,记录新创建的绑定是严格绑定。
返回unused 。
9.1.1.1.4 InitializeBinding ( N , V )
声明式环境记录
envRec 的InitializeBinding具体方法接受参数N (字符串)
和V (ECMAScript语言值 )
并返回包含
unused 的正常完成 。它用于将名称为N 的标识符的当前绑定的绑定值设置为值V 。N 的未初始化绑定必须已经存在。调用时执行以下步骤:
断言 :
envRec 必须具有N 的未初始化绑定。
将envRec 中N 的绑定值设置为V 。
记录 envRec 中N 的绑定已被初始化。
返回unused 。
9.1.1.1.5 SetMutableBinding ( N , V ,
S )
声明式环境记录
envRec 的SetMutableBinding具体方法接受参数N (字符串)、
V (ECMAScript语言值 )
和S (布尔值)并返回包含
unused 的正常完成 或抛出完成 。它尝试将名称为N 的标识符的当前绑定的绑定值更改为值V 。N 的绑定通常已经存在,但在罕见情况下可能不存在。如果绑定是不可变绑定,当S 是true 时抛出TypeError 。调用时执行以下步骤:
如果envRec 没有N 的绑定,则
如果S 是true ,抛出ReferenceError 异常。
执行! envRec .CreateMutableBinding(N ,
true )。
执行! envRec .InitializeBinding(N ,
V )。
返回unused 。
如果envRec 中N 的绑定是严格绑定,将S 设置为true 。
如果envRec 中N 的绑定尚未初始化,则
抛出ReferenceError 异常。
否则如果envRec 中N 的绑定是可变绑定,则
将其绑定值更改为V 。
否则,
断言 :这是尝试更改不可变绑定的值。
如果S 是true ,抛出TypeError 异常。
返回unused 。
注
导致步骤1 缺失绑定的ECMAScript代码示例是:
function f ( ) { eval ("var x; x = (delete x, 0);" ); }
9.1.1.1.6 GetBindingValue ( N , S )
声明式环境记录
envRec 的GetBindingValue具体方法接受参数N (字符串)
和S (布尔值)并返回包含 ECMAScript语言值 的正常完成 或抛出完成 。它返回名称为N 的绑定标识符的值。如果绑定存在但未初始化,则抛出ReferenceError ,无论S 的值如何。调用时执行以下步骤:
断言 :
envRec 具有N 的绑定。
如果envRec 中N 的绑定是未初始化绑定,抛出ReferenceError 异常。
返回envRec 中当前绑定到N 的值。
9.1.1.1.7 DeleteBinding ( N )
声明式环境记录
envRec 的DeleteBinding具体方法接受参数N (字符串)
并返回包含 布尔值的正常完成 。它只能删除已明确指定为可删除的绑定。调用时执行以下步骤:
断言 :
envRec 具有N 的绑定。
如果envRec 中N 的绑定无法删除,返回false 。
从envRec 中移除N 的绑定。
返回true 。
9.1.1.1.8 HasThisBinding ( )
声明式环境记录
envRec 的HasThisBinding具体方法不接受参数并返回false 。调用时执行以下步骤:
返回false 。
注
常规声明式环境记录 (即既不是函数环境记录 也不是模块环境记录 的记录)不提供this
绑定。
9.1.1.1.9 HasSuperBinding ( )
声明式环境记录
envRec 的HasSuperBinding具体方法不接受参数并返回false 。调用时执行以下步骤:
返回false 。
注
常规声明式环境记录 (即既不是函数环境记录 也不是模块环境记录 的记录)不提供super
绑定。
9.1.1.1.10 WithBaseObject ( )
声明式环境记录
envRec 的WithBaseObject具体方法不接受参数并返回undefined 。调用时执行以下步骤:
返回undefined 。
9.1.1.2 对象环境记录
每个对象环境记录
都与一个称为其绑定对象 的对象相关联。对象环境记录绑定一组字符串标识符名称,
这些名称直接对应于其绑定对象的属性名称。不是标识符名称 形式的字符串的属性键 不包含在绑定标识符集合中。无论其[[Enumerable]] 属性的设置如何,自有属性和继承属性都包含在集合中。由于属性可以动态地从对象中添加和删除,对象环境记录绑定的标识符集合可能会作为任何添加或删除属性操作的副作用而发生变化。作为这种副作用结果创建的任何绑定都被认为是可变绑定,即使相应属性的Writable属性是false 。对象环境记录不存在不可变绑定。
为with
语句(14.11 )创建的对象环境记录可以提供其绑定对象作为函数调用中使用的隐式this 值。这种能力由布尔值[[IsWithEnvironment]] 字段控制。
对象环境记录具有表17 中列出的附加状态字段。
表17:对象环境记录 的附加字段
字段名称
值
含义
[[BindingObject]]
一个对象
此环境记录 的绑定对象。
[[IsWithEnvironment]]
布尔值
指示此环境记录 是否为with
语句创建。
9.1.1.2.1 HasBinding ( N )
对象环境记录
envRec 的HasBinding具体方法接受参数N (字符串)
并返回包含 布尔值的正常完成 或抛出完成 。它确定其关联的绑定对象是否具有名称为N 的属性。调用时执行以下步骤:
设bindingObject 为envRec .[[BindingObject]] 。
设foundBinding 为? HasProperty (bindingObject ,
N )。
如果foundBinding 是false ,返回false 。
如果envRec .[[IsWithEnvironment]] 是false ,返回true 。
设unscopables 为? Get (bindingObject ,
%Symbol.unscopables% )。
如果unscopables 是对象 ,则
设blocked 为ToBoolean (? Get (unscopables ,
N ))。
如果blocked 是true ,返回false 。
返回true 。
9.1.1.2.2 CreateMutableBinding ( N , D
)
对象环境记录
envRec 的CreateMutableBinding具体方法接受参数N (字符串)和D (布尔值)
并返回包含
unused 的正常完成 或抛出完成 。它在环境记录 的关联绑定对象中创建一个名称为N 的属性,并将其初始化为值undefined 。如果D 是true ,新属性的[[Configurable]] 属性设置为true ;否则设置为false 。调用时执行以下步骤:
设bindingObject 为envRec .[[BindingObject]] 。
执行? DefinePropertyOrThrow (bindingObject ,
N , PropertyDescriptor { [[Value]] :
undefined , [[Writable]] :
true , [[Enumerable]] :
true , [[Configurable]] :
D })。
返回unused 。
注
通常envRec 不会有N 的绑定,但如果有,DefinePropertyOrThrow 的语义可能导致现有绑定被替换或遮蔽,或导致返回异常完成 。
9.1.1.2.3 CreateImmutableBinding ( N ,
S )
对象环境记录 的CreateImmutableBinding具体方法在本规范中从未使用。
9.1.1.2.4 InitializeBinding ( N , V )
对象环境记录
envRec 的InitializeBinding具体方法接受参数N (字符串)和V (ECMAScript语言值 )
并返回包含
unused 的正常完成 或抛出完成 。它用于将名称为N 的标识符的当前绑定的绑定值设置为值V 。调用时执行以下步骤:
执行? envRec .SetMutableBinding (N ,
V , false )。
返回unused 。
注
在本规范中,对对象环境记录 的CreateMutableBinding的所有使用之后都紧跟相同名称的InitializeBinding调用。因此,本规范不显式跟踪对象环境记录 中绑定的初始化状态。
9.1.1.2.5 SetMutableBinding ( N , V ,
S )
对象环境记录
envRec 的SetMutableBinding具体方法接受参数N (字符串)、V (ECMAScript语言值 )
和S (布尔值)并返回包含
unused 的正常完成 或抛出完成 。它尝试将环境记录 关联绑定对象的名称为N 的属性的值设置为值V 。名称为N 的属性通常已经存在,但如果不存在或当前不可写,错误处理由S 确定。调用时执行以下步骤:
设bindingObject 为envRec .[[BindingObject]] 。
设stillExists 为? HasProperty (bindingObject ,
N )。
如果stillExists 是false 且S 是true ,抛出ReferenceError 异常。
执行? Set (bindingObject ,
N , V , S )。
返回unused 。
9.1.1.2.6 GetBindingValue ( N , S )
对象环境记录
envRec 的GetBindingValue具体方法接受参数N (字符串)和S (布尔值)
并返回包含 ECMAScript语言值 的正常完成 或抛出完成 。它返回其关联绑定对象的名称为N 的属性的值。该属性应该已经存在,但如果不存在,结果取决于S 。调用时执行以下步骤:
设bindingObject 为envRec .[[BindingObject]] 。
设value 为? HasProperty (bindingObject ,
N )。
如果value 是false ,则
如果S 是false ,返回undefined ;否则抛出ReferenceError 异常。
返回? Get (bindingObject ,
N )。
9.1.1.2.7 DeleteBinding ( N )
对象环境记录
envRec 的DeleteBinding具体方法接受参数N (字符串)
并返回包含 布尔值的正常完成 或抛出完成 。它只能删除对应于环境对象的[[Configurable]] 属性值为true 的属性的绑定。调用时执行以下步骤:
设bindingObject 为envRec .[[BindingObject]] 。
返回? bindingObject .[[Delete]] (N )。
9.1.1.2.8 HasThisBinding ( )
对象环境记录
envRec 的HasThisBinding具体方法不接受参数并返回false 。调用时执行以下步骤:
返回false 。
注
9.1.1.2.9 HasSuperBinding ( )
对象环境记录
envRec 的HasSuperBinding具体方法不接受参数并返回false 。调用时执行以下步骤:
返回false 。
注
9.1.1.2.10 WithBaseObject ( )
对象环境记录
envRec 的WithBaseObject具体方法不接受参数并返回对象或undefined 。调用时执行以下步骤:
如果envRec .[[IsWithEnvironment]] 是true ,返回envRec .[[BindingObject]] 。
否则,返回undefined 。
9.1.1.3 函数环境记录
函数环境记录 是一个声明式环境记录 ,用于表示函数的顶层作用域,如果函数不是箭头函数 ,则提供this
绑定。如果函数不是箭头函数 并且引用super
,其函数环境记录还包含用于在函数内执行super
方法调用的状态。
函数环境记录具有表18 中列出的附加状态字段。
表18:函数环境记录 的附加字段
字段名称
值
含义
[[ThisValue]]
一个ECMAScript语言值
这是用于此函数调用的this 值。
[[ThisBindingStatus]]
lexical 、initialized 或uninitialized
如果值是lexical ,这是一个箭头函数 ,不具有本地this 值。
[[FunctionObject]]
一个ECMAScript函数对象
调用导致创建此环境记录 的函数对象 。
[[NewTarget]]
一个构造函数 或undefined
如果此环境记录 由[[Construct]] 内部方法创建,[[NewTarget]] 是[[Construct]] 的newTarget 参数的值。否则,其值为undefined 。
函数环境记录支持表16 中列出的所有声明式环境记录 方法,除了HasThisBinding和HasSuperBinding,所有这些方法都共享相同的规范。此外,函数环境记录支持表19 中列出的方法:
表19:函数环境记录 的附加方法
方法
目的
GetThisBinding()
返回此环境记录 的this
绑定的值。如果this
绑定尚未初始化,则抛出ReferenceError 。
9.1.1.3.1 BindThisValue ( envRec , V )
抽象操作BindThisValue接受参数envRec (一个函数环境记录 )和V (一个ECMAScript语言值 )
并返回包含
unused 的正常完成 或抛出完成 。它设置envRec .[[ThisValue]] 并记录它已被初始化。调用时执行以下步骤:
断言 :
envRec .[[ThisBindingStatus]] 不是lexical 。
如果envRec .[[ThisBindingStatus]] 是initialized ,抛出ReferenceError 异常。
设置envRec .[[ThisValue]] 为V 。
设置envRec .[[ThisBindingStatus]] 为initialized 。
返回unused 。
9.1.1.3.2 HasThisBinding ( )
函数环境记录
envRec 的HasThisBinding具体方法不接受参数并返回布尔值。调用时执行以下步骤:
如果envRec .[[ThisBindingStatus]] 是lexical ,返回false ;否则,返回true 。
9.1.1.3.3 HasSuperBinding ( )
函数环境记录
envRec 的HasSuperBinding具体方法不接受参数并返回布尔值。调用时执行以下步骤:
如果envRec .[[ThisBindingStatus]] 是lexical ,返回false 。
如果envRec .[[FunctionObject]] .[[HomeObject]] 是undefined ,返回false ;否则,返回true 。
9.1.1.3.4 GetThisBinding ( )
函数环境记录
envRec 的GetThisBinding具体方法不接受参数并返回包含 ECMAScript语言值 的正常完成 或抛出完成 。调用时执行以下步骤:
断言 :
envRec .[[ThisBindingStatus]] 不是lexical 。
如果envRec .[[ThisBindingStatus]] 是uninitialized ,抛出ReferenceError 异常。
返回envRec .[[ThisValue]] 。
9.1.1.3.5 GetSuperBase ( envRec )
抽象操作GetSuperBase接受参数envRec (一个函数环境记录 )并返回对象、null 或undefined 。它返回作为envRec 中绑定的super
属性访问基础的对象。值undefined 表示这种访问将产生运行时错误。调用时执行以下步骤:
设home 为envRec .[[FunctionObject]] .[[HomeObject]] 。
如果home 是undefined ,返回undefined 。
断言 :
home 是一个普通对象 。
返回! home .[[GetPrototypeOf]] ()。
9.1.1.4 全局环境记录
全局环境记录 用于表示被在共同领域 中处理的所有ECMAScript 脚本 元素所共享的最外层作用域。全局环境记录为内置全局变量(第19 章)、全局对象 的属性以及在脚本 中出现的所有顶级声明(8.2.9 ,
8.2.11 )提供绑定。
全局环境记录在逻辑上是单个记录,但它被指定为一个封装对象环境记录 和声明式环境记录 的复合体。对象环境记录 以关联领域记录 的全局对象 为基础对象。这个全局对象 是全局环境记录的GetThisBinding具体方法返回的值。全局环境记录的对象环境记录 组件包含所有内置全局变量的绑定(第19 章)以及由全局代码中的函数声明 、生成器声明 、
异步函数声明 、异步生成器声明 或变量语句 引入的所有绑定。全局代码中所有其他ECMAScript声明的绑定包含在全局环境记录的声明式环境记录 组件中。
属性可以直接在全局对象 上创建。因此,全局环境记录的对象环境记录 组件可能包含由函数声明 、生成器声明 、
异步函数声明 、异步生成器声明 或变量声明 声明显式创建的绑定和作为全局对象 属性隐式创建的绑定。为了识别哪些绑定是使用声明显式创建的,全局环境记录维护一个使用CreateGlobalVarBinding 和CreateGlobalFunctionBinding 抽象操作 绑定的名称列表。
全局环境记录具有表20 中列出的附加字段和表21 中列出的附加方法。
表20:全局环境记录 的附加字段
表21:全局环境记录 的附加方法
方法
目的
GetThisBinding()
返回此环境记录 的this
绑定的值。
9.1.1.4.1 HasBinding ( N )
全局环境记录
envRec 的HasBinding具体方法接受参数N (字符串)
并返回包含 布尔值的正常完成 或抛出完成 。它确定参数标识符是否是记录绑定的标识符之一。调用时执行以下步骤:
设DclRec 为envRec .[[DeclarativeRecord]] 。
如果! DclRec .HasBinding(N )是true ,
返回true 。
设ObjRec 为envRec .[[ObjectRecord]] 。
返回? ObjRec .HasBinding (N )。
9.1.1.4.2 CreateMutableBinding ( N , D
)
全局环境记录
envRec 的CreateMutableBinding具体方法接受参数N (字符串)和D (布尔值)
并返回包含
unused 的正常完成 或抛出完成 。它为名称N 创建一个新的未初始化的可变绑定。绑定在关联的声明式记录中创建。声明式记录中不得已存在N 的绑定。如果D 是true ,则新绑定被标记为可删除的。调用时执行以下步骤:
设DclRec 为envRec .[[DeclarativeRecord]] 。
如果! DclRec .HasBinding(N )是true ,
抛出TypeError 异常。
返回! DclRec .CreateMutableBinding(N ,
D )。
9.1.1.4.3 CreateImmutableBinding ( N ,
S )
全局环境记录
envRec 的CreateImmutableBinding具体方法接受参数N (字符串)和S (布尔值)
并返回包含
unused 的正常完成 或抛出完成 。它为名称N 创建一个新的未初始化的不可变绑定。此环境记录 中不得已存在N 的绑定。如果S 是true ,则新绑定被标记为严格绑定。调用时执行以下步骤:
设DclRec 为envRec .[[DeclarativeRecord]] 。
如果! DclRec .HasBinding(N )是true ,
抛出TypeError 异常。
返回! DclRec .CreateImmutableBinding(N ,
S )。
9.1.1.4.4 InitializeBinding ( N , V )
全局环境记录
envRec 的InitializeBinding具体方法接受参数N (字符串)和V (ECMAScript语言值 )
并返回包含
unused 的正常完成 或抛出完成 。它用于将名称为N 的标识符的当前绑定的绑定值设置为值V 。N 的未初始化绑定必须已经存在。调用时执行以下步骤:
设DclRec 为envRec .[[DeclarativeRecord]] 。
如果! DclRec .HasBinding(N )是true ,
则
返回! DclRec .InitializeBinding(N ,
V )。
断言 :
如果绑定存在,它必须在对象环境记录 中。
设ObjRec 为envRec .[[ObjectRecord]] 。
返回? ObjRec .InitializeBinding (N ,
V )。
9.1.1.4.5 SetMutableBinding ( N , V ,
S )
全局环境记录
envRec 的SetMutableBinding具体方法接受参数N (字符串)、V (ECMAScript语言值 )
和S (布尔值)并返回包含
unused 的正常完成 或抛出完成 。它尝试将名称为N 的标识符的当前绑定的绑定值更改为值V 。如果绑定是不可变绑定且S 是true ,则抛出TypeError 。名称为N 的属性通常已经存在,但如果不存在或当前不可写,错误处理由S 确定。调用时执行以下步骤:
设DclRec 为envRec .[[DeclarativeRecord]] 。
如果! DclRec .HasBinding(N )是true ,
则
返回? DclRec .SetMutableBinding(N ,
V , S )。
设ObjRec 为envRec .[[ObjectRecord]] 。
返回? ObjRec .SetMutableBinding (N ,
V , S )。
9.1.1.4.6 GetBindingValue ( N , S )
全局环境记录
envRec 的GetBindingValue具体方法接受参数N (字符串)
和S (布尔值)并返回包含 ECMAScript语言值 的正常完成 或抛出完成 。它返回名称为N 的绑定标识符的值。如果绑定是未初始化绑定,则抛出ReferenceError 异常。名称为N 的属性通常已经存在,但如果不存在或当前不可写,错误处理由S 确定。调用时执行以下步骤:
设DclRec 为envRec .[[DeclarativeRecord]] 。
如果! DclRec .HasBinding(N )是true ,
则
返回? DclRec .GetBindingValue(N ,
S )。
设ObjRec 为envRec .[[ObjectRecord]] 。
返回? ObjRec .GetBindingValue (N ,
S )。
9.1.1.4.7 DeleteBinding ( N )
全局环境记录
envRec 的DeleteBinding具体方法接受参数N (字符串)
并返回包含 布尔值的正常完成 或抛出完成 。它只能删除已明确指定为可删除的绑定。调用时执行以下步骤:
设DclRec 为envRec .[[DeclarativeRecord]] 。
如果! DclRec .HasBinding(N )是true ,
则
返回! DclRec .DeleteBinding(N )。
设ObjRec 为envRec .[[ObjectRecord]] 。
设globalObject 为ObjRec .[[BindingObject]] 。
设existingProp 为? HasOwnProperty (globalObject ,
N )。
如果existingProp 是true ,则
返回? ObjRec .DeleteBinding (N )。
返回true 。
9.1.1.4.8 HasThisBinding ( )
全局环境记录
envRec 的HasThisBinding具体方法不接受参数并返回true 。调用时执行以下步骤:
返回true 。
注
9.1.1.4.9 HasSuperBinding ( )
全局环境记录
envRec 的HasSuperBinding具体方法不接受参数并返回false 。调用时执行以下步骤:
返回false 。
注
9.1.1.4.10 WithBaseObject ( )
全局环境记录
envRec 的WithBaseObject具体方法不接受参数并返回undefined 。调用时执行以下步骤:
返回undefined 。
9.1.1.4.11 GetThisBinding ( )
全局环境记录
envRec 的GetThisBinding具体方法不接受参数并返回包含 对象的正常完成 。调用时执行以下步骤:
返回envRec .[[GlobalThisValue]] 。
9.1.1.4.12 HasLexicalDeclaration ( envRec ,
N )
抽象操作HasLexicalDeclaration接受参数envRec (一个全局环境记录 )
和N (字符串)并返回布尔值。它确定参数标识符是否在envRec 中有使用词法声明如词法声明 或类声明 创建的绑定。调用时执行以下步骤:
设DclRec 为envRec .[[DeclarativeRecord]] 。
返回! DclRec .HasBinding(N )。
9.1.1.4.13 HasRestrictedGlobalProperty ( envRec ,
N )
抽象操作HasRestrictedGlobalProperty接受参数envRec (一个全局环境记录 )
和N (字符串)并返回包含 布尔值的正常完成 或抛出完成 。它确定参数标识符是否是全局对象 的属性名称,该属性不得被全局词法绑定遮蔽。调用时执行以下步骤:
设ObjRec 为envRec .[[ObjectRecord]] 。
设globalObject 为ObjRec .[[BindingObject]] 。
设existingProp 为? globalObject .[[GetOwnProperty]] (N )。
如果existingProp 是undefined ,返回false 。
如果existingProp .[[Configurable]] 是true ,返回false 。
返回true 。
注
属性可能存在于全局对象 上,这些属性是直接创建的而不是使用var或函数声明声明的。不能创建与全局对象 的不可配置属性同名的全局词法绑定。全局属性"undefined" 就是这样一个属性的例子。
9.1.1.4.14 CanDeclareGlobalVar ( envRec ,
N )
抽象操作CanDeclareGlobalVar接受参数envRec (一个全局环境记录 )
和N (字符串)并返回包含 布尔值的正常完成 或抛出完成 。它确定如果为相同参数N 调用相应的CreateGlobalVarBinding 调用是否会成功。允许冗余的var声明和对预先存在的全局对象 属性的var声明。调用时执行以下步骤:
设ObjRec 为envRec .[[ObjectRecord]] 。
设globalObject 为ObjRec .[[BindingObject]] 。
设hasProperty 为? HasOwnProperty (globalObject ,
N )。
如果hasProperty 是true ,返回true 。
返回? IsExtensible (globalObject )。
9.1.1.4.15 CanDeclareGlobalFunction ( envRec ,
N )
抽象操作CanDeclareGlobalFunction接受参数envRec (一个全局环境记录 )
和N (字符串)并返回包含 布尔值的正常完成 或抛出完成 。它确定如果为相同参数N 调用相应的CreateGlobalFunctionBinding 调用是否会成功。调用时执行以下步骤:
设ObjRec 为envRec .[[ObjectRecord]] 。
设globalObject 为ObjRec .[[BindingObject]] 。
设existingProp 为? globalObject .[[GetOwnProperty]] (N )。
如果existingProp 是undefined ,返回? IsExtensible (globalObject )。
如果existingProp .[[Configurable]] 是true ,返回true 。
如果IsDataDescriptor (existingProp )
是true 且existingProp 有属性值{ [[Writable]] : true , [[Enumerable]] :
true },返回true 。
返回false 。
9.1.1.4.16 CreateGlobalVarBinding ( envRec ,
N , D )
抽象操作CreateGlobalVarBinding接受参数envRec (一个全局环境记录 )、N (字符串)和D (布尔值)
并返回包含
unused 的正常完成 或抛出完成 。它在关联的对象环境记录 中创建并初始化可变绑定。如果绑定已经存在,则重用它并假定已初始化。调用时执行以下步骤:
设ObjRec 为envRec .[[ObjectRecord]] 。
设globalObject 为ObjRec .[[BindingObject]] 。
设hasProperty 为? HasOwnProperty (globalObject ,
N )。
设extensible 为? IsExtensible (globalObject )。
如果hasProperty 是false 且extensible 是true ,则
执行? ObjRec .CreateMutableBinding (N ,
D )。
执行? ObjRec .InitializeBinding (N ,
undefined )。
返回unused 。
9.1.1.4.17 CreateGlobalFunctionBinding ( envRec ,
N , V , D )
抽象操作CreateGlobalFunctionBinding接受参数envRec (一个全局环境记录 )、N (字符串)、V (ECMAScript语言值 )
和D (布尔值)并返回包含
unused 的正常完成 或抛出完成 。它在关联的对象环境记录 中创建并初始化可变绑定。如果绑定已经存在,则替换它。调用时执行以下步骤:
设ObjRec 为envRec .[[ObjectRecord]] 。
设globalObject 为ObjRec .[[BindingObject]] 。
设existingProp 为? globalObject .[[GetOwnProperty]] (N )。
如果existingProp 是undefined 或existingProp .[[Configurable]] 是true ,则
设desc 为属性描述符{ [[Value]] :
V , [[Writable]] :
true , [[Enumerable]] :
true , [[Configurable]] :
D }。
否则,
设desc 为属性描述符{ [[Value]] :
V }。
执行? DefinePropertyOrThrow (globalObject ,
N , desc )。
执行? Set (globalObject ,
N , V , false )。
返回unused 。
注
全局函数声明总是表示为全局对象 的自有属性。如果可能,现有的自有属性会被重新配置为具有标准的属性值集合。步骤7 等效于调用InitializeBinding具体方法所做的操作,如果globalObject 是代理,将产生相同的代理陷阱调用序列。
9.1.1.5 模块环境记录
模块环境记录 是一个
声明式环境记录 ,用于表示 ECMAScript
模块 的外部作用域。除了普通的可变和不可变绑定之外,模块环境记录还提供不可变的导入绑定,这些绑定提供对存在于另一个
环境记录 中的目标绑定的间接访问。
模块环境记录支持 声明式环境记录 在 表 16
中列出的所有方法,除了 GetBindingValue、DeleteBinding、HasThisBinding 和 GetThisBinding
之外,所有这些方法都共享相同的规范。此外,模块环境记录支持 表
22 中列出的方法:
表 22:模块环境记录 的附加方法
方法
目的
GetThisBinding()
返回此 环境记录 的
this
绑定的值。
9.1.1.5.1 GetBindingValue ( N , S )
模块环境记录 envRec 的
GetBindingValue 具体方法接收参数 N (一个字符串)和 S (一个布尔值),并返回 包含 ECMAScript 语言值 的正常完成或
抛出完成 。它返回名称为
N 的绑定标识符的值。但是,如果绑定是间接绑定,则返回目标绑定的值。如果绑定存在但未初始化,则抛出
ReferenceError 。调用时执行以下步骤:
断言 :
S 是 true 。
断言 :
envRec 有一个 N 的绑定。
如果 N 的绑定是间接绑定,那么
设 M 和 N2 为创建此 N 绑定时提供的间接值。
设 targetEnv 为 M .[[Environment]] 。
如果 targetEnv 是 empty ,抛出
ReferenceError 异常。
返回 ? targetEnv .GetBindingValue (N2 ,
true )。
如果 envRec 中 N 的绑定是未初始化的绑定,抛出
ReferenceError 异常。
返回 envRec 中当前绑定到 N 的值。
注
S 将始终为 true ,因为 模块 始终是 严格模式代码 。
9.1.1.5.2 DeleteBinding ( N )
模块环境记录 的 DeleteBinding
具体方法在本规范中从未使用。
注
模块环境记录 仅在严格代码中使用,并且早期错误 规则防止在严格代码中将 delete 操作符应用于会解析为
模块环境记录 绑定的
引用记录 。参见
13.5.1.1 。
9.1.1.5.3 HasThisBinding ( )
模块环境记录 envRec 的
HasThisBinding 具体方法不接收参数,返回 true 。调用时执行以下步骤:
返回 true 。
注
9.1.1.5.4 GetThisBinding ( )
模块环境记录 envRec 的
GetThisBinding 具体方法不接收参数,返回 包含
undefined 的正常完成。调用时执行以下步骤:
返回 undefined 。
9.1.1.5.5 CreateImportBinding ( envRec ,
N , M , N2 )
抽象操作 CreateImportBinding 接收参数 envRec (一个 模块环境记录 )、N (一个字符串)、M (一个
模块记录 )和
N2 (一个字符串),并返回 unused 。它为名称 N
创建一个新的已初始化的不可变间接绑定。envRec 中不能已经存在 N 的绑定。N2 是存在于
M 的 模块环境记录 中的绑定的名称。对新绑定值的访问将间接访问目标绑定的绑定值。调用时执行以下步骤:
断言 :
envRec 还没有 N 的绑定。
断言 :
当 M .[[Environment]] 被实例化时,它将有一个
N2 的直接绑定。
在 envRec 中为 N 创建一个不可变的间接绑定,该绑定引用 M 和
N2 作为其目标绑定,并记录该绑定已初始化。
返回 unused 。
9.1.2 环境记录操作
本规范中使用以下抽象操作 来操作环境记录 :
9.1.2.1 GetIdentifierReference ( env ,
name , strict )
抽象操作 GetIdentifierReference 接收参数 env (一个环境记录 或
null )、name (一个字符串)和 strict (一个布尔值),并返回包含 引用记录 的正常完成或抛出完成 。调用时执行以下步骤:
如果 env 是 null ,那么
返回引用记录
{ [[Base]] :
unresolvable , [[ReferencedName]] : name , [[Strict]] : strict , [[ThisValue]] : empty }。
设 exists 为 ? env .HasBinding (name )。
如果 exists 是 true ,那么
返回引用记录
{ [[Base]] :
env , [[ReferencedName]] :
name , [[Strict]] : strict ,
[[ThisValue]] : empty }。
否则,
设 outer 为 env .[[OuterEnv]] 。
返回 ? GetIdentifierReference (outer ,
name , strict )。
9.1.2.2 NewDeclarativeEnvironment ( E )
抽象操作 NewDeclarativeEnvironment 接收参数 E (一个环境记录 或
null ),并返回一个声明式环境记录 。调用时执行以下步骤:
设 env 为一个不包含绑定的新声明式环境记录 。
设置 env .[[OuterEnv]] 为 E 。
返回 env 。
9.1.2.3 NewObjectEnvironment ( O , W ,
E )
抽象操作 NewObjectEnvironment 接收参数 O (一个对象)、W (一个布尔值)和
E (一个环境记录 或
null ),并返回一个对象环境记录 。调用时执行以下步骤:
设 env 为一个新的对象环境记录 。
设置 env .[[BindingObject]] 为 O 。
设置 env .[[IsWithEnvironment]] 为 W 。
设置 env .[[OuterEnv]] 为 E 。
返回 env 。
9.1.2.4 NewFunctionEnvironment ( F ,
newTarget )
抽象操作 NewFunctionEnvironment 接收参数 F (一个 ECMAScript 函数对象 )和
newTarget (一个对象或 undefined ),并返回一个函数环境记录 。调用时执行以下步骤:
设 env 为一个不包含绑定的新函数环境记录 。
设置 env .[[FunctionObject]] 为 F 。
如果 F .[[ThisMode]] 是
lexical ,设置 env .[[ThisBindingStatus]] 为 lexical 。
否则,设置 env .[[ThisBindingStatus]] 为
uninitialized 。
设置 env .[[NewTarget]] 为 newTarget 。
设置 env .[[OuterEnv]] 为 F .[[Environment]] 。
返回 env 。
9.1.2.5 NewGlobalEnvironment ( G ,
thisValue )
抽象操作 NewGlobalEnvironment 接收参数 G (一个对象)和 thisValue (一个对象),并返回一个全局环境记录 。调用时执行以下步骤:
设 objRec 为 NewObjectEnvironment (G ,
false , null )。
设 dclRec 为 NewDeclarativeEnvironment (null )。
设 env 为一个新的全局环境记录 。
设置 env .[[ObjectRecord]] 为 objRec 。
设置 env .[[GlobalThisValue]] 为
thisValue 。
设置 env .[[DeclarativeRecord]] 为
dclRec 。
设置 env .[[OuterEnv]] 为 null 。
返回 env 。
9.1.2.6 NewModuleEnvironment ( E )
抽象操作 NewModuleEnvironment 接收参数 E (一个环境记录 ),并返回一个模块环境记录 。调用时执行以下步骤:
设 env 为一个不包含绑定的新模块环境记录 。
设置 env .[[OuterEnv]] 为 E 。
返回 env 。
9.2 私有环境记录
私有环境记录 是一种规范机制,用于基于 ECMAScript 代码中 类声明 和 类表达式 的词法嵌套结构来跟踪私有名称 。它们类似于但区别于环境记录 。每个私有环境记录 都与一个 类声明 或 类表达式 关联。每次求值这样的类时,都会创建一个新的私有环境记录 来记录该类声明的私有名称 。
每个私有环境记录 都具有表 23 中定义的字段。
表 23:私有环境记录 字段
9.2.1 私有环境记录操作
本规范中使用以下抽象操作 来操作私有环境记录 :
9.2.1.1 NewPrivateEnvironment ( outerPrivateEnv )
抽象操作 NewPrivateEnvironment 接收参数 outerPrivateEnv (一个私有环境记录 或
null ),并返回一个私有环境记录 。调用时执行以下步骤:
设 names 为一个新的空列表 。
返回私有环境记录 {
[[OuterPrivateEnvironment]] : outerPrivateEnv ,
[[Names]] : names }。
9.2.1.2 ResolvePrivateIdentifier ( privateEnv ,
identifier )
抽象操作 ResolvePrivateIdentifier 接收参数 privateEnv (一个私有环境记录 )和
identifier (一个字符串),并返回一个私有名称 。调用时执行以下步骤:
设 names 为 privateEnv .[[Names]] 。
对于 names 的每个私有名称 pn ,执行
如果 pn .[[Description]] 是
identifier ,那么
返回 pn 。
设 outerPrivateEnv 为 privateEnv .[[OuterPrivateEnvironment]] 。
断言 :
outerPrivateEnv 不是 null 。
返回 ResolvePrivateIdentifier (outerPrivateEnv ,
identifier )。
9.3 领域
在求值之前,所有 ECMAScript 代码都必须与一个领域 关联。从概念上讲,一个领域 由一组内建对象、一个 ECMAScript 全局环境、在该全局环境作用域内加载的所有 ECMAScript
代码以及其他关联的状态和资源组成。
在本规范中,领域 表示为具有表
24 中指定字段的领域记录 :
表 24:领域记录 字段
9.3.1 InitializeHostDefinedRealm ( )
抽象操作 InitializeHostDefinedRealm 不接收参数,并返回包含
unused 的正常完成或抛出完成 。调用时执行以下步骤:
设 realm 为一个新的领域记录 。
执行 CreateIntrinsics (realm )。
设置 realm .[[AgentSignifier]] 为 AgentSignifier ()。
设置 realm .[[TemplateMap]] 为一个新的空列表 。
设 newContext 为一个新的执行上下文 。
设置 newContext 的 Function 为 null 。
设置 newContext 的领域 为 realm 。
设置 newContext 的 ScriptOrModule 为 null 。
将 newContext 推入执行上下文栈 ;newContext
现在是运行执行上下文 。
如果宿主 要求使用异质对象 作为
realm 的全局对象 ,那么
设 global 为以宿主定义 的方式创建的这样一个对象。
否则,
设 global 为 OrdinaryObjectCreate (realm .[[Intrinsics]] .[[%Object.prototype% ]])。
如果宿主 要求
realm 的全局作用域中的 this
绑定返回除全局对象 之外的对象,那么
设 thisValue 为以宿主定义 的方式创建的这样一个对象。
否则,
设 thisValue 为 global 。
设置 realm .[[GlobalObject]] 为 global 。
设置 realm .[[GlobalEnv]] 为 NewGlobalEnvironment (global ,
thisValue )。
执行 ? SetDefaultGlobalBindings (realm )。
在 global 上创建任何宿主定义 的全局对象 属性。
返回 unused 。
9.3.2 CreateIntrinsics ( realmRec )
抽象操作 CreateIntrinsics 接收参数 realmRec (一个领域记录 ),并返回 unused 。调用时执行以下步骤:
设置 realmRec .[[Intrinsics]] 为一个新的记录 。
使用表 6 中列出的值设置
realmRec .[[Intrinsics]]
的字段。字段名称是表第一列中列出的名称。每个字段的值是一个新的对象值,完全且递归地填充了属性值,如子句19 到28 中每个对象的规范所定义。所有对象属性值都是新创建的对象值。所有作为内建函数对象 的值都通过执行 CreateBuiltinFunction (steps ,
length , name , slots , realmRec ,
prototype ) 创建,其中 steps 是本规范提供的该函数的定义,name 是函数
"name" 属性的初始值,length 是函数 "length"
属性的初始值,slots 是函数指定的内部插槽名称的列表(如果有),prototype 是函数 [[Prototype]] 内部插槽的指定值。内建对象及其属性的创建必须有序,以避免依赖尚未创建的对象。
执行 AddRestrictedFunctionProperties (realmRec .[[Intrinsics]] .[[%Function.prototype% ]],
realmRec )。
返回 unused 。
9.3.3 SetDefaultGlobalBindings ( realmRec )
抽象操作 SetDefaultGlobalBindings 接收参数 realmRec (一个领域记录 ),并返回包含
unused 的正常完成或抛出完成 。调用时执行以下步骤:
设 global 为 realmRec .[[GlobalObject]] 。
对于子句19 中指定的全局对象的每个属性,执行
设 name 为属性名称 的字符串值。
设 desc 为该属性的完全填充的数据属性描述符 ,包含该属性的指定特性。对于19.2 、19.3 或19.4 中列出的属性,[[Value]] 特性的值是来自 realmRec 的相应内建对象。
执行 ? DefinePropertyOrThrow (global ,
name , desc )。
返回 unused 。
9.4 执行上下文
执行上下文 是一种规范设备,用于跟踪 ECMAScript
实现对代码的运行时求值。在任何时候,每个代理 最多有一个实际在执行代码的执行上下文。这被称为代理 的运行执行上下文 。本规范中对运行执行上下文 的所有引用都指周围代理 的运行执行上下文 。
执行上下文栈 用于跟踪执行上下文。运行执行上下文 始终是该栈的顶部元素。每当控制从与当前运行执行上下文 关联的可执行代码转移到与该执行上下文不关联的可执行代码时,就会创建一个新的执行上下文。新创建的执行上下文被推入栈中并成为运行执行上下文 。
执行上下文包含跟踪其关联代码的执行进度所需的任何实现特定状态。每个执行上下文至少具有表 25 中列出的状态组件。
表 25:所有执行上下文的状态组件
运行执行上下文 对代码的求值 可能在本规范内定义的各个点被暂停。一旦运行执行上下文 被暂停,不同的执行上下文可能成为运行执行上下文 并开始求值其代码。在稍后的某个时间,被暂停的执行上下文可能再次成为运行执行上下文 并在之前被暂停的点继续求值其代码。运行执行上下文 状态在执行上下文间的转换通常以类似栈的后进先出方式发生。然而,某些
ECMAScript 特性需要运行执行上下文 的非 LIFO 转换。
运行执行上下文 的领域 组件的值也被称为当前领域记录 。运行执行上下文 的 Function 组件的值也被称为活动函数对象 。
ECMAScript 代码执行上下文 具有表
26 中列出的附加状态组件。
表 26:ECMAScript 代码执行上下文的附加状态组件
执行上下文的 LexicalEnvironment 和 VariableEnvironment 组件始终是环境记录 。
表示生成器求值的执行上下文具有表
27 中列出的附加状态组件。
表 27:生成器执行上下文的附加状态组件
组件
目的
Generator
此执行上下文 正在求值的生成器。
在大多数情况下,只有运行执行上下文 (执行上下文栈 的顶部)被本规范内的算法直接操作。因此,当使用术语"LexicalEnvironment"和"VariableEnvironment"而不加限定时,它们指的是运行执行上下文 的这些组件。
执行上下文纯粹是一种规范机制,不需要对应 ECMAScript 实现的任何特定工件。ECMAScript 代码不可能直接访问或观察执行上下文。
9.4.1 GetActiveScriptOrModule ( )
抽象操作 GetActiveScriptOrModule 不接收参数,并返回脚本记录 、模块记录 或
null 。它用于基于运行执行上下文 确定运行的脚本或模块。调用时执行以下步骤:
如果执行上下文栈 为空,返回
null 。
设 ec 为执行上下文栈 上 ScriptOrModule 组件不为
null 的最顶层执行上下文 。
如果不存在这样的执行上下文 ,返回
null 。否则,返回 ec 的 ScriptOrModule。
9.4.2 ResolveBinding ( name [ , env ] )
抽象操作 ResolveBinding 接收参数 name (一个字符串)和可选参数 env (一个环境记录 或
undefined ),并返回包含 引用记录 的正常完成或抛出完成 。它用于确定
name 的绑定。env 可用于显式提供要搜索绑定的环境记录 。调用时执行以下步骤:
如果 env 不存在或 env 是 undefined ,那么
设置 env 为运行执行上下文 的
LexicalEnvironment。
断言 :
env 是一个环境记录 。
设 strict 为 IsStrict (正在求值的语法产生式)。
返回 ? GetIdentifierReference (env ,
name , strict )。
注
ResolveBinding 的结果始终是一个引用记录 ,其 [[ReferencedName]] 字段为 name 。
9.4.3 GetThisEnvironment ( )
抽象操作 GetThisEnvironment 不接收参数,并返回一个环境记录 。它找到当前提供关键字 this
绑定的环境记录 。调用时执行以下步骤:
设 env 为运行执行上下文 的 LexicalEnvironment。
重复,
设 exists 为 env .HasThisBinding()。
如果 exists 是 true ,返回 env 。
设 outer 为 env .[[OuterEnv]] 。
断言 :
outer 不是 null 。
设置 env 为 outer 。
注
步骤2 中的循环将始终终止,因为环境列表总是以具有
this
绑定的全局环境结束。
9.4.5 ResolveThisBinding ( )
抽象操作 ResolveThisBinding 不接收参数,并返回包含 ECMAScript 语言值 的正常完成或抛出完成 。它使用运行执行上下文 的 LexicalEnvironment 确定关键字 this
的绑定。调用时执行以下步骤:
设 envRec 为 GetThisEnvironment ()。
返回 ? envRec .GetThisBinding()。
9.4.5 GetNewTarget ( )
抽象操作 GetNewTarget 不接收参数,并返回一个对象或 undefined 。它使用运行执行上下文 的 LexicalEnvironment 确定
NewTarget 值。调用时执行以下步骤:
设 envRec 为 GetThisEnvironment ()。
断言 :
envRec 有一个 [[NewTarget]] 字段。
返回 envRec .[[NewTarget]] 。
9.4.6 GetGlobalObject ( )
抽象操作 GetGlobalObject 不接收参数,并返回一个对象。它返回当前运行执行上下文 使用的全局对象 。调用时执行以下步骤:
设 currentRealm 为当前领域记录 。
返回 currentRealm .[[GlobalObject]] 。
9.5 作业和宿主操作入队作业
作业 是一个无参数的抽象闭包 ,当没有其他 ECMAScript 计算正在进行时,它启动
ECMAScript 计算。
作业 由特定代理 中的 ECMAScript 宿主环境 调度执行。本规范描述了宿主钩子 HostEnqueueGenericJob 、HostEnqueueFinalizationRegistryCleanupJob 、HostEnqueuePromiseJob 和HostEnqueueTimeoutJob 来调度作业。本规范中的宿主钩子 按对作业调度施加的附加约束进行组织。宿主 可以定义调度作业的附加抽象操作 。这些操作接受作业 抽象闭包 和领域 (一个领域记录 或null )作为参数。如果提供了领域记录 ,这些操作调度作业在将来某个时间在提供的领域 中执行,在拥有该领域 的代理 中。如果为领域 提供null ,则作业不会求值 ECMAScript
代码。它们的实现必须符合以下要求:
注 1
宿主环境 不需要在调度方面统一对待
作业 。例如,Web 浏览器和 Node.js 将 Promise 处理
作业 视为比其他工作更高的优先级;未来的特性可能添加不被视为如此高优先级的
作业 。
在任何特定时间,scriptOrModule (一个脚本记录 、一个模块记录 或null )是活动脚本或模块 ,如果所有以下条件都为真:
在任何特定时间,如果所有以下条件都为真,则执行准备求值 ECMAScript 代码 :
注 2
宿主环境 可以通过将执行上下文 推入执行上下文栈 来准备执行求值代码。具体步骤是实现定义 的。
领域 的具体选择取决于宿主环境 。这个初始执行上下文 和领域 仅在调用任何回调函数之前使用。当调用与作业 相关的回调函数(如 Promise
处理程序)时,调用会推入自己的执行上下文 和领域 。
特定类型的作业 有附加的一致性要求。
9.5.1 作业回调记录
作业回调记录 是用于存储函数对象 和宿主定义 值的记录 值。通过宿主 入队的作业 调用的函数对象 可能有附加的宿主定义 上下文。为了传播状态,作业 抽象闭包 不应该直接捕获和调用函数对象 。相反,使用HostMakeJobCallback 和HostCallJobCallback 。
注
例如,WHATWG HTML 规范(https://html.spec.whatwg.org/ )使用宿主定义 值来为
Promise 回调传播现任设置对象。
作业回调记录具有表 28 中列出的字段。
表 28:作业回调记录 字段
字段名称
值
含义
[[Callback]]
一个函数对象
调用作业 时要调用的函数。
[[HostDefined]]
任何值(默认值为empty )
为宿主 保留使用的字段。
9.5.2 HostMakeJobCallback ( callback )
宿主定义 的抽象操作
HostMakeJobCallback 接收参数 callback (一个函数对象 ),并返回一个作业回调记录 。
HostMakeJobCallback 的实现必须符合以下要求:
它必须返回一个作业回调记录 ,其[[Callback]] 字段为callback 。
HostMakeJobCallback 的默认实现在调用时执行以下步骤:
返回作业回调记录 { [[Callback]] : callback , [[HostDefined]] : empty }。
非 Web 浏览器的 ECMAScript 宿主 必须使用
HostMakeJobCallback 的默认实现。
注
这在回调被传递给负责其最终调度和运行的函数时调用。例如,promise.then(thenAction)
在调用
Promise.prototype.then
时对 thenAction
调用
MakeJobCallback,而不是在调度反应作业 时。
9.5.3 HostCallJobCallback ( jobCallback , V ,
argumentsList )
宿主定义 的抽象操作
HostCallJobCallback 接收参数 jobCallback (一个作业回调记录 )、V (一个ECMAScript 语言值 )和
argumentsList (ECMAScript 语言值 的列表 ),并返回包含 ECMAScript 语言值 的正常完成或抛出完成 。
HostCallJobCallback 的实现必须符合以下要求:
它必须执行并返回Call (jobCallback .[[Callback]] , V , argumentsList )的结果。
注
这个要求意味着宿主 不能改变本规范中定义的函数对象 的[[Call]] 行为。
HostCallJobCallback 的默认实现在调用时执行以下步骤:
断言 :
IsCallable (jobCallback .[[Callback]] ) 是true 。
返回 ? Call (jobCallback .[[Callback]] , V , argumentsList )。
非 Web 浏览器的 ECMAScript 宿主 必须使用
HostCallJobCallback 的默认实现。
9.5.4 HostEnqueueGenericJob ( job , realm )
宿主定义 的抽象操作
HostEnqueueGenericJob 接收参数 job (一个作业 抽象闭包 )和realm (一个领域记录 ),并返回unused 。它在由realm .[[AgentSignifier]] 表示的代理 中的领域 realm
中调度job 在将来某个时间执行。与此算法一起使用的抽象闭包 旨在无附加约束(如优先级和排序)地调度。
HostEnqueueGenericJob 的实现必须符合9.5 中的要求。
9.5.5 HostEnqueuePromiseJob ( job , realm )
宿主定义 的抽象操作
HostEnqueuePromiseJob 接收参数 job (一个作业 抽象闭包 )和realm (一个领域记录 或null ),并返回unused 。它调度job 在将来某个时间执行。与此算法一起使用的抽象闭包 旨在与 Promise 处理相关,或者以与 Promise
处理操作相等的优先级调度。
HostEnqueuePromiseJob 的实现必须符合9.5 中的要求以及以下要求:
注
NewPromiseResolveThenableJob 返回的作业 的realm 通常是在then 函数对象 上调用GetFunctionRealm 的结果。NewPromiseReactionJob 返回的作业 的realm 通常是在处理程序不是undefined 时在处理程序上调用GetFunctionRealm 的结果。如果处理程序是undefined ,则realm 为null 。对于两种类型的作业 ,当GetFunctionRealm 异常完成(即在被撤销的代理上调用)时,realm 是GetFunctionRealm 调用时的当前领域记录 。当realm 为null 时,不会求值用户
ECMAScript 代码,也不会创建新的 ECMAScript 对象(例如错误对象)。例如,WHATWG HTML 规范(https://html.spec.whatwg.org/ )使用realm 来检查运行脚本的能力和入口 概念。
9.5.6 HostEnqueueTimeoutJob ( timeoutJob ,
realm , milliseconds )
宿主定义 的抽象操作
HostEnqueueTimeoutJob 接收参数 timeoutJob (一个作业 抽象闭包 )、realm (一个领域记录 )和milliseconds (一个非负有限 数字),并返回unused 。它在由realm .[[AgentSignifier]] 表示的代理 中的领域 realm
中调度timeoutJob 在至少milliseconds 毫秒后执行。
HostEnqueueTimeoutJob 的实现必须符合9.5 中的要求。
9.6 代理
代理 包含一组 ECMAScript 执行上下文 、一个执行上下文栈 、一个运行执行上下文 、一个代理记录 和一个执行线程 。除了执行线程 之外,代理 的组成部分专属于该代理 。
代理 的执行线程 在该代理 的执行上下文 上独立于其他代理 执行算法步骤,但是一个执行线程 可以被多个代理 用作执行线程 ,只要共享该线程的代理 都没有[[CanBlock]] 字段为true 的代理记录 。
注 1
例如,一些 Web 浏览器在浏览器窗口的多个不相关选项卡之间共享单个执行线程 。
当代理 的执行线程 正在执行算法步骤时,该代理 是那些步骤的周围代理 。这些步骤使用周围代理 来访问在该代理 内持有的规范级执行对象:运行执行上下文 、执行上下文栈 和代理记录 的字段。
代理标识符 是用于标识代理 的全局唯一不透明值。
表 29:代理记录 字段
字段名称
值
含义
[[LittleEndian]]
布尔值
当算法GetValueFromBuffer 和SetValueInBuffer 需要时为isLittleEndian 参数计算的默认值。选择是实现定义 的,应该是对实现最有效的选择。一旦该值被观察到,它就不能改变。
[[CanBlock]]
布尔值
确定代理 是否可以阻塞。
[[Signifier]]
一个代理标识符
在其代理集群 内唯一标识代理 。
[[IsLockFree1]]
布尔值
如果对单字节值的原子操作是无锁的,则为true ,否则为false 。
[[IsLockFree2]]
布尔值
如果对双字节值的原子操作是无锁的,则为true ,否则为false 。
[[IsLockFree8]]
布尔值
如果对八字节值的原子操作是无锁的,则为true ,否则为false 。
[[CandidateExecution]]
一个候选执行 记录
参见内存模型 。
[[KeptAlive]]
对象或符号的列表
初始为一个新的空列表 ,表示要保持活跃直到当前作业 结束的对象和/或符号列表。
[[ModuleAsyncEvaluationCount]]
一个整数
初始为 0,用于为异步或具有异步依赖的模块的[[AsyncEvaluationOrder]] 字段分配唯一的递增值。
一旦[[Signifier]] 、[[IsLockFree1]] 和[[IsLockFree2]] 的值被代理集群 中的任何代理 观察到,它们就不能改变。
注 2
[[IsLockFree1]] 和[[IsLockFree2]] 的值不一定由硬件决定,也可能反映可能随时间和 ECMAScript 实现而变化的实现选择。
没有[[IsLockFree4]] 字段:4 字节原子操作总是无锁的。
实际上,如果原子操作是用任何类型的锁实现的,则该操作不是无锁的。无锁并不意味着无等待:对于完成无锁原子操作可能需要多少个机器步骤没有上限。
大小为n 的原子访问是无锁的,并不意味着大小为n 的非原子访问的(感知的)原子性,具体来说,非原子访问仍然可能作为几个单独的内存访问序列来执行。详见ReadSharedMemory 和WriteSharedMemory 。
注 3
代理 是一种规范机制,不需要对应
ECMAScript 实现的任何特定工件。
9.6.1 AgentSignifier ( )
抽象操作 AgentSignifier 不接收参数,并返回一个代理标识符 。调用时执行以下步骤:
设AR 为周围代理 的代理记录 。
返回AR .[[Signifier]] 。
9.6.2 AgentCanSuspend ( )
抽象操作 AgentCanSuspend 不接收参数,并返回一个布尔值。调用时执行以下步骤:
设AR 为周围代理 的代理记录 。
返回AR .[[CanBlock]] 。
注
在某些环境中,给定代理 暂停可能不合理。例如,在 Web
浏览器环境中,禁止暂停文档的主事件处理线程可能是合理的,而仍然允许工作线程的事件处理线程暂停。
9.6.3 IncrementModuleAsyncEvaluationCount ( )
抽象操作 IncrementModuleAsyncEvaluationCount 不接收参数,并返回一个整数 。调用时执行以下步骤:
设AR 为周围代理 的代理记录 。
设count 为AR .[[ModuleAsyncEvaluationCount]] 。
设置AR .[[ModuleAsyncEvaluationCount]] 为count
+ 1。
返回count 。
注
此值仅用于跟踪挂起模块之间的相对求值顺序。当没有挂起模块时,实现可以不可观察地将[[ModuleAsyncEvaluationCount]] 重置为 0。
9.7 代理集群
代理集群 是可以通过操作共享内存进行通信的代理 的最大集合。
注 1
不同代理 内的程序可以通过未指定的方式共享内存。至少,SharedArrayBuffers
的后备内存可以在集群中的代理 之间共享。
可能存在可以通过消息传递进行通信但不能共享内存的代理 ;它们永远不在同一个代理集群中。
每个代理 都恰好属于一个代理集群。
注 2
集群中的代理 不需要在某个特定时间点都处于活跃状态。如果代理 A 创建另一个代理 B ,之后 A 终止且 B
创建代理 C ,如果
A 可以与 B 共享一些内存且 B 可以与 C 共享一些内存,则这三个代理 在同一个集群中。
集群内的所有代理 在其各自代理记录 中的[[LittleEndian]] 字段必须具有相同的值。
注 3
如果代理集群内不同的代理 具有不同的[[LittleEndian]] 值,则很难将共享内存用于多字节数据。
集群内的所有代理 在其各自代理记录 中的[[IsLockFree1]] 字段必须具有相同的值;[[IsLockFree2]] 字段也是如此。
集群内的所有代理 在其各自代理记录 中的[[Signifier]] 字段必须具有不同的值。
嵌入可以在代理 不知情或不配合的情况下停用(停止前进进度)或激活(恢复前进进度)代理 。如果嵌入这样做,它不得让集群中的某些代理 保持活跃状态,而集群中的其他代理 被无限期地停用。
注 4
前述限制的目的是避免代理 因为另一个代理 被停用而死锁或饥饿的情况。例如,如果具有独立于任何窗口中文档的生命周期的 HTML
共享工作线程被允许与这种独立文档的专用工作线程共享内存,并且文档及其专用工作线程在专用工作线程持有锁时被停用(例如,文档被推入其窗口的历史记录),然后共享工作线程尝试获取锁,那么共享工作线程将被阻塞,直到专用工作线程再次被激活(如果有的话)。与此同时,试图从其他窗口访问共享工作线程的其他工作线程将饥饿。
此限制的含义是,不属于嵌入中同一暂停/唤醒集合的代理 之间将无法共享内存。
嵌入可以在代理 集群的其他代理 事先不知情或不配合的情况下终止代理 。如果代理 不是通过自身或集群中另一个代理 的程序动作终止,而是被集群外部的力量终止,那么嵌入必须选择两种策略之一:要么终止集群中的所有代理 ,要么提供可靠的 API,允许集群中的代理 进行协调,使得集群的至少一个剩余成员能够检测到终止,终止数据包含足够的信息来标识被终止的代理 。
注 5
这种类型的终止的例子包括:操作系统或用户终止在单独进程中运行的代理 ;嵌入本身终止与其他代理 在同一进程中运行的代理 ,当按代理 的资源计算表明该代理 失控时。
以下每个规范值以及从它们可传递到达的值都恰好属于一个代理集群。
在集群中任何代理 对任何 ECMAScript
代码进行任何求值之前,集群中所有代理 的代理记录 的[[CandidateExecution]] 字段被设置为初始候选执行 。初始候选执行 是一个空候选执行 ,其[[EventsRecords]] 字段是一个列表 ,为每个代理 包含一个代理事件记录 ,其[[AgentSignifier]] 字段是该代理 的代理标识符 ,并且其[[EventList]] 和[[AgentSynchronizesWith]] 字段是空的列表 。
注 6
代理集群中的所有代理 在其代理记录 的[[CandidateExecution]] 字段中共享相同的候选执行 。候选执行 是内存模型 使用的规范机制。
注 7
代理集群是一种规范机制,不需要对应 ECMAScript 实现的任何特定工件。
9.8 前进进度
代理 取得前进进度 是指其根据本规范执行求值步骤。
当代理 的运行执行上下文 同步且无限期地等待外部事件时,该代理变为阻塞 状态。只有代理记录 的[[CanBlock]] 字段为true 的代理 才能在这种意义上变为阻塞状态。非阻塞 的代理 是指不处于阻塞状态的代理。
实现必须确保:
注
这与内存模型 中的活跃性保证一起,确保所有seq-cst 写入最终对所有代理 变为可观察的。
9.9 WeakRef 和 FinalizationRegistry 目标的处理模型
9.9.1 目标
本规范不保证任何对象或符号会被垃圾回收。不活跃 的对象或符号可能在很长时间后被释放,或者永远不被释放。因此,本规范在描述由垃圾回收触发的行为时使用"可能"一词。
WeakRefs 和FinalizationRegistrys 的语义基于在特定时间点发生的两个操作:
这两个动作(ClearKeptObjects 或CleanupFinalizationRegistry )都不能中断同步
ECMAScript 执行。因为宿主 可能组装更长的同步
ECMAScript 执行运行,本规范将ClearKeptObjects 和CleanupFinalizationRegistry 的调度推迟到宿主环境 。
一些 ECMAScript 实现包括在后台运行的垃圾收集器实现,包括当 ECMAScript 处于空闲状态时。让宿主环境 调度CleanupFinalizationRegistry 允许它恢复
ECMAScript 执行以运行终结器工作,这可能释放持有的值,减少整体内存使用。
9.9.2 活跃性
对于某个对象和/或符号集合S ,关于S 的假设 WeakRef
无关 执行是指这样的执行:其引用对象是S 元素的WeakRef 的抽象操作WeakRefDeref 总是返回undefined 。
注 1
WeakRef 无关性与活跃性一起捕获两个概念。一是
WeakRef 本身不会使其引用对象保持活跃。二是活跃性中的循环并不意味着值是活跃的。具体来说,如果确定
v 的活跃性依赖于确定
WeakRef 引用对象
r 的活跃性,则
r 的活跃性不能假设
v 的活跃性,这将是循环推理。
注 2
WeakRef 无关性是在对象或符号集合上定义的,而不是在单个值上定义的,以考虑循环。如果它是在单个值上定义的,那么循环中的
WeakRef 引用对象将被认为是活跃的,即使其身份只能通过循环中的其他
WeakRef 引用对象观察到。
注 3
通俗地说,如果包含单个对象或符号的每个集合都是活跃的,我们就说该对象或符号是活跃的。
在求值期间的任何时点,如果满足以下任一条件,则对象和/或符号集合S 被认为是活跃的 :
S 中的任何元素都包含在任何代理 的[[KeptAlive]] 列表 中。
存在一个关于S 的有效未来假设 WeakRef 无关执行,该执行观察S 中任何值的身份。
注 4
上述第二个条件旨在捕获这样的直觉:如果值的身份可以通过非
WeakRef 方式观察到,则该值是活跃的。值的身份可以通过观察严格相等比较或观察值被用作
Map 中的键来观察。
注 5
对象或符号在字段、内部槽或属性中的存在并不意味着该值是活跃的。例如,如果所讨论的值从未传回程序,那么它就无法被观察到。
WeakMap 中的键、WeakSet 的成员以及FinalizationRegistry 单元记录的[[WeakRefTarget]] 和[[UnregisterToken]] 字段都是这种情况。
上述定义意味着,如果 WeakMap 中的键不是活跃的,那么其对应的值也不一定是活跃的。
注 6
活跃性是保证引擎不得清空哪些
WeakRefs 的下界。这里定义的活跃性是不可判定的。实际上,引擎使用保守的近似,如可达性。预期会有很大的实现自由度。
9.9.3 执行
在任何时候,如果对象和/或符号集合S 不是活跃的 ,ECMAScript 实现可以原子地执行以下步骤:
对于S 的每个元素value ,执行
对于每个ref .[[WeakRefTarget]] 为value 的WeakRef
ref ,执行
设置ref .[[WeakRefTarget]] 为empty 。
对于每个fg .[[Cells]] 包含cell .[[WeakRefTarget]] 为value 的记录
cell 的FinalizationRegistry
fg ,执行
设置cell .[[WeakRefTarget]] 为empty 。
可选地,执行HostEnqueueFinalizationRegistryCleanupJob (fg )。
对于每个map .[[WeakMapData]] 包含r .[[Key]] 为value 的记录
r 的 WeakMap map ,执行
设置r .[[Key]] 为empty 。
设置r .[[Value]] 为empty 。
对于每个set .[[WeakSetData]] 包含value 的
WeakSet set ,执行
用值为empty 的元素替换set .[[WeakSetData]] 中值为value 的元素。
注 1
与活跃性定义一起,本条款规定了实现可以应用于WeakRefs 的优化。
可以在不观察对象身份的情况下访问对象。诸如死变量消除和对身份未被观察的非逃逸对象属性的标量替换等优化是允许的。因此,这些优化被允许可观察地清空指向此类对象的WeakRefs 。
另一方面,如果对象的身份是可观察的,并且该对象在WeakRef 的[[WeakRefTarget]] 内部槽中,则禁止可观察地清空WeakRef 的重新物化等优化。
因为调用HostEnqueueFinalizationRegistryCleanupJob 是可选的,FinalizationRegistry 中的注册对象不一定使该FinalizationRegistry 保持活跃 。实现可以因任何原因省略FinalizationRegistry 回调,例如,如果FinalizationRegistry 本身变为死亡,或者应用程序正在关闭。
注 2
实现没有义务为非活跃 对象或符号的最大集合清空WeakRefs 。
如果实现选择一个非活跃 集合S 来清空WeakRefs ,此定义要求它同时清空S 中所有值的WeakRefs 。换句话说,实现清空指向值v 的WeakRef 而不清空其他WeakRefs (如果不清空,可能导致观察到v 值的执行)是不符合规范的。
9.9.4 宿主钩子
9.9.4.1 HostEnqueueFinalizationRegistryCleanupJob (
finalizationRegistry )
宿主定义 的抽象操作
HostEnqueueFinalizationRegistryCleanupJob 接收参数finalizationRegistry (一个FinalizationRegistry ),并返回unused 。
设cleanupJob 为捕获finalizationRegistry 的无参数新作业 抽象闭包 ,调用时执行以下步骤:
设cleanupResult 为Completion (CleanupFinalizationRegistry (finalizationRegistry ))。
如果cleanupResult 是异常完成 ,执行任何宿主定义 的错误报告步骤。
返回unused 。
HostEnqueueFinalizationRegistryCleanupJob
的实现调度cleanupJob 在将来某个时间执行(如果可能)。它还必须符合9.5 中的要求。
9.10 ClearKeptObjects ( )
抽象操作 ClearKeptObjects 不接收参数,并返回unused 。预期 ECMAScript 实现在同步 ECMAScript 执行序列完成时调用
ClearKeptObjects。调用时执行以下步骤:
设agentRecord 为周围代理 的代理记录 。
设置agentRecord .[[KeptAlive]] 为一个新的空列表 。
返回unused 。
9.11 AddToKeptObjects ( value )
抽象操作 AddToKeptObjects 接收参数value (一个对象或符号),并返回unused 。调用时执行以下步骤:
设agentRecord 为周围代理 的代理记录 。
将value 追加到agentRecord .[[KeptAlive]] 。
返回unused 。
注
当抽象操作 AddToKeptObjects 使用目标对象或符号调用时,它将目标添加到一个列表中,该列表将强引用目标,直到调用
ClearKeptObjects 。
9.12 CleanupFinalizationRegistry ( finalizationRegistry )
抽象操作 CleanupFinalizationRegistry 接收参数finalizationRegistry (一个FinalizationRegistry ),并返回包含unused 的正常完成 或抛出完成 。调用时执行以下步骤:
断言 :finalizationRegistry 具有[[Cells]] 和[[CleanupCallback]] 内部槽。
设callback 为finalizationRegistry .[[CleanupCallback]] 。
当finalizationRegistry .[[Cells]] 包含cell .[[WeakRefTarget]] 为empty 的记录
cell 时,实现可以执行以下步骤:
选择任何这样的cell 。
从finalizationRegistry .[[Cells]] 中移除cell 。
执行? HostCallJobCallback (callback ,
undefined , « cell .[[HeldValue]] »)。
返回unused 。
9.13 CanBeHeldWeakly ( v )
抽象操作 CanBeHeldWeakly 接收参数v (一个ECMAScript
语言值 ),并返回一个布尔值。当且仅当v 适合用作弱引用时,它返回true 。只有适合用作弱引用的值才能作为
WeakMap 的键、WeakSet 的元素、WeakRef 的目标或FinalizationRegistry 的目标之一。调用时执行以下步骤:
如果v 是对象 ,返回true 。
如果v 是符号 且KeyForSymbol (v )为undefined ,返回true 。
返回false 。
注
没有语言身份 的语言值可以在没有先前引用的情况下体现,并且不适合用作弱引用。由Symbol.for 产生的符号值与其他符号值不同,没有语言身份,不适合用作弱引用。知名符号 可能永远不会被回收,但仍被视为适合用作弱引用,因为它们数量有限,因此可以通过各种实现方法进行管理。但是,在活跃 WeakMap
中与知名符号关联的任何值都不太可能被回收,并且在实现中可能"泄漏"内存资源。
10 普通对象和异构对象行为
10.1 普通对象内部方法和内部槽
所有普通对象 都有一个名为[[Prototype]] 的内部槽。此内部槽的值要么是null ,要么是一个对象,用于实现继承。假设一个名为P 的属性在普通对象
O 中不存在,但在其[[Prototype]] 对象上存在。如果P 引用[[Prototype]] 对象上的一个数据属性 ,O 对于get访问会继承它,使其表现得好像P 是O 的一个属性。如果P 引用[[Prototype]] 对象上的一个可写数据属性 ,对O 上P 的set访问会在O 上创建一个名为P 的新数据属性 。如果P 引用[[Prototype]] 对象上的一个不可写数据属性 ,对O 上P 的set访问会失败。如果P 引用[[Prototype]] 对象上的一个访问器属性 ,O 会继承该访问器用于get访问和set访问。
每个普通对象 都有一个布尔值[[Extensible]] 内部槽,用于满足6.1.7.3 中指定的可扩展性相关内部方法不变量。也就是说,一旦对象的[[Extensible]] 内部槽的值被设置为false ,就不再可能向对象添加属性、修改对象的[[Prototype]] 内部槽的值,或随后将[[Extensible]] 的值更改为true 。
在以下算法描述中,假设O 是一个普通对象 ,P 是一个属性键 值,V 是任何ECMAScript语言值 ,Desc 是一个属性描述符 记录。
每个普通对象 内部方法都委托给同名的抽象操作。如果这样的抽象操作依赖于另一个内部方法,那么内部方法在O 上被调用,而不是直接调用同名的抽象操作。这些语义确保当普通对象 内部方法应用于异构对象 时,它们重写的内部方法会被调用。
10.1.1 [[GetPrototypeOf]] ( )
普通对象
O 的[[GetPrototypeOf]] 内部方法不接受参数,返回一个包含 Object或null 的正常完成 。调用时执行以下步骤:
返回 OrdinaryGetPrototypeOf (O )。
10.1.1.1 OrdinaryGetPrototypeOf ( O )
抽象操作OrdinaryGetPrototypeOf接受参数O (一个Object),返回一个Object或null 。调用时执行以下步骤:
返回 O .[[Prototype]] 。
10.1.2 [[SetPrototypeOf]] ( V )
普通对象
O 的[[SetPrototypeOf]] 内部方法接受参数V (一个Object或null ),返回一个包含 Boolean的正常完成 。调用时执行以下步骤:
返回 OrdinarySetPrototypeOf (O ,
V )。
10.1.2.1 OrdinarySetPrototypeOf ( O , V )
抽象操作OrdinarySetPrototypeOf接受参数O (一个Object)和V (一个Object或null ),返回一个Boolean。调用时执行以下步骤:
令 current 为 O .[[Prototype]] 。
如果 SameValue (V ,
current ) 为 true ,返回 true 。
令 extensible 为 O .[[Extensible]] 。
如果 extensible 为 false ,返回 false 。
令 p 为 V 。
令 done 为 false 。
重复,当 done 为
false 时,
如果 p 为 null ,那么
设置 done 为 true 。
否则如果 SameValue (p ,
O ) 为 true ,那么
返回 false 。
否则,
如果 p .[[GetPrototypeOf]]
不是10.1.1 中定义的普通对象 内部方法,设置
done 为 true 。
否则,设置 p 为 p .[[Prototype]] 。
设置 O .[[Prototype]] 为 V 。
返回 true 。
注
步骤7 中的循环保证在仅包含使用[[GetPrototypeOf]] 和[[SetPrototypeOf]] 的普通对象 定义的对象的任何原型链中都不会出现循环。
10.1.3 [[IsExtensible]] ( )
普通对象
O 的[[IsExtensible]] 内部方法不接受参数,返回一个包含 Boolean的正常完成 。调用时执行以下步骤:
返回 OrdinaryIsExtensible (O )。
10.1.3.1 OrdinaryIsExtensible ( O )
抽象操作OrdinaryIsExtensible接受参数O (一个Object),返回一个Boolean。调用时执行以下步骤:
返回 O .[[Extensible]] 。
10.1.4 [[PreventExtensions]] ( )
普通对象
O 的[[PreventExtensions]] 内部方法不接受参数,返回一个包含 true 的正常完成 。调用时执行以下步骤:
返回 OrdinaryPreventExtensions (O )。
10.1.4.1 OrdinaryPreventExtensions ( O )
抽象操作OrdinaryPreventExtensions接受参数O (一个Object),返回true 。调用时执行以下步骤:
设置 O .[[Extensible]] 为 false 。
返回 true 。
10.1.5 [[GetOwnProperty]] ( P )
普通对象
O 的[[GetOwnProperty]] 内部方法接受参数P (一个属性键 ),返回一个包含 属性描述符 或undefined 的正常完成 。调用时执行以下步骤:
返回 OrdinaryGetOwnProperty (O ,
P )。
10.1.5.1 OrdinaryGetOwnProperty ( O , P )
抽象操作OrdinaryGetOwnProperty接受参数O (一个Object)和P (一个属性键 ),返回一个属性描述符 或undefined 。调用时执行以下步骤:
如果 O 没有键为 P 的自有属性,返回 undefined 。
令 D 为一个新创建的没有字段的属性描述符 。
令 X 为 O 的键为 P 的自有属性。
如果 X 是一个数据属性 ,那么
设置 D .[[Value]] 为 X 的[[Value]] 特性的值。
设置 D .[[Writable]] 为 X 的[[Writable]] 特性的值。
否则,
断言 :X 是一个访问器属性 。
设置 D .[[Get]] 为 X 的[[Get]] 特性的值。
设置 D .[[Set]] 为 X 的[[Set]] 特性的值。
设置 D .[[Enumerable]] 为 X 的[[Enumerable]] 特性的值。
设置 D .[[Configurable]] 为 X 的[[Configurable]] 特性的值。
返回 D 。
10.1.6 [[DefineOwnProperty]] (
P , Desc )
普通对象
O 的[[DefineOwnProperty]] 内部方法接受参数P (一个属性键 )和Desc (一个属性描述符 ),返回包含 Boolean的正常完成 或抛出完成 。调用时执行以下步骤:
返回 ? OrdinaryDefineOwnProperty (O ,
P , Desc )。
10.1.6.1 OrdinaryDefineOwnProperty ( O , P ,
Desc )
抽象操作OrdinaryDefineOwnProperty接受参数O (一个Object)、P (一个属性键 )和Desc (一个属性描述符 ),返回包含 Boolean的正常完成 或抛出完成 。调用时执行以下步骤:
令 current 为 ? O .[[GetOwnProperty]] (P )。
令 extensible 为 ? IsExtensible (O )。
返回 ValidateAndApplyPropertyDescriptor (O ,
P , extensible , Desc , current )。
10.1.6.2 IsCompatiblePropertyDescriptor ( Extensible ,
Desc , Current )
抽象操作IsCompatiblePropertyDescriptor接受参数Extensible (一个Boolean)、Desc (一个属性描述符 )和Current (一个属性描述符 或undefined ),返回一个Boolean。调用时执行以下步骤:
返回 ValidateAndApplyPropertyDescriptor (undefined ,
"" , Extensible , Desc , Current )。
10.1.6.3 ValidateAndApplyPropertyDescriptor ( O ,
P , extensible , Desc , current )
抽象操作ValidateAndApplyPropertyDescriptor接受参数O (一个Object或undefined )、P (一个属性键 )、extensible (一个Boolean)、Desc (一个属性描述符 )和current (一个属性描述符 或undefined ),返回一个Boolean。当且仅当Desc 可以作为具有指定extensibility 和当前属性current 的对象的属性应用,同时维护不变量 时,它返回true 。当这种应用是可能的且O 不是undefined 时,它对名为P 的属性执行此操作(必要时创建该属性)。调用时执行以下步骤:
断言 :P 是一个属性键 。
如果 current 为 undefined ,那么
如果 extensible 为 false ,返回
false 。
如果 O 为 undefined ,返回 true 。
如果 IsAccessorDescriptor (Desc )
为 true ,那么
在对象O 上创建一个名为P 的自有访问器属性 ,其[[Get]] 、[[Set]] 、[[Enumerable]] 和[[Configurable]] 特性分别设置为Desc 中对应字段的值(如果Desc 有该字段),否则设置为该特性的默认值 。
否则,
在对象O 上创建一个名为P 的自有数据属性 ,其[[Value]] 、[[Writable]] 、[[Enumerable]] 和[[Configurable]] 特性分别设置为Desc 中对应字段的值(如果Desc 有该字段),否则设置为该特性的默认值 。
返回 true 。
断言 :current 是一个完全填充的属性描述符 。
如果 Desc 没有任何字段,返回 true 。
如果 current .[[Configurable]] 为
false ,那么
如果 Desc 有[[Configurable]] 字段且Desc .[[Configurable]] 为 true ,返回
false 。
如果 Desc 有[[Enumerable]] 字段且Desc .[[Enumerable]] 不等于 current .[[Enumerable]] ,返回 false 。
如果 IsGenericDescriptor (Desc )
为 false 且 IsAccessorDescriptor (Desc )
不等于 IsAccessorDescriptor (current ),返回
false 。
如果 IsAccessorDescriptor (current )
为 true ,那么
如果 Desc 有[[Get]] 字段且SameValue (Desc .[[Get]] , current .[[Get]] ) 为 false ,返回
false 。
如果 Desc 有[[Set]] 字段且SameValue (Desc .[[Set]] , current .[[Set]] ) 为 false ,返回
false 。
否则如果 current .[[Writable]] 为
false ,那么
如果 Desc 有[[Writable]] 字段且Desc .[[Writable]] 为 true ,返回
false 。
注:SameValue 对NaN 值返回true ,这些值可能通过其他方式区分。在此处返回确保O 的任何现有属性保持未修改。
如果 Desc 有[[Value]] 字段,返回
SameValue (Desc .[[Value]] , current .[[Value]] )。
如果 O 不是 undefined ,那么
如果 IsDataDescriptor (current )
为 true 且 IsAccessorDescriptor (Desc )
为 true ,那么
如果 Desc 有[[Configurable]] 字段,令
configurable 为 Desc .[[Configurable]] ;否则令 configurable
为 current .[[Configurable]] 。
如果 Desc 有[[Enumerable]] 字段,令
enumerable 为 Desc .[[Enumerable]] ;否则令 enumerable 为
current .[[Enumerable]] 。
将对象O 的名为P 的属性替换为一个访问器属性 ,其[[Configurable]] 和[[Enumerable]] 特性分别设置为configurable 和enumerable ,其[[Get]] 和[[Set]] 特性设置为Desc 中对应字段的值(如果Desc 有该字段),否则设置为该特性的默认值 。
否则如果 IsAccessorDescriptor (current )
为 true 且 IsDataDescriptor (Desc )
为 true ,那么
如果 Desc 有[[Configurable]] 字段,令
configurable 为 Desc .[[Configurable]] ;否则令 configurable
为 current .[[Configurable]] 。
如果 Desc 有[[Enumerable]] 字段,令
enumerable 为 Desc .[[Enumerable]] ;否则令 enumerable 为
current .[[Enumerable]] 。
将对象O 的名为P 的属性替换为一个数据属性 ,其[[Configurable]] 和[[Enumerable]] 特性分别设置为configurable 和enumerable ,其[[Value]] 和[[Writable]] 特性设置为Desc 中对应字段的值(如果Desc 有该字段),否则设置为该特性的默认值 。
否则,
对于Desc 的每个字段,将对象O 的名为P 的属性的对应特性设置为该字段的值。
返回 true 。
10.1.7 [[HasProperty]] ( P )
普通对象
O 的[[HasProperty]] 内部方法接受参数P (一个属性键 ),返回包含 Boolean的正常完成 或抛出完成 。调用时执行以下步骤:
返回 ? OrdinaryHasProperty (O ,
P )。
10.1.7.1 OrdinaryHasProperty ( O , P )
抽象操作OrdinaryHasProperty接受参数O (一个Object)和P (一个属性键 ),返回包含 Boolean的正常完成 或抛出完成 。调用时执行以下步骤:
令 hasOwn 为 ? O .[[GetOwnProperty]] (P )。
如果 hasOwn 不是 undefined ,返回 true 。
令 parent 为 ? O .[[GetPrototypeOf]] ()。
如果 parent 不是 null ,那么
返回 ? parent .[[HasProperty]] (P )。
返回 false 。
10.1.8 [[Get]] ( P ,
Receiver )
普通对象
O 的[[Get]] 内部方法接受参数P (一个属性键 )和Receiver (一个ECMAScript语言值 ),返回包含 ECMAScript语言值 的正常完成 或抛出完成 。调用时执行以下步骤:
返回 ? OrdinaryGet (O , P ,
Receiver )。
10.1.8.1 OrdinaryGet ( O , P ,
Receiver )
抽象操作OrdinaryGet接受参数O (一个Object)、P (一个属性键 )和Receiver (一个ECMAScript语言值 ),返回包含 ECMAScript语言值 的正常完成 或抛出完成 。调用时执行以下步骤:
令 desc 为 ? O .[[GetOwnProperty]] (P )。
如果 desc 为 undefined ,那么
令 parent 为 ? O .[[GetPrototypeOf]] ()。
如果 parent 为 null ,返回
undefined 。
返回 ? parent .[[Get]] (P ,
Receiver )。
如果 IsDataDescriptor (desc )
为 true ,返回 desc .[[Value]] 。
断言 :IsAccessorDescriptor (desc )
为 true 。
令 getter 为 desc .[[Get]] 。
如果 getter 为 undefined ,返回 undefined 。
返回 ? Call (getter ,
Receiver )。
10.1.9 [[Set]] ( P ,
V , Receiver )
普通对象
O 的[[Set]] 内部方法接受参数P (一个属性键 )、V (一个ECMAScript语言值 )和Receiver (一个ECMAScript语言值 ),返回包含 Boolean的正常完成 或抛出完成 。调用时执行以下步骤:
返回 ? OrdinarySet (O , P ,
V , Receiver )。
10.1.9.1 OrdinarySet ( O , P , V ,
Receiver )
抽象操作OrdinarySet接受参数O (一个Object)、P (一个属性键 )、V (一个ECMAScript语言值 )和Receiver (一个ECMAScript语言值 ),返回包含 Boolean的正常完成 或抛出完成 。调用时执行以下步骤:
令 ownDesc 为 ? O .[[GetOwnProperty]] (P )。
返回 ? OrdinarySetWithOwnDescriptor (O ,
P , V , Receiver , ownDesc )。
10.1.9.2 OrdinarySetWithOwnDescriptor ( O ,
P , V , Receiver , ownDesc )
抽象操作OrdinarySetWithOwnDescriptor接受参数O (一个Object)、P (一个属性键 )、V (一个ECMAScript语言值 )、Receiver (一个ECMAScript语言值 )和ownDesc (一个属性描述符 或undefined ),返回包含 Boolean的正常完成 或抛出完成 。调用时执行以下步骤:
如果 ownDesc 为 undefined ,那么
令 parent 为 ? O .[[GetPrototypeOf]] ()。
如果 parent 不是 null ,那么
返回 ? parent .[[Set]] (P ,
V , Receiver )。
否则,
设置 ownDesc 为属性描述符 { [[Value]] :
undefined ,
[[Writable]] : true , [[Enumerable]] : true ,
[[Configurable]] :
true }。
如果 IsDataDescriptor (ownDesc )
为 true ,那么
如果 ownDesc .[[Writable]] 为
false ,返回 false 。
如果 Receiver 不是Object ,返回
false 。
令 existingDescriptor 为 ? Receiver .[[GetOwnProperty]] (P )。
如果 existingDescriptor 不是 undefined ,那么
如果 IsAccessorDescriptor (existingDescriptor )
为 true ,返回 false 。
如果 existingDescriptor .[[Writable]] 为 false ,
返回 false 。
令 valueDesc 为属性描述符 { [[Value]] :
V }。
返回 ? Receiver .[[DefineOwnProperty]] (P ,
valueDesc )。
否则,
断言 :Receiver 当前没有属性
P 。
返回 ? CreateDataProperty (Receiver ,
P , V )。
断言 :IsAccessorDescriptor (ownDesc )
为 true 。
令 setter 为 ownDesc .[[Set]] 。
如果 setter 为 undefined ,返回 false 。
执行 ? Call (setter ,
Receiver , « V »)。
返回 true 。
10.1.10 [[Delete]] ( P )
普通对象
O 的[[Delete]] 内部方法接受参数P (一个属性键 ),返回包含 Boolean的正常完成 或抛出完成 。调用时执行以下步骤:
返回 ? OrdinaryDelete (O , P )。
10.1.10.1 OrdinaryDelete ( O , P )
抽象操作OrdinaryDelete接受参数O (一个Object)和P (一个属性键 ),返回包含 Boolean的正常完成 或抛出完成 。调用时执行以下步骤:
令 desc 为 ? O .[[GetOwnProperty]] (P )。
如果 desc 为 undefined ,返回 true 。
如果 desc .[[Configurable]] 为
true ,那么
从 O 中移除名为 P 的自有属性。
返回 true 。
返回 false 。
10.1.11 [[OwnPropertyKeys]] ( )
普通对象
O 的[[OwnPropertyKeys]] 内部方法不接受参数,返回一个包含 属性键 的列表 的正常完成 。调用时执行以下步骤:
返回 OrdinaryOwnPropertyKeys (O )。
10.1.11.1 OrdinaryOwnPropertyKeys ( O )
抽象操作OrdinaryOwnPropertyKeys接受参数O (一个Object),返回一个属性键 的列表 。调用时执行以下步骤:
令 keys 为一个新的空列表 。
对于 O 的每个自有属性键 P ,满足 P
是数组索引 ,按升序数字索引顺序,执行
将 P 追加到 keys 。
对于 O 的每个自有属性键 P ,满足 P
是字符串 且
P 不是数组索引 ,按属性创建的升序时间顺序,执行
将 P 追加到 keys 。
对于 O 的每个自有属性键 P ,满足 P
是Symbol ,按属性创建的升序时间顺序,执行
将 P 追加到 keys 。
返回 keys 。
10.1.12 OrdinaryObjectCreate ( proto [ ,
additionalInternalSlotsList ] )
抽象操作OrdinaryObjectCreate接受参数proto (一个Object或null )和可选参数additionalInternalSlotsList (内部插槽名称的列表 ),返回一个Object。它用于指定新普通对象 的运行时创建。additionalInternalSlotsList 包含除[[Prototype]] 和[[Extensible]] 之外必须作为对象一部分定义的附加内部插槽的名称。如果未提供additionalInternalSlotsList ,则使用一个新的空列表 。调用时执行以下步骤:
令 internalSlotsList 为 « [[Prototype]] , [[Extensible]] »。
如果 additionalInternalSlotsList 存在,设置 internalSlotsList 为
internalSlotsList 和 additionalInternalSlotsList 的列表连接 。
令 O 为 MakeBasicObject (internalSlotsList )。
设置 O .[[Prototype]] 为 proto 。
返回 O 。
注
虽然OrdinaryObjectCreate除了调用MakeBasicObject 之外没有做更多的事情,但它的使用传达了创建普通对象 而不是奇异对象的意图。因此,在本规范中,任何随后以会使结果变成非普通对象的方式修改对象内部方法的算法都不会调用它。创建奇异对象 的操作直接调用MakeBasicObject 。
10.1.13 OrdinaryCreateFromConstructor ( constructor ,
intrinsicDefaultProto [ , internalSlotsList ] )
抽象操作OrdinaryCreateFromConstructor接受参数constructor (一个函数对象 )和intrinsicDefaultProto (一个字符串)以及可选参数internalSlotsList (内部插槽名称的列表 ),返回包含 Object的正常完成 或抛出完成 。它创建一个普通对象 ,其[[Prototype]] 值从构造器 的"prototype" 属性中检索(如果存在)。否则,由intrinsicDefaultProto 命名的内在值用于[[Prototype]] 。internalSlotsList 包含必须作为对象一部分定义的附加内部插槽的名称。如果未提供internalSlotsList ,则使用一个新的空列表 。调用时执行以下步骤:
断言 :intrinsicDefaultProto 是本规范的内在对象名称。对应的对象必须是旨在用作对象的[[Prototype]] 值的内在值。
令 proto 为 ? GetPrototypeFromConstructor (constructor ,
intrinsicDefaultProto )。
如果 internalSlotsList 存在,令 slotsList 为
internalSlotsList 。
否则,令 slotsList 为一个新的空列表 。
返回 OrdinaryObjectCreate (proto ,
slotsList )。
10.1.14 GetPrototypeFromConstructor ( constructor ,
intrinsicDefaultProto )
抽象操作GetPrototypeFromConstructor接受参数constructor (一个函数对象 )和intrinsicDefaultProto (一个字符串),返回包含 Object的正常完成 或抛出完成 。它确定应该用于创建对应于特定构造器 的对象的[[Prototype]] 值。该值从构造器 的"prototype" 属性中检索(如果存在)。否则,由intrinsicDefaultProto 命名的内在值用于[[Prototype]] 。调用时执行以下步骤:
断言 :intrinsicDefaultProto 是本规范的内在对象名称。对应的对象必须是旨在用作对象的[[Prototype]] 值的内在值。
令 proto 为 ? Get (constructor ,
"prototype" )。
如果 proto 不是Object ,那么
令 realm 为 ? GetFunctionRealm (constructor )。
设置 proto 为 realm 的名为 intrinsicDefaultProto
的内在对象。
返回 proto 。
注
如果constructor 不提供[[Prototype]] 值,则使用的默认值从constructor 函数的领域 获得,而不是从运行执行上下文 获得。
10.1.15 RequireInternalSlot ( O , internalSlot
)
抽象操作RequireInternalSlot接受参数O (一个ECMAScript语言值 )和internalSlot (一个内部插槽名称),返回包含 unused 的正常完成 或抛出完成 。除非O
是Object 且具有给定的内部插槽,否则它会抛出异常。调用时执行以下步骤:
如果 O 不是Object ,抛出 TypeError
异常。
如果 O 没有 internalSlot 内部插槽,抛出 TypeError 异常。
返回 unused 。
10.2 ECMAScript函数对象
ECMAScript函数对象 封装了在词法环境上封闭的参数化ECMAScript代码,并支持该代码的动态评估。ECMAScript函数对象 是一个普通对象 ,具有与其他普通对象 相同的内部插槽和相同的内部方法。ECMAScript函数对象 的代码可以是严格模式代码 (11.2.2 )或非严格代码 。代码为严格模式代码 的ECMAScript函数对象 称为严格函数 。代码不是严格模式代码 的称为非严格函数 。
除了[[Extensible]] 和[[Prototype]] 之外,ECMAScript函数对象 还具有表30 中列出的内部插槽。
表30:ECMAScript函数对象的内部插槽
内部插槽
类型
描述
[[Environment]]
一个环境记录
函数封闭的环境记录 。在评估函数代码时用作外部环境。
[[PrivateEnvironment]]
一个私有环境记录 或null
函数封闭的私有名称 的私有环境记录 。如果此函数在语法上不包含在类中,则为null 。在评估函数代码时用作内部类的外部私有环境。
[[FormalParameters]]
一个解析节点
定义函数形式参数列表的源文本的根解析节点。
[[ECMAScriptCode]]
一个解析节点
定义函数体的源文本的根解析节点。
[[ConstructorKind]]
base 或derived
函数是否为派生类构造器 。
[[Realm]]
一个领域记录
创建函数的领域 ,它提供在评估函数时访问的任何内在对象。
[[ScriptOrModule]]
一个脚本记录 或一个模块记录
创建函数的脚本或模块。
[[ThisMode]]
lexical 、strict 或global
定义如何在函数的形式参数和代码体中解释this
引用。lexical 表示this
引用词法封闭函数的this 值。strict 表示this 值完全按照函数调用提供的使用。global 表示undefined 或null 的this 值被解释为对全局对象 的引用,任何其他this 值首先传递给ToObject 。
[[Strict]]
一个Boolean
如果这是严格函数 则为true ,如果这是非严格函数 则为false 。
[[HomeObject]]
一个Object
如果函数使用super
,这是其[[GetPrototypeOf]] 提供super
属性查找开始的对象的对象。
[[SourceText]]
Unicode代码点序列
定义函数的源文本 。
[[Fields]]
类字段定义记录 的列表
如果函数是类,这是表示类的非静态字段和相应初始化器的记录 列表。
[[PrivateMethods]]
私有元素 的列表
如果函数是类,这是表示类的非静态私有方法和访问器的列表。
[[ClassFieldInitializerName]]
一个字符串、一个Symbol、一个私有名称 或empty
如果函数是作为类字段的初始化器创建的,则为字段的命名评估 使用的名称;否则为empty 。
[[IsClassConstructor]]
一个Boolean
指示函数是否为类构造器 。(如果为true ,调用函数的[[Call]] 将立即抛出TypeError 异常。)
所有ECMAScript函数对象 都有此处定义的[[Call]] 内部方法。同时也是构造器 的ECMAScript函数另外还有[[Construct]] 内部方法。
10.2.1 [[Call]] ( thisArgument ,
argumentsList )
ECMAScript函数对象 F 的[[Call]] 内部方法接受参数thisArgument (一个ECMAScript语言值 )和argumentsList (ECMAScript语言值 的列表 ),返回包含 ECMAScript语言值 的正常完成 或抛出完成 。调用时执行以下步骤:
令 callerContext 为运行执行上下文 。
令 calleeContext 为 PrepareForOrdinaryCall (F ,
undefined )。
断言 :calleeContext 现在是运行执行上下文 。
如果 F .[[IsClassConstructor]] 为
true ,那么
令 error 为新创建的 TypeError 对象。
注:error 在calleeContext 中使用F 的关联领域记录 创建。
从执行上下文栈 中移除calleeContext 并恢复callerContext 为运行执行上下文 。
返回 ThrowCompletion (error )。
执行 OrdinaryCallBindThis (F ,
calleeContext , thisArgument )。
令 result 为 Completion (OrdinaryCallEvaluateBody (F ,
argumentsList ))。
从执行上下文栈 中移除calleeContext 并恢复callerContext 为运行执行上下文 。
如果 result 是返回完成 ,返回
result .[[Value]] 。
断言 :result 是抛出完成 。
返回 ? result 。
注
当在步骤7 中从执行上下文栈 中移除calleeContext 时,如果它被挂起并保留以供可访问的生成器稍后恢复,则不得销毁它。
10.2.1.1 PrepareForOrdinaryCall ( F ,
newTarget )
抽象操作PrepareForOrdinaryCall接受参数F (一个ECMAScript函数对象 )和newTarget (一个Object或undefined ),返回一个执行上下文 。调用时执行以下步骤:
令 callerContext 为运行执行上下文 。
令 calleeContext 为新的ECMAScript代码执行上下文 。
设置 calleeContext 的Function为 F 。
令 calleeRealm 为 F .[[Realm]] 。
设置 calleeContext 的领域 为 calleeRealm 。
设置 calleeContext 的ScriptOrModule为 F .[[ScriptOrModule]] 。
令 localEnv 为 NewFunctionEnvironment (F ,
newTarget )。
设置 calleeContext 的LexicalEnvironment为 localEnv 。
设置 calleeContext 的VariableEnvironment为 localEnv 。
设置 calleeContext 的PrivateEnvironment为 F .[[PrivateEnvironment]] 。
如果 callerContext 尚未挂起,挂起 callerContext 。
将 calleeContext 推入执行上下文栈 ;calleeContext 现在是运行执行上下文 。
注:此点之后产生的任何异常对象都与 calleeRealm 关联。
返回 calleeContext 。
10.2.1.2 OrdinaryCallBindThis ( F ,
calleeContext , thisArgument )
抽象操作OrdinaryCallBindThis接受参数F (一个ECMAScript函数对象 )、calleeContext (一个执行上下文 )和thisArgument (一个ECMAScript语言值 ),返回unused 。调用时执行以下步骤:
令 thisMode 为 F .[[ThisMode]] 。
如果 thisMode 为 lexical ,返回
unused 。
令 calleeRealm 为 F .[[Realm]] 。
令 localEnv 为 calleeContext 的LexicalEnvironment。
如果 thisMode 为 strict ,那么
令 thisValue 为 thisArgument 。
否则,
如果 thisArgument 为 undefined 或
null ,那么
令 globalEnv 为 calleeRealm .[[GlobalEnv]] 。
断言 :globalEnv 是全局环境记录 。
令 thisValue 为 globalEnv .[[GlobalThisValue]] 。
否则,
令 thisValue 为 ! ToObject (thisArgument )。
注:ToObject 使用calleeRealm 产生包装器对象。
断言 :localEnv 是函数环境记录 。
断言 :下一步永远不会返回突然完成 ,因为localEnv .[[ThisBindingStatus]] 不是initialized 。
执行 ! BindThisValue (localEnv ,
thisValue )。
返回 unused 。
10.2.1.3 运行时语义:EvaluateBody
语法导向操作 EvaluateBody接受参数functionObject (一个ECMAScript函数对象 )和argumentsList (ECMAScript语言值 的列表 ),返回返回完成 或抛出完成 。它在以下产生式上分段定义:
FunctionBody :
FunctionStatementList
返回 ? FunctionBody 的 EvaluateFunctionBody ,参数为
functionObject 和 argumentsList 。
ConciseBody :
ExpressionBody
返回 ? ConciseBody 的 EvaluateConciseBody ,参数为
functionObject 和 argumentsList 。
GeneratorBody :
FunctionBody
返回 ? GeneratorBody 的 EvaluateGeneratorBody ,参数为
functionObject 和 argumentsList 。
AsyncGeneratorBody
: FunctionBody
返回 ? AsyncGeneratorBody 的 EvaluateAsyncGeneratorBody ,参数为
functionObject 和 argumentsList 。
AsyncFunctionBody
: FunctionBody
返回 ? AsyncFunctionBody 的 EvaluateAsyncFunctionBody ,参数为
functionObject 和 argumentsList 。
AsyncConciseBody
: ExpressionBody
返回 ? AsyncConciseBody 的 EvaluateAsyncConciseBody ,参数为
functionObject 和 argumentsList 。
Initializer :
=
AssignmentExpression
断言 :argumentsList 为空。
断言 :functionObject .[[ClassFieldInitializerName]] 不是empty 。
如果 IsAnonymousFunctionDefinition (AssignmentExpression ) 为
true ,那么
令 value 为 ? Initializer 的 NamedEvaluation ,参数为
functionObject .[[ClassFieldInitializerName]] 。
否则,
令 rhs 为 ? AssignmentExpression
的 Evaluation 。
令 value 为 ? GetValue (rhs )。
返回 ReturnCompletion (value )。
注
尽管字段初始化器构成函数边界,但调用FunctionDeclarationInstantiation 没有任何可观察的效果,因此被省略。
ClassStaticBlockBody
: ClassStaticBlockStatementList
断言 :argumentsList 为空。
返回 ? ClassStaticBlockBody 的
EvaluateClassStaticBlockBody ,参数为
functionObject 。
10.2.1.4 OrdinaryCallEvaluateBody ( F ,
argumentsList )
抽象操作OrdinaryCallEvaluateBody接受参数F (一个ECMAScript函数对象 )和argumentsList (ECMAScript语言值 的列表 ),返回返回完成 或抛出完成 。调用时执行以下步骤:
返回 ? F .[[ECMAScriptCode]] 的 EvaluateBody ,参数为 F 和
argumentsList 。
10.2.2 [[Construct]] (
argumentsList , newTarget )
ECMAScript函数对象 F 的[[Construct]] 内部方法接受参数argumentsList (ECMAScript语言值 的列表 )和newTarget (一个构造器 ),返回包含 Object的正常完成 或抛出完成 。调用时执行以下步骤:
令 callerContext 为运行执行上下文 。
令 kind 为 F .[[ConstructorKind]] 。
如果 kind 为 base ,那么
令 thisArgument 为 ? OrdinaryCreateFromConstructor (newTarget ,
"%Object.prototype%" )。
令 calleeContext 为 PrepareForOrdinaryCall (F ,
newTarget )。
断言 :calleeContext 现在是运行执行上下文 。
如果 kind 为 base ,那么
执行 OrdinaryCallBindThis (F ,
calleeContext , thisArgument )。
令 initializeResult 为 Completion (InitializeInstanceElements (thisArgument ,
F ))。
如果 initializeResult 是突然完成 ,那么
从执行上下文栈 中移除calleeContext 并恢复callerContext 为运行执行上下文 。
返回 ? initializeResult 。
令 constructorEnv 为 calleeContext 的LexicalEnvironment。
令 result 为 Completion (OrdinaryCallEvaluateBody (F ,
argumentsList ))。
从执行上下文栈 中移除calleeContext 并恢复callerContext 为运行执行上下文 。
如果 result 是抛出完成 ,那么
返回 ? result 。
断言 :result 是返回完成 。
如果 result .[[Value]] 是Object ,返回 result .[[Value]] 。
如果 kind 为 base ,返回 thisArgument 。
如果 result .[[Value]] 不是
undefined ,抛出 TypeError 异常。
令 thisBinding 为 ? constructorEnv .GetThisBinding()。
断言 :thisBinding 是Object 。
返回 thisBinding 。
10.2.3 OrdinaryFunctionCreate ( functionPrototype ,
sourceText , ParameterList , Body , thisMode ,
env , privateEnv )
抽象操作OrdinaryFunctionCreate接受参数functionPrototype (一个Object)、sourceText (Unicode代码点序列)、ParameterList (一个解析节点 )、Body (一个解析节点 )、thisMode (lexical-this 或non-lexical-this )、env (一个环境记录 )和privateEnv (一个私有环境记录 或null ),返回一个ECMAScript函数对象 。它用于指定运行时创建具有默认[[Call]] 内部方法且没有[[Construct]] 内部方法的新函数(尽管随后可能通过诸如MakeConstructor 之类的操作添加一个)。sourceText 是要创建的函数的语法定义的源文本。调用时执行以下步骤:
令 internalSlotsList 为表30 中列出的内部插槽。
令 F 为 OrdinaryObjectCreate (functionPrototype ,
internalSlotsList )。
设置 F .[[Call]] 为10.2.1 中指定的定义。
设置 F .[[SourceText]] 为 sourceText 。
设置 F .[[FormalParameters]] 为
ParameterList 。
设置 F .[[ECMAScriptCode]] 为 Body 。
令 Strict 为 IsStrict (Body )。
设置 F .[[Strict]] 为 Strict 。
如果 thisMode 为 lexical-this ,设置 F .[[ThisMode]] 为 lexical 。
否则,如果 Strict 为 true ,设置 F .[[ThisMode]] 为 strict 。
否则,设置 F .[[ThisMode]] 为
global 。
设置 F .[[IsClassConstructor]] 为
false 。
设置 F .[[Environment]] 为 env 。
设置 F .[[PrivateEnvironment]] 为 privateEnv 。
设置 F .[[ScriptOrModule]] 为 GetActiveScriptOrModule ()。
设置 F .[[Realm]] 为当前领域记录 。
设置 F .[[HomeObject]] 为 undefined 。
设置 F .[[Fields]] 为新的空列表 。
设置 F .[[PrivateMethods]] 为新的空列表 。
设置 F .[[ClassFieldInitializerName]] 为
empty 。
令 len 为 ParameterList 的ExpectedArgumentCount 。
执行 SetFunctionLength (F ,
len )。
返回 F 。
10.2.4 AddRestrictedFunctionProperties ( F ,
realm )
抽象操作AddRestrictedFunctionProperties接受参数F (一个函数对象 )和realm (一个领域记录 ),返回unused 。调用时执行以下步骤:
断言 :realm .[[Intrinsics]] .[[%ThrowTypeError% ]]存在且已被初始化。
令 thrower 为 realm .[[Intrinsics]] .[[%ThrowTypeError% ]]。
执行 ! DefinePropertyOrThrow (F ,
"caller" , PropertyDescriptor { [[Get]] :
thrower , [[Set]] : thrower , [[Enumerable]] : false , [[Configurable]] : true })。
执行 ! DefinePropertyOrThrow (F ,
"arguments" , PropertyDescriptor { [[Get]] :
thrower , [[Set]] : thrower , [[Enumerable]] : false , [[Configurable]] : true })。
返回 unused 。
10.2.4.1 %ThrowTypeError% ( )
此函数是%ThrowTypeError% 内在对象。
它是一个匿名的内置函数对象 ,为每个领域 定义一次。
调用时执行以下步骤:
抛出 TypeError 异常。
此函数的[[Extensible]] 内部插槽的值为false 。
此函数的"length" 属性具有特性{ [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
此函数的"name" 属性具有特性{ [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
10.2.5 MakeConstructor ( F [ ,
writablePrototype [ , prototype ] ] )
抽象操作MakeConstructor接受参数F (一个ECMAScript函数对象 或内置函数对象 )和可选参数writablePrototype (一个Boolean)和prototype (一个Object),返回unused 。它将F 转换为构造器 。调用时执行以下步骤:
如果 F 是ECMAScript函数对象 ,那么
断言 :IsConstructor (F ) 为
false 。
断言 :F 是一个可扩展对象,且没有"prototype" 自身属性。
设置 F .[[Construct]] 为10.2.2 中指定的定义。
否则,
设置 F .[[Construct]] 为10.3.2 中指定的定义。
设置 F .[[ConstructorKind]] 为
base 。
如果 writablePrototype 不存在,设置 writablePrototype 为
true 。
如果 prototype 不存在,那么
设置 prototype 为 OrdinaryObjectCreate (%Object.prototype% )。
执行 ! DefinePropertyOrThrow (prototype ,
"constructor" , PropertyDescriptor { [[Value]] : F , [[Writable]] : writablePrototype , [[Enumerable]] : false , [[Configurable]] : true })。
执行 ! DefinePropertyOrThrow (F ,
"prototype" , PropertyDescriptor { [[Value]] :
prototype , [[Writable]] :
writablePrototype , [[Enumerable]] :
false , [[Configurable]] :
false })。
返回 unused 。
10.2.6 MakeClassConstructor ( F )
抽象操作MakeClassConstructor接受参数F (一个ECMAScript函数对象 ),返回unused 。调用时执行以下步骤:
断言 :F .[[IsClassConstructor]] 为 false 。
设置 F .[[IsClassConstructor]] 为
true 。
返回 unused 。
10.2.7 MakeMethod ( F , homeObject )
抽象操作MakeMethod接受参数F (一个ECMAScript函数对象 )和homeObject (一个Object),返回unused 。它将F 配置为方法。调用时执行以下步骤:
断言 :homeObject 是普通对象 。
设置 F .[[HomeObject]] 为 homeObject 。
返回 unused 。
10.2.8 DefineMethodProperty ( homeObject , key ,
closure , enumerable )
抽象操作DefineMethodProperty接受参数homeObject (一个Object)、key (一个属性键 或私有名称 )、closure (一个函数对象 )和enumerable (一个Boolean),返回包含 私有元素 或unused 的正常完成 ,或突然完成 。调用时执行以下步骤:
断言 :homeObject 是普通的、可扩展的对象。
如果 key 是私有名称 ,那么
返回 私有元素 { [[Key]] : key , [[Kind]] : method , [[Value]] : closure }。
否则,
令 desc 为PropertyDescriptor { [[Value]] :
closure , [[Writable]] :
true , [[Enumerable]] :
enumerable , [[Configurable]] :
true }。
执行 ? DefinePropertyOrThrow (homeObject ,
key , desc )。
注:DefinePropertyOrThrow 仅在尝试定义key 为"prototype" 的类静态方法时返回突然完成 。
返回 unused 。
10.2.9 SetFunctionName ( F , name [ ,
prefix ] )
抽象操作SetFunctionName接受参数F (一个函数对象 )和name (一个属性键 或私有名称 )和可选参数prefix (一个String),返回unused 。它为F 添加"name" 属性。调用时执行以下步骤:
断言 :F 是可扩展对象且没有"name" 自身属性。
如果 name 是Symbol ,那么
令 description 为 name 的[[Description]] 值。
如果 description 为 undefined ,设置 name
为空字符串。
否则,设置 name
为"[" 、description 和"]" 的字符串连接 。
否则,如果 name 是私有名称 ,那么
设置 name 为 name .[[Description]] 。
如果 F 有[[InitialName]] 内部插槽,那么
设置 F .[[InitialName]] 为 name 。
如果 prefix 存在,那么
设置 name 为prefix 、代码单元0x0020(空格)和name 的字符串连接 。
如果 F 有[[InitialName]] 内部插槽,那么
可选地,设置 F .[[InitialName]] 为
name 。
执行 ! DefinePropertyOrThrow (F ,
"name" , PropertyDescriptor { [[Value]] :
name , [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] : true })。
返回 unused 。
10.2.10 SetFunctionLength ( F , length )
抽象操作SetFunctionLength接受参数F (一个函数对象 )和length (非负整数 或+∞),返回unused 。它为F 添加"length" 属性。调用时执行以下步骤:
断言 :F 是可扩展对象且没有"length" 自身属性。
执行 ! DefinePropertyOrThrow (F ,
"length" , PropertyDescriptor { [[Value]] :
𝔽 (length ),
[[Writable]] : false , [[Enumerable]] : false , [[Configurable]] : true })。
返回 unused 。
10.2.11 FunctionDeclarationInstantiation ( func ,
argumentsList )
抽象操作FunctionDeclarationInstantiation接受参数func (一个ECMAScript函数对象 )和argumentsList (ECMAScript语言值 的列表 ),返回包含 unused 的正常完成 或突然完成 。func 是正在为其建立执行上下文 的函数对象 。
注1
当为评估ECMAScript函数建立执行上下文 时,会创建新的函数环境记录 ,并在该环境记录 中实例化每个形参的绑定。函数体中的每个声明也会被实例化。如果函数的形参不包含任何默认值初始化器,则函数体声明会在与参数相同的环境记录 中实例化。如果存在默认值参数初始化器,则为函数体声明创建第二个环境记录 。形参和函数作为FunctionDeclarationInstantiation的一部分被初始化。所有其他绑定在函数体评估期间被初始化。
调用时执行以下步骤:
令 calleeContext 为运行执行上下文 。
令 code 为 func .[[ECMAScriptCode]] 。
令 strict 为 func .[[Strict]] 。
令 formals 为 func .[[FormalParameters]] 。
令 parameterNames 为 formals 的BoundNames 。
如果 parameterNames 有任何重复条目,令 hasDuplicates 为
true 。否则,令 hasDuplicates 为 false 。
令 simpleParameterList 为 formals 的IsSimpleParameterList 。
令 hasParameterExpressions 为 formals 的ContainsExpression 。
令 varNames 为 code 的VarDeclaredNames 。
令 varDeclarations 为 code 的VarScopedDeclarations 。
令 lexicalNames 为 code 的LexicallyDeclaredNames 。
令 functionNames 为新的空列表 。
令 functionsToInitialize 为新的空列表 。
对于 varDeclarations 的每个元素 d ,按反向列表 顺序,执行
如果 d 既不是VariableDeclaration ,也不是ForBinding ,也不是BindingIdentifier ,那么
断言 :d 要么是FunctionDeclaration ,要么是GeneratorDeclaration ,要么是AsyncFunctionDeclaration ,要么是AsyncGeneratorDeclaration 。
令 fn 为 d 的BoundNames 的唯一元素。
如果 functionNames 不包含 fn ,那么
将 fn 作为第一个元素插入 functionNames 。
注:如果有多个同名函数声明,使用最后一个声明。
将 d 作为第一个元素插入 functionsToInitialize 。
令 argumentsObjectNeeded 为 true 。
如果 func .[[ThisMode]] 为
lexical ,那么
注:箭头函数从不有arguments对象。
设置 argumentsObjectNeeded 为 false 。
否则,如果 parameterNames 包含 "arguments" ,那么
设置 argumentsObjectNeeded 为 false 。
否则,如果 hasParameterExpressions 为 false ,那么
如果 functionNames 包含 "arguments" 或
lexicalNames 包含 "arguments" ,那么
设置 argumentsObjectNeeded 为 false 。
如果 strict 为 true 或 hasParameterExpressions 为
false ,那么
注:由于严格模式代码 中对eval
的调用不能创建在eval
之外可见的新绑定,因此参数只需要单一的环境记录 。
令 env 为 calleeContext 的LexicalEnvironment。
否则,
注:需要单独的环境记录 以确保形参列表中直接eval 调用创建的绑定位于声明参数的环境之外。
令 calleeEnv 为 calleeContext 的LexicalEnvironment。
令 env 为 NewDeclarativeEnvironment (calleeEnv )。
断言 :calleeContext
的VariableEnvironment和 calleeEnv 是同一个环境记录 。
设置 calleeContext 的LexicalEnvironment为 env 。
对于 parameterNames 的每个字符串 paramName ,执行
令 alreadyDeclared 为
! env .HasBinding(paramName )。
注:早期错误 确保重复参数名只能出现在没有参数默认值或剩余参数的非严格函数 中。
如果 alreadyDeclared 为 false ,那么
执行 ! env .CreateMutableBinding(paramName ,
false )。
如果 hasDuplicates 为 true ,那么
执行 ! env .InitializeBinding(paramName ,
undefined )。
如果 argumentsObjectNeeded 为 true ,那么
如果 strict 为 true 或 simpleParameterList
为 false ,那么
令 ao 为 CreateUnmappedArgumentsObject (argumentsList )。
否则,
注:映射的参数对象仅为没有剩余参数、任何参数默认值初始化器或任何解构参数的非严格函数 提供。
令 ao 为 CreateMappedArgumentsObject (func ,
formals , argumentsList , env )。
如果 strict 为 true ,那么
执行
! env .CreateImmutableBinding("arguments" ,
false )。
注:在严格模式代码 中,早期错误 防止尝试赋值给此绑定,因此其可变性不可观察。
否则,
执行
! env .CreateMutableBinding("arguments" ,
false )。
执行 ! env .InitializeBinding("arguments" ,
ao )。
令 parameterBindings 为 parameterNames 和 «
"arguments" » 的列表连接 。
否则,
令 parameterBindings 为 parameterNames 。
令 iteratorRecord 为 CreateListIteratorRecord (argumentsList )。
如果 hasDuplicates 为 true ,那么
执行 ? formals 的IteratorBindingInitialization ,参数为
iteratorRecord 和 undefined 。
否则,
执行 ? formals 的IteratorBindingInitialization ,参数为
iteratorRecord 和 env 。
如果 hasParameterExpressions 为 false ,那么
注:参数和顶级var只需要单一的环境记录 。
令 instantiatedVarNames 为列表
parameterBindings 的副本。
对于 varNames 的每个元素 n ,执行
如果 instantiatedVarNames 不包含 n ,那么
将 n 追加到 instantiatedVarNames 。
执行 ! env .CreateMutableBinding(n ,
false )。
执行 ! env .InitializeBinding(n ,
undefined )。
令 varEnv 为 env 。
否则,
注:需要单独的环境记录 以确保形参列表中表达式创建的闭包不能看到函数体中的声明。
令 varEnv 为 NewDeclarativeEnvironment (env )。
设置 calleeContext 的VariableEnvironment为 varEnv 。
令 instantiatedVarNames 为新的空列表 。
对于 varNames 的每个元素 n ,执行
如果 instantiatedVarNames 不包含 n ,那么
将 n 追加到 instantiatedVarNames 。
执行 ! varEnv .CreateMutableBinding(n ,
false )。
如果 parameterBindings 不包含 n ,或如果
functionNames 包含 n ,那么
令 initialValue 为
undefined 。
否则,
令 initialValue 为
! env .GetBindingValue(n ,
false )。
执行 ! varEnv .InitializeBinding(n ,
initialValue )。
注:与形参同名的var最初具有与相应初始化参数相同的值。
注:附录B.3.2.1 在此处添加了额外的步骤。
如果 strict 为 false ,那么
令 lexEnv 为 NewDeclarativeEnvironment (varEnv )。
注:非严格函数 对顶级词法声明使用单独的环境记录 ,以便直接eval 可以确定eval代码引入的任何var作用域声明是否与预先存在的顶级词法作用域声明冲突。这对于严格函数 不是必需的,因为严格的直接eval 总是将所有声明放入新的环境记录 中。
否则,
令 lexEnv 为 varEnv 。
设置 calleeContext 的LexicalEnvironment为 lexEnv 。
令 lexDeclarations 为 code 的LexicallyScopedDeclarations 。
对于 lexDeclarations 的每个元素 d ,执行
注:词法声明的名称不能与函数/生成器声明、形参或var名称相同。词法声明的名称仅在此处实例化但未初始化。
对于 d 的BoundNames 的每个元素
dn ,执行
如果 d 的IsConstantDeclaration 为
true ,那么
执行
! lexEnv .CreateImmutableBinding(dn ,
true )。
否则,
执行 ! lexEnv .CreateMutableBinding(dn ,
false )。
令 privateEnv 为 calleeContext 的PrivateEnvironment。
对于 functionsToInitialize 的每个解析节点 f ,执行
令 fn 为 f 的BoundNames 的唯一元素。
令 fo 为 f 的InstantiateFunctionObject ,参数为
lexEnv 和 privateEnv 。
执行 ! varEnv .SetMutableBinding(fn , fo ,
false )。
返回 unused 。
注2
B.3.2 为上述算法提供了扩展,这对于与早于ECMAScript
2015的ECMAScript的Web浏览器实现的向后兼容性是必需的。
10.3 内置函数对象
内置函数对象 是普通对象 ;它必须满足10.1 中规定的普通对象 的要求。
除了每个普通对象 所需的内部插槽(见10.1 )之外,内置函数对象 还必须具有以下内部插槽:
[[Realm]] ,一个领域记录 ,表示创建函数的领域 。
[[InitialName]] ,一个字符串,是函数的初始名称。它被20.2.3.5 使用。
内置函数对象 的[[Prototype]] 内部插槽的初始值是%Function.prototype% ,除非另有规定。
内置函数对象 必须具有符合10.3.1 中定义的[[Call]] 内部方法。
内置函数对象 当且仅当它被描述为"构造器 ",或者本规范中的某个算法明确设置其[[Construct]] 内部方法时,才具有[[Construct]] 内部方法。这样的[[Construct]] 内部方法必须符合10.3.2 中的定义。
实现可以提供本规范中未定义的其他内置函数对象 。
10.3.1 [[Call]] ( thisArgument ,
argumentsList )
内置函数对象
F 的[[Call]] 内部方法接受参数thisArgument (ECMAScript语言值 )和argumentsList (ECMAScript语言值 的列表 ),返回包含 ECMAScript语言值 的正常完成 或抛出完成 。调用时执行以下步骤:
返回 ? BuiltinCallOrConstruct (F ,
thisArgument , argumentsList , undefined )。
10.3.2 [[Construct]] (
argumentsList , newTarget )
内置函数对象
F 的[[Construct]] 内部方法(当该方法存在时)接受参数argumentsList (ECMAScript语言值 的列表 )和newTarget (一个构造器 ),返回包含 Object的正常完成 或抛出完成 。调用时执行以下步骤:
令 result 为 ? BuiltinCallOrConstruct (F ,
uninitialized , argumentsList , newTarget )。
断言 :result 是Object 。
返回 result 。
10.3.3 BuiltinCallOrConstruct ( F ,
thisArgument , argumentsList , newTarget )
抽象操作BuiltinCallOrConstruct接受参数F (内置函数对象 )、thisArgument (ECMAScript语言值 或uninitialized )、argumentsList (ECMAScript语言值 的列表 )和newTarget (构造器 或undefined ),返回包含 ECMAScript语言值 的正常完成 或抛出完成 。调用时执行以下步骤:
令 callerContext 为运行执行上下文 。
如果 callerContext 尚未被挂起,挂起 callerContext 。
令 calleeContext 为新的执行上下文 。
设置 calleeContext 的Function为 F 。
令 calleeRealm 为 F .[[Realm]] 。
设置 calleeContext 的领域 为 calleeRealm 。
设置 calleeContext 的ScriptOrModule为 null 。
执行 calleeContext 的任何必要的实现定义的 初始化。
将 calleeContext 推入执行上下文栈 ;calleeContext
现在是运行执行上下文 。
令 result 为完成记录 ,其为评估结果 ,以符合 F 规范的方式评估 F 。如果
thisArgument 为 uninitialized ,则 this
值未初始化;否则,thisArgument 提供 this 值。argumentsList
提供具名参数。newTarget 提供NewTarget值。
注:如果 F 在本文档中定义,"F 的规范"是通过算法步骤或其他方式为其指定的行为。
从执行上下文栈 中移除
calleeContext 并将 callerContext 恢复为运行执行上下文 。
返回 ? result 。
注
当从执行上下文栈 中移除
calleeContext 时,如果它已被挂起并被可访问的生成器保留以供稍后恢复,则不得销毁它。
10.3.4 CreateBuiltinFunction ( behaviour ,
length , name , additionalInternalSlotsList [ , realm
[ , prototype [ , prefix ] ] ] )
抽象操作CreateBuiltinFunction接受参数behaviour (抽象闭包 、一组算法步骤或本规范中提供的函数行为的某些其他定义)、length (非负整数 或+∞)、name (属性键 或私有名称 )和additionalInternalSlotsList (内部插槽名称的列表 )和可选参数realm (领域记录 )、prototype (Object或null )和prefix (字符串),返回内置函数对象 。additionalInternalSlotsList
包含必须作为对象的一部分定义的其他内部插槽的名称。此操作创建内置函数对象 。调用时执行以下步骤:
如果 realm 不存在,设置 realm 为当前领域记录 。
如果 prototype 不存在,设置 prototype 为
realm .[[Intrinsics]] .[[%Function.prototype% ]]。
令 internalSlotsList 为列表 ,包含10.3 为即将创建的内置函数对象 所需的所有内部插槽的名称。
将 additionalInternalSlotsList 的元素追加到 internalSlotsList 。
令 func 为新的内置函数对象 ,当调用时,使用提供的参数作为 behaviour
指定的相应参数的值,执行 behaviour 描述的操作。新的函数对象 具有名称为
internalSlotsList 元素的内部插槽,以及 [[InitialName]] 内部插槽。
设置 func .[[Prototype]] 为 prototype 。
设置 func .[[Extensible]] 为 true 。
设置 func .[[Realm]] 为 realm 。
设置 func .[[InitialName]] 为 null 。
执行 SetFunctionLength (func ,
length )。
如果 prefix 不存在,那么
执行 SetFunctionName (func ,
name )。
否则,
执行 SetFunctionName (func ,
name , prefix )。
返回 func 。
本规范中定义的每个内置函数都是通过调用CreateBuiltinFunction抽象操作创建的。
10.4 内置异质对象内部方法和插槽
本规范定义了几种内置异质对象 。这些对象通常表现得像普通对象 ,除了一些特定情况。以下异质对象 使用普通对象 的内部方法,除非在下面明确指定了其他方法:
10.4.1 绑定函数异质对象
绑定函数异质对象 是一个异质对象 ,它包装另一个函数对象 。绑定函数异质对象 是可调用的(它有[[Call]] 内部方法,可能有[[Construct]] 内部方法)。调用绑定函数异质对象 通常会调用其包装的函数。
如果对象的[[Call]] 和(如果适用)[[Construct]] 内部方法使用以下实现,其他基本内部方法使用10.1 中的定义,则该对象是绑定函数异质对象 。这些方法在BoundFunctionCreate 中安装。
绑定函数异质对象 没有表30 中列出的ECMAScript函数对象 的内部插槽。相反,除了[[Prototype]] 和[[Extensible]] 之外,它们还有表31 中列出的内部插槽。
表31:绑定函数异质对象的内部插槽
内部插槽
类型
描述
[[BoundTargetFunction]]
可调用对象
被包装的函数对象 。
[[BoundThis]]
ECMAScript语言值
调用包装函数时总是作为this 值传递的值。
[[BoundArguments]]
ECMAScript语言值 的列表
一个值列表,其元素用作对包装函数的任何调用的前几个参数。
10.4.1.1 [[Call]] (
thisArgument , argumentsList )
绑定函数异质对象 F 的[[Call]] 内部方法接受参数thisArgument (ECMAScript语言值 )和argumentsList (ECMAScript语言值 的列表 ),返回包含 ECMAScript语言值 的正常完成 或抛出完成 。调用时执行以下步骤:
令 target 为 F .[[BoundTargetFunction]] 。
令 boundThis 为 F .[[BoundThis]] 。
令 boundArgs 为 F .[[BoundArguments]] 。
令 args 为 boundArgs 和 argumentsList 的列表连接 。
返回 ? Call (target ,
boundThis , args )。
10.4.1.2 [[Construct]] (
argumentsList , newTarget )
绑定函数异质对象 F 的[[Construct]] 内部方法接受参数argumentsList (ECMAScript语言值 的列表 )和newTarget (构造器 ),返回包含 对象的正常完成 或抛出完成 。调用时执行以下步骤:
令 target 为 F .[[BoundTargetFunction]] 。
断言 :IsConstructor (target ) 为
true 。
令 boundArgs 为 F .[[BoundArguments]] 。
令 args 为 boundArgs 和 argumentsList 的列表连接 。
如果 SameValue (F ,
newTarget ) 为 true ,设置 newTarget 为
target 。
返回 ? Construct (target ,
args , newTarget )。
10.4.1.3 BoundFunctionCreate ( targetFunction ,
boundThis , boundArgs )
抽象操作BoundFunctionCreate接受参数targetFunction (函数对象 )、boundThis (ECMAScript语言值 )和boundArgs (ECMAScript语言值 的列表 ),返回包含 函数对象 的正常完成 或抛出完成 。它用于指定新绑定函数异质对象 的创建。调用时执行以下步骤:
令 proto 为 ? targetFunction .[[GetPrototypeOf]] ()。
令 internalSlotsList 为 « [[Prototype]] , [[Extensible]] » 和表31 中列出的内部插槽的列表连接 。
令 obj 为 MakeBasicObject (internalSlotsList )。
设置 obj .[[Prototype]] 为 proto 。
按照10.4.1.1 中的描述设置
obj .[[Call]] 。
如果 IsConstructor (targetFunction )
为 true ,那么
按照10.4.1.2 中的描述设置
obj .[[Construct]] 。
设置 obj .[[BoundTargetFunction]] 为
targetFunction 。
设置 obj .[[BoundThis]] 为 boundThis 。
设置 obj .[[BoundArguments]] 为
boundArgs 。
返回 obj 。
10.4.2 数组异质对象
数组是一个异质对象 ,它对数组索引 属性键 给予特殊处理(见6.1.7 )。属性名 是数组索引 的属性也称为元素 。每个数组都有一个不可配置的"length" 属性,其值始终是非负整数 ,其数学值 严格小于232 。"length" 属性的值在数值上大于名称为数组索引 的每个自有属性的名称;每当创建或更改数组的自有属性时,会根据需要调整其他属性以维持此不变性。具体来说,每当添加名称为数组索引 的自有属性时,如有必要,"length" 属性的值会更改为该数组索引 的数值加一;每当"length" 属性的值更改时,名称为数组索引 且值不小于新长度的每个自有属性都会被删除。此约束仅适用于数组的自有属性,不受可能从其原型继承的"length" 或数组索引 属性的影响。
如果对象的[[DefineOwnProperty]] 内部方法使用以下实现,其他基本内部方法使用10.1 中的定义,则该对象是数组异质对象 (或简称数组)。这些方法在ArrayCreate 中安装。
10.4.2.1 [[DefineOwnProperty]] (
P , Desc )
数组异质对象 A 的[[DefineOwnProperty]] 内部方法接受参数P (属性键 )和Desc (属性描述符 ),返回包含 布尔值的正常完成 或抛出完成 。调用时执行以下步骤:
如果 P 是 "length" ,那么
返回 ? ArraySetLength (A ,
Desc )。
否则,如果 P 是数组索引 ,那么
令 lengthDesc 为 OrdinaryGetOwnProperty (A ,
"length" )。
断言 :lengthDesc 不是
undefined 。
断言 :IsDataDescriptor (lengthDesc )
为 true 。
断言 :lengthDesc .[[Configurable]] 为 false 。
令 length 为 lengthDesc .[[Value]] 。
断言 :length 是非负整数 。
令 index 为 ! ToUint32 (P )。
如果 index ≥ length 且 lengthDesc .[[Writable]] 为 false ,返回
false 。
令 succeeded 为 ! OrdinaryDefineOwnProperty (A ,
P , Desc )。
如果 succeeded 为 false ,返回
false 。
如果 index ≥ length ,那么
设置 lengthDesc .[[Value]] 为
index + 1 𝔽 。
设置 succeeded 为 ! OrdinaryDefineOwnProperty (A ,
"length" , lengthDesc )。
断言 :succeeded 为
true 。
返回 true 。
返回 ? OrdinaryDefineOwnProperty (A ,
P , Desc )。
10.4.2.2 ArrayCreate ( length [ , proto ]
)
抽象操作ArrayCreate接受参数length (非负整数 )和可选参数proto (对象),返回包含 数组异质对象 的正常完成 或抛出完成 。它用于指定新数组的创建。调用时执行以下步骤:
如果 length > 232 - 1,抛出 RangeError 异常。
如果 proto 不存在,设置 proto 为 %Array.prototype% 。
令 A 为 MakeBasicObject (« [[Prototype]] , [[Extensible]] »)。
设置 A .[[Prototype]] 为 proto 。
按照10.4.2.1 中指定的设置
A .[[DefineOwnProperty]] 。
执行 ! OrdinaryDefineOwnProperty (A ,
"length" , PropertyDescriptor { [[Value]] : 𝔽 (length ), [[Writable]] : true , [[Enumerable]] : false , [[Configurable]] : false })。
返回 A 。
10.4.2.3 ArraySpeciesCreate ( originalArray ,
length )
抽象操作ArraySpeciesCreate接受参数originalArray (对象)和length (非负整数 ),返回包含 对象的正常完成 或抛出完成 。它用于指定使用从originalArray 派生的构造器 函数创建新数组或类似对象。它不强制构造器 函数返回数组。调用时执行以下步骤:
令 isArray 为 ? IsArray (originalArray )。
如果 isArray 为 false ,返回 ? ArrayCreate (length )。
令 C 为 ? Get (originalArray ,
"constructor" )。
如果 IsConstructor (C ) 为
true ,那么
令 thisRealm 为 当前领域记录 。
令 realmC 为 ? GetFunctionRealm (C )。
如果 thisRealm 和 realmC 不是同一个领域记录 ,那么
如果 SameValue (C ,
realmC .[[Intrinsics]] .[[%Array% ]]) 为
true ,设置 C 为
undefined 。
如果 C 是对象 ,那么
设置 C 为 ? Get (C , %Symbol.species% )。
如果 C 为 null ,设置 C 为
undefined 。
如果 C 为 undefined ,返回 ? ArrayCreate (length )。
如果 IsConstructor (C ) 为
false ,抛出 TypeError 异常。
返回 ? Construct (C , « 𝔽 (length ) »)。
注
如果originalArray 是使用不是运行执行上下文 的领域 的领域 的标准内置数组构造器 创建的,那么使用运行执行上下文 的领域 创建新数组。这与Web浏览器的历史行为保持兼容,这些浏览器历史上对现在使用ArraySpeciesCreate定义的Array.prototype
方法有这种行为。
10.4.2.4 ArraySetLength ( A , Desc )
抽象操作ArraySetLength接受参数A (数组)和Desc (属性描述符 ),返回包含 布尔值的正常完成 或抛出完成 。调用时执行以下步骤:
如果 Desc 没有 [[Value]] 字段,那么
返回 ! OrdinaryDefineOwnProperty (A ,
"length" , Desc )。
令 newLenDesc 为 Desc 的副本。
令 newLen 为 ? ToUint32 (Desc .[[Value]] )。
令 numberLen 为 ? ToNumber (Desc .[[Value]] )。
如果 SameValueZero (newLen ,
numberLen ) 为 false ,抛出 RangeError
异常。
设置 newLenDesc .[[Value]] 为 newLen 。
令 oldLenDesc 为 OrdinaryGetOwnProperty (A ,
"length" )。
断言 :oldLenDesc 不是
undefined 。
断言 :IsDataDescriptor (oldLenDesc )
为 true 。
断言 :oldLenDesc .[[Configurable]] 为 false 。
令 oldLen 为 oldLenDesc .[[Value]] 。
如果 newLen ≥ oldLen ,那么
返回 ! OrdinaryDefineOwnProperty (A ,
"length" , newLenDesc )。
如果 oldLenDesc .[[Writable]] 为
false ,返回 false 。
如果 newLenDesc 没有 [[Writable]] 字段或
newLenDesc .[[Writable]] 为
true ,那么
令 newWritable 为 true 。
否则,
注:如果任何元素无法删除,将[[Writable]] 属性设置为false 会被延迟。
令 newWritable 为 false 。
设置 newLenDesc .[[Writable]] 为
true 。
令 succeeded 为 ! OrdinaryDefineOwnProperty (A ,
"length" , newLenDesc )。
如果 succeeded 为 false ,返回 false 。
对于 A 的每个自有属性键 P ,如果 P
是数组索引 且 ! ToUint32 (P ) ≥
newLen ,按数值索引降序执行
令 deleteSucceeded 为 ! A .[[Delete]] (P )。
如果 deleteSucceeded 为 false ,那么
设置 newLenDesc .[[Value]] 为
! ToUint32 (P ) +
1 𝔽 。
如果 newWritable 为 false ,设置
newLenDesc .[[Writable]] 为
false 。
执行 ! OrdinaryDefineOwnProperty (A ,
"length" , newLenDesc )。
返回 false 。
如果 newWritable 为 false ,那么
设置 succeeded 为 ! OrdinaryDefineOwnProperty (A ,
"length" , PropertyDescriptor { [[Writable]] : false })。
断言 :succeeded 为
true 。
返回 true 。
注
在步骤3 和4 中,如果Desc .[[Value]] 是对象,则其valueOf
方法会被调用两次。这是传统行为,从本规范第2版开始就以此效果进行了指定。
10.4.3 字符串异质对象
字符串对象是一个异质对象 ,它封装一个字符串值并暴露对应于字符串值各个码元元素的虚拟整数索引的 数据属性 。字符串异质对象 总是有一个名为"length" 的数据属性 ,其值是封装的字符串值的长度。码元数据属性 和"length" 属性都是不可写和不可配置的。
如果对象的[[GetOwnProperty]] 、[[DefineOwnProperty]] 和[[OwnPropertyKeys]] 内部方法使用以下实现,其他基本内部方法使用10.1 中的定义,则该对象是字符串异质对象 (或简称字符串对象)。这些方法在StringCreate 中安装。
字符串异质对象 具有与普通对象 相同的内部插槽。它们还有一个[[StringData]] 内部插槽。
10.4.3.1 [[GetOwnProperty]] (
P )
字符串异质对象 S 的[[GetOwnProperty]] 内部方法接受参数P (属性键 ),返回包含 属性描述符 或undefined 的正常完成 。调用时执行以下步骤:
令 desc 为 OrdinaryGetOwnProperty (S ,
P )。
如果 desc 不是 undefined ,返回 desc 。
返回 StringGetOwnProperty (S ,
P )。
10.4.3.2 [[DefineOwnProperty]] (
P , Desc )
字符串异质对象 S 的[[DefineOwnProperty]] 内部方法接受参数P (属性键 )和Desc (属性描述符 ),返回包含 布尔值的正常完成 。调用时执行以下步骤:
令 stringDesc 为 StringGetOwnProperty (S ,
P )。
如果 stringDesc 不是 undefined ,那么
令 extensible 为 S .[[Extensible]] 。
返回 IsCompatiblePropertyDescriptor (extensible ,
Desc , stringDesc )。
返回 ! OrdinaryDefineOwnProperty (S ,
P , Desc )。
10.4.3.3 [[OwnPropertyKeys]] ( )
字符串异质对象 O 的[[OwnPropertyKeys]] 内部方法不接受参数,返回包含 属性键 的列表 的正常完成 。调用时执行以下步骤:
令 keys 为新的空列表 。
令 str 为 O .[[StringData]] 。
断言 :str 是字符串 。
令 len 为 str 的长度。
对于每个整数
i ,0 ≤ i < len ,按升序执行
将 ! ToString (𝔽 (i )) 追加到
keys 。
对于 O 的每个自有属性键 P ,如果 P
是数组索引 且 ! ToIntegerOrInfinity (P )
≥ len ,按数值索引升序执行
将 P 追加到 keys 。
对于 O 的每个自有属性键 P ,如果 P
是字符串 且
P 不是数组索引 ,按属性创建的时间升序执行
将 P 追加到 keys 。
对于 O 的每个自有属性键 P ,如果 P
是Symbol ,按属性创建的时间升序执行
将 P 追加到 keys 。
返回 keys 。
10.4.3.4 StringCreate ( value , prototype )
抽象操作StringCreate接受参数value (字符串)和prototype (对象),返回字符串异质对象 。它用于指定新字符串异质对象 的创建。调用时执行以下步骤:
令 S 为 MakeBasicObject (« [[Prototype]] , [[Extensible]] , [[StringData]] »)。
设置 S .[[Prototype]] 为 prototype 。
设置 S .[[StringData]] 为 value 。
按照10.4.3.1 中指定的设置
S .[[GetOwnProperty]] 。
按照10.4.3.2 中指定的设置
S .[[DefineOwnProperty]] 。
按照10.4.3.3 中指定的设置
S .[[OwnPropertyKeys]] 。
令 length 为 value 的长度。
执行 ! DefinePropertyOrThrow (S ,
"length" , PropertyDescriptor { [[Value]] : 𝔽 (length ), [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] : false })。
返回 S 。
10.4.3.5 StringGetOwnProperty ( S , P )
抽象操作StringGetOwnProperty接受参数S (具有[[StringData]] 内部插槽的对象)和P (属性键 ),返回属性描述符 或undefined 。调用时执行以下步骤:
如果 P 不是字符串 ,返回
undefined 。
令 index 为 CanonicalNumericIndexString (P )。
如果 index 不是整数 ,返回 undefined 。
如果 index 是 -0 𝔽 或 index <
-0 𝔽 ,返回 undefined 。
令 str 为 S .[[StringData]] 。
断言 :str 是字符串 。
令 len 为 str 的长度。
如果 ℝ (index )
≥ len ,返回 undefined 。
令 resultStr 为 str 从 ℝ (index ) 到 ℝ (index ) + 1 的子字符串 。
返回 PropertyDescriptor { [[Value]] : resultStr ,
[[Writable]] : false , [[Enumerable]] : true , [[Configurable]] : false }。
10.4.4 Arguments 异质对象
大多数ECMAScript函数向其代码提供一个arguments对象。根据函数定义的特征,其arguments对象要么是普通对象 ,要么是arguments异质对象 。Arguments异质对象 是一个异质对象 ,其数组索引 属性映射到其关联ECMAScript函数调用的形式参数绑定。
如果对象的内部方法使用以下实现,其他未在此指定的方法使用10.1 中的实现,则该对象是arguments异质对象 。这些方法在CreateMappedArgumentsObject 中安装。
注1
Arguments异质对象 具有与普通对象 相同的内部插槽。它们还有一个[[ParameterMap]] 内部插槽。普通arguments对象也有一个[[ParameterMap]] 内部插槽,其值始终是undefined 。对于普通argument对象,[[ParameterMap]] 内部插槽仅被Object.prototype.toString
(20.1.3.6 )用于识别它们。
注2
Arguments异质对象 的整数索引的 数据属性 ,其数值名称值小于对应函数对象 的形式参数数量,最初与函数执行上下文 中对应的参数绑定共享其值。这意味着更改属性会更改参数绑定的对应值,反之亦然。如果删除然后重新定义此类属性,或者将属性更改为访问器属性 ,则此对应关系会被破坏。如果arguments对象是普通对象 ,其属性值只是传递给函数的参数的副本,属性值与形式参数值之间没有动态链接。
注3
ParameterMap对象及其属性值被用作指定arguments对象与参数绑定对应关系的设备。ParameterMap对象和作为其属性值的对象不能从ECMAScript代码中直接观察到。ECMAScript实现不需要实际创建或使用此类对象来实现指定的语义。
注4
普通arguments对象定义一个名为"callee" 的不可配置访问器属性 ,访问时抛出TypeError 异常。"callee" 属性对于arguments异质对象 有更具体的含义,这些对象仅为某些类别的非严格函数 创建。在普通变体中定义此属性是为了确保符合标准的ECMAScript实现不会以任何其他方式定义它。
注5
Arguments异质对象 的ECMAScript实现历史上包含一个名为"caller" 的访问器属性 。在ECMAScript
2017之前,本规范包括在普通arguments对象上定义抛出"caller" 属性的定义。由于实现不再包含此扩展,ECMAScript
2017放弃了对抛出"caller" 访问器的要求。
10.4.4.1 [[GetOwnProperty]] (
P )
Arguments异质对象 args 的[[GetOwnProperty]] 内部方法接受参数P (属性键 ),返回包含 属性描述符 或undefined 的正常完成 。调用时执行以下步骤:
令 desc 为 OrdinaryGetOwnProperty (args ,
P )。
如果 desc 是 undefined ,返回 undefined 。
令 map 为 args .[[ParameterMap]] 。
令 isMapped 为 ! HasOwnProperty (map ,
P )。
如果 isMapped 为 true ,那么
设置 desc .[[Value]] 为 ! Get (map ,
P )。
返回 desc 。
10.4.4.2 [[DefineOwnProperty]] (
P , Desc )
Arguments异质对象 args 的[[DefineOwnProperty]] 内部方法接受参数P (属性键 )和Desc (属性描述符 ),返回包含 布尔值的正常完成 。调用时执行以下步骤:
令 map 为 args .[[ParameterMap]] 。
令 isMapped 为 ! HasOwnProperty (map ,
P )。
令 newArgDesc 为 Desc 。
如果 isMapped 为 true 且 IsDataDescriptor (Desc )
为 true ,那么
如果 Desc 没有 [[Value]] 字段,Desc
有 [[Writable]] 字段,且 Desc .[[Writable]] 为 false ,那么
设置 newArgDesc 为 Desc 的副本。
设置 newArgDesc .[[Value]] 为
! Get (map ,
P )。
令 allowed 为 ! OrdinaryDefineOwnProperty (args ,
P , newArgDesc )。
如果 allowed 为 false ,返回 false 。
如果 isMapped 为 true ,那么
如果 IsAccessorDescriptor (Desc )
为 true ,那么
执行 ! map .[[Delete]] (P )。
否则,
如果 Desc 有 [[Value]] 字段,那么
断言 :以下Set将成功,因为由arguments对象映射的形式参数总是可写的。
执行 ! Set (map ,
P , Desc .[[Value]] ,
false )。
如果 Desc 有 [[Writable]] 字段且
Desc .[[Writable]] 为
false ,那么
执行 ! map .[[Delete]] (P )。
返回 true 。
10.4.4.3 [[Get]] ( P ,
Receiver )
Arguments异质对象 args 的[[Get]] 内部方法接受参数P (属性键 )和Receiver (ECMAScript语言值 ),返回包含 ECMAScript语言值 的正常完成 或抛出完成 。调用时执行以下步骤:
令 map 为 args .[[ParameterMap]] 。
令 isMapped 为 ! HasOwnProperty (map ,
P )。
如果 isMapped 为 false ,那么
返回 ? OrdinaryGet (args ,
P , Receiver )。
否则,
断言 :map 包含 P
的形式参数映射。
返回 ! Get (map ,
P )。
10.4.4.4 [[Set]] ( P ,
V , Receiver )
Arguments异质对象 args 的[[Set]] 内部方法接受参数P (属性键 )、V (ECMAScript语言值 )和Receiver (ECMAScript语言值 ),返回包含 布尔值的正常完成 或抛出完成 。调用时执行以下步骤:
如果 SameValue (args ,
Receiver ) 为 false ,那么
令 isMapped 为 false 。
否则,
令 map 为 args .[[ParameterMap]] 。
令 isMapped 为 ! HasOwnProperty (map ,
P )。
如果 isMapped 为 true ,那么
断言 :以下Set将成功,因为由arguments对象映射的形式参数总是可写的。
执行 ! Set (map ,
P , V , false )。
返回 ? OrdinarySet (args ,
P , V , Receiver )。
10.4.4.5 [[Delete]] ( P )
Arguments异质对象 args 的[[Delete]] 内部方法接受参数P (属性键 ),返回包含 布尔值的正常完成 或抛出完成 。调用时执行以下步骤:
令 map 为 args .[[ParameterMap]] 。
令 isMapped 为 ! HasOwnProperty (map ,
P )。
令 result 为 ? OrdinaryDelete (args ,
P )。
如果 result 为 true 且 isMapped 为
true ,那么
执行 ! map .[[Delete]] (P )。
返回 result 。
10.4.4.6 CreateUnmappedArgumentsObject (
argumentsList )
抽象操作CreateUnmappedArgumentsObject接受参数argumentsList (ECMAScript语言值 的列表 ),返回普通对象 。调用时执行以下步骤:
令 len 为 argumentsList 中元素的数量。
令 obj 为 OrdinaryObjectCreate (%Object.prototype% ,
« [[ParameterMap]] »)。
设置 obj .[[ParameterMap]] 为
undefined 。
执行 ! DefinePropertyOrThrow (obj ,
"length" , PropertyDescriptor { [[Value]] : 𝔽 (len ), [[Writable]] : true , [[Enumerable]] : false , [[Configurable]] : true })。
令 index 为 0。
重复,当 index < len 时,
令 val 为 argumentsList [index ]。
执行 ! CreateDataPropertyOrThrow (obj ,
! ToString (𝔽 (index )),
val )。
设置 index 为 index + 1。
执行 ! DefinePropertyOrThrow (obj ,
%Symbol.iterator% ,
PropertyDescriptor { [[Value]] : %Array.prototype.values%,
[[Writable]] : true , [[Enumerable]] : false , [[Configurable]] : true })。
执行 ! DefinePropertyOrThrow (obj ,
"callee" , PropertyDescriptor { [[Get]] :
%ThrowTypeError% , [[Set]] : %ThrowTypeError% ,
[[Enumerable]] : false , [[Configurable]] : false })。
返回 obj 。
10.4.4.7 CreateMappedArgumentsObject ( func ,
formals , argumentsList , env )
抽象操作CreateMappedArgumentsObject接受参数func (对象)、formals (解析节点 )、argumentsList (ECMAScript语言值 的列表 )和env (环境记录 ),返回arguments异质对象 。调用时执行以下步骤:
断言 :formals
不包含剩余参数、任何绑定模式或任何初始化器。它可能包含重复标识符。
令 len 为 argumentsList 中元素的数量。
令 obj 为 MakeBasicObject (« [[Prototype]] , [[Extensible]] , [[ParameterMap]] »)。
按照10.4.4.1 中指定的设置
obj .[[GetOwnProperty]] 。
按照10.4.4.2 中指定的设置
obj .[[DefineOwnProperty]] 。
按照10.4.4.3 中指定的设置
obj .[[Get]] 。
按照10.4.4.4 中指定的设置
obj .[[Set]] 。
按照10.4.4.5 中指定的设置
obj .[[Delete]] 。
设置 obj .[[Prototype]] 为 %Object.prototype% 。
令 map 为 OrdinaryObjectCreate (null )。
设置 obj .[[ParameterMap]] 为 map 。
令 parameterNames 为 formals 的BoundNames 。
令 numberOfParameters 为 parameterNames 中元素的数量。
令 index 为 0。
重复,当 index < len 时,
令 val 为 argumentsList [index ]。
执行 ! CreateDataPropertyOrThrow (obj ,
! ToString (𝔽 (index )),
val )。
设置 index 为 index + 1。
执行 ! DefinePropertyOrThrow (obj ,
"length" , PropertyDescriptor { [[Value]] : 𝔽 (len ), [[Writable]] : true , [[Enumerable]] : false , [[Configurable]] : true })。
令 mappedNames 为新的空列表 。
设置 index 为 numberOfParameters - 1。
重复,当 index ≥ 0 时,
令 name 为 parameterNames [index ]。
如果 mappedNames 不包含 name ,那么
将 name 追加到 mappedNames 。
如果 index < len ,那么
令 g 为 MakeArgGetter (name ,
env )。
令 p 为 MakeArgSetter (name ,
env )。
执行 ! map .[[DefineOwnProperty]] (! ToString (𝔽 (index )),
PropertyDescriptor { [[Set]] :
p , [[Get]] :
g , [[Enumerable]] :
false , [[Configurable]] :
true })。
设置 index 为 index - 1。
执行 ! DefinePropertyOrThrow (obj ,
%Symbol.iterator% ,
PropertyDescriptor { [[Value]] : %Array.prototype.values%,
[[Writable]] : true , [[Enumerable]] : false , [[Configurable]] : true })。
执行 ! DefinePropertyOrThrow (obj ,
"callee" , PropertyDescriptor { [[Value]] : func , [[Writable]] : true , [[Enumerable]] : false , [[Configurable]] : true })。
返回 obj 。
10.4.4.7.1 MakeArgGetter ( name , env )
抽象操作MakeArgGetter接受参数name (字符串)和env (环境记录 ),返回函数对象 。它创建一个内置函数对象 ,执行时返回在env 中为name 绑定的值。调用时执行以下步骤:
令 getterClosure 为新的抽象闭包 ,没有参数,捕获name 和env ,调用时执行以下步骤:
返回 env .GetBindingValue(name ,
false )。
令 getter 为 CreateBuiltinFunction (getterClosure ,
0, "" , « »)。
注:getter 从不直接被ECMAScript代码访问。
返回 getter 。
10.4.4.7.2 MakeArgSetter ( name , env )
抽象操作MakeArgSetter接受参数name (字符串)和env (环境记录 ),返回函数对象 。它创建一个内置函数对象 ,执行时在env 中为name 设置绑定的值。调用时执行以下步骤:
令 setterClosure 为新的抽象闭包 ,参数为(value ),捕获name 和env ,调用时执行以下步骤:
返回 ! env .SetMutableBinding(name ,
value , false )。
令 setter 为 CreateBuiltinFunction (setterClosure ,
1, "" , « »)。
注:setter 从不直接被ECMAScript代码访问。
返回 setter 。
10.4.5 TypedArray 异质对象
TypedArray 是一个
异质对象 ,它对作为
规范数字字符串 的 属性键 执行特殊处理,使用界内的
整数索引
子集来索引统一类型的元素,并强制执行其余部分不存在且不引起原型链遍历的不变性。
注
因为对于任何数字 n ,ToString (n ) 都是一个 规范数字字符串 ,实现可以将数字视为
属性键
用于 TypedArrays ,而无需实际执行字符串转换。
TypedArrays 除了与
普通对象
相同的内部插槽外,还有 [[ViewedArrayBuffer]] 、[[ArrayLength]] 、[[ByteOffset]] 、[[ContentType]] 和 [[TypedArrayName]] 内部插槽。
如果一个对象的 [[PreventExtensions]] 、[[GetOwnProperty]] 、[[HasProperty]] 、[[DefineOwnProperty]] 、[[Get]] 、[[Set]] 、[[Delete]] 和 [[OwnPropertyKeys]] 内部方法使用本节中的定义,并且其他基本内部方法使用
10.1
中找到的定义,则该对象是一个 TypedArray 。这些方法由 TypedArrayCreate 安装。
10.4.5.1 [[PreventExtensions]] ( )
TypedArray
O 的 [[PreventExtensions]] 内部方法不接受参数并返回一个
包含
布尔值的正常完成。它在被调用时执行以下步骤:
注:6.1.7.3
中指定的可扩展性相关的不变性不允许此方法在 O 可以获得(或失去然后重新获得)属性时返回
true ,这可能发生在当其底层缓冲区被调整大小时具有 整数索引 名称的属性上。
如果 IsTypedArrayFixedLength (O )
是 false ,返回 false 。
返回 OrdinaryPreventExtensions (O )。
10.4.5.2 [[GetOwnProperty]] (
P )
TypedArray
O 的 [[GetOwnProperty]] 内部方法接受参数 P (一个
属性键 )并返回一个 包含 属性描述符 或
undefined 的正常完成。它在被调用时执行以下步骤:
如果 P 是一个字符串 ,那么
让 numericIndex 为 CanonicalNumericIndexString (P )。
如果 numericIndex 不是 undefined ,那么
让 value 为 TypedArrayGetElement (O ,
numericIndex )。
如果 value 是 undefined ,返回
undefined 。
返回属性描述符 { [[Value]] :
value ,[[Writable]] :
true ,[[Enumerable]] :
true ,[[Configurable]] :
true }。
返回 OrdinaryGetOwnProperty (O ,
P )。
10.4.5.3 [[HasProperty]] ( P
)
TypedArray
O 的 [[HasProperty]] 内部方法接受参数 P (一个 属性键 )并返回
包含 布尔值的正常完成或
抛出完成 。它在被调用时执行以下步骤:
如果 P 是一个字符串 ,那么
让 numericIndex 为 CanonicalNumericIndexString (P )。
如果 numericIndex 不是 undefined ,返回
IsValidIntegerIndex (O ,
numericIndex )。
返回 ? OrdinaryHasProperty (O ,
P )。
10.4.5.4 [[DefineOwnProperty]] (
P , Desc )
TypedArray
O 的 [[DefineOwnProperty]] 内部方法接受参数 P (一个
属性键 )和
Desc (一个 属性描述符 )并返回
包含 布尔值的正常完成或
抛出完成 。它在被调用时执行以下步骤:
如果 P 是一个字符串 ,那么
让 numericIndex 为 CanonicalNumericIndexString (P )。
如果 numericIndex 不是 undefined ,那么
如果 IsValidIntegerIndex (O ,
numericIndex ) 是 false ,返回
false 。
如果 Desc 有一个 [[Configurable]]
字段且 Desc .[[Configurable]]
是 false ,返回 false 。
如果 Desc 有一个 [[Enumerable]]
字段且 Desc .[[Enumerable]] 是
false ,返回 false 。
如果 IsAccessorDescriptor (Desc )
是 true ,返回 false 。
如果 Desc 有一个 [[Writable]] 字段
且 Desc .[[Writable]] 是
false ,返回 false 。
如果 Desc 有一个 [[Value]] 字段,
执行 ? TypedArraySetElement (O ,
numericIndex , Desc .[[Value]] )。
返回 true 。
返回 ! OrdinaryDefineOwnProperty (O ,
P , Desc )。
10.4.5.5 [[Get]] ( P ,
Receiver )
TypedArray
O 的 [[Get]] 内部方法接受参数 P (一个 属性键 )和
Receiver (一个 ECMAScript 语言值 )并返回 包含 ECMAScript 语言值 的正常完成或 抛出完成 。它在被调用时执行以下步骤:
如果 P 是一个字符串 ,那么
让 numericIndex 为 CanonicalNumericIndexString (P )。
如果 numericIndex 不是 undefined ,那么
返回 TypedArrayGetElement (O ,
numericIndex )。
返回 ? OrdinaryGet (O , P ,
Receiver )。
10.4.5.6 [[Set]] ( P ,
V , Receiver )
TypedArray
O 的 [[Set]] 内部方法接受参数 P (一个 属性键 )、V (一个 ECMAScript 语言值 )和
Receiver (一个 ECMAScript 语言值 )并返回 包含 布尔值的正常完成或
抛出完成 。它在被调用时执行以下步骤:
如果 P 是一个字符串 ,那么
让 numericIndex 为 CanonicalNumericIndexString (P )。
如果 numericIndex 不是 undefined ,那么
如果 SameValue (O ,
Receiver ) 是 true ,那么
执行 ? TypedArraySetElement (O ,
numericIndex , V )。
返回 true 。
如果 IsValidIntegerIndex (O ,
numericIndex ) 是 false ,返回
true 。
返回 ? OrdinarySet (O , P ,
V , Receiver )。
10.4.5.7 [[Delete]] ( P )
TypedArray
O 的 [[Delete]] 内部方法接受参数 P (一个 属性键 )并返回
包含
布尔值的正常完成。它在被调用时执行以下步骤:
如果 P 是一个字符串 ,那么
让 numericIndex 为 CanonicalNumericIndexString (P )。
如果 numericIndex 不是 undefined ,那么
如果 IsValidIntegerIndex (O ,
numericIndex ) 是 false ,返回
true ;否则返回 false 。
返回 ! OrdinaryDelete (O ,
P )。
10.4.5.8 [[OwnPropertyKeys]] ( )
TypedArray
O 的 [[OwnPropertyKeys]] 内部方法不接受参数并返回 包含 属性键 的
列表 的正常完成。它在被调用时执行以下步骤:
让 taRecord 为 MakeTypedArrayWithBufferWitnessRecord (O ,
seq-cst )。
让 keys 为一个新的空 列表 。
如果 IsTypedArrayOutOfBounds (taRecord )
是 false ,那么
让 length 为 TypedArrayLength (taRecord )。
对于每个满足 0 ≤ i < length 的 整数 i ,按升序,执行
将 ! ToString (𝔽 (i )) 追加到
keys 。
对于 O 的每个自己的 属性键 P ,使得 P
是一个字符串
且 P 不是一个 整数索引 ,按属性创建的升序时间顺序,执行
将 P 追加到 keys 。
对于 O 的每个自己的 属性键 P ,使得 P
是一个符号 ,按属性创建的升序时间顺序,执行
将 P 追加到 keys 。
返回 keys 。
10.4.5.9 TypedArray 带缓冲区见证记录
TypedArray
带缓冲区见证记录 是一个用于封装 TypedArray 以及所查看缓冲区的缓存字节长度的 记录 值。当所查看的缓冲区是
可增长的
SharedArrayBuffer 时,它用于帮助确保字节长度数据块的单个共享内存读取事件。
TypedArray 带缓冲区见证记录具有 表
32 中列出的字段。
表 32:TypedArray
带缓冲区见证记录 字段
字段名称
值
含义
[[Object]]
一个 TypedArray
其缓冲区字节长度被加载的 TypedArray 。
[[CachedBufferByteLength]]
一个非负 整数 或
detached
创建 记录
时对象的 [[ViewedArrayBuffer]] 的字节长度。
10.4.5.10 MakeTypedArrayWithBufferWitnessRecord (
obj , order )
抽象操作 MakeTypedArrayWithBufferWitnessRecord 接受参数 obj (一个 TypedArray )和
order (seq-cst 或 unordered )并返回一个
TypedArray
带缓冲区见证记录 。它在被调用时执行以下步骤:
让 buffer 为 obj .[[ViewedArrayBuffer]] 。
如果 IsDetachedBuffer (buffer )
是 true ,那么
让 byteLength 为 detached 。
否则,
让 byteLength 为 ArrayBufferByteLength (buffer ,
order )。
返回 TypedArray
带缓冲区见证记录 { [[Object]] :
obj , [[CachedBufferByteLength]] :
byteLength }。
10.4.5.11 TypedArrayCreate ( prototype )
抽象操作 TypedArrayCreate 接受参数 prototype (一个对象)并返回一个 TypedArray 。它用于指定新 TypedArrays
的创建。它在被调用时执行以下步骤:
让 internalSlotsList 为 « [[Prototype]] 、[[Extensible]] 、[[ViewedArrayBuffer]] 、[[TypedArrayName]] 、[[ContentType]] 、[[ByteLength]] 、
[[ByteOffset]] 、[[ArrayLength]] »。
让 A 为 MakeBasicObject (internalSlotsList )。
设置 A .[[PreventExtensions]] 如 10.4.5.1 中所指定。
设置 A .[[GetOwnProperty]] 如 10.4.5.2 中所指定。
设置 A .[[HasProperty]] 如 10.4.5.3 中所指定。
设置 A .[[DefineOwnProperty]] 如 10.4.5.4 中所指定。
设置 A .[[Get]] 如 10.4.5.5 中所指定。
设置 A .[[Set]] 如 10.4.5.6 中所指定。
设置 A .[[Delete]] 如 10.4.5.7 中所指定。
设置 A .[[OwnPropertyKeys]] 如 10.4.5.8 中所指定。
设置 A .[[Prototype]] 为 prototype 。
返回 A 。
10.4.5.12 TypedArrayByteLength ( taRecord )
抽象操作 TypedArrayByteLength 接受参数 taRecord (一个 TypedArray
带缓冲区见证记录 )并返回一个非负 整数 。它在被调用时执行以下步骤:
如果 IsTypedArrayOutOfBounds (taRecord )
是 true ,返回 0。
让 length 为 TypedArrayLength (taRecord )。
如果 length = 0,返回 0。
让 O 为 taRecord .[[Object]] 。
如果 O .[[ByteLength]] 不是
auto ,返回 O .[[ByteLength]] 。
让 elementSize 为 TypedArrayElementSize (O )。
返回 length × elementSize 。
10.4.5.13 TypedArrayLength ( taRecord )
抽象操作 TypedArrayLength 接受参数 taRecord (一个 TypedArray
带缓冲区见证记录 )并返回一个非负 整数 。它在被调用时执行以下步骤:
断言 :
IsTypedArrayOutOfBounds (taRecord )
是 false 。
让 O 为 taRecord .[[Object]] 。
如果 O .[[ArrayLength]] 不是
auto ,返回 O .[[ArrayLength]] 。
断言 :
IsFixedLengthArrayBuffer (O .[[ViewedArrayBuffer]] ) 是 false 。
让 byteOffset 为 O .[[ByteOffset]] 。
让 elementSize 为 TypedArrayElementSize (O )。
让 byteLength 为 taRecord .[[CachedBufferByteLength]] 。
断言 :
byteLength 不是 detached 。
返回 floor ((byteLength -
byteOffset ) / elementSize )。
10.4.5.14 IsTypedArrayOutOfBounds ( taRecord )
抽象操作 IsTypedArrayOutOfBounds 接受参数 taRecord (一个 TypedArray
带缓冲区见证记录 )并返回一个布尔值。它检查对象的任何数字属性是否引用了在底层缓冲区边界内不包含的索引处的值。它在被调用时执行以下步骤:
让 O 为 taRecord .[[Object]] 。
让 bufferByteLength 为 taRecord .[[CachedBufferByteLength]] 。
断言 :
IsDetachedBuffer (O .[[ViewedArrayBuffer]] ) 是 true 当且仅当
bufferByteLength 是 detached 。
如果 bufferByteLength 是 detached ,返回
true 。
让 byteOffsetStart 为 O .[[ByteOffset]] 。
如果 O .[[ArrayLength]] 是
auto ,那么
让 byteOffsetEnd 为 bufferByteLength 。
否则,
让 elementSize 为 TypedArrayElementSize (O )。
让 byteOffsetEnd 为 byteOffsetStart +
O .[[ArrayLength]] ×
elementSize 。
如果 byteOffsetStart > bufferByteLength 或
byteOffsetEnd > bufferByteLength ,返回
true 。
注:0长度的 TypedArrays 不被认为是越界的。
返回 false 。
10.4.5.15 IsTypedArrayFixedLength ( O )
抽象操作 IsTypedArrayFixedLength 接受参数 O (一个 TypedArray )并返回一个布尔值。它在被调用时执行以下步骤:
如果 O .[[ArrayLength]] 是
auto ,返回 false 。
让 buffer 为 O .[[ViewedArrayBuffer]] 。
如果 IsFixedLengthArrayBuffer (buffer )
是 false 且 IsSharedArrayBuffer (buffer )
是 false ,返回 false 。
返回 true 。
10.4.5.16 IsValidIntegerIndex ( O , index )
抽象操作 IsValidIntegerIndex 接受参数 O (一个 TypedArray )和
index (一个数字)并返回一个布尔值。它在被调用时执行以下步骤:
如果 IsDetachedBuffer (O .[[ViewedArrayBuffer]] ) 是 true ,返回
false 。
如果 index 不是一个 整数数字 ,返回 false 。
如果 index 是 -0 𝔽 或 index <
-0 𝔽 ,返回 false 。
让 taRecord 为 MakeTypedArrayWithBufferWitnessRecord (O ,
unordered )。
注:当 O 的支持缓冲区是 可增长的
SharedArrayBuffer 时,边界检查不是同步操作。
如果 IsTypedArrayOutOfBounds (taRecord )
是 true ,返回 false 。
让 length 为 TypedArrayLength (taRecord )。
如果 ℝ (index )
≥ length ,返回 false 。
返回 true 。
10.4.5.17 TypedArrayGetElement ( O , index
)
抽象操作 TypedArrayGetElement 接受参数 O (一个 TypedArray )和 index (一个数字)并返回一个数字、一个
BigInt 或 undefined 。它在被调用时执行以下步骤:
如果 IsValidIntegerIndex (O ,
index ) 是 false ,返回 undefined 。
让 offset 为 O .[[ByteOffset]] 。
让 elementSize 为 TypedArrayElementSize (O )。
让 byteIndexInBuffer 为 (ℝ (index ) × elementSize ) +
offset 。
让 elementType 为 TypedArrayElementType (O )。
返回 GetValueFromBuffer (O .[[ViewedArrayBuffer]] , byteIndexInBuffer ,
elementType , true , unordered )。
10.4.5.18 TypedArraySetElement ( O , index ,
value )
抽象操作 TypedArraySetElement 接受参数 O (一个 TypedArray )、index (一个数字)和
value (一个 ECMAScript 语言值 )并返回 包含
unused 的正常完成或 抛出完成 。它在被调用时执行以下步骤:
如果 O .[[ContentType]] 是
bigint ,让 numValue 为 ? ToBigInt (value )。
否则,让 numValue 为 ? ToNumber (value )。
如果 IsValidIntegerIndex (O ,
index ) 是 true ,那么
让 offset 为 O .[[ByteOffset]] 。
让 elementSize 为 TypedArrayElementSize (O )。
让 byteIndexInBuffer 为 (ℝ (index ) ×
elementSize ) + offset 。
让 elementType 为 TypedArrayElementType (O )。
执行 SetValueInBuffer (O .[[ViewedArrayBuffer]] , byteIndexInBuffer ,
elementType , numValue , true ,
unordered )。
返回 unused 。
注
此操作总是显得成功,但是当尝试写入 TypedArray 的末尾之外或写入由分离的 ArrayBuffer 支持的
TypedArray 时,它没有效果。
10.4.5.19 IsArrayBufferViewOutOfBounds ( O )
抽象操作 IsArrayBufferViewOutOfBounds 接受参数 O (一个 TypedArray 或一个 DataView)并返回一个布尔值。它检查
TypedArray
的任何数字属性或 DataView 对象的方法是否可以引用在底层数据块边界内不包含的索引处的值。此抽象操作作为上游规范的便利而存在。它在被调用时执行以下步骤:
如果 O 有一个 [[DataView]] 内部插槽,那么
让 viewRecord 为 MakeDataViewWithBufferWitnessRecord (O ,
seq-cst )。
返回 IsViewOutOfBounds (viewRecord )。
让 taRecord 为 MakeTypedArrayWithBufferWitnessRecord (O ,
seq-cst )。
返回 IsTypedArrayOutOfBounds (taRecord )。
10.4.6 模块命名空间异质对象
模块命名空间异质对象 是一个 异质对象 ,它暴露从
ECMAScript 模块 导出的绑定(参见 16.2.3 )。模块命名空间异质对象 的字符串键自己的属性与 模块 导出的绑定名称之间存在一对一的对应关系。导出的绑定包括使用
export *
导出项间接导出的任何绑定。每个字符串值自己的 属性键 是对应导出绑定名称的 StringValue 。这些是
模块命名空间异质对象 的唯一字符串键属性。每个这样的属性都具有属性
{ [[Writable]] : true 、[[Enumerable]] : true 、[[Configurable]] : false }。模块命名空间异质对象 是不可扩展的。
如果一个对象的 [[GetPrototypeOf]] 、[[SetPrototypeOf]] 、[[IsExtensible]] 、[[PreventExtensions]] 、[[GetOwnProperty]] 、[[DefineOwnProperty]] 、[[HasProperty]] 、[[Get]] 、[[Set]] 、[[Delete]] 和 [[OwnPropertyKeys]]
内部方法使用本节中的定义,并且其他基本内部方法使用 10.1
中找到的定义,则该对象是一个 模块命名空间异质对象 。这些方法由 ModuleNamespaceCreate 安装。
模块命名空间异质对象 具有 表 33
中定义的内部插槽。
表 33:模块命名空间异质对象的内部插槽
内部插槽
类型
描述
[[Module]]
一个 模块记录
此命名空间暴露其导出的 模块记录 。
[[Exports]]
一个字符串的 列表
一个 列表 ,其元素是作为此对象自己的属性暴露的导出名称的字符串值。该列表按
字典代码单元顺序 排序。
10.4.6.1 [[GetPrototypeOf]] ( )
模块命名空间异质对象 的 [[GetPrototypeOf]] 内部方法不接受参数并返回 包含
null 的正常完成。它在被调用时执行以下步骤:
返回 null 。
10.4.6.2 [[SetPrototypeOf]] (
V )
模块命名空间异质对象 O 的 [[SetPrototypeOf]] 内部方法接受参数 V (一个对象或
null )并返回 包含
布尔值的正常完成。它在被调用时执行以下步骤:
返回 ! SetImmutablePrototype (O ,
V )。
10.4.6.3 [[IsExtensible]] ( )
模块命名空间异质对象 的 [[IsExtensible]] 内部方法不接受参数并返回 包含
false 的正常完成。它在被调用时执行以下步骤:
返回 false 。
10.4.6.4 [[PreventExtensions]] ( )
模块命名空间异质对象 的 [[PreventExtensions]] 内部方法不接受参数并返回 包含
true 的正常完成。它在被调用时执行以下步骤:
返回 true 。
10.4.6.5 [[GetOwnProperty]] (
P )
模块命名空间异质对象 O 的 [[GetOwnProperty]] 内部方法接受参数 P (一个 属性键 )并返回
包含 属性描述符 或
undefined 的正常完成,或 抛出完成 。它在被调用时执行以下步骤:
如果 P 是一个符号 ,返回
OrdinaryGetOwnProperty (O ,
P )。
让 exports 为 O .[[Exports]] 。
如果 exports 不包含 P ,返回 undefined 。
让 value 为 ? O .[[Get]] (P , O )。
返回属性描述符 { [[Value]] : value 、[[Writable]] : true 、[[Enumerable]] : true 、[[Configurable]] : false }。
10.4.6.6 [[DefineOwnProperty]] (
P , Desc )
模块命名空间异质对象 O 的 [[DefineOwnProperty]] 内部方法接受参数 P (一个 属性键 )和
Desc (一个 属性描述符 )并返回
包含 布尔值的正常完成或
抛出完成 。它在被调用时执行以下步骤:
如果 P 是一个符号 ,返回
! OrdinaryDefineOwnProperty (O ,
P , Desc )。
让 current 为 ? O .[[GetOwnProperty]] (P )。
如果 current 是 undefined ,返回 false 。
如果 Desc 有一个 [[Configurable]] 字段且
Desc .[[Configurable]] 是
true ,返回 false 。
如果 Desc 有一个 [[Enumerable]] 字段且
Desc .[[Enumerable]] 是
false ,返回 false 。
如果 IsAccessorDescriptor (Desc )
是 true ,返回 false 。
如果 Desc 有一个 [[Writable]] 字段且
Desc .[[Writable]] 是 false ,返回
false 。
如果 Desc 有一个 [[Value]] 字段,返回 SameValue (Desc .[[Value]] , current .[[Value]] )。
返回 true 。
10.4.6.7 [[HasProperty]] ( P
)
模块命名空间异质对象 O 的 [[HasProperty]] 内部方法接受参数 P (一个 属性键 )并返回
包含
布尔值的正常完成。它在被调用时执行以下步骤:
如果 P 是一个符号 ,返回
! OrdinaryHasProperty (O ,
P )。
让 exports 为 O .[[Exports]] 。
如果 exports 包含 P ,返回 true 。
返回 false 。
10.4.6.8 [[Get]] ( P ,
Receiver )
模块命名空间异质对象 O 的 [[Get]] 内部方法接受参数 P (一个 属性键 )和 Receiver (一个
ECMAScript 语言值 )并返回 包含 ECMAScript 语言值 的正常完成或 抛出完成 。它在被调用时执行以下步骤:
如果 P 是一个符号 ,那么
返回 ! OrdinaryGet (O ,
P , Receiver )。
让 exports 为 O .[[Exports]] 。
如果 exports 不包含 P ,返回 undefined 。
让 m 为 O .[[Module]] 。
让 binding 为 m .ResolveExport(P )。
断言 :
binding 是一个 ResolvedBinding 记录 。
让 targetModule 为 binding .[[Module]] 。
断言 :
targetModule 不是 undefined 。
如果 binding .[[BindingName]] 是
namespace ,那么
返回 GetModuleNamespace (targetModule )。
让 targetEnv 为 targetModule .[[Environment]] 。
如果 targetEnv 是 empty ,抛出一个
ReferenceError 异常。
返回 ? targetEnv .GetBindingValue(binding .[[BindingName]] , true )。
注
ResolveExport 是无副作用的。每当使用特定的 exportName 、resolveSet
对作为参数调用此操作时,它必须返回相同的结果。实现可能选择预计算或缓存每个 模块命名空间异质对象 的 [[Exports]] 的 ResolveExport 结果。
10.4.6.9 [[Set]] ( P ,
V , Receiver )
模块命名空间异质对象 的 [[Set]] 内部方法接受参数 P (一个 属性键 )、V (一个 ECMAScript 语言值 )和
Receiver (一个 ECMAScript 语言值 )并返回 包含
false 的正常完成。它在被调用时执行以下步骤:
返回 false 。
10.4.6.10 [[Delete]] ( P )
模块命名空间异质对象 O 的 [[Delete]] 内部方法接受参数 P (一个 属性键 )并返回 包含
布尔值的正常完成。它在被调用时执行以下步骤:
如果 P 是一个符号 ,那么
返回 ! OrdinaryDelete (O ,
P )。
让 exports 为 O .[[Exports]] 。
如果 exports 包含 P ,返回 false 。
返回 true 。
10.4.6.11 [[OwnPropertyKeys]] ( )
模块命名空间异质对象 O 的 [[OwnPropertyKeys]] 内部方法不接受参数并返回 包含 属性键 的
列表 的正常完成。它在被调用时执行以下步骤:
让 exports 为 O .[[Exports]] 。
让 symbolKeys 为 OrdinaryOwnPropertyKeys (O )。
返回 exports 和 symbolKeys 的 列表连接 。
10.4.6.12 ModuleNamespaceCreate ( module ,
exports )
抽象操作 ModuleNamespaceCreate 接受参数 module (一个 模块记录 )和 exports (一个字符串的
列表 )并返回一个 模块命名空间异质对象 。它用于指定新 模块命名空间异质对象 的创建。它在被调用时执行以下步骤:
断言 :
module .[[Namespace]] 是
empty 。
让 internalSlotsList 为 表
33 中列出的内部插槽。
让 M 为 MakeBasicObject (internalSlotsList )。
设置 M 的基本内部方法为 10.4.6 中指定的定义。
设置 M .[[Module]] 为 module 。
让 sortedExports 为一个 列表 ,其元素是
exports 的元素,按 字典代码单元顺序
排序。
设置 M .[[Exports]] 为 sortedExports 。
创建 M 的自己的属性,对应于 28.3 中的定义。
设置 module .[[Namespace]] 为 M 。
返回 M 。
10.4.7 不可变原型异质对象
不可变原型异质对象 是一个 异质对象 ,它具有一个 [[Prototype]] 内部插槽,一旦初始化后就不会更改。
如果一个对象的 [[SetPrototypeOf]] 内部方法使用以下实现,则该对象是一个 不可变原型异质对象 。(其他基本内部方法可以使用任何实现,取决于所涉及的特定 不可变原型异质对象 。)
注
与其他 异质对象 不同,没有为 不可变原型异质对象
提供专门的创建抽象操作。这是因为它们仅被 %Object.prototype%
和 宿主环境 使用,而在 宿主环境 中,相关对象可能在其他方面也是异质的,因此需要它们自己的专门创建操作。
10.4.7.1 [[SetPrototypeOf]] (
V )
不可变原型异质对象 O 的
[[SetPrototypeOf]] 内部方法接受参数 V (一个对象或
null )并返回 包含
布尔值的正常完成或 抛出完成 。它在被调用时执行以下步骤:
返回 ? SetImmutablePrototype (O ,
V )。
10.4.7.2 SetImmutablePrototype ( O , V )
抽象操作 SetImmutablePrototype 接受参数 O (一个对象)和 V (一个对象或
null )并返回 包含
布尔值的正常完成或 抛出完成 。它在被调用时执行以下步骤:
让 current 为 ? O .[[GetPrototypeOf]] ()。
如果 SameValue (V ,
current ) 是 true ,返回 true 。
返回 false 。
10.5 代理对象内部方法和内部插槽
代理对象是一个 异质对象 ,其基本内部方法部分使用 ECMAScript 代码实现。每个代理对象都有一个名为 [[ProxyHandler]] 的内部插槽。[[ProxyHandler]]
的值是一个对象,称为代理的处理器对象 ,或者是 null 。处理器对象的方法(参见 表
34 )可用于增强代理对象一个或多个内部方法的实现。每个代理对象还有一个名为 [[ProxyTarget]] 的内部插槽,其值要么是一个对象,要么是
null 。这个对象称为代理的目标对象 。
如果一个对象的基本内部方法(包括 [[Call]] 和 [[Construct]] ,如果适用)使用本节中的定义,则该对象是一个 代理异质对象 。这些内部方法在 ProxyCreate 中安装。
表 34:代理处理器方法
内部方法
处理器方法
[[GetPrototypeOf]]
getPrototypeOf
[[SetPrototypeOf]]
setPrototypeOf
[[IsExtensible]]
isExtensible
[[PreventExtensions]]
preventExtensions
[[GetOwnProperty]]
getOwnPropertyDescriptor
[[DefineOwnProperty]]
defineProperty
[[HasProperty]]
has
[[Get]]
get
[[Set]]
set
[[Delete]]
deleteProperty
[[OwnPropertyKeys]]
ownKeys
[[Call]]
apply
[[Construct]]
construct
当调用处理器方法来提供代理对象内部方法的实现时,处理器方法将代理的目标对象作为参数传递。代理的处理器对象不一定具有与每个基本内部方法相对应的方法。如果处理器对象没有与内部陷阱相对应的方法,则在代理上调用内部方法会导致在代理的目标对象上调用相应的内部方法。
代理对象的 [[ProxyHandler]] 和 [[ProxyTarget]]
内部插槽在创建对象时总是被初始化,通常不能被修改。某些代理对象以允许它们随后被撤销 的方式创建。当代理被撤销时,其 [[ProxyHandler]] 和 [[ProxyTarget]] 内部插槽被设置为
null ,导致该代理对象上内部方法的后续调用抛出 TypeError 异常。
因为代理对象允许通过任意 ECMAScript 代码提供内部方法的实现,所以可以定义一个代理对象,其处理器方法违反了 6.1.7.3
中定义的不变量。6.1.7.3
中定义的一些内部方法不变量是基本的完整性不变量。这些不变量由本节中指定的代理对象内部方法显式强制执行。ECMAScript 实现必须在所有可能的不变量违反的情况下保持健壮。
在以下算法描述中,假设 O 是一个 ECMAScript 代理对象,P 是一个 属性键 值,V 是任何 ECMAScript 语言值 ,Desc 是一个
属性描述符 记录。
10.5.1 [[GetPrototypeOf]] ( )
代理异质对象 O 的 [[GetPrototypeOf]] 内部方法不接受参数并返回 包含 对象或
null 的正常完成,或 抛出完成 。它在被调用时执行以下步骤:
执行 ? ValidateNonRevokedProxy (O )。
让 target 为 O .[[ProxyTarget]] 。
让 handler 为 O .[[ProxyHandler]] 。
断言 :
handler 是一个对象 。
让 trap 为 ? GetMethod (handler ,
"getPrototypeOf" )。
如果 trap 是 undefined ,那么
返回 ? target .[[GetPrototypeOf]] ()。
让 handlerProto 为 ? Call (trap ,
handler , « target »)。
如果 handlerProto 不是一个对象 且 handlerProto 不是
null ,抛出一个 TypeError 异常。
让 extensibleTarget 为 ? IsExtensible (target )。
如果 extensibleTarget 是 true ,返回 handlerProto 。
让 targetProto 为 ? target .[[GetPrototypeOf]] ()。
如果 SameValue (handlerProto ,
targetProto ) 是 false ,抛出一个 TypeError 异常。
返回 handlerProto 。
注
代理对象的 [[GetPrototypeOf]] 强制执行以下不变量:
[[GetPrototypeOf]] 的结果必须是一个对象或 null 。
如果目标对象不可扩展,应用于代理对象的 [[GetPrototypeOf]] 必须返回与应用于代理对象的目标对象的
[[GetPrototypeOf]] 相同的值。
10.5.2 [[SetPrototypeOf]] ( V )
代理异质对象 O 的 [[SetPrototypeOf]] 内部方法接受参数 V (一个对象或
null )并返回 包含
布尔值的正常完成或 抛出完成 。它在被调用时执行以下步骤:
执行 ? ValidateNonRevokedProxy (O )。
让 target 为 O .[[ProxyTarget]] 。
让 handler 为 O .[[ProxyHandler]] 。
断言 :
handler 是一个对象 。
让 trap 为 ? GetMethod (handler ,
"setPrototypeOf" )。
如果 trap 是 undefined ,那么
返回 ? target .[[SetPrototypeOf]] (V )。
让 booleanTrapResult 为 ToBoolean (? Call (trap , handler , «
target , V »))。
如果 booleanTrapResult 是 false ,返回 false 。
让 extensibleTarget 为 ? IsExtensible (target )。
如果 extensibleTarget 是 true ,返回 true 。
让 targetProto 为 ? target .[[GetPrototypeOf]] ()。
如果 SameValue (V ,
targetProto ) 是 false ,抛出一个 TypeError 异常。
返回 true 。
注
代理对象的 [[SetPrototypeOf]] 强制执行以下不变量:
[[SetPrototypeOf]] 的结果 是一个布尔值 。
如果目标对象不可扩展,参数值必须与应用于目标对象的 [[GetPrototypeOf]] 的结果相同。
10.5.3 [[IsExtensible]] ( )
代理异质对象 O 的 [[IsExtensible]] 内部方法不接受参数并返回 包含 布尔值的正常完成或 抛出完成 。它在被调用时执行以下步骤:
执行 ? ValidateNonRevokedProxy (O )。
让 target 为 O .[[ProxyTarget]] 。
让 handler 为 O .[[ProxyHandler]] 。
断言 :
handler 是一个对象 。
让 trap 为 ? GetMethod (handler ,
"isExtensible" )。
如果 trap 是 undefined ,那么
返回 ? IsExtensible (target )。
让 booleanTrapResult 为 ToBoolean (? Call (trap , handler , «
target »))。
让 targetResult 为 ? IsExtensible (target )。
如果 booleanTrapResult 不是 targetResult ,抛出一个
TypeError 异常。
返回 booleanTrapResult 。
注
代理对象的 [[IsExtensible]] 强制执行以下不变量:
[[IsExtensible]] 的结果 是一个布尔值 。
应用于代理对象的 [[IsExtensible]] 必须返回与应用于代理对象的目标对象的 [[IsExtensible]] 相同的值。
10.5.4 [[PreventExtensions]] ( )
代理异质对象 O 的 [[PreventExtensions]] 内部方法不接受参数并返回 包含 布尔值的正常完成或 抛出完成 。它在被调用时执行以下步骤:
执行 ? ValidateNonRevokedProxy (O )。
让 target 为 O .[[ProxyTarget]] 。
让 handler 为 O .[[ProxyHandler]] 。
断言 :
handler 是一个对象 。
让 trap 为 ? GetMethod (handler ,
"preventExtensions" )。
如果 trap 是 undefined ,那么
返回 ? target .[[PreventExtensions]] () 。
让 booleanTrapResult 为 ToBoolean (? Call (trap , handler , «
target »))。
如果 booleanTrapResult 是 true ,那么
让 extensibleTarget 为 ? IsExtensible (target )。
如果 extensibleTarget 是 true ,抛出一个
TypeError 异常。
返回 booleanTrapResult 。
注
代理对象的 [[PreventExtensions]] 强制执行以下不变量:
[[PreventExtensions]] 的结果 是一个布尔值 。
应用于代理对象的 [[PreventExtensions]] 仅在应用于代理对象的目标对象的 [[IsExtensible]] 为 false 时才返回
true 。
10.5.5 [[GetOwnProperty]] ( P )
代理异质对象 O 的 [[GetOwnProperty]] 内部方法接受参数 P (一个 属性键 )并返回 包含 属性描述符 或
undefined 的正常完成,或 抛出完成 。它在被调用时执行以下步骤:
执行 ? ValidateNonRevokedProxy (O )。
让 target 为 O .[[ProxyTarget]] 。
让 handler 为 O .[[ProxyHandler]] 。
断言 :
handler 是一个对象 。
让 trap 为 ? GetMethod (handler ,
"getOwnPropertyDescriptor" )。
如果 trap 是 undefined ,那么
返回 ? target .[[GetOwnProperty]] (P )。
让 trapResultObj 为 ? Call (trap ,
handler , « target , P »)。
如果 trapResultObj 不是一个对象 且 trapResultObj 不是
undefined ,抛出一个 TypeError 异常。
让 targetDesc 为 ? target .[[GetOwnProperty]] (P )。
如果 trapResultObj 是 undefined ,那么
如果 targetDesc 是 undefined ,返回
undefined 。
如果 targetDesc .[[Configurable]] 是
false ,抛出一个 TypeError 异常。
让 extensibleTarget 为 ? IsExtensible (target )。
如果 extensibleTarget 是 false ,抛出一个
TypeError 异常。
返回 undefined 。
让 extensibleTarget 为 ? IsExtensible (target )。
让 resultDesc 为 ? ToPropertyDescriptor (trapResultObj )。
执行 CompletePropertyDescriptor (resultDesc )。
让 valid 为 IsCompatiblePropertyDescriptor (extensibleTarget ,
resultDesc , targetDesc )。
如果 valid 是 false ,抛出一个 TypeError 异常。
如果 resultDesc .[[Configurable]] 是
false ,那么
如果 targetDesc 是 undefined 或
targetDesc .[[Configurable]] 是
true ,那么
抛出一个 TypeError 异常。
如果 resultDesc 有一个 [[Writable]] 字段且
resultDesc .[[Writable]] 是
false ,那么
断言 :targetDesc 有一个 [[Writable]] 字段。
如果 targetDesc .[[Writable]] 是
true ,抛出一个 TypeError 异常。
返回 resultDesc 。
注
代理对象的 [[GetOwnProperty]] 强制执行以下不变量:
[[GetOwnProperty]] 的结果必须是一个对象或
undefined 。
如果属性作为目标对象的不可配置自有属性存在,则不能报告该属性不存在。
如果属性作为不可扩展目标对象的自有属性存在,则不能报告该属性不存在。
如果属性不作为目标对象的自有属性存在且目标对象不可扩展,则不能报告该属性存在。
除非属性作为目标对象的不可配置自有属性存在,否则不能报告该属性为不可配置。
除非属性作为目标对象的不可配置、不可写自有属性存在,否则不能报告该属性既不可配置又不可写。
10.5.6 [[DefineOwnProperty]] (
P , Desc )
代理异质对象 O 的 [[DefineOwnProperty]] 内部方法接受参数 P (一个 属性键 )和
Desc (一个 属性描述符 )并返回 包含 布尔值的正常完成或 抛出完成 。它在被调用时执行以下步骤:
执行 ? ValidateNonRevokedProxy (O )。
让 target 为 O .[[ProxyTarget]] 。
让 handler 为 O .[[ProxyHandler]] 。
断言 :
handler 是一个对象 。
让 trap 为 ? GetMethod (handler ,
"defineProperty" )。
如果 trap 是 undefined ,那么
返回 ? target .[[DefineOwnProperty]] (P ,
Desc )。
让 descObj 为 FromPropertyDescriptor (Desc )。
让 booleanTrapResult 为 ToBoolean (? Call (trap , handler , «
target , P , descObj »))。
如果 booleanTrapResult 是 false ,返回 false 。
让 targetDesc 为 ? target .[[GetOwnProperty]] (P )。
让 extensibleTarget 为 ? IsExtensible (target )。
如果 Desc 有一个 [[Configurable]] 字段且
Desc .[[Configurable]] 是 false ,那么
让 settingConfigFalse 为 true 。
否则,
让 settingConfigFalse 为 false 。
如果 targetDesc 是 undefined ,那么
如果 extensibleTarget 是 false ,抛出一个
TypeError 异常。
如果 settingConfigFalse 是 true ,抛出一个
TypeError 异常。
否则,
如果 IsCompatiblePropertyDescriptor (extensibleTarget ,
Desc , targetDesc ) 是 false ,抛出一个
TypeError 异常。
如果 settingConfigFalse 是 true 且
targetDesc .[[Configurable]] 是
true ,抛出一个 TypeError 异常。
如果 IsDataDescriptor (targetDesc )
是 true ,targetDesc .[[Configurable]] 是 false ,且
targetDesc .[[Writable]] 是
true ,那么
如果 Desc 有一个 [[Writable]] 字段且
Desc .[[Writable]] 是
false ,抛出一个 TypeError 异常。
返回 true 。
注
代理对象的 [[DefineOwnProperty]] 强制执行以下不变量:
[[DefineOwnProperty]] 的结果 是一个布尔值 。
如果目标对象不可扩展,则不能添加属性。
除非目标对象存在相应的不可配置自有属性,否则属性不能为不可配置。
除非目标对象存在相应的不可配置、不可写自有属性,否则不可配置属性不能为不可写。
如果属性有相应的目标对象属性,则使用 [[DefineOwnProperty]] 将该属性的 属性描述符
应用于目标对象不会抛出异常。
10.5.7 [[HasProperty]] ( P )
代理异质对象 O 的 [[HasProperty]] 内部方法接受参数 P (一个 属性键 )并返回 包含 布尔值的正常完成或 抛出完成 。它在被调用时执行以下步骤:
执行 ? ValidateNonRevokedProxy (O )。
让 target 为 O .[[ProxyTarget]] 。
让 handler 为 O .[[ProxyHandler]] 。
断言 :
handler 是一个对象 。
让 trap 为 ? GetMethod (handler ,
"has" )。
如果 trap 是 undefined ,那么
返回 ? target .[[HasProperty]] (P )。
让 booleanTrapResult 为 ToBoolean (? Call (trap , handler , «
target , P »))。
如果 booleanTrapResult 是 false ,那么
让 targetDesc 为 ? target .[[GetOwnProperty]] (P )。
如果 targetDesc 不是 undefined ,那么
如果 targetDesc .[[Configurable]] 是
false ,抛出一个 TypeError 异常。
让 extensibleTarget 为 ? IsExtensible (target )。
如果 extensibleTarget 是 false ,抛出一个
TypeError 异常。
返回 booleanTrapResult 。
注
代理对象的 [[HasProperty]] 强制执行以下不变量:
[[HasProperty]] 的结果 是一个布尔值 。
如果属性作为目标对象的不可配置自有属性存在,则不能报告该属性不存在。
如果属性作为目标对象的自有属性存在且目标对象不可扩展,则不能报告该属性不存在。
10.5.8 [[Get]] ( P ,
Receiver )
代理异质对象 O 的 [[Get]] 内部方法接受参数 P (一个 属性键 )和 Receiver (一个 ECMAScript 语言值 )并返回 包含 ECMAScript 语言值 的正常完成或 抛出完成 。它在被调用时执行以下步骤:
执行 ? ValidateNonRevokedProxy (O )。
让 target 为 O .[[ProxyTarget]] 。
让 handler 为 O .[[ProxyHandler]] 。
断言 :
handler 是一个对象 。
让 trap 为 ? GetMethod (handler ,
"get" )。
如果 trap 是 undefined ,那么
返回 ? target .[[Get]] (P , Receiver )。
让 trapResult 为 ? Call (trap ,
handler , « target , P , Receiver »)。
让 targetDesc 为 ? target .[[GetOwnProperty]] (P )。
如果 targetDesc 不是 undefined 且 targetDesc .[[Configurable]] 是 false ,那么
如果 IsDataDescriptor (targetDesc )
是 true 且 targetDesc .[[Writable]] 是 false ,那么
如果 SameValue (trapResult ,
targetDesc .[[Value]] ) 是
false ,抛出一个 TypeError 异常。
如果 IsAccessorDescriptor (targetDesc )
是 true 且 targetDesc .[[Get]] 是 undefined ,那么
如果 trapResult 不是 undefined ,抛出一个
TypeError 异常。
返回 trapResult 。
注
代理对象的 [[Get]] 强制执行以下不变量:
如果目标对象属性是不可写、不可配置的自有 数据属性 ,则为属性报告的值必须与相应目标对象属性的值相同。
如果相应的目标对象属性是不可配置的自有 访问器属性 ,且其 [[Get]] 特性为 undefined ,则为属性报告的值必须是
undefined 。
10.5.9 [[Set]] ( P ,
V , Receiver )
代理异质对象 O 的 [[Set]] 内部方法接受参数 P (一个 属性键 )、V (一个 ECMAScript 语言值 )和
Receiver (一个 ECMAScript 语言值 )并返回 包含 布尔值的正常完成或 抛出完成 。它在被调用时执行以下步骤:
执行 ? ValidateNonRevokedProxy (O )。
让 target 为 O .[[ProxyTarget]] 。
让 handler 为 O .[[ProxyHandler]] 。
断言 :
handler 是一个对象 。
让 trap 为 ? GetMethod (handler ,
"set" )。
如果 trap 是 undefined ,那么
返回 ? target .[[Set]] (P , V ,
Receiver )。
让 booleanTrapResult 为 ToBoolean (? Call (trap , handler , «
target , P , V , Receiver »))。
如果 booleanTrapResult 是 false ,返回 false 。
让 targetDesc 为 ? target .[[GetOwnProperty]] (P )。
如果 targetDesc 不是 undefined 且 targetDesc .[[Configurable]] 是 false ,那么
如果 IsDataDescriptor (targetDesc )
是 true 且 targetDesc .[[Writable]] 是 false ,那么
如果 SameValue (V ,
targetDesc .[[Value]] ) 是
false ,抛出一个 TypeError 异常。
如果 IsAccessorDescriptor (targetDesc )
是 true ,那么
如果 targetDesc .[[Set]] 是
undefined ,抛出一个 TypeError 异常。
返回 true 。
注
代理对象的 [[Set]] 强制执行以下不变量:
[[Set]] 的结果 是一个布尔值 。
如果相应的目标对象属性是不可写、不可配置的自有 数据属性 ,则不能将属性的值更改为与相应目标对象属性的值不同。
如果相应的目标对象属性是不可配置的自有 访问器属性 ,且其 [[Set]] 特性为 undefined ,则不能设置属性的值。
10.5.10 [[Delete]] ( P )
代理异质对象 O 的 [[Delete]] 内部方法接受参数 P (一个 属性键 )并返回 包含 布尔值的正常完成或 抛出完成 。它在被调用时执行以下步骤:
执行 ? ValidateNonRevokedProxy (O )。
让 target 为 O .[[ProxyTarget]] 。
让 handler 为 O .[[ProxyHandler]] 。
断言 :
handler 是一个对象 。
让 trap 为 ? GetMethod (handler ,
"deleteProperty" )。
如果 trap 是 undefined ,那么
返回 ? target .[[Delete]] (P )。
让 booleanTrapResult 为 ToBoolean (? Call (trap , handler , «
target , P »))。
如果 booleanTrapResult 是 false ,返回 false 。
让 targetDesc 为 ? target .[[GetOwnProperty]] (P )。
如果 targetDesc 是 undefined ,返回 true 。
如果 targetDesc .[[Configurable]] 是
false ,抛出一个 TypeError 异常。
让 extensibleTarget 为 ? IsExtensible (target )。
如果 extensibleTarget 是 false ,抛出一个
TypeError 异常。
返回 true 。
注
代理对象的 [[Delete]] 强制执行以下不变量:
[[Delete]] 的结果 是一个布尔值 。
如果属性作为目标对象的不可配置自有属性存在,则不能报告该属性被删除。
如果属性作为目标对象的自有属性存在且目标对象不可扩展,则不能报告该属性被删除。
10.5.11 [[OwnPropertyKeys]] ( )
代理异质对象 O 的 [[OwnPropertyKeys]] 内部方法不接受参数并返回 包含 列表 的正常完成(该列表包含 属性键 )或 抛出完成 。它在被调用时执行以下步骤:
执行 ? ValidateNonRevokedProxy (O )。
让 target 为 O .[[ProxyTarget]] 。
让 handler 为 O .[[ProxyHandler]] 。
断言 :
handler 是一个对象 。
让 trap 为 ? GetMethod (handler ,
"ownKeys" )。
如果 trap 是 undefined ,那么
返回 ? target .[[OwnPropertyKeys]] () 。
让 trapResultArray 为 ? Call (trap ,
handler , « target »)。
让 trapResult 为 ? CreateListFromArrayLike (trapResultArray ,
property-key )。
如果 trapResult 包含任何重复条目,抛出一个 TypeError 异常。
让 extensibleTarget 为 ? IsExtensible (target )。
让 targetKeys 为 ? target .[[OwnPropertyKeys]] () 。
断言 :
targetKeys 是一个包含 属性键 的 列表 。
断言 :
targetKeys 不包含重复条目。
让 targetConfigurableKeys 为一个新的空 列表 。
让 targetNonconfigurableKeys 为一个新的空 列表 。
对 targetKeys 的每个元素 key ,执行
让 desc 为 ? target .[[GetOwnProperty]] (key )。
如果 desc 不是 undefined 且 desc .[[Configurable]] 是 false ,那么
将 key 追加到 targetNonconfigurableKeys 。
否则,
将 key 追加到 targetConfigurableKeys 。
如果 extensibleTarget 是 true 且
targetNonconfigurableKeys 是空的,那么
返回 trapResult 。
让 uncheckedResultKeys 为一个 列表 ,其元素是
trapResult 的元素。
对 targetNonconfigurableKeys 的每个元素 key ,执行
如果 uncheckedResultKeys 不包含 key ,抛出一个
TypeError 异常。
从 uncheckedResultKeys 中移除 key 。
如果 extensibleTarget 是 true ,返回 trapResult 。
对 targetConfigurableKeys 的每个元素 key ,执行
如果 uncheckedResultKeys 不包含 key ,抛出一个
TypeError 异常。
从 uncheckedResultKeys 中移除 key 。
如果 uncheckedResultKeys 不是空的,抛出一个 TypeError 异常。
返回 trapResult 。
注
代理对象的 [[OwnPropertyKeys]] 强制执行以下不变量:
[[OwnPropertyKeys]] 的结果是一个 列表 。
返回的 列表 不包含重复条目。
返回的 列表 的每个元素都是一个
属性键 。
结果 列表
必须包含目标对象所有不可配置自有属性的键。
如果目标对象不可扩展,则结果 列表
必须包含目标对象自有属性的所有键,且不包含其他值。
10.5.12 [[Call]] ( thisArgument ,
argumentsList )
代理异质对象 O 的 [[Call]] 内部方法接受参数 thisArgument (一个 ECMAScript 语言值 )和
argumentsList (一个包含 ECMAScript 语言值 的 列表 )并返回 包含 ECMAScript 语言值 的正常完成或 抛出完成 。它在被调用时执行以下步骤:
执行 ? ValidateNonRevokedProxy (O )。
让 target 为 O .[[ProxyTarget]] 。
让 handler 为 O .[[ProxyHandler]] 。
断言 :
handler 是一个对象 。
让 trap 为 ? GetMethod (handler ,
"apply" )。
如果 trap 是 undefined ,那么
返回 ? Call (target ,
thisArgument , argumentsList )。
让 argArray 为 CreateArrayFromList (argumentsList )。
返回 ? Call (trap , handler , «
target , thisArgument , argArray »)。
注
代理异质对象 只有在其 [[ProxyTarget]] 内部插槽的初始值是具有 [[Call]]
内部方法的对象时,才具有 [[Call]] 内部方法。
10.5.13 [[Construct]] (
argumentsList , newTarget )
代理异质对象 O 的 [[Construct]] 内部方法接受参数 argumentsList (一个包含 ECMAScript 语言值 的 列表 )和
newTarget (一个 构造函数 )并返回 包含 对象的正常完成或 抛出完成 。它在被调用时执行以下步骤:
执行 ? ValidateNonRevokedProxy (O )。
让 target 为 O .[[ProxyTarget]] 。
断言 :
IsConstructor (target ) 是
true 。
让 handler 为 O .[[ProxyHandler]] 。
断言 :
handler 是一个对象 。
让 trap 为 ? GetMethod (handler ,
"construct" )。
如果 trap 是 undefined ,那么
返回 ? Construct (target ,
argumentsList , newTarget )。
让 argArray 为 CreateArrayFromList (argumentsList )。
让 newObj 为 ? Call (trap , handler , «
target , argArray , newTarget »)。
如果 newObj 不是一个对象 ,抛出一个 TypeError
异常。
返回 newObj 。
注 1
代理异质对象 只有在其 [[ProxyTarget]] 内部插槽的初始值是具有 [[Construct]] 内部方法的对象时,才具有 [[Construct]] 内部方法。
注 2
代理对象的 [[Construct]] 强制执行以下不变量:
[[Construct]] 的结果必须是一个对象。
10.5.14 ValidateNonRevokedProxy ( proxy )
抽象操作 ValidateNonRevokedProxy 接受参数 proxy (一个 代理异质对象 )并返回 包含
unused 的正常完成或 抛出完成 。如果
proxy 已被撤销,它会抛出一个 TypeError 异常。它在被调用时执行以下步骤:
如果 proxy .[[ProxyTarget]] 是
null ,抛出一个 TypeError 异常。
断言 :
proxy .[[ProxyHandler]] 不是 null 。
返回 unused 。
10.5.15 ProxyCreate ( target , handler )
抽象操作 ProxyCreate 接受参数 target (一个 ECMAScript 语言值 )和
handler (一个 ECMAScript 语言值 )并返回 包含 代理异质对象 的正常完成或 抛出完成 。它用于指定新代理对象的创建。它在被调用时执行以下步骤:
如果 target 不是一个对象 ,抛出一个 TypeError
异常。
如果 handler 不是一个对象 ,抛出一个 TypeError
异常。
让 P 为 MakeBasicObject (« [[ProxyHandler]] , [[ProxyTarget]] »)。
将 P 的基本内部方法(除了 [[Call]] 和 [[Construct]] )设置为 10.5
中指定的定义。
如果 IsCallable (target ) 是
true ,那么
按照 10.5.12
中的指定设置 P .[[Call]] 。
如果 IsConstructor (target )
是 true ,那么
按照 10.5.13
中的指定设置 P .[[Construct]] 。
设置 P .[[ProxyTarget]] 为 target 。
设置 P .[[ProxyHandler]] 为 handler 。
返回 P 。
11 ECMAScript 语言:源文本
11.1 源文本
语法
SourceCharacter ::
任何 Unicode 码点
ECMAScript 源文本 是一个 Unicode 码点序列。所有从 U+0000 到 U+10FFFF 的 Unicode
码点值,包括代理码点,都可以出现在 ECMAScript 语法允许的 ECMAScript 源文本中。用于存储和交换 ECMAScript
源文本的实际编码与本规范无关。无论外部源文本编码如何,符合要求的 ECMAScript 实现都会将源文本处理为等效的 SourceCharacter 值序列,每个 SourceCharacter 都是一个 Unicode 码点。符合要求的 ECMAScript
实现不需要对源文本执行任何规范化,也不需要表现得好像它们正在执行源文本规范化。
组合字符序列的组成部分被视为单独的 Unicode 码点,即使用户可能认为整个序列是一个字符。
注
在字符串字面量、正则表达式字面量、模板字面量和标识符中,任何 Unicode 码点也可以使用明确表示码点数值的 Unicode
转义序列来表示。在注释中,这样的转义序列作为注释的一部分被有效忽略。
ECMAScript 在 Unicode 转义序列的行为上与 Java 编程语言不同。在 Java 程序中,如果 Unicode 转义序列 \u000A
出现在单行注释中,它会被解释为行终止符(Unicode 码点 U+000A 是换行符 (LF)),因此下一个码点不是注释的一部分。同样,如果 Unicode 转义序列
\u000A
出现在 Java 程序的字符串字面量中,它同样被解释为行终止符,这在字符串字面量中是不允许的——必须写 \n
而不是
\u000A
来使换行符 (LF) 成为字符串字面量值的一部分。在 ECMAScript 程序中,出现在注释中的 Unicode
转义序列永远不会被解释,因此不能促成注释的终止。同样,出现在 ECMAScript 程序字符串字面量中的 Unicode
转义序列总是对字面量有贡献,永远不会被解释为行终止符或可能终止字符串字面量的码点。
11.1.1 静态语义:UTF16EncodeCodePoint ( cp )
抽象操作 UTF16EncodeCodePoint 接受参数 cp (一个 Unicode 码点)并返回一个字符串。它在被调用时执行以下步骤:
断言 :0 ≤
cp ≤ 0x10FFFF。
如果 cp ≤ 0xFFFF,返回由数值为 cp 的码元组成的字符串值。
令 cu1 为数值为 floor ((cp - 0x10000) /
0x400) + 0xD800 的码元。
令 cu2 为数值为 ((cp - 0x10000)
modulo
0x400) + 0xDC00 的码元。
返回 cu1 和 cu2 的 字符串连接 。
11.1.2 静态语义:CodePointsToString ( text )
抽象操作 CodePointsToString 接受参数 text (一个 Unicode 码点序列)并返回一个字符串。它将 text
转换为字符串值,如 6.1.4 中所述。它在被调用时执行以下步骤:
令 result 为空字符串。
对于 text 的每个码点 cp ,执行
设置 result 为 result 和 UTF16EncodeCodePoint (cp )
的 字符串连接 。
返回 result 。
11.1.3 静态语义:UTF16SurrogatePairToCodePoint (
lead , trail )
抽象操作 UTF16SurrogatePairToCodePoint 接受参数 lead (一个码元)和 trail (一个码元)并返回一个码点。形成
UTF-16 代理对 的两个码元被转换为码点。它在被调用时执行以下步骤:
断言 :
lead 是一个 前导代理 ,trail
是一个 后尾代理 。
令 cp 为 (lead - 0xD800) × 0x400 + (trail - 0xDC00) +
0x10000。
返回码点 cp 。
11.1.4 静态语义:CodePointAt ( string ,
position )
抽象操作 CodePointAt 接受参数 string (一个字符串)和 position (一个非负 整数 )并返回一个具有字段 [[CodePoint]] (一个码点)、[[CodeUnitCount]]
(一个正 整数 )和 [[IsUnpairedSurrogate]] (一个布尔值)的 记录 。它将 string
解释为 UTF-16 编码的码点序列,如 6.1.4
中所述,并从中读取一个从索引 position 处的码元开始的单个码点。它在被调用时执行以下步骤:
令 size 为 string 的长度。
断言 :
position ≥ 0 且 position < size 。
令 first 为 string 中索引 position 处的码元。
令 cp 为数值等于 first 数值的码点。
如果 first 既不是 前导代理 也不是 后尾代理 ,那么
返回 记录 {
[[CodePoint]] : cp , [[CodeUnitCount]] : 1, [[IsUnpairedSurrogate]] :
false }。
如果 first 是 后尾代理 或 position + 1 =
size ,那么
返回 记录 {
[[CodePoint]] : cp , [[CodeUnitCount]] : 1, [[IsUnpairedSurrogate]] : true }。
令 second 为 string 中索引 position + 1 处的码元。
如果 second 不是 后尾代理 ,那么
返回 记录 {
[[CodePoint]] : cp , [[CodeUnitCount]] : 1, [[IsUnpairedSurrogate]] : true }。
设置 cp 为 UTF16SurrogatePairToCodePoint (first ,
second )。
返回 记录 { [[CodePoint]] : cp , [[CodeUnitCount]] : 2, [[IsUnpairedSurrogate]] : false }。
11.1.5 静态语义:StringToCodePoints ( string )
抽象操作 StringToCodePoints 接受参数 string (一个字符串)并返回一个码点的 列表 。它返回将 string
解释为 UTF-16 编码的 Unicode 文本所产生的 Unicode 码点序列,如 6.1.4 中所述。它在被调用时执行以下步骤:
令 codePoints 为一个新的空 列表 。
令 size 为 string 的长度。
令 position 为 0。
重复,当 position < size 时,
令 cp 为 CodePointAt (string ,
position )。
将 cp .[[CodePoint]] 追加到
codePoints 。
设置 position 为 position + cp .[[CodeUnitCount]] 。
返回 codePoints 。
11.1.6 静态语义:ParseText ( sourceText ,
goalSymbol )
抽象操作 ParseText 接受参数 sourceText (一个字符串或 Unicode 码点序列)和 goalSymbol (ECMAScript
语法中的一个非终结符)并返回一个 解析节点 或一个非空的 SyntaxError
对象 列表 。它在被调用时执行以下步骤:
如果 sourceText 是一个字符串 ,设置
sourceText 为 StringToCodePoints (sourceText )。
尝试使用 goalSymbol 作为 目标符号 来解析
sourceText ,并分析解析结果以查找任何 早期错误 条件。解析和 早期错误 检测可以以 实现定义 的方式交错进行。
如果解析成功且未发现 早期错误 ,返回解析产生的解析树根部的 解析节点 (goalSymbol 的一个实例)。
否则,返回一个包含一个或多个表示解析错误和/或 早期错误 的 SyntaxError 对象的
列表 。如果存在多个解析错误或
早期错误 ,列表中错误对象的数量和顺序是 实现定义 的,但至少必须存在一个。
注 1
考虑一个在特定点有 早期错误 ,在后面的点也有语法错误的文本。一个先执行解析阶段再执行 早期错误
阶段的实现可能会报告语法错误而不继续进行 早期错误 阶段。一个交错进行这两个活动的实现可能会报告 早期错误
而不继续查找语法错误。第三种实现可能会报告两个错误。所有这些行为都是符合要求的。
注 2
11.2 源代码类型
ECMAScript 代码有四种类型:
注 1
函数代码通常作为函数定义(15.2 )、箭头函数定义
(15.3 )、方法定义
(15.4 )、生成器函数定义
(15.5 )、异步函数定义
(15.8 )、异步生成器函数定义
(15.6 )
和异步箭头函数(15.9 )的主体提供。
函数代码也派生自 Function 构造函数
(20.2.1.1 )、GeneratorFunction
构造函数 (27.3.1.1 )和 AsyncFunction
构造函数 (27.7.1.1 )的参数。
注 2
将 BindingIdentifier
包含在函数代码中的实际效果是,严格模式代码 的早期错误会应用于作为函数名称的 BindingIdentifier ,该函数的主体包含 "use strict"
指令,即使周围的代码不是 严格模式代码 。
11.2.1 指令序言和 Use Strict 指令
指令序言 是作为 FunctionBody 、ScriptBody 或 ModuleBody 的初始 StatementListItem 或 ModuleItem 出现的最长 ExpressionStatement
序列,并且序列中的每个 ExpressionStatement 完全由一个 StringLiteral
标记后跟一个分号组成。分号可以显式出现,也可以通过自动分号插入(12.10 )插入。一个
指令序言 可以是一个空序列。
Use Strict 指令
是 指令序言 中的一个 ExpressionStatement ,其 StringLiteral 是精确的码点序列
"use strict"
或 'use strict'
。一个 Use Strict 指令 不能包含 EscapeSequence 或 LineContinuation 。
一个 指令序言 可能包含多个 Use Strict
指令 。但是,如果发生这种情况,实现可能会发出警告。
注
指令序言 的 ExpressionStatement
在包含的产生式求值期间正常求值。实现可以为那些不是 Use Strict 指令 且出现在 指令序言 中的 ExpressionStatement
定义实现特定的含义。如果存在适当的通知机制,当实现在 指令序言 中遇到一个不是 Use
Strict 指令 且没有由实现定义的含义的 ExpressionStatement 时,应发出警告。
11.2.2 严格模式代码
ECMAScript 句法单元可以使用非限制性或严格模式语法和语义(4.3.2 )进行处理。在以下情况下,代码被解释为 严格模式代码 :
不是严格模式代码的 ECMAScript 代码称为 非严格代码 。
11.2.2.1 静态语义:IsStrict ( node )
抽象操作 IsStrict 接受参数 node (一个 解析节点 )并返回一个布尔值。它在被调用时执行以下步骤:
如果 node 匹配的源文本 是
严格模式代码 ,返回
true ;否则返回 false 。
11.2.3 非 ECMAScript 函数
ECMAScript 实现可以支持对函数 奇异对象 的求值,其求值行为以某种 宿主定义 的可执行代码形式表示,而不是 ECMAScript
源文本 。从调用或被此类 函数对象 调用的 ECMAScript 代码的角度来看,函数对象 是在
ECMAScript 代码中定义的还是内置函数是不可观察的。
12 ECMAScript 语言:词法语法
ECMAScript 脚本 或 模块
的源文本首先被转换为输入元素序列,这些输入元素是标记、行终止符、注释或空白符。源文本从左到右扫描,重复地取尽可能长的码点序列作为下一个输入元素。
在某些情况下,词法输入元素的识别对消费输入元素的句法语法上下文很敏感。这需要词法语法具有多个 目标符号 。InputElementHashbangOrRegExp 目标用于 脚本 或 模块 的开始。InputElementRegExpOrTemplateTail
目标用于允许 RegularExpressionLiteral 、TemplateMiddle 或 TemplateTail 的句法语法上下文中。InputElementRegExp 目标符号 用于所有允许 RegularExpressionLiteral 但不允许 TemplateMiddle 或 TemplateTail 的句法语法上下文中。InputElementTemplateTail
目标用于所有允许 TemplateMiddle 或 TemplateTail 但不允许 RegularExpressionLiteral
的句法语法上下文中。在所有其他上下文中,InputElementDiv
用作词法 目标符号 。
注
使用多个词法目标确保不存在会影响自动分号插入的词法歧义。例如,不存在既允许前导除法或除法赋值又允许前导 RegularExpressionLiteral
的句法语法上下文。这不受分号插入的影响(参见 12.10 );在如下例子中:
a = b
/hi/g.exec (c).map (d);
其中 LineTerminator
后第一个非空白、非注释码点是 U+002F(斜线),且句法上下文允许除法或除法赋值,则不会在 LineTerminator 处插入分号。也就是说,上述例子的解释方式与以下相同:
a = b / hi / g.exec (c).map (d);
语法
InputElementDiv ::
WhiteSpace
LineTerminator
Comment
CommonToken
DivPunctuator
RightBracePunctuator
InputElementRegExp ::
WhiteSpace
LineTerminator
Comment
CommonToken
RightBracePunctuator
RegularExpressionLiteral
InputElementRegExpOrTemplateTail
::
WhiteSpace
LineTerminator
Comment
CommonToken
RegularExpressionLiteral
TemplateSubstitutionTail
InputElementTemplateTail
::
WhiteSpace
LineTerminator
Comment
CommonToken
DivPunctuator
TemplateSubstitutionTail
InputElementHashbangOrRegExp
::
WhiteSpace
LineTerminator
Comment
CommonToken
HashbangComment
RegularExpressionLiteral
12.1 Unicode 格式控制字符
Unicode 格式控制字符(即 Unicode 字符数据库中类别为 "Cf" 的字符,如从左到右标记或从右到左标记)是在缺乏用于此目的的高级协议(如标记语言)的情况下用于控制文本范围格式的控制代码。
允许格式控制字符出现在源文本中是有用的,以便于编辑和显示。所有格式控制字符都可以在注释中以及字符串字面量、模板字面量和正则表达式字面量中使用。
U+FEFF(零宽度无间断空格)是一个格式控制字符,主要用于文本的开头,以将其标记为 Unicode 并允许检测文本的编码和字节顺序。用于此目的的 <ZWNBSP>
字符有时也可能出现在文本开头之后,例如作为连接文件的结果。在 ECMAScript 源文本 中,<ZWNBSP>
码点在注释、字符串字面量、模板字面量和正则表达式字面量之外被视为空白字符(参见 12.2 )。
12.2 空白符
空白码点用于改善源文本的可读性并将标记(不可分割的词法单元)彼此分离,但在其他方面是无关紧要的。空白码点可以出现在任意两个标记之间以及输入的开始或结束处。空白码点可以出现在 StringLiteral 、RegularExpressionLiteral 、Template 或 TemplateSubstitutionTail
中,在这些地方它们被视为构成字面量值一部分的重要码点。它们也可以出现在 Comment 中,但不能出现在任何其他类型的标记内。
ECMAScript 空白码点列在 表 35 中。
表 35:空白码点
码点
名称
缩写
U+0009
字符制表符
<TAB>
U+000B
行制表符
<VT>
U+000C
换页符 (FF)
<FF>
U+FEFF
零宽度无间断空格
<ZWNBSP>
通用类别 "Space_Separator" 中的任何码点
<USP>
注 1
U+0020(空格)和 U+00A0(无间断空格)码点是 <USP> 的一部分。
注 2
除了 表 35 中列出的码点外,ECMAScript WhiteSpace 有意排除了所有具有 Unicode
"White_Space" 属性但未归类为通用类别 "Space_Separator"("Zs")的码点。
语法
WhiteSpace ::
<TAB>
<VT>
<FF>
<ZWNBSP>
<USP>
12.3 行终止符
与空白码点一样,行终止符码点用于改善源文本的可读性并将标记(不可分割的词法单元)彼此分离。但是,与空白码点不同,行终止符对句法语法的行为有一定影响。通常,行终止符可以出现在任意两个标记之间,但在句法语法禁止的少数地方则不行。行终止符还会影响自动分号插入的过程(12.10 )。行终止符不能出现在任何标记内,除了 StringLiteral 、Template 或 TemplateSubstitutionTail 。<LF> 和
<CR> 行终止符不能出现在 StringLiteral 标记内,除非作为 LineContinuation 的一部分。
行终止符可以出现在 MultiLineComment
内,但不能出现在 SingleLineComment 内。
行终止符被包含在正则表达式中 \s
类匹配的空白码点集合中。
ECMAScript 行终止符码点列在 表 36 中。
表 36:行终止符码点
码点
Unicode 名称
缩写
U+000A
换行符 (LF)
<LF>
U+000D
回车符 (CR)
<CR>
U+2028
行分隔符
<LS>
U+2029
段分隔符
<PS>
只有 表 36 中的 Unicode 码点被视为行终止符。其他换行或断行的
Unicode 码点不被视为行终止符,但如果它们满足 表 35 中列出的要求,则被视为空白符。序列
<CR><LF> 通常用作行终止符。为了报告行号的目的,它应该被视为单个 SourceCharacter 。
语法
LineTerminator ::
<LF>
<CR>
<LS>
<PS>
LineTerminatorSequence
::
<LF>
<CR>
[lookahead ≠ <LF> ]
<LS>
<PS>
<CR>
<LF>
12.5 Hashbang 注释
Hashbang 注释对位置敏感,与其他类型的注释一样,从句法语法的输入元素流中被丢弃。
语法
12.6 标记
语法
CommonToken ::
IdentifierName
PrivateIdentifier
Punctuator
NumericLiteral
StringLiteral
Template
注
12.7 名称和关键字
IdentifierName 和 ReservedWord 是根据 Unicode 标准附件
#31《标识符和模式语法》中给定的默认标识符语法进行解释的标记,但有一些小的修改。ReservedWord 是 IdentifierName 的一个枚举子集。句法语法将 Identifier 定义为不是 ReservedWord 的 IdentifierName 。Unicode 标识符语法基于
Unicode 标准规定的字符属性。所有符合的 ECMAScript 实现必须将最新版本 Unicode 标准中指定类别的 Unicode 码点视为属于那些类别。ECMAScript 实现可以识别在
Unicode 标准后续版本中定义的标识符码点。
注 1
本标准规定了特定的码点添加:U+0024(美元符号)和 U+005F(下划线)允许出现在 IdentifierName 的任何位置。
语法
PrivateIdentifier ::
#
IdentifierName
IdentifierName ::
IdentifierStart
IdentifierName
IdentifierPart
IdentifierStart ::
IdentifierStartChar
\
UnicodeEscapeSequence
IdentifierPart ::
IdentifierPartChar
\
UnicodeEscapeSequence
IdentifierStartChar
::
UnicodeIDStart
$
_
IdentifierPartChar ::
UnicodeIDContinue
$
AsciiLetter ::
one of a b c
d e f g h
i j k l m
n o p q r
s t u v w
x y z A B
C D E F G
H I J K L
M N O P Q
R S T U V
W X Y Z
UnicodeIDStart ::
任何具有 Unicode 属性 "ID_Start" 的 Unicode 码点
UnicodeIDContinue ::
任何具有 Unicode 属性 "ID_Continue" 的 Unicode 码点
非终结符 UnicodeEscapeSequence
的定义在 12.9.4 中给出。
注 2
注 3
具有 Unicode 属性 "ID_Start" 和 "ID_Continue" 的码点集合分别包括具有 Unicode 属性 "Other_ID_Start" 和
"Other_ID_Continue" 的码点。
12.7.1 标识符名称
Unicode 转义序列在 IdentifierName
中是允许的,它们贡献一个等于 UnicodeEscapeSequence 的 IdentifierCodePoint 的单个 Unicode
码点。UnicodeEscapeSequence 前面的 \
不贡献任何码点。UnicodeEscapeSequence 不能用于为 IdentifierName
贡献一个本来无效的码点。换句话说,如果 \
UnicodeEscapeSequence 序列被它所贡献的 SourceCharacter 替换,结果仍然必须是一个有效的
IdentifierName ,且具有与原始
IdentifierName 完全相同的 SourceCharacter 元素序列。本规范中对
IdentifierName
的所有解释都基于它们的实际码点,无论是否使用转义序列来贡献任何特定码点。
根据 Unicode 标准规范等价的两个 IdentifierName 是不 相等的,除非在替换每个 UnicodeEscapeSequence
后,它们由完全相同的码点序列表示。
12.7.1.1 静态语义:早期错误
IdentifierStart
::
\
UnicodeEscapeSequence
IdentifierPart ::
\
UnicodeEscapeSequence
12.7.1.2 静态语义:IdentifierCodePoints
语法导向操作
IdentifierCodePoints 不接受参数并返回码点的 列表 。它在以下产生式上分段定义:
IdentifierName ::
IdentifierStart
设 cp 为 IdentifierStart 的 IdentifierCodePoint 。
返回 « cp »。
IdentifierName ::
IdentifierName
IdentifierPart
设 cps 为派生的 IdentifierName 的 IdentifierCodePoints 。
设 cp 为 IdentifierPart 的 IdentifierCodePoint 。
返回 cps 和 « cp » 的 列表连接 。
12.7.1.3 静态语义:IdentifierCodePoint
语法导向操作
IdentifierCodePoint 不接受参数并返回一个码点。它在以下产生式上分段定义:
IdentifierStart
:: IdentifierStartChar
返回 IdentifierStartChar 匹配的码点。
IdentifierPart ::
IdentifierPartChar
返回 IdentifierPartChar 匹配的码点。
UnicodeEscapeSequence
::
u
Hex4Digits
返回数值等于 Hex4Digits 的
MV 的码点。
UnicodeEscapeSequence
::
u{
CodePoint
}
返回数值等于 CodePoint 的 MV
的码点。
12.7.2 关键字和保留字
关键字 是匹配 IdentifierName
但也有句法用途的标记;也就是说,它在某些句法产生式中以固定宽度
字体直接出现。ECMAScript 的关键字包括
if
、while
、async
、await
等等。
保留字 是不能用作标识符的 IdentifierName 。许多关键字是保留字,但有些不是,有些只在特定上下文中保留。if
和 while
是保留字。await
只在异步函数和模块内保留。async
不是保留的;它可以无限制地用作变量名或语句标签。
本规范使用语法产生式和 早期错误 规则的组合来指定哪些名称是有效标识符,哪些是保留字。下面 ReservedWord 列表中的所有标记,除了
await
和 yield
,都是无条件保留的。await
和 yield
的例外在
13.1
中使用参数化句法产生式指定。最后,几个 早期错误 规则限制有效标识符的集合。参见 13.1.1 、14.3.1.1 、14.7.5.1
和 15.7.1 。总结来说,标识符名称有五个类别:
总是允许作为标识符且不是关键字的,如 Math
、window
、toString
和
_
;
从不允许作为标识符的,即下面列出的 ReservedWord (除了 await
和
yield
);
上下文允许作为标识符的,即 await
和 yield
;
在 严格模式代码
中上下文不允许作为标识符的:let
、static
、implements
、interface
、package
、private
、protected
和 public
;
总是允许作为标识符,但也在某些句法产生式中作为关键字出现,在不允许 Identifier
的地方:as
、async
、from
、get
、meta
、of
、set
和 target
。
条件关键字 或 上下文关键字 这个术语有时用来指属于后三个类别的关键字,因此可以在某些上下文中用作标识符,在其他上下文中用作关键字。
语法
ReservedWord ::
one of await break
case catch class const
continue debugger default
delete do else enum
export extends false finally
for function if import
in instanceof new null
return super switch this
throw true try typeof
var void while with
yield
注 1
根据 5.1.5 ,语法中的关键字匹配特定 SourceCharacter
元素的文字序列。关键字中的码点不能用 \
UnicodeEscapeSequence 表示。
IdentifierName 可以包含
\
UnicodeEscapeSequence ,但不可能通过拼写
els\u{65}
来声明名为 "else" 的变量。13.1.1 中的
早期错误
规则排除了与保留字具有相同 StringValue 的标识符。
注 2
enum
目前在本规范中未用作关键字。它是一个未来保留字 ,留作未来语言扩展中用作关键字。
类似地,implements
、interface
、package
、private
、protected
和 public
在 严格模式代码 中是未来保留字。
注 3
名称 arguments
和 eval
不是关键字,但它们在 严格模式代码 中受到一些限制。参见 13.1.1 、8.6.4 、15.2.1 、15.5.1 、15.6.1
和 15.8.1 。
12.8 标点符号
语法
Punctuator ::
OptionalChainingPunctuator
OtherPunctuator
OptionalChainingPunctuator
::
?.
[lookahead ∉ DecimalDigit ]
OtherPunctuator ::
one of { ( )
[ ] . ... ;
, < > <=
>= == != ===
!== + - * %
** ++ -- <<
>> >>> & |
^ ! ~ &&
|| ?? ? : =
+= -= *= %= **=
<<= >>= >>>=
&= |= ^= &&=
||= ??= =>
DivPunctuator ::
/
/=
RightBracePunctuator
::
}
12.9 字面量
12.9.1 Null 字面量
语法
NullLiteral ::
null
12.9.2 布尔字面量
语法
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
NumericLiteralSeparator opt
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 不能是 IdentifierStart 或 DecimalDigit 。
注
例如:3in
是一个错误,而不是两个输入元素 3
和 in
。
12.9.3.1 静态语义:早期错误
NumericLiteral ::
LegacyOctalIntegerLiteral
DecimalIntegerLiteral
:: NonOctalDecimalIntegerLiteral
如果 IsStrict (this production) 是
true ,则这是语法错误。
注
12.9.3.2 静态语义:MV
数值字面量表示 Number 类型 或
BigInt 类型 的值。
12.9.3.3 静态语义:NumericValue
语法导向操作
NumericValue 不接受参数并返回一个 Number 或 BigInt。它在以下产生式上分段定义:
NumericLiteral ::
DecimalLiteral
返回 RoundMVResult (DecimalLiteral 的
MV)。
NumericLiteral ::
NonDecimalIntegerLiteral
返回 𝔽 (NonDecimalIntegerLiteral
的 MV)。
NumericLiteral ::
LegacyOctalIntegerLiteral
返回 𝔽 (LegacyOctalIntegerLiteral
的 MV)。
NumericLiteral ::
NonDecimalIntegerLiteral
BigIntLiteralSuffix
返回 NonDecimalIntegerLiteral
的 MV 的 BigInt 值 。
DecimalBigIntegerLiteral
::
0
BigIntLiteralSuffix
返回 0 ℤ 。
DecimalBigIntegerLiteral
::
NonZeroDigit
BigIntLiteralSuffix
返回 NonZeroDigit 的
MV 的 BigInt 值 。
DecimalBigIntegerLiteral
::
NonZeroDigit
DecimalDigits
BigIntLiteralSuffix
NonZeroDigit
NumericLiteralSeparator
DecimalDigits
BigIntLiteralSuffix
让 n 为 DecimalDigits 中的码点数,不包括所有 NumericLiteralSeparator
的出现。
让 mv 为(NonZeroDigit 的 MV ×
10n )加上 DecimalDigits 的 MV。
返回 ℤ (mv )。
12.9.4 字符串字面量
注 1
字符串字面量是用单引号或双引号括起来的 0 个或多个 Unicode 码点。Unicode
码点也可以用转义序列表示。除了结束引号码点、U+005C(反斜杠)、U+000D(回车符)和
U+000A(换行符)之外,所有码点都可以直接出现在字符串字面量中。任何码点都可以以转义序列的形式出现。字符串字面量求值为 ECMAScript String 值。生成这些
String 值时,Unicode 码点按照 11.1.1 中定义的方式进行 UTF-16
编码。属于基本多语言平面的码点被编码为字符串的单个码元素。所有其他码点被编码为字符串的两个码元素。
语法
StringLiteral ::
"
DoubleStringCharacters opt
"
'
SingleStringCharacters opt
'
DoubleStringCharacters
::
DoubleStringCharacter
DoubleStringCharacters opt
SingleStringCharacters
::
SingleStringCharacter
SingleStringCharacters opt
DoubleStringCharacter
::
SourceCharacter
but not one of " or \ or LineTerminator
<LS>
<PS>
\
EscapeSequence
LineContinuation
SingleStringCharacter
::
SourceCharacter
but not one of ' or \ or LineTerminator
<LS>
<PS>
\
EscapeSequence
LineContinuation
LineContinuation ::
\
LineTerminatorSequence
EscapeSequence ::
CharacterEscapeSequence
0
[lookahead ∉ DecimalDigit ]
LegacyOctalEscapeSequence
NonOctalDecimalEscapeSequence
HexEscapeSequence
UnicodeEscapeSequence
CharacterEscapeSequence
::
SingleEscapeCharacter
NonEscapeCharacter
SingleEscapeCharacter
:: one of '
" \ b f n
r t v
NonEscapeCharacter
::
SourceCharacter
but not one of EscapeCharacter or LineTerminator
EscapeCharacter ::
SingleEscapeCharacter
DecimalDigit
x
u
LegacyOctalEscapeSequence
::
0
[lookahead ∈ { 8 , 9 }]
NonZeroOctalDigit
[lookahead ∉ OctalDigit ]
ZeroToThree
OctalDigit
[lookahead ∉ OctalDigit ]
FourToSeven
OctalDigit
ZeroToThree
OctalDigit
OctalDigit
NonZeroOctalDigit
::
OctalDigit but
not 0
ZeroToThree ::
one of 0 1 2
3
FourToSeven ::
one of 4 5 6
7
NonOctalDecimalEscapeSequence
:: one of 8
9
HexEscapeSequence
::
x
HexDigit
HexDigit
UnicodeEscapeSequence
::
u
Hex4Digits
u{
CodePoint
}
Hex4Digits ::
HexDigit
HexDigit
HexDigit
HexDigit
非终结符 HexDigit 的定义在 12.9.3 中给出。SourceCharacter 在 11.1 中定义。
注 2
<LF> 和 <CR> 不能出现在字符串字面量中,除非作为 LineContinuation
的一部分来产生空码点序列。在字符串字面量的 String 值中包含它们的正确方法是使用转义序列,如 \n
或 \u000A
。
12.9.4.1 静态语义:早期错误
EscapeSequence ::
LegacyOctalEscapeSequence
NonOctalDecimalEscapeSequence
如果 IsStrict (this production) 是
true ,则这是语法错误。
注 1
注 2
字符串字面量可能出现在将封闭代码置于 严格模式 的 Use
Strict 指令 之前,实现必须注意对这类字面量强制执行上述规则。例如,以下源文本包含语法错误:
function invalid ( ) { "\7" ; "use strict" ; }
12.9.4.2 静态语义:SV
语法导向操作
SV 不接受参数并返回一个 String。
字符串字面量表示 String 类型 的值。SV
通过对字符串字面量的各个部分进行递归应用来为字符串字面量产生 String 值。作为此过程的一部分,字符串字面量内的一些 Unicode 码点被解释为具有 数学值 ,如下所述或在 12.9.3 中所述。
表 37:字符串单字符转义序列
转义序列
码元值
Unicode 字符名称
符号
\b
0x0008
BACKSPACE
<BS>
\t
0x0009
CHARACTER TABULATION
<HT>
\n
0x000A
LINE FEED (LF)
<LF>
\v
0x000B
LINE TABULATION
<VT>
\f
0x000C
FORM FEED (FF)
<FF>
\r
0x000D
CARRIAGE RETURN (CR)
<CR>
\"
0x0022
QUOTATION MARK
"
\'
0x0027
APOSTROPHE
'
\\
0x005C
REVERSE SOLIDUS
\
12.9.4.3 静态语义:MV
12.9.5 正则表达式字面量
注 1
正则表达式字面量是一个输入元素,每次求值该字面量时都会被转换为 RegExp 对象(参见 22.2 )。程序中的两个正则表达式字面量求值为正则表达式对象,即使两个字面量的内容相同,它们也永远不会比较为
===
。RegExp 对象也可以在运行时通过 new RegExp
或调用 RegExp 构造函数
作为函数来创建(参见 22.2.4 )。
下面的产生式描述了正则表达式字面量的语法,并被输入元素扫描器用来找到正则表达式字面量的结尾。包含 RegularExpressionBody 和 RegularExpressionFlags
的源文本随后使用更严格的 ECMAScript 正则表达式语法(22.2.1 )再次解析。
实现可以扩展在 22.2.1 中定义的 ECMAScript 正则表达式语法,但不得扩展下面定义的 RegularExpressionBody 和
RegularExpressionFlags 产生式或这些产生式使用的产生式。
语法
RegularExpressionLiteral
::
/
RegularExpressionBody
/
RegularExpressionFlags
RegularExpressionBody
::
RegularExpressionFirstChar
RegularExpressionChars
RegularExpressionChars
::
[empty]
RegularExpressionChars
RegularExpressionChar
RegularExpressionFirstChar
::
RegularExpressionNonTerminator
but not one of * or \ or / or
[
RegularExpressionBackslashSequence
RegularExpressionClass
RegularExpressionChar
::
RegularExpressionNonTerminator
but not one of \ or / or
[
RegularExpressionBackslashSequence
RegularExpressionClass
RegularExpressionBackslashSequence
::
\
RegularExpressionNonTerminator
RegularExpressionNonTerminator
::
SourceCharacter
but not LineTerminator
RegularExpressionClass
::
[
RegularExpressionClassChars
]
RegularExpressionClassChars
::
[empty]
RegularExpressionClassChars
RegularExpressionClassChar
RegularExpressionClassChar
::
RegularExpressionNonTerminator
but not one of ] or \
RegularExpressionBackslashSequence
RegularExpressionFlags
::
[empty]
RegularExpressionFlags
IdentifierPartChar
注 2
正则表达式字面量不能为空;码元序列 //
不是表示空正则表达式字面量,而是开始单行注释。要指定空正则表达式,请使用:/(?:)/
。
12.9.5.1 静态语义:BodyText
语法导向操作
BodyText 不接受参数并返回源文本。它在以下产生式上分段定义:
RegularExpressionLiteral
::
/
RegularExpressionBody
/
RegularExpressionFlags
返回被识别为 RegularExpressionBody 的源文本。
12.9.5.2 静态语义:FlagText
语法导向操作
FlagText 不接受参数并返回源文本。它在以下产生式上分段定义:
RegularExpressionLiteral
::
/
RegularExpressionBody
/
RegularExpressionFlags
返回被识别为 RegularExpressionFlags
的源文本。
12.9.6 模板字面量词法组件
语法
Template ::
NoSubstitutionTemplate
TemplateHead
NoSubstitutionTemplate
::
`
TemplateCharacters opt
`
TemplateHead ::
`
TemplateCharacters opt
${
TemplateSubstitutionTail
::
TemplateMiddle
TemplateTail
TemplateMiddle ::
}
TemplateCharacters opt
${
TemplateTail ::
}
TemplateCharacters opt
`
TemplateCharacters
::
TemplateCharacter
TemplateCharacters opt
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
注
12.9.6.1 静态语义:TV
语法导向操作
TV 不接受参数并返回 String 或 undefined 。模板字面量组件被 TV 解释为 String 类型 的值。TV
用于构造模板对象的索引组件(通俗地说,模板值)。在 TV 中,转义序列被转义序列表示的 Unicode 码点的 UTF-16 码元替换。
12.9.6.2 静态语义:TRV
语法导向操作
TRV 不接受参数并返回 String。模板字面量组件被 TRV 解释为 String 类型 的值。TRV
用于构造模板对象的原始组件(通俗地说,模板原始值)。TRV 类似于 TV ,区别在于在 TRV 中,转义序列按照它们在字面量中出现的方式被解释。
注
TV 排除 LineContinuation
的码元,而 TRV 包含它们。<CR><LF> 和 <CR> LineTerminatorSequence 对于
TV 和 TRV 都被规范化为
<LF>。需要显式的 TemplateEscapeSequence 来包含
<CR> 或 <CR><LF> 序列。
12.10 自动分号插入
大多数 ECMAScript
语句和声明必须以分号结尾。这些分号可以始终显式地出现在源文本中。但是,为了方便起见,在某些情况下可以从源文本中省略这些分号。这些情况通过说分号在这些情况下被自动插入到源代码标记流中来描述。
12.10.1 自动分号插入规则
在以下规则中,"标记"是指使用当前词法目标符号 确定的实际识别的词法标记,如第 12 章所述。
分号插入有三个基本规则:
当从左到右解析源文本时,遇到语法的任何产生式都不允许的标记(称为违规标记 ),如果满足以下一个或多个条件,则在违规标记之前自动插入分号:
当从左到右解析源文本时,遇到标记输入流的结尾,并且解析器无法将输入标记流解析为目标非终结符的单个实例,则在输入流的结尾自动插入分号。
当从左到右解析源文本时,遇到语法的某些产生式允许的标记,但该产生式是受限产生式 ,并且该标记将是紧接着受限产生式中注释"[no LineTerminator
here]"之后的终结符或非终结符的第一个标记(因此这样的标记称为受限标记),并且受限标记与前一个标记之间至少有一个 LineTerminator 分隔,则在受限标记之前自动插入分号。
但是,前述规则有一个额外的覆盖条件:如果分号随后会被解析为空语句,或者该分号会成为 for
语句头部中的两个分号之一(参见 14.7.4 ),则永远不会自动插入分号。
注
以下是语法中唯一的受限产生式:
UpdateExpression [Yield,
Await] :
LeftHandSideExpression [?Yield,
?Await]
[no LineTerminator
here]
++
LeftHandSideExpression [?Yield,
?Await]
[no LineTerminator
here]
--
ContinueStatement [Yield,
Await] :
continue
;
continue
[no LineTerminator
here]
LabelIdentifier [?Yield,
?Await]
;
BreakStatement [Yield,
Await] :
break
;
break
[no LineTerminator
here]
LabelIdentifier [?Yield,
?Await]
;
ReturnStatement [Yield,
Await] :
return
;
return
[no LineTerminator
here]
Expression [+In,
?Yield, ?Await]
;
ThrowStatement [Yield,
Await] :
throw
[no LineTerminator
here]
Expression [+In,
?Yield, ?Await]
;
YieldExpression [In,
Await] :
yield
yield
[no LineTerminator
here]
AssignmentExpression [?In,
+Yield, ?Await]
yield
[no LineTerminator
here]
*
AssignmentExpression [?In,
+Yield, ?Await]
ArrowFunction [In,
Yield, Await] :
ArrowParameters [?Yield,
?Await]
[no LineTerminator
here]
=>
ConciseBody [?In]
AsyncFunctionDeclaration [Yield,
Await, Default] :
async
[no LineTerminator
here]
function
BindingIdentifier [?Yield,
?Await]
(
FormalParameters [~Yield,
+Await]
)
{
AsyncFunctionBody
}
[+Default]
async
[no LineTerminator
here]
function
(
FormalParameters [~Yield,
+Await]
)
{
AsyncFunctionBody
}
AsyncFunctionExpression
:
async
[no LineTerminator
here]
function
BindingIdentifier [~Yield,
+Await] opt
(
FormalParameters [~Yield,
+Await]
)
{
AsyncFunctionBody
}
AsyncMethod [Yield,
Await] :
async
[no LineTerminator
here]
ClassElementName [?Yield,
?Await]
(
UniqueFormalParameters [~Yield,
+Await]
)
{
AsyncFunctionBody
}
AsyncGeneratorDeclaration [Yield,
Await, Default] :
async
[no LineTerminator
here]
function
*
BindingIdentifier [?Yield,
?Await]
(
FormalParameters [+Yield,
+Await]
)
{
AsyncGeneratorBody
}
[+Default]
async
[no LineTerminator
here]
function
*
(
FormalParameters [+Yield,
+Await]
)
{
AsyncGeneratorBody
}
AsyncGeneratorExpression
:
async
[no LineTerminator
here]
function
*
BindingIdentifier [+Yield,
+Await] opt
(
FormalParameters [+Yield,
+Await]
)
{
AsyncGeneratorBody
}
AsyncGeneratorMethod [Yield,
Await] :
async
[no LineTerminator
here]
*
ClassElementName [?Yield,
?Await]
(
UniqueFormalParameters [+Yield,
+Await]
)
{
AsyncGeneratorBody
}
AsyncArrowFunction [In,
Yield, Await] :
async
[no LineTerminator
here]
AsyncArrowBindingIdentifier [?Yield]
[no LineTerminator
here]
=>
AsyncConciseBody [?In]
CoverCallExpressionAndAsyncArrowHead [?Yield,
?Await]
[no LineTerminator
here]
=>
AsyncConciseBody [?In]
AsyncArrowHead
:
async
[no LineTerminator
here]
ArrowFormalParameters [~Yield,
+Await]
这些受限产生式的实际效果如下:
当遇到 ++
或 --
标记时,解析器会将其视为后缀运算符,如果在前一个标记和 ++
或
--
标记之间至少有一个 LineTerminator ,则在 ++
或
--
标记之前自动插入分号。
当遇到 continue
、break
、return
、throw
或 yield
标记,并且在下一个标记之前遇到 LineTerminator 时,在
continue
、break
、return
、throw
或
yield
标记之后自动插入分号。
当箭头函数参数后面在 =>
标记之前有 LineTerminator
时,自动插入分号,标点符号会导致语法错误。
当 async
标记后面在 function
或 IdentifierName 或 (
标记之前有 LineTerminator
时,自动插入分号,async
标记不被视为与后续标记相同表达式或类元素的一部分。
当 async
标记后面在 *
标记之前有 LineTerminator
时,自动插入分号,标点符号会导致语法错误。
给 ECMAScript 程序员的实际建议是:
后缀 ++
或 --
运算符应该与其操作数在同一行。
return
或 throw
语句中的 Expression 或 yield
表达式中的
AssignmentExpression 应该与
return
、throw
或 yield
标记在同一行开始。
break
或 continue
语句中的 LabelIdentifier 应该与
break
或 continue
标记在同一行。
箭头函数参数的结尾和其 =>
应该在同一行。
异步函数或方法前面的 async
标记应该与紧接着的标记在同一行。
12.10.2 自动分号插入示例
本节是非规范性的。
源代码
{ 1 2 } 3
不是 ECMAScript 语法中的有效句子,即使有自动分号插入规则。相反,源代码
{ 1
2 } 3
也不是有效的 ECMAScript 句子,但通过自动分号插入转换为以下内容:
{ 1
;2 ;} 3 ;
这是一个有效的 ECMAScript 句子。
源代码
for (a; b
)
不是有效的 ECMAScript 句子,并且不会被自动分号插入更改,因为 for
语句的头部需要分号。自动分号插入永远不会插入 for
语句头部中的两个分号之一。
源代码
return
a + b
通过自动分号插入转换为以下内容:
return ;
a + b;
注 1
表达式 a + b
不被视为 return
语句要返回的值,因为 LineTerminator 将其与标记
return
分开。
源代码
a = b
++c
通过自动分号插入转换为以下内容:
a = b;
++c;
注 2
标记 ++
不被视为应用于变量 b
的后缀运算符,因为 LineTerminator 出现在 b
和
++
之间。
源代码
if (a > b)
else c = d
不是有效的 ECMAScript 句子,并且不会被自动分号插入在 else
标记之前更改,即使在该点语法的任何产生式都不适用,因为自动插入的分号随后会被解析为空语句。
源代码
a = b + c
(d + e).print ()
不会 被自动分号插入转换,因为第二行开始的括号表达式可以被解释为函数调用的参数列表:
a = b + c (d + e).print ()
在赋值语句必须以左括号开始的情况下,程序员最好在前一个语句的末尾提供显式分号,而不是依赖自动分号插入。
12.10.3 自动分号插入的有趣情况
本节是非规范性的。
ECMAScript 程序可以通过依赖自动分号插入以很少分号的风格编写。如上所述,分号不会在每个换行符处插入,自动分号插入可能依赖于跨行终止符的多个标记。
随着新的语法特性被添加到 ECMAScript 中,可能会添加额外的语法产生式,这些产生式会导致依赖自动分号插入的行在解析时改变语法产生式。
就本节而言,如果自动分号插入的情况是可能插入或不插入分号的地方,取决于其前面的源文本,则被认为是有趣的。本节的其余部分描述了这个版本的 ECMAScript 中自动分号插入的许多有趣情况。
12.10.3.1 语句列表中自动分号插入的有趣情况
在 StatementList 中,许多
StatementListItem
以分号结尾,这些分号可以使用自动分号插入省略。根据上述规则,在结束表达式的行末尾,如果下一行以以下任何内容开始,则需要分号:
12.10.3.2 自动分号插入和"[no LineTerminator here]"的情况
本节是非规范性的。
ECMAScript 包含包括"[no LineTerminator
here]"的语法产生式。这些产生式有时是在语法中拥有可选操作数的手段。在这些位置引入 LineTerminator
会通过使用没有可选操作数的语法产生式来改变源文本的语法产生式。
本节的其余部分描述了这个版本的 ECMAScript 中使用"[no LineTerminator here]"的许多产生式。
12.10.3.2.1 带有可选操作数和"[no LineTerminator here]"的语法产生式列表
13 ECMAScript 语言:表达式
13.1 标识符
语法
IdentifierReference [Yield,
Await] :
Identifier
[~Yield]
yield
[~Await]
await
BindingIdentifier [Yield,
Await] :
Identifier
yield
await
LabelIdentifier [Yield,
Await] :
Identifier
[~Yield]
yield
[~Await]
await
Identifier :
IdentifierName
but not ReservedWord
注
yield
和 await
在语法中被允许作为 BindingIdentifier ,并在下面的静态语义 中被禁止,以防止在以下情况中自动分号插入
let
await 0 ;
13.1.1 静态语义:早期错误
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
Identifier : IdentifierName but not
ReservedWord
注
13.1.2 静态语义:StringValue
语法导向操作
StringValue 不接受参数并返回 String。它在以下产生式上分段定义:
IdentifierName ::
IdentifierStart
IdentifierName
IdentifierPart
令 idTextUnescaped 为 IdentifierName 的 IdentifierCodePoints 。
返回 CodePointsToString (idTextUnescaped )。
IdentifierReference
: yield
BindingIdentifier
: yield
LabelIdentifier :
yield
返回 "yield" 。
IdentifierReference
: await
BindingIdentifier
: await
LabelIdentifier :
await
返回 "await" 。
Identifier : IdentifierName but not
ReservedWord
返回 IdentifierName 的
StringValue 。
PrivateIdentifier
::
#
IdentifierName
返回 0x0023(数字符号)与 IdentifierName 的 StringValue 的 字符串连接 。
ModuleExportName :
StringLiteral
返回 StringLiteral 的
SV 。
13.1.3 运行时语义:Evaluation
IdentifierReference
: Identifier
返回 ? ResolveBinding (Identifier 的 StringValue )。
IdentifierReference
: yield
返回 ? ResolveBinding ("yield" )。
IdentifierReference
: await
返回 ? ResolveBinding ("await" )。
注 1
求值 IdentifierReference 的结果总是
Reference 类型的值。
注 2
在非严格代码 中,关键字
yield
可以用作标识符。求值 IdentifierReference
解析 yield
的绑定,就像它是 Identifier 一样。早期错误限制确保这种求值只能在非严格代码 中发生。
13.2 主表达式
语法
PrimaryExpression [Yield,
Await] :
this
IdentifierReference [?Yield,
?Await]
Literal
ArrayLiteral [?Yield,
?Await]
ObjectLiteral [?Yield,
?Await]
FunctionExpression
ClassExpression [?Yield,
?Await]
GeneratorExpression
AsyncFunctionExpression
AsyncGeneratorExpression
RegularExpressionLiteral
TemplateLiteral [?Yield,
?Await, ~Tagged]
CoverParenthesizedExpressionAndArrowParameterList [?Yield,
?Await]
CoverParenthesizedExpressionAndArrowParameterList [Yield,
Await] :
(
Expression [+In, ?Yield,
?Await]
)
(
Expression [+In, ?Yield,
?Await]
,
)
(
)
(
...
BindingIdentifier [?Yield,
?Await]
)
(
...
BindingPattern [?Yield,
?Await]
)
(
Expression [+In, ?Yield,
?Await]
,
...
BindingIdentifier [?Yield,
?Await]
)
(
Expression [+In, ?Yield,
?Await]
,
...
BindingPattern [?Yield,
?Await]
)
补充语法
当处理产生式的实例时
PrimaryExpression [Yield,
Await] : CoverParenthesizedExpressionAndArrowParameterList [?Yield,
?Await]
对 CoverParenthesizedExpressionAndArrowParameterList
的解释使用以下语法进行细化:
ParenthesizedExpression [Yield,
Await] :
(
Expression [+In, ?Yield,
?Await]
)
13.2.1 this
关键字
13.2.1.1 运行时语义:Evaluation
PrimaryExpression
: this
返回 ? ResolveThisBinding ()。
13.2.2 标识符引用
关于 IdentifierReference ,请参见 13.1 。
13.2.3 字面量
语法
Literal :
NullLiteral
BooleanLiteral
NumericLiteral
StringLiteral
13.2.3.1 运行时语义:Evaluation
Literal : NullLiteral
返回 null 。
Literal : BooleanLiteral
如果 BooleanLiteral 是标记
false
,返回 false 。
如果 BooleanLiteral 是标记
true
,返回 true 。
Literal : NumericLiteral
返回 NumericLiteral 的 NumericValue ,如 12.9.3 中定义。
Literal : StringLiteral
返回 StringLiteral
的 SV ,如 12.9.4.2 中定义。
13.2.4 数组初始化器
注
ArrayLiteral
是一个表达式,描述使用零个或多个表达式的列表来初始化数组,每个表达式代表一个数组元素,包含在方括号中。元素不需要是字面量;每次求值数组初始化器时都会对它们进行求值。
数组元素可以在元素列表的开头、中间或末尾省略。当元素列表中的逗号前面没有 AssignmentExpression (即开头的逗号或另一个逗号后面的逗号)时,缺失的数组元素会增加数组的长度并增加后续元素的索引。省略的数组元素未定义。如果在数组末尾省略了元素,该元素不会增加数组的长度。
语法
ArrayLiteral [Yield,
Await] :
[
Elision opt
]
[
ElementList [?Yield,
?Await]
]
[
ElementList [?Yield,
?Await]
,
Elision opt
]
ElementList [Yield,
Await] :
Elision opt
AssignmentExpression [+In,
?Yield, ?Await]
Elision opt
SpreadElement [?Yield,
?Await]
ElementList [?Yield,
?Await]
,
Elision opt
AssignmentExpression [+In,
?Yield, ?Await]
ElementList [?Yield,
?Await]
,
Elision opt
SpreadElement [?Yield,
?Await]
Elision :
,
Elision
,
SpreadElement [Yield,
Await] :
...
AssignmentExpression [+In,
?Yield, ?Await]
13.2.4.1 运行时语义:ArrayAccumulation
语法导向操作
ArrayAccumulation 接受参数 array (一个数组)和 nextIndex (一个整数 )并返回包含 一个整数 的正常完成 或一个突然完成 。它在以下产生式上分段定义:
Elision : ,
令 len 为 nextIndex + 1。
执行 ? Set (array ,
"length" , 𝔽 (len ), true )。
注:如果 len 超过 232 - 1,上述步骤会抛出异常。
返回 len 。
Elision :
Elision
,
返回 ? Elision 与参数
array 和 (nextIndex + 1) 的 ArrayAccumulation 。
ElementList :
Elision opt
AssignmentExpression
如果 Elision 存在,则
设置 nextIndex 为 ? Elision 与参数 array 和
nextIndex 的 ArrayAccumulation 。
令 initResult 为 ? AssignmentExpression 的
Evaluation 。
令 initValue 为 ? GetValue (initResult )。
执行 ! CreateDataPropertyOrThrow (array ,
! ToString (𝔽 (nextIndex )),
initValue )。
返回 nextIndex + 1。
ElementList :
Elision opt
SpreadElement
如果 Elision 存在,则
设置 nextIndex 为 ? Elision 与参数 array 和
nextIndex 的 ArrayAccumulation 。
返回 ? SpreadElement 与参数 array 和
nextIndex 的 ArrayAccumulation 。
ElementList :
ElementList
,
Elision opt
AssignmentExpression
设置 nextIndex 为 ? ElementList 与参数 array 和
nextIndex 的 ArrayAccumulation 。
如果 Elision 存在,则
设置 nextIndex 为 ? Elision 与参数 array 和
nextIndex 的 ArrayAccumulation 。
令 initResult 为 ? AssignmentExpression 的
Evaluation 。
令 initValue 为 ? GetValue (initResult )。
执行 ! CreateDataPropertyOrThrow (array ,
! ToString (𝔽 (nextIndex )),
initValue )。
返回 nextIndex + 1。
ElementList :
ElementList
,
Elision opt
SpreadElement
设置 nextIndex 为 ? ElementList 与参数 array 和
nextIndex 的 ArrayAccumulation 。
如果 Elision 存在,则
设置 nextIndex 为 ? Elision 与参数 array 和
nextIndex 的 ArrayAccumulation 。
返回 ? SpreadElement 与参数 array 和
nextIndex 的 ArrayAccumulation 。
SpreadElement :
...
AssignmentExpression
令 spreadRef 为 ? AssignmentExpression 的
Evaluation 。
令 spreadObj 为 ? GetValue (spreadRef )。
令 iteratorRecord 为 ? GetIterator (spreadObj ,
sync )。
重复,
令 next 为 ? IteratorStepValue (iteratorRecord )。
如果 next 是 done ,返回
nextIndex 。
执行 ! CreateDataPropertyOrThrow (array ,
! ToString (𝔽 (nextIndex )),
next )。
设置 nextIndex 为 nextIndex + 1。
注
使用 CreateDataPropertyOrThrow
来确保为数组定义自己的属性,即使标准内置的Array
原型对象 已经以会阻止使用 [[Set]] 创建新自己属性的方式被修改。
13.2.4.2 运行时语义:Evaluation
ArrayLiteral :
[
Elision opt
]
令 array 为 ! ArrayCreate (0)。
如果 Elision 存在,则
执行 ? Elision 与参数 array 和 0 的
ArrayAccumulation 。
返回 array 。
ArrayLiteral :
[
ElementList
]
令 array 为 ! ArrayCreate (0)。
执行 ? ElementList 与参数 array 和 0 的
ArrayAccumulation 。
返回 array 。
ArrayLiteral :
[
ElementList
,
Elision opt
]
令 array 为 ! ArrayCreate (0)。
令 nextIndex 为 ? ElementList 与参数 array 和 0 的
ArrayAccumulation 。
如果 Elision 存在,则
执行 ? Elision 与参数 array 和
nextIndex 的 ArrayAccumulation 。
返回 array 。
13.2.5 对象初始化器
注 1
对象初始化器是一个表达式,描述对象的初始化,以类似字面量的形式编写。它是零个或多个属性键 和关联值的对的列表,包含在花括号中。值不需要是字面量;每次求值对象初始化器时都会对它们进行求值。
语法
ObjectLiteral [Yield,
Await] :
{
}
{
PropertyDefinitionList [?Yield,
?Await]
}
{
PropertyDefinitionList [?Yield,
?Await]
,
}
PropertyDefinitionList [Yield,
Await] :
PropertyDefinition [?Yield,
?Await]
PropertyDefinitionList [?Yield,
?Await]
,
PropertyDefinition [?Yield,
?Await]
PropertyDefinition [Yield,
Await] :
IdentifierReference [?Yield,
?Await]
CoverInitializedName [?Yield,
?Await]
PropertyName [?Yield,
?Await]
:
AssignmentExpression [+In,
?Yield, ?Await]
MethodDefinition [?Yield,
?Await]
...
AssignmentExpression [+In,
?Yield, ?Await]
PropertyName [Yield,
Await] :
LiteralPropertyName
ComputedPropertyName [?Yield,
?Await]
LiteralPropertyName
:
IdentifierName
StringLiteral
NumericLiteral
ComputedPropertyName [Yield,
Await] :
[
AssignmentExpression [+In,
?Yield, ?Await]
]
CoverInitializedName [Yield,
Await] :
IdentifierReference [?Yield,
?Await]
Initializer [+In, ?Yield,
?Await]
Initializer [In, Yield,
Await] :
=
AssignmentExpression [?In,
?Yield, ?Await]
注 2
注 3
在某些上下文中,ObjectLiteral
用作更受限制的次级语法的覆盖语法。CoverInitializedName
产生式是完全覆盖这些次级语法所必需的。但是,在期望实际 ObjectLiteral 的正常上下文中,使用此产生式会导致早期语法错误。
13.2.5.1 静态语义:早期错误
PropertyDefinition
: MethodDefinition
除了描述实际的对象初始化器之外,ObjectLiteral 产生式还用作 ObjectAssignmentPattern
的覆盖语法,并且可能被识别为 CoverParenthesizedExpressionAndArrowParameterList
的一部分。当 ObjectLiteral
出现在需要 ObjectAssignmentPattern
的上下文中时,以下早期错误规则不 适用。此外,在最初解析 CoverParenthesizedExpressionAndArrowParameterList
或 CoverCallExpressionAndAsyncArrowHead
时,它们也不适用。
PropertyDefinition
: CoverInitializedName
注 1
此产生式的存在是为了让 ObjectLiteral 可以作为 ObjectAssignmentPattern
的覆盖语法。它不能出现在实际的对象初始化器中。
ObjectLiteral :
{
PropertyDefinitionList
}
{
PropertyDefinitionList
,
}
注 2
13.2.5.2 静态语义:IsComputedPropertyKey
语法导向操作
IsComputedPropertyKey 不接受参数并返回布尔值。它在以下产生式上分段定义:
PropertyName :
LiteralPropertyName
返回 false 。
PropertyName :
ComputedPropertyName
返回 true 。
13.2.5.3 静态语义:PropertyNameList
语法导向操作
PropertyNameList 不接受参数并返回字符串的列表 。它在以下产生式上分段定义:
PropertyDefinitionList
: PropertyDefinition
令 propName 为 PropertyDefinition 的 PropName 。
如果 propName 是 empty ,返回新的空列表 。
返回 « propName »。
PropertyDefinitionList
:
PropertyDefinitionList
,
PropertyDefinition
令 list 为 PropertyDefinitionList 的
PropertyNameList 。
令 propName 为 PropertyDefinition 的 PropName 。
如果 propName 是 empty ,返回 list 。
返回 list 和 « propName » 的列表连接 。
13.2.5.4 运行时语义:Evaluation
ObjectLiteral :
{
}
返回 OrdinaryObjectCreate (%Object.prototype% )。
ObjectLiteral :
{
PropertyDefinitionList
}
{
PropertyDefinitionList
,
}
令 obj 为 OrdinaryObjectCreate (%Object.prototype% )。
执行 ? PropertyDefinitionList 与参数
obj 的 PropertyDefinitionEvaluation 。
返回 obj 。
LiteralPropertyName
: IdentifierName
返回 IdentifierName 的 StringValue 。
LiteralPropertyName
: StringLiteral
返回 StringLiteral
的 SV 。
LiteralPropertyName
: NumericLiteral
令 nbr 为 NumericLiteral 的 NumericValue 。
返回 ! ToString (nbr )。
ComputedPropertyName
:
[
AssignmentExpression
]
令 exprValue 为 ? AssignmentExpression 的
Evaluation 。
令 propName 为 ? GetValue (exprValue )。
返回 ? ToPropertyKey (propName )。
13.2.5.5 运行时语义:PropertyDefinitionEvaluation
语法导向操作
PropertyDefinitionEvaluation 接受参数 object (一个对象)并返回包含
unused 的正常完成 或突然完成 。它在以下产生式上分段定义:
PropertyDefinitionList
:
PropertyDefinitionList
,
PropertyDefinition
执行 ? PropertyDefinitionList 与参数
object 的 PropertyDefinitionEvaluation 。
执行 ? PropertyDefinition 与参数
object 的 PropertyDefinitionEvaluation 。
返回 unused 。
PropertyDefinition
:
...
AssignmentExpression
令 exprValue 为 ? AssignmentExpression 的
Evaluation 。
令 fromValue 为 ? GetValue (exprValue )。
令 excludedNames 为新的空列表 。
执行 ? CopyDataProperties (object ,
fromValue , excludedNames )。
返回 unused 。
PropertyDefinition
: IdentifierReference
令 propName 为 IdentifierReference 的
StringValue 。
令 exprValue 为 ? IdentifierReference 的
Evaluation 。
令 propValue 为 ? GetValue (exprValue )。
断言 :
object 是一个普通的、可扩展的、没有不可配置属性的对象。
执行 ! CreateDataPropertyOrThrow (object ,
propName , propValue )。
返回 unused 。
PropertyDefinition
:
PropertyName
:
AssignmentExpression
令 propKey 为 ? PropertyName 的 Evaluation 。
如果此 PropertyDefinition 包含在正在为
ParseJSON 求值的 Script 中(参见 ParseJSON 的步骤 6 ),则
令 isProtoSetter 为 false 。
否则,如果 propKey 是 "__proto__" 并且 PropertyName 的
IsComputedPropertyKey
是 false ,则
令 isProtoSetter 为 true 。
否则,
令 isProtoSetter 为 false 。
如果 IsAnonymousFunctionDefinition (AssignmentExpression ) 是
true 并且 isProtoSetter 是 false ,则
令 propValue 为 ? AssignmentExpression
与参数 propKey 的 NamedEvaluation 。
否则,
令 exprValueRef 为 ? AssignmentExpression
的 Evaluation 。
令 propValue 为 ? GetValue (exprValueRef )。
如果 isProtoSetter 是 true ,则
如果 propValue 是对象 或 propValue 是
null ,则
执行 ! object .[[SetPrototypeOf]] (propValue )。
返回 unused 。
断言 :
object 是一个普通的、可扩展的、没有不可配置属性的对象。
执行 ! CreateDataPropertyOrThrow (object ,
propKey , propValue )。
返回 unused 。
PropertyDefinition
: MethodDefinition
执行 ? MethodDefinition 与参数
object 和 true 的 MethodDefinitionEvaluation 。
返回 unused 。
13.2.6 函数定义表达式
有关
PrimaryExpression
: FunctionExpression
,参见 15.2 。
有关
PrimaryExpression
: GeneratorExpression
,参见 15.5 。
有关
PrimaryExpression
: ClassExpression
,参见 15.7 。
有关
PrimaryExpression
: AsyncFunctionExpression
,参见 15.8 。
有关
PrimaryExpression
: AsyncGeneratorExpression
,参见 15.6 。
13.2.7 正则表达式字面量
语法
参见 12.9.5 。
13.2.7.1 静态语义:早期错误
PrimaryExpression
: RegularExpressionLiteral
13.2.7.2 静态语义:IsValidRegularExpressionLiteral (
literal )
抽象操作 IsValidRegularExpressionLiteral 接受参数 literal (一个 RegularExpressionLiteral
解析节点 )并返回布尔值。它确定其参数是否是有效的正则表达式字面量。调用时执行以下步骤:
令 flags 为 literal 的 FlagText 。
如果 flags 包含除
d
、g
、i
、m
、s
、u
、v
或 y
之外的任何码点,或者如果 flags 包含任何码点超过一次,返回
false 。
如果 flags 包含 u
,令 u 为 true ;否则令
u 为 false 。
如果 flags 包含 v
,令 v 为 true ;否则令
v 为 false 。
令 patternText 为 literal 的 BodyText 。
如果 u 是 false 且 v 是
false ,则
令 stringValue 为 CodePointsToString (patternText )。
设置 patternText 为通过将 stringValue 的每个 16 位元素解释为 Unicode
BMP 码点而产生的码点序列。UTF-16 解码不应用于这些元素。
令 parseResult 为 ParsePattern (patternText ,
u , v )。
如果 parseResult 是解析节点 ,返回
true ;否则返回 false 。
13.2.7.3 运行时语义:Evaluation
PrimaryExpression
: RegularExpressionLiteral
令 pattern 为 CodePointsToString (RegularExpressionLiteral
的 BodyText )。
令 flags 为 CodePointsToString (RegularExpressionLiteral
的 FlagText )。
返回 ! RegExpCreate (pattern ,
flags )。
13.2.8 模板字面量
语法
TemplateLiteral [Yield, Await,
Tagged] :
NoSubstitutionTemplate
SubstitutionTemplate [?Yield,
?Await, ?Tagged]
SubstitutionTemplate [Yield,
Await, Tagged] :
TemplateHead
Expression [+In, ?Yield,
?Await]
TemplateSpans [?Yield,
?Await, ?Tagged]
TemplateSpans [Yield, Await,
Tagged] :
TemplateTail
TemplateMiddleList [?Yield,
?Await, ?Tagged]
TemplateTail
TemplateMiddleList [Yield,
Await, Tagged] :
TemplateMiddle
Expression [+In, ?Yield,
?Await]
TemplateMiddleList [?Yield,
?Await, ?Tagged]
TemplateMiddle
Expression [+In, ?Yield,
?Await]
13.2.8.1 静态语义:早期错误
TemplateLiteral [Yield,
Await, Tagged] :
NoSubstitutionTemplate
TemplateLiteral [Yield,
Await, Tagged] :
SubstitutionTemplate [?Yield,
?Await, ?Tagged]
SubstitutionTemplate [Yield,
Await, Tagged] :
TemplateHead
Expression [+In, ?Yield,
?Await]
TemplateSpans [?Yield,
?Await, ?Tagged]
TemplateSpans [Yield, Await,
Tagged] : TemplateTail
TemplateMiddleList [Yield,
Await, Tagged] :
TemplateMiddle
Expression [+In, ?Yield,
?Await]
TemplateMiddleList [?Yield,
?Await, ?Tagged]
TemplateMiddle
Expression [+In, ?Yield,
?Await]
13.2.8.2 静态语义:TemplateStrings
语法导向操作
TemplateStrings 接受参数 raw (布尔值)并返回字符串或 undefined 的列表 。它在以下产生式上分段定义:
TemplateLiteral
: NoSubstitutionTemplate
返回 « TemplateString (NoSubstitutionTemplate ,
raw ) »。
SubstitutionTemplate
:
TemplateHead
Expression
TemplateSpans
令 head 为 « TemplateString (TemplateHead ,
raw ) »。
令 tail 为 TemplateSpans 使用参数 raw 的
TemplateStrings 。
返回 head 和 tail 的列表连接 。
TemplateSpans :
TemplateTail
返回 « TemplateString (TemplateTail ,
raw ) »。
TemplateSpans :
TemplateMiddleList
TemplateTail
令 middle 为 TemplateMiddleList 使用参数
raw 的 TemplateStrings 。
令 tail 为 « TemplateString (TemplateTail ,
raw ) »。
返回 middle 和 tail 的列表连接 。
TemplateMiddleList
:
TemplateMiddle
Expression
返回 « TemplateString (TemplateMiddle ,
raw ) »。
TemplateMiddleList
:
TemplateMiddleList
TemplateMiddle
Expression
令 front 为 TemplateMiddleList 使用参数
raw 的 TemplateStrings 。
令 last 为 « TemplateString (TemplateMiddle ,
raw ) »。
返回 front 和 last 的列表连接 。
13.2.8.3 静态语义:TemplateString ( templateToken ,
raw )
抽象操作 TemplateString 接受参数 templateToken (一个 NoSubstitutionTemplate 解析节点 、TemplateHead 解析节点 、TemplateMiddle 解析节点 ,或 TemplateTail 解析节点 )和 raw (布尔值)并返回字符串或
undefined 。调用时执行以下步骤:
如果 raw 是 true ,则
令 string 为 templateToken 的 TRV 。
否则,
令 string 为 templateToken 的 TV 。
返回 string 。
注
如果 raw 是 false 且 templateToken 包含 NotEscapeSequence ,此操作返回
undefined 。在所有其他情况下,它返回字符串。
13.2.8.4 GetTemplateObject ( templateLiteral )
抽象操作 GetTemplateObject 接受参数 templateLiteral (一个解析节点 )并返回数组。调用时执行以下步骤:
令 realm 为当前领域记录 。
令 templateRegistry 为 realm .[[TemplateMap]] 。
对于 templateRegistry 的每个元素 e ,执行
如果 e .[[Site]] 与
templateLiteral 是同一个解析节点 ,则
返回 e .[[Array]] 。
令 rawStrings 为 templateLiteral 使用参数 true 的
TemplateStrings 。
断言 :rawStrings 是字符串的列表 。
令 cookedStrings 为 templateLiteral 使用参数
false 的 TemplateStrings 。
令 count 为列表
cookedStrings 中的元素数量。
断言 :count ≤ 232 - 1。
令 template 为 ! ArrayCreate (count )。
令 rawObj 为 ! ArrayCreate (count )。
令 index 为 0。
重复,当 index < count 时,
令 prop 为 ! ToString (𝔽 (index ))。
令 cookedValue 为 cookedStrings [index ]。
执行 ! DefinePropertyOrThrow (template ,
prop , PropertyDescriptor { [[Value]] :
cookedValue , [[Writable]] :
false , [[Enumerable]] :
true , [[Configurable]] :
false })。
令 rawValue 为字符串值 rawStrings [index ]。
执行 ! DefinePropertyOrThrow (rawObj ,
prop , PropertyDescriptor { [[Value]] :
rawValue , [[Writable]] :
false , [[Enumerable]] :
true , [[Configurable]] :
false })。
设置 index 为 index + 1。
执行 ! SetIntegrityLevel (rawObj ,
frozen )。
执行 ! DefinePropertyOrThrow (template ,
"raw" , PropertyDescriptor { [[Value]] :
rawObj , [[Writable]] : false ,
[[Enumerable]] : false , [[Configurable]] : false })。
执行 ! SetIntegrityLevel (template ,
frozen )。
将记录 { [[Site]] : templateLiteral , [[Array]] : template } 附加到
realm .[[TemplateMap]] 。
返回 template 。
注 1
注 2
领域 程序代码中的每个
TemplateLiteral
都与一个唯一的模板对象相关联,该对象用于带标签模板的求值(13.2.8.6 )。模板对象被冻结,每次求值特定带标签模板时都使用相同的模板对象。模板对象是在首次求值
TemplateLiteral
时惰性创建,还是在首次求值前急切创建,是实现选择,ECMAScript 代码无法观察到。
注 3
本规范的未来版本可能定义模板对象的附加不可枚举属性。
13.2.8.5 运行时语义:SubstitutionEvaluation
语法导向操作
SubstitutionEvaluation 不接受参数并返回包含
ECMAScript 语言值 的列表 的正常完成 或突然完成 。它在以下产生式上分段定义:
TemplateSpans :
TemplateTail
返回新的空列表 。
TemplateSpans :
TemplateMiddleList
TemplateTail
返回 ? TemplateMiddleList 的 SubstitutionEvaluation 。
TemplateMiddleList
:
TemplateMiddle
Expression
令 subRef 为 ? Expression 的 Evaluation 。
令 sub 为 ? GetValue (subRef )。
返回 « sub »。
TemplateMiddleList
:
TemplateMiddleList
TemplateMiddle
Expression
令 preceding 为 ? TemplateMiddleList 的 SubstitutionEvaluation 。
令 nextRef 为 ? Expression 的 Evaluation 。
令 next 为 ? GetValue (nextRef )。
返回 preceding 和 « next » 的列表连接 。
13.2.8.6 运行时语义:Evaluation
TemplateLiteral
: NoSubstitutionTemplate
返回 NoSubstitutionTemplate 的
TV ,如 12.9.6 中定义。
SubstitutionTemplate
:
TemplateHead
Expression
TemplateSpans
令 head 为 TemplateHead 的 TV ,如 12.9.6 中定义。
令 subRef 为 ? Expression 的 Evaluation 。
令 sub 为 ? GetValue (subRef )。
令 middle 为 ? ToString (sub )。
令 tail 为 ? TemplateSpans 的 Evaluation 。
返回 head 、middle 和 tail 的字符串连接 。
注 1
应用于 Expression
值的字符串转换语义类似于 String.prototype.concat
而不是 +
运算符。
TemplateSpans :
TemplateTail
返回 TemplateTail 的
TV ,如 12.9.6 中定义。
TemplateSpans :
TemplateMiddleList
TemplateTail
令 head 为 ? TemplateMiddleList 的 Evaluation 。
令 tail 为 TemplateTail 的 TV ,如 12.9.6 中定义。
返回 head 和 tail 的字符串连接 。
TemplateMiddleList
:
TemplateMiddle
Expression
令 head 为 TemplateMiddle 的 TV ,如
12.9.6 中定义。
令 subRef 为 ? Expression 的 Evaluation 。
令 sub 为 ? GetValue (subRef )。
令 middle 为 ? ToString (sub )。
返回 head 和 middle 的字符串连接 。
注 2
应用于 Expression
值的字符串转换语义类似于 String.prototype.concat
而不是 +
运算符。
TemplateMiddleList
:
TemplateMiddleList
TemplateMiddle
Expression
令 rest 为 ? TemplateMiddleList 的 Evaluation 。
令 middle 为 TemplateMiddle 的 TV ,如
12.9.6 中定义。
令 subRef 为 ? Expression 的 Evaluation 。
令 sub 为 ? GetValue (subRef )。
令 last 为 ? ToString (sub )。
返回 rest 、middle 和 last 的字符串连接 。
注 3
应用于 Expression
值的字符串转换语义类似于 String.prototype.concat
而不是 +
运算符。
13.2.9 分组运算符
13.2.9.1 静态语义:早期错误
PrimaryExpression
: CoverParenthesizedExpressionAndArrowParameterList
13.2.9.2 运行时语义:Evaluation
PrimaryExpression
: CoverParenthesizedExpressionAndArrowParameterList
令 expr 为被 CoverParenthesizedExpressionAndArrowParameterList
覆盖 的 ParenthesizedExpression 。
返回 ? expr 的 Evaluation 。
ParenthesizedExpression
:
(
Expression
)
返回 ? Expression
的 Evaluation 。这可能是引用类型。
注
此算法不对 Expression 的
Evaluation 应用 GetValue 。这样做的主要动机是使 delete
和 typeof
等运算符可以应用于带括号的表达式。
13.3 左值表达式
语法
MemberExpression [Yield,
Await] :
PrimaryExpression [?Yield,
?Await]
MemberExpression [?Yield,
?Await]
[
Expression [+In, ?Yield,
?Await]
]
MemberExpression [?Yield,
?Await]
.
IdentifierName
MemberExpression [?Yield,
?Await]
TemplateLiteral [?Yield,
?Await, +Tagged]
SuperProperty [?Yield,
?Await]
MetaProperty
new
MemberExpression [?Yield,
?Await]
Arguments [?Yield,
?Await]
MemberExpression [?Yield,
?Await]
.
PrivateIdentifier
SuperProperty [Yield,
Await] :
super
[
Expression [+In, ?Yield,
?Await]
]
super
.
IdentifierName
MetaProperty :
NewTarget
ImportMeta
NewTarget :
new
.
target
ImportMeta :
import
.
meta
NewExpression [Yield,
Await] :
MemberExpression [?Yield,
?Await]
new
NewExpression [?Yield,
?Await]
CallExpression [Yield,
Await] :
CoverCallExpressionAndAsyncArrowHead [?Yield,
?Await]
SuperCall [?Yield,
?Await]
ImportCall [?Yield,
?Await]
CallExpression [?Yield,
?Await]
Arguments [?Yield,
?Await]
CallExpression [?Yield,
?Await]
[
Expression [+In, ?Yield,
?Await]
]
CallExpression [?Yield,
?Await]
.
IdentifierName
CallExpression [?Yield,
?Await]
TemplateLiteral [?Yield,
?Await, +Tagged]
CallExpression [?Yield,
?Await]
.
PrivateIdentifier
SuperCall [Yield,
Await] :
super
Arguments [?Yield,
?Await]
ImportCall [Yield,
Await] :
import
(
AssignmentExpression [+In,
?Yield, ?Await]
,opt
)
import
(
AssignmentExpression [+In,
?Yield, ?Await]
,
AssignmentExpression [+In,
?Yield, ?Await]
,opt
)
Arguments [Yield,
Await] :
(
)
(
ArgumentList [?Yield,
?Await]
)
(
ArgumentList [?Yield,
?Await]
,
)
ArgumentList [Yield,
Await] :
AssignmentExpression [+In,
?Yield, ?Await]
...
AssignmentExpression [+In,
?Yield, ?Await]
ArgumentList [?Yield,
?Await]
,
AssignmentExpression [+In,
?Yield, ?Await]
ArgumentList [?Yield,
?Await]
,
...
AssignmentExpression [+In,
?Yield, ?Await]
OptionalExpression [Yield,
Await] :
MemberExpression [?Yield,
?Await]
OptionalChain [?Yield,
?Await]
CallExpression [?Yield,
?Await]
OptionalChain [?Yield,
?Await]
OptionalExpression [?Yield,
?Await]
OptionalChain [?Yield,
?Await]
OptionalChain [Yield,
Await] :
?.
Arguments [?Yield,
?Await]
?.
[
Expression [+In, ?Yield,
?Await]
]
?.
IdentifierName
?.
TemplateLiteral [?Yield,
?Await, +Tagged]
?.
PrivateIdentifier
OptionalChain [?Yield,
?Await]
Arguments [?Yield,
?Await]
OptionalChain [?Yield,
?Await]
[
Expression [+In, ?Yield,
?Await]
]
OptionalChain [?Yield,
?Await]
.
IdentifierName
OptionalChain [?Yield,
?Await]
TemplateLiteral [?Yield,
?Await, +Tagged]
OptionalChain [?Yield,
?Await]
.
PrivateIdentifier
LeftHandSideExpression [Yield,
Await] :
NewExpression [?Yield,
?Await]
CallExpression [?Yield,
?Await]
OptionalExpression [?Yield,
?Await]
补充语法
当处理产生式的实例时
CallExpression :
CoverCallExpressionAndAsyncArrowHead
使用以下语法细化对 CoverCallExpressionAndAsyncArrowHead
的解释:
CallMemberExpression [Yield,
Await] :
MemberExpression [?Yield,
?Await]
Arguments [?Yield,
?Await]
13.3.1 静态语义
13.3.1.1 静态语义:早期错误
OptionalChain :
?.
TemplateLiteral
OptionalChain
TemplateLiteral
注
此产生式的存在是为了防止自动分号插入规则(12.10 )应用于以下代码:
a?.b
`c`
这样它就不会被解释为两个有效的语句。目的是与没有可选链的类似代码保持一致:
a.b
`c`
这是一个有效的语句,其中不应用自动分号插入。
ImportMeta :
import
.
meta
13.3.2 属性访问器
注
属性通过名称进行访问,可以使用点记法:
或括号记法:
点记法通过以下语法转换解释:
在行为上等同于
同样地
在行为上等同于
其中 <identifier-name-string > 是 IdentifierName 的 StringValue 。
13.3.2.1 运行时语义:Evaluation
MemberExpression
:
MemberExpression
[
Expression
]
令 baseReference 为 ? MemberExpression 的 Evaluation 。
令 baseValue 为 ? GetValue (baseReference )。
令 strict 为此 MemberExpression 的 IsStrict 。
返回 ? EvaluatePropertyAccessWithExpressionKey (baseValue ,
Expression ,
strict )。
MemberExpression
:
MemberExpression
.
IdentifierName
令 baseReference 为 ? MemberExpression 的 Evaluation 。
令 baseValue 为 ? GetValue (baseReference )。
令 strict 为此 MemberExpression 的 IsStrict 。
返回 EvaluatePropertyAccessWithIdentifierKey (baseValue ,
IdentifierName ,
strict )。
MemberExpression
:
MemberExpression
.
PrivateIdentifier
令 baseReference 为 ? MemberExpression 的 Evaluation 。
令 baseValue 为 ? GetValue (baseReference )。
令 fieldNameString 为 PrivateIdentifier 的 StringValue 。
返回 MakePrivateReference (baseValue ,
fieldNameString )。
CallExpression :
CallExpression
[
Expression
]
令 baseReference 为 ? CallExpression 的 Evaluation 。
令 baseValue 为 ? GetValue (baseReference )。
令 strict 为此 CallExpression 的 IsStrict 。
返回 ? EvaluatePropertyAccessWithExpressionKey (baseValue ,
Expression ,
strict )。
CallExpression :
CallExpression
.
IdentifierName
令 baseReference 为 ? CallExpression 的 Evaluation 。
令 baseValue 为 ? GetValue (baseReference )。
令 strict 为此 CallExpression 的 IsStrict 。
返回 EvaluatePropertyAccessWithIdentifierKey (baseValue ,
IdentifierName ,
strict )。
CallExpression :
CallExpression
.
PrivateIdentifier
令 baseReference 为 ? CallExpression 的 Evaluation 。
令 baseValue 为 ? GetValue (baseReference )。
令 fieldNameString 为 PrivateIdentifier 的 StringValue 。
返回 MakePrivateReference (baseValue ,
fieldNameString )。
13.3.3 EvaluatePropertyAccessWithExpressionKey (
baseValue , expression , strict )
抽象操作 EvaluatePropertyAccessWithExpressionKey 接受参数
baseValue (一个 ECMAScript 语言值 )、
expression (一个 Expression 解析节点 )和
strict (一个布尔值),返回包含
引用记录 的正常完成 或突然完成 。当调用时执行以下步骤:
令 propertyNameReference 为 ? expression 的 Evaluation 。
令 propertyNameValue 为 ? GetValue (propertyNameReference )。
注:在大多数情况下,ToPropertyKey 将在此步骤之后立即对
propertyNameValue 执行。但是,在 a[b] = c
的情况下,它将直到 c
求值之后才执行。
返回引用记录
{ [[Base]] : baseValue , [[ReferencedName]] : propertyNameValue , [[Strict]] : strict , [[ThisValue]] : empty }。
13.3.4 EvaluatePropertyAccessWithIdentifierKey (
baseValue , identifierName , strict )
抽象操作 EvaluatePropertyAccessWithIdentifierKey 接受参数
baseValue (一个 ECMAScript 语言值 )、
identifierName (一个 IdentifierName 解析节点 )和 strict (一个布尔值),返回一个
引用记录 。当调用时执行以下步骤:
令 propertyNameString 为 identifierName 的 StringValue 。
返回引用记录
{ [[Base]] : baseValue , [[ReferencedName]] : propertyNameString , [[Strict]] : strict , [[ThisValue]] : empty }。
13.3.5 new
运算符
13.3.5.1 运行时语义:Evaluation
NewExpression :
new
NewExpression
返回 ? EvaluateNew (NewExpression ,
empty )。
MemberExpression
:
new
MemberExpression
Arguments
返回 ? EvaluateNew (MemberExpression , Arguments )。
13.3.5.1.1 EvaluateNew ( constructExpr ,
arguments )
抽象操作 EvaluateNew 接受参数 constructExpr (一个 NewExpression 解析节点 或一个 MemberExpression 解析节点 )和
arguments (empty 或一个 Arguments 解析节点 ),返回包含 ECMAScript 语言值 的正常完成 或突然完成 。当调用时执行以下步骤:
令 ref 为 ? constructExpr 的 Evaluation 。
令 constructor 为 ? GetValue (ref )。
如果 arguments 是 empty ,则
令 argList 为新的空列表 。
否则,
令 argList 为 ? arguments 的 ArgumentListEvaluation 。
如果 IsConstructor (constructor )
是 false ,抛出 TypeError 异常。
返回 ? Construct (constructor ,
argList )。
13.3.6 函数调用
13.3.6.1 运行时语义:Evaluation
CallExpression :
CoverCallExpressionAndAsyncArrowHead
令 expr 为被 CoverCallExpressionAndAsyncArrowHead
覆盖 的 CallMemberExpression 。
令 memberExpr 为 expr 的 MemberExpression 。
令 arguments 为 expr 的 Arguments 。
令 ref 为 ? memberExpr 的 Evaluation 。
令 func 为 ? GetValue (ref )。
如果 ref 是引用记录 ,IsPropertyReference (ref )
是 false ,且 ref .[[ReferencedName]] 是 "eval" ,则
如果 SameValue (func ,
%eval% ) 是
true ,则
令 argList 为 ? arguments 的 ArgumentListEvaluation 。
如果 argList 没有元素,返回 undefined 。
令 evalArg 为 argList 的第一个元素。
如果此 CallExpression 的
IsStrict 是
true ,则令 strictCaller 为
true 。否则令 strictCaller 为
false 。
返回
? PerformEval (evalArg ,
strictCaller , true )。
令 thisCall 为此 CallExpression 。
令 tailCall 为 IsInTailPosition (thisCall )。
返回 ? EvaluateCall (func ,
ref , arguments , tailCall )。
执行步骤 6.a.v 的 CallExpression
求值是直接 eval 。
CallExpression :
CallExpression
Arguments
令 ref 为 ? CallExpression 的 Evaluation 。
令 func 为 ? GetValue (ref )。
令 thisCall 为此 CallExpression 。
令 tailCall 为 IsInTailPosition (thisCall )。
返回 ? EvaluateCall (func ,
ref , Arguments , tailCall )。
13.3.6.2 EvaluateCall ( func , ref ,
arguments , tailPosition )
抽象操作 EvaluateCall 接受参数 func (一个 ECMAScript 语言值 )、
ref (一个 ECMAScript 语言值 或引用记录 )、
arguments (一个 解析节点 )和
tailPosition (一个布尔值),返回包含
ECMAScript 语言值 的正常完成 或突然完成 。当调用时执行以下步骤:
如果 ref 是引用记录 ,则
如果 IsPropertyReference (ref )
是 true ,则
令 thisValue 为 GetThisValue (ref )。
否则,
令 refEnv 为 ref .[[Base]] 。
断言 :refEnv
是环境记录 。
令 thisValue 为 refEnv .WithBaseObject()。
否则,
令 thisValue 为 undefined 。
令 argList 为 ? arguments 的 ArgumentListEvaluation 。
如果 func 不是对象 ,抛出 TypeError
异常。
如果 IsCallable (func ) 是
false ,抛出 TypeError 异常。
如果 tailPosition 是 true ,执行 PrepareForTailCall ()。
返回 ? Call (func ,
thisValue , argList )。
13.3.7 super
关键字
13.3.7.1 运行时语义:Evaluation
SuperProperty :
super
[
Expression
]
令 env 为 GetThisEnvironment ()。
令 actualThis 为 ? env .GetThisBinding()。
令 propertyNameReference 为 ? Expression 的 Evaluation 。
令 propertyNameValue 为 ? GetValue (propertyNameReference )。
令 strict 为此 SuperProperty 的 IsStrict 。
注:在大多数情况下,ToPropertyKey 将在此步骤之后立即对
propertyNameValue 执行。但是,在 super[b] = c
的情况下,它将直到
c
求值之后才执行。
返回 MakeSuperPropertyReference (actualThis ,
propertyNameValue , strict )。
SuperProperty :
super
.
IdentifierName
令 env 为 GetThisEnvironment ()。
令 actualThis 为 ? env .GetThisBinding()。
令 propertyKey 为 IdentifierName 的 StringValue 。
令 strict 为此 SuperProperty 的 IsStrict 。
返回 MakeSuperPropertyReference (actualThis ,
propertyKey , strict )。
SuperCall :
super
Arguments
令 newTarget 为 GetNewTarget ()。
断言 :
newTarget 是构造器 。
令 func 为 GetSuperConstructor ()。
令 argList 为 ? Arguments 的 ArgumentListEvaluation 。
如果 IsConstructor (func ) 是
false ,抛出 TypeError 异常。
令 result 为 ? Construct (func ,
argList , newTarget )。
令 thisER 为 GetThisEnvironment ()。
断言 :
thisER 是函数环境记录 。
执行 ? BindThisValue (thisER ,
result )。
令 F 为 thisER .[[FunctionObject]] 。
断言 :
F 是 ECMAScript 函数对象 。
执行 ? InitializeInstanceElements (result ,
F )。
返回 result 。
13.3.7.2 GetSuperConstructor ( )
抽象操作 GetSuperConstructor 不接受参数,返回一个 ECMAScript
语言值 。当调用时执行以下步骤:
令 envRec 为 GetThisEnvironment ()。
断言 :
envRec 是函数环境记录 。
令 activeFunction 为 envRec .[[FunctionObject]] 。
断言 :
activeFunction 是 ECMAScript 函数对象 。
令 superConstructor 为 ! activeFunction .[[GetPrototypeOf]] ()。
返回 superConstructor 。
13.3.7.3 MakeSuperPropertyReference ( actualThis ,
propertyKey , strict )
抽象操作 MakeSuperPropertyReference 接受参数 actualThis (一个 ECMAScript 语言值 )、
propertyKey (一个 ECMAScript 语言值 )和
strict (一个布尔值),返回一个 Super 引用记录 。当调用时执行以下步骤:
令 env 为 GetThisEnvironment ()。
断言 :
env .HasSuperBinding() 是 true 。
断言 :
env 是函数环境记录 。
令 baseValue 为 GetSuperBase (env )。
返回引用记录 { [[Base]] :
baseValue , [[ReferencedName]] :
propertyKey , [[Strict]] : strict , [[ThisValue]] : actualThis }。
13.3.8 参数列表
注
13.3.8.1 运行时语义:ArgumentListEvaluation
语法制导操作
ArgumentListEvaluation 不接受参数,返回包含
ECMAScript 语言值 的 列表 的正常完成 或突然完成 。它在以下产生式上分段定义:
Arguments :
(
)
返回新的空列表 。
ArgumentList :
AssignmentExpression
令 ref 为 ? AssignmentExpression 的
Evaluation 。
令 arg 为 ? GetValue (ref )。
返回 « arg »。
ArgumentList :
...
AssignmentExpression
令 list 为新的空列表 。
令 spreadRef 为 ? AssignmentExpression 的
Evaluation 。
令 spreadObj 为 ? GetValue (spreadRef )。
令 iteratorRecord 为 ? GetIterator (spreadObj ,
sync )。
重复,
令 next 为 ? IteratorStepValue (iteratorRecord )。
如果 next 是 done ,返回 list 。
将 next 附加到 list 。
ArgumentList :
ArgumentList
,
AssignmentExpression
令 precedingArgs 为 ? ArgumentList 的 ArgumentListEvaluation 。
令 ref 为 ? AssignmentExpression 的
Evaluation 。
令 arg 为 ? GetValue (ref )。
返回 precedingArgs 和 « arg » 的列表连接 。
ArgumentList :
ArgumentList
,
...
AssignmentExpression
令 precedingArgs 为 ? ArgumentList 的 ArgumentListEvaluation 。
令 spreadRef 为 ? AssignmentExpression 的
Evaluation 。
令 iteratorRecord 为 ? GetIterator (?
GetValue (spreadRef ),
sync )。
重复,
令 next 为 ? IteratorStepValue (iteratorRecord )。
如果 next 是 done ,返回
precedingArgs 。
将 next 附加到 precedingArgs 。
TemplateLiteral
: NoSubstitutionTemplate
令 templateLiteral 为此 TemplateLiteral 。
令 siteObj 为 GetTemplateObject (templateLiteral )。
返回 « siteObj »。
TemplateLiteral
: SubstitutionTemplate
令 templateLiteral 为此 TemplateLiteral 。
令 siteObj 为 GetTemplateObject (templateLiteral )。
令 remaining 为 ? SubstitutionTemplate 的
ArgumentListEvaluation 。
返回 « siteObj » 和 remaining 的列表连接 。
SubstitutionTemplate
:
TemplateHead
Expression
TemplateSpans
令 firstSubRef 为 ? Expression 的 Evaluation 。
令 firstSub 为 ? GetValue (firstSubRef )。
令 restSub 为 ? TemplateSpans 的 SubstitutionEvaluation 。
断言 :
restSub 是可能为空的列表 。
返回 « firstSub » 和 restSub 的列表连接 。
13.3.9 可选链
注
可选链是一个或多个属性访问和函数调用的链,其中第一个以标记 ?.
开始。
13.3.9.1 运行时语义:Evaluation
OptionalExpression
:
MemberExpression
OptionalChain
令 baseReference 为 ? MemberExpression 的 Evaluation 。
令 baseValue 为 ? GetValue (baseReference )。
如果 baseValue 是 undefined 或 null ,则
返回 undefined 。
返回 ? OptionalChain 以 baseValue
和 baseReference 为参数的 ChainEvaluation 。
OptionalExpression
:
CallExpression
OptionalChain
令 baseReference 为 ? CallExpression 的 Evaluation 。
令 baseValue 为 ? GetValue (baseReference )。
如果 baseValue 是 undefined 或 null ,则
返回 undefined 。
返回 ? OptionalChain 以 baseValue
和 baseReference 为参数的 ChainEvaluation 。
OptionalExpression
:
OptionalExpression
OptionalChain
令 baseReference 为 ? OptionalExpression 的 Evaluation 。
令 baseValue 为 ? GetValue (baseReference )。
如果 baseValue 是 undefined 或 null ,则
返回 undefined 。
返回 ? OptionalChain 以 baseValue
和 baseReference 为参数的 ChainEvaluation 。
13.3.9.2 运行时语义:ChainEvaluation
语法制导操作
ChainEvaluation 接受参数 baseValue (一个 ECMAScript 语言值 )和
baseReference (一个 ECMAScript
语言值 或引用记录 ),返回包含 ECMAScript 语言值 或引用记录 的正常完成 ,或突然完成 。它在以下产生式上分段定义:
OptionalChain :
?.
Arguments
令 thisChain 为此 OptionalChain 。
令 tailCall 为 IsInTailPosition (thisChain )。
返回 ? EvaluateCall (baseValue ,
baseReference , Arguments , tailCall )。
OptionalChain :
?.
[
Expression
]
令 strict 为此 OptionalChain 的 IsStrict 。
返回 ? EvaluatePropertyAccessWithExpressionKey (baseValue ,
Expression ,
strict )。
OptionalChain :
?.
IdentifierName
令 strict 为此 OptionalChain 的 IsStrict 。
返回 EvaluatePropertyAccessWithIdentifierKey (baseValue ,
IdentifierName ,
strict )。
OptionalChain :
?.
PrivateIdentifier
令 fieldNameString 为 PrivateIdentifier 的 StringValue 。
返回 MakePrivateReference (baseValue ,
fieldNameString )。
OptionalChain :
OptionalChain
Arguments
令 optionalChain 为 OptionalChain 。
令 newReference 为 ? optionalChain 以 baseValue 和
baseReference 为参数的 ChainEvaluation 。
令 newValue 为 ? GetValue (newReference )。
令 thisChain 为此 OptionalChain 。
令 tailCall 为 IsInTailPosition (thisChain )。
返回 ? EvaluateCall (newValue ,
newReference , Arguments , tailCall )。
OptionalChain :
OptionalChain
[
Expression
]
令 optionalChain 为 OptionalChain 。
令 newReference 为 ? optionalChain 以 baseValue 和
baseReference 为参数的 ChainEvaluation 。
令 newValue 为 ? GetValue (newReference )。
令 strict 为此 OptionalChain 的 IsStrict 。
返回 ? EvaluatePropertyAccessWithExpressionKey (newValue ,
Expression ,
strict )。
OptionalChain :
OptionalChain
.
IdentifierName
令 optionalChain 为 OptionalChain 。
令 newReference 为 ? optionalChain 以 baseValue 和
baseReference 为参数的 ChainEvaluation 。
令 newValue 为 ? GetValue (newReference )。
令 strict 为此 OptionalChain 的 IsStrict 。
返回 EvaluatePropertyAccessWithIdentifierKey (newValue ,
IdentifierName ,
strict )。
OptionalChain :
OptionalChain
.
PrivateIdentifier
令 optionalChain 为 OptionalChain 。
令 newReference 为 ? optionalChain 以 baseValue 和
baseReference 为参数的 ChainEvaluation 。
令 newValue 为 ? GetValue (newReference )。
令 fieldNameString 为 PrivateIdentifier 的 StringValue 。
返回 MakePrivateReference (newValue ,
fieldNameString )。
13.3.10 Import 调用
13.3.10.1 运行时语义:Evaluation
ImportCall :
import
(
AssignmentExpression
,opt
)
返回 ? EvaluateImportCall (AssignmentExpression )。
ImportCall :
import
(
AssignmentExpression
,
AssignmentExpression
,opt
)
返回 ? EvaluateImportCall (第一个 AssignmentExpression , 第二个
AssignmentExpression )。
13.3.10.2 EvaluateImportCall ( specifierExpression [
, optionsExpression ] )
抽象操作 EvaluateImportCall 接受参数 specifierExpression (一个 解析节点 )和可选参数
optionsExpression (一个 解析节点 ),返回包含 Promise
的正常完成 或突然完成 。当调用时执行以下步骤:
令 referrer 为 GetActiveScriptOrModule ()。
如果 referrer 是 null ,设置 referrer 为当前 Realm
记录 。
令 specifierRef 为 ? specifierExpression 的 Evaluation 。
令 specifier 为 ? GetValue (specifierRef )。
如果 optionsExpression 存在,则
令 optionsRef 为 ? optionsExpression 的 Evaluation 。
令 options 为 ? GetValue (optionsRef )。
否则,
令 options 为 undefined 。
令 promiseCapability 为 ! NewPromiseCapability (%Promise% )。
令 specifierString 为 Completion (ToString (specifier ))。
IfAbruptRejectPromise (specifierString ,
promiseCapability )。
令 attributes 为新的空列表 。
如果 options 不是 undefined ,则
如果 options 不是对象 ,则
执行 ! Call (promiseCapability .[[Reject]] , undefined , «
新创建的 TypeError 对象 »)。
返回 promiseCapability .[[Promise]] 。
令 attributesObj 为 Completion (Get (options ,
"with" ))。
IfAbruptRejectPromise (attributesObj ,
promiseCapability )。
如果 attributesObj 不是 undefined ,则
如果 attributesObj 不是对象 ,则
执行 ! Call (promiseCapability .[[Reject]] ,
undefined , « 新创建的
TypeError 对象 »)。
返回 promiseCapability .[[Promise]] 。
令 entries 为 Completion (EnumerableOwnProperties (attributesObj ,
key+value ))。
IfAbruptRejectPromise (entries ,
promiseCapability )。
对于 entries 的每个元素 entry ,执行
令 key 为 ! Get (entry ,
"0" )。
令 value 为 ! Get (entry ,
"1" )。
如果 key 是字符串 ,则
如果 value 不是字符串 ,则
执行 ! Call (promiseCapability .[[Reject]] ,
undefined , « 新创建的
TypeError
对象 »)。
返回 promiseCapability .[[Promise]] 。
将ImportAttribute
记录 { [[Key]] : key ,
[[Value]] :
value } 附加到 attributes 。
如果 AllImportAttributesSupported (attributes )
是 false ,则
执行 ! Call (promiseCapability .[[Reject]] , undefined , «
新创建的 TypeError 对象 »)。
返回 promiseCapability .[[Promise]] 。
按照其 [[Key]] 字段的字典序对 attributes
进行排序,将每个此类字段的值视为 UTF-16 代码单元值的序列。注:此排序仅在禁止宿主 基于属性枚举的顺序改变行为这一点上是可观察的。
令 moduleRequest 为新的ModuleRequest
记录 { [[Specifier]] :
specifierString , [[Attributes]] :
attributes }。
执行 HostLoadImportedModule (referrer ,
moduleRequest , empty ,
promiseCapability )。
返回 promiseCapability .[[Promise]] 。
13.3.10.3 ContinueDynamicImport ( promiseCapability ,
moduleCompletion )
抽象操作 ContinueDynamicImport 接受参数 promiseCapability (一个 PromiseCapability 记录 )和
moduleCompletion (包含
模块记录 的正常完成 或抛出完成 ),返回
unused 。它完成最初由 import()
调用开始的动态导入过程,适当地解决或拒绝由该调用返回的 promise。当调用时执行以下步骤:
如果 moduleCompletion 是突然完成 ,则
执行 ! Call (promiseCapability .[[Reject]] , undefined , «
moduleCompletion .[[Value]] »)。
返回 unused 。
令 module 为 moduleCompletion .[[Value]] 。
令 loadPromise 为 module .LoadRequestedModules()。
令 rejectedClosure 为新的抽象闭包 ,参数为
(reason ),捕获 promiseCapability 并在调用时执行以下步骤:
执行 ! Call (promiseCapability .[[Reject]] , undefined , «
reason »)。
返回 unused 。
令 onRejected 为 CreateBuiltinFunction (rejectedClosure ,
1, "" , « »)。
令 linkAndEvaluateClosure 为新的抽象闭包 ,无参数,捕获
module 、promiseCapability 和
onRejected 并在调用时执行以下步骤:
令 link 为 Completion (module .Link())。
如果 link 是突然完成 ,则
执行 ! Call (promiseCapability .[[Reject]] , undefined , «
link .[[Value]] »)。
返回 unused 。
令 evaluatePromise 为 module .Evaluate()。
令 fulfilledClosure 为新的抽象闭包 ,无参数,捕获
module 和 promiseCapability
并在调用时执行以下步骤:
令 namespace 为 GetModuleNamespace (module )。
执行 ! Call (promiseCapability .[[Resolve]] , undefined , «
namespace »)。
返回 unused 。
令 onFulfilled 为 CreateBuiltinFunction (fulfilledClosure ,
0, "" , « »)。
执行 PerformPromiseThen (evaluatePromise ,
onFulfilled , onRejected )。
返回 unused 。
令 linkAndEvaluate 为 CreateBuiltinFunction (linkAndEvaluateClosure ,
0, "" , « »)。
执行 PerformPromiseThen (loadPromise ,
linkAndEvaluate , onRejected )。
返回 unused 。
13.3.11 标记模板
注
标记模板是一个函数调用,其中调用的参数来源于 TemplateLiteral
(13.2.8 )。实际参数包括模板对象(13.2.8.4 )和通过求值嵌入在 TemplateLiteral
中的表达式产生的值。
13.3.11.1 运行时语义:Evaluation
MemberExpression
:
MemberExpression
TemplateLiteral
令 tagRef 为 ? MemberExpression 的 Evaluation 。
令 tagFunc 为 ? GetValue (tagRef )。
令 thisCall 为此 MemberExpression 。
令 tailCall 为 IsInTailPosition (thisCall )。
返回 ? EvaluateCall (tagFunc ,
tagRef , TemplateLiteral ,
tailCall )。
CallExpression :
CallExpression
TemplateLiteral
令 tagRef 为 ? CallExpression 的 Evaluation 。
令 tagFunc 为 ? GetValue (tagRef )。
令 thisCall 为此 CallExpression 。
令 tailCall 为 IsInTailPosition (thisCall )。
返回 ? EvaluateCall (tagFunc ,
tagRef , TemplateLiteral ,
tailCall )。
13.3.12 元属性
13.3.12.1 运行时语义:Evaluation
NewTarget :
new
.
target
返回 GetNewTarget ()。
ImportMeta :
import
.
meta
令 module 为 GetActiveScriptOrModule ()。
断言 :
module 是源文本模块记录 。
令 importMeta 为 module .[[ImportMeta]] 。
如果 importMeta 是 empty ,则
设置 importMeta 为 OrdinaryObjectCreate (null )。
令 importMetaValues 为 HostGetImportMetaProperties (module )。
对于 importMetaValues 的每个记录
{ [[Key]] , [[Value]] } p ,执行
执行 ! CreateDataPropertyOrThrow (importMeta ,
p .[[Key]] , p .[[Value]] )。
执行 HostFinalizeImportMeta (importMeta ,
module )。
设置 module .[[ImportMeta]] 为
importMeta 。
返回 importMeta 。
否则,
断言 :importMeta
是对象 。
返回 importMeta 。
13.3.12.1.1 HostGetImportMetaProperties (
moduleRecord )
宿主定义的 抽象操作
HostGetImportMetaProperties 接受参数 moduleRecord (一个模块记录 ),返回包含字段 [[Key]] (一个属性键 )和 [[Value]] (一个ECMAScript
语言值 )的记录 的列表 。它允许宿主 为从
import.meta
返回的对象提供属性键 和值。
HostGetImportMetaProperties 的默认实现是返回新的空列表 。
13.3.12.1.2 HostFinalizeImportMeta ( importMeta ,
moduleRecord )
宿主定义的 抽象操作
HostFinalizeImportMeta 接受参数 importMeta (一个对象)和
moduleRecord (一个模块记录 ),返回
unused 。它允许宿主 执行任何特殊操作来准备从 import.meta
返回的对象。
大多数宿主 只需简单地定义
HostGetImportMetaProperties ,并保持
HostFinalizeImportMeta 的默认行为。然而,HostFinalizeImportMeta 为需要在对象暴露给 ECMAScript
代码之前直接操作对象的宿主 提供了"紧急出口"。
HostFinalizeImportMeta 的默认实现是返回
unused 。
13.4 更新表达式
语法
UpdateExpression [Yield,
Await] :
LeftHandSideExpression [?Yield,
?Await]
LeftHandSideExpression [?Yield,
?Await]
[no LineTerminator here]
++
LeftHandSideExpression [?Yield,
?Await]
[no LineTerminator here]
--
++
UnaryExpression [?Yield,
?Await]
--
UnaryExpression [?Yield,
?Await]
13.4.1 静态语义:早期错误
UpdateExpression :
LeftHandSideExpression
++
LeftHandSideExpression
--
UpdateExpression :
++
UnaryExpression
--
UnaryExpression
13.4.2 后缀递增运算符
13.4.2.1 运行时语义:Evaluation
UpdateExpression
:
LeftHandSideExpression
++
令 lhs 为 ? LeftHandSideExpression 的
Evaluation 。
令 oldValue 为 ? ToNumeric (?
GetValue (lhs ))。
如果 oldValue 是数字 ,则
令 newValue 为 Number::add (oldValue ,
1 𝔽 )。
否则,
断言 :oldValue 是
BigInt 。
令 newValue 为 BigInt::add (oldValue ,
1 ℤ )。
执行 ? PutValue (lhs ,
newValue )。
返回 oldValue 。
13.4.3 后缀递减运算符
13.4.3.1 运行时语义:Evaluation
UpdateExpression
:
LeftHandSideExpression
--
令 lhs 为 ? LeftHandSideExpression 的
Evaluation 。
令 oldValue 为 ? ToNumeric (?
GetValue (lhs ))。
如果 oldValue 是数字 ,则
令 newValue 为 Number::subtract (oldValue ,
1 𝔽 )。
否则,
断言 :oldValue 是
BigInt 。
令 newValue 为 BigInt::subtract (oldValue ,
1 ℤ )。
执行 ? PutValue (lhs ,
newValue )。
返回 oldValue 。
13.4.4 前缀递增运算符
13.4.4.1 运行时语义:Evaluation
UpdateExpression
:
++
UnaryExpression
令 expr 为 ? UnaryExpression 的 Evaluation 。
令 oldValue 为 ? ToNumeric (?
GetValue (expr ))。
如果 oldValue 是数字 ,则
令 newValue 为 Number::add (oldValue ,
1 𝔽 )。
否则,
断言 :oldValue 是
BigInt 。
令 newValue 为 BigInt::add (oldValue ,
1 ℤ )。
执行 ? PutValue (expr ,
newValue )。
返回 newValue 。
13.4.5 前缀递减运算符
13.4.5.1 运行时语义:Evaluation
UpdateExpression
:
--
UnaryExpression
令 expr 为 ? UnaryExpression 的 Evaluation 。
令 oldValue 为 ? ToNumeric (?
GetValue (expr ))。
如果 oldValue 是数字 ,则
令 newValue 为 Number::subtract (oldValue ,
1 𝔽 )。
否则,
断言 :oldValue 是
BigInt 。
令 newValue 为 BigInt::subtract (oldValue ,
1 ℤ )。
执行 ? PutValue (expr ,
newValue )。
返回 newValue 。
13.5 一元运算符
语法
UnaryExpression [Yield,
Await] :
UpdateExpression [?Yield,
?Await]
delete
UnaryExpression [?Yield,
?Await]
void
UnaryExpression [?Yield,
?Await]
typeof
UnaryExpression [?Yield,
?Await]
+
UnaryExpression [?Yield,
?Await]
-
UnaryExpression [?Yield,
?Await]
~
UnaryExpression [?Yield,
?Await]
!
UnaryExpression [?Yield,
?Await]
[+Await]
AwaitExpression [?Yield]
13.5.1 delete
运算符
13.5.1.1 静态语义:早期错误
UnaryExpression
:
delete
UnaryExpression
注
最后一条规则意味着如 delete (((foo)))
这样的表达式由于第一条规则的递归应用而产生早期错误 。
13.5.1.2 运行时语义:Evaluation
UnaryExpression
:
delete
UnaryExpression
令 ref 为 ? UnaryExpression 的 Evaluation 。
如果 ref 不是引用记录 ,返回
true 。
如果 IsUnresolvableReference (ref )
是 true ,则
断言 :ref .[[Strict]] 是 false 。
返回 true 。
如果 IsPropertyReference (ref )
是 true ,则
断言 :IsPrivateReference (ref )
是 false 。
如果 IsSuperReference (ref )
是 true ,抛出 ReferenceError
异常。
令 baseObj 为
? ToObject (ref .[[Base]] )。
如果 ref .[[ReferencedName]] 不是属性键 ,则
设置 ref .[[ReferencedName]] 为
? ToPropertyKey (ref .[[ReferencedName]] )。
令 deleteStatus 为 ? baseObj .[[Delete]] (ref .[[ReferencedName]] )。
如果 deleteStatus 是 false 并且
ref .[[Strict]] 是
true ,抛出 TypeError 异常。
返回 deleteStatus 。
否则,
令 base 为 ref .[[Base]] 。
断言 :base 是环境记录 。
返回 ? base .DeleteBinding (ref .[[ReferencedName]] )。
注 1
当 delete
运算符出现在严格模式代码 中时,如果其 UnaryExpression
是对变量、函数参数或函数名的直接引用,则抛出 SyntaxError 异常。此外,如果 delete
运算符出现在严格模式代码 中并且要删除的属性具有属性 { [[Configurable]] : false }(或者无法删除),则抛出
TypeError 异常。
注 2
可能在步骤 4.c
中创建的对象在上述抽象操作和普通对象 [[Delete]] 内部方法之外是不可访问的。实现可能选择避免实际创建该对象。
13.5.2 void
运算符
13.5.2.1 运行时语义:Evaluation
UnaryExpression
:
void
UnaryExpression
令 expr 为 ? UnaryExpression 的 Evaluation 。
执行 ? GetValue (expr )。
返回 undefined 。
注
即使不使用 GetValue 的值,也必须调用它,因为它可能有可观察的副作用。
13.5.3 typeof
运算符
13.5.3.1 运行时语义:Evaluation
UnaryExpression
:
typeof
UnaryExpression
令 val 为 ? UnaryExpression 的 Evaluation 。
如果 val 是引用记录 ,则
如果 IsUnresolvableReference (val )
是 true ,返回 "undefined" 。
设置 val 为 ? GetValue (val )。
如果 val 是 undefined ,返回
"undefined" 。
如果 val 是 null ,返回 "object" 。
如果 val 是字符串 ,返回
"string" 。
如果 val 是符号 ,返回
"symbol" 。
如果 val 是布尔值 ,返回
"boolean" 。
如果 val 是数字 ,返回
"number" 。
如果 val 是
BigInt ,返回 "bigint" 。
断言 :
val 是对象 。
注:此步骤在 B.3.6.3 节中被替换。
如果 val 具有 [[Call]] 内部槽,返回
"function" 。
返回 "object" 。
13.5.4 一元 +
运算符
注
13.5.4.1 运行时语义:Evaluation
UnaryExpression
:
+
UnaryExpression
令 expr 为 ? UnaryExpression 的 Evaluation 。
返回 ? ToNumber (? GetValue (expr ))。
13.5.5 一元 -
运算符
注
一元 -
运算符将其操作数转换为数值然后对其取反。对 +0 𝔽 取反产生
-0 𝔽 ,对 -0 𝔽
取反产生 +0 𝔽 。
13.5.5.1 运行时语义:Evaluation
UnaryExpression
:
-
UnaryExpression
令 expr 为 ? UnaryExpression 的 Evaluation 。
令 oldValue 为 ? ToNumeric (?
GetValue (expr ))。
如果 oldValue 是数字 ,则
返回 Number::unaryMinus (oldValue )。
否则,
断言 :oldValue 是
BigInt 。
返回 BigInt::unaryMinus (oldValue )。
13.5.6 按位非运算符(~
)
13.5.6.1 运行时语义:Evaluation
UnaryExpression
:
~
UnaryExpression
令 expr 为 ? UnaryExpression 的 Evaluation 。
令 oldValue 为 ? ToNumeric (?
GetValue (expr ))。
如果 oldValue 是数字 ,则
返回 Number::bitwiseNOT (oldValue )。
否则,
断言 :oldValue 是
BigInt 。
返回 BigInt::bitwiseNOT (oldValue )。
13.5.7 逻辑非运算符(!
)
13.5.7.1 运行时语义:Evaluation
UnaryExpression
:
!
UnaryExpression
令 expr 为 ? UnaryExpression 的 Evaluation 。
令 oldValue 为 ToBoolean (? GetValue (expr ))。
如果 oldValue 是 true ,返回 false 。
返回 true 。
13.6 幂运算符
语法
ExponentiationExpression [Yield,
Await] :
UnaryExpression [?Yield,
?Await]
UpdateExpression [?Yield,
?Await]
**
ExponentiationExpression [?Yield,
?Await]
13.6.1 运行时语义:Evaluation
ExponentiationExpression
:
UpdateExpression
**
ExponentiationExpression
返回 ? EvaluateStringOrNumericBinaryExpression (UpdateExpression ,
**
, ExponentiationExpression )。
13.7 乘法运算符
语法
MultiplicativeExpression [Yield,
Await] :
ExponentiationExpression [?Yield,
?Await]
MultiplicativeExpression [?Yield,
?Await]
MultiplicativeOperator
ExponentiationExpression [?Yield,
?Await]
MultiplicativeOperator
: one of * /
%
注
*
运算符执行乘法,产生其操作数的乘积。
/
运算符执行除法,产生其操作数的商。
%
运算符产生隐含除法中其操作数的余数。
13.7.1 运行时语义:Evaluation
MultiplicativeExpression
:
MultiplicativeExpression
MultiplicativeOperator
ExponentiationExpression
令 opText 为 MultiplicativeOperator
匹配的源文本 。
返回 ? EvaluateStringOrNumericBinaryExpression (MultiplicativeExpression ,
opText , ExponentiationExpression )。
13.8 加法运算符
语法
AdditiveExpression [Yield,
Await] :
MultiplicativeExpression [?Yield,
?Await]
AdditiveExpression [?Yield,
?Await]
+
MultiplicativeExpression [?Yield,
?Await]
AdditiveExpression [?Yield,
?Await]
-
MultiplicativeExpression [?Yield,
?Await]
13.8.1 加法运算符(+
)
注
13.8.1.1 运行时语义:Evaluation
AdditiveExpression
:
AdditiveExpression
+
MultiplicativeExpression
返回 ? EvaluateStringOrNumericBinaryExpression (AdditiveExpression ,
+
, MultiplicativeExpression )。
13.8.2 减法运算符(-
)
注
13.8.2.1 运行时语义:Evaluation
AdditiveExpression
:
AdditiveExpression
-
MultiplicativeExpression
返回 ? EvaluateStringOrNumericBinaryExpression (AdditiveExpression ,
-
, MultiplicativeExpression )。
13.9 按位移位运算符
语法
ShiftExpression [Yield,
Await] :
AdditiveExpression [?Yield,
?Await]
ShiftExpression [?Yield,
?Await]
<<
AdditiveExpression [?Yield,
?Await]
ShiftExpression [?Yield,
?Await]
>>
AdditiveExpression [?Yield,
?Await]
ShiftExpression [?Yield,
?Await]
>>>
AdditiveExpression [?Yield,
?Await]
13.9.1 左移运算符(<<
)
注
对左操作数执行按位左移操作,移位量由右操作数指定。
13.9.1.1 运行时语义:Evaluation
ShiftExpression
:
ShiftExpression
<<
AdditiveExpression
返回 ? EvaluateStringOrNumericBinaryExpression (ShiftExpression ,
<<
, AdditiveExpression )。
13.9.2 有符号右移运算符(>>
)
注
对左操作数执行符号填充的按位右移操作,移位量由右操作数指定。
13.9.2.1 运行时语义:Evaluation
ShiftExpression
:
ShiftExpression
>>
AdditiveExpression
返回 ? EvaluateStringOrNumericBinaryExpression (ShiftExpression ,
>>
, AdditiveExpression )。
13.9.3 无符号右移运算符(>>>
)
注
对左操作数执行零填充的按位右移操作,移位量由右操作数指定。
13.9.3.1 运行时语义:Evaluation
ShiftExpression
:
ShiftExpression
>>>
AdditiveExpression
返回 ? EvaluateStringOrNumericBinaryExpression (ShiftExpression ,
>>>
, AdditiveExpression )。
13.10 关系运算符
注 1
关系运算符的求值结果总是布尔类型,反映运算符所命名的关系是否在其两个操作数之间成立。
语法
RelationalExpression [In,
Yield, Await] :
ShiftExpression [?Yield,
?Await]
RelationalExpression [?In,
?Yield, ?Await]
<
ShiftExpression [?Yield,
?Await]
RelationalExpression [?In,
?Yield, ?Await]
>
ShiftExpression [?Yield,
?Await]
RelationalExpression [?In,
?Yield, ?Await]
<=
ShiftExpression [?Yield,
?Await]
RelationalExpression [?In,
?Yield, ?Await]
>=
ShiftExpression [?Yield,
?Await]
RelationalExpression [?In,
?Yield, ?Await]
instanceof
ShiftExpression [?Yield,
?Await]
[+In]
RelationalExpression [+In,
?Yield, ?Await]
in
ShiftExpression [?Yield,
?Await]
[+In]
PrivateIdentifier
in
ShiftExpression [?Yield,
?Await]
注 2
需要 [In] 语法参数来避免关系表达式中的 in
运算符与 for
语句中的 in
运算符混淆。
13.10.1 运行时语义:Evaluation
RelationalExpression
:
RelationalExpression
<
ShiftExpression
令 lRef 为 ? RelationalExpression 的 Evaluation 。
令 lVal 为 ? GetValue (lRef )。
令 rRef 为 ? ShiftExpression 的 Evaluation 。
令 rVal 为 ? GetValue (rRef )。
令 r 为 ? IsLessThan (lVal , rVal ,
true )。
如果 r 是 undefined ,返回 false 。否则,返回
r 。
RelationalExpression
:
RelationalExpression
>
ShiftExpression
令 lRef 为 ? RelationalExpression 的 Evaluation 。
令 lVal 为 ? GetValue (lRef )。
令 rRef 为 ? ShiftExpression 的 Evaluation 。
令 rVal 为 ? GetValue (rRef )。
令 r 为 ? IsLessThan (rVal , lVal ,
false )。
如果 r 是 undefined ,返回 false 。否则,返回
r 。
RelationalExpression
:
RelationalExpression
<=
ShiftExpression
令 lRef 为 ? RelationalExpression 的 Evaluation 。
令 lVal 为 ? GetValue (lRef )。
令 rRef 为 ? ShiftExpression 的 Evaluation 。
令 rVal 为 ? GetValue (rRef )。
令 r 为 ? IsLessThan (rVal , lVal ,
false )。
如果 r 是 true 或 undefined ,返回
false 。否则,返回 true 。
RelationalExpression
:
RelationalExpression
>=
ShiftExpression
令 lRef 为 ? RelationalExpression 的 Evaluation 。
令 lVal 为 ? GetValue (lRef )。
令 rRef 为 ? ShiftExpression 的 Evaluation 。
令 rVal 为 ? GetValue (rRef )。
令 r 为 ? IsLessThan (lVal , rVal ,
true )。
如果 r 是 true 或 undefined ,返回
false 。否则,返回 true 。
RelationalExpression
:
RelationalExpression
instanceof
ShiftExpression
令 lRef 为 ? RelationalExpression 的 Evaluation 。
令 lVal 为 ? GetValue (lRef )。
令 rRef 为 ? ShiftExpression 的 Evaluation 。
令 rVal 为 ? GetValue (rRef )。
返回 ? InstanceofOperator (lVal ,
rVal )。
RelationalExpression
:
RelationalExpression
in
ShiftExpression
令 lRef 为 ? RelationalExpression 的 Evaluation 。
令 lVal 为 ? GetValue (lRef )。
令 rRef 为 ? ShiftExpression 的 Evaluation 。
令 rVal 为 ? GetValue (rRef )。
如果 rVal 不是对象 ,抛出 TypeError 异常。
返回 ? HasProperty (rVal , ? ToPropertyKey (lVal ))。
RelationalExpression
:
PrivateIdentifier
in
ShiftExpression
令 privateIdentifier 为 PrivateIdentifier 的 StringValue 。
令 rRef 为 ? ShiftExpression 的 Evaluation 。
令 rVal 为 ? GetValue (rRef )。
如果 rVal 不是对象 ,抛出 TypeError 异常。
令 privateEnv 为正在运行的执行上下文 的 PrivateEnvironment。
断言 :
privateEnv 不是 null 。
令 privateName 为 ResolvePrivateIdentifier (privateEnv ,
privateIdentifier )。
如果 PrivateElementFind (rVal ,
privateName ) 不是 empty ,返回 true 。
返回 false 。
13.10.2 InstanceofOperator ( V , target )
抽象操作 InstanceofOperator 接受参数 V (ECMAScript 语言值 )和
target (ECMAScript 语言值 )并且返回包含 布尔值的正常完成 或抛出完成 。它实现用于确定
V 是否为 target 实例的通用算法,通过咨询 target 的 %Symbol.hasInstance% 方法,或如果不存在,则确定
target 的 "prototype" 属性的值是否存在于 V 的原型链中。调用时执行以下步骤:
如果 target 不是对象 ,抛出 TypeError 异常。
令 instOfHandler 为 ? GetMethod (target , %Symbol.hasInstance% )。
如果 instOfHandler 不是 undefined ,则
返回 ToBoolean (? Call (instOfHandler ,
target , « V »))。
如果 IsCallable (target ) 是
false ,抛出 TypeError 异常。
返回 ? OrdinaryHasInstance (target ,
V )。
注
步骤 4 和 5 提供与 ECMAScript
早期版本的兼容性,这些版本没有使用 %Symbol.hasInstance% 方法来定义
instanceof
运算符语义。如果对象没有定义或继承 %Symbol.hasInstance% ,它使用默认的
instanceof
语义。
13.11 相等运算符
注
相等运算符的求值结果总是布尔类型,反映运算符所命名的关系是否在其两个操作数之间成立。
语法
EqualityExpression [In, Yield,
Await] :
RelationalExpression [?In,
?Yield, ?Await]
EqualityExpression [?In,
?Yield, ?Await]
==
RelationalExpression [?In,
?Yield, ?Await]
EqualityExpression [?In,
?Yield, ?Await]
!=
RelationalExpression [?In,
?Yield, ?Await]
EqualityExpression [?In,
?Yield, ?Await]
===
RelationalExpression [?In,
?Yield, ?Await]
EqualityExpression [?In,
?Yield, ?Await]
!==
RelationalExpression [?In,
?Yield, ?Await]
13.11.1 运行时语义:Evaluation
EqualityExpression
:
EqualityExpression
==
RelationalExpression
令 lRef 为 ? EqualityExpression 的 Evaluation 。
令 lVal 为 ? GetValue (lRef )。
令 rRef 为 ? RelationalExpression 的 Evaluation 。
令 rVal 为 ? GetValue (rRef )。
返回 ? IsLooselyEqual (rVal ,
lVal )。
EqualityExpression
:
EqualityExpression
!=
RelationalExpression
令 lRef 为 ? EqualityExpression 的 Evaluation 。
令 lVal 为 ? GetValue (lRef )。
令 rRef 为 ? RelationalExpression 的 Evaluation 。
令 rVal 为 ? GetValue (rRef )。
令 r 为 ? IsLooselyEqual (rVal ,
lVal )。
如果 r 是 true ,返回 false 。否则,返回
true 。
EqualityExpression
:
EqualityExpression
===
RelationalExpression
令 lRef 为 ? EqualityExpression 的 Evaluation 。
令 lVal 为 ? GetValue (lRef )。
令 rRef 为 ? RelationalExpression 的 Evaluation 。
令 rVal 为 ? GetValue (rRef )。
返回 IsStrictlyEqual (rVal ,
lVal )。
EqualityExpression
:
EqualityExpression
!==
RelationalExpression
令 lRef 为 ? EqualityExpression 的 Evaluation 。
令 lVal 为 ? GetValue (lRef )。
令 rRef 为 ? RelationalExpression 的 Evaluation 。
令 rVal 为 ? GetValue (rRef )。
令 r 为 IsStrictlyEqual (rVal ,
lVal )。
如果 r 是 true ,返回 false 。否则,返回
true 。
注 1
根据上述相等性定义:
字符串比较可以通过以下方式强制进行:`${a}` == `${b}`
。
数值比较可以通过以下方式强制进行:+a == +b
。
布尔比较可以通过以下方式强制进行:!a == !b
。
注 2
相等运算符维持以下不变性:
A != B
等价于 !(A == B)
。
A == B
等价于 B == A
,除了 A
和 B
的求值顺序。
注 3
相等运算符并不总是传递的。例如,可能有两个不同的 String 对象,每个代表相同的 String 值;每个 String 对象都会被 ==
运算符认为等于 String 值,但两个 String 对象彼此不相等。例如:
new String("a") == "a"
和 "a" == new String("a")
都是
true 。
new String("a") == new String("a")
是 false 。
注 4
字符串的比较使用简单的代码单元值序列相等性测试。没有尝试使用 Unicode 规范中定义的更复杂的、面向语义的字符或字符串相等性和排序定义。因此,根据 Unicode
标准规范相等的字符串值可能测试为不相等。实际上,此算法假设两个字符串都已经是规范化形式。
13.12 二元按位运算符
语法
BitwiseANDExpression [In,
Yield, Await] :
EqualityExpression [?In,
?Yield, ?Await]
BitwiseANDExpression [?In,
?Yield, ?Await]
&
EqualityExpression [?In,
?Yield, ?Await]
BitwiseXORExpression [In,
Yield, Await] :
BitwiseANDExpression [?In,
?Yield, ?Await]
BitwiseXORExpression [?In,
?Yield, ?Await]
^
BitwiseANDExpression [?In,
?Yield, ?Await]
BitwiseORExpression [In,
Yield, Await] :
BitwiseXORExpression [?In,
?Yield, ?Await]
BitwiseORExpression [?In,
?Yield, ?Await]
|
BitwiseXORExpression [?In,
?Yield, ?Await]
13.12.1 运行时语义:Evaluation
BitwiseANDExpression
:
BitwiseANDExpression
&
EqualityExpression
返回 ? EvaluateStringOrNumericBinaryExpression (BitwiseANDExpression ,
&
, EqualityExpression )。
BitwiseXORExpression
:
BitwiseXORExpression
^
BitwiseANDExpression
返回 ? EvaluateStringOrNumericBinaryExpression (BitwiseXORExpression ,
^
, BitwiseANDExpression )。
BitwiseORExpression
:
BitwiseORExpression
|
BitwiseXORExpression
返回 ? EvaluateStringOrNumericBinaryExpression (BitwiseORExpression ,
|
, BitwiseXORExpression )。
13.13 二元逻辑运算符
语法
LogicalANDExpression [In,
Yield, Await] :
BitwiseORExpression [?In,
?Yield, ?Await]
LogicalANDExpression [?In,
?Yield, ?Await]
&&
BitwiseORExpression [?In,
?Yield, ?Await]
LogicalORExpression [In,
Yield, Await] :
LogicalANDExpression [?In,
?Yield, ?Await]
LogicalORExpression [?In,
?Yield, ?Await]
||
LogicalANDExpression [?In,
?Yield, ?Await]
CoalesceExpression [In, Yield,
Await] :
CoalesceExpressionHead [?In,
?Yield, ?Await]
??
BitwiseORExpression [?In,
?Yield, ?Await]
CoalesceExpressionHead [In,
Yield, Await] :
CoalesceExpression [?In,
?Yield, ?Await]
BitwiseORExpression [?In,
?Yield, ?Await]
ShortCircuitExpression [In,
Yield, Await] :
LogicalORExpression [?In,
?Yield, ?Await]
CoalesceExpression [?In,
?Yield, ?Await]
注
&&
或 ||
运算符产生的值不一定是布尔类型。产生的值总是两个操作数表达式之一的值。
13.13.1 运行时语义:Evaluation
LogicalANDExpression
:
LogicalANDExpression
&&
BitwiseORExpression
令 lRef 为 ? LogicalANDExpression 的 Evaluation 。
令 lVal 为 ? GetValue (lRef )。
如果 ToBoolean (lVal ) 是
false ,返回 lVal 。
令 rRef 为 ? BitwiseORExpression 的 Evaluation 。
返回 ? GetValue (rRef )。
LogicalORExpression
:
LogicalORExpression
||
LogicalANDExpression
令 lRef 为 ? LogicalORExpression 的 Evaluation 。
令 lVal 为 ? GetValue (lRef )。
如果 ToBoolean (lVal ) 是
true ,返回 lVal 。
令 rRef 为 ? LogicalANDExpression 的 Evaluation 。
返回 ? GetValue (rRef )。
CoalesceExpression
:
CoalesceExpressionHead
??
BitwiseORExpression
令 lRef 为 ? CoalesceExpressionHead 的
Evaluation 。
令 lVal 为 ? GetValue (lRef )。
如果 lVal 是 undefined 或 null ,则
令 rRef 为 ? BitwiseORExpression 的
Evaluation 。
返回 ? GetValue (rRef )。
否则,
返回 lVal 。
13.14 条件运算符 ( ? :
)
语法
ConditionalExpression [In,
Yield, Await] :
ShortCircuitExpression [?In,
?Yield, ?Await]
ShortCircuitExpression [?In,
?Yield, ?Await]
?
AssignmentExpression [+In,
?Yield, ?Await]
:
AssignmentExpression [?In,
?Yield, ?Await]
注
ECMAScript 中 ConditionalExpression 的语法与 C 和 Java
中的语法略有不同,后者允许第二个子表达式是 Expression ,但限制第三个表达式必须是 ConditionalExpression 。ECMAScript
中这种差异的动机是允许赋值表达式由条件的任一分支控制,并消除作为中间表达式的逗号表达式这种令人困惑且相当无用的情况。
13.14.1 运行时语义:Evaluation
ConditionalExpression
:
ShortCircuitExpression
?
AssignmentExpression
:
AssignmentExpression
令 lRef 为 ? ShortCircuitExpression 的
Evaluation 。
令 lVal 为 ToBoolean (? GetValue (lRef ))。
如果 lVal 是 true ,则
令 trueRef 为 ? 第一个 AssignmentExpression 的
Evaluation 。
返回 ? GetValue (trueRef )。
否则,
令 falseRef 为 ? 第二个 AssignmentExpression 的
Evaluation 。
返回 ? GetValue (falseRef )。
13.15 赋值运算符
语法
AssignmentExpression [In,
Yield, Await] :
ConditionalExpression [?In,
?Yield, ?Await]
[+Yield]
YieldExpression [?In,
?Await]
ArrowFunction [?In, ?Yield,
?Await]
AsyncArrowFunction [?In,
?Yield, ?Await]
LeftHandSideExpression [?Yield,
?Await]
=
AssignmentExpression [?In,
?Yield, ?Await]
LeftHandSideExpression [?Yield,
?Await]
AssignmentOperator
AssignmentExpression [?In,
?Yield, ?Await]
LeftHandSideExpression [?Yield,
?Await]
&&=
AssignmentExpression [?In,
?Yield, ?Await]
LeftHandSideExpression [?Yield,
?Await]
||=
AssignmentExpression [?In,
?Yield, ?Await]
LeftHandSideExpression [?Yield,
?Await]
??=
AssignmentExpression [?In,
?Yield, ?Await]
AssignmentOperator :
one of *= /= %=
+= -= <<= >>=
>>>= &= ^= |=
**=
13.15.1 静态语义:早期错误
AssignmentExpression
:
LeftHandSideExpression
=
AssignmentExpression
AssignmentExpression
:
LeftHandSideExpression
AssignmentOperator
AssignmentExpression
LeftHandSideExpression
&&=
AssignmentExpression
LeftHandSideExpression
||=
AssignmentExpression
LeftHandSideExpression
??=
AssignmentExpression
13.15.2 运行时语义:Evaluation
AssignmentExpression
:
LeftHandSideExpression
=
AssignmentExpression
如果 LeftHandSideExpression 既不是
ObjectLiteral 也不是
ArrayLiteral ,则
令 lRef 为 ? LeftHandSideExpression
的 Evaluation 。
如果 IsAnonymousFunctionDefinition (AssignmentExpression ) 是
true 且 LeftHandSideExpression
的 IsIdentifierRef
是 true ,则
令 lhs 为 LeftHandSideExpression
的 StringValue 。
令 rVal 为 ? AssignmentExpression
以参数 lhs 进行的 NamedEvaluation 。
否则,
令 rRef 为 ? AssignmentExpression
的 Evaluation 。
令 rVal 为 ? GetValue (rRef )。
执行
? PutValue (lRef ,
rVal )。
返回 rVal 。
令 assignmentPattern 为由 LeftHandSideExpression
覆盖 的 AssignmentPattern 。
令 rRef 为 ? AssignmentExpression 的 Evaluation 。
令 rVal 为 ? GetValue (rRef )。
执行 ? assignmentPattern 以参数 rVal 进行的 DestructuringAssignmentEvaluation 。
返回 rVal 。
AssignmentExpression
:
LeftHandSideExpression
AssignmentOperator
AssignmentExpression
令 lRef 为 ? LeftHandSideExpression 的
Evaluation 。
令 lVal 为
? GetValue (lRef )。
令 rRef 为 ? AssignmentExpression 的 Evaluation 。
令 rVal 为 ? GetValue (rRef )。
令 assignmentOpText 为 AssignmentOperator 匹配的源代码文本 。
令 opText 为下表中与
assignmentOpText 关联的 Unicode 代码点序列:
assignmentOpText
opText
**=
**
*=
*
/=
/
%=
%
+=
+
-=
-
<<=
<<
>>=
>>
>>>=
>>>
&=
&
^=
^
|=
|
令 r 为 ? ApplyStringOrNumericBinaryOperator (lVal ,
opText , rVal )。
执行 ? PutValue (lRef , r )。
返回 r 。
AssignmentExpression
:
LeftHandSideExpression
&&=
AssignmentExpression
令 lRef 为 ? LeftHandSideExpression 的
Evaluation 。
令 lVal 为
? GetValue (lRef )。
如果 ToBoolean (lVal ) 是
false ,返回 lVal 。
如果 IsAnonymousFunctionDefinition (AssignmentExpression ) 是
true 且 LeftHandSideExpression 的
IsIdentifierRef 是
true ,则
令 lhs 为 LeftHandSideExpression
的 StringValue 。
令 rVal 为 ? AssignmentExpression 以参数
lhs 进行的 NamedEvaluation 。
否则,
令 rRef 为 ? AssignmentExpression 的
Evaluation 。
令 rVal 为 ? GetValue (rRef )。
执行 ? PutValue (lRef , rVal )。
返回 rVal 。
AssignmentExpression
:
LeftHandSideExpression
||=
AssignmentExpression
令 lRef 为 ? LeftHandSideExpression 的
Evaluation 。
令 lVal 为
? GetValue (lRef )。
如果 ToBoolean (lVal ) 是
true ,返回 lVal 。
如果 IsAnonymousFunctionDefinition (AssignmentExpression ) 是
true 且 LeftHandSideExpression 的
IsIdentifierRef 是
true ,则
令 lhs 为 LeftHandSideExpression
的 StringValue 。
令 rVal 为 ? AssignmentExpression 以参数
lhs 进行的 NamedEvaluation 。
否则,
令 rRef 为 ? AssignmentExpression 的
Evaluation 。
令 rVal 为 ? GetValue (rRef )。
执行 ? PutValue (lRef , rVal )。
返回 rVal 。
AssignmentExpression
:
LeftHandSideExpression
??=
AssignmentExpression
令 lRef 为 ? LeftHandSideExpression 的
Evaluation 。
令 lVal 为
? GetValue (lRef )。
如果 lVal 既不是 undefined 也不是 null ,
返回 lVal 。
如果 IsAnonymousFunctionDefinition (AssignmentExpression ) 是
true 且 LeftHandSideExpression 的
IsIdentifierRef 是
true ,则
令 lhs 为 LeftHandSideExpression
的 StringValue 。
令 rVal 为 ? AssignmentExpression 以参数
lhs 进行的 NamedEvaluation 。
否则,
令 rRef 为 ? AssignmentExpression 的
Evaluation 。
令 rVal 为 ? GetValue (rRef )。
执行 ? PutValue (lRef , rVal )。
返回 rVal 。
注
当此表达式出现在严格模式代码 中时,如果步骤 1.d 、
2 、
2 、
2 、
2
中的 lRef 是不可解析的引用,这是运行时错误。如果是,则抛出 ReferenceError 异常。此外,如果步骤
8 、
6 、
6 、
6
中的 lRef 引用具有属性值 {
[[Writable]] : false } 的数据属性 ,或引用具有属性值 { [[Set]] : undefined } 的访问器属性 ,或引用对象的不存在属性且该对象的 IsExtensible 谓词返回值
false ,这是运行时错误。在这些情况下会抛出 TypeError 异常。
13.15.3 ApplyStringOrNumericBinaryOperator ( lVal ,
opText , rVal )
抽象操作 ApplyStringOrNumericBinaryOperator 接受参数 lVal (一个ECMAScript 语言值 )、
opText (**
、*
、/
、%
、
+
、-
、<<
、>>
、
>>>
、&
、^
或 |
)和
rVal (一个ECMAScript 语言值 ),并返回包含 String、BigInt 或
Number 的正常完成 ,或抛出完成 。当调用时,它执行以下步骤:
如果 opText 是 +
,则
令 lPrim 为 ? ToPrimitive (lVal )。
令 rPrim 为 ? ToPrimitive (rVal )。
如果 lPrim 是
String 或 rPrim 是
String ,则
令 lStr 为 ? ToString (lPrim )。
令 rStr 为 ? ToString (rPrim )。
返回 lStr 和 rStr 的字符串拼接 。
设置 lVal 为 lPrim 。
设置 rVal 为 rPrim 。
注:此时,这必须是数值运算。
令 lNum 为 ? ToNumeric (lVal )。
令 rNum 为 ? ToNumeric (rVal )。
如果 SameType (lNum , rNum )
是 false ,抛出 TypeError 异常。
如果 lNum 是
BigInt ,则
如果 opText 是 **
,返回 ? BigInt::exponentiate (lNum ,
rNum )。
如果 opText 是 /
,返回 ? BigInt::divide (lNum ,
rNum )。
如果 opText 是 %
,返回 ? BigInt::remainder (lNum ,
rNum )。
如果 opText 是 >>>
,返回 ? BigInt::unsignedRightShift (lNum ,
rNum )。
令 operation 为下表中与 opText 关联的抽象操作:
否则,
断言 :
lNum 是
Number 。
令 operation 为下表中与 opText 关联的抽象操作:
返回 operation (lNum , rNum )。
注 1
在步骤 1.a 和 1.b 中对 ToPrimitive 的调用中没有提供提示。除 Date
外的所有标准对象都将缺少提示处理为给定 number ;Date 将缺少提示处理为给定
string 。异质对象 可能以其他方式处理缺少提示的情况。
注 2
步骤 1.c 与 IsLessThan
算法的步骤 3 不同,使用逻辑或运算而不是逻辑与运算。
13.15.4 EvaluateStringOrNumericBinaryExpression (
leftOperand , opText , rightOperand )
抽象操作 EvaluateStringOrNumericBinaryExpression 接受参数
leftOperand (一个解析节点 )、opText (一个 Unicode 代码点序列)和
rightOperand (一个解析节点 ),并返回包含 String、BigInt 或
Number 的正常完成 ,或异常完成 。当调用时,它执行以下步骤:
令 lRef 为 ? leftOperand 的 Evaluation 。
令 lVal 为 ? GetValue (lRef )。
令 rRef 为 ? rightOperand 的 Evaluation 。
令 rVal 为 ? GetValue (rRef )。
返回 ? 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] :
[
Elision opt
AssignmentRestElement [?Yield,
?Await] opt
]
[
AssignmentElementList [?Yield,
?Await]
]
[
AssignmentElementList [?Yield,
?Await]
,
Elision opt
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] :
Elision opt
AssignmentElement [?Yield,
?Await]
AssignmentProperty [Yield,
Await] :
IdentifierReference [?Yield,
?Await]
Initializer [+In, ?Yield,
?Await] opt
PropertyName [?Yield,
?Await]
:
AssignmentElement [?Yield,
?Await]
AssignmentElement [Yield,
Await] :
DestructuringAssignmentTarget [?Yield,
?Await]
Initializer [+In, ?Yield,
?Await] opt
AssignmentRestElement [Yield,
Await] :
...
DestructuringAssignmentTarget [?Yield,
?Await]
DestructuringAssignmentTarget [Yield,
Await] :
LeftHandSideExpression [?Yield,
?Await]
13.15.5.1 静态语义:早期错误
AssignmentProperty
:
IdentifierReference
Initializer opt
AssignmentRestProperty
:
...
DestructuringAssignmentTarget
DestructuringAssignmentTarget
: LeftHandSideExpression
13.15.5.2 运行时语义:DestructuringAssignmentEvaluation
语法导向操作
DestructuringAssignmentEvaluation 接受参数
value (一个ECMAScript 语言值 ),并返回包含
unused 的正常完成 或异常完成 。
它在以下产生式上分段定义:
ObjectAssignmentPattern
:
{
}
执行 ? RequireObjectCoercible (value )。
返回 unused 。
ObjectAssignmentPattern
:
{
AssignmentPropertyList
}
{
AssignmentPropertyList
,
}
执行 ? RequireObjectCoercible (value )。
执行 ? AssignmentPropertyList 以参数
value 进行的 PropertyDestructuringAssignmentEvaluation 。
返回 unused 。
ObjectAssignmentPattern
:
{
AssignmentRestProperty
}
执行 ? RequireObjectCoercible (value )。
令 excludedNames 为一个新的空列表 。
返回 ? AssignmentRestProperty 以参数
value 和 excludedNames 进行的 RestDestructuringAssignmentEvaluation 。
ObjectAssignmentPattern
:
{
AssignmentPropertyList
,
AssignmentRestProperty
}
执行 ? RequireObjectCoercible (value )。
令 excludedNames 为 ? AssignmentPropertyList 以参数
value 进行的 PropertyDestructuringAssignmentEvaluation 。
返回 ? AssignmentRestProperty 以参数
value 和 excludedNames 进行的 RestDestructuringAssignmentEvaluation 。
ArrayAssignmentPattern
:
[
]
令 iteratorRecord 为 ? GetIterator (value ,
sync )。
返回 ? IteratorClose (iteratorRecord ,
NormalCompletion (unused ))。
ArrayAssignmentPattern
:
[
Elision
]
令 iteratorRecord 为 ? GetIterator (value ,
sync )。
令 result 为 Completion (Elision 以参数
iteratorRecord 进行的 IteratorDestructuringAssignmentEvaluation )。
如果 iteratorRecord .[[Done]] 是
false ,返回 ? IteratorClose (iteratorRecord ,
result )。
返回 result 。
ArrayAssignmentPattern
:
[
Elision opt
AssignmentRestElement
]
令 iteratorRecord 为 ? GetIterator (value ,
sync )。
如果存在 Elision ,则
令 status 为 Completion (Elision 以参数
iteratorRecord 进行的 IteratorDestructuringAssignmentEvaluation )。
如果 status 是异常完成 ,则
断言 :
iteratorRecord .[[Done]] 是
true 。
返回 ? status 。
令 result 为 Completion (AssignmentRestElement 以参数
iteratorRecord 进行的 IteratorDestructuringAssignmentEvaluation )。
如果 iteratorRecord .[[Done]] 是
false ,返回 ? IteratorClose (iteratorRecord ,
result )。
返回 result 。
ArrayAssignmentPattern
:
[
AssignmentElementList
]
令 iteratorRecord 为 ? GetIterator (value ,
sync )。
令 result 为 Completion (AssignmentElementList 以参数
iteratorRecord 进行的 IteratorDestructuringAssignmentEvaluation )。
如果 iteratorRecord .[[Done]] 是
false ,返回 ? IteratorClose (iteratorRecord ,
result )。
返回 result 。
ArrayAssignmentPattern
:
[
AssignmentElementList
,
Elision opt
AssignmentRestElement opt
]
令 iteratorRecord 为 ? GetIterator (value ,
sync )。
令 status 为 Completion (AssignmentElementList 以参数
iteratorRecord 进行的 IteratorDestructuringAssignmentEvaluation )。
如果 status 是异常完成 ,则
如果 iteratorRecord .[[Done]] 是
false ,返回 ? IteratorClose (iteratorRecord ,
status )。
返回 ? status 。
如果存在 Elision ,则
设置 status 为 Completion (Elision 以参数
iteratorRecord 进行的 IteratorDestructuringAssignmentEvaluation )。
如果 status 是异常完成 ,则
断言 :
iteratorRecord .[[Done]] 是
true 。
返回 ? status 。
如果存在 AssignmentRestElement ,则
设置 status 为 Completion (AssignmentRestElement
以参数 iteratorRecord 进行的 IteratorDestructuringAssignmentEvaluation )。
如果 iteratorRecord .[[Done]] 是
false ,返回 ? IteratorClose (iteratorRecord ,
status )。
返回 ? status 。
13.15.5.3 运行时语义:PropertyDestructuringAssignmentEvaluation
语法导向操作
PropertyDestructuringAssignmentEvaluation 接受参数
value (一个ECMAScript 语言值 ),并返回包含 属性键 的列表 的正常完成 或异常完成 。它收集所有解构的属性键 的列表。它在以下产生式上分段定义:
AssignmentPropertyList
:
AssignmentPropertyList
,
AssignmentProperty
令 propertyNames 为 ? AssignmentPropertyList 以参数
value 进行的 PropertyDestructuringAssignmentEvaluation 。
令 nextNames 为 ? AssignmentProperty 以参数
value 进行的 PropertyDestructuringAssignmentEvaluation 。
返回 propertyNames 和 nextNames 的列表拼接 。
AssignmentProperty
:
IdentifierReference
Initializer opt
令 P 为 IdentifierReference 的
StringValue 。
令 lRef 为 ? ResolveBinding (P )。
令 v 为 ? GetV (value , P )。
如果存在 Initializer 且
v 是 undefined ,则
如果 IsAnonymousFunctionDefinition (Initializer ) 是
true ,则
设置 v 为 ? Initializer 以参数
P 进行的 NamedEvaluation 。
否则,
令 defaultValue 为 ? Initializer 的
Evaluation 。
设置 v 为 ? GetValue (defaultValue )。
执行 ? PutValue (lRef , v )。
返回 « P »。
AssignmentProperty
:
PropertyName
:
AssignmentElement
令 name 为 ? PropertyName 的 Evaluation 。
执行 ? AssignmentElement 以参数
value 和 name 进行的 KeyedDestructuringAssignmentEvaluation 。
返回 « name »。
13.15.5.4 运行时语义:RestDestructuringAssignmentEvaluation
语法导向操作
RestDestructuringAssignmentEvaluation 接受参数
value (一个ECMAScript 语言值 )和
excludedNames (属性键 的列表 ),并返回包含
unused 的正常完成 或异常完成 。
它在以下产生式上分段定义:
AssignmentRestProperty
:
...
DestructuringAssignmentTarget
令 lRef 为 ? DestructuringAssignmentTarget
的 Evaluation 。
令 restObj 为 OrdinaryObjectCreate (%Object.prototype% )。
执行 ? CopyDataProperties (restObj ,
value , excludedNames )。
返回 ? PutValue (lRef ,
restObj )。
13.15.5.5 运行时语义:IteratorDestructuringAssignmentEvaluation
语法导向操作
IteratorDestructuringAssignmentEvaluation 接受参数
iteratorRecord (一个迭代器记录 ),并返回包含
unused 的正常完成 或异常完成 。
它在以下产生式上分段定义:
AssignmentElementList
: AssignmentElisionElement
返回 ? AssignmentElisionElement
以参数 iteratorRecord 进行的 IteratorDestructuringAssignmentEvaluation 。
AssignmentElementList
:
AssignmentElementList
,
AssignmentElisionElement
执行 ? AssignmentElementList 以参数
iteratorRecord 进行的 IteratorDestructuringAssignmentEvaluation 。
返回 ? AssignmentElisionElement
以参数 iteratorRecord 进行的 IteratorDestructuringAssignmentEvaluation 。
AssignmentElisionElement
: AssignmentElement
返回 ? AssignmentElement 以参数
iteratorRecord 进行的 IteratorDestructuringAssignmentEvaluation 。
AssignmentElisionElement
:
Elision
AssignmentElement
执行 ? Elision 以参数
iteratorRecord 进行的 IteratorDestructuringAssignmentEvaluation 。
返回 ? AssignmentElement 以参数
iteratorRecord 进行的 IteratorDestructuringAssignmentEvaluation 。
Elision : ,
如果 iteratorRecord .[[Done]] 是
false ,则
执行 ? IteratorStep (iteratorRecord )。
返回 unused 。
Elision :
Elision
,
执行 ? Elision 以参数
iteratorRecord 进行的 IteratorDestructuringAssignmentEvaluation 。
如果 iteratorRecord .[[Done]] 是
false ,则
执行 ? IteratorStep (iteratorRecord )。
返回 unused 。
AssignmentElement
:
DestructuringAssignmentTarget
Initializer opt
如果 DestructuringAssignmentTarget
既不是 ObjectLiteral
也不是 ArrayLiteral ,则
令 lRef 为 ? DestructuringAssignmentTarget
的 Evaluation 。
令 value 为 undefined 。
如果 iteratorRecord .[[Done]] 是
false ,则
令 next 为 ? IteratorStepValue (iteratorRecord )。
如果 next 不是 done ,则
设置 value 为 next 。
如果存在 Initializer 且
value 是 undefined ,则
如果 IsAnonymousFunctionDefinition (Initializer ) 是
true 且 DestructuringAssignmentTarget
的 IsIdentifierRef
是 true ,则
令 target 为 DestructuringAssignmentTarget
的 StringValue 。
令 v 为 ? Initializer 以参数
target 进行的 NamedEvaluation 。
否则,
令 defaultValue 为 ? Initializer 的
Evaluation 。
令 v 为 ? GetValue (defaultValue )。
否则,
令 v 为 value 。
如果 DestructuringAssignmentTarget
是 ObjectLiteral 或
ArrayLiteral ,则
令 nestedAssignmentPattern 为被 DestructuringAssignmentTarget
覆盖 的 AssignmentPattern 。
返回 ? nestedAssignmentPattern 以参数 v 进行的 DestructuringAssignmentEvaluation 。
返回 ? PutValue (lRef , v )。
注
AssignmentRestElement
:
...
DestructuringAssignmentTarget
如果 DestructuringAssignmentTarget
既不是 ObjectLiteral
也不是 ArrayLiteral ,则
令 lRef 为 ? DestructuringAssignmentTarget
的 Evaluation 。
令 A 为 ! ArrayCreate (0)。
令 n 为 0。
重复,只要 iteratorRecord .[[Done]] 是
false ,
令 next 为 ? IteratorStepValue (iteratorRecord )。
如果 next 不是 done ,则
执行 ! CreateDataPropertyOrThrow (A ,
! ToString (𝔽 (n )),
next )。
设置 n 为 n + 1。
如果 DestructuringAssignmentTarget
既不是 ObjectLiteral
也不是 ArrayLiteral ,则
返回 ? PutValue (lRef ,
A )。
令 nestedAssignmentPattern 为被 DestructuringAssignmentTarget
覆盖 的 AssignmentPattern 。
返回 ? nestedAssignmentPattern 以参数 A 进行的 DestructuringAssignmentEvaluation 。
13.15.5.6 运行时语义:KeyedDestructuringAssignmentEvaluation
语法导向操作
KeyedDestructuringAssignmentEvaluation 接受参数
value (一个ECMAScript 语言值 )和
propertyName (一个属性键 ),并返回包含
unused 的正常完成 或异常完成 。
它在以下产生式上分段定义:
AssignmentElement
:
DestructuringAssignmentTarget
Initializer opt
如果 DestructuringAssignmentTarget
既不是 ObjectLiteral
也不是 ArrayLiteral ,则
令 lRef 为 ? DestructuringAssignmentTarget
的 Evaluation 。
令 v 为 ? GetV (value ,
propertyName )。
如果存在 Initializer 且
v 是 undefined ,则
如果 IsAnonymousFunctionDefinition (Initializer ) 是
true 且 DestructuringAssignmentTarget
的 IsIdentifierRef
是 true ,则
令 target 为 DestructuringAssignmentTarget
的 StringValue 。
令 rhsValue 为 ? Initializer 以参数
target 进行的 NamedEvaluation 。
否则,
令 defaultValue 为 ? Initializer 的
Evaluation 。
令 rhsValue 为 ? GetValue (defaultValue )。
否则,
令 rhsValue 为 v 。
如果 DestructuringAssignmentTarget
是 ObjectLiteral 或
ArrayLiteral ,则
令 assignmentPattern 为被 DestructuringAssignmentTarget
覆盖 的 AssignmentPattern 。
返回 ? assignmentPattern 以参数 rhsValue 进行的 DestructuringAssignmentEvaluation 。
返回 ? PutValue (lRef ,
rhsValue )。
13.16 逗号操作符 ( ,
)
语法
Expression [In, Yield,
Await] :
AssignmentExpression [?In,
?Yield, ?Await]
Expression [?In, ?Yield,
?Await]
,
AssignmentExpression [?In,
?Yield, ?Await]
13.16.1 运行时语义:Evaluation
Expression :
Expression
,
AssignmentExpression
令 lRef 为 ? Expression 的 Evaluation 。
执行 ? GetValue (lRef )。
令 rRef 为 ? AssignmentExpression 的 Evaluation 。
返回 ? GetValue (rRef )。
注
必须调用 GetValue ,即使其值未被使用,因为它可能具有可观察的副作用。
14 ECMAScript 语言:语句和声明
语法
Statement [Yield, Await,
Return] :
BlockStatement [?Yield, ?Await,
?Return]
VariableStatement [?Yield,
?Await]
EmptyStatement
ExpressionStatement [?Yield,
?Await]
IfStatement [?Yield, ?Await,
?Return]
BreakableStatement [?Yield,
?Await, ?Return]
ContinueStatement [?Yield,
?Await]
BreakStatement [?Yield,
?Await]
[+Return]
ReturnStatement [?Yield,
?Await]
WithStatement [?Yield, ?Await,
?Return]
LabelledStatement [?Yield,
?Await, ?Return]
ThrowStatement [?Yield,
?Await]
TryStatement [?Yield, ?Await,
?Return]
DebuggerStatement
Declaration [Yield,
Await] :
HoistableDeclaration [?Yield,
?Await, ~Default]
ClassDeclaration [?Yield, ?Await,
~Default]
LexicalDeclaration [+In,
?Yield, ?Await]
HoistableDeclaration [Yield,
Await, Default] :
FunctionDeclaration [?Yield,
?Await, ?Default]
GeneratorDeclaration [?Yield,
?Await, ?Default]
AsyncFunctionDeclaration [?Yield,
?Await, ?Default]
AsyncGeneratorDeclaration [?Yield,
?Await, ?Default]
BreakableStatement [Yield, Await,
Return] :
IterationStatement [?Yield,
?Await, ?Return]
SwitchStatement [?Yield, ?Await,
?Return]
14.1 语句语义
14.1.1 运行时语义:Evaluation
HoistableDeclaration
:
GeneratorDeclaration
AsyncFunctionDeclaration
AsyncGeneratorDeclaration
返回 empty 。
HoistableDeclaration
: FunctionDeclaration
返回 ? FunctionDeclaration 的 Evaluation 。
BreakableStatement
:
IterationStatement
SwitchStatement
令 newLabelSet 为一个新的空列表 。
返回 ? 此 BreakableStatement
以参数 newLabelSet 进行的 LabelledEvaluation 。
14.2 块
语法
BlockStatement [Yield, Await,
Return] :
Block [?Yield, ?Await,
?Return]
Block [Yield, Await,
Return] :
{
StatementList [?Yield, ?Await,
?Return] opt
}
StatementList [Yield, Await,
Return] :
StatementListItem [?Yield,
?Await, ?Return]
StatementList [?Yield, ?Await,
?Return]
StatementListItem [?Yield,
?Await, ?Return]
StatementListItem [Yield, Await,
Return] :
Statement [?Yield, ?Await,
?Return]
Declaration [?Yield,
?Await]
14.2.1 静态语义:早期错误
Block :
{
StatementList
}
14.2.2 运行时语义:Evaluation
Block :
{
}
返回 empty 。
Block :
{
StatementList
}
令 oldEnv 为运行中执行上下文 的 LexicalEnvironment。
令 blockEnv 为 NewDeclarativeEnvironment (oldEnv )。
执行 BlockDeclarationInstantiation (StatementList ,
blockEnv )。
设置运行中执行上下文 的
LexicalEnvironment 为 blockEnv 。
令 blockValue 为 Completion (StatementList 的 Evaluation )。
设置运行中执行上下文 的
LexicalEnvironment 为 oldEnv 。
返回 ? blockValue 。
注1
无论控制如何离开 Block ,LexicalEnvironment 总是恢复到其之前的状态。
StatementList :
StatementList
StatementListItem
令 sl 为 ? StatementList 的 Evaluation 。
令 s 为 Completion (StatementListItem 的 Evaluation )。
返回 ? UpdateEmpty (s , sl )。
注2
StatementList 的值是
StatementList
中最后一个产生值的项的值。例如,以下对 eval
函数的调用都返回值 1:
eval ("1;;;;;" )
eval ("1;{}" )
eval ("1;var a;" )
14.2.3 BlockDeclarationInstantiation ( code ,
env )
抽象操作 BlockDeclarationInstantiation 接受参数 code (一个解析节点 )和
env (一个声明式环境记录 ),并返回
unused 。code 是对应于块主体的解析节点 。env
是要在其中创建绑定的环境记录 。
注
当计算 Block 或 CaseBlock 时,会创建一个新的声明式环境记录 ,并且块中声明的每个块作用域变量、常量、函数或类的绑定会在环境记录 中实例化。
调用时执行以下步骤:
令 declarations 为 code 的 LexicallyScopedDeclarations 。
令 privateEnv 为运行中执行上下文 的 PrivateEnvironment。
对于 declarations 的每个元素 d ,执行
对于 d 的 BoundNames 的每个元素
dn ,执行
如果 d 的 IsConstantDeclaration
是 true ,则
执行
! env .CreateImmutableBinding(dn ,
true )。
否则,
执行
! env .CreateMutableBinding(dn ,
false )。注:此步骤在 B.3.2.6
节中被替换。
如果 d 是 FunctionDeclaration 、GeneratorDeclaration 、AsyncFunctionDeclaration
或 AsyncGeneratorDeclaration ,则
令 fn 为 d 的 BoundNames
的唯一元素。
令 fo 为 d 以参数 env 和
privateEnv 进行的 InstantiateFunctionObject 。
执行
! env .InitializeBinding(fn , fo )。
注:此步骤在 B.3.2.6
节中被替换。
返回 unused 。
14.3 声明和变量语句
14.3.1 Let 和 Const 声明
注
let
和 const
声明定义的变量作用域限定在运行中执行上下文 的
LexicalEnvironment。这些变量在其包含的环境记录 实例化时创建,但在变量的 LexicalBinding
被计算之前不能以任何方式访问。由带有 Initializer 的 LexicalBinding 定义的变量在 LexicalBinding
被计算时(而不是在变量创建时)被赋予其 Initializer 的 AssignmentExpression 的值。如果
let
声明中的 LexicalBinding
没有 Initializer ,则在
LexicalBinding
被计算时,该变量被赋值为 undefined 。
语法
LexicalDeclaration [In,
Yield, Await] :
LetOrConst
BindingList [?In, ?Yield,
?Await]
;
LetOrConst :
let
const
BindingList [In, Yield,
Await] :
LexicalBinding [?In,
?Yield, ?Await]
BindingList [?In, ?Yield,
?Await]
,
LexicalBinding [?In,
?Yield, ?Await]
LexicalBinding [In, Yield,
Await] :
BindingIdentifier [?Yield,
?Await]
Initializer [?In, ?Yield,
?Await] opt
BindingPattern [?Yield,
?Await]
Initializer [?In, ?Yield,
?Await]
14.3.1.1 静态语义:早期错误
LexicalDeclaration
:
LetOrConst
BindingList
;
LexicalBinding :
BindingIdentifier
Initializer opt
14.3.1.2 运行时语义:Evaluation
LexicalDeclaration
:
LetOrConst
BindingList
;
执行 ? BindingList 的 Evaluation 。
返回 empty 。
BindingList :
BindingList
,
LexicalBinding
执行 ? BindingList 的 Evaluation 。
返回 ? LexicalBinding 的 Evaluation 。
LexicalBinding :
BindingIdentifier
令 lhs 为 ! ResolveBinding (BindingIdentifier
的 StringValue )。
执行 ! InitializeReferencedBinding (lhs ,
undefined )。
返回 empty 。
注
静态语义 规则确保这种形式的 LexicalBinding
永远不会出现在
const
声明中。
LexicalBinding :
BindingIdentifier
Initializer
令 bindingId 为 BindingIdentifier 的 StringValue 。
令 lhs 为 ! ResolveBinding (bindingId )。
如果 IsAnonymousFunctionDefinition (Initializer ) 是
true ,则
令 value 为 ? Initializer
以参数 bindingId 进行的 NamedEvaluation 。
否则,
令 rhs 为 ? Initializer 的 Evaluation 。
令 value 为 ? GetValue (rhs )。
执行 ! InitializeReferencedBinding (lhs ,
value )。
返回 empty 。
LexicalBinding :
BindingPattern
Initializer
令 rhs 为 ? Initializer 的 Evaluation 。
令 value 为 ? GetValue (rhs )。
令 env 为运行中执行上下文 的
LexicalEnvironment。
返回 ? BindingPattern 以参数 value
和 env 进行的 BindingInitialization 。
14.3.2 变量语句
注
var
语句声明的变量作用域限定在运行中执行上下文 的
VariableEnvironment。var 变量在其包含的环境记录 实例化时创建,并在创建时初始化为
undefined 。在任何 VariableEnvironment 的作用域内,相同的 BindingIdentifier
可以出现在多个 VariableDeclaration
中,但这些声明共同只定义一个变量。由带有 Initializer 的 VariableDeclaration
定义的变量在 VariableDeclaration
执行时(而不是在变量创建时)被赋予其 Initializer 的 AssignmentExpression 的值。
语法
VariableStatement [Yield,
Await] :
var
VariableDeclarationList [+In,
?Yield, ?Await]
;
VariableDeclarationList [In,
Yield, Await] :
VariableDeclaration [?In,
?Yield, ?Await]
VariableDeclarationList [?In,
?Yield, ?Await]
,
VariableDeclaration [?In,
?Yield, ?Await]
VariableDeclaration [In,
Yield, Await] :
BindingIdentifier [?Yield,
?Await]
Initializer [?In, ?Yield,
?Await] opt
BindingPattern [?Yield,
?Await]
Initializer [?In, ?Yield,
?Await]
14.3.2.1 运行时语义:Evaluation
VariableStatement
:
var
VariableDeclarationList
;
执行 ? VariableDeclarationList 的
Evaluation 。
返回 empty 。
VariableDeclarationList
:
VariableDeclarationList
,
VariableDeclaration
执行 ? VariableDeclarationList 的
Evaluation 。
返回 ? VariableDeclaration 的
Evaluation 。
VariableDeclaration
: BindingIdentifier
返回 empty 。
VariableDeclaration
:
BindingIdentifier
Initializer
令 bindingId 为 BindingIdentifier 的 StringValue 。
令 lhs 为 ? ResolveBinding (bindingId )。
如果 IsAnonymousFunctionDefinition (Initializer ) 是
true ,则
令 value 为 ? Initializer
以参数 bindingId 进行的 NamedEvaluation 。
否则,
令 rhs 为 ? Initializer 的 Evaluation 。
令 value 为 ? GetValue (rhs )。
执行 ? PutValue (lhs ,
value )。
返回 empty 。
注
如果 VariableDeclaration 嵌套在 with
语句中,且 VariableDeclaration 中的 BindingIdentifier
与 with 语句的对象环境记录 的绑定对象的属性名 相同,则步骤 5 将把
value 赋值给该属性,而不是赋值给 Identifier 的 VariableEnvironment 绑定。
VariableDeclaration
:
BindingPattern
Initializer
令 rhs 为 ? Initializer 的 Evaluation 。
令 rVal 为 ? GetValue (rhs )。
返回 ? BindingPattern 以参数 rVal
和 undefined 进行的 BindingInitialization 。
14.3.3 解构绑定模式
语法
BindingPattern [Yield,
Await] :
ObjectBindingPattern [?Yield,
?Await]
ArrayBindingPattern [?Yield,
?Await]
ObjectBindingPattern [Yield,
Await] :
{
}
{
BindingRestProperty [?Yield,
?Await]
}
{
BindingPropertyList [?Yield,
?Await]
}
{
BindingPropertyList [?Yield,
?Await]
,
BindingRestProperty [?Yield,
?Await] opt
}
ArrayBindingPattern [Yield,
Await] :
[
Elision opt
BindingRestElement [?Yield,
?Await] opt
]
[
BindingElementList [?Yield,
?Await]
]
[
BindingElementList [?Yield,
?Await]
,
Elision opt
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] :
Elision opt
BindingElement [?Yield,
?Await]
BindingProperty [Yield,
Await] :
SingleNameBinding [?Yield,
?Await]
PropertyName [?Yield,
?Await]
:
BindingElement [?Yield,
?Await]
BindingElement [Yield,
Await] :
SingleNameBinding [?Yield,
?Await]
BindingPattern [?Yield,
?Await]
Initializer [+In, ?Yield,
?Await] opt
SingleNameBinding [Yield,
Await] :
BindingIdentifier [?Yield,
?Await]
Initializer [+In, ?Yield,
?Await] opt
BindingRestElement [Yield,
Await] :
...
BindingIdentifier [?Yield,
?Await]
...
BindingPattern [?Yield,
?Await]
14.3.3.1 运行时语义:PropertyBindingInitialization
语法制导操作
PropertyBindingInitialization 接受参数
value (一个ECMAScript 语言值 )和
environment (一个环境记录 或
undefined ),并返回包含 列表 的属性键 的正常完成或突然完成 。它收集所有已绑定属性名的列表。它在以下产生式上分段定义:
BindingPropertyList
:
BindingPropertyList
,
BindingProperty
令 boundNames 为 ? BindingPropertyList 以参数
value 和 environment 进行的 PropertyBindingInitialization 。
令 nextNames 为 ? BindingProperty 以参数
value 和 environment 进行的 PropertyBindingInitialization 。
返回 boundNames 和 nextNames 的列表连接 。
BindingProperty
: SingleNameBinding
令 name 为 SingleNameBinding 的 BoundNames 的唯一元素。
执行 ? SingleNameBinding 以参数
value 、environment 和 name 进行的 KeyedBindingInitialization 。
返回 « name »。
BindingProperty
:
PropertyName
:
BindingElement
令 P 为 ? PropertyName 的 Evaluation 。
执行 ? BindingElement 以参数
value 、environment 和 P 进行的 KeyedBindingInitialization 。
返回 « P »。
14.3.3.2 运行时语义:RestBindingInitialization
语法制导操作
RestBindingInitialization 接受参数 value
(一个ECMAScript 语言值 )、
environment (一个环境记录 或
undefined )和 excludedNames (一个列表 ,包含属性键 ),并返回包含
unused 的正常完成或突然完成 。它在以下产生式上分段定义:
BindingRestProperty
:
...
BindingIdentifier
令 lhs 为 ? ResolveBinding (BindingIdentifier 的 StringValue ,
environment )。
令 restObj 为 OrdinaryObjectCreate (%Object.prototype% )。
执行 ? CopyDataProperties (restObj ,
value ,excludedNames )。
如果 environment 是 undefined ,返回 ? PutValue (lhs ,
restObj )。
返回 ? InitializeReferencedBinding (lhs ,
restObj )。
14.3.3.3 运行时语义:KeyedBindingInitialization
语法制导操作
KeyedBindingInitialization 接受参数 value
(一个ECMAScript 语言值 )、
environment (一个环境记录 或
undefined )和 propertyName (一个属性键 ),并返回包含
unused 的正常完成或突然完成 。
注
当为 environment 传递 undefined 时,表示应该使用 PutValue
操作来分配初始化值。这是非严格函数 的形参列表的情况。在这种情况下,形参绑定会被预初始化,以处理可能存在多个同名参数的情况。
它在以下产生式上分段定义:
BindingElement :
BindingPattern
Initializer opt
令 v 为 ? GetV (value ,
propertyName )。
如果存在 Initializer 且
v 是 undefined ,则
令 defaultValue 为 ? Initializer 的 Evaluation 。
设置 v 为 ? GetValue (defaultValue )。
返回 ? BindingPattern 以参数 v 和
environment 进行的 BindingInitialization 。
SingleNameBinding
:
BindingIdentifier
Initializer opt
令 bindingId 为 BindingIdentifier 的 StringValue 。
令 lhs 为 ? ResolveBinding (bindingId ,
environment )。
令 v 为 ? GetV (value ,
propertyName )。
如果存在 Initializer 且
v 是 undefined ,则
如果 IsAnonymousFunctionDefinition (Initializer ) 是
true ,则
设置 v 为 ? Initializer 以参数
bindingId 进行的 NamedEvaluation 。
否则,
令 defaultValue 为 ? Initializer 的
Evaluation 。
设置 v 为 ? GetValue (defaultValue )。
如果 environment 是 undefined ,返回 ? PutValue (lhs ,v )。
返回 ? InitializeReferencedBinding (lhs ,
v )。
14.4 空语句
语法
EmptyStatement :
;
14.4.1 运行时语义:Evaluation
EmptyStatement :
;
返回 empty 。
14.5 表达式语句
语法
ExpressionStatement [Yield,
Await] :
[lookahead ∉ { { , function , async
[no LineTerminator here]
function , class , let
[ }]
Expression [+In, ?Yield,
?Await]
;
注
14.5.1 运行时语义:Evaluation
ExpressionStatement
:
Expression
;
令 exprRef 为 ? Expression 的 Evaluation 。
返回 ? GetValue (exprRef )。
14.6 if
语句
语法
IfStatement [Yield, Await,
Return] :
if
(
Expression [+In, ?Yield,
?Await]
)
Statement [?Yield, ?Await,
?Return]
else
Statement [?Yield, ?Await,
?Return]
if
(
Expression [+In, ?Yield,
?Await]
)
Statement [?Yield, ?Await,
?Return]
[lookahead ≠ else ]
注
前瞻限制 [lookahead ≠ else
] 以通常的方式解决了经典的"悬空 else"问题。也就是说,当关联的
if
的选择在其他方面模糊时,else
与候选 if
中最近的(最内层的)关联。
14.6.1 静态语义:早期错误
IfStatement :
if
(
Expression
)
Statement
else
Statement
IfStatement :
if
(
Expression
)
Statement
注
只有在实现B.3.1
中指定的扩展时,才需要应用此规则。
14.6.2 运行时语义:Evaluation
IfStatement :
if
(
Expression
)
Statement
else
Statement
令 exprRef 为 ? Expression 的 Evaluation 。
令 exprValue 为 ToBoolean (? GetValue (exprRef ))。
如果 exprValue 是 true ,则
令 stmtCompletion 为 Completion (第一个 Statement 的 Evaluation )。
否则,
令 stmtCompletion 为 Completion (第二个 Statement 的 Evaluation )。
返回 ? UpdateEmpty (stmtCompletion ,
undefined )。
IfStatement :
if
(
Expression
)
Statement
令 exprRef 为 ? Expression 的 Evaluation 。
令 exprValue 为 ToBoolean (? GetValue (exprRef ))。
如果 exprValue 是 false ,则
返回 undefined 。
否则,
令 stmtCompletion 为 Completion (Statement 的 Evaluation )。
返回 ? UpdateEmpty (stmtCompletion ,
undefined )。
14.7 迭代语句
语法
IterationStatement [Yield,
Await, Return] :
DoWhileStatement [?Yield,
?Await, ?Return]
WhileStatement [?Yield, ?Await,
?Return]
ForStatement [?Yield, ?Await,
?Return]
ForInOfStatement [?Yield,
?Await, ?Return]
14.7.1 语义
14.7.1.1 LoopContinues ( completion ,
labelSet )
抽象操作 LoopContinues 接受参数 completion (一个完成记录 )
和 labelSet (一个列表 ,包含字符串),并返回一个布尔值。调用时执行以下步骤:
如果 completion 是正常完成 ,返回
true 。
如果 completion 不是continue
完成 ,返回 false 。
如果 completion .[[Target]] 是
empty ,返回 true 。
如果 labelSet 包含 completion .[[Target]] ,返回 true 。
返回 false 。
注
14.7.1.2 运行时语义:LoopEvaluation
语法制导操作
LoopEvaluation 接受参数 labelSet (一个列表 ,包含字符串),并返回包含 ECMAScript 语言值 的正常完成或突然完成 。它在以下产生式上分段定义:
IterationStatement
: DoWhileStatement
返回 ? DoWhileStatement 以参数
labelSet 进行的 DoWhileLoopEvaluation 。
IterationStatement
: WhileStatement
返回 ? WhileStatement 以参数
labelSet 进行的 WhileLoopEvaluation 。
IterationStatement
: ForStatement
返回 ? ForStatement 以参数 labelSet
进行的 ForLoopEvaluation 。
IterationStatement
: ForInOfStatement
返回 ? ForInOfStatement 以参数
labelSet 进行的 ForInOfLoopEvaluation 。
14.7.2 do
-while
语句
语法
DoWhileStatement [Yield,
Await, Return] :
do
Statement [?Yield, ?Await,
?Return]
while
(
Expression [+In, ?Yield,
?Await]
)
;
14.7.2.1 静态语义:早期错误
DoWhileStatement
:
do
Statement
while
(
Expression
)
;
注
只有在实现B.3.1
中指定的扩展时,才需要应用此规则。
14.7.2.2 运行时语义:DoWhileLoopEvaluation
语法制导操作
DoWhileLoopEvaluation 接受参数 labelSet (一个列表 ,包含字符串),并返回包含 ECMAScript 语言值 的正常完成或突然完成 。它在以下产生式上分段定义:
DoWhileStatement
:
do
Statement
while
(
Expression
)
;
令 V 为 undefined 。
重复,
令 stmtResult 为 Completion (Statement 的
Evaluation )。
如果 LoopContinues (stmtResult ,
labelSet ) 是 false ,返回 ? UpdateEmpty (stmtResult ,
V )。
如果 stmtResult .[[Value]] 不是
empty ,设置 V 为 stmtResult .[[Value]] 。
令 exprRef 为 ? Expression 的 Evaluation 。
令 exprValue 为 ? GetValue (exprRef )。
如果 ToBoolean (exprValue )
是 false ,返回 V 。
14.7.3 while
语句
语法
WhileStatement [Yield, Await,
Return] :
while
(
Expression [+In, ?Yield,
?Await]
)
Statement [?Yield, ?Await,
?Return]
14.7.3.1 静态语义:早期错误
WhileStatement :
while
(
Expression
)
Statement
注
只有在实现B.3.1
中指定的扩展时,才需要应用此规则。
14.7.3.2 运行时语义:WhileLoopEvaluation
语法制导操作
WhileLoopEvaluation 接受参数 labelSet (一个列表 ,包含字符串),并返回包含 ECMAScript 语言值 的正常完成或突然完成 。它在以下产生式上分段定义:
WhileStatement :
while
(
Expression
)
Statement
令 V 为 undefined 。
重复,
令 exprRef 为 ? Expression 的 Evaluation 。
令 exprValue 为 ? GetValue (exprRef )。
如果 ToBoolean (exprValue )
是 false ,返回 V 。
令 stmtResult 为 Completion (Statement 的
Evaluation )。
如果 LoopContinues (stmtResult ,
labelSet ) 是 false ,返回 ? UpdateEmpty (stmtResult ,
V )。
如果 stmtResult .[[Value]] 不是
empty ,设置 V 为 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 静态语义:早期错误
ForStatement :
for
(
Expression opt
;
Expression opt
;
Expression opt
)
Statement
for
(
var
VariableDeclarationList
;
Expression opt
;
Expression opt
)
Statement
for
(
LexicalDeclaration
Expression opt
;
Expression opt
)
Statement
注
只有在实现B.3.1
中指定的扩展时,才需要应用此规则。
ForStatement :
for
(
LexicalDeclaration
Expression opt
;
Expression opt
)
Statement
14.7.4.2 运行时语义:ForLoopEvaluation
语法制导操作
ForLoopEvaluation 接受参数 labelSet (一个列表 ,包含字符串),并返回包含 ECMAScript 语言值 的正常完成或突然完成 。它在以下产生式上分段定义:
ForStatement :
for
(
Expression opt
;
Expression opt
;
Expression opt
)
Statement
如果第一个 Expression
存在,则
令 exprRef 为 ? 第一个 Expression 的 Evaluation 。
执行 ? GetValue (exprRef )。
如果第二个 Expression
存在,令
test 为第二个 Expression ;否则,令
test 为 empty 。
如果第三个 Expression
存在,令
increment 为第三个 Expression ;否则,令
increment 为 empty 。
返回 ? ForBodyEvaluation (test ,
increment ,Statement ,« »,
labelSet )。
ForStatement :
for
(
var
VariableDeclarationList
;
Expression opt
;
Expression opt
)
Statement
执行 ? VariableDeclarationList 的
Evaluation 。
如果第一个 Expression
存在,令
test 为第一个 Expression ;否则,令
test 为 empty 。
如果第二个 Expression
存在,令
increment 为第二个 Expression ;否则,令
increment 为 empty 。
返回 ? ForBodyEvaluation (test ,
increment ,Statement ,« »,
labelSet )。
ForStatement :
for
(
LexicalDeclaration
Expression opt
;
Expression opt
)
Statement
令 oldEnv 为运行中执行上下文 的
LexicalEnvironment。
令 loopEnv 为 NewDeclarativeEnvironment (oldEnv )。
令 isConst 为 LexicalDeclaration 的 IsConstantDeclaration 。
令 boundNames 为 LexicalDeclaration 的 BoundNames 。
对 boundNames 的每个元素 dn ,执行
如果 isConst 是 true ,则
执行
! loopEnv .CreateImmutableBinding(dn ,
true )。
否则,
执行
! loopEnv .CreateMutableBinding(dn ,
false )。
设置运行中执行上下文 的
LexicalEnvironment 为 loopEnv 。
令 forDcl 为 Completion (LexicalDeclaration 的 Evaluation )。
如果 forDcl 是突然完成 ,则
设置运行中执行上下文 的
LexicalEnvironment 为 oldEnv 。
返回 ? forDcl 。
如果 isConst 是 false ,令 perIterationLets
为 boundNames ;否则令 perIterationLets 为新的空列表 。
如果第一个 Expression
存在,令
test 为第一个 Expression ;否则,令
test 为 empty 。
如果第二个 Expression
存在,令
increment 为第二个 Expression ;否则,令
increment 为 empty 。
令 bodyResult 为 Completion (ForBodyEvaluation (test ,
increment ,Statement ,perIterationLets ,
labelSet ))。
设置运行中执行上下文 的
LexicalEnvironment 为 oldEnv 。
返回 ? bodyResult 。
14.7.4.3 ForBodyEvaluation ( test ,
increment , stmt , perIterationBindings , labelSet
)
抽象操作 ForBodyEvaluation 接受参数 test (一个 Expression 解析节点 或
empty )、increment (一个
Expression 解析节点 或
empty )、stmt (一个 Statement 解析节点 )、perIterationBindings (一个列表 ,包含字符串)和
labelSet (一个列表 ,包含字符串),并返回包含 ECMAScript 语言值 的正常完成或突然完成 。调用时执行以下步骤:
令 V 为 undefined 。
执行 ? CreatePerIterationEnvironment (perIterationBindings )。
重复,
如果 test 不是 empty ,则
令 testRef 为 ? test 的 Evaluation 。
令 testValue 为 ? GetValue (testRef )。
如果 ToBoolean (testValue )
是 false ,返回 V 。
令 result 为 Completion (stmt
的 Evaluation )。
如果 LoopContinues (result ,
labelSet ) 是 false ,返回 ? UpdateEmpty (result ,
V )。
如果 result .[[Value]] 不是
empty ,设置 V 为 result .[[Value]] 。
执行 ? CreatePerIterationEnvironment (perIterationBindings )。
如果 increment 不是 empty ,则
令 incRef 为 ? increment 的 Evaluation 。
执行 ? GetValue (incRef )。
14.7.4.4 CreatePerIterationEnvironment (
perIterationBindings )
抽象操作 CreatePerIterationEnvironment 接受参数
perIterationBindings (一个列表 ,包含字符串),并返回包含
unused 的正常完成或throw 完成 。调用时执行以下步骤:
如果 perIterationBindings 有任何元素,则
令 lastIterationEnv 为运行中执行上下文 的
LexicalEnvironment。
令 outer 为 lastIterationEnv .[[OuterEnv]] 。
断言 :outer 不是
null 。
令 thisIterationEnv 为 NewDeclarativeEnvironment (outer )。
对 perIterationBindings 的每个元素 bn ,执行
执行
! thisIterationEnv .CreateMutableBinding(bn ,
false )。
令 lastValue 为
? lastIterationEnv .GetBindingValue(bn ,
true )。
执行
! thisIterationEnv .InitializeBinding(bn ,
lastValue )。
设置运行中执行上下文 的
LexicalEnvironment 为
thisIterationEnv 。
返回 unused 。
14.7.5 for
-in
、
for
-of
和 for
-await
-of
语句
语法
ForInOfStatement [Yield,
Await, Return] :
for
(
[lookahead ≠ let
[ ]
LeftHandSideExpression [?Yield,
?Await]
in
Expression [+In, ?Yield,
?Await]
)
Statement [?Yield, ?Await,
?Return]
for
(
var
ForBinding [?Yield,
?Await]
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]
注
14.7.5.1 静态语义:早期错误
ForInOfStatement
:
for
(
LeftHandSideExpression
in
Expression
)
Statement
for
(
var
ForBinding
in
Expression
)
Statement
for
(
ForDeclaration
in
Expression
)
Statement
for
(
LeftHandSideExpression
of
AssignmentExpression
)
Statement
for
(
var
ForBinding
of
AssignmentExpression
)
Statement
for
(
ForDeclaration
of
AssignmentExpression
)
Statement
for
await
(
LeftHandSideExpression
of
AssignmentExpression
)
Statement
for
await
(
var
ForBinding
of
AssignmentExpression
)
Statement
for
await
(
ForDeclaration
of
AssignmentExpression
)
Statement
注
只有在实现B.3.1
中指定的扩展时,才需要应用此规则。
ForInOfStatement
:
for
(
LeftHandSideExpression
in
Expression
)
Statement
for
(
LeftHandSideExpression
of
AssignmentExpression
)
Statement
for
await
(
LeftHandSideExpression
of
AssignmentExpression
)
Statement
ForInOfStatement
:
for
(
ForDeclaration
in
Expression
)
Statement
for
(
ForDeclaration
of
AssignmentExpression
)
Statement
for
await
(
ForDeclaration
of
AssignmentExpression
)
Statement
14.7.5.2 静态语义:IsDestructuring
语法制导操作
IsDestructuring 不接受参数并返回布尔值。它在以下产生式上分段定义:
MemberExpression
: PrimaryExpression
如果 PrimaryExpression 是
ObjectLiteral 或
ArrayLiteral ,
返回 true 。
返回 false 。
MemberExpression
:
MemberExpression
[
Expression
]
MemberExpression
.
IdentifierName
MemberExpression
TemplateLiteral
SuperProperty
MetaProperty
new
MemberExpression
Arguments
MemberExpression
.
PrivateIdentifier
NewExpression :
new
NewExpression
LeftHandSideExpression
:
CallExpression
OptionalExpression
返回 false 。
ForDeclaration :
LetOrConst
ForBinding
返回 ForBinding 的
IsDestructuring 。
ForBinding : BindingIdentifier
返回 false 。
ForBinding : BindingPattern
返回 true 。
注
14.7.5.3 运行时语义:ForDeclarationBindingInitialization
语法制导操作
ForDeclarationBindingInitialization 接受参数
value (一个ECMAScript 语言值 )和
environment (一个环境记录 或
undefined ),并返回包含
unused 的正常完成或突然完成 。
注
传递 undefined 作为 environment 表示应该使用 PutValue
操作来分配初始化值。这是 var
语句和某些非严格函数 的形式参数列表的情况(见10.2.11 )。在这些情况下,词法绑定被提升并在其初始化程序求值之前预初始化。
它在以下产生式上分段定义:
ForDeclaration :
LetOrConst
ForBinding
返回 ? ForBinding
以参数 value 和 environment 进行的 BindingInitialization 。
14.7.5.4 运行时语义:ForDeclarationBindingInstantiation
语法制导操作
ForDeclarationBindingInstantiation 接受参数
environment (一个声明式环境记录 )并返回
unused 。它在以下产生式上分段定义:
ForDeclaration :
LetOrConst
ForBinding
对 ForBinding 的
BoundNames 的每个元素
name ,执行
如果 LetOrConst 的 IsConstantDeclaration
是 true ,则
执行
! environment .CreateImmutableBinding(name ,
true )。
否则,
执行
! environment .CreateMutableBinding(name ,
false )。
返回 unused 。
14.7.5.5 运行时语义:ForInOfLoopEvaluation
语法制导操作
ForInOfLoopEvaluation 接受参数 labelSet (一个包含字符串的列表 ),并返回包含 ECMAScript 语言值 的正常完成或突然完成 。它在以下产生式上分段定义:
ForInOfStatement
:
for
(
LeftHandSideExpression
in
Expression
)
Statement
令 keyResult 为 ? ForIn/OfHeadEvaluation (« », Expression ,
enumerate )。
返回 ? ForIn/OfBodyEvaluation (LeftHandSideExpression ,
Statement ,
keyResult , enumerate ,
assignment , labelSet )。
ForInOfStatement
:
for
(
var
ForBinding
in
Expression
)
Statement
令 keyResult 为 ? ForIn/OfHeadEvaluation (« », Expression ,
enumerate )。
返回 ? ForIn/OfBodyEvaluation (ForBinding , Statement ,
keyResult , enumerate ,
var-binding , labelSet )。
ForInOfStatement
:
for
(
ForDeclaration
in
Expression
)
Statement
令 keyResult 为 ? ForIn/OfHeadEvaluation (ForDeclaration 的
BoundNames ,
Expression ,
enumerate )。
返回 ? ForIn/OfBodyEvaluation (ForDeclaration ,
Statement ,
keyResult , enumerate ,
lexical-binding , labelSet )。
ForInOfStatement
:
for
(
LeftHandSideExpression
of
AssignmentExpression
)
Statement
令 keyResult 为 ? ForIn/OfHeadEvaluation (« », AssignmentExpression ,
iterate )。
返回 ? ForIn/OfBodyEvaluation (LeftHandSideExpression ,
Statement ,
keyResult , iterate ,
assignment , labelSet )。
ForInOfStatement
:
for
(
var
ForBinding
of
AssignmentExpression
)
Statement
令 keyResult 为 ? ForIn/OfHeadEvaluation (« », AssignmentExpression ,
iterate )。
返回 ? ForIn/OfBodyEvaluation (ForBinding , Statement ,
keyResult , iterate ,
var-binding , labelSet )。
ForInOfStatement
:
for
(
ForDeclaration
of
AssignmentExpression
)
Statement
令 keyResult 为 ? ForIn/OfHeadEvaluation (ForDeclaration 的
BoundNames ,
AssignmentExpression ,
iterate )。
返回 ? ForIn/OfBodyEvaluation (ForDeclaration ,
Statement ,
keyResult , iterate ,
lexical-binding , labelSet )。
ForInOfStatement
:
for
await
(
LeftHandSideExpression
of
AssignmentExpression
)
Statement
令 keyResult 为 ? ForIn/OfHeadEvaluation (« », AssignmentExpression ,
async-iterate )。
返回 ? ForIn/OfBodyEvaluation (LeftHandSideExpression ,
Statement ,
keyResult , iterate ,
assignment , labelSet ,
async )。
ForInOfStatement
:
for
await
(
var
ForBinding
of
AssignmentExpression
)
Statement
令 keyResult 为 ? ForIn/OfHeadEvaluation (« », AssignmentExpression ,
async-iterate )。
返回 ? ForIn/OfBodyEvaluation (ForBinding , Statement ,
keyResult , iterate ,
var-binding , labelSet ,
async )。
ForInOfStatement
:
for
await
(
ForDeclaration
of
AssignmentExpression
)
Statement
令 keyResult 为 ? ForIn/OfHeadEvaluation (ForDeclaration 的
BoundNames ,
AssignmentExpression ,
async-iterate )。
返回 ? ForIn/OfBodyEvaluation (ForDeclaration ,
Statement ,
keyResult , iterate ,
lexical-binding , labelSet ,
async )。
注
14.7.5.6 ForIn/OfHeadEvaluation (
uninitializedBoundNames , expr , iterationKind )
抽象操作 ForIn/OfHeadEvaluation 接受参数
uninitializedBoundNames (一个包含字符串的列表 )、
expr (一个 Expression 解析节点 或一个 AssignmentExpression 解析节点 ),以及
iterationKind (enumerate 、iterate 或
async-iterate ),并返回包含 迭代器记录 的正常完成或突然完成 。它在被调用时执行以下步骤:
令 oldEnv 为运行执行上下文 的
LexicalEnvironment。
如果 uninitializedBoundNames 不为空,则
断言 :
uninitializedBoundNames 没有重复的条目。
令 newEnv 为 NewDeclarativeEnvironment (oldEnv )。
对 uninitializedBoundNames 的每个字符串 name ,执行
执行
! newEnv .CreateMutableBinding(name ,
false )。
设置运行执行上下文 的
LexicalEnvironment 为 newEnv 。
令 exprRef 为 Completion (Evaluation of expr )。
设置运行执行上下文 的 LexicalEnvironment
为 oldEnv 。
令 exprValue 为 ? GetValue (?
exprRef )。
如果 iterationKind 是 enumerate ,则
如果 exprValue 是 undefined 或
null ,则
返回 完成记录
{ [[Type]] :
break , [[Value]] :
empty , [[Target]] :
empty }。
令 obj 为 ! ToObject (exprValue )。
令 iterator 为 EnumerateObjectProperties (obj )。
令 nextMethod 为 ! GetV (iterator ,
"next" )。
返回迭代器记录 { [[Iterator]] : iterator , [[NextMethod]] : nextMethod , [[Done]] : false }。
否则,
断言 :
iterationKind 是
iterate 或
async-iterate 。
如果 iterationKind 是 async-iterate ,令
iteratorKind 为 async 。
否则,令 iteratorKind 为 sync 。
返回 ? GetIterator (exprValue ,
iteratorKind )。
14.7.5.7 ForIn/OfBodyEvaluation ( lhs ,
stmt , iteratorRecord , iterationKind , lhsKind ,
labelSet [ , iteratorKind ] )
抽象操作 ForIn/OfBodyEvaluation 接受参数 lhs (一个解析节点 )、stmt (一个
Statement 解析节点 )、iteratorRecord (一个迭代器记录 )、iterationKind (enumerate
或
iterate )、lhsKind (assignment 、var-binding
或 lexical-binding )、labelSet (一个包含字符串的列表 )以及可选参数
iteratorKind (sync 或
async ),并返回包含 ECMAScript 语言值 的正常完成或突然完成 。它在被调用时执行以下步骤:
如果 iteratorKind 不存在,设置 iteratorKind 为
sync 。
令 oldEnv 为运行执行上下文 的
LexicalEnvironment。
令 V 为 undefined 。
令 destructuring 为 lhs 的 IsDestructuring 。
如果 destructuring 是 true 且 lhsKind 是
assignment ,则
断言 :
lhs 是一个 LeftHandSideExpression 。
令 assignmentPattern 为被 lhs 覆盖 的 AssignmentPattern 。
重复,
令 nextResult 为 ? Call (iteratorRecord .[[NextMethod]] , iteratorRecord .[[Iterator]] )。
如果 iteratorKind 是 async ,设置
nextResult 为 ? Await (nextResult )。
如果 nextResult 不是对象 ,抛出
TypeError 异常。
令 done 为 ? IteratorComplete (nextResult )。
如果 done 是 true ,返回 V 。
令 nextValue 为 ? IteratorValue (nextResult )。
如果 lhsKind 是 assignment 或
var-binding ,则
如果 destructuring 是 true ,则
如果 lhsKind 是 assignment ,
则
令 status 为 Completion (以参数
nextValue 对 assignmentPattern
进行的 DestructuringAssignmentEvaluation )。
否则,
断言 :
lhsKind 是
var-binding 。
断言 :
lhs 是一个 ForBinding 。
令 status 为 Completion (以参数
nextValue 和
undefined 对 lhs 进行的
BindingInitialization )。
否则,
令 lhsRef 为 Completion (Evaluation of
lhs )。(它可能被重复求值。)
如果 lhsRef 是突然完成 ,则
令 status 为 lhsRef 。
否则,
令 status 为 Completion (PutValue (lhsRef .[[Value]] ,
nextValue ))。
否则,
断言 :lhsKind 是
lexical-binding 。
断言 :lhs 是一个
ForDeclaration 。
令 iterationEnv 为 NewDeclarativeEnvironment (oldEnv )。
以参数 iterationEnv 对 lhs 执行 ForDeclarationBindingInstantiation 。
设置运行执行上下文 的
LexicalEnvironment 为
iterationEnv 。
如果 destructuring 是 true ,则
令 status 为 Completion (以参数
nextValue 和
iterationEnv 对 lhs 进行的 ForDeclarationBindingInitialization )。
否则,
断言 :lhs
绑定单个名称。
令 lhsName 为 lhs 的 BoundNames
的唯一元素。
令 lhsRef 为 ! ResolveBinding (lhsName )。
令 status 为 Completion (InitializeReferencedBinding (lhsRef ,
nextValue ))。
如果 status 是突然完成 ,则
设置运行执行上下文 的
LexicalEnvironment 为
oldEnv 。
如果 iteratorKind 是 async ,返回
? AsyncIteratorClose (iteratorRecord ,
status )。
如果 iterationKind 是 enumerate ,
则
返回 ? status 。
否则,
断言 :
iterationKind 是 iterate 。
返回 ? IteratorClose (iteratorRecord ,
status )。
令 result 为 Completion (Evaluation of stmt )。
设置运行执行上下文 的
LexicalEnvironment 为 oldEnv 。
如果 LoopContinues (result ,
labelSet ) 是 false ,则
如果 iterationKind 是 enumerate ,
则
返回 ? UpdateEmpty (result ,
V )。
否则,
断言 :
iterationKind 是 iterate 。
设置 status 为 Completion (UpdateEmpty (result ,
V ))。
如果 iteratorKind 是 async ,
返回 ? AsyncIteratorClose (iteratorRecord ,
status )。
返回 ? IteratorClose (iteratorRecord ,
status )。
如果 result .[[Value]] 不是
empty ,设置 V 为 result .[[Value]] 。
14.7.5.8 运行时语义:Evaluation
BindingIdentifier
:
Identifier
yield
await
令 bindingId 为 BindingIdentifier 的 StringValue 。
返回 ? ResolveBinding (bindingId )。
14.7.5.9 EnumerateObjectProperties ( O )
抽象操作 EnumerateObjectProperties 接受参数 O (一个对象),并返回一个迭代器对象 。它在被调用时执行以下步骤:
返回一个迭代器对象 ,其
next
方法遍历 O 的所有可枚举属性的字符串值键。该迭代器对象 永远不能直接被 ECMAScript
代码访问。枚举属性的机制和顺序没有指定,但必须符合下面指定的规则。
迭代器 的 throw
和
return
方法是 null 且永远不会被调用。迭代器 的 next
方法处理对象属性以确定属性键 是否应该作为迭代器 值返回。返回的属性键 不包括 Symbol
键。目标对象的属性可能在枚举期间被删除。在被迭代器 的 next
方法处理之前被删除的属性将被忽略。如果在枚举期间向目标对象添加新属性,则不保证新添加的属性会在活跃的枚举中被处理。属性名 在任何枚举中最多被迭代器 的
next
方法返回一次。
枚举目标对象的属性包括枚举其原型的属性,以及原型的原型,依此类推,递归进行;但如果原型的属性与已经被迭代器 的 next
方法处理过的属性同名,则该原型属性不会被处理。在确定原型对象的属性是否已被处理时,不考虑 [[Enumerable]]
特性的值。原型对象的可枚举属性名必须通过调用 EnumerateObjectProperties 并传递原型对象作为参数来获得。EnumerateObjectProperties
必须通过调用目标对象的 [[OwnPropertyKeys]] 内部方法来获得目标对象的自有属性键 。目标对象的属性特性必须通过调用其 [[GetOwnProperty]]
内部方法来获得。
此外,如果 O 或其原型链中的任何对象都不是代理异质对象 、TypedArray 、模块命名空间异质对象 或实现提供的异质对象 ,则迭代器 必须表现得如同由 CreateForInIterator (O )
给出的迭代器 一样,直到发生以下情况之一:
O 或其原型链中对象的 [[Prototype]] 内部槽的值发生变化,
从 O 或其原型链中的对象删除了一个属性,
向 O 的原型链中的对象添加了一个属性,或
O 或其原型链中对象的属性的 [[Enumerable]] 特性值发生变化。
注 1
ECMAScript 实现不需要直接实现14.7.5.10.2.1
中的算法。它们可以选择任何实现,只要其行为不偏离该算法,除非违反了上一段中的约束之一。
以下是符合这些规则的 ECMAScript 生成器函数的信息性定义:
function * EnumerateObjectProperties (obj) {
const visited = new Set ();
for (const key of Reflect .ownKeys (obj)) {
if (typeof key === "symbol" ) continue ;
const desc = Reflect .getOwnPropertyDescriptor (obj, key);
if (desc) {
visited.add (key);
if (desc.enumerable ) yield key;
}
}
const proto = Reflect .getPrototypeOf (obj);
if (proto === null ) return ;
for (const protoKey of EnumerateObjectProperties (proto)) {
if (!visited.has (protoKey)) yield protoKey;
}
}
注 2
选择不要求实现匹配
CreateForInIterator 的
异质对象 列表,是因为历史上实现在这些情况下的行为有所不同,而在所有其他情况下是一致的。
14.7.5.10 For-In 迭代器对象
For-In
迭代器 是表示对某个特定对象进行特定迭代的对象。For-In 迭代器对象永远不能直接被 ECMAScript 代码访问;它们只是为了说明 EnumerateObjectProperties
的行为而存在。
14.7.5.10.1 CreateForInIterator ( object )
抽象操作 CreateForInIterator 接受参数 object (一个对象),并返回一个 For-In 迭代器 。它用于创建一个 For-In 迭代器对象 ,该对象以特定顺序遍历
object 的自有和继承的可枚举字符串属性。它在被调用时执行以下步骤:
令 iterator 为 OrdinaryObjectCreate (%ForInIteratorPrototype% ,
« [[Object]] , [[ObjectWasVisited]] , [[VisitedKeys]] , [[RemainingKeys]] »)。
设置 iterator .[[Object]] 为
object 。
设置 iterator .[[ObjectWasVisited]] 为
false 。
设置 iterator .[[VisitedKeys]] 为一个新的空列表 。
设置 iterator .[[RemainingKeys]]
为一个新的空列表 。
返回 iterator 。
14.7.5.10.2 %ForInIteratorPrototype% 对象
%ForInIteratorPrototype% 对象:
14.7.5.10.2.1 %ForInIteratorPrototype%.next ( )
令 O 为 this 值。
断言 :
O 是对象 。
断言 :
O 具有 For-In
迭代器 实例的所有内部槽(14.7.5.10.3 )。
令 object 为 O .[[Object]] 。
重复,
如果 O .[[ObjectWasVisited]] 是
false ,则
令 keys 为 ? object .[[OwnPropertyKeys]] () 。
对 keys 的每个元素 key ,执行
如果 key 是字符串 ,则
将 key 追加到 O .[[RemainingKeys]] 。
设置 O .[[ObjectWasVisited]]
为
true 。
重复,当 O .[[RemainingKeys]] 不为空时,
令 r 为 O .[[RemainingKeys]] 的第一个元素。
从 O .[[RemainingKeys]]
中移除第一个元素。
如果 O .[[VisitedKeys]]
不包含 r ,则
令 desc 为 ? object .[[GetOwnProperty]] (r )。
如果 desc 不是
undefined ,则
将 r 追加到 O .[[VisitedKeys]] 。
如果 desc .[[Enumerable]] 是
true ,返回 CreateIteratorResultObject (r ,
false )。
设置 object 为 ? object .[[GetPrototypeOf]] () 。
设置 O .[[Object]] 为
object 。
设置 O .[[ObjectWasVisited]] 为
false 。
如果 object 是 null ,返回 CreateIteratorResultObject (undefined ,
true )。
14.7.5.10.3 For-In 迭代器实例的属性
For-In 迭代器 实例是普通对象 ,它们从 %ForInIteratorPrototype%
内在对象继承属性。For-In 迭代器 实例最初使用 表 38 中列出的内部槽创建。
表 38:For-In 迭代器 实例的内部槽
内部槽
类型
描述
[[Object]]
一个对象
正在迭代其属性的对象值。
[[ObjectWasVisited]]
一个布尔值
如果迭代器 已在 [[Object]] 上调用了 [[OwnPropertyKeys]] ,则为
true ,否则为 false 。
[[VisitedKeys]]
一个包含字符串的列表
到目前为止已被此迭代器 发出的值。
[[RemainingKeys]]
一个包含字符串的列表
在迭代其原型的属性之前(如果其原型不是 null ),当前对象剩余要发出的值。
14.8 continue
语句
语法
ContinueStatement [Yield,
Await] :
continue
;
continue
[no LineTerminator
here]
LabelIdentifier [?Yield,
?Await]
;
14.8.1 静态语义:早期错误
ContinueStatement
:
continue
;
continue
LabelIdentifier
;
14.8.2 运行时语义:Evaluation
ContinueStatement
:
continue
;
返回 完成记录 { [[Type]] :
continue , [[Value]] :
empty , [[Target]] :
empty }。
ContinueStatement
:
continue
LabelIdentifier
;
令 label 为 LabelIdentifier 的 StringValue 。
返回 完成记录 { [[Type]] :
continue , [[Value]] :
empty , [[Target]] :
label }。
14.9 break
语句
语法
BreakStatement [Yield,
Await] :
break
;
break
[no LineTerminator
here]
LabelIdentifier [?Yield,
?Await]
;
14.9.1 静态语义:早期错误
BreakStatement :
break
;
14.9.2 运行时语义:Evaluation
BreakStatement :
break
;
返回 完成记录 { [[Type]] :
break , [[Value]] :
empty , [[Target]] :
empty }。
BreakStatement :
break
LabelIdentifier
;
令 label 为 LabelIdentifier 的 StringValue 。
返回 完成记录 { [[Type]] :
break , [[Value]] :
empty , [[Target]] :
label }。
14.10 return
语句
语法
ReturnStatement [Yield,
Await] :
return
;
return
[no LineTerminator
here]
Expression [+In, ?Yield,
?Await]
;
注
return
语句使函数停止执行,并且在大多数情况下将值返回给调用者。如果省略了 Expression ,则返回值是
undefined 。否则,返回值是 Expression 的值。根据周围的上下文,return
语句可能实际上不会将值返回给调用者。例如,在 try
块中,return
语句的完成记录 可能在对
finally
块进行求值期间被另一个完成记录 替换。
14.10.1 运行时语义:Evaluation
ReturnStatement :
return
;
返回 ReturnCompletion (undefined )。
ReturnStatement :
return
Expression
;
令 exprRef 为 ? Evaluation of Expression 。
令 exprValue 为 ? GetValue (exprRef )。
如果 GetGeneratorKind () 是
async ,设置 exprValue 为 ? Await (exprValue )。
返回 ReturnCompletion (exprValue )。
14.11 with
语句
注 1
不鼓励在新的 ECMAScript 代码中使用Legacy with
语句。考虑在严格模式代码 和非严格代码 中都允许的替代方案,例如解构赋值 。
语法
WithStatement [Yield, Await,
Return] :
with
(
Expression [+In, ?Yield,
?Await]
)
Statement [?Yield, ?Await,
?Return]
注 2
with
语句将计算对象的对象环境记录 添加到运行执行上下文 的词法环境中。然后使用这个增强的词法环境执行语句。最后,恢复原始的词法环境。
14.11.1 静态语义:早期错误
WithStatement :
with
(
Expression
)
Statement
注
只有在实现了B.3.1
中指定的扩展时,才需要应用第二条规则。
14.11.2 运行时语义:Evaluation
WithStatement :
with
(
Expression
)
Statement
令 val 为 ? Evaluation of Expression 。
令 obj 为 ? ToObject (? GetValue (val ))。
令 oldEnv 为运行执行上下文 的 LexicalEnvironment。
令 newEnv 为 NewObjectEnvironment (obj ,
true , oldEnv )。
设置运行执行上下文 的
LexicalEnvironment 为 newEnv 。
令 C 为 Completion (Evaluation
of Statement )。
设置运行执行上下文 的
LexicalEnvironment 为 oldEnv 。
返回 ? UpdateEmpty (C ,
undefined )。
注
无论控制如何离开嵌入的 Statement ,无论是正常方式还是通过某种形式的突然完成 或异常,LexicalEnvironment
总是恢复到其原来的状态。
14.12 switch
语句
语法
SwitchStatement [Yield, Await,
Return] :
switch
(
Expression [+In, ?Yield,
?Await]
)
CaseBlock [?Yield, ?Await,
?Return]
CaseBlock [Yield, Await,
Return] :
{
CaseClauses [?Yield, ?Await,
?Return] opt
}
{
CaseClauses [?Yield, ?Await,
?Return] opt
DefaultClause [?Yield, ?Await,
?Return]
CaseClauses [?Yield, ?Await,
?Return] opt
}
CaseClauses [Yield, Await,
Return] :
CaseClause [?Yield, ?Await,
?Return]
CaseClauses [?Yield, ?Await,
?Return]
CaseClause [?Yield, ?Await,
?Return]
CaseClause [Yield, Await,
Return] :
case
Expression [+In, ?Yield,
?Await]
:
StatementList [?Yield, ?Await,
?Return] opt
DefaultClause [Yield, Await,
Return] :
default
:
StatementList [?Yield, ?Await,
?Return] opt
14.12.1 静态语义:早期错误
SwitchStatement :
switch
(
Expression
)
CaseBlock
14.12.2 运行时语义:CaseBlockEvaluation
语法制导操作
CaseBlockEvaluation 接受参数 input (一个
ECMAScript 语言值 )并
返回一个 包含 ECMAScript 语言值 的 正常完成 或 突然完成 。它按以下产生式分段定义:
CaseBlock :
{
}
返回 undefined 。
CaseBlock :
{
CaseClauses
}
令 V 为 undefined 。
令 A 为 CaseClauses 中按源文本顺序排列的 CaseClause 项的 列表 。
令 found 为 false 。
对于 A 中的每个 CaseClause
C ,执行
如果 found 是 false ,则
设置 found 为 ? CaseClauseIsSelected (C ,
input )。
如果 found 是 true ,则
令 R 为 Completion (Evaluation of C )。
如果 R .[[Value]] 不是
empty ,设置 V 为 R .[[Value]] 。
如果 R 是 突然完成 ,返回
? UpdateEmpty (R ,
V )。
返回 V 。
CaseBlock :
{
CaseClauses opt
DefaultClause
CaseClauses opt
}
令 V 为 undefined 。
如果第一个 CaseClauses 存在,则
令 A 为第一个 CaseClauses 中按源文本顺序排列的 CaseClause 项的
列表 。
否则,
令 A 为一个新的空 列表 。
令 found 为 false 。
对于 A 中的每个 CaseClause
C ,执行
如果 found 是 false ,则
设置 found 为 ? CaseClauseIsSelected (C ,
input )。
如果 found 是 true ,则
令 R 为 Completion (Evaluation of C )。
如果 R .[[Value]] 不是
empty ,设置 V 为 R .[[Value]] 。
如果 R 是 突然完成 ,返回
? UpdateEmpty (R ,
V )。
令 foundInB 为 false 。
如果第二个 CaseClauses
存在,则
令 B 为第二个 CaseClauses 中按源文本顺序排列的 CaseClause 项的
列表 。
否则,
令 B 为一个新的空 列表 。
如果 found 是 false ,则
对于 B 中的每个 CaseClause
C ,执行
如果 foundInB 是 false ,则
设置 foundInB 为 ? CaseClauseIsSelected (C ,
input )。
如果 foundInB 是 true ,则
令 R 为 Completion (Evaluation of CaseClause
C )。
如果 R .[[Value]] 不是
empty ,设置 V 为
R .[[Value]] 。
如果 R 是 突然完成 ,返回
? UpdateEmpty (R ,
V )。
如果 foundInB 是 true ,返回 V 。
令 defaultR 为 Completion (Evaluation
of DefaultClause )。
如果 defaultR .[[Value]] 不是
empty ,设置 V 为 defaultR .[[Value]] 。
如果 defaultR 是 突然完成 ,返回
? UpdateEmpty (defaultR ,
V )。
注:以下是对第二个 CaseClauses
的另一次完整迭代。
对于 B 中的每个 CaseClause
C ,执行
令 R 为 Completion (Evaluation of CaseClause
C )。
如果 R .[[Value]] 不是
empty ,设置 V 为 R .[[Value]] 。
如果 R 是 突然完成 ,返回
? UpdateEmpty (R ,
V )。
返回 V 。
14.12.3 CaseClauseIsSelected ( C , input )
抽象操作 CaseClauseIsSelected 接受参数 C (一个 CaseClause 解析节点 )和 input (一个
ECMAScript 语言值 )并
返回一个 包含 Boolean 的 正常完成 或 突然完成 。它
确定 C 是否匹配 input 。调用时执行以下步骤:
断言 :
C 是产生式
CaseClause :
case
Expression
:
StatementList opt
的实例。
令 exprRef 为 ? Evaluation of
C 的 Expression 。
令 clauseSelector 为 ? GetValue (exprRef )。
返回 IsStrictlyEqual (input ,
clauseSelector )。
注
此操作不执行 C 的 StatementList (如果有)。CaseBlock 算法使用其
返回值来确定从哪个 StatementList 开始执行。
14.12.4 运行时语义:Evaluation
SwitchStatement :
switch
(
Expression
)
CaseBlock
令 exprRef 为 ? Evaluation of Expression 。
令 switchValue 为 ? GetValue (exprRef )。
令 oldEnv 为 运行执行上下文 的 LexicalEnvironment。
令 blockEnv 为 NewDeclarativeEnvironment (oldEnv )。
执行 BlockDeclarationInstantiation (CaseBlock ,
blockEnv )。
设置 运行执行上下文 的
LexicalEnvironment 为 blockEnv 。
令 R 为 Completion (CaseBlockEvaluation of CaseBlock with argument
switchValue )。
设置 运行执行上下文 的
LexicalEnvironment 为 oldEnv 。
返回 R 。
注
无论控制如何离开 SwitchStatement ,LexicalEnvironment
总是恢复到之前的状态。
CaseClause :
case
Expression
:
返回 empty 。
CaseClause :
case
Expression
:
StatementList
返回 ? Evaluation of StatementList 。
DefaultClause :
default
:
返回 empty 。
DefaultClause :
default
:
StatementList
返回 ? Evaluation of StatementList 。
14.13 标签语句
语法
LabelledStatement [Yield, Await,
Return] :
LabelIdentifier [?Yield,
?Await]
:
LabelledItem [?Yield, ?Await,
?Return]
LabelledItem [Yield, Await,
Return] :
Statement [?Yield, ?Await,
?Return]
FunctionDeclaration [?Yield,
?Await, ~Default]
注
一个 Statement
可以用标签作为前缀。标签语句只与带标签的 break
和 continue
语句结合使用。ECMAScript 没有 goto
语句。一个
Statement 可以是
LabelledStatement
的一部分,
而它本身又可以是另一个 LabelledStatement
的一部分,以此类推。以这种方式引入的标签在描述各个语句的语义时统称为"当前标签集"。
14.13.1 静态语义:早期错误
LabelledItem : FunctionDeclaration
注
14.13.2 静态语义:IsLabelledFunction ( stmt )
抽象操作 IsLabelledFunction 接受参数 stmt (一个 Statement 解析节点 )并返回一个 Boolean。调用时执行以下步骤:
如果 stmt 不是 LabelledStatement ,返回
false 。
令 item 为 stmt 的 LabelledItem 。
如果 item 是
LabelledItem
: FunctionDeclaration
,返回 true 。
令 subStmt 为 item 的 Statement 。
返回 IsLabelledFunction (subStmt )。
14.13.3 运行时语义:Evaluation
LabelledStatement
:
LabelIdentifier
:
LabelledItem
返回 ? LabelledEvaluation of this LabelledStatement
with argument « »。
14.13.4 运行时语义:LabelledEvaluation
语法制导操作
LabelledEvaluation 接受参数 labelSet (一个
字符串的 列表 )并
返回一个 包含 ECMAScript 语言值 或
empty 的 正常完成 ,或
突然完成 。它按以下产生式分段定义:
BreakableStatement
: IterationStatement
令 stmtResult 为 Completion (LoopEvaluation of IterationStatement with argument
labelSet )。
如果 stmtResult 是 break
完成 ,则
如果 stmtResult .[[Target]] 是
empty ,则
如果 stmtResult .[[Value]] 是
empty ,设置 stmtResult 为 NormalCompletion (undefined )。
否则,设置 stmtResult 为 NormalCompletion (stmtResult .[[Value]] )。
返回 ? stmtResult 。
BreakableStatement
: SwitchStatement
令 stmtResult 为 Completion (Evaluation
of SwitchStatement )。
如果 stmtResult 是 break
完成 ,则
如果 stmtResult .[[Target]] 是
empty ,则
如果 stmtResult .[[Value]] 是
empty ,设置 stmtResult 为 NormalCompletion (undefined )。
否则,设置 stmtResult 为 NormalCompletion (stmtResult .[[Value]] )。
返回 ? stmtResult 。
注 1
LabelledStatement
:
LabelIdentifier
:
LabelledItem
令 label 为 LabelIdentifier 的 StringValue 。
令 newLabelSet 为
labelSet 和 « label » 的 列表连接 。
令 stmtResult 为 Completion (LabelledEvaluation of LabelledItem with argument
newLabelSet )。
如果 stmtResult 是 break
完成 且 stmtResult .[[Target]] 是
label ,则
设置 stmtResult 为 NormalCompletion (stmtResult .[[Value]] )。
返回 ? stmtResult 。
LabelledItem : FunctionDeclaration
返回 ? Evaluation of FunctionDeclaration 。
Statement :
BlockStatement
VariableStatement
EmptyStatement
ExpressionStatement
IfStatement
ContinueStatement
BreakStatement
ReturnStatement
WithStatement
ThrowStatement
TryStatement
DebuggerStatement
返回 ? Evaluation of Statement 。
注 2
14.14 throw
语句
语法
ThrowStatement [Yield,
Await] :
throw
[no LineTerminator
here]
Expression [+In, ?Yield,
?Await]
;
14.14.1 运行时语义:Evaluation
ThrowStatement :
throw
Expression
;
令 exprRef 为 ? Evaluation of Expression 。
令 exprValue 为 ? GetValue (exprRef )。
返回 ThrowCompletion (exprValue )。
14.15 try
语句
语法
TryStatement [Yield, Await,
Return] :
try
Block [?Yield, ?Await,
?Return]
Catch [?Yield, ?Await,
?Return]
try
Block [?Yield, ?Await,
?Return]
Finally [?Yield, ?Await,
?Return]
try
Block [?Yield, ?Await,
?Return]
Catch [?Yield, ?Await,
?Return]
Finally [?Yield, ?Await,
?Return]
Catch [Yield,
Await,
Return] :
catch
(
CatchParameter [?Yield,
?Await]
)
Block [?Yield, ?Await,
?Return]
catch
Block [?Yield, ?Await,
?Return]
Finally [Yield, Await,
Return] :
finally
Block [?Yield, ?Await,
?Return]
CatchParameter [Yield,
Await] :
BindingIdentifier [?Yield,
?Await]
BindingPattern [?Yield,
?Await]
注
try
语句包含一个可能发生异常情况的代码块,比如运行时错误或 throw
语句。catch
子句提供异常处理代码。当 catch 子句捕获异常时,其
CatchParameter 绑定到该异常。
14.15.1 静态语义:早期错误
Catch :
catch
(
CatchParameter
)
Block
注
此产生式的替代 静态语义 在 B.3.4 中给出。
14.15.2 运行时语义:CatchClauseEvaluation
语法制导操作
CatchClauseEvaluation 接受参数 thrownValue (一个
ECMAScript 语言值 )并
返回一个 包含 ECMAScript 语言值 或
empty 的 正常完成 ,或
突然完成 。它按以下产生式分段定义:
Catch :
catch
(
CatchParameter
)
Block
令 oldEnv 为 运行执行上下文 的 LexicalEnvironment。
令 catchEnv 为 NewDeclarativeEnvironment (oldEnv )。
对于 CatchParameter 的
BoundNames 中的每个元素
argName ,执行
执行 ! catchEnv .CreateMutableBinding(argName ,
false )。
设置 运行执行上下文 的
LexicalEnvironment 为 catchEnv 。
令 status 为 Completion (BindingInitialization of CatchParameter with
arguments thrownValue and catchEnv )。
如果 status 是 突然完成 ,则
设置 运行执行上下文 的
LexicalEnvironment 为 oldEnv 。
返回 ? status 。
令 B 为 Completion (Evaluation
of Block )。
设置 运行执行上下文 的
LexicalEnvironment 为 oldEnv 。
返回 ? B 。
Catch :
catch
Block
返回 ? Evaluation of Block 。
注
无论控制如何离开 Block ,LexicalEnvironment 总是恢复到之前的状态。
14.15.3 运行时语义:Evaluation
TryStatement :
try
Block
Catch
令 B 为 Completion (Evaluation
of Block )。
如果 B 是 throw
完成 ,令 C 为 Completion (CatchClauseEvaluation of Catch with argument
B .[[Value]] )。
否则,令 C 为 B 。
返回 ? UpdateEmpty (C ,
undefined )。
TryStatement :
try
Block
Finally
令 B 为 Completion (Evaluation
of Block )。
令 F 为 Completion (Evaluation
of Finally )。
如果 F 是 正常完成 ,设置
F 为 B 。
返回 ? UpdateEmpty (F ,
undefined )。
TryStatement :
try
Block
Catch
Finally
令 B 为 Completion (Evaluation
of Block )。
如果 B 是 throw
完成 ,令 C 为 Completion (CatchClauseEvaluation of Catch with argument
B .[[Value]] )。
否则,令 C 为 B 。
令 F 为 Completion (Evaluation
of Finally )。
如果 F 是 正常完成 ,设置
F 为 C 。
返回 ? UpdateEmpty (F ,
undefined )。
14.16 debugger
语句
语法
DebuggerStatement :
debugger
;
14.16.1 运行时语义:Evaluation
注
计算 DebuggerStatement
可能允许实现在调试器下运行时触发断点。如果调试器不存在或不活跃,此语句没有可观察的效果。
DebuggerStatement
:
debugger
;
如果 实现定义的 调试设施可用且已启用,则
执行 实现定义的
调试动作。
返回一个新的 实现定义的
完成记录 。
否则,
返回 empty 。
15 ECMAScript 语言:函数和类
注
各种 ECMAScript 语言元素会导致创建 ECMAScript 函数对象 (10.2 )。这些函数的 Evaluation 从执行其
[[Call]] 内部方法开始(10.2.1 )。
15.1 参数列表
语法
UniqueFormalParameters [Yield,
Await] :
FormalParameters [?Yield,
?Await]
FormalParameters [Yield,
Await] :
[empty]
FunctionRestParameter [?Yield,
?Await]
FormalParameterList [?Yield,
?Await]
FormalParameterList [?Yield,
?Await]
,
FormalParameterList [?Yield,
?Await]
,
FunctionRestParameter [?Yield,
?Await]
FormalParameterList [Yield,
Await] :
FormalParameter [?Yield,
?Await]
FormalParameterList [?Yield,
?Await]
,
FormalParameter [?Yield,
?Await]
FunctionRestParameter [Yield,
Await] :
BindingRestElement [?Yield,
?Await]
FormalParameter [Yield,
Await] :
BindingElement [?Yield,
?Await]
15.1.1 静态语义:早期错误
UniqueFormalParameters
: FormalParameters
FormalParameters :
FormalParameterList
注
15.1.2 静态语义:ContainsExpression
语法制导操作
ContainsExpression 不接受参数并返回一个 Boolean。它按以下产生式分段定义:
ObjectBindingPattern
:
{
}
{
BindingRestProperty
}
返回 false 。
ObjectBindingPattern
:
{
BindingPropertyList
,
BindingRestProperty
}
返回 BindingPropertyList 的 ContainsExpression 。
ArrayBindingPattern
:
[
Elision opt
]
返回 false 。
ArrayBindingPattern
:
[
Elision opt
BindingRestElement
]
返回 BindingRestElement 的 ContainsExpression 。
ArrayBindingPattern
:
[
BindingElementList
,
Elision opt
]
返回 BindingElementList 的 ContainsExpression 。
ArrayBindingPattern
:
[
BindingElementList
,
Elision opt
BindingRestElement
]
令 has 为 BindingElementList 的 ContainsExpression 。
如果 has 是 true ,返回 true 。
返回 BindingRestElement 的 ContainsExpression 。
BindingPropertyList
:
BindingPropertyList
,
BindingProperty
令 has 为 BindingPropertyList 的 ContainsExpression 。
如果 has 是 true ,返回 true 。
返回 BindingProperty
的 ContainsExpression 。
BindingElementList
:
BindingElementList
,
BindingElisionElement
令 has 为 BindingElementList 的 ContainsExpression 。
如果 has 是 true ,返回 true 。
返回 BindingElisionElement 的
ContainsExpression 。
BindingElisionElement
:
Elision opt
BindingElement
返回 BindingElement 的
ContainsExpression 。
BindingProperty :
PropertyName
:
BindingElement
令 has 为 PropertyName 的 IsComputedPropertyKey 。
如果 has 是 true ,返回 true 。
返回 BindingElement 的
ContainsExpression 。
BindingElement :
BindingPattern
Initializer
返回 true 。
SingleNameBinding
: BindingIdentifier
返回 false 。
SingleNameBinding
:
BindingIdentifier
Initializer
返回 true 。
BindingRestElement
:
...
BindingIdentifier
返回 false 。
BindingRestElement
:
...
BindingPattern
返回 BindingPattern 的
ContainsExpression 。
FormalParameters :
[empty]
返回 false 。
FormalParameters :
FormalParameterList
,
FunctionRestParameter
如果 FormalParameterList 的 ContainsExpression
是 true ,返回 true 。
返回 FunctionRestParameter 的
ContainsExpression 。
FormalParameterList
:
FormalParameterList
,
FormalParameter
如果 FormalParameterList 的 ContainsExpression
是 true ,返回 true 。
返回 FormalParameter
的 ContainsExpression 。
ArrowParameters :
BindingIdentifier
返回 false 。
ArrowParameters :
CoverParenthesizedExpressionAndArrowParameterList
令 formals 为由 CoverParenthesizedExpressionAndArrowParameterList
覆盖 的 ArrowFormalParameters 。
返回 formals 的 ContainsExpression 。
AsyncArrowBindingIdentifier
: BindingIdentifier
返回 false 。
15.1.3 静态语义:IsSimpleParameterList
语法制导操作
IsSimpleParameterList 不接受参数并返回一个 Boolean。它按以下产生式分段定义:
BindingElement :
BindingPattern
返回 false 。
BindingElement :
BindingPattern
Initializer
返回 false 。
SingleNameBinding
: BindingIdentifier
返回 true 。
SingleNameBinding
:
BindingIdentifier
Initializer
返回 false 。
FormalParameters :
[empty]
返回 true 。
FormalParameters :
FunctionRestParameter
返回 false 。
FormalParameters :
FormalParameterList
,
FunctionRestParameter
返回 false 。
FormalParameterList
:
FormalParameterList
,
FormalParameter
如果 FormalParameterList 的 IsSimpleParameterList
是 false ,返回 false 。
返回 FormalParameter
的 IsSimpleParameterList 。
FormalParameter :
BindingElement
返回 BindingElement 的
IsSimpleParameterList 。
ArrowParameters :
BindingIdentifier
返回 true 。
ArrowParameters :
CoverParenthesizedExpressionAndArrowParameterList
令 formals 为由 CoverParenthesizedExpressionAndArrowParameterList
覆盖 的 ArrowFormalParameters 。
返回 formals 的 IsSimpleParameterList 。
AsyncArrowBindingIdentifier
: BindingIdentifier
返回 true 。
CoverCallExpressionAndAsyncArrowHead
:
MemberExpression
Arguments
令 head 为由 CoverCallExpressionAndAsyncArrowHead
覆盖 的 AsyncArrowHead 。
返回 head 的 IsSimpleParameterList 。
15.1.4 静态语义:HasInitializer
语法制导操作
HasInitializer 不接受参数并返回一个 Boolean。它按以下产生式分段定义:
BindingElement :
BindingPattern
返回 false 。
BindingElement :
BindingPattern
Initializer
返回 true 。
SingleNameBinding
: BindingIdentifier
返回 false 。
SingleNameBinding
:
BindingIdentifier
Initializer
返回 true 。
FormalParameterList
:
FormalParameterList
,
FormalParameter
如果 FormalParameterList 的 HasInitializer 是
true ,返回 true 。
返回 FormalParameter
的 HasInitializer 。
15.1.5 静态语义:ExpectedArgumentCount
语法制导操作
ExpectedArgumentCount 不接受参数并返回一个非负 整数 。它按以下产生式分段定义:
FormalParameters :
[empty]
FunctionRestParameter
返回 0。
FormalParameters :
FormalParameterList
,
FunctionRestParameter
返回 FormalParameterList 的 ExpectedArgumentCount 。
注
FormalParameterList 的
ExpectedArgumentCount 是在剩余参数或第一个具有初始化器的 FormalParameter 左侧的 FormalParameters
的数量。没有初始化器的 FormalParameter
可以出现在第一个有初始化器的参数之后,但这样的参数被认为是可选的,其默认值为 undefined 。
FormalParameterList
: FormalParameter
如果 FormalParameter
的 HasInitializer 是
true ,返回 0。
返回 1。
FormalParameterList
:
FormalParameterList
,
FormalParameter
令 count 为 FormalParameterList 的 ExpectedArgumentCount 。
如果 FormalParameterList 的 HasInitializer 是
true 或 FormalParameter 的 HasInitializer 是
true ,返回 count 。
返回 count + 1。
ArrowParameters :
BindingIdentifier
返回 1。
ArrowParameters :
CoverParenthesizedExpressionAndArrowParameterList
令 formals 为由 CoverParenthesizedExpressionAndArrowParameterList
覆盖 的 ArrowFormalParameters 。
返回 formals 的 ExpectedArgumentCount 。
PropertySetParameterList
: FormalParameter
如果 FormalParameter
的 HasInitializer 是
true ,返回 0。
返回 1。
AsyncArrowBindingIdentifier
: BindingIdentifier
返回 1。
15.2 函数定义
语法
FunctionDeclaration [Yield,
Await, Default] :
function
BindingIdentifier [?Yield,
?Await]
(
FormalParameters [~Yield,
~Await]
)
{
FunctionBody [~Yield,
~Await]
}
[+Default]
function
(
FormalParameters [~Yield,
~Await]
)
{
FunctionBody [~Yield,
~Await]
}
FunctionExpression :
function
BindingIdentifier [~Yield,
~Await] opt
(
FormalParameters [~Yield,
~Await]
)
{
FunctionBody [~Yield,
~Await]
}
FunctionBody [Yield,
Await] :
FunctionStatementList [?Yield,
?Await]
FunctionStatementList [Yield,
Await] :
StatementList [?Yield, ?Await,
+Return] opt
15.2.1 静态语义:早期错误
FunctionDeclaration
:
function
BindingIdentifier
(
FormalParameters
)
{
FunctionBody
}
function
(
FormalParameters
)
{
FunctionBody
}
FunctionExpression
:
function
BindingIdentifier opt
(
FormalParameters
)
{
FunctionBody
}
注
FunctionBody 的
LexicallyDeclaredNames
不包括使用 var 或 function 声明绑定的标识符。
FunctionBody : FunctionStatementList
15.2.2 静态语义:FunctionBodyContainsUseStrict
语法制导操作
FunctionBodyContainsUseStrict 不接受参数并返回一个 Boolean。它按以下产生式分段定义:
FunctionBody : FunctionStatementList
如果 FunctionBody 的
指令序言 包含一个 Use
Strict 指令 ,返回 true ;否则,返回
false 。
15.2.3 运行时语义:EvaluateFunctionBody
语法制导操作
EvaluateFunctionBody 接受参数 functionObject (一个 ECMAScript 函数对象 )和
argumentsList (一个 ECMAScript 语言值 的 List )并返回一个 return completion 或
throw
completion 。它按以下产生式分段定义:
FunctionBody : FunctionStatementList
执行 ? FunctionDeclarationInstantiation (functionObject ,
argumentsList )。
执行 ? Evaluation of FunctionStatementList 。
注:如果前面的步骤产生了一个 normal
completion ,那么求值通过继续执行到 FunctionStatementList 的末尾而结束。
返回 ReturnCompletion (undefined )。
15.2.4 运行时语义:InstantiateOrdinaryFunctionObject
语法制导操作
InstantiateOrdinaryFunctionObject 接受参数 env (一个 Environment Record )和
privateEnv (一个 PrivateEnvironment Record 或
null )并返回一个 ECMAScript 函数对象 。它按以下产生式分段定义:
FunctionDeclaration
:
function
BindingIdentifier
(
FormalParameters
)
{
FunctionBody
}
令 name 为 BindingIdentifier 的 StringValue 。
令 sourceText 为 FunctionDeclaration 匹配的源文本 。
令 F 为 OrdinaryFunctionCreate (%Function.prototype% ,
sourceText , FormalParameters , FunctionBody ,
non-lexical-this , env , privateEnv )。
执行 SetFunctionName (F ,
name )。
执行 MakeConstructor (F )。
返回 F 。
FunctionDeclaration
:
function
(
FormalParameters
)
{
FunctionBody
}
令 sourceText 为 FunctionDeclaration 匹配的源文本 。
令 F 为 OrdinaryFunctionCreate (%Function.prototype% ,
sourceText , FormalParameters , FunctionBody ,
non-lexical-this , env , privateEnv )。
执行 SetFunctionName (F ,
"default" )。
执行 MakeConstructor (F )。
返回 F 。
注
匿名 FunctionDeclaration 只能作为
export default
声明的一部分出现,因此其函数代码总是 严格模式代码 。
15.2.5 运行时语义:InstantiateOrdinaryFunctionExpression
语法制导操作
InstantiateOrdinaryFunctionExpression 接受可选参数 name (一个 属性键 或 私有名称 )并返回一个 ECMAScript 函数对象 。它按以下产生式分段定义:
FunctionExpression
:
function
(
FormalParameters
)
{
FunctionBody
}
如果不存在 name ,设置 name 为 "" 。
令 env 为 运行执行上下文 的 LexicalEnvironment。
令 privateEnv 为 运行执行上下文 的 PrivateEnvironment。
令 sourceText 为 FunctionExpression 匹配的源文本 。
令 closure 为 OrdinaryFunctionCreate (%Function.prototype% ,
sourceText , FormalParameters , FunctionBody ,
non-lexical-this , env , privateEnv )。
执行 SetFunctionName (closure ,
name )。
执行 MakeConstructor (closure )。
返回 closure 。
FunctionExpression
:
function
BindingIdentifier
(
FormalParameters
)
{
FunctionBody
}
断言 :name 不存在。
设置 name 为 BindingIdentifier 的 StringValue 。
令 outerEnv 为 运行执行上下文 的 LexicalEnvironment。
令 funcEnv 为 NewDeclarativeEnvironment (outerEnv )。
执行 ! funcEnv .CreateImmutableBinding(name ,
false )。
令 privateEnv 为 运行执行上下文 的 PrivateEnvironment。
令 sourceText 为 FunctionExpression 匹配的源文本 。
令 closure 为 OrdinaryFunctionCreate (%Function.prototype% ,
sourceText , FormalParameters , FunctionBody ,
non-lexical-this , funcEnv , privateEnv )。
执行 SetFunctionName (closure ,
name )。
执行 MakeConstructor (closure )。
执行 ! funcEnv .InitializeBinding(name ,
closure )。
返回 closure 。
注
15.2.6 运行时语义:Evaluation
FunctionDeclaration
:
function
BindingIdentifier
(
FormalParameters
)
{
FunctionBody
}
返回 empty 。
注 1
FunctionDeclaration
:
function
(
FormalParameters
)
{
FunctionBody
}
返回 empty 。
FunctionExpression
:
function
BindingIdentifier opt
(
FormalParameters
)
{
FunctionBody
}
返回 FunctionExpression 的 InstantiateOrdinaryFunctionExpression 。
注 2
对于使用 FunctionDeclaration 或 FunctionExpression
定义的每个函数,都会自动创建一个 "prototype" 属性,以允许该函数被用作 构造函数 。
FunctionStatementList
: [empty]
返回 undefined 。
15.3 箭头函数定义
语法
ArrowFunction [In, Yield,
Await] :
ArrowParameters [?Yield,
?Await]
[no LineTerminator here]
=>
ConciseBody [?In]
ArrowParameters [Yield,
Await] :
BindingIdentifier [?Yield,
?Await]
CoverParenthesizedExpressionAndArrowParameterList [?Yield,
?Await]
ConciseBody [In]
:
[lookahead ≠ { ]
ExpressionBody [?In,
~Await]
{
FunctionBody [~Yield,
~Await]
}
ExpressionBody [In,
Await] :
AssignmentExpression [?In,
~Yield, ?Await]
补充语法
当处理产生式的实例
ArrowParameters [Yield,
Await] : CoverParenthesizedExpressionAndArrowParameterList [?Yield,
?Await]
时,CoverParenthesizedExpressionAndArrowParameterList
的解释使用以下语法进行细化:
ArrowFormalParameters [Yield,
Await] :
(
UniqueFormalParameters [?Yield,
?Await]
)
15.3.1 静态语义:早期错误
ArrowFunction :
ArrowParameters
=>
ConciseBody
ArrowParameters :
CoverParenthesizedExpressionAndArrowParameterList
15.3.2 静态语义:ConciseBodyContainsUseStrict
语法制导操作
ConciseBodyContainsUseStrict 不接受参数并返回一个 Boolean。它按以下产生式分段定义:
ConciseBody : ExpressionBody
返回 false 。
ConciseBody :
{
FunctionBody
}
返回 FunctionBody 的
FunctionBodyContainsUseStrict 。
15.3.3 运行时语义:EvaluateConciseBody
语法制导操作
EvaluateConciseBody 接受参数 functionObject (一个 ECMAScript 函数对象 )和
argumentsList (一个 ECMAScript 语言值 的 List )并返回一个 return completion 或
throw
completion 。它按以下产生式分段定义:
ConciseBody : ExpressionBody
执行 ? FunctionDeclarationInstantiation (functionObject ,
argumentsList )。
返回 ? Evaluation of ExpressionBody 。
15.3.4 运行时语义:InstantiateArrowFunctionExpression
语法制导操作
InstantiateArrowFunctionExpression 接受可选参数 name (一个 属性键 或 私有名称 )并返回一个 ECMAScript 函数对象 。它按以下产生式分段定义:
ArrowFunction :
ArrowParameters
=>
ConciseBody
如果不存在 name ,设置 name 为 "" 。
令 env 为 运行执行上下文 的 LexicalEnvironment。
令 privateEnv 为 运行执行上下文 的 PrivateEnvironment。
令 sourceText 为 ArrowFunction 匹配的源文本 。
令 closure 为 OrdinaryFunctionCreate (%Function.prototype% ,
sourceText , ArrowParameters , ConciseBody ,
lexical-this , env , privateEnv )。
执行 SetFunctionName (closure ,
name )。
返回 closure 。
注
ArrowFunction 不为
arguments
、super
、this
或 new.target
定义局部绑定。ArrowFunction
内对 arguments
、super
、this
或 new.target
的任何引用都必须解析为词法封闭环境中的绑定。通常这会是紧邻封闭函数的函数环境。尽管 ArrowFunction 可能包含对 super
的引用,但在步骤 5 中创建的
函数对象 不会通过执行 MakeMethod 而成为方法。引用
super
的 ArrowFunction 总是包含在非 ArrowFunction 中,实现
super
所需的状态可以通过被 ArrowFunction 的 函数对象 捕获的 env 访问。
15.3.5 运行时语义:Evaluation
ArrowFunction :
ArrowParameters
=>
ConciseBody
返回 ArrowFunction 的
InstantiateArrowFunctionExpression 。
ExpressionBody :
AssignmentExpression
令 exprRef 为 ? Evaluation of AssignmentExpression 。
令 exprValue 为 ? GetValue (exprRef )。
返回 ReturnCompletion (exprValue )。
15.4 方法定义
语法
MethodDefinition [Yield,
Await] :
ClassElementName [?Yield,
?Await]
(
UniqueFormalParameters [~Yield,
~Await]
)
{
FunctionBody [~Yield,
~Await]
}
GeneratorMethod [?Yield,
?Await]
AsyncMethod [?Yield,
?Await]
AsyncGeneratorMethod [?Yield,
?Await]
get
ClassElementName [?Yield,
?Await]
(
)
{
FunctionBody [~Yield,
~Await]
}
set
ClassElementName [?Yield,
?Await]
(
PropertySetParameterList
)
{
FunctionBody [~Yield,
~Await]
}
PropertySetParameterList
:
FormalParameter [~Yield,
~Await]
15.4.1 静态语义:早期错误
MethodDefinition :
ClassElementName
(
UniqueFormalParameters
)
{
FunctionBody
}
MethodDefinition :
set
ClassElementName
(
PropertySetParameterList
)
{
FunctionBody
}
15.4.2 静态语义:HasDirectSuper
语法制导操作
HasDirectSuper 不接受参数并返回一个 Boolean。它按以下产生式分段定义:
MethodDefinition :
ClassElementName
(
UniqueFormalParameters
)
{
FunctionBody
}
如果 UniqueFormalParameters
Contains SuperCall 是
true ,返回 true 。
返回 FunctionBody
Contains SuperCall 。
MethodDefinition :
get
ClassElementName
(
)
{
FunctionBody
}
返回 FunctionBody
Contains SuperCall 。
MethodDefinition :
set
ClassElementName
(
PropertySetParameterList
)
{
FunctionBody
}
如果 PropertySetParameterList
Contains SuperCall 是
true ,返回 true 。
返回 FunctionBody
Contains SuperCall 。
GeneratorMethod :
*
ClassElementName
(
UniqueFormalParameters
)
{
GeneratorBody
}
如果 UniqueFormalParameters
Contains SuperCall 是
true ,返回 true 。
返回 GeneratorBody
Contains SuperCall 。
AsyncGeneratorMethod
:
async
*
ClassElementName
(
UniqueFormalParameters
)
{
AsyncGeneratorBody
}
如果 UniqueFormalParameters
Contains SuperCall 是
true ,返回 true 。
返回 AsyncGeneratorBody Contains SuperCall 。
AsyncMethod :
async
ClassElementName
(
UniqueFormalParameters
)
{
AsyncFunctionBody
}
如果 UniqueFormalParameters
Contains SuperCall 是
true ,返回 true 。
返回 AsyncFunctionBody Contains SuperCall 。
15.4.3 静态语义:SpecialMethod
语法制导操作
SpecialMethod 不接受参数并返回一个 Boolean。它按以下产生式分段定义:
MethodDefinition :
ClassElementName
(
UniqueFormalParameters
)
{
FunctionBody
}
返回 false 。
MethodDefinition :
GeneratorMethod
AsyncMethod
AsyncGeneratorMethod
get
ClassElementName
(
)
{
FunctionBody
}
set
ClassElementName
(
PropertySetParameterList
)
{
FunctionBody
}
返回 true 。
15.4.4 运行时语义:DefineMethod
语法制导操作
DefineMethod 接受参数 object (一个 Object)和可选参数 functionPrototype (一个 Object)并返回
包含 一个 Record (字段为 [[Key]] (一个 属性键 )和 [[Closure]] (一个
ECMAScript 函数对象 ))的 normal completion 或
abrupt
completion 。它按以下产生式分段定义:
MethodDefinition :
ClassElementName
(
UniqueFormalParameters
)
{
FunctionBody
}
令 propKey 为 ? Evaluation of ClassElementName 。
令 env 为 运行执行上下文 的 LexicalEnvironment。
令 privateEnv 为 运行执行上下文 的 PrivateEnvironment。
如果存在 functionPrototype ,那么
令 prototype 为 functionPrototype 。
否则,
令 prototype 为 %Function.prototype% 。
令 sourceText 为 MethodDefinition 匹配的源文本 。
令 closure 为 OrdinaryFunctionCreate (prototype ,
sourceText , UniqueFormalParameters , FunctionBody ,
non-lexical-this , env , privateEnv )。
执行 MakeMethod (closure ,
object )。
返回 Record { [[Key]] : propKey , [[Closure]] : closure }。
15.4.5 运行时语义:MethodDefinitionEvaluation
语法制导操作
MethodDefinitionEvaluation 接受参数 object (一个 Object)和 enumerable (一个
Boolean)并返回 包含 PrivateElement 或
unused 的 normal
completion ,或 abrupt
completion 。它按以下产生式分段定义:
MethodDefinition :
ClassElementName
(
UniqueFormalParameters
)
{
FunctionBody
}
令 methodDef 为 MethodDefinition 以参数
object 的 ? DefineMethod 。
执行 SetFunctionName (methodDef .[[Closure]] , methodDef .[[Key]] )。
返回 ? DefineMethodProperty (object ,
methodDef .[[Key]] , methodDef .[[Closure]] , enumerable )。
MethodDefinition :
get
ClassElementName
(
)
{
FunctionBody
}
令 propKey 为 ? Evaluation of ClassElementName 。
令 env 为 运行执行上下文 的 LexicalEnvironment。
令 privateEnv 为 运行执行上下文 的 PrivateEnvironment。
令 sourceText 为 MethodDefinition 匹配的源文本 。
令 formalParameterList 为产生式
FormalParameters
: [empty]
的实例。
令 closure 为 OrdinaryFunctionCreate (%Function.prototype% ,
sourceText , formalParameterList , FunctionBody ,
non-lexical-this , env , privateEnv )。
执行 MakeMethod (closure ,
object )。
执行 SetFunctionName (closure ,
propKey , "get" )。
如果 propKey 是 私有名称 ,那么
返回 PrivateElement
{ [[Key]] : propKey , [[Kind]] : accessor , [[Get]] : closure , [[Set]] : undefined }。
否则,
令 desc 为 PropertyDescriptor { [[Get]] :
closure , [[Enumerable]] :
enumerable , [[Configurable]] :
true }。
执行 ? DefinePropertyOrThrow (object ,
propKey , desc )。
返回 unused 。
MethodDefinition :
set
ClassElementName
(
PropertySetParameterList
)
{
FunctionBody
}
令 propKey 为 ? Evaluation of ClassElementName 。
令 env 为 运行执行上下文 的 LexicalEnvironment。
令 privateEnv 为 运行执行上下文 的 PrivateEnvironment。
令 sourceText 为 MethodDefinition 匹配的源文本 。
令 closure 为 OrdinaryFunctionCreate (%Function.prototype% ,
sourceText , PropertySetParameterList ,
FunctionBody ,
non-lexical-this , env , privateEnv )。
执行 MakeMethod (closure ,
object )。
执行 SetFunctionName (closure ,
propKey , "set" )。
如果 propKey 是 私有名称 ,那么
返回 PrivateElement
{ [[Key]] : propKey , [[Kind]] : accessor , [[Get]] : undefined , [[Set]] : closure }。
否则,
令 desc 为 PropertyDescriptor { [[Set]] :
closure , [[Enumerable]] :
enumerable , [[Configurable]] :
true }。
执行 ? DefinePropertyOrThrow (object ,
propKey , desc )。
返回 unused 。
GeneratorMethod :
*
ClassElementName
(
UniqueFormalParameters
)
{
GeneratorBody
}
令 propKey 为 ? Evaluation of ClassElementName 。
令 env 为 运行执行上下文 的 LexicalEnvironment。
令 privateEnv 为 运行执行上下文 的 PrivateEnvironment。
令 sourceText 为 GeneratorMethod 匹配的源文本 。
令 closure 为 OrdinaryFunctionCreate (%GeneratorFunction.prototype% ,
sourceText , UniqueFormalParameters , GeneratorBody ,
non-lexical-this , env , privateEnv )。
执行 MakeMethod (closure ,
object )。
执行 SetFunctionName (closure ,
propKey )。
令 prototype 为 OrdinaryObjectCreate (%GeneratorPrototype% )。
执行 ! DefinePropertyOrThrow (closure ,
"prototype" , PropertyDescriptor { [[Value]] :
prototype , [[Writable]] : true ,
[[Enumerable]] : false , [[Configurable]] : false })。
返回 ? DefineMethodProperty (object ,
propKey , closure , enumerable )。
AsyncGeneratorMethod
:
async
*
ClassElementName
(
UniqueFormalParameters
)
{
AsyncGeneratorBody
}
令 propKey 为 ? Evaluation of ClassElementName 。
令 env 为 运行执行上下文 的 LexicalEnvironment。
令 privateEnv 为 运行执行上下文 的 PrivateEnvironment。
令 sourceText 为 AsyncGeneratorMethod 匹配的源文本 。
令 closure 为 OrdinaryFunctionCreate (%AsyncGeneratorFunction.prototype% ,
sourceText , UniqueFormalParameters , AsyncGeneratorBody ,
non-lexical-this , env , privateEnv )。
执行 MakeMethod (closure ,
object )。
执行 SetFunctionName (closure ,
propKey )。
令 prototype 为 OrdinaryObjectCreate (%AsyncGeneratorPrototype% )。
执行 ! DefinePropertyOrThrow (closure ,
"prototype" , PropertyDescriptor { [[Value]] :
prototype , [[Writable]] : true ,
[[Enumerable]] : false , [[Configurable]] : false })。
返回 ? DefineMethodProperty (object ,
propKey , closure , enumerable )。
AsyncMethod :
async
ClassElementName
(
UniqueFormalParameters
)
{
AsyncFunctionBody
}
令 propKey 为 ? Evaluation of ClassElementName 。
令 env 为 运行执行上下文 的 LexicalEnvironment。
令 privateEnv 为 运行执行上下文 的 PrivateEnvironment。
令 sourceText 为 AsyncMethod 匹配的源文本 。
令 closure 为 OrdinaryFunctionCreate (%AsyncFunction.prototype% ,
sourceText , UniqueFormalParameters , AsyncFunctionBody ,
non-lexical-this , env , privateEnv )。
执行 MakeMethod (closure ,
object )。
执行 SetFunctionName (closure ,
propKey )。
返回 ? DefineMethodProperty (object ,
propKey , closure , enumerable )。
15.5 生成器函数定义
语法
GeneratorDeclaration [Yield,
Await, Default] :
function
*
BindingIdentifier [?Yield,
?Await]
(
FormalParameters [+Yield,
~Await]
)
{
GeneratorBody
}
[+Default]
function
*
(
FormalParameters [+Yield,
~Await]
)
{
GeneratorBody
}
GeneratorExpression
:
function
*
BindingIdentifier [+Yield,
~Await] opt
(
FormalParameters [+Yield,
~Await]
)
{
GeneratorBody
}
GeneratorMethod [Yield,
Await] :
*
ClassElementName [?Yield,
?Await]
(
UniqueFormalParameters [+Yield,
~Await]
)
{
GeneratorBody
}
GeneratorBody :
FunctionBody [+Yield,
~Await]
YieldExpression [In,
Await] :
yield
yield
[no LineTerminator here]
AssignmentExpression [?In,
+Yield, ?Await]
yield
[no LineTerminator here]
*
AssignmentExpression [?In,
+Yield, ?Await]
注 1
注 2
YieldExpression
不能在生成器函数的 FormalParameters 中使用,因为作为 FormalParameters
一部分的任何表达式都在生成的 Generator 处于可恢复状态之前被求值。
注 3
与 Generators 相关的 抽象操作 在
27.5.3 中定义。
15.5.1 静态语义:早期错误
GeneratorMethod :
*
ClassElementName
(
UniqueFormalParameters
)
{
GeneratorBody
}
GeneratorDeclaration
:
function
*
BindingIdentifier
(
FormalParameters
)
{
GeneratorBody
}
function
*
(
FormalParameters
)
{
GeneratorBody
}
GeneratorExpression
:
function
*
BindingIdentifier opt
(
FormalParameters
)
{
GeneratorBody
}
15.5.2 运行时语义:EvaluateGeneratorBody
语法制导操作
EvaluateGeneratorBody 接受参数 functionObject (一个 ECMAScript 函数对象 )和
argumentsList (一个 List of
ECMAScript 语言值 ),并返回 throw completion 或
return
completion 。它按以下产生式分段定义:
GeneratorBody :
FunctionBody
执行 ? FunctionDeclarationInstantiation (functionObject ,
argumentsList )。
令 G 为 ? OrdinaryCreateFromConstructor (functionObject ,
"%GeneratorPrototype%" , « [[GeneratorState]] , [[GeneratorContext]] , [[GeneratorBrand]] »)。
设置 G .[[GeneratorBrand]] 为
empty 。
设置 G .[[GeneratorState]] 为
suspended-start 。
执行 GeneratorStart (G , FunctionBody )。
返回 ReturnCompletion (G )。
15.5.3 运行时语义:InstantiateGeneratorFunctionObject
语法制导操作
InstantiateGeneratorFunctionObject 接受参数 env (一个 Environment Record )和
privateEnv (一个 PrivateEnvironment Record 或
null ),并返回一个 ECMAScript 函数对象 。它按以下产生式分段定义:
GeneratorDeclaration
:
function
*
BindingIdentifier
(
FormalParameters
)
{
GeneratorBody
}
令 name 为 BindingIdentifier 的 StringValue 。
令 sourceText 为 GeneratorDeclaration 匹配的源文本 。
令 F 为 OrdinaryFunctionCreate (%GeneratorFunction.prototype% ,
sourceText , FormalParameters , GeneratorBody ,
non-lexical-this , env , privateEnv )。
执行 SetFunctionName (F ,
name )。
令 prototype 为 OrdinaryObjectCreate (%GeneratorPrototype% )。
执行 ! DefinePropertyOrThrow (F ,
"prototype" , PropertyDescriptor { [[Value]] :
prototype , [[Writable]] : true ,
[[Enumerable]] : false , [[Configurable]] : false })。
返回 F 。
GeneratorDeclaration
:
function
*
(
FormalParameters
)
{
GeneratorBody
}
令 sourceText 为 GeneratorDeclaration 匹配的源文本 。
令 F 为 OrdinaryFunctionCreate (%GeneratorFunction.prototype% ,
sourceText , FormalParameters , GeneratorBody ,
non-lexical-this , env , privateEnv )。
执行 SetFunctionName (F ,
"default" )。
令 prototype 为 OrdinaryObjectCreate (%GeneratorPrototype% )。
执行 ! DefinePropertyOrThrow (F ,
"prototype" , PropertyDescriptor { [[Value]] :
prototype , [[Writable]] : true ,
[[Enumerable]] : false , [[Configurable]] : false })。
返回 F 。
注
匿名的 GeneratorDeclaration 只能作为
export default
声明的一部分出现,因此其函数代码总是 严格模式代码 。
15.5.4 运行时语义:InstantiateGeneratorFunctionExpression
语法制导操作
InstantiateGeneratorFunctionExpression 接受可选参数 name (一个 属性键 或 私有名称 ),并返回一个 ECMAScript 函数对象 。它按以下产生式分段定义:
GeneratorExpression
:
function
*
(
FormalParameters
)
{
GeneratorBody
}
如果 name 不存在,设置 name 为 "" 。
令 env 为 运行执行上下文 的 LexicalEnvironment。
令 privateEnv 为 运行执行上下文 的 PrivateEnvironment。
令 sourceText 为 GeneratorExpression 匹配的源文本 。
令 closure 为 OrdinaryFunctionCreate (%GeneratorFunction.prototype% ,
sourceText , FormalParameters , GeneratorBody ,
non-lexical-this , env , privateEnv )。
执行 SetFunctionName (closure ,
name )。
令 prototype 为 OrdinaryObjectCreate (%GeneratorPrototype% )。
执行 ! DefinePropertyOrThrow (closure ,
"prototype" , PropertyDescriptor { [[Value]] :
prototype , [[Writable]] : true ,
[[Enumerable]] : false , [[Configurable]] : false })。
返回 closure 。
GeneratorExpression
:
function
*
BindingIdentifier
(
FormalParameters
)
{
GeneratorBody
}
断言 :name 不存在。
设置 name 为 BindingIdentifier 的 StringValue 。
令 outerEnv 为 运行执行上下文 的 LexicalEnvironment。
令 funcEnv 为 NewDeclarativeEnvironment (outerEnv )。
执行 ! funcEnv .CreateImmutableBinding(name ,
false )。
令 privateEnv 为 运行执行上下文 的 PrivateEnvironment。
令 sourceText 为 GeneratorExpression 匹配的源文本 。
令 closure 为 OrdinaryFunctionCreate (%GeneratorFunction.prototype% ,
sourceText , FormalParameters , GeneratorBody ,
non-lexical-this , funcEnv , privateEnv )。
执行 SetFunctionName (closure ,
name )。
令 prototype 为 OrdinaryObjectCreate (%GeneratorPrototype% )。
执行 ! DefinePropertyOrThrow (closure ,
"prototype" , PropertyDescriptor { [[Value]] :
prototype , [[Writable]] : true ,
[[Enumerable]] : false , [[Configurable]] : false })。
执行 ! funcEnv .InitializeBinding(name ,
closure )。
返回 closure 。
注释
15.5.5 运行时语义:Evaluation
GeneratorExpression
:
function
*
BindingIdentifier opt
(
FormalParameters
)
{
GeneratorBody
}
返回 GeneratorExpression 的 InstantiateGeneratorFunctionExpression 。
YieldExpression :
yield
返回 ? Yield (undefined )。
YieldExpression :
yield
AssignmentExpression
令 exprRef 为 ? Evaluation of AssignmentExpression 。
令 value 为 ? GetValue (exprRef )。
返回 ? Yield (value )。
YieldExpression :
yield
*
AssignmentExpression
令 generatorKind 为 GetGeneratorKind ()。
断言 :generatorKind 是
sync 或 async 。
令 exprRef 为 ? Evaluation of AssignmentExpression 。
令 value 为 ? GetValue (exprRef )。
令 iteratorRecord 为 ? GetIterator (value ,
generatorKind )。
令 iterator 为 iteratorRecord .[[Iterator]] 。
令 received 为 NormalCompletion (undefined )。
重复,
如果 received 是一个 normal
completion ,那么
令 innerResult 为 ? Call (iteratorRecord .[[NextMethod]] , iteratorRecord .[[Iterator]] , « received .[[Value]] »)。
如果 generatorKind 是 async ,设置
innerResult 为 ? Await (innerResult )。
如果 innerResult 不是
Object ,抛出 TypeError 异常。
令 done 为 ? IteratorComplete (innerResult )。
如果 done 是 true ,那么
返回 ? IteratorValue (innerResult )。
如果 generatorKind 是 async ,设置
received 为 Completion (AsyncGeneratorYield (?
IteratorValue (innerResult )))。
否则,设置 received 为 Completion (GeneratorYield (innerResult ))。
否则如果 received 是一个 throw
completion ,那么
令 throw 为 ? GetMethod (iterator ,
"throw" )。
如果 throw 不是 undefined ,那么
令 innerResult 为 ? Call (throw ,
iterator , « received .[[Value]] »)。
如果 generatorKind 是 async ,设置
innerResult 为 ? Await (innerResult )。
注释:来自内部 迭代器
throw
方法的异常会被传播。来自内部 throw
方法的
Normal
completion 的处理方式与内部 next
类似。
如果 innerResult 不是
Object ,抛出 TypeError
异常。
令 done 为 ? IteratorComplete (innerResult )。
如果 done 是 true ,那么
返回 ? IteratorValue (innerResult )。
如果 generatorKind 是 async ,设置
received 为 Completion (AsyncGeneratorYield (?
IteratorValue (innerResult )))。
否则,设置 received 为 Completion (GeneratorYield (innerResult ))。
否则,
注释:如果 iterator 没有 throw
方法,这个 throw 将终止
yield*
循环。但首先我们需要给 iterator 一个清理的机会。
令 closeCompletion 为 NormalCompletion (empty )。
如果 generatorKind 是 async ,执行
? AsyncIteratorClose (iteratorRecord ,
closeCompletion )。
否则,执行 ? IteratorClose (iteratorRecord ,
closeCompletion )。
注释:下一步抛出 TypeError 表示存在 yield*
协议违反:iterator 没有 throw
方法。
抛出 TypeError 异常。
否则,
断言 :received 是一个
return
completion 。
令 return 为 ? GetMethod (iterator ,
"return" )。
如果 return 是 undefined ,那么
设置 value 为 received .[[Value]] 。
如果 generatorKind 是 async ,那么
设置 value 为 ? Await (value )。
返回 ReturnCompletion (value )。
令 innerReturnResult 为 ? Call (return ,
iterator , « received .[[Value]] »)。
如果 generatorKind 是 async ,设置
innerReturnResult 为 ? Await (innerReturnResult )。
如果 innerReturnResult 不是
Object ,抛出 TypeError 异常。
令 done 为 ? IteratorComplete (innerReturnResult )。
如果 done 是 true ,那么
设置 value 为 ? IteratorValue (innerReturnResult )。
返回 ReturnCompletion (value )。
如果 generatorKind 是 async ,设置
received 为 Completion (AsyncGeneratorYield (?
IteratorValue (innerReturnResult )))。
否则,设置 received 为 Completion (GeneratorYield (innerReturnResult ))。
15.6 异步生成器函数定义
语法
AsyncGeneratorDeclaration [Yield,
Await, Default] :
async
[no LineTerminator here]
function
*
BindingIdentifier [?Yield,
?Await]
(
FormalParameters [+Yield,
+Await]
)
{
AsyncGeneratorBody
}
[+Default]
async
[no LineTerminator here]
function
*
(
FormalParameters [+Yield,
+Await]
)
{
AsyncGeneratorBody
}
AsyncGeneratorExpression
:
async
[no LineTerminator here]
function
*
BindingIdentifier [+Yield,
+Await] opt
(
FormalParameters [+Yield,
+Await]
)
{
AsyncGeneratorBody
}
AsyncGeneratorMethod [Yield,
Await] :
async
[no LineTerminator here]
*
ClassElementName [?Yield,
?Await]
(
UniqueFormalParameters [+Yield,
+Await]
)
{
AsyncGeneratorBody
}
AsyncGeneratorBody :
FunctionBody [+Yield,
+Await]
注释 1
YieldExpression 和
AwaitExpression
不能在异步生成器函数的 FormalParameters 中使用,因为作为 FormalParameters
一部分的任何表达式都在生成的 AsyncGenerator 处于可恢复状态之前被求值。
注释 2
与 AsyncGenerators 相关的 抽象操作 在
27.6.3 中定义。
15.6.1 静态语义:早期错误
AsyncGeneratorMethod
:
async
*
ClassElementName
(
UniqueFormalParameters
)
{
AsyncGeneratorBody
}
AsyncGeneratorDeclaration
:
async
function
*
BindingIdentifier
(
FormalParameters
)
{
AsyncGeneratorBody
}
async
function
*
(
FormalParameters
)
{
AsyncGeneratorBody
}
AsyncGeneratorExpression
:
async
function
*
BindingIdentifier opt
(
FormalParameters
)
{
AsyncGeneratorBody
}
15.6.2 运行时语义:EvaluateAsyncGeneratorBody
语法制导操作
EvaluateAsyncGeneratorBody 接受参数 functionObject (一个 ECMAScript 函数对象 )和
argumentsList (一个 List of
ECMAScript 语言值 ),并返回 throw completion 或
return
completion 。它按以下产生式分段定义:
AsyncGeneratorBody
: FunctionBody
执行 ? FunctionDeclarationInstantiation (functionObject ,
argumentsList )。
令 generator 为 ? OrdinaryCreateFromConstructor (functionObject ,
"%AsyncGeneratorPrototype%" , « [[AsyncGeneratorState]] , [[AsyncGeneratorContext]] , [[AsyncGeneratorQueue]] , [[GeneratorBrand]] »)。
设置 generator .[[GeneratorBrand]] 为
empty 。
设置 generator .[[AsyncGeneratorState]] 为
suspended-start 。
执行 AsyncGeneratorStart (generator ,
FunctionBody )。
返回 ReturnCompletion (generator )。
15.6.3 运行时语义:InstantiateAsyncGeneratorFunctionObject
语法制导操作
InstantiateAsyncGeneratorFunctionObject 接受参数 env (一个 Environment Record )和
privateEnv (一个 PrivateEnvironment Record 或
null ),并返回一个 ECMAScript 函数对象 。它按以下产生式分段定义:
AsyncGeneratorDeclaration
:
async
function
*
BindingIdentifier
(
FormalParameters
)
{
AsyncGeneratorBody
}
令 name 为 BindingIdentifier 的 StringValue 。
令 sourceText 为 AsyncGeneratorDeclaration
匹配的源文本 。
令 F 为 OrdinaryFunctionCreate (%AsyncGeneratorFunction.prototype% ,
sourceText , FormalParameters , AsyncGeneratorBody ,
non-lexical-this , env , privateEnv )。
执行 SetFunctionName (F ,
name )。
令 prototype 为 OrdinaryObjectCreate (%AsyncGeneratorPrototype% )。
执行 ! DefinePropertyOrThrow (F ,
"prototype" , PropertyDescriptor { [[Value]] :
prototype , [[Writable]] : true ,
[[Enumerable]] : false , [[Configurable]] : false })。
返回 F 。
AsyncGeneratorDeclaration
:
async
function
*
(
FormalParameters
)
{
AsyncGeneratorBody
}
令 sourceText 为 AsyncGeneratorDeclaration
匹配的源文本 。
令 F 为 OrdinaryFunctionCreate (%AsyncGeneratorFunction.prototype% ,
sourceText , FormalParameters , AsyncGeneratorBody ,
non-lexical-this , env , privateEnv )。
执行 SetFunctionName (F ,
"default" )。
令 prototype 为 OrdinaryObjectCreate (%AsyncGeneratorPrototype% )。
执行 ! DefinePropertyOrThrow (F ,
"prototype" , PropertyDescriptor { [[Value]] :
prototype , [[Writable]] : true ,
[[Enumerable]] : false , [[Configurable]] : false })。
返回 F 。
注释
匿名的 AsyncGeneratorDeclaration
只能作为 export default
声明的一部分出现。
15.6.4 运行时语义:InstantiateAsyncGeneratorFunctionExpression
语法制导操作
InstantiateAsyncGeneratorFunctionExpression 接受可选参数 name (一个 属性键 或 私有名称 ),并返回一个 ECMAScript 函数对象 。它按以下产生式分段定义:
AsyncGeneratorExpression
:
async
function
*
(
FormalParameters
)
{
AsyncGeneratorBody
}
如果 name 不存在,设置 name 为 "" 。
令 env 为 运行执行上下文 的 LexicalEnvironment。
令 privateEnv 为 运行执行上下文 的 PrivateEnvironment。
令 sourceText 为 AsyncGeneratorExpression
匹配的源文本 。
令 closure 为 OrdinaryFunctionCreate (%AsyncGeneratorFunction.prototype% ,
sourceText , FormalParameters , AsyncGeneratorBody ,
non-lexical-this , env , privateEnv )。
执行 SetFunctionName (closure ,
name )。
令 prototype 为 OrdinaryObjectCreate (%AsyncGeneratorPrototype% )。
执行 ! DefinePropertyOrThrow (closure ,
"prototype" , PropertyDescriptor { [[Value]] :
prototype , [[Writable]] : true ,
[[Enumerable]] : false , [[Configurable]] : false })。
返回 closure 。
AsyncGeneratorExpression
:
async
function
*
BindingIdentifier
(
FormalParameters
)
{
AsyncGeneratorBody
}
断言 :name 不存在。
设置 name 为 BindingIdentifier 的 StringValue 。
令 outerEnv 为 运行执行上下文 的 LexicalEnvironment。
令 funcEnv 为 NewDeclarativeEnvironment (outerEnv )。
执行 ! funcEnv .CreateImmutableBinding(name ,
false )。
令 privateEnv 为 运行执行上下文 的 PrivateEnvironment。
令 sourceText 为 AsyncGeneratorExpression
匹配的源文本 。
令 closure 为 OrdinaryFunctionCreate (%AsyncGeneratorFunction.prototype% ,
sourceText , FormalParameters , AsyncGeneratorBody ,
non-lexical-this , funcEnv , privateEnv )。
执行 SetFunctionName (closure ,
name )。
令 prototype 为 OrdinaryObjectCreate (%AsyncGeneratorPrototype% )。
执行 ! DefinePropertyOrThrow (closure ,
"prototype" , PropertyDescriptor { [[Value]] :
prototype , [[Writable]] : true ,
[[Enumerable]] : false , [[Configurable]] : false })。
执行 ! funcEnv .InitializeBinding(name ,
closure )。
返回 closure 。
注释
15.6.5 运行时语义:Evaluation
AsyncGeneratorExpression
:
async
function
*
BindingIdentifier opt
(
FormalParameters
)
{
AsyncGeneratorBody
}
返回 AsyncGeneratorExpression 的
InstantiateAsyncGeneratorFunctionExpression 。
15.7 类定义
语法
ClassDeclaration [Yield, Await,
Default] :
class
BindingIdentifier [?Yield,
?Await]
ClassTail [?Yield,
?Await]
[+Default]
class
ClassTail [?Yield,
?Await]
ClassExpression [Yield,
Await] :
class
BindingIdentifier [?Yield,
?Await] opt
ClassTail [?Yield,
?Await]
ClassTail [Yield,
Await] :
ClassHeritage [?Yield,
?Await] opt
{
ClassBody [?Yield,
?Await] opt
}
ClassHeritage [Yield,
Await] :
extends
LeftHandSideExpression [?Yield,
?Await]
ClassBody [Yield,
Await] :
ClassElementList [?Yield,
?Await]
ClassElementList [Yield,
Await] :
ClassElement [?Yield,
?Await]
ClassElementList [?Yield,
?Await]
ClassElement [?Yield,
?Await]
ClassElement [Yield,
Await] :
MethodDefinition [?Yield,
?Await]
static
MethodDefinition [?Yield,
?Await]
FieldDefinition [?Yield,
?Await]
;
static
FieldDefinition [?Yield,
?Await]
;
ClassStaticBlock
;
FieldDefinition [Yield,
Await] :
ClassElementName [?Yield,
?Await]
Initializer [+In, ?Yield,
?Await] opt
ClassElementName [Yield,
Await] :
PropertyName [?Yield,
?Await]
PrivateIdentifier
ClassStaticBlock :
static
{
ClassStaticBlockBody
}
ClassStaticBlockBody
:
ClassStaticBlockStatementList
ClassStaticBlockStatementList
:
StatementList [~Yield, +Await,
~Return] opt
注释
15.7.1 静态语义:早期错误
ClassTail :
ClassHeritage opt
{
ClassBody
}
ClassBody : ClassElementList
ClassElement : MethodDefinition
ClassElement :
static
MethodDefinition
ClassElement :
FieldDefinition
;
ClassElement :
static
FieldDefinition
;
FieldDefinition :
ClassElementName
Initializer opt
ClassElementName :
PrivateIdentifier
ClassStaticBlockBody
: ClassStaticBlockStatementList
15.7.2 静态语义:ClassElementKind
语法制导操作
ClassElementKind 不接受参数,返回
constructor-method 、non-constructor-method 或
empty 。它按以下产生式分段定义:
ClassElement : MethodDefinition
如果 MethodDefinition 的 PropName 是
"constructor" ,返回 constructor-method 。
返回 non-constructor-method 。
ClassElement :
static
MethodDefinition
FieldDefinition
;
static
FieldDefinition
;
返回 non-constructor-method 。
ClassElement : ClassStaticBlock
返回 non-constructor-method 。
ClassElement : ;
返回 empty 。
15.7.3 静态语义:ConstructorMethod
语法制导操作
ConstructorMethod 不接受参数,返回一个 ClassElement 解析节点 或
empty 。它按以下产生式分段定义:
ClassElementList :
ClassElement
如果 ClassElement 的
ClassElementKind 是
constructor-method ,返回 ClassElement 。
返回 empty 。
ClassElementList :
ClassElementList
ClassElement
令 head 为 ClassElementList 的 ConstructorMethod 。
如果 head 不是 empty ,返回 head 。
如果 ClassElement 的
ClassElementKind 是
constructor-method ,返回 ClassElement 。
返回 empty 。
注释
早期错误规则确保只有一个名为 "constructor" 的方法定义,并且它不是 访问器属性 或生成器定义。
15.7.4 静态语义:IsStatic
语法制导操作
IsStatic 不接受参数,返回一个布尔值。它按以下产生式分段定义:
ClassElement : MethodDefinition
返回 false 。
ClassElement :
static
MethodDefinition
返回 true 。
ClassElement :
FieldDefinition
;
返回 false 。
ClassElement :
static
FieldDefinition
;
返回 true 。
ClassElement : ClassStaticBlock
返回 true 。
ClassElement : ;
返回 false 。
15.7.5 静态语义:NonConstructorElements
语法制导操作
NonConstructorElements 不接受参数,返回一个 List of
ClassElement 解析节点 。它按以下产生式分段定义:
ClassElementList :
ClassElement
如果 ClassElement 的
ClassElementKind 是
non-constructor-method ,则
返回 « ClassElement »。
返回一个新的空 List 。
ClassElementList :
ClassElementList
ClassElement
令 list 为 ClassElementList 的 NonConstructorElements 。
如果 ClassElement 的
ClassElementKind 是
non-constructor-method ,则
将 ClassElement
追加到 list 的末尾。
返回 list 。
15.7.6 静态语义:PrototypePropertyNameList
语法制导操作
PrototypePropertyNameList 不接受参数,返回一个 List of
属性键 。它按以下产生式分段定义:
ClassElementList :
ClassElement
令 propName 为 ClassElement 的 PropName 。
如果 propName 是 empty ,返回一个新的空 List 。
如果 ClassElement 的
IsStatic 是
true ,返回一个新的空 List 。
返回 « propName »。
ClassElementList :
ClassElementList
ClassElement
令 list 为 ClassElementList 的 PrototypePropertyNameList 。
令 propName 为 ClassElement 的 PropName 。
如果 propName 是 empty ,返回 list 。
如果 ClassElement 的
IsStatic 是
true ,返回 list 。
返回 list 和 « propName » 的 列表连接 。
15.7.7 静态语义:AllPrivateIdentifiersValid
语法制导操作
AllPrivateIdentifiersValid 接受参数 names (一个 List of Strings),返回一个布尔值。
本规范中每个未在下面列出的语法产生式替代都隐含地具有以下 AllPrivateIdentifiersValid 的默认定义:
对于此 解析节点 的每个子节点 child ,执行
如果 child 是非终结符的实例,则
如果 child 的 AllPrivateIdentifiersValid
在参数 names 下是 false ,返回
false 。
返回 true 。
MemberExpression :
MemberExpression
.
PrivateIdentifier
如果 names 包含 PrivateIdentifier 的 StringValue ,则
返回 MemberExpression 的 AllPrivateIdentifiersValid
在参数 names 下的结果。
返回 false 。
CallExpression :
CallExpression
.
PrivateIdentifier
如果 names 包含 PrivateIdentifier 的 StringValue ,则
返回 CallExpression 的 AllPrivateIdentifiersValid
在参数 names 下的结果。
返回 false 。
OptionalChain :
?.
PrivateIdentifier
如果 names 包含 PrivateIdentifier 的 StringValue ,返回
true 。
返回 false 。
OptionalChain :
OptionalChain
.
PrivateIdentifier
如果 names 包含 PrivateIdentifier 的 StringValue ,则
返回 OptionalChain 的 AllPrivateIdentifiersValid
在参数 names 下的结果。
返回 false 。
ClassBody : ClassElementList
令 newNames 为 names 和 ClassBody 的 PrivateBoundIdentifiers
的 列表连接 。
返回 ClassElementList 的 AllPrivateIdentifiersValid
在参数 newNames 下的结果。
RelationalExpression
:
PrivateIdentifier
in
ShiftExpression
如果 names 包含 PrivateIdentifier 的 StringValue ,则
返回 ShiftExpression 的 AllPrivateIdentifiersValid
在参数 names 下的结果。
返回 false 。
15.7.8 静态语义:PrivateBoundIdentifiers
语法制导操作
PrivateBoundIdentifiers 不接受参数,返回一个 List of
Strings。它按以下产生式分段定义:
FieldDefinition :
ClassElementName
Initializer opt
返回 ClassElementName 的 PrivateBoundIdentifiers 。
ClassElementName :
PrivateIdentifier
返回一个 List ,其唯一元素是
PrivateIdentifier
的 StringValue 。
ClassElementName :
PropertyName
ClassElement :
ClassStaticBlock
;
返回一个新的空 List 。
ClassElementList :
ClassElementList
ClassElement
令 names1 为 ClassElementList 的 PrivateBoundIdentifiers 。
令 names2 为 ClassElement 的 PrivateBoundIdentifiers 。
返回 names1 和 names2 的 列表连接 。
MethodDefinition :
ClassElementName
(
UniqueFormalParameters
)
{
FunctionBody
}
get
ClassElementName
(
)
{
FunctionBody
}
set
ClassElementName
(
PropertySetParameterList
)
{
FunctionBody
}
GeneratorMethod :
*
ClassElementName
(
UniqueFormalParameters
)
{
GeneratorBody
}
AsyncMethod :
async
ClassElementName
(
UniqueFormalParameters
)
{
AsyncFunctionBody
}
AsyncGeneratorMethod
:
async
*
ClassElementName
(
UniqueFormalParameters
)
{
AsyncGeneratorBody
}
返回 ClassElementName 的 PrivateBoundIdentifiers 。
15.7.9 静态语义:ContainsArguments
语法制导操作
ContainsArguments 不接受参数,返回一个布尔值。
本规范中每个未在下面列出的语法产生式替代都隐含地具有以下 ContainsArguments 的默认定义:
对于此 解析节点 的每个子节点 child ,执行
如果 child 是非终结符的实例,则
如果 child 的 ContainsArguments
是 true ,返回 true 。
返回 false 。
IdentifierReference
: Identifier
如果 Identifier 的
StringValue 是
"arguments" ,返回 true 。
返回 false 。
FunctionDeclaration
:
function
BindingIdentifier
(
FormalParameters
)
{
FunctionBody
}
function
(
FormalParameters
)
{
FunctionBody
}
FunctionExpression
:
function
BindingIdentifier opt
(
FormalParameters
)
{
FunctionBody
}
GeneratorDeclaration
:
function
*
BindingIdentifier
(
FormalParameters
)
{
GeneratorBody
}
function
*
(
FormalParameters
)
{
GeneratorBody
}
GeneratorExpression
:
function
*
BindingIdentifier opt
(
FormalParameters
)
{
GeneratorBody
}
AsyncGeneratorDeclaration
:
async
function
*
BindingIdentifier
(
FormalParameters
)
{
AsyncGeneratorBody
}
async
function
*
(
FormalParameters
)
{
AsyncGeneratorBody
}
AsyncGeneratorExpression
:
async
function
*
BindingIdentifier opt
(
FormalParameters
)
{
AsyncGeneratorBody
}
AsyncFunctionDeclaration
:
async
function
BindingIdentifier
(
FormalParameters
)
{
AsyncFunctionBody
}
async
function
(
FormalParameters
)
{
AsyncFunctionBody
}
AsyncFunctionExpression
:
async
function
BindingIdentifier opt
(
FormalParameters
)
{
AsyncFunctionBody
}
返回 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
}
返回 ClassElementName 的 ContainsArguments 。
15.7.10 运行时语义:ClassFieldDefinitionEvaluation
语法制导操作
ClassFieldDefinitionEvaluation 接受参数 homeObject (一个 Object),返回一个 正常完成包含 一个 ClassFieldDefinition
Record 或一个 突然完成 。它按以下产生式分段定义:
FieldDefinition :
ClassElementName
Initializer opt
令 name 为 ? ClassElementName 的 Evaluation 。
如果 Initializer 存在,则
令 formalParameterList 为产生式
FormalParameters
: [empty]
的一个实例。
令 env 为 正在运行的执行上下文 的
LexicalEnvironment。
令 privateEnv 为 正在运行的执行上下文 的
PrivateEnvironment。
令 sourceText 为空的 Unicode 代码点序列。
令 initializer 为 OrdinaryFunctionCreate (%Function.prototype% ,
sourceText , formalParameterList , Initializer ,
non-lexical-this , env , privateEnv )。
执行 MakeMethod (initializer ,
homeObject )。
设置 initializer .[[ClassFieldInitializerName]]
为 name 。
否则,
令 initializer 为 empty 。
返回 ClassFieldDefinition
Record { [[Name]] : name , [[Initializer]] : initializer }。
注释
为 initializer 创建的函数永远不能被 ECMAScript 代码直接访问。
15.7.11 运行时语义:ClassStaticBlockDefinitionEvaluation
语法制导操作
ClassStaticBlockDefinitionEvaluation 接受参数 homeObject (一个 Object),返回一个 ClassStaticBlockDefinition
Record 。它按以下产生式分段定义:
ClassStaticBlock :
static
{
ClassStaticBlockBody
}
令 lex 为 正在运行的执行上下文 的
LexicalEnvironment。
令 privateEnv 为 正在运行的执行上下文 的
PrivateEnvironment。
令 sourceText 为空的 Unicode 代码点序列。
令 formalParameters 为产生式
FormalParameters
: [empty]
的一个实例。
令 bodyFunction 为 OrdinaryFunctionCreate (%Function.prototype% ,
sourceText , formalParameters , ClassStaticBlockBody ,
non-lexical-this , lex , privateEnv )。
执行 MakeMethod (bodyFunction ,
homeObject )。
返回 ClassStaticBlockDefinition
Record { [[BodyFunction]] :
bodyFunction }。
注释
函数 bodyFunction 永远不能被 ECMAScript 代码直接访问。
15.7.12 运行时语义:EvaluateClassStaticBlockBody
语法制导操作
EvaluateClassStaticBlockBody 接受参数 functionObject (一个 ECMAScript 函数对象 ),返回一个
返回完成 或一个 抛出完成 。它按以下产生式分段定义:
ClassStaticBlockBody
: ClassStaticBlockStatementList
断言 :functionObject 是由 ClassStaticBlockDefinitionEvaluation
步骤 5 创建的合成函数。
执行 ! FunctionDeclarationInstantiation (functionObject ,
« »)。
执行 ? ClassStaticBlockStatementList
的 Evaluation 。
返回 ReturnCompletion (undefined )。
15.7.13 运行时语义:ClassElementEvaluation
语法制导操作
ClassElementEvaluation 接受参数 object (一个 Object),返回一个 正常完成包含 一个 ClassFieldDefinition
Record 、一个 ClassStaticBlockDefinition
Record 、一个 PrivateElement 或
unused ,或一个 突然完成 。它按以下产生式分段定义:
ClassElement :
FieldDefinition
;
static
FieldDefinition
;
返回 ? FieldDefinition 的 ClassFieldDefinitionEvaluation ,参数为
object 。
ClassElement :
MethodDefinition
static
MethodDefinition
返回 ? MethodDefinition 的 MethodDefinitionEvaluation ,参数为
object 和 false 。
ClassElement : ClassStaticBlock
返回 ClassStaticBlock 的 ClassStaticBlockDefinitionEvaluation ,参数为
object 。
ClassElement : ;
返回 unused 。
15.7.14 运行时语义:ClassDefinitionEvaluation
语法制导操作
ClassDefinitionEvaluation 接受参数 classBinding (一个 String 或
undefined )和 className (一个 属性键 或一个 Private
Name ),返回一个 正常完成包含 一个
函数对象
或一个 突然完成 。
注释
为了便于规范,私有方法和访问器与私有字段一起包含在类实例的 [[PrivateElements]]
槽中。但是,任何给定对象要么拥有给定类定义的所有私有方法和访问器,要么一个都没有。这个特性的设计使得实现可以选择使用不需要单独跟踪每个方法或访问器的策略来实现私有方法和访问器。
例如,实现可以直接将实例私有方法与其相应的 Private Name 关联,并为每个对象跟踪哪些类 构造函数
曾以该对象作为其 this
值运行过。然后在对象上查找实例私有方法就包括检查定义该方法的类 构造函数 是否已被用于初始化该对象,然后返回与
Private
Name 关联的方法。
这与私有字段不同:因为字段初始化器可能在类实例化期间抛出异常,单个对象可能拥有给定类的私有字段的某个真子集,因此私有字段通常必须单独跟踪。
它按以下产生式分段定义:
ClassTail :
ClassHeritage opt
{
ClassBody opt
}
令 env 为 正在运行的执行上下文 的
LexicalEnvironment。
令 classEnv 为 NewDeclarativeEnvironment (env )。
如果 classBinding 不是 undefined ,则
执行 ! classEnv .CreateImmutableBinding(classBinding ,
true )。
令 outerPrivateEnvironment 为 正在运行的执行上下文 的
PrivateEnvironment。
令 classPrivateEnvironment 为 NewPrivateEnvironment (outerPrivateEnvironment )。
如果 ClassBody 存在,则
对于 ClassBody 的
PrivateBoundIdentifiers
中的每个 String dn ,执行
如果 classPrivateEnvironment .[[Names]]
包含一个 Private Name
pn 使得 pn .[[Description]]
是 dn ,则
断言 :这只可能发生在 getter/setter
对。
否则,
令 name 为一个新的 Private
Name ,其 [[Description]] 是 dn 。
将 name 追加到 classPrivateEnvironment .[[Names]] 。
如果 ClassHeritage
不存在,则
令 protoParent 为 %Object.prototype% 。
令 constructorParent 为 %Function.prototype% 。
否则,
设置 正在运行的执行上下文 的
LexicalEnvironment 为 classEnv 。
注释:当求值 ClassHeritage 时,正在运行的执行上下文 的
PrivateEnvironment 是 outerPrivateEnvironment 。
令 superclassRef 为 Completion (ClassHeritage 的
Evaluation )。
设置 正在运行的执行上下文 的
LexicalEnvironment 为 env 。
令 superclass 为 ? GetValue (?
superclassRef )。
如果 superclass 是 null ,则
令 protoParent 为 null 。
令 constructorParent 为 %Function.prototype% 。
否则,如果 IsConstructor (superclass )
是 false ,则
抛出 TypeError 异常。
否则,
令 protoParent 为 ? Get (superclass ,
"prototype" )。
如果 protoParent 不是对象 且
protoParent 不是 null ,抛出
TypeError 异常。
令 constructorParent 为 superclass 。
令 proto 为 OrdinaryObjectCreate (protoParent )。
如果 ClassBody 不存在,令
constructor 为 empty 。
否则,令 constructor 为 ClassBody 的 ConstructorMethod 。
设置 正在运行的执行上下文 的 LexicalEnvironment
为 classEnv 。
设置 正在运行的执行上下文 的 PrivateEnvironment
为 classPrivateEnvironment 。
如果 constructor 是 empty ,则
令 defaultConstructor 为一个新的 抽象闭包 ,不接受参数,不捕获任何值,调用时执行以下步骤:
令 args 为通过 [[Call]] 或 [[Construct]] 传递给此函数的参数 List 。
如果 NewTarget 是 undefined ,抛出
TypeError 异常。
令 F 为 活跃函数对象 。
如果 F .[[ConstructorKind]] 是
derived ,则
注释:此分支的行为类似于
constructor(...args) { super(...args); }
。最显著的区别是,虽然前述
ECMAScript 源文本
会可观察地调用 %Array.prototype%
上的 %Symbol.iterator%
方法,但此函数不会。
令 func 为 ! F .[[GetPrototypeOf]] ()。
如果 IsConstructor (func )
是 false ,抛出 TypeError 异常。
令 result 为 ? Construct (func ,
args , NewTarget)。
否则,
注释:此分支的行为类似于 constructor() {}
。
令 result 为 ? OrdinaryCreateFromConstructor (NewTarget,
"%Object.prototype%" )。
执行 ? InitializeInstanceElements (result ,
F )。
返回 result 。
令 F 为 CreateBuiltinFunction (defaultConstructor ,
0, className , « [[ConstructorKind]] , [[SourceText]] », 当前 Realm Record ,
constructorParent )。
否则,
令 constructorInfo 为 ! constructor 的 DefineMethod ,参数为
proto 和 constructorParent 。
令 F 为 constructorInfo .[[Closure]] 。
执行 MakeClassConstructor (F )。
执行 SetFunctionName (F ,
className )。
执行 MakeConstructor (F ,
false , proto )。
如果 ClassHeritage
存在,设置 F .[[ConstructorKind]] 为
derived 。
执行 ! DefineMethodProperty (proto ,
"constructor" , F , false )。
如果 ClassBody 不存在,令
elements 为一个新的空 List 。
否则,令 elements 为 ClassBody 的 NonConstructorElements 。
令 instancePrivateMethods 为一个新的空 List 。
令 staticPrivateMethods 为一个新的空 List 。
令 instanceFields 为一个新的空 List 。
令 staticElements 为一个新的空 List 。
对于 elements 中的每个 ClassElement e ,执行
如果 e 的 IsStatic 是
false ,则
令 element 为 Completion (e
的 ClassElementEvaluation ,参数为
proto )。
否则,
令 element 为 Completion (e
的 ClassElementEvaluation ,参数为
F )。
如果 element 是一个 突然完成 ,则
设置 正在运行的执行上下文 的
LexicalEnvironment 为 env 。
设置 正在运行的执行上下文 的
PrivateEnvironment 为 outerPrivateEnvironment 。
返回 ? element 。
设置 element 为 ! element 。
如果 element 是一个 PrivateElement ,则
断言 :element .[[Kind]] 是 method 或
accessor 。
如果 e 的 IsStatic 是
false ,令 container 为
instancePrivateMethods 。
否则,令 container 为 staticPrivateMethods 。
如果 container 包含一个 PrivateElement
pe 使得 pe .[[Key]] 是
element .[[Key]] ,则
断言 :element .[[Kind]] 和 pe .[[Kind]] 都是
accessor 。
如果 element .[[Get]] 是
undefined ,则
令 combined 为 PrivateElement
{ [[Key]] :
element .[[Key]] ,
[[Kind]] :
accessor , [[Get]] : pe .[[Get]] , [[Set]] : element .[[Set]] }。
否则,
令 combined 为 PrivateElement
{ [[Key]] :
element .[[Key]] ,
[[Kind]] :
accessor , [[Get]] : element .[[Get]] , [[Set]] : pe .[[Set]] }。
在 container 中将 pe 替换为 combined 。
否则,
将 element 追加到 container 。
否则,如果 element 是一个 ClassFieldDefinition
Record ,则
如果 e 的 IsStatic 是
false ,将 element 追加到
instanceFields 。
否则,将 element 追加到 staticElements 。
否则,如果 element 是一个 ClassStaticBlockDefinition
Record ,则
将 element 追加到 staticElements 。
设置 正在运行的执行上下文 的 LexicalEnvironment
为 env 。
如果 classBinding 不是 undefined ,则
执行 ! classEnv .InitializeBinding(classBinding ,
F )。
设置 F .[[PrivateMethods]] 为
instancePrivateMethods 。
设置 F .[[Fields]] 为 instanceFields 。
对于 staticPrivateMethods 中的每个 PrivateElement
method ,执行
执行 ! PrivateMethodOrAccessorAdd (F ,
method )。
对于 staticElements 中的每个元素 elementRecord ,执行
如果 elementRecord 是一个 ClassFieldDefinition
Record ,则
令 result 为 Completion (DefineField (F ,
elementRecord ))。
否则,
断言 :elementRecord 是一个
ClassStaticBlockDefinition
Record 。
令 result 为 Completion (Call (elementRecord .[[BodyFunction]] , F ))。
如果 result 是一个 突然完成 ,则
设置 正在运行的执行上下文 的
PrivateEnvironment 为 outerPrivateEnvironment 。
返回 ? result 。
设置 正在运行的执行上下文 的 PrivateEnvironment
为 outerPrivateEnvironment 。
返回 F 。
15.7.15 运行时语义:BindingClassDeclarationEvaluation
语法制导操作
BindingClassDeclarationEvaluation 不接受参数,返回一个 正常完成包含 一个 函数对象 或一个
突然完成 。它按以下产生式分段定义:
ClassDeclaration :
class
BindingIdentifier
ClassTail
令 className 为 BindingIdentifier 的 StringValue 。
令 value 为 ? ClassTail 的 ClassDefinitionEvaluation ,参数为
className 和 className 。
设置 value .[[SourceText]] 为 ClassDeclaration 匹配的源文本 。
令 env 为 正在运行的执行上下文 的
LexicalEnvironment。
执行 ? InitializeBoundName (className ,
value , env )。
返回 value 。
ClassDeclaration :
class
ClassTail
令 value 为 ? ClassTail 的 ClassDefinitionEvaluation ,参数为
undefined 和 "default" 。
设置 value .[[SourceText]] 为 ClassDeclaration 匹配的源文本 。
返回 value 。
注释
ClassDeclaration
:
class
ClassTail
只作为 ExportDeclaration
的一部分出现,其绑定的建立作为该产生式的求值操作的一部分处理。参见 16.2.3.7 。
15.7.16 运行时语义:Evaluation
ClassDeclaration :
class
BindingIdentifier
ClassTail
执行 ? 此 ClassDeclaration 的 BindingClassDeclarationEvaluation 。
返回 empty 。
注释
ClassExpression :
class
ClassTail
令 value 为 ? ClassTail 的 ClassDefinitionEvaluation ,参数为
undefined 和 "" 。
设置 value .[[SourceText]] 为 ClassExpression 匹配的源文本 。
返回 value 。
ClassExpression :
class
BindingIdentifier
ClassTail
令 className 为 BindingIdentifier 的 StringValue 。
令 value 为 ? ClassTail 的 ClassDefinitionEvaluation ,参数为
className 和 className 。
设置 value .[[SourceText]] 为 ClassExpression 匹配的源文本 。
返回 value 。
ClassElementName :
PrivateIdentifier
令 privateIdentifier 为 PrivateIdentifier 的 StringValue 。
令 privateEnvRec 为 正在运行的执行上下文 的
PrivateEnvironment。
令 names 为 privateEnvRec .[[Names]] 。
断言 :names 中恰好有一个元素是 Private
Name ,其 [[Description]] 是
privateIdentifier 。
令 privateName 为 names 中 [[Description]] 是
privateIdentifier 的 Private Name 。
返回 privateName 。
ClassStaticBlockStatementList
: [empty]
返回 undefined 。
15.8 异步函数定义
语法
AsyncFunctionDeclaration [Yield,
Await, Default] :
async
[no LineTerminator here]
function
BindingIdentifier [?Yield,
?Await]
(
FormalParameters [~Yield,
+Await]
)
{
AsyncFunctionBody
}
[+Default]
async
[no LineTerminator here]
function
(
FormalParameters [~Yield,
+Await]
)
{
AsyncFunctionBody
}
AsyncFunctionExpression
:
async
[no LineTerminator here]
function
BindingIdentifier [~Yield,
+Await] opt
(
FormalParameters [~Yield,
+Await]
)
{
AsyncFunctionBody
}
AsyncMethod [Yield,
Await] :
async
[no LineTerminator here]
ClassElementName [?Yield,
?Await]
(
UniqueFormalParameters [~Yield,
+Await]
)
{
AsyncFunctionBody
}
AsyncFunctionBody :
FunctionBody [~Yield,
+Await]
AwaitExpression [Yield]
:
await
UnaryExpression [?Yield,
+Await]
注释 1
当存在 [Await] 参数时,await
被解析为 AwaitExpression 的关键字 。[Await]
参数在以下上下文的顶层存在,尽管根据非终结符(如 FunctionBody ),在某些上下文中该参数可能不存在:
当 Script 是语法目标符号 时,当不存在 [Await]
参数时,await
可能被解析为标识符。这包括以下上下文:
注释 2
与 YieldExpression 不同,省略
AwaitExpression
的操作数是语法错误。你必须等待某些东西。
15.8.1 静态语义:早期错误
AsyncMethod :
async
ClassElementName
(
UniqueFormalParameters
)
{
AsyncFunctionBody
}
AsyncFunctionDeclaration
:
async
function
BindingIdentifier
(
FormalParameters
)
{
AsyncFunctionBody
}
async
function
(
FormalParameters
)
{
AsyncFunctionBody
}
AsyncFunctionExpression
:
async
function
BindingIdentifier opt
(
FormalParameters
)
{
AsyncFunctionBody
}
15.8.2 运行时语义:InstantiateAsyncFunctionObject
语法制导操作
InstantiateAsyncFunctionObject 接受参数 env (一个 Environment Record )和
privateEnv (一个 PrivateEnvironment Record 或
null ),返回一个 ECMAScript 函数对象 。它按以下产生式分段定义:
AsyncFunctionDeclaration
:
async
function
BindingIdentifier
(
FormalParameters
)
{
AsyncFunctionBody
}
令 name 为 BindingIdentifier 的 StringValue 。
令 sourceText 为 AsyncFunctionDeclaration
匹配的源文本 。
令 F 为 OrdinaryFunctionCreate (%AsyncFunction.prototype% ,
sourceText , FormalParameters , AsyncFunctionBody ,
non-lexical-this , env , privateEnv )。
执行 SetFunctionName (F ,
name )。
返回 F 。
AsyncFunctionDeclaration
:
async
function
(
FormalParameters
)
{
AsyncFunctionBody
}
令 sourceText 为 AsyncFunctionDeclaration
匹配的源文本 。
令 F 为 OrdinaryFunctionCreate (%AsyncFunction.prototype% ,
sourceText , FormalParameters , AsyncFunctionBody ,
non-lexical-this , env , privateEnv )。
执行 SetFunctionName (F ,
"default" )。
返回 F 。
15.8.3 运行时语义:InstantiateAsyncFunctionExpression
语法制导操作
InstantiateAsyncFunctionExpression 接受可选参数 name (一个 属性键 或一个 Private
Name ),返回一个 ECMAScript 函数对象 。它按以下产生式分段定义:
AsyncFunctionExpression
:
async
function
(
FormalParameters
)
{
AsyncFunctionBody
}
如果 name 不存在,设置 name 为 "" 。
令 env 为 正在运行的执行上下文 的
LexicalEnvironment。
令 privateEnv 为 正在运行的执行上下文 的
PrivateEnvironment。
令 sourceText 为 AsyncFunctionExpression
匹配的源文本 。
令 closure 为 OrdinaryFunctionCreate (%AsyncFunction.prototype% ,
sourceText , FormalParameters , AsyncFunctionBody ,
non-lexical-this , env , privateEnv )。
执行 SetFunctionName (closure ,
name )。
返回 closure 。
AsyncFunctionExpression
:
async
function
BindingIdentifier
(
FormalParameters
)
{
AsyncFunctionBody
}
断言 :name 不存在。
设置 name 为 BindingIdentifier 的 StringValue 。
令 outerEnv 为 正在运行的执行上下文 的
LexicalEnvironment。
令 funcEnv 为 NewDeclarativeEnvironment (outerEnv )。
执行 ! funcEnv .CreateImmutableBinding(name ,
false )。
令 privateEnv 为 正在运行的执行上下文 的
PrivateEnvironment。
令 sourceText 为 AsyncFunctionExpression
匹配的源文本 。
令 closure 为 OrdinaryFunctionCreate (%AsyncFunction.prototype% ,
sourceText , FormalParameters , AsyncFunctionBody ,
non-lexical-this , funcEnv , privateEnv )。
执行 SetFunctionName (closure ,
name )。
执行 ! funcEnv .InitializeBinding(name , closure )。
返回 closure 。
注释
15.8.4 运行时语义:EvaluateAsyncFunctionBody
语法制导操作
EvaluateAsyncFunctionBody 接受参数 functionObject (一个 ECMAScript 函数对象 )和
argumentsList (一个 List of
ECMAScript 语言值 ),返回一个 返回完成 。它按以下产生式分段定义:
AsyncFunctionBody
: FunctionBody
令 promiseCapability 为 ! NewPromiseCapability (%Promise% )。
令 completion 为 Completion (FunctionDeclarationInstantiation (functionObject ,
argumentsList ))。
如果 completion 是一个 突然完成 ,则
执行 ! Call (promiseCapability .[[Reject]] , undefined , «
completion .[[Value]] »)。
否则,
执行 AsyncFunctionStart (promiseCapability ,
FunctionBody )。
返回 ReturnCompletion (promiseCapability .[[Promise]] )。
15.8.5 运行时语义:Evaluation
AsyncFunctionExpression
:
async
function
BindingIdentifier opt
(
FormalParameters
)
{
AsyncFunctionBody
}
返回 AsyncFunctionExpression 的
InstantiateAsyncFunctionExpression 。
AwaitExpression :
await
UnaryExpression
令 exprRef 为 ? UnaryExpression 的 Evaluation 。
令 value 为 ? GetValue (exprRef )。
返回 ? Await (value )。
15.9 异步箭头函数定义
语法
AsyncArrowFunction [In, Yield,
Await] :
async
[no LineTerminator here]
AsyncArrowBindingIdentifier [?Yield]
[no LineTerminator here]
=>
AsyncConciseBody [?In]
CoverCallExpressionAndAsyncArrowHead [?Yield,
?Await]
[no LineTerminator here]
=>
AsyncConciseBody [?In]
AsyncConciseBody [In]
:
[lookahead ≠ { ]
ExpressionBody [?In,
+Await]
{
AsyncFunctionBody
}
AsyncArrowBindingIdentifier [Yield]
:
BindingIdentifier [?Yield,
+Await]
CoverCallExpressionAndAsyncArrowHead [Yield,
Await] :
MemberExpression [?Yield,
?Await]
Arguments [?Yield,
?Await]
补充语法
当处理产生式实例
AsyncArrowFunction
:
CoverCallExpressionAndAsyncArrowHead
=>
AsyncConciseBody
时,使用以下语法来细化对 CoverCallExpressionAndAsyncArrowHead
的解释:
AsyncArrowHead :
async
[no LineTerminator here]
ArrowFormalParameters [~Yield,
+Await]
15.9.1 静态语义:早期错误
AsyncArrowFunction
:
async
AsyncArrowBindingIdentifier
=>
AsyncConciseBody
AsyncArrowFunction
:
CoverCallExpressionAndAsyncArrowHead
=>
AsyncConciseBody
15.9.2 静态语义:AsyncConciseBodyContainsUseStrict
语法制导操作
AsyncConciseBodyContainsUseStrict 不接受参数,返回一个 Boolean。它按以下产生式分段定义:
AsyncConciseBody :
ExpressionBody
返回 false 。
AsyncConciseBody :
{
AsyncFunctionBody
}
返回 AsyncFunctionBody 的 FunctionBodyContainsUseStrict 。
15.9.3 运行时语义:EvaluateAsyncConciseBody
语法制导操作
EvaluateAsyncConciseBody 接受参数 functionObject (一个 ECMAScript 函数对象 )和
argumentsList (一个 List of
ECMAScript 语言值 ),返回一个 返回完成 。它按以下产生式分段定义:
AsyncConciseBody :
ExpressionBody
令 promiseCapability 为 ! NewPromiseCapability (%Promise% )。
令 completion 为 Completion (FunctionDeclarationInstantiation (functionObject ,
argumentsList ))。
如果 completion 是一个 突然完成 ,则
执行 ! Call (promiseCapability .[[Reject]] , undefined , «
completion .[[Value]] »)。
否则,
执行 AsyncFunctionStart (promiseCapability ,
ExpressionBody )。
返回 ReturnCompletion (promiseCapability .[[Promise]] )。
15.9.4 运行时语义:InstantiateAsyncArrowFunctionExpression
语法制导操作
InstantiateAsyncArrowFunctionExpression 接受可选参数 name (一个 属性键 或一个 Private
Name ),返回一个 ECMAScript 函数对象 。它按以下产生式分段定义:
AsyncArrowFunction
:
async
AsyncArrowBindingIdentifier
=>
AsyncConciseBody
如果 name 不存在,设置 name 为 "" 。
令 env 为 正在运行的执行上下文 的
LexicalEnvironment。
令 privateEnv 为 正在运行的执行上下文 的
PrivateEnvironment。
令 sourceText 为 AsyncArrowFunction 匹配的源文本 。
令 parameters 为 AsyncArrowBindingIdentifier 。
令 closure 为 OrdinaryFunctionCreate (%AsyncFunction.prototype% ,
sourceText , parameters , AsyncConciseBody ,
lexical-this , env , privateEnv )。
执行 SetFunctionName (closure ,
name )。
返回 closure 。
AsyncArrowFunction
:
CoverCallExpressionAndAsyncArrowHead
=>
AsyncConciseBody
如果 name 不存在,设置 name 为 "" 。
令 env 为 正在运行的执行上下文 的
LexicalEnvironment。
令 privateEnv 为 正在运行的执行上下文 的
PrivateEnvironment。
令 sourceText 为 AsyncArrowFunction 匹配的源文本 。
令 head 为被 CoverCallExpressionAndAsyncArrowHead
覆盖 的 AsyncArrowHead 。
令 parameters 为 head 的 ArrowFormalParameters 。
令 closure 为 OrdinaryFunctionCreate (%AsyncFunction.prototype% ,
sourceText , parameters , AsyncConciseBody ,
lexical-this , env , privateEnv )。
执行 SetFunctionName (closure ,
name )。
返回 closure 。
15.9.5 运行时语义:Evaluation
AsyncArrowFunction
:
async
AsyncArrowBindingIdentifier
=>
AsyncConciseBody
CoverCallExpressionAndAsyncArrowHead
=>
AsyncConciseBody
返回 AsyncArrowFunction 的 InstantiateAsyncArrowFunctionExpression 。
15.10 尾位置调用
15.10.1 静态语义:IsInTailPosition ( call )
抽象操作 IsInTailPosition 接受参数 call (一个 CallExpression 解析节点 、一个 MemberExpression 解析节点 ,或一个 OptionalChain 解析节点 ),返回一个 Boolean。调用时执行以下步骤:
如果 IsStrict (call ) 是
false ,返回 false 。
如果 call 不包含在 FunctionBody 、ConciseBody 或 AsyncConciseBody 中,返回
false 。
令 body 为最紧密包含 call 的 FunctionBody 、ConciseBody 或 AsyncConciseBody 。
如果 body 是 GeneratorBody 的 FunctionBody ,返回
false 。
如果 body 是 AsyncFunctionBody 的 FunctionBody ,返回
false 。
如果 body 是 AsyncGeneratorBody 的 FunctionBody ,返回
false 。
如果 body 是 AsyncConciseBody ,返回
false 。
返回 body 以参数 call 进行的 HasCallInTailPosition
的结果。
注释
尾位置调用仅在 严格模式代码 中定义,因为有一个常见的非标准语言扩展(参见
10.2.4 )可以观察调用者上下文链。
15.10.2 静态语义:HasCallInTailPosition
语法制导操作
HasCallInTailPosition 接受参数 call (一个 CallExpression 解析节点 、一个 MemberExpression 解析节点 ,或一个 OptionalChain 解析节点 ),返回一个 Boolean。
注释 1
call 是一个 解析节点 ,表示特定范围的源文本。当以下算法将
call 与另一个 解析节点 进行比较时,这是测试它们是否表示相同的源文本。
注释 2
紧接着返回调用结果的 GetValue 的潜在尾位置调用也是可能的尾位置调用。函数调用不能返回
Reference
Record ,因此这样的 GetValue 操作将总是返回与实际函数调用结果相同的值。
它按以下产生式分段定义:
StatementList :
StatementList
StatementListItem
令 has 为 StatementList 以参数 call 进行的
HasCallInTailPosition 。
如果 has 是 true ,返回 true 。
返回 StatementListItem 以参数
call 进行的 HasCallInTailPosition 。
FunctionStatementList
:
[empty]
StatementListItem
:
Declaration
Statement :
VariableStatement
EmptyStatement
ExpressionStatement
ContinueStatement
BreakStatement
ThrowStatement
DebuggerStatement
Block :
{
}
ReturnStatement :
return
;
LabelledItem :
FunctionDeclaration
ForInOfStatement :
for
(
LeftHandSideExpression
of
AssignmentExpression
)
Statement
for
(
var
ForBinding
of
AssignmentExpression
)
Statement
for
(
ForDeclaration
of
AssignmentExpression
)
Statement
CaseBlock :
{
}
返回 false 。
IfStatement :
if
(
Expression
)
Statement
else
Statement
令 has 为第一个 Statement 以参数 call 进行的 HasCallInTailPosition 。
如果 has 是 true ,返回 true 。
返回第二个 Statement 以参数
call 进行的 HasCallInTailPosition 。
IfStatement :
if
(
Expression
)
Statement
DoWhileStatement :
do
Statement
while
(
Expression
)
;
WhileStatement :
while
(
Expression
)
Statement
ForStatement :
for
(
Expression opt
;
Expression opt
;
Expression opt
)
Statement
for
(
var
VariableDeclarationList
;
Expression opt
;
Expression opt
)
Statement
for
(
LexicalDeclaration
Expression opt
;
Expression opt
)
Statement
ForInOfStatement :
for
(
LeftHandSideExpression
in
Expression
)
Statement
for
(
var
ForBinding
in
Expression
)
Statement
for
(
ForDeclaration
in
Expression
)
Statement
WithStatement :
with
(
Expression
)
Statement
返回 Statement 以参数
call 进行的 HasCallInTailPosition 。
LabelledStatement
:
LabelIdentifier
:
LabelledItem
返回 LabelledItem 以参数
call 进行的 HasCallInTailPosition 。
ReturnStatement :
return
Expression
;
返回 Expression 以参数
call 进行的 HasCallInTailPosition 。
SwitchStatement :
switch
(
Expression
)
CaseBlock
返回 CaseBlock 以参数
call 进行的 HasCallInTailPosition 。
CaseBlock :
{
CaseClauses opt
DefaultClause
CaseClauses opt
}
令 has 为 false 。
如果存在第一个 CaseClauses ,将
has 设置为第一个 CaseClauses 以参数 call 进行的
HasCallInTailPosition 。
如果 has 是 true ,返回 true 。
将 has 设置为 DefaultClause 以参数 call 进行的
HasCallInTailPosition 。
如果 has 是 true ,返回 true 。
如果存在第二个 CaseClauses ,将
has 设置为第二个 CaseClauses 以参数 call 进行的
HasCallInTailPosition 。
返回 has 。
CaseClauses :
CaseClauses
CaseClause
令 has 为 CaseClauses 以参数 call 进行的
HasCallInTailPosition 。
如果 has 是 true ,返回 true 。
返回 CaseClause 以参数
call 进行的 HasCallInTailPosition 。
CaseClause :
case
Expression
:
StatementList opt
DefaultClause :
default
:
StatementList opt
如果存在 StatementList ,返回
StatementList 以参数
call 进行的 HasCallInTailPosition 。
返回 false 。
TryStatement :
try
Block
Catch
返回 Catch 以参数 call
进行的 HasCallInTailPosition 。
TryStatement :
try
Block
Finally
try
Block
Catch
Finally
返回 Finally 以参数
call 进行的 HasCallInTailPosition 。
Catch :
catch
(
CatchParameter
)
Block
返回 Block 以参数 call
进行的 HasCallInTailPosition 。
AssignmentExpression
:
YieldExpression
ArrowFunction
AsyncArrowFunction
LeftHandSideExpression
=
AssignmentExpression
LeftHandSideExpression
AssignmentOperator
AssignmentExpression
LeftHandSideExpression
&&=
AssignmentExpression
LeftHandSideExpression
||=
AssignmentExpression
LeftHandSideExpression
??=
AssignmentExpression
BitwiseANDExpression
:
BitwiseANDExpression
&
EqualityExpression
BitwiseXORExpression
:
BitwiseXORExpression
^
BitwiseANDExpression
BitwiseORExpression
:
BitwiseORExpression
|
BitwiseXORExpression
EqualityExpression
:
EqualityExpression
==
RelationalExpression
EqualityExpression
!=
RelationalExpression
EqualityExpression
===
RelationalExpression
EqualityExpression
!==
RelationalExpression
RelationalExpression
:
RelationalExpression
<
ShiftExpression
RelationalExpression
>
ShiftExpression
RelationalExpression
<=
ShiftExpression
RelationalExpression
>=
ShiftExpression
RelationalExpression
instanceof
ShiftExpression
RelationalExpression
in
ShiftExpression
PrivateIdentifier
in
ShiftExpression
ShiftExpression :
ShiftExpression
<<
AdditiveExpression
ShiftExpression
>>
AdditiveExpression
ShiftExpression
>>>
AdditiveExpression
AdditiveExpression
:
AdditiveExpression
+
MultiplicativeExpression
AdditiveExpression
-
MultiplicativeExpression
MultiplicativeExpression
:
MultiplicativeExpression
MultiplicativeOperator
ExponentiationExpression
ExponentiationExpression
:
UpdateExpression
**
ExponentiationExpression
UpdateExpression :
LeftHandSideExpression
++
LeftHandSideExpression
--
++
UnaryExpression
--
UnaryExpression
UnaryExpression :
delete
UnaryExpression
void
UnaryExpression
typeof
UnaryExpression
+
UnaryExpression
-
UnaryExpression
~
UnaryExpression
!
UnaryExpression
AwaitExpression
CallExpression :
SuperCall
ImportCall
CallExpression
[
Expression
]
CallExpression
.
IdentifierName
CallExpression
.
PrivateIdentifier
NewExpression :
new
NewExpression
MemberExpression :
MemberExpression
[
Expression
]
MemberExpression
.
IdentifierName
SuperProperty
MetaProperty
new
MemberExpression
Arguments
MemberExpression
.
PrivateIdentifier
PrimaryExpression
:
this
IdentifierReference
Literal
ArrayLiteral
ObjectLiteral
FunctionExpression
ClassExpression
GeneratorExpression
AsyncFunctionExpression
AsyncGeneratorExpression
RegularExpressionLiteral
TemplateLiteral
返回 false 。
Expression :
AssignmentExpression
Expression
,
AssignmentExpression
返回 AssignmentExpression 以参数
call 进行的 HasCallInTailPosition 。
ConditionalExpression
:
ShortCircuitExpression
?
AssignmentExpression
:
AssignmentExpression
令 has 为第一个 AssignmentExpression 以参数
call 进行的 HasCallInTailPosition 。
如果 has 是 true ,返回 true 。
返回第二个 AssignmentExpression 以参数
call 进行的 HasCallInTailPosition 。
LogicalANDExpression
:
LogicalANDExpression
&&
BitwiseORExpression
返回 BitwiseORExpression 以参数
call 进行的 HasCallInTailPosition 。
LogicalORExpression
:
LogicalORExpression
||
LogicalANDExpression
返回 LogicalANDExpression 以参数
call 进行的 HasCallInTailPosition 。
CoalesceExpression
:
CoalesceExpressionHead
??
BitwiseORExpression
返回 BitwiseORExpression 以参数
call 进行的 HasCallInTailPosition 。
CallExpression :
CoverCallExpressionAndAsyncArrowHead
CallExpression
Arguments
CallExpression
TemplateLiteral
如果此 CallExpression 是
call ,返回 true 。
返回 false 。
OptionalExpression
:
MemberExpression
OptionalChain
CallExpression
OptionalChain
OptionalExpression
OptionalChain
返回 OptionalChain 以参数
call 进行的 HasCallInTailPosition 。
OptionalChain :
?.
[
Expression
]
?.
IdentifierName
?.
PrivateIdentifier
OptionalChain
[
Expression
]
OptionalChain
.
IdentifierName
OptionalChain
.
PrivateIdentifier
返回 false 。
OptionalChain :
?.
Arguments
OptionalChain
Arguments
如果此 OptionalChain 是
call ,返回 true 。
返回 false 。
MemberExpression :
MemberExpression
TemplateLiteral
如果此 MemberExpression 是 call ,返回
true 。
返回 false 。
PrimaryExpression
: CoverParenthesizedExpressionAndArrowParameterList
令 expr 为被 CoverParenthesizedExpressionAndArrowParameterList
覆盖 的 ParenthesizedExpression 。
返回 expr 以参数 call 进行的 HasCallInTailPosition 。
ParenthesizedExpression
:
(
Expression
)
返回 Expression 以参数
call 进行的 HasCallInTailPosition 。
15.10.3 PrepareForTailCall ( )
抽象操作 PrepareForTailCall 不接受参数,返回 unused 。调用时执行以下步骤:
断言 :当前 执行上下文 随后不会用于任何 ECMAScript
代码或内置函数的求值。在调用此抽象操作之后对 Call 的调用将在执行任何此类求值之前创建并推入一个新的 执行上下文 。
丢弃与当前 执行上下文 关联的所有资源。
返回 unused 。
尾位置调用必须在调用目标函数之前释放与当前执行函数 执行上下文 关联的任何瞬态内部资源,或重用这些资源来支持目标函数。
注释
例如,尾位置调用应该仅按目标函数的激活记录大小超出调用函数激活记录大小的量来增长实现的激活记录栈。如果目标函数的激活记录更小,则栈的总大小应该减少。
16 ECMAScript 语言:脚本和模块
16.1 脚本
语法
Script :
ScriptBody opt
ScriptBody :
StatementList [~Yield, ~Await,
~Return]
16.1.1 静态语义:早期错误
Script : ScriptBody
ScriptBody : StatementList
16.1.2 静态语义:ScriptIsStrict
语法制导操作
ScriptIsStrict 不接受参数,返回一个 Boolean。它按以下产生式分段定义:
Script : ScriptBody opt
如果 ScriptBody 存在且
ScriptBody 的 指令序言 包含一个 Use
Strict 指令 ,返回 true ;否则,返回
false 。
16.1.3 运行时语义:Evaluation
Script : [empty]
返回 undefined 。
16.1.4 脚本记录
脚本记录 封装了关于被求值脚本的信息。每个脚本记录包含
表
39 中列出的字段。
表 39:脚本记录 字段
16.1.5 ParseScript ( sourceText , realm ,
hostDefined )
抽象操作 ParseScript 接受参数 sourceText (ECMAScript 源文本 )、realm (一个 Realm Record )和
hostDefined (任何东西),返回一个 脚本记录 或一个非空的 SyntaxError 对象
List 。它基于将
sourceText 解析为 Script
的结果创建一个 脚本记录 。调用时执行以下步骤:
令 script 为 ParseText (sourceText , Script )。
如果 script 是一个错误的 List ,返回
script 。
返回 脚本记录 { [[Realm]] :
realm ,
[[ECMAScriptCode]] : script , [[LoadedModules]] : « », [[HostDefined]] : hostDefined }。
注释
实现可以在对该脚本源文本执行 ParseScript 之前解析脚本源文本并分析其早期错误条件。但是,任何错误的报告必须推迟到本规范实际对该源文本执行 ParseScript
的时候。
16.1.6 ScriptEvaluation ( scriptRecord )
抽象操作 ScriptEvaluation 接受参数 scriptRecord (一个 脚本记录 ),返回包含一个 ECMAScript 语言值 的 正常完成 或一个 突然完成 。调用时执行以下步骤:
令 globalEnv 为 scriptRecord .[[Realm]] .[[GlobalEnv]] 。
令 scriptContext 为一个新的 ECMAScript
代码执行上下文 。
设置 scriptContext 的 Function 为 null 。
设置 scriptContext 的 Realm 为 scriptRecord .[[Realm]] 。
设置 scriptContext 的 ScriptOrModule 为 scriptRecord 。
设置 scriptContext 的 VariableEnvironment 为 globalEnv 。
设置 scriptContext 的 LexicalEnvironment 为 globalEnv 。
设置 scriptContext 的 PrivateEnvironment 为 null 。
挂起 正在运行的执行上下文 。
将 scriptContext 推入 执行上下文栈 ;scriptContext
现在是 正在运行的执行上下文 。
令 script 为 scriptRecord .[[ECMAScriptCode]] 。
令 result 为 Completion (GlobalDeclarationInstantiation (script ,
globalEnv ))。
如果 result 是一个 正常完成 ,则
设置 result 为 Completion (script 的
Evaluation )。
如果 result 是一个 正常完成 且
result .[[Value]] 是
empty ,则
设置 result 为 NormalCompletion (undefined )。
挂起 scriptContext 并将其从 执行上下文栈 中移除。
断言 :执行上下文栈 不为空。
恢复现在位于 执行上下文栈 顶部的上下文作为 正在运行的执行上下文 。
返回 ? result 。
16.1.7 GlobalDeclarationInstantiation ( script ,
env )
抽象操作 GlobalDeclarationInstantiation 接受参数 script (一个 Script 解析节点 )和 env (一个
全局环境记录 ),返回包含
unused 的 正常完成 或一个
抛出完成 。script
是正在为其建立 执行上下文 的 Script 。env 是要在其中创建绑定的全局环境。
注释 1
当为求值脚本建立 执行上下文
时,声明在当前全局环境中实例化。代码中声明的每个全局绑定都被实例化。
调用时执行以下步骤:
令 lexNames 为 script 的 LexicallyDeclaredNames 。
令 varNames 为 script 的 VarDeclaredNames 。
对于 lexNames 的每个元素 name ,执行
如果 HasLexicalDeclaration (env ,
name ) 是 true ,抛出一个 SyntaxError
异常。
令 hasRestrictedGlobal 为 ? HasRestrictedGlobalProperty (env ,
name )。
注释:全局 var
和 function
绑定(除了由非严格 直接
eval 引入的那些)是不可配置的,因此是受限制的全局属性。
如果 hasRestrictedGlobal 是 true ,抛出一个
SyntaxError 异常。
对于 varNames 的每个元素 name ,执行
如果 HasLexicalDeclaration (env ,
name ) 是 true ,抛出一个 SyntaxError
异常。
令 varDeclarations 为 script 的 VarScopedDeclarations 。
令 functionsToInitialize 为一个新的空 List 。
令 declaredFunctionNames 为一个新的空 List 。
对于 varDeclarations 的每个元素 d ,按反向 List 顺序,执行
如果 d 不是 VariableDeclaration 、ForBinding 或 BindingIdentifier ,则
断言 :d 是 FunctionDeclaration 、GeneratorDeclaration 、AsyncFunctionDeclaration
或 AsyncGeneratorDeclaration 。
注释:如果同一个名称有多个函数声明,使用最后的声明。
令 fn 为 d 的 BoundNames
的唯一元素。
如果 declaredFunctionNames 不包含 fn ,则
令 fnDefinable 为 ? CanDeclareGlobalFunction (env ,
fn )。
如果 fnDefinable 是 false ,抛出一个
TypeError 异常。
将 fn 追加到 declaredFunctionNames 。
将 d 作为 functionsToInitialize 的第一个元素插入。
令 declaredVarNames 为一个新的空 List 。
对于 varDeclarations 的每个元素 d ,执行
如果 d 是 VariableDeclaration 、ForBinding 或 BindingIdentifier ,则
对于 d 的 BoundNames
的每个字符串 vn ,执行
如果 declaredFunctionNames 不包含 vn ,则
令 vnDefinable 为 ? CanDeclareGlobalVar (env ,
vn )。
如果 vnDefinable 是
false ,抛出一个
TypeError 异常。
如果 declaredVarNames 不包含 vn ,则
将 vn 追加到 declaredVarNames 。
注释:如果 全局对象 是一个 普通对象 ,则在此算法步骤之后不会发生异常终止。但是,如果 全局对象 是一个 Proxy
异质对象 ,它可能表现出在以下某些步骤中导致异常终止的行为。
注释:附录 B.3.2.2
在此处添加了附加步骤。
令 lexDeclarations 为 script 的 LexicallyScopedDeclarations 。
令 privateEnv 为 null 。
对于 lexDeclarations 的每个元素 d ,执行
注释:词法声明的名称仅在此处实例化但不初始化。
对于 d 的 BoundNames 的每个元素
dn ,执行
如果 d 的 IsConstantDeclaration
是 true ,则
执行 ? env .CreateImmutableBinding (dn ,
true )。
否则,
执行 ? env .CreateMutableBinding (dn ,
false )。
对于 functionsToInitialize 的每个 解析节点 f ,执行
令 fn 为 f 的 BoundNames 的唯一元素。
令 fo 为 f 以参数 env 和 privateEnv 进行的
InstantiateFunctionObject 。
执行 ? CreateGlobalFunctionBinding (env ,
fn , fo , false )。
对于 declaredVarNames 的每个字符串 vn ,执行
执行 ? CreateGlobalVarBinding (env ,
vn , false )。
返回 unused 。
注释 2
16.1.1 中指定的
早期错误
防止了函数/var 声明与 let/const/class 声明之间的名称冲突,以及单个 Script 内包含的声明的 let/const/class
绑定的重新声明。但是,这种跨越多个 Script
的冲突和重新声明在 GlobalDeclarationInstantiation 期间被检测为运行时错误。如果检测到任何此类错误,则不会为脚本实例化绑定。但是,如果
全局对象 使用 Proxy
异质对象 定义,则冲突声明的运行时测试可能不可靠,导致 突然完成
和一些全局声明未被实例化。如果发生这种情况,Script
的代码不会被求值。
与显式的 var 或 function 声明不同,直接在 全局对象 上创建的属性会导致可能被 let/const/class
声明遮蔽的全局绑定。
16.2 模块
语法
Module :
ModuleBody opt
ModuleBody :
ModuleItemList
ModuleItemList :
ModuleItem
ModuleItemList
ModuleItem
ModuleItem :
ImportDeclaration
ExportDeclaration
StatementListItem [~Yield,
+Await, ~Return]
ModuleExportName :
IdentifierName
StringLiteral
16.2.1 模块语义
16.2.1.1 静态语义:早期错误
ModuleBody : ModuleItemList
注
重复 ExportedNames 规则
意味着在 ModuleBody
中包含多个 export default
ExportDeclaration 项是语法错误。在
Module
求值之前的模块链接期间检查与冲突或重复声明相关的其他错误条件。如果检测到任何此类错误,则不会对 Module 进行求值。
ModuleExportName
: StringLiteral
16.2.1.2 静态语义:ImportedLocalNames (
importEntries )
抽象操作 ImportedLocalNames 接受参数 importEntries (一个
List of ImportEntry
Records )并返回一个字符串的 List 。它创建一个包含所有由
importEntries 定义的本地名称绑定的 List 。调用时它执行以下步骤:
让 localNames 为一个新的空 List 。
对于 importEntries 的每个 ImportEntry Record
i ,执行
将 i .[[LocalName]] 追加到
localNames 。
返回 localNames 。
16.2.1.3 ModuleRequest 记录
ModuleRequest
Record 表示带有给定导入属性的模块导入请求。它由以下字段组成:
表 40:ModuleRequest Record 字段
LoadedModuleRequest Record 表示模块导入请求以及结果 Module Record 。它由表 表
40 中定义的相同字段组成,并添加了
[[Module]] :
表 41:LoadedModuleRequest Record
字段
ImportAttribute Record 由以下字段组成:
表 42:ImportAttribute Record 字段
字段名称
值类型
含义
[[Key]]
一个字符串
属性键
[[Value]]
一个字符串
属性值
16.2.1.3.1 ModuleRequestsEqual ( left ,
right )
抽象操作 ModuleRequestsEqual 接受参数 left (一个 ModuleRequest Record
或一个 LoadedModuleRequest Record )
和 right (一个 ModuleRequest Record 或一个 LoadedModuleRequest Record )
并返回一个布尔值。调用时它执行以下步骤:
如果 left .[[Specifier]] 不是
right .[[Specifier]] ,返回
false 。
让 leftAttrs 为 left .[[Attributes]] 。
让 rightAttrs 为 right .[[Attributes]] 。
让 leftAttrsCount 为 leftAttrs 中元素的数量。
让 rightAttrsCount 为 rightAttrs 中元素的数量。
如果 leftAttrsCount ≠ rightAttrsCount ,返回
false 。
对于 leftAttrs 的每个 ImportAttribute
Record
l ,执行
如果 rightAttrs 不包含一个 ImportAttribute
Record r 使得 l .[[Key]] 是 r .[[Key]] 且 l .[[Value]] 是 r .[[Value]] ,返回 false 。
返回 true 。
16.2.1.4 静态语义:ModuleRequests
语法导向操作
ModuleRequests 不接受参数并返回一个 List of
ModuleRequest Records 。它对以下产生式逐段定义:
Module : [empty]
返回一个新的空 List 。
ModuleItemList :
ModuleItem
返回 ModuleItem 的
ModuleRequests 。
ModuleItemList :
ModuleItemList
ModuleItem
让 requests 为 ModuleItemList 的 ModuleRequests 。
让 additionalRequests 为 ModuleItem 的 ModuleRequests 。
对于 additionalRequests 的每个 ModuleRequest
Record
mr ,执行
如果 requests 不包含一个 ModuleRequest
Record
mr2 使得 ModuleRequestsEqual (mr ,
mr2 ) 是 true ,那么
将 mr 追加到 requests 。
返回 requests 。
ModuleItem : StatementListItem
返回一个新的空 List 。
ImportDeclaration
:
import
ImportClause
FromClause
;
让 specifier 为 FromClause 的 SV 。
返回一个 List ,其唯一元素是
ModuleRequest Record { [[Specifier]] : specifier , [[Attributes]] : « » }。
ImportDeclaration
:
import
ImportClause
FromClause
WithClause
;
让 specifier 为 FromClause 的 SV 。
让 attributes 为 WithClause 的 WithClauseToAttributes 。
返回一个 List ,其唯一元素是
ModuleRequest Record { [[Specifier]] : specifier , [[Attributes]] : attributes }。
ImportDeclaration
:
import
ModuleSpecifier
;
让 specifier 为 ModuleSpecifier 的 SV 。
返回一个 List ,其唯一元素是
ModuleRequest Record { [[Specifier]] : specifier , [[Attributes]] : « » }。
ImportDeclaration
:
import
ModuleSpecifier
WithClause
;
让 specifier 为 ModuleSpecifier 的 SV 。
让 attributes 为 WithClause 的 WithClauseToAttributes 。
返回一个 List ,其唯一元素是
ModuleRequest Record { [[Specifier]] : specifier , [[Attributes]] : attributes }。
ExportDeclaration
:
export
ExportFromClause
FromClause
;
让 specifier 为 FromClause 的 SV 。
返回一个 List ,其唯一元素是
ModuleRequest Record { [[Specifier]] : specifier , [[Attributes]] : « » }。
ExportDeclaration
:
export
ExportFromClause
FromClause
WithClause
;
让 specifier 为 FromClause 的 SV 。
让 attributes 为 WithClause 的 WithClauseToAttributes 。
返回一个 List ,其唯一元素是
ModuleRequest Record { [[Specifier]] : specifier , [[Attributes]] : attributes }。
ExportDeclaration
:
export
NamedExports
;
export
VariableStatement
export
Declaration
export
default
HoistableDeclaration
export
default
ClassDeclaration
export
default
AssignmentExpression
;
返回一个新的空 List 。
16.2.1.5 抽象模块记录
Module Record
封装了单个模块的导入和导出的结构信息。此信息用于链接连接模块集合的导入和导出。Module Record 包含四个仅在求值模块时使用的字段。
出于规范目的,Module Record 值是 Record
规范类型的值,可以认为存在于一个简单的面向对象层次结构中,其中 Module
Record 是一个抽象类,具有抽象和具体子类。本规范定义了名为 Cyclic Module Record 的抽象子类及其名为 Source
Text Module Record 的具体子类。其他规范和实现可以定义对应于它们定义的替代模块定义设施的额外 Module Record
子类。
Module Record 定义了 表 43 中列出的字段。所有 Module
Definition 子类至少包含这些字段。Module Record 还定义了 表 44 中的抽象方法列表。所有
Module
definition 子类必须提供这些抽象方法的具体实现。
表 43:Module Record 字段
表 44:Module
Records 的抽象方法
方法
目的
LoadRequestedModules([hostDefined ])
通过递归加载所有依赖项为链接准备模块,并返回一个 promise。
GetExportedNames([exportStarSet ])
返回从此模块直接或间接导出的所有名称的列表。
在调用此方法之前,LoadRequestedModules 必须已成功完成。
ResolveExport(exportName [, resolveSet ])
返回此模块导出的名称的绑定。绑定由 ResolvedBinding
Record 表示,形式为 { [[Module]] :
Module
Record , [[BindingName]] : String |
namespace }。如果导出是没有任何模块中直接绑定的模块命名空间对象,[[BindingName]] 将设置为
namespace 。如果名称无法解析,返回
null ,如果找到多个绑定,返回
ambiguous 。
每次使用特定的 exportName 、resolveSet
对作为参数调用此操作时,必须返回相同的结果。
在调用此方法之前,LoadRequestedModules 必须已成功完成。
Link()
通过传递性地解析所有模块依赖项并创建 Module
Environment
Record 为求值准备模块。
在调用此方法之前,LoadRequestedModules 必须已成功完成。
Evaluate()
返回用于此模块及其依赖项求值的 promise,在成功求值或已成功求值时解析,在求值错误或已求值失败时拒绝。如果 promise
被拒绝,期望 宿主 处理 promise 拒绝并重新抛出求值错误。
在调用此方法之前,Link 必须已成功完成。
16.2.1.5.1 EvaluateModuleSync ( module )
抽象操作 EvaluateModuleSync 接受参数 module (一个 Module Record )并返回
一个 正常完成,包含
unused 或一个 抛出完成 。它同步求值
module ,前提是调用者保证 module 的求值将返回一个已经结算的 promise。调用时它执行以下步骤:
断言 :
module 不是 Cyclic Module
Record 。
让 promise 为 module .Evaluate()。
断言 :
promise .[[PromiseState]] 是
fulfilled 或 rejected 。
如果 promise .[[PromiseState]] 是
rejected ,那么
如果 promise .[[PromiseIsHandled]] 是
false ,执行 HostPromiseRejectionTracker (promise ,
"handle" )。
设置 promise .[[PromiseIsHandled]] 为
true 。
返回 ThrowCompletion (promise .[[PromiseResult]] )。
返回 unused 。
16.2.1.6 循环模块记录
Cyclic Module
Record 用于表示可以与 Cyclic
Module Record 类型的子类的其他模块参与依赖循环的模块的信息。不是 Cyclic
Module Record 类型的子类的 Module Records 不得与
Source Text Module
Records 参与依赖循环。
除了 表 43 中定义的字段外,Cyclic
Module Records 还具有 表 45 中列出的附加字段
表 45:Cyclic Module
Records 的附加字段
字段名称
值类型
含义
[[Status]]
new 、unlinked 、
linking 、linked 、
evaluating 、
evaluating-async 或
evaluated
初始为 new 。随着模块在其生命周期中的进展,按顺序转换为
unlinked 、linking 、
linked 、evaluating 、
可能是 evaluating-async 、
evaluated 。
evaluating-async 表示此模块排队等待在其异步依赖完成时执行,或者它是一个
[[HasTLA]] 字段为
true 的模块,已执行并等待顶级完成。
[[EvaluationError]]
一个 抛出完成
或 empty
表示求值期间发生的异常的 抛出完成 。如果没有发生异常或
[[Status]] 不是
evaluated ,则为 undefined 。
[[DFSIndex]]
一个 整数 或
empty
仅在 Link 和 Evaluate 期间使用的辅助字段。如果 [[Status]] 是
linking 或 evaluating ,
此非负数记录模块在依赖图的深度优先遍历中首次访问的点。
[[DFSAncestorIndex]]
一个 整数 或
empty
仅在 Link 和 Evaluate 期间使用的辅助字段。如果 [[Status]] 是
linking 或 evaluating ,
这是模块自己的 [[DFSIndex]] 或同一强连通分量中"较早"模块的该值。
[[RequestedModules]]
ModuleRequest
Records 的 List
与此模块中的导入关联的 ModuleRequest
Records 的 List 。该
List
按导入的源文本出现顺序排列。
[[LoadedModules]]
LoadedModuleRequest
Records 的 List
从此记录表示的模块用于请求导入具有相对导入属性的模块的说明符字符串到已解析的 Module
Record 的映射。该列表不包含两个不同的 Records
r1 和 r2 ,使得 ModuleRequestsEqual (r1 ,
r2 ) 为 true 。
[[CycleRoot]]
一个 Cyclic Module Record
或 empty
循环的第一个访问模块,强连通分量的根 DFS 祖先。对于不在循环中的模块,这将是模块本身。一旦 Evaluate 完成,模块的 [[DFSAncestorIndex]] 是其 [[CycleRoot]] 的 [[DFSIndex]] 。
[[HasTLA]]
一个布尔值
此模块是否单独异步(例如,如果它是包含顶级等待的 Source Text Module
Record )。具有异步依赖项并不意味着此字段为
true 。此字段在模块解析后不得更改。
[[AsyncEvaluationOrder]]
unset 、一个 整数 或
done
此字段初始设置为 unset ,对于完全同步的模块保持
unset 。对于自身异步或具有异步依赖项的模块,它设置为一个 整数 ,该整数确定 16.2.1.6.1.3.4
排队执行待处理模块的顺序。
一旦待处理模块被执行,该字段设置为
done 。
[[TopLevelCapability]]
一个 PromiseCapability
Record 或 empty
如果此模块是某个循环的 [[CycleRoot]] ,并且在该循环中的某个模块上调用了
Evaluate(),此字段包含该整个求值的 PromiseCapability
Record 。它用于解决从 Evaluate() 抽象方法返回的 Promise
对象。除非为这些依赖项中的某些启动了顶级 Evaluate(),否则该字段对于该模块的任何依赖项都将是
empty 。
[[AsyncParentModules]]
Cyclic Module
Records 的 List
如果此模块或依赖项的 [[HasTLA]] 为
true ,并且执行正在进行中,这会跟踪此模块的顶级执行作业的父导入器。这些父模块在此模块成功完成执行之前不会开始执行。
[[PendingAsyncDependencies]]
一个 整数 或
empty
如果此模块有任何异步依赖项,这会跟踪此模块剩余要执行的异步依赖模块数量。
当此字段达到 0 且没有执行错误时,具有异步依赖项的模块将被执行。
除了 表 44
中定义的方法外,Cyclic
Module Records 还具有 表 46 中列出的附加方法
表 46:Cyclic Module Records 的附加抽象方法
GraphLoadingState Record 是一个 Record ,包含有关模块图加载过程的信息。它用于在调用
HostLoadImportedModule 后继续加载。每个
GraphLoadingState Record 都有
表 47 中定义的字段:
表 47:GraphLoadingState Record
字段
16.2.1.6.1 Module Record 抽象方法的实现
以下是 Cyclic Module Record
的具体方法,它们实现了 表
44 中定义的相应 Module Record
抽象方法。
16.2.1.6.1.1 LoadRequestedModules ( [
hostDefined ] )
Cyclic Module
Record module 的 LoadRequestedModules 具体方法接受可选参数
hostDefined (任何内容)并返回一个 Promise。它填充 module 依赖图中所有 Module Records 的 [[LoadedModules]] (大部分工作由辅助函数 InnerModuleLoading
完成)。它接受一个可选的 hostDefined 参数,该参数传递给 HostLoadImportedModule
钩子。调用时执行以下步骤:
如果 hostDefined 不存在,让 hostDefined 为
empty 。
让 pc 为 ! NewPromiseCapability (%Promise% )。
让 state 为 GraphLoadingState
Record { [[IsLoading]] :
true ,[[PendingModulesCount]] :
1,[[Visited]] : « »,[[PromiseCapability]] : pc ,[[HostDefined]] : hostDefined }。
执行 InnerModuleLoading (state ,
module )。
返回 pc .[[Promise]] 。
注意
hostDefined 参数可用于传递获取导入模块所需的附加信息。例如,HTML 使用它为
<link rel="preload" as="...">
标签设置正确的 fetch 目标。
import()
表达式从不设置 hostDefined
参数。
16.2.1.6.1.1.1 InnerModuleLoading (
state , module )
抽象操作 InnerModuleLoading 接受参数 state (一个
GraphLoadingState
Record )和 module (一个 Module Record )并返回
unused 。它被 LoadRequestedModules 用于递归执行 module
依赖图的实际加载过程。调用时执行以下步骤:
断言 :state .[[IsLoading]] 是 true 。
如果 module 是 Cyclic Module
Record ,module .[[Status]] 是 new ,并且
state .[[Visited]] 不包含
module ,那么
将 module 追加到 state .[[Visited]] 。
让 requestedModulesCount 为 module .[[RequestedModules]] 中的元素数量。
设置 state .[[PendingModulesCount]] 为
state .[[PendingModulesCount]] +
requestedModulesCount 。
对于 module .[[RequestedModules]] 的每个 ModuleRequest
Record request ,执行
如果 AllImportAttributesSupported (request .[[Attributes]] ) 是
false ,那么
让 error 为 ThrowCompletion (一个新创建的
SyntaxError
对象)。
执行 ContinueModuleLoading (state ,
error )。
否则,如果 module .[[LoadedModules]] 包含一个 LoadedModuleRequest
Record record ,使得
ModuleRequestsEqual (record ,
request ) 是 true ,那么
执行 InnerModuleLoading (state ,
record .[[Module]] )。
否则,
执行 HostLoadImportedModule (module ,
request , state .[[HostDefined]] ,
state )。
注意:HostLoadImportedModule
将调用 FinishLoadingImportedModule ,
它通过 ContinueModuleLoading
重新进入图加载过程。
如果 state .[[IsLoading]] 是
false ,返回
unused 。
断言 :state .[[PendingModulesCount]] ≥ 1。
设置 state .[[PendingModulesCount]] 为
state .[[PendingModulesCount]] - 1。
如果 state .[[PendingModulesCount]] =
0,那么
设置 state .[[IsLoading]] 为
false 。
对于 state .[[Visited]] 的每个
Cyclic Module
Record loaded ,执行
如果 loaded .[[Status]]
是 new ,设置
loaded .[[Status]] 为
unlinked 。
执行 ! Call (state .[[PromiseCapability]] .[[Resolve]] ,
undefined , «
undefined »)。
返回 unused 。
16.2.1.6.1.1.2 ContinueModuleLoading (
state , moduleCompletion )
抽象操作 ContinueModuleLoading 接受参数 state (一个
GraphLoadingState
Record )和 moduleCompletion (一个 包含
Module Record 的
正常完成 或一个
抛出
完成 )并返回 unused 。它用于在调用 HostLoadImportedModule
后重新进入加载过程。
调用时执行以下步骤:
如果 state .[[IsLoading]] 是
false ,返回 unused 。
如果 moduleCompletion 是 正常
完成 ,那么
执行 InnerModuleLoading (state ,
moduleCompletion .[[Value]] )。
否则,
设置 state .[[IsLoading]] 为
false 。
执行 ! Call (state .[[PromiseCapability]] .[[Reject]] ,
undefined , « moduleCompletion .[[Value]] »)。
返回 unused 。
16.2.1.6.1.2 Link ( )
Cyclic Module
Record module 的 Link 具体方法不接受参数,并返回一个 包含
unused 的 正常
完成 或一个 抛出
完成 。成功时,Link 将此模块的 [[Status]] 从
unlinked 转换为
linked 。失败时,抛出异常并且此模块的
[[Status]] 保持为 unlinked 。(大部分工作由辅助函数
InnerModuleLinking
完成。)调用时执行以下步骤:
断言 :module .[[Status]] 是
unlinked 、linked 、
evaluating-async 或
evaluated 之一。
让 stack 为一个新的空 List 。
让 result 为 Completion (InnerModuleLinking (module ,
stack , 0))。
如果 result 是 突然完成 ,那么
对于 stack 的每个 Cyclic Module
Record m ,执行
断言 :
m .[[Status]] 是
linking 。
设置 m .[[Status]] 为
unlinked 。
断言 :module .[[Status]] 是
unlinked 。
返回 ? result 。
断言 :module .[[Status]] 是 linked 、
evaluating-async 或
evaluated 之一。
断言 :stack 是空的。
返回 unused 。
16.2.1.6.1.2.1 InnerModuleLinking (
module , stack , index )
抽象操作 InnerModuleLinking 接受参数 module (一个
Module Record )、
stack (Cyclic Module Records 的
List )和
index (一个非负 整数 ),并返回一个 包含 非负
整数 的
正常完成 或一个
抛出
完成 。它被 Link 用于对 module
以及依赖图中的所有其他模块递归执行实际的链接过程。stack 和 index
参数,以及模块的 [[DFSIndex]] 和 [[DFSAncestorIndex]] 字段,跟踪深度优先搜索(DFS)遍历。特别地,[[DFSAncestorIndex]] 用于发现强连通分量(SCC),使得 SCC 中的所有模块一起转换为
linked 。调用时执行以下步骤:
如果 module 不是 Cyclic Module
Record ,那么
执行 ? module .Link()。
返回 index 。
如果 module .[[Status]] 是
linking 、linked 、
evaluating-async 或
evaluated 之一,那么
返回 index 。
断言 :module .[[Status]] 是 unlinked 。
设置 module .[[Status]] 为
linking 。
设置 module .[[DFSIndex]] 为
index 。
设置 module .[[DFSAncestorIndex]] 为
index 。
设置 index 为 index + 1。
将 module 追加到 stack 。
对于 module .[[RequestedModules]] 的每个
ModuleRequest Record
request ,执行
让 requiredModule 为 GetImportedModule (module ,
request )。
设置 index 为 ? InnerModuleLinking (requiredModule ,
stack , index )。
如果 requiredModule 是 Cyclic Module
Record ,那么
断言 :
requiredModule .[[Status]] 是
linking 、
linked 、
evaluating-async 或
evaluated 之一。
断言 :
requiredModule .[[Status]] 是
linking 当且仅当
stack 包含 requiredModule 。
如果 requiredModule .[[Status]] 是
linking ,那么
设置 module .[[DFSAncestorIndex]] 为
min (module .[[DFSAncestorIndex]] ,
requiredModule .[[DFSAncestorIndex]] )。
执行 ? module .InitializeEnvironment()。
断言 :module 在
stack 中恰好出现一次。
断言 :module .[[DFSAncestorIndex]] ≤ module .[[DFSIndex]] 。
如果 module .[[DFSAncestorIndex]] =
module .[[DFSIndex]] ,那么
让 done 为 false 。
重复,当 done 是 false 时,
让 requiredModule 为 stack 的最后一个元素。
移除 stack 的最后一个元素。
断言 :
requiredModule 是 Cyclic Module
Record 。
设置 requiredModule .[[Status]] 为
linked 。
如果 requiredModule 和 module 是同一个
Module
Record ,设置 done 为
true 。
返回 index 。
16.2.1.6.1.3 Evaluate ( )
Cyclic Module
Record module 的 Evaluate 具体方法不接受参数并返回一个
Promise。Evaluate 将此模块的 [[Status]] 从
linked 转换为 evaluating-async 或
evaluated 。当第一次在给定强连通分量中的模块上调用时,Evaluate 创建并返回一个 Promise,该
Promise 在模块完成求值时解析。此 Promise 存储在该分量的 [[CycleRoot]] 的 [[TopLevelCapability]] 字段中。在该分量中任何模块上后续调用 Evaluate 都会返回相同的
Promise。(大部分工作由辅助函数 InnerModuleEvaluation
完成。)调用时执行以下步骤:
断言 :此次 Evaluate 调用不会与 surrounding agent 内的另一次
Evaluate 调用同时发生。
断言 :module .[[Status]] 是 linked 、
evaluating-async 或
evaluated 之一。
如果 module .[[Status]] 是
evaluating-async 或 evaluated ,
设置 module 为 module .[[CycleRoot]] 。
如果 module .[[TopLevelCapability]] 不是
empty ,那么
返回 module .[[TopLevelCapability]] .[[Promise]] 。
让 stack 为一个新的空 List 。
让 capability 为 ! NewPromiseCapability (%Promise% )。
设置 module .[[TopLevelCapability]] 为
capability 。
让 result 为 Completion (InnerModuleEvaluation (module ,
stack , 0))。
如果 result 是 突然完成 ,那么
对于 stack 的每个 Cyclic Module
Record m ,执行
断言 :
m .[[Status]] 是
evaluating 。
断言 :
m .[[AsyncEvaluationOrder]] 是
unset 。
设置 m .[[Status]] 为
evaluated 。
设置 m .[[EvaluationError]]
为
result 。
断言 :module .[[Status]] 是
evaluated 。
断言 :module .[[EvaluationError]] 和 result
是相同的 Completion
Record 。
执行 ! Call (capability .[[Reject]] , undefined , «
result .[[Value]] »)。
否则,
断言 :module .[[Status]] 是
evaluating-async 或
evaluated 。
断言 :module .[[EvaluationError]] 是
empty 。
如果 module .[[Status]] 是
evaluated ,那么
注意:这意味着 module 的求值同步完成。
断言 :
module .[[AsyncEvaluationOrder]] 是
unset 。
执行 ! Call (capability .[[Resolve]] ,
undefined , «
undefined »)。
断言 :stack 是空的。
返回 capability .[[Promise]] 。
16.2.1.6.1.3.1 InnerModuleEvaluation (
module , stack , index )
抽象操作 InnerModuleEvaluation 接受参数 module (一个
Module Record )、
stack (Cyclic Module Records 的
List )和
index (一个非负 整数 ),并返回一个 包含 非负
整数 的
正常完成 或一个
抛出
完成 。它被 Evaluate 用于对 module
以及依赖图中的所有其他模块递归执行实际的求值过程。stack 和 index
参数,以及 module 的 [[DFSIndex]]
和 [[DFSAncestorIndex]] 字段,其使用方式与 InnerModuleLinking
中相同。调用时执行以下步骤:
如果 module 不是 Cyclic Module
Record ,那么
执行 ? EvaluateModuleSync (module )。
返回 index 。
如果 module .[[Status]] 是
evaluating-async 或
evaluated ,那么
如果 module .[[EvaluationError]] 是
empty ,返回 index 。
否则,返回 ? module .[[EvaluationError]] 。
如果 module .[[Status]] 是
evaluating ,返回 index 。
断言 :module .[[Status]] 是 linked 。
设置 module .[[Status]] 为
evaluating 。
设置 module .[[DFSIndex]] 为
index 。
设置 module .[[DFSAncestorIndex]] 为
index 。
设置 module .[[PendingAsyncDependencies]] 为 0。
设置 index 为 index + 1。
将 module 追加到 stack 。
对于 module .[[RequestedModules]] 的每个
ModuleRequest Record
request ,执行
让 requiredModule 为 GetImportedModule (module ,
request )。
设置 index 为 ? InnerModuleEvaluation (requiredModule ,
stack , index )。
如果 requiredModule 是 Cyclic Module
Record ,那么
断言 :
requiredModule .[[Status]] 是
evaluating 、
evaluating-async 或
evaluated 之一。
断言 :
requiredModule .[[Status]] 是
evaluating 当且仅当
stack 包含 requiredModule 。
如果 requiredModule .[[Status]] 是
evaluating ,那么
设置 module .[[DFSAncestorIndex]] 为
min (module .[[DFSAncestorIndex]] ,
requiredModule .[[DFSAncestorIndex]] )。
否则,
设置 requiredModule 为
requiredModule .[[CycleRoot]] 。
断言 :
requiredModule .[[Status]] 是
evaluating-async 或
evaluated 。
如果 requiredModule .[[EvaluationError]] 不是
empty ,返回
? requiredModule .[[EvaluationError]] 。
如果 requiredModule .[[AsyncEvaluationOrder]] 是
整数 ,那么
设置 module .[[PendingAsyncDependencies]]
为 module .[[PendingAsyncDependencies]]
+ 1。
将 module 追加到
requiredModule .[[AsyncParentModules]] 。
如果 module .[[PendingAsyncDependencies]] > 0 或
module .[[HasTLA]] 是
true ,那么
断言 :
module .[[AsyncEvaluationOrder]] 是
unset 。
设置 module .[[AsyncEvaluationOrder]] 为 IncrementModuleAsyncEvaluationCount ()。
如果 module .[[PendingAsyncDependencies]] = 0,
执行 ExecuteAsyncModule (module )。
否则,
执行 ? module .ExecuteModule() 。
断言 :module 在
stack 中恰好出现一次。
断言 :module .[[DFSAncestorIndex]] ≤ module .[[DFSIndex]] 。
如果 module .[[DFSAncestorIndex]] =
module .[[DFSIndex]] ,那么
让 done 为 false 。
重复,当 done 是 false 时,
让 requiredModule 为 stack 的最后一个元素。
移除 stack 的最后一个元素。
断言 :
requiredModule 是 Cyclic Module
Record 。
断言 :
requiredModule .[[AsyncEvaluationOrder]] 是
整数 或
unset 。
如果 requiredModule .[[AsyncEvaluationOrder]] 是
unset ,设置
requiredModule .[[Status]] 为
evaluated 。
否则,设置 requiredModule .[[Status]] 为
evaluating-async 。
如果 requiredModule 和 module 是同一个
Module
Record ,设置 done 为
true 。
设置 requiredModule .[[CycleRoot]] 为
module 。
返回 index 。
注意 1
模块在被 InnerModuleEvaluation 遍历时处于 evaluating
状态。模块在执行完成时处于 evaluated 状态,或者在执行期间如果其 [[HasTLA]] 字段为
true 或具有异步依赖时处于
evaluating-async 状态。
注意 2
当异步循环不是 evaluating 时,依赖于异步循环模块的任何模块将通过 [[CycleRoot]]
依赖于循环根的执行。这确保循环状态可以通过其根模块状态作为单个强连通分量进行处理。
16.2.1.6.1.3.2 ExecuteAsyncModule (
module )
抽象操作 ExecuteAsyncModule 接受参数 module (一个
Cyclic Module Record )并返回
unused 。调用时执行以下步骤:
断言 :module .[[Status]] 是
evaluating 或
evaluating-async 。
断言 :module .[[HasTLA]] 是 true 。
让 capability 为 ! NewPromiseCapability (%Promise% )。
让 fulfilledClosure 为一个新的 Abstract Closure ,
不接受参数,捕获 module ,并在调用时执行以下步骤:
执行 AsyncModuleExecutionFulfilled (module )。
返回 undefined 。
让 onFulfilled 为 CreateBuiltinFunction (fulfilledClosure ,
0, "" , « »)。
让 rejectedClosure 为一个新的 Abstract Closure ,
接受参数 (error ),捕获 module ,并在调用时执行以下步骤:
执行 AsyncModuleExecutionRejected (module ,
error )。
返回 undefined 。
让 onRejected 为 CreateBuiltinFunction (rejectedClosure ,
0, "" , « »)。
执行 PerformPromiseThen (capability .[[Promise]] , onFulfilled ,
onRejected )。
执行 ! module .ExecuteModule (capability )。
返回 unused 。
16.2.1.6.1.3.3 GatherAvailableAncestors (
module , execList )
抽象操作 GatherAvailableAncestors 接受参数 module
(一个 Cyclic Module Record )和
execList (Cyclic Module Records 的
List )并返回
unused 。调用时执行以下步骤:
对于 module .[[AsyncParentModules]] 的每个
Cyclic Module Record
m ,执行
如果 execList 不包含 m 且
m .[[CycleRoot]] .[[EvaluationError]] 是
empty ,那么
断言 :
m .[[Status]] 是
evaluating-async 。
断言 :
m .[[EvaluationError]] 是
empty 。
断言 :
m .[[AsyncEvaluationOrder]] 是
整数 。
断言 :
m .[[PendingAsyncDependencies]]
> 0。
设置 m .[[PendingAsyncDependencies]] 为
m .[[PendingAsyncDependencies]] -
1。
如果 m .[[PendingAsyncDependencies]] =
0,那么
将 m 追加到 execList 。
如果 m .[[HasTLA]] 是
false ,执行 GatherAvailableAncestors (m ,
execList )。
返回 unused 。
注意
当根 module 的异步执行完成时,此函数确定能够在此完成时同步执行的模块列表,将它们填充到
execList 中。
16.2.1.6.1.3.4 AsyncModuleExecutionFulfilled (
module )
抽象操作 AsyncModuleExecutionFulfilled 接受参数
module (一个 Cyclic Module Record )并返回
unused 。调用时执行以下步骤:
如果 module .[[Status]] 是
evaluated ,那么
断言 :
module .[[EvaluationError]]
不是 empty 。
返回 unused 。
断言 :module .[[Status]] 是
evaluating-async 。
断言 :module .[[AsyncEvaluationOrder]] 是 整数 。
断言 :module .[[EvaluationError]] 是
empty 。
设置 module .[[AsyncEvaluationOrder]]
为 done 。
设置 module .[[Status]] 为
evaluated 。
如果 module .[[TopLevelCapability]] 不是
empty ,那么
断言 :
module .[[CycleRoot]] 和
module 是同一个 Module
Record 。
执行 ! Call (module .[[TopLevelCapability]] .[[Resolve]] ,
undefined , «
undefined »)。
让 execList 为一个新的空 List 。
执行 GatherAvailableAncestors (module ,
execList )。
断言 :execList 的所有元素都将其
[[AsyncEvaluationOrder]] 字段设置为 整数 ,[[PendingAsyncDependencies]] 字段设置为 0,[[EvaluationError]] 字段设置为
empty 。
让 sortedExecList 为一个 List ,
其元素是 execList 的元素,按其
[[AsyncEvaluationOrder]] 字段升序排序。
对于 sortedExecList 的每个 Cyclic Module
Record
m ,执行
如果 m .[[Status]] 是
evaluated ,那么
断言 :
m .[[EvaluationError]] 不是
empty 。
否则,如果 m .[[HasTLA]] 是
true ,那么
执行 ExecuteAsyncModule (m )。
否则,
让 result 为 m .ExecuteModule() 。
如果 result 是 突然完成 ,那么
执行 AsyncModuleExecutionRejected (m ,
result .[[Value]] )。
否则,
设置 m .[[AsyncEvaluationOrder]]
为 done 。
设置 m .[[Status]] 为
evaluated 。
如果 m .[[TopLevelCapability]]
不是 empty ,那么
断言 :
m .[[CycleRoot]]
和 m 是同一个 Module
Record 。
执行 ! Call (m .[[TopLevelCapability]] .[[Resolve]] ,
undefined , «
undefined »)。
返回 unused 。
16.2.1.6.1.3.5 AsyncModuleExecutionRejected (
module , error )
抽象操作 AsyncModuleExecutionRejected 接受参数
module (一个 Cyclic Module Record )和
error (一个 ECMAScript
语言值 )并返回 unused 。调用时执行以下步骤:
如果 module .[[Status]] 是
evaluated ,那么
断言 :
module .[[EvaluationError]]
不是 empty 。
返回 unused 。
断言 :module .[[Status]] 是
evaluating-async 。
断言 :module .[[AsyncEvaluationOrder]] 是 整数 。
断言 :module .[[EvaluationError]] 是
empty 。
设置 module .[[EvaluationError]] 为
ThrowCompletion (error )。
设置 module .[[Status]] 为
evaluated 。
设置 module .[[AsyncEvaluationOrder]]
为 done 。
注意:module .[[AsyncEvaluationOrder]]
设置为
done 是为了与 AsyncModuleExecutionFulfilled
保持对称。
在 InnerModuleEvaluation
中,
当模块的 [[EvaluationError]] 内部槽不是
empty 时,其 [[AsyncEvaluationOrder]] 内部槽的值未被使用。
对于 module .[[AsyncParentModules]] 的每个
Cyclic Module Record
m ,执行
执行 AsyncModuleExecutionRejected (m ,
error )。
如果 module .[[TopLevelCapability]] 不是
empty ,那么
断言 :
module .[[CycleRoot]] 和
module 是同一个 Module
Record 。
执行 ! Call (module .[[TopLevelCapability]] .[[Reject]] ,
undefined , « error »)。
返回 unused 。
16.2.1.6.2 循环模块记录图示例
这个非规范性章节提供了一系列常见模块图链接和求值的示例,特别关注错误如何发生。
首先考虑以下简单的模块图:
图 2:一个简单的模块图
让我们首先假设没有错误条件。当 宿主
首次调用
A .LoadRequestedModules() 时,这将按假设成功完成,并递归加载 B 和 C
的依赖(分别是 C 和无),然后设置 A .[[Status]] =
B .[[Status]] =
C .[[Status]] = unlinked 。
然后,当 宿主
调用 A .Link() 时,它将成功完成(再次按假设),使得
A .[[Status]] = B .[[Status]] = C .[[Status]] =
linked。这些准备步骤可以在任何时候执行。稍后,当 宿主 准备承担模块的任何可能副作用时,它可以调用
A .Evaluate(),这将成功完成,返回一个解析为
undefined 的 Promise(再次按假设),递归地首先求值 C ,然后是
B 。此时每个模块的 [[Status]] 将是
evaluated 。
然后考虑在成功调用 A .LoadRequestedModules() 后涉及链接错误的情况。如果 C 的 InnerModuleLinking
成功,但之后 B 失败,例如因为它导入了 C 不提供的内容,那么原始的
A .Link() 将失败,A 和 B 的 [[Status]] 保持 unlinked 。
不过,C 的 [[Status]] 已变为 linked 。
最后,考虑在成功调用 Link() 后涉及求值错误的情况。如果 C 的 InnerModuleEvaluation
成功,但之后 B 失败,例如因为 B 包含抛出异常的代码,那么原始的
A .Evaluate() 将失败,返回一个被拒绝的 Promise。生成的异常将记录在 A 和 B 的
[[EvaluationError]] 字段中,它们的 [[Status]]
将变为 evaluated 。
C 也将变为 evaluated ,但与 A 和 B
相反,它将保持没有 [[EvaluationError]] ,因为它成功完成了求值。
存储异常确保任何时候 宿主
尝试通过调用它们的 Evaluate() 方法重用 A 或 B 时,它将遇到相同的异常。(宿主 不需要重用 Cyclic
Module Records ;类似地,宿主 不需要暴露这些方法抛出的异常对象。然而,规范启用了这样的用法。)
现在考虑一种不同类型的错误条件:
图 3:具有无法解析模块的模块图
在这种情况下,模块 A 声明对某个其他模块的依赖,但该模块不存在 Module Record ,即
HostLoadImportedModule 在被询问时调用
FinishLoadingImportedModule
时传递异常。这可能由于各种原因发生,例如对应的资源不存在,或者资源存在但 ParseModule 在尝试解析生成的源文本时返回一些错误。宿主 可以选择通过传递给 FinishLoadingImportedModule
的完成来暴露失败原因。
在任何情况下,这个异常导致加载失败,这使得 A 的 [[Status]] 保持
new 。
这里加载、链接和求值错误之间的差异是由于以下特征:
求值
必须只执行一次,因为它可能导致副作用;因此记住求值是否已经执行很重要,即使不成功。(在错误情况下,记住异常也是有意义的,因为否则后续的 Evaluate()
调用将必须合成一个新的异常。)
另一方面,链接是无副作用的,因此即使失败,也可以稍后重试而不会有问题。
加载与 宿主
密切交互,对于其中一些,可能希望允许用户重试失败的加载(例如,如果失败是由临时不良网络条件引起的)。
现在,考虑一个有循环的模块图:
图 4:循环模块图
这里我们假设入口点是模块 A ,因此 宿主 通过调用
A .LoadRequestedModules() 进行,这对 A 执行 InnerModuleLoading 。
这反过来对 B 和 C 调用 InnerModuleLoading 。
由于循环,这再次对 A 触发 InnerModuleLoading ,
但此时它是无操作的,因为 A 的依赖加载已经在这个 LoadRequestedModules 过程中被触发。当图中的所有模块都被成功加载时,它们的
[[Status]] 同时从 new 转换为
unlinked 。
然后 宿主
通过调用 A .Link() 继续,这对 A 执行 InnerModuleLinking 。
这反过来对 B 调用 InnerModuleLinking 。
由于循环,这再次对 A 触发 InnerModuleLinking ,
但此时它是无操作的,因为 A .[[Status]] 已经是
linking 。
当控制回到 A 并且对 C 触发 InnerModuleLinking
时,B .[[Status]] 本身保持 linking 。
在这返回后,C .[[Status]]
是 linked ,A 和 B 一起从
linking 转换为
linked ;这是设计如此,因为它们形成强连通分量。可以同时转换同一 SCC
中模块的状态,因为在这个阶段,模块图通过深度优先搜索遍历。
在成功情况下,循环模块图的求值阶段也发生类似的故事。
现在考虑 A 有链接错误的情况;例如,它尝试从 C 导入一个不存在的绑定。在这种情况下,上述步骤仍然发生,包括从第二次对
A 调用 InnerModuleLinking 的早期返回。
然而,一旦我们展开回到对 A 的原始 InnerModuleLinking ,
它在 InitializeEnvironment 期间失败,即在 C .ResolveExport() 之后立即。抛出的
SyntaxError 异常传播到 A .Link,它重置当前在其 stack
上的所有模块(这些总是正好是仍然 linking 的模块)。因此 A 和 B 都变为
unlinked 。注意 C 保持为 linked 。
或者,考虑 A 有求值错误的情况;例如,它的源代码抛出异常。在这种情况下,上述步骤的求值时类似仍然发生,包括从第二次对 A 调用
InnerModuleEvaluation 的早期返回。
然而,一旦我们展开回到对 A 的原始 InnerModuleEvaluation ,
它按假设失败。抛出的异常传播到 A .Evaluate(),它将错误记录在当前在其 stack 上的所有模块(即仍然
evaluating 的模块)以及通过 [[AsyncParentModules]] 中,这形成了一个链,用于包含或依赖顶层 await
的模块,通过 AsyncModuleExecutionRejected
算法贯穿整个依赖图。因此 A 和 B 都变为 evaluated ,异常记录在
A 和 B 的 [[EvaluationError]] 字段中,而
C
保持为 evaluated ,没有 [[EvaluationError]] 。
最后,考虑一个有循环的模块图,其中所有模块都异步完成:
图 5:异步循环模块图
加载和链接像之前一样发生,所有模块最终的 [[Status]] 设置为
linked 。
调用 A .Evaluate() 对 A 、B 和 D 调用 InnerModuleEvaluation ,
它们都转换为 evaluating 。然后再次对 A 调用 InnerModuleEvaluation ,
这是无操作的,因为它已经是 evaluating 。此时,D .[[PendingAsyncDependencies]] 是 0,因此调用 ExecuteAsyncModule (D ),
我们用一个新的 PromiseCapability 调用 D .ExecuteModule,跟踪 D 的异步执行。我们展开回到对
B 的 InnerModuleEvaluation ,
设置 B .[[PendingAsyncDependencies]]
为 1,B .[[AsyncEvaluationOrder]] 为 1。我们展开回到对
A 的原始 InnerModuleEvaluation ,
设置 A .[[PendingAsyncDependencies]]
为 1。在 A 依赖项循环的下一次迭代中,我们对 C 调用 InnerModuleEvaluation ,
因此对 D (再次无操作)和 E 。由于 E 没有依赖项且不是循环的一部分,我们以与 D
相同的方式调用 ExecuteAsyncModule (E ),
E 立即从堆栈中移除。我们再次展开到对 C 的 InnerModuleEvaluation ,
设置 C .[[AsyncEvaluationOrder]] 为 3。现在我们完成对
A 依赖项的循环,设置 A .[[AsyncEvaluationOrder]] 为
4,并从堆栈中移除整个强连通分量,同时将所有模块转换为 evaluating-async 。此时,模块的字段如 表 48 所示。
表 48:初始 Evaluate() 调用后的模块字段
字段
模块
A
B
C
D
E
[[DFSIndex]]
0
1
3
2
4
[[DFSAncestorIndex]]
0
0
0
0
4
[[Status]]
evaluating-async
evaluating-async
evaluating-async
evaluating-async
evaluating-async
[[AsyncEvaluationOrder]]
4
1
3
0
2
[[AsyncParentModules]]
« »
« A »
« A »
« B , C »
« C »
[[PendingAsyncDependencies]]
2(B 和 C )
1(D )
2(D 和 E )
0
0
让我们假设 E 首先完成执行。当发生这种情况时,调用 AsyncModuleExecutionFulfilled ,
E .[[Status]] 设置为
evaluated ,C .[[PendingAsyncDependencies]] 递减为 1。更新模块的字段如 表 49 所示。
表 49:模块 E 完成执行后的模块字段
字段
模块
C
E
[[DFSIndex]]
3
4
[[DFSAncestorIndex]]
0
4
[[Status]]
evaluating-async
evaluated
[[AsyncEvaluationOrder]]
3
2
[[AsyncParentModules]]
« A »
« C »
[[PendingAsyncDependencies]]
1(D )
0
D 接下来完成(因为它是唯一仍在执行的模块)。当发生这种情况时,再次调用 AsyncModuleExecutionFulfilled ,
D .[[Status]] 设置为
evaluated 。其可用于执行的祖先是 B
(其 [[AsyncEvaluationOrder]] 是 1)和 C
(其 [[AsyncEvaluationOrder]] 是 3),因此 B 将首先处理:
B .[[PendingAsyncDependencies]]
递减为 0,对 B 调用 ExecuteAsyncModule ,
它开始执行。C .[[PendingAsyncDependencies]] 也递减为
0,C 开始执行(如果 B 包含 await
,可能与 B 并行)。更新模块的字段如
表 50 所示。
表 50:模块 D 完成执行后的模块字段
字段
模块
B
C
D
[[DFSIndex]]
1
3
2
[[DFSAncestorIndex]]
0
0
0
[[Status]]
evaluating-async
evaluating-async
evaluated
[[AsyncEvaluationOrder]]
1
3
0
[[AsyncParentModules]]
« A »
« A »
« B , C »
[[PendingAsyncDependencies]]
0
0
0
让我们假设 C 接下来完成执行。当发生这种情况时,再次调用 AsyncModuleExecutionFulfilled ,
C .[[Status]] 设置为
evaluated ,A .[[PendingAsyncDependencies]] 递减为 1。更新模块的字段如 表 51 所示。
表 51:模块 C 完成执行后的模块字段
字段
模块
A
C
[[DFSIndex]]
0
3
[[DFSAncestorIndex]]
0
0
[[Status]]
evaluating-async
evaluated
[[AsyncEvaluationOrder]]
4
3
[[AsyncParentModules]]
« »
« A »
[[PendingAsyncDependencies]]
1(B )
0
然后,B 完成执行。当发生这种情况时,再次调用 AsyncModuleExecutionFulfilled ,
B .[[Status]] 设置为 evaluated 。
A .[[PendingAsyncDependencies]] 递减为 0,因此调用 ExecuteAsyncModule ,
它开始执行。更新模块的字段如 表 52
所示。
表 52:模块 B 完成执行后的模块字段
字段
模块
A
B
[[DFSIndex]]
0
1
[[DFSAncestorIndex]]
0
0
[[Status]]
evaluating-async
evaluated
[[AsyncEvaluationOrder]]
4
1
[[AsyncParentModules]]
« »
« A »
[[PendingAsyncDependencies]]
0
0
最后,A 完成执行。当发生这种情况时,再次调用 AsyncModuleExecutionFulfilled ,
A .[[Status]] 设置为
evaluated 。此时,A .[[TopLevelCapability]] 中的 Promise(从
A .Evaluate() 返回)被解析,这结束了对此模块图的处理。更新模块的字段如 表 53 所示。
表 53:模块 A 完成执行后的模块字段
字段
模块
A
[[DFSIndex]]
0
[[DFSAncestorIndex]]
0
[[Status]]
evaluated
[[AsyncEvaluationOrder]]
4
[[AsyncParentModules]]
« »
[[PendingAsyncDependencies]]
0
或者,考虑失败情况,其中 C 在 B 完成执行之前执行失败并返回错误。当发生这种情况时,调用 AsyncModuleExecutionRejected ,
它设置 C .[[Status]] 为
evaluated ,C .[[EvaluationError]] 为错误。然后通过对每个 AsyncParentModules 执行 AsyncModuleExecutionRejected
将此错误传播到所有 AsyncParentModules。更新模块的字段如 表 54 所示。
表 54:模块 C 出错完成后的模块字段
字段
模块
A
C
[[DFSIndex]]
0
3
[[DFSAncestorIndex]]
0
0
[[Status]]
evaluated
evaluated
[[AsyncEvaluationOrder]]
4
3
[[AsyncParentModules]]
« »
« A »
[[PendingAsyncDependencies]]
1(B )
0
[[EvaluationError]]
empty
C 的求值错误
A 将被拒绝,错误与 C 相同,因为 C 将用 C 的错误对 A
调用 AsyncModuleExecutionRejected 。
A .[[Status]] 设置为 evaluated 。此时
A .[[TopLevelCapability]] 中的 Promise(从
A .Evaluate() 返回)被拒绝。更新模块的字段如 表
55 所示。
表 55:模块 A 被拒绝后的模块字段
字段
模块
A
[[DFSIndex]]
0
[[DFSAncestorIndex]]
0
[[Status]]
evaluated
[[AsyncEvaluationOrder]]
4
[[AsyncParentModules]]
« »
[[PendingAsyncDependencies]]
0
[[EvaluationError]]
C 的 求值 错误
然后,B 完成执行且没有错误。当发生这种情况时,再次调用 AsyncModuleExecutionFulfilled ,
B .[[Status]] 设置为 evaluated 。对
B 调用 GatherAvailableAncestors 。
然而,A .[[CycleRoot]]
是 A ,它有求值错误,因此它不会被添加到返回的 sortedExecList 中,AsyncModuleExecutionFulfilled
将返回而不进行进一步处理。B 的任何未来导入者将从 C 设置在循环根 A 上的求值错误中解析
B .[[CycleRoot]] .[[EvaluationError]] 的拒绝。更新模块的字段如 表 56 所示。
表 56:模块 B 在错误图中完成执行后的模块字段
字段
模块
A
B
[[DFSIndex]]
0
1
[[DFSAncestorIndex]]
0
0
[[Status]]
evaluated
evaluated
[[AsyncEvaluationOrder]]
4
1
[[AsyncParentModules]]
« »
« A »
[[PendingAsyncDependencies]]
0
0
[[EvaluationError]]
C 的 求值 错误
empty
16.2.1.7 源文本模块记录
源文本模块记录 用于表示从使用 目标符号 Module 解析的 ECMAScript
源文本 (11 )定义的模块信息。其字段包含关于模块导入和导出名称的摘要信息,其具体方法使用这些摘要来链接和求值模块。
源文本模块记录 可以与抽象 Module Record
类型的其他子类存在于模块图中,并且可以与 Cyclic Module Record 类型的其他子类参与循环。
除了在 表 45 中定义的字段外,源文本模块记录 还有在 表 57
中列出的其他字段。每个字段最初在 ParseModule 中设置。
表 57:源文本模块记录 的附加字段
字段名称
值类型
含义
[[ECMAScriptCode]]
一个 解析节点
使用 Module 作为
目标符号
解析此模块源文本的结果。
[[Context]]
一个 ECMAScript
代码执行上下文 或 empty
与此模块关联的 执行上下文 。在模块环境初始化之前为
empty 。
[[ImportMeta]]
一个对象或 empty
通过 import.meta
元属性暴露的对象。在被 ECMAScript 代码访问之前为
empty 。
[[ImportEntries]]
一个 列表 ,包含
ImportEntry 记录
从此模块代码派生的 ImportEntry 记录的 列表 。
[[LocalExportEntries]]
一个 列表 ,包含
ExportEntry 记录
从此模块代码派生的 ExportEntry 记录的 列表 ,对应于模块内发生的声明。
[[IndirectExportEntries]]
一个 列表 ,包含
ExportEntry 记录
从此模块代码派生的 ExportEntry 记录的 列表 ,对应于模块内发生的重新导出导入或来自
export * as namespace
声明的导出。
[[StarExportEntries]]
一个 列表 ,包含
ExportEntry 记录
从此模块代码派生的 ExportEntry 记录的 列表 ,对应于模块内发生的
export *
声明,不包括 export * as namespace
声明。
ImportEntry
记录 是一个 记录 ,摘要了关于单个声明性导入的信息。每个
ImportEntry 记录 都有在 表 58 中定义的字段:
表 58:ImportEntry 记录 字段
注 1
表
59 给出了用于表示语法导入形式的 ImportEntry 记录字段的示例:
表 59(信息性):导入形式到 ImportEntry
记录 的映射
导入语句形式
[[ModuleRequest]]
[[ImportName]]
[[LocalName]]
import v from "mod";
"mod"
"default"
"v"
import * as ns from "mod";
"mod"
namespace-object
"ns"
import {x} from "mod";
"mod"
"x"
"x"
import {x as v} from "mod";
"mod"
"x"
"v"
import "mod";
不创建 ImportEntry
记录 。
ExportEntry
记录 是一个 记录 ,摘要了关于单个声明性导出的信息。每个
ExportEntry 记录 都有在 表
60 中定义的字段:
表 60:ExportEntry 记录 字段
注 2
表
61 给出了用于表示语法导出形式的 ExportEntry 记录字段的示例:
表 61(信息性):导出形式到 ExportEntry
记录 的映射
导出语句形式
[[ExportName]]
[[ModuleRequest]]
[[ImportName]]
[[LocalName]]
export var v;
"v"
null
null
"v"
export default function f() {}
"default"
null
null
"f"
export default function () {}
"default"
null
null
"*default*"
export default 42;
"default"
null
null
"*default*"
export {x};
"x"
null
null
"x"
export {v as x};
"x"
null
null
"v"
export {x} from "mod";
"x"
"mod"
"x"
null
export {v as x} from "mod";
"x"
"mod"
"v"
null
export * from "mod";
null
"mod"
all-but-default
null
export * as ns from "mod";
"ns"
"mod"
all
null
以下定义指定了 源文本模块记录 所需的具体方法和其他 抽象操作
16.2.1.7.1 ParseModule ( sourceText ,
realm , hostDefined )
抽象操作 ParseModule 接受参数 sourceText (ECMAScript
源文本 )、realm (一个 Realm Record )和
hostDefined (任意值),返回一个 源文本模块记录 或一个非空的
列表 ,包含
SyntaxError 对象。它基于将 sourceText 作为 Module 解析的结果创建一个 源文本模块记录 。调用时执行以下步骤:
设 body 为 ParseText (sourceText ,
Module )。
如果 body 是一个错误的 列表 ,返回
body 。
设 requestedModules 为 body 的 ModuleRequests 。
设 importEntries 为 body 的 ImportEntries 。
设 importedBoundNames 为 ImportedLocalNames (importEntries )。
设 indirectExportEntries 为一个新的空 列表 。
设 localExportEntries 为一个新的空 列表 。
设 starExportEntries 为一个新的空 列表 。
设 exportEntries 为 body 的 ExportEntries 。
对于 exportEntries 中的每个 ExportEntry
Record
ee ,执行
如果 ee .[[ModuleRequest]] 是
null ,那么
如果 importedBoundNames 不包含
ee .[[LocalName]] ,那么
将 ee 附加到 localExportEntries 。
否则,
设 ie 为 importEntries 中 [[LocalName]] 是
ee .[[LocalName]]
的元素。
如果 ie .[[ImportName]]
是 namespace-object ,那么
注:这是对导入模块命名空间对象的重新导出。
将 ee 附加到
localExportEntries 。
否则,
注:这是对单个名称的重新导出。
将 ExportEntry
Record { [[ModuleRequest]] :
ie .[[ModuleRequest]] , [[ImportName]] :
ie .[[ImportName]] , [[LocalName]] :
null , [[ExportName]] :
ee .[[ExportName]] }
附加到
indirectExportEntries 。
否则如果 ee .[[ImportName]] 是
all-but-default ,那么
断言 :ee .[[ExportName]] 是
null 。
将 ee 附加到 starExportEntries 。
否则,
将 ee 附加到 indirectExportEntries 。
设 async 为 body Contains
await
。
返回 源文本模块记录
{ [[Realm]] : realm , [[Environment]] : empty , [[Namespace]] : empty , [[CycleRoot]] : empty , [[HasTLA]] : async , [[AsyncEvaluationOrder]] : unset ,
[[TopLevelCapability]] : empty ,
[[AsyncParentModules]] : « », [[PendingAsyncDependencies]] :
empty , [[Status]] :
new , [[EvaluationError]] :
empty , [[HostDefined]] :
hostDefined , [[ECMAScriptCode]] :
body , [[Context]] :
empty , [[ImportMeta]] :
empty , [[RequestedModules]] :
requestedModules , [[LoadedModules]] :
« », [[ImportEntries]] : importEntries ,
[[LocalExportEntries]] : localExportEntries ,
[[IndirectExportEntries]] :
indirectExportEntries , [[StarExportEntries]] : starExportEntries ,
[[DFSIndex]] : empty , [[DFSAncestorIndex]] :
empty }。
注
实现可能在对该模块源文本求值 ParseModule 之前解析模块源文本并分析其早期错误条件。然而,任何错误的报告都必须推迟到本规范实际对该源文本执行
ParseModule 的时刻。
16.2.1.7.2 模块记录抽象方法的实现
以下是 源文本模块记录 的具体方法,实现了 表 44 中定义的相应
模块记录 抽象方法。
16.2.1.7.2.1 GetExportedNames ( [
exportStarSet ] )
源文本模块记录 module 的
GetExportedNames 具体方法接受可选参数
exportStarSet (一个包含 源文本模块记录 的
列表 ),返回一个包含字符串的
列表 。调用时执行以下步骤:
断言 :module .[[Status]] 不是 new 。
如果 exportStarSet 不存在,设 exportStarSet 为一个新的空 列表 。
如果 exportStarSet 包含 module ,那么
断言 :我们已达到 export *
循环的起点。
返回一个新的空 列表 。
将 module 附加到 exportStarSet 。
设 exportedNames 为一个新的空 列表 。
对于 module .[[LocalExportEntries]] 中的每个
ExportEntry Record
e ,执行
断言 :module
为此导出提供直接绑定。
断言 :e .[[ExportName]] 不是
null 。
将 e .[[ExportName]] 附加到
exportedNames 。
对于 module .[[IndirectExportEntries]] 中的每个
ExportEntry Record
e ,执行
断言 :module
为此导出导入特定绑定。
断言 :e .[[ExportName]] 不是
null 。
将 e .[[ExportName]] 附加到
exportedNames 。
对于 module .[[StarExportEntries]] 中的每个
ExportEntry Record
e ,执行
断言 :e .[[ModuleRequest]] 不是
null 。
设 requestedModule 为 GetImportedModule (module ,
e .[[ModuleRequest]] )。
设 starNames 为
requestedModule .GetExportedNames(exportStarSet )。
对于 starNames 的每个元素 n ,执行
如果 n 不是 "default" ,那么
如果 exportedNames 不包含
n ,那么
将 n 附加到
exportedNames 。
返回 exportedNames 。
注
GetExportedNames 不会过滤掉或为具有歧义星号导出绑定的名称抛出异常。
16.2.1.7.2.2 ResolveExport ( exportName [ ,
resolveSet ] )
源文本模块记录 module 的
ResolveExport 具体方法接受参数 exportName (一个字符串)和可选参数
resolveSet (一个包含字段 [[Module]] (一个 模块记录 )和 [[ExportName]] (一个字符串)的 记录 的 列表 ),返回一个
ResolvedBinding
Record 、null 或
ambiguous 。
ResolveExport 尝试将导入绑定解析为实际的定义模块和本地绑定名称。定义模块可能是调用此方法的 模块记录 所表示的模块,或该模块导入的其他模块。参数
resolveSet 用于检测未解析的循环导入/导出路径。如果到达的特定 模块记录 和
exportName 的配对已在 resolveSet 中,则遇到了导入循环。在递归调用 ResolveExport
之前,由 module 和
exportName 组成的配对会添加到 resolveSet 。
如果找到定义模块,返回一个 ResolvedBinding
Record { [[Module]] , [[BindingName]]
}。此记录标识最初请求导出的已解析绑定,除非这是没有本地绑定的命名空间导出。在这种情况下,[[BindingName]] 将设置为
namespace 。如果没有找到定义或请求被发现是循环的,返回
null 。如果请求被发现是歧义的,返回 ambiguous 。
调用时执行以下步骤:
断言 :module .[[Status]] 不是 new 。
如果 resolveSet 不存在,设 resolveSet 为一个新的空 列表 。
对于 resolveSet 中的每个 记录
{ [[Module]] , [[ExportName]] } r ,执行
如果 module 和 r .[[Module]] 是同一个 模块记录 且
exportName 是
r .[[ExportName]] ,那么
断言 :这是一个循环导入请求。
返回 null 。
将 记录
{ [[Module]] : module , [[ExportName]] : exportName } 附加到
resolveSet 。
对于 module .[[LocalExportEntries]] 中的每个
ExportEntry Record
e ,执行
如果 e .[[ExportName]] 是
exportName ,那么
断言 :
module 为此导出提供直接绑定。
返回 ResolvedBinding
Record { [[Module]] : module , [[BindingName]] : e .[[LocalName]] }。
对于 module .[[IndirectExportEntries]] 中的每个
ExportEntry Record
e ,执行
如果 e .[[ExportName]] 是
exportName ,那么
断言 :
e .[[ModuleRequest]] 不是
null 。
设 importedModule 为 GetImportedModule (module ,
e .[[ModuleRequest]] )。
如果 e .[[ImportName]] 是
all ,那么
断言 :
module 不为此导出提供直接绑定。
返回 ResolvedBinding
Record { [[Module]] :
importedModule , [[BindingName]] :
namespace }。
否则,
断言 :
module 为此导出导入特定绑定。
断言 :
e .[[ImportName]]
是一个字符串 。
返回
importedModule .ResolveExport(e .[[ImportName]] ,
resolveSet )。
如果 exportName 是 "default" ,那么
断言 :此模块没有显式定义
default
导出。
返回 null 。
注:default
导出不能由 export * from "mod"
声明提供。
设 starResolution 为 null 。
对于 module .[[StarExportEntries]] 中的每个
ExportEntry Record
e ,执行
断言 :e .[[ModuleRequest]] 不是
null 。
设 importedModule 为 GetImportedModule (module ,
e .[[ModuleRequest]] )。
设 resolution 为
importedModule .ResolveExport(exportName ,
resolveSet )。
如果 resolution 是 ambiguous ,返回
ambiguous 。
如果 resolution 不是 null ,那么
断言 :
resolution 是一个 ResolvedBinding
Record 。
如果 starResolution 是 null ,那么
设 starResolution 为
resolution 。
否则,
断言 :有多个包含请求名称的
*
导入。
如果 resolution .[[Module]] 和
starResolution .[[Module]] 不是同一个 模块记录 ,返回
ambiguous 。
如果 resolution .[[BindingName]] 不是
starResolution .[[BindingName]] 且
resolution .[[BindingName]] 或
starResolution .[[BindingName]] 中的任一个是
namespace ,返回
ambiguous 。
如果 resolution .[[BindingName]] 是一个字符串 ,
starResolution .[[BindingName]] 是一个字符串 ,且
resolution .[[BindingName]] 不是
starResolution .[[BindingName]] ,返回
ambiguous 。
返回 starResolution 。
16.2.1.7.3 循环模块记录抽象方法的实现
以下是 源文本模块记录 的具体方法,实现了 表 46 中定义的相应 循环模块记录 抽象方法。
16.2.1.7.3.1 InitializeEnvironment ( )
源文本模块记录
module 的 InitializeEnvironment 具体方法不接受参数,返回 包含
unused 的正常完成,或 抛出完成 。调用时执行以下步骤:
对于 module .[[IndirectExportEntries]] 中的每个
ExportEntry Record
e ,执行
断言 :e .[[ExportName]] 不是
null 。
设 resolution 为
module .ResolveExport(e .[[ExportName]] )。
如果 resolution 是 null 或
ambiguous ,抛出 SyntaxError
异常。
断言 :resolution
是一个 ResolvedBinding
Record 。
断言 :module 的所有命名导出都是可解析的。
设 realm 为 module .[[Realm]] 。
断言 :realm 不是
undefined 。
设 env 为 NewModuleEnvironment (realm .[[GlobalEnv]] )。
设 module .[[Environment]] 为
env 。
对于 module .[[ImportEntries]] 中的每个
ImportEntry Record
in ,执行
设 importedModule 为 GetImportedModule (module ,
in .[[ModuleRequest]] )。
如果 in .[[ImportName]] 是
namespace-object ,那么
设 namespace 为 GetModuleNamespace (importedModule )。
执行
! env .CreateImmutableBinding(in .[[LocalName]] ,
true )。
执行
! env .InitializeBinding(in .[[LocalName]] ,
namespace )。
否则,
设 resolution 为
importedModule .ResolveExport(in .[[ImportName]] )。
如果 resolution 是 null
或 ambiguous ,抛出
SyntaxError 异常。
如果 resolution .[[BindingName]] 是
namespace ,那么
设 namespace 为 GetModuleNamespace (resolution .[[Module]] )。
执行
! env .CreateImmutableBinding(in .[[LocalName]] ,
true )。
执行
! env .InitializeBinding(in .[[LocalName]] ,
namespace )。
否则,
执行 CreateImportBinding (env ,
in .[[LocalName]] ,
resolution .[[Module]] ,
resolution .[[BindingName]] )。
设 moduleContext 为一个新的 ECMAScript
代码执行上下文 。
设 moduleContext 的 Function 为 null 。
断言 :module .[[Realm]] 不是 undefined 。
设 moduleContext 的 Realm 为
module .[[Realm]] 。
设 moduleContext 的 ScriptOrModule 为 module 。
设 moduleContext 的 VariableEnvironment 为
module .[[Environment]] 。
设 moduleContext 的 LexicalEnvironment 为
module .[[Environment]] 。
设 moduleContext 的 PrivateEnvironment 为
null 。
设 module .[[Context]] 为
moduleContext 。
将 moduleContext 压入 执行上下文栈 ;moduleContext
现在是 运行的执行上下文 。
设 code 为 module .[[ECMAScriptCode]] 。
设 varDeclarations 为 code 的 VarScopedDeclarations 。
设 declaredVarNames 为一个新的空 列表 。
对于 varDeclarations 的每个元素 d ,执行
对于 d 的 BoundNames
的每个元素 dn ,执行
如果 declaredVarNames 不包含
dn ,那么
执行
! env .CreateMutableBinding(dn ,
false )。
执行
! env .InitializeBinding(dn ,
undefined )。
将 dn 附加到 declaredVarNames 。
设 lexDeclarations 为 code 的 LexicallyScopedDeclarations 。
设 privateEnv 为 null 。
对于 lexDeclarations 的每个元素 d ,执行
对于 d 的 BoundNames
的每个元素 dn ,执行
如果 d 的 IsConstantDeclaration
是 true ,那么
执行
! env .CreateImmutableBinding(dn ,
true )。
否则,
执行
! env .CreateMutableBinding(dn ,
false )。
如果 d 是 FunctionDeclaration 、GeneratorDeclaration 、AsyncFunctionDeclaration
或 AsyncGeneratorDeclaration ,那么
设 fo 为 d 的 InstantiateFunctionObject ,参数为
env 和
privateEnv 。
执行
! env .InitializeBinding(dn ,
fo )。
从 执行上下文栈 中移除
moduleContext 。
返回 unused 。
16.2.1.7.3.2 ExecuteModule ( [ capability ] )
源文本模块记录 module 的
ExecuteModule 具体方法接受可选参数
capability (一个 PromiseCapability
Record ),返回 包含
unused 的正常完成,或 抛出完成 。调用时执行以下步骤:
设 moduleContext 为一个新的 ECMAScript
代码执行上下文 。
设 moduleContext 的 Function 为 null 。
设 moduleContext 的 Realm 为
module .[[Realm]] 。
设 moduleContext 的 ScriptOrModule 为 module 。
断言 :module
已被链接,其模块环境中的声明已被实例化。
设 moduleContext 的 VariableEnvironment 为
module .[[Environment]] 。
设 moduleContext 的 LexicalEnvironment 为
module .[[Environment]] 。
暂停 运行的执行上下文 。
如果 module .[[HasTLA]] 是
false ,那么
断言 :capability
不存在。
将 moduleContext 压入 执行上下文栈 ;moduleContext
现在是
运行的执行上下文 。
设 result 为 Completion (module .[[ECMAScriptCode]] 的 Evaluation )。
暂停 moduleContext 并从 执行上下文栈 中移除它。
恢复现在位于 执行上下文栈
顶部的上下文作为 运行的执行上下文 。
如果 result 是一个 异常完成 ,那么
返回 ? result 。
否则,
断言 :capability
是一个 PromiseCapability
Record 。
执行 AsyncBlockStart (capability ,
module .[[ECMAScriptCode]] ,
moduleContext )。
返回 unused 。
16.2.1.8 合成模块记录
合成模块记录 用于表示由规范定义的模块的信息。其导出名称在创建时静态定义,而其对应的值可以通过 SetSyntheticModuleExport
随时间变化。它没有导入或依赖项。
注
合成模块记录可用于定义各种模块类型:例如,JSON 模块或 CSS 模块。
除了 表 43 中定义的字段外,合成模块记录还具有 表 62 中列出的附加字段。
表 62:合成模块记录 的附加字段
字段名称
值类型
含义
[[ExportNames]]
字符串的 列表
模块的导出名称。此列表不包含重复项。
[[EvaluationSteps]]
一个 抽象闭包
在模块求值时执行的初始化逻辑,以 合成模块记录 作为其唯一参数。它不得修改
[[ExportNames]] 。它可能返回一个 异常完成 。
16.2.1.8.1 CreateDefaultExportSyntheticModule (
defaultExport )
抽象操作 CreateDefaultExportSyntheticModule 接受参数
defaultExport (一个 ECMAScript
语言值 ),返回一个 合成模块记录 。它创建一个默认导出为
defaultExport 的 合成模块记录 。调用时执行以下步骤:
设 realm 为 当前 Realm Record 。
设 setDefaultExport 为一个新的 抽象闭包 ,参数为
(module ),捕获
defaultExport 并在调用时执行以下步骤:
执行 SetSyntheticModuleExport (module ,
"default" , defaultExport )。
返回 NormalCompletion (unused )。
返回 合成模块记录 { [[Realm]] :
realm , [[Environment]] :
empty , [[Namespace]] :
empty , [[HostDefined]] :
undefined , [[ExportNames]] : «
"default" », [[EvaluationSteps]] : setDefaultExport }。
16.2.1.8.2 ParseJSONModule ( source )
抽象操作 ParseJSONModule 接受参数 source (一个字符串),返回 包含 一个 合成模块记录 的正常完成,或 抛出完成 。调用时执行以下步骤:
设 json 为 ? ParseJSON (source )。
返回 CreateDefaultExportSyntheticModule (json )。
16.2.1.8.3 SetSyntheticModuleExport ( module ,
exportName , exportValue )
抽象操作 SetSyntheticModuleExport 接受参数 module (一个 合成模块记录 )、exportName (一个字符串)和
exportValue (一个 ECMAScript
语言值 ),返回 unused 。它可用于设置或更改 合成模块记录 现有导出的导出值。调用时执行以下步骤:
断言 :
module .[[ExportNames]] 包含
exportName 。
设 envRec 为 module .[[Environment]] 。
断言 :
envRec 不是 empty 。
执行 envRec .SetMutableBinding(exportName ,
exportValue , true )。
返回 unused 。
16.2.1.8.4 模块记录抽象方法的实现
以下是 合成模块记录 的具体方法,实现了 表 44 中定义的相应
模块记录 抽象方法。
16.2.1.8.4.1 LoadRequestedModules ( )
合成模块记录
module 的 LoadRequestedModules 具体方法不接受参数,返回一个 Promise。调用时执行以下步骤:
返回 ! PromiseResolve (%Promise% ,
undefined )。
注
16.2.1.8.4.2 GetExportedNames ( )
合成模块记录
module 的 GetExportedNames 具体方法不接受参数,返回一个包含字符串的 列表 。调用时执行以下步骤:
返回 module .[[ExportNames]] 。
16.2.1.8.4.3 ResolveExport ( exportName )
合成模块记录 module
的 ResolveExport 具体方法接受参数 exportName (一个字符串),返回一个 ResolvedBinding Record 或
null 。调用时执行以下步骤:
如果 module .[[ExportNames]] 不包含
exportName ,返回 null 。
返回 ResolvedBinding Record
{ [[Module]] : module , [[BindingName]] : exportName }。
16.2.1.8.4.4 Link ( )
合成模块记录 module
的 Link 具体方法不接受参数,返回 包含
unused 的正常完成。调用时执行以下步骤:
设 realm 为 module .[[Realm]] 。
设 env 为 NewModuleEnvironment (realm .[[GlobalEnv]] )。
设 module .[[Environment]] 为
env 。
对于 module .[[ExportNames]] 的每个字符串
exportName ,执行
执行
! env .CreateMutableBinding(exportName ,
false )。
执行
! env .InitializeBinding(exportName ,
undefined )。
返回 NormalCompletion (unused )。
16.2.1.8.4.5 Evaluate ( )
合成模块记录 module
的 Evaluate 具体方法不接受参数,返回一个 Promise。调用时执行以下步骤:
设 moduleContext 为一个新的 ECMAScript
代码执行上下文 。
设 moduleContext 的 Function 为 null 。
设 moduleContext 的 Realm 为
module .[[Realm]] 。
设 moduleContext 的 ScriptOrModule 为 module 。
设 moduleContext 的 VariableEnvironment 为
module .[[Environment]] 。
设 moduleContext 的 LexicalEnvironment 为
module .[[Environment]] 。
暂停 运行的执行上下文 。
将 moduleContext 压入 执行上下文栈 ;moduleContext
现在是 运行的执行上下文 。
设 steps 为 module .[[EvaluationSteps]] 。
设 result 为 Completion (steps (module ))。
暂停 moduleContext 并从 执行上下文栈
中移除它。
恢复现在位于 执行上下文栈 顶部的上下文作为
运行的执行上下文 。
设 pc 为 ! NewPromiseCapability (%Promise% )。
IfAbruptRejectPromise (result ,
pc )。
执行 ! Call (pc .[[Resolve]] , undefined , «
undefined »)。
返回 pc .[[Promise]] 。
16.2.1.9 GetImportedModule ( referrer ,
request )
抽象操作 GetImportedModule 接受参数 referrer (一个 循环模块记录 )和
request (一个 ModuleRequest Record ),返回一个 模块记录 。调用时执行以下步骤:
设 records 为一个 列表 ,由
referrer .[[LoadedModules]] 中满足 ModuleRequestsEqual (r ,
request ) 为 true 的每个 LoadedModuleRequest Record
r 组成。
断言 :
records 恰好有一个元素,因为在调用此抽象操作之前,LoadRequestedModules 已在 referrer
上成功完成。
设 record 为 records 的唯一元素。
返回 record .[[Module]] 。
16.2.1.10 HostLoadImportedModule ( referrer ,
moduleRequest , hostDefined , payload )
宿主定义 的抽象操作
HostLoadImportedModule 接受参数 referrer (一个 脚本记录 、一个 循环模块记录 或一个 Realm
Record )、moduleRequest (一个 ModuleRequest
Record )、hostDefined (任何值)和 payload (一个 GraphLoadingState Record 或一个
PromiseCapability Record ),返回
unused 。
注 1
referrer 可以是 Realm Record 的一个例子是在 Web 浏览器 宿主 中。在那里,如果用户点击由以下代码给出的控件
<button type ="button" onclick ="import('./foo.mjs')" > Click me</button >
当 import()
表达式运行时,将没有
活动脚本或模块 。更一般地,这可能发生在
宿主 将具有
null ScriptOrModule 组件的 执行上下文 推入
执行上下文栈 的任何情况下。
HostLoadImportedModule 的实现必须符合以下要求:
宿主环境 必须执行 FinishLoadingImportedModule (referrer ,
moduleRequest , payload , result ),其中
result 是 包含 已加载的 模块记录 的正常完成或 抛出完成 ,可以是同步或异步的。
如果此操作被多次调用,使用两个 (referrer ,
moduleRequest ) 对,满足:
第一个 referrer 与第二个 referrer 相同;
ModuleRequestsEqual (第一个
moduleRequest , 第二个 moduleRequest ) 为
true ;
并且它执行 FinishLoadingImportedModule (referrer ,
moduleRequest , payload , result ),其中
result 是 正常完成 ,那么它必须每次都用相同的
result 执行 FinishLoadingImportedModule (referrer ,
moduleRequest , payload , result )。
如果 moduleRequest .[[Attributes]] 有一个条目
entry ,使得 entry .[[Key]] 是
"type" 且 entry .[[Value]] 是
"json" ,当 宿主环境
执行 FinishLoadingImportedModule (referrer ,
moduleRequest , payload , result ) 时,result
必须是调用 ParseJSONModule 返回的 完成记录 或
抛出完成 。
操作必须将 payload 视为要传递给
FinishLoadingImportedModule
的不透明值。
执行的实际过程是 宿主定义 的,但通常包括执行加载适当的 模块记录 所需的任何 I/O 操作。多个不同的
(referrer , moduleRequest .[[Specifier]] ,
moduleRequest .[[Attributes]] ) 三元组可能映射到同一个 模块记录 实例。实际的映射语义是 宿主定义 的,但通常作为映射过程的一部分,会对 specifier
应用规范化过程。典型的规范化过程包括扩展相对和缩写路径说明符等操作。
注 2
上述文本要求 宿主 在使用
type: "json"
导入时支持 JSON 模块(并且 HostLoadImportedModule 正常完成),但它不禁止
宿主 在不使用
type: "json"
导入时支持 JSON 模块。
16.2.1.11 FinishLoadingImportedModule ( referrer ,
moduleRequest , payload , result )
抽象操作 FinishLoadingImportedModule 接受参数 referrer (一个 脚本记录 、一个 循环模块记录 或一个 Realm
Record )、moduleRequest (一个 ModuleRequest
Record )、payload (一个 GraphLoadingState Record 或一个
PromiseCapability Record )和
result (包含 一个
模块记录 的正常完成或 抛出完成 ),返回
unused 。调用时执行以下步骤:
如果 result 是 正常完成 ,那么
如果 referrer .[[LoadedModules]] 包含一个
LoadedModuleRequest
Record record ,使得 ModuleRequestsEqual (record ,
moduleRequest ) 为 true ,那么
断言 :record .[[Module]] 和 result .[[Value]] 是同一个 模块记录 。
否则,
将 LoadedModuleRequest
Record { [[Specifier]] : moduleRequest .[[Specifier]] , [[Attributes]] :
moduleRequest .[[Attributes]] ,
[[Module]] : result .[[Value]] } 附加到
referrer .[[LoadedModules]] 。
如果 payload 是 GraphLoadingState
Record ,那么
执行 ContinueModuleLoading (payload ,
result )。
否则,
执行 ContinueDynamicImport (payload ,
result )。
返回 unused 。
16.2.1.12 AllImportAttributesSupported ( attributes )
抽象操作 AllImportAttributesSupported 接受参数 attributes (一个包含 ImportAttribute Records 的 列表 ),返回一个布尔值。调用时执行以下步骤:
设 supported 为 HostGetSupportedImportAttributes ()。
对于 attributes 的每个 ImportAttribute
Record
attribute ,执行
如果 supported 不包含 attribute .[[Key]] ,返回 false 。
返回 true 。
16.2.1.12.1 HostGetSupportedImportAttributes ( )
宿主定义 的抽象操作
HostGetSupportedImportAttributes 不接受参数,返回一个包含字符串的 列表 。它允许 宿主环境 指定它们支持的导入属性。只有具有受支持键的属性才会提供给
宿主 。
HostGetSupportedImportAttributes 的实现必须符合以下要求:
它必须返回一个包含字符串的 列表 ,每个字符串表示一个受支持的属性。
每次调用此操作时,它必须返回相同的 列表 ,包含相同顺序的相同内容。
HostGetSupportedImportAttributes 的默认实现是返回一个新的空 列表 。
注
要求
宿主 指定其受支持的导入属性,而不是将所有属性传递给
宿主 并让其选择要处理哪些属性的目的,是确保不受支持的属性在不同
宿主 之间以一致的方式处理。
16.2.1.13 GetModuleNamespace ( module )
抽象操作 GetModuleNamespace 接受参数 module (模块记录 具体子类的实例),返回一个模块命名空间对象。它检索表示
module 导出的模块命名空间对象,在第一次请求时惰性创建它,并将其存储在 module .[[Namespace]] 中以供将来检索。调用时执行以下步骤:
断言 :如果
module 是 循环模块记录 ,那么
module .[[Status]] 不是
new 或 unlinked 。
设 namespace 为 module .[[Namespace]] 。
如果 namespace 是 empty ,那么
设 exportedNames 为 module .GetExportedNames()。
设 unambiguousNames 为一个新的空 列表 。
对于 exportedNames 的每个元素 name ,执行
设 resolution 为
module .ResolveExport(name )。
如果 resolution 是 ResolvedBinding
Record ,将 name 附加到
unambiguousNames 。
设 namespace 为 ModuleNamespaceCreate (module ,
unambiguousNames )。
返回 namespace 。
注
GetModuleNamespace
永远不会抛出异常。相反,无法解析的名称在此时简单地从命名空间中排除。除非它们都是未在任何地方明确请求的歧义星号导出,否则稍后会导致真正的链接错误。
16.2.1.14 运行时语义:求值
Module : [empty]
返回 undefined 。
ModuleBody : ModuleItemList
设 result 为 Completion (ModuleItemList 的
求值 )。
如果 result 是 正常完成 且
result .[[Value]] 是
empty ,那么
返回 undefined 。
返回 ? result 。
ModuleItemList :
ModuleItemList
ModuleItem
设 sl 为 ? ModuleItemList 的 求值 。
设 s 为 Completion (ModuleItem 的 求值 )。
返回 ? UpdateEmpty (s ,
sl )。
注
ModuleItem : ImportDeclaration
返回 empty 。
16.2.2 导入
语法
ImportDeclaration
:
import
ImportClause
FromClause
WithClause opt
;
import
ModuleSpecifier
WithClause opt
;
ImportClause :
ImportedDefaultBinding
NameSpaceImport
NamedImports
ImportedDefaultBinding
,
NameSpaceImport
ImportedDefaultBinding
,
NamedImports
ImportedDefaultBinding
:
ImportedBinding
NameSpaceImport :
*
as
ImportedBinding
NamedImports :
{
}
{
ImportsList
}
{
ImportsList
,
}
FromClause :
from
ModuleSpecifier
ImportsList :
ImportSpecifier
ImportsList
,
ImportSpecifier
ImportSpecifier :
ImportedBinding
ModuleExportName
as
ImportedBinding
ModuleSpecifier :
StringLiteral
ImportedBinding :
BindingIdentifier [~Yield,
+Await]
WithClause :
with
{
}
with
{
WithEntries
,opt
}
WithEntries :
AttributeKey
:
StringLiteral
AttributeKey
:
StringLiteral
,
WithEntries
AttributeKey :
IdentifierName
StringLiteral
16.2.2.1 静态语义:早期错误
ModuleItem : ImportDeclaration
WithClause :
with
{
WithEntries
,opt
}
16.2.2.2 静态语义:ImportEntries
语法导向操作
ImportEntries 不接受参数,返回一个包含 ImportEntry
Records 的 列表 。它在以下产生式上分段定义:
Module : [empty]
返回一个新的空 列表 。
ModuleItemList :
ModuleItemList
ModuleItem
设 entries1 为 ModuleItemList 的 ImportEntries 。
设 entries2 为 ModuleItem 的 ImportEntries 。
返回 entries1 和 entries2 的 列表连接 。
ModuleItem :
ExportDeclaration
StatementListItem
返回一个新的空 列表 。
ImportDeclaration
:
import
ImportClause
FromClause
WithClause opt
;
设 module 为 ImportDeclaration 的 ModuleRequests
的唯一元素。
返回 ImportClause
以参数 module 的 ImportEntriesForModule 。
ImportDeclaration
:
import
ModuleSpecifier
WithClause opt
;
返回一个新的空 列表 。
16.2.2.3 静态语义:ImportEntriesForModule
语法导向操作
ImportEntriesForModule 接受参数 module (一个 ModuleRequest
Record ),返回一个包含 ImportEntry
Records 的 列表 。它在以下产生式上分段定义:
ImportClause :
ImportedDefaultBinding
,
NameSpaceImport
设 entries1 为 ImportedDefaultBinding 以参数
module 的 ImportEntriesForModule 。
设 entries2 为 NameSpaceImport 以参数
module 的 ImportEntriesForModule 。
返回 entries1 和 entries2 的 列表连接 。
ImportClause :
ImportedDefaultBinding
,
NamedImports
设 entries1 为 ImportedDefaultBinding 以参数
module 的 ImportEntriesForModule 。
设 entries2 为 NamedImports
以参数 module 的 ImportEntriesForModule 。
返回 entries1 和 entries2 的 列表连接 。
ImportedDefaultBinding
: ImportedBinding
设 localName 为 ImportedBinding 的 BoundNames 的唯一元素。
设 defaultEntry 为 ImportEntry Record {
[[ModuleRequest]] : module , [[ImportName]] : "default" , [[LocalName]] : localName }。
返回 « defaultEntry »。
NameSpaceImport
:
*
as
ImportedBinding
设 localName 为 ImportedBinding 的 StringValue 。
设 entry 为 ImportEntry Record { [[ModuleRequest]] : module , [[ImportName]] : namespace-object ,
[[LocalName]] : localName }。
返回 « entry »。
NamedImports :
{
}
返回一个新的空 列表 。
ImportsList :
ImportsList
,
ImportSpecifier
设 specs1 为 ImportsList 以参数 module 的
ImportEntriesForModule 。
设 specs2 为 ImportSpecifier 以参数
module 的 ImportEntriesForModule 。
返回 specs1 和 specs2 的 列表连接 。
ImportSpecifier
: ImportedBinding
设 localName 为 ImportedBinding 的 BoundNames 的唯一元素。
设 entry 为 ImportEntry Record { [[ModuleRequest]] : module , [[ImportName]] : localName , [[LocalName]] : localName }。
返回 « entry »。
ImportSpecifier
:
ModuleExportName
as
ImportedBinding
设 importName 为 ModuleExportName 的 StringValue 。
设 localName 为 ImportedBinding 的 StringValue 。
设 entry 为 ImportEntry Record { [[ModuleRequest]] : module , [[ImportName]] : importName , [[LocalName]] : localName }。
返回 « entry »。
16.2.2.4 静态语义:WithClauseToAttributes
语法导向操作
WithClauseToAttributes 不接受参数,返回一个包含 ImportAttribute Records
的 列表 。它在以下产生式上分段定义:
WithClause :
with
{
}
返回一个新的空 列表 。
WithClause :
with
{
WithEntries
,opt
}
设 attributes 为 WithEntries 的 WithClauseToAttributes 。
根据 attributes 的 [[Key]] 字段的字典序对其进行排序,将每个这样的字段值视为
UTF-16 代码单元值的序列。注:此排序仅在禁止 宿主 根据属性枚举的顺序改变行为时可观察到。
返回 attributes 。
WithEntries :
AttributeKey
:
StringLiteral
设 key 为 AttributeKey 的 PropName 。
设 entry 为 ImportAttribute
Record { [[Key]] : key ,
[[Value]] : StringLiteral 的 SV }。
返回 « entry »。
WithEntries :
AttributeKey
:
StringLiteral
,
WithEntries
设 key 为 AttributeKey 的 PropName 。
设 entry 为 ImportAttribute
Record { [[Key]] : key ,
[[Value]] : StringLiteral 的 SV }。
设 rest 为 WithEntries 的 WithClauseToAttributes 。
返回 « entry » 和 rest 的 列表连接 。
16.2.3 导出
语法
ExportDeclaration
:
export
ExportFromClause
FromClause
WithClause opt
;
export
NamedExports
;
export
VariableStatement [~Yield,
+Await]
export
Declaration [~Yield,
+Await]
export
default
HoistableDeclaration [~Yield,
+Await, +Default]
export
default
ClassDeclaration [~Yield,
+Await, +Default]
export
default
[lookahead ∉ { function , async
[no LineTerminator here]
function , class }]
AssignmentExpression [+In,
~Yield, +Await]
;
ExportFromClause :
*
*
as
ModuleExportName
NamedExports
NamedExports :
{
}
{
ExportsList
}
{
ExportsList
,
}
ExportsList :
ExportSpecifier
ExportsList
,
ExportSpecifier
ExportSpecifier :
ModuleExportName
ModuleExportName
as
ModuleExportName
16.2.3.1 静态语义:早期错误
ExportDeclaration
:
export
NamedExports
;
注
16.2.3.2 静态语义:ExportedBindings
语法导向操作
ExportedBindings 不接受参数,返回一个字符串 列表 。
注
ExportedBindings 是与 Module 的 ExportedNames
明确关联的本地绑定名称。
它在以下产生式上分段定义:
ModuleItemList :
ModuleItemList
ModuleItem
设 names1 为 ModuleItemList 的 ExportedBindings 。
设 names2 为 ModuleItem 的 ExportedBindings 。
返回 names1 和 names2 的 列表连接 。
ModuleItem :
ImportDeclaration
StatementListItem
返回一个新的空 列表 。
ExportDeclaration
:
export
ExportFromClause
FromClause
WithClause opt
;
返回一个新的空 列表 。
ExportDeclaration
:
export
NamedExports
;
返回 NamedExports 的
ExportedBindings 。
ExportDeclaration
:
export
VariableStatement
返回 VariableStatement 的 BoundNames 。
ExportDeclaration
:
export
Declaration
返回 Declaration 的
BoundNames 。
ExportDeclaration
:
export
default
HoistableDeclaration
export
default
ClassDeclaration
export
default
AssignmentExpression
;
返回此 ExportDeclaration 的 BoundNames 。
NamedExports :
{
}
返回一个新的空 列表 。
ExportsList :
ExportsList
,
ExportSpecifier
设 names1 为 ExportsList 的 ExportedBindings 。
设 names2 为 ExportSpecifier 的 ExportedBindings 。
返回 names1 和 names2 的 列表连接 。
ExportSpecifier
: ModuleExportName
返回一个 列表 ,其唯一元素是
ModuleExportName 的 StringValue 。
ExportSpecifier
:
ModuleExportName
as
ModuleExportName
返回一个 列表 ,其唯一元素是第一个
ModuleExportName 的 StringValue 。
16.2.3.3 静态语义:ExportedNames
语法导向操作
ExportedNames 不接受参数,返回一个字符串 列表 。
注
ExportedNames 是 Module
明确映射到其本地名称绑定之一的外部可见名称。
它在以下产生式上分段定义:
ModuleItemList :
ModuleItemList
ModuleItem
设 names1 为 ModuleItemList 的 ExportedNames 。
设 names2 为 ModuleItem 的 ExportedNames 。
返回 names1 和 names2 的 列表连接 。
ModuleItem : ExportDeclaration
返回 ExportDeclaration 的 ExportedNames 。
ModuleItem :
ImportDeclaration
StatementListItem
返回一个新的空 列表 。
ExportDeclaration
:
export
ExportFromClause
FromClause
WithClause opt
;
返回 ExportFromClause 的 ExportedNames 。
ExportFromClause
: *
返回一个新的空 列表 。
ExportFromClause
:
*
as
ModuleExportName
返回一个 列表 ,其唯一元素是
ModuleExportName 的 StringValue 。
ExportFromClause
: NamedExports
返回 NamedExports 的
ExportedNames 。
ExportDeclaration
:
export
VariableStatement
返回 VariableStatement 的 BoundNames 。
ExportDeclaration
:
export
Declaration
返回 Declaration 的
BoundNames 。
ExportDeclaration
:
export
default
HoistableDeclaration
export
default
ClassDeclaration
export
default
AssignmentExpression
;
返回 « "default" »。
NamedExports :
{
}
返回一个新的空 列表 。
ExportsList :
ExportsList
,
ExportSpecifier
设 names1 为 ExportsList 的 ExportedNames 。
设 names2 为 ExportSpecifier 的 ExportedNames 。
返回 names1 和 names2 的 列表连接 。
ExportSpecifier
: ModuleExportName
返回一个 列表 ,其唯一元素是
ModuleExportName 的 StringValue 。
ExportSpecifier
:
ModuleExportName
as
ModuleExportName
返回一个 列表 ,其唯一元素是第二个
ModuleExportName 的 StringValue 。
16.2.3.4 静态语义:ExportEntries
语法导向操作
ExportEntries 不接受参数,返回一个包含 ExportEntry
Records 的 列表 。它在以下产生式上分段定义:
Module : [empty]
返回一个新的空 列表 。
ModuleItemList :
ModuleItemList
ModuleItem
设 entries1 为 ModuleItemList 的 ExportEntries 。
设 entries2 为 ModuleItem 的 ExportEntries 。
返回 entries1 和 entries2 的 列表连接 。
ModuleItem :
ImportDeclaration
StatementListItem
返回一个新的空 列表 。
ExportDeclaration
:
export
ExportFromClause
FromClause
WithClause opt
;
设 module 为 ExportDeclaration 的 ModuleRequests
的唯一元素。
返回 ExportFromClause 以参数
module 的 ExportEntriesForModule 。
ExportDeclaration
:
export
NamedExports
;
返回 NamedExports
以参数 null 的 ExportEntriesForModule 。
ExportDeclaration
:
export
VariableStatement
设 entries 为一个新的空 列表 。
设 names 为 VariableStatement 的 BoundNames 。
对于 names 的每个元素 name ,执行
将 ExportEntry Record { [[ModuleRequest]] : null , [[ImportName]] : null , [[LocalName]] : name , [[ExportName]] : name } 追加到
entries 。
返回 entries 。
ExportDeclaration
:
export
Declaration
设 entries 为一个新的空 列表 。
设 names 为 Declaration 的 BoundNames 。
对于 names 的每个元素 name ,执行
将 ExportEntry Record { [[ModuleRequest]] : null , [[ImportName]] : null , [[LocalName]] : name , [[ExportName]] : name } 追加到
entries 。
返回 entries 。
ExportDeclaration
:
export
default
HoistableDeclaration
设 names 为 HoistableDeclaration 的
BoundNames 。
设 localName 为 names 的唯一元素。
返回一个 列表 ,其唯一元素是一个新的
ExportEntry Record { [[ModuleRequest]] : null , [[ImportName]] : null , [[LocalName]] : localName , [[ExportName]] : "default" }。
ExportDeclaration
:
export
default
ClassDeclaration
设 names 为 ClassDeclaration 的 BoundNames 。
设 localName 为 names 的唯一元素。
返回一个 列表 ,其唯一元素是一个新的
ExportEntry Record { [[ModuleRequest]] : null , [[ImportName]] : null , [[LocalName]] : localName , [[ExportName]] : "default" }。
ExportDeclaration
:
export
default
AssignmentExpression
;
设 entry 为 ExportEntry Record { [[ModuleRequest]] : null , [[ImportName]] : null , [[LocalName]] : "*default*" , [[ExportName]] : "default" }。
返回 « entry »。
注
"*default*" 在本规范中用作匿名默认导出值的合成名称。详见 此注释 。
16.2.3.5 静态语义:ExportEntriesForModule
语法导向操作
ExportEntriesForModule 接受参数 module (一个 ModuleRequest Record 或
null )并返回一个包含 ExportEntry
Records 的 列表 。它在以下产生式上分段定义:
ExportFromClause
: *
设 entry 为 ExportEntry Record { [[ModuleRequest]] : module , [[ImportName]] : all-but-default , [[LocalName]] : null , [[ExportName]] : null }。
返回 « entry »。
ExportFromClause
:
*
as
ModuleExportName
设 exportName 为 ModuleExportName 的 StringValue 。
设 entry 为 ExportEntry Record { [[ModuleRequest]] : module , [[ImportName]] : all , [[LocalName]] : null , [[ExportName]] : exportName }。
返回 « entry »。
NamedExports :
{
}
返回一个新的空 列表 。
ExportsList :
ExportsList
,
ExportSpecifier
设 specs1 为 ExportsList 以参数 module 的
ExportEntriesForModule 。
设 specs2 为 ExportSpecifier 以参数
module 的 ExportEntriesForModule 。
返回 specs1 和 specs2 的 列表连接 。
ExportSpecifier
: ModuleExportName
设 sourceName 为 ModuleExportName 的 StringValue 。
如果 module 是 null ,那么
设 localName 为 sourceName 。
设 importName 为 null 。
否则,
设 localName 为 null 。
设 importName 为 sourceName 。
返回一个 列表 ,其唯一元素是一个新的
ExportEntry Record { [[ModuleRequest]] : module , [[ImportName]] : importName , [[LocalName]] : localName , [[ExportName]] : sourceName }。
ExportSpecifier
:
ModuleExportName
as
ModuleExportName
设 sourceName 为第一个 ModuleExportName 的 StringValue 。
设 exportName 为第二个 ModuleExportName 的 StringValue 。
如果 module 是 null ,那么
设 localName 为 sourceName 。
设 importName 为 null 。
否则,
设 localName 为 null 。
设 importName 为 sourceName 。
返回一个 列表 ,其唯一元素是一个新的
ExportEntry Record { [[ModuleRequest]] : module , [[ImportName]] : importName , [[LocalName]] : localName , [[ExportName]] : exportName }。
16.2.3.6 静态语义:ReferencedBindings
语法导向操作
ReferencedBindings 不接受参数,返回一个包含 解析节点 的 列表 。它在以下产生式上分段定义:
NamedExports :
{
}
返回一个新的空 列表 。
ExportsList :
ExportsList
,
ExportSpecifier
设 names1 为 ExportsList 的 ReferencedBindings 。
设 names2 为 ExportSpecifier 的 ReferencedBindings 。
返回 names1 和 names2 的 列表连接 。
ExportSpecifier
:
ModuleExportName
as
ModuleExportName
返回第一个 ModuleExportName 的 ReferencedBindings 。
ModuleExportName
: IdentifierName
返回一个 列表 ,其唯一元素是
IdentifierName 。
ModuleExportName
: StringLiteral
返回一个 列表 ,其唯一元素是
StringLiteral 。
16.2.3.7 运行时语义:Evaluation
ExportDeclaration
:
export
ExportFromClause
FromClause
WithClause opt
;
export
NamedExports
;
返回 empty 。
ExportDeclaration
:
export
VariableStatement
返回 ? VariableStatement 的 Evaluation 。
ExportDeclaration
:
export
Declaration
返回 ? Declaration 的 Evaluation 。
ExportDeclaration
:
export
default
HoistableDeclaration
返回 ? HoistableDeclaration 的
Evaluation 。
ExportDeclaration
:
export
default
ClassDeclaration
设 value 为 ? ClassDeclaration 的 BindingClassDeclarationEvaluation 。
设 className 为 ClassDeclaration 的 BoundNames 的唯一元素。
如果 className 是 "*default*" ,那么
设 env 为 正在运行的执行上下文 的
LexicalEnvironment。
执行 ? InitializeBoundName ("*default*" ,
value , env )。
返回 empty 。
ExportDeclaration
:
export
default
AssignmentExpression
;
如果 IsAnonymousFunctionDefinition (AssignmentExpression ) 是
true ,那么
设 value 为 ? AssignmentExpression
以参数 "default" 的 NamedEvaluation 。
否则,
设 rhs 为 ? AssignmentExpression
的 Evaluation 。
设 value 为 ? GetValue (rhs )。
设 env 为 正在运行的执行上下文 的
LexicalEnvironment。
执行 ? InitializeBoundName ("*default*" ,
value , env )。
返回 empty 。
17 错误处理和语言扩展
实现必须在评估相关的 ECMAScript 语言结构时报告大部分错误。早期错误 是可以在评估包含错误的 Script 中的任何结构之前检测和报告的错误。早期错误 的存在会阻止结构的评估。实现必须在 ParseScript 中解析 Script 时报告 Script 中的 早期错误 。Module 中的 早期错误 在 Module 将要被评估的时候报告,并且 Module 永远不会被初始化。eval 代码中的 早期错误 在调用 eval
时报告,并阻止 eval
代码的评估。所有不是 早期错误 的错误都是运行时错误。
实现必须将本规范的"静态语义:早期错误"子条款中列出的任何条件的出现报告为 早期错误 。
即使编译器可以证明结构在任何情况下都不能无错误地执行,实现也不应将其他类型的错误视为 早期错误 。实现可以在这种情况下发出早期警告,但它不应该在相关结构实际执行之前报告错误。
实现应按规定报告所有错误,除了以下情况:
除了在 17.1 中的限制外,宿主 或实现可以扩展 Script 语法、Module 语法以及正则表达式模式或标志语法。为了允许这一点,所有被允许抛出
SyntaxError 的操作(如调用 eval
、使用正则表达式字面量或使用 Function 或 RegExp 构造器 )都被允许表现出 宿主定义的 行为,而不是在遇到脚本语法或正则表达式模式或标志语法的 宿主定义的 扩展时抛出
SyntaxError 。
除了在 17.1 中的限制外,宿主 或实现可以提供超出本规范中描述的附加类型、值、对象、属性和函数。这可能导致结构(如在全局作用域中查找变量)具有
宿主定义的 行为,而不是抛出错误(如 ReferenceError )。
17.1 禁止的扩展
实现不得以以下方式扩展本规范:
18 ECMAScript 标准内置对象
每当 ECMAScript Script 或 Module 开始执行时,都有某些内置对象可用。其中,全局对象 是执行程序的全局环境的一部分。其他对象可以作为 全局对象 的初始属性访问,或者作为可访问的内置对象的属性间接访问。
除非另有规定,可作为函数调用的内置对象是内置 函数对象 ,具有 10.3 中描述的特性。除非另有规定,内置对象的 [[Extensible]] 内部插槽最初具有值 true 。每个内置 函数对象 都有一个 [[Realm]] 内部插槽,其值是对象最初为其创建的 境界 的 Realm Record 。
许多内置对象都是函数:它们可以用参数调用。其中一些还是 构造器 :它们是用于与 new
操作符一起使用的函数。对于每个内置函数,本规范描述了该函数所需的参数和该 函数对象 的属性。对于每个内置 构造器 ,本规范还描述了该 构造器 的原型对象的属性以及调用该 构造器 的 new
表达式返回的特定对象实例的属性。
除非在特定函数的描述中另有规定,如果内置函数或 构造器 给定的参数少于函数指定要求的参数,该函数或 构造器 的行为应完全如同已给定了足够的附加参数,每个这样的参数都是
undefined 值。这样的缺失参数被认为是"不存在的",并且可以通过规范算法以这种方式识别。在特定函数的描述中,术语"this
值"和"NewTarget"具有 10.3 中给出的含义。
除非在特定函数的描述中另有规定,如果所描述的内置函数或 构造器 给定的参数比函数指定允许的更多,则额外的参数由调用评估然后被函数忽略。但是,实现可以定义与这些参数相关的实现特定行为,只要该行为不是简单基于额外参数存在而抛出
TypeError 异常。
注 1
鼓励向内置函数集添加附加功能的实现通过添加新函数而不是向现有函数添加新参数来实现。
除非另有规定,每个内置函数和每个内置 构造器 都将 Function 原型对象 作为其 [[Prototype]] 内部插槽的值,该对象是表达式 Function.prototype
(20.2.3 )的初始值。
除非另有规定,每个内置原型对象都将 Object 原型对象 作为其 [[Prototype]] 内部插槽的值,该对象是表达式 Object.prototype
(20.1.3 )的初始值,除了 Object 原型对象 本身。
如果本规范通过算法步骤定义内置 构造器 的行为,那么这就是它在 [[Call]] 和 [[Construct]] 目的上的行为。如果这样的算法需要区分这两种情况,它会检查 NewTarget 是否为
undefined ,这表示 [[Call]] 调用。
未被标识为 构造器 的内置 函数对象 不实现 [[Construct]] 内部方法,除非在特定函数的描述中另有规定。
不是 构造器 的内置 函数对象 没有
"prototype" 属性,除非在特定函数的描述中另有规定。
本规范中定义的每个内置函数都是通过调用 CreateBuiltinFunction 抽象操作(10.3.4 )创建的。length 和 name
参数的值是 "length" 和 "name" 属性的初始值,如下所述。prefix
参数的值也在下面类似地讨论。
每个内置 函数对象 ,包括
构造器 ,都有一个
"length" 属性,其值是非负的 整数 。除非另有规定,此值是函数描述的子条款标题中显示的必需参数数。可选参数和剩余参数不包括在参数计数中。
注 2
例如,Array 原型对象 的
"map" 属性的初始值的 函数对象 在子条款标题"Array.prototype.map (callback [ ,
thisArg])"下描述,显示了两个命名参数 callback 和 thisArg,后者是可选的;因此该 函数对象 的 "length"
属性的值是 1 𝔽 。
除非另有规定,内置 函数对象 的 "length" 属性具有特性 { [[Writable]] : false , [[Enumerable]] :
false , [[Configurable]] : true }。
每个内置 函数对象 ,包括
构造器 ,都有一个
"name" 属性,其值 是一个字符串 。除非另有规定,此值是本规范中给予函数的名称。被标识为匿名函数的函数使用空字符串作为
"name" 属性的值。对于被指定为对象属性的函数,名称值是用于访问函数的 属性名 字符串。被指定为内置属性的 get 或 set 访问器函数的函数在调用
CreateBuiltinFunction 时将
"get" 或 "set" (分别)传递给 prefix 参数。
对于 属性键 是 Symbol
值的每个内置函数,"name" 属性的值被显式指定。如果这样的显式指定值以前缀 "get " 或 "set
" 开头,并且为其指定的函数是内置属性的 get 或 set 访问器函数,则不带前缀的值传递给 name 参数,并且值
"get" 或 "set" (分别)在调用 CreateBuiltinFunction 时传递给
prefix 参数。
除非另有规定,内置 函数对象 的 "name" 属性具有特性 { [[Writable]] : false , [[Enumerable]] :
false , [[Configurable]] : true }。
条款 19 到
28 以及附录
B.2 中描述的每个其他 数据属性 都具有特性 { [[Writable]] : true , [[Enumerable]] :
false , [[Configurable]] : true },除非另有规定。
条款 19 到
28 以及附录
B.2 中描述的每个 访问器属性 都具有特性 { [[Enumerable]] : false , [[Configurable]] : true },除非另有规定。如果只描述了 get 访问器函数,则 set
访问器函数是默认值 undefined 。如果只描述了 set 访问器,则 get 访问器是默认值 undefined 。
19 全局对象
全局对象 :
在控制进入任何 执行上下文 之前创建。
没有 [[Construct]] 内部方法;它不能作为 构造器 与 new
操作符一起使用。
没有 [[Call]] 内部方法;它不能作为函数调用。
有一个 [[Prototype]] 内部插槽,其值是 宿主定义的 。
除了本规范中定义的属性外,还可能有 宿主定义的 属性。这可能包括一个值为全局对象本身的属性。
19.1 全局对象的值属性
19.1.1 globalThis
Realm Record
realm 中 全局对象 的 "globalThis" 属性的初始值是
realm .[[GlobalEnv]] .[[GlobalThisValue]] 。
此属性具有特性 { [[Writable]] :
true , [[Enumerable]] : false , [[Configurable]] : true }。
19.1.2 Infinity
Infinity
的值是 +∞ 𝔽 (见 6.1.6.1 )。此属性具有特性 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] : false }。
19.1.3 NaN
NaN
的值是 NaN (见 6.1.6.1 )。此属性具有特性 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] : false }。
19.1.4 undefined
undefined
的值是 undefined (见 6.1.1 )。此属性具有特性 {
[[Writable]] : false ,
[[Enumerable]] : false , [[Configurable]] : false }。
19.2 全局对象的函数属性
19.2.1 eval ( x )
此函数是 %eval% 内置对象。
当被调用时执行以下步骤:
返回 ? PerformEval (x ,
false , false )。
19.2.1.1 PerformEval ( x , strictCaller ,
direct )
抽象操作 PerformEval 接受参数 x (一个 ECMAScript
语言值 )、strictCaller (一个布尔值)和 direct (一个布尔值),返回一个包含
ECMAScript 语言值 的 正常完成 或一个 抛出完成 。当被调用时执行以下步骤:
断言 :如果
direct 是 false ,那么 strictCaller 也是
false 。
如果 x 不是字符串 ,返回
x 。
设 evalRealm 为 当前 Realm Record 。
注:在 直接
eval 的情况下,evalRealm 是 eval
调用者和
eval
函数本身的 境界 。
执行 ? HostEnsureCanCompileStrings (evalRealm ,
« », x , direct )。
设 inFunction 为 false 。
设 inMethod 为 false 。
设 inDerivedConstructor 为 false 。
设 inClassFieldInitializer 为 false 。
如果 direct 是 true ,那么
设 thisEnvRec 为 GetThisEnvironment ()。
如果 thisEnvRec 是一个 函数环境记录 ,那么
设 F 为 thisEnvRec .[[FunctionObject]] 。
设 inFunction 为 true 。
设 inMethod 为 thisEnvRec .HasSuperBinding()。
如果 F .[[ConstructorKind]] 是
derived ,设 inDerivedConstructor 为
true 。
设 classFieldInitializerName 为 F .[[ClassFieldInitializerName]] 。
如果 classFieldInitializerName 不是
empty ,设 inClassFieldInitializer 为
true 。
以 实现定义的 顺序执行以下子步骤,可能交替进行解析和错误检测:
设 script 为 ParseText (x , Script )。
如果 script 是一个错误的 列表 ,抛出
SyntaxError 异常。
如果 script Contains
ScriptBody
是 false ,返回 undefined 。
设 body 为 script 的 ScriptBody 。
如果 inFunction 是 false 且 body
Contains
NewTarget ,
抛出 SyntaxError 异常。
如果 inMethod 是 false 且 body
Contains
SuperProperty ,抛出
SyntaxError 异常。
如果 inDerivedConstructor 是 false 且
body Contains
SuperCall ,
抛出 SyntaxError 异常。
如果 inClassFieldInitializer 是 true 且
body 的 ContainsArguments
是 true ,抛出 SyntaxError 异常。
如果 strictCaller 是 true ,设 strictEval 为
true 。
否则,设 strictEval 为 script 的 ScriptIsStrict 。
设 runningContext 为 正在运行的执行上下文 。
注:如果 direct 是 true ,runningContext
将是执行 直接
eval 的 执行上下文 。如果
direct 是 false ,runningContext 将是调用
eval
函数的 执行上下文 。
如果 direct 是 true ,那么
设 lexEnv 为 NewDeclarativeEnvironment (runningContext
的 LexicalEnvironment)。
设 varEnv 为 runningContext 的 VariableEnvironment。
设 privateEnv 为 runningContext 的 PrivateEnvironment。
否则,
设 lexEnv 为 NewDeclarativeEnvironment (evalRealm .[[GlobalEnv]] )。
设 varEnv 为 evalRealm .[[GlobalEnv]] 。
设 privateEnv 为 null 。
如果 strictEval 是 true ,设 varEnv 为
lexEnv 。
如果 runningContext 尚未挂起,挂起 runningContext 。
设 evalContext 为一个新的 ECMAScript
代码执行上下文 。
设 evalContext 的 Function 为 null 。
设 evalContext 的 Realm 为 evalRealm 。
设 evalContext 的 ScriptOrModule 为 runningContext 的
ScriptOrModule。
设 evalContext 的 VariableEnvironment 为 varEnv 。
设 evalContext 的 LexicalEnvironment 为 lexEnv 。
设 evalContext 的 PrivateEnvironment 为 privateEnv 。
将 evalContext 推入 执行上下文栈 ;evalContext
现在是 正在运行的执行上下文 。
设 result 为 Completion (EvalDeclarationInstantiation (body ,
varEnv , lexEnv , privateEnv ,
strictEval ))。
如果 result 是一个 正常完成 ,那么
设 result 为 Completion (body
的 Evaluation )。
如果 result 是一个 正常完成 且
result .[[Value]] 是
empty ,那么
设 result 为 NormalCompletion (undefined )。
挂起 evalContext 并将其从 执行上下文栈 中移除。
恢复现在位于 执行上下文栈 顶部的上下文作为 正在运行的执行上下文 。
返回 ? result 。
注
如果调用上下文的代码或 eval 代码是 严格模式代码 ,那么 eval 代码不能在调用 eval
的调用上下文的变量环境中实例化变量或函数绑定。相反,这些绑定在只有 eval 代码可访问的新 VariableEnvironment 中实例化。由
let
、const
或 class
声明引入的绑定总是在新的
LexicalEnvironment 中实例化。
19.2.1.2 HostEnsureCanCompileStrings ( calleeRealm ,
parameterStrings , bodyString , direct )
宿主定义的 抽象操作 HostEnsureCanCompileStrings 接受参数
calleeRealm (一个 Realm
Record )、parameterStrings (一个字符串的 列表 )、bodyString (一个字符串)和
direct (一个布尔值),返回一个包含 unused 的 正常完成 或一个 抛出完成 。它允许 宿主环境 阻止某些允许开发者将字符串解释和评估为 ECMAScript 代码的
ECMAScript 函数。
parameterStrings 表示在使用函数 构造器 之一时将连接在一起以构建参数列表的字符串。bodyString
表示函数体或传递给 eval
调用的字符串。direct 表示评估是否是 直接 eval 。
HostEnsureCanCompileStrings 的默认实现是返回 NormalCompletion (unused )。
19.2.1.3 EvalDeclarationInstantiation ( body ,
varEnv , lexEnv , privateEnv , strict )
抽象操作 EvalDeclarationInstantiation 接受参数 body (一个 ScriptBody 解析节点 )、varEnv (一个 环境记录 )、lexEnv (一个 声明式环境记录 )、privateEnv (一个
私有环境记录 或 null )和
strict (一个布尔值),返回一个包含 unused 的 正常完成 或一个 抛出完成 。当被调用时执行以下步骤:
设 varNames 为 body 的 VarDeclaredNames 。
设 varDeclarations 为 body 的 VarScopedDeclarations 。
如果 strict 是 false ,那么
如果 varEnv 是一个 全局环境记录 ,那么
对于 varNames 的每个元素 name ,执行
如果 HasLexicalDeclaration (varEnv ,
name ) 是 true ,抛出
SyntaxError 异常。
注:eval
不会创建被全局词法声明遮蔽的全局 var 声明。
设 thisEnv 为 lexEnv 。
断言 :以下循环将终止。
重复,当 thisEnv 和 varEnv 不是同一个 环境记录 时,
如果 thisEnv 不是对象
环境记录 ,那么
注:with 语句的环境不能包含任何词法声明,因此不需要检查 var/let 提升冲突。
对于 varNames 的每个元素 name ,执行
如果
! thisEnv .HasBinding(name )
是 true ,那么
抛出 SyntaxError 异常。
注:附录 B.3.4
为上述步骤定义了替代语义。
注:直接
eval 不会将 var 声明提升到同名的词法声明之上。
设 thisEnv 为 thisEnv .[[OuterEnv]] 。
设 privateIdentifiers 为一个新的空 列表 。
设 pointer 为 privateEnv 。
重复,当 pointer 不是 null 时,
对于 pointer .[[Names]] 的每个 私有名称
binding ,执行
如果 privateIdentifiers 不包含
binding .[[Description]] ,将
binding .[[Description]] 添加到
privateIdentifiers 。
设 pointer 为 pointer .[[OuterPrivateEnvironment]] 。
如果 body 以参数 privateIdentifiers 的 AllPrivateIdentifiersValid
是 false ,抛出 SyntaxError 异常。
设 functionsToInitialize 为一个新的空 列表 。
设 declaredFunctionNames 为一个新的空 列表 。
对于 varDeclarations 的每个元素 d ,以反向 列表 顺序,执行
如果 d 不是 VariableDeclaration 、ForBinding 或
BindingIdentifier ,那么
断言 :d 是 FunctionDeclaration 、GeneratorDeclaration 、AsyncFunctionDeclaration
或 AsyncGeneratorDeclaration 。
注:如果同一个名称有多个函数声明,使用最后一个声明。
设 fn 为 d 的 BoundNames
的唯一元素。
如果 declaredFunctionNames 不包含 fn ,那么
如果 varEnv 是一个 全局环境记录 ,那么
设 fnDefinable 为 ? CanDeclareGlobalFunction (varEnv ,
fn )。
如果 fnDefinable 是
false ,抛出
TypeError 异常。
将 fn 添加到 declaredFunctionNames 。
将 d 插入为 functionsToInitialize 的第一个元素。
设 declaredVarNames 为一个新的空 列表 。
对于 varDeclarations 的每个元素 d ,执行
如果 d 是 VariableDeclaration 、ForBinding 或
BindingIdentifier ,那么
对于 d 的 BoundNames
的每个字符串 vn ,执行
如果 declaredFunctionNames 不包含 vn ,那么
如果 varEnv 是一个 全局环境记录 ,那么
设 vnDefinable 为
? CanDeclareGlobalVar (varEnv ,
vn )。
如果 vnDefinable 是
false ,抛出
TypeError 异常。
如果 declaredVarNames 不包含 vn ,那么
将 vn 添加到
declaredVarNames 。
注:附录 B.3.2.3
在此处添加额外的步骤。
注:除非 varEnv 是一个
全局环境记录 且 全局对象 是一个 Proxy
异质对象 ,否则在此算法步骤之后不会发生异常终止。
设 lexDeclarations 为 body 的 LexicallyScopedDeclarations 。
对于 lexDeclarations 的每个元素 d ,执行
注:词法声明的名称仅在此处实例化但不初始化。
对于 d 的 BoundNames
的每个元素 dn ,执行
如果 d 的 IsConstantDeclaration
是 true ,那么
执行
? lexEnv .CreateImmutableBinding(dn ,
true )。
否则,
执行
? lexEnv .CreateMutableBinding(dn ,
false )。
对于 functionsToInitialize 的每个 解析节点
f ,执行
设 fn 为 f 的 BoundNames
的唯一元素。
设 fo 为 f 以参数 lexEnv 和 privateEnv
的 InstantiateFunctionObject 。
如果 varEnv 是一个 全局环境记录 ,那么
执行 ? CreateGlobalFunctionBinding (varEnv ,
fn , fo , true )。
否则,
设 bindingExists 为
! varEnv .HasBinding(fn )。
如果 bindingExists 是 false ,那么
注:由于步骤 14
之前的验证,以下调用不能返回 异常完成 。
执行
! varEnv .CreateMutableBinding(fn ,
true )。
执行
! varEnv .InitializeBinding(fn ,
fo )。
否则,
执行
! varEnv .SetMutableBinding(fn ,
fo , false )。
对于 declaredVarNames 的每个字符串 vn ,执行
如果 varEnv 是一个 全局环境记录 ,那么
执行 ? CreateGlobalVarBinding (varEnv ,
vn , true )。
否则,
设 bindingExists 为
! varEnv .HasBinding(vn )。
如果 bindingExists 是 false ,那么
注:由于步骤 14
之前的验证,以下调用不能返回 异常完成 。
执行
! varEnv .CreateMutableBinding(vn ,
true )。
执行
! varEnv .InitializeBinding(vn ,
undefined )。
返回 unused 。
注
19.2.2 isFinite ( number )
此函数是 %isFinite% 内置对象。
当被调用时执行以下步骤:
设 num 为 ? ToNumber (number )。
如果 num 不是 有限的 ,返回 false 。
否则,返回 true 。
19.2.3 isNaN ( number )
此函数是 %isNaN% 内置对象。
当被调用时执行以下步骤:
设 num 为 ? ToNumber (number )。
如果 num 是 NaN ,返回 true 。
否则,返回 false 。
注
ECMAScript 代码测试值 X
是否为 NaN 的可靠方法是使用形式为
X !== X
的表达式。当且仅当 X
是 NaN 时,结果将是
true 。
19.2.4 parseFloat ( string )
此函数根据对 string 参数内容作为十进制字面量的解释产生一个数值。
它是 %parseFloat% 内置对象。
当被调用时执行以下步骤:
设 inputString 为 ? ToString (string )。
设 trimmedString 为 ! TrimString (inputString ,
start )。
设 trimmed 为 StringToCodePoints (trimmedString )。
设 trimmedPrefix 为满足 StrDecimalLiteral 语法的
trimmed 的最长前缀,可能是 trimmed 本身。如果没有这样的前缀,返回 NaN 。
设 parsedNumber 为 ParseText (trimmedPrefix , StrDecimalLiteral )。
断言 :
parsedNumber 是一个 解析节点 。
返回 parsedNumber 的 StringNumericValue 。
注
此函数可能仅将 string 的前导部分解释为数值;它忽略任何不能解释为十进制字面量表示法一部分的代码单元,并且不会给出任何此类代码单元被忽略的指示。
19.2.5 parseInt ( string , radix )
此函数根据指定的 radix 对 string 内容的解释产生一个 整数 。忽略 string 中的前导空白。如果
radix 强制转换为 0(例如当它是 undefined 时),则假设为 10,除非数字表示以
"0x" 或 "0X" 开头,在这种情况下假设为 16。如果 radix 是
16,数字表示可以可选地以 "0x" 或 "0X" 开头。
它是 %parseInt% 内置对象。
当被调用时执行以下步骤:
设 inputString 为 ? ToString (string )。
设 S 为 ! TrimString (inputString ,
start )。
设 sign 为 1。
如果 S 不为空且 S 的第一个代码单元是代码单元 0x002D(连字符减号),设 sign 为 -1。
如果 S 不为空且 S 的第一个代码单元是代码单元 0x002B(加号)或代码单元 0x002D(连字符减号),设
S 为 S 从索引 1 开始的 子字符串 。
设 R 为 ℝ (?
ToInt32 (radix ))。
设 stripPrefix 为 true 。
如果 R ≠ 0,那么
如果 R < 2 或 R > 36,返回 NaN 。
如果 R ≠ 16,设 stripPrefix 为 false 。
否则,
设 R 为 10。
如果 stripPrefix 是 true ,那么
如果 S 的长度至少为 2 且 S 的前两个代码单元是 "0x" 或
"0X" ,那么
设 S 为 S 从索引 2 开始的 子字符串 。
设 R 为 16。
如果 S 包含不是基数-R 数字的代码单元,设 end 为 S
中第一个这样的代码单元的索引;否则,设 end 为 S 的长度。
设 Z 为 S 从 0 到 end 的 子字符串 。
如果 Z 为空,返回 NaN 。
设 mathInt 为以基数-R 表示法表示的 Z 所表示的 整数 值,使用字母 A 到
Z 和 a 到 z 表示值 10 到 35 的数字。(但是,如果 R = 10 且 Z
包含超过 20 个有效数字,实现可以选择将第 20 个之后的每个有效数字替换为 0 数字;如果 R 不是 2、4、8、10、16 或 32 之一,那么
mathInt 可能是一个 实现近似的 整数 ,表示 Z
在基数-R 表示法中表示的 整数 值。)
如果 mathInt = 0,那么
如果 sign = -1,返回 -0 𝔽 。
返回 +0 𝔽 。
返回 𝔽 (sign ×
mathInt )。
注
此函数可能仅将 string 的前导部分解释为 整数 值;它忽略任何不能解释为 整数 表示法一部分的代码单元,并且不会给出任何此类代码单元被忽略的指示。
19.2.6 URI 处理函数
统一资源标识符(URI)是标识资源(例如网页或文件)和访问它们的传输协议(例如 HTTP 或 FTP)的字符串。ECMAScript 语言本身不提供对使用 URI
的任何支持,除了本节中描述的编码和解码 URI 的函数。encodeURI
和 decodeURI
旨在与完整的 URI
一起工作;它们假设任何保留字符都旨在具有特殊含义(例如,作为分隔符),因此不进行编码。encodeURIComponent
和
decodeURIComponent
旨在与 URI 的各个组件一起工作;它们假设任何保留字符表示文本,必须编码以避免在组件是完整 URI 的一部分时具有特殊含义。
注 1
保留字符集基于 RFC 2396,不反映更新的 RFC 3986 引入的更改。
注 2
许多 ECMAScript 实现提供操作网页的附加函数和方法;这些函数超出了本标准的范围。
19.2.6.1 decodeURI ( encodedURI )
此函数计算 URI 的新版本,其中每个可能由 encodeURI
函数引入的转义序列和 UTF-8 编码都被其表示的代码点的 UTF-16 编码替换。不可能由
encodeURI
引入的转义序列不被替换。
它是 %decodeURI% 内置对象。
当被调用时执行以下步骤:
设 uriString 为 ? ToString (encodedURI )。
设 preserveEscapeSet 为 ";/?:@&=+$,#" 。
返回 ? Decode (uriString ,
preserveEscapeSet )。
19.2.6.2 decodeURIComponent ( encodedURIComponent )
此函数计算 URI 的新版本,其中每个可能由 encodeURIComponent
函数引入的转义序列和 UTF-8 编码都被其表示的代码点的 UTF-16
编码替换。
它是 %decodeURIComponent% 内置对象。
当被调用时执行以下步骤:
设 componentString 为 ? ToString (encodedURIComponent )。
设 preserveEscapeSet 为空字符串。
返回 ? Decode (componentString ,
preserveEscapeSet )。
19.2.6.3 encodeURI ( uri )
此函数计算 UTF-16 编码(6.1.4 )URI
的新版本,其中某些代码点的每个实例都被表示代码点的 UTF-8 编码的一个、两个、三个或四个转义序列替换。
它是 %encodeURI% 内置对象。
当被调用时执行以下步骤:
设 uriString 为 ? ToString (uri )。
设 extraUnescaped 为 ";/?:@&=+$,#" 。
返回 ? Encode (uriString ,
extraUnescaped )。
19.2.6.4 encodeURIComponent ( uriComponent )
此函数计算 UTF-16 编码(6.1.4 )URI
的新版本,其中某些代码点的每个实例都被表示代码点的 UTF-8 编码的一个、两个、三个或四个转义序列替换。
它是 %encodeURIComponent% 内置对象。
当被调用时执行以下步骤:
设 componentString 为 ? ToString (uriComponent )。
设 extraUnescaped 为空字符串。
返回 ? Encode (componentString ,
extraUnescaped )。
19.2.6.5 Encode ( string , extraUnescaped )
抽象操作 Encode 接受参数 string (一个字符串)和 extraUnescaped (一个字符串),返回一个包含字符串的
正常完成 或一个 抛出完成 。它执行 URI 编码和转义,将
string 解释为 6.1.4
中描述的 UTF-16 编码代码点序列。如果字符在 RFC 2396 中被标识为未保留的或出现在 extraUnescaped
中,则不进行转义。当被调用时执行以下步骤:
设 len 为 string 的长度。
设 R 为空字符串。
设 alwaysUnescaped 为 ASCII 单词字符 和
"-.!~*'()" 的 字符串连接 。
设 unescapedSet 为 alwaysUnescaped 和 extraUnescaped 的
字符串连接 。
设 k 为 0。
重复,当 k < len 时,
设 C 为 string 中索引 k 处的代码单元。
如果 unescapedSet 包含 C ,那么
设 k 为 k + 1。
设 R 为 R 和 C 的 字符串连接 。
否则,
设 cp 为 CodePointAt (string ,
k )。
如果 cp .[[IsUnpairedSurrogate]] 是
true ,抛出 URIError 异常。
设 k 为 k + cp .[[CodeUnitCount]] 。
设 Octets 为通过对 cp .[[CodePoint]] 应用 UTF-8 变换得到的八位字节的 列表 。
对于 Octets 的每个元素 octet ,执行
设 hex 为 octet 的字符串表示,格式化为大写十六进制数。
设 R 为 R 、"%" 和
StringPad (hex ,
2, "0" , start ) 的
字符串连接 。
返回 R 。
注
因为百分号编码用于表示单个八位字节,所以单个代码点可能表示为多个连续的转义序列(其 8 位 UTF-8 代码单元的每一个对应一个)。
19.2.6.6 Decode ( string ,
preserveEscapeSet )
抽象操作 Decode 接受参数 string (一个字符串)和 preserveEscapeSet (一个字符串),返回一个包含字符串的
正常完成 或一个 抛出完成 。它执行 URI
反转义和解码,保留与 preserveEscapeSet 中的基本拉丁字符对应的任何转义序列。当被调用时执行以下步骤:
设 len 为 string 的长度。
设 R 为空字符串。
设 k 为 0。
重复,当 k < len 时,
设 C 为 string 中索引 k 处的代码单元。
设 S 为 C 。
如果 C 是代码单元 0x0025(百分号),那么
如果 k + 3 > len ,抛出
URIError 异常。
设 escape 为 string 从 k 到
k + 3 的 子字符串 。
设 B 为 ParseHexOctet (string ,
k + 1)。
如果 B 不是一个 整数 ,抛出
URIError 异常。
设 k 为 k + 2。
设 n 为 B 中前导 1 位的数量。
如果 n = 0,那么
设 asciiChar 为数值为 B 的代码单元。
如果 preserveEscapeSet 包含 asciiChar ,设
S 为 escape 。否则,设 S 为
asciiChar 。
否则,
如果 n = 1 或 n > 4,抛出
URIError 异常。
设 Octets 为 « B »。
设 j 为 1。
重复,当 j < n 时,
设 k 为 k + 1。
如果 k + 3 > len ,抛出
URIError 异常。
如果 string 中索引 k 处的代码单元不是代码单元
0x0025(百分号),抛出 URIError 异常。
设 continuationByte 为 ParseHexOctet (string ,
k + 1)。
如果 continuationByte 不是一个 整数 ,抛出
URIError 异常。
将 continuationByte 添加到 Octets 。
设 k 为 k + 2。
设 j 为 j + 1。
断言 :Octets
的长度是 n 。
如果 Octets 不包含 Unicode 代码点的有效 UTF-8 编码,抛出
URIError 异常。
设 V 为通过对 Octets 应用 UTF-8
变换获得的代码点,即从八位字节的 列表 到
21 位值。
设 S 为 UTF16EncodeCodePoint (V )。
设 R 为 R 和 S 的 字符串连接 。
设 k 为 k + 1。
返回 R 。
注
RFC 3629 禁止解码无效的 UTF-8 八位字节序列。例如,无效序列 0xC0 0x80 不得解码为代码单元 0x0000。Decode
算法的实现在遇到此类无效序列时必须抛出 URIError 。
19.2.6.7 ParseHexOctet ( string , position
)
抽象操作 ParseHexOctet 接受参数 string (一个字符串)和 position (一个非负 整数 ),返回一个非负 整数 或一个非空的
SyntaxError 对象的 列表 。它解析
string 中指定 position 处的两个十六进制字符序列为一个无符号 8 位 整数 。当被调用时执行以下步骤:
设 len 为 string 的长度。
断言 :
position + 2 ≤ len 。
设 hexDigits 为 string 从 position 到
position + 2 的 子字符串 。
设 parseResult 为 ParseText (hexDigits , HexDigits [~Sep] )。
如果 parseResult 不是一个 解析节点 ,返回
parseResult 。
设 n 为 parseResult 的 MV。
断言 :
n 在从 0 到 255 的 闭区间 内。
返回 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 ] )
此函数在被调用时执行以下步骤:
如果 NewTarget 既不是 undefined 也不是 活动函数对象 ,那么
返回 ? OrdinaryCreateFromConstructor (NewTarget,
"%Object.prototype%" )。
如果 value 是 undefined 或 null ,返回
OrdinaryObjectCreate (%Object.prototype% )。
返回 ! ToObject (value )。
20.1.2 Object 构造器的属性
Object 构造器 :
20.1.2.1 Object.assign ( target ,
...sources )
此函数从一个或多个源对象复制所有可枚举自有属性的值到 target 对象。
当被调用时执行以下步骤:
设 to 为 ? ToObject (target )。
如果只传递了一个参数,返回 to 。
对于 sources 的每个元素 nextSource ,执行
如果 nextSource 既不是 undefined 也不是
null ,那么
设 from 为 ! ToObject (nextSource )。
设 keys 为 ? from .[[OwnPropertyKeys]] () 。
对于 keys 的每个元素 nextKey ,执行
设 desc 为 ? from .[[GetOwnProperty]] (nextKey )。
如果 desc 不是 undefined 且
desc .[[Enumerable]] 是
true ,那么
设 propValue 为 ? Get (from ,
nextKey )。
执行 ? Set (to ,
nextKey , propValue ,
true )。
返回 to 。
此函数的 "length" 属性是 2 𝔽 。
20.1.2.2 Object.create ( O , Properties )
此函数创建一个具有指定原型的新对象。
当被调用时执行以下步骤:
如果 O 不是一个对象 且 O 不是
null ,抛出 TypeError 异常。
设 obj 为 OrdinaryObjectCreate (O )。
如果 Properties 不是 undefined ,那么
返回 ? ObjectDefineProperties (obj ,
Properties )。
返回 obj 。
20.1.2.3 Object.defineProperties ( O ,
Properties )
此函数添加自有属性和/或更新对象现有自有属性的特性。
当被调用时执行以下步骤:
如果 O 不是一个对象 ,抛出
TypeError 异常。
返回 ? ObjectDefineProperties (O ,
Properties )。
20.1.2.3.1 ObjectDefineProperties ( O ,
Properties )
抽象操作 ObjectDefineProperties 接受参数 O (一个对象)和 Properties (一个 ECMAScript 语言值 ),返回一个包含对象的
正常完成 或一个
抛出完成 。当被调用时执行以下步骤:
设 props 为 ? ToObject (Properties )。
设 keys 为 ? props .[[OwnPropertyKeys]] () 。
设 descriptors 为一个新的空 列表 。
对于 keys 的每个元素 nextKey ,执行
设 propDesc 为 ? props .[[GetOwnProperty]] (nextKey )。
如果 propDesc 不是 undefined 且
propDesc .[[Enumerable]] 是
true ,那么
设 descObj 为 ? Get (props ,
nextKey )。
设 desc 为 ? ToPropertyDescriptor (descObj )。
将 记录
{ [[Key]] : nextKey , [[Descriptor]] : desc }
追加到 descriptors 。
对于 descriptors 的每个元素 property ,执行
执行 ? DefinePropertyOrThrow (O ,
property .[[Key]] ,
property .[[Descriptor]] )。
返回 O 。
20.1.2.4 Object.defineProperty ( O , P ,
Attributes )
此函数添加一个自有属性和/或更新对象现有自有属性的特性。
当被调用时执行以下步骤:
如果 O 不是一个对象 ,抛出
TypeError 异常。
设 key 为 ? ToPropertyKey (P )。
设 desc 为 ? ToPropertyDescriptor (Attributes )。
执行 ? DefinePropertyOrThrow (O ,
key , desc )。
返回 O 。
20.1.2.5 Object.entries ( O )
此函数在被调用时执行以下步骤:
设 obj 为 ? ToObject (O )。
设 entryList 为 ? EnumerableOwnProperties (obj ,
key+value )。
返回 CreateArrayFromList (entryList )。
20.1.2.6 Object.freeze ( O )
此函数在被调用时执行以下步骤:
如果 O 不是一个对象 ,返回 O 。
设 status 为 ? SetIntegrityLevel (O ,
frozen )。
如果 status 是 false ,抛出 TypeError 异常。
返回 O 。
20.1.2.7 Object.fromEntries ( iterable )
此函数在被调用时执行以下步骤:
执行 ? RequireObjectCoercible (iterable )。
设 obj 为 OrdinaryObjectCreate (%Object.prototype% )。
断言 :
obj 是一个可扩展的 普通对象 ,没有自有属性。
设 closure 为一个新的 抽象闭包 ,参数为 (key ,
value ),捕获 obj ,当被调用时执行以下步骤:
设 propertyKey 为 ? ToPropertyKey (key )。
执行 ! CreateDataPropertyOrThrow (obj ,
propertyKey , value )。
返回 undefined 。
设 adder 为 CreateBuiltinFunction (closure ,
2, "" , « »)。
返回 ? AddEntriesFromIterable (obj ,
iterable , adder )。
注
为 adder 创建的函数永远不会直接被 ECMAScript 代码访问。
20.1.2.8 Object.getOwnPropertyDescriptor ( O ,
P )
此函数在被调用时执行以下步骤:
设 obj 为 ? ToObject (O )。
设 key 为 ? ToPropertyKey (P )。
设 desc 为 ? obj .[[GetOwnProperty]] (key )。
返回 FromPropertyDescriptor (desc )。
20.1.2.9 Object.getOwnPropertyDescriptors ( O )
此函数在被调用时执行以下步骤:
设 obj 为 ? ToObject (O )。
设 ownKeys 为 ? obj .[[OwnPropertyKeys]] () 。
设 descriptors 为 OrdinaryObjectCreate (%Object.prototype% )。
对于 ownKeys 的每个元素 key ,执行
设 desc 为 ? obj .[[GetOwnProperty]] (key )。
设 descriptor 为 FromPropertyDescriptor (desc )。
如果 descriptor 不是 undefined ,执行 ! CreateDataPropertyOrThrow (descriptors ,
key , descriptor )。
返回 descriptors 。
20.1.2.10 Object.getOwnPropertyNames ( O )
此函数在被调用时执行以下步骤:
返回 CreateArrayFromList (?
GetOwnPropertyKeys (O ,
string ))。
20.1.2.11 Object.getOwnPropertySymbols ( O )
此函数在被调用时执行以下步骤:
返回 CreateArrayFromList (?
GetOwnPropertyKeys (O ,
symbol ))。
20.1.2.11.1 GetOwnPropertyKeys ( O ,
type )
抽象操作 GetOwnPropertyKeys 接受参数 O (一个 ECMAScript 语言值 )和
type (string 或 symbol ),返回一个包含
属性键 的 列表 的 正常完成 或一个
抛出完成 。当被调用时执行以下步骤:
设 obj 为 ? ToObject (O )。
设 keys 为 ? obj .[[OwnPropertyKeys]] () 。
设 nameList 为一个新的空 列表 。
对于 keys 的每个元素 nextKey ,执行
如果 nextKey 是一个符号 且
type 是 symbol ,或者如果 nextKey
是一个字符串 且
type 是 string ,那么
将 nextKey 追加到 nameList 。
返回 nameList 。
20.1.2.12 Object.getPrototypeOf ( O )
此函数在被调用时执行以下步骤:
设 obj 为 ? ToObject (O )。
返回 ? obj .[[GetPrototypeOf]] () 。
20.1.2.13 Object.groupBy ( items , callback
)
注
callback 应该是一个接受两个参数的函数。groupBy
按升序为 items
中的每个元素调用一次 callback ,并构造一个新对象。callback 返回的每个值都被强制转换为 属性键 。对于每个这样的 属性键 ,结果对象有一个属性,其键是该 属性键 ,其值是一个数组,包含 callback
返回值强制转换为该键的所有元素。
callback 用两个参数调用:元素的值和元素的索引。
groupBy
的返回值是一个不继承自 %Object.prototype%
的对象。
此函数在被调用时执行以下步骤:
设 groups 为 ? GroupBy (items ,
callback , property )。
设 obj 为 OrdinaryObjectCreate (null )。
对于 groups 的每个 记录 { [[Key]] , [[Elements]] }
g ,执行
设 elements 为 CreateArrayFromList (g .[[Elements]] )。
执行 ! CreateDataPropertyOrThrow (obj ,
g .[[Key]] , elements )。
返回 obj 。
20.1.2.14 Object.hasOwn ( O , P )
此函数在被调用时执行以下步骤:
设 obj 为 ? ToObject (O )。
设 key 为 ? ToPropertyKey (P )。
返回 ? HasOwnProperty (obj ,
key )。
20.1.2.15 Object.is ( value1 , value2 )
此函数在被调用时执行以下步骤:
返回 SameValue (value1 ,
value2 )。
20.1.2.16 Object.isExtensible ( O )
此函数在被调用时执行以下步骤:
如果 O 不是一个对象 ,返回 false 。
返回 ? IsExtensible (O )。
20.1.2.17 Object.isFrozen ( O )
此函数在被调用时执行以下步骤:
如果 O 不是一个对象 ,返回 true 。
返回 ? TestIntegrityLevel (O ,
frozen )。
20.1.2.18 Object.isSealed ( O )
此函数在被调用时执行以下步骤:
如果 O 不是一个对象 ,返回 true 。
返回 ? TestIntegrityLevel (O ,
sealed )。
20.1.2.19 Object.keys ( O )
此函数在被调用时执行以下步骤:
设 obj 为 ? ToObject (O )。
设 keyList 为 ? EnumerableOwnProperties (obj ,
key )。
返回 CreateArrayFromList (keyList )。
20.1.2.20 Object.preventExtensions ( O )
此函数在被调用时执行以下步骤:
如果 O 不是一个对象 ,返回 O 。
设 status 为 ? O .[[PreventExtensions]] () 。
如果 status 是 false ,抛出 TypeError 异常。
返回 O 。
20.1.2.21 Object.prototype
Object.prototype
的初始值是 Object 原型对象 。
此属性有特性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
20.1.2.22 Object.seal ( O )
此函数在被调用时执行以下步骤:
如果 O 不是一个对象 ,返回 O 。
设 status 为 ? SetIntegrityLevel (O ,
sealed )。
如果 status 是 false ,抛出 TypeError 异常。
返回 O 。
20.1.2.23 Object.setPrototypeOf ( O , proto
)
此函数在被调用时执行以下步骤:
设 O 为 ? RequireObjectCoercible (O )。
如果 proto 不是一个对象 且 proto
不是 null ,抛出 TypeError 异常。
如果 O 不是一个对象 ,返回 O 。
设 status 为 ? O .[[SetPrototypeOf]] (proto )。
如果 status 是 false ,抛出 TypeError 异常。
返回 O 。
20.1.2.24 Object.values ( O )
此函数在被调用时执行以下步骤:
设 obj 为 ? ToObject (O )。
设 valueList 为 ? EnumerableOwnProperties (obj ,
value )。
返回 CreateArrayFromList (valueList )。
20.1.3 Object 原型对象的属性
Object 原型对象 :
是 %Object.prototype% 。
有一个 [[Extensible]] 内部槽,其值是 true 。
有为 普通对象 定义的内部方法,除了 [[SetPrototypeOf]] 方法,它按照 10.4.7.1
中的定义。
(因此,它是一个 不可变原型外来对象 。)
有一个 [[Prototype]] 内部槽,其值是 null 。
20.1.3.1 Object.prototype.constructor
Object.prototype.constructor
的初始值是 %Object% 。
20.1.3.2 Object.prototype.hasOwnProperty ( V )
此方法在被调用时执行以下步骤:
设 P 为 ? ToPropertyKey (V )。
设 O 为 ? ToObject (this 值)。
返回 ? HasOwnProperty (O ,
P )。
注
步骤 1 和 2 的顺序是为了确保,即使
this 值是 undefined 或
null ,在此规范的以前版本中步骤 1 会抛出的任何异常都将继续被抛出。
20.1.3.3 Object.prototype.isPrototypeOf ( V )
此方法在被调用时执行以下步骤:
如果 V 不是一个对象 ,返回 false 。
设 O 为 ? ToObject (this 值)。
重复,
设 V 为 ? V .[[GetPrototypeOf]] () 。
如果 V 是 null ,返回 false 。
如果 SameValue (O ,
V ) 是 true ,返回 true 。
注
步骤 1 和 2 的顺序保持了此规范的以前版本为
V 不是对象且 this 值是 undefined 或
null 的情况指定的行为。
20.1.3.4 Object.prototype.propertyIsEnumerable ( V )
此方法在被调用时执行以下步骤:
设 P 为 ? ToPropertyKey (V )。
设 O 为 ? ToObject (this 值)。
设 desc 为 ? O .[[GetOwnProperty]] (P )。
如果 desc 是 undefined ,返回 false 。
返回 desc .[[Enumerable]] 。
注 1
注 2
步骤 1 和 2 的顺序是为了确保,即使
this 值是 undefined 或
null ,在此规范的以前版本中步骤 1
会抛出的任何异常都将继续被抛出。
20.1.3.5 Object.prototype.toLocaleString ( [
reserved1 [ , reserved2 ] ] )
此方法在被调用时执行以下步骤:
设 O 为 this 值。
返回 ? Invoke (O ,
"toString" )。
此方法的可选参数未被使用,但旨在对应 ECMA-402 toLocaleString
方法使用的参数模式。不包含 ECMA-402
支持的实现不得将这些参数位置用于其他目的。
注 1
此方法为没有区域敏感的 toString
行为的对象提供通用的 toLocaleString
实现。Array
、Number
、Date
和 %TypedArray%
提供它们自己的区域敏感的 toLocaleString
方法。
注 2
ECMA-402 故意不为此默认实现提供替代方案。
20.1.3.6 Object.prototype.toString ( )
此方法在被调用时执行以下步骤:
如果 this 值是 undefined ,返回 "[object
Undefined]" 。
如果 this 值是 null ,返回 "[object
Null]" 。
设 O 为 ! ToObject (this 值)。
设 isArray 为 ? IsArray (O )。
如果 isArray 是 true ,设 builtinTag 为
"Array" 。
否则如果 O 有一个 [[ParameterMap]] 内部槽,设
builtinTag 为 "Arguments" 。
否则如果 O 有一个 [[Call]] 内部方法,设 builtinTag
为 "Function" 。
否则如果 O 有一个 [[ErrorData]] 内部槽,设
builtinTag 为 "Error" 。
否则如果 O 有一个 [[BooleanData]] 内部槽,设
builtinTag 为 "Boolean" 。
否则如果 O 有一个 [[NumberData]] 内部槽,设
builtinTag 为 "Number" 。
否则如果 O 有一个 [[StringData]] 内部槽,设
builtinTag 为 "String" 。
否则如果 O 有一个 [[DateValue]] 内部槽,设
builtinTag 为 "Date" 。
否则如果 O 有一个 [[RegExpMatcher]] 内部槽,设
builtinTag 为 "RegExp" 。
否则,设 builtinTag 为 "Object" 。
设 tag 为 ? Get (O ,
%Symbol.toStringTag% )。
如果 tag 不是一个字符串 ,设
tag 为 builtinTag 。
返回 "[object " 、tag 和 "]" 的 字符串连接 。
注
历史上,此方法偶尔被用来访问 [[Class]]
内部槽的字符串值,该内部槽在此规范的以前版本中用作各种内建对象的名义类型标签。上述 toString
的定义为使用
toString
作为那些特定类型的内建对象测试的遗留代码保持兼容性。它不为其他类型的内建或程序定义的对象提供可靠的类型测试机制。此外,程序可以以会使此类遗留类型测试的可靠性失效的方式使用
%Symbol.toStringTag% 。
20.1.3.7 Object.prototype.valueOf ( )
此方法在被调用时执行以下步骤:
返回 ? ToObject (this 值)。
20.1.3.8 Object.prototype.__proto__
Object.prototype.__proto__
是一个 访问器属性 ,有特性 { [[Enumerable]] : false ,[[Configurable]] : true }。[[Get]] 和 [[Set]] 特性定义如下:
20.1.3.8.1 get Object.prototype.__proto__
[[Get]] 特性的值是一个不需要参数的内建函数。当被调用时执行以下步骤:
设 O 为 ? ToObject (this
值)。
返回 ? O .[[GetPrototypeOf]] () 。
20.1.3.8.2 set Object.prototype.__proto__
[[Set]] 特性的值是一个接受参数 proto 的内建函数。当被调用时执行以下步骤:
设 O 为 ? RequireObjectCoercible (this
值)。
如果 proto 不是一个对象 且 proto 不是
null ,返回 undefined 。
如果 O 不是一个对象 ,返回
undefined 。
设 status 为 ? O .[[SetPrototypeOf]] (proto )。
如果 status 是 false ,抛出 TypeError
异常。
返回 undefined 。
20.1.3.9 遗留的 Object.prototype 访问器方法
20.1.3.9.1 Object.prototype.__defineGetter__ ( P ,
getter )
此方法在被调用时执行以下步骤:
设 O 为 ? ToObject (this
值)。
如果 IsCallable (getter ) 是
false ,抛出 TypeError 异常。
设 desc 为 PropertyDescriptor { [[Get]] :
getter ,[[Enumerable]] :
true ,[[Configurable]] :
true }。
设 key 为 ? ToPropertyKey (P )。
执行 ? DefinePropertyOrThrow (O ,
key , desc )。
返回 undefined 。
20.1.3.9.2 Object.prototype.__defineSetter__ ( P ,
setter )
此方法在被调用时执行以下步骤:
设 O 为 ? ToObject (this
值)。
如果 IsCallable (setter ) 是
false ,抛出 TypeError 异常。
设 desc 为 PropertyDescriptor { [[Set]] :
setter ,[[Enumerable]] :
true ,[[Configurable]] :
true }。
设 key 为 ? ToPropertyKey (P )。
执行 ? DefinePropertyOrThrow (O ,
key , desc )。
返回 undefined 。
20.1.3.9.3 Object.prototype.__lookupGetter__ ( P
)
此方法在被调用时执行以下步骤:
设 O 为 ? ToObject (this
值)。
设 key 为 ? ToPropertyKey (P )。
重复,
设 desc 为 ? O .[[GetOwnProperty]] (key )。
如果 desc 不是 undefined ,那么
如果 IsAccessorDescriptor (desc )
是 true ,返回 desc .[[Get]] 。
返回 undefined 。
设 O 为 ? O .[[GetPrototypeOf]] () 。
如果 O 是 null ,返回
undefined 。
20.1.3.9.4 Object.prototype.__lookupSetter__ ( P
)
此方法在被调用时执行以下步骤:
设 O 为 ? ToObject (this
值)。
设 key 为 ? ToPropertyKey (P )。
重复,
设 desc 为 ? O .[[GetOwnProperty]] (key )。
如果 desc 不是 undefined ,那么
如果 IsAccessorDescriptor (desc )
是 true ,返回 desc .[[Set]] 。
返回 undefined 。
设 O 为 ? O .[[GetPrototypeOf]] () 。
如果 O 是 null ,返回
undefined 。
20.1.4 Object 实例的属性
Object 实例除了从 Object
原型对象 继承的属性外,没有特殊属性。
20.2 Function 对象
20.2.1 Function 构造器
Function 构造器 :
是 %Function% 。
是 全局对象 的 "Function" 属性的初始值。
当作为函数而不是作为 构造器 调用时,创建并初始化一个新的 函数对象 。因此函数调用 Function(…)
等价于使用相同参数的对象创建表达式 new Function(…)
。
可以用作类定义中 extends
子句的值。打算继承指定的 Function 行为的子类 构造器 必须包含一个对 Function 构造器 的
super
调用,以创建和初始化具有内建函数行为所需的内部槽的子类实例。所有用于定义 函数对象 的 ECMAScript 语法形式都创建
Function 的实例。除了内建的 GeneratorFunction、AsyncFunction 和 AsyncGeneratorFunction 子类之外,没有语法方式来创建
Function 子类的实例。
20.2.1.1 Function ( ...parameterArgs ,
bodyArg )
最后一个参数(如果有的话)指定函数的主体(可执行代码);任何前面的参数指定形式参数。
此函数在被调用时执行以下步骤:
设 C 为 活动函数对象 。
如果 bodyArg 不存在,设 bodyArg 为空字符串。
返回 ? CreateDynamicFunction (C ,
NewTarget, normal , parameterArgs ,
bodyArg )。
注
为要指定的每个形式参数都有一个参数是允许的但不是必需的。例如,以下三个表达式都产生相同的结果:
new Function ("a" , "b" , "c" , "return a+b+c" )
new Function ("a, b, c" , "return a+b+c" )
new Function ("a,b" , "c" , "return a+b+c" )
20.2.1.1.1 CreateDynamicFunction ( constructor ,
newTarget , kind , parameterArgs , bodyArg )
抽象操作 CreateDynamicFunction 接受参数 constructor (一个 构造器 )、newTarget (一个
构造器 或
undefined )、kind (normal 、generator 、async
或 async-generator )、parameterArgs (ECMAScript 语言值 的 列表 )和
bodyArg (一个 ECMAScript 语言值 ),返回一个
包含 ECMAScript
函数对象 的 正常完成 或一个
抛出完成 。constructor
是执行此操作的 构造器 函数。newTarget 是最初应用
new
的 构造器 。parameterArgs 和
bodyArg 反映传递给 constructor 的参数值。当被调用时执行以下步骤:
如果 newTarget 是 undefined ,设 newTarget 为
constructor 。
如果 kind 是 normal ,那么
设 prefix 为 "function" 。
设 exprSym 为语法符号 FunctionExpression 。
设 bodySym 为语法符号 FunctionBody [~Yield,
~Await] 。
设 parameterSym 为语法符号 FormalParameters [~Yield,
~Await] 。
设 fallbackProto 为 "%Function.prototype%" 。
否则如果 kind 是 generator ,那么
设 prefix 为 "function*" 。
设 exprSym 为语法符号 GeneratorExpression 。
设 bodySym 为语法符号 GeneratorBody 。
设 parameterSym 为语法符号 FormalParameters [+Yield,
~Await] 。
设 fallbackProto 为
"%GeneratorFunction.prototype%" 。
否则如果 kind 是 async ,那么
设 prefix 为 "async function" 。
设 exprSym 为语法符号 AsyncFunctionExpression 。
设 bodySym 为语法符号 AsyncFunctionBody 。
设 parameterSym 为语法符号 FormalParameters [~Yield,
+Await] 。
设 fallbackProto 为
"%AsyncFunction.prototype%" 。
否则,
断言 :kind 是
async-generator 。
设 prefix 为 "async function*" 。
设 exprSym 为语法符号 AsyncGeneratorExpression 。
设 bodySym 为语法符号 AsyncGeneratorBody 。
设 parameterSym 为语法符号 FormalParameters [+Yield,
+Await] 。
设 fallbackProto 为
"%AsyncGeneratorFunction.prototype%" 。
设 argCount 为 parameterArgs 中元素的数量。
设 parameterStrings 为一个新的空 列表 。
对于 parameterArgs 的每个元素 arg ,执行
将 ? ToString (arg ) 追加到
parameterStrings 。
设 bodyString 为 ? ToString (bodyArg )。
设 currentRealm 为 当前 Realm 记录 。
执行 ? HostEnsureCanCompileStrings (currentRealm ,
parameterStrings , bodyString , false )。
设 P 为空字符串。
如果 argCount > 0,那么
设 P 为 parameterStrings [0]。
设 k 为 1。
重复,当 k < argCount 时,
设 nextArgString 为
parameterStrings [k ]。
设 P 为 P 、"," (逗号)和
nextArgString 的 字符串连接 。
设 k 为 k + 1。
设 bodyParseString 为 0x000A(换行符)、bodyString 和 0x000A(换行符)的
字符串连接 。
设 sourceString 为 prefix 、"
anonymous(" 、P 、0x000A(换行符)、")
{" 、bodyParseString 和 "}" 的 字符串连接 。
设 sourceText 为 StringToCodePoints (sourceString )。
设 parameters 为 ParseText (P ,
parameterSym )。
如果 parameters 是一个错误的 列表 ,抛出
SyntaxError 异常。
设 body 为 ParseText (bodyParseString ,
bodySym )。
如果 body 是一个错误的 列表 ,抛出
SyntaxError 异常。
注:参数和主体分别解析以确保各自都是有效的。例如,new Function("/*", "*/ ) {")
不会计算为函数。
注:如果达到这一步,sourceText 必须具有 exprSym
的语法(尽管反向含义不成立)。接下来两步的目的是执行直接应用于 exprSym 的任何早期错误规则。
设 expr 为 ParseText (sourceText ,
exprSym )。
如果 expr 是一个错误的 列表 ,抛出
SyntaxError 异常。
设 proto 为 ? GetPrototypeFromConstructor (newTarget ,
fallbackProto )。
设 env 为 currentRealm .[[GlobalEnv]] 。
设 privateEnv 为 null 。
设 F 为 OrdinaryFunctionCreate (proto ,
sourceText , parameters , body ,
non-lexical-this , env , privateEnv )。
执行 SetFunctionName (F ,
"anonymous" )。
如果 kind 是 generator ,那么
设 prototype 为 OrdinaryObjectCreate (%GeneratorPrototype% )。
执行 ! DefinePropertyOrThrow (F ,
"prototype" , PropertyDescriptor { [[Value]] : prototype , [[Writable]] : true , [[Enumerable]] : false , [[Configurable]] :
false })。
否则如果 kind 是 async-generator ,那么
设 prototype 为 OrdinaryObjectCreate (%AsyncGeneratorPrototype% )。
执行 ! DefinePropertyOrThrow (F ,
"prototype" , PropertyDescriptor { [[Value]] : prototype , [[Writable]] : true , [[Enumerable]] : false , [[Configurable]] :
false })。
否则如果 kind 是 normal ,那么
执行 MakeConstructor (F )。
注:kind 为 async 的函数不可构造且没有 [[Construct]] 内部方法或 "prototype" 属性。
返回 F 。
注
CreateDynamicFunction 在它创建的任何 kind 不是 async
的函数上定义一个 "prototype" 属性,以提供函数将被用作 构造器 的可能性。
20.2.2 Function 构造器的属性
Function 构造器 :
20.2.2.1 Function.prototype
Function.prototype
的值是 Function
原型对象 。
此属性有特性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
20.2.3 Function 原型对象的属性
Function 原型对象 :
是 %Function.prototype% 。
本身是一个内建的 函数对象 。
接受任何参数并在调用时返回 undefined 。
没有 [[Construct]] 内部方法;它不能与 new
操作符一起用作 构造器 。
有一个 [[Prototype]] 内部槽,其值是 %Object.prototype% 。
没有 "prototype" 属性。
有一个 "length" 属性,其值是 +0 𝔽 。
有一个 "name" 属性,其值是空字符串。
注
Function 原型对象被指定为 函数对象 ,以确保与在 ECMAScript 2015 规范之前创建的
ECMAScript 代码的兼容性。
20.2.3.1 Function.prototype.apply ( thisArg ,
argArray )
此方法在被调用时执行以下步骤:
设 func 为 this 值。
如果 IsCallable (func ) 是
false ,抛出 TypeError 异常。
如果 argArray 是 undefined 或 null ,那么
执行 PrepareForTailCall ()。
返回 ? Call (func ,
thisArg )。
设 argList 为 ? CreateListFromArrayLike (argArray )。
执行 PrepareForTailCall ()。
返回 ? Call (func , thisArg ,
argList )。
注 1
thisArg 值被不加修改地传递作为 this
值。这是与第3版的变化,在第3版中,undefined 或 null 的
thisArg 被替换为 全局对象 ,并且 ToObject
被应用于所有其他值,该结果被传递作为 this 值。尽管 thisArg
被不加修改地传递,非严格函数 在进入函数时仍然执行这些转换。
注 2
如果 func 是箭头函数或 绑定函数外来对象 ,那么
thisArg 将在步骤 6 的函数
[[Call]] 中被忽略。
20.2.3.2 Function.prototype.bind ( thisArg ,
...args )
此方法在被调用时执行以下步骤:
设 Target 为 this 值。
如果 IsCallable (Target ) 是
false ,抛出 TypeError 异常。
设 F 为 ? BoundFunctionCreate (Target ,
thisArg , args )。
设 L 为 0。
设 targetHasLength 为 ? HasOwnProperty (Target ,
"length" )。
如果 targetHasLength 是 true ,那么
设 targetLen 为 ? Get (Target ,
"length" )。
如果 targetLen 是一个数值 ,那么
如果 targetLen 是 +∞ 𝔽 ,那么
设 L 为 +∞。
否则如果 targetLen 是 -∞ 𝔽 ,那么
设 L 为 0。
否则,
设 targetLenAsInt 为 ! ToIntegerOrInfinity (targetLen )。
断言 :targetLenAsInt
是 有限的 。
设 argCount 为 args 中元素的数量。
设 L 为 max (targetLenAsInt
- argCount , 0)。
执行 SetFunctionLength (F ,
L )。
设 targetName 为 ? Get (Target ,
"name" )。
如果 targetName 不是字符串 ,设
targetName 为空字符串。
执行 SetFunctionName (F ,
targetName , "bound" )。
返回 F 。
注 1
使用 Function.prototype.bind
创建的 函数对象 是 外来对象 。它们也没有
"prototype" 属性。
注 2
如果 Target 是箭头函数或 绑定函数外来对象 ,那么传递给此方法的
thisArg 将不会被后续对 F 的调用使用。
20.2.3.3 Function.prototype.call ( thisArg ,
...args )
此方法在被调用时执行以下步骤:
设 func 为 this 值。
如果 IsCallable (func ) 是
false ,抛出 TypeError 异常。
执行 PrepareForTailCall ()。
返回 ? Call (func ,
thisArg ,
args )。
注 1
thisArg 值被不加修改地传递作为 this
值。这是与第3版的变化,在第3版中,undefined 或 null 的
thisArg 被替换为 全局对象 ,并且 ToObject
被应用于所有其他值,该结果被传递作为 this 值。尽管 thisArg
被不加修改地传递,非严格函数 在进入函数时仍然执行这些转换。
注 2
如果 func 是箭头函数或 绑定函数外来对象 ,那么
thisArg 将在步骤 4 的函数 [[Call]] 中被忽略。
20.2.3.4 Function.prototype.constructor
Function.prototype.constructor
的初始值是 %Function% 。
20.2.3.5 Function.prototype.toString ( )
此方法在被调用时执行以下步骤:
设 func 为 this 值。
如果 func 是一个对象 ,func 有一个 [[SourceText]] 内部槽,func .[[SourceText]] 是一个 Unicode 码点序列,并且 HostHasSourceTextAvailable (func )
是 true ,那么
返回 CodePointsToString (func .[[SourceText]] )。
如果 func 是一个 内建函数对象 ,返回
func 的 实现定义的 字符串源代码表示。该表示必须具有 NativeFunction
的语法。另外,如果 func 有一个 [[InitialName]] 内部槽且
func .[[InitialName]] 是一个字符串 ,返回的字符串中与
NativeFunctionAccessor opt
PropertyName
匹配的部分必须是 func .[[InitialName]] 的值。
如果 func 是一个对象 且 IsCallable (func ) 是
true ,返回 func 的 实现定义的 字符串源代码表示。该表示必须具有 NativeFunction 的语法。
抛出 TypeError 异常。
NativeFunction :
function
NativeFunctionAccessor opt
PropertyName [~Yield,
~Await] opt
(
FormalParameters [~Yield,
~Await]
)
{
[
native
code
]
}
NativeFunctionAccessor
:
get
set
20.2.3.6 Function.prototype [ %Symbol.hasInstance% ] (
V )
此方法在被调用时执行以下步骤:
设 F 为 this 值。
返回 ? OrdinaryHasInstance (F ,
V )。
此属性有特性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
注
这是大多数函数继承的 %Symbol.hasInstance%
的默认实现。%Symbol.hasInstance%
被 instanceof
操作符调用,以确定值是否是特定 构造器 的实例。诸如
v instanceof F
的表达式计算为
F[%Symbol .hasInstance %](v)
构造器 函数可以通过在函数上公开不同的
%Symbol.hasInstance%
方法来控制哪些对象被 instanceof
识别为其实例。
此属性是不可写和不可配置的,以防止可能用于全局暴露绑定函数目标函数的篡改。
此方法的 "name" 属性的值是 "[Symbol.hasInstance]" 。
20.2.4 Function 实例
每个 Function 实例都是一个 ECMAScript 函数对象 ,并具有 表 30
中列出的内部槽。使用 Function.prototype.bind
方法(20.2.3.2 )创建的 函数对象 具有
表 31
中列出的内部槽。
Function 实例有以下属性:
20.2.4.1 length
"length" 属性的值是一个 整数 ,表示函数期望的典型参数数量。但是,语言允许使用其他数量的参数调用函数。当使用的参数数量与其
"length" 属性指定的数量不同时,函数的行为取决于该函数。此属性有特性 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] : true }。
20.2.4.2 name
"name" 属性的值 是一个字符串 ,用于描述该函数。该名称没有语义意义,但通常是在
ECMAScript
源文本 中的定义点用来引用函数的变量或 属性名 。此属性有特性 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] : true }。
本规范没有关联上下文名称的匿名函数对象使用空字符串作为 "name" 属性的值。
20.2.4.3 prototype
可以用作 构造器 的
Function 实例有一个 "prototype" 属性。每当创建这样的 Function 实例时,还会创建另一个 普通对象 ,并且它是函数的 "prototype"
属性的初始值。除非另有说明,"prototype" 属性的值用于初始化当该函数作为 构造器 调用时所创建对象的 [[Prototype]] 内部槽。
此属性有特性 { [[Writable]] :
true , [[Enumerable]] : false ,
[[Configurable]] : false }。
注
使用 Function.prototype.bind
创建的 函数对象 ,或通过求值 MethodDefinition (不是 GeneratorMethod 或
AsyncGeneratorMethod )或
ArrowFunction
创建的函数对象没有 "prototype" 属性。
20.2.5 HostHasSourceTextAvailable ( func )
宿主定义的 抽象操作
HostHasSourceTextAvailable 接受参数 func (一个 函数对象 )并返回一个布尔值。它允许 宿主环境 阻止为
func 提供源文本。
HostHasSourceTextAvailable 的实现必须符合以下要求:
它必须相对于其参数是确定性的。每次使用特定的 func 作为参数调用时,它必须返回相同的结果。
HostHasSourceTextAvailable 的默认实现是返回 true 。
20.3 Boolean 对象
20.3.1 Boolean 构造器
Boolean 构造器 :
是 %Boolean% 。
是 全局对象 的 "Boolean" 属性的初始值。
当作为 构造器 调用时,创建并初始化一个新的 Boolean 对象。
当作为函数而不是作为 构造器 调用时,执行类型转换。
可以用作类定义中 extends
子句的值。打算继承指定的 Boolean 行为的子类 构造器 必须包含一个对 Boolean 构造器 的
super
调用,以创建和初始化具有 [[BooleanData]] 内部槽的子类实例。
20.3.1.1 Boolean ( value )
此函数在被调用时执行以下步骤:
设 b 为 ToBoolean (value )。
如果 NewTarget 是 undefined ,返回 b 。
设 O 为 ? OrdinaryCreateFromConstructor (NewTarget,
"%Boolean.prototype%" , « [[BooleanData]] »)。
设 O .[[BooleanData]] 为 b 。
返回 O 。
20.3.2 Boolean 构造器的属性
Boolean 构造器 :
20.3.2.1 Boolean.prototype
Boolean.prototype
的初始值是 Boolean 原型对象 。
此属性有特性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
20.3.3 Boolean 原型对象的属性
Boolean 原型对象 :
是 %Boolean.prototype% 。
是一个 普通对象 。
本身是一个 Boolean 对象;它有一个 [[BooleanData]] 内部槽,值为
false 。
有一个 [[Prototype]] 内部槽,其值是 %Object.prototype% 。
20.3.3.1 Boolean.prototype.constructor
Boolean.prototype.constructor
的初始值是 %Boolean% 。
20.3.3.2 Boolean.prototype.toString ( )
此方法在被调用时执行以下步骤:
设 b 为 ? ThisBooleanValue (this
value)。
如果 b 是 true ,返回 "true" ;否则返回
"false" 。
20.3.3.3 Boolean.prototype.valueOf ( )
此方法在被调用时执行以下步骤:
返回 ? ThisBooleanValue (this
value)。
20.3.3.3.1 ThisBooleanValue ( value )
抽象操作 ThisBooleanValue 接受参数 value (一个 ECMAScript 语言值 )并返回一个
包含 布尔值的 正常完成 或一个
抛出完成 。当被调用时执行以下步骤:
如果 value 是一个布尔值 ,返回
value 。
如果 value 是一个对象 且 value 有一个 [[BooleanData]] 内部槽,那么
设 b 为 value .[[BooleanData]] 。
断言 :b 是一个布尔值 。
返回 b 。
抛出 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 ] )
此函数在被调用时执行以下步骤:
如果 NewTarget 不是 undefined ,抛出 TypeError 异常。
如果 description 是 undefined ,设 descString
为 undefined 。
否则,设 descString 为 ? ToString (description )。
返回一个新的 Symbol,其 [[Description]] 是 descString 。
20.4.2 Symbol 构造器的属性
Symbol 构造器 :
20.4.2.1 Symbol.asyncIterator
Symbol.asyncIterator
的初始值是众所周知的符号 %Symbol.asyncIterator% (表
1 )。
此属性有特性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
20.4.2.2 Symbol.for ( key )
此函数在被调用时执行以下步骤:
设 stringKey 为 ? ToString (key )。
对于 GlobalSymbolRegistry 列表 的每个元素
e ,执行
如果 e .[[Key]] 是 stringKey ,
返回 e .[[Symbol]] 。
断言 :GlobalSymbolRegistry
列表 当前不包含 stringKey 的条目。
设 newSymbol 为一个新的 Symbol,其 [[Description]] 是
stringKey 。
将 GlobalSymbolRegistry 记录 { [[Key]] : stringKey , [[Symbol]] : newSymbol } 追加到 GlobalSymbolRegistry 列表 。
返回 newSymbol 。
GlobalSymbolRegistry 列表 是一个只能追加的 列表 ,全局可用。它被所有 Realm 共享。在任何 ECMAScript
代码的求值之前,它被初始化为一个新的空 列表 。GlobalSymbolRegistry
列表的元素是具有 表 63 中定义的结构的
记录 。
表 63:GlobalSymbolRegistry 记录 字段
字段名
值
用法
[[Key]]
一个字符串
用于全局标识 Symbol 的字符串键。
[[Symbol]]
一个 Symbol
可以从任何 Realm 检索的符号。
20.4.2.3 Symbol.hasInstance
Symbol.hasInstance
的初始值是众所周知的符号 %Symbol.hasInstance% (表
1 )。
此属性有特性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
20.4.2.4 Symbol.isConcatSpreadable
Symbol.isConcatSpreadable
的初始值是众所周知的符号 %Symbol.isConcatSpreadable% (表
1 )。
此属性有特性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
20.4.2.5 Symbol.iterator
Symbol.iterator
的初始值是众所周知的符号 %Symbol.iterator% (表
1 )。
此属性有特性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
20.4.2.6 Symbol.keyFor ( sym )
此函数在被调用时执行以下步骤:
如果 sym 不是
Symbol ,抛出 TypeError 异常。
返回 KeyForSymbol (sym )。
20.4.2.7 Symbol.match
Symbol.match
的初始值是众所周知的符号 %Symbol.match% (表
1 )。
此属性有特性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
20.4.2.8 Symbol.matchAll
Symbol.matchAll
的初始值是众所周知的符号 %Symbol.matchAll% (表
1 )。
此属性有特性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
20.4.2.9 Symbol.prototype
Symbol.prototype
的初始值是 Symbol 原型对象 。
此属性有特性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
20.4.2.10 Symbol.replace
Symbol.replace
的初始值是众所周知的符号 %Symbol.replace% (表
1 )。
此属性有特性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
20.4.2.11 Symbol.search
Symbol.search
的初始值是众所周知的符号 %Symbol.search% (表
1 )。
此属性有特性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
20.4.2.12 Symbol.species
Symbol.species
的初始值是众所周知的符号 %Symbol.species% (表
1 )。
此属性有特性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
20.4.2.13 Symbol.split
Symbol.split
的初始值是众所周知的符号 %Symbol.split% (表
1 )。
此属性有特性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
20.4.2.14 Symbol.toPrimitive
Symbol.toPrimitive
的初始值是众所周知的符号 %Symbol.toPrimitive% (表
1 )。
此属性有特性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
20.4.2.15 Symbol.toStringTag
Symbol.toStringTag
的初始值是众所周知的符号 %Symbol.toStringTag% (表
1 )。
此属性有特性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
20.4.2.16 Symbol.unscopables
Symbol.unscopables
的初始值是众所周知的符号 %Symbol.unscopables% (表
1 )。
此属性有特性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
20.4.3 Symbol 原型对象的属性
Symbol 原型对象 :
20.4.3.1 Symbol.prototype.constructor
Symbol.prototype.constructor
的初始值是 %Symbol% 。
20.4.3.2 get Symbol.prototype.description
Symbol.prototype.description
是一个 访问器属性 ,其 set 访问器函数是
undefined 。其 get 访问器函数在被调用时执行以下步骤:
设 s 为 this 值。
设 sym 为 ? ThisSymbolValue (s )。
返回 sym .[[Description]] 。
20.4.3.3 Symbol.prototype.toString ( )
此方法在被调用时执行以下步骤:
设 sym 为 ? ThisSymbolValue (this
value)。
返回 SymbolDescriptiveString (sym )。
20.4.3.3.1 SymbolDescriptiveString ( sym )
抽象操作 SymbolDescriptiveString 接受参数 sym (一个 Symbol)并返回一个字符串。当被调用时执行以下步骤:
设 desc 为 sym 的 [[Description]] 值。
如果 desc 是 undefined ,设 desc 为空字符串。
断言 :desc 是一个字符串 。
返回 "Symbol(" 、desc 和 ")" 的
字符串连接 。
20.4.3.4 Symbol.prototype.valueOf ( )
此方法在被调用时执行以下步骤:
返回 ? ThisSymbolValue (this
value)。
20.4.3.4.1 ThisSymbolValue ( value )
抽象操作 ThisSymbolValue 接受参数 value (一个 ECMAScript 语言值 )并返回一个
包含 Symbol 的
正常完成 或一个
抛出完成 。当被调用时执行以下步骤:
如果 value 是一个
Symbol ,返回 value 。
如果 value 是一个对象 且 value 有一个 [[SymbolData]] 内部槽,那么
设 s 为 value .[[SymbolData]] 。
断言 :s 是一个
Symbol 。
返回 s 。
抛出 TypeError 异常。
20.4.3.5 Symbol.prototype [ %Symbol.toPrimitive% ] (
hint )
此方法被 ECMAScript 语言操作符调用,以将 Symbol 对象转换为原始值。
当被调用时执行以下步骤:
返回 ? ThisSymbolValue (this
value)。
注
此属性有特性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : true }。
此方法的 "name" 属性的值是 "[Symbol.toPrimitive]" 。
20.4.3.6 Symbol.prototype [ %Symbol.toStringTag% ]
%Symbol.toStringTag% 属性的初始值是字符串值
"Symbol" 。
此属性有特性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : true }。
20.4.4 Symbol 实例的属性
Symbol 实例是从 Symbol 原型对象 继承属性的
普通对象 。Symbol 实例有一个 [[SymbolData]] 内部槽。[[SymbolData]] 内部槽是此 Symbol
对象表示的 Symbol 值。
20.4.5 Symbol 的抽象操作
20.4.5.1 KeyForSymbol ( sym )
抽象操作 KeyForSymbol 接受参数 sym (一个 Symbol)并返回一个字符串或 undefined 。如果
sym 在 GlobalSymbolRegistry 列表 中,将返回用于注册
sym 的字符串。当被调用时执行以下步骤:
对于 GlobalSymbolRegistry 列表 的每个元素
e ,执行
如果 SameValue (e .[[Symbol]] , sym ) 是
true ,返回 e .[[Key]] 。
断言 :GlobalSymbolRegistry
列表 当前不包含 sym 的条目。
返回 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 ] )
此函数在被调用时执行以下步骤:
如果 NewTarget 是 undefined ,设 newTarget 为 活动函数对象 ;否则设
newTarget 为 NewTarget。
设 O 为 ? OrdinaryCreateFromConstructor (newTarget ,
"%Error.prototype%" , « [[ErrorData]] »)。
如果 message 不是 undefined ,那么
设 msg 为 ? ToString (message )。
执行 CreateNonEnumerableDataPropertyOrThrow (O ,
"message" , msg )。
执行 ? InstallErrorCause (O ,
options )。
返回 O 。
20.5.2 Error 构造器的属性
Error 构造器 :
20.5.2.1 Error.prototype
Error.prototype
的初始值是 Error 原型对象 。
此属性有特性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
20.5.3 Error 原型对象的属性
Error 原型对象 :
是 %Error.prototype% 。
是一个 普通对象 。
不是 Error 实例,并且没有 [[ErrorData]] 内部槽。
有一个 [[Prototype]] 内部槽,其值是 %Object.prototype% 。
20.5.3.1 Error.prototype.constructor
Error.prototype.constructor
的初始值是 %Error% 。
20.5.3.2 Error.prototype.message
Error.prototype.message
的初始值是空字符串。
20.5.3.3 Error.prototype.name
Error.prototype.name
的初始值是 "Error" 。
20.5.3.4 Error.prototype.toString ( )
此方法在被调用时执行以下步骤:
设 O 为 this 值。
如果 O 不是对象 ,抛出 TypeError
异常。
设 name 为 ? Get (O ,
"name" )。
如果 name 是 undefined ,设 name 为
"Error" ;否则设 name 为 ? ToString (name )。
设 msg 为 ? Get (O ,
"message" )。
如果 msg 是 undefined ,设 msg 为空字符串;否则设
msg 为 ? ToString (msg )。
如果 name 是空字符串,返回 msg 。
如果 msg 是空字符串,返回 name 。
返回 name 、代码单元 0x003A(冒号)、代码单元 0x0020(空格)和 msg 的 字符串连接 。
20.5.4 Error 实例的属性
Error 实例是从 Error 原型对象 继承属性的
普通对象 ,并有一个值为 undefined 的 [[ErrorData]] 内部槽。[[ErrorData]] 的唯一指定用途是在
Object.prototype.toString
中将 Error、AggregateError 和 NativeError 实例标识为
Error 对象。
20.5.5 本标准中使用的原生 Error 类型
当检测到运行时错误时,会抛出下面 NativeError 对象之一或 AggregateError 对象的新实例。所有 NativeError
对象共享相同的结构,如 20.5.6 中所述。
20.5.5.1 EvalError
EvalError 构造器 是 %EvalError% 。
此异常当前在本规范中未使用。保留此对象是为了与本规范的先前版本兼容。
20.5.5.2 RangeError
RangeError 构造器 是 %RangeError% 。
表示一个不在允许值集合或范围内的值。
20.5.5.3 ReferenceError
ReferenceError 构造器 是 %ReferenceError% 。
表示检测到无效引用。
20.5.5.4 SyntaxError
SyntaxError 构造器 是 %SyntaxError% 。
表示发生了解析错误。
20.5.5.5 TypeError
TypeError 构造器 是 %TypeError% 。
TypeError 用于表示不成功的操作,当其他 NativeError 对象都不适合表示失败原因时使用。
20.5.5.6 URIError
URIError 构造器 是 %URIError% 。
表示某个全局 URI 处理函数的使用方式与其定义不兼容。
20.5.6 NativeError 对象结构
这些对象中的每一个都具有下面描述的结构,仅在用作 构造器 名称和原型对象的 "name" 属性中使用的名称上有所不同。
对于每个错误对象,定义中对 NativeError 的引用应替换为 20.5.5 中的相应错误对象名称。
20.5.6.1 NativeError 构造器
每个 NativeError 构造器 :
当作为函数而不是作为 构造器 调用时,创建并初始化一个新的 NativeError
对象。将对象作为函数调用等同于使用相同参数将其作为 构造器 调用。因此函数调用
NativeError (…)
等同于具有相同参数的对象创建表达式
new NativeError (…)
。
可以用作类定义中 extends
子句的值。打算继承指定的 NativeError 行为的子类 构造器 必须包含一个对
NativeError 构造器 的 super
调用,以创建和初始化具有 [[ErrorData]] 内部槽的子类实例。
20.5.6.1.1 NativeError ( message [ ,
options ] )
每个 NativeError 函数在被调用时执行以下步骤:
如果 NewTarget 是 undefined ,设 newTarget 为 活动函数对象 ;否则设
newTarget 为 NewTarget。
设 O 为
? OrdinaryCreateFromConstructor (newTarget ,
"%NativeError .prototype%"
, « [[ErrorData]] »)。
如果 message 不是 undefined ,那么
设 msg 为 ? ToString (message )。
执行 CreateNonEnumerableDataPropertyOrThrow (O ,
"message" , msg )。
执行 ? InstallErrorCause (O ,
options )。
返回 O 。
在步骤 2
中传递的字符串的实际值是
"%EvalError.prototype%" 、"%RangeError.prototype%" 、"%ReferenceError.prototype%" 、"%SyntaxError.prototype%" 、"%TypeError.prototype%"
或 "%URIError.prototype%" 中的一个,对应于正在定义的 NativeError
构造器 。
20.5.6.2 NativeError 构造器的属性
每个 NativeError 构造器 :
有一个 [[Prototype]] 内部槽,其值是 %Error% 。
有一个 "name" 属性,其值是字符串值 "NativeError " 。
有以下属性:
20.5.6.2.1 NativeError .prototype
NativeError .prototype
的初始值是一个 NativeError
原型对象(20.5.6.3 )。每个
NativeError 构造器 都有一个不同的原型对象。
此属性有特性 { [[Writable]] :
false , [[Enumerable]] :
false , [[Configurable]] :
false }。
20.5.6.3 NativeError 原型对象的属性
每个 NativeError 原型对象 :
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、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 ] )
此函数在被调用时执行以下步骤:
如果 NewTarget 是 undefined ,设 newTarget 为 活动函数对象 ;否则设
newTarget 为 NewTarget。
设 O 为 ? OrdinaryCreateFromConstructor (newTarget ,
"%AggregateError.prototype%" , « [[ErrorData]] »)。
如果 message 不是 undefined ,那么
设 msg 为 ? ToString (message )。
执行 CreateNonEnumerableDataPropertyOrThrow (O ,
"message" , msg )。
执行 ? InstallErrorCause (O ,
options )。
设 errorsList 为 ? IteratorToList (? GetIterator (errors ,
sync ))。
执行 ! DefinePropertyOrThrow (O ,
"errors" , PropertyDescriptor { [[Configurable]] : true , [[Enumerable]] : false , [[Writable]] : true , [[Value]] : CreateArrayFromList (errorsList ) })。
返回 O 。
20.5.7.2 AggregateError 构造器的属性
AggregateError 构造器 :
有一个 [[Prototype]] 内部槽,其值是 %Error% 。
有以下属性:
20.5.7.2.1 AggregateError.prototype
AggregateError.prototype
的初始值是 %AggregateError.prototype% 。
此属性有特性 { [[Writable]] :
false , [[Enumerable]] :
false , [[Configurable]] :
false }。
20.5.7.3 AggregateError 原型对象的属性
AggregateError 原型对象 :
是 %AggregateError.prototype% 。
是一个 普通对象 。
不是 Error 实例或 AggregateError 实例,并且没有 [[ErrorData]] 内部槽。
有一个 [[Prototype]] 内部槽,其值是 %Error.prototype% 。
20.5.7.3.1 AggregateError.prototype.constructor
AggregateError.prototype.constructor
的初始值是 %AggregateError% 。
20.5.7.3.2 AggregateError.prototype.message
AggregateError.prototype.message
的初始值是空字符串。
20.5.7.3.3 AggregateError.prototype.name
AggregateError.prototype.name
的初始值是 "AggregateError" 。
20.5.7.4 AggregateError 实例的属性
AggregateError 实例是从其 AggregateError
原型对象 继承属性的 普通对象 ,并有一个值为 undefined 的
[[ErrorData]] 内部槽。[[ErrorData]] 的唯一指定用途是被
Object.prototype.toString
(20.1.3.6 )用来标识
Error、AggregateError 或 NativeError 实例。
20.5.8 Error 对象的抽象操作
20.5.8.1 InstallErrorCause ( O , options )
抽象操作 InstallErrorCause 接受参数 O (一个对象)和 options (一个 ECMAScript 语言值 ),并返回一个 包含
unused 的 正常完成 或一个 抛出完成 。当
options 上存在 "cause" 属性时,它用于在 O 上创建一个
"cause" 属性。当被调用时执行以下步骤:
如果 options 是一个对象 且 ? HasProperty (options ,
"cause" ) 是 true ,那么
设 cause 为 ? Get (options ,
"cause" )。
执行 CreateNonEnumerableDataPropertyOrThrow (O ,
"cause" , cause )。
返回 unused 。
21 数字和日期
21.1 Number 对象
21.1.1 Number 构造器
Number 构造器 :
是 %Number% 。
是 全局对象 的 "Number" 属性的初始值。
当作为 构造器 调用时,创建并初始化一个新的 Number 对象。
当作为函数而不是作为 构造器 调用时,执行类型转换。
可以用作类定义中 extends
子句的值。打算继承指定的 Number 行为的子类 构造器 必须包含一个对 Number 构造器 的
super
调用,以创建和初始化具有 [[NumberData]] 内部槽的子类实例。
21.1.1.1 Number ( value )
此函数在被调用时执行以下步骤:
如果 value 存在,那么
设 prim 为 ? ToNumeric (value )。
如果 prim 是
BigInt ,设 n 为 𝔽 (ℝ (prim ))。
否则,设 n 为 prim 。
否则,
设 n 为 +0 𝔽 。
如果 NewTarget 是 undefined ,返回 n 。
设 O 为 ? OrdinaryCreateFromConstructor (NewTarget,
"%Number.prototype%" , « [[NumberData]] »)。
设置 O .[[NumberData]] 为 n 。
返回 O 。
21.1.2 Number 构造器的属性
Number 构造器 :
21.1.2.1 Number.EPSILON
Number.EPSILON
的值是 1 与大于 1 的可表示为 Number 值的最小值之间差值的幅度的 Number
值 ,约为 2.2204460492503130808472633361816 × 10-16 。
此属性有特性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
21.1.2.2 Number.isFinite ( number )
此函数在被调用时执行以下步骤:
如果 number 不是
Number ,返回 false 。
如果 number 不是 有限的 ,返回 false 。
否则,返回 true 。
21.1.2.3 Number.isInteger ( number )
此函数在被调用时执行以下步骤:
如果 number 是 整数 Number ,返回 true 。
返回 false 。
21.1.2.4 Number.isNaN ( number )
此函数在被调用时执行以下步骤:
如果 number 不是
Number ,返回 false 。
如果 number 是 NaN ,返回 true 。
否则,返回 false 。
注
此函数与全局 isNaN 函数(19.2.3 )的不同之处在于,它在确定参数是否为
NaN 之前不会将其转换为 Number。
21.1.2.5 Number.isSafeInteger ( number )
注
当且仅当 n 的 Number 值 不是任何其他 整数 的 Number
值 时,整数 n 是"安全整数 "。
此函数在被调用时执行以下步骤:
如果 number 是 整数 Number ,那么
如果 abs (ℝ (number )) ≤
253 - 1,返回 true 。
返回 false 。
21.1.2.6 Number.MAX_SAFE_INTEGER
注
由于 IEEE
754-2019 精度限制所必需的舍入行为,每个大于
Number.MAX_SAFE_INTEGER
的 整数 的 Number 值 都与至少一个其他
整数 共享。因此,这些大幅度的 整数 不是 安全的 ,并且不保证能准确表示为 Number
值,甚至不保证彼此可区分。例如,9007199254740992
和 9007199254740993
都计算为
Number 值 9007199254740992 𝔽 。
Number.MAX_SAFE_INTEGER
的值是
9007199254740991 𝔽 (𝔽 (253 - 1))。
此属性有特性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
21.1.2.7 Number.MAX_VALUE
Number.MAX_VALUE
的值是 Number
类型 的最大正 有限 值,约为 1.7976931348623157 ×
10308 。
此属性有特性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
21.1.2.8 Number.MIN_SAFE_INTEGER
注
由于 IEEE
754-2019 精度限制所必需的舍入行为,每个小于
Number.MIN_SAFE_INTEGER
的 整数 的 Number 值 都与至少一个其他
整数 共享。因此,这些大幅度的 整数 不是 安全的 ,并且不保证能准确表示为 Number
值,甚至不保证彼此可区分。例如,-9007199254740992
和 -9007199254740993
都计算为
Number 值 -9007199254740992 𝔽 。
Number.MIN_SAFE_INTEGER
的值是
-9007199254740991 𝔽 (𝔽 (-(253 - 1)))。
此属性有特性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
21.1.2.9 Number.MIN_VALUE
Number.MIN_VALUE
的值是 Number
类型 的最小正值,约为 5 × 10-324 。
在 IEEE
754-2019
双精度二进制表示中,最小可能值是非正规化数。如果实现不支持非正规化值,Number.MIN_VALUE
的值必须是实现实际能表示的最小非零正值。
此属性有特性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
21.1.2.10 Number.NaN
Number.NaN
的值是 NaN 。
此属性有特性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
21.1.2.11 Number.NEGATIVE_INFINITY
Number.NEGATIVE_INFINITY
的值是 -∞ 𝔽 。
此属性有特性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
21.1.2.12 Number.parseFloat ( string )
"parseFloat" 属性的初始值是 %parseFloat% 。
21.1.2.13 Number.parseInt ( string , radix
)
"parseInt" 属性的初始值是 %parseInt% 。
21.1.2.14 Number.POSITIVE_INFINITY
Number.POSITIVE_INFINITY
的值是 +∞ 𝔽 。
此属性有特性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
21.1.2.15 Number.prototype
Number.prototype
的初始值是 Number 原型对象 。
此属性有特性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
21.1.3 Number 原型对象的属性
Number 原型对象 :
是 %Number.prototype% 。
是一个 普通对象 。
本身是一个 Number 对象;它有一个 [[NumberData]] 内部槽,值为
+0 𝔽 。
有一个 [[Prototype]] 内部槽,其值是 %Object.prototype% 。
除非明确说明,下面定义的 Number 原型对象的方法不是通用的,传递给它们的 this 值必须是 Number 值或具有已初始化为 Number 值的
[[NumberData]] 内部槽的对象。
方法规范中的短语"此 Number 值"是指通过将方法调用的 this 值作为参数调用抽象操作 ThisNumberValue 返回的结果。
21.1.3.1 Number.prototype.constructor
Number.prototype.constructor
的初始值是 %Number% 。
21.1.3.2 Number.prototype.toExponential (
fractionDigits )
此方法返回一个字符串,包含以十进制指数记法表示的此 Number 值,有效数字的小数点前有一位数字,小数点后有 fractionDigits 位数字。如果
fractionDigits 是 undefined ,它包含尽可能多的有效数字位数以唯一地指定 Number(就像在
ToString
中一样,除了在这种情况下 Number 总是以指数记法输出)。
当被调用时执行以下步骤:
设 x 为 ? ThisNumberValue (this
value)。
设 f 为 ? ToIntegerOrInfinity (fractionDigits )。
断言 :如果
fractionDigits 是 undefined ,那么 f 是 0。
如果 x 不是 有限的 ,返回 Number::toString (x ,
10)。
如果 f < 0 或 f > 100,抛出 RangeError 异常。
设置 x 为 ℝ (x )。
设 s 为空字符串。
如果 x < 0,那么
设置 s 为 "-" 。
设置 x 为 -x 。
如果 x = 0,那么
设 m 为由 f + 1 个代码单元 0x0030(数字零)组成的字符串值。
设 e 为 0。
否则,
如果 fractionDigits 不是 undefined ,那么
设 e 和 n 为 整数 ,使得
10f ≤ n <
10f + 1 且 n ×
10e - f - x
尽可能接近零。如果有两组这样的 e 和 n ,选择使 n ×
10e - f 更大的 e 和
n 。
否则,
设
e 、n 和 ff 为 整数 ,使得 ff ≥
0,10ff ≤ n <
10ff + 1 ,𝔽 (n ×
10e - ff ) 是 𝔽 (x ),
且 ff 尽可能小。注意 n 的十进制表示有 ff + 1
位数字,n 不能被 10 整除,且 n 的最低有效位不一定由这些条件唯一确定。
设置 f 为 ff 。
设 m 为由 n 的十进制表示的数字组成的字符串值(按顺序,没有前导零)。
如果 f ≠ 0,那么
设 a 为 m 的第一个代码单元。
设 b 为 m 的其他 f 个代码单元。
设置 m 为 a 、"." 和 b 的
字符串连接 。
如果 e = 0,那么
设 c 为 "+" 。
设 d 为 "0" 。
否则,
如果 e > 0,那么
设 c 为 "+" 。
否则,
断言 :e < 0。
设 c 为 "-" 。
设置 e 为 -e 。
设 d 为由 e 的十进制表示的数字组成的字符串值(按顺序,没有前导零)。
设置 m 为 m 、"e" 、c 和 d 的
字符串连接 。
返回 s 和 m 的 字符串连接 。
注
对于提供比上述规则要求更准确转换的实现,建议将以下步骤 10.b.i
的替代版本用作指导:
设 e 、n 和 f 为 整数 ,使得 f ≥ 0,
10f ≤ n < 10f + 1 ,
𝔽 (n × 10e -
f ) 是 𝔽 (x ),且 f 尽可能小。如果
n 有多种可能性,选择使 𝔽 (n ×
10e - f ) 在值上最接近 𝔽 (x ) 的
n 值。如果有两个这样的可能 n 值,选择偶数的那个。
21.1.3.3 Number.prototype.toFixed ( fractionDigits )
注 1
此方法返回一个字符串,包含以十进制定点记法表示的此 Number 值,小数点后有 fractionDigits 位数字。如果
fractionDigits 是 undefined ,假定为 0。
当被调用时执行以下步骤:
设 x 为 ? ThisNumberValue (this
value)。
设 f 为 ? ToIntegerOrInfinity (fractionDigits )。
断言 :如果
fractionDigits 是 undefined ,那么 f 是 0。
如果 f 不是 有限的 ,抛出 RangeError 异常。
如果 f < 0 或 f > 100,抛出 RangeError 异常。
如果 x 不是 有限的 ,返回 Number::toString (x ,
10)。
设置 x 为 ℝ (x )。
设 s 为空字符串。
如果 x < 0,那么
设置 s 为 "-" 。
设置 x 为 -x 。
如果 x ≥ 1021 ,那么
设 m 为 ! ToString (𝔽 (x ))。
否则,
设 n 为一个 整数 ,使得 n /
10f - x 尽可能接近零。如果有两个这样的 n ,选择较大的
n 。
如果 n = 0,设 m 为 "0" 。否则,设
m 为由 n 的十进制表示的数字组成的字符串值(按顺序,没有前导零)。
如果 f ≠ 0,那么
设 k 为 m 的长度。
如果 k ≤ f ,那么
设 z 为由 f + 1 - k 个代码单元
0x0030(数字零)组成的字符串值。
设置 m 为 z 和 m 的 字符串连接 。
设置 k 为 f + 1。
设 a 为 m 的前 k - f 个代码单元。
设 b 为 m 的其他 f 个代码单元。
设置 m 为 a 、"." 和 b
的 字符串连接 。
返回 s 和 m 的 字符串连接 。
注 2
对于某些值,toFixed
的输出可能比 toString
更精确,因为 toString
只打印足够的有效数字来区分该数字与相邻的 Number 值。例如,
(1000000000000000128).toString()
返回
"1000000000000000100" ,而
(1000000000000000128).toFixed(0)
返回
"1000000000000000128" 。
21.1.3.4 Number.prototype.toLocaleString ( [
reserved1 [ , reserved2 ] ] )
包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按照 ECMA-402 规范中的规定实现此方法。如果 ECMAScript 实现不包含 ECMA-402
API,则使用此方法的以下规范:
此方法产生一个字符串值,该值表示根据 宿主环境 当前区域设置的约定格式化的此 Number 值。此方法是 实现定义的 ,允许(但不鼓励)它返回与
toString
相同的内容。
此方法的可选参数的含义在 ECMA-402 规范中定义;不包含 ECMA-402 支持的实现不得将这些参数位置用于任何其他用途。
21.1.3.5 Number.prototype.toPrecision ( precision )
此方法返回一个字符串,包含以十进制指数记法表示的此 Number 值,有效数字的小数点前有一位数字,小数点后有 precision - 1 位数字,或者以十进制定点记法表示,有
precision 个有效数字。如果 precision 是 undefined ,它改为调用
ToString 。
当被调用时执行以下步骤:
设 x 为 ? ThisNumberValue (this
value)。
如果 precision 是 undefined ,返回 ! ToString (x )。
设 p 为 ? ToIntegerOrInfinity (precision )。
如果 x 不是 有限的 ,返回 Number::toString (x ,
10)。
如果 p < 1 或 p > 100,抛出 RangeError 异常。
设置 x 为 ℝ (x )。
设 s 为空字符串。
如果 x < 0,那么
设置 s 为代码单元 0x002D(连字符减号)。
设置 x 为 -x 。
如果 x = 0,那么
设 m 为由 p 个代码单元 0x0030(数字零)组成的字符串值。
设 e 为 0。
否则,
设 e 和 n 为 整数 ,使得
10p - 1 ≤ n < 10p
且 n × 10e - p + 1 -
x 尽可能接近零。如果有两组这样的 e 和 n ,选择使 n ×
10e - p + 1 更大的 e 和
n 。
设 m 为由 n 的十进制表示的数字组成的字符串值(按顺序,没有前导零)。
如果 e < -6 或 e ≥ p ,那么
断言 :e ≠ 0。
如果 p ≠ 1,那么
设 a 为 m 的第一个代码单元。
设 b 为 m 的其他 p - 1 个代码单元。
设置 m 为 a 、"." 和
b 的 字符串连接 。
如果 e > 0,那么
设 c 为代码单元 0x002B(加号)。
否则,
断言 :e
< 0。
设 c 为代码单元 0x002D(连字符减号)。
设置 e 为 -e 。
设 d 为由 e 的十进制表示的数字组成的字符串值(按顺序,没有前导零)。
返回 s 、m 、代码单元 0x0065(拉丁小写字母 E)、c 和
d 的 字符串连接 。
如果 e = p - 1,返回 s 和 m 的 字符串连接 。
如果 e ≥ 0,那么
设置 m 为 m 的前 e + 1 个代码单元、代码单元 0x002E(句号)和
m 的其余 p - (e + 1) 个代码单元的 字符串连接 。
否则,
设置 m 为代码单元 0x0030(数字零)、代码单元 0x002E(句号)、-(e + 1) 个代码单元
0x0030(数字零)和字符串 m 的 字符串连接 。
返回 s 和 m 的 字符串连接 。
21.1.3.6 Number.prototype.toString ( [ radix ] )
注
可选的 radix 应该是在从 2 𝔽 到
36 𝔽 的 包含区间 内的 整数
Number 值。如果 radix 是
undefined ,那么使用 10 𝔽 作为
radix 的值。
此方法在被调用时执行以下步骤:
设 x 为 ? ThisNumberValue (this
value)。
如果 radix 是 undefined ,设 radixMV 为 10。
否则,设 radixMV 为 ? ToIntegerOrInfinity (radix )。
如果 radixMV 不在从 2 到 36 的 包含区间 内,抛出
RangeError 异常。
返回 Number::toString (x ,
radixMV )。
此方法不是通用的;如果其 this 值 不是 Number 或 Number
对象,它会抛出 TypeError 异常。因此,它不能转移到其他类型的对象上用作方法。
此方法的 "length" 属性是 1 𝔽 。
21.1.3.7 Number.prototype.valueOf ( )
返回 ? ThisNumberValue (this
value)。
21.1.3.7.1 ThisNumberValue ( value )
抽象操作 ThisNumberValue 接受参数 value (一个 ECMAScript 语言值 ),并返回一个
包含 Number 的
正常完成 或一个
抛出完成 。当被调用时执行以下步骤:
如果 value 是
Number ,返回 value 。
如果 value 是对象 且 value
有 [[NumberData]] 内部槽,那么
设 n 为 value .[[NumberData]] 。
断言 :n 是
Number 。
返回 n 。
抛出 TypeError 异常。
21.1.4 Number 实例的属性
Number 实例是从 Number 原型对象 继承属性的
普通对象 。Number 实例还有一个 [[NumberData]] 内部槽。[[NumberData]] 内部槽是此 Number
对象表示的 Number 值。
21.2 BigInt 对象
21.2.1 BigInt 构造器
BigInt 构造器 :
是 %BigInt% 。
是 全局对象 的 "BigInt" 属性的初始值。
当作为函数而不是作为 构造器 调用时,执行类型转换。
不打算与 new
操作符一起使用或被子类化。它可以用作类定义中 extends
子句的值,但对 BigInt 构造器 的
super
调用将导致异常。
21.2.1.1 BigInt ( value )
此函数在被调用时执行以下步骤:
如果 NewTarget 不是 undefined ,抛出 TypeError 异常。
设 prim 为 ? ToPrimitive (value ,
number )。
如果 prim 是
Number ,返回 ? NumberToBigInt (prim )。
否则,返回 ? ToBigInt (prim )。
21.2.1.1.1 NumberToBigInt ( number )
抽象操作 NumberToBigInt 接受参数 number (一个 Number),并返回一个 包含 BigInt 的
正常完成 或一个
抛出完成 。当被调用时执行以下步骤:
如果 number 不是 整数 Number ,
抛出 RangeError 异常。
返回 ℤ (ℝ (number ))。
21.2.2 BigInt 构造器的属性
BigInt 构造器 :
21.2.2.1 BigInt.asIntN ( bits , bigint )
此函数在被调用时执行以下步骤:
设置 bits 为 ? ToIndex (bits )。
设置 bigint 为 ? ToBigInt (bigint )。
设 mod 为 ℝ (bigint ) modulo
2bits 。
如果 mod ≥ 2bits - 1 ,返回 ℤ (mod -
2bits );否则,返回 ℤ (mod )。
21.2.2.2 BigInt.asUintN ( bits , bigint )
此函数在被调用时执行以下步骤:
设置 bits 为 ? ToIndex (bits )。
设置 bigint 为 ? ToBigInt (bigint )。
返回 ℤ (ℝ (bigint )
modulo
2bits )。
21.2.2.3 BigInt.prototype
BigInt.prototype
的初始值是 BigInt 原型对象 。
此属性有特性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
21.2.3 BigInt 原型对象的属性
BigInt 原型对象 :
方法规范中的短语"此 BigInt 值"是指通过将方法调用的 this 值作为参数调用抽象操作 ThisBigIntValue 返回的结果。
21.2.3.1 BigInt.prototype.constructor
BigInt.prototype.constructor
的初始值是 %BigInt% 。
21.2.3.2 BigInt.prototype.toLocaleString ( [
reserved1 [ , reserved2 ] ] )
包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按照 ECMA-402 规范中的规定实现此方法。如果 ECMAScript 实现不包含 ECMA-402
API,则使用此方法的以下规范:
此方法产生一个字符串值,该值表示根据 宿主环境 当前区域设置的约定格式化的此 BigInt 值。此方法是 实现定义的 ,允许(但不鼓励)它返回与
toString
相同的内容。
此方法的可选参数的含义在 ECMA-402 规范中定义;不包含 ECMA-402 支持的实现不得将这些参数位置用于任何其他用途。
21.2.3.3 BigInt.prototype.toString ( [ radix ] )
注
可选的 radix 应该是在从 2 𝔽 到
36 𝔽 的 包含区间 内的 整数
Number 值。如果 radix 是
undefined ,那么使用 10 𝔽 作为
radix 的值。
此方法在被调用时执行以下步骤:
设 x 为 ? ThisBigIntValue (this
value)。
如果 radix 是 undefined ,设 radixMV 为 10。
否则,设 radixMV 为 ? ToIntegerOrInfinity (radix )。
如果 radixMV 不在从 2 到 36 的 包含区间 内,抛出
RangeError 异常。
返回 BigInt::toString (x ,
radixMV )。
此方法不是通用的;如果其 this 值 不是 BigInt 或 BigInt
对象,它会抛出 TypeError 异常。因此,它不能转移到其他类型的对象上用作方法。
21.2.3.4 BigInt.prototype.valueOf ( )
返回 ? ThisBigIntValue (this
value)。
21.2.3.4.1 ThisBigIntValue ( value )
抽象操作 ThisBigIntValue 接受参数 value (一个 ECMAScript 语言值 ),并返回一个
包含 BigInt 的
正常完成 或一个
抛出完成 。当被调用时执行以下步骤:
如果 value 是
BigInt ,返回 value 。
如果 value 是对象 且 value
有 [[BigIntData]] 内部槽,那么
断言 :value .[[BigIntData]] 是
BigInt 。
返回 value .[[BigIntData]] 。
抛出 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]] 内部方法;它不能作为函数被调用。
注
在此规范中,短语"x 的 Number 值 "具有在 6.1.6.1 中定义的技术含义。
21.3.1 Math 对象的值属性
21.3.1.1 Math.E
e (自然对数的底)的 Number 值 ,约为 2.7182818284590452354。
此属性有特性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
21.3.1.2 Math.LN10
10 的自然对数的 Number 值 ,约为 2.302585092994046。
此属性有特性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
21.3.1.3 Math.LN2
2 的自然对数的 Number
值 ,约为 0.6931471805599453。
此属性有特性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
21.3.1.4 Math.LOG10E
e (自然对数的底)的以 10 为底的对数的 Number 值 ;此值约为 0.4342944819032518。
此属性有特性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
注
Math.LOG10E
的值约为 Math.LN10
值的倒数。
21.3.1.5 Math.LOG2E
e (自然对数的底)的以 2 为底的对数的 Number 值 ;此值约为 1.4426950408889634。
此属性有特性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
注
Math.LOG2E
的值约为 Math.LN2
值的倒数。
21.3.1.6 Math.PI
π(圆的周长与其直径的比值)的 Number 值 ,约为 3.1415926535897932。
此属性有特性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
21.3.1.7 Math.SQRT1_2
½ 的平方根的 Number
值 ,约为 0.7071067811865476。
此属性有特性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
注
Math.SQRT1_2
的值约为 Math.SQRT2
值的倒数。
21.3.1.8 Math.SQRT2
2 的平方根的 Number
值 ,约为 1.4142135623730951。
此属性有特性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
21.3.1.9 Math [ %Symbol.toStringTag% ]
%Symbol.toStringTag% 属性的初始值是字符串值
"Math" 。
此属性有特性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : true }。
21.3.2 Math 对象的函数属性
注
函数
acos
、acosh
、asin
、asinh
、atan
、atanh
、atan2
、cbrt
、cos
、cosh
、exp
、expm1
、hypot
、log
、log1p
、log2
、log10
、pow
、random
、sin
、sinh
、tan
和 tanh
的行为在此处未被精确指定,除了要求对表示感兴趣的边界情况的某些参数值有特定结果。对于其他参数值,这些函数意图计算熟悉的数学函数结果的近似值,但在近似算法的选择上允许一定的灵活性。总的意图是实现者应该能够在给定硬件平台上为
ECMAScript 使用与该平台上 C 程序员可用的相同数学库。
虽然算法的选择留给实现,但建议(但不是本标准规定的)实现使用 IEEE 754-2019 算术的近似算法,这些算法包含在
fdlibm
中,这是来自 Sun Microsystems 的可自由分发的数学库(http://www.netlib.org/fdlibm )。
21.3.2.1 Math.abs ( x )
此函数返回 x 的绝对值;结果与 x 具有相同的量级但符号为正。
当被调用时执行以下步骤:
设 n 为 ? ToNumber (x )。
如果 n 是 NaN ,返回 NaN 。
如果 n 是 -0 𝔽 ,返回
+0 𝔽 。
如果 n 是 -∞ 𝔽 ,返回
+∞ 𝔽 。
如果 n < -0 𝔽 ,返回 -n 。
返回 n 。
21.3.2.2 Math.acos ( x )
此函数返回 x 的反余弦值。结果以弧度表示,在从
+0 𝔽 到 𝔽 (π) 的闭区间 内。
它在被调用时执行以下步骤:
设 n 为 ? ToNumber (x )。
如果 n 是 NaN ,n >
1 𝔽 ,或 n <
-1 𝔽 ,返回 NaN 。
如果 n 是 1 𝔽 ,返回
+0 𝔽 。
返回一个实现近似 的 Number 值,表示
ℝ (n ) 的反余弦值。
21.3.2.3 Math.acosh ( x )
此函数返回 x 的反双曲余弦值。
它在被调用时执行以下步骤:
设 n 为 ? ToNumber (x )。
如果 n 是 NaN 或
+∞ 𝔽 ,返回 n 。
如果 n 是 1 𝔽 ,返回
+0 𝔽 。
如果 n < 1 𝔽 ,返回
NaN 。
返回一个实现近似 的 Number 值,表示
ℝ (n )
的反双曲余弦值。
21.3.2.4 Math.asin ( x )
此函数返回 x 的反正弦值。结果以弧度表示,在从 𝔽 (-π / 2) 到 𝔽 (π / 2) 的闭区间 内。
它在被调用时执行以下步骤:
设 n 为 ? ToNumber (x )。
如果 n 是 NaN ,
+0 𝔽 ,或 -0 𝔽 之一,返回
n 。
如果 n > 1 𝔽 或 n <
-1 𝔽 ,返回 NaN 。
返回一个实现近似 的 Number 值,表示
ℝ (n ) 的反正弦值。
21.3.2.5 Math.asinh ( x )
此函数返回 x 的反双曲正弦值。
它在被调用时执行以下步骤:
设 n 为 ? ToNumber (x )。
如果 n 不是有限的 或 n 是
+0 𝔽 或 -0 𝔽 ,返回
n 。
返回一个实现近似 的 Number 值,表示
ℝ (n )
的反双曲正弦值。
21.3.2.6 Math.atan ( x )
此函数返回 x 的反正切值。结果以弧度表示,在从 𝔽 (-π / 2) 到 𝔽 (π / 2) 的闭区间 内。
它在被调用时执行以下步骤:
设 n 为 ? ToNumber (x )。
如果 n 是 NaN ,
+0 𝔽 ,或 -0 𝔽 之一,返回
n 。
如果 n 是 +∞ 𝔽 ,返回一个实现近似 的 Number 值,表示 π / 2。
如果 n 是 -∞ 𝔽 ,返回一个实现近似 的 Number 值,表示 -π / 2。
返回一个实现近似 的 Number 值,表示
ℝ (n ) 的反正切值。
21.3.2.7 Math.atanh ( x )
此函数返回 x 的反双曲正切值。
它在被调用时执行以下步骤:
设 n 为 ? ToNumber (x )。
如果 n 是 NaN ,
+0 𝔽 ,或 -0 𝔽 之一,返回
n 。
如果 n > 1 𝔽 或 n <
-1 𝔽 ,返回 NaN 。
如果 n 是 1 𝔽 ,返回
+∞ 𝔽 。
如果 n 是 -1 𝔽 ,返回
-∞ 𝔽 。
返回一个实现近似 的 Number 值,表示
ℝ (n )
的反双曲正切值。
21.3.2.8 Math.atan2 ( y , x )
此函数返回参数 y 和 x 的商 y /
x 的反正切值,其中 y 和 x 的符号用于确定
结果的象限。请注意,对于双参数反正切函数,参数名为 y 的位于第一位而参数名为 x 的位于第二位是有意的和传统的。结果以弧度表示,在从 -π
到 +π 的闭区间 内。
它在被调用时执行以下步骤:
设 ny 为 ? ToNumber (y )。
设 nx 为 ? ToNumber (x )。
如果 ny 是 NaN 或 nx 是
NaN ,返回 NaN 。
如果 ny 是 +∞ 𝔽 ,则
如果 nx 是 +∞ 𝔽 ,返回一个实现近似 的 Number 值,表示
π / 4。
如果 nx 是 -∞ 𝔽 ,返回一个实现近似 的 Number 值,表示
3π / 4。
返回一个实现近似 的 Number 值,表示
π / 2。
如果 ny 是 -∞ 𝔽 ,则
如果 nx 是 +∞ 𝔽 ,返回一个实现近似 的 Number 值,表示
-π / 4。
如果 nx 是 -∞ 𝔽 ,返回一个实现近似 的 Number 值,表示
-3π / 4。
返回一个实现近似 的 Number 值,表示
-π / 2。
如果 ny 是 +0 𝔽 ,则
如果 nx > +0 𝔽 或 nx 是
+0 𝔽 ,返回
+0 𝔽 。
返回一个实现近似 的 Number 值,表示
π。
如果 ny 是 -0 𝔽 ,则
如果 nx > +0 𝔽 或 nx 是
+0 𝔽 ,返回
-0 𝔽 。
返回一个实现近似 的 Number 值,表示
-π。
断言 :
ny 是有限的 且既不是
+0 𝔽 也不是 -0 𝔽 。
如果 ny > +0 𝔽 ,则
如果 nx 是 +∞ 𝔽 ,返回
+0 𝔽 。
如果 nx 是 -∞ 𝔽 ,返回一个实现近似 的 Number 值,表示
π。
如果 nx 是 +0 𝔽 或
-0 𝔽 ,返回一个实现近似 的 Number 值,表示
π / 2。
如果 ny < -0 𝔽 ,则
如果 nx 是 +∞ 𝔽 ,返回
-0 𝔽 。
如果 nx 是 -∞ 𝔽 ,返回一个实现近似 的 Number 值,表示
-π。
如果 nx 是 +0 𝔽 或
-0 𝔽 ,返回一个实现近似 的 Number 值,表示
-π / 2。
断言 :
nx 是有限的 且既不是
+0 𝔽 也不是 -0 𝔽 。
设 r 为 abs (ℝ (ny ) / ℝ (nx )) 的反正切值。
如果 nx < -0 𝔽 ,则
如果 ny > +0 𝔽 ,设 r
为 π - r 。
否则,设 r 为 -π + r 。
否则,
如果 ny < -0 𝔽 ,设 r
为 -r 。
返回一个实现近似 的 Number 值,表示
r 。
21.3.2.9 Math.cbrt ( x )
此函数返回 x 的立方根。
它在被调用时执行以下步骤:
设 n 为 ? ToNumber (x )。
如果 n 不是有限的 或 n 是
+0 𝔽 或 -0 𝔽 ,返回
n 。
返回一个实现近似 的 Number 值,表示
ℝ (n ) 的立方根。
21.3.2.10 Math.ceil ( x )
此函数返回不小于 x 的最小(最接近 -∞)整数 Number 值。如果 x 已经是一个整数
Number ,结果就是
x 。
它在被调用时执行以下步骤:
设 n 为 ? ToNumber (x )。
如果 n 不是有限的 或 n 是
+0 𝔽 或 -0 𝔽 ,返回
n 。
如果 n < -0 𝔽 且 n >
-1 𝔽 ,返回 -0 𝔽 。
如果 n 是一个整数 Number ,返回 n 。
返回不小于 n 的最小(最接近 -∞)整数 Number 值。
注意
Math.ceil(x)
的值与
-Math.floor(-x)
的值相同。
21.3.2.11 Math.clz32 ( x )
此函数在被调用时执行以下步骤:
设 n 为 ? ToUint32 (x )。
设 p 为 n 的无符号 32 位二进制表示中前导零位的数量。
返回 𝔽 (p )。
注意
如果 n 是 +0 𝔽 或
-0 𝔽 ,此方法返回
32 𝔽 。如果 n 的 32 位二进制编码的最高有效位是 1,此方法返回
+0 𝔽 。
21.3.2.12 Math.cos ( x )
此函数返回 x 的余弦值。参数以弧度表示。
它在被调用时执行以下步骤:
设 n 为 ? ToNumber (x )。
如果 n 不是有限的 ,返回 NaN 。
如果 n 是 +0 𝔽 或
-0 𝔽 ,返回 1 𝔽 。
返回一个实现近似 的 Number 值,表示
ℝ (n ) 的余弦值。
21.3.2.13 Math.cosh ( x )
此函数返回 x 的双曲余弦值。
它在被调用时执行以下步骤:
设 n 为 ? ToNumber (x )。
如果 n 是 NaN ,返回 NaN 。
如果 n 是 +∞ 𝔽 或
-∞ 𝔽 ,返回 +∞ 𝔽 。
如果 n 是 +0 𝔽 或
-0 𝔽 ,返回 1 𝔽 。
返回一个实现近似 的 Number 值,表示
ℝ (n )
的双曲余弦值。
注意
Math.cosh(x)
的值与
(Math.exp(x) + Math.exp(-x)) / 2
的值相同。
21.3.2.14 Math.exp ( x )
此函数返回 x 的指数函数(e 的 x 次幂,其中 e 是自然对数的底)。
它在被调用时执行以下步骤:
设 n 为 ? ToNumber (x )。
如果 n 是 NaN 或
+∞ 𝔽 ,返回 n 。
如果 n 是 +0 𝔽 或
-0 𝔽 ,返回 1 𝔽 。
如果 n 是 -∞ 𝔽 ,返回
+0 𝔽 。
返回一个实现近似 的 Number 值,表示
ℝ (n )
的指数函数。
21.3.2.15 Math.expm1 ( x )
此函数返回从 x 的指数函数(e 的 x 次幂,其中 e 是自然对数的底)中减去 1
的结果。该结果以一种即使当 x 的值接近 0 时也很准确的方式计算。
它在被调用时执行以下步骤:
设 n 为 ? ToNumber (x )。
如果 n 是 NaN ,
+0 𝔽 ,-0 𝔽 ,或
+∞ 𝔽 之一,返回 n 。
如果 n 是 -∞ 𝔽 ,返回
-1 𝔽 。
设 exp 为 ℝ (n ) 的指数函数。
返回一个实现近似 的 Number 值,表示
exp - 1。
21.3.2.16 Math.floor ( x )
此函数返回不大于 x 的最大(最接近 +∞)整数 Number 值。如果 x 已经是一个整数
Number ,结果就是 x 。
它在被调用时执行以下步骤:
设 n 为 ? ToNumber (x )。
如果 n 不是有限的 或 n 是
+0 𝔽 或 -0 𝔽 ,返回
n 。
如果 n < 1 𝔽 且 n >
+0 𝔽 ,返回 +0 𝔽 。
如果 n 是一个整数 Number ,返回 n 。
返回不大于 n 的最大(最接近 +∞)整数 Number 值。
注意
Math.floor(x)
的值与
-Math.ceil(-x)
的值相同。
21.3.2.17 Math.fround ( x )
此函数在被调用时执行以下步骤:
设 n 为 ? ToNumber (x )。
如果 n 是 NaN ,返回 NaN 。
如果 n 是 +0 𝔽 ,
-0 𝔽 ,+∞ 𝔽 ,或
-∞ 𝔽 之一,返回 n 。
设 n32 为使用 roundTiesToEven 模式将 n 转换为 IEEE
754-2019 binary32 格式的结果。
设 n64 为将 n32 转换为 IEEE
754-2019 binary64 格式的结果。
返回对应于 n64 的 ECMAScript Number 值。
21.3.2.18 Math.f16round ( x )
此函数在被调用时执行以下步骤:
设 n 为 ? ToNumber (x )。
如果 n 是 NaN ,返回 NaN 。
如果 n 是 +0 𝔽 ,
-0 𝔽 ,+∞ 𝔽 ,或
-∞ 𝔽 之一,返回 n 。
设 n16 为使用 roundTiesToEven 模式将 n 转换为 IEEE
754-2019 binary16 格式的结果。
设 n64 为将 n16 转换为 IEEE
754-2019 binary64 格式的结果。
返回对应于 n64 的 ECMAScript Number 值。
注意
此操作与先转换为 binary32 再转换为 binary16 是不同的,因为可能存在双重舍入:例如,考虑数字 k =
1.00048828125000022204 𝔽 ,对于它,Math.f16round(k )
是 1.0009765625 𝔽 ,但
Math.f16round(Math.fround(k )) 是 1 𝔽 。
并非所有平台都提供从 binary64 转换为 binary16 的原生支持。有各种库可以提供此功能,包括 MIT 许可的 half 库。或者,可以首先在 roundTiesToEven 下从
binary64 转换为 binary32,然后检查结果是否可能导致不正确的双重舍入。可能导致问题的情况可以通过调整 binary32 值的尾数来明确处理,使其成为在
roundTiesToOdd 下执行初始转换时会产生的值。然后在 roundTiesToEven 下将调整后的值转换为 binary16 就会产生正确的值。
21.3.2.19 Math.hypot ( ...args )
给定零个或多个参数,此函数返回其参数的平方和的平方根。
它在被调用时执行以下步骤:
设 coerced 为一个新的空列表 。
对于 args 的每个元素 arg ,执行
设 n 为 ? ToNumber (arg )。
将 n 追加到 coerced 。
对于 coerced 的每个元素 number ,执行
如果 number 是 +∞ 𝔽 或
-∞ 𝔽 ,返回
+∞ 𝔽 。
设 onlyZero 为 true 。
对于 coerced 的每个元素 number ,执行
如果 number 是 NaN ,返回
NaN 。
如果 number 既不是 +0 𝔽 也不是
-0 𝔽 ,设 onlyZero 为
false 。
如果 onlyZero 是 true ,返回
+0 𝔽 。
返回一个实现近似 的 Number 值,表示
coerced 元素的数学值 的平方和的平方根。
此函数的 "length" 属性是
2 𝔽 。
注意
实现应当注意避免当此函数以两个或更多参数调用时,在朴素实现中容易发生的溢出和下溢导致的精度损失。
21.3.2.20 Math.imul ( x , y )
此函数在被调用时执行以下步骤:
设 a 为 ℝ (?
ToUint32 (x ))。
设 b 为 ℝ (?
ToUint32 (y ))。
设 product 为 (a × b ) 模 232 。
如果 product ≥ 231 ,返回 𝔽 (product -
232 );否则返回 𝔽 (product )。
21.3.2.21 Math.log ( x )
此函数返回 x 的自然对数。
它在被调用时执行以下步骤:
设 n 为 ? ToNumber (x )。
如果 n 是 NaN 或
+∞ 𝔽 ,返回 n 。
如果 n 是 1 𝔽 ,返回
+0 𝔽 。
如果 n 是 +0 𝔽 或
-0 𝔽 ,返回 -∞ 𝔽 。
如果 n < -0 𝔽 ,返回
NaN 。
返回一个实现近似 的 Number 值,表示
ℝ (n )
的自然对数。
21.3.2.22 Math.log1p ( x )
此函数返回 1 + x 的自然对数。该结果以一种即使当 x 的值接近零时也很准确的方式计算。
它在被调用时执行以下步骤:
设 n 为 ? ToNumber (x )。
如果 n 是 NaN ,
+0 𝔽 ,-0 𝔽 ,或
+∞ 𝔽 之一,返回 n 。
如果 n 是 -1 𝔽 ,返回
-∞ 𝔽 。
如果 n < -1 𝔽 ,返回
NaN 。
返回一个实现近似 的 Number 值,表示 1 +
ℝ (n )
的自然对数。
21.3.2.23 Math.log10 ( x )
此函数返回 x 的以 10 为底的对数。
它在被调用时执行以下步骤:
设 n 为 ? ToNumber (x )。
如果 n 是 NaN 或
+∞ 𝔽 ,返回 n 。
如果 n 是 1 𝔽 ,返回
+0 𝔽 。
如果 n 是 +0 𝔽 或
-0 𝔽 ,返回 -∞ 𝔽 。
如果 n < -0 𝔽 ,返回
NaN 。
返回一个实现近似 的 Number 值,表示
ℝ (n ) 的以 10
为底的对数。
21.3.2.24 Math.log2 ( x )
此函数返回 x 的以 2 为底的对数。
它在被调用时执行以下步骤:
设 n 为 ? ToNumber (x )。
如果 n 是 NaN 或
+∞ 𝔽 ,返回 n 。
如果 n 是 1 𝔽 ,返回
+0 𝔽 。
如果 n 是 +0 𝔽 或
-0 𝔽 ,返回 -∞ 𝔽 。
如果 n < -0 𝔽 ,返回
NaN 。
返回一个实现近似 的 Number 值,表示
ℝ (n ) 的以 2
为底的对数。
21.3.2.25 Math.max ( ...args )
给定零个或多个参数,此函数对每个参数调用 ToNumber 并返回结果值中的最大值。
它在被调用时执行以下步骤:
设 coerced 为一个新的空列表 。
对于 args 的每个元素 arg ,执行
设 n 为 ? ToNumber (arg )。
将 n 追加到 coerced 。
设 highest 为 -∞ 𝔽 。
对于 coerced 的每个元素 number ,执行
如果 number 是 NaN ,返回
NaN 。
如果 number 是 +0 𝔽 且
highest 是 -0 𝔽 ,设
highest 为 +0 𝔽 。
如果 number > highest ,设 highest 为
number 。
返回 highest 。
注意
确定最大值的值比较使用 IsLessThan 算法完成,但是
+0 𝔽 被认为大于
-0 𝔽 。
此函数的 "length" 属性是
2 𝔽 。
21.3.2.26 Math.min ( ...args )
给定零个或多个参数,此函数对每个参数调用 ToNumber 并返回结果值中的最小值。
它在被调用时执行以下步骤:
设 coerced 为一个新的空列表 。
对于 args 的每个元素 arg ,执行
设 n 为 ? ToNumber (arg )。
将 n 追加到 coerced 。
设 lowest 为 +∞ 𝔽 。
对于 coerced 的每个元素 number ,执行
如果 number 是 NaN ,返回
NaN 。
如果 number 是 -0 𝔽 且
lowest 是 +0 𝔽 ,设
lowest 为 -0 𝔽 。
如果 number < lowest ,设 lowest 为
number 。
返回 lowest 。
注意
确定最小值的值比较使用 IsLessThan 算法完成,但是
+0 𝔽 被认为大于
-0 𝔽 。
此函数的 "length" 属性是
2 𝔽 。
21.3.2.27 Math.pow ( base , exponent )
此函数在被调用时执行以下步骤:
设 base 为 ? ToNumber (base )。
设 exponent 为 ? ToNumber (exponent )。
返回 Number::exponentiate (base ,
exponent )。
21.3.2.28 Math.random ( )
此函数返回一个具有正号的 Number 值,大于或等于
+0 𝔽 但严格小于 1 𝔽 ,
使用实现定义 的算法或策略随机或伪随机选择,在该范围内具有近似均匀分布。
为不同领域 创建的每个
Math.random
函数必须从连续调用中产生不同的值序列。
21.3.2.29 Math.round ( x )
此函数返回最接近 x 且为整数的 Number 值。如果两个整数
Number 与 x 的距离相等,则结果是更接近 +∞ 的 Number 值。如果 x
已经是整数,结果就是
x 。
它在被调用时执行以下步骤:
设 n 为 ? ToNumber (x )。
如果 n 不是有限的 或 n 是一个整数
Number ,返回 n 。
如果 n < 0.5 𝔽 且 n >
+0 𝔽 ,返回 +0 𝔽 。
如果 n < -0 𝔽 且 n ≥
-0.5 𝔽 ,返回 -0 𝔽 。
返回最接近 n 的整数 Number ,在平局的情况下优选更接近 +∞ 的 Number。
注意 1
Math.round(3.5)
返回 4,但 Math.round(-3.5)
返回 -3。
注意 2
Math.round(x)
的值并不总是与
Math.floor(x + 0.5)
的值相同。当 x
是
-0 𝔽 或 x
小于
-0 𝔽 但大于或等于
-0.5 𝔽 时,Math.round(x)
返回
-0 𝔽 ,但 Math.floor(x + 0.5)
返回
+0 𝔽 。Math.round(x)
也可能因为计算
x + 0.5
时的内部舍入而与
Math.floor(x + 0.5)
的值不同。
21.3.2.30 Math.sign ( x )
此函数返回 x 的符号,指示 x 是正数、负数还是零。
它在被调用时执行以下步骤:
设 n 为 ? ToNumber (x )。
如果 n 是 NaN ,
+0 𝔽 ,或 -0 𝔽 之一,返回
n 。
如果 n < -0 𝔽 ,返回
-1 𝔽 。
返回 1 𝔽 。
21.3.2.31 Math.sin ( x )
此函数返回 x 的正弦值。参数以弧度表示。
它在被调用时执行以下步骤:
设 n 为 ? ToNumber (x )。
如果 n 是 NaN ,
+0 𝔽 ,或 -0 𝔽 之一,返回
n 。
如果 n 是 +∞ 𝔽 或
-∞ 𝔽 ,返回 NaN 。
返回一个实现近似 的 Number 值,表示
ℝ (n ) 的正弦值。
21.3.2.32 Math.sinh ( x )
此函数返回 x 的双曲正弦值。
它在被调用时执行以下步骤:
设 n 为 ? ToNumber (x )。
如果 n 不是有限的 或 n 是
+0 𝔽 或 -0 𝔽 ,返回
n 。
返回一个实现近似 的 Number 值,表示
ℝ (n )
的双曲正弦值。
注意
Math.sinh(x)
的值与
(Math.exp(x) - Math.exp(-x)) / 2
的值相同。
21.3.2.33 Math.sqrt ( x )
此函数返回 x 的平方根。
它在被调用时执行以下步骤:
设 n 为 ? ToNumber (x )。
如果 n 是 NaN ,
+0 𝔽 ,-0 𝔽 ,或
+∞ 𝔽 之一,返回 n 。
如果 n < -0 𝔽 ,返回
NaN 。
返回 𝔽 (ℝ (n ) 的平方根)。
21.3.2.34 Math.tan ( x )
此函数返回 x 的正切值。参数以弧度表示。
它在被调用时执行以下步骤:
设 n 为 ? ToNumber (x )。
如果 n 是 NaN ,
+0 𝔽 ,或 -0 𝔽 之一,返回
n 。
如果 n 是 +∞ 𝔽 或
-∞ 𝔽 ,返回 NaN 。
返回一个实现近似 的 Number 值,表示
ℝ (n ) 的正切值。
21.3.2.35 Math.tanh ( x )
此函数返回 x 的双曲正切值。
它在被调用时执行以下步骤:
设 n 为 ? ToNumber (x )。
如果 n 是 NaN ,
+0 𝔽 ,或 -0 𝔽 之一,返回
n 。
如果 n 是 +∞ 𝔽 ,返回
1 𝔽 。
如果 n 是 -∞ 𝔽 ,返回
-1 𝔽 。
返回一个实现近似 的 Number 值,表示
ℝ (n )
的双曲正切值。
注意
Math.tanh(x)
的值与
(Math.exp(x) - Math.exp(-x)) / (Math.exp(x) + Math.exp(-x))
的值相同。
21.3.2.36 Math.trunc ( x )
此函数返回数字 x 的整数部分,移除任何小数位。如果 x 已经是整数,结果就是 x 。
它在被调用时执行以下步骤:
设 n 为 ? ToNumber (x )。
如果 n 不是有限的 或 n 是
+0 𝔽 或 -0 𝔽 ,返回
n 。
如果 n < 1 𝔽 且 n >
+0 𝔽 ,返回 +0 𝔽 。
如果 n < -0 𝔽 且 n >
-1 𝔽 ,返回 -0 𝔽 。
返回最接近 n 且朝向 +0 𝔽 方向的整数
Number 。
21.4 Date 对象
21.4.1 Date 对象概述和抽象操作的定义
以下抽象操作 对时间值 (在 21.4.1.1
中定义)进行操作。注意,在任何情况下,如果这些函数的任何参数是 NaN ,结果将是
NaN 。
21.4.1.1 时间值和时间范围
ECMAScript 中的时间测量类似于 POSIX 中的时间测量,特别是共享以前推格里高利历为基础的定义,以 1970 年 1 月 1 日 UTC 午夜开始为纪元 ,并且将每一天计算为恰好 86,400 秒(每秒为 1000 毫秒)。
ECMAScript 时间值 是一个
Number ,要么是一个有限 的整数
Number ,表示精确到毫秒的时间瞬间,要么是 NaN ,表示没有特定的时间瞬间。是
24 × 60 × 60 × 1000 = 86,400,000 的倍数(即,对于某个整数 d 为
86,400,000 ×
d )的时间值表示在纪元 之后 d 个完整 UTC 天(负 d 表示在纪元 之前)的 UTC
天开始时的瞬间。任何其他有限 时间值
t 相对于最大的前导时间值 s (其为这样的倍数)定义,并表示在与 s 相同的 UTC 天内但在它之后
(t
- s ) 毫秒发生的瞬间。
时间值不考虑 UTC 闰秒——没有时间值表示正闰秒内的瞬间,并且有时间值表示被负闰秒从 UTC 时间线中移除的瞬间。然而,时间值的定义仍然产生与 UTC
的分段对齐,仅在闰秒边界处有不连续性,在闰秒之外没有差异。
Number 可以精确表示从 -9,007,199,254,740,992 到
9,007,199,254,740,992 的所有整数 (21.1.2.8 和 21.1.2.6 )。时间值支持稍小的范围,从
-8,640,000,000,000,000 到 8,640,000,000,000,000 毫秒。这产生了一个支持的时间值范围,恰好相对于 1970 年 1 月 1 日 UTC
午夜为 -100,000,000 天到 100,000,000 天。
1970 年 1 月 1 日 UTC 午夜开始的确切时刻由时间值 +0 𝔽 表示。
注意
在前推格里高利历中,闰年恰好是那些既能被 4 整除,又能被 400 整除或不能被 100 整除的年份。
前推格里高利历的 400 年周期包含 97 个闰年。这产生平均每年 365.2425 天,即 31,556,952,000 毫秒。因此,Number
能以毫秒精度精确表示的最大范围大约是相对于 1970 年的 -285,426 到 285,426 年。本节中指定的时间值支持的较小范围大约是相对于 1970 年的
-273,790 到 273,790 年。
21.4.1.2 时间相关常量
这些常量被以下部分的算法引用。
HoursPerDay = 24
MinutesPerHour = 60
SecondsPerMinute = 60
msPerSecond = 1000 𝔽
21.4.1.3 Day ( t )
抽象操作 Day 接受参数 t (一个有限 的时间值 )并返回一个整数
Number 。它返回 t 所在天的天数。它在被调用时执行以下步骤:
返回 𝔽 (floor (ℝ (t / msPerDay )))。
21.4.1.4 TimeWithinDay ( t )
抽象操作 TimeWithinDay 接受参数 t (一个有限 的时间值 )并返回一个在从
+0 𝔽 (包含)到 msPerDay (不包含)的区间 内的整数
Number 。它返回自 t 所在天开始以来的毫秒数。它在被调用时执行以下步骤:
返回 𝔽 (ℝ (t ) 模
ℝ (msPerDay ))。
21.4.1.5 DaysInYear ( y )
抽象操作 DaysInYear 接受参数 y (一个整数
Number )并返回 365 𝔽 或
366 𝔽 。它返回年份 y 中的天数。闰年有 366 天;所有其他年份有 365
天。它在被调用时执行以下步骤:
设 ry 为 ℝ (y )。
如果 (ry 模 400) = 0,返回
366 𝔽 。
如果 (ry 模 100) = 0,返回
365 𝔽 。
如果 (ry 模 4) = 0,返回
366 𝔽 。
返回 365 𝔽 。
21.4.1.6 DayFromYear ( y )
抽象操作 DayFromYear 接受参数 y (一个整数
Number )并返回一个整数 Number 。它返回年份 y
第一天的天数。它在被调用时执行以下步骤:
设 ry 为 ℝ (y )。
注意:在以下步骤中,
numYears1 、numYears4 、numYears100 和
numYears400 分别表示在纪元 和年份 y 开始之间发生的可被 1、4、100 和 400
整除的年数。如果 y 在纪元 之前,该数字为负数。
设 numYears1 为 (ry - 1970)。
设 numYears4 为 floor ((ry - 1969) / 4)。
设 numYears100 为 floor ((ry - 1901) / 100)。
设 numYears400 为 floor ((ry - 1601) / 400)。
返回 𝔽 (365 ×
numYears1 + numYears4 - numYears100 +
numYears400 )。
21.4.1.7 TimeFromYear ( y )
抽象操作 TimeFromYear 接受参数 y (一个整数
Number )并返回一个时间值 。它返回年份
y 开始的时间值 。它在被调用时执行以下步骤:
返回 msPerDay × DayFromYear (y )。
21.4.1.8 YearFromTime ( t )
抽象操作 YearFromTime 接受参数 t (一个有限 的时间值 )并返回一个整数
Number 。它返回 t 所在的年份。它在被调用时执行以下步骤:
返回最大的整数 Number y (最接近 +∞),使得
TimeFromYear (y ) ≤
t 。
21.4.1.9 DayWithinYear ( t )
抽象操作 DayWithinYear 接受参数 t (一个有限 的时间值 )并返回一个在从
+0 𝔽 到 365 𝔽 的闭区间 内的整数
Number 。它在被调用时执行以下步骤:
返回 Day (t ) - DayFromYear (YearFromTime (t ))。
21.4.1.10 InLeapYear ( t )
抽象操作 InLeapYear 接受参数 t (一个有限 的时间值 )并返回
+0 𝔽 或 1 𝔽 。如果 t
在闰年内,它返回
1 𝔽 ,否则返回 +0 𝔽 。它在被调用时执行以下步骤:
如果 DaysInYear (YearFromTime (t )) 是
366 𝔽 ,返回 1 𝔽 ;否则返回
+0 𝔽 。
21.4.1.11 MonthFromTime ( t )
抽象操作 MonthFromTime 接受参数 t (一个有限 的时间值 )并返回一个在从
+0 𝔽 到 11 𝔽 的闭区间 内的整数
Number 。它返回一个标识 t 所在月份的 Number。月份值
+0 𝔽 指定一月;1 𝔽
指定二月;2 𝔽 指定三月;
3 𝔽 指定四月;4 𝔽
指定五月;5 𝔽 指定六月;
6 𝔽 指定七月;7 𝔽
指定八月;8 𝔽 指定九月;
9 𝔽 指定十月;10 𝔽
指定十一月;11 𝔽 指定十二月。注意
MonthFromTime(+0 𝔽 ) =
+0 𝔽 ,对应于 1970 年 1 月 1 日星期四。它在被调用时执行以下步骤:
设 inLeapYear 为 InLeapYear (t )。
设 dayWithinYear 为 DayWithinYear (t )。
如果 dayWithinYear < 31 𝔽 ,返回
+0 𝔽 。
如果 dayWithinYear < 59 𝔽 +
inLeapYear ,返回 1 𝔽 。
如果 dayWithinYear < 90 𝔽 +
inLeapYear ,返回 2 𝔽 。
如果 dayWithinYear < 120 𝔽 +
inLeapYear ,返回 3 𝔽 。
如果 dayWithinYear < 151 𝔽 +
inLeapYear ,返回 4 𝔽 。
如果 dayWithinYear < 181 𝔽 +
inLeapYear ,返回 5 𝔽 。
如果 dayWithinYear < 212 𝔽 +
inLeapYear ,返回 6 𝔽 。
如果 dayWithinYear < 243 𝔽 +
inLeapYear ,返回 7 𝔽 。
如果 dayWithinYear < 273 𝔽 +
inLeapYear ,返回 8 𝔽 。
如果 dayWithinYear < 304 𝔽 +
inLeapYear ,返回 9 𝔽 。
如果 dayWithinYear < 334 𝔽 +
inLeapYear ,返回 10 𝔽 。
断言 :
dayWithinYear < 365 𝔽 +
inLeapYear 。
返回 11 𝔽 。
21.4.1.12 DateFromTime ( t )
抽象操作 DateFromTime 接受参数 t (一个有限 的时间值 )并返回一个在从
1 𝔽 到 31 𝔽 的闭区间 内的整数
Number 。它返回 t 所在月份的日期。它在被调用时执行以下步骤:
设 inLeapYear 为 InLeapYear (t )。
设 dayWithinYear 为 DayWithinYear (t )。
设 month 为 MonthFromTime (t )。
如果 month 是 +0 𝔽 ,返回
dayWithinYear + 1 𝔽 。
如果 month 是 1 𝔽 ,返回
dayWithinYear - 30 𝔽 。
如果 month 是 2 𝔽 ,返回
dayWithinYear - 58 𝔽 -
inLeapYear 。
如果 month 是 3 𝔽 ,返回
dayWithinYear - 89 𝔽 -
inLeapYear 。
如果 month 是 4 𝔽 ,返回
dayWithinYear - 119 𝔽 -
inLeapYear 。
如果 month 是 5 𝔽 ,返回
dayWithinYear - 150 𝔽 -
inLeapYear 。
如果 month 是 6 𝔽 ,返回
dayWithinYear - 180 𝔽 -
inLeapYear 。
如果 month 是 7 𝔽 ,返回
dayWithinYear - 211 𝔽 -
inLeapYear 。
如果 month 是 8 𝔽 ,返回
dayWithinYear - 242 𝔽 -
inLeapYear 。
如果 month 是 9 𝔽 ,返回
dayWithinYear - 272 𝔽 -
inLeapYear 。
如果 month 是 10 𝔽 ,返回
dayWithinYear - 303 𝔽 -
inLeapYear 。
断言 :
month 是 11 𝔽 。
返回 dayWithinYear - 333 𝔽 -
inLeapYear 。
21.4.1.13 WeekDay ( t )
抽象操作 WeekDay 接受参数 t (一个有限 的时间值 )并返回一个在从
+0 𝔽 到 6 𝔽 的闭区间 内的整数
Number 。它返回一个标识 t 所在星期几的 Number。星期值
+0 𝔽 指定星期日;1 𝔽
指定星期一;2 𝔽 指定星期二;
3 𝔽 指定星期三;4 𝔽
指定星期四;5 𝔽 指定星期五;
6 𝔽 指定星期六。注意 WeekDay(+0 𝔽 ) =
4 𝔽 ,对应于 1970 年 1 月 1 日星期四。它在被调用时执行以下步骤:
返回 𝔽 (ℝ (Day (t ) +
4 𝔽 ) 模 7)。
21.4.1.14 HourFromTime ( t )
抽象操作 HourFromTime 接受参数 t (一个有限 的时间值 )并返回一个在从
+0 𝔽 到 23 𝔽 的闭区间 内的整数
Number 。它返回 t 所在天的小时。它在被调用时执行以下步骤:
返回 𝔽 (floor (ℝ (t / msPerHour )) 模 HoursPerDay )。
21.4.1.15 MinFromTime ( t )
抽象操作 MinFromTime 接受参数 t (一个有限 的时间值 )并返回一个在从
+0 𝔽 到 59 𝔽 的闭区间 内的整数
Number 。它返回 t 所在小时的分钟。它在被调用时执行以下步骤:
返回 𝔽 (floor (ℝ (t / msPerMinute )) 模 MinutesPerHour )。
21.4.1.16 SecFromTime ( t )
抽象操作 SecFromTime 接受参数 t (一个有限 的时间值 )并返回一个在从
+0 𝔽 到 59 𝔽 的闭区间 内的整数
Number 。它返回 t 所在分钟的秒数。它在被调用时执行以下步骤:
返回 𝔽 (floor (ℝ (t / msPerSecond )) 模 SecondsPerMinute )。
21.4.1.17 msFromTime ( t )
抽象操作 msFromTime 接受参数 t (一个有限 的时间值 )并返回一个在从
+0 𝔽 到 999 𝔽 的闭区间 内的整数
Number 。它返回 t 所在秒的毫秒数。它在被调用时执行以下步骤:
返回 𝔽 (ℝ (t ) 模
ℝ (msPerSecond ))。
21.4.1.18 GetUTCEpochNanoseconds ( year ,
month , day , hour , minute , second ,
millisecond , microsecond , nanosecond )
抽象操作 GetUTCEpochNanoseconds 接受参数 year (一个整数 )、
month (一个在 1 到 12 的闭区间 内的整数 )、day (一个在 1 到 31
的闭区间 内的整数 )、hour (一个在 0 到 23
的闭区间 内的整数 )、minute (一个在 0 到 59
的闭区间 内的整数 )、second (一个在 0 到 59
的闭区间 内的整数 )、millisecond (一个在 0 到 999
的闭区间 内的整数 )、microsecond (一个在 0 到 999
的闭区间 内的整数 )和 nanosecond (一个在 0 到 999
的闭区间 内的整数 )并返回一个 BigInt。返回值表示自纪元 以来对应于给定 ISO 8601 日历日期和
UTC 挂钟时间的纳秒数。它在被调用时执行以下步骤:
设 date 为 MakeDay (𝔽 (year ), 𝔽 (month - 1),
𝔽 (day ))。
设 time 为 MakeTime (𝔽 (hour ), 𝔽 (minute ),
𝔽 (second ), 𝔽 (millisecond ))。
设 ms 为 MakeDate (date ,
time )。
断言 :
ms 是一个整数 Number 。
返回 ℤ (ℝ (ms ) ×
106 + microsecond × 103 + nanosecond )。
21.4.1.19 时区标识符
ECMAScript 中的时区由时区标识符 表示,它们是完全由在从
0x0000 到 0x007F 的闭区间 内的代码单元组成的字符串。ECMAScript 实现支持的时区可能是可用命名时区 ,由 AvailableNamedTimeZoneIdentifiers
返回的时区标识符记录 的 [[Identifier]] 字段表示,或者是偏移时区 ,由 IsTimeZoneOffsetString 返回
true 的字符串表示。
主要时区标识符 是可用命名时区的首选标识符。
非主要时区标识符 是不是主要时区标识符的可用命名时区标识符。
可用命名时区标识符 要么是主要时区标识符,要么是非主要时区标识符。
每个可用命名时区标识符恰好与一个可用命名时区关联。
每个可用命名时区恰好与一个主要时区标识符和零个或多个非主要时区标识符关联。
ECMAScript 实现必须支持标识符为 "UTC" 的可用命名时区,该标识符必须是 UTC 时区的主要时区标识符。
此外,实现可以支持任意数量的其他可用命名时区。
遵循 ECMA-402 国际化 API 规范中描述的时区要求的实现称为时区感知 的。
时区感知实现必须支持对应于 IANA 时区数据库的 Zone 和 Link 名称的可用命名时区,并且仅支持这些名称。
在时区感知实现中,主要时区标识符是 Zone 名称,非主要时区标识符是 Link 名称,分别在 IANA 时区数据库中,除非被 ECMA-402 规范中指定的 AvailableNamedTimeZoneIdentifiers
特别覆盖。
不支持整个 IANA 时区数据库的实现仍然建议使用 IANA 时区数据库名称作为标识符来表示时区。
21.4.1.20 GetNamedTimeZoneEpochNanoseconds (
timeZoneIdentifier , year , month , day ,
hour , minute , second , millisecond ,
microsecond , nanosecond )
实现定义 的抽象操作
GetNamedTimeZoneEpochNanoseconds 接受参数
timeZoneIdentifier (一个字符串)、year (一个整数 )、month (一个在 1 到 12
的闭区间 内的整数 )、day (一个在 1 到 31
的闭区间 内的整数 )、hour (一个在 0 到 23
的闭区间 内的整数 )、minute (一个在 0 到 59
的闭区间 内的整数 )、second (一个在 0 到 59
的闭区间 内的整数 )、millisecond (一个在 0 到 999
的闭区间 内的整数 )、microsecond (一个在 0 到 999
的闭区间 内的整数 )和 nanosecond (一个在 0 到 999
的闭区间 内的整数 )并返回一个 BigInt 的列表 。
返回的列表 中的每个值表示自纪元 以来对应于给定 ISO 8601 日历日期和在由
timeZoneIdentifier 标识的命名时区中的挂钟时间的纳秒数。
当输入表示由于负时区转换(例如夏令时结束或由于时区规则变更导致时区偏移减少)而多次出现的本地时间时,返回的列表 将有多个元素,并将按数值升序排序。
当输入表示由于正时区转换(例如夏令时开始或由于时区规则变更导致时区偏移增加)而跳过的本地时间时,返回的列表 将为空。
否则,返回的列表 将有一个元素。
GetNamedTimeZoneEpochNanoseconds 的默认实现,用于不包含任何时区本地政治规则的 ECMAScript 实现,在被调用时执行以下步骤:
断言 :
timeZoneIdentifier 是 "UTC" 。
设 epochNanoseconds 为 GetUTCEpochNanoseconds (year ,
month , day , hour , minute ,
second , millisecond , microsecond ,
nanosecond )。
返回 « epochNanoseconds »。
注意
时区感知 实现(建议所有其他实现也如此)需要使用
IANA 时区数据库 https://www.iana.org/time-zones/
的时区信息。
2017 年 11 月 5 日在 America/New_York 的凌晨 1:30 重复了两次,所以
GetNamedTimeZoneEpochNanoseconds("America/New_York" , 2017, 11, 5,
1, 30, 0, 0, 0, 0) 将返回一个长度为 2 的列表 ,其中第一个元素表示
05:30 UTC(对应于 UTC 偏移 -04:00 的 01:30 美国东部夏令时),第二个元素表示 06:30
UTC(对应于 UTC 偏移 -05:00 的 01:30 美国东部标准时间)。
2017 年 3 月 12 日在 America/New_York 的凌晨 2:30 不存在,所以
GetNamedTimeZoneEpochNanoseconds("America/New_York" , 2017, 3, 12,
2, 30, 0, 0, 0, 0) 将返回一个空的列表 。
21.4.1.21 GetNamedTimeZoneOffsetNanoseconds (
timeZoneIdentifier , epochNanoseconds )
实现定义 的抽象操作
GetNamedTimeZoneOffsetNanoseconds 接受参数 timeZoneIdentifier (一个字符串)和
epochNanoseconds (一个 BigInt)并返回一个整数 。
返回的整数 表示由
timeZoneIdentifier 标识的命名时区在对应于相对于纪元 的 epochNanoseconds 的瞬间的 UTC 偏移,均以纳秒为单位。
GetNamedTimeZoneOffsetNanoseconds 的默认实现,用于不包含任何时区本地政治规则的 ECMAScript 实现,在被调用时执行以下步骤:
断言 :
timeZoneIdentifier 是 "UTC" 。
返回 0。
注意
21.4.1.22 时区标识符记录
时区标识符记录 是一个记录 ,用于描述一个可用命名时区标识符 及其对应的主要时区标识符 。
时区标识符记录具有表 64 中列出的字段。
表 64:时区标识符记录 字段
字段名
值
含义
[[Identifier]]
一个字符串
实现支持的可用命名时区标识符 。
[[PrimaryIdentifier]]
一个字符串
[[Identifier]] 解析到的主要时区标识符 。
注意
如果 [[Identifier]] 是一个主要时区标识符 ,那么 [[Identifier]] 就是
[[PrimaryIdentifier]] 。
21.4.1.23 AvailableNamedTimeZoneIdentifiers ( )
实现定义 的抽象操作
AvailableNamedTimeZoneIdentifiers 不接受参数并返回一个时区标识符记录 的列表 。
其结果描述此实现中所有可用命名时区标识符 ,以及对应于每个可用命名时区标识符 的主要时区标识符 。
该列表 根据每个时区标识符记录 的 [[Identifier]] 字段排序。
时区感知 实现,包括所有实现 ECMA-402 国际化 API
的实现,必须按照 ECMA-402 规范中指定的方式实现 AvailableNamedTimeZoneIdentifiers 抽象操作。
对于不是时区感知 的实现,AvailableNamedTimeZoneIdentifiers
在被调用时执行以下步骤:
如果实现不包含任何时区的本地政治规则,那么
返回 « 时区标识符记录 {
[[Identifier]] : "UTC" , [[PrimaryIdentifier]] :
"UTC" } »。
设 identifiers 为按字典序代码单元顺序 排序的唯一可用命名时区标识符 的列表 。
设 result 为一个新的空列表 。
对于 identifiers 的每个元素 identifier ,执行
设 primary 为 identifier 。
如果 identifier 是此实现中的非主要时区标识符 并且
identifier 不是 "UTC" ,那么
设 primary 为与 identifier 关联的主要时区标识符 。
注意:实现可能需要迭代解析 identifier 以获得主要时区标识符 。
设 record 为时区标识符记录 {
[[Identifier]] :
identifier , [[PrimaryIdentifier]] :
primary }。
将 record 附加到 result 。
断言 :
result 包含一个时区标识符记录
r ,使得 r .[[Identifier]] 是
"UTC" 并且
r .[[PrimaryIdentifier]] 是
"UTC" 。
返回 result 。
21.4.1.24 SystemTimeZoneIdentifier ( )
实现定义 的抽象操作 SystemTimeZoneIdentifier
不接受参数并返回一个字符串。
它返回一个表示宿主环境 当前时区的字符串,该字符串要么是一个表示 UTC
偏移的字符串(IsTimeZoneOffsetString 对其返回
true ),要么是一个主要时区标识符 。
它在被调用时执行以下步骤:
如果实现仅支持 UTC 时区,返回 "UTC" 。
设 systemTimeZoneString 为表示宿主环境 当前时区的字符串,要么是一个主要时区标识符 ,要么是一个偏移时区 标识符。
返回 systemTimeZoneString 。
注意
为了确保实现在 Date 对象的方法中通常提供的功能级别,建议 SystemTimeZoneIdentifier 返回对应于宿主环境 时区设置的 IANA 时区名称(如果存在的话)。
GetNamedTimeZoneEpochNanoseconds
和 GetNamedTimeZoneOffsetNanoseconds
必须反映该时区中标准时间和夏令时的本地政治规则(如果存在这些规则)。
例如,如果宿主环境 是系统上的浏览器,用户选择了美国东部时间作为他们的时区,
SystemTimeZoneIdentifier 返回 "America/New_York" 。
21.4.1.25 LocalTime ( t )
抽象操作 LocalTime 接受参数 t (一个有限 的时间值 )并返回一个整数
Number 。
它将 t 从 UTC 转换为本地时间。
应该使用在 t 时刻生效的标准时间和夏令时的本地政治规则来按照本节规定的方式确定结果。
它在被调用时执行以下步骤:
设 systemTimeZoneIdentifier 为 SystemTimeZoneIdentifier ()。
如果 IsTimeZoneOffsetString (systemTimeZoneIdentifier )
是 true ,那么
设 offsetNs 为 ParseTimeZoneOffsetString (systemTimeZoneIdentifier )。
否则,
设 offsetNs 为 GetNamedTimeZoneOffsetNanoseconds (systemTimeZoneIdentifier ,
ℤ (ℝ (t ) ×
106 ))。
设 offsetMs 为 truncate (offsetNs /
106 )。
返回 t + 𝔽 (offsetMs )。
注意 1
注意 2
时区感知 实现(建议所有其他实现也如此)需要使用
IANA 时区数据库 https://www.iana.org/time-zones/
的时区信息。
注意 3
在负时区转换时,当有重复时间时(例如夏令时结束或时区调整减少),两个不同的输入时间值 t UTC 会转换为相同的本地时间 tlocal 。
LocalTime(UTC (t local ))
不一定总是等于 t local 。相应地,UTC (LocalTime(t UTC ))
不一定总是等于 t UTC 。
21.4.1.26 UTC ( t )
抽象操作 UTC 接受参数 t (一个 Number)并返回一个时间值 。
它将 t 从本地时间转换为 UTC 时间值 。
应该使用在 t 时刻生效的标准时间和夏令时的本地政治规则来按照本节规定的方式确定结果。
它在被调用时执行以下步骤:
如果 t 不是有限 的,返回 NaN 。
设 systemTimeZoneIdentifier 为 SystemTimeZoneIdentifier ()。
如果 IsTimeZoneOffsetString (systemTimeZoneIdentifier )
是 true ,那么
设 offsetNs 为 ParseTimeZoneOffsetString (systemTimeZoneIdentifier )。
否则,
设 possibleInstants 为 GetNamedTimeZoneEpochNanoseconds (systemTimeZoneIdentifier ,
ℝ (YearFromTime (t )),
ℝ (MonthFromTime (t ))
+ 1, ℝ (DateFromTime (t )),
ℝ (HourFromTime (t )),
ℝ (MinFromTime (t )),
ℝ (SecFromTime (t )),
ℝ (msFromTime (t )), 0,
0)。
注意:以下步骤确保当 t
表示在负时区转换时多次重复的本地时间(例如夏令时结束或由于时区规则变更导致时区偏移减少)或在正时区转换时跳过的本地时间(例如夏令时开始或由于时区规则变更导致时区偏移增加)时,t
使用转换前的时区偏移进行解释。
如果 possibleInstants 不为空,那么
设 disambiguatedInstant 为
possibleInstants [0]。
否则,
注意:t 表示在正时区转换时跳过的本地时间(例如由于夏令时开始或时区规则变更增加 UTC 偏移)。
设 possibleInstantsBefore 为
GetNamedTimeZoneEpochNanoseconds (systemTimeZoneIdentifier ,
ℝ (YearFromTime (tBefore )),
ℝ (MonthFromTime (tBefore ))
+ 1, ℝ (DateFromTime (tBefore )),
ℝ (HourFromTime (tBefore )),
ℝ (MinFromTime (tBefore )),
ℝ (SecFromTime (tBefore )),
ℝ (msFromTime (tBefore )),
0, 0),其中 tBefore 是小于 t 的最大整数 Number ,使得
possibleInstantsBefore 不为空(即,tBefore
表示转换前的最后一个本地时间)。
设 disambiguatedInstant 为
possibleInstantsBefore 的最后一个元素。
设 offsetNs 为 GetNamedTimeZoneOffsetNanoseconds (systemTimeZoneIdentifier ,
disambiguatedInstant )。
设 offsetMs 为 truncate (offsetNs /
106 )。
返回 t - 𝔽 (offsetMs )。
输入 t 名义上是一个时间值 ,但可以是任何 Number 值。
算法不得将 t 限制在时间值 范围内,以便可以支持对应于时间值 范围边界的输入,而不管本地 UTC 偏移如何。
例如,最大时间值 是 8.64 ×
1015 ,对应于 "+275760-09-13T00:00:00Z" 。
在本地时区偏移在该瞬间比 UTC 提前 1 小时的环境中,它由更大的输入 8.64 × 1015 + 3.6 ×
106 表示,对应于 "+275760-09-13T01:00:00+01:00" 。
如果实现中没有本地时间 t 的政治规则,结果就是 t ,因为 SystemTimeZoneIdentifier 返回
"UTC" ,GetNamedTimeZoneOffsetNanoseconds
返回 0。
注意 1
时区感知 实现(建议所有其他实现也如此)需要使用
IANA 时区数据库 https://www.iana.org/time-zones/
的时区信息。
2017 年 11 月 5 日在 America/New_York 的凌晨 1:30 重复了两次(回退),但必须解释为 1:30 AM UTC-04 而不是 1:30
AM UTC-05。
在 UTC(TimeClip (MakeDate (MakeDay (2017, 10, 5), MakeTime (1, 30, 0, 0))))
中,offsetMs 的值是 -4 × msPerHour 。
2017 年 3 月 12 日在 America/New_York 的凌晨 2:30 不存在,但必须解释为 2:30 AM UTC-05(相当于 3:30 AM
UTC-04)。
在 UTC(TimeClip (MakeDate (MakeDay (2017, 2, 12), MakeTime (2, 30, 0, 0))))
中,offsetMs 的值是 -5 × msPerHour 。
注意 2
UTC(LocalTime (t UTC ))
不一定总是等于 t UTC 。相应地,LocalTime (UTC(t local ))
不一定总是等于 t local 。
21.4.1.27 MakeTime ( hour , min ,
sec , ms )
抽象操作 MakeTime 接受参数 hour (一个 Number)、min (一个
Number)、sec (一个 Number)和 ms (一个 Number)并返回一个 Number。它
计算毫秒数。它在被调用时执行以下步骤:
如果 hour 不是有限 的,min 不是有限 的,
sec 不是有限 的,或 ms 不是有限 的,返回
NaN 。
设 h 为 𝔽 (! ToIntegerOrInfinity (hour ))。
设 m 为 𝔽 (! ToIntegerOrInfinity (min ))。
设 s 为 𝔽 (! ToIntegerOrInfinity (sec ))。
设 milli 为 𝔽 (! ToIntegerOrInfinity (ms ))。
返回 ((h × msPerHour + m × msPerMinute ) + s ×
msPerSecond ) + milli 。
注意
MakeTime 中的算术是浮点算术,它不满足结合律,所以操作必须按正确的顺序执行。
21.4.1.28 MakeDay ( year , month ,
date )
抽象操作 MakeDay 接受参数 year (一个 Number)、month
(一个 Number)和 date (一个 Number)并返回一个 Number。它计算天数。它在被调用时执行以下步骤:
如果 year 不是有限 的,month 不是有限 的,或
date 不是有限 的,返回 NaN 。
设 y 为 𝔽 (! ToIntegerOrInfinity (year ))。
设 m 为 𝔽 (! ToIntegerOrInfinity (month ))。
设 dt 为 𝔽 (! ToIntegerOrInfinity (date ))。
设 ym 为 y + 𝔽 (floor (ℝ (m ) / 12))。
如果 ym 不是有限 的,返回 NaN 。
设 mn 为 𝔽 (ℝ (m ) modulo 12)。
找到一个有限 的时间值
t ,使得 YearFromTime (t ) 是
ym ,MonthFromTime (t ) 是
mn ,并且 DateFromTime (t ) 是
1 𝔽 ;但如果这不可能(因为某些
参数超出范围),返回 NaN 。
返回 Day (t ) + dt -
1 𝔽 。
21.4.1.29 MakeDate ( day , time )
抽象操作 MakeDate 接受参数 day (一个 Number)和 time
(一个 Number)并返回一个 Number。它计算毫秒数。它在被调用时执行以下步骤:
如果 day 不是有限 的或 time 不是有限 的,返回
NaN 。
设 tv 为 day × msPerDay + time 。
如果 tv 不是有限 的,返回 NaN 。
返回 tv 。
21.4.1.30 MakeFullYear ( year )
抽象操作 MakeFullYear 接受参数 year (一个 Number)并返回一个整数
Number 或 NaN 。它返回与 year 的整数 部分关联的完整年份,将闭区间 0
到 99 中的任何值解释为自 1900 年开始以来的年数。为了与推算格里高利历保持一致,"完整年份"定义为自第 0 年(公元前 1
年)开始以来完整年份的有符号计数。它在被调用时执行以下步骤:
如果 year 是 NaN ,返回 NaN 。
设 truncated 为 ! ToIntegerOrInfinity (year )。
如果 truncated 在闭区间
0 到 99 中,返回 1900 𝔽 + 𝔽 (truncated )。
返回 𝔽 (truncated )。
21.4.1.31 TimeClip ( time )
抽象操作 TimeClip 接受参数 time (一个 Number)并返回一个
Number。它计算毫秒数。它在被调用时执行以下步骤:
如果 time 不是有限 的,返回 NaN 。
如果 abs (ℝ (time )) > 8.64 × 1015 ,
返回 NaN 。
返回 𝔽 (!
ToIntegerOrInfinity (time ))。
21.4.1.32 日期时间字符串格式
ECMAScript 基于 ISO 8601 日历日期扩展格式的简化版本定义了日期时间的字符串交换格式。格式如下:
YYYY-MM-DDTHH:mm:ss.sssZ
其中各元素如下:
YYYY
是推算格里高利历中的年份,作为从 0000 到 9999 的四位十进制数字,或作为由 "+" 或
"-" 后跟六位十进制数字的扩展年份 。
-
"-" (连字符)在字符串中字面出现两次。
MM
是一年中的月份,作为从 01(一月)到 12(十二月)的两位十进制数字。
DD
是一个月中的日期,作为从 01 到 31 的两位十进制数字。
T
"T" 在字符串中字面出现,表示时间元素的开始。
HH
是自午夜以来经过的完整小时数,作为从 00 到 24 的两位十进制数字。
:
":" (冒号)在字符串中字面出现两次。
mm
是自小时开始以来的完整分钟数,作为从 00 到 59 的两位十进制数字。
ss
是自分钟开始以来的完整秒数,作为从 00 到 59 的两位十进制数字。
.
"." (点)在字符串中字面出现。
sss
是自秒开始以来的完整毫秒数,作为三位十进制数字。
Z
是 UTC 偏移表示,指定为 "Z" (对于无偏移的 UTC)或作为 "+"
或
"-" 后跟时间表达式 HH:mm
(时区偏移字符串格式 的子集,分别用于指示本地时间早于或晚于
UTC)
此格式包括仅日期形式:
YYYY
YYYY-MM
YYYY-MM-DD
它还包括"日期时间"形式,由上述仅日期形式之一紧接一个以下时间形式(可附加可选的 UTC 偏移表示)组成:
THH:mm
THH:mm:ss
THH:mm:ss.sss
包含超出边界或不符合要求元素的字符串不是此格式的有效实例。
注意 1
由于每一天都以午夜开始和结束,00:00
和 24:00
这两种表示法可用于区分可能与一个日期关联的两个午夜。这意味着以下两种表示法指的是完全相同的时间点:1995-02-04T24:00
和
1995-02-05T00:00
。将后一种形式解释为"日历日的结束"与 ISO 8601
一致,尽管该规范将其保留用于描述时间间隔,并且不允许在单个时间点的表示中使用。
注意 2
不存在指定民用时区缩写(如 CET、EST 等)的国际标准,有时同一缩写甚至用于两个非常不同的时区。出于这个原因,ISO 8601 和此格式都指定时区偏移的数字表示。
21.4.1.32.1 扩展年份
涵盖从 1970 年 1 月 1 日向前或向后约 273,790 年的完整时间值 范围(21.4.1.1 )需要表示 0 之前或 9999
之后的年份。ISO 8601 允许扩展年份表示,但仅在信息交换伙伴相互同意的情况下。在简化的 ECMAScript 格式中,这种扩展年份表示应有 6 位数字,并且始终以 + 或
- 符号为前缀。年份 0 被认为是正数,必须以 + 符号为前缀。将年份 0 表示为 -000000 是无效的。匹配带有扩展年份的日期时间字符串格式 的字符串,如果表示超出时间值 范围的时间瞬间,将被 Date.parse
视为不可识别,并导致该函数返回
NaN ,而不回退到实现特定的行为或启发式。
注意
带有扩展年份的日期时间值示例:
-271821-04-20T00:00:00Z
公元前 271822 年
-000001-01-01T00:00:00Z
公元前 2 年
+000000-01-01T00:00:00Z
公元前 1 年
+000001-01-01T00:00:00Z
公元 1 年
+001970-01-01T00:00:00Z
公元 1970 年
+002009-12-15T00:00:00Z
公元 2009 年
+275760-09-13T00:00:00Z
公元 275760 年
21.4.1.33 时区偏移字符串格式
ECMAScript 定义了一个来源于 ISO 8601 的 UTC 偏移字符串交换格式。
该格式由以下语法描述。
语法
UTCOffset :::
ASCIISign
Hour
ASCIISign
Hour
HourSubcomponents [+Extended]
ASCIISign
Hour
HourSubcomponents [~Extended]
ASCIISign :::
one of + -
Hour :::
0
DecimalDigit
1
DecimalDigit
20
21
22
23
HourSubcomponents [Extended]
:::
TimeSeparator [?Extended]
MinuteSecond
TimeSeparator [?Extended]
MinuteSecond
TimeSeparator [?Extended]
MinuteSecond
TemporalDecimalFraction opt
TimeSeparator [Extended]
::: [+Extended]
:
[~Extended]
[empty]
MinuteSecond :::
0
DecimalDigit
1
DecimalDigit
2
DecimalDigit
3
DecimalDigit
4
DecimalDigit
5
DecimalDigit
TemporalDecimalFraction
:::
TemporalDecimalSeparator
DecimalDigit
TemporalDecimalSeparator
DecimalDigit
DecimalDigit
TemporalDecimalSeparator
DecimalDigit
DecimalDigit
DecimalDigit
TemporalDecimalSeparator
DecimalDigit
DecimalDigit
DecimalDigit
DecimalDigit
TemporalDecimalSeparator
DecimalDigit
DecimalDigit
DecimalDigit
DecimalDigit
DecimalDigit
TemporalDecimalSeparator
DecimalDigit
DecimalDigit
DecimalDigit
DecimalDigit
DecimalDigit
DecimalDigit
TemporalDecimalSeparator
DecimalDigit
DecimalDigit
DecimalDigit
DecimalDigit
DecimalDigit
DecimalDigit
DecimalDigit
TemporalDecimalSeparator
DecimalDigit
DecimalDigit
DecimalDigit
DecimalDigit
DecimalDigit
DecimalDigit
DecimalDigit
DecimalDigit
TemporalDecimalSeparator
DecimalDigit
DecimalDigit
DecimalDigit
DecimalDigit
DecimalDigit
DecimalDigit
DecimalDigit
DecimalDigit
DecimalDigit
TemporalDecimalSeparator
::: one of .
,
21.4.1.33.1 IsTimeZoneOffsetString ( offsetString
)
抽象操作 IsTimeZoneOffsetString 接受参数 offsetString (一个
String)并返回一个 Boolean。返回值指示
offsetString 是否符合 UTCOffset 给出的语法。它在被调用时执行以下步骤:
设 parseResult 为 ParseText (offsetString ,
UTCOffset )。
如果 parseResult 是一个错误的列表 ,返回
false 。
返回 true 。
21.4.1.33.2 ParseTimeZoneOffsetString (
offsetString )
抽象操作 ParseTimeZoneOffsetString 接受参数 offsetString
(一个 String)并返回一个整数 。返回值是对应于字符串 offsetString 的 UTC
偏移,以纳秒为单位。它在被调用时执行以下步骤:
设 parseResult 为 ParseText (offsetString ,
UTCOffset )。
断言 :parseResult 不是一个错误的列表 。
断言 :parseResult 包含一个
ASCIISign
解析节点 。
设 parsedSign 为 parseResult 中包含的 ASCIISign 解析节点 匹配的源文本 。
如果 parsedSign 是单个代码点 U+002D(连字符减号),那么
设 sign 为 -1。
否则,
设 sign 为 1。
注意:下面 StringToNumber
的应用不会丢失精度,因为每个解析值都保证是一个足够短的十进制数字字符串。
断言 :parseResult 包含一个
Hour 解析节点 。
设 parsedHours 为 parseResult 中包含的 Hour 解析节点 匹配的源文本 。
设 hours 为 ℝ (StringToNumber (CodePointsToString (parsedHours )))。
如果 parseResult 不包含 MinuteSecond 解析节点 ,那么
设 minutes 为 0。
否则,
设 parsedMinutes 为 parseResult 中包含的第一个 MinuteSecond 解析节点 匹配的源文本 。
设 minutes 为 ℝ (StringToNumber (CodePointsToString (parsedMinutes )))。
如果 parseResult 不包含两个 MinuteSecond 解析节点 ,那么
设 seconds 为 0。
否则,
设 parsedSeconds 为 parseResult 中包含的第二个 MinuteSecond 解析节点 匹配的源文本 。
设 seconds 为 ℝ (StringToNumber (CodePointsToString (parsedSeconds )))。
如果 parseResult 不包含 TemporalDecimalFraction
解析节点 ,那么
设 nanoseconds 为 0。
否则,
设 parsedFraction 为 parseResult 中包含的 TemporalDecimalFraction
解析节点 匹配的源文本 。
设 fraction 为 CodePointsToString (parsedFraction )
和 "000000000" 的字符串连接 。
设 nanosecondsString 为 fraction 从 1 到 10 的子字符串 。
设 nanoseconds 为 ℝ (StringToNumber (nanosecondsString ))。
返回 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 )
当调用此函数时,将执行以下步骤:
如果 NewTarget 为 undefined ,则
令 now 为标识当前时间的 时间值 (UTC)。
返回 ToDateString (now )。
令 numberOfArgs 为 values 中元素的数量。
如果 numberOfArgs = 0,则
令 dv 为标识当前时间的 时间值 (UTC)。
否则如果 numberOfArgs = 1,则
令 value 为 values [0]。
如果 value 是一个对象 且 value 具有
[[DateValue]] 内部槽,则
令 tv 为 value .[[DateValue]] 。
否则,
令 v 为 ? ToPrimitive (value )。
如果 v 是字符串 ,则
断言 :下一步永远不会返回 非正常完成 ,因为
v
是字符串 。
令 tv 为以与 parse
方法 (21.4.3.2 )
完全相同的方式解析 v 作为日期的结果。
否则,
令 tv 为 ? ToNumber (v )。
令 dv 为 TimeClip (tv )。
否则,
断言 :numberOfArgs ≥ 2。
令 y 为 ? ToNumber (values [0])。
令 m 为 ? ToNumber (values [1])。
如果 numberOfArgs > 2,令 dt 为 ? ToNumber (values [2]);否则令
dt 为 1 𝔽 。
如果 numberOfArgs > 3,令 h 为 ? ToNumber (values [3]);否则令
h 为 +0 𝔽 。
如果 numberOfArgs > 4,令 min 为 ? ToNumber (values [4]);否则令
min 为 +0 𝔽 。
如果 numberOfArgs > 5,令 s 为 ? ToNumber (values [5]);否则令
s 为 +0 𝔽 。
如果 numberOfArgs > 6,令 milli 为 ? ToNumber (values [6]);否则令
milli 为 +0 𝔽 。
令 yr 为 MakeFullYear (y )。
令 finalDate 为 MakeDate (MakeDay (yr ,
m , dt ), MakeTime (h ,
min , s , milli ))。
令 dv 为 TimeClip (UTC (finalDate ))。
令 O 为 ? OrdinaryCreateFromConstructor (NewTarget,
"%Date.prototype%" , « [[DateValue]] »)。
设置 O .[[DateValue]] 为 dv 。
返回 O 。
21.4.3 Date 构造函数的属性
Date 构造函数 :
21.4.3.1 Date.now ( )
此函数返回表示调用时 UTC 日期和时间的 时间值 。
21.4.3.2 Date.parse ( string )
此函数对其参数应用 ToString 运算符。如果 ToString 产生 非正常完成 ,则会立即返回该
Completion
Record 。否则,此函数将结果字符串作为日期和时间进行解释;返回一个 Number,即与该日期和时间对应的 UTC 时间值 。字符串可能会被解释为本地时间、UTC
时间或其他时区的时间,具体取决于字符串的内容。函数首先尝试按照日期时间字符串格式 (21.4.1.32 ),包括扩展年份,解析该字符串。如果字符串不符合该格式,函数可以退回到实现相关的启发式算法或实现相关的日期格式。无法识别或包含越界格式元素值的字符串会导致该函数返回
NaN 。
如果字符串符合 日期时间字符串格式 ,则缺失的格式元素将用替代值补齐。当
MM
或 DD
元素缺失时,使用 "01" 。当
HH
、mm
或 ss
元素缺失时,使用 "00" 。当
sss
元素缺失时,使用 "000" 。当缺少 UTC 偏移表示时,仅日期形式被解释为 UTC
时间,日期-时间形式被解释为本地时间。
如果 x
是 ECMAScript 某一实现中毫秒数为零的 Date,则在该实现中,以下所有表达式(如果所有相关属性都是初始值)应产生相同的数值:
x.valueOf ()
Date .parse (x.toString ())
Date .parse (x.toUTCString ())
Date .parse (x.toISOString ())
然而,下面的表达式
Date .parse (x.toLocaleString ())
不要求产生与前三个表达式相同的数值,并且通常当传入的字符串不符合日期时间字符串格式 (21.4.1.32 ),且无法由
toString
或 toUTCString
方法在该实现中产生时,该函数的返回值是 实现定义 的。
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 ] ] ] ] ] ] )
当调用此函数时,将执行以下步骤:
令 y 为 ? ToNumber (year )。
如果 month 存在,令 m 为 ? ToNumber (month );否则,令
m 为 +0 𝔽 。
如果 date 存在,令 dt 为 ? ToNumber (date );否则,令
dt 为 1 𝔽 。
如果 hours 存在,令 h 为 ? ToNumber (hours );否则,令
h 为 +0 𝔽 。
如果 minutes 存在,令 min 为 ? ToNumber (minutes );否则,令
min 为 +0 𝔽 。
如果 seconds 存在,令 s 为 ? ToNumber (seconds );否则,令
s 为 +0 𝔽 。
如果 ms 存在,令 milli 为 ? ToNumber (ms );否则,令
milli 为 +0 𝔽 。
令 yr 为 MakeFullYear (y )。
返回 TimeClip (MakeDate (MakeDay (yr , m ,
dt ), MakeTime (h , min ,
s , milli )))。
该函数的 "length" 属性值为 7 𝔽 。
注意
此函数与 Date 构造函数 有两点不同:它返回一个 Number 形式的 时间值 ,而不是创建一个
Date,并且参数被解释为 UTC,而不是本地时间。
21.4.4 Date 原型对象的属性
Date 原型对象 :
是 %Date.prototype% 。
它本身是一个 普通对象 。
不是 Date 实例,也没有 [[DateValue]] 内部槽。
具有 [[Prototype]] 内部槽,其值为 %Object.prototype% 。
除非另有明确规定,下文定义的 Date 原型对象的方法不是泛型的,传递给它们的 this 值必须是一个已经初始化了 [[DateValue]] 内部槽,并且该槽为一个 时间值 的对象。
21.4.4.1 Date.prototype.constructor
Date.prototype.constructor
的初始值是 %Date% 。
21.4.4.2 Date.prototype.getDate ( )
调用该方法时,执行以下步骤:
令 dateObject 为 this 值。
执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
令 t 为 dateObject .[[DateValue]] 。
如果 t 为 NaN ,则返回 NaN 。
返回 DateFromTime (LocalTime (t ))。
21.4.4.3 Date.prototype.getDay ( )
调用该方法时,执行以下步骤:
令 dateObject 为 this 值。
执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
令 t 为 dateObject .[[DateValue]] 。
如果 t 为 NaN ,则返回 NaN 。
返回 WeekDay (LocalTime (t ))。
21.4.4.4 Date.prototype.getFullYear ( )
调用该方法时,执行以下步骤:
令 dateObject 为 this 值。
执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
令 t 为 dateObject .[[DateValue]] 。
如果 t 为 NaN ,则返回 NaN 。
返回 YearFromTime (LocalTime (t ))。
21.4.4.5 Date.prototype.getHours ( )
调用该方法时,执行以下步骤:
令 dateObject 为 this 值。
执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
令 t 为 dateObject .[[DateValue]] 。
如果 t 为 NaN ,则返回 NaN 。
返回 HourFromTime (LocalTime (t ))。
21.4.4.6 Date.prototype.getMilliseconds ( )
调用该方法时,执行以下步骤:
令 dateObject 为 this 值。
执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
令 t 为 dateObject .[[DateValue]] 。
如果 t 为 NaN ,则返回 NaN 。
返回 msFromTime (LocalTime (t ))。
21.4.4.7 Date.prototype.getMinutes ( )
调用该方法时,执行以下步骤:
令 dateObject 为 this 值。
执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
令 t 为 dateObject .[[DateValue]] 。
如果 t 为 NaN ,则返回 NaN 。
返回 MinFromTime (LocalTime (t ))。
21.4.4.8 Date.prototype.getMonth ( )
调用该方法时,执行以下步骤:
令 dateObject 为 this 值。
执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
令 t 为 dateObject .[[DateValue]] 。
如果 t 为 NaN ,则返回 NaN 。
返回 MonthFromTime (LocalTime (t ))。
21.4.4.9 Date.prototype.getSeconds ( )
调用该方法时,执行以下步骤:
令 dateObject 为 this 值。
执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
令 t 为 dateObject .[[DateValue]] 。
如果 t 为 NaN ,则返回 NaN 。
返回 SecFromTime (LocalTime (t ))。
21.4.4.10 Date.prototype.getTime ( )
调用该方法时,执行以下步骤:
令 dateObject 为 this 值。
执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
返回 dateObject .[[DateValue]] 。
21.4.4.11 Date.prototype.getTimezoneOffset ( )
调用该方法时,执行以下步骤:
令 dateObject 为 this 值。
执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
令 t 为 dateObject .[[DateValue]] 。
如果 t 为 NaN ,则返回 NaN 。
返回 (t - LocalTime (t )) / msPerMinute 。
21.4.4.12 Date.prototype.getUTCDate ( )
调用该方法时,执行以下步骤:
令 dateObject 为 this 值。
执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
令 t 为 dateObject .[[DateValue]] 。
如果 t 为 NaN ,则返回 NaN 。
返回 DateFromTime (t )。
21.4.4.13 Date.prototype.getUTCDay ( )
调用该方法时,执行以下步骤:
令 dateObject 为 this 值。
执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
令 t 为 dateObject .[[DateValue]] 。
如果 t 为 NaN ,则返回 NaN 。
返回 WeekDay (t )。
21.4.4.14 Date.prototype.getUTCFullYear ( )
调用该方法时,执行以下步骤:
令 dateObject 为 this 值。
执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
令 t 为 dateObject .[[DateValue]] 。
如果 t 为 NaN ,则返回 NaN 。
返回 YearFromTime (t )。
21.4.4.15 Date.prototype.getUTCHours ( )
调用该方法时,执行以下步骤:
令 dateObject 为 this 值。
执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
令 t 为 dateObject .[[DateValue]] 。
如果 t 为 NaN ,则返回 NaN 。
返回 HourFromTime (t )。
21.4.4.16 Date.prototype.getUTCMilliseconds ( )
调用该方法时,执行以下步骤:
令 dateObject 为 this 值。
执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
令 t 为 dateObject .[[DateValue]] 。
如果 t 为 NaN ,则返回 NaN 。
返回 msFromTime (t )。
21.4.4.17 Date.prototype.getUTCMinutes ( )
调用该方法时,执行以下步骤:
令 dateObject 为 this 值。
执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
令 t 为 dateObject .[[DateValue]] 。
如果 t 为 NaN ,则返回 NaN 。
返回 MinFromTime (t )。
21.4.4.18 Date.prototype.getUTCMonth ( )
调用该方法时,执行以下步骤:
令 dateObject 为 this 值。
执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
令 t 为 dateObject .[[DateValue]] 。
如果 t 为 NaN ,则返回 NaN 。
返回 MonthFromTime (t )。
21.4.4.19 Date.prototype.getUTCSeconds ( )
调用该方法时,执行以下步骤:
令 dateObject 为 this 值。
执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
令 t 为 dateObject .[[DateValue]] 。
如果 t 为 NaN ,则返回 NaN 。
返回 SecFromTime (t )。
21.4.4.20 Date.prototype.setDate ( date )
调用该方法时,执行以下步骤:
令 dateObject 为 this 值。
执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
令 t 为 dateObject .[[DateValue]] 。
令 dt 为 ? ToNumber (date )。
如果 t 为 NaN ,则返回 NaN 。
设置 t 为 LocalTime (t )。
令 newDate 为 MakeDate (MakeDay (YearFromTime (t ),
MonthFromTime (t ),
dt ), TimeWithinDay (t ))。
令 u 为 TimeClip (UTC (newDate ))。
设置 dateObject .[[DateValue]] 为 u 。
返回 u 。
21.4.4.21 Date.prototype.setFullYear ( year [ ,
month [ , date ] ] )
调用该方法时,执行以下步骤:
令 dateObject 为 this 值。
执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
令 t 为 dateObject .[[DateValue]] 。
令 y 为 ? ToNumber (year )。
如果 t 为 NaN ,则设置 t 为
+0 𝔽 ;否则,设置 t 为 LocalTime (t )。
如果 month 未给出,令 m 为 MonthFromTime (t );否则,令
m 为 ? ToNumber (month )。
如果 date 未给出,令 dt 为 DateFromTime (t );否则,令
dt 为 ? ToNumber (date )。
令 newDate 为 MakeDate (MakeDay (y ,
m , dt ), TimeWithinDay (t ))。
令 u 为 TimeClip (UTC (newDate ))。
设置 dateObject .[[DateValue]] 为 u 。
返回 u 。
该方法的 "length" 属性值为 3 𝔽 。
注意
如果未给出 month ,本方法表现为 month 的值为 getMonth()
。如果未给出
date ,则表现为 date 的值为 getDate()
。
21.4.4.22 Date.prototype.setHours ( hour [ ,
min [ , sec [ , ms ] ] ] )
调用该方法时,执行以下步骤:
令 dateObject 为 this 值。
执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
令 t 为 dateObject .[[DateValue]] 。
令 h 为 ? ToNumber (hour )。
如果 min 给出,令 m 为 ? ToNumber (min )。
如果 sec 给出,令 s 为 ? ToNumber (sec )。
如果 ms 给出,令 milli 为 ? ToNumber (ms )。
如果 t 为 NaN ,则返回 NaN 。
设置 t 为 LocalTime (t )。
如果 min 未给出,令 m 为 MinFromTime (t )。
如果 sec 未给出,令 s 为 SecFromTime (t )。
如果 ms 未给出,令 milli 为 msFromTime (t )。
令 date 为 MakeDate (Day (t ), MakeTime (h , m ,
s , milli ))。
令 u 为 TimeClip (UTC (date ))。
设置 dateObject .[[DateValue]] 为 u 。
返回 u 。
该方法的 "length" 属性值为 4 𝔽 。
注意
如果未给出 min ,本方法表现为 min 的值为 getMinutes()
。如果未给出
sec ,则表现为 sec 的值为 getSeconds()
。如果未给出
ms ,则表现为 ms 的值为 getMilliseconds()
。
21.4.4.23 Date.prototype.setMilliseconds ( ms )
调用该方法时,执行以下步骤:
令 dateObject 为 this 值。
执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
令 t 为 dateObject .[[DateValue]] 。
将 ms 设为 ? ToNumber (ms )。
如果 t 为 NaN ,返回 NaN 。
将 t 设为 LocalTime (t )。
令 time 为 MakeTime (HourFromTime (t ),
MinFromTime (t ), SecFromTime (t ),
ms )。
令 u 为 TimeClip (UTC (MakeDate (Day (t ),
time )))。
设置 dateObject .[[DateValue]] 为 u 。
返回 u 。
21.4.4.24 Date.prototype.setMinutes ( min [ ,
sec [ , ms ] ] )
调用该方法时,执行以下步骤:
令 dateObject 为 this 值。
执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
令 t 为 dateObject .[[DateValue]] 。
令 m 为 ? ToNumber (min )。
如果 sec 给出,令 s 为 ? ToNumber (sec )。
如果 ms 给出,令 milli 为 ? ToNumber (ms )。
如果 t 为 NaN ,返回 NaN 。
设置 t 为 LocalTime (t )。
如果 sec 未给出,令 s 为 SecFromTime (t )。
如果 ms 未给出,令 milli 为 msFromTime (t )。
令 date 为 MakeDate (Day (t ), MakeTime (HourFromTime (t ),
m , s , milli ))。
令 u 为 TimeClip (UTC (date ))。
设置 dateObject .[[DateValue]] 为 u 。
返回 u 。
该方法的 "length" 属性值为 3 𝔽 。
注意
如果未给出 sec ,本方法表现为 sec 的值为 getSeconds()
。如果未给出
ms ,则表现为 ms 的值为 getMilliseconds()
。
21.4.4.25 Date.prototype.setMonth ( month [ ,
date ] )
调用该方法时,执行以下步骤:
令 dateObject 为 this 值。
执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
令 t 为 dateObject .[[DateValue]] 。
令 m 为 ? ToNumber (month )。
如果 date 给出,令 dt 为 ? ToNumber (date )。
如果 t 为 NaN ,返回 NaN 。
设置 t 为 LocalTime (t )。
如果 date 未给出,令 dt 为 DateFromTime (t )。
令 newDate 为 MakeDate (MakeDay (YearFromTime (t ),
m , dt ), TimeWithinDay (t ))。
令 u 为 TimeClip (UTC (newDate ))。
设置 dateObject .[[DateValue]] 为 u 。
返回 u 。
该方法的 "length" 属性值为 2 𝔽 。
注意
如果未给出 date ,本方法表现为 date 的值为 getDate()
。
21.4.4.26 Date.prototype.setSeconds ( sec [ ,
ms ] )
调用该方法时,执行以下步骤:
令 dateObject 为 this 值。
执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
令 t 为 dateObject .[[DateValue]] 。
令 s 为 ? ToNumber (sec )。
如果 ms 给出,令 milli 为 ? ToNumber (ms )。
如果 t 为 NaN ,返回 NaN 。
设置 t 为 LocalTime (t )。
如果 ms 未给出,令 milli 为 msFromTime (t )。
令 date 为 MakeDate (Day (t ), MakeTime (HourFromTime (t ),
MinFromTime (t ),
s , milli ))。
令 u 为 TimeClip (UTC (date ))。
设置 dateObject .[[DateValue]] 为 u 。
返回 u 。
该方法的 "length" 属性值为 2 𝔽 。
注意
如果未给出 ms ,本方法表现为 ms 的值为 getMilliseconds()
。
21.4.4.27 Date.prototype.setTime ( time )
调用该方法时,执行以下步骤:
令 dateObject 为 this 值。
执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
令 t 为 ? ToNumber (time )。
令 v 为 TimeClip (t )。
设置 dateObject .[[DateValue]] 为 v 。
返回 v 。
21.4.4.28 Date.prototype.setUTCDate ( date )
调用该方法时,执行以下步骤:
令 dateObject 为 this 值。
执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
令 t 为 dateObject .[[DateValue]] 。
令 dt 为 ? ToNumber (date )。
如果 t 为 NaN ,返回 NaN 。
令 newDate 为 MakeDate (MakeDay (YearFromTime (t ),
MonthFromTime (t ),
dt ), TimeWithinDay (t ))。
令 v 为 TimeClip (newDate )。
设置 dateObject .[[DateValue]] 为 v 。
返回 v 。
21.4.4.29 Date.prototype.setUTCFullYear ( year [ ,
month [ , date ] ] )
调用该方法时,执行以下步骤:
令 dateObject 为 this 值。
执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
令 t 为 dateObject .[[DateValue]] 。
如果 t 为 NaN ,则设置 t 为
+0 𝔽 。
令 y 为 ? ToNumber (year )。
如果 month 未给出,令 m 为 MonthFromTime (t );
否则,令 m 为 ? ToNumber (month )。
如果 date 未给出,令 dt 为 DateFromTime (t );
否则,令 dt 为 ? ToNumber (date )。
令 newDate 为 MakeDate (MakeDay (y ,
m , dt ), TimeWithinDay (t ))。
令 v 为 TimeClip (newDate )。
设置 dateObject .[[DateValue]] 为 v 。
返回 v 。
该方法的 "length" 属性值为 3 𝔽 。
注意
如果未给出 month ,本方法表现为 month 的值为 getUTCMonth()
。如果未给出
date ,则表现为 date 的值为 getUTCDate()
。
21.4.4.30 Date.prototype.setUTCHours ( hour [ ,
min [ , sec [ , ms ] ] ] )
调用该方法时,执行以下步骤:
令 dateObject 为 this 值。
执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
令 t 为 dateObject .[[DateValue]] 。
令 h 为 ? ToNumber (hour )。
如果 min 给出,令 m 为 ? ToNumber (min )。
如果 sec 给出,令 s 为 ? ToNumber (sec )。
如果 ms 给出,令 milli 为 ? ToNumber (ms )。
如果 t 为 NaN ,返回 NaN 。
如果 min 未给出,令 m 为 MinFromTime (t )。
如果 sec 未给出,令 s 为 SecFromTime (t )。
如果 ms 未给出,令 milli 为 msFromTime (t )。
令 date 为 MakeDate (Day (t ), MakeTime (h , m ,
s , milli ))。
令 v 为 TimeClip (date )。
设置 dateObject .[[DateValue]] 为 v 。
返回 v 。
该方法的 "length" 属性值为 4 𝔽 。
注意
如果未给出 min ,本方法表现为 min 的值为 getUTCMinutes()
。如果未给出
sec ,则表现为 sec 的值为 getUTCSeconds()
。如果未给出
ms ,则表现为 ms 的值为 getUTCMilliseconds()
。
21.4.4.31 Date.prototype.setUTCMilliseconds ( ms )
调用该方法时,执行以下步骤:
令 dateObject 为 this 值。
执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
令 t 为 dateObject .[[DateValue]] 。
将 ms 设为 ? ToNumber (ms )。
如果 t 为 NaN ,返回 NaN 。
令 time 为 MakeTime (HourFromTime (t ),
MinFromTime (t ), SecFromTime (t ),
ms )。
令 v 为 TimeClip (MakeDate (Day (t ),
time ))。
设置 dateObject .[[DateValue]] 为 v 。
返回 v 。
21.4.4.32 Date.prototype.setUTCMinutes ( min [ ,
sec [ , ms ] ] )
调用该方法时,执行以下步骤:
令 dateObject 为 this 值。
执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
令 t 为 dateObject .[[DateValue]] 。
令 m 为 ? ToNumber (min )。
如果 sec 给出,令 s 为 ? ToNumber (sec )。
如果 ms 给出,令 milli 为 ? ToNumber (ms )。
如果 t 为 NaN ,返回 NaN 。
如果 sec 未给出,令 s 为 SecFromTime (t )。
如果 ms 未给出,令 milli 为 msFromTime (t )。
令 date 为 MakeDate (Day (t ), MakeTime (HourFromTime (t ),
m , s , milli ))。
令 v 为 TimeClip (date )。
设置 dateObject .[[DateValue]] 为 v 。
返回 v 。
该方法的 "length" 属性值为 3 𝔽 。
注意
如果未给出 sec ,本方法表现为 sec 的值为 getUTCSeconds()
。如果未给出
ms ,则表现为 ms 的值为 getUTCMilliseconds()
。
21.4.4.33 Date.prototype.setUTCMonth ( month [ ,
date ] )
调用该方法时,执行以下步骤:
令 dateObject 为 this 值。
执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
令 t 为 dateObject .[[DateValue]] 。
令 m 为 ? ToNumber (month )。
如果 date 给出,令 dt 为 ? ToNumber (date )。
如果 t 为 NaN ,返回 NaN 。
如果 date 未给出,令 dt 为 DateFromTime (t )。
令 newDate 为 MakeDate (MakeDay (YearFromTime (t ),
m , dt ), TimeWithinDay (t ))。
令 v 为 TimeClip (newDate )。
设置 dateObject .[[DateValue]] 为 v 。
返回 v 。
该方法的 "length" 属性值为 2 𝔽 。
注意
如果未给出 date ,本方法表现为 date 的值为 getUTCDate()
。
21.4.4.34 Date.prototype.setUTCSeconds ( sec [ ,
ms ] )
调用该方法时,执行以下步骤:
令 dateObject 为 this 值。
执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
令 t 为 dateObject .[[DateValue]] 。
令 s 为 ? ToNumber (sec )。
如果 ms 给出,令 milli 为 ? ToNumber (ms )。
如果 t 为 NaN ,返回 NaN 。
如果 ms 未给出,令 milli 为 msFromTime (t )。
令 date 为 MakeDate (Day (t ), MakeTime (HourFromTime (t ),
MinFromTime (t ),
s , milli ))。
令 v 为 TimeClip (date )。
设置 dateObject .[[DateValue]] 为 v 。
返回 v 。
该方法的 "length" 属性值为 2 𝔽 。
注意
如果未给出 ms ,本方法表现为 ms 的值为 getUTCMilliseconds()
。
21.4.4.35 Date.prototype.toDateString ( )
调用该方法时,执行以下步骤:
令 dateObject 为 this 值。
执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
令 tv 为 dateObject .[[DateValue]] 。
如果 tv 为 NaN ,返回 "Invalid
Date" 。
令 t 为 LocalTime (tv )。
返回 DateString (t )。
21.4.4.36 Date.prototype.toISOString ( )
调用该方法时,执行以下步骤:
令 dateObject 为 this 值。
执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
令 tv 为 dateObject .[[DateValue]] 。
如果 tv 为 NaN ,抛出 RangeError 异常。
断言 :tv 是一个 整数
Number 。
如果 tv 所对应的年份不能用 日期时间字符串格式
表示,则抛出 RangeError 异常。
返回 tv 在 UTC 时标下、日期时间字符串格式
的字符串表示,包括所有格式元素及 UTC 偏移 "Z"。
21.4.4.37 Date.prototype.toJSON ( key )
此方法为 JSON.stringify
(25.5.2 ) 提供 Date 的字符串表示。
调用该方法时,执行以下步骤:
令 O 为 ? ToObject (this 值)。
令 tv 为 ? ToPrimitive (O ,
number )。
如果 tv 是
Number 且 tv 不是 有限值 ,则返回
null 。
返回 ? Invoke (O ,
"toISOString" )。
注意 1
注意 2
此方法有意设计为泛型;它不要求其 this 值为 Date。因此,可以转移到其他类型的对象上作为方法使用。但该对象必须有
toISOString
方法。
21.4.4.38 Date.prototype.toLocaleDateString ( [
reserved1 [ , reserved2 ] ] )
包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按照 ECMA-402 规范实现此方法。如果 ECMAScript 实现未包含 ECMA-402
API,则使用以下规范:
该方法返回一个字符串值。字符串内容是实现定义 的,但旨在以方便且易于理解的形式,表示当前时区下 Date
的“日期”部分,符合宿主环境 当前区域设置的习惯。
本方法的可选参数含义在 ECMA-402 规范中定义;未包含 ECMA-402 支持的实现不得将这些参数位置用于其他用途。
21.4.4.39 Date.prototype.toLocaleString ( [ reserved1
[ , reserved2 ] ] )
包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按照 ECMA-402 规范实现此方法。如果 ECMAScript 实现未包含 ECMA-402
API,则使用以下规范:
该方法返回一个字符串值。字符串内容是实现定义 的,但旨在以方便且易于理解的形式,表示当前时区下的
Date,符合宿主环境 当前区域设置的习惯。
本方法的可选参数含义在 ECMA-402 规范中定义;未包含 ECMA-402 支持的实现不得将这些参数位置用于其他用途。
21.4.4.40 Date.prototype.toLocaleTimeString ( [
reserved1 [ , reserved2 ] ] )
包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按照 ECMA-402 规范实现此方法。如果 ECMAScript 实现未包含 ECMA-402
API,则使用以下规范:
该方法返回一个字符串值。字符串内容是实现定义 的,但旨在以方便且易于理解的形式,表示当前时区下 Date
的“时间”部分,符合宿主环境 当前区域设置的习惯。
本方法的可选参数含义在 ECMA-402 规范中定义;未包含 ECMA-402 支持的实现不得将这些参数位置用于其他用途。
21.4.4.41 Date.prototype.toString ( )
调用该方法时,执行以下步骤:
令 dateObject 为 this 值。
执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
令 tv 为 dateObject .[[DateValue]] 。
返回 ToDateString (tv )。
注意 1
对于任何 Date d
,如果 d.[[DateValue]]
能被
1000 整除,则 Date.parse(d.toString())
的结果等于
d.valueOf()
。参见21.4.3.2 。
注意 2
此方法不是泛型;如果其 this 值不是 Date,则会抛出 TypeError
异常。因此,不能转移到其他类型的对象用作方法。
21.4.4.41.1 TimeString ( tv )
抽象操作 TimeString 接受参数 tv (Number,但不是 NaN ),返回一个字符串。调用时执行以下步骤:
令 hour 为 ToZeroPaddedDecimalString (ℝ (HourFromTime (tv )),
2)。
令 minute 为 ToZeroPaddedDecimalString (ℝ (MinFromTime (tv )), 2)。
令 second 为 ToZeroPaddedDecimalString (ℝ (SecFromTime (tv )), 2)。
返回 字符串拼接
hour 、":" 、minute 、":" 、second 、0x0020(空格)、"GMT" 。
21.4.4.41.2 DateString ( tv )
抽象操作 DateString 接受参数 tv (Number,但不是 NaN ),返回一个字符串。调用时执行以下步骤:
令 weekday 为 表 65 中编号为
WeekDay (tv ) 的 Name。
令 month 为 表 66
中编号为 MonthFromTime (tv ) 的
Name。
令 day 为 ToZeroPaddedDecimalString (ℝ (DateFromTime (tv )),
2)。
令 yv 为 YearFromTime (tv )。
如果 yv 是 +0 𝔽 或 yv >
+0 𝔽 ,则 yearSign 为空字符串;否则
yearSign 为 "-" 。
令 paddedYear 为 ToZeroPaddedDecimalString (abs (ℝ (yv )), 4)。
返回 字符串拼接
weekday 、0x0020(空格)、month 、0x0020、day 、0x0020、yearSign
和 paddedYear 。
表 65:一周中各天的名称
编号
名称
+0 𝔽
"Sun"
1 𝔽
"Mon"
2 𝔽
"Tue"
3 𝔽
"Wed"
4 𝔽
"Thu"
5 𝔽
"Fri"
6 𝔽
"Sat"
表 66:一年中各月的名称
编号
名称
+0 𝔽
"Jan"
1 𝔽
"Feb"
2 𝔽
"Mar"
3 𝔽
"Apr"
4 𝔽
"May"
5 𝔽
"Jun"
6 𝔽
"Jul"
7 𝔽
"Aug"
8 𝔽
"Sep"
9 𝔽
"Oct"
10 𝔽
"Nov"
11 𝔽
"Dec"
21.4.4.41.3 TimeZoneString ( tv )
抽象操作 TimeZoneString 接受参数 tv (整数
Number ),返回一个字符串。调用时执行以下步骤:
令 systemTimeZoneIdentifier 为 SystemTimeZoneIdentifier ()。
如果 IsTimeZoneOffsetString (systemTimeZoneIdentifier )
为 true ,则
令 offsetNs 为 ParseTimeZoneOffsetString (systemTimeZoneIdentifier )。
否则,
令 offsetNs 为 GetNamedTimeZoneOffsetNanoseconds (systemTimeZoneIdentifier ,
ℤ (ℝ (tv ) × 106 ))。
令 offset 为 𝔽 (truncate (offsetNs /
106 ))。
如果 offset 为 +0 𝔽 或 offset
> +0 𝔽 ,则
令 offsetSign 为 "+" 。
令 absOffset 为 offset 。
否则,
令 offsetSign 为 "-" 。
令 absOffset 为 -offset 。
令 offsetMin 为 ToZeroPaddedDecimalString (ℝ (MinFromTime (absOffset )),
2)。
令 offsetHour 为 ToZeroPaddedDecimalString (ℝ (HourFromTime (absOffset )),
2)。
令 tzName 为一个实现定义 的字符串,其值可以为空字符串,也可以是
0x0020(空格)、0x0028(左括号)、实现定义 的时区名称和
0x0029(右括号)的字符串拼接。
返回 字符串拼接
offsetSign 、offsetHour 、offsetMin 和
tzName 。
21.4.4.41.4 ToDateString ( tv )
抽象操作 ToDateString 接受参数 tv (整数 Number 或
NaN ),返回一个字符串。调用时执行以下步骤:
如果 tv 为 NaN ,返回 "Invalid Date" 。
令 t 为 LocalTime (tv )。
返回 字符串拼接 DateString (t )、0x0020(空格)、TimeString (t ) 和
TimeZoneString (tv )。
21.4.4.42 Date.prototype.toTimeString ( )
调用该方法时,执行以下步骤:
令 dateObject 为 this 值。
执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
令 tv 为 dateObject .[[DateValue]] 。
如果 tv 为 NaN ,返回 "Invalid Date" 。
令 t 为 LocalTime (tv )。
返回 字符串拼接 TimeString (t ) 和 TimeZoneString (tv )。
21.4.4.43 Date.prototype.toUTCString ( )
该方法返回一个字符串值,表示与 this 值对应的时间点。字符串格式基于 RFC 7231 的 "HTTP-date",并推广以支持
ECMAScript Dates 支持的完整时间范围。
调用该方法时,执行以下步骤:
令 dateObject 为 this 值。
执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
令 tv 为 dateObject .[[DateValue]] 。
如果 tv 为 NaN ,返回 "Invalid Date" 。
令 weekday 为 表 65 中编号为 WeekDay (tv ) 的 Name。
令 month 为 表 66 中编号为 MonthFromTime (tv ) 的
Name。
令 day 为 ToZeroPaddedDecimalString (ℝ (DateFromTime (tv )), 2)。
令 yv 为 YearFromTime (tv )。
如果 yv 是 +0 𝔽 或 yv >
+0 𝔽 ,则 yearSign 为空字符串;否则
yearSign 为 "-" 。
令 paddedYear 为 ToZeroPaddedDecimalString (abs (ℝ (yv )), 4)。
返回 字符串拼接
weekday 、"," 、0x0020(空格)、day 、0x0020、month 、0x0020、yearSign 、paddedYear 、0x0020
和 TimeString (tv )。
21.4.4.44 Date.prototype.valueOf ( )
调用该方法时,执行以下步骤:
令 dateObject 为 this 值。
执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
返回 dateObject .[[DateValue]] 。
21.4.4.45 Date.prototype [ %Symbol.toPrimitive% ] (
hint )
此方法被 ECMAScript 语言运算符调用,用于将 Date 转换为原始值。hint 的允许值为
"default" 、"number" 和 "string" 。Date
是内置 ECMAScript 对象中唯一将 "default" 视为等价于 "string"
的对象。所有其他内置 ECMAScript 对象都将 "default" 视为等价于 "number" 。
调用该方法时,执行以下步骤:
令 O 为 this 值。
如果 O 不是对象 ,则抛出 TypeError
异常。
如果 hint 是 "string" 或 "default" ,则
令 tryFirst 为 string 。
否则如果 hint 是 "number" ,则
令 tryFirst 为 number 。
否则,
抛出 TypeError 异常。
返回 ? OrdinaryToPrimitive (O ,
tryFirst )。
该属性具有属性 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] : true }。
本方法的 "name" 属性值为 "[Symbol.toPrimitive]" 。
21.4.5 Date 实例的属性
Date 实例是普通对象 ,继承自Date 原型对象 的属性。Date
实例还拥有一个 [[DateValue]] 内部槽。[[DateValue]] 内部槽即该
Date 实例所表示的时间值 。
22 文本处理
22.1 字符串对象
22.1.1 String 构造函数
String 构造函数 :
是 %String% 。
是 "String" 属性在 全局对象 上的初始值。
作为 构造函数
调用时,创建并初始化一个新的 String 对象。
作为函数调用而非 构造函数 时,执行类型转换。
可作为类定义中 extends
子句的值使用。打算继承指定 String 行为的子类 构造函数 必须包含对 String 构造函数 的
super
调用,以用 [[StringData]] 内部槽创建并初始化子类实例。
22.1.1.1 String ( value )
当调用该函数时,执行以下步骤:
如果 value 未给出,则
令 s 为空字符串。
否则,
如果 NewTarget 为 undefined 且 value 是
Symbol ,则返回 SymbolDescriptiveString (value )。
令 s 为 ? ToString (value )。
如果 NewTarget 为 undefined ,返回 s 。
返回 StringCreate (s ,
? GetPrototypeFromConstructor (NewTarget,
"%String.prototype%" ))。
22.1.2 String 构造函数的属性
String 构造函数 :
22.1.2.1 String.fromCharCode ( ...codeUnits )
该函数可以接收任意数量的参数,这些参数形成余参数 codeUnits 。
调用该函数时,执行以下步骤:
令 result 为空字符串。
对于 codeUnits 中的每个元素 next ,执行
令 nextCU 为数值为 ℝ (? ToUint16 (next )) 的码元。
将 result 设为 字符串拼接
result 和 nextCU 的结果。
返回 result 。
该函数的 "length" 属性值为 1 𝔽 。
22.1.2.2 String.fromCodePoint ( ...codePoints )
该函数可以接收任意数量的参数,这些参数形成余参数 codePoints 。
调用该函数时,执行以下步骤:
令 result 为空字符串。
对于 codePoints 中的每个元素 next ,执行
令 nextCP 为 ? ToNumber (next )。
如果 nextCP 不是 整数 Number ,抛出
RangeError 异常。
如果 ℝ (nextCP ) < 0 或 ℝ (nextCP ) > 0x10FFFF,抛出
RangeError 异常。
将 result 设为 字符串拼接
result 和 UTF16EncodeCodePoint (ℝ (nextCP )) 的结果。
断言 :如果
codePoints 为空,则 result 为空字符串。
返回 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 。
调用该函数时,执行以下步骤:
令 substitutionCount 为 substitutions 的元素个数。
令 cooked 为 ? ToObject (template )。
令 literals 为 ? ToObject (? Get (cooked ,
"raw" ))。
令 literalCount 为 ? LengthOfArrayLike (literals )。
如果 literalCount ≤ 0,返回空字符串。
令 R 为空字符串。
令 nextIndex 为 0。
重复,
令 nextLiteralVal 为 ? Get (literals ,
! ToString (𝔽 (nextIndex )))。
令 nextLiteral 为 ? ToString (nextLiteralVal )。
将 R 设为 字符串拼接 R 和
nextLiteral 的结果。
如果 nextIndex + 1 = literalCount ,返回 R 。
如果 nextIndex < substitutionCount ,则
令 nextSubVal 为
substitutions [nextIndex ]。
令 nextSub 为 ? ToString (nextSubVal )。
将 R 设为 字符串拼接
R 和 nextSub 的结果。
将 nextIndex 设为 nextIndex + 1。
注意
该函数用于作为标记模板(Tagged Template)(13.3.11 )的标记函数使用。当以此方式调用时,第一个参数将是格式良好的模板对象,其余参数是替换值。
22.1.3 String 原型对象的属性
String 原型对象 :
是 %String.prototype% 。
是 String
特殊对象 ,并拥有为此类对象规定的内部方法。
有一个 [[StringData]] 内部槽,其值为空字符串。
有一个 "length" 属性,其初始值为 +0 𝔽 ,属性为 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] : false }。
有一个 [[Prototype]] 内部槽,其值为 %Object.prototype% 。
除非另有明确声明,下文定义的 String 原型对象的方法都不是泛型方法,传递给它们的 this 值必须是 String 值或具有已初始化为 String
值的 [[StringData]] 内部槽的对象。
22.1.3.1 String.prototype.at ( index )
令 O 为 ? RequireObjectCoercible (this
值)。
令 S 为 ? ToString (O )。
令 len 为 S 的长度。
令 relativeIndex 为 ? ToIntegerOrInfinity (index )。
如果 relativeIndex ≥ 0,则
令 k 为 relativeIndex 。
否则,
令 k 为 len + relativeIndex 。
如果 k < 0 或 k ≥ len ,返回
undefined 。
返回 substring S 从 k 到
k + 1。
22.1.3.2 String.prototype.charAt ( pos )
注 1
此方法返回包含在将此对象转换为 String 后的字符串中索引为 pos
的码元的单元素字符串。如果该索引处没有元素,则返回空字符串。结果是
String 值,而不是 String 对象。
如果 pos
是 整数 Number ,则
x.charAt(pos)
的结果等价于 x.substring(pos, pos + 1)
。
调用该方法时,执行以下步骤:
令 O 为 ? RequireObjectCoercible (this
值)。
令 S 为 ? ToString (O )。
令 position 为 ? ToIntegerOrInfinity (pos )。
令 size 为 S 的长度。
如果 position < 0 或 position ≥ size ,返回空字符串。
返回 substring S 从
position 到 position + 1。
注 2
此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。
22.1.3.3 String.prototype.charCodeAt ( pos )
注 1
此方法返回一个 Number(一个非负的整数 Number ,小于
216 ),表示将此对象转换为 String 后字符串中索引为 pos 处的码元的数值。如果该索引处没有元素,则结果为
NaN 。
调用该方法时,执行以下步骤:
令 O 为 ? RequireObjectCoercible (this
值)。
令 S 为 ? ToString (O )。
令 position 为 ? ToIntegerOrInfinity (pos )。
令 size 为 S 的长度。
如果 position < 0 或 position ≥ size ,返回
NaN 。
返回 Number value for 字符串 S
中索引为 position 的码元的数值。
注 2
此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。
22.1.3.4 String.prototype.codePointAt ( pos )
注 1
此方法返回一个非负的整数 Number ,小于等于
0x10FFFF 𝔽 ,表示在将该对象转换为 String 后字符串中索引为 pos
处开始的 UTF-16 编码码点(6.1.4 )的数值。如果该索引处没有元素,则结果为
undefined 。如果 pos 处不是有效的 UTF-16 代理对 的开始,则结果为 pos 处的码元。
调用该方法时,执行以下步骤:
令 O 为 ? RequireObjectCoercible (this
值)。
令 S 为 ? ToString (O )。
令 position 为 ? ToIntegerOrInfinity (pos )。
令 size 为 S 的长度。
如果 position < 0 或 position ≥ size ,返回
undefined 。
令 cp 为 CodePointAt (S ,
position )。
返回 𝔽 (cp .[[CodePoint]] )。
注 2
此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。
22.1.3.5 String.prototype.concat ( ...args )
注 1
调用此方法时,返回由 this 值(转换为 String)码元后跟每个参数转换为 String 后的码元组成的 String
值。结果是
String 值,而不是 String 对象。
调用该方法时,执行以下步骤:
令 O 为 ? RequireObjectCoercible (this
值)。
令 S 为 ? ToString (O )。
令 R 为 S 。
对于 args 中的每个元素 next ,执行
令 nextString 为 ? ToString (next )。
将 R 设为 字符串拼接 R 和
nextString 的结果。
返回 R 。
该方法的 "length" 属性值为 1 𝔽 。
注 2
此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。
22.1.3.6 String.prototype.constructor
String.prototype.constructor
的初始值为 %String% 。
22.1.3.7 String.prototype.endsWith ( searchString [ ,
endPosition ] )
调用该方法时,执行以下步骤:
令 O 为 ? RequireObjectCoercible (this
值)。
令 S 为 ? ToString (O )。
令 isRegExp 为 ? IsRegExp (searchString )。
如果 isRegExp 为 true ,抛出 TypeError 异常。
令 searchStr 为 ? ToString (searchString )。
令 len 为 S 的长度。
如果 endPosition 为 undefined ,令 pos 为
len ;否则令 pos 为 ? ToIntegerOrInfinity (endPosition )。
令 end 为 clamping pos 介于 0 和
len 之间的结果。
令 searchLength 为 searchStr 的长度。
如果 searchLength = 0,返回 true 。
令 start 为 end - searchLength 。
如果 start < 0,返回 false 。
令 substring 为 substring S 从 start 到
end 。
如果 substring 等于 searchStr ,返回 true 。
返回 false 。
注 1
如果 searchString (转换为 String)码元序列与本对象(转换为 String)中从 endPosition -
length(this) 开始的对应码元相同,则该方法返回 true ,否则返回 false 。
注 2
如果第一个参数是 RegExp 抛出异常,是为了允许后续标准版本定义支持此类参数值的扩展。
注 3
此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。
22.1.3.8 String.prototype.includes ( searchString [ ,
position ] )
调用该方法时,执行以下步骤:
令 O 为 ? RequireObjectCoercible (this
值)。
令 S 为 ? ToString (O )。
令 isRegExp 为 ? IsRegExp (searchString )。
如果 isRegExp 为 true ,抛出 TypeError 异常。
令 searchStr 为 ? ToString (searchString )。
令 pos 为 ? ToIntegerOrInfinity (position )。
断言 :如果
position 为 undefined ,则 pos 为 0。
令 len 为 S 的长度。
令 start 为 clamping pos 介于 0 和
len 之间的结果。
令 index 为 StringIndexOf (S ,
searchStr , start )。
如果 index 为 not-found ,返回 false 。
返回 true 。
注 1
如果 searchString 作为子串 出现在将此对象转换为 String
后的结果中,且索引大于等于 position ,则该函数返回 true ;否则返回
false 。如果 position 为 undefined ,则默认值为
0,因此会搜索整个字符串。
注 2
如果第一个参数是 RegExp 抛出异常,是为了允许后续标准版本定义支持此类参数值的扩展。
注 3
此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。
22.1.3.9 String.prototype.indexOf ( searchString [ ,
position ] )
注 1
如果 searchString 作为子串 出现在将此对象转换为 String
后的结果中,且索引大于等于 position ,则返回最小的此类索引,否则返回
-1 𝔽 。如果 position 为
undefined ,则假定为 +0 𝔽 ,即搜索整个字符串。
调用该方法时,执行以下步骤:
令 O 为 ? RequireObjectCoercible (this
值)。
令 S 为 ? ToString (O )。
令 searchStr 为 ? ToString (searchString )。
令 pos 为 ? ToIntegerOrInfinity (position )。
断言 :如果
position 为 undefined ,则 pos 为 0。
令 len 为 S 的长度。
令 start 为 clamping pos 介于 0 和
len 之间的结果。
令 result 为 StringIndexOf (S ,
searchStr , start )。
如果 result 为 not-found ,返回
-1 𝔽 。
返回 𝔽 (result )。
注 2
此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。
22.1.3.10 String.prototype.isWellFormed ( )
调用该方法时,执行以下步骤:
令 O 为 ? RequireObjectCoercible (this
值)。
令 S 为 ? ToString (O )。
返回 IsStringWellFormedUnicode (S )。
22.1.3.11 String.prototype.lastIndexOf ( searchString
[ , position ] )
注 1
如果 searchString 作为子串 出现在将此对象转换为 String
后的结果中,且索引小于等于 position ,则返回最大的此类索引,否则返回
-1 𝔽 。如果 position 为
undefined ,则假定为字符串长度,即搜索整个字符串。
调用该方法时,执行以下步骤:
令 O 为 ? RequireObjectCoercible (this
值)。
令 S 为 ? ToString (O )。
令 searchStr 为 ? ToString (searchString )。
令 numPos 为 ? ToNumber (position )。
断言 :如果
position 为 undefined ,则 numPos 为
NaN 。
如果 numPos 为 NaN ,令 pos 为 +∞;否则,令
pos 为 ! ToIntegerOrInfinity (numPos )。
令 len 为 S 的长度。
令 searchLen 为 searchStr 的长度。
令 start 为 clamping pos 介于 0 和
len - searchLen 之间的结果。
令 result 为 StringLastIndexOf (S ,
searchStr , start )。
如果 result 为 not-found ,返回
-1 𝔽 。
返回 𝔽 (result )。
注 2
此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。
22.1.3.12 String.prototype.localeCompare ( that [ ,
reserved1 [ , reserved2 ] ] )
包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按照 ECMA-402 规范实现此方法。如果 ECMAScript 实现未包含 ECMA-402
API,则使用以下规范:
该方法返回一个除 NaN 以外的 Number,表示将 this 值(转换为字符串
S )与 that (转换为字符串 thatValue )进行实现定义 的本地敏感字符串比较的结果。该结果旨在与 宿主环境 当前区域设置的排序顺序 相对应,当 S 排在
thatValue 之前时为负,排在之后时为正,否则为零(表示 S 和 thatValue 之间无相对顺序)。
在执行比较前,该方法会按如下步骤准备字符串:
令 O 为 ? RequireObjectCoercible (this
值)。
令 S 为 ? ToString (O )。
令 thatValue 为 ? ToString (that )。
本方法的第二和第三个可选参数的含义在 ECMA-402 规范中定义;未包含 ECMA-402 支持的实现不得将这些参数位置用于其他用途。
实际返回值为实现定义 ,以允许编码额外信息,但作为两个参数的方法时,要求作为一致的比较器 ,对所有字符串集合定义全序关系。该方法还要求根据 Unicode
标准识别和遵循规范等价,包括在比较可区分但规范等价的字符串时返回 +0 𝔽 。
注 1
此方法本身不适合作为 Array.prototype.sort
的参数,因为后者需要两个参数的函数。
注 2
此方法可依赖 ECMAScript 环境从宿主环境 获得的任意语言/区域敏感比较功能,并旨在按照宿主环境当前区域设置的习惯进行比较。但无论比较能力如何,本方法都必须根据
Unicode 标准识别和遵循规范等价——例如,以下比较都必须返回 +0 𝔽 :
"\u212B" .localeCompare ("A\u030A" )
"\u2126" .localeCompare ("\u03A9" )
"\u1E69" .localeCompare ("s\u0307\u0323" )
"\u1E0B\u0323" .localeCompare ("\u1E0D\u0307" )
"\u1100\u1161" .localeCompare ("\uAC00" )
关于规范等价的定义和讨论,参见 Unicode 标准第 2 章和第 3 章,以及 Unicode Standard Annex #15, Unicode
Normalization Forms 和 Unicode
Technical Note #5, Canonical Equivalence in Applications 。另见 Unicode Technical Standard #10, Unicode
Collation Algorithm 。
建议本方法不应遵循 Unicode 兼容等价或 Unicode 标准第 3 章第 3.7 节定义的兼容分解。
注 3
此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。
22.1.3.13 String.prototype.match ( regexp )
调用该方法时,执行以下步骤:
令 O 为 ? RequireObjectCoercible (this
值)。
如果 regexp 既不是 undefined 也不是 null ,则
令 matcher 为 ? GetMethod (regexp ,
%Symbol.match% )。
如果 matcher 不为 undefined ,则
返回 ? Call (matcher ,
regexp , « O »)。
令 S 为 ? ToString (O )。
令 rx 为 ? RegExpCreate (regexp ,
undefined )。
返回 ? Invoke (rx , %Symbol.match% , «
S »)。
注
此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。
22.1.3.14 String.prototype.matchAll ( regexp )
该方法对将 this 值表示的字符串与 regexp 进行正则表达式匹配,并返回一个迭代器 ,该迭代器会产生匹配结果。每个匹配结果是一个数组,其第一个元素为匹配到的字符串片段,后跟任何捕获组匹配到的片段。如果正则表达式从未匹配,返回的迭代器不会产生任何匹配结果。
调用该方法时,执行以下步骤:
令 O 为 ? RequireObjectCoercible (this
值)。
如果 regexp 既不是 undefined 也不是 null ,则
令 isRegExp 为 ? IsRegExp (regexp )。
如果 isRegExp 为 true ,则
令 flags 为 ? Get (regexp ,
"flags" )。
执行 ? RequireObjectCoercible (flags )。
如果 ? ToString (flags )
不包含 "g" ,抛出 TypeError 异常。
令 matcher 为 ? GetMethod (regexp ,
%Symbol.matchAll% )。
如果 matcher 不为 undefined ,则
返回 ? Call (matcher ,
regexp , « O »)。
令 S 为 ? ToString (O )。
令 rx 为 ? RegExpCreate (regexp ,
"g" )。
返回 ? Invoke (rx , %Symbol.matchAll% , «
S »)。
注 1
此方法有意设计为泛型,不要求其 this 值为 String
对象。因此,可以转移到其他类型的对象上作为方法使用。
注 2
与 String.prototype.split
类似,String.prototype.matchAll
通常不应改变其输入。
22.1.3.15 String.prototype.normalize ( [ form ] )
调用该方法时,执行以下步骤:
令 O 为 ? RequireObjectCoercible (this
值)。
令 S 为 ? ToString (O )。
如果 form 为 undefined ,令 f 为
"NFC" 。
否则,令 f 为 ? ToString (form )。
如果 f 不是
"NFC" 、"NFD" 、"NFKC" 或
"NFKD" 之一,则抛出 RangeError 异常。
令 ns 为将 S 按 最新 Unicode
标准,Normalization Forms 中由 f 命名的规范形式规范化后的字符串值。
返回 ns 。
注
此方法有意设计为泛型,不要求其 this 值为 String 对象。因此可以转移到其他类型的对象上作为方法使用。
22.1.3.16 String.prototype.padEnd ( maxLength [ ,
fillString ] )
调用该方法时,执行以下步骤:
令 O 为 ? RequireObjectCoercible (this
值)。
返回 ? StringPaddingBuiltinsImpl (O ,
maxLength , fillString , end )。
22.1.3.17 String.prototype.padStart ( maxLength [ ,
fillString ] )
调用该方法时,执行以下步骤:
令 O 为 ? RequireObjectCoercible (this
值)。
返回 ? StringPaddingBuiltinsImpl (O ,
maxLength , fillString , start )。
22.1.3.17.1 StringPaddingBuiltinsImpl ( O ,
maxLength , fillString , placement )
抽象操作 StringPaddingBuiltinsImpl 接收参数 O (ECMAScript
语言值 )、maxLength (ECMAScript
语言值 )、fillString (ECMAScript 语言值 )和
placement (start 或
end ),返回字符串或抛出异常。调用时执行以下步骤:
令 S 为 ? ToString (O )。
令 intMaxLength 为 ℝ (? ToLength (maxLength ))。
令 stringLength 为 S 的长度。
如果 intMaxLength ≤ stringLength ,返回 S 。
如果 fillString 为 undefined ,设置 fillString
为仅包含码元 0x0020(空格)的字符串。
否则,设置 fillString 为 ? ToString (fillString )。
返回 StringPad (S ,
intMaxLength , fillString , placement )。
22.1.3.17.2 StringPad ( S , maxLength ,
fillString , placement )
抽象操作 StringPad 接收参数 S (字符串)、maxLength (非负整数 )、fillString (字符串)和
placement (start 或
end ),返回字符串。调用时执行以下步骤:
令 stringLength 为 S 的长度。
如果 maxLength ≤ stringLength ,返回 S 。
如果 fillString 为空字符串,返回 S 。
令 fillLen 为 maxLength - stringLength 。
令 truncatedStringFiller 为重复拼接 fillString 并截断为
fillLen 长度的字符串。
如果 placement 为 start ,返回 字符串拼接
truncatedStringFiller 和 S 的结果。
否则,返回 字符串拼接 S 和
truncatedStringFiller 的结果。
注 1
maxLength 参数会被限制,不能小于 S 的长度。
注 2
fillString 参数的默认值为 " " (仅包含码元 0x0020 空格的字符串)。
22.1.3.17.3 ToZeroPaddedDecimalString ( n ,
minLength )
抽象操作 ToZeroPaddedDecimalString 接收参数 n (非负整数 )和
minLength (非负整数 ),返回字符串。调用时执行以下步骤:
令 S 为 n 的字符串表示,格式为十进制数。
返回 StringPad (S ,
minLength , "0" , start )。
22.1.3.18 String.prototype.repeat ( count )
调用该方法时,执行以下步骤:
令 O 为 ? RequireObjectCoercible (this
值)。
令 S 为 ? ToString (O )。
令 n 为 ? ToIntegerOrInfinity (count )。
如果 n < 0 或 n = +∞,抛出 RangeError 异常。
如果 n = 0,返回空字符串。
返回由 S 拼接 n 次组成的字符串值。
注 1
此方法会创建由 this 值(转换为字符串)的码元重复 count 次组成的字符串值。
注 2
此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。
22.1.3.19 String.prototype.replace ( searchValue ,
replaceValue )
调用该方法时,执行以下步骤:
令 O 为 ? RequireObjectCoercible (this
值)。
如果 searchValue 既不是 undefined 也不是
null ,则
令 replacer 为 ? GetMethod (searchValue ,
%Symbol.replace% )。
如果 replacer 不为 undefined ,则
返回 ? Call (replacer ,
searchValue , « O ,
replaceValue »)。
令 string 为 ? ToString (O )。
令 searchString 为 ? ToString (searchValue )。
令 functionalReplace 为 IsCallable (replaceValue )。
如果 functionalReplace 为 false ,则
将 replaceValue 设为 ? ToString (replaceValue )。
令 searchLength 为 searchString 的长度。
令 position 为 StringIndexOf (string ,
searchString , 0)。
如果 position 为 not-found ,返回 string 。
令 preceding 为 substring string 从 0 到
position 。
令 following 为 substring string 从
position + searchLength 。
如果 functionalReplace 为 true ,则
令 replacement 为 ? ToString (? Call (replaceValue ,
undefined , « searchString , 𝔽 (position ),
string »))。
否则,
断言 :replaceValue 是
String 。
令 captures 为新的空List 。
令 replacement 为 ! GetSubstitution (searchString ,
string , position , captures ,
undefined , replaceValue )。
返回 字符串拼接
preceding 、replacement 和 following 。
注
此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。
22.1.3.19.1 GetSubstitution ( matched ,
str , position , captures , namedCaptures ,
replacementTemplate )
抽象操作 GetSubstitution 接收参数
matched (字符串)、str (字符串)、position (非负整数 )、captures (字符串或
undefined 的List )、namedCaptures (对象或
undefined )、replacementTemplate (字符串),返回字符串或抛出异常。此抽象操作中,十进制数字 是
0x0030 (DIGIT ZERO) 到 0x0039 (DIGIT NINE) 区间的码元。调用时执行以下步骤:
令 stringLength 为 str 的长度。
断言 :position ≤
stringLength 。
令 result 为空字符串。
令 templateRemainder 为 replacementTemplate 。
重复,直到 templateRemainder 为空字符串,
注:以下步骤隔离
ref (templateRemainder 的前缀),确定
refReplacement (其替换内容),然后将该替换内容追加到 result 。
如果 templateRemainder 以 "$$" 开头,则
令 ref 为 "$$" 。
令 refReplacement 为 "$" 。
否则,如果 templateRemainder 以 "$`" 开头,则
令 ref 为 "$`" 。
令 refReplacement 为 substring
str 从 0 到 position 。
否则,如果 templateRemainder 以 "$&" 开头,则
令 ref 为 "$&" 。
令 refReplacement 为 matched 。
否则,如果 templateRemainder 以
"$'" (0x0024(美元符号)后接 0x0027(撇号))开头,则
令 ref 为 "$'" 。
令 matchLength 为 matched 的长度。
令 tailPos 为 position +
matchLength 。
令 refReplacement 为 substring
str 从 min (tailPos ,
stringLength )。
注:tailPos 只有在该抽象操作由对 %RegExp.prototype% 的 %Symbol.replace%
内置方法调用,且对象的 "exec" 属性不是内置
%RegExp.prototype.exec% 时才会超过 stringLength 。
否则,如果 templateRemainder 以 "$" 后跟 1
个或多个十进制数字开头,则
如果 templateRemainder 以 "$" 后跟 2
个或更多十进制数字开头,令 digitCount 为 2,否则为 1。
令 digits 为 substring
templateRemainder 从 1 到 1 + digitCount 。
令 index 为 ℝ (StringToNumber (digits ))。
断言 :0 ≤ index ≤
99。
令 captureLen 为 captures 的元素个数。
如果 index > captureLen 且
digitCount = 2,则
注:两位数替换模式指定的索引超出捕获组数量时,视为一位数替换模式后跟一个字面数字。
令 digitCount 为 1。
令 digits 为 substring
digits 从 0 到 1。
令 index 为 ℝ (StringToNumber (digits ))。
令 ref 为 substring
templateRemainder 从 0 到 1 + digitCount 。
如果 1 ≤ index ≤ captureLen ,则
令 capture 为
captures [index - 1]。
如果 capture 为 undefined ,则
令 refReplacement 为空字符串。
否则,
令 refReplacement 为
capture 。
否则,
令 refReplacement 为 ref 。
否则,如果 templateRemainder 以 "$<" 开头,则
令 gtPos 为 StringIndexOf (templateRemainder ,
">" , 0)。
如果 gtPos 为 not-found 或
namedCaptures 为 undefined ,则
令 ref 为 "$<" 。
令 refReplacement 为 ref 。
否则,
令 ref 为 substring
templateRemainder 从 0 到 gtPos + 1。
令 groupName 为 substring
templateRemainder 从 2 到 gtPos 。
断言 :namedCaptures
是对象 。
令 capture 为 ? Get (namedCaptures ,
groupName )。
如果 capture 为 undefined ,则
令 refReplacement 为空字符串。
否则,
令 refReplacement 为 ? ToString (capture )。
否则,
令 ref 为 substring
templateRemainder 从 0 到 1。
令 refReplacement 为 ref 。
令 refLength 为 ref 的长度。
将 templateRemainder 设为 substring
templateRemainder 从 refLength 。
将 result 设为 字符串拼接
result 和 refReplacement 的结果。
返回 result 。
22.1.3.20 String.prototype.replaceAll ( searchValue ,
replaceValue )
调用该方法时,执行以下步骤:
令 O 为 ? RequireObjectCoercible (this
值)。
如果 searchValue 既不是 undefined 也不是
null ,则
令 isRegExp 为 ? IsRegExp (searchValue )。
如果 isRegExp 为 true ,则
令 flags 为 ? Get (searchValue ,
"flags" )。
执行 ? RequireObjectCoercible (flags )。
如果 ? ToString (flags )
不包含 "g" ,抛出 TypeError 异常。
令 replacer 为 ? GetMethod (searchValue ,
%Symbol.replace% )。
如果 replacer 不为 undefined ,则
返回 ? Call (replacer ,
searchValue , « O , replaceValue »)。
令 string 为 ? ToString (O )。
令 searchString 为 ? ToString (searchValue )。
令 functionalReplace 为 IsCallable (replaceValue )。
如果 functionalReplace 为 false ,则
将 replaceValue 设为 ? ToString (replaceValue )。
令 searchLength 为 searchString 的长度。
令 advanceBy 为 max (1, searchLength )。
令 matchPositions 为新的空 List 。
令 position 为 StringIndexOf (string ,
searchString , 0)。
重复,直到 position 为 not-found ,
将 position 添加到 matchPositions 。
将 position 设为 StringIndexOf (string ,
searchString , position + advanceBy )。
令 endOfLastMatch 为 0。
令 result 为空字符串。
对于 matchPositions 中的每个元素 p ,执行
令 preserved 为 substring string 从
endOfLastMatch 到 p 。
如果 functionalReplace 为 true ,则
令 replacement 为 ? ToString (? Call (replaceValue ,
undefined , « searchString , 𝔽 (p ),
string »))。
否则,
断言 :replaceValue
是
String 。
令 captures 为新的空List 。
令 replacement 为 ! GetSubstitution (searchString ,
string , p , captures ,
undefined , replaceValue )。
将 result 设为 字符串拼接
result 、preserved 和 replacement 的结果。
将 endOfLastMatch 设为 p + searchLength 。
如果 endOfLastMatch < string 的长度,则
将 result 设为 字符串拼接
result 和 substring string 从
endOfLastMatch 。
返回 result 。
22.1.3.21 String.prototype.search ( regexp )
调用该方法时,执行以下步骤:
令 O 为 ? RequireObjectCoercible (this
值)。
如果 regexp 既不是 undefined 也不是 null ,则
令 searcher 为 ? GetMethod (regexp ,
%Symbol.search% )。
如果 searcher 不为 undefined ,则
返回 ? Call (searcher ,
regexp , « O »)。
令 string 为 ? ToString (O )。
令 rx 为 ? RegExpCreate (regexp ,
undefined )。
返回 ? Invoke (rx , %Symbol.search% , «
string »)。
注
此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。
22.1.3.22 String.prototype.slice ( start ,
end )
该方法返回将此对象转换为字符串后的子串 ,从索引 start 开始,到但不包括索引
end (或若 end 为 undefined ,则直到字符串末尾)。如果
start 为负,则视为 sourceLength +
start ,其中 sourceLength 是字符串长度。如果 end 为负,则视为
sourceLength + end 。结果是 String 值,而不是
String 对象。
调用该方法时,执行以下步骤:
令 O 为 ? RequireObjectCoercible (this
值)。
令 S 为 ? ToString (O )。
令 len 为 S 的长度。
令 intStart 为 ? ToIntegerOrInfinity (start )。
如果 intStart = -∞,令 from 为 0。
否则若 intStart < 0,令 from 为 max (len +
intStart , 0)。
否则,令 from 为 min (intStart , len )。
如果 end 为 undefined ,令 intEnd 为
len ;否则令 intEnd 为 ? ToIntegerOrInfinity (end )。
如果 intEnd = -∞,令 to 为 0。
否则若 intEnd < 0,令 to 为 max (len +
intEnd , 0)。
否则,令 to 为 min (intEnd , len )。
如果 from ≥ to ,返回空字符串。
返回 substring S 从 from 到
to 。
注
此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此可以转移到其他类型的对象上作为方法使用。
22.1.3.23 String.prototype.split ( separator ,
limit )
该方法返回一个数组,将此对象转换为字符串后的子串存储在其中。子串是通过从左到右查找 separator
的出现位置确定的;这些出现位置不会包含在返回数组的任何字符串中,而是用来分割字符串。separator 的值可以是任意长度的字符串,也可以是具有
%Symbol.split% 方法的对象(如 RegExp)。
调用该方法时,执行以下步骤:
令 O 为 ? RequireObjectCoercible (this
值)。
如果 separator 既不是 undefined 也不是
null ,则
令 splitter 为 ? GetMethod (separator ,
%Symbol.split% )。
如果 splitter 不为 undefined ,则
返回 ? Call (splitter ,
separator , « O , limit »)。
令 S 为 ? ToString (O )。
如果 limit 为 undefined ,令 lim 为 232
- 1;否则令 lim 为 ℝ (? ToUint32 (limit ))。
令 R 为 ? ToString (separator )。
如果 lim = 0,则
返回 CreateArrayFromList («
»)。
如果 separator 为 undefined ,则
返回 CreateArrayFromList («
S »)。
令 separatorLength 为 R 的长度。
如果 separatorLength = 0,则
令 strLen 为 S 的长度。
令 outLen 为 clamping lim 在 0 和
strLen 之间的结果。
令 head 为 substring S 从 0 到
outLen 。
令 codeUnits 为一个 List ,包含
head 的所有码元。
返回 CreateArrayFromList (codeUnits )。
如果 S 为空字符串,返回 CreateArrayFromList («
S »)。
令 substrings 为新的空 List 。
令 i 为 0。
令 j 为 StringIndexOf (S ,
R , 0)。
重复,直到 j 为 not-found ,
令 T 为 substring S 从
i 到 j 。
将 T 添加到 substrings 。
如果 substrings 的元素个数为 lim ,返回 CreateArrayFromList (substrings )。
将 i 设为 j + separatorLength 。
将 j 设为 StringIndexOf (S ,
R , i )。
令 T 为 substring S 从 i 。
将 T 添加到 substrings 。
返回 CreateArrayFromList (substrings )。
注 1
separator 的值可以为空字符串。在这种情况下,separator
不会匹配输入字符串开头或结尾的空子串 ,也不会匹配前一个分隔符匹配后结尾的空子串 。如果
separator
为空字符串,则字符串被拆分为单个码元元素;结果数组的长度等于字符串的长度,每个子串 只包含一个码元。
如果 this 值(或其转换结果)为空字符串,则结果取决于 separator
能否匹配空字符串。如果可以,结果数组不包含任何元素;否则,结果数组包含一个元素,即空字符串。
如果 separator 为 undefined ,结果数组只包含一个字符串,即
this 的值(转换为字符串)。如果 limit 不为
undefined ,则输出数组会被截断为不超过 limit 个元素。
注 2
此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。
22.1.3.24 String.prototype.startsWith ( searchString
[ , position ] )
调用该方法时,执行以下步骤:
令 O 为 ? RequireObjectCoercible (this
值)。
令 S 为 ? ToString (O )。
令 isRegExp 为 ? IsRegExp (searchString )。
如果 isRegExp 为 true ,抛出 TypeError 异常。
令 searchStr 为 ? ToString (searchString )。
令 len 为 S 的长度。
如果 position 为 undefined ,令 pos 为 0;否则令
pos 为 ? ToIntegerOrInfinity (position )。
令 start 为 clamping pos 在 0 和 len
之间的结果。
令 searchLength 为 searchStr 的长度。
如果 searchLength = 0,返回 true 。
令 end 为 start + searchLength 。
如果 end > len ,返回 false 。
令 substring 为 substring S 从 start 到
end 。
如果 substring 等于 searchStr ,返回 true 。
返回 false 。
注 1
如果 searchString (转换为字符串)的码元序列与本对象(转换为字符串)从 position
开始的对应码元相同,则返回 true ,否则返回 false 。
注 2
如果第一个参数是 RegExp 抛出异常,是为了允许后续标准版本定义支持此类参数值的扩展。
注 3
此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。
22.1.3.25 String.prototype.substring ( start ,
end )
该方法返回将此对象转换为字符串后的子串 ,从索引 start 开始,到但不包括字符串的索引
end (或若 end 为 undefined ,则直到字符串末尾)。结果是 String 值,而不是
String 对象。
如果任一参数为 NaN 或负数,则用零替换;如果任一参数严格大于字符串长度,则用字符串长度替换。
如果 start 严格大于 end ,则交换两者。
调用该方法时,执行以下步骤:
令 O 为 ? RequireObjectCoercible (this
值)。
令 S 为 ? ToString (O )。
令 len 为 S 的长度。
令 intStart 为 ? ToIntegerOrInfinity (start )。
如果 end 为 undefined ,令 intEnd 为
len ;否则令 intEnd 为 ? ToIntegerOrInfinity (end )。
令 finalStart 为 clamping intStart 在 0 和
len 之间的结果。
令 finalEnd 为 clamping intEnd 在 0 和
len 之间的结果。
令 from 为 min (finalStart ,
finalEnd )。
令 to 为 max (finalStart ,
finalEnd )。
返回 substring S 从 from 到
to 。
注
此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。
22.1.3.26 String.prototype.toLocaleLowerCase ( [
reserved1 [ , reserved2 ] ] )
包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按照 ECMA-402 规范实现此方法。如果 ECMAScript 实现未包含 ECMA-402
API,则使用以下规范:
该方法将 String 值作为 UTF-16 编码码点序列解释,如 6.1.4
中描述。
其行为与 toLowerCase
相同,但旨在根据 宿主环境 当前区域设置的惯例产生区域敏感的结果。仅在少数(如土耳其语)该语言规则与常规
Unicode 大小写映射冲突的情况下才会有差异。
该方法的可选参数含义由 ECMA-402 规范定义;未包含 ECMA-402 支持的实现不得将这些参数位置用于其他用途。
注
此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。
22.1.3.27 String.prototype.toLocaleUpperCase ( [
reserved1 [ , reserved2 ] ] )
包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按照 ECMA-402 规范实现此方法。如果 ECMAScript 实现未包含 ECMA-402
API,则使用以下规范:
该方法将 String 值作为 UTF-16 编码码点序列解释,如 6.1.4
中描述。
其行为与 toUpperCase
相同,但旨在根据 宿主环境 当前区域设置的惯例产生区域敏感的结果。仅在少数(如土耳其语)该语言规则与常规
Unicode 大小写映射冲突的情况下才会有差异。
该方法的可选参数含义由 ECMA-402 规范定义;未包含 ECMA-402 支持的实现不得将这些参数位置用于其他用途。
注
此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。
22.1.3.28 String.prototype.toLowerCase ( )
该方法将 String 值作为 UTF-16 编码码点序列解释,如 6.1.4
中描述。
调用该方法时,执行以下步骤:
令 O 为 ? RequireObjectCoercible (this
值)。
令 S 为 ? ToString (O )。
令 sText 为 StringToCodePoints (S )。
令 lowerText 为根据 Unicode 默认大小写转换算法对 sText 执行 toLowercase。
令 L 为 CodePointsToString (lowerText )。
返回 L 。
结果必须依据 Unicode 字符数据库中的区域无关大小写映射得出(这不仅包括 UnicodeData.txt
文件,还包括伴随的 SpecialCasing.txt
文件中所有区域无关的映射)。
注 1
某些码点的大小写映射可能产生多个码点。在这种情况下,结果字符串的长度可能与源字符串不同。由于 toUpperCase
和
toLowerCase
都具有上下文相关行为,这些方法并不对称。换言之,s.toUpperCase().toLowerCase()
不一定等于
s.toLowerCase()
。
注 2
此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。
22.1.3.29 String.prototype.toString ( )
调用该方法时,执行以下步骤:
返回 ? ThisStringValue (this
值)。
注
对于 String 对象,此方法恰好返回与 valueOf
方法相同的值。
22.1.3.30 String.prototype.toUpperCase ( )
该方法将 String 值作为 UTF-16 编码码点序列解释,如 6.1.4
中描述。
其行为与 String.prototype.toLowerCase
完全相同,只是字符串使用 Unicode 默认大小写转换的 toUppercase
算法进行映射。
注
此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。
22.1.3.31 String.prototype.toWellFormed ( )
该方法返回此对象的字符串表示,将所有不是代理对 一部分的前导代理项 和尾随代理项 替换为 U+FFFD(替换字符)。
调用该方法时,执行以下步骤:
令 O 为 ? RequireObjectCoercible (this
值)。
令 S 为 ? ToString (O )。
令 strLen 为 S 的长度。
令 k 为 0。
令 result 为空字符串。
重复,直到 k < strLen ,
令 cp 为 CodePointAt (S ,
k )。
如果 cp .[[IsUnpairedSurrogate]] 为
true ,则
将 result 设为 字符串拼接
result 和 0xFFFD(替换字符)的结果。
否则,
将 result 设为 字符串拼接
result 和 UTF16EncodeCodePoint (cp .[[CodePoint]] ) 的结果。
将 k 设为 k + cp .[[CodeUnitCount]] 。
返回 result 。
22.1.3.32 String.prototype.trim ( )
该方法将 String 值作为 UTF-16 编码码点序列解释,如 6.1.4
中描述。
调用该方法时,执行以下步骤:
令 S 为 this 值。
返回 ? TrimString (S ,
start+end )。
注
此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。
22.1.3.32.1 TrimString ( string , where
)
抽象操作 TrimString 接收参数 string (ECMAScript
语言值 )和
where (start 、end 或
start+end ),返回字符串或抛出异常。它将 string 解释为 UTF-16 编码码点序列,如
6.1.4
规定。调用时执行以下步骤:
令 str 为 ? RequireObjectCoercible (string )。
令 S 为 ? ToString (str )。
如果 where 为 start ,则
令 T 为 S 去除前导空白后的字符串值。
否则若 where 为 end ,则
令 T 为 S 去除尾随空白后的字符串值。
否则,
断言 :where 为
start+end 。
令 T 为 S 去除前导和尾随空白后的字符串值。
返回 T 。
空白的定义为 WhiteSpace 和
LineTerminator
的并集。在判断 Unicode 码点是否属于 Unicode 一般类别 “Space_Separator” (“Zs”) 时,码元序列被解释为 6.1.4 规定的
UTF-16 编码码点序列。
22.1.3.33 String.prototype.trimEnd ( )
该方法将 String 值作为 UTF-16 编码码点序列解释,如 6.1.4
中描述。
调用该方法时,执行以下步骤:
令 S 为 this 值。
返回 ? TrimString (S ,
end )。
注
此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。
22.1.3.34 String.prototype.trimStart ( )
该方法将 String 值作为 UTF-16 编码码点序列解释,如 6.1.4
中描述。
调用该方法时,执行以下步骤:
令 S 为 this 值。
返回 ? TrimString (S ,
start )。
注
此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。
22.1.3.35 String.prototype.valueOf ( )
调用该方法时,执行以下步骤:
返回 ? ThisStringValue (this
值)。
22.1.3.35.1 ThisStringValue ( value )
抽象操作 ThisStringValue 接收参数 value (ECMAScript
语言值 ),返回字符串或抛出异常。调用时执行以下步骤:
如果 value 是
String ,返回 value 。
如果 value 是对象 且 value 具有 [[StringData]] 内部槽,则
令 s 为 value .[[StringData]] 。
断言 :s 是
String 。
返回 s 。
抛出 TypeError 异常。
22.1.3.36 String.prototype [ %Symbol.iterator% ] ( )
该方法返回一个迭代器对象 ,用于遍历字符串值的每个码点,每次返回一个字符串值。
调用该方法时,执行以下步骤:
令 O 为 ? RequireObjectCoercible (this
值)。
令 s 为 ? ToString (O )。
令 closure 为新的抽象闭包 ,无参数,捕获
s ,并在被调用时执行以下步骤:
令 len 为 s 的长度。
令 position 为 0。
重复,直到 position < len ,
令 cp 为 CodePointAt (s ,
position )。
令 nextIndex 为 position + cp .[[CodeUnitCount]] 。
令 resultString 为 substring
s 从 position 到 nextIndex 。
将 position 设为 nextIndex 。
执行 ? GeneratorYield (CreateIteratorResultObject (resultString ,
false ))。
返回 undefined 。
返回 CreateIteratorFromClosure (closure ,
"%StringIteratorPrototype%" , %StringIteratorPrototype% )。
该方法的 "name" 属性值为 "[Symbol.iterator]" 。
22.1.4 String 实例的属性
String 实例是 String 特殊对象 ,并具有为此类对象规定的内部方法。String 实例继承自
String 原型对象
的属性。String 实例还具有 [[StringData]] 内部槽。[[StringData]] 内部槽是该 String 对象所表示的 String 值。
String 实例具有 "length" 属性,以及一组具有 整数索引 名称的可枚举属性。
22.1.4.1 length
该 String 对象所表示的 String 值中的元素数量。
一旦 String 对象被初始化,此属性不可更改。它具有属性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
22.1.5 String 迭代器对象
String 迭代器 是表示对某个特定 String 实例对象的某次特定迭代的对象。String 迭代器对象没有命名的构造函数 。而是通过调用 String
实例对象的某些方法创建 String 迭代器对象。
22.1.5.1 %StringIteratorPrototype% 对象
%StringIteratorPrototype% 对象:
22.1.5.1.1 %StringIteratorPrototype%.next ( )
返回 ? GeneratorResume (this
值, empty ,
"%StringIteratorPrototype%" )。
22.1.5.1.2 %StringIteratorPrototype% [ %Symbol.toStringTag%
]
%Symbol.toStringTag% 属性的初始值为字符串值
"String Iterator" 。
该属性具有属性 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] : true }。
22.2 RegExp(正则表达式)对象
RegExp 对象包含一个正则表达式和相关的标志(flags)。
注
正则表达式的形式和功能模仿了 Perl 5 编程语言中的正则表达式机制。
22.2.1 模式(Patterns)
RegExp 构造函数
对输入模式字符串应用以下语法。如果该语法无法将字符串解释为 Pattern 的展开,则会发生错误。
语法
Pattern [UnicodeMode, UnicodeSetsMode,
NamedCaptureGroups] ::
Disjunction [?UnicodeMode,
?UnicodeSetsMode, ?NamedCaptureGroups]
Disjunction [UnicodeMode,
UnicodeSetsMode, NamedCaptureGroups]
::
Alternative [?UnicodeMode,
?UnicodeSetsMode, ?NamedCaptureGroups]
Alternative [?UnicodeMode,
?UnicodeSetsMode, ?NamedCaptureGroups]
|
Disjunction [?UnicodeMode,
?UnicodeSetsMode, ?NamedCaptureGroups]
Alternative [UnicodeMode,
UnicodeSetsMode, NamedCaptureGroups]
::
[empty]
Alternative [?UnicodeMode,
?UnicodeSetsMode, ?NamedCaptureGroups]
Term [?UnicodeMode, ?UnicodeSetsMode,
?NamedCaptureGroups]
Term [UnicodeMode, UnicodeSetsMode,
NamedCaptureGroups] ::
Assertion [?UnicodeMode,
?UnicodeSetsMode, ?NamedCaptureGroups]
Atom [?UnicodeMode, ?UnicodeSetsMode,
?NamedCaptureGroups]
Atom [?UnicodeMode, ?UnicodeSetsMode,
?NamedCaptureGroups]
Quantifier
Assertion [UnicodeMode,
UnicodeSetsMode, NamedCaptureGroups]
::
^
$
\b
\B
(?=
Disjunction [?UnicodeMode,
?UnicodeSetsMode, ?NamedCaptureGroups]
)
(?!
Disjunction [?UnicodeMode,
?UnicodeSetsMode, ?NamedCaptureGroups]
)
(?<=
Disjunction [?UnicodeMode,
?UnicodeSetsMode, ?NamedCaptureGroups]
)
(?<!
Disjunction [?UnicodeMode,
?UnicodeSetsMode, ?NamedCaptureGroups]
)
Quantifier ::
QuantifierPrefix
QuantifierPrefix
?
QuantifierPrefix ::
*
+
?
{
DecimalDigits [~Sep]
}
{
DecimalDigits [~Sep]
,}
{
DecimalDigits [~Sep]
,
DecimalDigits [~Sep]
}
Atom [UnicodeMode, UnicodeSetsMode,
NamedCaptureGroups] ::
PatternCharacter
.
\
AtomEscape [?UnicodeMode,
?NamedCaptureGroups]
CharacterClass [?UnicodeMode,
?UnicodeSetsMode]
(
GroupSpecifier [?UnicodeMode] opt
Disjunction [?UnicodeMode,
?UnicodeSetsMode, ?NamedCaptureGroups]
)
(?
RegularExpressionModifiers
:
Disjunction [?UnicodeMode,
?UnicodeSetsMode, ?NamedCaptureGroups]
)
(?
RegularExpressionModifiers
-
RegularExpressionModifiers
:
Disjunction [?UnicodeMode,
?UnicodeSetsMode, ?NamedCaptureGroups]
)
RegularExpressionModifiers
::
[empty]
RegularExpressionModifiers
RegularExpressionModifier
RegularExpressionModifier
:: one of i
m s
SyntaxCharacter ::
one of ^ $ \
. * + ? (
) [ ] { }
|
PatternCharacter ::
SourceCharacter
but not SyntaxCharacter
AtomEscape [UnicodeMode,
NamedCaptureGroups] ::
DecimalEscape
CharacterClassEscape [?UnicodeMode]
CharacterEscape [?UnicodeMode]
[+NamedCaptureGroups]
k
GroupName [?UnicodeMode]
CharacterEscape [UnicodeMode]
::
ControlEscape
c
AsciiLetter
0
[lookahead ∉ DecimalDigit ]
HexEscapeSequence
RegExpUnicodeEscapeSequence [?UnicodeMode]
IdentityEscape [?UnicodeMode]
ControlEscape ::
one of f n r
t v
GroupSpecifier [UnicodeMode]
::
?
GroupName [?UnicodeMode]
GroupName [UnicodeMode]
::
<
RegExpIdentifierName [?UnicodeMode]
>
RegExpIdentifierName [UnicodeMode]
::
RegExpIdentifierStart [?UnicodeMode]
RegExpIdentifierName [?UnicodeMode]
RegExpIdentifierPart [?UnicodeMode]
RegExpIdentifierStart [UnicodeMode]
::
IdentifierStartChar
\
RegExpUnicodeEscapeSequence [+UnicodeMode]
[~UnicodeMode]
UnicodeLeadSurrogate
UnicodeTrailSurrogate
RegExpIdentifierPart [UnicodeMode]
::
IdentifierPartChar
\
RegExpUnicodeEscapeSequence [+UnicodeMode]
[~UnicodeMode]
UnicodeLeadSurrogate
UnicodeTrailSurrogate
RegExpUnicodeEscapeSequence [UnicodeMode]
:: [+UnicodeMode]
u
HexLeadSurrogate
\u
HexTrailSurrogate
[+UnicodeMode]
u
HexLeadSurrogate
[+UnicodeMode]
u
HexTrailSurrogate
[+UnicodeMode]
u
HexNonSurrogate
[~UnicodeMode]
u
Hex4Digits
[+UnicodeMode]
u{
CodePoint
}
UnicodeLeadSurrogate
::
any Unicode code point in the inclusive interval from U+D800 to
U+DBFF
UnicodeTrailSurrogate
::
any Unicode code point in the inclusive interval from U+DC00 to
U+DFFF
每个 \u
HexTrailSurrogate ,其关联的 u
HexLeadSurrogate
存在歧义时,应将其关联到最近且本来没有对应 \u
HexTrailSurrogate 的 u
HexLeadSurrogate 。
HexLeadSurrogate ::
Hex4Digits
but only if the MV of Hex4Digits is in the inclusive interval from 0xD800 to
0xDBFF
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
UnicodePropertyNameCharacters opt
UnicodePropertyValue
::
UnicodePropertyValueCharacters
LoneUnicodePropertyNameOrValue
::
UnicodePropertyValueCharacters
UnicodePropertyValueCharacters
::
UnicodePropertyValueCharacter
UnicodePropertyValueCharacters opt
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
ClassUnion opt
ClassSetOperand
ClassUnion opt
ClassIntersection
::
ClassSetOperand
&&
[lookahead ≠ & ]
ClassSetOperand
ClassIntersection
&&
[lookahead ≠ & ]
ClassSetOperand
ClassSubtraction ::
ClassSetOperand
--
ClassSetOperand
ClassSubtraction
--
ClassSetOperand
ClassSetRange ::
ClassSetCharacter
-
ClassSetCharacter
ClassSetOperand ::
NestedClass
ClassStringDisjunction
ClassSetCharacter
NestedClass ::
[
[lookahead ≠ ^ ]
ClassContents [+UnicodeMode,
+UnicodeSetsMode]
]
[^
ClassContents [+UnicodeMode,
+UnicodeSetsMode]
]
\
CharacterClassEscape [+UnicodeMode]
注 1
ClassStringDisjunction
::
\q{
ClassStringDisjunctionContents
}
ClassStringDisjunctionContents
::
ClassString
ClassString
|
ClassStringDisjunctionContents
ClassString ::
[empty]
NonEmptyClassString
NonEmptyClassString
::
ClassSetCharacter
NonEmptyClassString opt
ClassSetCharacter
::
[lookahead ∉ ClassSetReservedDoublePunctuator ]
SourceCharacter
but not ClassSetSyntaxCharacter
\
CharacterEscape [+UnicodeMode]
\
ClassSetReservedPunctuator
\b
ClassSetReservedDoublePunctuator
:: one of &&
!! ## $$ %%
** ++ ,, ..
:: ;; << ==
>> ?? @@ ^^
`` ~~
ClassSetSyntaxCharacter
:: one of (
) [ ] { }
/ - \ |
ClassSetReservedPunctuator
:: one of &
- ! # % ,
: ; < =
> @ ` ~
注 2
本节中的多项产生式在 B.1.2 节中给出了替代定义。
22.2.1.1 静态语义:早期错误(Static Semantics: Early Errors)
注
Pattern :: Disjunction
QuantifierPrefix
::
{
DecimalDigits
,
DecimalDigits
}
Atom ::
(?
RegularExpressionModifiers
:
Disjunction
)
Atom ::
(?
RegularExpressionModifiers
-
RegularExpressionModifiers
:
Disjunction
)
AtomEscape ::
k
GroupName
AtomEscape ::
DecimalEscape
NonemptyClassRanges
::
ClassAtom
-
ClassAtom
ClassContents
NonemptyClassRangesNoDash
::
ClassAtomNoDash
-
ClassAtom
ClassContents
RegExpIdentifierStart
::
\
RegExpUnicodeEscapeSequence
RegExpIdentifierStart
::
UnicodeLeadSurrogate
UnicodeTrailSurrogate
RegExpIdentifierPart
::
\
RegExpUnicodeEscapeSequence
RegExpIdentifierPart
::
UnicodeLeadSurrogate
UnicodeTrailSurrogate
UnicodePropertyValueExpression
::
UnicodePropertyName
=
UnicodePropertyValue
UnicodePropertyValueExpression
::
LoneUnicodePropertyNameOrValue
CharacterClassEscape
::
P{
UnicodePropertyValueExpression
}
CharacterClass
::
[^
ClassContents
]
NestedClass
::
[^
ClassContents
]
ClassSetRange
::
ClassSetCharacter
-
ClassSetCharacter
22.2.1.2 静态语义:CountLeftCapturingParensWithin (node )
抽象操作 CountLeftCapturingParensWithin 接收参数 node (一个 解析节点 ),返回一个非负整数 。它返回 node 中左捕获括号的数量。左捕获括号 是任何与以下产生式的 (
终结符匹配的 (
模式字符:
Atom ::
(
GroupSpecifier opt
Disjunction
)
注
调用时,执行以下步骤:
断言 :node 是 正则表达式模式语法 中的某个产生式的实例。
返回 node 内部所包含的以下解析节点的数量:
Atom ::
(
GroupSpecifier opt
Disjunction
)
解析节点
22.2.1.3 静态语义:CountLeftCapturingParensBefore (node )
抽象操作 CountLeftCapturingParensBefore 接收参数 node (一个 解析节点 ),返回一个非负整数 。它返回封闭模式中出现在 node
左侧的左捕获括号 的数量。
注
调用时,执行以下步骤:
断言 :node 是 正则表达式模式语法 中的某个产生式的实例。
令 pattern 为包含 node 的 Pattern 。
返回 pattern 内部,出现在 node 之前或包含 node 的以下解析节点的数量:
Atom ::
(
GroupSpecifier opt
Disjunction
)
解析节点
22.2.1.4 静态语义:MightBothParticipate (x , y )
抽象操作 MightBothParticipate 接收参数 x (一个 解析节点 )和 y (一个
解析节点 ),返回布尔值。调用时,执行以下步骤:
断言 :x 和 y 拥有同一个封闭的
Pattern 。
如果该封闭 Pattern 包含如下
Disjunction
::
Alternative
|
Disjunction
解析节点 ,使得 x 包含于
Alternative 中且
y 包含于派生的 Disjunction 中,或者 x 包含于派生的
Disjunction 中且
y 包含于 Alternative 中,则返回
false 。
返回 true 。
22.2.1.5 静态语义:CapturingGroupNumber
语法定向操作
CapturingGroupNumber 无参数,返回正整数 。
注
在以下产生式中分段定义:
DecimalEscape ::
NonZeroDigit
返回 NonZeroDigit 的
MV。
DecimalEscape ::
NonZeroDigit
DecimalDigits
令 n 为 DecimalDigits 中码点的数量。
返回 (NonZeroDigit 的
MV × 10n 加 DecimalDigits 的 MV)。
“NonZeroDigit 的 MV” 和
“DecimalDigits 的 MV” 的定义见
12.9.3 。
22.2.1.6 静态语义:IsCharacterClass
语法定向操作
IsCharacterClass 无参数,返回布尔值。
注
在以下产生式中分段定义:
ClassAtom ::
-
ClassAtomNoDash
::
SourceCharacter
但不是 \ 、] 或 - 之一
ClassEscape ::
b
-
CharacterEscape
返回 false 。
ClassEscape ::
CharacterClassEscape
返回 true 。
22.2.1.7 静态语义:CharacterValue
语法定向操作
CharacterValue 无参数,返回非负整数 。
注 1
在以下产生式中分段定义:
ClassAtom :: -
返回 U+002D(连字符 HYPHEN-MINUS)的数值。
ClassAtomNoDash
:: SourceCharacter 但不是
\ 、] 或 - 之一
令 ch 为 SourceCharacter 匹配的码点。
返回 ch 的数值。
ClassEscape ::
b
返回 U+0008(退格 BACKSPACE)的数值。
ClassEscape ::
返回 U+002D(连字符 HYPHEN-MINUS)的数值。
CharacterEscape
:: ControlEscape
按照 表 67 返回数值。
表 67: ControlEscape 码点数值
ControlEscape
数值
码点
Unicode 名称
符号
t
9
U+0009
CHARACTER TABULATION
<HT>
n
10
U+000A
LINE FEED (LF)
<LF>
v
11
U+000B
LINE TABULATION
<VT>
f
12
U+000C
FORM FEED (FF)
<FF>
r
13
U+000D
CARRIAGE RETURN (CR)
<CR>
CharacterEscape
::
c
AsciiLetter
令 ch 为 AsciiLetter 匹配的码点。
令 i 为 ch 的数值。
返回 i 除以 32 的余数。
CharacterEscape
::
0
[lookahead ∉ DecimalDigit ]
返回 U+0000(NULL)的数值。
注 2
\0
表示 <NUL> 字符,且不能后跟十进制数字。
CharacterEscape
:: HexEscapeSequence
返回 HexEscapeSequence 的 MV。
RegExpUnicodeEscapeSequence
::
u
HexLeadSurrogate
\u
HexTrailSurrogate
令 lead 为 CharacterValue
of HexLeadSurrogate 。
令 trail 为 CharacterValue
of HexTrailSurrogate 。
令 cp 为 UTF16SurrogatePairToCodePoint (lead ,
trail )。
返回 cp 的数值。
RegExpUnicodeEscapeSequence
::
u
Hex4Digits
返回 Hex4Digits 的 MV。
RegExpUnicodeEscapeSequence
::
u{
CodePoint
}
返回 CodePoint 的 MV。
HexLeadSurrogate
:: Hex4Digits
HexTrailSurrogate
:: Hex4Digits
HexNonSurrogate
:: Hex4Digits
返回 Hex4Digits 的 MV。
CharacterEscape
:: IdentityEscape
令 ch 为 IdentityEscape 匹配的码点。
返回 ch 的数值。
ClassSetCharacter
:: SourceCharacter 但不是
ClassSetSyntaxCharacter
令 ch 为 SourceCharacter 匹配的码点。
返回 ch 的数值。
ClassSetCharacter
::
\
ClassSetReservedPunctuator
令 ch 为 ClassSetReservedPunctuator
匹配的码点。
返回 ch 的数值。
ClassSetCharacter
:: \b
返回 U+0008(退格 BACKSPACE)的数值。
22.2.1.8 静态语义:MayContainStrings
语法定向操作
MayContainStrings 无参数,返回布尔值。它在以下产生式中分段定义:
CharacterClassEscape
::
d
D
s
S
w
W
P{
UnicodePropertyValueExpression
}
UnicodePropertyValueExpression
::
UnicodePropertyName
=
UnicodePropertyValue
NestedClass
::
[^
ClassContents
]
ClassContents
::
[empty]
NonemptyClassRanges
ClassSetOperand
::
ClassSetCharacter
返回 false 。
UnicodePropertyValueExpression
::
LoneUnicodePropertyNameOrValue
如果
source text
matched by
LoneUnicodePropertyNameOrValue
是 表
71 “属性名”列中列出的字符串的二进制属性,则返回 true 。
返回 false 。
ClassUnion
::
ClassSetRange
ClassUnion opt
如果 ClassUnion 存在,返回
MayContainStrings
of ClassUnion 。
返回 false 。
ClassUnion
::
ClassSetOperand
ClassUnion opt
如果 MayContainStrings
of ClassSetOperand 为
true ,返回 true 。
如果 ClassUnion 存在,返回
MayContainStrings
of ClassUnion 。
返回 false 。
ClassIntersection
::
ClassSetOperand
&&
ClassSetOperand
如果 MayContainStrings
of 第一个 ClassSetOperand 为
false ,返回 false 。
如果 MayContainStrings
of 第二个 ClassSetOperand 为
false ,返回 false 。
返回 true 。
ClassIntersection
::
ClassIntersection
&&
ClassSetOperand
如果 MayContainStrings
of ClassIntersection 为
false ,返回 false 。
如果 MayContainStrings
of ClassSetOperand 为
false ,返回 false 。
返回 true 。
ClassSubtraction
::
ClassSetOperand
--
ClassSetOperand
返回第一个 MayContainStrings
of ClassSetOperand 。
ClassSubtraction
::
ClassSubtraction
--
ClassSetOperand
返回 MayContainStrings
of ClassSubtraction 。
ClassStringDisjunctionContents
::
ClassString
|
ClassStringDisjunctionContents
如果 MayContainStrings
of ClassString 为
true ,返回 true 。
返回 MayContainStrings
of ClassStringDisjunctionContents 。
ClassString
::
[empty]
返回 true 。
ClassString
::
NonEmptyClassString
返回 MayContainStrings
of NonEmptyClassString 。
NonEmptyClassString
::
ClassSetCharacter
NonEmptyClassString opt
如果 NonEmptyClassString 存在,返回
true 。
返回 false 。
22.2.1.9 静态语义:GroupSpecifiersThatMatch
(thisGroupName )
抽象操作 GroupSpecifiersThatMatch 接收参数 thisGroupName (一个 GroupName 解析节点 ),返回 List 类型的 GroupSpecifier 解析节点 。调用时,执行如下步骤:
令 name 为 CapturingGroupName
of thisGroupName 。
令 pattern 为包含 thisGroupName 的 Pattern 。
令 result 为一个新的空 List 。
对于 pattern 包含的每个 GroupSpecifier gs ,执行:
如果 gs 的 CapturingGroupName
等于 name ,则:
将 gs 添加至 result 。
返回 result 。
22.2.1.10 静态语义:CapturingGroupName
语法定向操作
CapturingGroupName 无参数,返回字符串。它在以下产生式中分段定义:
GroupName ::
<
RegExpIdentifierName
>
令 idTextUnescaped 为 RegExpIdentifierCodePoints
of RegExpIdentifierName 。
返回 CodePointsToString (idTextUnescaped )。
22.2.1.11 静态语义:RegExpIdentifierCodePoints
语法定向操作
RegExpIdentifierCodePoints 无参数,返回码点 List 。它在以下产生式中分段定义:
RegExpIdentifierName
::
RegExpIdentifierStart
令 cp 为 RegExpIdentifierCodePoint
of RegExpIdentifierStart 。
返回 « cp »。
RegExpIdentifierName
::
RegExpIdentifierName
RegExpIdentifierPart
令 cps 为派生的 RegExpIdentifierCodePoints
of RegExpIdentifierName 。
令 cp 为 RegExpIdentifierCodePoint
of RegExpIdentifierPart 。
返回 list-concatenation of
cps 和 « cp »。
22.2.1.12 静态语义:RegExpIdentifierCodePoint
语法定向操作
RegExpIdentifierCodePoint 无参数,返回码点。它在以下产生式中分段定义:
RegExpIdentifierStart
::
IdentifierStartChar
返回 IdentifierStartChar 匹配的码点。
RegExpIdentifierPart
::
IdentifierPartChar
返回 IdentifierPartChar 匹配的码点。
RegExpIdentifierStart
::
\
RegExpUnicodeEscapeSequence
RegExpIdentifierPart
::
\
RegExpUnicodeEscapeSequence
返回数值为 CharacterValue
of RegExpUnicodeEscapeSequence
的码点。
RegExpIdentifierStart
::
UnicodeLeadSurrogate
UnicodeTrailSurrogate
RegExpIdentifierPart
::
UnicodeLeadSurrogate
UnicodeTrailSurrogate
令 lead 为 UnicodeLeadSurrogate
匹配的码点的数值所对应的码元。
令 trail 为 UnicodeTrailSurrogate
匹配的码点的数值所对应的码元。
返回 UTF16SurrogatePairToCodePoint (lead ,
trail )。
22.2.2 模式语义(Pattern Semantics)
正则表达式模式会按照下述过程被转换为一个 抽象闭包(Abstract
Closure) 。实现可以使用比下文所列更高效的算法,只要结果一致。该 抽象闭包 用作 RegExp 对象的 [[RegExpMatcher]] 内部槽的值。
如果一个 Pattern 的关联标志既不包含
u
也不包含 v
,则它是 BMP 模式。否则,它是 Unicode 模式。BMP 模式会针对被解释为由处于基本多文种平面(BMP)范围内的
Unicode 码点组成的 16 位值序列的字符串进行匹配。Unicode 模式则针对被解释为用 UTF-16 编码的 Unicode 码点序列的字符串进行匹配。在描述 BMP
模式行为时,“character” 表示单个 16 位的 Unicode BMP 码点。在描述 Unicode 模式行为时,“character” 表示一个 UTF-16
编码的码点(6.1.4 )。无论哪种情况,“character
value” 都指对应非编码码点的数值。
Pattern 的语法和语义定义为其源文本为一个 List ,其中每个元素为 SourceCharacter ,对应一个 Unicode
码点。如果 BMP 模式包含了非 BMP 的 SourceCharacter ,则整个模式会被用 UTF-16
编码,并将该编码的各个码元作为 List 的元素。
注
例如,假设一个模式在源文本中表示为单个非 BMP 字符 U+1D11E(MUSICAL SYMBOL G CLEF)。作为 Unicode 模式解释时,它是一个仅包含该码点
U+1D11E 的元素(字符)List 。然而,作为 BMP
模式解释时,它会首先被 UTF-16 编码,得到两个元素的 List ,其码元分别为 0xD834
和 0xDD1E。
模式会以 ECMAScript 字符串值的形式传递给 RegExp 构造函数 ,其中非 BMP 字符已经用 UTF-16 编码。例如,该 MUSICAL
SYMBOL G CLEF 单字符模式,表达为字符串值时,是长度为 2 的字符串,其元素为 0xD834 和 0xDD1E 码元。因此,若作为包含两个模式字符的 BMP
模式处理,不需要再对字符串做转换;但若作为 Unicode 模式处理,则需用 UTF16SurrogatePairToCodePoint
得到仅含一个模式字符(码点 U+1D11E)的 List 。
实现不一定真的需要进行这些 UTF-16 的转换,但本规范要求,模式匹配的语义要如同进行了这些转换一样。
22.2.2.1 符号说明(Notation)
下述描述使用以下内部数据结构:
22.2.2.1.1 RegExp 记录(RegExp Records)
RegExp Record 是一个 Record ,用于存储 RegExp
在编译及可能的匹配期间需要的信息。
它包含如下字段:
表 68: RegExp Record 字段
字段名
值
含义
[[IgnoreCase]]
布尔值
指示 RegExp 标志中是否出现 "i"
[[Multiline]]
布尔值
指示 RegExp 标志中是否出现 "m"
[[DotAll]]
布尔值
指示 RegExp 标志中是否出现 "s"
[[Unicode]]
布尔值
指示 RegExp 标志中是否出现 "u"
[[UnicodeSets]]
布尔值
指示 RegExp 标志中是否出现 "v"
[[CapturingGroupsCount]]
非负整数
RegExp 模式中的 左捕获括号
的数量
22.2.2.2 运行时语义:CompilePattern
语法定向操作
CompilePattern 接收参数 rer (一个 RegExp Record ),返回一个
抽象闭包(Abstract Closure) ,该闭包接收一个字符
List 和一个非负 整数 ,返回一个 MatchState 或
failure 。它在以下产生式中分段定义:
Pattern ::
Disjunction
令 m 为 CompileSubpattern of Disjunction ,参数为
rer 和 forward 。
返回一个新 抽象闭包 ,参数为 (Input ,
index ),捕获 rer 和 m ,调用时执行以下步骤:
断言 :Input 为字符 List 。
断言 :0 ≤ index ≤
Input 的元素数量。
令 c 为一个新 MatcherContinuation ,参数
(y ),不捕获任何内容,调用时:
断言 :y 为 MatchState 。
返回 y 。
令 cap 为 rer .[[CapturingGroupsCount]] 个
undefined 的 List ,索引从
1 到 rer .[[CapturingGroupsCount]] 。
令 x 为 MatchState { [[Input]] : Input , [[EndIndex]] : index , [[Captures]] : cap }。
返回 m (x , c )。
注
Pattern 会被编译为 抽象闭包(Abstract Closure) 。RegExpBuiltinExec 可以将该过程应用于字符
List
及其偏移量,以判断模式是否会正好从该偏移处开始匹配,并在匹配时获得捕获括号的值。本节算法允许编译过程中抛出
SyntaxError ;但一旦编译成功,匹配时除非发生实现相关异常(如内存溢出)不会抛出异常。
22.2.2.3 运行时语义:CompileSubpattern
语法定向操作
CompileSubpattern 接收参数 rer (一个 RegExp Record )和
direction (forward 或 backward ),返回一个
Matcher 。
注 1
在以下产生式中分段定义:
Disjunction ::
Alternative
|
Disjunction
令 m1 为 CompileSubpattern of Alternative ,参数为
rer 和 direction 。
令 m2 为 CompileSubpattern of Disjunction ,参数为
rer 和 direction 。
返回 MatchTwoAlternatives (m1 ,
m2 )。
注 2
|
正则表达式操作符分隔两个备选项。模式首先尝试匹配左侧 Alternative (后接正则表达式剩余部分);如果失败,则尝试匹配右侧
Disjunction (后接剩余部分)。如果左侧 Alternative 、右侧 Disjunction
和剩余部分都有选择点,则会先穷尽剩余部分的所有选择,再移动到右侧。若左侧所有选择用尽,则会尝试右侧。被 |
跳过的部分中的捕获括号,其值为
undefined 而非字符串。例如:
/a|ab/.exec("abc")
返回结果为 "a" 而非 "ab" 。再例如:
/((a)|(ab))((c)|(bc))/.exec("abc")
返回数组:
["abc", "a", "a", undefined, "bc", undefined, "bc"]
而不是:
["abc", "ab", undefined, "ab", "c", "c", undefined]
两个备选项的尝试顺序与 direction 的值无关。
Alternative ::
[empty]
返回 EmptyMatcher ()。
Alternative ::
Alternative
Term
令 m1 为 CompileSubpattern of Alternative ,参数为
rer 和 direction 。
令 m2 为 CompileSubpattern of Term ,参数为 rer 和
direction 。
返回 MatchSequence (m1 ,
m2 , direction )。
注 3
连续的 Term 会尝试同时匹配
Input 的连续部分。当 direction 为 forward
时,若左、右和剩余部分都有选择点,则会先穷尽剩余、再穷尽右侧、最后再穷尽左侧的选择。当 direction 为
backward 时,左、右的顺序交换。
Term ::
Assertion
返回 CompileAssertion of Assertion ,参数为
rer 。
注 4
所得 Matcher 与 direction 无关。
Term ::
Atom
返回 CompileAtom of Atom ,参数为 rer 和
direction 。
Term ::
Atom
Quantifier
令 m 为 CompileAtom of Atom ,参数为 rer 和
direction 。
令 q 为 CompileQuantifier of Quantifier 。
断言 :q .[[Min]] ≤ q .[[Max]] 。
令 parenIndex 为 CountLeftCapturingParensBefore (Term )。
令 parenCount 为 CountLeftCapturingParensWithin (Atom )。
返回一个新 Matcher ,参数为 (x ,
c ),捕获 m 、q 、parenIndex 和
parenCount ,调用时:
断言 :x 为 MatchState 。
断言 :c 为 MatcherContinuation 。
返回 RepeatMatcher (m ,
q .[[Min]] , q .[[Max]] , q .[[Greedy]] , x , c ,
parenIndex , parenCount )。
22.2.2.3.1 RepeatMatcher (m , min ,
max , greedy , x , c , parenIndex ,
parenCount )
抽象操作 RepeatMatcher 接收参数 m (一个 Matcher )、min (非负
整数 )、max (非负 整数 或
+∞)、greedy (布尔值)、x (MatchState )、c (MatcherContinuation )、parenIndex (非负
整数 )、parenCount (非负 整数 ),返回一个 MatchState 或
failure 。调用时执行以下步骤:
如果 max = 0,返回 c (x )。
令 d 为一个新 MatcherContinuation ,参数
(y ),捕获
m 、min 、max 、greedy 、x 、c 、parenIndex 、parenCount ,调用时:
断言 :y 为 MatchState 。
如果 min = 0 且 y .[[EndIndex]] = x .[[EndIndex]] ,返回 failure 。
如果 min = 0,令 min2 为 0;否则,令 min2 为
min - 1。
如果 max = +∞,令 max2 为 +∞;否则,令 max2 为
max - 1。
返回 RepeatMatcher (m ,
min2 , max2 , greedy , y ,
c , parenIndex , parenCount )。
令 cap 为 x .[[Captures]] 的副本。
对于 整数 k ,在 闭区间 parenIndex + 1
到 parenIndex + parenCount ,令 cap [k ] =
undefined 。
令 Input 为 x .[[Input]] 。
令 e 为 x .[[EndIndex]] 。
令 xr 为 MatchState { [[Input]] : Input , [[EndIndex]] : e , [[Captures]] : cap }。
如果 min ≠ 0,返回 m (xr , d )。
如果 greedy 为 false ,则:
令 z 为 c (x )。
如果 z 不为 failure ,返回 z 。
返回 m (xr , d )。
令 z 为 m (xr , d )。
如果 z 不为 failure ,返回 z 。
返回 c (x )。
注 1
一个 Atom 后跟 Quantifier 时,会根据
Quantifier
指定的次数重复。Quantifier
可以是非贪婪的(尽量少匹配)或贪婪的(尽量多匹配)。重复的是 Atom 的模式本身,不同重复可匹配不同的输入子串。
注 2
如果 Atom
和剩余部分都有选择点,会先尽量多(或少,若非贪婪)匹配 Atom ,再穷尽剩余选择,然后再回溯到上一次重复。可以用这种选择点顺序写出求最大公约数的正则表达式。
注 3
RepeatMatcher 的 步骤
4 每次重复时都会清除 Atom 的捕获结果。
注 4
RepeatMatcher 的 2.b 指出:当已满足最小重复次数时,若
Atom
匹配空字符串,则不再继续重复,防止无限循环。
22.2.2.3.2 EmptyMatcher ( )
抽象操作 EmptyMatcher 无参数,返回一个 Matcher 。调用时执行以下步骤:
返回一个新 Matcher ,参数 (x ,
c ),不捕获任何内容,调用时:
断言 :x 为 MatchState 。
断言 :c 为 MatcherContinuation 。
返回 c (x )。
22.2.2.3.3 MatchTwoAlternatives (m1 ,
m2 )
抽象操作 MatchTwoAlternatives 接收参数 m1 (Matcher )和
m2 (Matcher ),返回一个 Matcher 。调用时执行以下步骤:
返回一个新 Matcher ,参数 (x ,
c ),捕获 m1 和 m2 ,调用时:
断言 :x 为 MatchState 。
断言 :c 为 MatcherContinuation 。
令 r 为 m1 (x , c )。
若 r 非 failure ,返回 r 。
返回 m2 (x , c )。
22.2.2.3.4 MatchSequence (m1 , m2 ,
direction )
抽象操作 MatchSequence 接收参数 m1 (Matcher )、m2 (Matcher )、direction (forward
或 backward ),返回一个 Matcher 。调用时执行以下步骤:
如果 direction 为 forward ,则:
返回一个新 Matcher ,参数 (x ,
c ),捕获 m1 和 m2 ,调用时:
断言 :x 为 MatchState 。
断言 :c 为 MatcherContinuation 。
令 d 为一个新 MatcherContinuation ,参数
(y ),捕获 c 和 m2 ,调用时:
断言 :y 为
MatchState 。
返回 m2 (y , c )。
返回 m1 (x , d )。
否则:
断言 :direction 为
backward 。
返回一个新 Matcher ,参数 (x ,
c ),捕获 m1 和 m2 ,调用时:
断言 :x 为 MatchState 。
断言 :c 为 MatcherContinuation 。
令 d 为一个新 MatcherContinuation ,参数
(y ),捕获 c 和 m1 ,调用时:
断言 :y 为
MatchState 。
返回 m1 (y , c )。
返回 m2 (x , d )。
22.2.2.4 运行时语义:CompileAssertion
语法定向操作
CompileAssertion 接收参数 rer (RegExp Record ),返回一个 Matcher 。
注 1
在以下产生式中分段定义:
Assertion :: ^
返回一个新 Matcher ,参数 (x ,
c ),捕获 rer ,调用时:
断言 :x 为 MatchState 。
断言 :c 为 MatcherContinuation 。
令 Input = x .[[Input]] 。
令 e = x .[[EndIndex]] 。
如果 e = 0,或 rer .[[Multiline]]
为 true 且 Input [e - 1] 匹配 LineTerminator ,则:
返回 c (x )。
返回 failure 。
注 2
即使正则表达式使用 y
标志,^
也只会在 Input 开头或(若
rer .[[Multiline]] 为
true )行首匹配。
Assertion :: $
返回一个新 Matcher ,参数 (x ,
c ),捕获 rer ,调用时:
断言 :x 为 MatchState 。
断言 :c 为 MatcherContinuation 。
令 Input = x .[[Input]] 。
令 e = x .[[EndIndex]] 。
令 InputLength = Input 的元素数量。
如果 e = InputLength ,或 rer .[[Multiline]] 为 true 且
Input [e ] 匹配 LineTerminator ,则:
返回 c (x )。
返回 failure 。
Assertion :: \b
返回一个新 Matcher ,参数 (x ,
c ),捕获 rer ,调用时:
断言 :x 为 MatchState 。
断言 :c 为 MatcherContinuation 。
令 Input = x .[[Input]] 。
令 e = x .[[EndIndex]] 。
令 a = IsWordChar (rer ,
Input , e - 1)。
令 b = IsWordChar (rer ,
Input , e )。
如果 a 为 true 且 b 为
false ,或 a 为 false 且
b 为 true ,返回 c (x )。
返回 failure 。
Assertion :: \B
返回一个新 Matcher ,参数 (x ,
c ),捕获 rer ,调用时:
断言 :x 为 MatchState 。
断言 :c 为 MatcherContinuation 。
令 Input = x .[[Input]] 。
令 e = x .[[EndIndex]] 。
令 a = IsWordChar (rer ,
Input , e - 1)。
令 b = IsWordChar (rer ,
Input , e )。
如果 a 和 b 同为 true 或同为
false ,返回 c (x )。
返回 failure 。
Assertion ::
(?=
Disjunction
)
令 m 为 CompileSubpattern of Disjunction ,参数为
rer 和 forward 。
返回一个新 Matcher ,参数 (x ,
c ),捕获 m ,调用时:
断言 :x 为 MatchState 。
断言 :c 为 MatcherContinuation 。
令 d 为一个新 MatcherContinuation ,参数
(y ),不捕获内容,调用时:
断言 :y 为 MatchState 。
返回 y 。
令 r 为 m (x , d )。
若 r 为 failure ,返回
failure 。
断言 :r 为 MatchState 。
令 cap = r .[[Captures]] 。
令 Input = x .[[Input]] 。
令 xe = x .[[EndIndex]] 。
令 z 为 MatchState { [[Input]] : Input , [[EndIndex]] : xe , [[Captures]] : cap }。
返回 c (z )。
注 3
形式 (?=
Disjunction )
表示零宽度正向先行断言。其内部模式需在当前位置匹配成功,但当前位置不会推进。lookahead 内部无回溯。
Assertion ::
(?!
Disjunction
)
令 m 为 CompileSubpattern of Disjunction ,参数为
rer 和 forward 。
返回一个新 Matcher ,参数 (x ,
c ),捕获 m ,调用时:
断言 :x 为 MatchState 。
断言 :c 为 MatcherContinuation 。
令 d 为一个新 MatcherContinuation ,参数
(y ),不捕获内容,调用时:
断言 :y 为 MatchState 。
返回 y 。
令 r 为 m (x , d )。
若 r 非 failure ,返回
failure 。
返回 c (x )。
注 4
形式 (?!
Disjunction )
表示零宽度负向先行断言。其内部模式需在当前位置匹配失败。
Assertion ::
(?<=
Disjunction
)
令 m 为 CompileSubpattern of Disjunction ,参数为
rer 和 backward 。
返回一个新 Matcher ,参数 (x ,
c ),捕获 m ,调用时:
断言 :x 为 MatchState 。
断言 :c 为 MatcherContinuation 。
令 d 为一个新 MatcherContinuation ,参数
(y ),不捕获内容,调用时:
断言 :y 为 MatchState 。
返回 y 。
令 r 为 m (x , d )。
若 r 为 failure ,返回
failure 。
断言 :r 为 MatchState 。
令 cap = r .[[Captures]] 。
令 Input = x .[[Input]] 。
令 xe = x .[[EndIndex]] 。
令 z 为 MatchState { [[Input]] : Input , [[EndIndex]] : xe , [[Captures]] : cap }。
返回 c (z )。
Assertion ::
(?<!
Disjunction
)
令 m 为 CompileSubpattern of Disjunction ,参数为
rer 和 backward 。
返回一个新 Matcher ,参数 (x ,
c ),捕获 m ,调用时:
断言 :x 为 MatchState 。
断言 :c 为 MatcherContinuation 。
令 d 为一个新 MatcherContinuation ,参数
(y ),不捕获内容,调用时:
断言 :y 为 MatchState 。
返回 y 。
令 r 为 m (x , d )。
若 r 非 failure ,返回
failure 。
返回 c (x )。
22.2.2.4.1 IsWordChar (rer , Input ,
e )
抽象操作 IsWordChar 接收参数 rer (RegExp
Record )、Input (字符 List )、e (整数 ),返回布尔值。调用时执行以下步骤:
令 InputLength = Input 的元素数量。
如果 e = -1 或 e = InputLength ,返回
false 。
令 c = Input [e ]。
如果 WordCharacters (rer )
包含 c ,返回 true 。
返回 false 。
22.2.2.5 运行时语义:CompileQuantifier
语法定向操作
CompileQuantifier 无参数,返回一个包含字段 [[Min]] (非负 整数 )、[[Max]] (非负 整数 或 +∞)、[[Greedy]] (布尔值)的
Record 。在以下产生式中分段定义:
Quantifier ::
QuantifierPrefix
令 qp 为 CompileQuantifierPrefix
of QuantifierPrefix 。
返回 Record { [[Min]] : qp .[[Min]] ,
[[Max]] : qp .[[Max]] ,
[[Greedy]] : true }。
Quantifier ::
QuantifierPrefix
?
令 qp 为 CompileQuantifierPrefix
of QuantifierPrefix 。
返回 Record { [[Min]] : qp .[[Min]] ,
[[Max]] : qp .[[Max]] ,
[[Greedy]] : false }。
22.2.2.6 运行时语义:CompileQuantifierPrefix
语法定向操作
CompileQuantifierPrefix 无参数,返回包含 [[Min]] (非负 整数 )、[[Max]] (非负 整数 或 +∞)字段的 Record 。在以下产生式中分段定义:
QuantifierPrefix
:: *
返回 Record { [[Min]] : 0, [[Max]] : +∞ }。
QuantifierPrefix
:: +
返回 Record { [[Min]] : 1, [[Max]] : +∞ }。
QuantifierPrefix
:: ?
返回 Record { [[Min]] : 0, [[Max]] : 1 }。
QuantifierPrefix
::
{
DecimalDigits
}
令 i 为 DecimalDigits 的 MV(见 12.9.3 )。
返回 Record { [[Min]] : i , [[Max]] :
i }。
QuantifierPrefix
::
{
DecimalDigits
,}
令 i 为 DecimalDigits 的 MV。
返回 Record { [[Min]] : i , [[Max]] : +∞
}。
QuantifierPrefix
::
{
DecimalDigits
,
DecimalDigits
}
令 i 为第一个 DecimalDigits 的 MV。
令 j 为第二个 DecimalDigits 的 MV。
返回 Record { [[Min]] : i , [[Max]] :
j }。
22.2.2.7 运行时语义:CompileAtom
语法定向操作
CompileAtom 接收参数 rer (RegExp Record )和
direction (forward 或 backward ),返回
Matcher 。
注 1
在以下产生式中分段定义:
Atom ::
PatternCharacter
令 ch 为 PatternCharacter 匹配的字符。
令 A 为仅包含字符 ch 的单元素 CharSet 。
返回 CharacterSetMatcher (rer ,
A , false , direction )。
Atom ::
.
令 A 为 AllCharacters (rer )。
如果 rer .[[DotAll]] 不为 true ,则:
从 A 中移除所有 LineTerminator 产生式右侧的码点对应的字符。
返回 CharacterSetMatcher (rer ,
A , false , direction )。
Atom ::
CharacterClass
令 cc 为 CompileCharacterClass of
CharacterClass ,参数为 rer 。
令 cs = cc .[[CharSet]] 。
如果 rer .[[UnicodeSets]] 为
false ,或 cs 的所有 CharSetElement
都是单字符(包括 cs 为空),则返回 CharacterSetMatcher (rer ,
cs , cc .[[Invert]] ,
direction )。
断言 :cc .[[Invert]] 为 false 。
令 lm 为 Matchers 的空 List 。
对于 cs 中每个包含多个字符的 CharSetElement
s (按长度降序遍历),执行:
令 cs2 为仅包含 s 最后一个码点的单元素 CharSet 。
令 m2 为 CharacterSetMatcher (rer ,
cs2 , false , direction )。
对于 s 中每个码点 c1 (从倒数第二个码点开始反向遍历),执行:
令 cs1 为仅包含 c1 的单元素 CharSet 。
令 m1 为 CharacterSetMatcher (rer ,
cs1 , false , direction )。
令 m2 = MatchSequence (m1 ,
m2 , direction )。
将 m2 添加到 lm 。
令 singles 为 cs 中所有单字符 CharSetElement
组成的 CharSet 。
将 CharacterSetMatcher (rer ,
singles , false , direction ) 添加到
lm 。
如果 cs 包含空序列,则将 EmptyMatcher () 添加到 lm 。
令 m2 为 lm 的最后一个 Matcher 。
对于 lm 中每个 Matcher
m1 (从倒数第二个元素开始反向遍历),执行:
令 m2 = MatchTwoAlternatives (m1 ,
m2 )。
返回 m2 。
Atom ::
(
GroupSpecifier opt
Disjunction
)
令 m 为 CompileSubpattern of Disjunction ,参数为
rer 和 direction 。
令 parenIndex = CountLeftCapturingParensBefore (Atom )。
返回一个新 Matcher ,参数 (x ,
c ),捕获 direction 、m 、parenIndex ,调用时:
断言 :x 为 MatchState 。
断言 :c 为 MatcherContinuation 。
令 d 为一个新 MatcherContinuation ,参数
(y ),捕获
x 、c 、direction 、parenIndex ,调用时:
断言 :y 为 MatchState 。
令 cap 为 y .[[Captures]] 的副本。
令 Input = x .[[Input]] 。
令 xe = x .[[EndIndex]] 。
令 ye = y .[[EndIndex]] 。
如果 direction 为 forward ,则:
断言 :xe ≤ ye 。
令 r 为 CaptureRange { [[StartIndex]] : xe , [[EndIndex]] : ye }。
否则:
断言 :direction 为
backward 。
断言 :ye ≤ xe 。
令 r 为 CaptureRange { [[StartIndex]] : ye , [[EndIndex]] : xe }。
设置 cap [parenIndex + 1] = r 。
令 z 为 MatchState { [[Input]] : Input , [[EndIndex]] : ye , [[Captures]] : cap }。
返回 c (z )。
返回 m (x , d )。
注 2
形如 (
Disjunction )
的括号既用于分组,也用于保存匹配结果。可以通过反向引用、替换字符串或结果数组使用该结果。用 (?:
... )
可禁用捕获行为。
Atom ::
(?
RegularExpressionModifiers
:
Disjunction
)
令 addModifiers 为 source text
matched by RegularExpressionModifiers 。
令 removeModifiers 为空字符串。
令 modifiedRer = UpdateModifiers (rer ,
CodePointsToString (addModifiers ),
removeModifiers )。
返回 CompileSubpattern of Disjunction ,参数为
modifiedRer 和 direction 。
Atom ::
(?
RegularExpressionModifiers
-
RegularExpressionModifiers
:
Disjunction
)
令 addModifiers 为 source text
matched by 第一个 RegularExpressionModifiers 。
令 removeModifiers 为 source text
matched by 第二个 RegularExpressionModifiers 。
令 modifiedRer = UpdateModifiers (rer ,
CodePointsToString (addModifiers ),
CodePointsToString (removeModifiers ))。
返回 CompileSubpattern of Disjunction ,参数为
modifiedRer 和 direction 。
AtomEscape ::
DecimalEscape
令 n 为 CapturingGroupNumber
of DecimalEscape 。
断言 :n ≤ rer .[[CapturingGroupsCount]] 。
返回 BackreferenceMatcher (rer ,
« n », direction )。
注 3
形如 \
后跟非零十进制数字 n 的转义序列,匹配第 n 个捕获括号的结果。括号数不足 n
是错误。若 n 个括号有但第 n 个未捕获内容,则反向引用总是成功。
AtomEscape ::
CharacterEscape
令 cv 为 CharacterValue
of CharacterEscape 。
令 ch 为字符值为 cv 的字符。
令 A 为仅包含字符 ch 的单元素 CharSet 。
返回 CharacterSetMatcher (rer ,
A , false , direction )。
AtomEscape ::
CharacterClassEscape
令 cs 为 CompileToCharSet of CharacterClassEscape ,参数为
rer 。
如果 rer .[[UnicodeSets]] 为
false ,或 cs 的所有 CharSetElement
都是单字符(包括 cs 为空),则返回 CharacterSetMatcher (rer ,
cs , false , direction )。
令 lm 为 Matchers 的空 List 。
对于 cs 中每个包含多个字符的 CharSetElement
s (按长度降序遍历),执行:
令 cs2 为仅包含 s 最后一个码点的单元素 CharSet 。
令 m2 为 CharacterSetMatcher (rer ,
cs2 , false , direction )。
对于 s 中每个码点 c1 (从倒数第二个码点开始反向遍历),执行:
令 cs1 为仅包含 c1 的单元素 CharSet 。
令 m1 为 CharacterSetMatcher (rer ,
cs1 , false , direction )。
令 m2 = MatchSequence (m1 ,
m2 , direction )。
将 m2 添加到 lm 。
令 singles 为 cs 中所有单字符 CharSetElement
组成的 CharSet 。
将 CharacterSetMatcher (rer ,
singles , false , direction ) 添加到
lm 。
如果 cs 包含空序列,则将 EmptyMatcher () 添加到 lm 。
令 m2 为 lm 的最后一个 Matcher 。
对于 lm 中每个 Matcher
m1 (从倒数第二个元素开始反向遍历),执行:
令 m2 = MatchTwoAlternatives (m1 ,
m2 )。
返回 m2 。
AtomEscape ::
k
GroupName
令 matchingGroupSpecifiers 为 GroupSpecifiersThatMatch (GroupName )。
令 parenIndices 为一个新的空 List 。
对于 matchingGroupSpecifiers 中的每一个 GroupSpecifier
groupSpecifier ,执行:
令 parenIndex = CountLeftCapturingParensBefore (groupSpecifier )。
将 parenIndex 添加到 parenIndices 。
返回 BackreferenceMatcher (rer ,
parenIndices , direction )。
22.2.2.7.1 CharacterSetMatcher (rer ,
A , invert , direction )
抽象操作 CharacterSetMatcher 接收参数 rer (RegExp
Record )、A (CharSet )、invert (布尔值)、direction (forward
或 backward ),返回 Matcher 。调用时执行如下步骤:
如果 rer .[[UnicodeSets]] 为
true ,则:
断言 :invert 为
false 。
断言 :A 的每个 CharSetElement 都是单字符。
返回一个新 Matcher ,参数 (x ,
c ),捕获
rer 、A 、invert 、direction ,调用时:
断言 :x 为 MatchState 。
断言 :c 为 MatcherContinuation 。
令 Input = x .[[Input]] 。
令 e = x .[[EndIndex]] 。
若 direction 为 forward ,令 f =
e + 1。
否则,令 f = e - 1。
令 InputLength = Input 的元素数量。
若 f < 0 或 f > InputLength ,返回
failure 。
令 index = min (e , f )。
令 ch = Input [index ]。
令 cc = Canonicalize (rer ,
ch )。
如果存在 A 中仅含字符 a 的 CharSetElement ,且
Canonicalize (rer ,
a ) 等于 cc ,则 found =
true ,否则 found = false 。
若 invert 为 false 且 found 为
false ,返回 failure 。
若 invert 为 true 且 found 为
true ,返回 failure 。
令 cap = x .[[Captures]] 。
令 y = MatchState { [[Input]] : Input , [[EndIndex]] : f , [[Captures]] : cap }。
返回 c (y )。
22.2.2.7.2 BackreferenceMatcher (rer ,
ns , direction )
抽象操作 BackreferenceMatcher 接收参数 rer (RegExp
Record )、ns (正 整数 的 List )、direction (forward
或 backward ),返回 Matcher 。调用时执行如下步骤:
返回一个新 Matcher ,参数 (x ,
c ),捕获 rer 、ns 、direction ,调用时:
断言 :x 为 MatchState 。
断言 :c 为 MatcherContinuation 。
令 Input = x .[[Input]] 。
令 cap = x .[[Captures]] 。
令 r = undefined 。
对于 ns 中的每个 整数 n ,执行:
若 cap [n ] 非 undefined ,则:
断言 :r 为
undefined 。
令 r = cap [n ]。
若 r 为 undefined ,返回
c (x )。
令 e = x .[[EndIndex]] 。
令 rs = r .[[StartIndex]] 。
令 re = r .[[EndIndex]] 。
令 len = re - rs 。
若 direction 为 forward ,令 f =
e + len 。
否则,令 f = e - len 。
令 InputLength = Input 的元素数量。
若 f < 0 或 f > InputLength ,返回
failure 。
令 g = min (e , f )。
若存在 0(含)到 len (不含)间的 整数 i ,使得
Canonicalize (rer ,
Input [rs +i ]) ≠ Canonicalize (rer ,
Input [g +i ]),返回
failure 。
令 y = MatchState { [[Input]] : Input , [[EndIndex]] : f , [[Captures]] : cap }。
返回 c (y )。
22.2.2.7.3 Canonicalize (rer , ch )
抽象操作 Canonicalize 接收参数 rer (RegExp
Record )、ch (字符),返回一个字符。调用时执行如下步骤:
若 HasEitherUnicodeFlag (rer )
为 true 且 rer .[[IgnoreCase]] 为 true ,则:
若 CaseFolding.txt
提供了 ch 的简单或通用大小写折叠映射,则返回应用该映射后的 ch 。
返回 ch 。
若 rer .[[IgnoreCase]] 为
false ,返回 ch 。
断言 :ch 是 UTF-16 码元。
令 cp 为 ch 的数值对应的码点。
令 u 为根据 Unicode 默认大小写转换算法 toUppercase(« cp »)。
令 uStr = CodePointsToString (u )。
若 uStr 长度 ≠ 1,返回 ch 。
令 cu = uStr 的唯一码元。
若 ch 数值 ≥ 128 且 cu 数值 < 128,返回 ch 。
返回 cu 。
注
当 HasEitherUnicodeFlag (rer )
为 true 且大小写不敏感时,所有字符都用 Unicode
标准的简单大小写折叠映射进行大小写折叠再比较。简单映射总是映射为单一码点(如 ß
不会变为 ss
或
SS
)。但部分非Basic Latin字符可映射为Basic Latin内字符,如 ſ
会折叠为
s
,K
会折叠为 k
,因此如 /[a-z]/ui
可匹配这些字符。
当 HasEitherUnicodeFlag (rer )
为 false 时,映射基于 Unicode 默认大小写转换算法的 toUppercase,而不是
toCasefold,存在差异。例如 Ω
(U+2126)用 toUppercase 仍为自身,但 toCasefold 会变为
ω
。所以 "\u2126"
能被 /[ω]/ui
匹配,不能被
/[ω]/i
匹配。非Basic Latin的字符不会映射到Basic Latin内字符。
22.2.2.7.4 UpdateModifiers (rer , add ,
remove )
抽象操作 UpdateModifiers 接收参数 rer (RegExp
Record )、add (字符串)、remove (字符串),返回一个 RegExp
Record 。调用时执行如下步骤:
断言 :add 与 remove
没有公共元素。
令 ignoreCase = rer .[[IgnoreCase]] 。
令 multiline = rer .[[Multiline]] 。
令 dotAll = rer .[[DotAll]] 。
令 unicode = rer .[[Unicode]] 。
令 unicodeSets = rer .[[UnicodeSets]] 。
令 capturingGroupsCount = rer .[[CapturingGroupsCount]] 。
如果 remove 包含 "i" ,则令 ignoreCase =
false 。
否则若 add 包含 "i" ,则令 ignoreCase =
true 。
如果 remove 包含 "m" ,则令 multiline =
false 。
否则若 add 包含 "m" ,则令 multiline =
true 。
如果 remove 包含 "s" ,则令 dotAll =
false 。
否则若 add 包含 "s" ,则令 dotAll =
true 。
返回 RegExp Record {
[[IgnoreCase]] : ignoreCase ,
[[Multiline]] : multiline ,
[[DotAll]] : dotAll ,
[[Unicode]] : unicode ,
[[UnicodeSets]] : unicodeSets ,
[[CapturingGroupsCount]] :
capturingGroupsCount
}。
22.2.2.8 运行时语义:CompileCharacterClass
语法定向操作
CompileCharacterClass 接收参数 rer (RegExp Record ),返回含字段 [[CharSet]] (CharSet )和 [[Invert]] (布尔值)的 Record 。在以下产生式中分段定义:
CharacterClass ::
[
ClassContents
]
令 A 为 CompileToCharSet of ClassContents ,参数为
rer 。
返回 Record { [[CharSet]] : A , [[Invert]] : false }。
CharacterClass ::
[^
ClassContents
]
令 A 为 CompileToCharSet of ClassContents ,参数为
rer 。
如果 rer .[[UnicodeSets]] 为
true ,则:
返回 Record {
[[CharSet]] : CharacterComplement (rer ,
A ), [[Invert]] : false }。
返回 Record { [[CharSet]] : A , [[Invert]] : true }。
22.2.2.9 运行时语义:CompileToCharSet
语法定向操作
CompileToCharSet 接收参数 rer (RegExp Record ),返回 CharSet 。
注 1
在以下产生式中分段定义:
ClassContents ::
[empty]
返回空 CharSet 。
NonemptyClassRanges
::
ClassAtom
NonemptyClassRangesNoDash
令 A = CompileToCharSet of ClassAtom ,参数为
rer 。
令 B = CompileToCharSet of NonemptyClassRangesNoDash ,参数为
rer 。
返回 A 与 B 的并集。
NonemptyClassRanges
::
ClassAtom
-
ClassAtom
ClassContents
令 A = CompileToCharSet of 第一个 ClassAtom ,参数为
rer 。
令 B = CompileToCharSet of 第二个 ClassAtom ,参数为
rer 。
令 C = CompileToCharSet of ClassContents ,参数为
rer 。
令 D = CharacterRange (A ,
B )。
返回 D 与 C 的并集。
NonemptyClassRangesNoDash
::
ClassAtomNoDash
NonemptyClassRangesNoDash
令 A = CompileToCharSet of ClassAtomNoDash ,参数为
rer 。
令 B = CompileToCharSet of NonemptyClassRangesNoDash ,参数为
rer 。
返回 A 与 B 的并集。
NonemptyClassRangesNoDash
::
ClassAtomNoDash
-
ClassAtom
ClassContents
令 A = CompileToCharSet of ClassAtomNoDash ,参数为
rer 。
令 B = CompileToCharSet of ClassAtom ,参数为
rer 。
令 C = CompileToCharSet of ClassContents ,参数为
rer 。
令 D = CharacterRange (A ,
B )。
返回 D 与 C 的并集。
注 2
ClassContents
可扩展为单个 ClassAtom 或由两个
ClassAtom
用连字符分隔的区间。后者情况下,ClassContents 包含两个 ClassAtom (含)之间的所有字符;如其中任一不是单字符(如
\w),或左端大于右端,则为错误。
注 3
即使忽略大小写,区间两端字符的大小写在区间确定时依然重要。例如 /[E-F]/i
只匹配 E
,
F
, e
, f
,而 /[E-f]/i
匹配 Basic
Latin 字母及 [
, \
, ]
, ^
,
_
, `
。
注 4
-
可被当作字面量或区间。若在 ClassContents 首尾、区间端点、或区间后,视为字面量。
ClassAtom ::
-
返回仅包含字符 -
U+002D (HYPHEN-MINUS) 的 CharSet 。
ClassAtomNoDash
::
SourceCharacter
但不能是 \ 、] 或 -
返回仅包含 SourceCharacter 匹配字符的 CharSet 。
ClassEscape ::
b
-
CharacterEscape
令 cv 为本 ClassEscape 的 CharacterValue 。
令 c 为字符值为 cv 的字符。
返回仅包含字符 c 的 CharSet 。
注 5
ClassAtom
可使用正则中允许的转义序列,除 \b
、\B
和反向引用外。类中 \b
表示退格符,\B
和反向引用会报错。在 ClassAtom 使用反向引用是错误的。
CharacterClassEscape
::
d
返回包含字符 0
到 9
的十元素 CharSet 。
CharacterClassEscape
::
D
令 S 为 CharacterClassEscape ::
d
返回的 CharSet 。
返回 CharacterComplement (rer ,
S )。
CharacterClassEscape
::
s
返回包含 WhiteSpace 或
LineTerminator
产生式右侧所有码点的 CharSet 。
CharacterClassEscape
::
S
令 S 为 CharacterClassEscape ::
s
返回的 CharSet 。
返回 CharacterComplement (rer ,
S )。
CharacterClassEscape
::
w
返回 MaybeSimpleCaseFolding (rer ,
WordCharacters (rer ))。
CharacterClassEscape
::
W
令 S 为 CharacterClassEscape ::
w
返回的 CharSet 。
返回 CharacterComplement (rer ,
S )。
CharacterClassEscape
::
p{
UnicodePropertyValueExpression
}
返回 CompileToCharSet of UnicodePropertyValueExpression ,参数为
rer 。
CharacterClassEscape
::
P{
UnicodePropertyValueExpression
}
令 S 为 CompileToCharSet of UnicodePropertyValueExpression ,参数为
rer 。
断言 :S 仅包含单一码点。
返回 CharacterComplement (rer ,
S )。
UnicodePropertyValueExpression
::
UnicodePropertyName
=
UnicodePropertyValue
令 ps 为 source text
matched by UnicodePropertyName 。
令 p 为 UnicodeMatchProperty (rer ,
ps )。
断言 :p 是 表 69 “Property
name and aliases” 列中列出的 Unicode 属性名 或属性别名。
令 vs 为 source text
matched by UnicodePropertyValue 。
令 v 为 UnicodeMatchPropertyValue (p ,
vs )。
令 A 为包含所有在字符数据库定义中具有属性 p 且值为 v 的 Unicode 码点的
CharSet 。
返回 MaybeSimpleCaseFolding (rer ,
A )。
UnicodePropertyValueExpression
::
LoneUnicodePropertyNameOrValue
令 s 为 source text
matched by LoneUnicodePropertyNameOrValue 。
如果 UnicodeMatchPropertyValue (General_Category
,
s ) 是 PropertyValueAliases.txt
中 General_Category (gc) 属性的 Unicode 属性值或属性值别名,则:
返回包含所有字符数据库定义中属性 “General_Category” 值为 s 的 Unicode 码点的 CharSet 。
令 p 为 UnicodeMatchProperty (rer ,
s )。
断言 :p 是 表 70 “Property name
and aliases” 列中列出的二值 Unicode 属性或二值属性别名,或 表 71
“Property name” 列中列出的字符串的二值 Unicode 属性。
令 A 为包含所有字符数据库定义中属性 p 值为 “True” 的 CharSetElements 的 CharSet 。
返回 MaybeSimpleCaseFolding (rer ,
A )。
ClassUnion ::
ClassSetRange
ClassUnion opt
令 A 为 CompileToCharSet of ClassSetRange ,参数为
rer 。
如果 ClassUnion 存在,则:
令 B 为 CompileToCharSet of ClassUnion ,参数为
rer 。
返回 CharSets A 与
B 的并集。
返回 A 。
ClassUnion ::
ClassSetOperand
ClassUnion opt
令 A 为 CompileToCharSet of ClassSetOperand ,参数为
rer 。
如果 ClassUnion 存在,则:
令 B 为 CompileToCharSet of ClassUnion ,参数为
rer 。
返回 CharSets A 与
B 的并集。
返回 A 。
ClassIntersection
::
ClassSetOperand
&&
ClassSetOperand
令 A 为 CompileToCharSet of 第一个 ClassSetOperand ,参数为
rer 。
令 B 为 CompileToCharSet of 第二个 ClassSetOperand ,参数为
rer 。
返回 CharSets A 与 B
的交集。
ClassIntersection
::
ClassIntersection
&&
ClassSetOperand
令 A 为 CompileToCharSet of ClassIntersection ,参数为
rer 。
令 B 为 CompileToCharSet of ClassSetOperand ,参数为
rer 。
返回 CharSets A 与 B
的交集。
ClassSubtraction
::
ClassSetOperand
--
ClassSetOperand
令 A 为第一个 CompileToCharSet of ClassSetOperand ,参数为
rer 。
令 B 为第二个 CompileToCharSet of ClassSetOperand ,参数为
rer 。
返回包含所有属于 A 但不属于 B 的 CharSetElements 的 CharSet 。
ClassSubtraction
::
ClassSubtraction
--
ClassSetOperand
令 A 为 CompileToCharSet of ClassSubtraction ,参数为
rer 。
令 B 为 CompileToCharSet of ClassSetOperand ,参数为
rer 。
返回包含所有属于 A 但不属于 B 的 CharSetElements 的 CharSet 。
ClassSetRange ::
ClassSetCharacter
-
ClassSetCharacter
令 A 为第一个 CompileToCharSet of ClassSetCharacter ,参数为
rer 。
令 B 为第二个 CompileToCharSet of ClassSetCharacter ,参数为
rer 。
返回 MaybeSimpleCaseFolding (rer ,
CharacterRange (A ,
B ))。
注 6
结果通常包含两个或更多区间。当 UnicodeSets 为 true 且 IgnoreCase 为
true 时,MaybeSimpleCaseFolding (rer ,
[Ā-č]) 只包含该区间中奇数码点。
ClassSetOperand
::
ClassSetCharacter
令 A 为 CompileToCharSet of ClassSetCharacter ,参数为
rer 。
返回 MaybeSimpleCaseFolding (rer ,
A )。
ClassSetOperand
::
ClassStringDisjunction
令 A 为 CompileToCharSet of ClassStringDisjunction ,参数为
rer 。
返回 MaybeSimpleCaseFolding (rer ,
A )。
ClassSetOperand
::
NestedClass
返回 CompileToCharSet of NestedClass ,参数为
rer 。
NestedClass ::
[
ClassContents
]
返回 CompileToCharSet of ClassContents ,参数为
rer 。
NestedClass ::
[^
ClassContents
]
令 A 为 CompileToCharSet of ClassContents ,参数为
rer 。
返回 CharacterComplement (rer ,
A )。
NestedClass ::
\
CharacterClassEscape
返回 CompileToCharSet of CharacterClassEscape ,参数为
rer 。
ClassStringDisjunction
::
\q{
ClassStringDisjunctionContents
}
返回 CompileToCharSet of ClassStringDisjunctionContents ,参数为
rer 。
ClassStringDisjunctionContents
::
ClassString
令 s 为 CompileClassSetString of
ClassString ,参数为
rer 。
返回仅包含字符串 s 的 CharSet 。
ClassStringDisjunctionContents
::
ClassString
|
ClassStringDisjunctionContents
令 s 为 CompileClassSetString of
ClassString ,参数为
rer 。
令 A 为仅包含字符串 s 的 CharSet 。
令 B 为 CompileToCharSet of ClassStringDisjunctionContents ,参数为
rer 。
返回 CharSets A 与 B
的并集。
ClassSetCharacter
::
SourceCharacter
但不能是 ClassSetSyntaxCharacter
\
CharacterEscape
\
ClassSetReservedPunctuator
令 cv 为本 ClassSetCharacter 的 CharacterValue 。
令 c 为字符值为 cv 的字符。
返回仅包含字符 c 的 CharSet 。
ClassSetCharacter
::
\b
返回仅包含字符 U+0008 (BACKSPACE) 的 CharSet 。
22.2.2.9.1 CharacterRange (A , B )
抽象操作 CharacterRange 接收参数 A (CharSet )和
B (CharSet ),返回 CharSet 。调用时执行如下步骤:
断言 :A 和 B 各自仅包含一个字符。
令 a 为 A 中的唯一字符。
令 b 为 B 中的唯一字符。
令 i 为字符 a 的字符值。
令 j 为字符 b 的字符值。
断言 :i ≤ j 。
返回包含所有字符值在 i 到 j (含)区间的字符的 CharSet 。
22.2.2.9.2 HasEitherUnicodeFlag (rer )
抽象操作 HasEitherUnicodeFlag 接收参数 rer (RegExp
Record ),返回布尔值。调用时执行如下步骤:
如果 rer .[[Unicode]] 为 true
或 rer .[[UnicodeSets]] 为
true ,则:
返回 true 。
返回 false 。
22.2.2.9.3 WordCharacters (rer )
抽象操作 WordCharacters 接收参数 rer (RegExp Record ),返回
CharSet 。返回正则表达式中
\b
、\B
、\w
、\W
所认为的“单词字符”。调用时执行如下步骤:
令 basicWordChars 为包含所有 ASCII 单词字符 的
CharSet 。
令 extraWordChars 为包含所有字符 c 的 CharSet ,其中 c 不在
basicWordChars 内,但 Canonicalize (rer ,
c ) 在 basicWordChars 内。
断言 :除非
HasEitherUnicodeFlag (rer )
为 true 且 rer .[[IgnoreCase]] 为 true ,否则
extraWordChars 为空。
返回 basicWordChars 与 extraWordChars 的并集。
22.2.2.9.4 AllCharacters (rer )
抽象操作 AllCharacters 接收参数 rer (RegExp Record ),返回
CharSet 。根据正则表达式标志返回“所有字符”的集合。调用时执行如下步骤:
如果 rer .[[UnicodeSets]] 为
true 且 rer .[[IgnoreCase]]
为 true :
返回包含所有无 简单大小写折叠 映射(即
scf (c )=c )的
Unicode 码点 c 的 CharSet 。
否则若 HasEitherUnicodeFlag (rer )
为 true :
返回包含所有码点值的 CharSet 。
否则:
返回包含所有码元值的 CharSet 。
22.2.2.9.5 MaybeSimpleCaseFolding (rer ,
A )
抽象操作 MaybeSimpleCaseFolding 接收参数 rer (RegExp
Record )、A (CharSet ),返回 CharSet 。如果 rer .[[UnicodeSets]] 为 false 或 rer .[[IgnoreCase]] 为 false ,则返回 A 。否则,使用
Unicode Character Database 中 简单大小写折叠 (scf(cp ) )的定义,对
A 的每个 CharSetElement 的每个码点字符做映射,并返回结果
CharSet 。调用时执行如下步骤:
如果 rer .[[UnicodeSets]] 为
false 或 rer .[[IgnoreCase]] 为 false ,返回
A 。
令 B 为一个新的空 CharSet 。
对 A 的每一个 CharSetElement
s ,执行:
令 t 为空字符序列。
对 s 中每一个码点 cp ,执行:
将 scf (cp ) 附加到
t 。
将 t 添加到 B 。
返回 B 。
22.2.2.9.6 CharacterComplement (rer ,
S )
抽象操作 CharacterComplement 接收参数 rer (RegExp
Record )、S (CharSet ),返回 CharSet 。调用时执行如下步骤:
令 A = AllCharacters (rer )。
返回包含所有属于 A 但不属于 S 的 CharSetElements 的 CharSet 。
22.2.2.9.7 UnicodeMatchProperty (rer ,
p )
抽象操作 UnicodeMatchProperty 接收参数 rer (RegExp
Record )、p (ECMAScript 源文本 ),返回 Unicode
属性名 。调用时执行如下步骤:
如果 rer .[[UnicodeSets]] 为
true 且 p 是 表 71
“Property name” 列中的 Unicode 属性名,则:
返回 Unicode 码点 p 组成的 List 。
断言 :p 是 表 69 、“Property
name and aliases” 或 表 70
中的 Unicode 属性名或属性别名。
令 c 为该行 “Canonical property name” 列中给出的 p 的规范属性名。
返回 Unicode 码点 c 组成的 List 。
实现必须支持 表 69 、表 70 和 表 71 中列出的
Unicode 属性名和别名。为保证互操作性,实现不得支持其他属性名或别名。
注 1
例如,Script_Extensions
(属性名 )和
scx
(属性别名)有效,但 script_extensions
或 Scx
无效。
注 2
这些属性集合是 UTS18 RL1.2 要求的超集。
注 3
这些表中的拼写(包括大小写)与 Unicode Character Database 文件 PropertyAliases.txt
保持一致。该文件中的拼写是 保证稳定的 。
表 69:非二值(非布尔型)Unicode 属性别名及其规范属性名
表 70:二值(布尔型)Unicode 属性别名及其规范属性名
表 71:字符串的二值(布尔型)Unicode 属性
属性名
Basic_Emoji
(基础表情符号)
Emoji_Keycap_Sequence
(表情符号按键序列)
RGI_Emoji_Modifier_Sequence
(RGI表情符号修饰符序列)
RGI_Emoji_Flag_Sequence
(RGI表情符号旗帜序列)
RGI_Emoji_Tag_Sequence
(RGI表情符号标签序列)
RGI_Emoji_ZWJ_Sequence
(RGI表情符号ZWJ序列)
RGI_Emoji
(RGI表情符号)
22.2.2.9.8 UnicodeMatchPropertyValue (p ,
v )
抽象操作 UnicodeMatchPropertyValue 接收参数 p (ECMAScript 源文本 )和
v (ECMAScript 源文本 ),返回一个 Unicode
属性值。调用时执行如下步骤:
断言 :p 是 表
69 “规范属性名”列中列出的规范、无别名的 Unicode 属性名 。
断言 :v 是 PropertyValueAliases.txt
中针对属性 p 列出的属性值或属性值别名。
令 value 为 v 的规范属性值,其值为对应行“规范属性值”列中给出的内容。
返回 Unicode 码点 value 组成的 List 。
实现必须支持 表 69 中属性对应的 PropertyValueAliases.txt
文件中列出的 Unicode 属性值和属性值别名。为保证互操作性,实现不得支持其他属性值或属性值别名。
注 1
例如,Xpeo
和 Old_Persian
是有效的
Script_Extensions
属性值,但 xpeo
和
Old Persian
无效。
注 2
此算法不同于 UAX44
中列出的符号值匹配规则 :不会忽略大小写、空白 、U+002D(连字符)和 U+005F(下划线),并且不支持
Is
前缀。
22.2.2.10 运行时语义:CompileClassSetString
语法定向操作
CompileClassSetString 接收参数 rer (RegExp
Record ),返回一个字符序列。该操作按以下产生式分段定义:
ClassString ::
[empty]
返回空的字符序列。
ClassString ::
NonEmptyClassString
返回 CompileClassSetString of
NonEmptyClassString ,参数为
rer 。
NonEmptyClassString
::
ClassSetCharacter
NonEmptyClassString
opt
令 cs 为 CompileToCharSet of ClassSetCharacter ,参数为
rer 。
令 s1 为 cs 的唯一 CharSetElement
的字符序列。
如果 NonEmptyClassString 存在,则:
令 s2 为 CompileClassSetString
of NonEmptyClassString ,参数为
rer 。
返回 s1 和 s2 的拼接。
返回 s1 。
22.2.3 正则表达式创建的抽象操作
22.2.3.1 RegExpCreate ( P , F )
抽象操作 RegExpCreate 接收参数 P (一个 ECMAScript 语言值 )和
F (字符串或 undefined ),返回 包含 对象的正常完成,或
抛出完成 。调用时执行如下步骤:
令 obj 为 ! RegExpAlloc (%RegExp% )。
返回 ? RegExpInitialize (obj ,
P , F )。
22.2.3.2 RegExpAlloc ( newTarget )
抽象操作 RegExpAlloc 接收参数 newTarget (构造函数 ),返回 包含 对象的正常完成,或
抛出完成 。调用时执行如下步骤:
令 obj 为 ? OrdinaryCreateFromConstructor (newTarget ,
"%RegExp.prototype%" , « [[OriginalSource]] , [[OriginalFlags]] , [[RegExpRecord]] , [[RegExpMatcher]]
»)。
执行 ! DefinePropertyOrThrow (obj ,
"lastIndex" , PropertyDescriptor { [[Writable]] : true , [[Enumerable]] : false , [[Configurable]] : false })。
返回 obj 。
22.2.3.3 RegExpInitialize ( obj , pattern ,
flags )
抽象操作 RegExpInitialize 接收参数 obj (对象)、pattern (ECMAScript
语言值 )、flags (ECMAScript
语言值 ),返回 包含 对象的正常完成,或
抛出完成 。调用时执行如下步骤:
如果 pattern 是 undefined ,令 P 为空字符串。
否则,令 P 为 ? ToString (pattern )。
如果 flags 是 undefined ,令 F 为空字符串。
否则,令 F 为 ? ToString (flags )。
如果 F 包含除
"d" 、"g" 、"i" 、"m" 、"s" 、"u" 、"v" 、"y"
以外的任何代码单元,或 F 中有任何代码单元出现多次,则抛出 SyntaxError 异常。
如果 F 包含 "i" ,令 i =
true ;否则 i = false 。
如果 F 包含 "m" ,令 m =
true ;否则 m = false 。
如果 F 包含 "s" ,令 s =
true ;否则 s = false 。
如果 F 包含 "u" ,令 u =
true ;否则 u = false 。
如果 F 包含 "v" ,令 v =
true ;否则 v = false 。
如果 u 为 true 或 v 为 true ,则
令 patternText = StringToCodePoints (P )。
否则:
令 patternText 为将 P 的每个 16 位元素按 Unicode BMP
码点解释的结果。不会对这些元素做 UTF-16 解码。
令 parseResult = ParsePattern (patternText ,
u , v )。
如果 parseResult 是一个非空的 List ,且包含
SyntaxError 对象,则抛出 SyntaxError 异常。
断言 :parseResult 是一个 Pattern 解析节点 。
设置 obj .[[OriginalSource]] = P 。
设置 obj .[[OriginalFlags]] = F 。
令 capturingGroupsCount = CountLeftCapturingParensWithin (parseResult )。
令 rer 为 RegExp Record { [[IgnoreCase]] : i , [[Multiline]] : m , [[DotAll]] : s , [[Unicode]] : u , [[UnicodeSets]] : v , [[CapturingGroupsCount]] : capturingGroupsCount }。
设置 obj .[[RegExpRecord]] = rer 。
设置 obj .[[RegExpMatcher]] = CompilePattern of
parseResult ,参数为 rer 。
执行 ? Set (obj ,
"lastIndex" , +0 𝔽 ,
true )。
返回 obj 。
22.2.3.4 静态语义:ParsePattern (patternText ,
u , v )
抽象操作 ParsePattern 接收参数
patternText (Unicode码点序列)、u (布尔值)、v (布尔值),返回一个 解析节点 ,或一个非空的 List (元素为
SyntaxError 对象)。
注
调用时执行如下步骤:
如果 v 为 true 且 u 为 true ,
令 parseResult 为包含一个或多个 SyntaxError 对象的
List 。
否则,如果 v 为 true ,
令 parseResult = ParseText (patternText ,
Pattern [+UnicodeMode,
+UnicodeSetsMode,
+NamedCaptureGroups] )。
否则,如果 u 为 true ,
令 parseResult = ParseText (patternText ,
Pattern [+UnicodeMode,
~UnicodeSetsMode,
+NamedCaptureGroups] )。
否则:
令 parseResult = ParseText (patternText ,
Pattern [~UnicodeMode,
~UnicodeSetsMode,
+NamedCaptureGroups] )。
返回 parseResult 。
22.2.4 RegExp 构造函数
RegExp 构造函数 :
即 %RegExp% 。
是 全局对象 的 "RegExp" 属性的初始值。
作为 构造函数 调用时,会创建并初始化一个新的 RegExp 对象。
当作普通函数而非 构造函数 调用时,返回一个新的 RegExp 对象,或者如果唯一参数本身就是 RegExp
对象,则返回该参数本身。
可以作为类定义的 extends
子句的值。子类 构造函数 如果要继承指定的 RegExp 行为,必须包含对 RegExp 构造函数 的
super
调用,以便用必要的内部插槽来创建并初始化子类实例。
22.2.4.1 RegExp ( pattern , flags )
该函数被调用时执行以下步骤:
令 patternIsRegExp 为 ? IsRegExp (pattern )。
如果 NewTarget 是 undefined ,则
令 newTarget 为 活动函数对象 。
如果 patternIsRegExp 是 true 且 flags 是
undefined ,则
令 patternConstructor 为 ? Get (pattern ,
"constructor" )。
如果 SameValue (newTarget ,
patternConstructor ) 为 true ,返回
pattern 。
否则,
令 newTarget 为 NewTarget。
如果 pattern 是一个对象 且 pattern 有 [[RegExpMatcher]] 内部插槽,则
令 P 为 pattern .[[OriginalSource]] 。
如果 flags 是 undefined ,令 F 为
pattern .[[OriginalFlags]] 。
否则,令 F 为 flags 。
否则如果 patternIsRegExp 是 true ,则
令 P 为 ? Get (pattern ,
"source" )。
如果 flags 是 undefined ,则
令 F 为 ? Get (pattern ,
"flags" )。
否则,
令 F 为 flags 。
否则,
令 P 为 pattern 。
令 F 为 flags 。
令 O 为 ? RegExpAlloc (newTarget )。
返回 ? RegExpInitialize (O ,
P , F )。
注
如果 pattern 是通过 StringLiteral
传递的,会在该字符串被本函数处理前进行常规的转义序列替换。如果 pattern 必须包含一个转义序列以便被本函数识别,则必须在 StringLiteral 内对所有
U+005C(反斜杠)码点进行转义,以防止它们在形成 StringLiteral 内容时被移除。
22.2.5 RegExp 构造函数的属性
RegExp 构造函数 :
22.2.5.1 RegExp.escape ( S )
该函数返回 S 的一个副本,其中正则表达式模式 中可能具有特殊含义的字符都被替换为等价的转义序列。
调用时执行以下步骤:
如果 S 不是字符串 ,抛出
TypeError 异常。
令 escaped 为空字符串。
令 cpList 为 StringToCodePoints (S )。
对于 cpList 中的每个码点 cp ,执行
如果 escaped 为空字符串,且 cp 匹配 十进制数字 或 ASCII 字母 ,
则
注:转义首位数字可保证输出对应的模式文本在 \0 字符转义或 十进制转义 (如 \1)后仍能匹配
S,不会被解释为前一转义序列的扩展。首位 ASCII 字母的转义同理,适用于 \c 后的情况。
令 numericValue 为 cp 的数值。
令 hex 为 Number::toString (𝔽 (numericValue ), 16)。
断言 :hex 长度为 2。
设置 escaped 为字符串拼接 0x005C(反斜杠)、"x" 及 hex 。
否则,
设置 escaped 为 escaped 与 EncodeForRegExpEscape (cp )
的字符串拼接。
返回 escaped 。
注
虽然名字相似,EscapeRegExpPattern 和
RegExp.escape
并不执行类似操作。前者用于将模式转义为字符串表示,后者用于将字符串转义为模式内部使用。
22.2.5.1.1 EncodeForRegExpEscape ( cp )
抽象操作 EncodeForRegExpEscape 接收参数 cp (码点),返回一个字符串。返回值即为匹配 cp 的模式
Pattern 。如 cp
为空白字符或 ASCII 标点,则返回转义序列。否则,返回 cp 本身的字符串表示。调用时执行如下步骤:
如果 cp 匹配 SyntaxCharacter 或等于
U+002F(/),则
返回 0x005C(反斜杠)与 UTF16EncodeCodePoint (cp )
的字符串拼接。
否则,如果 cp 在 表
67 的“Code Point”列中,则
返回 0x005C(反斜杠)与该行“ControlEscape”列字符串的字符串拼接。
令 otherPunctuators 为字符串 ",-=<>#&!%:;@~'`" 与 0x0022(引号)。
令 toEscape 为 StringToCodePoints (otherPunctuators )。
如果 toEscape 包含 cp ,或 cp 匹配 WhiteSpace 、LineTerminator ,或
cp 与 前导代理项 或尾随代理项 数值相同,则
令 cpNum 为 cp 的数值。
如果 cpNum ≤ 0xFF,则
令 hex 为 Number::toString (𝔽 (cpNum ), 16)。
返回 0x005C(反斜杠)、"x" 及 StringPad (hex ,
2, "0", start ) 的字符串拼接。
令 escaped 为空字符串。
令 codeUnits 为 UTF16EncodeCodePoint (cp )。
对于 codeUnits 中每个 code unit cu ,执行
设置 escaped 为 escaped 与 UnicodeEscape (cu )
的字符串拼接。
返回 escaped 。
返回 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 访问器函数调用时执行如下步骤:
返回 this 值。
此函数的 "name" 属性值为 "get [Symbol.species]" 。
注
RegExp 原型方法通常使用其 this 值的 构造函数 来创建派生对象。但子类 构造函数
可以通过重定义其 %Symbol.species% 属性来覆盖此默认行为。
22.2.6 RegExp 原型对象的属性
RegExp 原型对象 :
即 %RegExp.prototype% 。
是一个 普通对象 。
不是 RegExp 实例,不具有 [[RegExpMatcher]] 内部插槽,也没有 RegExp 实例对象的其他内部插槽。
拥有 [[Prototype]] 内部插槽,其值为 %Object.prototype% 。
注
RegExp 原型对象自身没有 "valueOf" 属性,但它从 Object 原型对象
继承了 "valueOf" 属性。
22.2.6.1 RegExp.prototype.constructor
RegExp.prototype.constructor
的初始值为 %RegExp% 。
22.2.6.2 RegExp.prototype.exec ( string )
该方法在 string 中搜索正则表达式的匹配项,并返回包含匹配结果的数组,若 string 不匹配则返回
null 。
调用时执行如下步骤:
令 R 为 this 值。
执行 ? RequireInternalSlot (R ,
[[RegExpMatcher]] )。
令 S 为 ? ToString (string )。
返回 ? RegExpBuiltinExec (R ,
S )。
22.2.6.3 get RegExp.prototype.dotAll
RegExp.prototype.dotAll
是一个 访问器属性 ,其 set 访问器函数为
undefined 。get 访问器函数调用时执行如下步骤:
令 R 为 this 值。
令 cu 为码元 0x0073(小写字母 s)。
返回 ? RegExpHasFlag (R ,
cu )。
22.2.6.4 get RegExp.prototype.flags
RegExp.prototype.flags
是一个 访问器属性 ,其 set 访问器函数为
undefined 。get 访问器函数调用时执行如下步骤:
令 R 为 this 值。
如果 R 不是对象 ,抛出 TypeError
异常。
令 codeUnits 为一个新的空 List 。
令 hasIndices 为 ToBoolean (? Get (R ,
"hasIndices" ))。
如果 hasIndices 为 true ,将码元 0x0064(小写字母 d)添加到
codeUnits 。
令 global 为 ToBoolean (? Get (R ,
"global" ))。
如果 global 为 true ,将码元 0x0067(g)添加到
codeUnits 。
令 ignoreCase 为 ToBoolean (? Get (R ,
"ignoreCase" ))。
如果 ignoreCase 为 true ,将码元 0x0069(i)添加到
codeUnits 。
令 multiline 为 ToBoolean (? Get (R ,
"multiline" ))。
如果 multiline 为 true ,将码元 0x006D(m)添加到
codeUnits 。
令 dotAll 为 ToBoolean (? Get (R ,
"dotAll" ))。
如果 dotAll 为 true ,将码元 0x0073(s)添加到
codeUnits 。
令 unicode 为 ToBoolean (? Get (R ,
"unicode" ))。
如果 unicode 为 true ,将码元 0x0075(u)添加到
codeUnits 。
令 unicodeSets 为 ToBoolean (? Get (R ,
"unicodeSets" ))。
如果 unicodeSets 为 true ,将码元 0x0076(v)添加到
codeUnits 。
令 sticky 为 ToBoolean (? Get (R ,
"sticky" ))。
如果 sticky 为 true ,将码元 0x0079(y)添加到
codeUnits 。
返回由 List
codeUnits 组成的字符串;若 codeUnits 为空,则返回空字符串。
22.2.6.4.1 RegExpHasFlag ( R , codeUnit
)
抽象操作 RegExpHasFlag 接收参数 R (ECMAScript
语言值 )和 codeUnit (码元),返回一个 包含 布尔值或
undefined 的正常完成,或 抛出完成 。调用时执行如下步骤:
如果 R 不是对象 ,抛出
TypeError 异常。
如果 R 没有 [[OriginalFlags]] 内部插槽,则
如果 SameValue (R ,
%RegExp.prototype% )
为 true ,返回 undefined 。
否则,抛出 TypeError 异常。
令 flags 为 R .[[OriginalFlags]] 。
如果 flags 包含 codeUnit ,返回 true 。
返回 false 。
22.2.6.5 get RegExp.prototype.global
RegExp.prototype.global
是一个 访问器属性 ,其 set 访问器函数为
undefined 。get 访问器函数调用时执行如下步骤:
令 R 为 this 值。
令 cu 为码元 0x0067(g)。
返回 ? RegExpHasFlag (R ,
cu )。
22.2.6.6 get RegExp.prototype.hasIndices
RegExp.prototype.hasIndices
是一个 访问器属性 ,其 set 访问器函数为
undefined 。get 访问器函数调用时执行如下步骤:
令 R 为 this 值。
令 cu 为码元 0x0064(d)。
返回 ? RegExpHasFlag (R ,
cu )。
22.2.6.7 get RegExp.prototype.ignoreCase
RegExp.prototype.ignoreCase
是一个 访问器属性 ,其 set 访问器函数为
undefined 。get 访问器函数调用时执行如下步骤:
令 R 为 this 值。
令 cu 为码元 0x0069(i)。
返回 ? RegExpHasFlag (R ,
cu )。
22.2.6.8 RegExp.prototype [ %Symbol.match% ] ( string
)
该方法调用时执行如下步骤:
令 rx 为 this 值。
如果 rx 不是对象 ,抛出 TypeError
异常。
令 S 为 ? ToString (string )。
令 flags 为 ? ToString (? Get (rx ,
"flags" ))。
如果 flags 不包含 "g" ,则
返回 ? RegExpExec (rx ,
S )。
否则,
如果 flags 包含 "u" 或 flags 包含
"v" ,令 fullUnicode 为
true 。否则,令 fullUnicode 为
false 。
执行 ? Set (rx ,
"lastIndex" , +0 𝔽 ,
true )。
令 A 为 ! ArrayCreate (0)。
令 n 为 0。
重复,
令 result 为 ? RegExpExec (rx ,
S )。
如果 result 为 null ,则
如果 n = 0,返回 null 。
返回 A 。
否则,
令 matchStr 为 ? ToString (?
Get (result ,
"0" ))。
执行 ! CreateDataPropertyOrThrow (A ,
! ToString (𝔽 (n )),
matchStr )。
如果 matchStr 是空字符串,则
令 thisIndex 为 ℝ (?
ToLength (?
Get (rx ,
"lastIndex" )))。
令 nextIndex 为 AdvanceStringIndex (S ,
thisIndex , fullUnicode )。
执行 ? Set (rx ,
"lastIndex" , 𝔽 (nextIndex ),
true )。
设置 n 为 n + 1。
该方法的 "name" 属性值为 "[Symbol.match]" 。
注
%Symbol.match% 属性被 IsRegExp
抽象操作用于识别具有正则表达式基本行为的对象。如果缺少 %Symbol.match%
属性,或该属性的值经布尔转换不是 true ,则表明该对象不应被当作正则表达式对象使用。
22.2.6.9 RegExp.prototype [ %Symbol.matchAll% ] (
string )
该方法调用时执行如下步骤:
令 R 为 this 值。
如果 R 不是对象 ,抛出 TypeError
异常。
令 S 为 ? ToString (string )。
令 C 为 ? SpeciesConstructor (R ,
%RegExp% )。
令 flags 为 ? ToString (? Get (R ,
"flags" ))。
令 matcher 为 ? Construct (C ,
« R ,
flags »)。
令 lastIndex 为 ? ToLength (? Get (R ,
"lastIndex" ))。
执行 ? Set (matcher ,
"lastIndex" , lastIndex , true )。
如果 flags 包含 "g" ,令 global 为
true 。
否则,令 global 为 false 。
如果 flags 包含 "u" 或 flags 包含
"v" ,令 fullUnicode 为 true 。
否则,令 fullUnicode 为 false 。
返回 CreateRegExpStringIterator (matcher ,
S , global , fullUnicode )。
该方法的 "name" 属性值为 "[Symbol.matchAll]" 。
22.2.6.10 get RegExp.prototype.multiline
RegExp.prototype.multiline
是一个 访问器属性 ,其 set 访问器函数为
undefined 。get 访问器函数调用时执行如下步骤:
令 R 为 this 值。
令 cu 为码元 0x006D(m)。
返回 ? RegExpHasFlag (R ,
cu )。
22.2.6.11 RegExp.prototype [ %Symbol.replace% ] (
string , replaceValue )
该方法调用时执行如下步骤:
令 rx 为 this 值。
如果 rx 不是对象 ,抛出 TypeError
异常。
令 S 为 ? ToString (string )。
令 lengthS 为 S 的长度。
令 functionalReplace 为 IsCallable (replaceValue )。
如果 functionalReplace 为 false ,则
设置 replaceValue 为 ? ToString (replaceValue )。
令 flags 为 ? ToString (? Get (rx ,
"flags" ))。
如果 flags 包含 "g" ,令 global 为
true ;否则 global 为 false 。
如果 global 为 true ,则
执行 ? Set (rx ,
"lastIndex" , +0 𝔽 ,
true )。
令 results 为一个新的空 List 。
令 done 为 false 。
重复,直到 done 为 false ,
令 result 为 ? RegExpExec (rx ,
S )。
如果 result 为 null ,则
设置 done 为 true 。
否则,
将 result 添加到 results 。
如果 global 为 false ,则
设置 done 为 true 。
否则,
令 matchStr 为 ? ToString (?
Get (result ,
"0" ))。
如果 matchStr 是空字符串,则
令 thisIndex 为 ℝ (?
ToLength (?
Get (rx ,
"lastIndex" )))。
如果 flags 包含 "u" 或
flags 包含 "v" ,令
fullUnicode 为 true ;否则
fullUnicode 为 false 。
令 nextIndex 为 AdvanceStringIndex (S ,
thisIndex , fullUnicode )。
执行 ? Set (rx ,
"lastIndex" , 𝔽 (nextIndex ),
true )。
令 accumulatedResult 为空字符串。
令 nextSourcePosition 为 0。
对于 results 中的每个元素 result ,执行
令 resultLength 为 ? LengthOfArrayLike (result )。
令 nCaptures 为 max (resultLength - 1, 0)。
令 matched 为 ? ToString (?
Get (result ,
"0" ))。
令 matchLength 为 matched 的长度。
令 position 为 ? ToIntegerOrInfinity (? Get (result ,
"index" ))。
将 position 限制在 0 到 lengthS 之间。
令 captures 为一个新的空 List 。
令 n 为 1。
重复,直到 n ≤ nCaptures ,
令 capN 为 ? Get (result ,
! ToString (𝔽 (n )))。
如果 capN 不为 undefined ,则
设置 capN 为 ? ToString (capN )。
将 capN 添加到 captures 。
注:当 n = 1 时,上一步将第一个元素放入 captures (索引 0)。更一般地,第
n 个捕获组(第 n 对括号捕获的字符)在 captures [n - 1]。
设置 n 为 n + 1。
令 namedCaptures 为 ? Get (result ,
"groups" )。
如果 functionalReplace 为 true ,则
令 replacerArgs 为 « matched
»、captures 和 « 𝔽 (position ),
S » 的列表拼接。
如果 namedCaptures 不为 undefined ,则
将 namedCaptures 添加到 replacerArgs 。
令 replacementValue 为 ? Call (replaceValue ,
undefined , replacerArgs )。
令 replacementString 为 ? ToString (replacementValue )。
否则,
如果 namedCaptures 不为 undefined ,则
设置 namedCaptures 为 ? ToObject (namedCaptures )。
令 replacementString 为 ? GetSubstitution (matched ,
S , position , captures ,
namedCaptures , replaceValue )。
如果 position ≥ nextSourcePosition ,则
注:position 通常不会倒退。如果发生,说明是行为异常的 RegExp 子类或通过副作用改变了 global
标志或 rx 的其它特性,此时对应替换会被忽略。
设置 accumulatedResult 为
accumulatedResult 、S 的
nextSourcePosition 到 position 子串、和
replacementString 的字符串拼接。
设置 nextSourcePosition 为 position +
matchLength 。
如果 nextSourcePosition ≥ lengthS ,返回
accumulatedResult 。
返回 accumulatedResult 与 S 从 nextSourcePosition
开始的子串的字符串拼接。
该方法的 "name" 属性值为 "[Symbol.replace]" 。
22.2.6.12 RegExp.prototype [ %Symbol.search% ] (
string )
该方法调用时执行如下步骤:
令 rx 为 this 值。
如果 rx 不是对象 ,抛出 TypeError
异常。
令 S 为 ? ToString (string )。
令 previousLastIndex 为 ? Get (rx ,
"lastIndex" )。
如果 previousLastIndex 不为 +0 𝔽 ,则
执行 ? Set (rx ,
"lastIndex" , +0 𝔽 ,
true )。
令 result 为 ? RegExpExec (rx , S )。
令 currentLastIndex 为 ? Get (rx ,
"lastIndex" )。
如果 SameValue (currentLastIndex ,
previousLastIndex ) 为 false ,则
执行 ? Set (rx ,
"lastIndex" , previousLastIndex ,
true )。
如果 result 为 null ,返回
-1 𝔽 。
返回 ? Get (result ,
"index" )。
该方法的 "name" 属性值为 "[Symbol.search]" 。
注
本 RegExp 对象的 "lastIndex" 和 "global"
属性在执行搜索时会被忽略,并且 "lastIndex" 属性保持不变。
22.2.6.13 get RegExp.prototype.source
RegExp.prototype.source
是一个 访问器属性 ,其 set 访问器函数为
undefined 。get 访问器函数调用时执行如下步骤:
令 R 为 this 值。
如果 R 不是对象 ,抛出 TypeError
异常。
如果 R 没有 [[OriginalSource]] 内部插槽,则
如果 SameValue (R ,
%RegExp.prototype% )
为 true ,返回 "(?:)" 。
否则,抛出 TypeError 异常。
断言 :R 拥有 [[OriginalFlags]] 内部插槽。
令 src 为 R .[[OriginalSource]] 。
令 flags 为 R .[[OriginalFlags]] 。
返回 EscapeRegExpPattern (src ,
flags )。
22.2.6.13.1 EscapeRegExpPattern ( P , F
)
抽象操作 EscapeRegExpPattern 接收参数 P (字符串)和 F (字符串),返回一个字符串。调用时执行如下步骤:
如果 F 包含 "v" ,则
令 patternSymbol 为 Pattern [+UnicodeMode,
+UnicodeSetsMode] 。
否则如果 F 包含 "u" ,则
令 patternSymbol 为 Pattern [+UnicodeMode,
~UnicodeSetsMode] 。
否则:
令 patternSymbol 为 Pattern [~UnicodeMode,
~UnicodeSetsMode] 。
令 S 为形式为 patternSymbol 的字符串,其内容等价于将 P 按 UTF-16
编码的 Unicode 码点解释后得到的模式,并对部分码点按下述方式转义。S 可能与 P 相同,也可能不同;但对
S 作为 patternSymbol 求值所得的 抽象闭包 必须与构造对象的 [[RegExpMatcher]] 内部插槽给出的 抽象闭包 行为一致。对同一 P 和
F 多次调用本操作,结果必须一致。
pattern 中的 /
及所有 LineTerminator 码点须在
S 中转义,以确保 字符串拼接
"/" 、S 、"/" 和 F 可作为
RegularExpressionLiteral
被解析,并与构造的正则表达式行为一致。如 P 为 "/" ,则 S 可为
"\/" 或 "\u002F" ,但不能为
"/" ,否则 ///
后接 F 会被解析为 单行注释 而不是
正则表达式字面量 。若
P 为空字符串,则 S 可为 "(?:)" 。
返回 S 。
注
尽管名字类似,RegExp.escape
与 EscapeRegExpPattern
并不执行类似操作。前者用于将字符串转义为可在模式中使用的内容,后者用于将模式转义为可作为字符串表示。
22.2.6.14 RegExp.prototype [ %Symbol.split% ] (
string , limit )
注 1
该方法返回一个数组,数组中存储了将 string 转换为字符串后的子串。这些子串是通过从左到右搜索 this
值正则表达式的匹配项确定的;这些匹配项不属于返回数组中的任何字符串,而是将字符串拆分开。
this
值可以是空正则表达式,也可以是能够匹配空字符串的正则表达式。在这种情况下,正则表达式不会匹配输入字符串开头或结尾的空子串,也不会匹配前一个分隔符匹配末尾的空子串。(例如,如果正则表达式匹配空字符串,则字符串会被拆分为单个码元元素;结果数组长度等于字符串长度,每个子串只包含一个码元。)某个索引处只考虑第一次匹配,即使回溯能得到非空子串匹配也不会采纳。(例如,/a*?/[Symbol.split]("ab")
的结果是 ["a", "b"]
,而 /a*/[Symbol.split]("ab")
的结果是
["","b"]
。)
如果 string 是(或转换为)空字符串,结果取决于正则表达式是否能匹配空字符串。如果能,结果数组无元素;否则,结果数组含一个元素,即空字符串。
如果正则表达式含有捕获括号,则每次 separator 匹配时,括号捕获的结果(包括
undefined )会被拼接进输出数组。例如,
/<(\/)?([^<> ]+)>/[Symbol.split]("A<B > bold</B > and<CODE > coded</CODE > ")
结果为数组
["A" , undefined , "B" , "bold" , "/" , "B" , "and" , undefined , "CODE" , "coded" , "/" , "CODE" , "" ]
如果 limit 不为 undefined ,则输出数组会被截断为不多于 limit
个元素。
该方法调用时执行如下步骤:
令 rx 为 this 值。
如果 rx 不是对象 ,抛出 TypeError
异常。
令 S 为 ? ToString (string )。
令 C 为 ? SpeciesConstructor (rx ,
%RegExp% )。
令 flags 为 ? ToString (? Get (rx ,
"flags" ))。
如果 flags 包含 "u" 或 flags 包含
"v" ,令 unicodeMatching 为 true 。
否则,令 unicodeMatching 为 false 。
如果 flags 包含 "y" ,令 newFlags 为
flags 。
否则,令 newFlags 为 flags 与 "y" 的字符串拼接。
令 splitter 为 ? Construct (C ,
« rx ,
newFlags »)。
令 A 为 ! ArrayCreate (0)。
令 lengthA 为 0。
如果 limit 是 undefined ,令 lim 为 232
- 1;否则,令 lim 为 ℝ (? ToUint32 (limit ))。
如果 lim = 0,返回 A 。
如果 S 是空字符串,则
令 z 为 ? RegExpExec (splitter ,
S )。
如果 z 不为 null ,返回 A 。
执行 ! CreateDataPropertyOrThrow (A ,
"0" , S )。
返回 A 。
令 size 为 S 的长度。
令 p 为 0。
令 q 为 p 。
重复,直到 q < size ,
执行 ? Set (splitter ,
"lastIndex" , 𝔽 (q ),
true )。
令 z 为 ? RegExpExec (splitter ,
S )。
如果 z 为 null ,则
设置 q 为 AdvanceStringIndex (S ,
q , unicodeMatching )。
否则,
令 e 为 ℝ (? ToLength (? Get (splitter ,
"lastIndex" )))。
将 e 限制为不大于 size 。
如果 e = p ,则
设置 q 为 AdvanceStringIndex (S ,
q , unicodeMatching )。
否则,
令 T 为 substring of
S 从 p 到 q 。
执行 ! CreateDataPropertyOrThrow (A ,
! ToString (𝔽 (lengthA )),
T )。
设置 lengthA 为 lengthA + 1。
如果 lengthA = lim ,返回 A 。
设置 p 为 e 。
令 numberOfCaptures 为 ? LengthOfArrayLike (z )。
将 numberOfCaptures 限制为
numberOfCaptures - 1 与 0 之间的最大值。
令 i 为 1。
重复,直到 i ≤ numberOfCaptures ,
令 nextCapture 为 ? Get (z ,
! ToString (𝔽 (i )))。
执行 ! CreateDataPropertyOrThrow (A ,
! ToString (𝔽 (lengthA )),
nextCapture )。
设置 i 为 i + 1。
设置 lengthA 为 lengthA + 1。
如果 lengthA = lim ,返回
A 。
设置 q 为 p 。
令 T 为 substring of S 从 p 到
size 。
执行 ! CreateDataPropertyOrThrow (A ,
! ToString (𝔽 (lengthA )),
T )。
返回 A 。
该方法的 "name" 属性值为 "[Symbol.split]" 。
注 2
该方法会忽略本 RegExp 对象的 "global" 和 "sticky" 属性值。
22.2.6.15 get RegExp.prototype.sticky
RegExp.prototype.sticky
是一个 访问器属性 ,其 set 访问器函数为
undefined 。get 访问器函数调用时执行如下步骤:
令 R 为 this 值。
令 cu 为码元 0x0079(y)。
返回 ? RegExpHasFlag (R ,
cu )。
22.2.6.16 RegExp.prototype.test ( S )
该方法调用时执行如下步骤:
令 R 为 this 值。
如果 R 不是对象 ,抛出 TypeError
异常。
令 string 为 ? ToString (S )。
令 match 为 ? RegExpExec (R ,
string )。
如果 match 不为 null ,返回 true ;否则返回
false 。
22.2.6.17 RegExp.prototype.toString ( )
令 R 为 this 值。
如果 R 不是对象 ,抛出 TypeError
异常。
令 pattern 为 ? ToString (? Get (R ,
"source" ))。
令 flags 为 ? ToString (? Get (R ,
"flags" ))。
令 result 为 字符串拼接
"/" 、pattern 、"/" 和 flags 。
返回 result 。
注
返回的字符串具有 RegularExpressionLiteral
的形式,求值后是另一个行为与本对象一致的 RegExp 对象。
22.2.6.18 get RegExp.prototype.unicode
RegExp.prototype.unicode
是一个 访问器属性 ,其 set 访问器函数为
undefined 。get 访问器函数调用时执行如下步骤:
令 R 为 this 值。
令 cu 为码元 0x0075(u)。
返回 ? RegExpHasFlag (R ,
cu )。
22.2.6.19 get RegExp.prototype.unicodeSets
RegExp.prototype.unicodeSets
是一个 访问器属性 ,其 set 访问器函数为
undefined 。get 访问器函数调用时执行如下步骤:
令 R 为 this 值。
令 cu 为码元 0x0076(v)。
返回 ? RegExpHasFlag (R ,
cu )。
22.2.7 正则匹配的抽象操作
22.2.7.1 RegExpExec ( R , S )
抽象操作 RegExpExec 接收参数 R (对象)和 S (字符串),返回 包含 对象或
null 的正常完成,或 抛出完成 。调用时执行如下步骤:
令 exec 为 ? Get (R ,
"exec" )。
如果 IsCallable (exec ) 为
true ,则
令 result 为 ? Call (exec ,
R , « S »)。
如果 result 不是对象 且 result 不是
null ,抛出 TypeError 异常。
返回 result 。
执行 ? RequireInternalSlot (R ,
[[RegExpMatcher]] )。
返回 ? RegExpBuiltinExec (R ,
S )。
注
如果未找到可调用的 "exec"
属性,本算法会退回内建正则匹配算法。这为针对早期版本编写的代码提供了兼容行为,此前大多数使用正则表达式的内建算法不会动态查找
"exec" 属性。
22.2.7.2 RegExpBuiltinExec ( R , S )
抽象操作 RegExpBuiltinExec 接收参数 R (初始化后的 RegExp 实例)和 S (字符串),返回 包含 一个 数组异类对象 或 null 的正常完成,或
抛出完成 。调用时执行如下步骤:
令 length 为 S 的长度。
令 lastIndex 为 ℝ (? ToLength (? Get (R ,
"lastIndex" )))。
令 flags 为 R .[[OriginalFlags]] 。
如果 flags 包含 "g" ,令 global 为
true ;否则为 false 。
如果 flags 包含 "y" ,令 sticky 为
true ;否则为 false 。
如果 flags 包含 "d" ,令 hasIndices 为
true ;否则为 false 。
如果 global 为 false 且 sticky 为
false ,将 lastIndex 设为 0。
令 matcher 为 R .[[RegExpMatcher]] 。
如果 flags 包含 "u" 或 flags 包含
"v" ,令 fullUnicode 为 true ;否则为
false 。
令 matchSucceeded 为 false 。
如果 fullUnicode 为 true ,令 input 为 StringToCodePoints (S );否则,令
input 为包含 S 各码元的 List 。
注:input 的每个元素都被视为一个字符。
重复,直到 matchSucceeded 为 false ,
如果 lastIndex > length ,则
如果 global 或 sticky 为 true ,则
执行 ? Set (R ,
"lastIndex" ,
+0 𝔽 ,
true )。
返回 null 。
令 inputIndex 为 S 索引 lastIndex 处对应
input 的下标。
令 r 为 matcher (input ,
inputIndex )。
如果 r 为 failure ,则
如果 sticky 为 true ,则
执行 ? Set (R ,
"lastIndex" ,
+0 𝔽 ,
true )。
返回 null 。
将 lastIndex 设为 AdvanceStringIndex (S ,
lastIndex , fullUnicode )。
否则,
断言 :r 是 MatchState 。
设置 matchSucceeded 为 true 。
令 e 为 r .[[EndIndex]] 。
如果 fullUnicode 为 true ,则将 e 设为 GetStringIndex (S ,
e )。
如果 global 或 sticky 为 true ,则
执行 ? Set (R ,
"lastIndex" , 𝔽 (e ),
true )。
令 n 为 r .[[Captures]] 的元素数。
断言 :n = R .[[RegExpRecord]] .[[CapturingGroupsCount]] 。
断言 :n < 232 - 1。
令 A 为 ! ArrayCreate (n + 1)。
断言 :A 的 "length"
数学值为 n + 1。
执行 ! CreateDataPropertyOrThrow (A ,
"index" , 𝔽 (lastIndex ))。
执行 ! CreateDataPropertyOrThrow (A ,
"input" , S )。
令 match 为 Match Record { [[StartIndex]] : lastIndex , [[EndIndex]] : e }。
令 indices 为一个新的空 List 。
令 groupNames 为一个新的空 List 。
将 match 添加到 indices 。
令 matchedSubstr 为 GetMatchString (S ,
match )。
执行 ! CreateDataPropertyOrThrow (A ,
"0" , matchedSubstr )。
如果 R 包含 GroupName ,
令 groups 为 OrdinaryObjectCreate (null )。
令 hasGroups 为 true 。
否则,
令 groups 为 undefined 。
令 hasGroups 为 false 。
执行 ! CreateDataPropertyOrThrow (A ,
"groups" , groups )。
令 matchedGroupNames 为一个新的空 List 。
对于所有 1 ≤ i ≤ n 的整数 i ,升序执行
令 captureI 为 r .[[Captures]]
的第 i 个元素。
如果 captureI 为 undefined ,
令 capturedValue 为 undefined 。
将 undefined 添加到 indices 。
否则,
令 captureStart 为 captureI .[[StartIndex]] 。
令 captureEnd 为 captureI .[[EndIndex]] 。
如果 fullUnicode 为 true ,
设置 captureStart 为 GetStringIndex (S ,
captureStart )。
设置 captureEnd 为 GetStringIndex (S ,
captureEnd )。
令 capture 为 Match
Record { [[StartIndex]] : captureStart ,
[[EndIndex]] : captureEnd }。
令 capturedValue 为 GetMatchString (S ,
capture )。
将 capture 添加到 indices 。
执行 ! CreateDataPropertyOrThrow (A ,
! ToString (𝔽 (i )),
capturedValue )。
如果 R 的第 i 个捕获带有 GroupName ,
令 s 为该 GroupName 的 CapturingGroupName 。
如果 matchedGroupNames 包含 s ,
断言 :capturedValue
为 undefined 。
将 undefined 添加到 groupNames 。
否则,
如果 capturedValue 不为
undefined ,将 s 添加到
matchedGroupNames 。
注:如有多个同名分组,groups 可能已有属性 s 。但因 groups
是普通对象,其属性均为可写数据属性,CreateDataPropertyOrThrow 调用必然成功。
执行 ! CreateDataPropertyOrThrow (groups ,
s , capturedValue )。
将 s 添加到 groupNames 。
否则,
将 undefined 添加到 groupNames 。
如果 hasIndices 为 true ,
令 indicesArray 为 MakeMatchIndicesIndexPairArray (S ,
indices , groupNames , hasGroups )。
执行 ! CreateDataPropertyOrThrow (A ,
"indices" , indicesArray )。
返回 A 。
22.2.7.3 AdvanceStringIndex ( S , index ,
unicode )
抽象操作 AdvanceStringIndex 接收参数
S (字符串)、index (非负整数)、unicode (布尔值),返回一个整数。调用时执行如下步骤:
断言 :index ≤ 253 - 1。
如果 unicode 为 false ,返回 index + 1。
令 length 为 S 的长度。
如果 index + 1 ≥ length ,返回 index + 1。
令 cp 为 CodePointAt (S ,
index )。
返回 index + cp .[[CodeUnitCount]] 。
22.2.7.4 GetStringIndex ( S ,
codePointIndex )
抽象操作 GetStringIndex 接收参数 S (字符串)和 codePointIndex (非负整数),返回一个非负整数。它将
S 作为 UTF-16 编码码点序列,根据 6.1.4 ,返回与码点索引
codePointIndex 对应的码元索引,若不存在则返回 S 的长度。调用时执行如下步骤:
如果 S 是空字符串,返回 0。
令 len 为 S 的长度。
令 codeUnitCount 为 0。
令 codePointCount 为 0。
重复,直到 codeUnitCount < len ,
如果 codePointCount = codePointIndex ,返回
codeUnitCount 。
令 cp 为 CodePointAt (S ,
codeUnitCount )。
设置 codeUnitCount 为 codeUnitCount + cp .[[CodeUnitCount]] 。
设置 codePointCount 为 codePointCount + 1。
返回 len 。
22.2.7.5 匹配记录(Match Records)
匹配记录(Match Record) 是一种 Record
值,用于封装正则匹配或捕获的起止索引。
匹配记录的字段列于 表
72 。
表 72:Match Record 字段
字段名
值
含义
[[StartIndex]]
非负 整数
匹配开始(包含)的字符串起始码元数。
[[EndIndex]]
一个 整数 ,且 ≥ [[StartIndex]]
匹配结束(不含)的字符串起始码元数。
22.2.7.6 GetMatchString ( S , match )
抽象操作 GetMatchString 接收参数 S (字符串)和 match (Match
Record ),返回一个字符串。调用时执行如下步骤:
断言 :match .[[StartIndex]] ≤ match .[[EndIndex]] ≤ S 的长度。
返回 S 从 match .[[StartIndex]] 到
match .[[EndIndex]] 的 子串 。
22.2.7.7 GetMatchIndexPair ( S , match )
抽象操作 GetMatchIndexPair 接收参数 S (字符串)和 match (Match
Record ),返回一个数组。调用时执行如下步骤:
断言 :match .[[StartIndex]] ≤ match .[[EndIndex]] ≤ S 的长度。
返回 CreateArrayFromList («𝔽 (match .[[StartIndex]] ), 𝔽 (match .[[EndIndex]] )»)。
22.2.7.8 MakeMatchIndicesIndexPairArray ( S ,
indices , groupNames , hasGroups )
抽象操作 MakeMatchIndicesIndexPairArray 接收参数 S (字符串)、indices (List ,元素为 Match
Records 或
undefined )、groupNames (List ,元素为字符串或
undefined )、hasGroups (布尔值),返回一个数组。调用时执行如下步骤:
令 n 为 indices 的元素数。
断言 :n < 232 - 1。
断言 :groupNames 有 n - 1
个元素。
注:groupNames 列表中的元素与 indices 列表自 indices [1] 起一一对应。
令 A 为 ! ArrayCreate (n )。
如果 hasGroups 为 true ,
令 groups 为 OrdinaryObjectCreate (null )。
否则,
令 groups 为 undefined 。
执行 ! CreateDataPropertyOrThrow (A ,
"groups" , groups )。
对于 0 ≤ i < n 的每个整数 i ,升序执行
令 matchIndices 为 indices [i ]。
如果 matchIndices 不为 undefined ,
令 matchIndexPair 为 GetMatchIndexPair (S ,
matchIndices )。
否则,
令 matchIndexPair 为 undefined 。
执行 ! CreateDataPropertyOrThrow (A ,
!ToString (𝔽 (i )),
matchIndexPair )。
如果 i > 0,
令 s 为 groupNames [i - 1]。
如果 s 不为 undefined ,
断言 :groups
不为 undefined 。
注:如有多个同名分组,groups 可能已经有 s 属性。因 groups
是普通对象,属性均为可写数据属性,CreateDataPropertyOrThrow 调用必然成功。
执行 ! CreateDataPropertyOrThrow (groups ,
s , matchIndexPair )。
返回 A 。
22.2.8 RegExp 实例的属性
RegExp 实例是 普通对象 ,继承自 RegExp 原型对象 。RegExp
实例具有内部插槽 [[OriginalSource]] 、[[OriginalFlags]] 、[[RegExpRecord]] 和 [[RegExpMatcher]] 。[[RegExpMatcher]] 插槽的值是该正则对象
模式 的 抽象闭包 表示。
注
在 ECMAScript 2015 之前,RegExp 实例被规范为拥有自身的数据属性 data properties
"source" 、"global" 、"ignoreCase"
和 "multiline" 。这些属性现在被规范为 RegExp.prototype
的 访问器属性 。
RegExp 实例还具有以下属性:
22.2.8.1 lastIndex
"lastIndex" 属性的值指定下次匹配时从字符串的哪个索引开始。使用时会被强制转换为 整数类型
Number (参见 22.2.7.2 )。该属性具有属性 { [[Writable]] : true , [[Enumerable]] : false , [[Configurable]] : false }。
22.2.9 RegExp 字符串迭代器对象
RegExp 字符串迭代器 是用于表示对某个特定字符串实例对象、针对某个特定 RegExp 实例对象进行迭代的对象。RegExp
字符串迭代器对象没有具名的 构造函数 ,而是通过调用某些 RegExp 实例对象的方法创建的。
22.2.9.1 CreateRegExpStringIterator ( R ,
S , global , fullUnicode )
抽象操作 CreateRegExpStringIterator 接收参数
R (对象)、S (字符串)、global (布尔值)、fullUnicode (布尔值),返回一个对象。调用时执行如下步骤:
令 iterator 为 OrdinaryObjectCreate (%RegExpStringIteratorPrototype% ,
« [[IteratingRegExp]] , [[IteratedString]] , [[Global]] ,
[[Unicode]] , [[Done]] »)。
设置 iterator .[[IteratingRegExp]] = R 。
设置 iterator .[[IteratedString]] = S 。
设置 iterator .[[Global]] = global 。
设置 iterator .[[Unicode]] =
fullUnicode 。
设置 iterator .[[Done]] = false 。
返回 iterator 。
22.2.9.2 %RegExpStringIteratorPrototype% 对象
%RegExpStringIteratorPrototype% 对象:
22.2.9.2.1 %RegExpStringIteratorPrototype%.next ( )
令 O 为 this 值。
如果 O 不是对象 ,抛出
TypeError 异常。
如果 O 不具有 RegExp
字符串迭代器 对象实例的所有内部插槽(见 22.2.9.3 ),抛出
TypeError 异常。
如果 O .[[Done]] 为 true ,
返回 CreateIteratorResultObject (undefined ,
true )。
令 R = O .[[IteratingRegExp]] 。
令 S = O .[[IteratedString]] 。
令 global = O .[[Global]] 。
令 fullUnicode = O .[[Unicode]] 。
令 match 为 ? RegExpExec (R ,
S )。
如果 match 为 null ,
设置 O .[[Done]] =
true 。
返回 CreateIteratorResultObject (undefined ,
true )。
如果 global 为 false ,
设置 O .[[Done]] =
true 。
返回 CreateIteratorResultObject (match ,
false )。
令 matchStr 为 ? ToString (?
Get (match ,
"0" ))。
如果 matchStr 是空字符串,
令 thisIndex 为 ℝ (? ToLength (? Get (R ,
"lastIndex" )))。
令 nextIndex 为 AdvanceStringIndex (S ,
thisIndex , fullUnicode )。
执行 ? Set (R ,
"lastIndex" , 𝔽 (nextIndex ),
true )。
返回 CreateIteratorResultObject (match ,
false )。
22.2.9.2.2 %RegExpStringIteratorPrototype% [
%Symbol.toStringTag% ]
%Symbol.toStringTag% 属性的初始值是字符串
"RegExp String Iterator" 。
该属性具有属性 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] : true }。
22.2.9.3 RegExp 字符串迭代器实例的属性
RegExp 字符串迭代器
实例是 普通对象 ,继承自 %RegExpStringIteratorPrototype%
内置对象。RegExp 字符串迭代器
实例初始时拥有 表 73 所列的内部插槽。
表 73:RegExp
字符串迭代器 实例的内部插槽
内部插槽
类型
描述
[[IteratingRegExp]]
对象
用于迭代的正则表达式。IsRegExp ([[IteratingRegExp]] ) 初始为
true 。
[[IteratedString]]
字符串
被迭代的字符串值。
[[Global]]
布尔值
指示 [[IteratingRegExp]] 是否为全局。
[[Unicode]]
布尔值
指示 [[IteratingRegExp]] 是否为 Unicode 模式。
[[Done]]
布尔值
指示迭代是否已完成。
23 索引集合
23.1 数组对象
数组是特殊对象 ,对某类属性名进行了特殊处理。关于此特殊处理的定义,见10.4.2 。
23.1.1 Array 构造函数
Array 构造函数 :
即 %Array% 。
是全局对象 的 "Array" 属性的初始值。
作为构造函数 调用时,会创建并初始化一个新的数组。
作为普通函数而不是构造函数 调用时,也会创建并初始化一个新的数组。因此,函数调用
Array(…)
等价于使用相同参数的对象创建表达式 new Array(…)
。
是一个其行为根据参数数量和类型而异的函数。
可用作类定义中 extends
子句的值。打算继承数组特殊行为的子类构造函数 ,必须包含对 Array 构造函数 的
super
调用,以初始化作为数组特殊对象 的子类实例。然而,大多数
Array.prototype
方法是泛型方法,不依赖于其 this 值为数组特殊对象 。
23.1.1.1 Array ( ...values )
当调用该函数时,执行以下步骤:
如果 NewTarget 为 undefined ,则令 newTarget 为活动函数对象 ;否则令
newTarget 为 NewTarget。
令 proto 为 ? GetPrototypeFromConstructor (newTarget ,
"%Array.prototype%" )。
令 numberOfArgs 为 values 中元素的数量。
如果 numberOfArgs = 0,则
返回 ! ArrayCreate (0,
proto )。
否则如果 numberOfArgs = 1,则
令 len 为 values [0]。
令 array 为 ! ArrayCreate (0,
proto )。
如果 len 不是数字类型 ,则
执行 ! CreateDataPropertyOrThrow (array ,
"0" , len )。
令 intLen 为 1 𝔽 。
否则,
令 intLen 为 ! ToUint32 (len )。
如果 SameValueZero (intLen ,
len ) 为 false ,则抛出
RangeError 异常。
执行 ! Set (array ,
"length" , intLen , true )。
返回 array 。
否则,
断言 :numberOfArgs ≥ 2。
令 array 为 ? ArrayCreate (numberOfArgs ,
proto )。
令 k 为 0。
重复,直到 k < numberOfArgs ,
令 Pk 为 ! ToString (𝔽 (k ))。
令 itemK 为 values [k ]。
执行 ! CreateDataPropertyOrThrow (array ,
Pk , itemK )。
令 k 为 k + 1。
断言 :array 的
"length" 属性的数学值为 numberOfArgs 。
返回 array 。
23.1.2 Array 构造函数的属性
Array 构造函数 :
23.1.2.1 Array.from ( items [ , mapper [ ,
thisArg ] ] )
当调用该方法时,执行以下步骤:
令 C 为 this 值。
如果 mapper 为 undefined ,则
令 mapping 为 false 。
否则,
如果 IsCallable (mapper )
为 false ,则抛出 TypeError 异常。
令 mapping 为 true 。
令 usingIterator 为 ? GetMethod (items , %Symbol.iterator% )。
如果 usingIterator 不为 undefined ,则
如果 IsConstructor (C )
为 true ,则
令 A 为 ? Construct (C )。
否则,
令 A 为 ! ArrayCreate (0)。
令 iteratorRecord 为 ? GetIteratorFromMethod (items ,
usingIterator )。
令 k 为 0。
重复,
如果 k ≥ 253 - 1,则
令 error 为 ThrowCompletion (新建的
TypeError 对象)。
返回 ? IteratorClose (iteratorRecord ,
error )。
令 Pk 为 ! ToString (𝔽 (k ))。
令 next 为 ? IteratorStepValue (iteratorRecord )。
如果 next 为 done ,则
执行 ? Set (A ,
"length" , 𝔽 (k ),
true )。
返回 A 。
如果 mapping 为 true ,则
令 mappedValue 为 Completion (Call (mapper ,
thisArg , « next , 𝔽 (k ) »))。
IfAbruptCloseIterator (mappedValue ,
iteratorRecord )。
否则,
令 mappedValue 为 next 。
令 defineStatus 为 Completion (CreateDataPropertyOrThrow (A ,
Pk , mappedValue ))。
IfAbruptCloseIterator (defineStatus ,
iteratorRecord )。
令 k 为 k + 1。
注:items 不是可迭代对象 ,因此假定其为类数组对象 。
令 arrayLike 为 ! ToObject (items )。
令 len 为 ? LengthOfArrayLike (arrayLike )。
如果 IsConstructor (C ) 为
true ,则
令 A 为 ? Construct (C , «
𝔽 (len ) »)。
否则,
令 A 为 ? ArrayCreate (len )。
令 k 为 0。
重复,直到 k < len ,
令 Pk 为 ! ToString (𝔽 (k ))。
令 kValue 为 ? Get (arrayLike ,
Pk )。
如果 mapping 为 true ,则
令 mappedValue 为 ? Call (mapper ,
thisArg , « kValue , 𝔽 (k )
»)。
否则,
令 mappedValue 为 kValue 。
执行 ? CreateDataPropertyOrThrow (A ,
Pk , mappedValue )。
令 k 为 k + 1。
执行 ? Set (A ,
"length" , 𝔽 (len ), true )。
返回 A 。
注
该方法是有意设计为泛型工厂方法;它不要求其 this 值为 Array 构造函数 。因此它可以被转移或继承到其它可用单一数字参数调用的构造函数 。
23.1.2.2 Array.isArray ( arg )
当调用该函数时,执行以下步骤:
返回 ? IsArray (arg )。
23.1.2.3 Array.of ( ...items )
当调用该方法时,执行以下步骤:
令 len 为 items 中元素的数量。
令 lenNumber 为 𝔽 (len )。
令 C 为 this 值。
如果 IsConstructor (C ) 为
true ,则
令 A 为 ? Construct (C , «
lenNumber »)。
否则,
令 A 为 ? ArrayCreate (len )。
令 k 为 0。
重复,直到 k < len ,
令 kValue 为 items [k ]。
令 Pk 为 ! ToString (𝔽 (k ))。
执行 ? CreateDataPropertyOrThrow (A ,
Pk , kValue )。
令 k 为 k + 1。
执行 ? Set (A ,
"length" , lenNumber , true )。
返回 A 。
注
该方法是有意设计为泛型工厂方法;它不要求其 this 值为 Array 构造函数 。因此它可以被转移或继承到其它可用单一数字参数调用的构造函数 。
23.1.2.4 Array.prototype
Array.prototype
的值为数组原型对象 。
该属性具有属性 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] : false }。
23.1.2.5 get Array [ %Symbol.species% ]
Array[%Symbol.species%]
是一个 访问器属性 ,其 set 访问器函数为
undefined 。其 get 访问器函数被调用时执行以下步骤:
返回 this 值。
该函数的 "name" 属性值为 "get [Symbol.species]" 。
注
数组原型方法通常使用其 this 值的 constructor
来创建派生对象。然而,子类构造函数 可以通过重写其 %Symbol.species% 属性来覆盖默认行为。
23.1.3 数组原型对象的属性
数组原型对象 :
即 %Array.prototype% 。
是数组特殊对象 ,并具有该类对象指定的内部方法。
具有一个 "length" 属性,其初始值为+0 𝔽 ,属性特性为 { [[Writable]] : true , [[Enumerable]] : false , [[Configurable]] : false }。
具有一个名为 [[Prototype]] 的内部槽,其值为 %Object.prototype% 。
注
数组原型对象被指定为数组特殊对象 ,以确保与 ECMAScript 2015 规范之前编写的
ECMAScript 代码兼容。
23.1.3.1 Array.prototype.at ( index )
令 O 为 ? ToObject (this 值)。
令 len 为 ? LengthOfArrayLike (O )。
令 relativeIndex 为 ? ToIntegerOrInfinity (index )。
如果 relativeIndex ≥ 0,则
令 k 为 relativeIndex 。
否则,
令 k 为 len + relativeIndex 。
如果 k < 0 或 k ≥ len ,返回
undefined 。
返回 ? Get (O , ! ToString (𝔽 (k )))。
23.1.3.2 Array.prototype.concat ( ...items )
该方法返回一个数组,包含该对象的数组元素后跟每个参数的数组元素。
调用时执行以下步骤:
令 O 为 ? ToObject (this 值)。
令 A 为 ? ArraySpeciesCreate (O , 0)。
令 n 为 0。
将 O 前置到 items 。
对 items 的每个元素 E ,执行
令 spreadable 为 ? IsConcatSpreadable (E )。
如果 spreadable 为 true ,则
令 len 为 ? LengthOfArrayLike (E )。
如果 n + len > 253 - 1,抛出
TypeError 异常。
令 k 为 0。
重复,直到 k < len ,
令 Pk 为 ! ToString (𝔽 (k ))。
令 exists 为 ? HasProperty (E ,
Pk )。
如果 exists 为 true ,则
令 subElement 为 ? Get (E ,
Pk )。
执行 ? CreateDataPropertyOrThrow (A ,
! ToString (𝔽 (n )),
subElement )。
令 n 为 n + 1。
令 k 为 k + 1。
否则,
注:E 作为单项加入而不是展开。
如果 n ≥ 253 - 1,抛出
TypeError 异常。
执行 ? CreateDataPropertyOrThrow (A ,
! ToString (𝔽 (n )), E )。
令 n 为 n + 1。
执行 ? Set (A ,
"length" , 𝔽 (n ), true )。
返回 A 。
该方法的 "length" 属性为 1 𝔽 。
注 1
在步骤 6 中显式设置
"length" 属性,是为了确保当 items 的最后一个非空元素有尾部空洞或 A
不是内建数组时长度正确。
注 2
该方法被设计为泛型;不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。
23.1.3.2.1 IsConcatSpreadable ( O )
抽象操作 IsConcatSpreadable 接收参数 O (一个 ECMAScript 语言值 ),并返回
包含 布尔值的正常完成,或
抛出完成 。调用时执行以下步骤:
如果 O 不是对象 ,返回
false 。
令 spreadable 为 ? Get (O ,
%Symbol.isConcatSpreadable% )。
如果 spreadable 不为 undefined ,返回 ToBoolean (spreadable )。
返回 ? IsArray (O )。
23.1.3.3 Array.prototype.constructor
Array.prototype.constructor
的初始值为 %Array% 。
23.1.3.4 Array.prototype.copyWithin ( target ,
start [ , end ] )
注 1
end 参数是可选的。如果未提供,则使用 this 值的长度。
注 2
如果 target 为负数,则视为 length +
target ,其中 length 是数组的长度。如果 start
为负数,则视为 length + start 。如果
end 为负数,则视为 length +
end 。
调用该方法时执行以下步骤:
令 O 为 ? ToObject (this 值)。
令 len 为 ? LengthOfArrayLike (O )。
令 relativeTarget 为 ? ToIntegerOrInfinity (target )。
如果 relativeTarget = -∞,令 to 为 0。
否则如果 relativeTarget < 0,令 to 为 max (len +
relativeTarget , 0)。
否则,令 to 为 min (relativeTarget ,
len )。
令 relativeStart 为 ? ToIntegerOrInfinity (start )。
如果 relativeStart = -∞,令 from 为 0。
否则如果 relativeStart < 0,令 from 为 max (len +
relativeStart , 0)。
否则,令 from 为 min (relativeStart ,
len )。
如果 end 为 undefined ,令 relativeEnd 为
len ;否则令 relativeEnd 为 ? ToIntegerOrInfinity (end )。
如果 relativeEnd = -∞,令 final 为 0。
否则如果 relativeEnd < 0,令 final 为 max (len +
relativeEnd , 0)。
否则,令 final 为 min (relativeEnd , len )。
令 count 为 min (final - from ,
len - to )。
如果 from < to 且 to < from +
count ,则
令 direction 为 -1。
设置 from 为 from + count - 1。
设置 to 为 to + count - 1。
否则,
令 direction 为 1。
重复,直到 count > 0,
令 fromKey 为 ! ToString (𝔽 (from ))。
令 toKey 为 ! ToString (𝔽 (to ))。
令 fromPresent 为 ? HasProperty (O ,
fromKey )。
如果 fromPresent 为 true ,则
令 fromValue 为 ? Get (O ,
fromKey )。
执行 ? Set (O ,
toKey , fromValue , true )。
否则,
断言 :fromPresent
为 false 。
执行 ? DeletePropertyOrThrow (O ,
toKey )。
设置 from 为 from + direction 。
设置 to 为 to + direction 。
设置 count 为 count - 1。
返回 O 。
注 3
该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。
23.1.3.5 Array.prototype.entries ( )
该方法调用时执行以下步骤:
令 O 为 ? ToObject (this 值)。
返回 CreateArrayIterator (O ,
key+value )。
23.1.3.6 Array.prototype.every ( callback [ ,
thisArg ] )
注 1
callback 应该是一个接受三个参数并返回可转换为布尔值的函数。every
会按升序对数组中实际存在的每个元素调用
callback 一次,直到遇到一个 callback 返回 false
的元素。如果找到这样的元素,every
会立即返回
false 。否则,every
返回
true 。callback 只会对数组中实际存在的元素调用,不会对数组中缺失的元素调用。
如果提供了 thisArg 参数,则每次调用 callback 时都会用作 this
值。如果未提供,则使用 undefined 。
callback 被调用时有三个参数:元素的值、元素的索引、被遍历的对象。
every
不会直接修改它所调用的对象,但该对象可能会被 callback 的调用修改。
every
处理的元素范围在第一次调用 callback 前就已确定。调用 every
之后添加到数组的元素不会被 callback 访问。如果数组中已存在的元素被修改,则传递给 callback 的值是在
every
访问该元素时的值;在 every
调用开始后被删除且尚未被访问的元素不会被访问。every
的行为类似于数学中的“全称量词”。特别地,对于空数组,它返回
true 。
该方法调用时执行以下步骤:
令 O 为 ? ToObject (this 值)。
令 len 为 ? LengthOfArrayLike (O )。
如果 IsCallable (callback ) 为
false ,抛出 TypeError 异常。
令 k 为 0。
重复,直到 k < len ,
令 Pk 为 ! ToString (𝔽 (k ))。
令 kPresent 为 ? HasProperty (O ,
Pk )。
如果 kPresent 为 true ,则
令 kValue 为 ? Get (O ,
Pk )。
令 testResult 为 ToBoolean (? Call (callback ,
thisArg , « kValue , 𝔽 (k ),
O »))。
如果 testResult 为 false ,返回
false 。
设置 k 为 k + 1。
返回 true 。
注 2
该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。
23.1.3.7 Array.prototype.fill ( value [ ,
start [ , end ] ] )
注 1
start 参数是可选的。如果未提供,则使用 +0 𝔽 。
end 参数是可选的。如果未提供,则使用 this 值的长度。
注 2
如果 start 为负数,则视为 length +
start ,其中 length 是数组的长度。如果 end 为负数,则视为
length + end 。
该方法调用时执行以下步骤:
令 O 为 ? ToObject (this 值)。
令 len 为 ? LengthOfArrayLike (O )。
令 relativeStart 为 ? ToIntegerOrInfinity (start )。
如果 relativeStart = -∞,令 k 为 0。
否则如果 relativeStart < 0,令 k 为 max (len +
relativeStart , 0)。
否则,令 k 为 min (relativeStart ,
len )。
如果 end 为 undefined ,令 relativeEnd 为
len ;否则令 relativeEnd 为 ? ToIntegerOrInfinity (end )。
如果 relativeEnd = -∞,令 final 为 0。
否则如果 relativeEnd < 0,令 final 为 max (len +
relativeEnd , 0)。
否则,令 final 为 min (relativeEnd , len )。
重复,直到 k < final ,
令 Pk 为 ! ToString (𝔽 (k ))。
执行 ? Set (O , Pk ,
value , true )。
令 k 为 k + 1。
返回 O 。
注 3
该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。
23.1.3.8 Array.prototype.filter ( callback [ ,
thisArg ] )
注 1
callback 应该是一个接受三个参数并返回可转换为布尔值的函数。filter
会按升序对数组中每个元素调用
callback 一次,并构造一个包含所有 callback 返回 true
的值的新数组。callback 只会对数组中实际存在的元素调用,不会对数组中缺失的元素调用。
如果提供了 thisArg 参数,则每次调用 callback 时都会用作 this
值。如果未提供,则使用 undefined 。
callback 被调用时有三个参数:元素的值、元素的索引、被遍历的对象。
filter
不会直接修改它所调用的对象,但该对象可能会被 callback 的调用修改。
filter
处理的元素范围在第一次调用 callback 前就已确定。调用 filter
之后添加到数组的元素不会被 callback 访问。如果数组中已存在的元素被修改,则传递给 callback 的值是在
filter
访问该元素时的值;在 filter
调用开始后被删除且尚未被访问的元素不会被访问。
该方法调用时执行以下步骤:
令 O 为 ? ToObject (this 值)。
令 len 为 ? LengthOfArrayLike (O )。
如果 IsCallable (callback ) 为
false ,抛出 TypeError 异常。
令 A 为 ? ArraySpeciesCreate (O , 0)。
令 k 为 0。
令 to 为 0。
重复,直到 k < len ,
令 Pk 为 ! ToString (𝔽 (k ))。
令 kPresent 为 ? HasProperty (O ,
Pk )。
如果 kPresent 为 true ,则
令 kValue 为 ? Get (O ,
Pk )。
令 selected 为 ToBoolean (? Call (callback ,
thisArg , « kValue , 𝔽 (k ),
O »))。
如果 selected 为 true ,则
执行 ? CreateDataPropertyOrThrow (A ,
! ToString (𝔽 (to )),
kValue )。
设置 to 为 to + 1。
设置 k 为 k + 1。
返回 A 。
注 2
该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。
23.1.3.9 Array.prototype.find ( predicate [ ,
thisArg ] )
注 1
该方法会按索引升序对数组的每个元素调用 predicate 一次,直到找到一个 predicate 返回可转换为
true 的值的元素。如果找到这样的元素,find
会立即返回该元素的值。否则,find
返回 undefined 。
更多信息见 FindViaPredicate 。
该方法调用时执行以下步骤:
令 O 为 ? ToObject (this 值)。
令 len 为 ? LengthOfArrayLike (O )。
令 findRec 为 ? FindViaPredicate (O ,
len , ascending , predicate ,
thisArg )。
返回 findRec .[[Value]] 。
注 2
该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。
23.1.3.10 Array.prototype.findIndex ( predicate [ ,
thisArg ] )
注 1
该方法会按索引升序对数组的每个元素调用 predicate 一次,直到找到一个 predicate 返回可转换为
true 的值的元素。如果找到这样的元素,findIndex
会立即返回该元素的索引。否则,findIndex
返回 -1。
更多信息见 FindViaPredicate 。
该方法调用时执行以下步骤:
令 O 为 ? ToObject (this 值)。
令 len 为 ? LengthOfArrayLike (O )。
令 findRec 为 ? FindViaPredicate (O ,
len , ascending , predicate ,
thisArg )。
返回 findRec .[[Index]] 。
注 2
该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。
23.1.3.11 Array.prototype.findLast ( predicate [ ,
thisArg ] )
注 1
该方法会按索引降序对数组的每个元素调用 predicate 一次,直到找到一个 predicate 返回可转换为
true 的值的元素。如果找到这样的元素,findLast
会立即返回该元素的值。否则,findLast
返回 undefined 。
更多信息见 FindViaPredicate 。
该方法调用时执行以下步骤:
令 O 为 ? ToObject (this 值)。
令 len 为 ? LengthOfArrayLike (O )。
令 findRec 为 ? FindViaPredicate (O ,
len , descending , predicate ,
thisArg )。
返回 findRec .[[Value]] 。
注 2
该方法被设计为泛型;它不要求其 this 值为数组对象。因此它可以转移到其他类型对象用作方法。
23.1.3.12 Array.prototype.findLastIndex ( predicate [
, thisArg ] )
注 1
该方法会按索引降序对数组的每个元素调用 predicate 一次,直到找到一个 predicate 返回可转换为
true 的值的元素。如果找到这样的元素,findLastIndex
会立即返回该元素的索引。否则,findLastIndex
返回 -1。
更多信息见 FindViaPredicate 。
该方法调用时执行以下步骤:
令 O 为 ? ToObject (this 值)。
令 len 为 ? LengthOfArrayLike (O )。
令 findRec 为 ? FindViaPredicate (O ,
len , descending , predicate ,
thisArg )。
返回 findRec .[[Index]] 。
注 2
该方法被设计为泛型;它不要求其 this 值为数组对象。因此它可以转移到其他类型对象用作方法。
23.1.3.12.1 FindViaPredicate ( O , len ,
direction , predicate , thisArg )
抽象操作 FindViaPredicate 接收参数 O (一个对象)、len (一个非负整数 )、direction (ascending
或 descending )、predicate (一个ECMAScript 语言值 )、和
thisArg (一个ECMAScript 语言值 ),返回一个包含字段
[[Index]] (一个整数 )和 [[Value]] (一个ECMAScript
语言值 )的记录 ,或抛出完成类型的
异常 。
O 应为类数组对象 或TypedArray 。该操作会按
direction 指示的顺序(升序或降序)对 O 的每个元素调用 predicate ,直到找到一个
predicate 返回可转换为 true
的值的元素。此时,该操作返回一个包含所找到元素索引和值的记录 。如果未找到这样的元素,则返回一个
记录 ,其索引为
-1 𝔽 ,值为 undefined 。
predicate 应为一个函数。对数组的每个元素调用时,传递三个参数:元素的值、元素的索引和被遍历的对象。其返回值会被转换为布尔值。
thisArg 会作为每次调用 predicate 时的 this 值。
该操作不会直接修改其调用的对象,但该对象可能会被 predicate 的调用修改。
处理的元素范围在首次调用 predicate 前(遍历开始前)就已确定。遍历后添加到数组的元素不会被 predicate
访问。如果数组中已存在的元素被修改,则传递给 predicate
的值为操作访问该元素时的值。在遍历开始后被删除且尚未被访问的元素依然会被访问,要么从原型获取,要么为 undefined 。
调用时执行以下步骤:
如果 IsCallable (predicate ) 为
false ,抛出 TypeError 异常。
如果 direction 是 ascending ,则
令 indices 为从 0(含)到 len (不含)区间内所有整数按升序排列的列表 。
否则,
令 indices 为从 0(含)到 len (不含)区间内所有整数按降序排列的列表 。
对于 indices 中的每个整数 k ,执行
令 Pk 为 ! ToString (𝔽 (k ))。
注:如果 O 是 TypedArray ,则下面对 Get
的调用会返回正常完成类型。
令 kValue 为 ? Get (O ,
Pk )。
令 testResult 为 ? Call (predicate ,
thisArg , « kValue , 𝔽 (k ),
O »)。
如果 ToBoolean (testResult )
为 true ,则返回 记录
{ [[Index]] : 𝔽 (k ), [[Value]] : kValue }。
返回 记录 {
[[Index]] : -1 𝔽 , [[Value]] : undefined }.
23.1.3.13 Array.prototype.flat ( [ depth ] )
该方法调用时执行以下步骤:
令 O 为 ? ToObject (this 值)。
令 sourceLen 为 ? LengthOfArrayLike (O )。
令 depthNum 为 1。
如果 depth 不等于 undefined ,则
设置 depthNum 为 ? ToIntegerOrInfinity (depth )。
如果 depthNum < 0,设置 depthNum 为 0。
令 A 为 ? ArraySpeciesCreate (O , 0)。
执行 ? FlattenIntoArray (A ,
O , sourceLen , 0, depthNum )。
返回 A 。
23.1.3.13.1 FlattenIntoArray ( target ,
source , sourceLen , start , depth [ ,
mapperFunction [ , thisArg ] ] )
抽象操作 FlattenIntoArray 接收参数
target (一个对象)、source (一个对象)、sourceLen (一个非负整数 )、start (一个非负整数 )、depth (一个非负整数 或+∞),可选参数
mapperFunction (一个函数对象 )、thisArg (一个ECMAScript 语言值 ),返回包含 非负整数 的正常完成,或抛出完成 。调用时执行以下步骤:
断言 :如果
mapperFunction 存在,则 IsCallable (mapperFunction )
为 true ,thisArg 存在,且 depth 为 1。
令 targetIndex 为 start 。
令 sourceIndex 为 +0 𝔽 。
重复,直到 ℝ (sourceIndex ) <
sourceLen ,
令 P 为 ! ToString (sourceIndex )。
令 exists 为 ? HasProperty (source ,
P )。
如果 exists 为 true ,则
令 element 为 ? Get (source ,
P )。
如果 mapperFunction 存在,则
设置 element 为 ? Call (mapperFunction ,
thisArg , « element ,
sourceIndex , source »)。
令 shouldFlatten 为 false 。
如果 depth > 0,则
设置 shouldFlatten 为 ? IsArray (element )。
如果 shouldFlatten 为 true ,则
如果 depth = +∞,令 newDepth 为 +∞。
否则,令 newDepth 为 depth - 1。
令 elementLen 为 ? LengthOfArrayLike (element )。
设置 targetIndex 为 ? FlattenIntoArray (target ,
element , elementLen ,
targetIndex , newDepth )。
否则,
如果 targetIndex ≥ 253 - 1,抛出
TypeError 异常。
执行 ? CreateDataPropertyOrThrow (target ,
! ToString (𝔽 (targetIndex )),
element )。
设置 targetIndex 为 targetIndex +
1。
设置 sourceIndex 为 sourceIndex +
1 𝔽 。
返回 targetIndex 。
23.1.3.14 Array.prototype.flatMap ( mapperFunction [
, thisArg ] )
该方法调用时执行以下步骤:
令 O 为 ? ToObject (this 值)。
令 sourceLen 为 ? LengthOfArrayLike (O )。
如果 IsCallable (mapperFunction )
为 false ,抛出 TypeError 异常。
令 A 为 ? ArraySpeciesCreate (O , 0)。
执行 ? FlattenIntoArray (A ,
O , sourceLen , 0, 1, mapperFunction ,
thisArg )。
返回 A 。
23.1.3.15 Array.prototype.forEach ( callback [ ,
thisArg ] )
注 1
callback 应该是一个接受三个参数的函数。forEach
对数组中实际存在的每个元素按升序调用
callback 一次。callback 只会对数组中实际存在的元素调用,不会对数组中缺失的元素调用。
如果提供了 thisArg 参数,则每次调用 callback 时都会用作 this
值。如果未提供,则使用 undefined 。
callback 被调用时有三个参数:元素的值、元素的索引、被遍历的对象。
forEach
不会直接修改它所调用的对象,但该对象可能会被 callback 的调用修改。
forEach
处理的元素范围在第一次调用 callback 前就已确定。调用 forEach
之后添加到数组的元素不会被 callback 访问。如果数组中已存在的元素被修改,则传递给 callback 的值是在
forEach
访问该元素时的值;在 forEach
调用开始后被删除且尚未被访问的元素不会被访问。
该方法调用时执行以下步骤:
令 O 为 ? ToObject (this 值)。
令 len 为 ? LengthOfArrayLike (O )。
如果 IsCallable (callback ) 为
false ,抛出 TypeError 异常。
令 k 为 0。
重复,直到 k < len ,
令 Pk 为 ! ToString (𝔽 (k ))。
令 kPresent 为 ? HasProperty (O ,
Pk )。
如果 kPresent 为 true ,则
令 kValue 为 ? Get (O ,
Pk )。
执行 ? Call (callback ,
thisArg , « kValue , 𝔽 (k ),
O »)。
设置 k 为 k + 1。
返回 undefined 。
注 2
该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。
23.1.3.16 Array.prototype.includes ( searchElement [
, fromIndex ] )
注 1
该方法会按升序将 searchElement 与数组的元素进行比较,使用 SameValueZero
算法,如果在任何位置找到,则返回 true ;否则返回 false 。
可选的第二个参数 fromIndex 默认为
+0 𝔽 (即搜索整个数组)。如果它大于等于数组长度,则返回
false ,即不会搜索数组。如果小于
-0 𝔽 ,则用作从数组末尾的偏移来计算 fromIndex 。如果计算得到的索引小于等于
+0 𝔽 ,则会搜索整个数组。
该方法调用时执行以下步骤:
令 O 为 ? ToObject (this 值)。
令 len 为 ? LengthOfArrayLike (O )。
如果 len = 0,返回 false 。
令 n 为 ? ToIntegerOrInfinity (fromIndex )。
断言 :如果
fromIndex 为 undefined ,则 n 为 0。
如果 n = +∞,返回 false 。
否则如果 n = -∞,设置 n 为 0。
如果 n ≥ 0,则
令 k 为 n 。
否则,
令 k 为 len + n 。
如果 k < 0,设置 k 为 0。
重复,直到 k < len ,
令 elementK 为 ? Get (O ,
! ToString (𝔽 (k )))。
如果 SameValueZero (searchElement ,
elementK ) 为 true ,返回
true 。
设置 k 为 k + 1。
返回 false 。
注 2
该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。
注 3
该方法有意与类似的 indexOf
方法有两点不同。第一,它使用 SameValueZero 算法,而不是
IsStrictlyEqual ,从而可以检测
NaN 数组元素。第二,它不会跳过缺失的数组元素,而是将它们视为 undefined 。
23.1.3.17 Array.prototype.indexOf ( searchElement [ ,
fromIndex ] )
该方法使用 IsStrictlyEqual 算法,按升序将
searchElement 与数组中的元素进行比较,如果在一个或多个索引处找到,则返回最小的那个索引;否则返回
-1 𝔽 。
注 1
可选的第二个参数 fromIndex 默认为
+0 𝔽 (即搜索整个数组)。如果它大于等于数组长度,则返回
-1 𝔽 ,即不会搜索数组。如果它小于
-0 𝔽 ,则用作从数组末尾的偏移来计算 fromIndex 。如果计算得到的索引小于等于
+0 𝔽 ,则会搜索整个数组。
该方法调用时执行以下步骤:
令 O 为 ? ToObject (this 值)。
令 len 为 ? LengthOfArrayLike (O )。
如果 len = 0,返回 -1 𝔽 。
令 n 为 ? ToIntegerOrInfinity (fromIndex )。
断言 :如果
fromIndex 为 undefined ,则 n 为 0。
如果 n = +∞,返回 -1 𝔽 。
否则如果 n = -∞,设置 n 为 0。
如果 n ≥ 0,则
令 k 为 n 。
否则,
令 k 为 len + n 。
如果 k < 0,设置 k 为 0。
重复,直到 k < len ,
令 Pk 为 ! ToString (𝔽 (k ))。
令 kPresent 为 ? HasProperty (O ,
Pk )。
如果 kPresent 为 true ,则
令 elementK 为 ? Get (O ,
Pk )。
如果 IsStrictlyEqual (searchElement ,
elementK ) 为 true ,返回 𝔽 (k )。
设置 k 为 k + 1。
返回 -1 𝔽 。
注 2
该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。
23.1.3.18 Array.prototype.join ( separator )
该方法将数组的元素转换为字符串,然后用 separator 分隔这些字符串并连接起来。如果没有提供分隔符,则使用单个逗号作为分隔符。
调用时按照以下步骤执行:
令 O 为 ? ToObject (this 值)。
令 len 为 ? LengthOfArrayLike (O )。
如果 separator 为 undefined ,令 sep 为
"," 。
否则,令 sep 为 ? ToString (separator )。
令 R 为空字符串。
令 k 为 0。
重复,直到 k < len ,
如果 k > 0,令 R 为 字符串拼接 R 和
sep 的结果。
令 element 为 ? Get (O ,
! ToString (𝔽 (k )))。
如果 element 既不是 undefined 也不是
null ,则
令 S 为 ? ToString (element )。
令 R 为 字符串拼接
R 和 S 的结果。
设置 k 为 k + 1。
返回 R 。
注
该方法被设计为泛型;它不要求其 this 值为数组。因此,它可以被转移到其他类型的对象上用作方法。
23.1.3.19 Array.prototype.keys ( )
该方法调用时执行以下步骤:
令 O 为 ? ToObject (this 值)。
返回 CreateArrayIterator (O ,
key )。
23.1.3.20 Array.prototype.lastIndexOf ( searchElement
[ , fromIndex ] )
注 1
该方法会按降序将 searchElement 与数组的元素比较,使用 IsStrictlyEqual
算法,如果在一个或多个索引处找到,则返回最大的那个索引;否则返回 -1 𝔽 。
可选的第二个参数 fromIndex 默认为数组长度减一(即搜索整个数组)。如果它大于等于数组长度,则会搜索整个数组。如果它小于
-0 𝔽 ,则用作从数组末尾的偏移来计算 fromIndex 。如果计算得到的索引小于等于
+0 𝔽 ,则返回 -1 𝔽 。
该方法调用时执行以下步骤:
令 O 为 ? ToObject (this 值)。
令 len 为 ? LengthOfArrayLike (O )。
如果 len = 0,返回 -1 𝔽 。
如果 fromIndex 存在,令 n 为 ? ToIntegerOrInfinity (fromIndex );
否则令 n 为 len - 1。
如果 n = -∞,返回 -1 𝔽 。
如果 n ≥ 0,则
令 k 为 min (n , len -
1)。
否则,
令 k 为 len + n 。
重复,直到 k ≥ 0,
令 Pk 为 ! ToString (𝔽 (k ))。
令 kPresent 为 ? HasProperty (O ,
Pk )。
如果 kPresent 为 true ,则
令 elementK 为 ? Get (O ,
Pk )。
如果 IsStrictlyEqual (searchElement ,
elementK ) 为 true ,返回 𝔽 (k )。
设置 k 为 k - 1。
返回 -1 𝔽 。
注 2
该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。
23.1.3.21 Array.prototype.map ( callback [ ,
thisArg ] )
注 1
callback 应该是一个接受三个参数的函数。map
会按升序对数组中每个元素调用
callback 一次,并用结果构造一个新数组。callback
只会对数组中实际存在的元素调用,不会对数组中缺失的元素调用。
如果提供了 thisArg 参数,则每次调用 callback 时都会用作 this
值。如果未提供,则使用 undefined 。
callback 被调用时有三个参数:元素的值、元素的索引、被遍历的对象。
map
不会直接修改它所调用的对象,但该对象可能会被 callback 的调用修改。
map
处理的元素范围在第一次调用 callback 前就已确定。调用 map
之后添加到数组的元素不会被 callback 访问。如果数组中已存在的元素被修改,则传递给 callback 的值是在
map
访问该元素时的值;在 map
调用开始后被删除且尚未被访问的元素不会被访问。
该方法调用时执行以下步骤:
令 O 为 ? ToObject (this 值)。
令 len 为 ? LengthOfArrayLike (O )。
如果 IsCallable (callback ) 为
false ,抛出 TypeError 异常。
令 A 为 ? ArraySpeciesCreate (O ,
len )。
令 k 为 0。
重复,直到 k < len ,
令 Pk 为 ! ToString (𝔽 (k ))。
令 kPresent 为 ? HasProperty (O ,
Pk )。
如果 kPresent 为 true ,则
令 kValue 为 ? Get (O ,
Pk )。
令 mappedValue 为 ? Call (callback ,
thisArg , « kValue , 𝔽 (k ),
O »)。
执行 ? CreateDataPropertyOrThrow (A ,
Pk , mappedValue )。
设置 k 为 k + 1。
返回 A 。
注 2
该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。
23.1.3.22 Array.prototype.pop ( )
注 1
该方法调用时执行以下步骤:
令 O 为 ? ToObject (this 值)。
令 len 为 ? LengthOfArrayLike (O )。
如果 len = 0,则
执行 ? Set (O ,
"length" , +0 𝔽 ,
true )。
返回 undefined 。
否则,
断言 :len > 0。
令 newLen 为 𝔽 (len - 1)。
令 index 为 ! ToString (newLen )。
令 element 为 ? Get (O ,
index )。
执行 ? DeletePropertyOrThrow (O ,
index )。
执行 ? Set (O ,
"length" , newLen , true )。
返回 element 。
注 2
该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。
23.1.3.23 Array.prototype.push ( ...items )
注 1
该方法将参数按出现顺序追加到数组末尾。它返回数组的新长度。
该方法调用时执行以下步骤:
令 O 为 ? ToObject (this 值)。
令 len 为 ? LengthOfArrayLike (O )。
令 argCount 为 items 中元素的数量。
如果 len + argCount > 253 - 1,抛出
TypeError 异常。
对于 items 的每个元素 E ,执行
执行 ? Set (O ,
! ToString (𝔽 (len )),
E , true )。
设置 len 为 len + 1。
执行 ? Set (O ,
"length" , 𝔽 (len ), true )。
返回 𝔽 (len )。
该方法的 "length" 属性为 1 𝔽 。
注 2
该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。
23.1.3.24 Array.prototype.reduce ( callback [ ,
initialValue ] )
注 1
callback 应为一个接受四个参数的函数。reduce
会对数组中第一个元素之后的每个元素按升序以函数形式调用
callback 一次。
callback 被调用时带四个参数:previousValue (上次调用 callback
的值)、currentValue (当前元素的值)、currentIndex 和被遍历的对象。首次调用
callback 时,previousValue 和 currentValue
可能有两种情况。如果调用 reduce
时提供了 initialValue ,则
previousValue 为 initialValue ,currentValue
为数组的第一个值。如果没有提供 initialValue ,则 previousValue
为数组的第一个值,currentValue 为第二个值。如果数组为空且未提供 initialValue ,会抛出
TypeError 。
reduce
不会直接修改其调用的对象,但对象可能会被 callback 的调用修改。
reduce
处理的元素范围在第一次调用 callback 前就已确定。调用 reduce
后添加到数组的元素不会被 callback 访问。如果数组中已存在的元素被修改,则传递给 callback 的值为
reduce
访问该元素时的值;在 reduce
调用开始后被删除且尚未被访问的元素不会被访问。
该方法调用时执行以下步骤:
令 O 为 ? ToObject (this 值)。
令 len 为 ? LengthOfArrayLike (O )。
如果 IsCallable (callback ) 为
false ,抛出 TypeError 异常。
如果 len = 0 且 initialValue 不存在,抛出 TypeError
异常。
令 k 为 0。
令 accumulator 为 undefined 。
如果 initialValue 存在,则
设置 accumulator 为 initialValue 。
否则,
令 kPresent 为 false 。
重复,直到 kPresent 为 false 且 k <
len ,
令 Pk 为 ! ToString (𝔽 (k ))。
设置 kPresent 为 ? HasProperty (O ,
Pk )。
如果 kPresent 为 true ,则
设置 accumulator 为 ? Get (O ,
Pk )。
设置 k 为 k + 1。
如果 kPresent 为 false ,抛出
TypeError 异常。
重复,直到 k < len ,
令 Pk 为 ! ToString (𝔽 (k ))。
令 kPresent 为 ? HasProperty (O ,
Pk )。
如果 kPresent 为 true ,则
令 kValue 为 ? Get (O ,
Pk )。
设置 accumulator 为 ? Call (callback ,
undefined , « accumulator ,
kValue , 𝔽 (k ),
O »)。
设置 k 为 k + 1。
返回 accumulator 。
注 2
该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。
23.1.3.25 Array.prototype.reduceRight ( callback [ ,
initialValue ] )
注 1
callback 应为一个接受四个参数的函数。reduceRight
会对数组中第一个元素之后的每个元素按降序以函数形式调用 callback 一次。
callback 被调用时带四个参数:previousValue (上次调用 callback
的值)、currentValue (当前元素的值)、currentIndex
和被遍历的对象。首次调用该函数时,previousValue 和 currentValue 可能有两种情况。如果调用
reduceRight
时提供了 initialValue ,则 previousValue 为
initialValue ,currentValue 为数组的最后一个值。如果没有提供
initialValue ,则 previousValue 为数组的最后一个值,currentValue
为倒数第二个值。如果数组为空且未提供 initialValue ,会抛出 TypeError 。
reduceRight
不会直接修改其调用的对象,但对象可能会被 callback 的调用修改。
reduceRight
处理的元素范围在第一次调用 callback 前就已确定。调用
reduceRight
后添加到数组的元素不会被 callback 访问。如果数组中已存在的元素被
callback 修改,则传递给 callback 的值为 reduceRight
访问该元素时的值;在 reduceRight
调用开始后被删除且尚未被访问的元素不会被访问。
该方法调用时执行以下步骤:
令 O 为 ? ToObject (this 值)。
令 len 为 ? LengthOfArrayLike (O )。
如果 IsCallable (callback ) 为
false ,抛出 TypeError 异常。
如果 len = 0 且 initialValue 不存在,抛出 TypeError
异常。
令 k 为 len - 1。
令 accumulator 为 undefined 。
如果 initialValue 存在,则
设置 accumulator 为 initialValue 。
否则,
令 kPresent 为 false 。
重复,直到 kPresent 为 false 且 k ≥ 0,
令 Pk 为 ! ToString (𝔽 (k ))。
设置 kPresent 为 ? HasProperty (O ,
Pk )。
如果 kPresent 为 true ,则
设置 accumulator 为 ? Get (O ,
Pk )。
设置 k 为 k - 1。
如果 kPresent 为 false ,抛出
TypeError 异常。
重复,直到 k ≥ 0,
令 Pk 为 ! ToString (𝔽 (k ))。
令 kPresent 为 ? HasProperty (O ,
Pk )。
如果 kPresent 为 true ,则
令 kValue 为 ? Get (O ,
Pk )。
设置 accumulator 为 ? Call (callback ,
undefined , « accumulator ,
kValue , 𝔽 (k ),
O »)。
设置 k 为 k - 1。
返回 accumulator 。
注 2
该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。
23.1.3.26 Array.prototype.reverse ( )
注 1
该方法重新排列数组元素,使其顺序颠倒。它返回反转后的数组。
该方法调用时执行以下步骤:
令 O 为 ? ToObject (this 值)。
令 len 为 ? LengthOfArrayLike (O )。
令 middle 为 floor (len / 2)。
令 lower 为 0。
重复,直到 lower ≠ middle ,
令 upper 为 len - lower - 1。
令 upperP 为 ! ToString (𝔽 (upper ))。
令 lowerP 为 ! ToString (𝔽 (lower ))。
令 lowerExists 为 ? HasProperty (O ,
lowerP )。
如果 lowerExists 为 true ,则
令 lowerValue 为 ? Get (O ,
lowerP )。
令 upperExists 为 ? HasProperty (O ,
upperP )。
如果 upperExists 为 true ,则
令 upperValue 为 ? Get (O ,
upperP )。
如果 lowerExists 为 true 且 upperExists
为 true ,则
执行 ? Set (O ,
lowerP , upperValue , true )。
执行 ? Set (O ,
upperP , lowerValue , true )。
否则如果 lowerExists 为 false 且
upperExists 为 true ,则
执行 ? Set (O ,
lowerP , upperValue , true )。
执行 ? DeletePropertyOrThrow (O ,
upperP )。
否则如果 lowerExists 为 true 且
upperExists 为 false ,则
执行 ? DeletePropertyOrThrow (O ,
lowerP )。
执行 ? Set (O ,
upperP , lowerValue , true )。
否则,
断言 :lowerExists 和
upperExists 都为 false 。
注:无操作需要执行。
设置 lower 为 lower + 1。
返回 O 。
注 2
该方法被设计为泛型;它不要求其 this 值为数组。因此,它可以被转移到其他类型的对象上用作方法。
23.1.3.27 Array.prototype.shift ( )
该方法移除数组的第一个元素并返回它。
调用时按照以下步骤执行:
令 O 为 ? ToObject (this 值)。
令 len 为 ? LengthOfArrayLike (O )。
如果 len = 0,则
执行 ? Set (O ,
"length" , +0 𝔽 ,
true )。
返回 undefined 。
令 first 为 ? Get (O ,
"0" )。
令 k 为 1。
重复,直到 k < len ,
令 from 为 ! ToString (𝔽 (k ))。
令 to 为 ! ToString (𝔽 (k - 1))。
令 fromPresent 为 ? HasProperty (O ,
from )。
如果 fromPresent 为 true ,则
令 fromValue 为 ? Get (O ,
from )。
执行 ? Set (O ,
to , fromValue , true )。
否则,
断言 :fromPresent 为
false 。
执行 ? DeletePropertyOrThrow (O ,
to )。
设置 k 为 k + 1。
执行 ? DeletePropertyOrThrow (O ,
! ToString (𝔽 (len - 1)))。
执行 ? Set (O ,
"length" , 𝔽 (len - 1), true )。
返回 first 。
注
该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。
23.1.3.28 Array.prototype.slice ( start ,
end )
该方法返回一个包含数组从元素 start 到(但不包括)元素 end 的元素的新数组(如果 end 是
undefined ,则一直到数组末尾)。如果 start 为负数,则视为 length + start ,其中 length
是数组长度。如果 end 为负数,则视为 length +
end ,其中 length 是数组长度。
调用时按照以下步骤执行:
令 O 为 ? ToObject (this 值)。
令 len 为 ? LengthOfArrayLike (O )。
令 relativeStart 为 ? ToIntegerOrInfinity (start )。
如果 relativeStart = -∞,令 k 为 0。
否则如果 relativeStart < 0,令 k 为 max (len +
relativeStart , 0)。
否则,令 k 为 min (relativeStart ,
len )。
如果 end 为 undefined ,令 relativeEnd 为
len ;否则令 relativeEnd 为 ? ToIntegerOrInfinity (end )。
如果 relativeEnd = -∞,令 final 为 0。
否则如果 relativeEnd < 0,令 final 为 max (len +
relativeEnd , 0)。
否则,令 final 为 min (relativeEnd , len )。
令 count 为 max (final - k , 0)。
令 A 为 ? ArraySpeciesCreate (O ,
count )。
令 n 为 0。
重复,直到 k < final ,
令 Pk 为 ! ToString (𝔽 (k ))。
令 kPresent 为 ? HasProperty (O ,
Pk )。
如果 kPresent 为 true ,则
令 kValue 为 ? Get (O ,
Pk )。
执行 ? CreateDataPropertyOrThrow (A ,
! ToString (𝔽 (n )),
kValue )。
设置 k 为 k + 1。
设置 n 为 n + 1。
执行 ? Set (A ,
"length" , 𝔽 (n ), true )。
返回 A 。
注 1
第 15 步显式设置
"length" 属性,旨在确保即使 A 不是内建数组时长度也是正确的。
注 2
该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。
23.1.3.29 Array.prototype.some ( callback [ ,
thisArg ] )
注 1
callback 应为一个接受三个参数并返回可转换为布尔值的函数。some
会对数组中实际存在的每个元素按升序调用
callback ,直到找到一个 callback 返回 true
的元素为止。如果找到这样的元素,some
会立即返回 true 。否则,some
返回 false 。callback 只会对数组中实际存在的元素调用,不会对数组中缺失的元素调用。
如果提供了 thisArg 参数,则每次调用 callback 时都会用作 this
值。如果未提供,则使用 undefined 。
callback 被调用时有三个参数:元素的值、元素的索引、被遍历的对象。
some
不会直接修改其调用的对象,但该对象可能会被 callback 的调用修改。
some
处理的元素范围在第一次调用 callback 前就已确定。调用 some
后添加到数组的元素不会被 callback 访问。如果数组中已存在的元素被修改,则传递给 callback 的值是在
some
访问该元素时的值;在 some
调用开始后被删除且尚未被访问的元素不会被访问。some
类似于数学中的“存在”量词。特别地,对于空数组,它返回
false 。
该方法调用时执行以下步骤:
令 O 为 ? ToObject (this 值)。
令 len 为 ? LengthOfArrayLike (O )。
如果 IsCallable (callback ) 为
false ,抛出 TypeError 异常。
令 k 为 0。
重复,直到 k < len ,
令 Pk 为 ! ToString (𝔽 (k ))。
令 kPresent 为 ? HasProperty (O ,
Pk )。
如果 kPresent 为 true ,则
令 kValue 为 ? Get (O ,
Pk )。
令 testResult 为 ToBoolean (? Call (callback ,
thisArg , « kValue , 𝔽 (k ),
O »))。
如果 testResult 为 true ,返回
true 。
设置 k 为 k + 1。
返回 false 。
注 2
该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。
23.1.3.30 Array.prototype.sort ( comparator )
该方法对数组的元素进行排序。如果 comparator 不为 undefined ,则应为一个接受两个参数
x 和 y 的函数,若 x < y ,返回负数;若 x >
y ,返回正数;否则返回零。
调用时按照以下步骤执行:
如果 comparator 不为
undefined 且 IsCallable (comparator ) 为
false ,抛出 TypeError 异常。
令 obj 为 ? ToObject (this 值)。
令 len 为 ? LengthOfArrayLike (obj )。
令 SortCompare 为一个新的 抽象闭包 ,带参数
(x , y ),捕获 comparator 并在调用时执行以下步骤:
返回 ? CompareArrayElements (x ,
y , comparator )。
令 sortedList 为 ? SortIndexedProperties (obj ,
len , SortCompare , skip-holes )。
令 itemCount 为 sortedList 中元素的数量。
令 j 为 0。
重复,直到 j < itemCount ,
执行 ? Set (obj ,
! ToString (𝔽 (j )),
sortedList [j ], true )。
设置 j 为 j + 1。
注:第 SortIndexedProperties 步骤(见
5 )使用
skip-holes 。剩余索引会被删除,以保留排序前检测到并排除的空洞数量。
重复,直到 j < len ,
执行 ? DeletePropertyOrThrow (obj ,
! ToString (𝔽 (j )))。
设置 j 为 j + 1。
返回 obj 。
注 1
由于不存在的属性值总是大于 undefined 属性值,而 undefined
总是大于任何其他值(见 CompareArrayElements ),undefined
属性值总是排序到结果的末尾,其后是不存在的属性值。
注 2
在第 5 和 6 步骤中由 ToString
抽象操作
执行的方法调用,可能导致 SortCompare 行为不是一个 一致性比较器 。
注 3
该方法被设计为泛型;它不要求其 this 值为数组。因此,它可以被转移到其他类型的对象上用作方法。
23.1.3.30.1 SortIndexedProperties ( obj ,
len , SortCompare , holes )
抽象操作 SortIndexedProperties 接收参数 obj (一个对象)、len (一个非负整数 )、SortCompare (一个带有两个参数的抽象闭包 )、holes (skip-holes
或 read-through-holes ),返回包含 List
的正常完成,或抛出完成 。调用时执行以下步骤:
令 items 为一个新的空List 。
令 k 为 0。
重复,直到 k < len ,
令 Pk 为 ! ToString (𝔽 (k ))。
如果 holes 为 skip-holes ,则
令 kRead 为 ? HasProperty (obj ,
Pk )。
否则,
断言 :holes 为
read-through-holes 。
令 kRead 为 true 。
如果 kRead 为 true ,则
令 kValue 为 ? Get (obj ,
Pk )。
将 kValue 添加到 items 。
设置 k 为 k + 1。
使用实现定义 的 对 SortCompare 的调用序列 对 items
进行排序。如果此过程中有任何调用返回 异常完成 ,则在进行任何进一步调用
SortCompare 前停止并返回该 Completion
Record 。
返回 items 。
排序顺序(sort order) 指的是上述算法中第 4
步执行后 items 的排列顺序。若 SortCompare 不是 items 元素的 一致性比较器 ,则 排序顺序 是
实现定义 。当通过 Array.prototype.sort 或 Array.prototype.toSorted 调用
SortIndexedProperties 时,如果 comparator 为 undefined ,且所有传给
SortCompare 的特定参数的 ToString 调用结果不一致,则 排序顺序 也是
实现定义 。
除非 排序顺序
被指定为 实现定义 ,否则必须满足以下所有条件:
存在对小于 itemCount 的非负整数 的某个数学排列 π,使得对于每个小于 itemCount
的非负整数
j ,有 old[j ] 与 new[π(j )] 完全一致。
对所有小于 itemCount 的非负整数 j 和 k ,如果 ℝ (SortCompare (old[j ],
old[k ])) < 0 ,则 π(j )
< π(k ) 。
对所有 j < k < itemCount 的非负整数 j 和
k ,如果 ℝ (SortCompare (old[j ],
old[k ])) = 0 ,则 π(j )
< π(k ) ;即排序是稳定的。
此处记号 old[j ] 表示第 4
步执行前 items [j ],而 new[j ] 表示执行后 items [j ]。
抽象闭包或函数 comparator 对于值集合 S 来说,如果对集合 S 中所有可能的值
a 、b 、c (可能相同)均满足以下要求,则称其为 一致性比较器 。记号 a <C
b 表示 ℝ (comparator (a ,
b )) < 0 ;a =C
b 表示 ℝ (comparator (a ,
b )) = 0 ;a
>C b 表示 ℝ (comparator (a ,
b )) > 0 。
对于给定的 a 和 b ,每次调用 comparator (a ,
b ) 总是返回相同的值 v 。此外,v 是一个
Number ,且 v 不是 NaN 。这意味着对于一对
a 和 b ,a <C b 、a
=C b 、a >C b 三者必有其一为真。
调用 comparator (a , b ) 不会修改 obj
或其原型链上的任何对象。
a =C a (自反性)
如果 a =C b ,则 b =C
a (对称性)
如果 a =C b 且 b =C
c ,则 a =C c (传递性)
如果 a <C b 且 b <C
c ,则 a <C c (传递性)
如果 a >C b 且 b >C
c ,则 a >C c (传递性)
注
上述条件是保证 comparator 将集合 S 划分为等价类并且这些等价类是全序所必需且充分的条件。
23.1.3.30.2 CompareArrayElements ( x ,
y , comparator )
抽象操作 CompareArrayElements 接收参数 x (一个ECMAScript
语言值 )、y (一个ECMAScript
语言值 )、comparator (一个函数对象 或undefined ),返回包含 Number
的正常完成,或异常完成 。调用时执行以下步骤:
如果 x 和 y 都是 undefined ,返回
+0 𝔽 。
如果 x 是 undefined ,返回
1 𝔽 。
如果 y 是 undefined ,返回
-1 𝔽 。
如果 comparator 不为 undefined ,则
令 v 为 ? ToNumber (? Call (comparator ,
undefined , « x , y »))。
如果 v 是 NaN ,返回
+0 𝔽 。
返回 v 。
令 xString 为 ? ToString (x )。
令 yString 为 ? ToString (y )。
令 xSmaller 为 ! IsLessThan (xString ,
yString , true )。
如果 xSmaller 为 true ,返回
-1 𝔽 。
令 ySmaller 为 ! IsLessThan (yString ,
xString , true )。
如果 ySmaller 为 true ,返回
1 𝔽 。
返回 +0 𝔽 。
23.1.3.31 Array.prototype.splice ( start ,
deleteCount , ...items )
注 1
该方法从整数索引 start 开始,删除数组中的 deleteCount 个元素,并用 items
的元素替换它们。它返回一个包含被删除元素(如有)的数组。
该方法调用时执行以下步骤:
令 O 为 ? ToObject (this 值)。
令 len 为 ? LengthOfArrayLike (O )。
令 relativeStart 为 ? ToIntegerOrInfinity (start )。
如果 relativeStart = -∞,令 actualStart 为 0。
否则如果 relativeStart < 0,令 actualStart 为 max (len
+ relativeStart , 0)。
否则,令 actualStart 为 min (relativeStart ,
len )。
令 itemCount 为 items 中元素的数量。
如果未传入 start ,则
令 actualDeleteCount 为 0。
否则如果未传入 deleteCount ,则
令 actualDeleteCount 为 len - actualStart 。
否则,
令 dc 为 ? ToIntegerOrInfinity (deleteCount )。
令 actualDeleteCount 为将 dc 限制在 0 到 len -
actualStart 之间的结果。
如果 len + itemCount - actualDeleteCount >
253 - 1,抛出 TypeError 异常。
令 A 为 ? ArraySpeciesCreate (O ,
actualDeleteCount )。
令 k 为 0。
重复,直到 k < actualDeleteCount ,
令 from 为 ! ToString (𝔽 (actualStart +
k ))。
如果 ? HasProperty (O ,
from ) 为 true ,则
令 fromValue 为 ? Get (O ,
from )。
执行 ? CreateDataPropertyOrThrow (A ,
! ToString (𝔽 (k )),
fromValue )。
设置 k 为 k + 1。
执行 ? Set (A ,
"length" , 𝔽 (actualDeleteCount ),
true )。
如果 itemCount < actualDeleteCount ,则
设置 k 为 actualStart 。
重复,直到 k < (len -
actualDeleteCount ),
令 from 为 ! ToString (𝔽 (k +
actualDeleteCount ))。
令 to 为 ! ToString (𝔽 (k +
itemCount ))。
如果 ? HasProperty (O ,
from ) 为 true ,则
令 fromValue 为 ? Get (O ,
from )。
执行 ? Set (O ,
to , fromValue ,
true )。
否则,
执行 ? DeletePropertyOrThrow (O ,
to )。
设置 k 为 k + 1。
设置 k 为 len 。
重复,直到 k > (len -
actualDeleteCount + itemCount ),
执行 ? DeletePropertyOrThrow (O ,
! ToString (𝔽 (k - 1)))。
设置 k 为 k - 1。
否则如果 itemCount > actualDeleteCount ,则
设置 k 为 (len - actualDeleteCount )。
重复,直到 k > actualStart ,
令 from 为 ! ToString (𝔽 (k +
actualDeleteCount - 1))。
令 to 为 ! ToString (𝔽 (k +
itemCount - 1))。
如果 ? HasProperty (O ,
from ) 为 true ,则
令 fromValue 为 ? Get (O ,
from )。
执行 ? Set (O ,
to , fromValue ,
true )。
否则,
执行 ? DeletePropertyOrThrow (O ,
to )。
设置 k 为 k - 1。
设置 k 为 actualStart 。
对于 items 的每个元素 E ,执行
执行 ? Set (O ,
! ToString (𝔽 (k )),
E , true )。
设置 k 为 k + 1。
执行 ? Set (O ,
"length" , 𝔽 (len - actualDeleteCount +
itemCount ), true )。
返回 A 。
注 2
在第 15 和 20 步中显式设置
"length" 属性,旨在确保即使操作对象不是内建数组时长度也是正确的。
注 3
该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。
23.1.3.32 Array.prototype.toLocaleString ( [
reserved1 [ , reserved2 ] ] )
包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按照 ECMA-402 规范实现此方法。如果 ECMAScript 实现不包含 ECMA-402
API,则使用下面对该方法的规范。
注 1
此方法的可选参数含义在 ECMA-402 规范中定义;不包含 ECMA-402 支持的实现不得将这些参数位置用于其他用途。
该方法调用时执行以下步骤:
令 array 为 ? ToObject (this 值)。
令 len 为 ? LengthOfArrayLike (array )。
令 separator 为适用于 宿主环境 当前区域设置的 实现定义 列表分隔符字符串值(如 ",
" )。
令 R 为空字符串。
令 k 为 0。
重复,直到 k < len ,
如果 k > 0,令 R 为 字符串拼接 R 和
separator 的结果。
令 element 为 ? Get (array ,
! ToString (𝔽 (k )))。
如果 element 既不是 undefined 也不是
null ,则
令 S 为 ? ToString (? Invoke (element ,
"toLocaleString" ))。
令 R 为 字符串拼接
R 和 S 的结果。
设置 k 为 k + 1。
返回 R 。
注 2
该方法使用元素各自的 toLocaleString
方法将数组元素转换为字符串,然后用实现定义的、区分区域设置的分隔符字符串把这些字符串连接起来。此方法类似于 toString
,但目的是生成符合
宿主环境 当前区域习惯的本地化结果。
注 3
该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。
23.1.3.33 Array.prototype.toReversed ( )
该方法调用时执行以下步骤:
令 O 为 ? ToObject (this 值)。
令 len 为 ? LengthOfArrayLike (O )。
令 A 为 ? ArrayCreate (len )。
令 k 为 0。
重复,直到 k < len ,
令 from 为 ! ToString (𝔽 (len -
k - 1))。
令 Pk 为 ! ToString (𝔽 (k ))。
令 fromValue 为 ? Get (O ,
from )。
执行 ! CreateDataPropertyOrThrow (A ,
Pk , fromValue )。
设置 k 为 k + 1。
返回 A 。
23.1.3.34 Array.prototype.toSorted ( comparator )
该方法调用时执行以下步骤:
如果 comparator 不为 undefined 且 IsCallable (comparator ) 为
false ,抛出 TypeError 异常。
令 O 为 ? ToObject (this 值)。
令 len 为 ? LengthOfArrayLike (O )。
令 A 为 ? ArrayCreate (len )。
令 SortCompare 为一个新的 抽象闭包 ,带参数
(x , y ),捕获 comparator 并在调用时执行以下步骤:
返回 ? CompareArrayElements (x ,
y , comparator )。
令 sortedList 为 ? SortIndexedProperties (O ,
len , SortCompare , read-through-holes )。
令 j 为 0。
重复,直到 j < len ,
执行 ! CreateDataPropertyOrThrow (A ,
! ToString (𝔽 (j )),
sortedList [j ])。
设置 j 为 j + 1。
返回 A 。
23.1.3.35 Array.prototype.toSpliced ( start ,
skipCount , ...items )
该方法调用时执行以下步骤:
令 O 为 ? ToObject (this 值)。
令 len 为 ? LengthOfArrayLike (O )。
令 relativeStart 为 ? ToIntegerOrInfinity (start )。
如果 relativeStart = -∞,令 actualStart 为 0。
否则如果 relativeStart < 0,令 actualStart 为 max (len
+ relativeStart , 0)。
否则,令 actualStart 为 min (relativeStart ,
len )。
令 insertCount 为 items 中元素的数量。
如果未传入 start ,则
令 actualSkipCount 为 0。
否则如果未传入 skipCount ,则
令 actualSkipCount 为 len - actualStart 。
否则,
令 sc 为 ? ToIntegerOrInfinity (skipCount )。
令 actualSkipCount 为将 sc 限制在 0 到 len -
actualStart 之间的结果。
令 newLen 为 len + insertCount -
actualSkipCount 。
如果 newLen > 253 - 1,抛出 TypeError
异常。
令 A 为 ? ArrayCreate (newLen )。
令 i 为 0。
令 r 为 actualStart + actualSkipCount 。
重复,直到 i < actualStart ,
令 Pi 为 ! ToString (𝔽 (i ))。
令 iValue 为 ? Get (O , Pi )。
执行 ! CreateDataPropertyOrThrow (A ,
Pi , iValue )。
设置 i 为 i + 1。
对于 items 的每个元素 E ,执行
令 Pi 为 ! ToString (𝔽 (i ))。
执行 ! CreateDataPropertyOrThrow (A ,
Pi , E )。
设置 i 为 i + 1。
重复,直到 i < newLen ,
令 Pi 为 ! ToString (𝔽 (i ))。
令 from 为 ! ToString (𝔽 (r ))。
令 fromValue 为 ? Get (O ,
from )。
执行 ! CreateDataPropertyOrThrow (A ,
Pi , fromValue )。
设置 i 为 i + 1。
设置 r 为 r + 1。
返回 A 。
23.1.3.36 Array.prototype.toString ( )
该方法调用时执行以下步骤:
令 array 为 ? ToObject (this 值)。
令 func 为 ? Get (array ,
"join" )。
如果 IsCallable (func ) 为
false ,则将 func 设为内建函数 %Object.prototype.toString%。
返回 ? Call (func , array )。
注
该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。
23.1.3.37 Array.prototype.unshift ( ...items )
该方法将参数添加到数组的开头,其在数组中的顺序与参数列表中的顺序相同。
该方法调用时执行以下步骤:
令 O 为 ? ToObject (this 值)。
令 len 为 ? LengthOfArrayLike (O )。
令 argCount 为 items 中元素的数量。
如果 argCount > 0,则
如果 len + argCount > 253 - 1,抛出
TypeError 异常。
令 k 为 len 。
重复,直到 k > 0,
令 from 为 ! ToString (𝔽 (k - 1))。
令 to 为 ! ToString (𝔽 (k +
argCount - 1))。
令 fromPresent 为 ? HasProperty (O ,
from )。
如果 fromPresent 为 true ,则
令 fromValue 为 ? Get (O ,
from )。
执行 ? Set (O ,
to , fromValue ,
true )。
否则,
断言 :
fromPresent 为 false 。
执行 ? DeletePropertyOrThrow (O ,
to )。
设置 k 为 k - 1。
令 j 为 +0 𝔽 。
对于 items 的每个元素 E ,执行
执行 ? Set (O ,
! ToString (j ),
E , true )。
设置 j 为 j +
1 𝔽 。
执行 ? Set (O ,
"length" , 𝔽 (len + argCount ),
true )。
返回 𝔽 (len + argCount )。
该方法的 "length" 属性为 1 𝔽 。
注
该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。
23.1.3.38 Array.prototype.values ( )
该方法调用时执行以下步骤:
令 O 为 ? ToObject (this 值)。
返回 CreateArrayIterator (O ,
value )。
23.1.3.39 Array.prototype.with ( index ,
value )
该方法调用时执行以下步骤:
令 O 为 ? ToObject (this 值)。
令 len 为 ? LengthOfArrayLike (O )。
令 relativeIndex 为 ? ToIntegerOrInfinity (index )。
如果 relativeIndex ≥ 0,令 actualIndex 为
relativeIndex 。
否则,令 actualIndex 为 len + relativeIndex 。
如果 actualIndex ≥ len 或 actualIndex < 0,抛出
RangeError 异常。
令 A 为 ? ArrayCreate (len )。
令 k 为 0。
重复,直到 k < len ,
令 Pk 为 ! ToString (𝔽 (k ))。
如果 k = actualIndex ,令 fromValue 为
value 。
否则,令 fromValue 为 ? Get (O , Pk )。
执行 ! CreateDataPropertyOrThrow (A ,
Pk , fromValue )。
设置 k 为 k + 1。
返回 A 。
23.1.3.40 Array.prototype [ %Symbol.iterator% ] ( )
%Symbol.iterator% 属性的初始值是
%Array.prototype.values%,定义见 23.1.3.38 。
23.1.3.41 Array.prototype [ %Symbol.unscopables% ]
%Symbol.unscopables% 数据属性
的初始值为通过以下步骤创建的对象:
令 unscopableList 为 OrdinaryObjectCreate (null )。
执行 ! CreateDataPropertyOrThrow (unscopableList ,
"at" , true )。
执行 ! CreateDataPropertyOrThrow (unscopableList ,
"copyWithin" , true )。
执行 ! CreateDataPropertyOrThrow (unscopableList ,
"entries" , true )。
执行 ! CreateDataPropertyOrThrow (unscopableList ,
"fill" , true )。
执行 ! CreateDataPropertyOrThrow (unscopableList ,
"find" , true )。
执行 ! CreateDataPropertyOrThrow (unscopableList ,
"findIndex" , true )。
执行 ! CreateDataPropertyOrThrow (unscopableList ,
"findLast" , true )。
执行 ! CreateDataPropertyOrThrow (unscopableList ,
"findLastIndex" , true )。
执行 ! CreateDataPropertyOrThrow (unscopableList ,
"flat" , true )。
执行 ! CreateDataPropertyOrThrow (unscopableList ,
"flatMap" , true )。
执行 ! CreateDataPropertyOrThrow (unscopableList ,
"includes" , true )。
执行 ! CreateDataPropertyOrThrow (unscopableList ,
"keys" , true )。
执行 ! CreateDataPropertyOrThrow (unscopableList ,
"toReversed" , true )。
执行 ! CreateDataPropertyOrThrow (unscopableList ,
"toSorted" , true )。
执行 ! CreateDataPropertyOrThrow (unscopableList ,
"toSpliced" , true )。
执行 ! CreateDataPropertyOrThrow (unscopableList ,
"values" , true )。
返回 unscopableList 。
该属性具有属性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : true }。
注
该对象的自有属性名是在 ECMAScript 2015 规范之前未作为 Array.prototype
标准属性包含的属性名。这些名称在
with
语句绑定时会被忽略,以保持现有代码的行为,这些代码可能在外部作用域中使用其中的某个名称作为绑定,而该作用域被
with
语句(其绑定对象为数组)所遮蔽。
"with" 未被包含在 unscopableList 中的原因是它已经是一个 保留字 。
23.1.4 数组实例的属性
数组实例是 数组特异对象 ,并具有为此类对象指定的内部方法。数组实例继承自 Array 原型对象 的属性。
数组实例有一个 "length" 属性,以及一组带有 数组索引 名称的可枚举属性。
23.1.4.1 length
Array 实例的 "length" 属性是一个 数据属性 ,其值总是数值上大于每个名称为 数组索引 、且可配置的自有属性的名称。
"length" 属性最初拥有属性 { [[Writable]] :
true , [[Enumerable]] : false ,
[[Configurable]] : false }。
注
减少 "length" 属性的值会导致删除其 数组索引
介于旧值和新值之间的自有数组元素。但不可配置属性不能被删除。试图将数组的 "length" 属性设置为小于或等于现有不可配置
数组索引 属性的最大数值自有 属性名 时,length 会被设置为比该不可配置数值自有 属性名 大 1 的数值。见 10.4.2.1 。
23.1.5 数组迭代器对象
数组迭代器 是一个表示对某个特定数组实例对象的特定迭代的对象。数组迭代器对象没有命名的 构造函数 。数组迭代器对象是通过调用数组实例对象的某些方法创建的。
23.1.5.1 CreateArrayIterator ( array , kind
)
抽象操作 CreateArrayIterator 接收参数 array (一个对象)和
kind (key+value 、key 或
value ),返回一个对象。用于为返回此类 迭代器 的 Array 方法创建
迭代器 对象。调用时执行以下步骤:
令 iterator 为 OrdinaryObjectCreate (%ArrayIteratorPrototype% ,
« [[IteratedArrayLike]] , [[ArrayLikeNextIndex]] , [[ArrayLikeIterationKind]] »)。
设置 iterator .[[IteratedArrayLike]] 为
array 。
设置 iterator .[[ArrayLikeNextIndex]] 为 0。
设置 iterator .[[ArrayLikeIterationKind]] 为
kind 。
返回 iterator 。
23.1.5.2 %ArrayIteratorPrototype% 对象
%ArrayIteratorPrototype% 对象:
23.1.5.2.1 %ArrayIteratorPrototype%.next ( )
令 O 为 this 值。
如果 O 不是对象 ,抛出
TypeError 异常。
如果 O 不具有 数组迭代器 实例(23.1.5.3 )的所有内部槽,抛出
TypeError 异常。
令 array 为 O .[[IteratedArrayLike]] 。
如果 array 为 undefined ,返回 CreateIteratorResultObject (undefined ,
true )。
令 index 为 O .[[ArrayLikeNextIndex]] 。
令 kind 为 O .[[ArrayLikeIterationKind]] 。
如果 array 具有 [[TypedArrayName]] 内部槽,则
令 taRecord 为 MakeTypedArrayWithBufferWitnessRecord (array ,
seq-cst )。
如果 IsTypedArrayOutOfBounds (taRecord )
为 true ,抛出 TypeError 异常。
令 len 为 TypedArrayLength (taRecord )。
否则,
令 len 为 ? LengthOfArrayLike (array )。
如果 index ≥ len ,则
设置 O .[[IteratedArrayLike]] 为
undefined 。
返回 CreateIteratorResultObject (undefined ,
true )。
设置 O .[[ArrayLikeNextIndex]] 为
index + 1。
令 indexNumber 为 𝔽 (index )。
如果 kind 是 key ,则
令 result 为 indexNumber 。
否则,
令 elementKey 为 ! ToString (indexNumber )。
令 elementValue 为 ? Get (array ,
elementKey )。
如果 kind 是 value ,则
令 result 为 elementValue 。
否则,
断言 : kind 是
key+value 。
令 result 为 CreateArrayFromList («
indexNumber , elementValue »)。
返回 CreateIteratorResultObject (result ,
false )。
23.1.5.2.2 %ArrayIteratorPrototype% [ %Symbol.toStringTag% ]
%Symbol.toStringTag% 属性的初始值为字符串值
"Array Iterator" 。
该属性具有属性 { [[Writable]] :
false , [[Enumerable]] :
false , [[Configurable]] :
true }。
23.1.5.3 数组迭代器实例的属性
数组迭代器 实例是 普通对象 ,继承自 %ArrayIteratorPrototype%
内建对象的属性。数组迭代器 实例创建时具有 表 74
中列出的内部槽。
表 74:数组迭代器 实例的内部槽
内部槽
类型
描述
[[IteratedArrayLike]]
一个对象或 undefined
被迭代的 类数组对象 。
[[ArrayLikeNextIndex]]
非负整数
该迭代器 要检查的下一个元素的整数索引 。
[[ArrayLikeIterationKind]]
key+value 、key 或
value
标识每次迭代返回什么类型值的值。
23.2 TypedArray 对象
TypedArray 展示了一个底层二进制数据缓冲区(25.1 )的类数组视图。TypedArray 元素类型 是所有 TypedArray
实例元素所具有的底层二进制标量数据类型。每种支持的元素类型都有一个不同的 TypedArray 构造函数 ,见 表 75 。表 75 中的每个 构造函数 都有一个对应的不同的原型对象。
表 75:TypedArray 构造函数
构造函数 名称及内建对象
元素类型
元素大小
转换操作
描述
Int8Array
%Int8Array%
int8
1
ToInt8
8 位二进制补码有符号整数
Uint8Array
%Uint8Array%
uint8
1
ToUint8
8 位无符号整数
Uint8ClampedArray
%Uint8ClampedArray%
uint8clamped
1
ToUint8Clamp
8 位无符号整数 (夹紧转换)
Int16Array
%Int16Array%
int16
2
ToInt16
16 位二进制补码有符号整数
Uint16Array
%Uint16Array%
uint16
2
ToUint16
16 位无符号整数
Int32Array
%Int32Array%
int32
4
ToInt32
32 位二进制补码有符号整数
Uint32Array
%Uint32Array%
uint32
4
ToUint32
32 位无符号整数
BigInt64Array
%BigInt64Array%
bigint64
8
ToBigInt64
64 位二进制补码有符号整数
BigUint64Array
%BigUint64Array%
biguint64
8
ToBigUint64
64 位无符号整数
Float16Array
%Float16Array%
float16
2
16 位 IEEE 浮点数
Float32Array
%Float32Array%
float32
4
32 位 IEEE 浮点数
Float64Array
%Float64Array%
float64
8
64 位 IEEE 浮点数
在下述定义中,对 TypedArray 的引用应替换为上表中相应的 构造函数 名称。
23.2.1 %TypedArray% 内建对象
%TypedArray% 内建对象:
是一个 构造函数
函数对象 ,所有 TypedArray 构造函数 对象都继承自它。
与其对应的原型对象一起,提供所有 TypedArray 构造函数 及其实例继承的公共属性。
没有全局名称,也不会作为 全局对象 的属性出现。
作为各类 TypedArray 构造函数 的抽象超类。
因为它是一个抽象类 构造函数 ,所以调用会抛出错误。TypedArray 构造函数 不会对它执行
super
调用。
23.2.1.1 %TypedArray% ( )
该函数被调用时执行以下步骤:
抛出 TypeError 异常。
该函数的 "length" 属性为
+0 𝔽 。
23.2.2 %TypedArray% 内建对象的属性
%TypedArray% 内建对象:
23.2.2.1 %TypedArray%.from ( source [ ,
mapper [ , thisArg ] ] )
该方法被调用时执行以下步骤:
令 C 为 this 值。
如果 IsConstructor (C ) 为
false ,抛出 TypeError 异常。
如果 mapper 为 undefined ,则
令 mapping 为 false 。
否则,
如果 IsCallable (mapper )
为 false ,抛出 TypeError 异常。
令 mapping 为 true 。
令 usingIterator 为 ? GetMethod (source , %Symbol.iterator% ).
如果 usingIterator 不为 undefined ,则
令 values 为 ? IteratorToList (? GetIteratorFromMethod (source ,
usingIterator ))。
令 len 为 values 中元素的数量。
令 targetObj 为 ? TypedArrayCreateFromConstructor (C ,
« 𝔽 (len ) »)。
令 k 为 0。
重复,直到 k < len ,
令 Pk 为 ! ToString (𝔽 (k ))。
令 kValue 为 values 的第一个元素。
从 values 移除第一个元素。
如果 mapping 为 true ,则
令 mappedValue 为 ? Call (mapper ,
thisArg , « kValue , 𝔽 (k ) »)。
否则,
令 mappedValue 为 kValue 。
执行 ? Set (targetObj ,
Pk , mappedValue , true )。
设置 k 为 k + 1。
断言 :values 现在是一个空的 List 。
返回 targetObj 。
注:source 不是 可迭代对象 ,所以假定它已经是 类数组对象 。
令 arrayLike 为 ! ToObject (source )。
令 len 为 ? LengthOfArrayLike (arrayLike )。
令 targetObj 为 ? TypedArrayCreateFromConstructor (C ,
« 𝔽 (len ) »)。
令 k 为 0。
重复,直到 k < len ,
令 Pk 为 ! ToString (𝔽 (k ))。
令 kValue 为 ? Get (arrayLike ,
Pk )。
如果 mapping 为 true ,则
令 mappedValue 为 ? Call (mapper ,
thisArg , « kValue , 𝔽 (k ) »)。
否则,
令 mappedValue 为 kValue 。
执行 ? Set (targetObj ,
Pk , mappedValue , true )。
设置 k 为 k + 1。
返回 targetObj 。
23.2.2.2 %TypedArray%.of ( ...items )
该方法被调用时执行以下步骤:
令 len 为 items 中元素的数量。
令 C 为 this 值。
如果 IsConstructor (C ) 为
false ,抛出 TypeError 异常。
令 newObj 为 ? TypedArrayCreateFromConstructor (C ,
« 𝔽 (len ) »)。
令 k 为 0。
重复,直到 k < len ,
令 kValue 为 items [k ]。
令 Pk 为 ! ToString (𝔽 (k ))。
执行 ? Set (newObj ,
Pk , kValue , true )。
设置 k 为 k + 1。
返回 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 访问器函数被调用时执行以下步骤:
返回 this 值。
该函数的 "name" 属性值为 "get [Symbol.species]" 。
注
%TypedArray.prototype%
的方法通常使用其 this 值的 构造函数 来创建派生对象。但是,子类构造函数 可以通过重新定义其 %Symbol.species% 属性来覆盖该默认行为。
23.2.3 %TypedArray% 原型对象的属性
%TypedArray% 原型对象 :
拥有一个 [[Prototype]] 内部槽,其值为 %Object.prototype% 。
即 %TypedArray.prototype% 。
是一个 普通对象 。
没有 [[ViewedArrayBuffer]] 或其它 TypedArray 实例对象专有的内部槽。
23.2.3.1 %TypedArray%.prototype.at ( index )
令 O 为 this 值。
令 taRecord 为 ? ValidateTypedArray (O ,
seq-cst )。
令 len 为 TypedArrayLength (taRecord )。
令 relativeIndex 为 ? ToIntegerOrInfinity (index )。
如果 relativeIndex ≥ 0,则
令 k 为 relativeIndex 。
否则,
令 k 为 len + relativeIndex 。
如果 k < 0 或 k ≥ len ,返回
undefined 。
返回 ! Get (O , ! ToString (𝔽 (k )))。
23.2.3.2 get %TypedArray%.prototype.buffer
%TypedArray% .prototype.buffer
是一个 访问器属性 ,其 set 访问器函数为
undefined 。其 get 访问器函数被调用时执行以下步骤:
令 O 为 this 值。
执行 ? RequireInternalSlot (O ,
[[TypedArrayName]] )。
断言 :
O 具有 [[ViewedArrayBuffer]] 内部槽。
令 buffer 为 O .[[ViewedArrayBuffer]] 。
返回 buffer 。
23.2.3.3 get %TypedArray%.prototype.byteLength
%TypedArray% .prototype.byteLength
是一个 访问器属性 ,其 set 访问器函数为
undefined 。其 get 访问器函数被调用时执行以下步骤:
令 O 为 this 值。
执行 ? RequireInternalSlot (O ,
[[TypedArrayName]] )。
断言 :
O 具有 [[ViewedArrayBuffer]] 内部槽。
令 taRecord 为 MakeTypedArrayWithBufferWitnessRecord (O ,
seq-cst )。
令 size 为 TypedArrayByteLength (taRecord )。
返回 𝔽 (size )。
23.2.3.4 get %TypedArray%.prototype.byteOffset
%TypedArray% .prototype.byteOffset
是一个 访问器属性 ,其 set 访问器函数为
undefined 。其 get 访问器函数被调用时执行以下步骤:
令 O 为 this 值。
执行 ? RequireInternalSlot (O ,
[[TypedArrayName]] )。
断言 :
O 具有 [[ViewedArrayBuffer]] 内部槽。
令 taRecord 为 MakeTypedArrayWithBufferWitnessRecord (O ,
seq-cst )。
如果 IsTypedArrayOutOfBounds (taRecord )
为 true ,返回 +0 𝔽 。
令 offset 为 O .[[ByteOffset]] 。
返回 𝔽 (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
相同。
该方法被调用时执行以下步骤:
令 O 为 this 值。
令 taRecord 为 ? ValidateTypedArray (O ,
seq-cst )。
令 len 为 TypedArrayLength (taRecord )。
令 relativeTarget 为 ? ToIntegerOrInfinity (target )。
如果 relativeTarget = -∞,令 targetIndex 为 0。
否则如果 relativeTarget < 0,令 targetIndex 为 max (len
+ relativeTarget , 0)。
否则,令 targetIndex 为 min (relativeTarget ,
len )。
令 relativeStart 为 ? ToIntegerOrInfinity (start )。
如果 relativeStart = -∞,令 startIndex 为 0。
否则如果 relativeStart < 0,令 startIndex 为 max (len
+ relativeStart , 0)。
否则,令 startIndex 为 min (relativeStart ,
len )。
如果 end 为 undefined ,令 relativeEnd 为
len ;否则令 relativeEnd 为 ? ToIntegerOrInfinity (end )。
如果 relativeEnd = -∞,令 endIndex 为 0。
否则如果 relativeEnd < 0,令 endIndex 为 max (len
+ relativeEnd , 0)。
否则,令 endIndex 为 min (relativeEnd , len )。
令 count 为 min (endIndex -
startIndex , len - targetIndex )。
如果 count > 0,则
注:拷贝操作必须以保持源数据比特级编码的方式执行。
令 buffer 为 O .[[ViewedArrayBuffer]] 。
设置 taRecord 为 MakeTypedArrayWithBufferWitnessRecord (O ,
seq-cst )。
如果 IsTypedArrayOutOfBounds (taRecord )
为 true ,抛出 TypeError 异常。
设置 len 为 TypedArrayLength (taRecord )。
令 elementSize 为 TypedArrayElementSize (O )。
令 byteOffset 为 O .[[ByteOffset]] 。
令 bufferByteLimit 为 (len × elementSize )
+ byteOffset 。
令 toByteIndex 为 (targetIndex ×
elementSize ) + byteOffset 。
令 fromByteIndex 为 (startIndex ×
elementSize ) + byteOffset 。
令 countBytes 为 count × elementSize 。
如果 fromByteIndex < toByteIndex 且
toByteIndex < fromByteIndex +
countBytes ,则
令 direction 为 -1。
设置 fromByteIndex 为 fromByteIndex +
countBytes - 1。
设置 toByteIndex 为 toByteIndex +
countBytes - 1。
否则,
令 direction 为 1。
重复,直到 countBytes > 0,
如果 fromByteIndex < bufferByteLimit 且
toByteIndex < bufferByteLimit ,则
令 value 为 GetValueFromBuffer (buffer ,
fromByteIndex , uint8 ,
true , unordered )。
执行 SetValueInBuffer (buffer ,
toByteIndex , uint8 ,
value , true ,
unordered )。
设置 fromByteIndex 为 fromByteIndex +
direction 。
设置 toByteIndex 为 toByteIndex +
direction 。
设置 countBytes 为 countBytes - 1。
否则,
设置 countBytes 为 0。
返回 O 。
23.2.3.7 %TypedArray%.prototype.entries ( )
该方法被调用时执行以下步骤:
令 O 为 this 值。
执行 ? ValidateTypedArray (O ,
seq-cst )。
返回 CreateArrayIterator (O ,
key+value )。
23.2.3.8 %TypedArray%.prototype.every ( callback [ ,
thisArg ] )
该方法的参数解释和用法与 23.1.3.6 中定义的
Array.prototype.every
相同。
该方法被调用时执行以下步骤:
令 O 为 this 值。
令 taRecord 为 ? ValidateTypedArray (O ,
seq-cst )。
令 len 为 TypedArrayLength (taRecord )。
如果 IsCallable (callback ) 为
false ,抛出 TypeError 异常。
令 k 为 0。
重复,直到 k < len ,
令 Pk 为 ! ToString (𝔽 (k ))。
令 kValue 为 ! Get (O , Pk )。
令 testResult 为 ToBoolean (? Call (callback ,
thisArg , « kValue , 𝔽 (k ),
O »))。
如果 testResult 为 false ,返回
false 。
设置 k 为 k + 1。
返回 true 。
该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。
23.2.3.9 %TypedArray%.prototype.fill ( value [ ,
start [ , end ] ] )
该方法的参数解释和用法与 23.1.3.7 中定义的
Array.prototype.fill
相同。
该方法被调用时执行以下步骤:
令 O 为 this 值。
令 taRecord 为 ? ValidateTypedArray (O ,
seq-cst )。
令 len 为 TypedArrayLength (taRecord )。
如果 O .[[ContentType]] 为
bigint ,将 value 设为 ? ToBigInt (value )。
否则,将 value 设为 ? ToNumber (value )。
令 relativeStart 为 ? ToIntegerOrInfinity (start )。
如果 relativeStart = -∞,令 startIndex 为 0。
否则如果 relativeStart < 0,令 startIndex 为 max (len
+ relativeStart , 0)。
否则,令 startIndex 为 min (relativeStart ,
len )。
如果 end 为 undefined ,令 relativeEnd 为
len ;否则令 relativeEnd 为 ? ToIntegerOrInfinity (end )。
如果 relativeEnd = -∞,令 endIndex 为 0。
否则如果 relativeEnd < 0,令 endIndex 为 max (len
+ relativeEnd , 0)。
否则,令 endIndex 为 min (relativeEnd , len )。
设置 taRecord 为 MakeTypedArrayWithBufferWitnessRecord (O ,
seq-cst )。
如果 IsTypedArrayOutOfBounds (taRecord )
为 true ,抛出 TypeError 异常。
设置 len 为 TypedArrayLength (taRecord )。
设置 endIndex 为 min (endIndex , len )。
令 k 为 startIndex 。
重复,直到 k < endIndex ,
令 Pk 为 ! ToString (𝔽 (k ))。
执行 ! Set (O ,
Pk , value , true )。
设置 k 为 k + 1。
返回 O 。
23.2.3.10 %TypedArray%.prototype.filter ( callback [
, thisArg ] )
该方法的参数解释和用法与 23.1.3.8 中定义的
Array.prototype.filter
相同。
该方法被调用时执行以下步骤:
令 O 为 this 值。
令 taRecord 为 ? ValidateTypedArray (O ,
seq-cst )。
令 len 为 TypedArrayLength (taRecord )。
如果 IsCallable (callback ) 为
false ,抛出 TypeError 异常。
令 kept 为一个新的空 List 。
令 captured 为 0。
令 k 为 0。
重复,直到 k < len ,
令 Pk 为 ! ToString (𝔽 (k ))。
令 kValue 为 ! Get (O , Pk )。
令 selected 为 ToBoolean (? Call (callback ,
thisArg , « kValue , 𝔽 (k ),
O »))。
如果 selected 为 true ,则
将 kValue 添加到 kept 。
设置 captured 为 captured + 1。
设置 k 为 k + 1。
令 A 为 ? TypedArraySpeciesCreate (O , «
𝔽 (captured ) »)。
令 n 为 0。
对于 kept 的每个元素 e ,执行
执行 ! Set (A ,
! ToString (𝔽 (n )),
e , true )。
设置 n 为 n + 1。
返回 A 。
该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。
23.2.3.11 %TypedArray%.prototype.find ( predicate [ ,
thisArg ] )
该方法的参数解释和用法与 23.1.3.9 中定义的
Array.prototype.find
相同。
该方法被调用时执行以下步骤:
令 O 为 this 值。
令 taRecord 为 ? ValidateTypedArray (O ,
seq-cst )。
令 len 为 TypedArrayLength (taRecord )。
令 findRec 为 ? FindViaPredicate (O ,
len , ascending , predicate ,
thisArg )。
返回 findRec .[[Value]] 。
该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。
23.2.3.12 %TypedArray%.prototype.findIndex (
predicate [ , thisArg ] )
该方法的参数解释和用法与 23.1.3.10 中定义的
Array.prototype.findIndex
相同。
该方法被调用时执行以下步骤:
令 O 为 this 值。
令 taRecord 为 ? ValidateTypedArray (O ,
seq-cst )。
令 len 为 TypedArrayLength (taRecord )。
令 findRec 为 ? FindViaPredicate (O ,
len , ascending , predicate ,
thisArg )。
返回 findRec .[[Index]] 。
该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。
23.2.3.13 %TypedArray%.prototype.findLast ( predicate
[ , thisArg ] )
该方法的参数解释和用法与 23.1.3.11 中定义的
Array.prototype.findLast
相同。
该方法被调用时执行以下步骤:
令 O 为 this 值。
令 taRecord 为 ? ValidateTypedArray (O ,
seq-cst )。
令 len 为 TypedArrayLength (taRecord )。
令 findRec 为 ? FindViaPredicate (O ,
len , descending , predicate ,
thisArg )。
返回 findRec .[[Value]] 。
该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。
23.2.3.14 %TypedArray%.prototype.findLastIndex (
predicate [ , thisArg ] )
该方法的参数解释和用法与 23.1.3.12 中定义的
Array.prototype.findLastIndex
相同。
该方法被调用时执行以下步骤:
令 O 为 this 值。
令 taRecord 为 ? ValidateTypedArray (O ,
seq-cst )。
令 len 为 TypedArrayLength (taRecord )。
令 findRec 为 ? FindViaPredicate (O ,
len , descending , predicate ,
thisArg )。
返回 findRec .[[Index]] 。
该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。
23.2.3.15 %TypedArray%.prototype.forEach ( callback [
, thisArg ] )
该方法的参数解释和用法与 23.1.3.15 中定义的
Array.prototype.forEach
相同。
该方法被调用时执行以下步骤:
令 O 为 this 值。
令 taRecord 为 ? ValidateTypedArray (O ,
seq-cst )。
令 len 为 TypedArrayLength (taRecord )。
如果 IsCallable (callback ) 为
false ,抛出 TypeError 异常。
令 k 为 0。
重复,直到 k < len ,
令 Pk 为 ! ToString (𝔽 (k ))。
令 kValue 为 ! Get (O , Pk )。
执行 ? Call (callback ,
thisArg , « kValue , 𝔽 (k ),
O »)。
设置 k 为 k + 1。
返回 undefined 。
该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。
23.2.3.16 %TypedArray%.prototype.includes (
searchElement [ , fromIndex ] )
该方法的参数解释和用法与 23.1.3.16 中定义的
Array.prototype.includes
相同。
该方法被调用时执行以下步骤:
令 O 为 this 值。
令 taRecord 为 ? ValidateTypedArray (O ,
seq-cst )。
令 len 为 TypedArrayLength (taRecord )。
如果 len = 0,返回 false 。
令 n 为 ? ToIntegerOrInfinity (fromIndex )。
断言 :如果
fromIndex 为 undefined ,则 n 为 0。
如果 n = +∞,返回 false 。
否则如果 n = -∞,设置 n 为 0。
如果 n ≥ 0,则
令 k 为 n 。
否则,
令 k 为 len + n 。
如果 k < 0,设置 k 为 0。
重复,直到 k < len ,
令 elementK 为 ! Get (O ,
! ToString (𝔽 (k )))。
如果 SameValueZero (searchElement ,
elementK ) 为 true ,返回
true 。
设置 k 为 k + 1。
返回 false 。
该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。
23.2.3.17 %TypedArray%.prototype.indexOf (
searchElement [ , fromIndex ] )
该方法的参数解释和用法与 23.1.3.17 中定义的
Array.prototype.indexOf
相同。
该方法被调用时执行以下步骤:
令 O 为 this 值。
令 taRecord 为 ? ValidateTypedArray (O ,
seq-cst )。
令 len 为 TypedArrayLength (taRecord )。
如果 len = 0,返回 -1 𝔽 。
令 n 为 ? ToIntegerOrInfinity (fromIndex )。
断言 :如果
fromIndex 为 undefined ,则 n 为 0。
如果 n = +∞,返回 -1 𝔽 。
否则如果 n = -∞,设置 n 为 0。
如果 n ≥ 0,则
令 k 为 n 。
否则,
令 k 为 len + n 。
如果 k < 0,设置 k 为 0。
重复,直到 k < len ,
令 Pk 为 ! ToString (𝔽 (k ))。
令 kPresent 为 ! HasProperty (O ,
Pk )。
如果 kPresent 为 true ,则
令 elementK 为 ! Get (O ,
Pk )。
如果 IsStrictlyEqual (searchElement ,
elementK ) 为 true ,返回 𝔽 (k )。
设置 k 为 k + 1。
返回 -1 𝔽 。
该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。
23.2.3.18 %TypedArray%.prototype.join ( separator )
该方法的参数解释和用法与 23.1.3.18 中定义的
Array.prototype.join
相同。
该方法被调用时执行以下步骤:
令 O 为 this 值。
令 taRecord 为 ? ValidateTypedArray (O ,
seq-cst )。
令 len 为 TypedArrayLength (taRecord )。
如果 separator 为 undefined ,令 sep 为
"," 。
否则,令 sep 为 ? ToString (separator )。
令 R 为空字符串。
令 k 为 0。
重复,直到 k < len ,
如果 k > 0,令 R 为 字符串拼接 R 和
sep 的结果。
令 element 为 ! Get (O ,
! ToString (𝔽 (k )))。
如果 element 不为 undefined ,则
令 S 为 ! ToString (element )。
令 R 为 字符串拼接
R 和 S 的结果。
设置 k 为 k + 1。
返回 R 。
该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。
23.2.3.19 %TypedArray%.prototype.keys ( )
该方法被调用时执行以下步骤:
令 O 为 this 值。
执行 ? ValidateTypedArray (O ,
seq-cst )。
返回 CreateArrayIterator (O ,
key )。
23.2.3.20 %TypedArray%.prototype.lastIndexOf (
searchElement [ , fromIndex ] )
该方法的参数解释和用法与 23.1.3.20 中定义的
Array.prototype.lastIndexOf
相同。
该方法被调用时执行以下步骤:
令 O 为 this 值。
令 taRecord 为 ? ValidateTypedArray (O ,
seq-cst )。
令 len 为 TypedArrayLength (taRecord )。
如果 len = 0,返回 -1 𝔽 。
如果 fromIndex 被传入,令 n 为 ? ToIntegerOrInfinity (fromIndex );否则令
n 为 len - 1。
如果 n = -∞,返回 -1 𝔽 。
如果 n ≥ 0,则
令 k 为 min (n , len -
1)。
否则,
令 k 为 len + n 。
重复,直到 k ≥ 0,
令 Pk 为 ! ToString (𝔽 (k ))。
令 kPresent 为 ! HasProperty (O ,
Pk )。
如果 kPresent 为 true ,则
令 elementK 为 ! Get (O ,
Pk )。
如果 IsStrictlyEqual (searchElement ,
elementK ) 为 true ,返回 𝔽 (k )。
设置 k 为 k - 1。
返回 -1 𝔽 。
该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。
23.2.3.21 get %TypedArray%.prototype.length
%TypedArray% .prototype.length
是一个 访问器属性 ,其 set 访问器函数为
undefined 。其 get 访问器函数被调用时执行以下步骤:
令 O 为 this 值。
执行 ? RequireInternalSlot (O ,
[[TypedArrayName]] )。
断言 :O 拥有 [[ViewedArrayBuffer]] 和 [[ArrayLength]] 内部槽。
令 taRecord 为 MakeTypedArrayWithBufferWitnessRecord (O ,
seq-cst )。
如果 IsTypedArrayOutOfBounds (taRecord )
为 true ,返回 +0 𝔽 。
令 length 为 TypedArrayLength (taRecord )。
返回 𝔽 (length )。
该函数不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。
23.2.3.22 %TypedArray%.prototype.map ( callback [ ,
thisArg ] )
该方法的参数解释和用法与 23.1.3.21 中定义的
Array.prototype.map
相同。
该方法被调用时执行以下步骤:
令 O 为 this 值。
令 taRecord 为 ? ValidateTypedArray (O ,
seq-cst )。
令 len 为 TypedArrayLength (taRecord )。
如果 IsCallable (callback ) 为
false ,抛出 TypeError 异常。
令 A 为 ? TypedArraySpeciesCreate (O , «
𝔽 (len ) »)。
令 k 为 0。
重复,直到 k < len ,
令 Pk 为 ! ToString (𝔽 (k ))。
令 kValue 为 ! Get (O , Pk )。
令 mappedValue 为 ? Call (callback ,
thisArg , « kValue , 𝔽 (k ),
O »)。
执行 ? Set (A , Pk ,
mappedValue , true )。
设置 k 为 k + 1。
返回 A 。
该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。
23.2.3.23 %TypedArray%.prototype.reduce ( callback [
, initialValue ] )
该方法的参数解释和用法与 23.1.3.24 中定义的
Array.prototype.reduce
相同。
该方法被调用时执行以下步骤:
令 O 为 this 值。
令 taRecord 为 ? ValidateTypedArray (O ,
seq-cst )。
令 len 为 TypedArrayLength (taRecord )。
如果 IsCallable (callback ) 为
false ,抛出 TypeError 异常。
如果 len = 0 且未传入 initialValue ,抛出 TypeError
异常。
令 k 为 0。
令 accumulator 为 undefined 。
如果 initialValue 被传入,则
将 accumulator 设为 initialValue 。
否则,
令 Pk 为 ! ToString (𝔽 (k ))。
将 accumulator 设为 ! Get (O , Pk )。
设置 k 为 k + 1。
重复,直到 k < len ,
令 Pk 为 ! ToString (𝔽 (k ))。
令 kValue 为 ! Get (O , Pk )。
将 accumulator 设为 ? Call (callback ,
undefined , « accumulator , kValue ,
𝔽 (k ), O »)。
设置 k 为 k + 1。
返回 accumulator 。
该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。
23.2.3.24 %TypedArray%.prototype.reduceRight (
callback [ , initialValue ] )
该方法的参数解释和用法与 23.1.3.25 中定义的
Array.prototype.reduceRight
相同。
该方法被调用时执行以下步骤:
令 O 为 this 值。
令 taRecord 为 ? ValidateTypedArray (O ,
seq-cst )。
令 len 为 TypedArrayLength (taRecord )。
如果 IsCallable (callback ) 为
false ,抛出 TypeError 异常。
如果 len = 0 且未传入 initialValue ,抛出 TypeError
异常。
令 k 为 len - 1。
令 accumulator 为 undefined 。
如果 initialValue 被传入,则
将 accumulator 设为 initialValue 。
否则,
令 Pk 为 ! ToString (𝔽 (k ))。
将 accumulator 设为 ! Get (O , Pk )。
设置 k 为 k - 1。
重复,直到 k ≥ 0,
令 Pk 为 ! ToString (𝔽 (k ))。
令 kValue 为 ! Get (O , Pk )。
将 accumulator 设为 ? Call (callback ,
undefined , « accumulator , kValue ,
𝔽 (k ), O »)。
设置 k 为 k - 1。
返回 accumulator 。
该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。
23.2.3.25 %TypedArray%.prototype.reverse ( )
该方法的参数解释和用法与 23.1.3.26 中定义的
Array.prototype.reverse
相同。
该方法被调用时执行以下步骤:
令 O 为 this 值。
令 taRecord 为 ? ValidateTypedArray (O ,
seq-cst )。
令 len 为 TypedArrayLength (taRecord )。
令 middle 为 floor (len / 2)。
令 lower 为 0。
重复,直到 lower ≠ middle ,
令 upper 为 len - lower - 1。
令 upperP 为 ! ToString (𝔽 (upper ))。
令 lowerP 为 ! ToString (𝔽 (lower ))。
令 lowerValue 为 ! Get (O ,
lowerP )。
令 upperValue 为 ! Get (O ,
upperP )。
执行 ! Set (O ,
lowerP , upperValue , true )。
执行 ! Set (O ,
upperP , lowerValue , true )。
设置 lower 为 lower + 1。
返回 O 。
该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。
23.2.3.26 %TypedArray%.prototype.set ( source [ ,
offset ] )
该方法会在此 TypedArray 中设置多个值,从 source 读取值。具体细节取决于 source 的类型。可选的
offset 值表示在此 TypedArray 中写入值的第一个元素索引。如果省略,假定为 0。
该方法被调用时执行以下步骤:
令 target 为 this 值。
执行 ? RequireInternalSlot (target ,
[[TypedArrayName]] )。
断言 :target 拥有 [[ViewedArrayBuffer]] 内部槽。
令 targetOffset 为 ? ToIntegerOrInfinity (offset )。
如果 targetOffset < 0,抛出 RangeError 异常。
如果 source 是带有 [[TypedArrayName]] 内部槽的 对象 ,则
执行 ? SetTypedArrayFromTypedArray (target ,
targetOffset , source )。
否则,
执行 ? SetTypedArrayFromArrayLike (target ,
targetOffset , source )。
返回 undefined 。
该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。
23.2.3.26.1 SetTypedArrayFromTypedArray ( target ,
targetOffset , source )
抽象操作 SetTypedArrayFromTypedArray 接收参数 target (一个 TypedArray )、targetOffset (一个非负
整数 或
+∞)、source (一个 TypedArray ),并返回 正常完成,包含
unused 或 抛出完成 。它会在
target 从索引 targetOffset 开始,读取 source 的值设置多个值。调用时执行以下步骤:
令 targetBuffer 为 target .[[ViewedArrayBuffer]] 。
令 targetRecord 为 MakeTypedArrayWithBufferWitnessRecord (target ,
seq-cst )。
如果 IsTypedArrayOutOfBounds (targetRecord )
为 true ,抛出 TypeError 异常。
令 targetLength 为 TypedArrayLength (targetRecord )。
令 srcBuffer 为 source .[[ViewedArrayBuffer]] 。
令 srcRecord 为 MakeTypedArrayWithBufferWitnessRecord (source ,
seq-cst )。
如果 IsTypedArrayOutOfBounds (srcRecord )
为 true ,抛出 TypeError 异常。
令 srcLength 为 TypedArrayLength (srcRecord )。
令 targetType 为 TypedArrayElementType (target )。
令 targetElementSize 为 TypedArrayElementSize (target )。
令 targetByteOffset 为 target .[[ByteOffset]] 。
令 srcType 为 TypedArrayElementType (source )。
令 srcElementSize 为 TypedArrayElementSize (source )。
令 srcByteOffset 为 source .[[ByteOffset]] 。
如果 targetOffset = +∞,抛出 RangeError 异常。
如果 srcLength + targetOffset >
targetLength ,抛出 RangeError 异常。
如果 target .[[ContentType]] 不等于
source .[[ContentType]] ,抛出
TypeError 异常。
如果 IsSharedArrayBuffer (srcBuffer )
为 true ,IsSharedArrayBuffer (targetBuffer )
为 true ,并且 srcBuffer .[[ArrayBufferData]] 等于 targetBuffer .[[ArrayBufferData]] ,则令 sameSharedArrayBuffer
为 true ;否则,令 sameSharedArrayBuffer 为
false 。
如果 SameValue (srcBuffer ,
targetBuffer ) 为 true 或
sameSharedArrayBuffer 为 true ,则
令 srcByteLength 为 TypedArrayByteLength (srcRecord )。
将 srcBuffer 设为 ? CloneArrayBuffer (srcBuffer ,
srcByteOffset , srcByteLength )。
令 srcByteIndex 为 0。
否则,
令 srcByteIndex 为 srcByteOffset 。
令 targetByteIndex 为 (targetOffset ×
targetElementSize ) + targetByteOffset 。
令 limit 为 targetByteIndex +
(targetElementSize × srcLength )。
如果 srcType 等于 targetType ,则
注:传输操作必须以保持源数据比特级编码的方式执行。
重复,直到 targetByteIndex < limit ,
令 value 为 GetValueFromBuffer (srcBuffer ,
srcByteIndex , uint8 ,
true , unordered )。
执行 SetValueInBuffer (targetBuffer ,
targetByteIndex , uint8 ,
value , true ,
unordered )。
设置 srcByteIndex 为 srcByteIndex + 1。
设置 targetByteIndex 为 targetByteIndex + 1。
否则,
重复,直到 targetByteIndex < limit ,
令 value 为 GetValueFromBuffer (srcBuffer ,
srcByteIndex , srcType ,
true , unordered )。
执行 SetValueInBuffer (targetBuffer ,
targetByteIndex , targetType ,
value , true ,
unordered )。
设置 srcByteIndex 为 srcByteIndex +
srcElementSize 。
设置 targetByteIndex 为 targetByteIndex +
targetElementSize 。
返回 unused 。
23.2.3.26.2 SetTypedArrayFromArrayLike ( target ,
targetOffset , source )
抽象操作 SetTypedArrayFromArrayLike 接收参数 target (一个 TypedArray )、targetOffset (一个非负
整数 或
+∞)、source (一个 ECMAScript
语言值 ,但不是 TypedArray ),并返回 正常完成,包含
unused 或 抛出完成 。它会在
target 从索引 targetOffset 开始,读取 source 的值设置多个值。调用时执行以下步骤:
令 targetRecord 为 MakeTypedArrayWithBufferWitnessRecord (target ,
seq-cst )。
如果 IsTypedArrayOutOfBounds (targetRecord )
为 true ,抛出 TypeError 异常。
令 targetLength 为 TypedArrayLength (targetRecord )。
令 src 为 ? ToObject (source )。
令 srcLength 为 ? LengthOfArrayLike (src )。
如果 targetOffset = +∞,抛出 RangeError 异常。
如果 srcLength + targetOffset >
targetLength ,抛出 RangeError 异常。
令 k 为 0。
重复,直到 k < srcLength ,
令 Pk 为 ! ToString (𝔽 (k ))。
令 value 为 ? Get (src ,
Pk )。
令 targetIndex 为 𝔽 (targetOffset +
k )。
执行 ? TypedArraySetElement (target ,
targetIndex , value )。
设置 k 为 k + 1。
返回 unused 。
23.2.3.27 %TypedArray%.prototype.slice ( start ,
end )
该方法的参数解释和用法与 23.1.3.28 中定义的
Array.prototype.slice
相同。
该方法被调用时执行以下步骤:
令 O 为 this 值。
令 taRecord 为 ? ValidateTypedArray (O ,
seq-cst )。
令 srcArrayLength 为 TypedArrayLength (taRecord )。
令 relativeStart 为 ? ToIntegerOrInfinity (start )。
如果 relativeStart = -∞,令 startIndex 为 0。
否则如果 relativeStart < 0,令 startIndex 为 max (srcArrayLength
+
relativeStart , 0)。
否则,令 startIndex 为 min (relativeStart ,
srcArrayLength )。
如果 end 为 undefined ,令 relativeEnd 为
srcArrayLength ;否则令 relativeEnd 为 ? ToIntegerOrInfinity (end )。
如果 relativeEnd = -∞,令 endIndex 为 0。
否则如果 relativeEnd < 0,令 endIndex 为 max (srcArrayLength
+
relativeEnd , 0)。
否则,令 endIndex 为 min (relativeEnd ,
srcArrayLength )。
令 countBytes 为 max (endIndex -
startIndex , 0)。
令 A 为 ? TypedArraySpeciesCreate (O , «
𝔽 (countBytes ) »)。
如果 countBytes > 0,则
设置 taRecord 为 MakeTypedArrayWithBufferWitnessRecord (O ,
seq-cst )。
如果 IsTypedArrayOutOfBounds (taRecord )
为 true ,抛出 TypeError 异常。
设置 endIndex 为 min (endIndex , TypedArrayLength (taRecord ))。
设置 countBytes 为 max (endIndex -
startIndex , 0)。
令 srcType 为 TypedArrayElementType (O )。
令 targetType 为 TypedArrayElementType (A )。
如果 srcType 等于 targetType ,则
注:传输操作必须以保持源数据比特级编码的方式执行。
令 srcBuffer 为 O .[[ViewedArrayBuffer]] 。
令 targetBuffer 为 A .[[ViewedArrayBuffer]] 。
令 elementSize 为 TypedArrayElementSize (O )。
令 srcByteOffset 为 O .[[ByteOffset]] 。
令 srcByteIndex 为 (startIndex ×
elementSize ) + srcByteOffset 。
令 targetByteIndex 为 A .[[ByteOffset]] 。
令 endByteIndex 为 targetByteIndex +
(countBytes × elementSize )。
重复,直到 targetByteIndex <
endByteIndex ,
令 value 为 GetValueFromBuffer (srcBuffer ,
srcByteIndex , uint8 ,
true , unordered )。
执行 SetValueInBuffer (targetBuffer ,
targetByteIndex , uint8 ,
value , true ,
unordered )。
设置 srcByteIndex 为 srcByteIndex + 1。
设置 targetByteIndex 为 targetByteIndex
+ 1。
否则,
令 n 为 0。
令 k 为 startIndex 。
重复,直到 k < endIndex ,
令 Pk 为 ! ToString (𝔽 (k ))。
令 kValue 为 ! Get (O ,
Pk )。
执行 ! Set (A ,
! ToString (𝔽 (n )),
kValue , true )。
设置 k 为 k + 1。
设置 n 为 n + 1。
返回 A 。
该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。
23.2.3.28 %TypedArray%.prototype.some ( callback [ ,
thisArg ] )
该方法的参数解释和用法与 23.1.3.29 中定义的
Array.prototype.some
相同。
该方法被调用时执行以下步骤:
令 O 为 this 值。
令 taRecord 为 ? ValidateTypedArray (O ,
seq-cst )。
令 len 为 TypedArrayLength (taRecord )。
如果 IsCallable (callback ) 为
false ,抛出 TypeError 异常。
令 k 为 0。
重复,直到 k < len ,
令 Pk 为 ! ToString (𝔽 (k ))。
令 kValue 为 ! Get (O , Pk )。
令 testResult 为 ToBoolean (? Call (callback ,
thisArg , « kValue , 𝔽 (k ),
O »))。
如果 testResult 为 true ,返回
true 。
设置 k 为 k + 1。
返回 false 。
该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。
23.2.3.29 %TypedArray%.prototype.sort ( comparator )
这是一个不同的方法,除下述说明外,其实现要求与 23.1.3.30 中定义的
Array.prototype.sort
相同。该方法的实现可以利用 this 值是一个具有固定长度且其
整数索引 属性不是稀疏的对象这一事实进行优化。
该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。
该方法被调用时执行以下步骤:
如果 comparator 不为 undefined 且 IsCallable (comparator ) 为
false ,抛出 TypeError 异常。
令 obj 为 this 值。
令 taRecord 为 ? ValidateTypedArray (obj ,
seq-cst )。
令 len 为 TypedArrayLength (taRecord )。
注:以下闭包执行数值比较,而不是 23.1.3.30 中使用的字符串比较。
令 SortCompare 为一个新的 抽象闭包 ,带参数
(x , y ),捕获 comparator 并在调用时执行以下步骤:
返回 ? CompareTypedArrayElements (x ,
y , comparator )。
令 sortedList 为 ? SortIndexedProperties (obj ,
len , SortCompare , read-through-holes )。
令 j 为 0。
重复,直到 j < len ,
执行 ! Set (obj ,
! ToString (𝔽 (j )),
sortedList [j ], true )。
设置 j 为 j + 1。
返回 obj 。
注
由于 NaN 总是大于任何其他值(见 CompareTypedArrayElements ),当
comparator 未提供时,NaN 属性值总是排在结果的末尾。
23.2.3.30 %TypedArray%.prototype.subarray ( start ,
end )
该方法返回一个新的 TypedArray ,其元素类型与此 TypedArray 的元素类型相同,ArrayBuffer 也与此
TypedArray 相同,引用 start (包含)到 end (不包含)区间内的元素。如果
start 或 end 为负数,则它表示从数组末尾开始的索引,而不是从头开始。
该方法被调用时执行以下步骤:
令 O 为 this 值。
执行 ? RequireInternalSlot (O ,
[[TypedArrayName]] )。
断言 :
O 拥有 [[ViewedArrayBuffer]] 内部槽。
令 buffer 为 O .[[ViewedArrayBuffer]] 。
令 srcRecord 为 MakeTypedArrayWithBufferWitnessRecord (O ,
seq-cst )。
如果 IsTypedArrayOutOfBounds (srcRecord )
为 true ,则
令 srcLength 为 0。
否则,
令 srcLength 为 TypedArrayLength (srcRecord )。
令 relativeStart 为 ? ToIntegerOrInfinity (start )。
如果 relativeStart = -∞,令 startIndex 为 0。
否则如果 relativeStart < 0,令 startIndex 为 max (srcLength +
relativeStart , 0)。
否则,令 startIndex 为 min (relativeStart ,
srcLength )。
令 elementSize 为 TypedArrayElementSize (O )。
令 srcByteOffset 为 O .[[ByteOffset]] 。
令 beginByteOffset 为 srcByteOffset + (startIndex
× elementSize )。
如果 O .[[ArrayLength]] 为
auto 且 end 为 undefined ,则
令 argumentsList 为 « buffer , 𝔽 (beginByteOffset ) »。
否则,
如果 end 为 undefined ,令
relativeEnd 为 srcLength ;否则令
relativeEnd 为 ? ToIntegerOrInfinity (end )。
如果 relativeEnd = -∞,令 endIndex 为 0。
否则如果 relativeEnd < 0,令 endIndex 为 max (srcLength +
relativeEnd , 0)。
否则,令 endIndex 为 min (relativeEnd ,
srcLength )。
令 newLength 为 max (endIndex -
startIndex , 0)。
令 argumentsList 为 « buffer , 𝔽 (beginByteOffset ), 𝔽 (newLength ) »。
返回 ? TypedArraySpeciesCreate (O ,
argumentsList )。
该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。
23.2.3.31 %TypedArray%.prototype.toLocaleString ( [
reserved1 [ , reserved2 ] ] )
这是一个不同的方法,其实现算法与 23.1.3.32 中定义的
Array.prototype.toLocaleString
相同,只是用 TypedArrayLength 替换了对
"length" 的 [[Get]] 操作。该算法的实现可以利用
this 值在底层缓冲区不可调整大小时具有固定长度且其 整数索引 属性不是稀疏的事实进行优化。但这种优化不能引入任何可观察的行为变化。
该方法不是泛型的。调用算法前会用 this 值和 seq-cst 作为参数调用 ValidateTypedArray 。如果其结果是 异常完成 ,则抛出该异常而不是执行算法。
注
如果 ECMAScript 实现包含 ECMA-402 国际化 API,则该方法基于 ECMA-402 规范中的
Array.prototype.toLocaleString
算法。
23.2.3.32 %TypedArray%.prototype.toReversed ( )
该方法被调用时执行以下步骤:
令 O 为 this 值。
令 taRecord 为 ? ValidateTypedArray (O ,
seq-cst )。
令 length 为 TypedArrayLength (taRecord )。
令 A 为 ? TypedArrayCreateSameType (O , «
𝔽 (length ) »)。
令 k 为 0。
重复,直到 k < length ,
令 from 为 ! ToString (𝔽 (length -
k - 1))。
令 Pk 为 ! ToString (𝔽 (k ))。
令 fromValue 为 ! Get (O ,
from )。
执行 ! Set (A ,
Pk , fromValue , true )。
设置 k 为 k + 1。
返回 A 。
23.2.3.33 %TypedArray%.prototype.toSorted (
comparator )
该方法被调用时执行以下步骤:
如果 comparator 不为 undefined 且 IsCallable (comparator ) 为
false ,抛出 TypeError 异常。
令 O 为 this 值。
令 taRecord 为 ? ValidateTypedArray (O ,
seq-cst )。
令 len 为 TypedArrayLength (taRecord )。
令 A 为 ? TypedArrayCreateSameType (O , «
𝔽 (len ) »)。
注:以下闭包执行数值比较,而不是 23.1.3.34 中使用的字符串比较。
令 SortCompare 为一个新的 抽象闭包 ,带参数
(x , y ),捕获 comparator 并在调用时执行以下步骤:
返回 ? CompareTypedArrayElements (x ,
y , comparator )。
令 sortedList 为 ? SortIndexedProperties (O ,
len , SortCompare , read-through-holes )。
令 j 为 0。
重复,直到 j < len ,
执行 ! Set (A ,
! ToString (𝔽 (j )),
sortedList [j ], true )。
设置 j 为 j + 1。
返回 A 。
23.2.3.34 %TypedArray%.prototype.toString ( )
"toString" 属性的初始值是 %Array.prototype.toString%,定义见 23.1.3.36 。
23.2.3.35 %TypedArray%.prototype.values ( )
该方法被调用时执行以下步骤:
令 O 为 this 值。
执行 ? ValidateTypedArray (O ,
seq-cst )。
返回 CreateArrayIterator (O ,
value )。
23.2.3.36 %TypedArray%.prototype.with ( index ,
value )
该方法被调用时执行以下步骤:
令 O 为 this 值。
令 taRecord 为 ? ValidateTypedArray (O ,
seq-cst )。
令 len 为 TypedArrayLength (taRecord )。
令 relativeIndex 为 ? ToIntegerOrInfinity (index )。
如果 relativeIndex ≥ 0,令 actualIndex 为
relativeIndex 。
否则,令 actualIndex 为 len + relativeIndex 。
如果 O .[[ContentType]] 为
bigint ,令 numericValue 为 ? ToBigInt (value )。
否则,令 numericValue 为 ? ToNumber (value )。
如果 IsValidIntegerIndex (O ,
𝔽 (actualIndex )) 为
false ,抛出 RangeError 异常。
令 A 为 ? TypedArrayCreateSameType (O , «
𝔽 (len ) »)。
令 k 为 0。
重复,直到 k < len ,
令 Pk 为 ! ToString (𝔽 (k ))。
如果 k = actualIndex ,令 fromValue 为
numericValue 。
否则,令 fromValue 为 ! Get (O ,
Pk )。
执行 ! Set (A ,
Pk , fromValue , true )。
设置 k 为 k + 1。
返回 A 。
23.2.3.37 %TypedArray%.prototype [ %Symbol.iterator% ] ( )
%Symbol.iterator% 属性的初始值是
%TypedArray.prototype.values%,定义见 23.2.3.35 。
23.2.3.38 get %TypedArray%.prototype [ %Symbol.toStringTag% ]
%TypedArray% .prototype[%Symbol.toStringTag%]
是一个 访问器属性 ,其 set 访问器函数为
undefined 。其 get 访问器函数被调用时执行以下步骤:
令 O 为 this 值。
如果 O 不是对象 ,返回
undefined 。
如果 O 没有 [[TypedArrayName]] 内部槽,返回
undefined 。
令 name 为 O .[[TypedArrayName]] 。
断言 :
name 是字符串 。
返回 name 。
该属性具有属性 { [[Enumerable]] :
false , [[Configurable]] : true
}。
该函数的 "name" 属性的初始值为 "get
[Symbol.toStringTag]" 。
23.2.4 TypedArray 对象的抽象操作
23.2.4.1 TypedArraySpeciesCreate ( exemplar ,
argumentList )
抽象操作 TypedArraySpeciesCreate 接收参数 exemplar (一个 TypedArray )和
argumentList (一个 List ,元素为 ECMAScript 语言值 ),返回 正常完成,包含 一个 TypedArray 或
抛出完成 。它用于指定用从
exemplar 派生的 构造函数 创建新的 TypedArray 。与 ArraySpeciesCreate 可以通过 %Symbol.species% 创建非数组对象不同,此操作强制要求该
构造函数
必须创建实际的 TypedArray 。调用时执行以下步骤:
令 defaultConstructor 为 表 75 中与
exemplar .[[TypedArrayName]] 同名的内建对象。
令 constructor 为 ? SpeciesConstructor (exemplar ,
defaultConstructor )。
令 result 为 ? TypedArrayCreateFromConstructor (constructor ,
argumentList )。
断言 :
result 拥有 [[TypedArrayName]] 和 [[ContentType]] 内部槽。
如果 result .[[ContentType]] 不等于
exemplar .[[ContentType]] ,抛出
TypeError 异常。
返回 result 。
23.2.4.2 TypedArrayCreateFromConstructor (
constructor , argumentList )
抽象操作 TypedArrayCreateFromConstructor 接收参数 constructor (一个 构造函数 )和
argumentList (一个 List ,元素为ECMAScript 语言值 ),返回 正常完成,包含 一个 TypedArray 或
抛出完成 。它用于指定用
构造函数
创建新的 TypedArray 。调用时执行以下步骤:
令 newTypedArray 为 ? Construct (constructor ,
argumentList )。
令 taRecord 为 ? ValidateTypedArray (newTypedArray ,
seq-cst )。
如果 argumentList 的元素数量为 1 且 argumentList [0] 是数字 ,则
如果 IsTypedArrayOutOfBounds (taRecord )
为 true ,抛出 TypeError 异常。
令 length 为 TypedArrayLength (taRecord )。
如果 length < ℝ (argumentList [0]),抛出
TypeError 异常。
返回 newTypedArray 。
23.2.4.3 TypedArrayCreateSameType ( exemplar ,
argumentList )
抽象操作 TypedArrayCreateSameType 接收参数 exemplar (一个 TypedArray )和
argumentList (一个 List ,元素为ECMAScript 语言值 ),返回 正常完成,包含 一个 TypedArray 或
抛出完成 。它用于指定用从
exemplar 派生的 构造函数 创建新的 TypedArray 。与 TypedArraySpeciesCreate 能通过
%Symbol.species% 构造自定义 TypedArray
子类不同,此操作始终使用内建 TypedArray 构造函数 。调用时执行以下步骤:
令 constructor 为 表 75
中与 exemplar .[[TypedArrayName]] 同名的内建对象。
令 result 为 ? TypedArrayCreateFromConstructor (constructor ,
argumentList )。
断言 :
result 拥有 [[TypedArrayName]] 和 [[ContentType]] 内部槽。
断言 :
result .[[ContentType]] 等于
exemplar .[[ContentType]] 。
返回 result 。
23.2.4.4 ValidateTypedArray ( O , order )
抽象操作 ValidateTypedArray 接收参数 O (一个 ECMAScript 语言值 )和
order (seq-cst 或 unordered ),返回
正常完成,包含 一个 TypedArray
带缓冲区见证记录 或 抛出完成 。调用时执行以下步骤:
执行 ? RequireInternalSlot (O ,
[[TypedArrayName]] )。
断言 :
O 拥有 [[ViewedArrayBuffer]] 内部槽。
令 taRecord 为 MakeTypedArrayWithBufferWitnessRecord (O ,
order )。
如果 IsTypedArrayOutOfBounds (taRecord )
为 true ,抛出 TypeError 异常。
返回 taRecord 。
23.2.4.5 TypedArrayElementSize ( O )
抽象操作 TypedArrayElementSize 接收参数 O (一个 TypedArray ),返回一个非负整数 。调用时执行以下步骤:
返回 表 75 中
O .[[TypedArrayName]] 指定的元素大小值。
23.2.4.6 TypedArrayElementType ( O )
抽象操作 TypedArrayElementType 接收参数 O (一个 TypedArray ),返回 TypedArray 元素类型 。调用时执行以下步骤:
返回 表 75 中
O .[[TypedArrayName]] 指定的元素类型值。
23.2.4.7 CompareTypedArrayElements ( x , y ,
comparator )
抽象操作 CompareTypedArrayElements 接收参数 x (一个 Number 或 BigInt)、y (一个 Number 或
BigInt)、comparator (一个 函数对象 或 undefined ),返回
正常完成,包含 一个 Number 或
异常完成 。调用时执行以下步骤:
断言 :
x 是
Number 且 y 是 Number ,或者
x 是
BigInt
且 y 是
BigInt 。
如果 comparator 不为 undefined ,则
令 v 为 ? ToNumber (?
Call (comparator ,
undefined , « x , y »))。
如果 v 为 NaN ,返回
+0 𝔽 。
返回 v 。
如果 x 和 y 都是 NaN ,返回
+0 𝔽 。
如果 x 是 NaN ,返回 1 𝔽 。
如果 y 是 NaN ,返回 -1 𝔽 。
如果 x < y ,返回 -1 𝔽 。
如果 x > y ,返回 1 𝔽 。
如果 x 是 -0 𝔽 且 y 是
+0 𝔽 ,返回 -1 𝔽 。
如果 x 是 +0 𝔽 且 y 是
-0 𝔽 ,返回 1 𝔽 。
返回 +0 𝔽 。
注
这执行的是数值比较,而不是
23.1.3.30.2 中的字符串比较。
23.2.5 TypedArray 构造函数
每个 TypedArray 构造函数 :
是一个内建对象,结构如下所述,唯一的区别是 构造函数 名称不同于 TypedArray ,见 表 75 。
是一个函数,其行为会根据参数的数量和类型而异。对 TypedArray 的实际调用行为取决于传递给它的参数数量和类型。
不应作为普通函数调用,否则会抛出异常。
可以用作类定义的 extends
子句的值。想要继承指定 TypedArray 行为的子类 构造函数 必须包含对
TypedArray 构造函数 的 super
调用,以用必要的内部状态创建和初始化子类实例,以支持 %TypedArray% .prototype
内建方法。
23.2.5.1 TypedArray ( ...args )
每个 TypedArray 构造函数 被调用时执行以下步骤:
如果 NewTarget 为 undefined ,抛出 TypeError 异常。
令 constructorName 为 表 75
中为此 TypedArray 构造函数 指定的 构造函数 名称的字符串值。
令 proto 为 "%TypedArray .prototype%"
。
令 numberOfArgs 为 args 的元素数量。
如果 numberOfArgs = 0,则
返回 ? AllocateTypedArray (constructorName ,
NewTarget, proto , 0)。
否则,
令 firstArgument 为 args [0]。
如果 firstArgument 是对象 ,则
令 O 为 ? AllocateTypedArray (constructorName ,
NewTarget, proto )。
如果 firstArgument 有 [[TypedArrayName]] 内部槽,则
执行 ? InitializeTypedArrayFromTypedArray (O ,
firstArgument )。
否则如果 firstArgument 有 [[ArrayBufferData]] 内部槽,则
如果 numberOfArgs > 1,令 byteOffset 为
args [1];否则令 byteOffset 为
undefined 。
如果 numberOfArgs > 2,令 length 为
args [2];否则令 length 为
undefined 。
执行 ? InitializeTypedArrayFromArrayBuffer (O ,
firstArgument , byteOffset ,
length )。
否则,
断言 :
firstArgument 是对象 且
firstArgument
没有 [[TypedArrayName]] 或 [[ArrayBufferData]] 内部槽。
令 usingIterator 为 ? GetMethod (firstArgument ,
%Symbol.iterator% )。
如果 usingIterator 不为
undefined ,则
令 values 为 ? IteratorToList (?
GetIteratorFromMethod (firstArgument ,
usingIterator ))。
执行 ? InitializeTypedArrayFromList (O ,
values )。
否则,
注:firstArgument 不是 可迭代对象 ,所以假定它已经是
类数组对象 。
执行 ? InitializeTypedArrayFromArrayLike (O ,
firstArgument )。
返回 O 。
否则,
断言 :
firstArgument 不是对象 。
令 elementLength 为 ? ToIndex (firstArgument )。
返回 ? AllocateTypedArray (constructorName ,
NewTarget, proto , elementLength )。
23.2.5.1.1 AllocateTypedArray ( constructorName ,
newTarget , defaultProto [ , length ] )
抽象操作 AllocateTypedArray 接收参数 constructorName (一个字符串,为 TypedArray
构造函数 名称,见 表
75 ),newTarget (一个 构造函数 ),defaultProto (一个字符串),可选参数
length (一个非负整数 ),返回 正常完成,包含 一个
TypedArray 或 抛出完成 。用于校验并创建
TypedArray 构造函数 的实例。如果传入了
length ,还会分配一个相应长度的 ArrayBuffer,并与新的 TypedArray
实例关联。AllocateTypedArray 提供了 TypedArray 共享的通用语义。调用时执行以下步骤:
令 proto 为 ? GetPrototypeFromConstructor (newTarget ,
defaultProto )。
令 obj 为 TypedArrayCreate (proto )。
断言 :obj .[[ViewedArrayBuffer]] 为 undefined 。
设置 obj .[[TypedArrayName]] 为
constructorName 。
如果 constructorName 是 "BigInt64Array" 或
"BigUint64Array" ,将 obj .[[ContentType]] 设为 bigint 。
否则,将 obj .[[ContentType]] 设为
number 。
如果未传入 length ,则
设置 obj .[[ByteLength]] 为 0。
设置 obj .[[ByteOffset]] 为 0。
设置 obj .[[ArrayLength]] 为 0。
否则,
执行 ? AllocateTypedArrayBuffer (obj ,
length )。
返回 obj 。
23.2.5.1.2 InitializeTypedArrayFromTypedArray (
O , srcArray )
抽象操作 InitializeTypedArrayFromTypedArray 接收参数 O (一个 TypedArray )和
srcArray (一个 TypedArray ),返回 正常完成,包含
unused 或 抛出完成 。调用时执行以下步骤:
令 srcData 为 srcArray .[[ViewedArrayBuffer]] 。
令 elementType 为 TypedArrayElementType (O )。
令 elementSize 为 TypedArrayElementSize (O )。
令 srcType 为 TypedArrayElementType (srcArray )。
令 srcElementSize 为 TypedArrayElementSize (srcArray )。
令 srcByteOffset 为 srcArray .[[ByteOffset]] 。
令 srcRecord 为 MakeTypedArrayWithBufferWitnessRecord (srcArray ,
seq-cst )。
如果 IsTypedArrayOutOfBounds (srcRecord )
为 true ,抛出 TypeError 异常。
令 elementLength 为 TypedArrayLength (srcRecord )。
令 byteLength 为 elementSize × elementLength 。
如果 elementType 等于 srcType ,则
令 data 为 ? CloneArrayBuffer (srcData ,
srcByteOffset , byteLength )。
否则,
令 data 为 ? AllocateArrayBuffer (%ArrayBuffer% ,
byteLength )。
如果 srcArray .[[ContentType]] 不等于
O .[[ContentType]] ,抛出
TypeError 异常。
令 srcByteIndex 为 srcByteOffset 。
令 targetByteIndex 为 0。
令 count 为 elementLength 。
重复,直到 count > 0,
令 value 为 GetValueFromBuffer (srcData ,
srcByteIndex , srcType ,
true , unordered )。
执行 SetValueInBuffer (data ,
targetByteIndex , elementType ,
value , true ,
unordered )。
设置 srcByteIndex 为 srcByteIndex +
srcElementSize 。
设置 targetByteIndex 为 targetByteIndex +
elementSize 。
设置 count 为 count - 1。
设置 O .[[ViewedArrayBuffer]] 为
data 。
设置 O .[[ByteLength]] 为
byteLength 。
设置 O .[[ByteOffset]] 为 0。
设置 O .[[ArrayLength]] 为
elementLength 。
返回 unused 。
23.2.6 TypedArray 构造函数的属性
每个 TypedArray 构造函数 :
拥有一个 [[Prototype]] 内部槽,其值为 %TypedArray% 。
有一个 "length" 属性,其值为 3 𝔽 。
有一个 "name" 属性,其值为 构造函数 在 表 75 中为其指定的字符串值。
拥有以下属性:
23.2.6.1 TypedArray .BYTES_PER_ELEMENT
TypedArray .BYTES_PER_ELEMENT
的值为 表 75 中为
TypedArray 指定的元素大小值。
该属性具有属性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
23.2.6.2 TypedArray .prototype
TypedArray .prototype
的初始值为对应的 TypedArray 原型内建对象(23.2.7 )。
该属性具有属性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
23.2.7 TypedArray 原型对象的属性
每个 TypedArray 原型对象:
23.2.7.1 TypedArray .prototype.BYTES_PER_ELEMENT
TypedArray .prototype.BYTES_PER_ELEMENT
的值为 表 75 中为
TypedArray 指定的元素大小值。
该属性具有属性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
23.2.7.2 TypedArray .prototype.constructor
某给定 TypedArray 构造函数 的原型的 "constructor"
属性的初始值为该 构造函数 本身。
23.2.8 TypedArray 实例的属性
TypedArray 实例是 TypedArrays 。每个 TypedArray 实例继承自对应的
TypedArray 原型对象。每个 TypedArray 实例都有如下内部槽:[[TypedArrayName]] 、[[ViewedArrayBuffer]] 、[[ByteLength]] 、[[ByteOffset]] 和 [[ArrayLength]] 。
24 键控集合
24.1 Map 对象
Map 是一种键/值对集合,其中键和值都可以是任意的 ECMAScript 语言值 。在 Map
的集合中,每个不同的键值只能出现在一个键/值对中。不同的键值通过 SameValueZero 比较算法进行区分。
Map 必须通过哈希表或其他机制实现,这些机制平均而言可以提供次线性的元素访问时间。本规范中所用的数据结构仅用于描述 Map 所需的可观察语义,而不是可行的实现模型。
24.1.1 Map 构造函数
Map 构造函数 :
即 %Map% 。
是 全局对象 的 "Map" 属性的初始值。
作为 构造函数
调用时会创建并初始化一个新的 Map。
不应作为普通函数调用,否则会抛出异常。
可以用作类定义的 extends
子句的值。想要继承指定 Map 行为的子类 构造函数 必须包含对 Map 构造函数 的
super
调用,以用必要的内部状态创建和初始化子类实例,以支持 Map.prototype
内建方法。
24.1.1.1 Map ( [ iterable ] )
该函数被调用时执行以下步骤:
如果 NewTarget 为 undefined ,抛出 TypeError 异常。
令 map 为 ? OrdinaryCreateFromConstructor (NewTarget,
"%Map.prototype%" , « [[MapData]] »)。
设置 map .[[MapData]] 为一个新的空 List 。
如果 iterable 为 undefined 或 null ,返回
map 。
令 adder 为 ? Get (map ,
"set" )。
如果 IsCallable (adder ) 为
false ,抛出 TypeError 异常。
返回 ? AddEntriesFromIterable (map ,
iterable , adder )。
注
如果参数 iterable 存在,期望它是一个实现了 %Symbol.iterator%
方法的对象,该方法返回一个 迭代器对象 ,它会生成一个包含两个元素的 类数组对象 ,第一个元素将用作 Map
的键,第二个元素作为与该键关联的值。
24.1.1.2 AddEntriesFromIterable ( target ,
iterable , adder )
抽象操作 AddEntriesFromIterable 接收参数 target (一个对象)、iterable (ECMAScript 语言值 ,但不是
undefined 或 null )、adder (一个 函数对象 ),返回 正常完成,包含 一个 ECMAScript 语言值 或 抛出完成 。adder
调用时其接收者为 target 。调用时执行以下步骤:
令 iteratorRecord 为 ? GetIterator (iterable ,
sync )。
重复,
令 next 为 ? IteratorStepValue (iteratorRecord )。
如果 next 为 done ,返回 target 。
如果 next 不是对象 ,则
令 error 为 ThrowCompletion (一个新创建的
TypeError 对象)。
返回 ? IteratorClose (iteratorRecord ,
error )。
令 k 为 Completion (Get (next ,
"0" ))。
IfAbruptCloseIterator (k ,
iteratorRecord )。
令 v 为 Completion (Get (next ,
"1" ))。
IfAbruptCloseIterator (v ,
iteratorRecord )。
令 status 为 Completion (Call (adder ,
target , « k , v »))。
IfAbruptCloseIterator (status ,
iteratorRecord )。
注
参数 iterable 期望是一个实现了 %Symbol.iterator%
方法的对象,该方法返回一个 迭代器对象 ,它会生成一个包含两个元素的 类数组对象 ,第一个元素用作 Map
的键,第二个元素作为与该键关联的值。
24.1.2 Map 构造函数的属性
Map 构造函数 :
24.1.2.1 Map.groupBy ( items , callback )
注
callback 应该是一个接受两个参数的函数。groupBy
会按照升序对 items
中的每个元素调用 callback 一次,并构造一个新的 Map。每个 callback 返回的值会作为 Map
的键。对于每个这样的键,结果 Map 有一个键为该键、值为包含所有 callback 返回该键的元素的数组的条目。
callback 的两个参数分别是元素的值和索引。
groupBy
的返回值是一个 Map。
该函数被调用时执行以下步骤:
令 groups 为 ? GroupBy (items ,
callback , collection )。
令 map 为 ! Construct (%Map% )。
对于 groups 中的每个 Record { [[Key]] , [[Elements]] }
g ,执行
令 elements 为 CreateArrayFromList (g .[[Elements]] )。
令 entry 为 Record
{ [[Key]] : g .[[Key]] , [[Value]] :
elements }。
将 entry 添加到 map .[[MapData]] 。
返回 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 访问器函数被调用时执行以下步骤:
返回 this 值。
该函数的 "name" 属性的值为 "get [Symbol.species]" 。
注
创建派生集合对象的方法应当调用 %Symbol.species% 以确定用于创建派生对象的
构造函数 。子类 构造函数 可以重写 %Symbol.species% 以更改默认的
构造函数 分配。
24.1.3 Map 原型对象的属性
Map 原型对象 :
24.1.3.1 Map.prototype.clear ( )
该方法被调用时执行以下步骤:
令 M 为 this 值。
执行 ? RequireInternalSlot (M ,
[[MapData]] )。
对于 M .[[MapData]] 中的每个 Record { [[Key]] , [[Value]] }
p ,执行
将 p .[[Key]] 设为
empty 。
将 p .[[Value]] 设为
empty 。
返回 undefined 。
注
现有的 [[MapData]] List
会被保留,因为可能存在正在遍历该 List 的
Map 迭代器对象 。
24.1.3.2 Map.prototype.constructor
Map.prototype.constructor
的初始值为 %Map% 。
24.1.3.3 Map.prototype.delete ( key )
该方法被调用时执行以下步骤:
令 M 为 this 值。
执行 ? RequireInternalSlot (M ,
[[MapData]] )。
将 key 设为 CanonicalizeKeyedCollectionKey (key )。
对于 M .[[MapData]] 中的每个 Record { [[Key]] , [[Value]] }
p ,执行
如果 p .[[Key]] 不为
empty 且 SameValue (p .[[Key]] , key ) 为 true ,则
将 p .[[Key]] 设为
empty 。
将 p .[[Value]] 设为
empty 。
返回 true 。
返回 false 。
注
empty 作为规范设备用来表示一个条目已被删除。实际实现可能会采取其他操作,比如在内部数据结构中物理删除该条目。
24.1.3.4 Map.prototype.entries ( )
该方法被调用时执行以下步骤:
令 M 为 this 值。
返回 ? CreateMapIterator (M ,
key+value )。
24.1.3.5 Map.prototype.forEach ( callback [ ,
thisArg ] )
该方法被调用时执行以下步骤:
令 M 为 this 值。
执行 ? RequireInternalSlot (M ,
[[MapData]] )。
如果 IsCallable (callback ) 为
false ,抛出 TypeError 异常。
令 entries 为 M .[[MapData]] 。
令 numEntries 为 entries 的元素个数。
令 index 为 0。
重复,直到 index < numEntries ,
令 e 为 entries [index ]。
设置 index 为 index + 1。
如果 e .[[Key]] 不为
empty ,则
执行 ? Call (callback ,
thisArg , « e .[[Value]] , e .[[Key]] , M »)。
注:在 callback 执行期间 entries 的元素数量可能增加。
设置 numEntries 为 entries 的当前元素数量。
返回 undefined 。
注
callback 应该是一个接受三个参数的函数。forEach
会按照键的插入顺序对 Map 中每个键/值对调用
callback 一次。只有实际存在的 Map 键才会被调用 callback ;已被删除的键不会被调用。
如果提供了 thisArg 参数,则该参数会作为每次调用 callback 时的
this 值。如果未提供,则使用 undefined 。
callback 的三个参数分别是项的值、项的键,以及被遍历的 Map。
forEach
本身不会直接修改被调用对象,但该对象可能会被 callback 的调用修改。map 的 [[MapData]] 的每个条目只会被访问一次。在 forEach
开始后添加的新键会被访问。如果某个键被访问后被删除并在 forEach
完成前重新添加,则该键会被再次访问。在
forEach
开始后但被访问前被删除的键不会被访问,除非该键在 forEach
完成前被再次添加。
24.1.3.6 Map.prototype.get ( key )
该方法被调用时执行以下步骤:
令 M 为 this 值。
执行 ? RequireInternalSlot (M ,
[[MapData]] )。
将 key 设为 CanonicalizeKeyedCollectionKey (key )。
对于 M .[[MapData]] 中的每个 Record { [[Key]] , [[Value]] }
p ,执行
如果 p .[[Key]] 不为
empty 且 SameValue (p .[[Key]] , key ) 为
true ,返回 p .[[Value]] 。
返回 undefined 。
24.1.3.7 Map.prototype.has ( key )
该方法被调用时执行以下步骤:
令 M 为 this 值。
执行 ? RequireInternalSlot (M ,
[[MapData]] )。
将 key 设为 CanonicalizeKeyedCollectionKey (key )。
对于 M .[[MapData]] 中的每个 Record { [[Key]] , [[Value]] }
p ,执行
如果 p .[[Key]] 不为
empty 且 SameValue (p .[[Key]] , key ) 为
true ,返回 true 。
返回 false 。
24.1.3.8 Map.prototype.keys ( )
该方法被调用时执行以下步骤:
令 M 为 this 值。
返回 ? CreateMapIterator (M ,
key )。
24.1.3.9 Map.prototype.set ( key , value )
该方法被调用时执行以下步骤:
令 M 为 this 值。
执行 ? RequireInternalSlot (M ,
[[MapData]] )。
将 key 设为 CanonicalizeKeyedCollectionKey (key )。
对于 M .[[MapData]] 中的每个 Record { [[Key]] , [[Value]] }
p ,执行
如果 p .[[Key]] 不为
empty 且 SameValue (p .[[Key]] , key ) 为 true ,则
将 p .[[Value]] 设为
value 。
返回 M 。
令 p 为 Record { [[Key]] : key , [[Value]] :
value }。
将 p 添加到 M .[[MapData]] 。
返回 M 。
24.1.3.10 get Map.prototype.size
Map.prototype.size
是一个 访问器属性 ,其 set 访问器函数为
undefined 。其 get 访问器函数被调用时执行以下步骤:
令 M 为 this 值。
执行 ? RequireInternalSlot (M ,
[[MapData]] )。
令 count 为 0。
对于 M .[[MapData]] 中的每个 Record { [[Key]] , [[Value]] }
p ,执行
如果 p .[[Key]] 不为
empty ,则将 count 设为 count + 1。
返回 𝔽 (count )。
24.1.3.11 Map.prototype.values ( )
该方法被调用时执行以下步骤:
令 M 为 this 值。
返回 ? CreateMapIterator (M ,
value )。
24.1.3.12 Map.prototype [ %Symbol.iterator% ] ( )
%Symbol.iterator% 属性的初始值为
%Map.prototype.entries%,定义见 24.1.3.4 。
24.1.3.13 Map.prototype [ %Symbol.toStringTag% ]
%Symbol.toStringTag% 属性的初始值为字符串值
"Map" 。
该属性具有属性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : true }。
24.1.4 Map 实例的属性
Map 实例是 普通对象 ,它们继承自 Map 原型的属性。Map 实例还拥有 [[MapData]] 内部槽。
24.1.5 Map 迭代器对象
Map
迭代器 是一个表示对某个特定 Map 实例对象的特定遍历的对象。Map 迭代器对象没有具名的 构造函数 。相反,Map 迭代器对象是通过调用 Map
实例对象的某些方法创建的。
24.1.5.1 CreateMapIterator ( map , kind )
抽象操作 CreateMapIterator 接收参数 map (一个 ECMAScript 语言值 )和
kind (key+value 、key 或
value ),返回 正常完成,包含 一个生成器,或
抛出完成 。用于为返回此类
迭代器 的 Map 方法创建 迭代器对象 。调用时执行以下步骤:
执行 ? RequireInternalSlot (map ,
[[MapData]] )。
令 closure 为一个新的 抽象闭包 ,无参数,捕获 map 和
kind ,调用时执行以下步骤:
令 entries 为 map .[[MapData]] 。
令 index 为 0。
令 numEntries 为 entries 的元素数量。
重复,直到 index < numEntries ,
令 e 为 entries [index ]。
设置 index 为 index + 1。
如果 e .[[Key]] 不为
empty ,则
如果 kind 是 key ,则
令 result 为 e .[[Key]] 。
否则如果 kind 是 value ,则
令 result 为 e .[[Value]] 。
否则,
断言 :kind
是 key+value 。
令 result 为 CreateArrayFromList («
e .[[Key]] ,
e .[[Value]] »)。
执行 ? GeneratorYield (CreateIteratorResultObject (result ,
false ))。
注:在 GeneratorYield
挂起本抽象操作执行期间,entries 的元素数量可能增加。
设置 numEntries 为 entries 的元素数量。
返回 undefined 。
返回 CreateIteratorFromClosure (closure ,
"%MapIteratorPrototype%" , %MapIteratorPrototype% )。
24.1.5.2 %MapIteratorPrototype% 对象
%MapIteratorPrototype% 对象:
24.1.5.2.1 %MapIteratorPrototype%.next ( )
返回 ? GeneratorResume (this
值, empty ,
"%MapIteratorPrototype%" )。
24.1.5.2.2 %MapIteratorPrototype% [ %Symbol.toStringTag% ]
%Symbol.toStringTag% 属性的初始值为字符串值
"Map Iterator" 。
该属性具有特性 { [[Writable]] :
false , [[Enumerable]] :
false , [[Configurable]] :
true }.
24.2 Set 对象
Set 对象是 ECMAScript 语言值 的集合。在 Set
的集合中,每个不同的值只能出现一次。不同的值通过 SameValueZero 比较算法进行区分。
Set 对象必须通过哈希表或其他机制实现,这些机制在平均情况下能提供次线性的元素访问时间。本规范中所用的数据结构仅用于描述 Set 对象所需的可观察语义,而非实际的实现模型。
24.2.1 Set 对象的抽象操作
24.2.1.1 Set 记录
Set 记录 是一个 Record 值,用于封装 Set
或类似对象的接口。
Set 记录具有 表 76 中列出的字段。
表 76: Set 记录 字段
字段名
值
含义
[[SetObject]]
一个对象
该 Set 或类似对象。
[[Size]]
一个非负的 整数 或 +∞
该对象报告的大小。
[[Has]]
一个 函数对象
该对象的 has
方法。
[[Keys]]
一个 函数对象
该对象的 keys
方法。
24.2.1.2 GetSetRecord ( obj )
抽象操作 GetSetRecord 接收参数 obj (一个 ECMAScript
语言值 ),返回 正常完成,包含 一个 Set 记录
或 抛出完成 。调用时执行以下步骤:
如果 obj 不是对象 ,抛出 TypeError
异常。
令 rawSize 为 ? Get (obj ,
"size" )。
令 numSize 为 ? ToNumber (rawSize )。
注:如果 rawSize 为 undefined ,则 numSize 会是
NaN 。
如果 numSize 为 NaN ,抛出 TypeError 异常。
令 intSize 为 ! ToIntegerOrInfinity (numSize )。
如果 intSize < 0,抛出 RangeError 异常。
令 has 为 ? Get (obj ,
"has" )。
如果 IsCallable (has ) 为
false ,抛出 TypeError 异常。
令 keys 为 ? Get (obj ,
"keys" )。
如果 IsCallable (keys ) 为
false ,抛出 TypeError 异常。
返回一个新的 Set 记录 { [[SetObject]] : obj , [[Size]] : intSize , [[Has]] : has , [[Keys]] :
keys }。
24.2.1.3 SetDataHas ( setData , value )
抽象操作 SetDataHas 接收参数 setData (一个 List ,元素为 ECMAScript 语言值 或
empty )和 value (一个 ECMAScript
语言值 ),返回一个布尔值。调用时执行以下步骤:
如果 SetDataIndex (setData ,
value ) 为 not-found ,返回 false 。
返回 true 。
24.2.1.4 SetDataIndex ( setData , value )
抽象操作 SetDataIndex 接收参数 setData (一个 List ,元素为 ECMAScript 语言值 或
empty )和 value (一个 ECMAScript 语言值 ),返回一个非负的
整数 或
not-found 。调用时执行以下步骤:
将 value 设为 CanonicalizeKeyedCollectionKey (value )。
令 size 为 setData 的元素数量。
令 index 为 0。
重复,直到 index < size ,
令 e 为 setData [index ]。
如果 e 不为 empty 且 e 等于
value ,则
返回 index 。
将 index 设为 index + 1。
返回 not-found 。
24.2.1.5 SetDataSize ( setData )
抽象操作 SetDataSize 接收参数 setData (一个 List ,元素为 ECMAScript 语言值 或
empty ),返回一个非负 整数 。调用时执行以下步骤:
令 count 为 0。
对于 setData 的每个元素 e ,执行
如果 e 不为 empty ,将 count 设为
count + 1。
返回 count 。
24.2.2 Set 构造函数
Set 构造函数 :
即 %Set% 。
是 全局对象 的 "Set" 属性的初始值。
作为 构造函数
调用时会创建并初始化一个新的 Set 对象。
不应作为普通函数调用,否则会抛出异常。
可以用作类定义的 extends
子句的值。想要继承指定 Set 行为的子类 构造函数 必须包含对 Set 构造函数 的
super
调用,以用必要的内部状态创建和初始化子类实例,以支持 Set.prototype
内建方法。
24.2.2.1 Set ( [ iterable ] )
该函数被调用时执行以下步骤:
如果 NewTarget 为 undefined ,抛出 TypeError 异常。
令 set 为 ? OrdinaryCreateFromConstructor (NewTarget,
"%Set.prototype%" , « [[SetData]] »)。
设置 set .[[SetData]] 为一个新的空 List 。
如果 iterable 为 undefined 或 null ,返回
set 。
令 adder 为 ? Get (set ,
"add" )。
如果 IsCallable (adder ) 为
false ,抛出 TypeError 异常。
令 iteratorRecord 为 ? GetIterator (iterable ,
sync )。
重复,
令 next 为 ? IteratorStepValue (iteratorRecord )。
如果 next 为 done ,返回 set 。
令 status 为 Completion (Call (adder ,
set , « next »))。
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 访问器函数被调用时执行以下步骤:
返回 this 值。
该函数的 "name" 属性值为 "get [Symbol.species]" 。
注
创建派生集合对象的方法应当调用 %Symbol.species% 以确定用于创建派生对象的
构造函数 。子类 构造函数 可以重写 %Symbol.species% 以更改默认的
构造函数 分配。
24.2.4 Set 原型对象的属性
Set 原型对象 :
24.2.4.1 Set.prototype.add ( value )
该方法被调用时执行以下步骤:
令 S 为 this 值。
执行 ? RequireInternalSlot (S ,
[[SetData]] ).
将 value 设为 CanonicalizeKeyedCollectionKey (value )。
对于 S .[[SetData]] 的每个元素 e ,执行
如果 e 不为 empty 且 SameValue (e ,
value ) 为 true ,则
返回 S 。
将 value 添加到 S .[[SetData]] 。
返回 S 。
24.2.4.2 Set.prototype.clear ( )
该方法被调用时执行以下步骤:
令 S 为 this 值。
执行 ? RequireInternalSlot (S ,
[[SetData]] ).
对于 S .[[SetData]] 的每个元素 e ,执行
将 S .[[SetData]] 中值为 e
的元素替换为值为 empty 的元素。
返回 undefined 。
注
现有的 [[SetData]] List
会被保留,因为可能存在正在遍历该 List 的
Set 迭代器对象 。
24.2.4.3 Set.prototype.constructor
Set.prototype.constructor
的初始值为 %Set% 。
24.2.4.4 Set.prototype.delete ( value )
该方法被调用时执行以下步骤:
令 S 为 this 值。
执行 ? RequireInternalSlot (S ,
[[SetData]] ).
将 value 设为 CanonicalizeKeyedCollectionKey (value )。
对于 S .[[SetData]] 的每个元素 e ,执行
如果 e 不为 empty 且 SameValue (e ,
value ) 为 true ,则
将 S .[[SetData]] 中值为 e
的元素替换为值为 empty 的元素。
返回 true 。
返回 false 。
注
empty 作为规范设备用来表示一个条目已被删除。实际实现可能会采取其他操作,比如在内部数据结构中物理删除该条目。
24.2.4.5 Set.prototype.difference ( other )
该方法被调用时执行以下步骤:
令 O 为 this 值。
执行 ? RequireInternalSlot (O ,
[[SetData]] ).
令 otherRec 为 ? GetSetRecord (other )。
令 resultSetData 为 O .[[SetData]]
的一个副本。
如果 SetDataSize (O .[[SetData]] ) ≤ otherRec .[[Size]] ,则
令 thisSize 为 O .[[SetData]]
的元素数量。
令 index 为 0。
重复,直到 index < thisSize ,
令 e 为 resultSetData [index ]。
如果 e 不为 empty ,则
令 inOther 为 ToBoolean (?
Call (otherRec .[[Has]] , otherRec .[[SetObject]] , «
e »))。
如果 inOther 为 true ,则
将 resultSetData [index ] 设为
empty 。
将 index 设为 index + 1。
否则,
令 keysIter 为 ? GetIteratorFromMethod (otherRec .[[SetObject]] , otherRec .[[Keys]] )。
令 next 为 not-started 。
重复,直到 next 不为 done ,
将 next 设为 ? IteratorStepValue (keysIter )。
如果 next 不为 done ,则
将 next 设为 CanonicalizeKeyedCollectionKey (next )。
令 valueIndex 为 SetDataIndex (resultSetData ,
next )。
如果 valueIndex 不为
not-found ,则
将 resultSetData [valueIndex ] 设为
empty 。
令 result 为 OrdinaryObjectCreate (%Set.prototype% ,
« [[SetData]] »)。
设置 result .[[SetData]] 为
resultSetData 。
返回 result 。
24.2.4.6 Set.prototype.entries ( )
该方法被调用时执行以下步骤:
令 S 为 this 值。
返回 ? CreateSetIterator (S ,
key+value )。
注
对于遍历目的,Set 类似于每个条目的键和值都相同的 Map。
24.2.4.7 Set.prototype.forEach ( callback [ ,
thisArg ] )
该方法被调用时执行以下步骤:
令 S 为 this 值。
执行 ? RequireInternalSlot (S ,
[[SetData]] )。
如果 IsCallable (callback ) 为
false ,抛出 TypeError 异常。
令 entries 为 S .[[SetData]] 。
令 numEntries 为 entries 的元素数量。
令 index 为 0。
重复,直到 index < numEntries ,
令 e 为 entries [index ]。
设置 index 为 index + 1。
如果 e 不为 empty ,则
执行 ? Call (callback ,
thisArg , « e , e ,
S »)。
注:在 callback 执行期间 entries 的数量可能增加。
设置 numEntries 为 entries 的当前元素数量。
返回 undefined 。
注
callback 应该是一个接受三个参数的函数。forEach
会按照值插入顺序对 Set 对象中每个存在的值调用
callback 一次。只有实际存在的 Set 值才会被调用 callback ;已被删除的键不会被调用。
如果提供了 thisArg 参数,则其会用作每次调用 callback 时的 this
值。如果未提供,则使用 undefined 。
callback 会被传入三个参数:前两个参数是 Set 中包含的同一个值,第三个参数是正在遍历的 Set 对象。
回调函数采用三个参数是为了与 Map 和 Array 的 forEach
方法的回调一致。对于 Set,每个元素既视为键又视为值。
forEach
本身不会直接修改被调用对象,但该对象可能会被 callback 的调用修改。
每个值通常只会被访问一次。不过,如果某个值被访问后被删除并在 forEach
完成前重新添加,则该值会被再次访问。在
forEach
开始后但被访问前被删除的值不会被访问,除非该值在 forEach
完成前被再次添加。在
forEach
开始后添加的新值会被访问。
24.2.4.8 Set.prototype.has ( value )
该方法被调用时执行以下步骤:
令 S 为 this 值。
执行 ? RequireInternalSlot (S ,
[[SetData]] )。
将 value 设为 CanonicalizeKeyedCollectionKey (value )。
对于 S .[[SetData]] 的每个元素 e ,执行
如果 e 不为 empty 且 SameValue (e ,
value ) 为 true ,返回 true 。
返回 false 。
24.2.4.9 Set.prototype.intersection ( other )
该方法被调用时执行以下步骤:
令 O 为 this 值。
执行 ? RequireInternalSlot (O ,
[[SetData]] )。
令 otherRec 为 ? GetSetRecord (other )。
令 resultSetData 为一个新的空 List 。
如果 SetDataSize (O .[[SetData]] ) ≤ otherRec .[[Size]] ,则
令 thisSize 为 O .[[SetData]]
的元素数量。
令 index 为 0。
重复,直到 index < thisSize ,
令 e 为 O .[[SetData]] [index ]。
设置 index 为 index + 1。
如果 e 不为 empty ,则
令 inOther 为 ToBoolean (?
Call (otherRec .[[Has]] , otherRec .[[SetObject]] , «
e »))。
如果 inOther 为 true ,则
注:较早对 otherRec .[[Has]] 的调用可能会移除并重新添加
O .[[SetData]]
的元素,这可能导致同一元素在本遍历中被访问两次。
如果 SetDataHas (resultSetData ,
e ) 为 false ,则
将 e 添加到 resultSetData 。
注:在 otherRec .[[Has]]
执行期间,O .[[SetData]]
的元素数量可能增加。
设置 thisSize 为 O .[[SetData]] 的当前元素数量。
否则,
令 keysIter 为 ? GetIteratorFromMethod (otherRec .[[SetObject]] , otherRec .[[Keys]] )。
令 next 为 not-started 。
重复,直到 next 不为 done ,
将 next 设为 ? IteratorStepValue (keysIter )。
如果 next 不为 done ,则
将 next 设为 CanonicalizeKeyedCollectionKey (next )。
令 inThis 为 SetDataHas (O .[[SetData]] , next )。
如果 inThis 为 true ,则
注:由于 other 是任意对象,其
"keys" 迭代器
可能会多次产出同一值。
如果 SetDataHas (resultSetData ,
next ) 为 false ,则
将 next 添加到
resultSetData 。
令 result 为 OrdinaryObjectCreate (%Set.prototype% ,
« [[SetData]] »)。
设置 result .[[SetData]] 为
resultSetData 。
返回 result 。
24.2.4.10 Set.prototype.isDisjointFrom ( other )
该方法被调用时执行以下步骤:
令 O 为 this 值。
执行 ? RequireInternalSlot (O ,
[[SetData]] )。
令 otherRec 为 ? GetSetRecord (other )。
如果 SetDataSize (O .[[SetData]] ) ≤ otherRec .[[Size]] ,则
令 thisSize 为 O .[[SetData]]
的元素数量。
令 index 为 0。
重复,直到 index < thisSize ,
令 e 为 O .[[SetData]] [index ]。
设置 index 为 index + 1。
如果 e 不为 empty ,则
令 inOther 为 ToBoolean (?
Call (otherRec .[[Has]] , otherRec .[[SetObject]] , «
e »))。
如果 inOther 为 true ,返回
false 。
注:在 otherRec .[[Has]]
执行期间,O .[[SetData]]
的元素数量可能增加。
设置 thisSize 为 O .[[SetData]] 的当前元素数量。
否则,
令 keysIter 为 ? GetIteratorFromMethod (otherRec .[[SetObject]] , otherRec .[[Keys]] )。
令 next 为 not-started 。
重复,直到 next 不为 done ,
将 next 设为 ? IteratorStepValue (keysIter )。
如果 next 不为 done ,则
如果 SetDataHas (O .[[SetData]] , next ) 为
true ,则
执行 ? IteratorClose (keysIter ,
NormalCompletion (unused ))。
返回 false 。
返回 true 。
24.2.4.11 Set.prototype.isSubsetOf ( other )
该方法被调用时执行以下步骤:
令 O 为 this 值。
执行 ? RequireInternalSlot (O ,
[[SetData]] )。
令 otherRec 为 ? GetSetRecord (other )。
如果 SetDataSize (O .[[SetData]] ) > otherRec .[[Size]] ,返回 false 。
令 thisSize 为 O .[[SetData]] 的元素数量。
令 index 为 0。
重复,直到 index < thisSize ,
令 e 为 O .[[SetData]] [index ]。
设置 index 为 index + 1。
如果 e 不为 empty ,则
令 inOther 为 ToBoolean (? Call (otherRec .[[Has]] , otherRec .[[SetObject]] , « e »))。
如果 inOther 为 false ,返回
false 。
注:在 otherRec .[[Has]]
执行期间,O .[[SetData]] 的元素数量可能增加。
设置 thisSize 为 O .[[SetData]] 的当前元素数量。
返回 true 。
24.2.4.12 Set.prototype.isSupersetOf ( other )
该方法被调用时执行以下步骤:
令 O 为 this 值。
执行 ? RequireInternalSlot (O ,
[[SetData]] )。
令 otherRec 为 ? GetSetRecord (other )。
如果 SetDataSize (O .[[SetData]] ) < otherRec .[[Size]] ,返回 false 。
令 keysIter 为 ? GetIteratorFromMethod (otherRec .[[SetObject]] , otherRec .[[Keys]] )。
令 next 为 not-started 。
重复,直到 next 不为 done ,
将 next 设为 ? IteratorStepValue (keysIter )。
如果 next 不为 done ,则
如果 SetDataHas (O .[[SetData]] , next ) 为
false ,则
执行 ? IteratorClose (keysIter ,
NormalCompletion (unused ))。
返回 false 。
返回 true 。
24.2.4.13 Set.prototype.keys ( )
"keys" 属性的初始值为 %Set.prototype.values%,定义见 24.2.4.17 。
注
对于遍历目的,Set 类似于每个条目的键和值都相同的 Map。
24.2.4.14 get Set.prototype.size
Set.prototype.size
是一个 访问器属性 ,其 set 访问器函数为
undefined 。其 get 访问器函数被调用时执行以下步骤:
令 S 为 this 值。
执行 ? RequireInternalSlot (S ,
[[SetData]] )。
令 size 为 SetDataSize (S .[[SetData]] )。
返回 𝔽 (size )。
24.2.4.15 Set.prototype.symmetricDifference ( other )
该方法被调用时执行以下步骤:
令 O 为 this 值。
执行 ? RequireInternalSlot (O ,
[[SetData]] )。
令 otherRec 为 ? GetSetRecord (other )。
令 keysIter 为 ? GetIteratorFromMethod (otherRec .[[SetObject]] , otherRec .[[Keys]] )。
令 resultSetData 为 O .[[SetData]]
的一个副本。
令 next 为 not-started 。
重复,直到 next 不为 done ,
将 next 设为 ? IteratorStepValue (keysIter )。
如果 next 不为 done ,则
将 next 设为 CanonicalizeKeyedCollectionKey (next )。
令 resultIndex 为 SetDataIndex (resultSetData ,
next )。
如果 resultIndex 为 not-found ,令
alreadyInResult 为 false 。否则令
alreadyInResult 为 true 。
如果 SetDataHas (O .[[SetData]] , next ) 为
true ,则
如果 alreadyInResult 为 true ,将
resultSetData [resultIndex ] 设为
empty 。
否则,
如果 alreadyInResult 为 false ,将
next 添加到 resultSetData 。
令 result 为 OrdinaryObjectCreate (%Set.prototype% ,
« [[SetData]] »)。
设置 result .[[SetData]] 为
resultSetData 。
返回 result 。
24.2.4.16 Set.prototype.union ( other )
该方法被调用时执行以下步骤:
令 O 为 this 值。
执行 ? RequireInternalSlot (O ,
[[SetData]] )。
令 otherRec 为 ? GetSetRecord (other )。
令 keysIter 为 ? GetIteratorFromMethod (otherRec .[[SetObject]] , otherRec .[[Keys]] )。
令 resultSetData 为 O .[[SetData]]
的一个副本。
令 next 为 not-started 。
重复,直到 next 不为 done ,
将 next 设为 ? IteratorStepValue (keysIter )。
如果 next 不为 done ,则
将 next 设为 CanonicalizeKeyedCollectionKey (next )。
如果 SetDataHas (resultSetData ,
next ) 为 false ,则
将 next 添加到 resultSetData 。
令 result 为 OrdinaryObjectCreate (%Set.prototype% ,
« [[SetData]] »)。
设置 result .[[SetData]] 为
resultSetData 。
返回 result 。
24.2.4.17 Set.prototype.values ( )
该方法被调用时执行以下步骤:
令 S 为 this 值。
返回 ? CreateSetIterator (S ,
value )。
24.2.4.18 Set.prototype [ %Symbol.iterator% ] ( )
%Symbol.iterator% 属性的初始值为
%Set.prototype.values%,定义见 24.2.4.17 。
24.2.4.19 Set.prototype [ %Symbol.toStringTag% ]
%Symbol.toStringTag% 属性的初始值为字符串值
"Set" 。
该属性具有属性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : true }。
24.2.5 Set 实例的属性
Set 实例是 普通对象 ,它们继承自 Set 原型的属性。Set 实例还拥有 [[SetData]] 内部槽。
24.2.6 Set 迭代器对象
Set
迭代器 是一个 普通对象 ,结构如下定义,用于表示对某个特定 Set 实例对象的特定遍历。Set
迭代器对象没有具名的 构造函数 。相反,Set 迭代器对象是通过调用 Set 实例对象的某些方法创建的。
24.2.6.1 CreateSetIterator ( set , kind )
抽象操作 CreateSetIterator 接收参数 set (一个 ECMAScript 语言值 )和
kind (key+value 或 value ),返回
正常完成,包含 一个生成器,或
抛出完成 。用于为返回此类
迭代器 的 Set 方法创建 迭代器对象 。调用时执行以下步骤:
执行 ? RequireInternalSlot (set ,
[[SetData]] )。
令 closure 为一个新的 抽象闭包 ,无参数,捕获 set 和
kind ,调用时执行以下步骤:
令 index 为 0。
令 entries 为 set .[[SetData]] 。
令 numEntries 为 entries 的元素数量。
重复,直到 index < numEntries ,
令 e 为 entries [index ]。
设置 index 为 index + 1。
如果 e 不为 empty ,则
如果 kind 是 key+value ,则
令 result 为 CreateArrayFromList («
e , e »)。
执行 ? GeneratorYield (CreateIteratorResultObject (result ,
false ))。
否则,
断言 :kind
是 value 。
执行 ? GeneratorYield (CreateIteratorResultObject (e ,
false ))。
注:在 GeneratorYield
挂起本抽象操作执行期间,entries 的元素数量可能增加。
设置 numEntries 为 entries 的当前元素数量。
返回 undefined 。
返回 CreateIteratorFromClosure (closure ,
"%SetIteratorPrototype%" , %SetIteratorPrototype% )。
24.2.6.2 %SetIteratorPrototype% 对象
%SetIteratorPrototype% 对象:
24.2.6.2.1 %SetIteratorPrototype%.next ( )
返回 ? GeneratorResume (this
值, empty ,
"%SetIteratorPrototype%" )。
24.2.6.2.2 %SetIteratorPrototype% [ %Symbol.toStringTag% ]
%Symbol.toStringTag% 属性的初始值为字符串值
"Set Iterator" 。
该属性具有属性 { [[Writable]] :
false , [[Enumerable]] :
false , [[Configurable]] :
true }.
24.3 WeakMap 对象
WeakMap 是键/值对的集合,其中键是对象和/或符号,值可以是任意的 ECMAScript 语言值 。WeakMap
可以用来查询是否包含某个特定键的键/值对,但没有机制用于枚举它所持有的所有键。在某些情况下,非 存活 的值会被从 WeakMap 的键中移除,详见 9.9.3 。
实现可能会对 WeakMap 的某个键/值对变得不可访问与被移除之间施加任意的延迟。如果这个延迟对 ECMAScript 程序是可观察的,则会带来不确定性,影响程序执行。因此,ECMAScript
的实现不得提供任何无需观察者持有该键即可观察 WeakMap 键的手段。
WeakMap 必须通过哈希表或其他机制实现,这些机制在平均情况下能提供次线性的键/值对访问时间。本规范中所用的数据结构仅用于描述 WeakMap 所需的可观察语义,而非实际的实现模型。
注
WeakMap 和 WeakSet 旨在为对象或符号动态关联状态,且如果没有 WeakMap 或 WeakSet
实例,该对象或符号变得不可访问并被垃圾回收机制回收时,不会“泄漏”内存资源。可以通过将 WeakMap 或 WeakSet 实例反向映射到每个对象/符号实现这一特性。或者,每个
WeakMap 或 WeakSet 实例可以内部存储其键和值数据,但这种方法需要 WeakMap/WeakSet 实现与垃圾回收器协作。下列参考文献介绍了对 WeakMap 和
WeakSet 实现可能有用的机制:
Barry Hayes. 1997. Ephemerons: a new finalization mechanism. 载于 Proceedings of the 12th
ACM SIGPLAN conference on Object-oriented programming, systems, languages, and
applications (OOPSLA '97) , A. Michael Berman (编辑). ACM, New York, NY, USA, 176-183,
http://doi.acm.org/10.1145/263698.263733 .
Alexandra Barros, Roberto Ierusalimschy, Eliminating Cycles in Weak Tables. Journal of
Universal Computer Science - J.UCS, vol. 14, no. 21, pp. 3481-3497, 2008, http://www.jucs.org/jucs_14_21/eliminating_cycles_in_weak
24.3.1 WeakMap 构造函数
WeakMap 构造函数 :
即 %WeakMap% 。
是 全局对象 的 "WeakMap" 属性的初始值。
作为 构造函数
调用时会创建并初始化一个新的 WeakMap。
不应作为普通函数调用,否则会抛出异常。
可以用作类定义的 extends
子句的值。想要继承指定 WeakMap 行为的子类 构造函数 必须包含对 WeakMap 构造函数 的
super
调用,以用必要的内部状态创建和初始化子类实例,以支持 WeakMap.prototype
内建方法。
24.3.1.1 WeakMap ( [ iterable ] )
该函数被调用时执行以下步骤:
如果 NewTarget 为 undefined ,抛出 TypeError 异常。
令 map 为 ? OrdinaryCreateFromConstructor (NewTarget,
"%WeakMap.prototype%" , « [[WeakMapData]] »)。
设置 map .[[WeakMapData]] 为一个新的空 List 。
如果 iterable 为 undefined 或 null ,返回
map 。
令 adder 为 ? Get (map ,
"set" )。
如果 IsCallable (adder ) 为
false ,抛出 TypeError 异常。
返回 ? AddEntriesFromIterable (map ,
iterable , adder )。
注
如果参数 iterable 存在,期望它是一个实现了 %Symbol.iterator%
方法的对象,该方法返回一个 迭代器对象 ,会产生一个二元素 类数组对象 ,其第一个元素作为 WeakMap
的键,第二个元素为要与该键关联的值。
24.3.2 WeakMap 构造函数的属性
WeakMap 构造函数 :
24.3.2.1 WeakMap.prototype
WeakMap.prototype
的初始值为 WeakMap 原型对象 。
该属性具有属性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
24.3.3 WeakMap 原型对象的属性
WeakMap 原型对象 :
24.3.3.1 WeakMap.prototype.constructor
WeakMap.prototype.constructor
的初始值为 %WeakMap% 。
24.3.3.2 WeakMap.prototype.delete ( key )
该方法被调用时执行以下步骤:
令 M 为 this 值。
执行 ? RequireInternalSlot (M ,
[[WeakMapData]] )。
如果 CanBeHeldWeakly (key )
为 false ,返回 false 。
对于 M .[[WeakMapData]] 中的每个 Record { [[Key]] , [[Value]] }
p ,执行
如果 p .[[Key]] 不为
empty 且 SameValue (p .[[Key]] , key ) 为 true ,则
将 p .[[Key]] 设为
empty 。
将 p .[[Value]] 设为
empty 。
返回 true 。
返回 false 。
注
empty 作为规范设备用来表示一个条目已被删除。实际实现可能会采取其他操作,比如在内部数据结构中物理删除该条目。
24.3.3.3 WeakMap.prototype.get ( key )
该方法被调用时执行以下步骤:
令 M 为 this 值。
执行 ? RequireInternalSlot (M ,
[[WeakMapData]] )。
如果 CanBeHeldWeakly (key )
为 false ,返回 undefined 。
对于 M .[[WeakMapData]] 中的每个 Record { [[Key]] , [[Value]] }
p ,执行
如果 p .[[Key]] 不为
empty 且 SameValue (p .[[Key]] , key ) 为
true ,返回 p .[[Value]] 。
返回 undefined 。
24.3.3.4 WeakMap.prototype.has ( key )
该方法被调用时执行以下步骤:
令 M 为 this 值。
执行 ? RequireInternalSlot (M ,
[[WeakMapData]] )。
如果 CanBeHeldWeakly (key )
为 false ,返回 false 。
对于 M .[[WeakMapData]] 中的每个 Record { [[Key]] , [[Value]] }
p ,执行
如果 p .[[Key]] 不为
empty 且 SameValue (p .[[Key]] , key ) 为
true ,返回 true 。
返回 false 。
24.3.3.5 WeakMap.prototype.set ( key ,
value )
该方法被调用时执行以下步骤:
令 M 为 this 值。
执行 ? RequireInternalSlot (M ,
[[WeakMapData]] )。
如果 CanBeHeldWeakly (key )
为 false ,抛出 TypeError 异常。
对于 M .[[WeakMapData]] 中的每个 Record { [[Key]] , [[Value]] }
p ,执行
如果 p .[[Key]] 不为
empty 且 SameValue (p .[[Key]] , key ) 为 true ,则
将 p .[[Value]] 设为
value 。
返回 M 。
令 p 为 Record { [[Key]] : key , [[Value]] :
value }。
将 p 添加到 M .[[WeakMapData]] 。
返回 M 。
24.3.3.6 WeakMap.prototype [ %Symbol.toStringTag% ]
%Symbol.toStringTag% 属性的初始值为字符串值
"WeakMap" 。
该属性具有属性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : true }。
24.3.4 WeakMap 实例的属性
WeakMap 实例是 普通对象 ,它们继承自 WeakMap 原型的属性。WeakMap 实例还拥有 [[WeakMapData]]
内部槽。
24.4 WeakSet 对象
WeakSet 是对象和/或符号的集合。在 WeakSet 的集合中,每个不同的对象或符号只能出现一次。WeakSet
可以用来查询是否包含某个特定值,但没有机制用于枚举它所持有的所有值。在某些情况下,非 存活 的值会被从 WeakSet 元素中移除,详见 9.9.3 。
实现可能会对 WeakSet 所包含的某个值变得不可访问与被移除之间施加任意的延迟。如果这个延迟对 ECMAScript 程序是可观察的,则会带来不确定性,影响程序执行。因此,ECMAScript
的实现不得提供任何无需观察者持有该值即可确定 WeakSet 是否包含该值的手段。
WeakSet 必须通过哈希表或其他机制实现,这些机制在平均情况下能提供次线性的元素访问时间。本规范中所用的数据结构仅用于描述 WeakSet 所需的可观察语义,而非实际的实现模型。
注
24.4.1 WeakSet 构造函数
WeakSet 构造函数 :
即 %WeakSet% 。
是 全局对象 的 "WeakSet" 属性的初始值。
作为 构造函数
调用时会创建并初始化一个新的 WeakSet。
不应作为普通函数调用,否则会抛出异常。
可以用作类定义的 extends
子句的值。想要继承指定 WeakSet 行为的子类 构造函数 必须包含对 WeakSet 构造函数 的
super
调用,以用必要的内部状态创建和初始化子类实例,以支持 WeakSet.prototype
内建方法。
24.4.1.1 WeakSet ( [ iterable ] )
该函数被调用时执行以下步骤:
如果 NewTarget 为 undefined ,抛出 TypeError 异常。
令 set 为 ? OrdinaryCreateFromConstructor (NewTarget,
"%WeakSet.prototype%" , « [[WeakSetData]] »)。
设置 set .[[WeakSetData]] 为一个新的空 List 。
如果 iterable 为 undefined 或 null ,返回
set 。
令 adder 为 ? Get (set ,
"add" )。
如果 IsCallable (adder ) 为
false ,抛出 TypeError 异常。
令 iteratorRecord 为 ? GetIterator (iterable ,
sync )。
重复,
令 next 为 ? IteratorStepValue (iteratorRecord )。
如果 next 为 done ,返回 set 。
令 status 为 Completion (Call (adder ,
set , « next »))。
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 原型对象 :
24.4.3.1 WeakSet.prototype.add ( value )
该方法被调用时执行以下步骤:
令 S 为 this 值。
执行 ? RequireInternalSlot (S ,
[[WeakSetData]] )。
如果 CanBeHeldWeakly (value )
为 false ,抛出 TypeError 异常。
对于 S .[[WeakSetData]] 的每个元素 e ,执行
如果 e 不为 empty 且 SameValue (e ,
value ) 为 true ,则
返回 S 。
将 value 添加到 S .[[WeakSetData]] 。
返回 S 。
24.4.3.2 WeakSet.prototype.constructor
WeakSet.prototype.constructor
的初始值为 %WeakSet% 。
24.4.3.3 WeakSet.prototype.delete ( value )
该方法被调用时执行以下步骤:
令 S 为 this 值。
执行 ? RequireInternalSlot (S ,
[[WeakSetData]] )。
如果 CanBeHeldWeakly (value )
为 false ,返回 false 。
对于 S .[[WeakSetData]] 的每个元素 e ,执行
如果 e 不为 empty 且 SameValue (e ,
value ) 为 true ,则
将 S .[[WeakSetData]] 中值为
e 的元素替换为值为 empty 的元素。
返回 true 。
返回 false 。
注
empty 作为规范设备用来表示一个条目已被删除。实际实现可能会采取其他操作,比如在内部数据结构中物理删除该条目。
24.4.3.4 WeakSet.prototype.has ( value )
该方法被调用时执行以下步骤:
令 S 为 this 值。
执行 ? RequireInternalSlot (S ,
[[WeakSetData]] )。
如果 CanBeHeldWeakly (value )
为 false ,返回 false 。
对于 S .[[WeakSetData]] 的每个元素 e ,执行
如果 e 不为 empty 且 SameValue (e ,
value ) 为 true ,返回 true 。
返回 false 。
24.4.3.5 WeakSet.prototype [ %Symbol.toStringTag% ]
%Symbol.toStringTag% 属性的初始值为字符串值
"WeakSet" 。
该属性具有属性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : true }。
24.4.4 WeakSet 实例的属性
WeakSet 实例是 普通对象 ,它们继承自 WeakSet 原型的属性。WeakSet 实例还拥有 [[WeakSetData]]
内部槽。
24.5 键控集合的抽象操作
24.5.1 CanonicalizeKeyedCollectionKey ( key )
抽象操作 CanonicalizeKeyedCollectionKey 接收参数 key (一个 ECMAScript 语言值 ),并返回一个 ECMAScript 语言值 。调用时执行以下步骤:
如果 key 是 -0 𝔽 ,返回
+0 𝔽 。
返回 key 。
25 结构化数据
25.1 ArrayBuffer 对象
25.1.1 记号
本节、25.4 以及 29 中的描述使用了读-改-写修改函数内部数据结构。
读-改-写修改函数
是一个数学函数,被表示为一个抽象闭包,接收两个 List 的
字节值
作为参数,并返回一个 List 的 字节值 。这些抽象闭包满足以下所有属性:
它们以原子方式执行其所有算法步骤。
它们的每个算法步骤都是不可观察的。
注
为帮助验证读-改-写修改函数的算法步骤是否构成了纯数学函数,推荐以下编辑约定:
25.1.2 固定长度和可调整长度的 ArrayBuffer 对象
固定长度 ArrayBuffer 是指创建后字节长度不可更改的 ArrayBuffer。
可调整长度 ArrayBuffer 是指其字节长度可以在创建后通过调用 ArrayBuffer.prototype.resize (
newLength ) 进行更改的 ArrayBuffer。
所创建的 ArrayBuffer 对象的种类取决于传递给 ArrayBuffer ( length [ , options ]
) 的参数。
25.1.3 ArrayBuffer 对象的抽象操作
25.1.3.1 AllocateArrayBuffer ( constructor ,
byteLength [ , maxByteLength ] )
抽象操作 AllocateArrayBuffer 接收参数 constructor (一个 构造函数 )、byteLength (非负整数 ),可选参数
maxByteLength (非负整数 或 empty ),返回一个 正常完成,包含 ArrayBuffer
或 抛出完成 。用于创建
ArrayBuffer。调用时执行以下步骤:
令 slots 为 « [[ArrayBufferData]] , [[ArrayBufferByteLength]] , [[ArrayBufferDetachKey]] »。
如果 maxByteLength 存在且不为 empty ,令
allocatingResizableBuffer 为 true ;否则令
allocatingResizableBuffer 为 false 。
如果 allocatingResizableBuffer 为 true ,则
如果 byteLength > maxByteLength ,抛出
RangeError 异常。
将 [[ArrayBufferMaxByteLength]] 添加到
slots 。
令 obj 为 ? OrdinaryCreateFromConstructor (constructor ,
"%ArrayBuffer.prototype%" , slots )。
令 block 为 ? CreateByteDataBlock (byteLength )。
设置 obj .[[ArrayBufferData]] 为 block 。
设置 obj .[[ArrayBufferByteLength]] 为
byteLength 。
如果 allocatingResizableBuffer 为 true ,则
如果无法创建由 maxByteLength 字节组成的 Data Block
block ,抛出 RangeError 异常。
注:可调整 ArrayBuffer 设计为支持原地增长。实现可能会在如虚拟内存无法预留等情况下抛出异常。
设置 obj .[[ArrayBufferMaxByteLength]] 为
maxByteLength 。
返回 obj 。
25.1.3.2 ArrayBufferByteLength ( arrayBuffer ,
order )
抽象操作 ArrayBufferByteLength 接收参数 arrayBuffer (一个 ArrayBuffer 或 SharedArrayBuffer)和
order (seq-cst 或 unordered ),返回一个非负
整数 。调用时执行以下步骤:
如果 IsSharedArrayBuffer (arrayBuffer )
为 true 且 arrayBuffer 有 [[ArrayBufferByteLengthData]] 内部槽,则
令 bufferByteLengthBlock 为 arrayBuffer .[[ArrayBufferByteLengthData]] 。
令 rawLength 为 GetRawBytesFromSharedBlock (bufferByteLengthBlock ,
0, biguint64 , true ,
order )。
令 isLittleEndian 为 周围代理 的
Agent
Record 的 [[LittleEndian]]
字段的值。
返回 ℝ (RawBytesToNumeric (biguint64 ,
rawLength , isLittleEndian ))。
断言 :
IsDetachedBuffer (arrayBuffer )
为 false 。
返回 arrayBuffer .[[ArrayBufferByteLength]] 。
25.1.3.3 ArrayBufferCopyAndDetach ( arrayBuffer ,
newLength , preserveResizability )
抽象操作 ArrayBufferCopyAndDetach 接收参数 arrayBuffer (一个 ECMAScript
语言值 )、newLength (一个 ECMAScript
语言值 )、preserveResizability (preserve-resizability
或 fixed-length ),返回一个 正常完成,包含 ArrayBuffer
或 抛出完成 。调用时执行以下步骤:
执行 ? RequireInternalSlot (arrayBuffer ,
[[ArrayBufferData]] )。
如果 IsSharedArrayBuffer (arrayBuffer )
为 true ,抛出 TypeError 异常。
如果 newLength 为 undefined ,则
令 newByteLength 为 arrayBuffer .[[ArrayBufferByteLength]] 。
否则,
令 newByteLength 为 ? ToIndex (newLength )。
如果 IsDetachedBuffer (arrayBuffer )
为 true ,抛出 TypeError 异常。
如果 preserveResizability 为 preserve-resizability 且
IsFixedLengthArrayBuffer (arrayBuffer )
为 false ,则
令 newMaxByteLength 为 arrayBuffer .[[ArrayBufferMaxByteLength]] 。
否则,
令 newMaxByteLength 为 empty 。
如果 arrayBuffer .[[ArrayBufferDetachKey]] 不为
undefined ,抛出 TypeError 异常。
令 newBuffer 为 ? AllocateArrayBuffer (%ArrayBuffer% ,
newByteLength , newMaxByteLength )。
令 copyLength 为 min (newByteLength ,
arrayBuffer .[[ArrayBufferByteLength]] )。
令 fromBlock 为 arrayBuffer .[[ArrayBufferData]] 。
令 toBlock 为 newBuffer .[[ArrayBufferData]] 。
执行 CopyDataBlockBytes (toBlock ,
0, fromBlock , 0, copyLength )。
注:新 Data Block 的创建和从旧 Data
Block 的数据复制都是不可观察的。实现可以将此方法实现为零拷贝移动或 realloc
。
执行 ! DetachArrayBuffer (arrayBuffer )。
返回 newBuffer 。
25.1.3.4 IsDetachedBuffer ( arrayBuffer )
抽象操作 IsDetachedBuffer 接收参数 arrayBuffer (一个 ArrayBuffer 或
SharedArrayBuffer),返回一个布尔值。调用时执行以下步骤:
如果 arrayBuffer .[[ArrayBufferData]] 为
null ,返回 true 。
返回 false 。
25.1.3.5 DetachArrayBuffer ( arrayBuffer [ ,
key ] )
抽象操作 DetachArrayBuffer 接收参数 arrayBuffer (一个 ArrayBuffer)和可选参数
key (任意值),返回 正常完成,包含
unused 或 抛出完成 。调用时执行以下步骤:
断言 :
IsSharedArrayBuffer (arrayBuffer )
为 false 。
如果 key 不存在,设置 key 为
undefined 。
如果 arrayBuffer .[[ArrayBufferDetachKey]] 不等于
key ,抛出 TypeError 异常。
设置 arrayBuffer .[[ArrayBufferData]] 为
null 。
设置 arrayBuffer .[[ArrayBufferByteLength]] 为 0。
返回 unused 。
注
分离 ArrayBuffer 实例会将用作其底层存储的 Data Block 与此实例解除关联,并将缓冲区字节长度设为 0。
25.1.3.6 CloneArrayBuffer ( srcBuffer ,
srcByteOffset , srcLength )
抽象操作 CloneArrayBuffer 接收参数 srcBuffer (一个 ArrayBuffer 或
SharedArrayBuffer)、srcByteOffset (非负整数 )、srcLength (非负整数 ),返回一个 正常完成,包含 ArrayBuffer
或 抛出完成 。它会创建一个新的
ArrayBuffer,其数据是 srcBuffer 在 srcByteOffset 起始,持续 srcLength
字节范围的数据的副本。调用时执行以下步骤:
断言 :
IsDetachedBuffer (srcBuffer )
为 false 。
令 targetBuffer 为 ? AllocateArrayBuffer (%ArrayBuffer% ,
srcLength )。
令 srcBlock 为 srcBuffer .[[ArrayBufferData]] 。
令 targetBlock 为 targetBuffer .[[ArrayBufferData]] 。
执行 CopyDataBlockBytes (targetBlock ,
0, srcBlock , srcByteOffset , srcLength )。
返回 targetBuffer 。
25.1.3.7 GetArrayBufferMaxByteLengthOption ( options
)
抽象操作 GetArrayBufferMaxByteLengthOption 接收参数 options (一个 ECMAScript 语言值 ),返回 正常完成,包含 非负整数 或empty ,或 抛出完成 。调用时执行以下步骤:
如果 options 不是一个对象 ,返回
empty 。
令 maxByteLength 为 ? Get (options ,
"maxByteLength" )。
如果 maxByteLength 为 undefined ,返回
empty 。
返回 ? ToIndex (maxByteLength )。
25.1.3.8 HostResizeArrayBuffer ( buffer ,
newByteLength )
宿主定义 抽象操作 HostResizeArrayBuffer 接收参数
buffer (一个 ArrayBuffer)和 newByteLength (非负整数 ),返回 正常完成,包含
handled 或 unhandled ,或 抛出完成 。它为 宿主 提供机会执行 实现定义 的 buffer 调整大小操作。如果
宿主 选择不处理
buffer 的调整大小,则可以返回 unhandled 以执行默认行为。
HostResizeArrayBuffer 的实现必须符合以下要求:
该抽象操作不会分离 buffer 。
如果该抽象操作以 handled 正常完成,则 buffer .[[ArrayBufferByteLength]] 为 newByteLength 。
HostResizeArrayBuffer 的默认实现是返回 NormalCompletion (unhandled )。
25.1.3.9 IsFixedLengthArrayBuffer ( arrayBuffer )
抽象操作 IsFixedLengthArrayBuffer 接收参数 arrayBuffer (一个 ArrayBuffer 或
SharedArrayBuffer),返回布尔值。调用时执行以下步骤:
如果 arrayBuffer 有 [[ArrayBufferMaxByteLength]]
内部槽,返回 false 。
返回 true 。
25.1.3.10 IsUnsignedElementType ( type )
抽象操作 IsUnsignedElementType 接收参数 type (一个 TypedArray
元素类型 ),返回布尔值。用于判断参数 type 是否是无符号 TypedArray 元素类型 。调用时执行以下步骤:
如果 type 是
uint8 、uint8clamped 、uint16 、uint32
或 biguint64 之一,返回 true 。
返回 false 。
25.1.3.11 IsUnclampedIntegerElementType ( type )
抽象操作 IsUnclampedIntegerElementType 接收参数 type (一个 TypedArray 元素类型 ),返回布尔值。用于判断参数
type 是否为 整数 类型的 TypedArray 元素类型 (不包括
uint8clamped )。调用时执行以下步骤:
如果 type 是
int8 、uint8 、int16 、uint16 、int32
或 uint32 之一,返回 true 。
返回 false 。
25.1.3.12 IsBigIntElementType ( type )
抽象操作 IsBigIntElementType 接收参数 type (一个 TypedArray
元素类型 ),返回布尔值。用于判断参数 type 是否为 BigInt 类型的
TypedArray 元素类型 。调用时执行以下步骤:
如果 type 是 biguint64 或
bigint64 ,返回 true 。
返回 false 。
25.1.3.13 IsNoTearConfiguration ( type ,
order )
抽象操作 IsNoTearConfiguration 接收参数 type (一个 TypedArray
元素类型 )、order (seq-cst 、unordered
或 init ),返回布尔值。调用时执行以下步骤:
如果 IsUnclampedIntegerElementType (type )
为 true ,返回 true 。
如果 IsBigIntElementType (type )
为 true 且 order 既不是 init 也不是
unordered ,返回 true 。
返回 false 。
25.1.3.14 RawBytesToNumeric ( type ,
rawBytes , isLittleEndian )
抽象操作 RawBytesToNumeric 接收参数 type (一个 TypedArray
元素类型 )、rawBytes (一个 List 的 字节值 )、isLittleEndian (布尔值),返回 Number
或 BigInt。调用时执行以下步骤:
令 elementSize 为 表 75
中元素类型 type 指定的元素大小值。
如果 isLittleEndian 为 false ,反转 rawBytes
的元素顺序。
如果 type 为 float16 ,则
令 value 为 rawBytes 的字节元素拼接并按小端位串方式解释成 IEEE 754-2019 binary16 值。
如果 value 是 NaN,返回 NaN 。
返回与 value 对应的 Number 值。
如果 type 为 float32 ,则
令 value 为 rawBytes 的字节元素拼接并按小端位串方式解释成 IEEE 754-2019 binary32 值。
如果 value 是 NaN,返回 NaN 。
返回与 value 对应的 Number 值。
如果 type 为 float64 ,则
令 value 为 rawBytes 的字节元素拼接并按小端位串方式解释成 IEEE 754-2019 binary64 值。
如果 value 是 NaN,返回 NaN 。
返回与 value 对应的 Number 值。
如果 IsUnsignedElementType (type )
为 true ,则
令 intValue 为 rawBytes 的字节元素拼接并按无符号小端二进制数的位串解释。
否则,
令 intValue 为 rawBytes 的字节元素拼接并按位长度为
elementSize × 8 的小端二进制补码数位串解释。
如果 IsBigIntElementType (type )
为 true ,返回与 intValue 对应的 BigInt 值。
否则,返回与 intValue 对应的 Number 值。
25.1.3.15 GetRawBytesFromSharedBlock ( block ,
byteIndex , type , isTypedArray , order )
抽象操作 GetRawBytesFromSharedBlock 接收参数 block (一个
共享数据块 )、byteIndex (非负整数 )、type (TypedArray
元素类型 )、isTypedArray (布尔值)、order (seq-cst
或
unordered ),返回一个 List ,元素为 字节值 。调用时执行以下步骤:
令 elementSize 为 表 75
中元素类型 type 对应的元素大小值。
令 execution 为 周围代理 的 Agent
Record 的 [[CandidateExecution]] 字段。
令 eventsRecord 为 execution .[[EventsRecords]] 中 [[AgentSignifier]] 等于 AgentSignifier () 的
Agent Events Record 。
如果 isTypedArray 为 true 且 IsNoTearConfiguration (type ,
order ) 为 true ,令 noTear 为
true ;否则令 noTear 为
false 。
令 rawValue 为一个长度为 elementSize 的 List ,其元素为非确定性选取的
字节值 。
注:在实现中,rawValue 是底层硬件的非原子或原子读取指令的结果。该非确定性是 内存模型 的语义规定,用于描述弱一致性硬件的可观察行为。
令 readEvent 为 ReadSharedMemory { [[Order]] : order , [[NoTear]] : noTear , [[Block]] : block , [[ByteIndex]] : byteIndex , [[ElementSize]] : elementSize }。
将 readEvent 添加到 eventsRecord .[[EventList]] 。
将 Chosen Value Record { [[Event]] : readEvent , [[ChosenValue]] : rawValue } 添加到
execution .[[ChosenValues]] 。
返回 rawValue 。
25.1.3.16 GetValueFromBuffer ( arrayBuffer ,
byteIndex , type , isTypedArray , order [ ,
isLittleEndian ] )
抽象操作 GetValueFromBuffer 接收参数 arrayBuffer (一个 ArrayBuffer 或
SharedArrayBuffer)、byteIndex (非负整数 )、type (TypedArray
元素类型 )、isTypedArray (布尔值)、order (seq-cst
或
unordered ),可选参数 isLittleEndian (布尔值),返回 Number 或
BigInt。调用时执行以下步骤:
断言 :
IsDetachedBuffer (arrayBuffer )
为 false 。
断言 :
arrayBuffer 从 byteIndex 开始有足够的字节以表示 type 类型的值。
令 block 为 arrayBuffer .[[ArrayBufferData]] 。
令 elementSize 为 表 75
中元素类型 type 指定的元素大小值。
如果 IsSharedArrayBuffer (arrayBuffer )
为 true ,则
断言 :block 是 共享数据块 。
令 rawValue 为 GetRawBytesFromSharedBlock (block ,
byteIndex , type , isTypedArray ,
order )。
否则,
令 rawValue 为一个 List ,其元素为
block 在 区间 byteIndex (含)到
byteIndex + elementSize (不含) 范围内的字节。
断言 :
rawValue 的元素数量为 elementSize 。
如果 isLittleEndian 未传入,设置 isLittleEndian 为 周围代理 的 Agent
Record 的 [[LittleEndian]] 字段的值。
返回 RawBytesToNumeric (type ,
rawValue , isLittleEndian )。
25.1.3.17 NumericToRawBytes ( type , value ,
isLittleEndian )
抽象操作 NumericToRawBytes 接收参数 type (一个 TypedArray
元素类型 )、value (Number 或
BigInt)、isLittleEndian (布尔值),返回一个 List ,元素为 字节值 。调用时执行以下步骤:
如果 type 为 float16 ,则
令 rawBytes 为一个 List ,其元素为将
value 按 roundTiesToEven 模式转换为 IEEE 754-2019
binary16 格式的 2 字节,字节顺序为小端序。如果 value 为 NaN ,则
rawBytes 可以设为任意实现选取的 IEEE 754-2019
binary16 NaN 编码。实现必须对每个可区分的 NaN 值始终选择相同的编码。
否则若 type 为 float32 ,则
令 rawBytes 为一个 List ,其元素为将
value 按 roundTiesToEven 模式转换为 IEEE 754-2019
binary32 格式的 4 字节,字节顺序为小端序。如果 value 为 NaN ,则
rawBytes 可以设为任意实现选取的 IEEE 754-2019
binary32 NaN 编码。实现必须对每个可区分的 NaN 值始终选择相同的编码。
否则若 type 为 float64 ,则
令 rawBytes 为一个 List ,其元素为
value 的 IEEE 754-2019 binary64 格式编码的
8 字节,字节顺序为小端序。如果 value 为 NaN ,则
rawBytes 可以设为任意实现选取的 IEEE 754-2019
binary64 NaN 编码。实现必须对每个可区分的 NaN 值始终选择相同的编码。
否则,
令 n 为 表
75 中元素类型 type 指定的元素大小值。
令 conversionOperation 为 表 75 中元素类型
type 在转换操作列指定的抽象操作。
令 intValue 为 ℝ (conversionOperation (value ))。
如果 intValue ≥ 0,则
令 rawBytes 为一个 List ,其元素为
intValue 的 n 字节二进制编码,字节顺序为小端序。
否则,
令 rawBytes 为一个 List ,其元素为
intValue 的 n 字节二进制补码编码,字节顺序为小端序。
如果 isLittleEndian 为 false ,反转 rawBytes
的元素顺序。
返回 rawBytes 。
25.1.3.18 SetValueInBuffer ( arrayBuffer ,
byteIndex , type , value , isTypedArray ,
order [ , isLittleEndian ] )
抽象操作 SetValueInBuffer 接收参数 arrayBuffer (一个 ArrayBuffer 或
SharedArrayBuffer)、byteIndex (非负整数 )、type (TypedArray
元素类型 )、value (Number 或
BigInt)、isTypedArray (布尔值)、order (seq-cst 、unordered
或 init ),可选参数 isLittleEndian (布尔值),返回
unused 。调用时执行以下步骤:
断言 :
IsDetachedBuffer (arrayBuffer )
为 false 。
断言 :
arrayBuffer 从 byteIndex 开始有足够的字节以表示 type 类型的值。
断言 :
如果 IsBigIntElementType (type )
为 true ,则 value 必须为 BigInt ;否则,value
必须为 Number 。
令 block 为 arrayBuffer .[[ArrayBufferData]] 。
令 elementSize 为 表 75
中元素类型 type 指定的元素大小值。
如果 isLittleEndian 未传入,设置 isLittleEndian 为 周围代理 的 Agent
Record 的 [[LittleEndian]] 字段的值。
令 rawBytes 为 NumericToRawBytes (type ,
value , isLittleEndian )。
如果 IsSharedArrayBuffer (arrayBuffer )
为 true ,则
令 execution 为 周围代理 的
Agent
Record 的 [[CandidateExecution]] 字段。
令 eventsRecord 为 execution .[[EventsRecords]] 中 [[AgentSignifier]] 等于 AgentSignifier () 的
Agent Events Record 。
如果 isTypedArray 为 true 且 IsNoTearConfiguration (type ,
order ) 为 true ,令 noTear 为
true ;否则令 noTear 为
false 。
将 WriteSharedMemory
{ [[Order]] : order , [[NoTear]] : noTear , [[Block]] : block , [[ByteIndex]] : byteIndex , [[ElementSize]] : elementSize , [[Payload]] : rawBytes } 添加到
eventsRecord .[[EventList]] 。
否则,
将 rawBytes 的各字节逐一存入 block ,起始于
block [byteIndex ]。
返回 unused 。
25.1.3.19 GetModifySetValueInBuffer ( arrayBuffer ,
byteIndex , type , value , op )
抽象操作 GetModifySetValueInBuffer 接收参数 arrayBuffer (一个 ArrayBuffer 或
SharedArrayBuffer)、byteIndex (非负整数 )、type (TypedArray
元素类型 )、value (Number 或 BigInt)、op (读-改-写修改函数 ),返回 Number 或
BigInt。调用时执行以下步骤:
断言 :
IsDetachedBuffer (arrayBuffer )
为 false 。
断言 :
arrayBuffer 从 byteIndex 开始有足够的字节以表示 type 类型的值。
断言 :
如果 IsBigIntElementType (type )
为 true ,则 value 必须为 BigInt ;否则,value
必须为 Number 。
令 block 为 arrayBuffer .[[ArrayBufferData]] 。
令 elementSize 为 表 75
中元素类型 type 指定的元素大小值。
令 isLittleEndian 为 周围代理 的 Agent
Record 的 [[LittleEndian]] 字段的值。
令 rawBytes 为 NumericToRawBytes (type ,
value , isLittleEndian )。
如果 IsSharedArrayBuffer (arrayBuffer )
为 true ,则
令 execution 为 周围代理 的
Agent
Record 的 [[CandidateExecution]] 字段。
令 eventsRecord 为 execution .[[EventsRecords]] 中 [[AgentSignifier]] 等于 AgentSignifier () 的
Agent Events Record 。
令 rawBytesRead 为一个长度为 elementSize 的 List ,其元素为非确定性选取的
字节值 。
注:在实现中,rawBytesRead 是底层硬件上 load-link、load-exclusive
或读-改-写指令操作数的结果。该非确定性是 内存模型 的语义规定,用于描述弱一致性硬件的可观察行为。
令 rmwEvent 为 ReadModifyWriteSharedMemory
{ [[Order]] : seq-cst , [[NoTear]] : true , [[Block]] : block , [[ByteIndex]] : byteIndex , [[ElementSize]] : elementSize , [[Payload]] : rawBytes , [[ModifyOp]] : op }。
将 rmwEvent 添加到 eventsRecord .[[EventList]] 。
将 Chosen Value Record
{ [[Event]] : rmwEvent , [[ChosenValue]] : rawBytesRead } 添加到
execution .[[ChosenValues]] 。
否则,
令 rawBytesRead 为一个长度为 elementSize 的 List ,其元素为从
block [byteIndex ] 起始的 elementSize 个字节。
令 rawBytesModified 为 op (rawBytesRead ,
rawBytes )。
将 rawBytesModified 的各字节逐一存入 block ,起始于
block [byteIndex ]。
返回 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
] )
该函数被调用时执行以下步骤:
如果 NewTarget 为 undefined ,抛出 TypeError 异常。
令 byteLength 为 ? ToIndex (length )。
令 requestedMaxByteLength 为 ? GetArrayBufferMaxByteLengthOption (options )。
返回 ? AllocateArrayBuffer (NewTarget,
byteLength , requestedMaxByteLength )。
25.1.5 ArrayBuffer 构造函数的属性
ArrayBuffer 构造函数 :
25.1.5.1 ArrayBuffer.isView ( arg )
该函数被调用时执行以下步骤:
如果 arg 不是一个对象 ,返回
false 。
如果 arg 有 [[ViewedArrayBuffer]] 内部槽,返回
true 。
返回 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 访问器函数被调用时执行以下步骤:
返回 this 值。
此函数的 "name" 属性值为 "get [Symbol.species]" 。
注
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 访问器函数被调用时执行以下步骤:
令 O 为 this 值。
执行 ? RequireInternalSlot (O ,
[[ArrayBufferData]] )。
如果 IsSharedArrayBuffer (O )
为 true ,抛出 TypeError 异常。
如果 IsDetachedBuffer (O )
为 true ,返回 +0 𝔽 。
令 length 为 O .[[ArrayBufferByteLength]] 。
返回 𝔽 (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 访问器函数被调用时执行以下步骤:
令 O 为 this 值。
执行 ? RequireInternalSlot (O ,
[[ArrayBufferData]] )。
如果 IsSharedArrayBuffer (O )
为 true ,抛出 TypeError 异常。
返回 IsDetachedBuffer (O )。
25.1.6.4 get ArrayBuffer.prototype.maxByteLength
ArrayBuffer.prototype.maxByteLength
是一个 访问器属性 ,其 set 访问器函数为
undefined 。其 get 访问器函数被调用时执行以下步骤:
令 O 为 this 值。
执行 ? RequireInternalSlot (O ,
[[ArrayBufferData]] )。
如果 IsSharedArrayBuffer (O )
为 true ,抛出 TypeError 异常。
如果 IsDetachedBuffer (O )
为 true ,返回 +0 𝔽 。
如果 IsFixedLengthArrayBuffer (O )
为 true ,则
令 length 为 O .[[ArrayBufferByteLength]] 。
否则,
令 length 为 O .[[ArrayBufferMaxByteLength]] 。
返回 𝔽 (length )。
25.1.6.5 get ArrayBuffer.prototype.resizable
ArrayBuffer.prototype.resizable
是一个 访问器属性 ,其 set 访问器函数为
undefined 。其 get 访问器函数被调用时执行以下步骤:
令 O 为 this 值。
执行 ? RequireInternalSlot (O ,
[[ArrayBufferData]] )。
如果 IsSharedArrayBuffer (O )
为 true ,抛出 TypeError 异常。
如果 IsFixedLengthArrayBuffer (O )
为 false ,返回 true ;否则返回
false 。
25.1.6.6 ArrayBuffer.prototype.resize ( newLength )
该方法被调用时执行以下步骤:
令 O 为 this 值。
执行 ? RequireInternalSlot (O ,
[[ArrayBufferMaxByteLength]] )。
如果 IsSharedArrayBuffer (O )
为 true ,抛出 TypeError 异常。
令 newByteLength 为 ? ToIndex (newLength )。
如果 IsDetachedBuffer (O )
为 true ,抛出 TypeError 异常。
如果 newByteLength > O .[[ArrayBufferMaxByteLength]] ,抛出
RangeError 异常。
令 hostHandled 为 ? HostResizeArrayBuffer (O ,
newByteLength )。
如果 hostHandled 为 handled ,返回
undefined 。
令 oldBlock 为 O .[[ArrayBufferData]] 。
令 newBlock 为 ? CreateByteDataBlock (newByteLength )。
令 copyLength 为 min (newByteLength ,
O .[[ArrayBufferByteLength]] )。
执行 CopyDataBlockBytes (newBlock ,
0, oldBlock , 0, copyLength )。
注:新 Data Block 的创建和从旧 Data
Block 的数据复制都是不可观察的。实现可以将此方法实现为原地增长或缩减。
设置 O .[[ArrayBufferData]] 为
newBlock 。
设置 O .[[ArrayBufferByteLength]] 为
newByteLength 。
返回 undefined 。
25.1.6.7 ArrayBuffer.prototype.slice ( start ,
end )
该方法被调用时执行以下步骤:
令 O 为 this 值。
执行 ? RequireInternalSlot (O ,
[[ArrayBufferData]] )。
如果 IsSharedArrayBuffer (O )
为 true ,抛出 TypeError 异常。
如果 IsDetachedBuffer (O )
为 true ,抛出 TypeError 异常。
令 len 为 O .[[ArrayBufferByteLength]] 。
令 relativeStart 为 ? ToIntegerOrInfinity (start )。
如果 relativeStart = -∞,令 first 为 0。
否则如果 relativeStart < 0,令 first 为 max (len
+ relativeStart , 0)。
否则,令 first 为 min (relativeStart ,
len )。
如果 end 为 undefined ,令 relativeEnd 为
len ;否则令 relativeEnd 为 ? ToIntegerOrInfinity (end )。
如果 relativeEnd = -∞,令 final 为 0。
否则如果 relativeEnd < 0,令 final 为 max (len +
relativeEnd , 0)。
否则,令 final 为 min (relativeEnd , len )。
令 newLen 为 max (final - first , 0)。
令 ctor 为 ? SpeciesConstructor (O ,
%ArrayBuffer% )。
令 new 为 ? Construct (ctor , « 𝔽 (newLen ) »)。
执行 ? RequireInternalSlot (new ,
[[ArrayBufferData]] )。
如果 IsSharedArrayBuffer (new )
为 true ,抛出 TypeError 异常。
如果 IsDetachedBuffer (new )
为 true ,抛出 TypeError 异常。
如果 SameValue (new , O )
为 true ,抛出 TypeError 异常。
如果 new .[[ArrayBufferByteLength]] <
newLen ,抛出 TypeError 异常。
注:上述步骤的副作用可能会分离或调整 O 的大小。
如果 IsDetachedBuffer (O )
为 true ,抛出 TypeError 异常。
令 fromBuf 为 O .[[ArrayBufferData]] 。
令 toBuf 为 new .[[ArrayBufferData]] 。
令 currentLen 为 O .[[ArrayBufferByteLength]] 。
如果 first < currentLen ,则
令 count 为 min (newLen ,
currentLen - first )。
执行 CopyDataBlockBytes (toBuf ,
0, fromBuf , first , count )。
返回 new 。
25.1.6.8 ArrayBuffer.prototype.transfer ( [ newLength
] )
该方法被调用时执行以下步骤:
令 O 为 this 值。
返回 ? ArrayBufferCopyAndDetach (O ,
newLength , preserve-resizability )。
25.1.6.9 ArrayBuffer.prototype.transferToFixedLength ( [
newLength ] )
该方法被调用时执行以下步骤:
令 O 为 this 值。
返回 ? ArrayBufferCopyAndDetach (O ,
newLength , fixed-length )。
25.1.6.10 ArrayBuffer.prototype [ %Symbol.toStringTag% ]
%Symbol.toStringTag% 属性的初始值为字符串值
"ArrayBuffer" 。
该属性具有属性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : true }。
25.1.7 ArrayBuffer 实例的属性
ArrayBuffer 实例继承自 ArrayBuffer
原型对象 的属性。每个 ArrayBuffer 实例都有一个 [[ArrayBufferData]] 内部槽、一个 [[ArrayBufferByteLength]] 内部槽,以及一个 [[ArrayBufferDetachKey]] 内部槽。可调整大小的 ArrayBuffer 实例还拥有 [[ArrayBufferMaxByteLength]] 内部槽。
如果 ArrayBuffer 实例的 [[ArrayBufferData]] 为
null ,则视为已分离,所有用于访问或修改该 ArrayBuffer 实例中数据的操作都会失败。
如果 ArrayBuffer 实例的 [[ArrayBufferDetachKey]] 被设置为非
undefined 的值,则所有 DetachArrayBuffer 调用都必须传递相同的“detach
key”作为参数,否则将抛出 TypeError。该内部槽只会被某些嵌入环境设置,而不会被本规范中的算法设置。
25.1.8 可调整长度 ArrayBuffer 指南
注 1
以下是针对使用 可调整长度
ArrayBuffer 的 ECMAScript 程序员的建议。
建议程序尽可能在其部署环境中进行测试。不同硬件设备的物理内存容量差异巨大。同样,虚拟内存子系统在不同的硬件设备和操作系统间也差异很大。在 64 位桌面 Web
浏览器上无内存溢出错误运行的应用程序,可能会在 32 位移动 Web 浏览器上耗尽内存。
为 可调整长度
ArrayBuffer 的 "maxByteLength"
选项选择数值时,建议选择应用程序所需的最小值。建议 "maxByteLength" 不超过
1,073,741,824(230 字节或 1GiB)。
请注意,为特定最大值成功构造一个 可调整长度
ArrayBuffer ,并不保证将来调整大小一定会成功。
注 2
以下是针对实现 可调整长度
ArrayBuffer 的 ECMAScript 实现者的建议。
可调整长度
ArrayBuffer 的实现可以为调整大小时复制、也可以通过预先保留虚拟内存实现原地扩展,或针对 构造函数 的
"maxByteLength" 选项的不同值组合二者。
如果 宿主 是多租户(即同时运行多个
ECMAScript 应用,例如 Web 浏览器),且实现选择通过预留虚拟内存实现原地扩展,我们建议 32 位和 64 位实现对
"maxByteLength" ≥ 1GiB 到 1.5GiB
的值都抛出异常。这样可以减少单个应用耗尽虚拟内存地址空间的可能,也有助于减小互操作性风险。
如果 宿主 没有虚拟内存(如无 MMU
的嵌入式设备),或 宿主
只通过复制实现调整大小,则可以接受 "maxByteLength" 选项的任意 Number
值 。但建议如果请求的内存块大小永远无法分配,则抛出
RangeError 。例如,请求的大小大于设备可用最大内存。
25.2 SharedArrayBuffer 对象
25.2.1 固定长度和可增长 SharedArrayBuffer 对象
固定长度 SharedArrayBuffer 是指创建后字节长度不可更改的 SharedArrayBuffer。
可增长 SharedArrayBuffer 是指其字节长度可以在创建后通过调用 SharedArrayBuffer.prototype.grow (
newLength ) 进行增加的 SharedArrayBuffer。
所创建的 SharedArrayBuffer 对象的种类取决于传递给 SharedArrayBuffer ( length
[ ,
options ] ) 的参数。
25.2.2 SharedArrayBuffer 对象的抽象操作
25.2.2.1 AllocateSharedArrayBuffer ( constructor ,
byteLength [ , maxByteLength ] )
抽象操作 AllocateSharedArrayBuffer 接收参数 constructor (一个 构造函数 )、byteLength (非负整数 ),可选参数
maxByteLength (非负整数 或 empty ),返回一个 正常完成,包含
SharedArrayBuffer 或 抛出完成 。用于创建
SharedArrayBuffer。调用时执行以下步骤:
令 slots 为 « [[ArrayBufferData]] »。
如果 maxByteLength 存在且不为 empty ,令
allocatingGrowableBuffer 为 true ;否则令
allocatingGrowableBuffer 为 false 。
如果 allocatingGrowableBuffer 为 true ,则
如果 byteLength > maxByteLength ,抛出
RangeError 异常。
将 [[ArrayBufferByteLengthData]] 和 [[ArrayBufferMaxByteLength]] 添加到 slots 。
否则,
将 [[ArrayBufferByteLength]] 添加到 slots 。
令 obj 为 ? OrdinaryCreateFromConstructor (constructor ,
"%SharedArrayBuffer.prototype%" , slots )。
如果 allocatingGrowableBuffer 为 true ,令
allocLength 为 maxByteLength ;否则令
allocLength 为 byteLength 。
令 block 为 ? CreateSharedByteDataBlock (allocLength )。
设置 obj .[[ArrayBufferData]] 为 block 。
如果 allocatingGrowableBuffer 为 true ,则
断言 :byteLength ≤
maxByteLength 。
令 byteLengthBlock 为 ? CreateSharedByteDataBlock (8)。
执行 SetValueInBuffer (byteLengthBlock ,
0, biguint64 , ℤ (byteLength ),
true , seq-cst )。
设置 obj .[[ArrayBufferByteLengthData]] 为
byteLengthBlock 。
设置 obj .[[ArrayBufferMaxByteLength]] 为
maxByteLength 。
否则,
设置 obj .[[ArrayBufferByteLength]] 为
byteLength 。
返回 obj 。
25.2.2.2 IsSharedArrayBuffer ( obj )
抽象操作 IsSharedArrayBuffer 接收参数 obj (一个 ArrayBuffer 或
SharedArrayBuffer),返回布尔值。用于检测对象是 ArrayBuffer、SharedArrayBuffer 还是二者的子类型。调用时执行以下步骤:
令 bufferData 为 obj .[[ArrayBufferData]] 。
如果 bufferData 为 null ,返回
false 。
如果 bufferData 是 Data Block ,返回
false 。
断言 :
bufferData 是一个 Shared Data Block 。
返回 true 。
25.2.2.3 HostGrowSharedArrayBuffer ( buffer ,
newByteLength )
宿主定义 抽象操作 HostGrowSharedArrayBuffer 接收参数
buffer (一个 SharedArrayBuffer)和
newByteLength (非负整数 ),返回 正常完成,包含
handled 或
unhandled ,或 抛出完成 。该操作为 宿主 提供机会执行 实现定义 的 buffer 扩容。如果
宿主 选择不处理
buffer 的扩容,则可返回 unhandled 以执行默认行为。
HostGrowSharedArrayBuffer 的实现必须符合以下要求:
如果该抽象操作不是以 unhandled 正常完成,并且 newByteLength <
buffer 当前字节长度或 newByteLength > buffer .[[ArrayBufferMaxByteLength]] ,抛出 RangeError
异常。
令 isLittleEndian 为 周围代理 的 Agent Record 的 [[LittleEndian]] 字段的值。如果该抽象操作以 handled
正常完成,则 周围代理 的 候选执行 中将添加一个 WriteSharedMemory 或
ReadModifyWriteSharedMemory
事件,其 [[Order]] 为 seq-cst ,[[Payload]] 为 NumericToRawBytes (biguint64 ,
newByteLength , isLittleEndian ),[[Block]]
为 buffer .[[ArrayBufferByteLengthData]] ,[[ByteIndex]] 为 0,[[ElementSize]] 为
8。这样可以确保对 SharedArrayBuffer.prototype.grow
的竞争调用不会“丢失”,即不会悄然无效。
注
上述第二点故意没有规定如何或何时读取 buffer 的当前字节长度。由于字节长度必须通过底层硬件上的原子读-改-写操作进行更新,采用
load-link/store-conditional 或 load-exclusive/store-exclusive
指令对的架构可能希望将配对指令保持在指令流中较近的位置。因此,SharedArrayBuffer.prototype.grow 自身不会在调用
HostGrowSharedArrayBuffer 前对 newByteLength 进行边界检查,也不要求何时读取当前字节长度。
这与 HostResizeArrayBuffer
形成对比,后者保证 newByteLength 的值在 0 到 buffer .[[ArrayBufferMaxByteLength]] 之间。
HostGrowSharedArrayBuffer 的默认实现是返回 NormalCompletion (unhandled )。
25.2.3 SharedArrayBuffer 构造函数
SharedArrayBuffer 构造函数 :
即 %SharedArrayBuffer% 。
如果该属性存在,则是 全局对象 的
"SharedArrayBuffer" 属性的初始值(见下文)。
作为 构造函数
调用时会创建并初始化一个新的 SharedArrayBuffer。
不应作为普通函数调用,否则会抛出异常。
可以用作类定义的 extends
子句的值。想要继承指定 SharedArrayBuffer 行为的子类 构造函数 必须包含对
SharedArrayBuffer 构造函数 的 super
调用,以用必要的内部状态创建和初始化子类实例,以支持 SharedArrayBuffer.prototype
内建方法。
如果 宿主 不提供对
SharedArrayBuffer 的并发访问,它可以省略 全局对象 的 "SharedArrayBuffer"
属性。
注
与 ArrayBuffer
不同,SharedArrayBuffer
不会被分离,其内部 [[ArrayBufferData]] 槽也永远不会是 null 。
25.2.3.1 SharedArrayBuffer ( length [ ,
options ] )
该函数被调用时执行以下步骤:
如果 NewTarget 为 undefined ,抛出 TypeError 异常。
令 byteLength 为 ? ToIndex (length )。
令 requestedMaxByteLength 为 ? GetArrayBufferMaxByteLengthOption (options )。
返回 ? 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 访问器函数被调用时执行以下步骤:
返回 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 访问器函数被调用时执行以下步骤:
令 O 为 this 值。
执行 ? RequireInternalSlot (O ,
[[ArrayBufferData]] )。
如果 IsSharedArrayBuffer (O )
为 false ,抛出 TypeError 异常。
令 length 为 ArrayBufferByteLength (O ,
seq-cst )。
返回 𝔽 (length )。
25.2.5.2 SharedArrayBuffer.prototype.constructor
SharedArrayBuffer.prototype.constructor
的初始值为 %SharedArrayBuffer% 。
25.2.5.3 SharedArrayBuffer.prototype.grow ( newLength
)
该方法被调用时执行以下步骤:
令 O 为 this 值。
执行 ? RequireInternalSlot (O ,
[[ArrayBufferMaxByteLength]] )。
如果 IsSharedArrayBuffer (O )
为 false ,抛出 TypeError 异常。
令 newByteLength 为 ? ToIndex (newLength )。
令 hostHandled 为 ? HostGrowSharedArrayBuffer (O ,
newByteLength )。
如果 hostHandled 为 handled ,返回
undefined 。
令 isLittleEndian 为 周围代理 的 Agent
Record 的 [[LittleEndian]] 字段的值。
令 byteLengthBlock 为 O .[[ArrayBufferByteLengthData]] 。
令 currentByteLengthRawBytes 为 GetRawBytesFromSharedBlock (byteLengthBlock ,
0, biguint64 , true ,
seq-cst )。
令 newByteLengthRawBytes 为 NumericToRawBytes (biguint64 ,
ℤ (newByteLength ),
isLittleEndian )。
重复,
注:这是一个比较并交换循环,用于确保对同一缓冲区的并发增长操作有全序、不丢失且不会悄然无效。当循环能够尝试无竞争地增长时退出。
令 currentByteLength 为 ℝ (RawBytesToNumeric (biguint64 ,
currentByteLengthRawBytes , isLittleEndian ))。
如果 newByteLength = currentByteLength ,返回
undefined 。
如果 newByteLength < currentByteLength 或
newByteLength > O .[[ArrayBufferMaxByteLength]] ,抛出
RangeError 异常。
令 byteLengthDelta 为 newByteLength -
currentByteLength 。
如果无法创建由 byteLengthDelta 字节组成的新 共享数据块 ,抛出
RangeError 异常。
注:此处不会创建并使用新的 共享数据块 。可增长 SharedArrayBuffer
的可观察行为通过在构造时分配最大值的 max 大小的 共享数据块 体现,本步骤用于要求实现遇到内存不足时必须抛出
RangeError 。
令 readByteLengthRawBytes 为 AtomicCompareExchangeInSharedBlock (byteLengthBlock ,
0, 8, currentByteLengthRawBytes ,
newByteLengthRawBytes )。
如果 ByteListEqual (readByteLengthRawBytes ,
currentByteLengthRawBytes ) 为 true ,返回
undefined 。
设置 currentByteLengthRawBytes 为
readByteLengthRawBytes 。
注
比较-交换操作更新长度出现伪失败是不允许的。如果新长度的边界检查通过且实现未耗尽内存,则总会在 候选执行 中添加一个 ReadModifyWriteSharedMemory
事件(即比较-交换成功)。
对 SharedArrayBuffer.prototype.grow 的并发调用是全序的。例如,考虑两个竞争调用:sab.grow(10)
和
sab.grow(20)
。这两个调用中的一个保证会赢得竞争。即使 sab.grow(20)
先发生,sab.grow(10)
也绝不会导致 sab
变小;此时它会抛出 RangeError。
25.2.5.4 get SharedArrayBuffer.prototype.growable
SharedArrayBuffer.prototype.growable
是一个 访问器属性 ,其 set 访问器函数为
undefined 。其 get 访问器函数被调用时执行以下步骤:
令 O 为 this 值。
执行 ? RequireInternalSlot (O ,
[[ArrayBufferData]] )。
如果 IsSharedArrayBuffer (O )
为 false ,抛出 TypeError 异常。
如果 IsFixedLengthArrayBuffer (O )
为 false ,返回 true ;否则返回
false 。
25.2.5.5 get SharedArrayBuffer.prototype.maxByteLength
SharedArrayBuffer.prototype.maxByteLength
是一个 访问器属性 ,其 set 访问器函数为
undefined 。其 get 访问器函数被调用时执行以下步骤:
令 O 为 this 值。
执行 ? RequireInternalSlot (O ,
[[ArrayBufferData]] )。
如果 IsSharedArrayBuffer (O )
为 false ,抛出 TypeError 异常。
如果 IsFixedLengthArrayBuffer (O )
为 true ,则
令 length 为 O .[[ArrayBufferByteLength]] 。
否则,
令 length 为 O .[[ArrayBufferMaxByteLength]] 。
返回 𝔽 (length )。
25.2.5.6 SharedArrayBuffer.prototype.slice ( start ,
end )
该方法被调用时执行以下步骤:
令 O 为 this 值。
执行 ? RequireInternalSlot (O ,
[[ArrayBufferData]] )。
如果 IsSharedArrayBuffer (O )
为 false ,抛出 TypeError 异常。
令 len 为 ArrayBufferByteLength (O ,
seq-cst )。
令 relativeStart 为 ? ToIntegerOrInfinity (start )。
如果 relativeStart = -∞,令 first 为 0。
否则如果 relativeStart < 0,令 first 为 max (len
+ relativeStart , 0)。
否则,令 first 为 min (relativeStart ,
len )。
如果 end 为 undefined ,令 relativeEnd 为
len ;否则令 relativeEnd 为 ? ToIntegerOrInfinity (end )。
如果 relativeEnd = -∞,令 final 为 0。
否则如果 relativeEnd < 0,令 final 为 max (len +
relativeEnd , 0)。
否则,令 final 为 min (relativeEnd , len )。
令 newLen 为 max (final - first , 0)。
令 ctor 为 ? SpeciesConstructor (O ,
%SharedArrayBuffer% )。
令 new 为 ? Construct (ctor , « 𝔽 (newLen ) »)。
执行 ? RequireInternalSlot (new ,
[[ArrayBufferData]] )。
如果 IsSharedArrayBuffer (new )
为 false ,抛出 TypeError 异常。
如果 new .[[ArrayBufferData]] 为 O .[[ArrayBufferData]] ,抛出 TypeError
异常。
如果 ArrayBufferByteLength (new ,
seq-cst ) < newLen ,抛出
TypeError 异常。
令 fromBuf 为 O .[[ArrayBufferData]] 。
令 toBuf 为 new .[[ArrayBufferData]] 。
执行 CopyDataBlockBytes (toBuf ,
0, fromBuf , first , newLen )。
返回 new 。
25.2.5.7 SharedArrayBuffer.prototype [ %Symbol.toStringTag% ]
%Symbol.toStringTag% 属性的初始值为字符串值
"SharedArrayBuffer" 。
该属性具有属性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : true }。
25.2.6 SharedArrayBuffer 实例的属性
SharedArrayBuffer 实例继承自 SharedArrayBuffer
原型对象 的属性。每个 SharedArrayBuffer 实例都有一个 [[ArrayBufferData]] 内部槽。不可增长的 SharedArrayBuffer 实例还有一个 [[ArrayBufferByteLength]] 内部槽。可增长的 SharedArrayBuffer 实例有 [[ArrayBufferByteLengthData]] 内部槽和 [[ArrayBufferMaxByteLength]] 内部槽。
注
SharedArrayBuffer 实例与 ArrayBuffer 实例不同,永远不会被分离。
25.2.7 可增长 SharedArrayBuffer 指南
注 1
以下是针对使用 可增长
SharedArrayBuffer 的 ECMAScript 程序员的建议。
建议程序尽可能在其部署环境中进行测试。不同硬件设备的物理内存容量差异巨大。同样,虚拟内存子系统在不同的硬件设备和操作系统间也差异很大。在 64 位桌面 Web
浏览器上无内存溢出错误运行的应用程序,可能会在 32 位移动 Web 浏览器上耗尽内存。
为 可增长
SharedArrayBuffer 的 "maxByteLength"
选项选择数值时,建议选择应用程序所需的最小值。建议 "maxByteLength" 不超过 1073741824(即 1GiB)。
请注意,为特定最大值成功构造一个 可增长
SharedArrayBuffer ,并不保证将来扩容一定会成功。
并非所有对 可增长
SharedArrayBuffer 长度的读取都是同步 seq-cst 读取。用于
整数索引 属性访问(如
u8[idx]
)的长度读取不是同步的。一般来说,在缺少显式同步的情况下,一次属性访问在范围内并不意味着同一 代理
中后续的属性访问也在范围内。相比之下,通过 SharedArrayBuffer 的 length
和 byteLength
getter、%TypedArray% .prototype
以及 DataView.prototype 的显式长度读取是同步的。内置方法在判断 TypedArray 是否完全越界时进行的长度加载也是同步的。
注 2
以下是针对实现 可增长
SharedArrayBuffer 的 ECMAScript 实现者的建议。
建议 可增长
SharedArrayBuffer 通过预先保留虚拟内存实现原地增长。
因为 grow 操作可能与可增长 SharedArrayBuffer 的内存访问并行发生,内存模型
的约束要求即使是无序访问也不会“撕裂”(即其值的位不会混淆)。实际上,这意味着可增长 SharedArrayBuffer
的底层数据块不能通过复制方式扩容,除非暂停所有操作。我们不建议采用暂停世界的实现策略,因为这会产生串行化点且效率低下。
扩容后新增的内存必须从创建时起就表现为全零,包括对并发访问也是如此。这可以通过按需零填充的虚拟内存页实现,或通过手动清零时的细致同步实现。
对可增长 SharedArrayBuffer 的 TypedArray 视图的 整数索引 属性访问,旨在与非可增长
SharedArrayBuffer 的 TypedArray
视图访问一样可优化,因为这些属性访问的长度加载不是同步的(见上方程序员指南)。例如,属性访问的越界检查仍然可以被提升到循环之外。
实际上,在没有虚拟内存的 宿主 (如无
MMU 的嵌入式设备)上,通过复制方式实现 可增长
SharedArrayBuffer 是很难的。在这类宿主上的可增长 SharedArrayBuffer
的内存使用行为可能会与有虚拟内存的宿主差异很大。这类 宿主 应当向用户明确说明内存使用预期。
25.3 DataView 对象
25.3.1 DataView 对象的抽象操作
25.3.1.1 带 Buffer 见证记录的 DataView
带 Buffer 见证记录的
DataView 是一个 Record
类型的值,用于封装一个 DataView 以及被查看缓冲区的缓存字节长度。当被查看缓冲区是可增长的 SharedArrayBuffers
时,用来确保只发生一次对字节长度数据块的共享内存读取事件。
带 Buffer 见证记录的 DataView 拥有 表
77 列出的字段。
表 77:带 Buffer
见证记录的 DataView 字段
字段名
值
含义
[[Object]]
一个 DataView
被加载缓冲区字节长度的 DataView 对象。
[[CachedBufferByteLength]]
一个非负整数 或
detached
创建该 Record
时对象的 [[ViewedArrayBuffer]] 的字节长度。
25.3.1.2 MakeDataViewWithBufferWitnessRecord ( obj ,
order )
抽象操作 MakeDataViewWithBufferWitnessRecord 接收参数 obj (一个 DataView)和
order (seq-cst 或 unordered ),返回一个
带 Buffer 见证记录的
DataView 。调用时执行以下步骤:
令 buffer 为 obj .[[ViewedArrayBuffer]] 。
如果 IsDetachedBuffer (buffer )
为 true ,则
令 byteLength 为 detached 。
否则,
令 byteLength 为 ArrayBufferByteLength (buffer ,
order )。
返回 带 Buffer 见证记录的
DataView { [[Object]] :
obj , [[CachedBufferByteLength]] :
byteLength }。
25.3.1.3 GetViewByteLength ( viewRecord )
抽象操作 GetViewByteLength 接收参数 viewRecord (一个 带 Buffer 见证记录的
DataView ),返回一个非负整数 。调用时执行以下步骤:
断言 :
IsViewOutOfBounds (viewRecord )
为 false 。
令 view 为 viewRecord .[[Object]] 。
如果 view .[[ByteLength]] 不为
auto ,返回 view .[[ByteLength]] 。
断言 :
IsFixedLengthArrayBuffer (view .[[ViewedArrayBuffer]] ) 为 false 。
令 byteOffset 为 view .[[ByteOffset]] 。
令 byteLength 为 viewRecord .[[CachedBufferByteLength]] 。
断言 :
byteLength 不为 detached 。
返回 byteLength - byteOffset 。
25.3.1.4 IsViewOutOfBounds ( viewRecord )
抽象操作 IsViewOutOfBounds 接收参数 viewRecord (一个 带 Buffer 见证记录的
DataView ),返回布尔值。调用时执行以下步骤:
令 view 为 viewRecord .[[Object]] 。
令 bufferByteLength 为 viewRecord .[[CachedBufferByteLength]] 。
断言 :
IsDetachedBuffer (view .[[ViewedArrayBuffer]] ) 为 true 当且仅当
bufferByteLength 为 detached 。
如果 bufferByteLength 为 detached ,返回
true 。
令 byteOffsetStart 为 view .[[ByteOffset]] 。
如果 view .[[ByteLength]] 为
auto ,则
令 byteOffsetEnd 为 bufferByteLength 。
否则,
令 byteOffsetEnd 为 byteOffsetStart +
view .[[ByteLength]] 。
如果 byteOffsetStart > bufferByteLength 或
byteOffsetEnd > bufferByteLength ,返回
true 。
注:长度为 0 的 DataView 不视为越界。
返回 false 。
25.3.1.5 GetViewValue ( view ,
requestIndex , isLittleEndian , type )
抽象操作 GetViewValue 接收参数 view (一个 ECMAScript
语言值 )、requestIndex (一个 ECMAScript
语言值 )、isLittleEndian (一个 ECMAScript
语言值 )、type (TypedArray 元素类型 ),返回
正常完成,包含 Number 或
BigInt,或 抛出完成 。被 DataView
实例上的函数用来从视图缓冲区获取值。调用时执行以下步骤:
执行 ? RequireInternalSlot (view ,
[[DataView]] )。
断言 :
view 拥有 [[ViewedArrayBuffer]] 内部槽。
令 getIndex 为 ? ToIndex (requestIndex )。
将 isLittleEndian 设为 ToBoolean (isLittleEndian )。
令 viewOffset 为 view .[[ByteOffset]] 。
令 viewRecord 为 MakeDataViewWithBufferWitnessRecord (view ,
unordered )。
注:当 view 的后备缓冲区为 可增长
SharedArrayBuffer 时,越界检查不是同步操作。
如果 IsViewOutOfBounds (viewRecord )
为 true ,抛出 TypeError 异常。
令 viewSize 为 GetViewByteLength (viewRecord )。
令 elementSize 为 表 75
中元素类型 type 指定的元素大小值。
如果 getIndex + elementSize > viewSize ,抛出
RangeError 异常。
令 bufferIndex 为 getIndex + viewOffset 。
返回 GetValueFromBuffer (view .[[ViewedArrayBuffer]] , bufferIndex ,
type , false , unordered ,
isLittleEndian )。
25.3.1.6 SetViewValue ( view ,
requestIndex , isLittleEndian , type , value )
抽象操作 SetViewValue 接收参数 view (一个 ECMAScript
语言值 )、requestIndex (一个 ECMAScript
语言值 )、isLittleEndian (一个 ECMAScript
语言值 )、type (TypedArray
元素类型 )、value (ECMAScript 语言值 ),返回 正常完成,包含
undefined 或 抛出完成 。被 DataView
实例上的函数用来将值存入视图缓冲区。调用时执行以下步骤:
执行 ? RequireInternalSlot (view ,
[[DataView]] )。
断言 :
view 拥有 [[ViewedArrayBuffer]] 内部槽。
令 getIndex 为 ? ToIndex (requestIndex )。
如果 IsBigIntElementType (type )
为 true ,令 numberValue 为 ? ToBigInt (value )。
否则,令 numberValue 为 ? ToNumber (value )。
将 isLittleEndian 设为 ToBoolean (isLittleEndian )。
令 viewOffset 为 view .[[ByteOffset]] 。
令 viewRecord 为 MakeDataViewWithBufferWitnessRecord (view ,
unordered )。
注:当 view 的后备缓冲区为 可增长
SharedArrayBuffer 时,越界检查不是同步操作。
如果 IsViewOutOfBounds (viewRecord )
为 true ,抛出 TypeError 异常。
令 viewSize 为 GetViewByteLength (viewRecord )。
令 elementSize 为 表 75
中元素类型 type 指定的元素大小值。
如果 getIndex + elementSize > viewSize ,抛出
RangeError 异常。
令 bufferIndex 为 getIndex + viewOffset 。
执行 SetValueInBuffer (view .[[ViewedArrayBuffer]] , bufferIndex ,
type , numberValue , false ,
unordered , isLittleEndian )。
返回 undefined 。
25.3.2 DataView 构造函数
DataView 构造函数 :
即 %DataView% 。
是 全局对象 的 "DataView"
属性的初始值。
作为 构造函数
调用时会创建并初始化一个新的 DataView。
不应作为普通函数调用,否则会抛出异常。
可以用作类定义的 extends
子句的值。想要继承指定 DataView 行为的子类 构造函数 必须包含对 DataView 构造函数 的
super
调用,以用必要的内部状态创建和初始化子类实例,以支持 DataView.prototype
内建方法。
25.3.2.1 DataView ( buffer [ , byteOffset
[ , byteLength ] ] )
该函数被调用时执行以下步骤:
如果 NewTarget 为 undefined ,抛出 TypeError 异常。
执行 ? RequireInternalSlot (buffer ,
[[ArrayBufferData]] )。
令 offset 为 ? ToIndex (byteOffset )。
如果 IsDetachedBuffer (buffer )
为 true ,抛出 TypeError 异常。
令 bufferByteLength 为 ArrayBufferByteLength (buffer ,
seq-cst )。
如果 offset > bufferByteLength ,抛出
RangeError 异常。
令 bufferIsFixedLength 为 IsFixedLengthArrayBuffer (buffer )。
如果 byteLength 为 undefined ,则
如果 bufferIsFixedLength 为 true ,则
令 viewByteLength 为 bufferByteLength -
offset 。
否则,
令 viewByteLength 为 auto 。
否则,
令 viewByteLength 为 ? ToIndex (byteLength )。
如果 offset + viewByteLength >
bufferByteLength ,抛出 RangeError 异常。
令 O 为 ? OrdinaryCreateFromConstructor (NewTarget,
"%DataView.prototype%" , « [[DataView]] ,
[[ViewedArrayBuffer]] , [[ByteLength]] , [[ByteOffset]] »)。
如果 IsDetachedBuffer (buffer )
为 true ,抛出 TypeError 异常。
将 bufferByteLength 设为 ArrayBufferByteLength (buffer ,
seq-cst )。
如果 offset > bufferByteLength ,抛出
RangeError 异常。
如果 byteLength 不为 undefined ,则
如果 offset + viewByteLength >
bufferByteLength ,抛出 RangeError 异常。
设置 O .[[ViewedArrayBuffer]] 为
buffer 。
设置 O .[[ByteLength]] 为
viewByteLength 。
设置 O .[[ByteOffset]] 为 offset 。
返回 O 。
25.3.3 DataView 构造函数的属性
DataView 构造函数 :
25.3.3.1 DataView.prototype
DataView.prototype
的初始值为 DataView
原型对象 。
该属性具有属性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
25.3.4 DataView 原型对象的属性
DataView 原型对象 :
即 %DataView.prototype% 。
拥有一个 [[Prototype]] 内部槽,其值为 %Object.prototype% 。
是一个 普通对象 。
没有 [[DataView]] 、[[ViewedArrayBuffer]] 、[[ByteLength]] 或
[[ByteOffset]] 内部槽。
25.3.4.1 get DataView.prototype.buffer
DataView.prototype.buffer
是一个 访问器属性 ,其 set 访问器函数为
undefined 。其 get 访问器函数被调用时执行以下步骤:
令 O 为 this 值。
执行 ? RequireInternalSlot (O ,
[[DataView]] )。
断言 :
O 拥有 [[ViewedArrayBuffer]] 内部槽。
令 buffer 为 O .[[ViewedArrayBuffer]] 。
返回 buffer 。
25.3.4.2 get DataView.prototype.byteLength
DataView.prototype.byteLength
是一个 访问器属性 ,其 set 访问器函数为
undefined 。其 get 访问器函数被调用时执行以下步骤:
令 O 为 this 值。
执行 ? RequireInternalSlot (O ,
[[DataView]] )。
断言 :
O 拥有 [[ViewedArrayBuffer]] 内部槽。
令 viewRecord 为 MakeDataViewWithBufferWitnessRecord (O ,
seq-cst )。
如果 IsViewOutOfBounds (viewRecord )
为 true ,抛出 TypeError 异常。
令 size 为 GetViewByteLength (viewRecord )。
返回 𝔽 (size )。
25.3.4.3 get DataView.prototype.byteOffset
DataView.prototype.byteOffset
是一个 访问器属性 ,其 set 访问器函数为
undefined 。其 get 访问器函数被调用时执行以下步骤:
令 O 为 this 值。
执行 ? RequireInternalSlot (O ,
[[DataView]] )。
断言 :
O 拥有 [[ViewedArrayBuffer]] 内部槽。
令 viewRecord 为 MakeDataViewWithBufferWitnessRecord (O ,
seq-cst )。
如果 IsViewOutOfBounds (viewRecord )
为 true ,抛出 TypeError 异常。
令 offset 为 O .[[ByteOffset]] 。
返回 𝔽 (offset )。
25.3.4.4 DataView.prototype.constructor
DataView.prototype.constructor
的初始值为 %DataView% 。
25.3.4.5 DataView.prototype.getBigInt64 ( byteOffset
[ , littleEndian ] )
该方法被调用时执行以下步骤:
令 view 为 this 值。
返回 ? GetViewValue (view ,
byteOffset , littleEndian , bigint64 ).
25.3.4.6 DataView.prototype.getBigUint64 ( byteOffset
[ , littleEndian ] )
该方法被调用时执行以下步骤:
令 view 为 this 值。
返回 ? GetViewValue (view ,
byteOffset , littleEndian , biguint64 ).
25.3.4.7 DataView.prototype.getFloat16 ( byteOffset [
, littleEndian ] )
该方法被调用时执行以下步骤:
令 view 为 this 值。
如果未传入 littleEndian ,则设置 littleEndian 为
false 。
返回 ? GetViewValue (view ,
byteOffset , littleEndian , float16 ).
25.3.4.8 DataView.prototype.getFloat32 ( byteOffset [
, littleEndian ] )
该方法被调用时执行以下步骤:
令 view 为 this 值。
如果未传入 littleEndian ,则设置 littleEndian 为
false 。
返回 ? GetViewValue (view ,
byteOffset , littleEndian , float32 ).
25.3.4.9 DataView.prototype.getFloat64 ( byteOffset [
, littleEndian ] )
该方法被调用时执行以下步骤:
令 view 为 this 值。
如果未传入 littleEndian ,则设置 littleEndian 为
false 。
返回 ? GetViewValue (view ,
byteOffset , littleEndian , float64 ).
25.3.4.10 DataView.prototype.getInt8 ( byteOffset )
该方法被调用时执行以下步骤:
令 view 为 this 值。
返回 ? GetViewValue (view ,
byteOffset , true , int8 ).
25.3.4.11 DataView.prototype.getInt16 ( byteOffset [
, littleEndian ] )
该方法被调用时执行以下步骤:
令 view 为 this 值。
如果未传入 littleEndian ,则设置 littleEndian 为
false 。
返回 ? GetViewValue (view ,
byteOffset , littleEndian , int16 ).
25.3.4.12 DataView.prototype.getInt32 ( byteOffset [
, littleEndian ] )
该方法被调用时执行以下步骤:
令 view 为 this 值。
如果未传入 littleEndian ,则设置 littleEndian 为
false 。
返回 ? GetViewValue (view ,
byteOffset , littleEndian , int32 ).
25.3.4.13 DataView.prototype.getUint8 ( byteOffset )
该方法被调用时执行以下步骤:
令 view 为 this 值。
返回 ? GetViewValue (view ,
byteOffset , true , uint8 ).
25.3.4.14 DataView.prototype.getUint16 ( byteOffset [
, littleEndian ] )
该方法被调用时执行以下步骤:
令 view 为 this 值。
如果未传入 littleEndian ,则设置 littleEndian 为
false 。
返回 ? GetViewValue (view ,
byteOffset , littleEndian , uint16 ).
25.3.4.15 DataView.prototype.getUint32 ( byteOffset [
, littleEndian ] )
该方法被调用时执行以下步骤:
令 view 为 this 值。
如果未传入 littleEndian ,则设置 littleEndian 为
false 。
返回 ? GetViewValue (view ,
byteOffset , littleEndian , uint32 ).
25.3.4.16 DataView.prototype.setBigInt64 (
byteOffset , value [ , littleEndian ] )
该方法被调用时执行以下步骤:
令 view 为 this 值。
返回 ? SetViewValue (view ,
byteOffset , littleEndian , bigint64 ,
value ).
25.3.4.17 DataView.prototype.setBigUint64 (
byteOffset , value [ , littleEndian ] )
该方法被调用时执行以下步骤:
令 view 为 this 值。
返回 ? SetViewValue (view ,
byteOffset , littleEndian , biguint64 ,
value ).
25.3.4.18 DataView.prototype.setFloat16 ( byteOffset ,
value [ , littleEndian ] )
该方法被调用时执行以下步骤:
令 view 为 this 值。
如果未传入 littleEndian ,则设置 littleEndian 为
false 。
返回 ? SetViewValue (view ,
byteOffset , littleEndian , float16 ,
value ).
25.3.4.19 DataView.prototype.setFloat32 ( byteOffset ,
value [ , littleEndian ] )
该方法被调用时执行以下步骤:
令 view 为 this 值。
如果未传入 littleEndian ,则设置 littleEndian 为
false 。
返回 ? SetViewValue (view ,
byteOffset , littleEndian , float32 ,
value ).
25.3.4.20 DataView.prototype.setFloat64 ( byteOffset ,
value [ , littleEndian ] )
该方法被调用时执行以下步骤:
令 view 为 this 值。
如果未传入 littleEndian ,则设置 littleEndian 为
false 。
返回 ? SetViewValue (view ,
byteOffset , littleEndian , float64 ,
value ).
25.3.4.21 DataView.prototype.setInt8 ( byteOffset ,
value )
该方法被调用时执行以下步骤:
令 view 为 this 值。
返回 ? SetViewValue (view ,
byteOffset , true , int8 ,
value ).
25.3.4.22 DataView.prototype.setInt16 ( byteOffset ,
value [ , littleEndian ] )
该方法被调用时执行以下步骤:
令 view 为 this 值。
如果未传入 littleEndian ,则设置 littleEndian 为
false 。
返回 ? SetViewValue (view ,
byteOffset , littleEndian , int16 ,
value ).
25.3.4.23 DataView.prototype.setInt32 ( byteOffset ,
value [ , littleEndian ] )
该方法被调用时执行以下步骤:
令 view 为 this 值。
如果未传入 littleEndian ,则设置 littleEndian 为
false 。
返回 ? SetViewValue (view ,
byteOffset , littleEndian , int32 ,
value ).
25.3.4.24 DataView.prototype.setUint8 ( byteOffset ,
value )
该方法被调用时执行以下步骤:
令 view 为 this 值。
返回 ? SetViewValue (view ,
byteOffset , true , uint8 ,
value ).
25.3.4.25 DataView.prototype.setUint16 ( byteOffset ,
value [ , littleEndian ] )
该方法被调用时执行以下步骤:
令 view 为 this 值。
如果未传入 littleEndian ,则设置 littleEndian 为
false 。
返回 ? SetViewValue (view ,
byteOffset , littleEndian , uint16 ,
value ).
25.3.4.26 DataView.prototype.setUint32 ( byteOffset ,
value [ , littleEndian ] )
该方法被调用时执行以下步骤:
令 view 为 this 值。
如果未传入 littleEndian ,则设置 littleEndian 为
false 。
返回 ? SetViewValue (view ,
byteOffset , littleEndian , uint32 ,
value ).
25.3.4.27 DataView.prototype [ %Symbol.toStringTag% ]
%Symbol.toStringTag% 属性的初始值为字符串值
"DataView" 。
该属性具有属性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : true }.
25.3.5 DataView 实例的属性
DataView 实例是普通对象 ,继承自 DataView 原型对象
的属性。每个 DataView 实例都有 [[DataView]] 、[[ViewedArrayBuffer]] 、[[ByteLength]] 和 [[ByteOffset]] 内部槽。
注
[[DataView]] 内部槽的值在本规范中不会被使用。该内部槽的简单存在用来标识通过 DataView 构造函数
创建的对象。
25.4 Atomics 对象
Atomics 对象:
即 %Atomics% 。
是 全局对象 的 "Atomics" 属性的初始值。
是一个 普通对象 。
拥有一个 [[Prototype]] 内部槽,其值为 %Object.prototype% 。
没有 [[Construct]] 内部方法;不能使用 new
运算符作为 构造函数 使用。
没有 [[Call]] 内部方法;不能作为函数调用。
Atomics 对象提供能在共享内存数组单元上以不可分割(原子)方式操作的函数,以及允许 代理 等待和派发原语事件的函数。规范使用 Atomics 函数,可以让通过共享内存通信的多代理 程序,即使在并行 CPU
上,也能以可理解的顺序执行。管理共享内存通信的规则由下文定义的 内存模型 提供。
注
关于 ECMAScript 中共享内存的编程和实现的参考指南,请参见 内存模型 一节末尾的注释。
25.4.1 Waiter 记录
Waiter 记录 是一个 Record 值,用于表示一次
Atomics.wait
或 Atomics.waitAsync
调用。
Waiter 记录的字段见 表
78 。
表 78:Waiter 记录 字段
字段名
值
含义
[[AgentSignifier]]
一个 agent
signifier
调用 Atomics.wait
或 Atomics.waitAsync
的 代理 。
[[PromiseCapability]]
一个 PromiseCapability
记录 或 blocking
如果表示一次 Atomics.waitAsync
调用,则为结果 Promise,否则为
blocking 。
[[TimeoutTime]]
非负 扩展数学值
最早可能触发超时的时间;使用 时间值 计算。
[[Result]]
"ok" 或 "timed-out"
调用的返回值。
25.4.2 WaiterList 记录
WaiterList 记录 用于解释通过 代理 进行
Atomics.wait
、Atomics.waitAsync
和 Atomics.notify
的等待与通知。
WaiterList 记录的字段见 表 79 。
表 79:WaiterList 记录 字段
字段名
值
含义
[[Waiters]]
一个 List
,元素为 Waiter 记录
等待在与该 WaiterList 相关联的位置上的 Atomics.wait
或
Atomics.waitAsync
调用。
[[MostRecentLeaveEvent]]
一个 Synchronize 事件
或 empty
最近一次离开其 临界区 的事件,如果从未进入过其
临界区 ,则为
empty 。
一个 WaiterList 中可以有多个 Waiter 记录 拥有相同的 代理标识符 。
代理簇 拥有一个 WaiterList 记录的存储区;该存储通过
(block , i ) 索引,其中 block 是 共享数据块 ,i 是
block 内存的字节偏移。WaiterList 记录是 代理 无关的:在 代理簇 中,任一 代理 按 (block ,
i ) 查找 WaiterList 记录,结果都是相同的 WaiterList 记录。
每个 WaiterList 记录有一个 临界区 ,用于在求值期间控制对该
WaiterList 记录的独占访问。每次只有一个 代理 可进入 WaiterList 记录的临界区。进入和离开 WaiterList 记录临界区由 抽象操作
EnterCriticalSection 和 LeaveCriticalSection 控制。对 WaiterList
记录的操作——添加和移除等待的 代理 、遍历代理列表、挂起和通知列表中的 代理 、设置与获取 Synchronize 事件 ——只能由已进入该 WaiterList
记录临界区的 代理 执行。
25.4.3 Atomics 的抽象操作
25.4.3.1 ValidateIntegerTypedArray ( typedArray ,
waitable )
抽象操作 ValidateIntegerTypedArray 接收参数 typedArray (一个 ECMAScript 语言值 )和
waitable (布尔值),返回 正常完成,包含 带 Buffer 见证记录的
TypedArray ,或 抛出完成 。调用时执行以下步骤:
令 taRecord 为 ? ValidateTypedArray (typedArray ,
unordered )。
注:当 typedArray 的后备缓冲区为 可增长
SharedArrayBuffer 时,越界检查不是同步操作。
如果 waitable 为 true ,则
如果 typedArray .[[TypedArrayName]] 既不是
"Int32Array" 也不是
"BigInt64Array" ,抛出 TypeError 异常。
否则,
令 type 为 TypedArrayElementType (typedArray )。
如果 IsUnclampedIntegerElementType (type )
为 false 且 IsBigIntElementType (type )
也为 false ,抛出 TypeError 异常。
返回 taRecord 。
25.4.3.2 ValidateAtomicAccess ( taRecord ,
requestIndex )
抽象操作 ValidateAtomicAccess 接收参数 taRecord (一个 带 Buffer 见证记录的
TypedArray )和 requestIndex (一个 ECMAScript 语言值 ),返回 正常完成,包含 一个 整数 ,或 抛出完成 。调用时执行以下步骤:
令 length 为 TypedArrayLength (taRecord )。
令 accessIndex 为 ? ToIndex (requestIndex )。
断言 :
accessIndex ≥ 0。
如果 accessIndex ≥ length ,抛出 RangeError
异常。
令 typedArray 为 taRecord .[[Object]] 。
令 elementSize 为 TypedArrayElementSize (typedArray )。
令 offset 为 typedArray .[[ByteOffset]] 。
返回 (accessIndex × elementSize ) + offset 。
25.4.3.3 ValidateAtomicAccessOnIntegerTypedArray (
typedArray , requestIndex )
抽象操作 ValidateAtomicAccessOnIntegerTypedArray 接收参数 typedArray (一个 ECMAScript 语言值 )和
requestIndex (一个 ECMAScript
语言值 ),返回 正常完成,包含 一个 整数 ,或 抛出完成 。调用时执行以下步骤:
令 taRecord 为 ? ValidateIntegerTypedArray (typedArray ,
false )。
返回 ? ValidateAtomicAccess (taRecord ,
requestIndex )。
25.4.3.4 RevalidateAtomicAccess ( typedArray ,
byteIndexInBuffer )
抽象操作 RevalidateAtomicAccess 接收参数 typedArray (一个 TypedArray )和
byteIndexInBuffer (一个 整数 ),返回 正常完成,包含
unused 或 抛出完成 。
该操作在 Atomics 方法中所有参数强制类型转换完成后重新校验用于原子操作的缓冲区索引,因为参数转换可能有任意副作用,导致缓冲区越界。当 typedArray
的后备缓冲区为 SharedArrayBuffer 时,本操作不会抛出异常。调用时执行以下步骤:
令 taRecord 为 MakeTypedArrayWithBufferWitnessRecord (typedArray ,
unordered )。
注:当 typedArray 的后备缓冲区为 可增长
SharedArrayBuffer 时,越界检查不是同步操作。
如果 IsTypedArrayOutOfBounds (taRecord )
为 true ,抛出 TypeError 异常。
断言 :
byteIndexInBuffer ≥ typedArray .[[ByteOffset]] 。
如果 byteIndexInBuffer ≥ taRecord .[[CachedBufferByteLength]] ,抛出
RangeError 异常。
返回 unused 。
25.4.3.5 GetWaiterList ( block , i )
抽象操作 GetWaiterList 接收参数 block (一个 共享数据块 )和 i (一个能被 4
整除的非负整数 ),返回一个
WaiterList 记录 。调用时执行以下步骤:
断言 :
i 和 i + 3 是 block 内存中的有效字节偏移。
返回由二元组 (block , i ) 引用的 WaiterList 记录 。
25.4.3.6 EnterCriticalSection ( WL )
抽象操作 EnterCriticalSection 接收参数 WL (一个 WaiterList 记录 ),返回
unused 。调用时执行以下步骤:
断言 :
当前代理 未处于任何 WaiterList 记录 的 临界区 中。
等待直到没有 代理 处于
WL 的 临界区 ,然后进入 WL 的
临界区 (不允许其他 代理 进入)。
如果 WL .[[MostRecentLeaveEvent]] 不为
empty ,则
注:至少进入过一次临界区的 WL 会有一个由 LeaveCriticalSection
设置的 Synchronize 事件 。
令 execution 为 当前代理 的
Agent
Record 的 [[CandidateExecution]] 字段。
令 eventsRecord 为 execution .[[EventsRecords]] 中 [[AgentSignifier]] 为 AgentSignifier () 的
Agent Events Record 。
令 enterEvent 为新的 Synchronize
事件 。
将 enterEvent 添加到 eventsRecord .[[EventList]] 。
将 (WL .[[MostRecentLeaveEvent]] ,
enterEvent ) 添加到 eventsRecord .[[AgentSynchronizesWith]] 。
返回 unused 。
当某个 代理 试图进入 临界区 时必须等待其它 代理 离开该区,则 EnterCriticalSection 存在 争用 。无争用时,EnterCriticalSection 的调用顺序可观察为 FIFO。有争用时,实现可选择任意顺序,但不得导致某
代理 无限期等待。
25.4.3.7 LeaveCriticalSection ( WL )
抽象操作 LeaveCriticalSection 接收参数 WL (一个 WaiterList 记录 ),返回
unused 。调用时执行以下步骤:
断言 :
当前代理 正处于 WL 的 临界区 中。
令 execution 为 当前代理 的 Agent
Record 的 [[CandidateExecution]] 字段。
令 eventsRecord 为 execution .[[EventsRecords]] 中 [[AgentSignifier]] 为 AgentSignifier () 的
Agent Events Record 。
令 leaveEvent 为新的 Synchronize
事件 。
将 leaveEvent 添加到 eventsRecord .[[EventList]] 。
设置 WL .[[MostRecentLeaveEvent]] 为
leaveEvent 。
离开 WL 的 临界区 。
返回 unused 。
25.4.3.8 AddWaiter ( WL , waiterRecord )
抽象操作 AddWaiter 接收参数 WL (一个 WaiterList 记录 )和
waiterRecord (一个 Waiter 记录 ),返回
unused 。调用时执行以下步骤:
断言 :
当前代理 正处于 WL 的 临界区 中。
断言 :
WL .[[Waiters]] 中没有其 [[PromiseCapability]] 字段等于 waiterRecord .[[PromiseCapability]] 且 [[AgentSignifier]] 字段等于 waiterRecord .[[AgentSignifier]] 的 Waiter 记录 。
将 waiterRecord 添加到 WL .[[Waiters]] 。
返回 unused 。
25.4.3.9 RemoveWaiter ( WL , waiterRecord )
抽象操作 RemoveWaiter 接收参数 WL (一个 WaiterList 记录 )和
waiterRecord (一个 Waiter 记录 ),返回
unused 。调用时执行以下步骤:
断言 :
当前代理 正处于 WL 的 临界区 中。
断言 :
WL .[[Waiters]] 包含 waiterRecord 。
从 WL .[[Waiters]] 中移除 waiterRecord 。
返回 unused 。
25.4.3.10 RemoveWaiters ( WL , c )
抽象操作 RemoveWaiters 接收参数 WL (一个 WaiterList 记录 )和
c (一个非负整数 或 +∞),返回 List ,元素为 Waiter
记录 。调用时执行以下步骤:
断言 :
当前代理 正处于 WL 的 临界区 中。
令 len 为 WL .[[Waiters]] 的元素数量。
令 n 为 min (c , len )。
令 L 为 List ,其元素为
WL .[[Waiters]] 的前 n 个元素。
从 WL .[[Waiters]] 中移除前 n 个元素。
返回 L 。
25.4.3.11 SuspendThisAgent ( WL ,
waiterRecord )
抽象操作 SuspendThisAgent 接收参数 WL (一个 WaiterList 记录 )和
waiterRecord (一个 Waiter 记录 ),返回
unused 。调用时执行以下步骤:
断言 :
当前代理 正处于 WL 的 临界区 中。
断言 :
WL .[[Waiters]] 包含 waiterRecord 。
令 thisAgent 为 AgentSignifier ()。
断言 :
waiterRecord .[[AgentSignifier]] 等于
thisAgent 。
断言 :
waiterRecord .[[PromiseCapability]] 为
blocking 。
断言 :
AgentCanSuspend () 为
true 。
执行 LeaveCriticalSection (WL )
并挂起 当前代理 直到时间为
waiterRecord .[[TimeoutTime]] ,整个操作应保证在离开
临界区 后到挂起生效前收到的通知不会丢失。当前代理 只能因为超时或因其他 代理 调用 NotifyWaiter 并传入 WL 和
thisAgent (即通过 Atomics.notify
调用)而被唤醒。
执行 EnterCriticalSection (WL )。
返回 unused 。
25.4.3.12 NotifyWaiter ( WL , waiterRecord
)
抽象操作 NotifyWaiter 接收参数 WL (一个 WaiterList 记录 )和
waiterRecord (一个 Waiter 记录 ),返回
unused 。调用时执行以下步骤:
断言 :
当前代理 正处于 WL 的 临界区 中。
如果 waiterRecord .[[PromiseCapability]] 为
blocking ,则
唤醒其标识符为 waiterRecord .[[AgentSignifier]]
的 代理 。
注:这会使 代理 在 SuspendThisAgent 中恢复执行。
否则如果 AgentSignifier () 等于
waiterRecord .[[AgentSignifier]] ,则
令 promiseCapability 为 waiterRecord .[[PromiseCapability]] 。
执行 ! Call (promiseCapability .[[Resolve]] , undefined , «
waiterRecord .[[Result]] »)。
否则,
执行 EnqueueResolveInAgentJob (waiterRecord .[[AgentSignifier]] , waiterRecord .[[PromiseCapability]] , waiterRecord .[[Result]] )。
返回 unused 。
注
一个 代理
不应以任何方式访问其他 代理 的 promise 能力,除了将其传递给 宿主 。
25.4.3.13 EnqueueResolveInAgentJob ( agentSignifier ,
promiseCapability , resolution )
抽象操作 EnqueueResolveInAgentJob 接收参数 agentSignifier (一个 代理标识符 )、promiseCapability (一个 PromiseCapability
记录 )、resolution ("ok" 或
"timed-out" ),返回 unused 。调用时执行以下步骤:
令 resolveJob 为新的 作业 抽象闭包 ,无参数,捕获
agentSignifier 、promiseCapability 和
resolution ,被调用时执行以下步骤:
断言 :AgentSignifier () 等于
agentSignifier 。
执行 ! Call (promiseCapability .[[Resolve]] , undefined , «
resolution »)。
返回 unused 。
令 realmInTargetAgent 为 ! GetFunctionRealm (promiseCapability .[[Resolve]] )。
断言 :
agentSignifier 等于 realmInTargetAgent .[[AgentSignifier]] 。
执行 HostEnqueueGenericJob (resolveJob ,
realmInTargetAgent )。
返回 unused 。
25.4.3.14 DoWait ( mode , typedArray ,
index , value , timeout )
抽象操作 DoWait 接收参数 mode (sync 或
async )、typedArray (一个 ECMAScript 语言值 )、
index (一个 ECMAScript 语言值 )、
value (一个 ECMAScript 语言值 )和
timeout (一个 ECMAScript 语言值 ),返回 正常完成,包含
Object、"not-equal" 、"timed-out" 或
"ok" ,或 抛出完成 。调用时执行以下步骤:
令 taRecord 为 ? ValidateIntegerTypedArray (typedArray ,
true )。
令 buffer 为 taRecord .[[Object]] .[[ViewedArrayBuffer]] 。
如果 IsSharedArrayBuffer (buffer )
为 false ,抛出 TypeError 异常。
令 i 为 ? ValidateAtomicAccess (taRecord ,
index )。
令 arrayTypeName 为 typedArray .[[TypedArrayName]] 。
如果 arrayTypeName 为 "BigInt64Array" ,令 v
为 ? ToBigInt64 (value )。
否则,令 v 为 ? ToInt32 (value )。
令 q 为 ? ToNumber (timeout )。
如果 q 是 NaN 或 +∞ 𝔽 ,令
t 为 +∞;否则如果 q 是
-∞ 𝔽 ,令 t 为 0;否则令 t 为
max (ℝ (q ), 0)。
如果 mode 为 sync 且 AgentCanSuspend ()
为
false ,抛出 TypeError 异常。
令 block 为 buffer .[[ArrayBufferData]] 。
令 offset 为 typedArray .[[ByteOffset]] 。
令 byteIndexInBuffer 为 (i × 4) + offset 。
令 WL 为 GetWaiterList (block ,
byteIndexInBuffer )。
如果 mode 为 sync ,则
令 promiseCapability 为 blocking 。
令 resultObject 为 undefined 。
否则,
令 promiseCapability 为 ! NewPromiseCapability (%Promise% )。
令 resultObject 为 OrdinaryObjectCreate (%Object.prototype% )。
执行 EnterCriticalSection (WL )。
令 elementType 为 TypedArrayElementType (typedArray )。
令 w 为 GetValueFromBuffer (buffer ,
byteIndexInBuffer , elementType , true ,
seq-cst )。
如果 v ≠ w ,则
执行 LeaveCriticalSection (WL )。
如果 mode 为 sync ,返回
"not-equal" 。
执行 ! CreateDataPropertyOrThrow (resultObject ,
"async" , false )。
执行 ! CreateDataPropertyOrThrow (resultObject ,
"value" , "not-equal" )。
返回 resultObject 。
如果 t = 0 且 mode 为 async ,则
注:同步即时超时不做特殊处理。异步即时超时有特殊处理以快速失败并避免不必要的 Promise 任务。
执行 LeaveCriticalSection (WL )。
执行 ! CreateDataPropertyOrThrow (resultObject ,
"async" , false )。
执行 ! CreateDataPropertyOrThrow (resultObject ,
"value" , "timed-out" )。
返回 resultObject 。
令 thisAgent 为 AgentSignifier ()。
令 now 为 时间值 (UTC),标识当前时间。
令 additionalTimeout 为实现定义的非负数学值 。
令 timeoutTime 为 ℝ (now ) + t +
additionalTimeout 。
注:当 t 为 +∞ 时,timeoutTime 也为 +∞。
令 waiterRecord 为新的 Waiter 记录 { [[AgentSignifier]] : thisAgent , [[PromiseCapability]] : promiseCapability , [[TimeoutTime]] : timeoutTime , [[Result]] : "ok" }。
执行 AddWaiter (WL ,
waiterRecord )。
如果 mode 为 sync ,则
执行 SuspendThisAgent (WL ,
waiterRecord )。
否则如果 timeoutTime 是 有限 ,则
执行 EnqueueAtomicsWaitAsyncTimeoutJob (WL ,
waiterRecord )。
执行 LeaveCriticalSection (WL )。
如果 mode 为 sync ,返回
waiterRecord .[[Result]] 。
执行 ! CreateDataPropertyOrThrow (resultObject ,
"async" , true )。
执行 ! CreateDataPropertyOrThrow (resultObject ,
"value" , promiseCapability .[[Promise]] )。
返回 resultObject 。
注
additionalTimeout 允许实现根据需要填充超时时间,比如降低功耗或粗化定时器分辨率以缓解计时攻击。该值在 DoWait
的不同调用之间可能不同。
25.4.3.15 EnqueueAtomicsWaitAsyncTimeoutJob ( WL ,
waiterRecord )
抽象操作 EnqueueAtomicsWaitAsyncTimeoutJob 接收参数 WL (一个 WaiterList 记录 )和
waiterRecord (一个 Waiter 记录 ),返回
unused 。调用时执行以下步骤:
令 timeoutJob 为新的 作业 抽象闭包 ,无参数,捕获
WL 和 waiterRecord ,被调用时执行以下步骤:
执行 EnterCriticalSection (WL )。
如果 WL .[[Waiters]] 包含
waiterRecord ,则
令 timeOfJobExecution 为 时间值 (UTC),标识当前时间。
断言 :ℝ (timeOfJobExecution ) ≥
waiterRecord .[[TimeoutTime]]
(忽略 时间值
可能的非单调性)。
设置 waiterRecord .[[Result]] 为
"timed-out" 。
执行 RemoveWaiter (WL ,
waiterRecord )。
执行 NotifyWaiter (WL ,
waiterRecord )。
执行 LeaveCriticalSection (WL )。
返回 unused 。
令 now 为 时间值 (UTC),标识当前时间。
令 currentRealm 为 当前 Realm 记录 。
执行 HostEnqueueTimeoutJob (timeoutJob ,
currentRealm , 𝔽 (waiterRecord .[[TimeoutTime]] ) - now ).
返回 unused 。
25.4.3.16 AtomicCompareExchangeInSharedBlock ( block ,
byteIndexInBuffer , elementSize , expectedBytes ,
replacementBytes )
抽象操作 AtomicCompareExchangeInSharedBlock 接收参数 block (一个 共享数据块 )、byteIndexInBuffer (一个
整数 )、elementSize (一个非负整数 )、expectedBytes (一个 List ,元素为 字节值 )、replacementBytes (一个 List ,元素为 字节值 ),返回一个 List ,元素为 字节值 。调用时执行以下步骤:
令 execution 为 当前代理 的 Agent
Record 的 [[CandidateExecution]] 字段。
令 eventsRecord 为 execution .[[EventsRecords]] 中 [[AgentSignifier]] 为 AgentSignifier () 的
Agent Events Record 。
令 rawBytesRead 为一个长度为 elementSize 的 List ,其元素为非确定性选择的
字节值 。
注:在实现中,rawBytesRead 是底层硬件上 load-link、load-exclusive 或读-改-写指令的结果。该非确定性由
内存模型 的语义规定,用于描述弱一致性硬件的可观测行为。
注:预期值与读取值的比较在 读改写修改函数
之外进行,以避免当预期值不等于读取值时产生不必要的强同步。
如果 ByteListEqual (rawBytesRead ,
expectedBytes ) 为 true ,则
令 second 为新的 读改写修改函数 ,参数为
(oldBytes , newBytes ),不捕获任何变量,调用时以原子方式执行以下步骤:
返回 newBytes 。
令 event 为 ReadModifyWriteSharedMemory
{ [[Order]] : seq-cst , [[NoTear]] : true , [[Block]] : block , [[ByteIndex]] : byteIndexInBuffer , [[ElementSize]] : elementSize , [[Payload]] : replacementBytes , [[ModifyOp]] : second }。
否则,
令 event 为 ReadSharedMemory
{ [[Order]] : seq-cst , [[NoTear]] : true , [[Block]] : block , [[ByteIndex]] : byteIndexInBuffer , [[ElementSize]] : elementSize }。
将 event 添加到 eventsRecord .[[EventList]] 。
将 Chosen Value 记录 { [[Event]] : event , [[ChosenValue]] : rawBytesRead } 添加到
execution .[[ChosenValues]] 。
返回 rawBytesRead 。
25.4.3.17 AtomicReadModifyWrite ( typedArray ,
index , value , op )
抽象操作 AtomicReadModifyWrite 接收参数 typedArray (一个
ECMAScript 语言值 )、
index (一个 ECMAScript 语言值 )、
value (一个 ECMAScript
语言值 )、op (一个 读改写修改函数 ),返回 正常完成,包含 Number 或
BigInt,或 抛出完成 。
op 接收两个 List (元素为 字节值 )参数,返回一个 List (元素为 字节值 )。该操作以原子方式加载一个值,与另一个值组合,并存储组合结果。返回被加载的值。调用时执行以下步骤:
令 byteIndexInBuffer 为 ? ValidateAtomicAccessOnIntegerTypedArray (typedArray ,
index )。
如果 typedArray .[[ContentType]] 为
bigint ,令 v 为 ? ToBigInt (value )。
否则,令 v 为 𝔽 (? ToIntegerOrInfinity (value ))。
执行 ? RevalidateAtomicAccess (typedArray ,
byteIndexInBuffer )。
令 buffer 为 typedArray .[[ViewedArrayBuffer]] 。
令 elementType 为 TypedArrayElementType (typedArray )。
返回 GetModifySetValueInBuffer (buffer ,
byteIndexInBuffer , elementType , v , op )。
25.4.3.18 ByteListBitwiseOp ( op , xBytes ,
yBytes )
抽象操作 ByteListBitwiseOp 接收参数 op (&
、^
或
|
)、xBytes (一个 List ,元素为 字节值 )、yBytes (一个 List ,元素为 字节值 ),返回 List ,元素为 字节值 。该操作以原子方式对参数的所有字节值 执行按位操作,并返回 List ,元素为 字节值 。调用时执行以下步骤:
断言 :
xBytes 和 yBytes 拥有相同数量的元素。
令 result 为新的空 List 。
令 i 为 0。
对于 xBytes 的每个元素 xByte ,执行
令 yByte 为 yBytes [i ]。
如果 op 为 &
,则
令 resultByte 为 xByte 与 yByte
执行按位与操作的结果。
否则如果 op 为 ^
,则
令 resultByte 为 xByte 与 yByte
执行按位异或操作的结果。
否则,
断言 :op 为
|
。
令 resultByte 为 xByte 与 yByte
执行按位或操作的结果。
设置 i 为 i + 1。
将 resultByte 添加到 result 。
返回 result 。
25.4.3.19 ByteListEqual ( xBytes , yBytes )
抽象操作 ByteListEqual 接收参数 xBytes (一个 List ,元素为 字节值 )和
yBytes (一个 List ,元素为 字节值 ),返回一个布尔值。调用时执行以下步骤:
如果 xBytes 和 yBytes 的元素数量不同,返回 false 。
令 i 为 0。
对于 xBytes 的每个元素 xByte ,执行
令 yByte 为 yBytes [i ]。
如果 xByte ≠ yByte ,返回 false 。
设置 i 为 i + 1。
返回 true 。
25.4.4 Atomics.add ( typedArray , index ,
value )
该函数被调用时执行以下步骤:
令 add 为一个新的 读改写修改函数 ,参数为 (xBytes ,
yBytes ),捕获 typedArray ,当被原子方式调用时,执行以下步骤:
令 type 为 TypedArrayElementType (typedArray )。
令 isLittleEndian 为 当前代理 的 Agent
Record 的 [[LittleEndian]] 字段的值。
令 x 为 RawBytesToNumeric (type ,
xBytes , isLittleEndian )。
令 y 为 RawBytesToNumeric (type ,
yBytes , isLittleEndian )。
如果 x 是
Number ,则
令 sum 为 Number::add (x ,
y )。
否则,
断言 :x 是
BigInt 。
令 sum 为 BigInt::add (x ,
y )。
令 sumBytes 为 NumericToRawBytes (type ,
sum , isLittleEndian )。
断言 :sumBytes 、xBytes 和
yBytes 具有相同的元素数量。
返回 sumBytes 。
返回 ? AtomicReadModifyWrite (typedArray ,
index , value , add )。
25.4.5 Atomics.and ( typedArray , index ,
value )
该函数被调用时执行以下步骤:
令 and 为一个新的 读改写修改函数 ,参数为 (xBytes ,
yBytes ),不捕获任何变量,当被原子方式调用时执行以下步骤:
返回 ByteListBitwiseOp (&
,
xBytes , yBytes )。
返回 ? AtomicReadModifyWrite (typedArray ,
index , value , and )。
25.4.6 Atomics.compareExchange ( typedArray ,
index , expectedValue , replacementValue )
该函数被调用时执行以下步骤:
令 byteIndexInBuffer 为 ? ValidateAtomicAccessOnIntegerTypedArray (typedArray ,
index )。
令 buffer 为 typedArray .[[ViewedArrayBuffer]] 。
令 block 为 buffer .[[ArrayBufferData]] 。
如果 typedArray .[[ContentType]] 为
bigint ,则
令 expected 为 ? ToBigInt (expectedValue )。
令 replacement 为 ? ToBigInt (replacementValue )。
否则,
令 expected 为 𝔽 (? ToIntegerOrInfinity (expectedValue ))。
令 replacement 为 𝔽 (? ToIntegerOrInfinity (replacementValue ))。
执行 ? RevalidateAtomicAccess (typedArray ,
byteIndexInBuffer )。
令 elementType 为 TypedArrayElementType (typedArray )。
令 elementSize 为 TypedArrayElementSize (typedArray )。
令 isLittleEndian 为 当前代理 的 Agent Record 的 [[LittleEndian]] 字段的值。
令 expectedBytes 为 NumericToRawBytes (elementType ,
expected , isLittleEndian )。
令 replacementBytes 为 NumericToRawBytes (elementType ,
replacement , isLittleEndian )。
如果 IsSharedArrayBuffer (buffer )
为 true ,则
令 rawBytesRead 为 AtomicCompareExchangeInSharedBlock (block ,
byteIndexInBuffer , elementSize , expectedBytes ,
replacementBytes )。
否则,
令 rawBytesRead 为一个长度为 elementSize 的 List ,其元素为从
block [byteIndexInBuffer ] 开始的 elementSize 个字节序列。
如果 ByteListEqual (rawBytesRead ,
expectedBytes ) 为 true ,则
将 replacementBytes 的各字节依次存入 block ,起始于
block [byteIndexInBuffer ]。
返回 RawBytesToNumeric (elementType ,
rawBytesRead , isLittleEndian )。
25.4.7 Atomics.exchange ( typedArray , index ,
value )
该函数被调用时执行以下步骤:
令 second 为一个新的 读改写修改函数 ,参数为
(oldBytes ,
newBytes ),不捕获任何变量,当被原子方式调用时执行以下步骤:
返回 newBytes 。
返回 ? AtomicReadModifyWrite (typedArray ,
index , value , second )。
25.4.8 Atomics.isLockFree ( size )
该函数被调用时执行以下步骤:
令 n 为 ? ToIntegerOrInfinity (size )。
令 AR 为 当前代理 的 Agent Record 。
如果 n = 1,返回 AR .[[IsLockFree1]] 。
如果 n = 2,返回 AR .[[IsLockFree2]] 。
如果 n = 4,返回 true 。
如果 n = 8,返回 AR .[[IsLockFree8]] 。
返回 false 。
注
该函数是一个优化原语。直观理解是:如果对一个字节数为 n
的数据执行原子操作(compareExchange
、load
、store
、add
、sub
、and
、or
、xor
或 exchange
)时,当前代理 不会获得该 n 字节之外的锁,则
Atomics.isLockFree
(n ) 会返回
true 。高性能算法会用该函数判断是在临界区 用锁还是原子操作。如果原子操作不是无锁的,算法通常自带锁效率更高。
Atomics.isLockFree
(4) 总是返回
true ,因为所有相关硬件都支持。可以假定此条件通常会简化程序。
无论该函数返回何值,所有原子操作都保证是原子的。例如,永远不会在操作中间有可见操作发生(如“撕裂”)。
25.4.9 Atomics.load ( typedArray , index )
该函数被调用时执行以下步骤:
令 byteIndexInBuffer 为 ? ValidateAtomicAccessOnIntegerTypedArray (typedArray ,
index )。
执行 ? RevalidateAtomicAccess (typedArray ,
byteIndexInBuffer )。
令 buffer 为 typedArray .[[ViewedArrayBuffer]] 。
令 elementType 为 TypedArrayElementType (typedArray )。
返回 GetValueFromBuffer (buffer ,
byteIndexInBuffer , elementType , true ,
seq-cst )。
25.4.10 Atomics.or ( typedArray , index ,
value )
该函数被调用时执行以下步骤:
令 or 为一个新的 读改写修改函数 ,参数为 (xBytes ,
yBytes ),不捕获任何变量,当被原子方式调用时执行以下步骤:
返回 ByteListBitwiseOp (|
,
xBytes , yBytes )。
返回 ? AtomicReadModifyWrite (typedArray ,
index , value , or )。
25.4.11 Atomics.store ( typedArray , index ,
value )
该函数被调用时执行以下步骤:
令 byteIndexInBuffer 为 ? ValidateAtomicAccessOnIntegerTypedArray (typedArray ,
index )。
如果 typedArray .[[ContentType]] 为
bigint ,令 v 为 ? ToBigInt (value )。
否则,令 v 为 𝔽 (? ToIntegerOrInfinity (value ))。
执行 ? RevalidateAtomicAccess (typedArray ,
byteIndexInBuffer )。
令 buffer 为 typedArray .[[ViewedArrayBuffer]] 。
令 elementType 为 TypedArrayElementType (typedArray )。
执行 SetValueInBuffer (buffer ,
byteIndexInBuffer , elementType , v ,
true , seq-cst )。
返回 v 。
25.4.12 Atomics.sub ( typedArray , index ,
value )
该函数被调用时执行以下步骤:
令 subtract 为一个新的 读改写修改函数 ,参数为
(xBytes , yBytes ),捕获 typedArray ,当被原子方式调用时,执行以下步骤:
令 type 为 TypedArrayElementType (typedArray )。
令 isLittleEndian 为 当前代理 的 Agent
Record 的 [[LittleEndian]] 字段的值。
令 x 为 RawBytesToNumeric (type ,
xBytes , isLittleEndian )。
令 y 为 RawBytesToNumeric (type ,
yBytes , isLittleEndian )。
如果 x 是
Number ,则
令 difference 为 Number::subtract (x ,
y )。
否则,
断言 :x 是
BigInt 。
令 difference 为 BigInt::subtract (x ,
y )。
令 differenceBytes 为 NumericToRawBytes (type ,
difference , isLittleEndian )。
断言 :differenceBytes 、xBytes
和 yBytes 具有相同的元素数量。
返回 differenceBytes 。
返回 ? AtomicReadModifyWrite (typedArray ,
index , value , subtract )。
25.4.13 Atomics.wait ( typedArray , index ,
value , timeout )
该函数会将当前代理 放入等待队列并挂起,直到被通知或超时,返回区分这些情况的字符串。
被调用时执行以下步骤:
返回 ? DoWait (sync ,
typedArray , index , value , timeout )。
25.4.14 Atomics.waitAsync ( typedArray , index ,
value , timeout )
该函数返回一个 Promise,当调用的 代理
被通知或超时时被 resolve。
被调用时执行以下步骤:
返回 ? DoWait (async ,
typedArray , index , value , timeout )。
25.4.15 Atomics.notify ( typedArray , index ,
count )
该函数会通知一些在等待队列中休眠的代理 。
被调用时执行以下步骤:
令 taRecord 为 ? ValidateIntegerTypedArray (typedArray ,
true )。
令 byteIndexInBuffer 为 ? ValidateAtomicAccess (taRecord ,
index )。
如果 count 为 undefined ,则
令 c 为 +∞。
否则,
令 intCount 为 ? ToIntegerOrInfinity (count )。
令 c 为 max (intCount , 0)。
令 buffer 为 typedArray .[[ViewedArrayBuffer]] 。
令 block 为 buffer .[[ArrayBufferData]] 。
如果 IsSharedArrayBuffer (buffer )
为 false ,返回 +0 𝔽 。
令 WL 为 GetWaiterList (block ,
byteIndexInBuffer )。
执行 EnterCriticalSection (WL )。
令 S 为 RemoveWaiters (WL ,
c )。
对于 S 的每个元素 W ,执行
执行 NotifyWaiter (WL ,
W )。
执行 LeaveCriticalSection (WL )。
令 n 为 S 的元素数量。
返回 𝔽 (n )。
25.4.16 Atomics.xor ( typedArray , index ,
value )
该函数被调用时执行以下步骤:
令 xor 为一个新的 读改写修改函数 ,参数为 (xBytes ,
yBytes ),不捕获任何变量,当被原子方式调用时执行以下步骤:
返回 ByteListBitwiseOp (^
,
xBytes , yBytes )。
返回 ? AtomicReadModifyWrite (typedArray ,
index , value , xor )。
25.4.17 Atomics [ %Symbol.toStringTag% ]
%Symbol.toStringTag% 属性的初始值为字符串值
"Atomics" 。
该属性具有属性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : true }.
25.5 JSON 对象
JSON 对象:
即 %JSON% 。
是 全局对象 的 "JSON" 属性的初始值。
是一个 普通对象 。
包含两个函数,parse
和 stringify
,用于解析和构造 JSON 文本。
有一个 [[Prototype]] 内部槽,其值为 %Object.prototype% 。
没有 [[Construct]] 内部方法;不能使用 new
运算符作为 构造函数 使用。
没有 [[Call]] 内部方法;不能作为函数调用。
JSON 数据交换格式在 ECMA-404 中定义。本规范中使用的 JSON 交换格式与 ECMA-404 描述的完全一致。JSON.parse
和
JSON.stringify
的符合实现,必须支持 ECMA-404 规范中描述的精确交换格式,不得对格式做任何删减或扩展。
25.5.1 JSON.parse ( text [ , reviver ] )
该函数用于解析 JSON 文本(JSON 格式的字符串),并生成一个 ECMAScript 语言值 。JSON
格式用与 ECMAScript 字面量、数组初始化器和对象初始化器类似的语法来表示字面量、数组和对象。解析后,JSON 对象被实现为 ECMAScript 对象,JSON 数组实现为
ECMAScript 数组实例。JSON 字符串、数字、布尔值和 null 分别实现为 ECMAScript 字符串、数字、布尔值和 null 。
可选参数 reviver 是一个带有两个参数 key 和 value 的函数。它可以过滤和转换结果。该函数会对解析产生的每一个
key /value 对调用,其返回值会替代原始值。如果返回原值,则结构不变。如果返回
undefined ,则该属性会从结果中删除。
令 jsonString 为 ? ToString (text )。
令 unfiltered 为 ? ParseJSON (jsonString )。
如果 IsCallable (reviver ) 为
true ,则
令 root 为 OrdinaryObjectCreate (%Object.prototype% )。
令 rootName 为空字符串。
执行 ! CreateDataPropertyOrThrow (root ,
rootName , unfiltered )。
返回 ? InternalizeJSONProperty (root ,
rootName , reviver )。
否则,
返回 unfiltered 。
该函数的 "length" 属性为 2 𝔽 。
25.5.1.1 ParseJSON ( text )
抽象操作 ParseJSON 接收参数 text (一个字符串),返回 正常完成,包含 一个 ECMAScript 语言值 ,或 抛出完成 。调用时执行以下步骤:
如果 StringToCodePoints (text )
不是 ECMA-404 规定的有效 JSON 文本,则抛出 SyntaxError 异常。
令 scriptString 为 字符串拼接
"(" 、text 和 ");" 的结果。
令 script 为 ParseText (scriptString ,
Script )。
注:Early
Error 规则在 13.2.5.1
对上述 ParseText 调用有特殊处理。
断言 :
script 是一个 解析节点 。
令 result 为 ! Evaluation (script ) 的结果。
注:PropertyDefinitionEvaluation
语义在 13.2.5.5
对上述求值有特殊处理。
断言 :result 必须是字符串、数字、布尔值、由 ArrayLiteral 或 ObjectLiteral 定义的对象,或
null 。
返回 result 。
符合要求的 JSON.parse
实现不允许扩展 JSON 语法。如果实现希望支持修改或扩展的 JSON 交换格式,必须通过另一个解析函数实现。
注 1
有效的 JSON 文本是 ECMAScript PrimaryExpression 语法的子集。步骤
1 检查 jsonString
是否符合该子集,步骤 8 断言求值结果类型正确。
然而,由于 13.2.5.5
在 ParseJSON 期间行为不同,同一源文本作为 PrimaryExpression 和 JSON
求值结果可能不同。此外,对象字面量中重复的 "__proto__" 属性的 Early Error 在 ParseJSON
期间不适用,这意味着 ParseJSON 接受的文本并不都是有效的 PrimaryExpression ,尽管语法匹配。
注 2
在对象内存在重复名称字符串时,词法上靠前的同名键对应的值会被后面的覆盖。
25.5.1.2 InternalizeJSONProperty ( holder ,
name , reviver )
抽象操作 InternalizeJSONProperty 接收参数
holder (对象)、name (字符串)、reviver (函数对象 ),返回 正常完成,包含 一个 ECMAScript 语言值 或 抛出完成 。
注
本算法有意不在 [[Delete]] 或 CreateDataProperty 返回
false 时抛出异常。
调用时执行以下步骤:
令 val 为 ? Get (holder , name )。
如果 val 是对象 ,则
令 isArray 为 ? IsArray (val )。
如果 isArray 为 true ,则
令 len 为 ? LengthOfArrayLike (val )。
令 I 为 0。
当 I < len 时重复,
令 prop 为 ! ToString (𝔽 (I ))。
令 newElement 为 ? InternalizeJSONProperty (val ,
prop , reviver )。
如果 newElement 为 undefined ,则
执行 ? val .[[Delete]] (prop )。
否则,
执行 ? CreateDataProperty (val ,
prop , newElement )。
设置 I 为 I + 1。
否则,
令 keys 为 ? EnumerableOwnProperties (val ,
key )。
对于 keys 的每个字符串 P ,执行
令 newElement 为 ? InternalizeJSONProperty (val ,
P , reviver )。
如果 newElement 为 undefined ,则
执行 ? val .[[Delete]] (P )。
否则,
执行 ? CreateDataProperty (val ,
P , newElement )。
返回 ? Call (reviver ,
holder , « name , val »)。
25.5.2 JSON.stringify ( value [ , replacer [ ,
space ] ] )
该函数返回一个表示 ECMAScript 语言值 的 UTF-16 编码 JSON
格式字符串,或 undefined 。它可以接收三个参数。value 参数是一个 ECMAScript
语言值 ,通常是对象或数组,也可以是字符串、布尔值、数字或 null 。可选参数
replacer 可以是一个函数,用于改变对象和数组的序列化方式,或者是一个字符串和数字数组,作为包含列表选择要序列化的对象属性。可选参数
space 是字符串 或数字,允许在结果中插入空白以提高人类可读性。
被调用时执行以下步骤:
令 stack 为一个新的空 List 。
令 indent 为空字符串。
令 PropertyList 为 undefined 。
令 ReplacerFunction 为 undefined 。
如果 replacer 是对象 ,则
如果 IsCallable (replacer ) 为
true ,则
设置 ReplacerFunction 为 replacer 。
否则,
令 isArray 为 ? IsArray (replacer )。
如果 isArray 为 true ,则
设置 PropertyList 为一个新的空 List 。
令 len 为 ? LengthOfArrayLike (replacer )。
令 k 为 0。
当 k < len 时重复,
令 prop 为 ! ToString (𝔽 (k ))。
令 v 为 ? Get (replacer ,
prop )。
令 item 为 undefined 。
如果 v 是字符串 ,则
设置 item 为 v 。
否则如果 v 是数字 ,则
设置 item 为 ! ToString (v )。
否则如果 v 是对象 ,则
如果 v 有 [[StringData]] 或 [[NumberData]] 内部槽,则设置
item 为 ? ToString (v )。
如果 item 不为 undefined
且 PropertyList 不包含 item ,则
将 item 添加到 PropertyList 。
设置 k 为 k + 1。
如果 space 是对象 ,则
如果 space 有 [[NumberData]] 内部槽,则
设置 space 为 ? ToNumber (space )。
否则如果 space 有 [[StringData]] 内部槽,则
设置 space 为 ? ToString (space )。
如果 space 是数字 ,则
令 spaceMV 为 ! ToIntegerOrInfinity (space )。
设置 spaceMV 为 min (10, spaceMV )。
如果 spaceMV < 1,令 gap 为空字符串;否则令 gap 为包含
spaceMV 个 0x0020 (SPACE) 码元的字符串。
否则如果 space 是字符串 ,则
如果 space 长度 ≤ 10,令 gap 为 space ;否则令
gap 为 space 的前 10 个字符。
否则,
令 gap 为空字符串。
令 wrapper 为 OrdinaryObjectCreate (%Object.prototype% )。
执行 ! CreateDataPropertyOrThrow (wrapper ,
空字符串, value )。
令 state 为 JSON 序列化记录 { [[ReplacerFunction]] :
ReplacerFunction , [[Stack]] : stack , [[Indent]] : indent , [[Gap]] :
gap , [[PropertyList]] :
PropertyList }。
返回 ? SerializeJSONProperty (state , 空字符串,
wrapper )。
该函数的 "length" 属性为 3 𝔽 。
注 1
JSON 结构可以任意嵌套,但必须无环。如果 value 是或包含循环结构,则该函数必须抛出 TypeError
异常。例如,以下值无法被序列化:
a = [];
a[0 ] = a;
my_text = JSON .stringify (a);
注 2
符号原始值的序列化规则如下:
null 在 JSON 文本中以字符串 "null" 表示。
undefined 不被序列化。
true 在 JSON 文本中以字符串 "true" 表示。
false 在 JSON 文本中以字符串 "false" 表示。
注 3
字符串值用引号("
)括起来。"
和 \
需用 \
转义。控制字符替换为
\u
HHHH 或更短的
\b
(退格)、\f
(换页)、\n
(换行)、\r
(回车)、\t
(制表)。
注 4
有限 数字序列化如同调用
ToString (number )。NaN
和 Infinity (无论正负)以字符串 "null" 表示。
注 5
没有 JSON 表示的值(如 undefined 和函数)不会产生字符串,而是产生
undefined 。在数组中这些值以字符串 "null"
表示。在对象中无法表示的值会导致该属性被排除于序列化结果之外。
注 6
对象以 U+007B(左大括号)开头,后接零个或多个属性(用 U+002C 逗号分隔),以
U+007D(右大括号)结尾。属性为带引号的字符串表示属性名、U+003A(冒号)和序列化后的值。数组以 U+005B(左中括号)开头,后接零个或多个值(用 U+002C
逗号分隔),以 U+005D(右中括号)结尾。
25.5.2.1 JSON 序列化记录
JSON 序列化记录 是一个 Record 值,用于支持序列化为 JSON
格式。
JSON 序列化记录的字段见 表 80 。
表 80:JSON 序列化记录 字段
字段名
值
含义
[[ReplacerFunction]]
函数对象 或
undefined
可为对象属性提供替换值的函数(来自 JSON.stringify 的 replacer 参数)。
[[PropertyList]]
List
的字符串,或 undefined
序列化非数组对象时要包含的属性名(来自 JSON.stringify 的 replacer 参数)。
[[Gap]]
字符串
缩进单位(来自 JSON.stringify 的 space 参数)。
[[Stack]]
List
的对象
正在序列化的嵌套对象集合。用于检测循环结构。
[[Indent]]
字符串
当前缩进。
25.5.2.2 SerializeJSONProperty ( state ,
key , holder )
抽象操作 SerializeJSONProperty 接收参数 state (JSON
序列化记录 )、key (字符串)、holder (对象),返回 正常完成,包含 字符串或
undefined ,或 抛出完成 。调用时执行以下步骤:
令 value 为 ? Get (holder , key )。
如果 value 是对象 或 value
是 BigInt ,则
令 toJSON 为 ? GetV (value ,
"toJSON" )。
如果 IsCallable (toJSON )
为 true ,则
设置 value 为 ? Call (toJSON ,
value , « key »)。
如果 state .[[ReplacerFunction]] 不为
undefined ,则
设置 value 为 ? Call (state .[[ReplacerFunction]] , holder , «
key , value »)。
如果 value 是对象 ,则
如果 value 有 [[NumberData]] 内部槽,则
设置 value 为 ? ToNumber (value )。
否则如果 value 有 [[StringData]] 内部槽,则
设置 value 为 ? ToString (value )。
否则如果 value 有 [[BooleanData]] 内部槽,则
设置 value 为 value .[[BooleanData]] 。
否则如果 value 有 [[BigIntData]] 内部槽,则
设置 value 为 value .[[BigIntData]] 。
如果 value 是 null ,返回 "null" 。
如果 value 是 true ,返回 "true" 。
如果 value 是 false ,返回 "false" 。
如果 value 是字符串 ,返回
QuoteJSONString (value )。
如果 value 是数字 ,则
如果 value 是 有限 ,返回 ! ToString (value )。
返回 "null" 。
如果 value 是
BigInt ,抛出 TypeError 异常。
如果 value 是对象 且 IsCallable (value ) 为
false ,则
令 isArray 为 ? IsArray (value )。
如果 isArray 为 true ,返回 ? SerializeJSONArray (state ,
value )。
返回 ? SerializeJSONObject (state ,
value )。
返回 undefined 。
25.5.2.3 QuoteJSONString ( value )
抽象操作 QuoteJSONString 接收参数 value (字符串),返回一个字符串。该操作将 value 用
0x0022(引号)码元包裹,并对其中某些码元进行转义。该操作将 value 作为 UTF-16 编码的码点序列处理,详见 6.1.4 。调用时执行以下步骤:
令 product 为仅包含 0x0022(引号)的字符串。
对于 StringToCodePoints (value )
的每个码点 C ,执行
如果 C 在 表
81 “码点”列中,则
设置 product 为 product
与该表对应“转义序列”的拼接结果。
否则如果 C 的数值小于 0x0020(空格),或 C 数值等于 前导代理项 或 后继代理项 ,则
令 unit 为其数值等于 C 的码元。
设置 product 为 product 与
UnicodeEscape (unit )
的拼接结果。
否则,
设置 product 为 product 与
UTF16EncodeCodePoint (C )
的拼接结果。
设置 product 为 product 与 0x0022(引号)码元的拼接结果。
返回 product 。
表 81:JSON 单字符转义序列
码点
Unicode 字符名
转义序列
U+0008
BACKSPACE
\b
U+0009
CHARACTER TABULATION
\t
U+000A
LINE FEED (LF)
\n
U+000C
FORM FEED (FF)
\f
U+000D
CARRIAGE RETURN (CR)
\r
U+0022
QUOTATION MARK
\"
U+005C
REVERSE SOLIDUS
\\
25.5.2.4 UnicodeEscape ( C )
抽象操作 UnicodeEscape 接收参数 C (一个码元),返回一个字符串。它将 C 表示为 Unicode
转义序列。调用时执行以下步骤:
令 n 为 C 的数值。
断言 :
n ≤ 0xFFFF。
令 hex 为 n 的字符串表示,格式为小写十六进制数。
返回 0x005C(反斜杠)、"u" 和 StringPad (hex , 4,
"0" , start ) 的字符串拼接 结果。
25.5.2.5 SerializeJSONObject ( state ,
value )
抽象操作 SerializeJSONObject 接收参数 state (一个 JSON 序列化记录 )和
value (对象),返回 正常完成,包含 字符串,或
抛出完成 。它会对一个对象进行序列化。调用时执行以下步骤:
如果 state .[[Stack]] 包含 value ,则抛出
TypeError 异常,因为结构是循环的。
将 value 添加到 state .[[Stack]] 。
令 stepBack 为 state .[[Indent]] 。
设置 state .[[Indent]] 为 state .[[Indent]] 与 state .[[Gap]] 的字符串拼接 结果。
如果 state .[[PropertyList]] 不为
undefined ,则
令 K 为 state .[[PropertyList]] 。
否则,
令 K 为 ? EnumerableOwnProperties (value ,
key )。
令 partial 为新的空 List 。
对于 K 的每个元素 P ,执行
令 strP 为 ? SerializeJSONProperty (state ,
P , value )。
如果 strP 不为 undefined ,则
令 member 为 QuoteJSONString (P )。
设置 member 为 member 与 ":"
的字符串拼接 结果。
如果 state .[[Gap]] 不为空字符串,则
设置 member 为 member 与
0x0020(空格)的字符串拼接 结果。
设置 member 为 member 与 strP
的字符串拼接 结果。
将 member 添加到 partial 。
如果 partial 为空,则
令 final 为 "{}" 。
否则,
如果 state .[[Gap]] 为空字符串,则
令 properties 为将 partial 所有元素字符串用
0x002C(逗号)分隔拼接得到的字符串。逗号不出现在首尾。
令 final 为 字符串拼接
"{" 、properties 和
"}" 。
否则,
令 separator 为 0x002C(逗号)、0x000A(换行符)和
state .[[Indent]] 拼接的字符串。
令 properties 为将 partial 所有元素字符串用
separator 分隔拼接得到的字符串,不在首尾插入分隔符。
令 final 为 字符串拼接
"{" 、0x000A(换行)、
state .[[Indent]] 、properties 、0x000A(换行)、stepBack
和 "}" 的结果。
移除 state .[[Stack]] 的最后一个元素。
设置 state .[[Indent]] 为 stepBack 。
返回 final 。
25.5.2.6 SerializeJSONArray ( state , value
)
抽象操作 SerializeJSONArray 接收参数 state (JSON 序列化记录 )和
value (ECMAScript 语言值 ),返回 正常完成,包含 字符串,或
抛出完成 。它会对一个数组进行序列化。调用时执行以下步骤:
如果 state .[[Stack]] 包含 value ,则抛出
TypeError 异常,因为结构是循环的。
将 value 添加到 state .[[Stack]] 。
令 stepBack 为 state .[[Indent]] 。
设置 state .[[Indent]] 为 state .[[Indent]] 与 state .[[Gap]] 的字符串拼接 结果。
令 partial 为新的空 List 。
令 len 为 ? LengthOfArrayLike (value )。
令 index 为 0。
当 index < len 时重复,
令 strP 为 ? SerializeJSONProperty (state ,
! ToString (𝔽 (index )),
value )。
如果 strP 为 undefined ,则
将 "null" 添加到 partial 。
否则,
将 strP 添加到 partial 。
设置 index 为 index + 1。
如果 partial 为空,则
令 final 为 "[]" 。
否则,
如果 state .[[Gap]] 为空字符串,则
令 properties 为将 partial 所有元素字符串用
0x002C(逗号)分隔拼接得到的字符串。逗号不出现在首尾。
令 final 为 字符串拼接
"[" 、properties 和
"]" 。
否则,
令 separator 为 0x002C(逗号)、0x000A(换行符)和
state .[[Indent]] 拼接的字符串。
令 properties 为将 partial 所有元素字符串用
separator 分隔拼接得到的字符串,不在首尾插入分隔符。
令 final 为 字符串拼接
"[" 、0x000A(换行)、
state .[[Indent]] 、properties 、0x000A(换行)、stepBack
和 "]" 的结果。
移除 state .[[Stack]] 的最后一个元素。
设置 state .[[Indent]] 为 stepBack 。
返回 final 。
注
数组的表现形式只包括区间 interval
[+0 𝔽 , array.length
) 内的元素。键不是 数组索引
的属性不会被序列化。数组以左中括号开头,元素用逗号分隔,右中括号结尾。
25.5.3 JSON [ %Symbol.toStringTag% ]
%Symbol.toStringTag% 属性的初始值为字符串值
"JSON" 。
该属性具有属性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : true }.
26 内存管理
26.1 WeakRef 对象
WeakRef
是一种对象,可以引用目标对象或符号,但不会阻止其被垃圾回收。WeakRef 可以被解引用以访问目标值(如果目标尚未被垃圾回收)。
26.1.1 WeakRef 构造函数
WeakRef 构造函数 :
即 %WeakRef% 。
是 全局对象 的 "WeakRef" 属性的初始值。
作为构造函数 被调用时,创建并初始化一个新的 WeakRef。
不应作为函数调用,否则会抛出异常。
可以用作类定义的 extends
子句中的值。希望继承指定 WeakRef
行为的子类构造函数 ,必须包含对
WeakRef
构造函数 的 super
调用,以使用支持
WeakRef.prototype
内置方法所需的内部状态来创建和初始化子类实例。
26.1.1.1 WeakRef ( target )
该函数被调用时执行以下步骤:
如果 NewTarget 为 undefined ,抛出 TypeError 异常。
如果 CanBeHeldWeakly (target )
为 false ,抛出 TypeError 异常。
令 weakRef 为 ? OrdinaryCreateFromConstructor (NewTarget,
"%WeakRef.prototype%" , « [[WeakRefTarget]] »)。
执行 AddToKeptObjects (target )。
设置 weakRef .[[WeakRefTarget]] 为
target 。
返回 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 原型 对象:
26.1.3.1 WeakRef.prototype.constructor
WeakRef.prototype.constructor
的初始值为 %WeakRef% 。
该属性具有属性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : true }。
26.1.3.2 WeakRef.prototype.deref ( )
该方法被调用时执行以下步骤:
令 weakRef 为 this 值。
执行 ? RequireInternalSlot (weakRef ,
[[WeakRefTarget]] )。
返回 WeakRefDeref (weakRef )。
注
如果 WeakRef 返回的
target 值不为 undefined ,则该 target 值在本次
ECMAScript 代码执行完成前不会被垃圾回收。AddToKeptObjects 操作确保读取一致性。
let target = { foo ( ) {} };
let weakRef = new WeakRef (target);
if (weakRef.deref ()) {
weakRef.deref ().foo ();
}
在上述例子中,如果第一次 deref 的结果不是 undefined ,则第二次 deref 同样不会是
undefined 。
26.1.3.3 WeakRef.prototype [ %Symbol.toStringTag% ]
%Symbol.toStringTag% 属性的初始值为字符串值
"WeakRef" 。
该属性具有属性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : true }。
26.1.4 WeakRef 抽象操作
26.1.4.1 WeakRefDeref ( weakRef )
抽象操作 WeakRefDeref 接收参数 weakRef (一个 WeakRef ),返回一个
ECMAScript 语言值 。调用时执行以下步骤:
令 target 为 weakRef .[[WeakRefTarget]] 。
如果 target 不为 empty ,则
执行 AddToKeptObjects (target )。
返回 target 。
返回 undefined 。
注
该抽象操作与 WeakRef.prototype.deref 分开定义,目的是为了能够简洁地定义活性(liveness)。
26.1.5 WeakRef 实例的属性
WeakRef 实例是 普通对象 ,继承自
WeakRef
原型 。WeakRef 实例还具有 [[WeakRefTarget]] 内部槽。
26.2 FinalizationRegistry 对象
FinalizationRegistry
是用于管理目标对象和符号被垃圾回收时执行清理操作的注册与注销的对象。
26.2.1 FinalizationRegistry 构造函数
FinalizationRegistry 构造函数 :
即 %FinalizationRegistry% 。
是 "FinalizationRegistry" 属性在 全局对象 上的初始值。
作为构造函数 被调用时,创建并初始化一个新的 FinalizationRegistry。
不应作为函数调用,否则会抛出异常。
可以用作类定义的 extends
子句中的值。希望继承指定 FinalizationRegistry
行为的子类构造函数 ,必须包含对
FinalizationRegistry
构造函数 的 super
调用,以使用支持
FinalizationRegistry.prototype
内置方法所需的内部状态来创建和初始化子类实例。
26.2.1.1 FinalizationRegistry ( cleanupCallback )
该函数被调用时执行以下步骤:
如果 NewTarget 为 undefined ,抛出 TypeError 异常。
如果 IsCallable (cleanupCallback )
为 false ,抛出 TypeError 异常。
令 finalizationRegistry 为 ? OrdinaryCreateFromConstructor (NewTarget,
"%FinalizationRegistry.prototype%" , « [[Realm]] , [[CleanupCallback]] ,
[[Cells]] »)。
令 fn 为 当前函数对象 。
设置 finalizationRegistry .[[Realm]] 为
fn .[[Realm]] 。
设置 finalizationRegistry .[[CleanupCallback]] 为
HostMakeJobCallback (cleanupCallback )。
设置 finalizationRegistry .[[Cells]] 为新的空 List 。
返回 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 ] )
该方法被调用时执行以下步骤:
令 finalizationRegistry 为 this 值。
执行 ? RequireInternalSlot (finalizationRegistry ,
[[Cells]] )。
如果 CanBeHeldWeakly (target )
为 false ,抛出 TypeError 异常。
如果 SameValue (target ,
heldValue ) 为 true ,抛出 TypeError 异常。
如果 CanBeHeldWeakly (unregisterToken )
为 false ,则
如果 unregisterToken 不为 undefined ,抛出
TypeError 异常。
设置 unregisterToken 为 empty 。
令 cell 为 Record { [[WeakRefTarget]] : target , [[HeldValue]] : heldValue , [[UnregisterToken]] : unregisterToken }。
将 cell 添加到 finalizationRegistry .[[Cells]] 。
返回 undefined 。
注
根据本规范中的算法和定义,当 finalizationRegistry .[[Cells]] 包含
cell 时,cell .[[HeldValue]] 是 活跃 的;但这不一定意味着 cell .[[UnregisterToken]] 或 cell .[[Target]] 也是 活跃 的。例如,将对象注册为其自身的注销 token
并不会让该对象永远存活。
26.2.3.3 FinalizationRegistry.prototype.unregister (
unregisterToken )
该方法被调用时执行以下步骤:
令 finalizationRegistry 为 this 值。
执行 ? RequireInternalSlot (finalizationRegistry ,
[[Cells]] )。
如果 CanBeHeldWeakly (unregisterToken )
为 false ,抛出 TypeError 异常。
令 removed 为 false 。
对于 Record { [[WeakRefTarget]] , [[HeldValue]] ,
[[UnregisterToken]] } cell 属于
finalizationRegistry .[[Cells]] ,执行
如果 cell .[[UnregisterToken]] 不为
empty 且 SameValue (cell .[[UnregisterToken]] , unregisterToken ) 为
true ,则
从 finalizationRegistry .[[Cells]]
移除 cell 。
设置 removed 为 true 。
返回 removed 。
26.2.3.4 FinalizationRegistry.prototype [ %Symbol.toStringTag% ]
%Symbol.toStringTag% 属性的初始值为字符串值
"FinalizationRegistry" 。
该属性具有属性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : true }。
26.2.4 FinalizationRegistry 实例的属性
FinalizationRegistry 实例是
普通对象 ,继承自 FinalizationRegistry
原型 。FinalizationRegistry
实例还具有 [[Cells]] 和 [[CleanupCallback]] 内部槽。
27 控制抽象对象
27.1 迭代
27.1.1 通用迭代接口
接口是一组属性键 ,其关联的值符合特定规范。任何对象只要提供了接口规范描述的所有属性,即符合 该接口。接口本身不是一个独立的对象。可能有许多分别实现的对象都符合同一个接口。单个对象也可能符合多个接口。
27.1.1.1 可迭代接口
可迭代接口
包含 表 82 中描述的属性:
表 82:可迭代 接口必需属性
属性
值
要求
%Symbol.iterator%
一个返回迭代器对象 的函数
返回的对象必须符合迭代器接口 。
27.1.1.2 迭代器接口
实现迭代器接口 的对象必须包含 表 83
所描述的属性。这类对象也可以实现 表
84 所述的属性。
表 83:迭代器 接口必需属性
注 1
参数可以传递给 next
函数,但具体解释和有效性取决于目标迭代器。for-of
语句和其他常见的迭代器使用者不会传递任何参数,因此期望以这种方式被使用的迭代器对象必须能够处理被无参调用的情况。
表 84:迭代器 接口可选属性
注 2
通常调用这些方法前应先检查其是否存在。某些 ECMAScript 语言特性(包括
for
-of
、yield*
和数组解构)在调用这些方法前会做存在性检查。大多数接受
可迭代对象 作为参数的 ECMAScript
库函数也有条件地调用这些方法。
27.1.1.3 异步可迭代接口
异步可迭代接口 包含 表 85 所描述的属性:
表 85:异步 可迭代 接口必需属性
27.1.1.4 异步迭代器接口
实现异步迭代器接口 的对象必须包含 表 86
中的属性。这类对象也可以实现 表 87 所述的属性。
表 86:异步 迭代器 接口必需属性
注 1
参数可以传递给 next
函数,但具体解释和有效性取决于目标异步迭代器。for
-await
-of
语句和其他常见的异步迭代器使用者不会传递任何参数,因此期望以这种方式被使用的异步迭代器对象必须能够处理被无参调用的情况。
表 87:异步 迭代器 接口可选属性
属性
值
要求
"return"
一个返回 IteratorResult
对象 的 Promise 的函数
返回的 promise 被 fulfill 时,必须 fulfill 为一个符合 IteratorResult
接口 的对象。调用此方法通知 异步迭代器对象 ,调用者不打算再对该对象进行
next
方法调用。返回的 promise fulfill 为一个 IteratorResult
对象 ,其 "done" 属性值通常为
true ,"value" 属性为
return
方法参数的值。但该要求不强制执行。
此外,作为 fulfill 值的 IteratorResult
对象 的 "value" 属性值不应为
promise(或"thenable")。如果参数以典型方式使用,则若为拒绝的 promise,应返回一个相同原因拒绝的
promise;若为 fulfill 的 promise,则其 fulfill 值应作为返回 promise 的 IteratorResult
对象 的 "value"
属性值。但这些要求也不强制执行。
"throw"
一个返回 IteratorResult
对象 的 Promise 的函数
返回的 promise 被 fulfill 时,必须 fulfill 为一个符合 IteratorResult
接口 的对象。调用此方法通知 异步迭代器对象 ,调用者检测到错误条件。参数可用于标识错误,通常是异常对象。典型响应是返回一个拒绝的
promise,拒绝原因为参数值。
如果返回的 promise 被 fulfill,IteratorResult
对象 的 "done" 属性值通常为
true 。此外,其 "value" 属性值不应为
promise(或"thenable"),但该要求不强制执行。
注 2
通常调用这些方法前应先检查其是否存在。某些 ECMAScript 语言特性(包括
for
-await
-of
和
yield*
)在调用这些方法前会做存在性检查。
27.1.1.5 IteratorResult 接口
IteratorResult
接口 包含 表 88 中列出的属性:
表 88:IteratorResult 接口属性
属性
值
要求
"done"
一个布尔值
这是 迭代器
next
方法调用的结果状态。如果已到达 迭代器
末尾,"done" 为
true 。如果未到达末尾,"done" 为
false ,且有一个可用的值。如果不存在 "done"
属性(无论是自身还是继承),则视为值为 false 。
"value"
一个 ECMAScript
语言值
如果 done 为 false ,这是当前迭代元素的值。如果 done 为
true ,这是 迭代器
的返回值(如果有的话)。如果 迭代器
没有返回值,则 "value" 为
undefined 。在这种情况下,如果符合要求的对象没有继承到显式的
"value" 属性,则该属性可不存在。
27.1.2 迭代器辅助对象
迭代器辅助对象 是一个普通对象 ,表示某个特定源迭代器对象 的惰性变换。迭代器辅助对象没有命名的构造函数 。相反,迭代器辅助对象是通过调用某些Iterator 实例对象的方法创建的。
27.1.2.1 %IteratorHelperPrototype% 对象
%IteratorHelperPrototype% 对象:
27.1.2.1.1 %IteratorHelperPrototype%.next ( )
返回 ? GeneratorResume (this
值, undefined , "Iterator Helper" ).
27.1.2.1.2 %IteratorHelperPrototype%.return ( )
令 O 为 this 值。
执行 ? RequireInternalSlot (O ,
[[UnderlyingIterator]] ).
断言 :O 有一个 [[GeneratorState]] 内部槽。
如果 O .[[GeneratorState]] 为
suspended-start ,则
设置 O .[[GeneratorState]] 为
completed 。
注:一旦生成器进入 completed 状态,就不会再离开,并且其相关的执行上下文 不会被恢复。此时与
O 关联的所有执行状态都可以被丢弃。
执行 ? IteratorClose (O .[[UnderlyingIterator]] , NormalCompletion (unused )).
返回 CreateIteratorResultObject (undefined ,
true ).
令 C 为 ReturnCompletion (undefined ).
返回 ? GeneratorResumeAbrupt (O ,
C , "Iterator Helper" ).
27.1.2.1.3 %IteratorHelperPrototype% [ %Symbol.toStringTag%
]
%Symbol.toStringTag% 属性的初始值为字符串值
"Iterator Helper" 。
该属性具有属性 { [[Writable]] :
false , [[Enumerable]] :
false , [[Configurable]] :
true }.
27.1.3 迭代器对象
27.1.3.1 Iterator 构造函数
Iterator 构造函数 :
即 %Iterator% 。
是 全局对象 的 "Iterator"
属性的初始值。
设计为可被子类化。可用作类定义中 extends 子句的值。
27.1.3.1.1 Iterator ( )
该函数被调用时执行以下步骤:
如果 NewTarget 为 undefined 或 当前函数对象 ,抛出
TypeError 异常。
返回 ? OrdinaryCreateFromConstructor (NewTarget,
"%Iterator.prototype%" ).
27.1.3.2 Iterator 构造函数的属性
Iterator 构造函数 :
27.1.3.2.1 Iterator.from ( O )
令 iteratorRecord 为 ? GetIteratorFlattenable (O ,
iterate-string-primitives ).
令 hasInstance 为 ? OrdinaryHasInstance (%Iterator% ,
iteratorRecord .[[Iterator]] ).
如果 hasInstance 为 true ,则
返回 iteratorRecord .[[Iterator]] 。
令 wrapper 为 OrdinaryObjectCreate (%WrapForValidIteratorPrototype% ,
« [[Iterated]] »)。
设置 wrapper .[[Iterated]] 为
iteratorRecord 。
返回 wrapper 。
27.1.3.2.1.1 %WrapForValidIteratorPrototype% 对象
%WrapForValidIteratorPrototype% 对象:
27.1.3.2.1.1.1 %WrapForValidIteratorPrototype%.next
( )
令 O 为 this 值。
执行 ? RequireInternalSlot (O ,
[[Iterated]] ).
令 iteratorRecord 为 O .[[Iterated]] 。
返回 ? Call (iteratorRecord .[[NextMethod]] , iteratorRecord .[[Iterator]] ).
27.1.3.2.1.1.2
%WrapForValidIteratorPrototype%.return ( )
令 O 为 this 值。
执行 ? RequireInternalSlot (O ,
[[Iterated]] ).
令 iterator 为 O .[[Iterated]] .[[Iterator]] 。
断言 :iterator
是对象 。
令 returnMethod 为 ? GetMethod (iterator ,
"return" ).
如果 returnMethod 为 undefined ,则
返回 CreateIteratorResultObject (undefined ,
true ).
返回 ? Call (returnMethod ,
iterator ).
27.1.3.2.2 Iterator.prototype
Iterator.prototype 的初始值是 Iterator
原型对象 。
该属性具有属性 { [[Writable]] :
false , [[Enumerable]] :
false , [[Configurable]] :
false }.
27.1.4 Iterator 原型对象的属性
Iterator 原型对象 :
注
本规范中所有实现了 迭代器接口 的对象都继承自
%Iterator.prototype%。ECMAScript 代码也可以定义继承自 %Iterator.prototype% 的对象。%Iterator.prototype%
提供了一个可为所有 迭代器对象 添加通用方法的位置。
以下表达式是 ECMAScript 代码访问 %Iterator.prototype% 对象的一种方式:
Object .getPrototypeOf (Object .getPrototypeOf ([][Symbol .iterator ]()))
27.1.4.1 Iterator.prototype.constructor
Iterator.prototype.constructor
是一个 访问器属性 ,属性为 { [[Enumerable]] : false , [[Configurable]] : true }。[[Get]] 和 [[Set]] 属性定义如下:
27.1.4.1.1 get Iterator.prototype.constructor
[[Get]] 属性值为一个不带参数的内置函数。被调用时执行以下步骤:
返回 %Iterator% 。
27.1.4.1.2 set Iterator.prototype.constructor
[[Set]] 属性值为一个带参数 v 的内置函数。被调用时执行以下步骤:
执行 ? SetterThatIgnoresPrototypeProperties (this
值, %Iterator.prototype% ,
"constructor" , v ).
返回 undefined 。
注
与大多数内置原型上的 "constructor" 属性不同,出于 Web 兼容性原因,该属性必须为访问器属性。
27.1.4.2 Iterator.prototype.drop ( limit )
该方法被调用时执行以下步骤:
令 O 为 this 值。
如果 O 不是对象 ,抛出 TypeError
异常。
令 iterated 为 迭代器记录 {
[[Iterator]] : O , [[NextMethod]] : undefined , [[Done]] : false }.
令 numLimit 为 Completion (ToNumber (limit ))。
IfAbruptCloseIterator (numLimit ,
iterated ).
如果 numLimit 是 NaN ,则
令 error 为 ThrowCompletion (新建的
RangeError 对象)。
返回 ? IteratorClose (iterated ,
error ).
令 integerLimit 为 ! ToIntegerOrInfinity (numLimit )。
如果 integerLimit < 0,则
令 error 为 ThrowCompletion (新建的
RangeError 对象)。
返回 ? IteratorClose (iterated ,
error ).
设置 iterated 为 ? GetIteratorDirect (O )。
令 closure 为一个新的 抽象闭包 ,无参数,捕获 iterated
和 integerLimit ,被调用时执行以下步骤:
令 remaining 为 integerLimit 。
当 remaining > 0 时重复:
如果 remaining ≠ +∞,则
设置 remaining 为 remaining - 1。
令 next 为 ? IteratorStep (iterated )。
如果 next 为 done ,返回 ReturnCompletion (undefined )。
重复:
令 value 为 ? IteratorStepValue (iterated )。
如果 value 为 done ,返回 ReturnCompletion (undefined )。
令 completion 为 Completion (Yield (value ))。
IfAbruptCloseIterator (completion ,
iterated )。
令 result 为 CreateIteratorFromClosure (closure ,
"Iterator Helper" , %IteratorHelperPrototype% ,
« [[UnderlyingIterator]] »)。
设置 result .[[UnderlyingIterator]] 为
iterated 。
返回 result 。
27.1.4.3 Iterator.prototype.every ( predicate )
该方法被调用时执行以下步骤:
令 O 为 this 值。
如果 O 不是对象 ,抛出 TypeError
异常。
令 iterated 为 迭代器记录 {
[[Iterator]] : O , [[NextMethod]] : undefined , [[Done]] : false }.
如果 IsCallable (predicate ) 为
false ,则
令 error 为 ThrowCompletion (新建的
TypeError 对象)。
返回 ? IteratorClose (iterated ,
error ).
设置 iterated 为 ? GetIteratorDirect (O )。
令 counter 为 0。
重复:
令 value 为 ? IteratorStepValue (iterated )。
如果 value 为 done ,返回
true 。
令 result 为 Completion (Call (predicate ,
undefined , « value , 𝔽 (counter ) »))。
IfAbruptCloseIterator (result ,
iterated )。
如果 ToBoolean (result ) 为
false ,返回 ? IteratorClose (iterated ,
NormalCompletion (false ))。
设置 counter 为 counter + 1。
27.1.4.4 Iterator.prototype.filter ( predicate )
该方法被调用时执行以下步骤:
令 O 为 this 值。
如果 O 不是对象 ,抛出 TypeError
异常。
令 iterated 为 迭代器记录 {
[[Iterator]] : O , [[NextMethod]] : undefined , [[Done]] : false }.
如果 IsCallable (predicate ) 为
false ,则
令 error 为 ThrowCompletion (新建的
TypeError 对象)。
返回 ? IteratorClose (iterated ,
error ).
设置 iterated 为 ? GetIteratorDirect (O )。
令 closure 为一个新的 抽象闭包 ,无参数,捕获 iterated
和 predicate ,被调用时执行以下步骤:
令 counter 为 0。
重复:
令 value 为 ? IteratorStepValue (iterated )。
如果 value 为 done ,返回 ReturnCompletion (undefined )。
令 selected 为 Completion (Call (predicate ,
undefined , « value , 𝔽 (counter ) »))。
IfAbruptCloseIterator (selected ,
iterated )。
如果 ToBoolean (selected )
为 true ,则
令 completion 为 Completion (Yield (value ))。
IfAbruptCloseIterator (completion ,
iterated )。
设置 counter 为 counter + 1。
令 result 为 CreateIteratorFromClosure (closure ,
"Iterator Helper" , %IteratorHelperPrototype% ,
« [[UnderlyingIterator]] »)。
设置 result .[[UnderlyingIterator]] 为
iterated 。
返回 result 。
27.1.4.5 Iterator.prototype.find ( predicate )
该方法被调用时执行以下步骤:
令 O 为 this 值。
如果 O 不是对象 ,抛出 TypeError
异常。
令 iterated 为 迭代器记录 {
[[Iterator]] : O , [[NextMethod]] : undefined , [[Done]] : false }.
如果 IsCallable (predicate ) 为
false ,则
令 error 为 ThrowCompletion (新建的
TypeError 对象)。
返回 ? IteratorClose (iterated ,
error ).
设置 iterated 为 ? GetIteratorDirect (O )。
令 counter 为 0。
重复:
令 value 为 ? IteratorStepValue (iterated )。
如果 value 为 done ,返回
undefined 。
令 result 为 Completion (Call (predicate ,
undefined , « value , 𝔽 (counter ) »))。
IfAbruptCloseIterator (result ,
iterated )。
如果 ToBoolean (result ) 为
true ,返回 ? IteratorClose (iterated ,
NormalCompletion (value ))。
设置 counter 为 counter + 1。
27.1.4.6 Iterator.prototype.flatMap ( mapper )
该方法被调用时执行以下步骤:
令 O 为 this 值。
如果 O 不是对象 ,抛出 TypeError
异常。
令 iterated 为 迭代器记录 {
[[Iterator]] : O , [[NextMethod]] : undefined , [[Done]] : false }.
如果 IsCallable (mapper ) 为
false ,则
令 error 为 ThrowCompletion (新建的
TypeError 对象)。
返回 ? IteratorClose (iterated ,
error ).
设置 iterated 为 ? GetIteratorDirect (O )。
令 closure 为一个新的 抽象闭包 ,无参数,捕获 iterated
和 mapper ,被调用时执行以下步骤:
令 counter 为 0。
重复:
令 value 为 ? IteratorStepValue (iterated )。
如果 value 为 done ,返回 ReturnCompletion (undefined )。
令 mapped 为 Completion (Call (mapper ,
undefined , « value , 𝔽 (counter ) »))。
IfAbruptCloseIterator (mapped ,
iterated )。
令 innerIterator 为 Completion (GetIteratorFlattenable (mapped ,
reject-primitives ))。
IfAbruptCloseIterator (innerIterator ,
iterated )。
令 innerAlive 为 true 。
当 innerAlive 为 true 时重复:
令 innerValue 为 Completion (IteratorStepValue (innerIterator ))。
IfAbruptCloseIterator (innerValue ,
iterated )。
如果 innerValue 为 done ,则
设置 innerAlive 为
false 。
否则,
令 completion 为 Completion (Yield (innerValue ))。
如果 completion 是 abrupt
completion ,则
令 backupCompletion 为 Completion (IteratorClose (innerIterator ,
completion ))。
IfAbruptCloseIterator (backupCompletion ,
iterated )。
返回 ? IteratorClose (iterated ,
completion )。
设置 counter 为 counter + 1。
令 result 为 CreateIteratorFromClosure (closure ,
"Iterator Helper" , %IteratorHelperPrototype% ,
« [[UnderlyingIterator]] »)。
设置 result .[[UnderlyingIterator]] 为
iterated 。
返回 result 。
27.1.4.7 Iterator.prototype.forEach ( procedure )
该方法被调用时执行以下步骤:
令 O 为 this 值。
如果 O 不是对象 ,抛出 TypeError
异常。
令 iterated 为 迭代器记录 {
[[Iterator]] : O , [[NextMethod]] : undefined , [[Done]] : false }.
如果 IsCallable (procedure ) 为
false ,则
令 error 为 ThrowCompletion (新建的
TypeError 对象)。
返回 ? IteratorClose (iterated ,
error ).
设置 iterated 为 ? GetIteratorDirect (O )。
令 counter 为 0。
重复:
令 value 为 ? IteratorStepValue (iterated )。
如果 value 为 done ,返回
undefined 。
令 result 为 Completion (Call (procedure ,
undefined , « value , 𝔽 (counter ) »))。
IfAbruptCloseIterator (result ,
iterated )。
设置 counter 为 counter + 1。
27.1.4.8 Iterator.prototype.map ( mapper )
该方法被调用时执行以下步骤:
令 O 为 this 值。
如果 O 不是对象 ,抛出 TypeError
异常。
令 iterated 为 迭代器记录 {
[[Iterator]] : O , [[NextMethod]] : undefined , [[Done]] : false }.
如果 IsCallable (mapper ) 为
false ,则
令 error 为 ThrowCompletion (新建的
TypeError 对象)。
返回 ? IteratorClose (iterated ,
error ).
设置 iterated 为 ? GetIteratorDirect (O )。
令 closure 为一个新的 抽象闭包 ,无参数,捕获 iterated
和 mapper ,被调用时执行以下步骤:
令 counter 为 0。
重复:
令 value 为 ? IteratorStepValue (iterated )。
如果 value 为 done ,返回 ReturnCompletion (undefined )。
令 mapped 为 Completion (Call (mapper ,
undefined , « value , 𝔽 (counter ) »))。
IfAbruptCloseIterator (mapped ,
iterated )。
令 completion 为 Completion (Yield (mapped ))。
IfAbruptCloseIterator (completion ,
iterated )。
设置 counter 为 counter + 1。
令 result 为 CreateIteratorFromClosure (closure ,
"Iterator Helper" , %IteratorHelperPrototype% ,
« [[UnderlyingIterator]] »)。
设置 result .[[UnderlyingIterator]] 为
iterated 。
返回 result 。
27.1.4.9 Iterator.prototype.reduce ( reducer [ ,
initialValue ] )
该方法被调用时执行以下步骤:
令 O 为 this 值。
如果 O 不是对象 ,抛出 TypeError
异常。
令 iterated 为 迭代器记录 {
[[Iterator]] : O , [[NextMethod]] : undefined , [[Done]] : false }.
如果 IsCallable (reducer ) 为
false ,则
令 error 为 ThrowCompletion (新建的
TypeError 对象)。
返回 ? IteratorClose (iterated ,
error ).
设置 iterated 为 ? GetIteratorDirect (O )。
如果 initialValue 未传入,则
令 accumulator 为 ? IteratorStepValue (iterated )。
如果 accumulator 为 done ,抛出
TypeError 异常。
令 counter 为 1。
否则,
令 accumulator 为 initialValue 。
令 counter 为 0。
重复,
令 value 为 ? IteratorStepValue (iterated )。
如果 value 为 done ,返回
accumulator 。
令 result 为 Completion (Call (reducer ,
undefined , « accumulator , value ,
𝔽 (counter ) »))。
IfAbruptCloseIterator (result ,
iterated )。
设置 accumulator 为 result 。
设置 counter 为 counter + 1。
27.1.4.10 Iterator.prototype.some ( predicate )
该方法被调用时执行以下步骤:
令 O 为 this 值。
如果 O 不是对象 ,抛出 TypeError
异常。
令 iterated 为 迭代器记录 {
[[Iterator]] : O , [[NextMethod]] : undefined , [[Done]] : false }.
如果 IsCallable (predicate ) 为
false ,则
令 error 为 ThrowCompletion (新建的
TypeError 对象)。
返回 ? IteratorClose (iterated ,
error ).
设置 iterated 为 ? GetIteratorDirect (O )。
令 counter 为 0。
重复,
令 value 为 ? IteratorStepValue (iterated )。
如果 value 为 done ,返回
false 。
令 result 为 Completion (Call (predicate ,
undefined , « value , 𝔽 (counter ) »))。
IfAbruptCloseIterator (result ,
iterated )。
如果 ToBoolean (result ) 为
true ,返回 ? IteratorClose (iterated ,
NormalCompletion (true ))。
设置 counter 为 counter + 1。
27.1.4.11 Iterator.prototype.take ( limit )
该方法被调用时执行以下步骤:
令 O 为 this 值。
如果 O 不是对象 ,抛出 TypeError
异常。
令 iterated 为 迭代器记录 {
[[Iterator]] : O , [[NextMethod]] : undefined , [[Done]] : false }.
令 numLimit 为 Completion (ToNumber (limit ))。
IfAbruptCloseIterator (numLimit ,
iterated )。
如果 numLimit 为 NaN ,则
令 error 为 ThrowCompletion (新建的
RangeError 对象)。
返回 ? IteratorClose (iterated ,
error )。
令 integerLimit 为 ! ToIntegerOrInfinity (numLimit )。
如果 integerLimit < 0,则
令 error 为 ThrowCompletion (新建的
RangeError 对象)。
返回 ? IteratorClose (iterated ,
error )。
设置 iterated 为 ? GetIteratorDirect (O )。
令 closure 为一个新的 抽象闭包 ,无参数,捕获 iterated
和 integerLimit ,被调用时执行以下步骤:
令 remaining 为 integerLimit 。
重复,
如果 remaining = 0,则
返回 ? IteratorClose (iterated ,
ReturnCompletion (undefined ))。
如果 remaining ≠ +∞,则
设置 remaining 为 remaining - 1。
令 value 为 ? IteratorStepValue (iterated )。
如果 value 为 done ,返回 ReturnCompletion (undefined )。
令 completion 为 Completion (Yield (value ))。
IfAbruptCloseIterator (completion ,
iterated )。
令 result 为 CreateIteratorFromClosure (closure ,
"Iterator Helper" , %IteratorHelperPrototype% ,
« [[UnderlyingIterator]] »)。
设置 result .[[UnderlyingIterator]] 为
iterated 。
返回 result 。
27.1.4.12 Iterator.prototype.toArray ( )
该方法被调用时执行以下步骤:
令 O 为 this 值。
如果 O 不是对象 ,抛出 TypeError
异常。
令 iterated 为 ? GetIteratorDirect (O )。
令 items 为一个新的空 List 。
重复,
令 value 为 ? IteratorStepValue (iterated )。
如果 value 为 done ,返回 CreateArrayFromList (items )。
将 value 添加到 items 。
27.1.4.13 Iterator.prototype [ %Symbol.iterator% ] ( )
该函数被调用时执行以下步骤:
返回 this 值。
该函数的 "name" 属性值为 "[Symbol.iterator]" 。
27.1.4.14 Iterator.prototype [ %Symbol.toStringTag% ]
Iterator.prototype[%Symbol.toStringTag%]
是一个 访问器属性 ,属性为 { [[Enumerable]] : false , [[Configurable]] : true }。[[Get]] 和 [[Set]] 属性定义如下:
27.1.4.14.1 get Iterator.prototype [ %Symbol.toStringTag% ]
[[Get]] 属性值为一个不带参数的内置函数。被调用时执行以下步骤:
返回 "Iterator" 。
27.1.4.14.2 set Iterator.prototype [ %Symbol.toStringTag% ]
[[Set]] 属性值为一个带参数 v 的内置函数。被调用时执行以下步骤:
执行 ? SetterThatIgnoresPrototypeProperties (this
值, %Iterator.prototype% ,
%Symbol.toStringTag% ,
v )。
返回 undefined 。
注
与大多数内置原型上的 %Symbol.toStringTag% 属性不同,出于
Web 兼容性原因,该属性必须为访问器属性。
27.1.5 %AsyncIteratorPrototype% 对象
%AsyncIteratorPrototype% 对象:
注
本规范中所有实现了 异步迭代器接口 的对象也都继承自
%AsyncIteratorPrototype%。ECMAScript 代码也可以定义继承自 %AsyncIteratorPrototype%
的对象。%AsyncIteratorPrototype% 对象为所有 异步迭代器对象
提供一个可添加通用方法的位置。
27.1.5.1 %AsyncIteratorPrototype% [ %Symbol.asyncIterator% ] ( )
该函数被调用时执行以下步骤:
返回 this 值。
该函数的 "name" 属性值为 "[Symbol.asyncIterator]" 。
27.1.6 从同步到异步的迭代器对象
从同步到异步的迭代器对象 是一种异步迭代器 ,用于适配某个特定的同步 迭代器 。从同步到异步的迭代器对象永远不会被 ECMAScript
代码直接访问。没有命名的 构造函数 用于从同步到异步的迭代器对象。相反,这些对象是通过 CreateAsyncFromSyncIterator
抽象操作在需要时创建的。
27.1.6.1 CreateAsyncFromSyncIterator (
syncIteratorRecord )
抽象操作 CreateAsyncFromSyncIterator 接收参数
syncIteratorRecord (一个 迭代器记录 ),并返回一个迭代器记录 。它用于从同步迭代器记录 创建一个异步迭代器记录 。调用时执行以下步骤:
令 asyncIterator 为 OrdinaryObjectCreate (%AsyncFromSyncIteratorPrototype% ,
« [[SyncIteratorRecord]] »)。
设置 asyncIterator .[[SyncIteratorRecord]] 为
syncIteratorRecord 。
令 nextMethod 为 ! Get (asyncIterator ,
"next" )。
令 iteratorRecord 为 迭代器记录 {
[[Iterator]] : asyncIterator , [[NextMethod]] : nextMethod , [[Done]] : false }。
返回 iteratorRecord 。
27.1.6.2 %AsyncFromSyncIteratorPrototype% 对象
%AsyncFromSyncIteratorPrototype% 对象:
27.1.6.2.1 %AsyncFromSyncIteratorPrototype%.next ( [
value ] )
令 O 为 this 值。
断言 :O 是一个对象 ,且有 [[SyncIteratorRecord]] 内部槽。
令 promiseCapability 为 ! NewPromiseCapability (%Promise% )。
令 syncIteratorRecord 为 O .[[SyncIteratorRecord]] 。
如果 value 存在,则
令 result 为 Completion (IteratorNext (syncIteratorRecord ,
value ))。
否则,
令 result 为 Completion (IteratorNext (syncIteratorRecord ))。
IfAbruptRejectPromise (result ,
promiseCapability )。
返回 AsyncFromSyncIteratorContinuation (result ,
promiseCapability , syncIteratorRecord ,
true )。
27.1.6.2.2 %AsyncFromSyncIteratorPrototype%.return ( [
value ] )
令 O 为 this 值。
断言 :O 是对象 ,且有 [[SyncIteratorRecord]] 内部槽。
令 promiseCapability 为 ! NewPromiseCapability (%Promise% )。
令 syncIteratorRecord 为 O .[[SyncIteratorRecord]] 。
令 syncIterator 为 syncIteratorRecord .[[Iterator]] 。
令 return 为 Completion (GetMethod (syncIterator ,
"return" ))。
IfAbruptRejectPromise (return ,
promiseCapability )。
如果 return 为 undefined ,则
令 iteratorResult 为 CreateIteratorResultObject (value ,
true )。
执行 ! Call (promiseCapability .[[Resolve]] , undefined , «
iteratorResult »)。
返回 promiseCapability .[[Promise]] 。
如果 value 存在,则
令 result 为 Completion (Call (return ,
syncIterator , « value »))。
否则,
令 result 为 Completion (Call (return ,
syncIterator ))。
IfAbruptRejectPromise (result ,
promiseCapability )。
如果 result 不是对象 ,则
执行 ! Call (promiseCapability .[[Reject]] , undefined , « 新建的
TypeError 对象 »)。
返回 promiseCapability .[[Promise]] 。
返回 AsyncFromSyncIteratorContinuation (result ,
promiseCapability , syncIteratorRecord ,
false )。
27.1.6.2.3 %AsyncFromSyncIteratorPrototype%.throw ( [
value ] )
注
令 O 为 this 值。
断言 :O 是对象 ,且有 [[SyncIteratorRecord]] 内部槽。
令 promiseCapability 为 ! NewPromiseCapability (%Promise% )。
令 syncIteratorRecord 为 O .[[SyncIteratorRecord]] 。
令 syncIterator 为 syncIteratorRecord .[[Iterator]] 。
令 throw 为 Completion (GetMethod (syncIterator ,
"throw" ))。
IfAbruptRejectPromise (throw ,
promiseCapability )。
如果 throw 为 undefined ,则
注:如果 syncIterator 没有 throw
方法,需要关闭它以便其有机会清理后再拒绝能力。
令 closeCompletion 为 NormalCompletion (empty )。
令 result 为 Completion (IteratorClose (syncIteratorRecord ,
closeCompletion ))。
IfAbruptRejectPromise (result ,
promiseCapability )。
注:下一步抛出 TypeError ,以表明协议违规:syncIterator 没有
throw
方法。
注:如果关闭 syncIterator 没有抛出,则忽略该操作结果,即使它产生了拒绝的 promise。
执行 ! Call (promiseCapability .[[Reject]] , undefined , « 新建的
TypeError 对象 »)。
返回 promiseCapability .[[Promise]] 。
如果 value 存在,则
令 result 为 Completion (Call (throw ,
syncIterator , « value »))。
否则,
令 result 为 Completion (Call (throw ,
syncIterator ))。
IfAbruptRejectPromise (result ,
promiseCapability )。
如果 result 不是对象 ,则
执行 ! Call (promiseCapability .[[Reject]] , undefined , « 新建的
TypeError 对象 »)。
返回 promiseCapability .[[Promise]] 。
返回 AsyncFromSyncIteratorContinuation (result ,
promiseCapability , syncIteratorRecord ,
true )。
27.1.6.3 从同步到异步的迭代器实例的属性
从同步到异步的 迭代器 实例是普通对象 ,继承自 %AsyncFromSyncIteratorPrototype%
本征对象。从同步到异步的 迭代器 实例最初创建时包含 表 89 所列的内部槽。
表 89:从同步到异步 迭代器 实例的内部槽
内部槽
类型
描述
[[SyncIteratorRecord]]
一个 迭代器记录
表示被适配的原始同步 迭代器 。
27.1.6.4 AsyncFromSyncIteratorContinuation ( result ,
promiseCapability , syncIteratorRecord , closeOnRejection )
抽象操作 AsyncFromSyncIteratorContinuation 接收参数 result
(一个对象)、promiseCapability (一个 PromiseCapability
记录 ,用于本征%Promise% )、syncIteratorRecord (一个迭代器记录 )、closeOnRejection (布尔值),并返回一个
Promise。调用时执行以下步骤:
注:由于 promiseCapability 来源于本征 %Promise% ,所以下文
IfAbruptRejectPromise 所导致的
promiseCapability .[[Reject]] 调用保证不会抛出异常。
令 done 为 Completion (IteratorComplete (result ))。
IfAbruptRejectPromise (done ,
promiseCapability )。
令 value 为 Completion (IteratorValue (result ))。
IfAbruptRejectPromise (value ,
promiseCapability )。
令 valueWrapper 为 Completion (PromiseResolve (%Promise% ,
value ))。
如果 valueWrapper 是 异常完成 ,done
为 false ,且 closeOnRejection 为 true ,则
将 valueWrapper 设为 Completion (IteratorClose (syncIteratorRecord ,
valueWrapper ))。
IfAbruptRejectPromise (valueWrapper ,
promiseCapability )。
令 unwrap 为一个新的 抽象闭包 ,参数为 (v ),捕获
done ,被调用时执行以下步骤:
返回 CreateIteratorResultObject (v ,
done )。
令 onFulfilled 为 CreateBuiltinFunction (unwrap ,
1, "" , « »)。
注:onFulfilled 用于处理 IteratorResult
对象 的 "value" 属性,以便在其为 promise
时等待并重新包装为“解包后”的 IteratorResult 对象 。
如果 done 为 true ,或 closeOnRejection 为
false ,则
令 onRejected 为 undefined 。
否则,
令 closeIterator 为一个新的 抽象闭包 ,参数为
(error ),捕获 syncIteratorRecord ,被调用时执行以下步骤:
返回 ? IteratorClose (syncIteratorRecord ,
ThrowCompletion (error ))。
令 onRejected 为 CreateBuiltinFunction (closeIterator ,
1, "" , « »)。
注:onRejected 用于在 IteratorResult
对象 的 "value" 属性为拒绝的 promise 时关闭
迭代器 。
执行 PerformPromiseThen (valueWrapper ,
onFulfilled , onRejected , promiseCapability )。
返回 promiseCapability .[[Promise]] 。
27.2 Promise 对象
Promise 是一个用于占位最终延迟(且可能是异步)计算结果的对象。
任何 Promise 都处于三种互斥状态之一:已兑现 、已拒绝 和 待定 :
如果 promise p
已兑现,则 p.then(f, r)
会立即入队一个 作业(Job) 调用函数 f
。
如果 promise p
已拒绝,则 p.then(f, r)
会立即入队一个 作业(Job) 调用函数 r
。
如果 promise 既未兑现也未拒绝,则为待定状态。
如果 promise 不是待定的,即已兑现或已拒绝,则称其为已定型(settled) 。
如果 promise 已定型,或已经“锁定”为与另一个 promise 状态一致,则称其为已解决(resolved) 。尝试解决或拒绝一个已解决的 promise
无效。未解决(unresolved )的 promise 即为未 resolved 的 promise。未解决的 promise 总是处于待定状态。已解决的 promise
可以是待定、已兑现或已拒绝状态。
27.2.1 Promise 抽象操作
27.2.1.1 PromiseCapability 记录
PromiseCapability 记录 是用于封装一个
Promise 或类 Promise 对象及其可解决或拒绝该 promise 的函数的记录(Record) 值。PromiseCapability
记录由 NewPromiseCapability 抽象操作生成。
PromiseCapability 记录拥有 表 90 所列字段。
表 90:PromiseCapability
记录 字段
字段名
值
含义
[[Promise]]
一个对象
可用作 promise 的对象。
[[Resolve]]
一个 函数对象
用于解决该 promise 的函数。
[[Reject]]
一个 函数对象
用于拒绝该 promise 的函数。
27.2.1.1.1 IfAbruptRejectPromise ( value ,
capability )
IfAbruptRejectPromise 是一组使用 PromiseCapability
记录 的算法步骤的简写。以下算法步骤:
IfAbruptRejectPromise (value ,
capability ).
等价于:
断言 :value 是一个Completion
Record 。
如果 value 是 异常完成 ,则
执行 ? Call (capability .[[Reject]] , undefined , «
value .[[Value]] »)。
返回 capability .[[Promise]] 。
否则,
将 value 设为 ! value 。
27.2.1.2 PromiseReaction 记录
PromiseReaction 记录 是一个
记录(Record) 值,用于存储当
promise 被以某个值解决(resolve)或拒绝(reject)时应如何响应的信息。PromiseReaction 记录由 PerformPromiseThen 抽象操作创建,并被 抽象闭包(Abstract Closure) (由 NewPromiseReactionJob 返回)使用。
PromiseReaction 记录具有 表 91 中列出的字段:
表 91:PromiseReaction 记录
字段
字段名
值
含义
[[Capability]]
一个 PromiseCapability
记录 或 undefined
此记录为其提供响应处理器(reaction handler)的 promise 的能力。
[[Type]]
fulfill 或 reject
当 [[Handler]] 为 empty
时,[[Type]] 用于指定与定型类型相关的行为。
[[Handler]]
一个 JobCallback 记录 或
empty
应应用于传入值的函数,其返回值决定派生 promise 的后续处理。如果 [[Handler]] 为 empty ,则会根据
[[Type]] 的值采用不同的函数。
27.2.1.3 CreateResolvingFunctions ( promise )
抽象操作 CreateResolvingFunctions 接收参数 promise (一个 Promise),并返回一个包含 [[Resolve]] (函数对象 ) 和 [[Reject]] (函数对象 )字段的 记录(Record) 。调用时执行以下步骤:
令 alreadyResolved 为 记录 { [[Value]] : false }。
令 stepsResolve 为 Promise Resolve
Functions 中定义的算法步骤。
令 lengthResolve 为 Promise Resolve
Functions 函数定义的非可选参数数量。
令 resolve 为 CreateBuiltinFunction (stepsResolve ,
lengthResolve , "" , « [[Promise]] , [[AlreadyResolved]] »)。
设置 resolve .[[Promise]] 为 promise 。
设置 resolve .[[AlreadyResolved]] 为
alreadyResolved 。
令 stepsReject 为 Promise Reject
Functions 中定义的算法步骤。
令 lengthReject 为 Promise Reject
Functions 函数定义的非可选参数数量。
令 reject 为 CreateBuiltinFunction (stepsReject ,
lengthReject , "" , « [[Promise]] , [[AlreadyResolved]] »)。
设置 reject .[[Promise]] 为 promise 。
设置 reject .[[AlreadyResolved]] 为
alreadyResolved 。
返回 记录 { [[Resolve]] : resolve , [[Reject]] : reject }。
27.2.1.3.1 Promise Reject Functions
promise reject 函数是一个匿名内置函数,具有 [[Promise]] 和 [[AlreadyResolved]] 内部槽。
当用参数 reason 调用 promise reject 函数时,执行以下步骤:
令 F 为 当前函数对象 。
断言 :F 有一个 [[Promise]] 内部槽,且其值 是对象 。
令 promise 为 F .[[Promise]] 。
令 alreadyResolved 为 F .[[AlreadyResolved]] 。
如果 alreadyResolved .[[Value]] 为
true ,返回 undefined 。
设置 alreadyResolved .[[Value]] 为
true 。
执行 RejectPromise (promise ,
reason )。
返回 undefined 。
promise reject 函数的 "length" 属性值为 1 𝔽 。
27.2.1.3.2 Promise Resolve Functions
promise resolve 函数是一个匿名内置函数,具有 [[Promise]] 和 [[AlreadyResolved]] 内部槽。
当用参数 resolution 调用 promise resolve 函数时,执行以下步骤:
令 F 为 当前函数对象 。
断言 :F 有一个 [[Promise]] 内部槽,且其值 是对象 。
令 promise 为 F .[[Promise]] 。
令 alreadyResolved 为 F .[[AlreadyResolved]] 。
如果 alreadyResolved .[[Value]] 为
true ,返回 undefined 。
设置 alreadyResolved .[[Value]] 为
true 。
如果 SameValue (resolution ,
promise ) 为 true ,则
令 selfResolutionError 为新建的 TypeError 对象。
执行 RejectPromise (promise ,
selfResolutionError )。
返回 undefined 。
如果 resolution 不是对象 ,则
执行 FulfillPromise (promise ,
resolution )。
返回 undefined 。
令 then 为 Completion (Get (resolution ,
"then" ))。
如果 then 是 异常完成 ,则
执行 RejectPromise (promise ,
then .[[Value]] )。
返回 undefined 。
令 thenAction 为 then .[[Value]] 。
如果 IsCallable (thenAction )
为 false ,则
执行 FulfillPromise (promise ,
resolution )。
返回 undefined 。
令 thenJobCallback 为 HostMakeJobCallback (thenAction )。
令 job 为 NewPromiseResolveThenableJob (promise ,
resolution , thenJobCallback )。
执行 HostEnqueuePromiseJob (job .[[Job]] , job .[[Realm]] )。
返回 undefined 。
promise resolve 函数的 "length" 属性值为 1 𝔽 。
27.2.1.4 FulfillPromise ( promise , value )
抽象操作 FulfillPromise 接收参数 promise (一个 Promise)和
value (一个 ECMAScript 语言值 ),返回
unused 。调用时执行以下步骤:
断言 :
promise .[[PromiseState]] 的值为
pending 。
令 reactions 为 promise .[[PromiseFulfillReactions]] 。
设置 promise .[[PromiseResult]] 为
value 。
设置 promise .[[PromiseFulfillReactions]] 为
undefined 。
设置 promise .[[PromiseRejectReactions]] 为
undefined 。
设置 promise .[[PromiseState]] 为
fulfilled 。
执行 TriggerPromiseReactions (reactions ,
value )。
返回 unused 。
27.2.1.5 NewPromiseCapability ( C )
抽象操作 NewPromiseCapability 接收参数 C (一个 ECMAScript 语言值 ),
返回一个 正常完成(normal completion)
包含 的 PromiseCapability
记录 或 抛出完成(throw
completion) 。它尝试将 C 作为 构造函数 ,以内置 Promise 构造函数 的方式,创建一个
promise 并提取其
resolve
和 reject
函数。promise 加上 resolve
和
reject
函数用于初始化一个新的
PromiseCapability 记录 。调用时执行以下步骤:
如果 IsConstructor (C ) 为
false ,抛出 TypeError 异常。
注:C 假设为一个 构造函数 ,且支持 Promise 构造函数
的参数约定(参见 27.2.3.1 )。
令 resolvingFunctions 为 记录 { [[Resolve]] : undefined , [[Reject]] : undefined }。
令 executorClosure 为一个新的 抽象闭包 ,
参数为 (resolve , reject ),捕获
resolvingFunctions ,调用时执行以下步骤:
如果 resolvingFunctions .[[Resolve]] 不为
undefined ,抛出 TypeError
异常。
如果 resolvingFunctions .[[Reject]] 不为
undefined ,抛出 TypeError
异常。
设置 resolvingFunctions .[[Resolve]] 为
resolve 。
设置 resolvingFunctions .[[Reject]] 为
reject 。
返回 undefined 。
令 executor 为 CreateBuiltinFunction (executorClosure ,
2, "" , « »)。
令 promise 为 ? Construct (C , «
executor »)。
如果 IsCallable (resolvingFunctions .[[Resolve]] ) 为 false ,抛出
TypeError 异常。
如果 IsCallable (resolvingFunctions .[[Reject]] ) 为 false ,抛出
TypeError 异常。
返回 PromiseCapability
记录 { [[Promise]] :
promise , [[Resolve]] :
resolvingFunctions .[[Resolve]] , [[Reject]] : resolvingFunctions .[[Reject]] }.
注
该抽象操作支持 Promise 子类化,因为它对于任何以与 Promise 构造函数 相同方式调用传入 executor
函数参数的 构造函数 都是通用的。用于将 Promise 构造函数
的静态方法泛化到任何子类。
27.2.1.6 IsPromise ( x )
抽象操作 IsPromise 接收参数 x (一个 ECMAScript
语言值 ),返回布尔值。该操作检查对象上的 promise 品牌。调用时执行以下步骤:
如果 x 不是对象 ,返回
false 。
如果 x 没有 [[PromiseState]] 内部槽,返回
false 。
返回 true 。
27.2.1.7 RejectPromise ( promise , reason )
抽象操作 RejectPromise 接收参数 promise (一个 Promise)和
reason (一个 ECMAScript 语言值 ),返回
unused 。调用时执行以下步骤:
断言 :
promise .[[PromiseState]] 的值为
pending 。
令 reactions 为 promise .[[PromiseRejectReactions]] 。
设置 promise .[[PromiseResult]] 为
reason 。
设置 promise .[[PromiseFulfillReactions]] 为
undefined 。
设置 promise .[[PromiseRejectReactions]] 为
undefined 。
设置 promise .[[PromiseState]] 为
rejected 。
如果 promise .[[PromiseIsHandled]] 为
false ,执行 HostPromiseRejectionTracker (promise ,
"reject" )。
执行 TriggerPromiseReactions (reactions ,
reason )。
返回 unused 。
27.2.1.8 TriggerPromiseReactions ( reactions ,
argument )
抽象操作 TriggerPromiseReactions 接收参数 reactions (一个
List ,元素为 PromiseReaction 记录 )和
argument (一个 ECMAScript 语言值 ),返回
unused 。它会为 reactions 中的每个记录入队一个新的 作业(Job) 。每个这样的 作业 会处理 PromiseReaction 记录 的 [[Type]] 和 [[Handler]] ,如果 [[Handler]] 不为 empty ,则调用它并传递参数。如果 [[Handler]] 为 empty ,则行为由 [[Type]] 决定。调用时执行以下步骤:
对 reactions 的每个元素 reaction ,执行
令 job 为 NewPromiseReactionJob (reaction ,
argument )。
执行 HostEnqueuePromiseJob (job .[[Job]] , job .[[Realm]] )。
返回 unused 。
27.2.1.9 HostPromiseRejectionTracker ( promise ,
operation )
宿主自定义
抽象操作 HostPromiseRejectionTracker 接收参数 promise (一个 Promise) 和
operation ("reject" 或 "handle" ),返回
unused 。它允许 宿主环境 跟踪 promise 拒绝。
HostPromiseRejectionTracker 的默认实现是返回 unused 。
注 1
HostPromiseRejectionTracker 在两种情况下被调用:
当 promise 被拒绝且没有任何处理器时,其 operation 参数为 "reject" 。
当首次为已拒绝的 promise 添加处理器时,其 operation 参数为 "handle" 。
典型的 HostPromiseRejectionTracker
实现可能会尝试通知开发者有未处理的拒绝,同时也要注意在新处理器被添加后,如果之前的通知失效要及时通知开发者。
注 2
如果 operation 是 "handle" ,实现不应以会影响垃圾回收的方式持有
promise 的引用。如果 operation 是 "reject" ,实现可以持有
promise 引用,因为拒绝情况预计较少且不会出现在热点代码路径上。
27.2.2 Promise 作业(Jobs)
27.2.2.1 NewPromiseReactionJob ( reaction ,
argument )
抽象操作 NewPromiseReactionJob 接收参数 reaction (一个 PromiseReaction 记录 )和
argument (一个 ECMAScript 语言值 ),返回一个带有字段
[[Job]] (一个 作业(Job) 抽象闭包 )和
[[Realm]] (一个 Realm 记录 或 null )的 记录(Record) 。它返回一个新的
作业 抽象闭包 ,该闭包会对传入值应用合适的处理器,并用处理器的返回值解决或拒绝与该处理器关联的派生
promise。调用时执行以下步骤:
令 job 为一个新的 作业(Job) 抽象闭包 ,
无参数,捕获 reaction 和 argument ,调用时执行以下步骤:
令 promiseCapability 为 reaction .[[Capability]] 。
令 type 为 reaction .[[Type]] 。
令 handler 为 reaction .[[Handler]] 。
如果 handler 为 empty ,则
如果 type 为 fulfill ,则
令 handlerResult 为 NormalCompletion (argument )。
否则,
断言 :
type 为 reject 。
令 handlerResult 为 ThrowCompletion (argument )。
否则,
令 handlerResult 为 Completion (HostCallJobCallback (handler ,
undefined , « argument »))。
如果 promiseCapability 为 undefined ,则
断言 :
handlerResult 不是 异常完成 。
返回 empty 。
断言 :promiseCapability
是 PromiseCapability
记录 。
如果 handlerResult 是 异常完成 ,则
返回 ? Call (promiseCapability .[[Reject]] , undefined , «
handlerResult .[[Value]] »)。
否则,
返回 ? Call (promiseCapability .[[Resolve]] , undefined , «
handlerResult .[[Value]] »)。
令 handlerRealm 为 null 。
如果 reaction .[[Handler]] 不为
empty ,则
令 getHandlerRealmResult 为 Completion (GetFunctionRealm (reaction .[[Handler]] .[[Callback]] ))。
如果 getHandlerRealmResult 是 正常完成 ,则设置
handlerRealm 为
getHandlerRealmResult .[[Value]] 。
否则,设置 handlerRealm 为 当前 Realm 记录 。
注:handlerRealm 除非 handler 为 undefined ,否则不会为
null 。当 handler 是被撤销的 Proxy 且没有 ECMAScript
代码运行时,handlerRealm 用于创建错误对象。
返回 记录 { [[Job]] : job , [[Realm]] :
handlerRealm }。
27.2.2.2 NewPromiseResolveThenableJob (
promiseToResolve , thenable , then )
抽象操作 NewPromiseResolveThenableJob 接收参数
promiseToResolve (一个 Promise)、thenable (一个对象)、then (一个
JobCallback 记录 ),返回一个带有字段
[[Job]] (一个 作业(Job) 抽象闭包 )和
[[Realm]] (一个 Realm 记录 )的 记录(Record) 。调用时执行以下步骤:
令 job 为一个新的 作业(Job) 抽象闭包 ,
无参数,捕获 promiseToResolve 、thenable 、then ,调用时执行以下步骤:
令 resolvingFunctions 为 CreateResolvingFunctions (promiseToResolve )。
令 thenCallResult 为 Completion (HostCallJobCallback (then ,
thenable , « resolvingFunctions .[[Resolve]] , resolvingFunctions .[[Reject]] »))。
如果 thenCallResult 是 异常完成 ,则
返回 ? Call (resolvingFunctions .[[Reject]] , undefined , «
thenCallResult .[[Value]] »)。
返回 ! thenCallResult 。
令 getThenRealmResult 为 Completion (GetFunctionRealm (then .[[Callback]] ))。
如果 getThenRealmResult 是 正常完成 ,则令
thenRealm 为
getThenRealmResult .[[Value]] 。
否则,令 thenRealm 为 当前 Realm 记录 。
注:thenRealm 永远不会为 null 。当
then .[[Callback]] 是被撤销的 Proxy
且没有代码运行时,thenRealm 用于创建错误对象。
返回 记录 { [[Job]] : job , [[Realm]] :
thenRealm }。
注
该 作业(Job) 使用提供的
thenable 及其 then
方法来解决给定 promise。该过程必须作为一个 作业(Job) 执行,以保证 then
方法的求值发生在任何外围代码的求值完成之后。
27.2.3 Promise 构造函数
Promise 构造函数 :
即 %Promise% 。
是 全局对象 的 "Promise" 属性的初始值。
作为 构造函数
调用时,会创建并初始化一个新的 Promise。
不应作为普通函数调用,否则会抛出异常。
可以用作类定义的 extends
子句中的值。意图继承指定 Promise 行为的子类 构造函数 ,必须在内部通过 super
调用
Promise 构造函数 ,以创建并初始化子类实例,并赋予其支持 Promise
与
Promise.prototype
内置方法所需的内部状态。
27.2.3.1 Promise ( executor )
该函数被调用时执行以下步骤:
如果 NewTarget 为 undefined ,抛出 TypeError 异常。
如果 IsCallable (executor ) 为
false ,抛出 TypeError 异常。
令 promise 为 ? OrdinaryCreateFromConstructor (NewTarget,
"%Promise.prototype%" , « [[PromiseState]] , [[PromiseResult]] , [[PromiseFulfillReactions]] , [[PromiseRejectReactions]] , [[PromiseIsHandled]] »)。
设置 promise .[[PromiseState]] 为
pending 。
设置 promise .[[PromiseResult]] 为
empty 。
设置 promise .[[PromiseFulfillReactions]] 为一个新的空
List 。
设置 promise .[[PromiseRejectReactions]] 为一个新的空
List 。
设置 promise .[[PromiseIsHandled]] 为
false 。
令 resolvingFunctions 为 CreateResolvingFunctions (promise )。
令 completion 为 Completion (Call (executor ,
undefined , « resolvingFunctions .[[Resolve]] , resolvingFunctions .[[Reject]] »))。
如果 completion 是 异常完成 ,则
执行 ? Call (resolvingFunctions .[[Reject]] , undefined , «
completion .[[Value]] »)。
返回 promise 。
注
executor 参数必须是 函数对象 。它用于启动和报告该 Promise
所表示的(可能是延迟的)操作的完成。executor 会以两个参数 resolve 和 reject 被调用。这两个参数是
executor 可用来报告延迟计算的最终完成或失败的函数。从 executor 返回并不意味着延迟操作已完成,只意味着已接受最终执行该操作的请求。
传递给 executor 的 resolve 函数接受一个参数。executor 代码最终可调用
resolve ,表示希望解决关联的 Promise。传递给 resolve
的参数表示延迟操作的最终值,可以是实际的兑现值,也可以是另一个 promise(如果 fulfilled)将提供值。
传递给 executor 的 reject 函数也接受一个参数。executor 代码最终可调用
reject ,表示关联的 Promise 被拒绝且永远不会兑现。传递给 reject 的参数用作 promise
的拒绝值。通常应为 Error 对象。
Promise 构造函数 传给 executor 的 resolve 和
reject 函数有能力实际解决和拒绝关联的 promise。子类可有不同的 构造函数 行为,传入自定义的 resolve 和
reject。
27.2.4 Promise 构造函数的属性
Promise 构造函数 :
27.2.4.1 Promise.all ( iterable )
该函数返回一个新的 promise,当传入的所有 promise 都已兑现时,其值为所有兑现值组成的数组;如果有任意一个 promise
被拒绝,则返回第一个被拒绝的原因。它在运行本算法时,会将传入的 iterable 的所有元素解析为 promise。
令 C 为 this 值。
令 promiseCapability 为 ? NewPromiseCapability (C )。
令 promiseResolve 为 Completion (GetPromiseResolve (C ))。
IfAbruptRejectPromise (promiseResolve ,
promiseCapability )。
令 iteratorRecord 为 Completion (GetIterator (iterable ,
sync ))。
IfAbruptRejectPromise (iteratorRecord ,
promiseCapability )。
令 result 为 Completion (PerformPromiseAll (iteratorRecord ,
C , promiseCapability , promiseResolve ))。
如果 result 是 异常完成 ,则
如果 iteratorRecord .[[Done]] 为
false ,则设置 result 为 Completion (IteratorClose (iteratorRecord ,
result ))。
IfAbruptRejectPromise (result ,
promiseCapability )。
返回 ! result 。
注
该函数要求其 this 值为一个支持 Promise 构造函数 参数规范的 构造函数
函数。
27.2.4.1.1 GetPromiseResolve ( promiseConstructor
)
抽象操作 GetPromiseResolve 接收参数 promiseConstructor (一个
构造函数 ),返回一个 正常完成
包含 的 函数对象 或 抛出完成 。调用时执行以下步骤:
令 promiseResolve 为 ? Get (promiseConstructor ,
"resolve" )。
如果 IsCallable (promiseResolve )
为 false ,抛出 TypeError 异常。
返回 promiseResolve 。
27.2.4.1.2 PerformPromiseAll ( iteratorRecord ,
constructor , resultCapability , promiseResolve )
抽象操作 PerformPromiseAll 接收参数 iteratorRecord (一个
迭代器记录 ),
constructor (一个 构造函数 ), resultCapability (一个
PromiseCapability 记录 ),
promiseResolve (一个 函数对象 ),返回 正常完成
包含 的 ECMAScript
语言值 或 抛出完成 。调用时执行以下步骤:
令 values 为一个新的空 List 。
令 remainingElementsCount 为 记录 {
[[Value]] : 1 }。
令 index 为 0。
重复,
令 next 为 ? IteratorStepValue (iteratorRecord )。
如果 next 为 done ,则
设置 remainingElementsCount .[[Value]] 为
remainingElementsCount .[[Value]] - 1。
如果 remainingElementsCount .[[Value]] = 0,则
令 valuesArray 为 CreateArrayFromList (values )。
执行 ? Call (resultCapability .[[Resolve]] ,
undefined , «
valuesArray »)。
返回 resultCapability .[[Promise]] 。
向 values 添加 undefined 。
令 nextPromise 为 ? Call (promiseResolve ,
constructor , « next »)。
令 steps 为 Promise.all
Resolve Element Functions 中定义的算法步骤。
令 length 为 Promise.all
Resolve Element Functions 函数定义的非可选参数数量。
令 onFulfilled 为 CreateBuiltinFunction (steps ,
length , "" , « [[AlreadyCalled]] , [[Index]] , [[Values]] ,
[[Capability]] , [[RemainingElements]] »)。
设置 onFulfilled .[[AlreadyCalled]] 为
false 。
设置 onFulfilled .[[Index]] 为
index 。
设置 onFulfilled .[[Values]] 为
values 。
设置 onFulfilled .[[Capability]] 为
resultCapability 。
设置 onFulfilled .[[RemainingElements]]
为
remainingElementsCount 。
设置 remainingElementsCount .[[Value]]
为 remainingElementsCount .[[Value]]
+ 1。
执行 ? Invoke (nextPromise ,
"then" , « onFulfilled ,
resultCapability .[[Reject]] »)。
设置 index 为 index + 1。
27.2.4.1.3 Promise.all
解析元素函数
Promise.all
解析元素函数是一个用于解析特定 Promise.all
元素的匿名内置函数。每个
Promise.all
解析元素函数都有 [[Index]] 、[[Values]] 、[[Capability]] 、[[RemainingElements]] 和 [[AlreadyCalled]] 内部槽。
当以参数 x 调用 Promise.all
解析元素函数时,执行以下步骤:
令 F 为 当前函数对象 。
如果 F .[[AlreadyCalled]] 为
true ,返回 undefined 。
设置 F .[[AlreadyCalled]] 为
true 。
令 index 为 F .[[Index]] 。
令 values 为 F .[[Values]] 。
令 promiseCapability 为 F .[[Capability]] 。
令 remainingElementsCount 为 F .[[RemainingElements]] 。
设置 values [index ] 为 x 。
设置 remainingElementsCount .[[Value]] 为
remainingElementsCount .[[Value]] - 1。
如果 remainingElementsCount .[[Value]] = 0,
则
令 valuesArray 为 CreateArrayFromList (values )。
返回 ? Call (promiseCapability .[[Resolve]] , undefined , «
valuesArray »)。
返回 undefined 。
Promise.all
解析元素函数的 "length" 属性值为
1 𝔽 。
27.2.4.2 Promise.allSettled ( iterable )
该函数返回一个 promise,在所有原始 promise 都已定型(即已兑现或已拒绝)后,用 promise 状态快照数组兑现。它在运行本算法时,会将传入的 iterable 的所有元素解析为 promise。
令 C 为 this 值。
令 promiseCapability 为 ? NewPromiseCapability (C )。
令 promiseResolve 为 Completion (GetPromiseResolve (C ))。
IfAbruptRejectPromise (promiseResolve ,
promiseCapability )。
令 iteratorRecord 为 Completion (GetIterator (iterable ,
sync ))。
IfAbruptRejectPromise (iteratorRecord ,
promiseCapability )。
令 result 为 Completion (PerformPromiseAllSettled (iteratorRecord ,
C , promiseCapability , promiseResolve ))。
如果 result 是 异常完成 ,则
如果 iteratorRecord .[[Done]] 为
false ,则设置 result 为 Completion (IteratorClose (iteratorRecord ,
result ))。
IfAbruptRejectPromise (result ,
promiseCapability )。
返回 ! result 。
注
该函数要求其 this 值为一个支持 Promise 构造函数 参数规范的 构造函数
函数。
27.2.4.2.1 PerformPromiseAllSettled (
iteratorRecord , constructor , resultCapability ,
promiseResolve )
抽象操作 PerformPromiseAllSettled 接收参数 iteratorRecord (一个 迭代器记录 )、
constructor (一个 构造函数 )、
resultCapability (一个 PromiseCapability
记录 )和
promiseResolve (一个 函数对象 ),返回 正常完成
包含 的 ECMAScript
语言值 或 抛出完成 。调用时执行以下步骤:
令 values 为一个新的空 List 。
令 remainingElementsCount 为 记录 {
[[Value]] : 1 }。
令 index 为 0。
重复,
令 next 为 ? IteratorStepValue (iteratorRecord )。
如果 next 为 done ,则
设置 remainingElementsCount .[[Value]] 为
remainingElementsCount .[[Value]] - 1。
如果 remainingElementsCount .[[Value]] = 0,则
令 valuesArray 为 CreateArrayFromList (values )。
执行 ? Call (resultCapability .[[Resolve]] ,
undefined , «
valuesArray »)。
返回 resultCapability .[[Promise]] 。
向 values 添加 undefined 。
令 nextPromise 为 ? Call (promiseResolve ,
constructor , « next »)。
令 stepsFulfilled 为 Promise.allSettled
解析元素函数 中定义的算法步骤。
令 lengthFulfilled 为 Promise.allSettled
解析元素函数 函数定义的非可选参数数量。
令 onFulfilled 为 CreateBuiltinFunction (stepsFulfilled ,
lengthFulfilled , "" , « [[AlreadyCalled]] , [[Index]] , [[Values]] ,
[[Capability]] , [[RemainingElements]] »)。
令 alreadyCalled 为 记录
{ [[Value]] : false }。
设置 onFulfilled .[[AlreadyCalled]] 为
alreadyCalled 。
设置 onFulfilled .[[Index]] 为
index 。
设置 onFulfilled .[[Values]] 为
values 。
设置 onFulfilled .[[Capability]] 为
resultCapability 。
设置 onFulfilled .[[RemainingElements]]
为
remainingElementsCount 。
令 stepsRejected 为 Promise.allSettled
拒绝元素函数 中定义的算法步骤。
令 lengthRejected 为 Promise.allSettled
拒绝元素函数 函数定义的非可选参数数量。
令 onRejected 为 CreateBuiltinFunction (stepsRejected ,
lengthRejected , "" , « [[AlreadyCalled]] , [[Index]] , [[Values]] ,
[[Capability]] , [[RemainingElements]] »)。
设置 onRejected .[[AlreadyCalled]] 为
alreadyCalled 。
设置 onRejected .[[Index]] 为
index 。
设置 onRejected .[[Values]] 为
values 。
设置 onRejected .[[Capability]] 为
resultCapability 。
设置 onRejected .[[RemainingElements]]
为 remainingElementsCount 。
设置 remainingElementsCount .[[Value]]
为 remainingElementsCount .[[Value]]
+ 1。
执行 ? Invoke (nextPromise ,
"then" , « onFulfilled ,
onRejected »)。
设置 index 为 index + 1。
27.2.4.2.2 Promise.allSettled
解析元素函数
Promise.allSettled
解析元素函数是一个匿名内置函数,用于解析特定的 Promise.allSettled
元素。每个 Promise.allSettled
解析元素函数都有 [[Index]] 、[[Values]] 、[[Capability]] 、[[RemainingElements]] 和 [[AlreadyCalled]] 内部槽。
当以参数 x 调用 Promise.allSettled
解析元素函数时,执行以下步骤:
令 F 为 当前函数对象 。
令 alreadyCalled 为 F .[[AlreadyCalled]] 。
如果 alreadyCalled .[[Value]] 为
true ,返回 undefined 。
设置 alreadyCalled .[[Value]] 为
true 。
令 index 为 F .[[Index]] 。
令 values 为 F .[[Values]] 。
令 promiseCapability 为 F .[[Capability]] 。
令 remainingElementsCount 为 F .[[RemainingElements]] 。
令 obj 为 OrdinaryObjectCreate (%Object.prototype% )。
执行 ! CreateDataPropertyOrThrow (obj ,
"status" , "fulfilled" )。
执行 ! CreateDataPropertyOrThrow (obj ,
"value" , x )。
设置 values [index ] 为 obj 。
设置 remainingElementsCount .[[Value]] 为
remainingElementsCount .[[Value]] - 1。
如果 remainingElementsCount .[[Value]] = 0,
则
令 valuesArray 为 CreateArrayFromList (values )。
返回 ? Call (promiseCapability .[[Resolve]] , undefined , «
valuesArray »)。
返回 undefined 。
Promise.allSettled
解析元素函数的 "length" 属性值为
1 𝔽 。
27.2.4.2.3 Promise.allSettled
拒绝元素函数
Promise.allSettled
拒绝元素函数是一个匿名内置函数,用于拒绝特定的 Promise.allSettled
元素。每个 Promise.allSettled
拒绝元素函数都有 [[Index]] 、[[Values]] 、[[Capability]] 、[[RemainingElements]] 和 [[AlreadyCalled]] 内部槽。
当以参数 x 调用 Promise.allSettled
拒绝元素函数时,执行以下步骤:
令 F 为 当前函数对象 。
令 alreadyCalled 为 F .[[AlreadyCalled]] 。
如果 alreadyCalled .[[Value]] 为
true ,返回 undefined 。
设置 alreadyCalled .[[Value]] 为
true 。
令 index 为 F .[[Index]] 。
令 values 为 F .[[Values]] 。
令 promiseCapability 为 F .[[Capability]] 。
令 remainingElementsCount 为 F .[[RemainingElements]] 。
令 obj 为 OrdinaryObjectCreate (%Object.prototype% )。
执行 ! CreateDataPropertyOrThrow (obj ,
"status" , "rejected" )。
执行 ! CreateDataPropertyOrThrow (obj ,
"reason" , x )。
设置 values [index ] 为 obj 。
设置 remainingElementsCount .[[Value]] 为
remainingElementsCount .[[Value]] - 1。
如果 remainingElementsCount .[[Value]] = 0,
则
令 valuesArray 为 CreateArrayFromList (values )。
返回 ? Call (promiseCapability .[[Resolve]] , undefined , «
valuesArray »)。
返回 undefined 。
Promise.allSettled
拒绝元素函数的 "length" 属性值为
1 𝔽 。
27.2.4.3 Promise.any ( iterable )
该函数返回一个 promise,该 promise 会被第一个兑现的输入 promise 兑现,或者如果所有输入 promise 都被拒绝,则以包含所有拒绝原因的
AggregateError
拒绝。在执行本算法时,会将传入的 iterable 的所有元素解析为
promise。
令 C 为 this 值。
令 promiseCapability 为 ? NewPromiseCapability (C )。
令 promiseResolve 为 Completion (GetPromiseResolve (C ))。
IfAbruptRejectPromise (promiseResolve ,
promiseCapability )。
令 iteratorRecord 为 Completion (GetIterator (iterable ,
sync ))。
IfAbruptRejectPromise (iteratorRecord ,
promiseCapability )。
令 result 为 Completion (PerformPromiseAny (iteratorRecord ,
C , promiseCapability , promiseResolve ))。
如果 result 是 异常完成 ,则
如果 iteratorRecord .[[Done]] 为
false ,则设置 result 为 Completion (IteratorClose (iteratorRecord ,
result ))。
IfAbruptRejectPromise (result ,
promiseCapability )。
返回 ! result 。
注
该函数要求其 this 值为支持 Promise
构造函数
参数规范的 构造函数 函数。
27.2.4.3.1 PerformPromiseAny ( iteratorRecord ,
constructor , resultCapability , promiseResolve )
抽象操作 PerformPromiseAny 接收参数 iteratorRecord (一个
迭代器记录 )、
constructor (一个 构造函数 )、resultCapability (一个
PromiseCapability 记录 )和
promiseResolve (一个 函数对象 ),返回 正常完成
包含 的 ECMAScript
语言值 或 抛出完成 。调用时执行以下步骤:
令 errors 为一个新的空 List 。
令 remainingElementsCount 为 记录 {
[[Value]] : 1 }。
令 index 为 0。
重复,
令 next 为 ? IteratorStepValue (iteratorRecord )。
如果 next 为 done ,则
设置 remainingElementsCount .[[Value]] 为
remainingElementsCount .[[Value]] - 1。
如果 remainingElementsCount .[[Value]] = 0,则
令 error 为新建的
AggregateError 对象。
执行 ! DefinePropertyOrThrow (error ,
"errors" , PropertyDescriptor { [[Configurable]] :
true , [[Enumerable]] :
false , [[Writable]] :
true , [[Value]] : CreateArrayFromList (errors ) }).
返回 ThrowCompletion (error )。
返回 resultCapability .[[Promise]] 。
向 errors 添加 undefined 。
令 nextPromise 为 ? Call (promiseResolve ,
constructor , « next »)。
令 stepsRejected 为 Promise.any
拒绝元素函数 中定义的算法步骤。
令 lengthRejected 为 Promise.any
拒绝元素函数 函数定义的非可选参数数量。
令 onRejected 为 CreateBuiltinFunction (stepsRejected ,
lengthRejected , "" , « [[AlreadyCalled]] , [[Index]] , [[Errors]] ,
[[Capability]] , [[RemainingElements]] »)。
设置 onRejected .[[AlreadyCalled]] 为
false 。
设置 onRejected .[[Index]] 为
index 。
设置 onRejected .[[Errors]] 为
errors 。
设置 onRejected .[[Capability]] 为
resultCapability 。
设置 onRejected .[[RemainingElements]]
为 remainingElementsCount 。
设置 remainingElementsCount .[[Value]]
为 remainingElementsCount .[[Value]]
+ 1。
执行 ? Invoke (nextPromise ,
"then" , « resultCapability .[[Resolve]] , onRejected »)。
设置 index 为 index + 1。
27.2.4.3.2 Promise.any
拒绝元素函数
Promise.any
拒绝元素函数是一个匿名内置函数,用于拒绝特定的 Promise.any
元素。每个
Promise.any
拒绝元素函数都有 [[Index]] 、
[[Errors]] 、[[Capability]] 、[[RemainingElements]] 和 [[AlreadyCalled]] 内部槽。
当以参数 x 调用 Promise.any
拒绝元素函数时,执行以下步骤:
令 F 为 当前函数对象 。
如果 F .[[AlreadyCalled]] 为
true ,返回 undefined 。
设置 F .[[AlreadyCalled]] 为
true 。
令 index 为 F .[[Index]] 。
令 errors 为 F .[[Errors]] 。
令 promiseCapability 为 F .[[Capability]] 。
令 remainingElementsCount 为 F .[[RemainingElements]] 。
设置 errors [index ] 为 x 。
设置 remainingElementsCount .[[Value]] 为
remainingElementsCount .[[Value]] - 1。
如果 remainingElementsCount .[[Value]] = 0,
则
令 error 为新建的 AggregateError 对象。
执行 ! DefinePropertyOrThrow (error ,
"errors" , PropertyDescriptor { [[Configurable]] : true , [[Enumerable]] : false , [[Writable]] : true , [[Value]] : CreateArrayFromList (errors ) }).
返回 ? Call (promiseCapability .[[Reject]] , undefined , «
error »)。
返回 undefined 。
Promise.any
拒绝元素函数的 "length" 属性值为
1 𝔽 。
27.2.4.4 Promise.prototype
Promise.prototype
的初始值为 Promise 原型对象 。
该属性具有属性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
27.2.4.5 Promise.race ( iterable )
该函数返回一个新的 promise,其定型方式与第一个定型的输入 promise 相同。在运行本算法时会把传入的 iterable 的所有元素解析为
promise。
令 C 为 this 值。
令 promiseCapability 为 ? NewPromiseCapability (C )。
令 promiseResolve 为 Completion (GetPromiseResolve (C ))。
IfAbruptRejectPromise (promiseResolve ,
promiseCapability )。
令 iteratorRecord 为 Completion (GetIterator (iterable ,
sync ))。
IfAbruptRejectPromise (iteratorRecord ,
promiseCapability )。
令 result 为 Completion (PerformPromiseRace (iteratorRecord ,
C , promiseCapability , promiseResolve ))。
如果 result 是 异常完成 ,则
如果 iteratorRecord .[[Done]] 为
false ,则设置 result 为 Completion (IteratorClose (iteratorRecord ,
result ))。
IfAbruptRejectPromise (result ,
promiseCapability )。
返回 ! result 。
注 1
如果 iterable 参数不产出任何值,或者由 iterable 产出的 promise 都不会定型,则该方法返回的待定
promise 将永远不会定型。
注 2
该函数期望其 this 值为一个支持 Promise 构造函数 参数规范的 构造函数
函数。还期望其 this 值提供一个 resolve
方法。
27.2.4.5.1 PerformPromiseRace ( iteratorRecord ,
constructor , resultCapability , promiseResolve )
抽象操作 PerformPromiseRace 接收参数 iteratorRecord (一个
迭代器记录 )、
constructor (一个 构造函数 )、
resultCapability (一个 PromiseCapability
记录 )和
promiseResolve (一个 函数对象 ),返回 正常完成包含 的
ECMAScript 语言值 或 抛出完成 。调用时执行以下步骤:
重复,
令 next 为 ? IteratorStepValue (iteratorRecord )。
如果 next 为 done ,则
返回 resultCapability .[[Promise]] 。
令 nextPromise 为 ? Call (promiseResolve ,
constructor , « next »)。
执行 ? Invoke (nextPromise ,
"then" , « resultCapability .[[Resolve]] , resultCapability .[[Reject]] »)。
27.2.4.6 Promise.reject ( r )
该函数返回一个以传入参数为拒绝原因的新 promise。
令 C 为 this 值。
令 promiseCapability 为 ? NewPromiseCapability (C )。
执行 ? Call (promiseCapability .[[Reject]] , undefined , «
r »)。
返回 promiseCapability .[[Promise]] 。
注
该函数期望其 this 值为一个支持 Promise 构造函数 参数规范的 构造函数 。
27.2.4.7 Promise.resolve ( x )
该函数返回一个用传入参数解决的新 promise,或者如果参数本身就是由该 构造函数 生成的 promise,则直接返回该参数。
令 C 为 this 值。
如果 C 不是对象 ,抛出 TypeError
异常。
返回 ? PromiseResolve (C ,
x )。
注
该函数期望其 this 值为一个支持 Promise 构造函数 参数规范的 构造函数 。
27.2.4.7.1 PromiseResolve ( C , x )
抽象操作 PromiseResolve 接收参数 C (一个对象)和
x (一个 ECMAScript 语言值 ),返回
正常完成
包含 的 ECMAScript
语言值
或 抛出完成 。它返回一个用
x 解决的新 promise。调用时执行以下步骤:
如果 IsPromise (x ) 为
true ,则
令 xConstructor 为 ? Get (x ,
"constructor" )。
如果 SameValue (xConstructor ,
C ) 为 true ,返回 x 。
令 promiseCapability 为 ? NewPromiseCapability (C )。
执行 ? Call (promiseCapability .[[Resolve]] , undefined , «
x »)。
返回 promiseCapability .[[Promise]] 。
27.2.4.8 Promise.try ( callback , ...args )
该函数被调用时执行以下步骤:
令 C 为 this 值。
如果 C 不是对象 ,抛出 TypeError
异常。
令 promiseCapability 为 ? NewPromiseCapability (C )。
令 status 为 Completion (Call (callback ,
undefined , args ))。
如果 status 是 异常完成 ,则
执行 ? Call (promiseCapability .[[Reject]] , undefined , «
status .[[Value]] »)。
否则,
执行 ? Call (promiseCapability .[[Resolve]] , undefined , «
status .[[Value]] »)。
返回 promiseCapability .[[Promise]] 。
注
该函数期望其 this 值为一个支持 Promise 构造函数 参数规范的 构造函数 。
27.2.4.9 Promise.withResolvers ( )
该函数返回一个包含三个属性的对象:一个新的 promise,以及与其关联的 resolve
和 reject
函数。
令 C 为 this 值。
令 promiseCapability 为 ? NewPromiseCapability (C )。
令 obj 为 OrdinaryObjectCreate (%Object.prototype% )。
执行 ! CreateDataPropertyOrThrow (obj ,
"promise" , promiseCapability .[[Promise]] )。
执行 ! CreateDataPropertyOrThrow (obj ,
"resolve" , promiseCapability .[[Resolve]] )。
执行 ! CreateDataPropertyOrThrow (obj ,
"reject" , promiseCapability .[[Reject]] )。
返回 obj 。
27.2.4.10 get Promise [ %Symbol.species% ]
Promise[%Symbol.species%]
是一个 访问器属性 ,其 set 访问器函数为
undefined 。其 get 访问器函数被调用时,执行以下步骤:
返回 this 值。
该函数的 "name" 属性值为 "get
[Symbol.species]" 。
注
Promise 原型方法通常使用其 this 值的 构造函数 来创建派生对象。然而,子类
构造函数 可以通过重定义其 %Symbol.species% 属性来覆盖该默认行为。
27.2.5 Promise 原型对象的属性
Promise 原型对象 :
即 %Promise.prototype% 。
拥有一个 [[Prototype]] 内部槽,其值为 %Object.prototype% 。
是一个 普通对象 。
没有 [[PromiseState]] 内部槽,也没有 Promise 实例的其他内部槽。
27.2.5.1 Promise.prototype.catch ( onRejected )
该方法被调用时执行以下步骤:
令 promise 为 this 值。
返回 ? Invoke (promise ,
"then" , « undefined ,
onRejected »)。
27.2.5.2 Promise.prototype.constructor
Promise.prototype.constructor
的初始值为 %Promise% 。
27.2.5.3 Promise.prototype.finally ( onFinally )
该方法被调用时执行以下步骤:
令 promise 为 this 值。
如果 promise 不是对象 ,抛出 TypeError
异常。
令 C 为 ? SpeciesConstructor (promise ,
%Promise% )。
断言 :
IsConstructor (C ) 为
true 。
如果 IsCallable (onFinally ) 为
false ,则
令 thenFinally 为 onFinally 。
令 catchFinally 为 onFinally 。
否则,
令 thenFinallyClosure 为一个新的 抽象闭包 ,
参数为 (value ),捕获 onFinally 和
C ,调用时执行以下步骤:
令 result 为 ? Call (onFinally ,
undefined )。
令 p 为 ? PromiseResolve (C ,
result )。
令 returnValue 为一个新的 抽象闭包
无参数,捕获 value ,调用时执行以下步骤:
返回 value 。
令 valueThunk 为 CreateBuiltinFunction (returnValue ,
0, "" , « »)。
返回 ? Invoke (p ,
"then" , « valueThunk »)。
令 thenFinally 为 CreateBuiltinFunction (thenFinallyClosure ,
1, "" , « »)。
令 catchFinallyClosure 为一个新的 抽象闭包 ,
参数为 (reason ),捕获 onFinally 和
C ,调用时执行以下步骤:
令 result 为 ? Call (onFinally ,
undefined )。
令 p 为 ? PromiseResolve (C ,
result )。
令 throwReason 为一个新的 抽象闭包
无参数,捕获 reason ,调用时执行以下步骤:
返回 ThrowCompletion (reason )。
令 thrower 为 CreateBuiltinFunction (throwReason ,
0, "" , « »)。
返回 ? Invoke (p ,
"then" , « thrower »)。
令 catchFinally 为 CreateBuiltinFunction (catchFinallyClosure ,
1, "" , « »)。
返回 ? Invoke (promise ,
"then" , « thenFinally ,
catchFinally »)。
27.2.5.4 Promise.prototype.then ( onFulfilled ,
onRejected )
该方法被调用时执行以下步骤:
令 promise 为 this 值。
如果 IsPromise (promise ) 为
false ,抛出 TypeError 异常。
令 C 为 ? SpeciesConstructor (promise ,
%Promise% )。
令 resultCapability 为 ? NewPromiseCapability (C )。
返回 PerformPromiseThen (promise ,
onFulfilled , onRejected , resultCapability )。
27.2.5.4.1 PerformPromiseThen ( promise ,
onFulfilled , onRejected [ , resultCapability ] )
抽象操作 PerformPromiseThen 接收参数 promise (一个 Promise),
onFulfilled (一个 ECMAScript
语言值 ),
onRejected (一个 ECMAScript
语言值 )
以及可选参数 resultCapability (一个 PromiseCapability
记录 ),
返回一个 ECMAScript 语言值 。
它使用 onFulfilled 和 onRejected 作为定型操作,对 promise 执行 “then”
操作。如果传入 resultCapability ,则通过更新 resultCapability 的 promise
存储结果;如果未传入,则说明 PerformPromiseThen 被规范内部操作调用,结果无关紧要。调用时执行以下步骤:
断言 :IsPromise (promise ) 为
true 。
如果未传入 resultCapability ,则
设置 resultCapability 为 undefined 。
如果 IsCallable (onFulfilled )
为 false ,则
令 onFulfilledJobCallback 为 empty 。
否则,
令 onFulfilledJobCallback 为 HostMakeJobCallback (onFulfilled )。
如果 IsCallable (onRejected )
为 false ,则
令 onRejectedJobCallback 为 empty 。
否则,
令 onRejectedJobCallback 为 HostMakeJobCallback (onRejected )。
令 fulfillReaction 为 PromiseReaction
记录 { [[Capability]] :
resultCapability , [[Type]] :
fulfill , [[Handler]] :
onFulfilledJobCallback }。
令 rejectReaction 为 PromiseReaction
记录 { [[Capability]] :
resultCapability , [[Type]] :
reject , [[Handler]] :
onRejectedJobCallback }。
如果 promise .[[PromiseState]] 为
pending ,则
将 fulfillReaction 添加到 promise .[[PromiseFulfillReactions]] 。
将 rejectReaction 添加到 promise .[[PromiseRejectReactions]] 。
否则如果 promise .[[PromiseState]] 为
fulfilled ,则
令 value 为 promise .[[PromiseResult]] 。
令 fulfillJob 为 NewPromiseReactionJob (fulfillReaction ,
value )。
执行 HostEnqueuePromiseJob (fulfillJob .[[Job]] , fulfillJob .[[Realm]] )。
否则,
断言 :promise .[[PromiseState]] 的值为
rejected 。
令 reason 为 promise .[[PromiseResult]] 。
如果 promise .[[PromiseIsHandled]] 为
false ,执行 HostPromiseRejectionTracker (promise ,
"handle" )。
令 rejectJob 为 NewPromiseReactionJob (rejectReaction ,
reason )。
执行 HostEnqueuePromiseJob (rejectJob .[[Job]] , rejectJob .[[Realm]] )。
设置 promise .[[PromiseIsHandled]] 为
true 。
如果 resultCapability 为 undefined ,则
返回 undefined 。
否则,
返回 resultCapability .[[Promise]] 。
27.2.5.5 Promise.prototype [ %Symbol.toStringTag% ]
%Symbol.toStringTag% 属性的初始值为字符串
"Promise" 。
该属性具有属性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : true }。
27.2.6 Promise 实例的属性
Promise 实例是普通对象 ,继承自
Promise
原型对象 (本征的,%Promise.prototype% )。
Promise 实例最初使用表 92 中描述的内部槽创建。
表 92:Promise 实例的内部槽
内部槽
类型
描述
[[PromiseState]]
pending 、fulfilled 或
rejected
控制 promise 对其 then
方法的调用如何反应。
[[PromiseResult]]
一个 ECMAScript 语言值
或 empty
promise 被兑现或拒绝时的值(如果有)。仅当 [[PromiseState]] 为
pending 时为 empty 。
[[PromiseFulfillReactions]]
一个 List
,元素为 PromiseReaction
记录
记录
,在 promise 从 pending 状态转换到
fulfilled
状态时处理。
[[PromiseRejectReactions]]
一个 List
,元素为 PromiseReaction
记录
记录
,在 promise 从 pending 状态转换到
rejected
状态时处理。
[[PromiseIsHandled]]
布尔值
指示 promise 是否曾经有过兑现或拒绝处理器;用于未处理拒绝的追踪。
27.3 GeneratorFunction 对象
GeneratorFunction 通常是通过求值 GeneratorDeclaration 、GeneratorExpression 和
GeneratorMethod 创建的函数。也可以通过调用
%GeneratorFunction% 内部对象创建。
图 6(信息性):Generator 对象关系
27.3.1 GeneratorFunction 构造函数
GeneratorFunction 构造函数 :
即 %GeneratorFunction% 。
是 Function
的子类。
被作为函数而不是 构造函数 调用时,会创建并初始化一个新的 GeneratorFunction。因此,函数调用
GeneratorFunction (…)
等价于用相同参数的对象创建表达式 new GeneratorFunction (…)
。
可以用作类定义的 extends
子句的值。意图继承指定 GeneratorFunction 行为的子类 构造函数 ,必须通过
super
调用 GeneratorFunction 构造函数 创建并初始化子类实例,并赋予其内置 GeneratorFunction
行为所需的内部槽。所有 ECMAScript 定义 generator 函数对象 的语法形式,都会创建 GeneratorFunction
的直接实例。没有语法手段可以创建 GeneratorFunction 子类的实例。
27.3.1.1 GeneratorFunction ( ...parameterArgs ,
bodyArg )
最后一个参数(如果有)指定生成器函数的主体(可执行代码);之前的所有参数指定形式参数。
该函数被调用时执行以下步骤:
令 C 为 当前函数对象 。
如果 bodyArg 不存在,则将 bodyArg 设为一个空字符串。
返回 ? CreateDynamicFunction (C ,
NewTarget, generator , parameterArgs ,
bodyArg )。
注
27.3.2 GeneratorFunction 构造函数的属性
GeneratorFunction 构造函数 :
是一个标准内置 函数对象 ,继承自 Function 构造函数 。
拥有 [[Prototype]] 内部槽,其值为 %Function% 。
拥有
"length" 属性,其值为 1 𝔽 。
拥有 "name" 属性,其值为
"GeneratorFunction" 。
拥有以下属性:
27.3.2.1 GeneratorFunction.prototype
GeneratorFunction.prototype
的初始值为 GeneratorFunction
原型对象 。
该属性具有属性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
27.3.3 GeneratorFunction 原型对象的属性
GeneratorFunction 原型对象 :
27.3.3.1 GeneratorFunction.prototype.constructor
GeneratorFunction.prototype.constructor
的初始值为 %GeneratorFunction% 。
该属性具有属性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : true }。
27.3.3.2 GeneratorFunction.prototype.prototype
GeneratorFunction.prototype.prototype
的初始值为 %GeneratorPrototype% 。
该属性具有属性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : true }。
27.3.3.3 GeneratorFunction.prototype [ %Symbol.toStringTag% ]
%Symbol.toStringTag% 属性的初始值为字符串
"GeneratorFunction" 。
该属性具有属性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : true }。
27.3.4 GeneratorFunction 实例
每个 GeneratorFunction 实例都是一个 ECMAScript 函数对象 ,并拥有 表 30
中列出的内部槽。所有此类实例的 [[IsClassConstructor]] 内部槽的值均为
false 。
每个 GeneratorFunction 实例拥有以下自有属性:
27.3.4.1 length
Function 实例的 "length" 属性规范,见 20.2.4.1 ,同样适用于
GeneratorFunction 实例。
27.3.4.2 name
Function 实例的 "name" 属性规范,见 20.2.4.2 ,同样适用于
GeneratorFunction 实例。
27.3.4.3 prototype
每当创建一个 GeneratorFunction 实例时,还会创建另一个 普通对象 ,作为生成器函数 "prototype"
属性的初始值。该 prototype 属性的值用于在 generator 函数对象 通过 [[Call]]
被调用时,初始化新创建的 Generator 的 [[Prototype]] 内部槽。
该属性具有属性 { [[Writable]] :
true , [[Enumerable]] : false ,
[[Configurable]] : false }。
注
与 Function 实例不同,GeneratorFunction 的 "prototype" 属性所指向的对象没有
"constructor" 属性,其值为该 GeneratorFunction 实例。
27.4 AsyncGeneratorFunction 对象
AsyncGeneratorFunction 通常是通过求值 AsyncGeneratorDeclaration 、AsyncGeneratorExpression 和
AsyncGeneratorMethod
语法产生式创建的函数。也可以通过调用 %AsyncGeneratorFunction%
内部对象创建。
27.4.1 AsyncGeneratorFunction 构造函数
AsyncGeneratorFunction 构造函数 :
即 %AsyncGeneratorFunction% 。
是 Function
的子类。
被作为函数而不是 构造函数 调用时,会创建并初始化一个新的
AsyncGeneratorFunction。因此,函数调用 AsyncGeneratorFunction (...)
等价于用相同参数的对象创建表达式
new AsyncGeneratorFunction (...)
。
可以用作类定义的 extends
子句的值。意图继承指定 AsyncGeneratorFunction 行为的子类 构造函数 ,必须通过
super
调用 AsyncGeneratorFunction 构造函数 创建并初始化子类实例,并赋予其内置
AsyncGeneratorFunction 行为所需的内部槽。所有 ECMAScript 定义 async generator 函数对象
的语法形式,都会创建 AsyncGeneratorFunction 的直接实例。没有语法手段可以创建 AsyncGeneratorFunction 子类的实例。
27.4.1.1 AsyncGeneratorFunction ( ...parameterArgs ,
bodyArg )
最后一个参数(如果有)指定异步生成器函数的主体(可执行代码);之前的所有参数指定形式参数。
该函数被调用时执行以下步骤:
令 C 为 当前函数对象 。
如果 bodyArg 不存在,则将 bodyArg 设为一个空字符串。
返回 ? CreateDynamicFunction (C ,
NewTarget, async-generator , parameterArgs ,
bodyArg )。
注
27.4.2 AsyncGeneratorFunction 构造函数的属性
AsyncGeneratorFunction 构造函数 :
是一个标准内置 函数对象 ,继承自 Function 构造函数 。
拥有 [[Prototype]] 内部槽,其值为 %Function% 。
拥有 "length" 属性,其值为
1 𝔽 。
拥有 "name" 属性,其值为
"AsyncGeneratorFunction" 。
拥有以下属性:
27.4.2.1 AsyncGeneratorFunction.prototype
AsyncGeneratorFunction.prototype
的初始值为 AsyncGeneratorFunction
原型对象 。
该属性具有属性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
27.4.3 AsyncGeneratorFunction 原型对象的属性
AsyncGeneratorFunction 原型对象 :
27.4.3.1 AsyncGeneratorFunction.prototype.constructor
AsyncGeneratorFunction.prototype.constructor
的初始值为 %AsyncGeneratorFunction% 。
该属性具有属性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : true }。
27.4.3.2 AsyncGeneratorFunction.prototype.prototype
AsyncGeneratorFunction.prototype.prototype
的初始值为 %AsyncGeneratorPrototype% 。
该属性具有属性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : true }。
27.4.3.3 AsyncGeneratorFunction.prototype [ %Symbol.toStringTag%
]
%Symbol.toStringTag% 属性的初始值为字符串
"AsyncGeneratorFunction" 。
该属性具有属性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : true }。
27.4.4 AsyncGeneratorFunction 实例
每个 AsyncGeneratorFunction 实例都是一个 ECMAScript 函数对象 ,并拥有 表 30
中列出的内部槽。所有此类实例的 [[IsClassConstructor]] 内部槽的值均为
false 。
每个 AsyncGeneratorFunction 实例拥有以下自有属性:
27.4.4.1 length
"length" 属性的值是一个 整数
Number ,表示异步生成器函数通常期望的参数个数。不过,语言允许使用其他数量的参数调用该函数。调用时参数数量与
"length" 属性值不一致时 AsyncGeneratorFunction 的表现取决于具体函数。
该属性具有属性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : true }。
27.4.4.2 name
Function 实例的 "name" 属性规范,见 20.2.4.2 ,同样适用于
AsyncGeneratorFunction 实例。
27.4.4.3 prototype
每当创建一个 AsyncGeneratorFunction 实例时,还会创建另一个 普通对象 ,作为异步生成器函数
"prototype" 属性的初始值。该 prototype 属性的值用于在 async generator 函数对象
通过 [[Call]] 被调用时,初始化新创建的 AsyncGenerator 的 [[Prototype]] 内部槽。
该属性具有属性 { [[Writable]] :
true , [[Enumerable]] : false ,
[[Configurable]] : false }。
注
与普通 Function 实例不同,AsyncGeneratorFunction 的 "prototype" 属性所指向的对象没有
"constructor" 属性,其值为该 AsyncGeneratorFunction 实例。
27.5 Generator 对象
Generator 是通过调用生成器函数创建的,同时符合 迭代器接口 和 可迭代接口 。
Generator 实例直接继承自创建该实例的生成器函数的 "prototype" 属性的初始值。Generator 实例间接继承自 %GeneratorPrototype% 。
27.5.1 %GeneratorPrototype% 对象
%GeneratorPrototype% 对象:
即 %GeneratorFunction.prototype.prototype% 。
是一个 普通对象 。
不是 Generator 实例,没有 [[GeneratorState]] 内部槽。
拥有 [[Prototype]] 内部槽,其值为 %Iterator.prototype% 。
具有所有 Generator 实例间接继承的属性。
27.5.1.1 %GeneratorPrototype%.constructor
%GeneratorPrototype% .constructor
的初始值为 %GeneratorFunction.prototype% 。
该属性具有属性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : true }。
27.5.1.2 %GeneratorPrototype%.next ( value )
返回 ? GeneratorResume (this
value, value , empty ).
27.5.1.3 %GeneratorPrototype%.return ( value )
该方法被调用时执行以下步骤:
令 g 为 this 值。
令 C 为 ReturnCompletion (value )。
返回 ? GeneratorResumeAbrupt (g ,
C , empty ).
27.5.1.4 %GeneratorPrototype%.throw ( exception )
该方法被调用时执行以下步骤:
令 g 为 this 值。
令 C 为 ThrowCompletion (exception )。
返回 ? GeneratorResumeAbrupt (g ,
C , empty ).
27.5.1.5 %GeneratorPrototype% [ %Symbol.toStringTag% ]
%Symbol.toStringTag% 属性的初始值为字符串
"Generator" 。
该属性具有属性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : true }。
27.5.2 Generator 实例的属性
Generator 实例最初使用 表 93 中描述的内部槽创建。
表 93:Generator 实例的内部槽
内部槽
类型
描述
[[GeneratorState]]
suspended-start 、
suspended-yield 、executing 或
completed
当前 generator 的执行状态。
[[GeneratorContext]]
一个 执行上下文
执行该 generator 代码时所用的 执行上下文 。
[[GeneratorBrand]]
字符串或 empty
用于区分不同类型 generator 的标记。由 ECMAScript 源文本
声明的 generator 的 [[GeneratorBrand]] 总是
empty 。
27.5.3 Generator 抽象操作
27.5.3.1 GeneratorStart ( generator ,
generatorBody )
抽象操作 GeneratorStart 接收参数 generator (一个 Generator)和 generatorBody (FunctionBody 解析节点 或无参数的 抽象闭包 ),返回
unused 。调用时执行以下步骤:
断言 :
generator .[[GeneratorState]] 的值为
suspended-start 。
令 genContext 为 当前执行上下文 。
将 genContext 的 Generator 组件设为 generator 。
令 closure 为一个新的 抽象闭包 ,无参数,捕获
generatorBody ,调用时执行以下步骤:
令 acGenContext 为 当前执行上下文 。
令 acGenerator 为 acGenContext 的 Generator 组件。
如果 generatorBody 是 解析节点 ,则
令 result 为 Completion (Evaluation of
generatorBody ).
否则,
断言 :
generatorBody 是一个无参数的 抽象闭包 。
令 result 为 Completion (generatorBody ())。
断言 :如果执行到这里,generator
要么抛出了异常,要么进行了隐式或显式 return。
从 执行上下文栈 移除
acGenContext ,并恢复 执行上下文 ,该上下文现在位于
执行上下文栈 顶部,作为
当前执行上下文 。
设置 acGenerator .[[GeneratorState]] 为
completed 。
注:一旦 generator 进入 completed 状态,就不会再离开,其关联的 执行上下文 也不会被恢复。此时与
acGenerator 相关的执行状态可以被丢弃。
如果 result 是 正常完成 ,则
令 resultValue 为 undefined 。
否则如果 result 是 return
完成 ,则
令 resultValue 为 result .[[Value]] 。
否则,
断言 :result 是
throw
完成 。
返回 ? result 。
返回 CreateIteratorResultObject (resultValue ,
true ).
设置 genContext 的代码求值状态,使得该 执行上下文 恢复时会调用
closure ,且无参数。
设置 generator .[[GeneratorContext]] 为
genContext 。
返回 unused 。
27.5.3.2 GeneratorValidate ( generator ,
generatorBrand )
抽象操作 GeneratorValidate 接收参数 generator (一个 ECMAScript 语言值 )和
generatorBrand (字符串或 empty ),返回 正常完成包含
suspended-start 、suspended-yield 或
completed 之一,或 抛出完成 。调用时执行以下步骤:
执行 ? RequireInternalSlot (generator ,
[[GeneratorState]] ).
执行 ? RequireInternalSlot (generator ,
[[GeneratorBrand]] ).
如果 generator .[[GeneratorBrand]] 不等于
generatorBrand ,抛出 TypeError 异常。
断言 :
generator 还有 [[GeneratorContext]] 内部槽。
令 state 为 generator .[[GeneratorState]] 。
如果 state 为 executing ,抛出
TypeError 异常。
返回 state 。
27.5.3.3 GeneratorResume ( generator ,
value , generatorBrand )
抽象操作 GeneratorResume 接收参数 generator (一个 ECMAScript 语言值 )、
value (一个 ECMAScript 语言值 或
empty )、generatorBrand (字符串或
empty ),返回 正常完成包含 的 ECMAScript 语言值 或 抛出完成 。调用时执行以下步骤:
令 state 为 ? GeneratorValidate (generator ,
generatorBrand ).
如果 state 为 completed ,返回 CreateIteratorResultObject (undefined ,
true ).
断言 :
state 为 suspended-start 或
suspended-yield 。
令 genContext 为 generator .[[GeneratorContext]] 。
令 methodContext 为 当前执行上下文 。
挂起 methodContext 。
设置 generator .[[GeneratorState]] 为
executing 。
将 genContext 压入 执行上下文栈 ;genContext
现在是 当前执行上下文 。
恢复 genContext 的挂起执行 ,以 NormalCompletion (value )
作为挂起操作的结果。令 result 为恢复运算返回的值。
断言 :
执行到这里时,genContext 已从 执行上下文栈
移除,methodContext 是当前 执行上下文 。
返回 ? result 。
27.5.3.4 GeneratorResumeAbrupt ( generator ,
abruptCompletion , generatorBrand )
抽象操作 GeneratorResumeAbrupt 接收参数 generator (一个
ECMAScript 语言值 ),
abruptCompletion (一个 return
完成 或 throw
完成 ),
以及 generatorBrand (字符串或 empty ),返回 正常完成包含 的 ECMAScript 语言值 或 抛出完成 。调用时执行以下步骤:
令 state 为 ? GeneratorValidate (generator ,
generatorBrand )。
如果 state 为 suspended-start ,则
设置 generator .[[GeneratorState]] 为
completed 。
注:一旦 generator 进入 completed 状态,就不会再离开,其关联的 执行上下文 也不会被恢复。此时与
generator 相关的执行状态可以被丢弃。
设置 state 为 completed 。
如果 state 为 completed ,则
如果 abruptCompletion 是 return
完成 ,则
返回 CreateIteratorResultObject (abruptCompletion .[[Value]] , true )。
返回 ? abruptCompletion 。
断言 :
state 为 suspended-yield 。
令 genContext 为 generator .[[GeneratorContext]] 。
令 methodContext 为 当前执行上下文 。
挂起 methodContext 。
设置 generator .[[GeneratorState]] 为
executing 。
将 genContext 压入 执行上下文栈 ;genContext
现在是 当前执行上下文 。
恢复 genContext 的挂起执行 ,以
abruptCompletion 作为挂起操作的结果。令 result 为恢复运算返回的 Completion
Record 。
断言 :
执行到这里时,genContext 已从 执行上下文栈
移除,methodContext 是当前 执行上下文 。
返回 ? result 。
27.5.3.5 GetGeneratorKind ( )
抽象操作 GetGeneratorKind 不带参数,返回
non-generator 、sync 或
async 。调用时执行以下步骤:
令 genContext 为 当前执行上下文 。
如果 genContext 没有 Generator 组件,返回 non-generator 。
令 generator 为 genContext 的 Generator 组件。
如果 generator 有 [[AsyncGeneratorState]] 内部槽,返回
async 。
否则,返回 sync 。
27.5.3.6 GeneratorYield ( iteratorResult )
抽象操作 GeneratorYield 接收参数 iteratorResult (一个符合 IteratorResult 接口 的对象),返回
正常完成包含 的 ECMAScript 语言值 或 异常完成 。调用时执行以下步骤:
令 genContext 为 当前执行上下文 。
断言 :
genContext 是 generator 的 执行上下文 。
令 generator 为 genContext 的 Generator 组件的值。
断言 :
GetGeneratorKind () 为
sync 。
设置 generator .[[GeneratorState]] 为
suspended-yield 。
从 执行上下文栈 移除
genContext ,并恢复 执行上下文 ,该上下文现在位于
执行上下文栈 顶部,作为 当前执行上下文 。
令 callerContext 为 当前执行上下文 。
恢复 callerContext ,传递 NormalCompletion (iteratorResult )。
如果 genContext 以后再次被恢复,令 resumptionValue 为恢复时携带的 Completion
Record 。
断言 :如果执行到这里,genContext 又成为 当前执行上下文 。
返回 resumptionValue 。
27.5.3.7 Yield ( value )
抽象操作 Yield 接收参数 value (一个 ECMAScript
语言值 ),返回 正常完成包含 的 ECMAScript 语言值 或 异常完成 。调用时执行以下步骤:
令 generatorKind 为 GetGeneratorKind ()。
如果 generatorKind 为 async ,返回 ? AsyncGeneratorYield (? Await (value ))。
否则,返回 ? GeneratorYield (CreateIteratorResultObject (value ,
false ))。
27.5.3.8 CreateIteratorFromClosure ( closure ,
generatorBrand , generatorPrototype [ , extraSlots ] )
抽象操作 CreateIteratorFromClosure 接收参数 closure (一个无参数的 抽象闭包 ),
generatorBrand (字符串或 empty ),
generatorPrototype (一个对象),以及可选参数 extraSlots (List ,其元素为内部槽名称),返回一个
Generator。调用时执行以下步骤:
注:closure 可以包含 Yield 操作,用于 yield 一个 IteratorResult 对象 。
如果 extraSlots 不存在,则将 extraSlots 设为一个新的空 List 。
令 internalSlotsList 为 list-concatenation (extraSlots
和 « [[GeneratorState]] , [[GeneratorContext]] , [[GeneratorBrand]] »)。
令 generator 为 OrdinaryObjectCreate (generatorPrototype ,
internalSlotsList )。
设置 generator .[[GeneratorBrand]] 为
generatorBrand 。
设置 generator .[[GeneratorState]] 为
suspended-start 。
令 callerContext 为 当前执行上下文 。
令 calleeContext 为一个新的 执行上下文 。
设置 calleeContext 的 Function 为 null 。
设置 calleeContext 的 Realm 为 当前 Realm Record 。
设置 calleeContext 的 ScriptOrModule 为 callerContext 的
ScriptOrModule。
如果 callerContext 尚未挂起,则挂起 callerContext 。
将 calleeContext 压入 执行上下文栈 ;calleeContext
现在是 当前执行上下文 。
执行 GeneratorStart (generator ,
closure )。
从 执行上下文栈 移除
calleeContext ,并恢复 callerContext 作为 当前执行上下文 。
返回 generator 。
27.6 AsyncGenerator 对象
AsyncGenerator 是通过调用异步生成器函数创建的,并同时符合
异步迭代器接口 和
异步可迭代接口 。
AsyncGenerator 实例直接继承自创建该实例的异步生成器函数 "prototype" 属性的初始值。AsyncGenerator 实例间接继承自
%AsyncGeneratorPrototype% 。
27.6.1 %AsyncGeneratorPrototype% 对象
%AsyncGeneratorPrototype% 对象:
即 %AsyncGeneratorFunction.prototype.prototype% 。
是一个 普通对象 。
不是 AsyncGenerator 实例,并且没有 [[AsyncGeneratorState]] 内部槽。
拥有 [[Prototype]] 内部槽,其值为 %AsyncIteratorPrototype% 。
具有所有 AsyncGenerator 实例间接继承的属性。
27.6.1.1 %AsyncGeneratorPrototype%.constructor
%AsyncGeneratorPrototype% .constructor
的初始值为 %AsyncGeneratorFunction.prototype% 。
该属性具有属性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : true }。
27.6.1.2 %AsyncGeneratorPrototype%.next ( value )
令 generator 为 this 值。
令 promiseCapability 为 ! NewPromiseCapability (%Promise% )。
令 result 为 Completion (AsyncGeneratorValidate (generator ,
empty ))。
IfAbruptRejectPromise (result ,
promiseCapability )。
令 state 为 generator .[[AsyncGeneratorState]] 。
如果 state 为 completed ,则
令 iteratorResult 为 CreateIteratorResultObject (undefined ,
true )。
执行 ! Call (promiseCapability .[[Resolve]] , undefined , «
iteratorResult »)。
返回 promiseCapability .[[Promise]] 。
令 completion 为 NormalCompletion (value )。
执行 AsyncGeneratorEnqueue (generator ,
completion , promiseCapability )。
如果 state 为 suspended-start 或
suspended-yield ,则
执行 AsyncGeneratorResume (generator ,
completion )。
否则,
断言 :state 为
executing 或 draining-queue 。
返回 promiseCapability .[[Promise]] 。
27.6.1.3 %AsyncGeneratorPrototype%.return ( value )
令 generator 为 this 值。
令 promiseCapability 为 ! NewPromiseCapability (%Promise% )。
令 result 为 Completion (AsyncGeneratorValidate (generator ,
empty ))。
IfAbruptRejectPromise (result ,
promiseCapability )。
令 completion 为 ReturnCompletion (value )。
执行 AsyncGeneratorEnqueue (generator ,
completion , promiseCapability )。
令 state 为 generator .[[AsyncGeneratorState]] 。
如果 state 为 suspended-start 或
completed ,则
设置 generator .[[AsyncGeneratorState]] 为
draining-queue 。
执行 AsyncGeneratorAwaitReturn (generator )。
否则如果 state 为 suspended-yield ,则
执行 AsyncGeneratorResume (generator ,
completion )。
否则,
断言 :state 为
executing 或 draining-queue 。
返回 promiseCapability .[[Promise]] 。
27.6.1.4 %AsyncGeneratorPrototype%.throw ( exception
)
令 generator 为 this 值。
令 promiseCapability 为 ! NewPromiseCapability (%Promise% )。
令 result 为 Completion (AsyncGeneratorValidate (generator ,
empty ))。
IfAbruptRejectPromise (result ,
promiseCapability )。
令 state 为 generator .[[AsyncGeneratorState]] 。
如果 state 为 suspended-start ,则
设置 generator .[[AsyncGeneratorState]] 为
completed 。
设置 state 为 completed 。
如果 state 为 completed ,则
执行 ! Call (promiseCapability .[[Reject]] , undefined , «
exception »)。
返回 promiseCapability .[[Promise]] 。
令 completion 为 ThrowCompletion (exception )。
执行 AsyncGeneratorEnqueue (generator ,
completion , promiseCapability )。
如果 state 为 suspended-yield ,则
执行 AsyncGeneratorResume (generator ,
completion )。
否则,
断言 :state 为
executing 或 draining-queue 。
返回 promiseCapability .[[Promise]] 。
27.6.1.5 %AsyncGeneratorPrototype% [ %Symbol.toStringTag% ]
%Symbol.toStringTag% 属性的初始值为字符串
"AsyncGenerator" 。
该属性具有属性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : true }。
27.6.2 AsyncGenerator 实例的属性
AsyncGenerator 实例最初使用如下内部槽创建:
表 94:AsyncGenerator 实例的内部槽
内部槽
类型
描述
[[AsyncGeneratorState]]
suspended-start 、
suspended-yield 、executing 、
draining-queue 或 completed
当前异步生成器的执行状态。
[[AsyncGeneratorContext]]
一个 执行上下文
执行该异步生成器代码时所用的 执行上下文 。
[[AsyncGeneratorQueue]]
一个 List
,元素为 AsyncGeneratorRequest
记录
记录
,表示恢复异步生成器的请求。除了状态转换期间,只有当 [[AsyncGeneratorState]]
为 executing 或 draining-queue
时该队列才非空。
[[GeneratorBrand]]
字符串或 empty
用于区分不同类型异步生成器的标记。由 ECMAScript 源文本 声明的异步生成器的 [[GeneratorBrand]] 总是 empty 。
27.6.3 AsyncGenerator 抽象操作
27.6.3.1 AsyncGeneratorRequest 记录
AsyncGeneratorRequest 是一个
记录 值,用于存储如何恢复异步生成器的信息,并包含兑现或拒绝相应
promise 的能力。
它们具有以下字段:
表 95:AsyncGeneratorRequest 记录 字段
27.6.3.2 AsyncGeneratorStart ( generator ,
generatorBody )
抽象操作 AsyncGeneratorStart 接收参数 generator (一个 AsyncGenerator)和
generatorBody (FunctionBody 解析节点 或无参数的 抽象闭包 ),返回
unused 。调用时执行以下步骤:
断言 :
generator .[[AsyncGeneratorState]] 为
suspended-start 。
令 genContext 为 当前执行上下文 。
将 genContext 的 Generator 组件设为 generator 。
令 closure 为一个新的 抽象闭包 ,无参数,捕获
generatorBody ,调用时执行以下步骤:
令 acGenContext 为 当前执行上下文 。
令 acGenerator 为 acGenContext 的 Generator 组件。
如果 generatorBody 是 解析节点 ,则
令 result 为 Completion (Evaluation of
generatorBody )。
否则,
断言 :
generatorBody 是一个无参数的 抽象闭包 。
令 result 为 Completion (generatorBody ())。
断言 :如果执行到这里,异步生成器要么抛出了异常,要么进行了隐式或显式
return。
从 执行上下文栈 移除
acGenContext ,并恢复 执行上下文 ,该上下文现在位于
执行上下文栈 顶部,作为
当前执行上下文 。
设置 acGenerator .[[AsyncGeneratorState]] 为
draining-queue 。
如果 result 是 正常完成 ,则将
result 设为 NormalCompletion (undefined )。
如果 result 是 return
完成 ,则将 result 设为 NormalCompletion (result .[[Value]] )。
执行 AsyncGeneratorCompleteStep (acGenerator ,
result , true )。
执行 AsyncGeneratorDrainQueue (acGenerator )。
返回 undefined 。
设置 genContext 的代码求值状态,使得该 执行上下文 恢复时会调用
closure ,且无参数。
设置 generator .[[AsyncGeneratorContext]] 为
genContext 。
设置 generator .[[AsyncGeneratorQueue]] 为一个新的空
List 。
返回 unused 。
27.6.3.3 AsyncGeneratorValidate ( generator ,
generatorBrand )
抽象操作 AsyncGeneratorValidate 接收参数 generator (一个
ECMAScript 语言值 )和
generatorBrand (字符串或 empty ),返回 正常完成包含
unused ,或 抛出完成 。调用时执行以下步骤:
执行 ? RequireInternalSlot (generator ,
[[AsyncGeneratorContext]] )。
执行 ? RequireInternalSlot (generator ,
[[AsyncGeneratorState]] )。
执行 ? RequireInternalSlot (generator ,
[[AsyncGeneratorQueue]] )。
如果 generator .[[GeneratorBrand]] 不等于
generatorBrand ,抛出 TypeError 异常。
返回 unused 。
27.6.3.4 AsyncGeneratorEnqueue ( generator ,
completion , promiseCapability )
抽象操作 AsyncGeneratorEnqueue 接收参数 generator (一个
AsyncGenerator)、completion (一个 Completion Record )和
promiseCapability (一个 PromiseCapability
记录 ),返回 unused 。调用时执行以下步骤:
令 request 为 AsyncGeneratorRequest
{ [[Completion]] : completion , [[Capability]] : promiseCapability }。
将 request 添加到 generator .[[AsyncGeneratorQueue]] 末尾。
返回 unused 。
27.6.3.5 AsyncGeneratorCompleteStep ( generator ,
completion , done [ , realm ] )
抽象操作 AsyncGeneratorCompleteStep 接收参数 generator (一个
AsyncGenerator)、completion (一个 Completion
Record )、done (一个布尔值),以及可选参数 realm (一个 Realm
Record ),返回 unused 。调用时执行以下步骤:
断言 :
generator .[[AsyncGeneratorQueue]] 不为空。
令 next 为 generator .[[AsyncGeneratorQueue]] 的第一个元素。
从 generator .[[AsyncGeneratorQueue]] 中移除第一个元素。
令 promiseCapability 为 next .[[Capability]] 。
令 value 为 completion .[[Value]] 。
如果 completion 是 throw 完成 ,则
执行 ! Call (promiseCapability .[[Reject]] , undefined , «
value »)。
否则,
断言 :completion 是 正常完成 。
如果 realm 存在,则
令 oldRealm 为 当前执行上下文 的
Realm 。
设置 当前执行上下文 的
Realm 为 realm 。
令 iteratorResult 为 CreateIteratorResultObject (value ,
done )。
设置 当前执行上下文 的
Realm 为 oldRealm 。
否则,
令 iteratorResult 为 CreateIteratorResultObject (value ,
done )。
执行 ! Call (promiseCapability .[[Resolve]] , undefined , «
iteratorResult »)。
返回 unused 。
27.6.3.6 AsyncGeneratorResume ( generator ,
completion )
抽象操作 AsyncGeneratorResume 接收参数 generator (一个 AsyncGenerator)和
completion (一个 Completion
Record ),返回 unused 。调用时执行以下步骤:
断言 :
generator .[[AsyncGeneratorState]] 为
suspended-start 或 suspended-yield 。
令 genContext 为 generator .[[AsyncGeneratorContext]] 。
令 callerContext 为 当前执行上下文 。
挂起 callerContext 。
设置 generator .[[AsyncGeneratorState]] 为
executing 。
将 genContext 压入 执行上下文栈 ;genContext
现在为 当前执行上下文 。
恢复 genContext 的挂起执行 ,以
completion 作为挂起操作的结果。令 result 为恢复运算返回的 Completion
Record 。
断言 :
result 绝不会是 异常完成 。
断言 :
执行到这里时,genContext 已从 执行上下文栈
移除,callerContext 是当前 执行上下文 。
返回 unused 。
27.6.3.7 AsyncGeneratorUnwrapYieldResumption (
resumptionValue )
抽象操作 AsyncGeneratorUnwrapYieldResumption 接收参数 resumptionValue (一个 Completion
Record ),返回 正常完成包含 的 ECMAScript 语言值 或 异常完成 。调用时执行以下步骤:
如果 resumptionValue 不是 return 完成 ,返回
? resumptionValue 。
令 awaited 为 Completion (Await (resumptionValue .[[Value]] ))。
如果 awaited 是 throw
完成 ,返回 ? awaited 。
断言 :
awaited 是 正常完成 。
返回 ReturnCompletion (awaited .[[Value]] )。
27.6.3.8 AsyncGeneratorYield ( value )
抽象操作 AsyncGeneratorYield 接收参数 value (一个 ECMAScript 语言值 ),返回 正常完成包含 的 ECMAScript 语言值 或 异常完成 。调用时执行以下步骤:
令 genContext 为 当前执行上下文 。
断言 :
genContext 是 generator 的 执行上下文 。
令 generator 为 genContext 的 Generator 组件的值。
断言 :
GetGeneratorKind () 为
async 。
令 completion 为 NormalCompletion (value )。
断言 :
执行上下文栈 至少有两个元素。
令 previousContext 为 执行上下文栈
的倒数第二个元素。
令 previousRealm 为 previousContext 的 Realm 。
执行 AsyncGeneratorCompleteStep (generator ,
completion , false , previousRealm )。
令 queue 为 generator .[[AsyncGeneratorQueue]] 。
如果 queue 不为空,则
注:执行继续,不会挂起 generator。
令 toYield 为 queue 的第一个元素。
令 resumptionValue 为 Completion (toYield .[[Completion]] )。
返回 ? AsyncGeneratorUnwrapYieldResumption (resumptionValue )。
否则,
设置 generator .[[AsyncGeneratorState]] 为
suspended-yield 。
从 执行上下文栈 移除
genContext ,并恢复 执行上下文 ,该上下文现在位于
执行上下文栈 顶部,作为
当前执行上下文 。
令 callerContext 为 当前执行上下文 。
恢复 callerContext ,传递 undefined 。如果
genContext 以后再次被恢复,令 resumptionValue
为恢复时携带的 Completion
Record 。
断言 :如果执行到这里,genContext 又成为
当前执行上下文 。
返回 ? AsyncGeneratorUnwrapYieldResumption (resumptionValue )。
27.6.3.9 AsyncGeneratorAwaitReturn ( generator )
抽象操作 AsyncGeneratorAwaitReturn 接收参数 generator (一个 AsyncGenerator),返回
unused 。调用时执行以下步骤:
断言 :
generator .[[AsyncGeneratorState]] 为
draining-queue 。
令 queue 为 generator .[[AsyncGeneratorQueue]] 。
断言 :
queue 不为空。
令 next 为 queue 的第一个元素。
令 completion 为 Completion (next .[[Completion]] )。
断言 :
completion 是 return
完成 。
令 promiseCompletion 为 Completion (PromiseResolve (%Promise% ,
completion .[[Value]] ))。
如果 promiseCompletion 是 异常完成 ,则
执行 AsyncGeneratorCompleteStep (generator ,
promiseCompletion , true )。
执行 AsyncGeneratorDrainQueue (generator )。
返回 unused 。
断言 :
promiseCompletion 是 正常完成 。
令 promise 为 promiseCompletion .[[Value]] 。
令 fulfilledClosure 为一个新的 抽象闭包 ,参数为
(value ),捕获 generator ,调用时执行以下步骤:
断言 :generator .[[AsyncGeneratorState]] 为
draining-queue 。
令 result 为 NormalCompletion (value )。
执行 AsyncGeneratorCompleteStep (generator ,
result , true )。
执行 AsyncGeneratorDrainQueue (generator )。
返回 undefined 。
令 onFulfilled 为 CreateBuiltinFunction (fulfilledClosure ,
1, "" , « »)。
令 rejectedClosure 为一个新的 抽象闭包 ,参数为
(reason ),捕获 generator ,调用时执行以下步骤:
断言 :generator .[[AsyncGeneratorState]] 为
draining-queue 。
令 result 为 ThrowCompletion (reason )。
执行 AsyncGeneratorCompleteStep (generator ,
result , true )。
执行 AsyncGeneratorDrainQueue (generator )。
返回 undefined 。
令 onRejected 为 CreateBuiltinFunction (rejectedClosure ,
1, "" , « »)。
执行 PerformPromiseThen (promise ,
onFulfilled , onRejected )。
返回 unused 。
27.6.3.10 AsyncGeneratorDrainQueue ( generator )
抽象操作 AsyncGeneratorDrainQueue 接收参数 generator (一个 AsyncGenerator),返回
unused 。它会持续清空 generator 的 AsyncGeneratorQueue,直到遇到一个持有 AsyncGeneratorRequest ,并包含
return 完成
的请求。调用时执行以下步骤:
断言 :
generator .[[AsyncGeneratorState]] 为
draining-queue 。
令 queue 为 generator .[[AsyncGeneratorQueue]] 。
重复,条件是 queue 不为空,
令 next 为 queue 的第一个元素。
令 completion 为 Completion (next .[[Completion]] )。
如果 completion 是 return
完成 ,则
执行 AsyncGeneratorAwaitReturn (generator )。
返回 unused 。
否则,
如果 completion 是 正常完成 ,则
将 completion 设为 NormalCompletion (undefined )。
执行 AsyncGeneratorCompleteStep (generator ,
completion , true )。
设置 generator .[[AsyncGeneratorState]] 为
completed 。
返回 unused 。
27.6.3.11 CreateAsyncIteratorFromClosure ( closure ,
generatorBrand , generatorPrototype )
抽象操作 CreateAsyncIteratorFromClosure 接收参数 closure (一个无参数的 抽象闭包 )、
generatorBrand (字符串或
empty )、generatorPrototype (一个对象),返回一个
AsyncGenerator。调用时执行以下步骤:
注:closure 可以包含 Await 操作和 Yield
操作用于 yield 一个 IteratorResult 对象 。
令 internalSlotsList 为 « [[AsyncGeneratorState]] ,
[[AsyncGeneratorContext]] , [[AsyncGeneratorQueue]] , [[GeneratorBrand]] »。
令 generator 为 OrdinaryObjectCreate (generatorPrototype ,
internalSlotsList )。
设置 generator .[[GeneratorBrand]] 为
generatorBrand 。
设置 generator .[[AsyncGeneratorState]] 为
suspended-start 。
令 callerContext 为 当前执行上下文 。
令 calleeContext 为一个新的 执行上下文 。
设置 calleeContext 的 Function 为 null 。
设置 calleeContext 的 Realm 为 当前 Realm Record 。
设置 calleeContext 的 ScriptOrModule 为 callerContext 的
ScriptOrModule。
如果 callerContext 尚未挂起,则挂起 callerContext 。
将 calleeContext 压入 执行上下文栈 ;calleeContext
现在为 当前执行上下文 。
执行 AsyncGeneratorStart (generator ,
closure )。
从 执行上下文栈 移除
calleeContext ,并恢复 callerContext 作为 当前执行上下文 。
返回 generator 。
27.7 AsyncFunction 对象
AsyncFunction 通常是通过求值 AsyncFunctionDeclaration 、AsyncFunctionExpression 、
AsyncMethod 和 AsyncArrowFunction 创建的函数。也可以通过调用
%AsyncFunction% 内部对象创建。
27.7.1 AsyncFunction 构造函数
AsyncFunction 构造函数 :
即 %AsyncFunction% 。
是 Function
的子类。
被作为函数而不是 构造函数 调用时,会创建并初始化一个新的 AsyncFunction。因此,函数调用
AsyncFunction(…)
等价于用相同参数的对象创建表达式 new AsyncFunction(…)
。
可以用作类定义的 extends
子句的值。意图继承指定 AsyncFunction 行为的子类 构造函数 ,必须通过 super
调用
AsyncFunction 构造函数 创建并初始化子类实例,并赋予其内置 async function 行为所需的内部槽。所有
ECMAScript 定义 async 函数对象 的语法形式,都会创建 AsyncFunction
的直接实例。没有语法手段可以创建 AsyncFunction 子类的实例。
27.7.1.1 AsyncFunction ( ...parameterArgs ,
bodyArg )
最后一个参数(如果有)指定异步函数的函数体(可执行代码);之前的所有参数指定形式参数。
该函数被调用时执行以下步骤:
令 C 为 当前函数对象 。
如果 bodyArg 未传入,则将 bodyArg 设为空字符串。
返回 ? CreateDynamicFunction (C ,
NewTarget, async , parameterArgs ,
bodyArg )。
注
27.7.2 AsyncFunction 构造函数的属性
AsyncFunction 构造函数 :
是一个标准内置 函数对象 ,继承自 Function 构造函数 。
拥有 [[Prototype]] 内部槽,其值为 %Function% 。
拥有 "length"
属性,其值为 1 𝔽 。
拥有 "name" 属性,其值为 "AsyncFunction" 。
拥有以下属性:
27.7.2.1 AsyncFunction.prototype
AsyncFunction.prototype
的初始值为 AsyncFunction 原型对象 。
该属性具有属性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
27.7.3 AsyncFunction 原型对象的属性
AsyncFunction 原型对象 :
27.7.3.1 AsyncFunction.prototype.constructor
AsyncFunction.prototype.constructor
的初始值为 %AsyncFunction% 。
该属性具有属性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : true }。
27.7.3.2 AsyncFunction.prototype [ %Symbol.toStringTag% ]
%Symbol.toStringTag% 属性的初始值为字符串
"AsyncFunction" 。
该属性具有属性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : true }。
27.7.4 AsyncFunction 实例
每个 AsyncFunction 实例都是一个 ECMAScript 函数对象 ,并拥有 表 30
中列出的内部槽。所有此类实例的 [[IsClassConstructor]] 内部槽的值均为
false 。AsyncFunction 实例不是 构造函数 ,没有 [[Construct]]
内部方法。AsyncFunction 实例没有 prototype 属性,因为它们不可构造。
每个 AsyncFunction 实例拥有以下自有属性:
27.7.4.1 length
Function 实例的 "length" 属性规范,见 20.2.4.1 ,同样适用于 AsyncFunction
实例。
27.7.4.2 name
Function 实例的 "name" 属性规范,见 20.2.4.2 ,同样适用于
AsyncFunction 实例。
27.7.5 异步函数的抽象操作
27.7.5.1 AsyncFunctionStart ( promiseCapability ,
asyncFunctionBody )
抽象操作 AsyncFunctionStart 接收参数 promiseCapability (一个
PromiseCapability 记录 )和
asyncFunctionBody (一个 FunctionBody 解析节点 、ExpressionBody 解析节点 或无参数的 抽象闭包 ),返回
unused 。调用时执行以下步骤:
令 runningContext 为 当前执行上下文 。
令 asyncContext 为 runningContext 的一个副本。
注:复制执行状态是为了 AsyncBlockStart
能恢复其执行。如果恢复当前正在执行的上下文是未定义的行为。
执行 AsyncBlockStart (promiseCapability ,
asyncFunctionBody , asyncContext )。
返回 unused 。
27.7.5.2 AsyncBlockStart ( promiseCapability ,
asyncBody , asyncContext )
抽象操作 AsyncBlockStart 接收参数 promiseCapability (一个
PromiseCapability 记录 ),
asyncBody (一个 解析节点 或无参数的 抽象闭包 ),
asyncContext (一个 执行上下文 ),返回
unused 。调用时执行以下步骤:
令 runningContext 为 当前执行上下文 。
令 closure 为一个新的 抽象闭包 ,无参数,捕获
promiseCapability 和
asyncBody ,调用时执行以下步骤:
令 acAsyncContext 为 当前执行上下文 。
如果 asyncBody 是 解析节点 ,则
令 result 为 Completion (Evaluation of
asyncBody )。
否则,
断言 :asyncBody
是一个无参数的 抽象闭包 。
令 result 为 Completion (asyncBody ())。
断言 :如果执行到这里,async function
要么抛出了异常,要么进行了隐式或显式 return;所有 await 已完成。
从 执行上下文栈 移除
acAsyncContext ,并恢复 执行上下文 ,该上下文现在位于
执行上下文栈 顶部,作为
当前执行上下文 。
如果 result 是 正常完成 ,则
执行 ! Call (promiseCapability .[[Resolve]] , undefined , «
undefined »)。
否则如果 result 是 return
完成 ,则
执行 ! Call (promiseCapability .[[Resolve]] , undefined , «
result .[[Value]] »)。
否则,
断言 :result 是
throw
完成 。
执行 ! Call (promiseCapability .[[Reject]] , undefined , «
result .[[Value]] »)。
返回
unused 。
设置 asyncContext 的代码求值状态,使得该 执行上下文 恢复时会调用
closure ,且无参数。
将 asyncContext 压入 执行上下文栈 ;asyncContext
现在为 当前执行上下文 。
恢复 asyncContext 的挂起执行 。令
result 为恢复运算返回的值。
断言 :
执行到这里时,asyncContext 已从 执行上下文栈
移除,runningContext 是当前 执行上下文 。
断言 :
result 是一个值为 unused 的 正常完成 。该值的来源可能为
Await ,或者如果
async function 没有 await,则为上面 2.i 步。
返回 unused 。
27.7.5.3 Await ( value )
抽象操作 Await 接收参数 value (一个 ECMAScript
语言值 ),返回 正常完成包含 的 ECMAScript 语言值 或
empty ,或 抛出完成 。调用时执行以下步骤:
令 asyncContext 为 当前执行上下文 。
令 promise 为 ? PromiseResolve (%Promise% , value )。
令 fulfilledClosure 为一个新的 抽象闭包 ,参数为
(v ),捕获 asyncContext ,调用时执行以下步骤:
令 prevContext 为 当前执行上下文 。
挂起 prevContext 。
将 asyncContext 压入 执行上下文栈 ;asyncContext
现在为 当前执行上下文 。
恢复 asyncContext 的挂起执行 ,以
NormalCompletion (v )
作为挂起操作的结果。
断言 :执行到这里时,asyncContext 已从
执行上下文栈
移除,prevContext 是当前 执行上下文 。
返回 undefined 。
令 onFulfilled 为 CreateBuiltinFunction (fulfilledClosure ,
1, "" , « »)。
令 rejectedClosure 为一个新的 抽象闭包 ,参数为
(reason ),捕获 asyncContext ,调用时执行以下步骤:
令 prevContext 为 当前执行上下文 。
挂起 prevContext 。
将 asyncContext 压入 执行上下文栈 ;asyncContext
现在为 当前执行上下文 。
恢复 asyncContext 的挂起执行 ,以
ThrowCompletion (reason )
作为挂起操作的结果。
断言 :执行到这里时,asyncContext 已从
执行上下文栈
移除,prevContext 是当前 执行上下文 。
返回 undefined 。
令 onRejected 为 CreateBuiltinFunction (rejectedClosure ,
1, "" , « »)。
执行 PerformPromiseThen (promise ,
onFulfilled , onRejected )。
从 asyncContext 中移除 执行上下文栈 ,并恢复
执行上下文 ,该上下文现在位于 执行上下文栈 顶部,作为 当前执行上下文 。
令 callerContext 为 当前执行上下文 。
恢复 callerContext ,传递 empty 。如果
asyncContext 以后再次被恢复,令 completion 为恢复时携带的 Completion
Record 。
断言 :如果执行到这里,asyncContext 又成为
当前执行上下文 。
返回 completion 。
28 反射
28.1 Reflect 对象
Reflect 对象:
即 %Reflect% 。
是 全局对象 的 "Reflect" 属性的初始值。
是一个 普通对象 。
有一个 [[Prototype]] 内部槽,其值为 %Object.prototype% 。
不是 函数对象 。
没有 [[Construct]] 内部方法;不能作为 构造函数 与 new
操作符一起使用。
没有 [[Call]] 内部方法;不能作为函数调用。
28.1.1 Reflect.apply ( target , thisArgument ,
argumentsList )
该函数被调用时执行以下步骤:
如果 IsCallable (target ) 为
false ,抛出 TypeError 异常。
令 args 为 ? CreateListFromArrayLike (argumentsList )。
执行 PrepareForTailCall ()。
返回 ? Call (target ,
thisArgument , args )。
28.1.2 Reflect.construct ( target ,
argumentsList [ , newTarget ] )
该函数被调用时执行以下步骤:
如果 IsConstructor (target ) 为
false ,抛出 TypeError 异常。
如果 newTarget 未传入,则将 newTarget 设为 target 。
否则如果 IsConstructor (newTarget ) 为
false ,抛出 TypeError 异常。
令 args 为 ? CreateListFromArrayLike (argumentsList )。
返回 ? Construct (target , args ,
newTarget )。
28.1.3 Reflect.defineProperty ( target ,
propertyKey , attributes )
该函数被调用时执行以下步骤:
如果 target 不是对象 ,抛出 TypeError 异常。
令 key 为 ? ToPropertyKey (propertyKey )。
令 desc 为 ? ToPropertyDescriptor (attributes )。
返回 ? target .[[DefineOwnProperty]] (key ,
desc )。
28.1.4 Reflect.deleteProperty ( target ,
propertyKey )
该函数被调用时执行以下步骤:
如果 target 不是对象 ,抛出 TypeError 异常。
令 key 为 ? ToPropertyKey (propertyKey )。
返回 ? target .[[Delete]] (key )。
28.1.5 Reflect.get ( target , propertyKey [ ,
receiver ] )
该函数被调用时执行以下步骤:
如果 target 不是对象 ,抛出 TypeError 异常。
令 key 为 ? ToPropertyKey (propertyKey )。
如果 receiver 未传入,则
将 receiver 设为 target 。
返回 ? target .[[Get]] (key , receiver )。
28.1.6 Reflect.getOwnPropertyDescriptor ( target ,
propertyKey )
该函数被调用时执行以下步骤:
如果 target 不是对象 ,抛出 TypeError 异常。
令 key 为 ? ToPropertyKey (propertyKey )。
令 desc 为 ? target .[[GetOwnProperty]] (key )。
返回 FromPropertyDescriptor (desc )。
28.1.7 Reflect.getPrototypeOf ( target )
该函数被调用时执行以下步骤:
如果 target 不是对象 ,抛出 TypeError 异常。
返回 ? target .[[GetPrototypeOf]] () 。
28.1.8 Reflect.has ( target , propertyKey )
该函数被调用时执行以下步骤:
如果 target 不是对象 ,抛出 TypeError 异常。
令 key 为 ? ToPropertyKey (propertyKey )。
返回 ? target .[[HasProperty]] (key )。
28.1.9 Reflect.isExtensible ( target )
该函数被调用时执行以下步骤:
如果 target 不是对象 ,抛出 TypeError 异常。
返回 ? target .[[IsExtensible]] () 。
28.1.10 Reflect.ownKeys ( target )
该函数被调用时执行以下步骤:
如果 target 不是对象 ,抛出 TypeError 异常。
令 keys 为 ? target .[[OwnPropertyKeys]] () 。
返回 CreateArrayFromList (keys )。
28.1.11 Reflect.preventExtensions ( target )
该函数被调用时执行以下步骤:
如果 target 不是对象 ,抛出 TypeError 异常。
返回 ? target .[[PreventExtensions]] () 。
28.1.12 Reflect.set ( target , propertyKey ,
V [ , receiver ] )
该函数被调用时执行以下步骤:
如果 target 不是对象 ,抛出 TypeError 异常。
令 key 为 ? ToPropertyKey (propertyKey )。
如果 receiver 未传入,则
将 receiver 设为 target 。
返回 ? target .[[Set]] (key , V ,
receiver )。
28.1.13 Reflect.setPrototypeOf ( target , proto
)
该函数被调用时执行以下步骤:
如果 target 不是对象 ,抛出 TypeError 异常。
如果 proto 不是对象 且 proto 也不是
null ,抛出 TypeError 异常。
返回 ? 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 )
该函数被调用时执行以下步骤:
如果 NewTarget 为 undefined ,抛出 TypeError 异常。
返回 ? ProxyCreate (target ,
handler )。
28.2.2 Proxy 构造函数的属性
Proxy 构造函数 :
有一个 [[Prototype]] 内部槽,其值为 %Function.prototype% 。
没有 "prototype" 属性,因为 Proxy 对象没有需要初始化的 [[Prototype]] 内部槽。
具有以下属性:
28.2.2.1 Proxy.revocable ( target , handler
)
该函数用于创建一个可撤销的 Proxy 对象。
被调用时执行以下步骤:
令 proxy 为 ? ProxyCreate (target ,
handler )。
令 revokerClosure 为一个新的 抽象闭包 ,无参数,不捕获任何变量,调用时执行以下步骤:
令 F 为 当前函数对象 。
令 p 为 F .[[RevocableProxy]] 。
如果 p 为 null ,返回 undefined 。
设置 F .[[RevocableProxy]] 为
null 。
断言 :p 是 Proxy 异常对象 。
设置 p .[[ProxyTarget]] 为
null 。
设置 p .[[ProxyHandler]] 为
null 。
返回 undefined 。
令 revoker 为 CreateBuiltinFunction (revokerClosure ,
0, "" , « [[RevocableProxy]] »)。
设置 revoker .[[RevocableProxy]] 为
proxy 。
令 result 为 OrdinaryObjectCreate (%Object.prototype% )。
执行 ! CreateDataPropertyOrThrow (result ,
"proxy" , proxy )。
执行 ! CreateDataPropertyOrThrow (result ,
"revoke" , revoker )。
返回 result 。
28.3 模块命名空间对象
模块命名空间对象是一个 模块命名空间异常对象 ,用于基于属性的运行时访问某个模块的导出绑定。模块命名空间对象没有
构造函数 。而是对每个由包含
ImportDeclaration 、且带有 NameSpaceImport 的模块都会创建这样一个对象。
除了 10.4.6
中指定的属性外,每个模块命名空间对象还具有以下自有属性:
28.3.1 %Symbol.toStringTag%
%Symbol.toStringTag% 属性的初始值为字符串
"Module" 。
该属性具有属性 { [[Writable]] :
false , [[Enumerable]] : false ,
[[Configurable]] : false }。
29 内存模型
内存一致性模型,或称内存模型 ,规定了通过访问由 SharedArrayBuffer 支持的 TypedArray 实例和对 Atomics 对象的方法,所引发的共享数据块事件 的可能顺序。当程序没有数据竞争(定义见下文)时,事件的顺序表现为顺序一致性,即,每个
agent
的动作交错执行。当程序存在数据竞争时,共享内存操作可能表现为非顺序一致性。例如,程序可能表现出违反因果关系的行为和其它令人惊讶的现象。这些现象来源于编译器的变换和 CPU
的设计(例如乱序执行和推测执行)。内存模型定义了程序何时表现为顺序一致的精确条件,以及数据竞争下可能读取的值。也就是说,不存在未定义行为。
内存模型被定义为对由 抽象操作 或 Atomics
对象上的方法在一次求值过程中引入的事件的关系约束。
注
本节为 SharedArrayBuffer 上 抽象操作 引入的事件提供了公理化模型。需要强调的是,与本规范其余部分不同,该模型不能用算法表达。抽象操作 非确定性地引入事件,是
ECMAScript
求值操作语义和内存模型公理化语义之间的接口。这些事件的语义通过考虑一次求值中的所有事件图来定义。它们既不是静态语义,也不是运行时语义。没有可行的算法实现,而是通过一组约束来决定某个事件图是否被允许。
29.1 内存模型基础
共享内存的访问(读和写)分为两组,原子访问和数据访问,定义见下。原子访问是顺序一致的,即,在一个 agent 集群 中,所有 agent 都同意一个严格的全序。非原子访问在所有
agent 间没有严格的全序,即无序。
注 1
不支持比顺序一致更弱、比无序更强的顺序(如 release-acquire)。
共享数据块事件 是 ReadSharedMemory 、WriteSharedMemory 或 ReadModifyWriteSharedMemory 记录 之一。
表 96:ReadSharedMemory 事件字段
字段名
值
含义
[[Order]]
seq-cst 或 unordered
内存模型为该事件保证的最弱顺序。
[[NoTear]]
布尔值
该事件是否允许从与本事件范围相等的多个写事件中读取。
[[Block]]
一个 共享数据块
事件所操作的块。
[[ByteIndex]]
非负 整数
在 [[Block]] 中读操作的字节地址。
[[ElementSize]]
非负 整数
读操作的大小。
表 97:WriteSharedMemory 事件字段
字段名
值
含义
[[Order]]
seq-cst 、unordered 或
init
内存模型为该事件保证的最弱顺序。
[[NoTear]]
布尔值
该事件是否允许被与本事件范围相等的多个读事件读取。
[[Block]]
一个 共享数据块
事件所操作的块。
[[ByteIndex]]
非负 整数
在 [[Block]] 中写操作的字节地址。
[[ElementSize]]
非负 整数
写操作的大小。
[[Payload]]
一个 List ,其元素为
字节值
其他事件将要读取的 List 的
字节值 。
表 98:ReadModifyWriteSharedMemory
事件字段
字段名
值
含义
[[Order]]
seq-cst
读-改-写事件总是顺序一致的。
[[NoTear]]
true
读-改-写事件不允许撕裂。
[[Block]]
一个 共享数据块
事件所操作的块。
[[ByteIndex]]
非负 整数
在 [[Block]] 中读-改-写操作的字节地址。
[[ElementSize]]
非负 整数
读-改-写操作的大小。
[[Payload]]
一个 List ,其元素为
字节值
将被传递给 [[ModifyOp]] 的 List 的
字节值 。
[[ModifyOp]]
一个 读-改-写修改函数
一个抽象闭包,接收读到的 List 的
字节值 和 [[Payload]] ,返回修改后的 List 的
字节值 。
这些事件由 抽象操作 或 Atomics
对象上的方法引入。
某些操作还可能引入 Synchronize 事件。Synchronize 事件 没有字段,仅用于直接约束其它事件允许的顺序。
除了 共享数据块
和 Synchronize 事件外,还有 宿主 特定的事件。
设 ReadSharedMemory、WriteSharedMemory 或 ReadModifyWriteSharedMemory 事件的范围为其 [[ByteIndex]] 到 [[ByteIndex]] + [[ElementSize]] - 1 的连续 整数 集合。两个事件的范围相等当且仅当事件拥有相同的 [[Block]] ,且范围元素一一相等。两个事件的范围重叠当且仅当事件拥有相同的 [[Block]] ,且范围不等、交集非空。两个事件的范围不相交当且仅当事件没有相同的 [[Block]] 或范围既不等也不重叠。
注 2
应考虑的 宿主 特定同步事件示例包括:将
SharedArrayBuffer 从一个 agent 发送到另一个(如浏览器中的 postMessage
),启动和停止
agent ,以及通过除共享内存外的通道在
agent
集群 内通信。对于某个具体执行 execution ,这些事件由 宿主 通过 host-synchronizes-with 严格偏序 提供。此外,宿主 可向
execution .[[EventList]] 添加 宿主 特定同步事件,以参与 is-agent-order-before 关系 。
事件在 候选执行 中由下文定义的关系排序。
29.2 Agent 事件记录
Agent 事件记录 是一个带有以下字段的 记录 。
表 99:Agent 事件记录 字段
29.3 选定值记录
选定值记录 是一个带有以下字段的 记录 。
表 100:选定值记录 字段
29.4 候选执行
候选执行 是对 agent 集群 求值的一个 记录 ,包含以下字段。
表 101:候选执行 记录 字段
空候选执行 是字段皆为空 List 的候选执行 记录 。
29.5 内存模型的抽象操作
29.5.1 EventSet ( execution )
抽象操作 EventSet 接收参数 execution (一个 候选执行 ),返回事件集合。调用时执行以下步骤:
令 events 为一个空集合。
对于 execution .[[EventsRecords]] 中的每个 Agent 事件记录 aer ,执行
对于 aer .[[EventList]] 中的每个事件 E ,执行
将 E 添加到 events 。
返回 events 。
29.5.2 SharedDataBlockEventSet ( execution )
抽象操作 SharedDataBlockEventSet 接收参数 execution (一个 候选执行 ),返回事件集合。调用时执行以下步骤:
令 events 为一个空集合。
对于 EventSet (execution ) 中的每个事件
E ,执行
如果 E 是 ReadSharedMemory 、WriteSharedMemory 或
ReadModifyWriteSharedMemory
事件,则将 E 添加到 events 。
返回 events 。
29.5.3 HostEventSet ( execution )
抽象操作 HostEventSet 接收参数 execution (一个 候选执行 ),返回事件集合。调用时执行以下步骤:
令 events 为一个空集合。
对于 EventSet (execution ) 中的每个事件
E ,执行
如果 E 不在 SharedDataBlockEventSet (execution )
中,则将 E 添加到 events 。
返回 events 。
29.5.4 ComposeWriteEventBytes ( execution ,
byteIndex , Ws )
抽象操作 ComposeWriteEventBytes 接收参数 execution (一个 候选执行 )、byteIndex (非负 整数 )、Ws (List ,元素为 WriteSharedMemory 或 ReadModifyWriteSharedMemory 事件),返回
字节值列表 。调用时执行以下步骤:
令 byteLocation 为 byteIndex 。
令 bytesRead 为一个新的空 List 。
对于 Ws 中的每个元素 W ,执行
断言 :W 的范围包含
byteLocation 。
令 payloadIndex 为 byteLocation - W .[[ByteIndex]] 。
如果 W 是 WriteSharedMemory
事件,则
令 byte 为 W .[[Payload]] [payloadIndex ]。
否则,
断言 :W 是 ReadModifyWriteSharedMemory
事件。
令 bytes 为 ValueOfReadEvent (execution ,
W )。
令 bytesModified 为 W .[[ModifyOp]] (bytes , W .[[Payload]] )。
令 byte 为
bytesModified [payloadIndex ]。
将 byte 添加到 bytesRead 。
令 byteLocation 设为 byteLocation + 1。
返回 bytesRead 。
注 1
读-改-写的修改 [[ModifyOp]] 由 Atomics 对象上的相应函数属性决定,这些属性会引入 ReadModifyWriteSharedMemory
事件。
注 2
29.5.5 ValueOfReadEvent ( execution , R )
抽象操作 ValueOfReadEvent 接收参数 execution (一个 候选执行 )和 R (一个
ReadSharedMemory 或 ReadModifyWriteSharedMemory 事件),返回
字节值列表 。调用时执行以下步骤:
令 Ws 为 reads-bytes-from (R ) in
execution 。
断言 :
Ws 是一个长度等于 R .[[ElementSize]] 的 WriteSharedMemory
或 ReadModifyWriteSharedMemory
事件的 List 。
返回 ComposeWriteEventBytes (execution ,
R .[[ByteIndex]] , Ws )。
29.6 候选执行的关系
以下关系和数学函数以某个 候选执行 为参数,对其事件进行排序。
29.6.1 is-agent-order-before
对于一个 候选执行
execution ,其 is-agent-order-before 关系 是满足以下条件的事件上的 最小关系 。
对于事件 E 和 D ,如果存在 Agent 事件记录
aer 在 execution .[[EventsRecords]] 中,使得
aer .[[EventList]] 同时包含 E 和 D 且
E 在 aer .[[EventList]] 的 List 顺序中位于
D 前,则 E is-agent-order-before D 。
注
每个 agent
在求值期间均以每-agent 严格全序 引入事件。这里是这些
严格全序 的并集。
29.6.2 reads-bytes-from
对于一个 候选执行
execution ,其 reads-bytes-from 函数是将 SharedDataBlockEventSet (execution )
中的事件映射为 List ,其元素为 SharedDataBlockEventSet (execution )
中的事件的数学函数,满足以下条件。
每个 候选执行 总是存在 reads-bytes-from 函数。
29.6.3 reads-from
对于一个 候选执行
execution ,其 reads-from 关系 是满足以下条件的事件上的 最小关系 。
29.6.4 host-synchronizes-with
对于一个 候选执行
execution ,其 host-synchronizes-with 关系 是 宿主 提供的、满足以下条件的 严格偏序 ,其作用于 宿主 特定事件。
注 1
对于 宿主 特定事件
E 和 D ,若 E host-synchronizes-with D ,则
E happens-before D 也成立。
注 2
该 关系 允许 宿主 提供额外的同步机制,比如 HTML
worker 之间的 postMessage
。
29.6.5 synchronizes-with
对于一个 候选执行
execution ,其 synchronizes-with 关系 是满足以下条件的事件上的 最小关系 。
对于事件 R 和 W ,如果 R reads-from W ,且
R .[[Order]] 为
seq-cst ,W .[[Order]] 也为
seq-cst ,且 R 、W 范围相等,则 W
synchronizes-with R 。
对于 execution .[[EventsRecords]] 中的每个
eventsRecord ,有:
若 eventsRecord .[[AgentSynchronizesWith]] 包含
(S , Sw ),则 S synchronizes-with Sw 。
若 execution .[[HostSynchronizesWith]] 包含 (E ,
D ),则 E synchronizes-with D 。
注 1
根据内存模型文献的惯例,在 候选执行 execution 中,是写事件
synchronizes-with 读事件,而不是读 synchronizes-with 写。
注 2
在 候选执行 execution
中,init 事件不参与此 关系 ,而是直接被
happens-before 约束。
注 3
在 候选执行 execution
中,并非所有通过 reads-from 关联的
seq-cst 事件都通过 synchronizes-with 关联。只有范围相等的事件才会通过
synchronizes-with 关联。
注 4
对于 共享数据块事件 R 和
W ,若 W synchronizes-with R ,则 R 可能 reads-from 其他写事件。
29.6.6 happens-before
对于一个 候选执行
execution ,其 happens-before 关系 是满足以下条件的事件上的 最小关系 。
注
由于 happens-before 是 agent -order 的超集,候选执行 与 ECMAScript 的单线程求值语义是一致的。
29.7 有效执行的属性
29.7.1 有效选定读取
候选执行 execution
具有有效选定读取,当且仅当下列算法返回 true 。
对于 ReadSharedMemory 或
ReadModifyWriteSharedMemory
事件 R ,属于 SharedDataBlockEventSet (execution ),执行
令 chosenValueRecord 为 execution .[[ChosenValues]] 中 [[Event]]
字段为 R 的元素。
令 chosenValue 为 chosenValueRecord .[[ChosenValue]] 。
令 readValue 为 ValueOfReadEvent (execution ,
R )。
令 chosenLen 为 chosenValue 的元素个数。
令 readLen 为 readValue 的元素个数。
如果 chosenLen ≠ readLen ,则
返回 false 。
如果存在某个 整数 i ,在 区间 [0,
chosenLen ) 内,使得 chosenValue [i ] ≠
readValue [i ],则
返回 false 。
返回 true 。
29.7.2 一致性读取
候选执行 execution
具有一致性读取,当且仅当下列算法返回 true 。
对于 ReadSharedMemory 或
ReadModifyWriteSharedMemory
事件 R ,属于 SharedDataBlockEventSet (execution ),执行
令 Ws 为 reads-bytes-from (R )
in execution 。
令 byteLocation 为 R .[[ByteIndex]] 。
对于 Ws 中的每个事件 W ,执行
如果 R happens-before
W ,则
返回 false 。
如果存在 WriteSharedMemory
或 ReadModifyWriteSharedMemory
事件 V ,其范围含有 byteLocation ,且 W happens-before
V ,且 V happens-before
R ,则
返回 false 。
令 byteLocation 设为 byteLocation + 1。
返回 true 。
29.7.3 无撕裂读取
候选执行 execution
具有无撕裂读取,当且仅当下列算法返回 true 。
对于 ReadSharedMemory 或
ReadModifyWriteSharedMemory
事件 R ,属于 SharedDataBlockEventSet (execution ),执行
如果 R .[[NoTear]] 为 true ,则
断言 :R .[[ByteIndex]] 除以 R .[[ElementSize]] 的余数为 0。
对于每个事件 W ,满足 R reads-from
W 且 W .[[NoTear]] 为
true ,执行
如果 R 和 W 范围相等,且存在事件 V ,使得
V 和 W 范围相等,V .[[NoTear]] 为
true ,W 和 V 不是同一个
共享数据块事件 ,且
R reads-from
V ,则
返回 false 。
返回 true 。
注
当事件通过访问 整数
TypedArray 引入时,其 [[NoTear]] 字段为 true ;若通过访问浮点 TypedArray 或
DataView 引入,则为 false 。
直观上,这一要求意味着当通过 整数 TypedArray
以对齐方式访问某内存范围时,在与其他范围相等的写事件发生 数据竞争
时,只有一个写事件可以“胜出”。更精确地说,对齐的读事件不能读取由多个、不同但范围相等的写事件拼凑出来的值。但对齐的读事件可以读取来自多个范围重叠写事件的字节。
29.7.4 顺序一致原子
对于 候选执行 execution ,is-memory-order-before 是 严格全序 ,作用于 EventSet (execution ) 的所有事件,并满足以下条件。
候选执行 拥有顺序一致原子性,当且仅当它存在
is-memory-order-before 关系 。
注 3
虽然 is-memory-order-before 覆盖 EventSet (execution ) 中所有事件,但那些未被
happens-before 或 synchronizes-with
约束的事件可以在该序列中的任意位置出现。
29.7.5 有效执行
候选执行 execution
是有效执行(或简称执行),当且仅当以下条件均为真:
所有程序至少有一个有效执行。
29.8 竞争
对于执行 execution 以及其中 SharedDataBlockEventSet (execution )
的事件 E 和 D ,如果下列算法返回 true ,则称 E 和 D
处于竞争 关系。
如果 E 和 D 不是同一个 共享数据块事件 ,则
如果不存在 E happens-before
D 且 D happens-before E ,则
如果 E 和 D 都是 WriteSharedMemory
或 ReadModifyWriteSharedMemory
事件,且 E 和 D 的范围不互不相交,则
返回 true 。
如果 E reads-from D 或
D reads-from
E ,则
返回 true 。
返回 false 。
29.9 数据竞争
对于执行 execution 以及其中 SharedDataBlockEventSet (execution )
的事件 E 和 D ,如果下列算法返回 true ,则称 E 和 D
处于数据竞争 关系。
如果 E 和 D 在 竞争 中,则
如果 E .[[Order]] 不是 seq-cst
或 D .[[Order]] 不是
seq-cst ,则
返回 true 。
如果 E 和 D 的范围重叠,则
返回 true 。
返回 false 。
29.10 数据竞争自由
若 SharedDataBlockEventSet (execution )
中不存在两个事件处于 数据竞争 ,则执行 execution 是数据竞争自由 的。
若程序的所有执行均为数据竞争自由,则称该程序为数据竞争自由程序。
内存模型 保证数据竞争自由程序的所有事件顺序一致。
29.11 共享内存指南
注 1
以下是 ECMAScript 程序员使用共享内存的指南。
我们建议程序保持 数据竞争自由 ,即确保不会在同一内存位置上发生并发的非原子操作。数据竞争自由 的程序具有交错语义,即每个 agent 求值语义中的每一步都与其他 agent
交错。对于 数据竞争自由 的程序,不必理解 内存模型
的细节。这些细节不太可能帮助更好地编写 ECMAScript。
更一般地说,即使程序不是数据竞争自由 ,只要原子操作未参与任何数据竞争,且竞争的所有操作访问大小相同,程序也可能表现为可预测。安排原子操作不参与竞争的最简单方法是确保原子操作和非原子操作使用不同的内存单元,并且不同大小的原子访问不同时访问同一单元。实际上,程序应尽可能将共享内存视为强类型内存。尽管如此,依赖于竞争的非原子访问的顺序和时序仍不可取,但如果内存被视为强类型,则竞争访问不会“撕裂”(值的各比特不会混合)。
注 2
以下是 ECMAScript 实现者为使用共享内存的程序编写编译器转换的指南。
建议在多 agent 环境中允许大多数在单
agent
环境下有效的程序转换,以保证多 agent 程序中每个 agent 的性能与单 agent
程序一样好。通常这些转换难以判断。这里概述了一些关于程序转换的规则,这些规则旨在具有规范性(即被 内存模型 隐含,或者比内存模型更强),但可能并不详尽。这些规则旨在适用于在引入
is-agent-order-before 关系 的事件之前的程序转换。
设agent-order 片段 为 is-agent-order-before 关系 中属于同一个 agent 的子集。
设一次读事件的可能读取值 为该事件在所有有效执行中 ValueOfReadEvent 的所有值的集合。
任何在无共享内存时有效的 agent-order 片段转换,在有共享内存时也是有效的,但有如下例外:
原子操作不可变 :程序转换不得导致 agent-order 片段内 seq-cst 事件与其
unordered 操作重排序,也不得使 seq-cst
操作彼此重排序,亦不得将 seq-cst 操作从 is-agent-order-before
关系 中移除。
(实际上,对重排序的禁止要求编译器假定每个 seq-cst 操作是一个同步,并会包含在最终 is-memory-order-before 关系 中,这在无跨
agent 程序分析时本来也应假定。同时也要求编译器假定所有调用其内存序未知的函数都可能包含 seq-cst 操作。)
读取必须稳定 :每个共享内存读取在一次执行中只能观察到一个值。
(例如,若程序语义上某次读取被多次执行,则程序只能观察到这些读取值中的一个。rematerialization 转换可能违反此规则。)
写入必须稳定 :所有可观察到的共享内存写入都必须由程序语义产生。
(例如,转换不能引入某些可观察写,如对更大位置的读-改-写操作来写入较小数据,写入程序本不可写的值,或对刚读取的位置写回刚读取的值,如果该位置在读取后可能被其他
agent 覆盖。)
可能读取值非空 :程序转换不能导致共享内存读取的可能读取值集合为空。
(反直觉地,本规则实际上限制了写入的变换,因为写入只有被读取事件读取时才有意义。例如,写入可以移动、合并,有时可在两个
seq-cst 操作间重排序,但不能删除所有更新某位置的写入;必须保留至少一个写。)
以下转换仍然有效:合并同一位置的多个非原子读取、重排序非原子读取、引入推测性非原子读取、合并同一位置的多个非原子写、重排序对不同位置的非原子写、将非原子读取抽出循环(即使影响终止)。注意,别名
TypedArrays 一般使证明位置不同变得困难。
注 3
以下是 ECMAScript 实现者为共享内存访问生成机器码的指南。
对于内存模型不弱于 ARM 或 Power
的体系结构,非原子存储和加载可直接编译为目标架构上的存储和加载指令。原子存储和加载可编译为保证顺序一致性的指令。如果没有这样的指令,则应使用内存屏障,例如在存储或加载两侧加屏障。读-改-写操作可编译为目标架构上的原子读-改-写指令,如
x86 的 LOCK
前缀指令、ARM 的 load-exclusive/store-exclusive、Power 的
load-link/store-conditional。
具体而言,内存模型 旨在允许如下代码生成:
假定程序中的每个原子操作都是必要的。
原子操作之间及与非原子操作之间绝不重排。
假定函数总是执行原子操作。
原子操作永远不会实现为更大数据的读-改-写,只能用非 lock-free
的原子操作(如果平台不支持相应大小的原子操作)。(假定每个平台都支持每种有意义大小的正常内存访问操作。)
朴素的代码生成模式如下:
常规加载和存储编译为单条加载或存储指令。
lock-free 原子加载与存储编译为完整(顺序一致性)屏障、常规加载或存储、再加完整屏障。
lock-free 原子读-改-写编译为完整屏障、原子读-改-写指令序列、再加完整屏障。
非 lock-free 原子操作编译为自旋锁获取、完整屏障、一系列非原子加载和存储指令、完整屏障、自旋锁释放。
只要某地址范围上的原子操作不与非原子写或不同尺寸的原子操作竞争,上述映射就是正确的。这已足够:内存模型 等同于将参与竞争的原子操作降级为非原子。另一方面,朴素映射很强:允许原子操作用作顺序一致性屏障,但内存模型 并不保证这一点。
在遵守内存模型 约束的前提下,也允许对这些基本模式进行本地优化。例如:
平台相关的明显改进可去除冗余屏障。例如,在 x86 上,lock-free 原子加载和存储两边的屏障可省略,除了存储后的屏障;lock-free
原子读-改-写指令无需屏障,因为它们都用 LOCK
前缀。在许多平台,存在多种强度的屏障,在某些情况下可用弱屏障而不破坏顺序一致性。
大多数现代平台支持 ECMAScript 所需全部数据尺寸的 lock-free 原子。若需非 lock-free
原子,原子操作体前后的屏障通常可合并到锁和解锁步骤。最简单方案是每个 SharedArrayBuffer 一个锁字。
还可有更复杂的本地优化,需要一些代码分析。例如,两个连续的屏障通常等价于单个屏障,因此两次原子操作生成的代码只需一个屏障隔开。在 x86
上,甚至可以省略原子存储后的屏障,因为该屏障只需用于分隔存储和后续加载。
附录 A (资料性附录) 语法摘要
A.1 词法语法
SourceCharacter ::
any Unicode code point
InputElementDiv ::
WhiteSpace
LineTerminator
Comment
CommonToken
DivPunctuator
RightBracePunctuator
InputElementRegExp ::
WhiteSpace
LineTerminator
Comment
CommonToken
RightBracePunctuator
RegularExpressionLiteral
InputElementRegExpOrTemplateTail
::
WhiteSpace
LineTerminator
Comment
CommonToken
RegularExpressionLiteral
TemplateSubstitutionTail
InputElementTemplateTail
::
WhiteSpace
LineTerminator
Comment
CommonToken
DivPunctuator
TemplateSubstitutionTail
InputElementHashbangOrRegExp
::
WhiteSpace
LineTerminator
Comment
CommonToken
HashbangComment
RegularExpressionLiteral
WhiteSpace ::
<TAB>
<VT>
<FF>
<ZWNBSP>
<USP>
LineTerminator ::
<LF>
<CR>
<LS>
<PS>
LineTerminatorSequence
::
<LF>
<CR>
[lookahead ≠ <LF> ]
<LS>
<PS>
<CR>
<LF>
Comment ::
MultiLineComment
SingleLineComment
MultiLineComment ::
/*
MultiLineCommentChars opt
*/
MultiLineCommentChars
::
MultiLineNotAsteriskChar
MultiLineCommentChars opt
*
PostAsteriskCommentChars opt
PostAsteriskCommentChars
::
MultiLineNotForwardSlashOrAsteriskChar
MultiLineCommentChars opt
*
PostAsteriskCommentChars opt
MultiLineNotAsteriskChar
::
SourceCharacter but not
*
MultiLineNotForwardSlashOrAsteriskChar
::
SourceCharacter but not one of
/ or *
SingleLineComment ::
//
SingleLineCommentChars opt
SingleLineCommentChars
::
SingleLineCommentChar
SingleLineCommentChars opt
SingleLineCommentChar
::
SourceCharacter but not
LineTerminator
HashbangComment ::
#!
SingleLineCommentChars opt
CommonToken ::
IdentifierName
PrivateIdentifier
Punctuator
NumericLiteral
StringLiteral
Template
PrivateIdentifier ::
#
IdentifierName
IdentifierName ::
IdentifierStart
IdentifierName
IdentifierPart
IdentifierStart ::
IdentifierStartChar
\
UnicodeEscapeSequence
IdentifierPart ::
IdentifierPartChar
\
UnicodeEscapeSequence
IdentifierStartChar ::
UnicodeIDStart
$
_
IdentifierPartChar ::
UnicodeIDContinue
$
AsciiLetter :: one
of a b c d
e f g h i
j k l m n
o p q r s
t u v w x
y z A B C
D E F G H
I J K L M
N O P Q R
S T U V W
X Y Z
UnicodeIDStart ::
any Unicode code point with the Unicode property “ID_Start”
UnicodeIDContinue ::
any Unicode code point with the Unicode property “ID_Continue”
ReservedWord :: one
of await break case
catch class const continue
debugger default delete do
else enum export extends
false finally for function
if import in instanceof
new null return super
switch this throw true
try typeof var void
while with yield
Punctuator ::
OptionalChainingPunctuator
OtherPunctuator
OptionalChainingPunctuator
::
?.
[lookahead ∉ DecimalDigit ]
OtherPunctuator ::
one of { ( )
[ ] . ... ;
, < > <=
>= == != === !==
+ - * % **
++ -- << >>
>>> & | ^
! ~ && || ??
? : = += -=
*= %= **= <<=
>>= >>>= &= |=
^= &&= ||= ??=
=>
DivPunctuator ::
/
/=
RightBracePunctuator ::
}
NullLiteral ::
null
BooleanLiteral ::
true
false
NumericLiteralSeparator
::
_
NumericLiteral ::
DecimalLiteral
DecimalBigIntegerLiteral
NonDecimalIntegerLiteral [+Sep]
NonDecimalIntegerLiteral [+Sep]
BigIntLiteralSuffix
LegacyOctalIntegerLiteral
DecimalBigIntegerLiteral
::
0
BigIntLiteralSuffix
NonZeroDigit
DecimalDigits [+Sep] opt
BigIntLiteralSuffix
NonZeroDigit
NumericLiteralSeparator
DecimalDigits [+Sep]
BigIntLiteralSuffix
NonDecimalIntegerLiteral [Sep]
::
BinaryIntegerLiteral [?Sep]
OctalIntegerLiteral [?Sep]
HexIntegerLiteral [?Sep]
BigIntLiteralSuffix ::
n
DecimalLiteral ::
DecimalIntegerLiteral
.
DecimalDigits [+Sep] opt
ExponentPart [+Sep] opt
.
DecimalDigits [+Sep]
ExponentPart [+Sep] opt
DecimalIntegerLiteral
ExponentPart [+Sep] opt
DecimalIntegerLiteral
::
0
NonZeroDigit
NonZeroDigit
NumericLiteralSeparator opt
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 ::
"
DoubleStringCharacters opt
"
'
SingleStringCharacters opt
'
DoubleStringCharacters
::
DoubleStringCharacter
DoubleStringCharacters opt
SingleStringCharacters
::
SingleStringCharacter
SingleStringCharacters opt
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
::
`
TemplateCharacters opt
`
TemplateHead ::
`
TemplateCharacters opt
${
TemplateSubstitutionTail
::
TemplateMiddle
TemplateTail
TemplateMiddle ::
}
TemplateCharacters opt
${
TemplateTail ::
}
TemplateCharacters opt
`
TemplateCharacters ::
TemplateCharacter
TemplateCharacters opt
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] :
[
Elision opt
]
[
ElementList [?Yield,
?Await]
]
[
ElementList [?Yield,
?Await]
,
Elision opt
]
ElementList [Yield,
Await] :
Elision opt
AssignmentExpression [+In,
?Yield, ?Await]
Elision opt
SpreadElement [?Yield,
?Await]
ElementList [?Yield,
?Await]
,
Elision opt
AssignmentExpression [+In,
?Yield, ?Await]
ElementList [?Yield,
?Await]
,
Elision opt
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] :
[
Elision opt
AssignmentRestElement [?Yield,
?Await] opt
]
[
AssignmentElementList [?Yield,
?Await]
]
[
AssignmentElementList [?Yield,
?Await]
,
Elision opt
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] :
Elision opt
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] :
[
Elision opt
BindingRestElement [?Yield,
?Await] opt
]
[
BindingElementList [?Yield,
?Await]
]
[
BindingElementList [?Yield,
?Await]
,
Elision opt
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] :
Elision opt
BindingElement [?Yield,
?Await]
BindingProperty [Yield,
Await] :
SingleNameBinding [?Yield,
?Await]
PropertyName [?Yield,
?Await]
:
BindingElement [?Yield,
?Await]
BindingElement [Yield,
Await] :
SingleNameBinding [?Yield,
?Await]
BindingPattern [?Yield,
?Await]
Initializer [+In, ?Yield,
?Await] opt
SingleNameBinding [Yield,
Await] :
BindingIdentifier [?Yield,
?Await]
Initializer [+In, ?Yield,
?Await] opt
BindingRestElement [Yield,
Await] :
...
BindingIdentifier [?Yield,
?Await]
...
BindingPattern [?Yield,
?Await]
EmptyStatement :
;
ExpressionStatement [Yield,
Await] :
[lookahead ∉ { { , function , async
[no LineTerminator
here]
function , class , let
[ }]
Expression [+In, ?Yield,
?Await]
;
IfStatement [Yield, Await,
Return] :
if
(
Expression [+In, ?Yield,
?Await]
)
Statement [?Yield, ?Await,
?Return]
else
Statement [?Yield, ?Await,
?Return]
if
(
Expression [+In, ?Yield,
?Await]
)
Statement [?Yield, ?Await,
?Return]
[lookahead ≠ else ]
IterationStatement [Yield, Await,
Return] :
DoWhileStatement [?Yield, ?Await,
?Return]
WhileStatement [?Yield, ?Await,
?Return]
ForStatement [?Yield, ?Await,
?Return]
ForInOfStatement [?Yield, ?Await,
?Return]
DoWhileStatement [Yield, Await,
Return] :
do
Statement [?Yield, ?Await,
?Return]
while
(
Expression [+In, ?Yield,
?Await]
)
;
WhileStatement [Yield, Await,
Return] :
while
(
Expression [+In, ?Yield,
?Await]
)
Statement [?Yield, ?Await,
?Return]
ForStatement [Yield, Await,
Return] :
for
(
[lookahead ≠ let
[ ]
Expression [~In, ?Yield,
?Await] opt
;
Expression [+In, ?Yield,
?Await] opt
;
Expression [+In, ?Yield,
?Await] opt
)
Statement [?Yield, ?Await,
?Return]
for
(
var
VariableDeclarationList [~In,
?Yield, ?Await]
;
Expression [+In, ?Yield,
?Await] opt
;
Expression [+In, ?Yield,
?Await] opt
)
Statement [?Yield, ?Await,
?Return]
for
(
LexicalDeclaration [~In,
?Yield, ?Await]
Expression [+In, ?Yield,
?Await] opt
;
Expression [+In, ?Yield,
?Await] opt
)
Statement [?Yield, ?Await,
?Return]
ForInOfStatement [Yield, Await,
Return] :
for
(
[lookahead ≠ let
[ ]
LeftHandSideExpression [?Yield,
?Await]
in
Expression [+In, ?Yield,
?Await]
)
Statement [?Yield, ?Await,
?Return]
for
(
var
ForBinding [?Yield,
?Await]
in
Expression [+In, ?Yield,
?Await]
)
Statement [?Yield, ?Await,
?Return]
for
(
ForDeclaration [?Yield,
?Await]
in
Expression [+In, ?Yield,
?Await]
)
Statement [?Yield, ?Await,
?Return]
for
(
[lookahead ∉ { let , async
of }]
LeftHandSideExpression [?Yield,
?Await]
of
AssignmentExpression [+In,
?Yield, ?Await]
)
Statement [?Yield, ?Await,
?Return]
for
(
var
ForBinding [?Yield,
?Await]
of
AssignmentExpression [+In,
?Yield, ?Await]
)
Statement [?Yield, ?Await,
?Return]
for
(
ForDeclaration [?Yield,
?Await]
of
AssignmentExpression [+In,
?Yield, ?Await]
)
Statement [?Yield, ?Await,
?Return]
[+Await]
for
await
(
[lookahead ≠ let ]
LeftHandSideExpression [?Yield,
?Await]
of
AssignmentExpression [+In,
?Yield, ?Await]
)
Statement [?Yield, ?Await,
?Return]
[+Await]
for
await
(
var
ForBinding [?Yield,
?Await]
of
AssignmentExpression [+In,
?Yield, ?Await]
)
Statement [?Yield, ?Await,
?Return]
[+Await]
for
await
(
ForDeclaration [?Yield,
?Await]
of
AssignmentExpression [+In,
?Yield, ?Await]
)
Statement [?Yield, ?Await,
?Return]
ForDeclaration [Yield,
Await] :
LetOrConst
ForBinding [?Yield,
?Await]
ForBinding [Yield,
Await] :
BindingIdentifier [?Yield,
?Await]
BindingPattern [?Yield,
?Await]
ContinueStatement [Yield,
Await] :
continue
;
continue
[no LineTerminator
here]
LabelIdentifier [?Yield,
?Await]
;
BreakStatement [Yield,
Await] :
break
;
break
[no LineTerminator
here]
LabelIdentifier [?Yield,
?Await]
;
ReturnStatement [Yield,
Await] :
return
;
return
[no LineTerminator
here]
Expression [+In, ?Yield,
?Await]
;
WithStatement [Yield, Await,
Return] :
with
(
Expression [+In, ?Yield,
?Await]
)
Statement [?Yield, ?Await,
?Return]
SwitchStatement [Yield, Await,
Return] :
switch
(
Expression [+In, ?Yield,
?Await]
)
CaseBlock [?Yield, ?Await,
?Return]
CaseBlock [Yield, Await,
Return] :
{
CaseClauses [?Yield, ?Await,
?Return] opt
}
{
CaseClauses [?Yield, ?Await,
?Return] opt
DefaultClause [?Yield, ?Await,
?Return]
CaseClauses [?Yield, ?Await,
?Return] opt
}
CaseClauses [Yield, Await,
Return] :
CaseClause [?Yield, ?Await,
?Return]
CaseClauses [?Yield, ?Await,
?Return]
CaseClause [?Yield, ?Await,
?Return]
CaseClause [Yield, Await,
Return] :
case
Expression [+In, ?Yield,
?Await]
:
StatementList [?Yield, ?Await,
?Return] opt
DefaultClause [Yield, Await,
Return] :
default
:
StatementList [?Yield, ?Await,
?Return] opt
LabelledStatement [Yield, Await,
Return] :
LabelIdentifier [?Yield,
?Await]
:
LabelledItem [?Yield, ?Await,
?Return]
LabelledItem [Yield, Await,
Return] :
Statement [?Yield, ?Await,
?Return]
FunctionDeclaration [?Yield,
?Await, ~Default]
ThrowStatement [Yield,
Await] :
throw
[no LineTerminator
here]
Expression [+In, ?Yield,
?Await]
;
TryStatement [Yield, Await,
Return] :
try
Block [?Yield, ?Await,
?Return]
Catch [?Yield, ?Await,
?Return]
try
Block [?Yield, ?Await,
?Return]
Finally [?Yield, ?Await,
?Return]
try
Block [?Yield, ?Await,
?Return]
Catch [?Yield, ?Await,
?Return]
Finally [?Yield, ?Await,
?Return]
Catch [Yield,
Await, Return] :
catch
(
CatchParameter [?Yield,
?Await]
)
Block [?Yield, ?Await,
?Return]
catch
Block [?Yield, ?Await,
?Return]
Finally [Yield, Await,
Return] :
finally
Block [?Yield, ?Await,
?Return]
CatchParameter [Yield,
Await] :
BindingIdentifier [?Yield,
?Await]
BindingPattern [?Yield,
?Await]
DebuggerStatement :
debugger
;
A.4 函数和类
UniqueFormalParameters [Yield,
Await] :
FormalParameters [?Yield,
?Await]
FormalParameters [Yield,
Await] :
[empty]
FunctionRestParameter [?Yield,
?Await]
FormalParameterList [?Yield,
?Await]
FormalParameterList [?Yield,
?Await]
,
FormalParameterList [?Yield,
?Await]
,
FunctionRestParameter [?Yield,
?Await]
FormalParameterList [Yield,
Await] :
FormalParameter [?Yield,
?Await]
FormalParameterList [?Yield,
?Await]
,
FormalParameter [?Yield,
?Await]
FunctionRestParameter [Yield,
Await] :
BindingRestElement [?Yield,
?Await]
FormalParameter [Yield,
Await] :
BindingElement [?Yield,
?Await]
FunctionDeclaration [Yield, Await,
Default] :
function
BindingIdentifier [?Yield,
?Await]
(
FormalParameters [~Yield,
~Await]
)
{
FunctionBody [~Yield,
~Await]
}
[+Default]
function
(
FormalParameters [~Yield,
~Await]
)
{
FunctionBody [~Yield,
~Await]
}
FunctionExpression :
function
BindingIdentifier [~Yield,
~Await] opt
(
FormalParameters [~Yield,
~Await]
)
{
FunctionBody [~Yield,
~Await]
}
FunctionBody [Yield,
Await] :
FunctionStatementList [?Yield,
?Await]
FunctionStatementList [Yield,
Await] :
StatementList [?Yield, ?Await,
+Return] opt
ArrowFunction [In, Yield,
Await] :
ArrowParameters [?Yield,
?Await]
[no LineTerminator
here]
=>
ConciseBody [?In]
ArrowParameters [Yield,
Await] :
BindingIdentifier [?Yield,
?Await]
CoverParenthesizedExpressionAndArrowParameterList [?Yield,
?Await]
ConciseBody [In]
:
[lookahead ≠ { ]
ExpressionBody [?In,
~Await]
{
FunctionBody [~Yield,
~Await]
}
ExpressionBody [In,
Await] :
AssignmentExpression [?In,
~Yield, ?Await]
当处理如下产生式的一个实例时
ArrowParameters [Yield,
Await] :
CoverParenthesizedExpressionAndArrowParameterList [?Yield,
?Await]
对 CoverParenthesizedExpressionAndArrowParameterList
的解释会使用以下语法进行精化:
ArrowFormalParameters [Yield,
Await] :
(
UniqueFormalParameters [?Yield,
?Await]
)
AsyncArrowFunction [In, Yield,
Await] :
async
[no LineTerminator
here]
AsyncArrowBindingIdentifier [?Yield]
[no LineTerminator
here]
=>
AsyncConciseBody [?In]
CoverCallExpressionAndAsyncArrowHead [?Yield,
?Await]
[no LineTerminator
here]
=>
AsyncConciseBody [?In]
AsyncConciseBody [In]
:
[lookahead ≠ { ]
ExpressionBody [?In,
+Await]
{
AsyncFunctionBody
}
AsyncArrowBindingIdentifier [Yield]
:
BindingIdentifier [?Yield,
+Await]
CoverCallExpressionAndAsyncArrowHead [Yield,
Await] :
MemberExpression [?Yield,
?Await]
Arguments [?Yield,
?Await]
当处理如下产生式的一个实例时
AsyncArrowFunction [In, Yield,
Await] :
CoverCallExpressionAndAsyncArrowHead [?Yield,
?Await]
[此处不能有 LineTerminator
]
=>
AsyncConciseBody [?In]
对 CoverCallExpressionAndAsyncArrowHead
的解释会使用以下语法进行精化:
AsyncArrowHead :
async
[no LineTerminator
here]
ArrowFormalParameters [~Yield,
+Await]
MethodDefinition [Yield,
Await] :
ClassElementName [?Yield,
?Await]
(
UniqueFormalParameters [~Yield,
~Await]
)
{
FunctionBody [~Yield,
~Await]
}
GeneratorMethod [?Yield,
?Await]
AsyncMethod [?Yield,
?Await]
AsyncGeneratorMethod [?Yield,
?Await]
get
ClassElementName [?Yield,
?Await]
(
)
{
FunctionBody [~Yield,
~Await]
}
set
ClassElementName [?Yield,
?Await]
(
PropertySetParameterList
)
{
FunctionBody [~Yield,
~Await]
}
PropertySetParameterList
:
FormalParameter [~Yield,
~Await]
GeneratorDeclaration [Yield,
Await, Default] :
function
*
BindingIdentifier [?Yield,
?Await]
(
FormalParameters [+Yield,
~Await]
)
{
GeneratorBody
}
[+Default]
function
*
(
FormalParameters [+Yield,
~Await]
)
{
GeneratorBody
}
GeneratorExpression :
function
*
BindingIdentifier [+Yield,
~Await] opt
(
FormalParameters [+Yield,
~Await]
)
{
GeneratorBody
}
GeneratorMethod [Yield,
Await] :
*
ClassElementName [?Yield,
?Await]
(
UniqueFormalParameters [+Yield,
~Await]
)
{
GeneratorBody
}
GeneratorBody :
FunctionBody [+Yield,
~Await]
YieldExpression [In,
Await] :
yield
yield
[no LineTerminator
here]
AssignmentExpression [?In,
+Yield, ?Await]
yield
[no LineTerminator
here]
*
AssignmentExpression [?In,
+Yield, ?Await]
AsyncGeneratorDeclaration [Yield,
Await, Default] :
async
[no LineTerminator
here]
function
*
BindingIdentifier [?Yield,
?Await]
(
FormalParameters [+Yield,
+Await]
)
{
AsyncGeneratorBody
}
[+Default]
async
[no LineTerminator
here]
function
*
(
FormalParameters [+Yield,
+Await]
)
{
AsyncGeneratorBody
}
AsyncGeneratorExpression
:
async
[no LineTerminator
here]
function
*
BindingIdentifier [+Yield,
+Await] opt
(
FormalParameters [+Yield,
+Await]
)
{
AsyncGeneratorBody
}
AsyncGeneratorMethod [Yield,
Await] :
async
[no LineTerminator
here]
*
ClassElementName [?Yield,
?Await]
(
UniqueFormalParameters [+Yield,
+Await]
)
{
AsyncGeneratorBody
}
AsyncGeneratorBody :
FunctionBody [+Yield,
+Await]
AsyncFunctionDeclaration [Yield,
Await, Default] :
async
[no LineTerminator
here]
function
BindingIdentifier [?Yield,
?Await]
(
FormalParameters [~Yield,
+Await]
)
{
AsyncFunctionBody
}
[+Default]
async
[no LineTerminator
here]
function
(
FormalParameters [~Yield,
+Await]
)
{
AsyncFunctionBody
}
AsyncFunctionExpression
:
async
[no LineTerminator
here]
function
BindingIdentifier [~Yield,
+Await] opt
(
FormalParameters [~Yield,
+Await]
)
{
AsyncFunctionBody
}
AsyncMethod [Yield,
Await] :
async
[no LineTerminator
here]
ClassElementName [?Yield,
?Await]
(
UniqueFormalParameters [~Yield,
+Await]
)
{
AsyncFunctionBody
}
AsyncFunctionBody :
FunctionBody [~Yield,
+Await]
AwaitExpression [Yield]
:
await
UnaryExpression [?Yield,
+Await]
ClassDeclaration [Yield, Await,
Default] :
class
BindingIdentifier [?Yield,
?Await]
ClassTail [?Yield,
?Await]
[+Default]
class
ClassTail [?Yield,
?Await]
ClassExpression [Yield,
Await] :
class
BindingIdentifier [?Yield,
?Await] opt
ClassTail [?Yield,
?Await]
ClassTail [Yield,
Await] :
ClassHeritage [?Yield,
?Await] opt
{
ClassBody [?Yield,
?Await] opt
}
ClassHeritage [Yield,
Await] :
extends
LeftHandSideExpression [?Yield,
?Await]
ClassBody [Yield,
Await] :
ClassElementList [?Yield,
?Await]
ClassElementList [Yield,
Await] :
ClassElement [?Yield,
?Await]
ClassElementList [?Yield,
?Await]
ClassElement [?Yield,
?Await]
ClassElement [Yield,
Await] :
MethodDefinition [?Yield,
?Await]
static
MethodDefinition [?Yield,
?Await]
FieldDefinition [?Yield,
?Await]
;
static
FieldDefinition [?Yield,
?Await]
;
ClassStaticBlock
;
FieldDefinition [Yield,
Await] :
ClassElementName [?Yield,
?Await]
Initializer [+In, ?Yield,
?Await] opt
ClassElementName [Yield,
Await] :
PropertyName [?Yield,
?Await]
PrivateIdentifier
ClassStaticBlock :
static
{
ClassStaticBlockBody
}
ClassStaticBlockBody :
ClassStaticBlockStatementList
ClassStaticBlockStatementList
:
StatementList [~Yield, +Await,
~Return] opt
A.5 Scripts and Modules
Script :
ScriptBody opt
ScriptBody :
StatementList [~Yield, ~Await,
~Return]
Module :
ModuleBody opt
ModuleBody :
ModuleItemList
ModuleItemList :
ModuleItem
ModuleItemList
ModuleItem
ModuleItem :
ImportDeclaration
ExportDeclaration
StatementListItem [~Yield,
+Await, ~Return]
ModuleExportName :
IdentifierName
StringLiteral
ImportDeclaration :
import
ImportClause
FromClause
WithClause opt
;
import
ModuleSpecifier
WithClause opt
;
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
WithClause opt
;
export
NamedExports
;
export
VariableStatement [~Yield,
+Await]
export
Declaration [~Yield,
+Await]
export
default
HoistableDeclaration [~Yield,
+Await, +Default]
export
default
ClassDeclaration [~Yield, +Await,
+Default]
export
default
[lookahead ∉ { function , async
[no LineTerminator
here]
function , class }]
AssignmentExpression [+In,
~Yield, +Await]
;
ExportFromClause :
*
*
as
ModuleExportName
NamedExports
NamedExports :
{
}
{
ExportsList
}
{
ExportsList
,
}
ExportsList :
ExportSpecifier
ExportsList
,
ExportSpecifier
ExportSpecifier :
ModuleExportName
ModuleExportName
as
ModuleExportName
A.6 数值转换
StringNumericLiteral
:::
StrWhiteSpace opt
StrWhiteSpace opt
StrNumericLiteral
StrWhiteSpace opt
StrWhiteSpace :::
StrWhiteSpaceChar
StrWhiteSpace opt
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
:::
StrWhiteSpace opt
StrWhiteSpace opt
StrIntegerLiteral
StrWhiteSpace opt
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
TemporalDecimalFraction opt
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
UnicodePropertyNameCharacters opt
UnicodePropertyValue ::
UnicodePropertyValueCharacters
LoneUnicodePropertyNameOrValue
::
UnicodePropertyValueCharacters
UnicodePropertyValueCharacters
::
UnicodePropertyValueCharacter
UnicodePropertyValueCharacters opt
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
ClassUnion opt
ClassSetOperand
ClassUnion opt
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
NonEmptyClassString opt
ClassSetCharacter ::
[lookahead ∉ ClassSetReservedDoublePunctuator ]
SourceCharacter but not
ClassSetSyntaxCharacter
\
CharacterEscape [+UnicodeMode]
\
ClassSetReservedPunctuator
\b
ClassSetReservedDoublePunctuator
:: one of &&
!! ## $$ %% **
++ ,, .. :: ;;
<< == >> ??
@@ ^^ `` ~~
ClassSetSyntaxCharacter
:: one of ( )
[ ] { } /
- \ |
ClassSetReservedPunctuator
:: one of & -
! # % , :
; < = > @
` ~
附录 B (规范性) 针对 Web 浏览器的 ECMAScript 额外特性
当 ECMAScript 宿主 是 Web 浏览器时,本附录中定义的
ECMAScript 语言语法和语义是必需的。如果 ECMAScript 宿主 不是 Web 浏览器,则本附录内容为规范性但可选项。
注意
本附录描述了 Web 浏览器 ECMAScript 宿主
的各种遗留特性和其他特性。本附录中指定的所有语言特性和行为都存在一个或多个不理想的特性,如果没有遗留使用,这些内容会从本规范中移除。然而,由于大量现有网页使用了这些特性,Web
浏览器必须继续支持它们。本附录中的规范定义了这些遗留特性的可互操作实现的要求。
这些特性不被认为是 ECMAScript 核心语言的一部分。编写新的 ECMAScript 代码时,程序员不应使用或假定这些特性和行为的存在。除非实现是 Web 浏览器的一部分,或需要运行
Web 浏览器所遇到的相同遗留 ECMAScript 代码,否则不建议 ECMAScript 实现实现这些特性。
B.1 额外语法
B.1.2 正则表达式模式
22.2.1
的语法进行了如下修改和扩展。这些更改引入了歧义,可以通过文法产生式的顺序和上下文信息来消除。在使用下述文法进行解析时,仅当前面的产生式备选项不匹配时,才会考虑每一个备选项。
这种可选的模式文法和语义仅更改了 BMP 模式的语法和语义。下列文法扩展包含带有 [UnicodeMode] 参数的产生式。然而,这些扩展并不会更改在 目标符号 上带有 [UnicodeMode] 参数时解析所识别的
Unicode 模式的语法。
语法
Term [UnicodeMode,
UnicodeSetsMode, NamedCaptureGroups]
:: [+UnicodeMode]
Assertion [+UnicodeMode,
?UnicodeSetsMode, ?NamedCaptureGroups]
[+UnicodeMode]
Atom [+UnicodeMode, ?UnicodeSetsMode,
?NamedCaptureGroups]
Quantifier
[+UnicodeMode]
Atom [+UnicodeMode, ?UnicodeSetsMode,
?NamedCaptureGroups]
[~UnicodeMode]
QuantifiableAssertion [?NamedCaptureGroups]
Quantifier
[~UnicodeMode]
Assertion [~UnicodeMode,
~UnicodeSetsMode, ?NamedCaptureGroups]
[~UnicodeMode]
ExtendedAtom [?NamedCaptureGroups]
Quantifier
[~UnicodeMode]
ExtendedAtom [?NamedCaptureGroups]
Assertion [UnicodeMode,
UnicodeSetsMode, NamedCaptureGroups]
::
^
$
\b
\B
[+UnicodeMode]
(?=
Disjunction [+UnicodeMode,
?UnicodeSetsMode, ?NamedCaptureGroups]
)
[+UnicodeMode]
(?!
Disjunction [+UnicodeMode,
?UnicodeSetsMode, ?NamedCaptureGroups]
)
[~UnicodeMode]
QuantifiableAssertion [?NamedCaptureGroups]
(?<=
Disjunction [?UnicodeMode,
?UnicodeSetsMode, ?NamedCaptureGroups]
)
(?<!
Disjunction [?UnicodeMode,
?UnicodeSetsMode, ?NamedCaptureGroups]
)
QuantifiableAssertion [NamedCaptureGroups]
::
(?=
Disjunction [~UnicodeMode,
~UnicodeSetsMode, ?NamedCaptureGroups]
)
(?!
Disjunction [~UnicodeMode,
~UnicodeSetsMode, ?NamedCaptureGroups]
)
ExtendedAtom [NamedCaptureGroups]
::
.
\
AtomEscape [~UnicodeMode,
?NamedCaptureGroups]
\
[lookahead = c ]
CharacterClass [~UnicodeMode,
~UnicodeSetsMode]
(
GroupSpecifier [~UnicodeMode] opt
Disjunction [~UnicodeMode,
~UnicodeSetsMode, ?NamedCaptureGroups]
)
(?
RegularExpressionModifiers
:
Disjunction [~UnicodeMode,
~UnicodeSetsMode, ?NamedCaptureGroups]
)
(?
RegularExpressionModifiers
-
RegularExpressionModifiers
:
Disjunction [~UnicodeMode,
~UnicodeSetsMode, ?NamedCaptureGroups]
)
InvalidBracedQuantifier
ExtendedPatternCharacter
InvalidBracedQuantifier
::
{
DecimalDigits [~Sep]
}
{
DecimalDigits [~Sep]
,}
{
DecimalDigits [~Sep]
,
DecimalDigits [~Sep]
}
ExtendedPatternCharacter
::
SourceCharacter
but not one of ^
$
\
.
*
+
?
(
)
[
|
AtomEscape [UnicodeMode,
NamedCaptureGroups] ::
[+UnicodeMode]
DecimalEscape
[~UnicodeMode]
DecimalEscape
but only if the CapturingGroupNumber
of DecimalEscape
is ≤ CountLeftCapturingParensWithin (the
Pattern containing
DecimalEscape )
CharacterClassEscape [?UnicodeMode]
CharacterEscape [?UnicodeMode,
?NamedCaptureGroups]
[+NamedCaptureGroups]
k
GroupName [?UnicodeMode]
CharacterEscape [UnicodeMode,
NamedCaptureGroups] ::
ControlEscape
c
AsciiLetter
0
[lookahead ∉ DecimalDigit ]
HexEscapeSequence
RegExpUnicodeEscapeSequence [?UnicodeMode]
[~UnicodeMode]
LegacyOctalEscapeSequence
IdentityEscape [?UnicodeMode,
?NamedCaptureGroups]
IdentityEscape [UnicodeMode,
NamedCaptureGroups] ::
[+UnicodeMode]
SyntaxCharacter
[+UnicodeMode]
/
[~UnicodeMode]
SourceCharacterIdentityEscape [?NamedCaptureGroups]
SourceCharacterIdentityEscape [NamedCaptureGroups]
:: [~NamedCaptureGroups]
SourceCharacter
but not c
[+NamedCaptureGroups]
SourceCharacter
but not one of c or k
ClassAtomNoDash [UnicodeMode,
NamedCaptureGroups] ::
SourceCharacter
but not one of \ or ] or
-
\
ClassEscape [?UnicodeMode,
?NamedCaptureGroups]
\
[lookahead = c ]
ClassEscape [UnicodeMode,
NamedCaptureGroups] ::
b
[+UnicodeMode]
-
[~UnicodeMode]
c
ClassControlLetter
CharacterClassEscape [?UnicodeMode]
CharacterEscape [?UnicodeMode,
?NamedCaptureGroups]
ClassControlLetter
::
DecimalDigit
_
注
当同一个左侧出现了带有 [+UnicodeMode] 和 [~UnicodeMode] 条件时,这是用于控制消歧优先级。
B.1.2.1 静态语义:早期错误
22.2.1.1 的语义扩展如下:
ExtendedAtom
:: InvalidBracedQuantifier
此外,以下产生式的规则通过添加高亮 文本被修改:
NonemptyClassRanges
::
ClassAtom
-
ClassAtom
ClassContents
NonemptyClassRangesNoDash
::
ClassAtomNoDash
-
ClassAtom
ClassContents
B.1.2.2 静态语义:CountLeftCapturingParensWithin 和
CountLeftCapturingParensBefore
在 CountLeftCapturingParensWithin
和 CountLeftCapturingParensBefore
的定义中,对 “
Atom ::
(
GroupSpecifier opt
Disjunction
)
” 的引用应被解释为 “
Atom ::
(
GroupSpecifier opt
Disjunction
)
” 或 “
ExtendedAtom
::
(
GroupSpecifier opt
Disjunction
)
”。
B.1.2.3 静态语义:IsCharacterClass
22.2.1.6
的语义扩展如下:
ClassAtomNoDash
::
\
[lookahead = c ]
返回 false 。
B.1.2.4 静态语义:CharacterValue
22.2.1.7
的语义扩展如下:
ClassAtomNoDash
::
\
[lookahead = c ]
返回 U+005C(反斜杠)的数值。
ClassEscape
::
c
ClassControlLetter
令 ch 为 ClassControlLetter
匹配的代码点。
令 i 为 ch 的数值。
返回 i 除以 32 的余数。
CharacterEscape
:: LegacyOctalEscapeSequence
返回 LegacyOctalEscapeSequence
的 MV(见 12.9.4.3 )。
B.1.2.5 运行时语义:CompileSubpattern
CompileSubpattern 的语义扩展如下:
Term ::
QuantifiableAssertion
Quantifier
规则与
Term ::
Atom
Quantifier
相同,但用 QuantifiableAssertion 替换了
Atom 。
Term ::
ExtendedAtom
Quantifier
规则与
Term ::
Atom
Quantifier
相同,但用 ExtendedAtom 替换了 Atom 。
Term :: ExtendedAtom
规则与
Term :: Atom
相同,但用 ExtendedAtom 替换了 Atom 。
B.1.2.6 运行时语义:CompileAssertion
CompileAssertion 对于
Assertion
::
(?=
Disjunction
)
和
Assertion
::
(?!
Disjunction
)
产生式的规则也适用于 QuantifiableAssertion 产生式,但用
QuantifiableAssertion 替换
Assertion 。
B.1.2.7 运行时语义:CompileAtom
CompileAtom 对 Atom 产生式(除了
Atom :: PatternCharacter
)的规则同样适用于 ExtendedAtom 产生式,但用 ExtendedAtom 替换 Atom 。同时也新增了如下带参数 direction
的规则:
ExtendedAtom
::
\
[lookahead = c ]
令 A 为包含单个字符 \
(U+005C,反斜杠)的 CharSet 。
返回 CharacterSetMatcher (rer ,
A , false , direction )。
ExtendedAtom
:: ExtendedPatternCharacter
令 ch 为 ExtendedPatternCharacter
所代表的字符。
令 A 为包含字符 ch 的单元素 CharSet 。
返回 CharacterSetMatcher (rer ,
A , false , direction )。
B.1.2.8 运行时语义:CompileToCharSet
22.2.2.9 的语义扩展如下:
以下两条规则替换了 CompileToCharSet 的对应规则。
NonemptyClassRanges
::
ClassAtom
-
ClassAtom
ClassContents
令 A 为第一个 ClassAtom 以 rer 作为参数调用
CompileToCharSet 的结果。
令 B 为第二个 ClassAtom 以 rer 作为参数调用
CompileToCharSet 的结果。
令 C 为 ClassContents 以 rer
作为参数调用 CompileToCharSet 的结果。
令 D 为 CharacterRangeOrUnion (rer ,
A , B )。
返回 D 与 C 的并集。
NonemptyClassRangesNoDash
::
ClassAtomNoDash
-
ClassAtom
ClassContents
令 A 为 ClassAtomNoDash 以
rer 作为参数调用 CompileToCharSet 的结果。
令 B 为 ClassAtom 以 rer 作为参数调用
CompileToCharSet 的结果。
令 C 为 ClassContents 以 rer
作为参数调用 CompileToCharSet 的结果。
令 D 为 CharacterRangeOrUnion (rer ,
A , B )。
返回 D 与 C 的并集。
此外,以下规则被添加到 CompileToCharSet 。
ClassEscape
::
c
ClassControlLetter
令 cv 为该 ClassEscape 的 CharacterValue 。
令 c 为字符值为 cv 的字符。
返回包含单个字符 c 的 CharSet 。
ClassAtomNoDash
::
\
[lookahead = c ]
返回包含单个字符 \
(U+005C,反斜杠)的 CharSet 。
注意
该产生式只会在字符类内的 \c
序列且其后不跟可接受的控制字符时被匹配到。
B.1.2.8.1 CharacterRangeOrUnion ( rer ,
A , B )
抽象操作 CharacterRangeOrUnion 接收参数 rer (一个 RegExp
Record )、A (一个 CharSet )与 B
(一个 CharSet ),并返回一个 CharSet 。调用时执行以下步骤:
如果 HasEitherUnicodeFlag (rer )
为 false ,则
如果 A 不正好包含一个字符或 B 不正好包含一个字符,则
令 C 为仅包含字符 -
(U+002D,连字符)的 CharSet 。
返回 CharSets
A 、B 和 C 的并集。
返回 CharacterRange (A ,
B )。
B.1.2.9 静态语义:ParsePattern ( patternText ,
u , v )
22.2.3.4 的语义扩展如下:
抽象操作 ParsePattern 接收参数 patternText (一组
Unicode 码点序列)、u (布尔值)和 v (布尔值)。调用时执行以下步骤:
如果 v 为 true 且 u 为 true ,则
令 parseResult 为包含一个或多个 SyntaxError 对象的
List 。
否则如果 v 为 true ,则
令 parseResult 为 ParseText (patternText ,
Pattern [+UnicodeMode,
+UnicodeSetsMode,
+NamedCaptureGroups] )。
否则如果 u 为 true ,则
令 parseResult 为 ParseText (patternText ,
Pattern [+UnicodeMode,
~UnicodeSetsMode,
+NamedCaptureGroups] )。
否则,
令 parseResult 为 ParseText (patternText ,
Pattern [~UnicodeMode,
~UnicodeSetsMode,
~NamedCaptureGroups] )。
如果 parseResult 是 语法解析节点(Parse
Node) ,且 parseResult 包含 GroupName ,则
将 parseResult 设置为 ParseText (patternText ,
Pattern [~UnicodeMode,
~UnicodeSetsMode,
+NamedCaptureGroups] )。
返回 parseResult 。
B.2 补充内置属性
当 ECMAScript 宿主
是网页浏览器时,标准内置对象会定义以下附加属性。
B.2.1 全局对象的附加属性
表102 中的条目被添加到
表6 中。
表102:附加知名内在对象
B.2.1.1 escape ( string )
此函数是 全局对象 的一个属性。它会计算一个新的字符串值,其中部分码元被十六进制转义序列替换。
当替换数值小于等于 0x00FF 的码元时,使用形如 %xx
的两位转义序列。当替换数值严格大于 0x00FF 的码元时,使用形如
%uxxxx
的四位转义序列。
它是 %escape% 内在对象。
调用时执行以下步骤:
将 string 设为 ? ToString (string ).
令 len 为 string 的长度。
令 R 为一个空字符串。
令 unescapedSet 为 字符串拼接 ASCII 单词字符 和
"@*+-./" 的结果。
令 k 为 0。
重复,条件为 k < len ,
令 C 为 string 中索引 k 处的码元。
如果 unescapedSet 包含 C ,则
令 S 为 C 。
否则,
令 n 为 C 的数值。
如果 n < 256,则
令 hex 为 n 的字符串表示,按大写十六进制格式。
令 S 为 字符串拼接
"%" 和 StringPad (hex ,
2, "0" , start )
的结果。
否则,
令 hex 为 n 的字符串表示,按大写十六进制格式。
令 S 为 字符串拼接
"%u" 和 StringPad (hex ,
4, "0" , start )
的结果。
将 R 设为 字符串拼接 R 和
S 的结果。
将 k 设为 k + 1。
返回 R 。
注意
该编码部分基于 RFC 1738 中描述的编码,但本标准中描述的完整编码如上所述,不考虑 RFC 1738 的内容。此编码未反映 RFC 3986 对 RFC 1738
的更改。
B.2.1.2 unescape ( string )
此函数是 全局对象 的一个属性。它会计算一个新的字符串值,将每个可能由
escape
函数引入的转义序列替换为其所代表的码元。
它是 %unescape% 内在对象。
调用时执行以下步骤:
将 string 设为 ? ToString (string ).
令 len 为 string 的长度。
令 R 为一个空字符串。
令 k 为 0。
重复,条件为 k < len ,
令 C 为 string 中索引 k 处的码元。
如果 C 是码元 0x0025(百分号),则
令 hexDigits 为一个空字符串。
令 optionalAdvance 为 0。
如果 k + 5 < len 且 string 中索引
k + 1 处的码元是 0x0075(小写字母 u),则
将 hexDigits 设为 子字符串
string 从 k + 2 到 k + 6。
将 optionalAdvance 设为 5。
否则如果 k + 3 ≤ len ,则
将 hexDigits 设为 子字符串
string 从 k + 1 到 k + 3。
将 optionalAdvance 设为 2。
令 parseResult 为 ParseText (hexDigits ,
HexDigits [~Sep] )。
如果 parseResult 是 解析节点 ,则
令 n 为 parseResult 的 MV。
将 C 设为数值为 n 的码元。
将 k 设为 k + optionalAdvance 。
将 R 设为 字符串拼接 R 和
C 的结果。
将 k 设为 k + 1。
返回 R 。
B.2.2 String.prototype 对象的附加属性
B.2.2.1 String.prototype.substr ( start ,
length )
该方法返回将 this 的值转换为字符串后的一个 子字符串 ,从索引
start 开始,长度为 length 个码元(如果 length 为
undefined ,则到字符串末尾为止)。如果 start 为负值,则视为 sourceLength + start ,其中
sourceLength 是字符串的长度。结果 是一个字符串 值,而不是字符串对象。
调用时执行以下步骤:
令 O 为 ? RequireObjectCoercible (this
的值)。
令 S 为 ? ToString (O ).
令 size 为 S 的长度。
令 intStart 为 ? ToIntegerOrInfinity (start )。
如果 intStart = -∞,则将 intStart 设为 0。
否则如果 intStart < 0,则将 intStart 设为 max (size +
intStart , 0)。
否则,将 intStart 设为 min (intStart , size )。
如果 length 是 undefined ,则令 intLength 为
size ;否则令 intLength 为 ? ToIntegerOrInfinity (length )。
将 intLength 限制在 0 到 size 之间,结果赋值给 intLength 。
令 intEnd 为 min (intStart +
intLength , size )。
返回 子字符串 S 从 intStart 到
intEnd 的结果。
注意
该方法本身是通用的;它不要求 this 是字符串对象。因此它可以被转移到其他类型的对象用作方法。
B.2.2.2 String.prototype.anchor ( name )
此方法被调用时执行以下步骤:
令 S 为 this 的值。
返回 ? CreateHTML (S ,
"a" , "name" , name )。
B.2.2.2.1 CreateHTML ( string , tag ,
attribute , value )
抽象操作 CreateHTML 接收参数 string (ECMAScript
语言值 ),
tag (字符串),attribute (字符串),和 value (ECMAScript 语言值 ),返回一个包含字符串的
正常完成 或 抛出完成 。调用时执行以下步骤:
令 str 为 ? RequireObjectCoercible (string )。
令 S 为 ? ToString (str )。
令 p1 为 字符串拼接
"<" 和 tag 。
如果 attribute 不是空字符串,则
令 V 为 ? ToString (value )。
令 escapedV 为 V 的字符串值,除了每个 0x0022(引号)都被
""" 替换。
将 p1 设为 字符串拼接 :
p1
码元 0x0020(空格)
attribute
码元 0x003D(等号)
码元 0x0022(引号)
escapedV
码元 0x0022(引号)
令 p2 为 字符串拼接 p1 和
">" 。
令 p3 为 字符串拼接 p2 和
S 。
令 p4 为 字符串拼接
p3 、"</" 、tag 和
">" 。
返回 p4 。
B.2.2.3 String.prototype.big ( )
此方法被调用时执行以下步骤:
令 S 为 this 的值。
返回 ? CreateHTML (S ,
"big" , "" , "" )。
B.2.2.4 String.prototype.blink ( )
此方法被调用时执行以下步骤:
令 S 为 this 的值。
返回 ? CreateHTML (S ,
"blink" , "" , "" )。
B.2.2.5 String.prototype.bold ( )
此方法被调用时执行以下步骤:
令 S 为 this 的值。
返回 ? CreateHTML (S ,
"b" , "" , "" )。
B.2.2.6 String.prototype.fixed ( )
此方法被调用时执行以下步骤:
令 S 为 this 的值。
返回 ? CreateHTML (S ,
"tt" , "" , "" )。
B.2.2.7 String.prototype.fontcolor ( colour )
此方法被调用时执行以下步骤:
令 S 为 this 的值。
返回 ? CreateHTML (S ,
"font" , "color" , colour )。
B.2.2.8 String.prototype.fontsize ( size )
此方法被调用时执行以下步骤:
令 S 为 this 的值。
返回 ? CreateHTML (S ,
"font" , "size" , size )。
B.2.2.9 String.prototype.italics ( )
此方法被调用时执行以下步骤:
令 S 为 this 的值。
返回 ? CreateHTML (S ,
"i" , "" , "" )。
B.2.2.10 String.prototype.link ( url )
此方法被调用时执行以下步骤:
令 S 为 this 的值。
返回 ? CreateHTML (S ,
"a" , "href" , url )。
B.2.2.11 String.prototype.small ( )
此方法被调用时执行以下步骤:
令 S 为 this 的值。
返回 ? CreateHTML (S ,
"small" , "" , "" )。
B.2.2.12 String.prototype.strike ( )
此方法被调用时执行以下步骤:
令 S 为 this 的值。
返回 ? CreateHTML (S ,
"strike" , "" , "" )。
B.2.2.13 String.prototype.sub ( )
此方法被调用时执行以下步骤:
令 S 为 this 的值。
返回 ? CreateHTML (S ,
"sub" , "" , "" )。
B.2.2.14 String.prototype.sup ( )
此方法被调用时执行以下步骤:
令 S 为 this 的值。
返回 ? CreateHTML (S ,
"sup" , "" , "" )。
B.2.2.15 String.prototype.trimLeft ( )
注意
推荐使用 "trimStart" 属性。"trimLeft"
属性主要为了兼容旧代码而保留。建议新 ECMAScript 代码使用 "trimStart" 属性。
"trimLeft" 属性的初始值为 %String.prototype.trimStart%,定义见 22.1.3.34 。
B.2.2.16 String.prototype.trimRight ( )
注意
推荐使用 "trimEnd" 属性。"trimRight"
属性主要为了兼容旧代码而保留。建议新 ECMAScript 代码使用 "trimEnd" 属性。
"trimRight" 属性的初始值为 %String.prototype.trimEnd%,定义见 22.1.3.33 。
B.2.3 Date.prototype 对象的附加属性
B.2.3.1 Date.prototype.getYear ( )
注意
在几乎所有场合都推荐使用 getFullYear
方法,因为它避免了“千年虫问题”。
该方法被调用时执行以下步骤:
令 dateObject 为 this 的值。
执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
令 t 为 dateObject .[[DateValue]] 。
如果 t 为 NaN ,返回 NaN 。
返回 YearFromTime (LocalTime (t )) -
1900 𝔽 。
B.2.3.2 Date.prototype.setYear ( year )
注意
在几乎所有场合都推荐使用 setFullYear
方法,因为它避免了“千年虫问题”。
该方法被调用时执行以下步骤:
令 dateObject 为 this 的值。
执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
令 t 为 dateObject .[[DateValue]] 。
令 y 为 ? ToNumber (year )。
如果 t 为 NaN ,则将 t 设为
+0 𝔽 ;否则将 t 设为 LocalTime (t )。
令 yyyy 为 MakeFullYear (y )。
令 d 为 MakeDay (yyyy , MonthFromTime (t ),
DateFromTime (t ))。
令 date 为 MakeDate (d , TimeWithinDay (t ))。
令 u 为 TimeClip (UTC (date ))。
将 dateObject .[[DateValue]] 设为 u 。
返回 u 。
B.2.3.3 Date.prototype.toGMTString ( )
注意
推荐使用 toUTCString
方法。本方法主要为了兼容旧代码而保留。
"toGMTString" 属性的初始值为 %Date.prototype.toUTCString%,定义见 21.4.4.43 。
B.2.4 RegExp.prototype 对象的附加属性
B.2.4.1 RegExp.prototype.compile ( pattern ,
flags )
此方法被调用时执行以下步骤:
令 O 为 this 的值。
执行 ? RequireInternalSlot (O ,
[[RegExpMatcher]] )。
如果 pattern 是一个对象 且 pattern 有 [[RegExpMatcher]] 内部槽,则
如果 flags 不是 undefined ,抛出
TypeError 异常。
令 P 为 pattern .[[OriginalSource]] 。
令 F 为 pattern .[[OriginalFlags]] 。
否则,
令 P 为 pattern 。
令 F 为 flags 。
返回 ? RegExpInitialize (O ,
P , F )。
注意
该方法会完全重新初始化 this 的 RegExp 对象,使用新的模式和标志。实现可能会把该方法的使用解释为表示结果 RegExp
对象将被多次使用,因此可以额外优化。
B.3 其他附加特性
B.3.1 带标签的函数声明
在 ECMAScript 2015 之前,LabelledStatement 的规范不允许将语句标签与 FunctionDeclaration
关联。然而,带标签的 FunctionDeclaration 是 非严格代码
的一个允许扩展,且大多数浏览器宿主的 ECMAScript 实现都支持该扩展。在 ECMAScript 2015 及以后,LabelledStatement 的语法产生式允许将 FunctionDeclaration 作为
LabelledItem 使用,但 14.13.1
包含一条早期错误规则,如果发生这种情况会产生语法错误。该规则通过添加高亮 文本进行了修改:
LabelledItem : FunctionDeclaration
如果该产生式匹配到的源码文本是 严格模式代码 ,则为语法错误。
注意
B.3.2 块级函数声明的 Web 兼容性语义
在 ECMAScript 2015 之前,ECMAScript 规范没有定义 FunctionDeclaration 作为 Block 语句的 StatementList 元素的情况。然而,这种形式的 FunctionDeclaration
是允许的扩展,大多数浏览器宿主的 ECMAScript 实现都允许它们。不幸的是,这种声明的语义在那些实现间有所不同。由于这些语义差异,现有使用 Block 级函数声明的 web ECMAScript
源文本 ,只有当用法仅依赖于所有这些实现的语义交集时,才能在各浏览器实现间移植。以下用例属于该语义交集:
函数在单个块内声明且仅在该块内被引用。
函数在单个 Block 内声明并可能被使用,但也被该
Block 之外的内部函数定义引用。
函数在单个块内声明并可能被使用,但也在后续块内被引用。
第一个用例与 ECMAScript 2015 提供的块级函数声明语义兼容。任何采用该用例的现有 ECMAScript 源文本 都将按照 第10章 、第14章 和
第15章
所定义的块级函数声明语义运行。
第二和第三个用例的 ECMAScript 2015 兼容性需要对 第10章 、第15章 、19.2.1 和 16.1.7 语义进行如下扩展。
如果 ECMAScript 实现有报告诊断警告信息的机制,当代码包含应用了这些兼容性语义且与非兼容性语义产生可观察差异的 FunctionDeclaration 时,应当产生警告。例如,如果未引入 var
绑定是因为其引入会导致 早期错误 ,则不应产生警告信息。
B.3.2.1 FunctionDeclarationInstantiation 的变更
在 FunctionDeclarationInstantiation
过程中,以下步骤替换 第29步 :
如果 strict 为 false ,则
对每个直接包含在任意 StatementList 的 FunctionDeclaration
f ,该 StatementList 又属于某个 Block 、CaseClause 或
DefaultClause x ,且
code Contains
x 为 true ,执行:
令 F 为 f 的 BindingIdentifier
的 StringValue 。
如果用 F 作为 BindingIdentifier
的 VariableStatement
替换 f ,不会为 func 产生任何早期错误,且
parameterNames 不包含 F ,则:
注意:仅当 F 既不是 VarDeclaredName,也不是形参名,也不是另一个 FunctionDeclaration
时,才在此实例化 var 绑定。
如果 instantiatedVarNames 不包含 F 且
F 不是 "arguments" ,则:
执行
! varEnv .CreateMutableBinding(F ,
false )。
执行
! varEnv .InitializeBinding(F ,
undefined )。
将 F 添加到 instantiatedVarNames 。
当对 FunctionDeclaration
f 求值时,执行以下步骤替换 FunctionDeclaration
的 Evaluation
算法(见 15.2.6 ):
令 fEnv 为当前执行上下文的 VariableEnvironment。
令 bEnv 为当前执行上下文的 LexicalEnvironment。
令 fObj 为
! bEnv .GetBindingValue(F ,
false )。
执行
! fEnv .SetMutableBinding(F ,
fObj , false )。
返回 unused 。
B.3.2.2 全局声明实例化的变更
在 GlobalDeclarationInstantiation
过程中,以下步骤替换 第12步 :
执行以下步骤:
令 strict 为 ScriptIsStrict (script )。
如果 strict 为 false ,则
令 declaredFunctionOrVarNames 为
declaredFunctionNames 和 declaredVarNames 的
列表拼接 。
对每个直接包含在任意 StatementList 的
FunctionDeclaration
f ,该 StatementList 又属于某个
Block 、CaseClause 或 DefaultClause
x ,且 script Contains
x 为 true ,执行:
令 F 为 f 的 BindingIdentifier
的 StringValue 。
如果用 F 作为 BindingIdentifier
的 VariableStatement
替换 f ,不会为 script 产生任何早期错误,则
如果 HasLexicalDeclaration (env ,
F ) 为 false ,则
令 fnDefinable 为
? CanDeclareGlobalVar (env ,
F )。
如果 fnDefinable 为
true ,则
注意:仅当 F 既不是
VarDeclaredName,也不是另一个 FunctionDeclaration
的名字时,这里才会实例化 var 绑定。
如果
declaredFunctionOrVarNames
不包含 F ,则
执行 ? CreateGlobalVarBinding (env ,
F ,
false )。
将 F 添加到
declaredFunctionOrVarNames 。
当对 FunctionDeclaration
f 求值时,执行以下步骤来替换 FunctionDeclaration
的 Evaluation
算法(见 15.2.6 ):
令 gEnv 为当前执行上下文的
VariableEnvironment。
令 bEnv 为当前执行上下文的
LexicalEnvironment。
令 fObj 为
! bEnv .GetBindingValue(F ,
false )。
执行 ? gEnv .SetMutableBinding (F ,
fObj ,
false )。
返回
unused 。
B.3.2.3 EvalDeclarationInstantiation 的变更
在 EvalDeclarationInstantiation
过程中,以下步骤替换 第13步 :
如果 strict 为 false ,则
令 declaredFunctionOrVarNames 为 declaredFunctionNames 和
declaredVarNames 的 列表拼接 。
对每个直接包含在任意 StatementList 的 FunctionDeclaration
f ,该 StatementList 又属于某个 Block 、CaseClause 或
DefaultClause x ,且
body Contains
x 为 true ,执行:
令 F 为 f 的 BindingIdentifier
的 StringValue 。
如果用 F 作为 BindingIdentifier
的 VariableStatement
替换 f ,不会为 body 产生任何早期错误,则
令 bindingExists 为 false 。
令 thisEnv 为 lexEnv 。
断言 :以下循环将终止。
重复,条件为 thisEnv 不等于 varEnv :
如果 thisEnv 不是对象
环境记录 ,则
如果
! thisEnv .HasBinding(F )
为 true ,则
令 bindingExists 为
true 。
将 thisEnv 设为 thisEnv .[[OuterEnv]] 。
如果 bindingExists 为 false 且
varEnv 是 全局环境记录 ,则
如果 HasLexicalDeclaration (varEnv ,
F ) 为 false ,则
令 fnDefinable 为
? CanDeclareGlobalVar (varEnv ,
F )。
否则,
令 fnDefinable 为
false 。
否则,
令 fnDefinable 为 true 。
如果 bindingExists 为 false 且
fnDefinable 为 true ,则
如果 declaredFunctionOrVarNames 不包含
F ,则
如果 varEnv 是 全局环境记录 ,则
执行 ? CreateGlobalVarBinding (varEnv ,
F ,
true )。
否则,
令 bindingExists 为
! varEnv .HasBinding(F )。
如果 bindingExists 为
false ,则
执行
! varEnv .CreateMutableBinding(F ,
true )。
执行
! varEnv .InitializeBinding(F ,
undefined )。
将 F 添加到
declaredFunctionOrVarNames 。
当对 FunctionDeclaration
f 求值时,执行以下步骤来替换 FunctionDeclaration
的 Evaluation
算法(见 15.2.6 ):
令 gEnv 为当前执行上下文的
VariableEnvironment。
令 bEnv 为当前执行上下文的
LexicalEnvironment。
令 fObj 为
! bEnv .GetBindingValue(F ,
false )。
执行 ? gEnv .SetMutableBinding (F ,
fObj , false )。
返回 unused 。
B.3.2.4 块静态语义:早期错误的变更
在 14.2.1
中,下列产生式的规则通过添加高亮 文本进行了修改:
Block :
{
StatementList
}
B.3.2.5 switch
语句静态语义:早期错误的变更
在 14.12.1
中,下列产生式规则通过添加高亮 文本进行了修改:
SwitchStatement
:
switch
(
Expression
)
CaseBlock
B.3.2.6 BlockDeclarationInstantiation 的变更
在 BlockDeclarationInstantiation
过程中,以下步骤替换 3.a.ii.1 :
如果 ! env .HasBinding(dn ) 为 false ,则
执行 ! env .CreateMutableBinding(dn ,
false )。
在 BlockDeclarationInstantiation
过程中,以下步骤替换 3.b.iii :
执行以下步骤:
如果 env 中 fn 的绑定是未初始化绑定,则
执行 ! env .InitializeBinding(fn ,
fo )。
否则,
断言 :d 是一个 FunctionDeclaration 。
执行 ! env .SetMutableBinding(fn ,
fo , false )。
B.3.3 IfStatement 语句子句中的 FunctionDeclarations
下述内容对 IfStatement
产生式进行了补充,详见 14.6 :
IfStatement [Yield, Await,
Return] :
if
(
Expression [+In, ?Yield,
?Await]
)
FunctionDeclaration [?Yield,
?Await, ~Default]
else
Statement [?Yield, ?Await,
?Return]
if
(
Expression [+In, ?Yield,
?Await]
)
Statement [?Yield, ?Await,
?Return]
else
FunctionDeclaration [?Yield,
?Await, ~Default]
if
(
Expression [+In, ?Yield,
?Await]
)
FunctionDeclaration [?Yield,
?Await, ~Default]
else
FunctionDeclaration [?Yield,
?Await, ~Default]
if
(
Expression [+In, ?Yield,
?Await]
)
FunctionDeclaration [?Yield,
?Await, ~Default]
[lookahead ≠ else ]
该产生式仅适用于解析非严格模式代码 时。由该产生式匹配的源文本 被处理为:其每个匹配的FunctionDeclaration [?Yield,
?Await, ~Default] 都被视为占据该位置的StatementListItem 中的唯一一个,并包含在一个BlockStatement 中。此类合成的BlockStatement 的语义包括在B.3.2 中指定的
Web 兼容性旧版语义。
B.3.4 Catch 代码块中的 VariableStatements
子条款 14.15.1
的内容被替换为以下内容:
Catch :
catch
(
CatchParameter
)
Block
注
Block 中的 Catch 子句可以包含与 CatchParameter 所绑定名称相同的
var
声明。在运行时,这些绑定会在 VariableDeclarationEnvironment 中实例化。它们不会遮蔽由 CatchParameter
引入的同名绑定,因此这些 var
声明的 Initializer 将会赋值给对应的 catch 参数,而不是
var
绑定。
这种修改后的行为也适用于 Block 中包含的通过 直接调用 eval 引入的
var
和 function
声明。这一更改是通过如下方式修改 19.2.1.3 的算法来实现的:
第 3.d.i.2.a.i
步被替换为:
如果 thisEnv 不是某个 Catch 子句的 环境记录 ,则抛出
SyntaxError 异常。
第 13.b.ii.4.a.i.i
步被替换为:
如果 thisEnv 不是某个 Catch 子句的 环境记录 ,则设 bindingExists
为 true 。
B.3.5 ForIn 语句头中的初始化器
下列内容补充了 ForInOfStatement 的产生式定义,详见 14.7.5 :
ForInOfStatement [Yield,
Await, Return] :
for
(
var
BindingIdentifier [?Yield,
?Await]
Initializer [~In, ?Yield,
?Await]
in
Expression [+In, ?Yield,
?Await]
)
Statement [?Yield, ?Await,
?Return]
该产生式仅在解析 非严格模式代码 时适用。
静态语义 中,ContainsDuplicateLabels
的定义在 8.3.1 中被如下内容扩充:
ForInOfStatement
:
for
(
var
BindingIdentifier
Initializer
in
Expression
)
Statement
返回 ContainsDuplicateLabels (参数为
labelSet )应用于 Statement 的结果。
静态语义 中,ContainsUndefinedBreakTarget
的定义在 8.3.2 中被如下内容扩充:
ForInOfStatement
:
for
(
var
BindingIdentifier
Initializer
in
Expression
)
Statement
返回 ContainsUndefinedBreakTarget (参数为
labelSet )应用于 Statement 的结果。
静态语义 中的ContainsUndefinedContinueTarget
在8.3.3 节被增强如下:
ForInOfStatement
:
for
(
var
BindingIdentifier
Initializer
in
Expression
)
Statement
返回 ContainsUndefinedContinueTarget
在 Statement 中,使用参数
iterationSet 和 « » 的结果。
静态语义 中的 IsDestructuring 在 14.7.5.2 中被增强如下:
BindingIdentifier
:
Identifier
yield
await
返回 false 。
在 静态语义 中,关于 VarDeclaredNames 的定义(位于
8.2.6 )被以下内容所扩展:
ForInOfStatement
:
for
(
var
BindingIdentifier
Initializer
in
Expression
)
Statement
令 names1 为 绑定名 ,来源于 BindingIdentifier 。
令 names2 为 变量声明名 ,来源于
语句 。
返回 列表连接 ,将 names1 和
names2 合并。
在 静态语义 中,关于 变量作用域声明 的定义(位于
8.2.7 )被以下内容所扩展:
ForInOfStatement
:
for
(
var
BindingIdentifier
Initializer
in
Expression
)
Statement
令 declarations1 为 « 绑定标识符 »。
令 declarations2 为 变量作用域声明
,来源于 语句 。
返回 列表连接 ,合并 declarations1 和
declarations2 。
在 运行时语义 中,关于 ForInOfLoopEvaluation
的定义(位于
14.7.5.5 )被以下内容所扩展:
ForInOfStatement
:
for
(
var
BindingIdentifier
Initializer
in
Expression
)
Statement
令 bindingId 为 字符串值 ,来源于 绑定标识符 。
令 lhs 为 ? 解析绑定 (bindingId )。
如果 是否匿名函数定义 (初始化器 ) 为
true ,则
令 value 为 ? 命名求值 ,对 初始化器 以 bindingId 作为参数。
否则,
令 rhs 为 ? 求值 ,对 初始化器 。
令 value 为 ? 取值 (rhs )。
执行 ? 赋值 (lhs , value )。
令 keyResult 为 ? ForIn/Of 头部求值 (« », 表达式 ,
enumerate )。
返回 ? ForIn/Of 主体求值 (绑定标识符 , 语句 , keyResult ,
enumerate , var-binding ,
labelSet )。
B.3.6 [[IsHTMLDDA]] 内部槽
[[IsHTMLDDA]] 内部槽 可能存在于 宿主定义 对象上。具有 [[IsHTMLDDA]] 内部槽的对象,在 ToBoolean 、IsLooselyEqual 抽象操作 中,以及作为
typeof
运算符 的操作数时,表现得如同
undefined 。
注
具有 [[IsHTMLDDA]] 内部槽的对象不会由本规范创建。但 Web 浏览器中的 document.all
对象 是一个带有此槽的 宿主定义 特殊对象 ,用于 Web
兼容性。除此之外,没有其他已知的此类对象,除 document.all
外,实现不应创建任何此类对象。
B.3.6.1 对 ToBoolean 的更改
以下步骤替换 3 步骤,见 ToBoolean :
如果 argument 是对象 且 argument 有 [[IsHTMLDDA]] 内部槽,则返回 false 。
B.3.6.2 对 IsLooselyEqual 的更改
以下步骤替换 4
步骤,见 IsLooselyEqual :
执行以下步骤:
如果 x 是对象 ,x 有 [[IsHTMLDDA]] 内部槽,且 y 为
undefined 或 null ,则返回
true 。
如果 x 为 undefined 或
null ,y 是对象 ,且
y 有 [[IsHTMLDDA]] 内部槽,则返回
true 。
B.3.6.3 对 typeof
运算符的更改
以下步骤替换 12 步骤,见 typeof
运算符的求值语义 :
如果 val 有 [[IsHTMLDDA]] 内部槽,则返回
"undefined" 。
B.3.7 HostMakeJobCallback 的非默认行为
HostMakeJobCallback 抽象操作允许作为 Web 浏览器的
宿主 指定非默认行为。
B.3.8 HostEnsureCanAddPrivateElement 的非默认行为
HostEnsureCanAddPrivateElement
抽象操作允许作为 Web 浏览器的 宿主
指定非默认行为。
附录 C (资料性) ECMAScript 的严格模式
严格模式的限制与例外
附录 D (说明性) 主机分层点
有关 4.2 中 主机 的定义,请参见该节。
D.1 主机钩子
HostCallJobCallback (...)
HostEnqueueFinalizationRegistryCleanupJob (...)
HostEnqueueGenericJob (...)
HostEnqueuePromiseJob (...)
HostEnqueueTimeoutJob (...)
HostEnsureCanCompileStrings (...)
HostFinalizeImportMeta (...)
HostGetImportMetaProperties (...)
HostGrowSharedArrayBuffer (...)
HostHasSourceTextAvailable (...)
HostLoadImportedModule (...)
HostGetSupportedImportAttributes (...)
HostMakeJobCallback (...)
HostPromiseRejectionTracker (...)
HostResizeArrayBuffer (...)
InitializeHostDefinedRealm (...)
D.2 主机定义字段
[[HostDefined]] 在 Realm 记录 上:见 表 24 。
[[HostDefined]] 在 Script 记录 上:见 表 39 。
[[HostDefined]] 在 模块记录 上:见
表
43 。
[[HostDefined]] 在 JobCallback 记录 上:见
表
28 。
[[HostSynchronizesWith]] 在候选执行上:见 表 101 。
[[IsHTMLDDA]] :见 B.3.6 。
D.3 主机定义对象
全局对象 :见第
19 节。
D.4 运行中的作业
在调用 作业 抽象闭包
之前的准备步骤,以及之后的清理步骤。参见 9.5 。
D.5 异常对象的内部方法
本规范未指定的任何 表 4 中的必要内部方法,适用于任何
异类对象 ,且其语义由主机环境定义。
D.6 内建对象与方法
本规范未定义的任何内建对象与方法,除非在
17.1
中有限制。
附录 E (说明性) ECMAScript 2015 中可能影响兼容性的修正和澄清
9.1.1.4.14 -9.1.1.4.17 第五版和5.1版使用属性存在性测试来确定对应新全局声明的
全局对象
属性是否已存在。ECMAScript 2015 采用自有属性存在性测试。这与大多数网页浏览器的实现方式一致。
10.4.2.1 :第五版将当前数组长度的捕获移到了对
整数 转换 数组索引
或新长度值之前。然而,如果转换过程存在副作用更改了数组长度,捕获的长度值可能会变得无效。ECMAScript 2015 规定必须在可能发生此类副作用之后捕获当前数组长度。
21.4.1.31 :之前的版本允许
TimeClip 抽象操作返回
+0 𝔽 或 -0 𝔽 作为 0 时间值 的表示。ECMAScript 2015 规定始终返回
+0 𝔽 。这意味着在 ECMAScript 2015 中,Date 的 时间值 永远不会被观察为
-0 𝔽 ,且返回时间值的方法也永远不会返回 -0 𝔽 。
21.4.1.32 :如果不存在 UTC
偏移表示,则使用本地时区。第五版错误地声明缺少时区应解释为 "z" 。
21.4.4.36 :如果年份无法用 21.4.1.32 指定的日期时间字符串格式表示,则抛出 RangeError
异常。之前版本未指定该情况的行为。
21.4.4.41 :之前版本未指定当 时间值 为 NaN 时
Date.prototype.toString
返回的值。ECMAScript 2015 指定返回字符串值 "Invalid Date" 。
22.2.4.1 , 22.2.6.13.1 :RegExp 实例的
"source" 属性值中的任何换行符代码点必须使用转义序列表示。5.1版仅要求转义 /
。
22.2.6.8 , 22.2.6.11 :在之前版本中,String.prototype.match
和 String.prototype.replace
的规范对于参数为带有 global
标志的 RegExp
情况是不正确的。之前规范声明每次尝试匹配时,如果 lastIndex
未改变,则应将其加1。正确行为是仅当模式匹配空字符串时才将 lastIndex
加1。
23.1.3.30 :之前版本未指定当 比较器 返回
NaN 时,Array.prototype.sort
如何处理。ECMAScript 2015 指定该值视作从比较器返回了
+0 𝔽 。ECMAScript 2015 还规定对比较器返回的结果应用 ToNumber 。之前版本对于非数值的比较器返回值的效果是 由实现决定 。实际上,大多数实现都会调用 ToNumber 。
附录 F (说明性) 与先前版本不兼容的新增内容和更改
6.2.5 :在 ECMAScript 2015
中,函数调用不允许返回 引用记录 。
7.1.4.1 :在 ECMAScript 2015
中,应用于字符串值的 ToNumber
现在可以识别并转换 BinaryIntegerLiteral
和 OctalIntegerLiteral
数字字符串。在先前的版本中,此类字符串会被转换为 NaN 。
9.3 :在
ECMAScript 2018 中,模板对象的规范化基于 解析节点 (源位置),而不是像先前版本中那样,在 Realm 中跨越该模板字面量或带标签模板的所有出现。
12.2 :在
ECMAScript 2016 中,强制使用 Unicode 8.0.0 或更高版本,而 ECMAScript 2015 强制使用 Unicode 5.1。特别地,这导致 U+180E MONGOLIAN
VOWEL SEPARATOR(蒙古文元音分隔符),在 ECMAScript 2015 中属于 Space_Separator
(Zs
)
类别并因此被视为空白,被移至 Format
(Cf
) 类别(自 Unicode 6.3.0 起)。这导致对空白敏感的方法表现不同。例如,在先前的版本中
"\u180E".trim().length
为 0
,但在 ECMAScript 2016 及更高版本中为
1
。此外,ECMAScript 2017 强制始终使用最新版本的 Unicode 标准。
12.7 :在 ECMAScript 2015 中,IdentifierName 的有效码点是根据 Unicode 属性
“ID_Start” 和 “ID_Continue” 指定的。在先前的版本中,有效的 IdentifierName 或 Identifier 码点是通过枚举各种 Unicode 码点类别来指定的。
12.10.1 :在 ECMAScript 2015 中,如果
do-while 语句末尾缺少分号,自动分号插入会添加一个分号。此更改使规范与大多数现有实现的实际行为保持一致。
13.2.5.1 :在
ECMAScript 2015 中,对象初始化器中出现重复的属性名不再是 早期错误 。
13.15.1 :在
ECMAScript 2015 中,包含对不可变绑定(例如 FunctionExpression 的函数名)进行赋值的 严格模式代码
不会产生 早期错误 。而是会产生运行时错误。
14.2 :在 ECMAScript 2015 中,以
token let 开头,后跟输入元素 LineTerminator ,然后是 Identifier 的 StatementList 是 LexicalDeclaration 的开始。在先前的版本中,自动分号插入总是在 Identifier 输入元素之前插入分号。
14.5 :在 ECMAScript 2015 中,以 token
let
开头,后跟 token [
的 StatementListItem 是 LexicalDeclaration 的开始。在先前的版本中,这样的序列会是 ExpressionStatement 的开始。
14.6.2 :在 ECMAScript 2015
中,IfStatement 的正常结果永远不会是
empty 。如果没有对 Statement 部分进行求值,或者如果求值的 Statement 部分产生包含 empty 的 正常完成 ,则 IfStatement 的结果是
undefined 。
14.7 :在 ECMAScript 2015 中,如果 for 语句的
(
标记紧随 token 序列 let [
,则 let
被视为 LexicalDeclaration 的开始。在先前的版本中,这样的 token 序列会是
Expression 的开始。
14.7 :在 ECMAScript 2015 中,如果 for-in 语句的 ( 标记紧随
token 序列 let [
,则 let
被视为 ForDeclaration 的开始。在先前的版本中,这样的 token 序列会是 LeftHandSideExpression 的开始。
14.7 :在 ECMAScript 2015 之前,初始化表达式可以作为 VariableDeclaration 的一部分出现,该声明位于
in
关键字 之前。在 ECMAScript 2015 中,处于相同位置的
ForBinding 不允许出现这样的初始化器。在 ECMAScript
2017 中,这样的初始化器仅在 非严格代码 中被允许。
14.7 :在 ECMAScript 2015 中,求值 IterationStatement 的结果永远不会是其 [[Value]] 为 empty 的 正常完成 。如果 IterationStatement 的 Statement 部分未被求值,或者 Statement 部分的最终求值产生其 [[Value]] 为 empty 的 正常完成 ,则求值 IterationStatement 的结果是其 [[Value]] 为 undefined 的 正常完成 。
14.11.2 :在 ECMAScript 2015
中,求值 WithStatement 的结果永远不会是其 [[Value]] 为 empty 的 正常完成 。如果 WithStatement 的 Statement 部分的求值产生其 [[Value]] 为 empty 的 正常完成 ,则求值 WithStatement 的结果是其 [[Value]] 为 undefined 的 正常完成 。
14.12.4 :在 ECMAScript
2015 中,求值 SwitchStatement 的结果永远不会是其
[[Value]] 为 empty 的 正常完成 。如果 SwitchStatement 的 CaseBlock 部分的求值产生其 [[Value]] 为 empty 的 正常完成 ,则求值 SwitchStatement 的结果是其 [[Value]] 为 undefined 的 正常完成 。
14.15 :在
ECMAScript 2015 中,如果 Catch 子句包含一个
var
声明,其 Identifier 与作为
Catch 子句参数的 Identifier 相同,则这是一个 早期错误 。在先前的版本中,这样的变量声明会在封闭的变量环境中实例化,但声明的 Initializer 值会赋给 Catch 参数。
14.15 ,19.2.1.3 :在 ECMAScript 2015 中,如果 Catch 子句对一个非严格的直接 eval
求值,其 eval
代码包含一个 var
或 FunctionDeclaration
声明,该声明绑定了与作为 Catch 子句参数的 Identifier 相同的 Identifier ,则会抛出一个运行时 SyntaxError 。
14.15.3 :在 ECMAScript 2015
中,TryStatement 的结果永远不会是
empty 。如果 TryStatement 的 Block 部分求值为包含 empty 的 正常完成 ,则 TryStatement 的结果是
undefined 。如果 TryStatement 的 Block 部分求值为 throw 完成 ,并且它有一个 Catch 部分,该部分求值为包含 empty 的
正常完成 ,那么如果不存在 Finally 子句,或者其 Finally 子句求值为一个 empty 的 正常完成 ,则 TryStatement 的结果是
undefined 。
15.4.5 在 ECMAScript 2015
中,作为 ObjectLiteral 中 访问器属性 的 [[Get]] 或 [[Set]] 属性值创建的 函数对象 不是 构造函数 ,并且它们没有
"prototype" 自有属性。在先前的版本中,它们是 构造函数 并且具有 "prototype" 属性。
20.1.2.6 :在
ECMAScript 2015 中,如果传递给 Object.freeze
的参数不是对象,则将其视为一个不可扩展且没有自有属性的 普通对象 。在先前的版本中,非对象参数总是导致抛出 TypeError 。
20.1.2.8 :在 ECMAScript 2015 中,如果传递给
Object.getOwnPropertyDescriptor
的参数不是对象,则会尝试使用 ToObject 对参数进行强制转换。如果强制转换成功,则使用结果代替原始参数值。在先前的版本中,非对象参数总是导致抛出
TypeError 。
20.1.2.10 :在 ECMAScript 2015 中,如果传递给
Object.getOwnPropertyNames
的参数不是对象,则会尝试使用 ToObject 对参数进行强制转换。如果强制转换成功,则使用结果代替原始参数值。在先前的版本中,非对象参数总是导致抛出
TypeError 。
20.1.2.12 :在 ECMAScript 2015 中,如果传递给
Object.getPrototypeOf
的参数不是对象,则会尝试使用 ToObject 对参数进行强制转换。如果强制转换成功,则使用结果代替原始参数值。在先前的版本中,非对象参数总是导致抛出
TypeError 。
20.1.2.16 :在 ECMAScript 2015 中,如果传递给
Object.isExtensible
的参数不是对象,则将其视为一个不可扩展且没有自有属性的 普通对象 。在先前的版本中,非对象参数总是导致抛出
TypeError 。
20.1.2.17 :在 ECMAScript 2015 中,如果传递给
Object.isFrozen
的参数不是对象,则将其视为一个不可扩展且没有自有属性的 普通对象 。在先前的版本中,非对象参数总是导致抛出
TypeError 。
20.1.2.18 :在 ECMAScript 2015 中,如果传递给
Object.isSealed
的参数不是对象,则将其视为一个不可扩展且没有自有属性的 普通对象 。在先前的版本中,非对象参数总是导致抛出
TypeError 。
20.1.2.19 :在
ECMAScript 2015 中,如果传递给 Object.keys
的参数不是对象,则会尝试使用 ToObject
对参数进行强制转换。如果强制转换成功,则使用结果代替原始参数值。在先前的版本中,非对象参数总是导致抛出 TypeError 。
20.1.2.20 :在 ECMAScript 2015 中,如果传递给
Object.preventExtensions
的参数不是对象,则将其视为一个不可扩展且没有自有属性的 普通对象 。在先前的版本中,非对象参数总是导致抛出
TypeError 。
20.1.2.22 :在
ECMAScript 2015 中,如果传递给 Object.seal
的参数不是对象,则将其视为一个不可扩展且没有自有属性的 普通对象 。在先前的版本中,非对象参数总是导致抛出 TypeError 。
20.2.3.2 :在 ECMAScript 2015 中,绑定函数的 [[Prototype]] 内部插槽设置为其目标函数的 [[GetPrototypeOf]]
值。在先前的版本中,[[Prototype]] 总是设置为 %Function.prototype% 。
20.2.4.1 :在 ECMAScript 2015 中,函数实例的
"length" 属性是可配置的。在先前的版本中,它是不可配置的。
20.5.6.2 :在 ECMAScript 2015
中,NativeError 构造函数 的 [[Prototype]] 内部插槽是 Error
构造函数 。在先前的版本中,它是
函数原型对象 。
21.4.4 在 ECMAScript 2015
中,Date 原型对象 不是 Date
实例。在先前的版本中,它是一个 TimeValue 为 NaN 的 Date 实例。
22.1.3.12 在 ECMAScript 2015
中,String.prototype.localeCompare
函数必须将根据 Unicode
标准在规范上等效的字符串视为相同。在先前的版本中,实现被允许忽略规范等效性,而可以使用逐位比较。
22.1.3.28 和 22.1.3.30 在 ECMAScript 2015
中,小写/大写转换处理作用于码点。在先前的版本中,这种转换处理仅应用于单个代码单元。唯一受影响的码点是 Unicode 的 Deseret 字符块中的码点。
22.1.3.32 在 ECMAScript 2015
中,String.prototype.trim
方法被定义为识别可能存在于 Unicode BMP 之外的空白码点。然而,截至 Unicode
7,尚未定义此类码点。在先前的版本中,此类码点不会被识别为空白。
22.2.4.1 在 ECMAScript 2015 中,如果
pattern 参数是 RegExp 实例且 flags 参数不是 undefined ,则会创建一个新的 RegExp
实例,其行为与 pattern 类似,只是 pattern 的标志被参数 flags 替换。在先前的版本中,当
pattern 是 RegExp 实例且 flags 不是 undefined 时,会抛出
TypeError 异常。
22.2.6 在 ECMAScript 2015
中,RegExp 原型对象 不是 RegExp
实例。在先前的版本中,它是一个模式为空字符串的 RegExp 实例。
22.2.6 在 ECMAScript 2015
中,"source" 、"global" 、"ignoreCase" 和
"multiline" 是在 RegExp 原型对象
上定义的 访问器属性 。在先前的版本中,它们是在 RegExp 实例上定义的 数据属性 。
25.4.15 :
在 ECMAScript 2019 中,Atomics.wake
已重命名为 Atomics.notify
,以防止与
Atomics.wait
混淆。
27.1.6.4 , 27.6.3.6 : 在 ECMAScript 2019 中,由
await
入队的 作业
数量减少了,这可能导致在 then()
调用和 await
表达式之间的解析顺序出现可观察的差异。
参考文献
IEEE 754-2019 : IEEE 浮点数算术标准 。电气和电子工程师协会,纽约 (2019)
注意
IEEE 754-2008 和 IEEE 754-2019 之间没有影响 ECMA-262 规范的规范性变更。
Unicode 标准 , 参见 <https://unicode.org/versions/latest >
Unicode 技术说明 #5:应用程序中的规范等价 , 参见 <https://unicode.org/notes/tn5/ >
Unicode 技术标准 #10:Unicode 排序算法 , 参见 <https://unicode.org/reports/tr10/ >
Unicode 标准附录 #15, Unicode 规范化形式 , 参见 <https://unicode.org/reports/tr15/ >
Unicode 标准附录 #18: Unicode 正则表达式 , 参见 <https://unicode.org/reports/tr18/ >
Unicode 标准附录 #24: Unicode Script
属性 , 参见 <https://unicode.org/reports/tr24/ >
Unicode 标准附录 #31, Unicode 标识符和模式语法 , 参见 <https://unicode.org/reports/tr31/ >
Unicode 标准附录 #44: Unicode 字符数据库 , 参见 <https://unicode.org/reports/tr44/ >
Unicode 技术标准 #51: Unicode Emoji , 参见 <https://unicode.org/reports/tr51/ >
IANA 时区数据库 , 参见 <https://www.iana.org/time-zones >
ISO 8601:2004(E) 数据元素和交换格式 — 信息交换 — 日期和时间表示法
RFC 1738 “统一资源定位符 (URL)” , 参见 <https://tools.ietf.org/html/rfc1738 >
RFC 2396 “统一资源标识符 (URI): 通用语法” , 参见 <https://tools.ietf.org/html/rfc2396 >
RFC 3629 “UTF-8, ISO 10646 的转换格式” , 参见 <https://tools.ietf.org/html/rfc3629 >
RFC 7231 “超文本传输协议 (HTTP/1.1): 语义和内容” , 参见 <https://tools.ietf.org/html/rfc7231 >
版本说明
本规范在 GitHub 上以名为 Ecmarkup 的纯文本源格式编写。Ecmarkup 是一种 HTML 和 Markdown
方言,它提供了一个框架和工具集,用于以纯文本编写 ECMAScript 规范,并将规范处理成功能齐全的 HTML 渲染,该渲染遵循本文档的编辑约定。Ecmarkup
构建并集成了许多其他格式和技术,包括用于定义语法的 Grammarkdown 和用于编写算法步骤的
Ecmarkdown 。本规范的 PDF 渲染是使用打印样式表制作的,该样式表利用了 CSS
分页媒体规范,并使用 PrinceXML 进行转换。
本规范的先前版本是使用 Word 编写的——构成该版本基础的 Ecmarkup 源文本是通过使用自动转换工具将 ECMAScript 2015 Word 文档转换为 Ecmarkup 而生成的。
Copyright & Software License
Ecma International
Rue du Rhone 114
CH-1204 Geneva
Tel: +41 22 849 6000
Fax: +41 22 849 6001
Web: https://ecma-international.org/
Copyright Notice
© 2025 Ecma International
This draft document may be copied and furnished to others, and derivative works that comment on or
otherwise explain it or assist in its implementation may be prepared, copied, published, and
distributed, in whole or in part, without restriction of any kind, provided that the above copyright
notice and this section are included on all such copies and derivative works. However, this document
itself may not be modified in any way, including by removing the copyright notice or references to
Ecma International, except as needed for the purpose of developing any document or deliverable
produced by Ecma International.
This disclaimer is valid only prior to final version of this document. After approval all rights on
the standard are reserved by Ecma International.
The limited permissions are granted through the standardization phase and will not be revoked by Ecma
International or its successors or assigns during this time.
This document and the information contained herein is provided on an "AS IS" basis and ECMA
INTERNATIONAL DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY
WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY OWNERSHIP RIGHTS OR ANY
IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
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:
Redistributions of source code must retain the above copyright notice, this list of conditions and
the following disclaimer.
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.
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.